Help with Components
-
Try iterating through all the entities that are returned in the "explosion". And make an array of all entities that are groups, comp_instances, and edges and faces. And you will need to check the parent of each of these to verify it is the same as the current level of editing. I think you should be able to tell if you are iterating over a face that is not grouped vs. one that is actually a part of an instance. Then if a face or edge or group or whatever does have a different parent than the current level, then you would obviously not want to add it to your final array of entities. So this would effectively weed out all entities that are being listed, even though they are inside an sub-component.
See if you can get that code up and running,
Chris
-
Chris, I have filtered out everything, and visually checked the parent of each entity. All have the model as their parent, but the error still persist.
The entities takes the form of #Sketchup::Face:0xe4d85c8, etc. A previous error messages made reference to requiring the form as Sketchup::Entity, and I wondered if I had to edit out "<#", and ">" from the variable. I tried to use v1.chop, but that failed, and the compiler reported that it was a "private" method. In any case, do I need to edit the form the array takes?
-
@honoluludesktop said:
Chris, I have filtered out everything, and visually checked the parent of each entity. All have the model as their parent, but the error still persist.
The entities takes the form of #Sketchup::Face:0xe4d85c8, etc. A previous error messages made reference to requiring the form as Sketchup::Entity, and I wondered if I had to edit out "<#", and ">" from the variable. I tried to use v1.chop, but that failed, and the compiler reported that it was a "private" method. In any case, do I need to edit the form the array takes?
No - not need to edit out <# and >. This is just what the string
Entity.to_sorEntity.inspectmethod outputs. It's automatically called when youputs entityto the console.What would help is if you posted more of the script so we can see the how it's working. Much easier than guessing.
-
I basically tried it two ways:
if comp.is_a? Sketchup;;ComponentInstance if @sel == "yes" comp.definition.entities.each do |subcomp| ###if entity is a sub componant if subcomp.is_a? Sketchup;;ComponentInstance comp_entities = [] comp_entities = comp.definition.entities #do stuff with entities here my_group = entities.add_group(comp_entities) #my_comp = my_group.to_component #my_comp.name= my_comp_name end end
andif comp.is_a? Sketchup;;ComponentInstance if @sel == "yes" comp.definition.entities.each do |subcomp| ###if entity is a sub componant if subcomp.is_a? Sketchup;;ComponentInstance comp_entities = comp.explode #do stuff here comp_entities.each do |filter| if filter.to_s.split(';0x').first != "#<Sketchup;;Loop" and filter.to_s.split(';0x').first != "#<Sketchup;;EdgeUse" and filter.to_s.split(';0x').first != "#<Sketchup;;AttributeDictionary" and filter.to_s.split(';0x').first != "#<Sketchup;;AttributeDictionaries" comp_ok_entities.push filter end end my_group = entities.add_group(comp_ok_entities) #my_comp = my_group.to_component #my_comp.name= my_comp_name end end -
Instead of adding the entities to a new group and converting it back to a component, make the component unique. http://code.google.com/apis/sketchup/docs/ourdoc/componentinstance.html#make_unique
(note, the API says it returntrue/false, but it really returns a newComponentInstance.)if comp.is_a? Sketchup;;ComponentInstance if @sel == "yes" comp.definition.entities.each do |subcomp| ###if entity is a sub componant if subcomp.is_a? Sketchup;;ComponentInstance my_comp = subcomp.make_unique comp_entities = my_comp.definition.entities #do stuff with entities here end end -
Understood, however my problem came about because I was having difficulty understanding transformations of individual ComponentInstance.definition.entities, and was only able to do it after exploding the component. Which brought me back to returning it into a component form. I assume that I can not return to the original definition (some component entities have been relocated), so I was trying to create a new component.
When I do the following with a component selection that has no sub-components:
comp_entities = [] selection.each do |g| if g.is_a? Sketchup;;ComponentInstance comp_entities = g.definition.entities #do stuff here my_group = entities.add_group(comp_entities) end endI get (eval):10:in βadd_groupβ: wrong argument type (expected Sketchup::Entity). When I add after #do stuff here
comp_entities.each do |f| puts f.parent endPuts echo's #Sketchup::ComponentDefinition:0xe4ba1a8 for each entity to the display, demonstrating that the entities have the same parent. So what is a "wrong argument type" for my_group = entities.add_group(comp_entities)?
-
Are you doing anything to the
comp_entitiesvariable?if you add right before your
add_groupadebug = comp_entities.to_a.select { |e| !e.is_a?(Sketchup;;Entity) } adebug.inspectWhat does it output? That snippet should return an array of everything in that collection which isn't inherited from
Sketchup::Entity. -
At this time, I am not doing anything, just trying to group the array of entities. Once I figure how to do that, I will place my procedure (rotates one of the entities) in the if-end "block" (is that the right word?).
-
In your snippet there, the variable
comp_entitiesis pointing to an entities object. That is not what.add_groupis expecting. That is what the error is..add_groupis expecting a single entitiy OR an array of entities. So just change the loine to this and see if it works:my_group = entities.add_group(comp_entities.to_a)I just added a
.to_ato turn the entities object into an actual aray. Now it should work, I think.Chris
-
ok, and I just got onto a machine with SU on it. I tested what happens if I explode a group and then try to add the entities returned in the explosion to a group. And I got the error about adding entities with the same parent. So far so good.
I found that exploding the component instance does not return the inner geometry of each sub-component like I thought it might be doing. So there really is no need to test the parent of each entity. It is just a matter of making an array of only the parts you want.
So I exploded the component instance, and I then made an array of just faces, edges, groups and componentinstances. And then added that array to a new group and it worked just fine. Here is what that code looks like:
model = Sketchup.active_model ents = model.active_entities explode_array = model.selection[0].explode good_ents = [] explode_array.each do |e| good_ents << e if e.is_a? Sketchup;;Face good_ents << e if e.is_a? Sketchup;;Edge good_ents << e if e.is_a? Sketchup;;Group good_ents << e if e.is_a? Sketchup;;ComponentInstance end ents.add_group( good_ents )And that works from the web console with a single component Instance selected, and it can have sub components and sub groups (but not sub-images since I didn't test for those.
Anyhow, I hope it helps. But in the end I think you might be better off approaching this entirely differently.
Chris
-
If you are rotating (or tranforming) everything inside a componentinstance, apply your tranformation to all the entities by using
Entities.transform_entitieshttp://code.google.com/apis/sketchup/docs/ourdoc/entities.html#transform_entitiesChris, that snippet can be made easier if you check for inheritance from the Drawingelements instead of individual classes.
model = Sketchup.active_model ents = model.active_entities explode_array = model.selection[0].explode good_ents = explode_array.select { |e| e.is_a?(Sketchup;;Drawingelement) } ents.add_group( good_ents ) -
Thanks, Guys. Not able to get back to this tonight, will try tomorrow night.
-
I like that Thom. I've also seen you use "select" a few times recently. I'll try to look at it, but is it different than collect? I recently ran across that one, and I never rememeber to use it. But they both appear to do about the same thing, and are remarkably useful for populating an array.
Chris
-
@chris fullmer said:
I like that Thom. I've also seen you use "select" a few times recently. I'll try to look at it, but is it different than collect? I recently ran across that one, and I never rememeber to use it. But they both appear to do about the same thing, and are remarkably useful for populating an array.
Chris
They are not the same.
Enumerable.collect(aliasEnumerable.map)arr = [0, 1, 2, 3, 4] arr.collect { |i| i * 2 }
returns:[0, 2, 4, 6, 8]
I use it for instance to collect Point3ds from vertices collections.
points = face.vertices.collect { |vertex| vertex.position }Enumerable.select(aliasEnumerable.find_all)
arr = [0, 1, 2, 3, 4] arr.select { |i| i%2 > 0 } # block returns true if i is an odd number
returns:[1, 3]I recently noticed this:
Enumerable.partition
arr = [0, 1, 2, 3, 4] arr.partition { |i| i%2 > 0 } # block returns true if i is and odd number
returns:[[1, 3], [0, 2, 4]]Also rather handy.
The
Enumerablemodule, which theArrayclass includes, has a number of very nice methods which I've found do many of the things I often do with arrays. I just haven't noticed them, partly because not everything in the Enumerable module isn't listed in the Array class docs.model.selection.all? { |e| e.is_a?(Sketchup::Edge) }or
[ruby:af7phbud]model.selection.any? { |e| e.is_a?(Sketchup::Edge) }[/ruby:af7phbud]
-
Wow those are great Thom. I see the difference now there with collect and select. And I really like that partition method. Not sure where I'd use it right now, but I have a feeling it might come in handy eventually.
Thanks!
Chris
-
Those five methods there has cut down many lines in my older codes.

-
Hi Guy, Finally got around to working on my program, and thanks to you it works. I have one question. How do I understand the following bit of code?
comp_new = comp_entities.select do |e| e.is_a?(Sketchup;;Drawingelement) endSorry for the long-hand, but it helps me to read my code, perhaps when I get better:-}
-
your variable name is a bit confusing. "comp_entities" is the resulting array from
.explode? Assuming it is:"comp_new" sounds like it's a ComponentInstance or ComponentDefinition, but in this case it will be a collection of entities.
Example of
.select:arr1.selectwill return a new array will all the elements ofarr1when the block returnstrue.In your case, you have an array returned from
.explode. That array contains lots of thing you don't want. But the common denominator for the items you do want is that they inherit from theDrawingElementclass. So we use the.selectmethod to extract only the items that inherits from that classe.is_a?(Sketchup::Drawingelement). -
Yes.
When you see in the API manual, for the
Faceclass for example: http://code.google.com/intl/nb/apis/sketchup/docs/ourdoc/face.html
Notice it says: Parent: DrawingelementAnd the
Drawingelementclass says Parent: EntityAnd the
Loopclass: Parent: EntitySo a Face
.is_a?(Sketchup::Face)==true
.is_a?(Sketchup::Drawingelement)==true
.is_a?(Sketchup::Entity)==trueBut a Loop
.is_a?(Sketchup::Loop)==true
.is_a?(Sketchup::Drawingelement)==false<- Notice
.is_a?(Sketchup::Entity)==trueBecause the relationship of a
Faceis:
Sketchup::Face<Sketchup::Drawingelement<Sketchup::Entity<ObjectWhile a
Loopis:
Sketchup::Loop<Sketchup::Entity<Object -
The Object Diagram is a nice graphical overview of the classes relationships: http://code.google.com/intl/nb/apis/sketchup/docs/diagram.html
Advertisement