Creating a nested component
-
Hi Everybody,
So, I'm trying to create a sub component and add entities from the parent component that satisfy a set of conditions. Been banging my head on the problem for a while and could use some explanation of how to make this work. Hoping that somebody that understands the nuances of add_group can break it down for me.
Overview:
Here's a sample model: https://dl.dropbox.com/u/4116128/example.skp
Here's what i want the output to look like: https://dl.dropbox.com/u/4116128/example-after.skp
When you look at each example model, make sure to turn on hidden geometry. If you look in outliner, you'll see that I selected the top left geometry of the component (manually), selected "make component", and chose to "Replace selection with component".
Below is part of the code I wrote to try to achieve the same outcome, it assumes you have selected the component in the model. Warning, this code causes a BUG SPLAT when you quit SketchUp.
am = Sketchup.active_model ci = am.selection[0] cd = ci.definition ents = cd.entities off = 8 max = [8.0, 82.25] tl_a = [] cd.entities.each do |ent| b_max = ent.bounds.max b_min = ent.bounds.max if b_max.x <= off && b_min.z.to_i >= (max[1] - off) tl_a<<ent end end tl_grp = ents.add_group tl_a
-
You cannot create a group with contents unless the contents are situated in the same context as that group, AND that context is the 'model.active_entities'...
So if you were making a group in the current context and as it's being made you add the current selection as the argument[s], then that is OK and it won't splat - because everything is already in the current context 'model.active_entities' - the user can't manually select objects outside of the active_entities ! BUT adding entities from another context or working outside of the 'model.active_entities' will surely splat.If I understand your code correctly you want to add a group into the selected component-instance's entities and 'move' some objects within the definition.entities into that group.
You cannot do it the way you show without a splat!
Had the objects you wished to 'move' been instances then you could create an initially empty group and than usegroup.entities.add_instance(inst.definition, inst.transformation)
, for a group it'd begroup.entities.add_instance(gp.entities.parent, gp.transformation)
BUT your entities are faces/edges - raw geometry - so you'll have to 'clone' them.
Make the collection [tl_a
] as before... but then use
tl_grp = ents.add_group()
and iterate through that collection of geometry, treating edges and faces differently...
e.g.tle_a.each{|e| if e.is_a?(Sketchup;;Edge) ed=tl_grp.entities.add_line(e.start, e.end) elsif e.is_a?(Sketchup;;Face) fa=tl_grp.entities.add_face(e.outer_loop.vertices) else ### is it ever going to be something else ? end }
Then when it's all 'cloned' into the new container you can use
ents.erase_entities(tl_a)
to remove the originals.
This geometry 'cloning' method should work with the simple forms you show - however, be aware that the 'cloned' geometry will be 'defaulted' and so it will not have the original's material[s], layer, hidden/smooth/soft/cast_shadows/receive_shadows-states, or any attributes; also any 'holes' in the faces [i.e. face.loops other than the face.outer_loop] won't 'replicate', without a lot more convoluted code - but all of this is possible IF it's needed...Unfortunately there is no API methods to change the active_context [except stepping back out towards the model.entities], or to usefully Edit.copy/cut then paste or paste-in-place... so learn to 'clone'...
-
Thanks TIG! I thought clone might have to be the approach, glad I got confirmation before heading down that path. I got it working in my code. However, did get one annoying side effect. My code creates several nested components, and for just one of the nested components all the faces end up inside out after cloning. I fixed it for now by using face.reverse!, but wanted to check if anybody knew why SketchUp was reversing the face normals for just one nested subcomponents created by cloning. I'm guessing the reversal could be avoided if I'm cloning entities in a specific order.
-
Entering a faces edges/vertices 'in order' to add a clone into another context will determine the normal of the new_face.
But it's always possible that the original face has been reversed if you took the edges ?
So get the original_face.normal and compare it with the new_face.normal [allowing for the transformation differences!] - then if they don't match you must reverse the new_face...
Advertisement