Can't regroup an exploded ComponentInstance
-
Problem Background/Context: Here's an example gallery of what I'm working with: http://imgur.com/a/Vfhjn
I need to perform an extremely complicated set of functions on a number of ComponentInstances that only correctly work when a piece I'm working with is flat in the X-Y plane. (They are pieces of wood I'm going to cut out.) However, the components have other axes, and in order to perform the operation I have to explode the component and re-group it. I cannot quickly rewrite the process to correctly adapt to different axes. I need to use explode/group as a workaround until I have more time to rewrite everything.
Problem: I am unable to use the existing functions to correctly explode/group. I need to be able to explode the ComponentInstance, then take all of the resulting entities and put them into a group, which I will then use with the functions I've written and delete the whole thing when I'm done.
Here's a sample of what happens if I have a single ComponentInstance selected and try to perform the operation in the command line (trimming irrelevant output).
ci = Sketchup.active_model.selection[0] #<Sketchup::ComponentInstance:0xbc75758> ents = ci.explode g = Sketchup.active_model.entities.add_group(ents) Error: #<ArgumentError: (eval):0:in
add_group': All Entities must have a common parent>`However, I can verify that all of the exploded entities do indeed have the correct parent:
parents = {} ents.each {|ent| p = ent.parent; parents[p] = 0 unless parents.keys.include?(p); parents[p] += 1} puts parents #<Sketchup::Model:0xbca10d8>5711
That means that of 5711 entities, all of them share a parent, but I can't get it to regroup correctly.
The problem gets worse if I actually try to do the above within my plugin instead of just the command line: not only can I not group them because they "don't all share a parent", but if I check the parent immediately after exploding, it is not showing that the parent is a Model object; the parent of the exploded entities is the ComponentDefinition!
So, I'm completely stuck. I'd have to rewrite a significant bit of my code to hack it to work with just open ungrouped faces, and that would completely destroy my future plans at scaling up the capabilities of the code to work with ComponentInstances and more complicated objects. Any suggestions on how I get this particular function to work?
-
Here is what I'm trying to do in the plugin itself:
Sketchup.active_model.start_operation "Gcode Clones" selection.each do |s| if s.class == Sketchup::ComponentInstance then temp_instance = Sketchup.active_model.entities.add_instance(s.definition,s.transformation) loose_entities = temp_instance.explode parent = loose_entities[0].parent new_group = parent.entities.add_group(loose_entities) @workpiece_groups << new_group @workpieces << Workpiece.new(@environment,new_group) end end Sketchup.active_model.commit_operation
Workpiece accepts a group and does all of my complicated logic.
[edit:] Since that formatting is incredibly hard to read, here's pretty formatting of that snippet: http://i.imgur.com/Zuf2dGf.png
-
not about your plugin… you can use a code block in you posts for better formatting
Sketchup.active_model.start_operation "Gcode Clones" selection.each do |s| if s.class == Sketchup;;ComponentInstance then temp_instance = Sketchup.active_model.entities.add_instance(s.definition,s.transformation) loose_entities = temp_instance.explode parent = loose_entities[0].parent new_group = parent.entities.add_group(loose_entities) @workpiece_groups << new_group @workpieces << Workpiece.new(@environment,new_group) end end Sketchup.active_model.commit_operation
john
-
Could you upload a component that is giving this error for us to play with?
When you explode groups/components, sometimes you get a bunch of unexpected things back. So it might require poking around to see what is being returned.
-
Quick example, if you explode the "Derrick" component that is used in some of the templates, these are the classes of objects that you get back form him:
Sketchup::AttributeDictionaries
Sketchup::AttributeDictionary
Sketchup::ComponentInstance
Sketchup::Curve
Sketchup::Edge
Sketchup::EdgeUse
Sketchup::Face
Sketchup::Loop
Sketchup::VertexMany of those are not entities that can be added to a group. So try being careful to just add edges, faces, construction geometry, instances, groups, and....anything else?
-
Agh. Does that mean that in order to re-group the exploded ComponentInstance, I've got to pull construction information from every single bit of geometry and completely re-add them using the .add_face, .add_curve, etc. functions? That's quite a headache--are you sure there's no other way to drop them in?
The problem occurs on every single ComponentInstance; I can make a component out of two lines, and the same errors occur from the code I posted above.
I'm currently working on a workaround for now, but it would still be very useful to know how to quickly re-group; currently my workaround consists of exploding the clone and storing all of the exploded entities indefinitely until the logic is complete, then executing a cleanup routine afterward. The only problem with this approach is that I'm holding 50,000+ entities in some variables and calling .erase! on them after the whole thing is done is locking up the client for two minutes while Sketchup processes thousands of .erase! calls.
-
Hmm, I know its doable. Can you group the entities inside the group first, and then explode the outer group? Does that do what you need?
-
A shorter version could be:
a=(Sketchup.active_model.selection[0].explode.find_all{|e|e if e.respond_to?(:bounds)}).uniq
Then later you can regroup the arraya
...
Sketchup.active_model.entities.add_group(a)
BUT remember that you must have the selection in the active model and the new group in the same entities collect - or else it will splat!
Also there is a risk that some of the entities ina
might be erased in the meantime - all depending on what you are doing... To protect you for this trip-hazard try something like this:
a=a.dup.find_all{|e|e.valid?}
before making the new group... -
Thank you both! I'm working on the code more later tonight, I'll try implementing that. It sounds like exactly what I was after.
-
This snippet works for me, and I think its fairly safe? (We'll let one of the other Ruby folk weigh in on that if they feel they need to ).
random_classes = [] ents_to_regroup = [] a = Sketchup.active_model.selection[0].explode a.each do |e| random_classes << e.class end random_classes.uniq! random_classes.each do |e| single_class_objects = a.grep(e) if single_class_objects[0].respond_to?(;bounds) then ents_to_regroup << single_class_objects end end ents_to_regroup.flatten! Sketchup.active_model.entities.add_group(ents_to_regroup)
This will take the selected component and explode it. It then looks at the class of every object that was returned and decides if that class can be added to a group by testing to see if an object from that class responds to the bounds method, (which is in the Drawingelement class and inherited by all valid SU geometry entities). So if an object from the given class does respond to the bounds method, then it is safe to try to add those objects back into a group. If they do not respond to that method, then they get skipped.
Hopefully the logic makes sense. That snippet worked fine for me. You do have to have an object selected to test that piece of code.
Chris
Advertisement