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

    Copy a Group within a Component in Ruby, preserve location

    Scheduled Pinned Locked Moved Developers' Forum
    8 Posts 4 Posters 1.9k 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.
    • H Offline
      hank
      last edited by

      Hello All,

      First off, sorry this is long-winded. I've found it hard to find other discussions on this (at least one's a mere mortal like myself could understand) hard to come by. Hopefully this will help someone else too!

      Let's say you have a component definition called "WALL" and within that component you have 3 groups, each on their own layer. One of the groups is on a layer named "WALL_PRIMATIVES"

      Now, say you have 3 instances of that component in a model, all with various locations, scales, etc.

      What I would like to do is go into each component instance and copy the group on the "WALL_PRIMITIVES" layer to the root model context (I think this would be called Sketchup.active_model).

      So, I have been able to successfully grab the target group using 2 the methods below, but neither one preserves the transformation (location, scale, etc.) of the group. Instead, what happens is that the copied groups end up in a position derived from the original definition, not the various instances they are pulled from.

      Both methods use...

      
      mod = Sketchup.active_model
      ent = mod.entities
      
      

      failed method # 1 - COPYING THE GROUP:

      
      mod.definitions.each{|d|
        next if d.image? || d.group? || d.name!="WALL" # skip images, groups, and any component not named "WALL"
        d.entities.each{ |wall_primative_group|
          if wall_primative_group.layer.name == "WALL_PRIMITIVES" # only proceed with groups on target layer
              group_copy = ent.add_instance(wall_primative_group.entities.parent, wall_primative_group.transformation)
          end
        }
      }
      
      

      failed method # 2 - COPYING THE FACES:

      
      temp_wall_primitives = ent.add_group # create an empty group to receive faces
      
      mod.definitions.each{|d|
        next if d.image? || d.group? || d.name!="WALL"
        d.entities.each{ |wall_primative_group|
          if wall_primative_group.layer.name == "WALL_PRIMITIVES"
            wall_primative_group.entities.each{ |wall_primative_group_entity|
              if wall_primative_group_entity.is_a? Sketchup;;Face
      		  puts wall_primative_group_entity
                new_face = temp_wall_primitives.entities.add_face(wall_primative_group_entity.vertices)
              end
            }
          end
        }
      }
      
      

      I think this has to do with iterating through definitions rather than instances per this discussion. However, if I try to iterate through the actual instances placed in the model, I cannot figure out how to even get to the target group. See the ERROR or PROBLEM comments in the code below...

      
      ent.each{ |all_ents|
        if all_ents.is_a? Sketchup;;ComponentInstance
          next if all_ents.definition.name!="WALL"
          #puts all_ents.definition.name
          #all_ents.entities.each{ |all_comps| #ERROR; undefined method `entities' for #<Sketchup;;ComponentInstance;0x007fb00ab02b08>
          #all_ents.each{ |all_comps| #ERROR; undefined method `each' for #<Sketchup;;ComponentInstance;0x007fb00ab02b08>
      	all_ents.parent.entities.each{ |all_comps| #PROBLEM; just pops me back to the top level because the parent is the model!
      	  puts all_comps.definition.name
          }
        end
      }
      
      

      Please help!

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

        @hank said:

        What I would like to do is go into each component instance and copy the group ...

        You cannot "go into an instance" really, when you double-click manually you are actually editing the definition's entities collection. Instances do not have their own entities collection. The model engine just renders "display" copies using the definition's entities.

        @hank said:

        on the "WALL_PRIMITIVES" layer

        You should come to understand that the originators of SketchUp chose a poor word "layers", as in SketchUp they are not geometric entity collections at all. Therefore no entities can be "ON" any layer.
        The objects that SketchUp calls layers are just display property sheets can can be shared by multiple entities, so that all those objects "associated" / "assigned to" a layer will share the same display behavior(s).

        @hank said:

        to the root model context (I think this would be called Sketchup.active_model).

        The object reference of the root entities collection, is returned by:
        Sketchup.active_model.entities

        I'm not here much anymore.

        1 Reply Last reply Reply Quote 0
        • H Offline
          hank
          last edited by

          @sdmitch: Thank you. This worked mostly, successfully copying the groups out to the model, however the transformations did not seem to make it. Of the 3 test "WALL" components in my file, one group was the correct size but moved, the other two were the wrong size AND moved.

          Also,

          ent = @mod.active_entities
          

          returned undefined method `active_entities' for nil:NilClass so I changed it to

          ent = mod.active_entities
          

          to get the script to run. Am I missing something about the @? Which I think means you are calling an "instance" variable?

          @Dan Rathbun: Thank you. I am just using the layer as an easy selector for the groups I want within the component. Do you recommend another way?

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

            If your start up method defines mod=Sketchup.active_model then that reference ' mod' is only used inside that method - no other methods 'see' it.
            Of course if you don't need multiple methods then a simple variable will suffice.

            But if your start up method defines @mod=Sketchup.active_model then that reference ' @mod' is then accessible in all other methods in that module/class, without having to define it again in each method. Used in more complex code where there can be several methods doing various operations that need to be 'coordinated'...

            A @variable is also remembered across uses of the same 'module' - so it's useful for remembering previous dialog entries during that session etc - as there is only one instance of the module per session...

            However, since launching a 'class' always makes a new instance of itself, any @variable it defines only exists that one use - although it is accessible across that class's methods it vanishes as the code completes.

            But there is another type - @@variable - which you set up in the class's code outside of any methods, so it is defaulted as the code is initially loaded, and then you use it inside methods, so in this way you can remember the class's variables across uses, e.g. to remember previous dialog entries during a session... although of course you wouldn't use it for the active_model as that can vary during a session and a @variable is more appropriate...

            TIG

            1 Reply Last reply Reply Quote 0
            • sdmitchS Offline
              sdmitch
              last edited by

              You were on the right track with method#1. Once you have the definition, you need to iterate the instances of that definition. When making the copy, you need to apply the transformations of both the component instance and the group in order to have the copy be the same as the original.

              mod = Sketchup.active_model
              ent = mod.active_entities
              mod.definitions.each{|d|
                next if d.image? || d.group? || d.name!="WALL" # skip images, groups, and any component not named "WALL"
                d.instances.each{|ci|
                  ci.definition.entities.each{ |wall_primative_group|
                    if wall_primative_group.layer.name == "WALL_PRIMITIVES" # only proceed with groups on target layer
                      group_copy = ent.add_instance(wall_primative_group.entities.parent, wall_primative_group.transformation*ci.transformation)
                      group_copy.name = 'WALL_PRIMITIVES'
                    end
                  }
                }
              }
              
              

              Nothing is worthless, it can always be used as a bad example.

              http://sdmitch.blogspot.com/

              1 Reply Last reply Reply Quote 0
              • sdmitchS Offline
                sdmitch
                last edited by

                @hank said:

                @sdmitch: Thank you. This worked mostly, successfully copying the groups out to the model, however the transformations did not seem to make it. Of the 3 test "WALL" components in my file, one group was the correct size but moved, the other two were the wrong size AND moved.

                Also,

                ent = @mod.active_entities
                

                returned undefined method `active_entities' for nil:NilClass so I changed it to

                ent = mod.active_entities
                

                to get the script to run. Am I missing something about the @? Which I think means you are calling an "instance" variable?

                @Dan Rathbun: Thank you. I am just using the layer as an easy selector for the groups I want within the component. Do you recommend another way?

                Sorry about that. I always use @variables as a habit and just missed removing that one. Looks like I got the 'transformation' order wrong which had no effect on my un-rotated un-scaled test wall. Try this one.

                mod = Sketchup.active_model
                ent = mod.active_entities
                mod.definitions.each{|d|
                  next if d.image? || d.group? || d.name!="WALL" # skip images, groups, and any component not named "WALL"
                  d.instances.each{|ci|
                    ci.definition.entities.each{ |wall_primative_group|
                      if wall_primative_group.layer.name == "WALL_PRIMITIVES" # only proceed with groups on target layer
                        group_copy = ent.add_instance(wall_primative_group.entities.parent,ci.transformation*wall_primative_group.transformation)
                        group_copy.name = 'WALL_PRIMITIVES_COPY'
                      end
                    }
                  }
                }
                
                

                Nothing is worthless, it can always be used as a bad example.

                http://sdmitch.blogspot.com/

                1 Reply Last reply Reply Quote 0
                • H Offline
                  hank
                  last edited by

                  @sdmitch: That was it! Thank you - makes sense now. Much appreciated!

                  @TIG: Thank you for the detailed explanation!

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

                    @hank said:

                    **@Dan Rathbun:**I am just using the layer as an easy selector for the groups I want within the component.

                    This is fine. Ie, using the layer property as a filter.

                    @hank said:

                    Do you recommend another way?

                    I recommend rereading what I wrote. It was just general information (triggered by incorrect terminology you chose to use in an earlier post.)

                    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