sketchucation logo sketchucation
    • Login
    ℹ️ Licensed Extensions | FredoBatch, ElevationProfile, FredoSketch, LayOps, MatSim and Pic2Shape will require license from Sept 1st More Info

    Help needed in traversing the Model

    Scheduled Pinned Locked Moved Developers' Forum
    15 Posts 5 Posters 370 Views 5 Watching
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • RichMorinR Offline
      RichMorin
      last edited by

      Executive Summary

      I need some help in traversing the Model, because I'm getting some
      results that I don't understand.

      Background

      My PF_Model class does a recursive treewalk through SketchUp's Model API,
      harvesting information on component definitions and instances, etc. The
      result is a data structure that I can index into to find components, etc.

      The shipping version of Product Connect pays no attention to the "visible?"
      status of either a component or the layer it resides in. This violates the
      Principle of Least Astonishment for modelers, who expect invisible portions
      of the current Model to be ignored pretty universally.

      So, I'm trying to add some code that will cause PF_Model to ignore anything
      within invisible component instances (whether hidden explicitly or residing
      on a hidden layer). However, in working on this, I got confusing results.

      Test Setup

      I have two Models, each of which contains three instances of a KraftMaid
      "Base Single Door" cabinet. In each Model:

      • One instance is visible.
      • One instance is explicitly hidden.
      • One instance is on an invisible layer.

      In one Model (KMc_s), three cabinet instances share the same definition.
      That is, I simply copied the cabinet and pasted it twice, then hid one
      copy and put the other on a hidden layer.

      In the other Model (KMc_u), each cabinet instance has a unique definition.
      That is, I did a Make Unique on each copied cabinet before hiding it, etc.

      Problem

      I'm seeing quite different behavior in the two Models and I'm not quite sure
      what is going on. The KMc_s (shared) Model gives me the following results:

      • It finds three entities of type ComponentInstance (ie, instances
        of the cabinet), only one of which is visible.

      • Looking in the cabinet component definition's entities (cd.entities)
        for objects of type ComponentInstance, it finds one visible instance
        of the drawer sub-component.

      The KMc_u (unique) Model, in contrast, gives me the following results:

      • It finds three top-level components (unique instances of the cabinet),
        only one of which is visible. In each one of the three, however, it
        finds three visible instances of the drawer.

      Analysis

      I suspect that there's a better way to traverse the model, if only because
      I shouldn't be finding three instances of the drawer sub-component in each
      unique instance of the cabinet. Suggestions?

      Failing that, I'd like to know why I'm seeing three visible instances of
      the drawer and (more to the point) how to tell them apart, etc.

      1 Reply Last reply Reply Quote 0
      • jolranJ Offline
        jolran
        last edited by

        Hi Rich!

        I think it might be difficult for anyone to help you if you don't post some code.
        (having a little hard time following your post)

        Sounds like the instances failed being unique ?

        OT: what happend to your excellent post on your blogg regarding dynamic component scripting explorations ?
        I cannot find it anymore. It was most intresting.

        1 Reply Last reply Reply Quote 0
        • RichMorinR Offline
          RichMorin
          last edited by

          @jolran said:

          I think it might be difficult for anyone to help you if you don't post some code.
          (having a little hard time following your post)

          Sounds like the instances failed being unique ?

          Problem is, this code is in the middle of a few thousand lines of framework code.
          However, I'll think about how I might extract a cut-down example.

          @jolran said:

          OT: what happened to your excellent post on your blog
          regarding dynamic component scripting explorations?
          I cannot find it anymore. It was most intresting.

          I don't recall writing a blog entry, but I have several pages in my wiki on the topic.
          Please take a look at http://wiki.cfcl.com/bin/view/SketchUp/Cookbook/DA

          -r

          1 Reply Last reply Reply Quote 0
          • Dan RathbunD Offline
            Dan Rathbun
            last edited by

            @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.

            I'm not here much anymore.

            1 Reply Last reply Reply Quote 0
            • jolranJ Offline
              jolran
              last edited by

              @unknownuser said:

              Problem is, this code is in the middle of a few thousand lines of framework code.

              Yeah, I understand.

              @unknownuser said:

              Please take a look at http://wiki.cfcl.com/bin/view/SketchUp/Cookbook/DA

              That's it! I was looking in the wrong place.
              Thank you.

              Sorry I couldent be more of assistance solving your problem.
              Hope Dan's suggestion will work for you.

              1 Reply Last reply Reply Quote 0
              • thomthomT Offline
                thomthom
                last edited by

                @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?

                Thomas Thomassen — SketchUp Monkey & Coding addict
                List of my plugins and link to the CookieWare fund

                1 Reply Last reply Reply Quote 0
                • TIGT Offline
                  TIG Moderator
                  last edited by

                  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 != model

                  do 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 @ 2

                  when 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 >> 2

                  Where 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

                  TIG

                  1 Reply Last reply Reply Quote 0
                  • RichMorinR Offline
                    RichMorin
                    last edited by

                    Thanks, all, that gives me quite a bit to chew on.

                    -r

                    1 Reply Last reply Reply Quote 0
                    • thomthomT Offline
                      thomthom
                      last edited by

                      TIG, isn't that a big convoluted when a simple tree traversal does the trick?

                      Thomas Thomassen — SketchUp Monkey & Coding addict
                      List of my plugins and link to the CookieWare fund

                      1 Reply Last reply Reply Quote 0
                      • TIGT Offline
                        TIG Moderator
                        last edited by

                        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

                        TIG

                        1 Reply Last reply Reply Quote 0
                        • thomthomT Offline
                          thomthom
                          last edited by

                          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.

                          Thomas Thomassen — SketchUp Monkey & Coding addict
                          List of my plugins and link to the CookieWare fund

                          1 Reply Last reply Reply Quote 0
                          • TIGT Offline
                            TIG Moderator
                            last edited by

                            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*** ==end

                            or 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...

                            TIG

                            1 Reply Last reply Reply Quote 0
                            • thomthomT Offline
                              thomthom
                              last edited by

                              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>
                              

                              2013-05-30_11h20_57.png

                              
                              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>
                              
                              

                              TraverseVisible.skp

                              Thomas Thomassen — SketchUp Monkey & Coding addict
                              List of my plugins and link to the CookieWare fund

                              1 Reply Last reply Reply Quote 0
                              • TIGT Offline
                                TIG Moderator
                                last edited by

                                ☀ OK... IF he only wants 'visible' 'containers' reported.

                                I suppose as well as Walk.visible(), a separate Walk.hidden() and a Walk.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...

                                TIG

                                1 Reply Last reply Reply Quote 0
                                • thomthomT Offline
                                  thomthom
                                  last edited by

                                  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.

                                  Thomas Thomassen — SketchUp Monkey & Coding addict
                                  List of my plugins and link to the CookieWare fund

                                  1 Reply Last reply Reply Quote 0
                                  • 1 / 1
                                  • First post
                                    Last post
                                  Buy SketchPlus
                                  Buy SUbD
                                  Buy WrapR
                                  Buy eBook
                                  Buy Modelur
                                  Buy Vertex Tools
                                  Buy SketchCuisine
                                  Buy FormFonts

                                  Advertisement