Batch identify connected matching geometries, convert to components?

Question for developers here. Is it possible for a script to identify matching geometry sets and then batch convert them to components? For example, I have a cad file with a bunch of dumb door geometries (converted from aec entities). The geometries of each door are exact, aside from rotation. Does the API allow for SketchUp to say “This collection of connected geometries is exactly like that collection of connected geometries. Make them all a component.”

dumb_doors.skp (112.2 KB)

It is certainly possible, but not necessarily easy. The API does not provide any analytic support or the like to help you. That is, the API does not have any methods that say “this collection of entities is geometrically the same as that collection except for location and rotation”. So your Ruby code will have to do all the work on its own.

Ironically, your model disobeys the standard advice about associating primitive edges only with Layer0 and this helps with one aspect of the problem: selecting only the geometry associated with doors! Your code can search the model for entities associated with the “dumb doors” layer and accumulate them in some appropriate structure. Layers do not organize or own entities, so you can’t go the other way (starting with a layer and gathering “its entities”).

The next issue is to isolate the entities that constitute each door, since the model has no existing structure that gathers them. In the model you uploaded, you could choose a radius and gather together entities that lie within that radius of each other. That will work, of course, only when the doors are adequately separated. I don’t think methods such as Edge#all_connected will work because the walls connect everything and, as noted, Layers don’t isolate geometry.

The final problem is to test that the geometry is identical but moved and rotated. This test is aggravated by computer arithmetic. That is, you will have to work with the relative positions of the vertices to do the test, and these computations will be inexact even if the doors are theoretically identical. In your specific case you can cheat if you are willing to stipulate that the doors are identical other than location and rotation (and even more if you stipulate that then are only rotated in steps of 90 degrees). Making those assumptions means you only need to find the location of a comparable reference point in each door and then test for which cardinal rotation the door has (not a simple task, but feasible). Accumulate the location and orientation info for all of the doors.

Following all of the above, you can create a new component from one of the doors’ geometry. Then delete all of the doors. Finally, place an instance of the component at each of the location and orientations by means of a transformation.

As I said, not necessarily easy…

1 Like

if you find one,

model  = Sketchup.active_model
defs = model.definitions
ents   = model.active_entities
sel    = model.selection
edges = ents.grep(Sketchup::Edge)
edges.find{|c| sel.add(c.all_connected) if c.curve}

or similar and then make it a component using the curves start for origin…

then find and replace the others with instances…


1 Like

After experimenting, I’ll revise one part of my previous reply: it turns out that in your model the walls are grouped, so Edge#all_connected will gather all of the parts of one door without getting any extra entities.