sketchucation logo sketchucation
    • Login
    1. Home
    2. danmacumber
    3. Posts
    ℹ️ Licensed Extensions | FredoBatch, ElevationProfile, FredoSketch, LayOps, MatSim and Pic2Shape will require license from Sept 1st More Info
    D
    Offline
    • Profile
    • Following 0
    • Followers 0
    • Topics 1
    • Posts 7
    • Groups 1

    Posts

    Recent Best Controversial
    • RE: Question about edit_transform

      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

      posted in Developers' Forum
      D
      danmacumber
    • RE: Question about edit_transform

      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
      
      posted in Developers' Forum
      D
      danmacumber
    • RE: Question about edit_transform

      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?

      posted in Developers' Forum
      D
      danmacumber
    • RE: Question about edit_transform

      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`

      posted in Developers' Forum
      D
      danmacumber
    • RE: Question about edit_transform

      Thanks ThomThom, let me know what you find out.

      Dan

      posted in Developers' Forum
      D
      danmacumber
    • RE: Question about edit_transform

      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?

      posted in Developers' Forum
      D
      danmacumber
    • Question about edit_transform

      I have some questions about edit_transform that I have never been able to
      fully figure out. I work on a plug-in that uses multiply nested groups. I
      keep track of the edit_transform each time the active_path changes
      using ModelObserver.onActivePathChanged.

      Initially, I assumed that the active path could only change one path at a
      time (e.g. either a push or a pop relative to the current active path).
      However, I have found that sometimes the active path can change multiple
      steps at a times with no intermediate calls to
      ModelObserver.onActivePathChanged. For example:

      [Group1, SubGroup1] to []

      or

      [Group1, SubGroup1] to [Group2, SubGroup2]

      I keep track of an array of edit transforms and would really like to be
      able to recreate the edit transform given the active path. Is that
      possible? If so is there a way to get an array of edit transforms
      correspond to the active path array (i.e. the edit transform for each entry
      in the active path)?

      In case I am asking too much, any better description of what the edit_transform is would be very helpful. The SketchUp API documentation is not really complete enough for me especially with respect to nested groups.

      Thanks a lot,
      Dan

      posted in Developers' Forum
      D
      danmacumber
    • 1 / 1