Help needed in traversing the Model
-
@dan rathbun said:
@richmorin said:
I suspect that there's a better way to traverse the model, ... Suggestions?
Whenever possible... directly traverse the model's DefintionList collection, and it's member's instances collections.
Problem is - in order to know if an instance if hidden you need to know if its parent nesting is hidden or not. You need to do a tree traversal for this.
Rich - I'm not sure why you are seeing this. But my CleanUp plugin also traverses the model looking for hidden entities - with the option of removing everything hidden. That works fine. So it appear that there's a bug in your code somewhere. So it's hard to make suggestions on the generic level when the problem is a specific one.
Are you able to reproduce it in a small test case?
-
I gave my answer elsewhere
@unknownuser said:
I assume you meant that there is one instance of each of the 'unique cabinets',
and only one of these is 'visible'...
but here are three instances of the 'drawer',
and all of them are visible.
This is correct.In each of the three cabinet definitions there is a visible drawer.
It is on a visible layer and not hidden - therefore it reports as 'visible'.
The fact that an instance of the definition that contains it is NOT visible is irrelevant to the correctness of this result.However, to get a 'proper' result...
Here's what I'd do...Iterate through all of the model.definitions, skipping those that are .image?
Set up an hash for each definition by name, and then hashes for all of its definition.instances
Set a 'hidden' flag 0=visible, 1=hidden and 2=hidden-layer for each instance.
For each instance we then use instance.parent and find its container's 'type':
If it's model then the flag is as it is set and we have done with that instance.
If it's container is a definition then check:***
if .group? then
find group.entities.definition.instances and iterate through those [there might be more than the expected one!]
else # it's a component
find container.instances and iterate through those
find each instance's 'hidden' flag 0/1/2
substitute the original instance's flag with that, but only if it's NOT 0 - i.e. the container is 'hidden' somehow...
***We need to repeat the 'container' checking until it becomes the model, setting the flag of the original instance if ever it >0
You can do this with:
parent=instance.parent
while parent != modeldo checks...
parent=container.parent
end
This way you can compile a list of all instances in the model and their hidden flags, with the flag adjusted by the hidden state of that instance's container, or the container's container etc up until the container is the model itself.So back with your 'uniqued' example... the 'hidden' status would now reports as:
cabinet:
1 @ 0
cabinet#1:
1 @ 1
cabinet#2:
1 @ 2
drawer:
1 @ 0
1 @ 1
1 @ 2when previously you would have got
drawer:
3 @ 0
because they ARE all 'visible' inside their container's - definition.entities
but the new checking regime will report their container's hidden status NOT their own hidden status...You could report the instance with its nesting and flags more clearly like this:
model:cabinet = 0:0 >> 0
model:cabinet#1 = 0:1 >> 1
model:cabinet#2 = 0:2 >> 2
and
model:cabinet:drawer = 0:0:0 >> 0
model:cabinet#1:drawer = 0:1:0 >> 1
model:cabinet#2:drawer = 0:2:0 >> 2Where the 'hidden' status of every container/instance is shown == 0:1:2 etc and the 'worst case' status extracted, in the example >> 2
Incidentally, in the 'non-unique' version you'd get:
model:cabinet = 0:0 >> 0
model:cabinet = 0:1 >> 1
model:cabinet = 0:2 >> 2
and
model:cabinet:drawer = 0:0:0 >> 0
model:cabinet:drawer = 0:1:0 >> 1
model:cabinet:drawer = 0:2:0 >> 2 -
Thanks, all, that gives me quite a bit to chew on.
-r
-
TIG, isn't that a big convoluted when a simple tree traversal does the trick?
-
Not if he wants to know all of the 'hidden' status of all nested component instances/groups.
Having a hidden container 1/2 will report its visible contained instance as visible 0... UNLESS he does a convoluted check and then he knows that although the contained instance is visible 0, its container is hidden 1/2, therefore he doesn't want to count that contained-instance as 0, because the user can't see it since its container is 1/2 !
Because it's possible to have multiple instances of containers of status 0/1/2 with contained objects of status 0/1/2 he needs to always take the worst case ? So for three instances with different hidden status, although a contained-instance is visible it reports hidden because it's container is hidden, conversely although a container is visible a contained- instance will report hidden IOF it is itself hidden...
container = 0 >> 0
container = 1 >> 1
container = 2 >> 2
and
container:contained = 0:0 >> 0
container:contained = 1:0 >> 1
container:contained = 2:0 >> 2
or
container#1 = 0 >> 0
container#1 = 1 >> 1
container#1 = 2 >> 2
and
container#1:contained = 0:0 >> 0
container#1:contained = 1:0 >> 1
container#1:contained = 2:0 >> 2
or for different statuses of the contained instance
container#1:contained = 0:0 >> 0
container#1:contained = 0:1 >> 1
container#1:contained = 0:2 >> 2 -
But if you traverse the tree structure you can easily inherit the hidden property of the container once as you crawl the hierarchy. No need to hashes or backtracing the parents.
-
BUT he doesn't want the hidden status of the container.
He wants the hidden status of the container OR the hidden status of the contained if it's NOT 0 ?container = 0 >> 0 ==dig deeper
container:contained = 0:0 >> 0 ==end
or
container = 1 >> 1 ==break
[container:contained = 1:0 >> 1 ==not needed as we already have '1']BUT
container = 0 >> 0 ==dig deeper
container:contained = 0:1 >> 1*** ==end
or
container = 1 >> 1 ==break
[container:contained = 1:1 >> 1 ==not needed as we already have '1']AND
container = 0 >> 0 ==dig deeper
container:contained = 0:1 >> 1*** ==endor for deeper nestings...
container = 0 >> 0 ==dig deeper
container:contained_container = 0:1 >> 1*** ==break
[container:contained_container:contained = 0:1:0 >> 1*** ==not needed as we already have '1']
or
container = 0 >> 0 ==dig deeper
container:contained_container = 0:0 >> 0 ==dig deeper
container:contained_container:contained = 0:0:1 >> 1*** ==end***NOT the container's status of 0, which is what you'd get by just taking the container's status ??
So any status != 0 in the 'upward direction' of the tree 'container:contained_container:contained...' sets the status...I'm not saying he needs a hash...
It was just a way of him ordering all of the data if he wanted it... -
Now you've lost me TIG...
As far as I gathered he was having problems where his traversal would not return the correct visible entities. When you need to get all visible entities it's easiest to just traverse the tree instead of
model.definitions
.<span class="syntaxdefault"><br />module Walk<br /><br /> def self</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">visible</span><span class="syntaxkeyword">(</span><span class="syntaxdefault"> entities </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> Sketchup</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">active_model</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">entities</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> level </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> 0 </span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault"> indent </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> </span><span class="syntaxstring">' '</span><span class="syntaxdefault"> </span><span class="syntaxkeyword">*</span><span class="syntaxdefault"> level<br /> for entity in entities<br /> next unless entity</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">visible</span><span class="syntaxkeyword">?</span><span class="syntaxdefault"> </span><span class="syntaxkeyword">&&</span><span class="syntaxdefault"> entity</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">layer</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">visible</span><span class="syntaxkeyword">?<br /></span><span class="syntaxdefault"> case entity<br /> when Sketchup</span><span class="syntaxkeyword">;;</span><span class="syntaxdefault">Group<br /> puts </span><span class="syntaxstring">"#{indent}#{entity.name} - #{entity.inspect}"<br /></span><span class="syntaxdefault"> self</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">visible</span><span class="syntaxkeyword">(</span><span class="syntaxdefault"> entity</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">entities</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> level </span><span class="syntaxkeyword">+</span><span class="syntaxdefault"> 1 </span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault"> when Sketchup</span><span class="syntaxkeyword">;;</span><span class="syntaxdefault">ComponentInstance<br /> puts </span><span class="syntaxstring">"#{indent}#{entity.definition.name} - #{entity.name} - #{entity.inspect}"<br /></span><span class="syntaxdefault"> self</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">visible</span><span class="syntaxkeyword">(</span><span class="syntaxdefault"> entity</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">definition</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">entities</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> level </span><span class="syntaxkeyword">+</span><span class="syntaxdefault"> 1 </span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault"> else<br /> </span><span class="syntaxcomment">#puts "#{indent}#{entity.inspect}"<br /></span><span class="syntaxdefault"> end<br /> end<br /> end<br /><br />end </span><span class="syntaxcomment"># module<br /></span><span class="syntaxdefault"> </span>
load 'c;/walk.rb' true Walk.visible A - - #<Sketchup;;ComponentInstance;0xb2bb7a8> B - - #<Sketchup;;ComponentInstance;0xbb563b8> C - - #<Sketchup;;ComponentInstance;0xbb52628> B - - #<Sketchup;;ComponentInstance;0xbb4fb58> C - - #<Sketchup;;ComponentInstance;0xbb52628> C - - #<Sketchup;;ComponentInstance;0xbb4f950> A - - #<Sketchup;;ComponentInstance;0xba4e40c> B - - #<Sketchup;;ComponentInstance;0xbb563b8> C - - #<Sketchup;;ComponentInstance;0xbb52628> #<Sketchup;;Entities;0xbb592d4>
-
OK... IF he only wants 'visible' 'containers' reported.
I suppose as well as
Walk.visible()
, a separateWalk.hidden()
and aWalk.layeroff()
could be used to collect that data too if needed ?Of course, instead of your
puts
he'd be collecting the items into a hash for use in his other code... -
Yes, it'd be trivial to collect hidden entities or collect stats. But the point being is that the code is compact and easy when you traverse like that instead of walking model.definitions which would require backtracing.
Advertisement