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

    Question about edit_transform

    Scheduled Pinned Locked Moved Developers' Forum
    11 Posts 4 Posters 1.8k Views 4 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.
    • thomthomT Offline
      thomthom
      last edited by

      The Outliner would let a user dig straight into any instance - without going through each step.

      The edit_transform is the total of the transformation for all the open instances.

      If you need into about each step in the path you can inspect model.active_path:
      http://www.sketchup.com/intl/en/developer/docs/ourdoc/model#active_path

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

      1 Reply Last reply Reply Quote 0
      • D Offline
        danmacumber
        last edited by

        Thanks ThomThom, I still don't quite see how to solve my problem. When I am editing a group, the transformation returned for each group (current group or any parent) in the active_path is identity. So if I am editing a group how can I get its parent's transformation?

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

          Ah, I see what you mean... even those transformations are being transformed when you open the groups... hm... I'd have to consult with the core team on this one.

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

          1 Reply Last reply Reply Quote 0
          • D Offline
            danmacumber
            last edited by

            Thanks ThomThom, let me know what you find out.

            Dan

            1 Reply Last reply Reply Quote 0
            • D Offline
              danmacumber
              last edited by

              Here is my best attempt to clearly illustrate my problem. Load the Ruby code attached at the bottom of this post. Run the method make_geometry, this will clean everything in your model and create two groups Group 1 and Group 2, Group 2 is nested inside of Group 1. Group 1 is translated 10 m in the X direction, Group 2 is translated 10 m in the Y direction. Run the print_geometry method from the top level, then from within Group 1, then from within Group 2. You will see this output:

              ` print_geometry
              active_path = []
              Group 1 transformation = (393.700787", 0", 0")
              Group 2 transformation = (0", 393.700787", 0")
              Edit transformation = (0", 0", 0")

              print_geometry
              active_path = [Group 1]
              Group 1 transformation = (0", 0", 0")
              Group 2 transformation = (393.700787", 393.700787", 0")
              Edit transformation = (393.700787", 0", 0")

              print_geometry
              active_path = [Group 1, Group 2]
              Group 1 transformation = (0", 0", 0")
              Group 2 transformation = (0", 0", 0")
              Edit transformation = (393.700787", 393.700787", 0")`

              At the top level, I can figure out the local transformation for both Group 1 and Group 2. At the second level (inside Group 1), I can get Group 1's transformation from the edit transform and I can get Group 2's transformation by applying the inverse of Group 1's transformation. However, from the third level (inside Group 2) there is information lost. I cannot figure out which part of the edit transform comes from Group 1's transformation and which part comes from Group 2's. Is there a solution to get transformations for both groups when we are inside of Group 2? I had been storing data in my own array in an onActivePathChanged observer. However, this falls apart when the active path changes by more than a single step.

              I have not seen a good answer to this question in any other post: http://sketchucation.com/forums/viewtopic.php?f=323%26amp;t=30067, http://sketchucation.com/forums/viewtopic.php?f=180%26amp;t=26212. Is there just no solution for this?

              ` def make_geometry

              clear everything out

              Sketchup.active_model.entities.clear!

              add the parent group

              $group1 = Sketchup.active_model.entities.add_group
              $group1.name = "Group 1"

              set parent’s transformation

              $group1.transformation = Geom::Transformation.translation(Geom::Point3d.new(10.m, 0, 0))

              add some points to the parent group

              $group1.entities.add_cpoint(Geom::Point3d.new(0.m, 0.m, 0.m))
              $group1.entities.add_cpoint(Geom::Point3d.new(5.m, 5.m, 3.m))

              add the child group

              $group2 = $group1.entities.add_group
              $group2.name = "Group 2"

              set child’s transformation

              $group2.transformation = Geom::Transformation.translation(Geom::Point3d.new(0, 10.m, 0))

              add some points to the child group

              $group2.entities.add_cpoint(Geom::Point3d.new(0.m, 0.m, 0.m))
              $group2.entities.add_cpoint(Geom::Point3d.new(5.m, 5.m, 3.m))
              end

              def print_active_path()
              result = []
              active_path = Sketchup.active_model.active_path
              active_path.each {|p| result << p.name} if active_path
              puts "active_path = [#{result.join(', ')}]"
              end

              def print_transformation(name, t)
              puts "#{name} = #{t.origin}"
              end

              def print_geometry
              print_active_path()
              print_transformation("Group 1 transformation", $group1.transformation)
              print_transformation("Group 2 transformation", $group2.transformation)
              print_transformation(" Edit transformation", Sketchup.active_model.edit_transform)
              nil
              end`

              1 Reply Last reply Reply Quote 0
              • D Offline
                dacastror
                last edited by

                tip: never use global variables ($)

                I think something like this is what you want

                
                def overall_transformation(instance)
                  model = Sketchup.active_model
                  path = model.active_path ? model.active_path ; []
                  indi = path.index(instance)
                  if indi
                    return model.edit_transform if indi == path.size-1
                    tr = path[0].local_transformation
                    for i in 1..indi
                      tr = path[i].local_transformation * tr
                    end
                  else
                    tr = instance.transformation
                    while (instance.parent.class != Sketchup;;Model)
                      instance = instance.parent.instances[0]
                      tr = instance.transformation * tr
                    end
                  end
                  return tr 
                end
                
                def find_instances
                  instancias = []; instancias.clear
                  mod = Sketchup.active_model
                  definitions = mod.definitions
                  for definition in definitions
                    instances = definition.instances
                    if instances.length > 0
                      entity = instances[0]
                      attr = entity.get_attribute "dic", "key"
                      instancias << entity if attr
                    end
                  end
                  return instancias
                end
                  
                def make_instance(entities,transformation)
                  p1 = [0,0,0]; p2 = [50,50,50]
                  group = entities.add_group
                  group.entities.add_line p1, p2
                  group.transform! transformation
                  return group
                end
                
                
                def make_2_instances_nested_transformed
                  model  = Sketchup.active_model
                  return "had been previously created" if find_instances.size>0
                  tr1    = Geom;;Transformation.translation [100,0,0]
                  tr2    = Geom;;Transformation.translation [0,100,0]
                  ents1  = model.entities
                  group1 = make_instance(ents1,tr1)
                  ents2  = group1.entities
                  group2 = make_instance(ents2,tr2)
                  group1.set_attribute "dic", "key", "info"
                  group2.set_attribute "dic", "key", "info"
                  "ok"
                end
                
                def find_instances_and_print_global_positions
                  instances = find_instances
                  group1 = instances[0]; group2 = instances[1]
                  origin1 = overall_transformation(group1).origin
                  origin2 = overall_transformation(group2).origin
                  puts "Group 1 global origin -> " + origin1.to_a.inspect
                  puts "Group 2 global origin -> " + origin2.to_a.inspect
                  "ok"
                end
                  
                #make_2_instances_nested_transformed
                #find_instances_and_print_global_positions
                
                

                first run make_2_instances_nested_transformed
                and then find_instances_and_print_global_positions on any active context

                this only works if instances are unique, this is just an idea
                for depth greater than 2 I do not think it works, local_transformation seems uncertain when this within instances of interest ...
                (google translator)

                1 Reply Last reply Reply Quote 0
                • D Offline
                  danmacumber
                  last edited by

                  Thank you dacastror, local_transformation seems to work. Does anyone have any information about local_transformation since it does not seem to be in the docs, http://www.sketchup.com/intl/en/developer/docs/methods#index_l? This post indicates that this method is provided by the Dynamic Components extension, http://sketchucation.com/forums/viewtopic.php?f=180%26amp;t=33182%26amp;start=15#p293542. Is there any documentation for the Dynamic Components extension?

                  In our plug-in, we only ever have two levels of nested groups and all groups are unique instances. So I guess this should work for us? As long as the SketchUp team doesn't remove the method?

                  1 Reply Last reply Reply Quote 0
                  • D Offline
                    danmacumber
                    last edited by

                    I have played around with dacastror's solution and I think there is still an underlying issue in SketchUp when the active_path changes more than one level at a time. I extended dacastror's code to include additional groups and components for testing. I also added some "handle" groups under each group and component that can be selected in the outliner to immediately make the parent context active. Under most situations find_instances_and_print_global_positions returns the correct value:

                    @unknownuser said:

                    Group 1 global origin -> [100.0, 0.0, 0.0]
                    Group 2 global origin -> [100.0, 100.0, 0.0]
                    Instance 3 global origin -> [100.0, -100.0, 0.0]
                    Group 4 global origin -> [-100.0, 0.0, 0.0]
                    Group 5 global origin -> [-100.0, 100.0, 0.0]
                    Instance 6 global origin -> [-100.0, -100.0, 0.0]
                    ok

                    However, if I start at the top level of the model, then make Instance 3 active by selecting the handle group 'Group 1->Instance 3 <Definition 3>->handle' in the outliner, find_instances_and_print_global_positions returns:

                    @unknownuser said:

                    Group 1 global origin -> [0.0, 0.0, 0.0]
                    Group 2 global origin -> [100.0, 100.0, 0.0]
                    Instance 3 global origin -> [100.0, -100.0, 0.0]
                    Group 4 global origin -> [-100.0, 0.0, 0.0]
                    Group 5 global origin -> [-100.0, 100.0, 0.0]
                    Instance 6 global origin -> [-100.0, -100.0, 0.0]
                    ok

                    If I start at the top level, then enter Group 1, then enter Instance 3, I get the correct result.

                    @unknownuser said:

                    when entering Group 1, then Instance 3, local_transformation of Group 1 is correct

                    Sketchup.active_model.active_path
                    [#Sketchup::Group:0x0000000d876d80, #Sketchup::ComponentInstance:0x0000000d8756d8]
                    Sketchup.active_model.active_path[0].local_transformation.to_a.inspect
                    [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 100.0, 0.0, 0.0, 1.0]

                    when jumping from top level to Instance 3, local_transformation of Group 1 is incorrect

                    Sketchup.active_model.active_path
                    [#Sketchup::Group:0x0000000d876d80, #Sketchup::ComponentInstance:0x0000000d8756d8]
                    Sketchup.active_model.active_path[0].local_transformation.to_a.inspect
                    [1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0]

                    I get similar results if I switch between other levels of the hierarchy in odd ways. I wonder if the implementation of local_transformation depends on the active path observer? I only seem to get these issues if I change the active path multiple elements at time.

                    def overall_transformation(instance)
                      model = Sketchup.active_model
                      path = model.active_path ? model.active_path ; []
                      
                      parents = []
                      parent = instance.parent
                      while (parent.class != Sketchup;;Model)
                        parents << parent
                        if parent.class == Sketchup;;ComponentDefinition
                          parent = parent.instances[0]
                        else
                          parent = parent.parent
                        end
                      end
                      
                      indi = path.index(instance)
                      
                      # if instance is in path
                      if indi
                        
                        # if instance is last entry in path
                        return model.edit_transform if indi == path.size-1
                        
                        # compute transformation up to and including instance
                        tr = path[0].local_transformation
                        for i in 1..indi
                          tr = path[i].local_transformation * tr
                        end
                        
                      else
                        # initialize with instance transformation
                        tr = instance.transformation
                        while (instance.parent.class != Sketchup;;Model)
                          # get parent
                          if instance.parent.class == Sketchup;;ComponentDefinition
                            instance = instance.parent.instances[0]
                          else
                            instance = instance.parent
                          end
                          
                          # is parent in path
                          indi = path.index(instance)
                          if indi
                            # when parent is in active path, it's transformation is just identity right?
                            #puts "parent found #{instance.transformation.to_a.inspect}"
                            tr = instance.transformation * tr
                          else
                            tr = instance.transformation * tr
                          end
                        end
                      end
                      
                      return tr
                    end
                    
                    def find_instances
                      instancias = []; instancias.clear
                      mod = Sketchup.active_model
                      definitions = mod.definitions
                      for definition in definitions
                        instances = definition.instances
                        if instances.length > 0
                          entity = instances[0]
                          attr = entity.get_attribute "dic", "key"
                          instancias << [attr, entity] if attr
                        end
                      end
                      # sort by key
                      instancias.sort {|x,y| x[0] <=> y[0]}
                      return instancias
                    end
                     
                    def make_group(entities,transformation,group_name)
                      p1 = [0,0,0]; p2 = [50,50,50]
                      group = entities.add_group
                      group.name = group_name
                      group.entities.add_line p1, p2
                      group.transform! transformation
                      return group
                    end
                    
                    # this group is not really of interest, just gives us a handle in the outliner to make parent active 
                    def make_handle_group(entities)
                      p1 = [0,0,0]; p2 = [50,50,50]
                      group = entities.add_group
                      group.name = "handle"
                      edge = group.entities.add_line p1, p2
                     	edge.visible = false
                      return group
                    end
                    
                    def make_instance(entities,transformation,definition_name,instance_name)
                      p1 = [0,0,0]; p2 = [50,50,50]
                      definition = Sketchup.active_model.definitions.add(definition_name)
                      definition.entities.add_line p1, p2
                      make_handle_group(definition.entities)
                      instance = entities.add_instance(definition, transformation)
                      instance.name = instance_name
                      return instance
                    end
                    
                    def make_instances
                      model  = Sketchup.active_model
                      return "had been previously created" if find_instances.size>0
                      model.definitions.purge_unused
                      tr1    = Geom;;Transformation.translation [100,0,0]
                      tr2    = Geom;;Transformation.translation [0,100,0]
                      tr3    = Geom;;Transformation.translation [0,-100,0]
                      group1 = make_group(model.entities,tr1,"Group 1"); make_handle_group(group1.entities)
                      group2 = make_group(group1.entities,tr2,"Group 2"); make_handle_group(group2.entities)
                      instance3 = make_instance(group1.entities,tr3,"Definition 3","Instance 3")  
                      group1.set_attribute "dic", "key", "Group 1"
                      group2.set_attribute "dic", "key", "Group 2"
                      instance3.set_attribute "dic", "key", "Instance 3"
                      
                      tr4    = Geom;;Transformation.translation [-100,0,0]
                      tr5    = Geom;;Transformation.translation [0,100,0]
                      tr6    = Geom;;Transformation.translation [0,-100,0]
                      group4 = make_group(model.entities,tr4,"Group 4"); make_handle_group(group4.entities)
                      group5 = make_group(group4.entities,tr5,"Group 5"); make_handle_group(group5.entities)
                      instance6 = make_instance(group4.entities,tr6,"Definition 6","Instance 6")
                      group4.set_attribute "dic", "key", "Group 4"
                      group5.set_attribute "dic", "key", "Group 5"
                      instance6.set_attribute "dic", "key", "Instance 6"
                      "ok"
                    end
                    
                    def find_instances_and_print_global_positions
                      instances = find_instances
                      instances.each do |instance|
                        origin = overall_transformation(instance[1]).origin
                        puts "#{instance[0]} global origin -> " + origin.to_a.inspect
                      end
                      "ok"
                    end
                     
                    #make_instances
                    #find_instances_and_print_global_positions
                    
                    1 Reply Last reply Reply Quote 0
                    • D Offline
                      danmacumber
                      last edited by

                      For reference this is the issue that this causes users of OpenStudio:

                      https://unmethours.com/question/1625/wall-flying-every-where/
                      https://github.com/NREL/OpenStudio/issues/1350

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

                        @danmacumber said:

                        This post indicates that this method is provided by the Dynamic Components extension.

                        Correct.

                        However, those methods that are listed as added to Sketchup::Drawingelement, that have to do with transformations, should not have been added at that level of the class hierarchy (in order to just add them to the Group and ComponentInstance subclasses.) IE, they got erroneously added to ALL Sketchup::Drawingelement subclasses. Those methods are meaningless with respect to primitive entity classes like Edge.

                        They should (and may in the future,) be defined within a mixin module, and then mixed ONLY into Sketchup::Group and Sketchup::ComponentInstance classes.

                        @danmacumber said:

                        Is there any documentation for the Dynamic Components extension?

                        Not at this time.

                        @danmacumber said:

                        I only seem to get these issues if I change the active path multiple elements at time. ... I get similar results if I switch between other levels of the hierarchy in odd ways.

                        I wonder if the implementation of local_transformation() depends on the active path observer?

                        I do "believe" it does. I think it does similar to what you described. It (the "DCX") saves transforms into hashes (using the object reference as the key.) I think they are global collection objects named $local_edit_transforms and $global_edit_transforms.

                        So you could write some watcher code into your tests that watch those collections. (Just do not write code that changes them or the DCs could stop working.)

                        @danmacumber said:

                        In our plug-in, we only ever have two levels of nested groups and all groups are unique instances. So I guess this should work for us? As long as the SketchUp team doesn't remove the method?

                        This would require that your users have the DC extension loaded, or your extension might have to require the dc loader script explicitly.

                        I'm not here much anymore.

                        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