After seeing this select similar post on xsibase, I wrote this Python example that uses the PolygonArea ICE attribute to find polygons with similar areas. I didn’t want to use a custom preference or any ppg, so this script looks for [more-or-less] equal areas rather than for a value range. It’d probably be more useful to look for areas within a certain range (but that would require user input).
To use this script, select a polygon and then run the script. It’ll select all polygons with the “same” area.
This ss_SelectSimilarPolys add-on uses a threshold to define an area range (and it uses PolygonArea too). RCTools also lets you specify an area range, along with a number of other things like number of edges and poly orientation, in its custom Polygon selection filter.
from siutils import si # Application from siutils import sidict # Dictionary from siutils import sisel # Selection from siutils import log # LogMessage from siutils import C # win32com.client.constants # Number of decimal places # For example, do I match .776 or .78 ? # With 2 decimal places, anything in the range (7.75, 7.85) will be caught by .78 gPrecision = 2 # Need this for .Polygons later... def dispFix( badDispatch ): import win32com.client.dynamic # Re-Wraps a bad dispatch into a working one: return win32com.client.dynamic.Dispatch(badDispatch) # Get selected polygons polys = sisel(0).SubComponent.ComponentCollection # Get index of first selected polygon ix = polys(0).Index # Get primitive of parent 3D object prim = sisel(0).SubComponent.Parent3DObject.ActivePrimitive prim = dispFix(prim) # Get PolygonArea DataArray (which is a tuple) attr = prim.GetICEAttributeFromName( "PolygonArea" ) areaData = attr.DataArray # Round PolygonArea to the specified precision roundedAreas = [round(x,gPrecision) for x in areaData] # Get the area that you want to match areaToMatch = roundedAreas[ ix ] # Get all polys with a similar PolygonArea and select them # # Function findall from http://effbot.org/zone/python-list.htm def findall(L, value, start=0): # generator version i = start - 1 try: while 1: i = L.index(value, i+1) yield i except ValueError: pass for ix in findall(roundedAreas, areaToMatch ): sisel.Add( prim.Geometry.Polygons( ix ) )
Interesting… You might also want to mention this post in this thread (http://tinyurl.com/7sbxlq3) over at the XSIBase, which I’m guessing inspired you to write it.
(It’s a sad fact not everybody yet visits this blog on a daily basis 😉 )
You could do a generic selection tool using ICE for the logic !
For example using an ICETree the user could set a rule (like “if polygon area > threshold”) that would set a boolean attribute (“IsSelectedPoly” for example). Then a python plugin would select the components based on this attribute ;).
I like this idea. But I got all the way down to writing the filter plugin before I realized that ICE was not evaluating my tree, and so the boolean attribute wasn’t defined.
The boolean attribute wasn’t being used anywhere, so unless I Show Values or use it somewhere, the attribute isn’t available for the filter plugin.
The only problem with using ICE is that the boolean attribute won’t be defined if you don’t use it somewhere. I got as far as writing the python filter plugin before I [re]discovered this…as soon as I turned off Show Values, the attribute was no longer defined and my filter failed 😦