sketchucation logo sketchucation
    • 登入
    Oops, your profile's looking a bit empty! To help us tailor your experience, please fill in key details like your SketchUp version, skill level, operating system, and more. Update and save your info on your profile page today!
    🔌 Smart Spline | Fluid way to handle splines for furniture design and complex structures. Download

    Find the global position of a Vertex in a Group/Component

    已排程 已置頂 已鎖定 已移動 Developers' Forum
    25 貼文 6 Posters 5.2k 瀏覽 6 Watching
    正在載入更多貼文
    • 從舊到新
    • 從新到舊
    • 最多點贊
    回覆
    • 在新貼文中回覆
    登入後回覆
    此主題已被刪除。只有擁有主題管理權限的使用者可以查看。
    • G 離線
      gbabcock
      最後由 編輯

      Being new to this, I've been searching around to find a way to get the global position of a vertex when it is in an unopened group, or even worse when it is in a nested group. I found a lot of good info in this forum, and learned that you need the Point3d of the vertex AND the Transformations of the parent Group(s) and/or Component(s). The problem is how to get the parents starting from an edge without walking the entire Group/Component/Model from the top-down.

      The SU API seems to be very top-down oriented, and it is not intuitive how you walk up the hierarchy. Assuming that this is correct?:

      HIERARCHY
      === Model
      ====== DefinitionList
      ========= ComponentDefinitions
      ============ ComponentInstances #collection of Group or Components Instances
      ============ Entities
      ============ ComponentDefinitions
      =============== ComponentInstances #collection of Group or Components Instances
      =============== Entities

      If so, then if you start with an edge (or face) in a Group/Component you can do this:

      • edge.parent #returns ComponentDefinition
      • edge.parent.instances[0] #returns first ComponentInstance of ComponentDefinition, a Group or Component
      • edge.parent.instances[0].parent #returns the next level ComponentDefinition or the Model
        Now you have the hierarchy of Groups/Components, and can easily access their Transformations!

      I've been messing around with this for the SketchyFFD and Position_Explorer plugins, but didn't come across this solution, so I thought I would post it for the group's opinion and/or entertainment 😉.

      #call with ent=a face or an edge
      #returns an array of Point3d objects that equal the global position of the vertices	
      #currently only gets the first ComponentInstance, works for Group, but Components may have many instances
      def getGlobalPosition(ent) 
      	g_pos=[] #array to store global positions of vertices
      
      	#get local position of vertices
      	ent.vertices.each_with_index{|vert,i|
      		g_pos[i]=vert.position
      	}
      
      	#get the parent
      	p=ent.parent
      
      	#while the parent is a group or component
      	while p.is_a? Sketchup;;ComponentDefinition
      		#get the group/component transformation
      		grp=p.instances[0]
      		grp_t=grp.transformation
      
      		#apply the group transformation to the stored position of the vertices
      		g_pos.each{|g|
      			g=g.transform! grp_t
      		}
      		
      		#get the next parent in the hierarchy
      		p=p.instances[0].parent
      	end	
      	return g_pos
      end
      

      Make sense?

      This performs reasonably well, does anyone know a faster way?

      Thanks,
      Glenn

      Glenn

      1 條回覆 最後回覆 回覆 引用 0
      • J 離線
        jessejames
        最後由 編輯

        @gbabcock said:

        Being new to this, I've been searching around to find a way to get the global position of a vertex when it is in an unopened group, or even worse when it is in a nested group.

        Lets make this simpler and use the term "collection" to refer to both groups and components. There is no difference in finding the "world coordinate" of a vertex contained in a collection whether or not the "collection" is "open" or "closed". If it's nested yes, but only a minor difference in the form of recursion.

        @gbabcock said:

        I found a lot of good info in this forum, and learned that you need the Point3d of the vertex AND the Transformations of the parent Group(s) and/or Component(s). The problem is how to get the parents starting from an edge without walking the entire Group/Component/Model from the top-down.

        You specifically need the "collections" origin which is a point and the point you wish to find. You see whenever a "collection" is created the origin of that "Collection" is equal to the minX, mixY and minZ "parent coordinates" of the bounding box of that collection. You can easily query this origin at any time by using...

        Tim Toady's first method

        collection.transformation.origin
        

        Tim Toady's second method

        collection.transformation.to_a[-1]
        

        ...since a transformation is just a four element array containing the [[Xaxis], [Yaxis], [Zaxis], [origin]] sub arrays.

        @gbabcock said:

        The SU API seems to be very top-down oriented, and it is not intuitive how you walk up the hierarchy. Assuming that this is correct?:

        HIERARCHY
        === Model
        ====== DefinitionList
        ========= ComponentDefinitions
        ============ ComponentInstances #collection of Group or Components Instances
        ============ Entities
        ============ ComponentDefinitions
        =============== ComponentInstances #collection of Group or Components Instances
        =============== Entities

        No thats completely wrong. The definition list is an attribute of MODEL just like ENTITIES is an attribute. If you where to map out a simplistic version of the API it might look like this...

        [warning: loose code ahead!]

        
        class Model(collection)
          self.definitionList = {def1, def2, ..., defN}
          self.entities = {ent1, ent2, ..., entN} # infinite nesting here!
          # lots more stuff here...
        end
        
        class Group
          self.entities = {ent1, ent2, ..., entN} # infinite nesting here!
          # more stuff
        end
        
        class ComponentInstance
          self.entities = {ent1, ent2, ..., entN} # infinite nesting here!
          # more stuff
        end
        
        model = Model()
        model.entites.push(Group())
        model.entites.push(....)
        ....
        
        

        (of course at the C level it's much different!) Model is just a top level "collection" like groups or components. You add all edges, faces, groups, components to the Model entities. and then you can nest infinitely (or until you run out of memory!) the collections in model.entities

        (I'll probably be lambasted for making such a simplistic model 😕, oh well!

        Anyhow just remember a vertex inside a collection has a position relative to the collections origin. So as an example... if vertexA is an entity contained in groupA which is a collection contained in the model.entities array then...

        @unknownuser said:

        if vertexA is at [0,0,1] and groupA's origin at [0,0,1] then the world space coordinates of vertexA will be at [0,0,2]

        PS There may be those of you who are wondering who Tim Toady is. Tim Toady is a pronunciation of the acronym TMTOWTDI (or TIMTOWTDI). Basically it describes a paradigm you new Ruby scripters will need to get acquainted with ...More info can be found here.

        PPS hopefully i have managed to shed some light on your dilemma and not simply confused you even more. I would like to go into more details at this time but "crikey" i need some sleep!

        Always sleep with a loaded gun under your pillow!

        1 條回覆 最後回覆 回覆 引用 0
        • thomthomT 離線
          thomthom
          最後由 編輯

          @jessejames said:

          There is no difference in finding the "world coordinate" of a vertex contained in a collection whether or not the "collection" is "open" or "closed". If it's nested yes, but only a minor difference in the form of recursion.

          SU changes the co-ordiates when you open a group/component. When a group or component is open SU returns global co-ordinates for the entities in that context.

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

          1 條回覆 最後回覆 回覆 引用 0
          • thomthomT 離線
            thomthom
            最後由 編輯

            @gbabcock said:

            The problem is how to get the parents starting from an edge without walking the entire Group/Component/Model from the top-down.

            The only time you can avoid that is if you're making a Tool using the PickHelper to pick out the entity. PickHelper also return the path to that entity.

            But if you're not making a point and click tool - then the only way is to traverse the entire model. It's one of the major complaints about the SketchUp API.

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

            1 條回覆 最後回覆 回覆 引用 0
            • G 離線
              gbabcock
              最後由 編輯

              jessejames, thats not quite what I was after, but thanks for the post!

              thomthom, thanks for the feedback. I'll check out PickHelper in any case, sounds interesting.

              BTW, the code snippet I posted does work, I was testing it last night, and it doesn't traverse the model. The only caveat was that I had to use group.make_unique on copies of groups due to the bug discussed on this forum.

              Glenn

              Glenn

              1 條回覆 最後回覆 回覆 引用 0
              • thomthomT 離線
                thomthom
                最後由 編輯

                @gbabcock said:

                BTW, the code snippet I posted does work, I was testing it last night, and it doesn't traverse the model.

                What was your testcase? With group or components? Did you try with scaled instances as well?

                @gbabcock said:

                The only caveat was that I had to use group.make_unique on copies of groups due to the bug discussed on this forum.

                Which one was that? Getting the correct parent for a group?
                http://forums.sketchucation.com/viewtopic.php?f=180&t=19765

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

                1 條回覆 最後回覆 回覆 引用 0
                • thomthomT 離線
                  thomthom
                  最後由 編輯

                  I'd avoid making groups unique. I some times get models made by others where groups have been used as components. Provided the groups have not been made unique I can still recover them, by using Selection Toys.

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

                  1 條回覆 最後回覆 回覆 引用 0
                  • G 離線
                    gbabcock
                    最後由 編輯

                    @thomthom said:

                    What was your testcase? With group or components? Did you try with scaled instances as well?

                    I tested Groups, nested Groups, scaled Groups, rotated Groups, translated Groups, Group copies, Components (single only). Works for all of them.

                    I've updated my Position Explorer tool, see attached. I'll post the update in the Plugins forum.

                    @thomthom said:

                    Which one was that?

                    http://forums.sketchucation.com/viewtopic.php?f=180&t=14062&p=105782

                    Glenn


                    Position Explorer 13 Feb 2010

                    Glenn

                    1 條回覆 最後回覆 回覆 引用 0
                    • G 離線
                      gbabcock
                      最後由 編輯

                      @thomthom said:

                      I'd avoid making groups unique. I some times get models made by others where groups have been used as components. Provided the groups have not been made unique I can still recover them, by using Selection Toys.

                      So how do I work around the bug? If I make a copy of a group and immediately try to get it's position I get the original's transformation.

                      Glenn

                      Glenn

                      1 條回覆 最後回覆 回覆 引用 0
                      • thomthomT 離線
                        thomthom
                        最後由 編輯

                        @unknownuser said:

                        #returns an array of Point3d objects that equal the global position of the vertices in an edge
                        #currently only gets the first parent instance, components may have many instances

                        You're not dealing with components with many instances? You only pick the first instance?

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

                        1 條回覆 最後回覆 回覆 引用 0
                        • G 離線
                          gbabcock
                          最後由 編輯

                          @thomthom said:

                          You're not dealing with components with many instances? You only pick the first instance?

                          I am, I just haven't gotten that far with the tool yet!

                          Glenn

                          1 條回覆 最後回覆 回覆 引用 0
                          • thomthomT 離線
                            thomthom
                            最後由 編輯

                            @gbabcock said:

                            @thomthom said:

                            You're not dealing with components with many instances? You only pick the first instance?

                            I am, I just haven't gotten that far with the tool yet!

                            Well, that is a key major problem. Getting the correct instance. It's why traversing the parent won't work, as you only get the definition, but no way of getting the right instance.
                            If you make components work, then you make groups with group copies work. They are the same thing under the hood.

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

                            1 條回覆 最後回覆 回覆 引用 0
                            • G 離線
                              gbabcock
                              最後由 編輯

                              Thanks, that's helpful. I'll play around with that.

                              Glenn

                              1 條回覆 最後回覆 回覆 引用 0
                              • G 離線
                                gbabcock
                                最後由 編輯

                                @thomthom said:

                                Well, that is a key major problem. Getting the correct instance...

                                OK, I see now. It's not a true hierarchy, since an element (vertex, face, edge, etc.) can be in more than one instance. Parent only gets you the Definition, with no way to get the correct Instance, as you said.

                                Thanks for helping me understand!

                                Glenn

                                1 條回覆 最後回覆 回覆 引用 0
                                • thomthomT 離線
                                  thomthom
                                  最後由 編輯

                                  Only way is to map the whole model, going from Model and up. Which is just a brute force way to do it. 😕

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

                                  1 條回覆 最後回覆 回覆 引用 0
                                  • J 離線
                                    jessejames
                                    最後由 編輯

                                    @thomthom said:

                                    SU changes the co-ordiates when you open a group/component. When a group or component is open SU returns global co-ordinates for the entities in that context.

                                    It seems Tim Toady is more prevalent that i had originally feared! 😮

                                    PS: Before some hot shot notices i made a mistake in accessing the origin using

                                    collection..transformation[-1]
                                    

                                    Since the transformation is a 16 element array an NOT a 4 element array of 4 element sub arrays that code will only return the last float.

                                    Always sleep with a loaded gun under your pillow!

                                    1 條回覆 最後回覆 回覆 引用 0
                                    • AdamBA 離線
                                      AdamB
                                      最後由 編輯

                                      @thomthom said:

                                      Only way is to map the whole model, going from Model and up. Which is just a brute force way to do it. 😕

                                      Not really true. Its certainly non-trivial but LightUp does it 😄. ie LightUp needs to find the transform of every instance of a Component called PointLightSource. Clearly starting at the top and walking down is "one way" buts its incredibly inefficient. Better is to get each instance (trivial) then work your way back up concatenating transforms as you go - and dealing with the fact that there can be many instances of Components as thomthom points out. Took a fair amount of head scratching but its all in lightcache.rb if you want to take a butchers.

                                      Its invoked by list = LightCache.flat(LightCache.walk(ent, ent.transformation)) which gives you back a list of transforms.

                                      Adam

                                      Developer of LightUp Click for website

                                      1 條回覆 最後回覆 回覆 引用 0
                                      • thomthomT 離線
                                        thomthom
                                        最後由 編輯

                                        Very interesting Adam. I'm glad to be proven wrong.

                                        I will for sure poke about that code of yours. Is it ok with you if I adapt it to a generic method and add it to my generic library shared between my plugins?

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

                                        1 條回覆 最後回覆 回覆 引用 0
                                        • G 離線
                                          gbabcock
                                          最後由 編輯

                                          @adamb said:

                                          Clearly starting at the top and walking down is "one way" buts its incredibly inefficient. Better is to get each instance (trivial) then work your way back up concatenating transforms as you go - and dealing with the fact that there can be many instances of Components as thomthom points out. Adam

                                          Exactly what I'm trying to do! Thanks, Adam, I'll check this out.

                                          Glenn

                                          1 條回覆 最後回覆 回覆 引用 0
                                          • G 離線
                                            gbabcock
                                            最後由 編輯

                                            OK, I think I'm getting a clearer picture now. ❗ Let me sum it up to make sure.

                                            Since we can have multiple instances of a Group/Component, there is a One-to-Many relationship between a Vertex and Transformations:

                                            Vertex->ComponentDefinition->ComponentInstances->ComponentInstance->Transformation

                                            model.jpg
                                            Therefore, to get the global position of a Vertex you need BOTH the Vertex (which is in ComponentDefinition) AND the specific ComponentInstance you are evaluating. From there you can walk UP the hierarchy of ComponentInstances and get their Transformations to apply to the Vertex.

                                            So in Ruby we have:
                                            Sketchup.active_model #top of model
                                            Sketchup.active_model.definitions #returns DefinitionList
                                            Sketchup.active_model.definitions[n] #returns ComponentDefinition[n] from array
                                            Sketchup.active_model.definitions[n].instances[n] #returns ComponentInstance[n] from array

                                            You can get a quick picture of this in SU with:

                                            Sketchup.active_model.definitions.each {|definition| puts "#{definition} contains #{definition.instances}\n" }
                                            

                                            Glenn

                                            1 條回覆 最後回覆 回覆 引用 0
                                            • 1
                                            • 2
                                            • 2 / 2
                                            • 第一個貼文
                                              最後的貼文
                                            Buy SketchPlus
                                            Buy SUbD
                                            Buy WrapR
                                            Buy eBook
                                            Buy Modelur
                                            Buy Vertex Tools
                                            Buy SketchCuisine
                                            Buy FormFonts

                                            Advertisement