Looping all entities
-
I'm a bit puzzled.
Sketchup.active_model.entities.each{|e|e.erase! if e.valid?}
works but doesn't delete all entitiesSketchup.active_model.entities.to_a.each{|e|e.erase! if e.valid?}
works and deletes all entitiesNow, does this mean that to loop all entities in a model i always have to put them in an array first?
I never have run into any problems before using the first method.Additionaly
f=0 Sketchup.active_model.entities.each{|ent| f+=1 Sketchup.active_model.selection.clear Sketchup.active_model.selection.add ent ent.erase! } puts f
returns 4095 (on a 11200 entities model)
whilef=0 Sketchup.active_model.entities.each{|ent| f+=1 Sketchup.active_model.selection.clear Sketchup.active_model.selection.add ent #ent.erase! } puts f
returns 11200 (on a 11200 entities model)
I must be missing something essential here...
-
A few points:
- Bulk operations are much faster than single operations.
<span class="syntaxdefault">model</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">entities</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">erase_entities</span><span class="syntaxkeyword">( </span><span class="syntaxdefault">array_of_entities </span><span class="syntaxkeyword">) </span><span class="syntaxdefault"></span>
Is faster than
<span class="syntaxdefault"></span><span class="syntaxkeyword">for </span><span class="syntaxdefault">entity in array_of_entities<br /> e</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">erase</span><span class="syntaxkeyword">!<br /></span><span class="syntaxdefault">end</span>
But when you want to clear the entire Enitites collection you can just use
<span class="syntaxdefault">model</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">entities</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">clear</span><span class="syntaxkeyword">! </span><span class="syntaxdefault"></span>
- Never iterate the Entities collection directly when you modify it.
<span class="syntaxdefault"></span><span class="syntaxkeyword">for </span><span class="syntaxdefault">entity in model</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">entities<br /> e</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">erase</span><span class="syntaxkeyword">!<br /></span><span class="syntaxdefault">end</span>
This will make some entities be skipped as you are modifying the Entities object you iterate.
Instead make an array copy of the entities:
<span class="syntaxdefault"></span><span class="syntaxkeyword">for </span><span class="syntaxdefault">entity in model</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">entities</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">to_a<br /> e</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">erase</span><span class="syntaxkeyword">!<br /></span><span class="syntaxdefault">end</span>
This will not skip any entities.
Model.entities
does not contain every entity in the model - only the root of the model hierarchy. Entities in Groups and Components are stored in the definitions inmodel.defintions
.
But if you want to empty the whole model,model.entities.clear!
is still the easiest.
http://www.thomthom.net/thoughts/2012/02/definitions-and-instances-in-sketchup/
-
@pout said:
went wrong
What went wrong? Examples?
@pout said:
So I can assume that Sketchup.active_model.entities.each{|e|
...
}
can always be incorrect even when just checking for something?No, just when you modify it. If you just read states and properties there should be no problems.
@pout said:
On point 1, what would be faster
The second - using
.erase_entities
. -
ThomThom
Thanks for the fast reply!
I did the test on a single box (not a group nor instance) and even then it went wrong
So I can assume that Sketchup.active_model.entities.each{|e|
...
}
can always be incorrect even when just checking for something (eg. check if the current entity has a certain value in it's attribute dictionary)?On point 1, what would be faster
Sketchup.active_model.entities.to_a.each{|e| check=e.get_attribute'x','y' if check==1 e.erase! end }
or
test=[] Sketchup.active_model.entities.to_a.each{|e| check=e.get_attribute'x','y' if check==1 test<<e end } model.entities.erase_entities(test)
-
@thomthom said:
What went wrong? Examples?
It goes wrong caused by the fact that the entities object is edited while executing the loop. So as you stated.
@thomthom said:
No, just when you modify it. If you just read states and properties there should be no problems.
Modify (like in push pull) or only when the entity is deleted?
@thomthom said:
The second - using
.erase_entities
.In the second case I could use Sketchup.active_model.entities.each (without the to_a) Correct? And if so would that be faster then with to_a?
Thx again!
-
@pout said:
It goes wrong caused by the fact that the entities object is edited while executing the loop. So as you stated.
Yes, this is where you need to use
to_a
.@pout said:
Modify (like in push pull) or only when the entity is deleted?
Anything that adds or removed entities to the collection.
@pout said:
Correct? And if so would that be faster then with to_a?
That won't be of much difference. What makes a difference is using bulk methods that affect multiple entities in one operation over methods that affect only one entity at a time.
-
Excellent information.
Thank you ThomThom, much appreciated!
Advertisement