• Login
sketchucation logo sketchucation
  • Login
⚠️ Libfredo 15.4b | Minor release with bugfixes and improvements Update

Plugin select only one instance + count instances

Scheduled Pinned Locked Moved Plugins
5 Posts 2 Posters 455 Views 2 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.
  • S Offline
    sb1305
    last edited by 29 Aug 2013, 08:37

    Hi guys,

    I am new here and I was wondering if somebody could help me with my problem.
    I have used Sketchup for some years, but I have just started working with Ruby.

    So here is my problem:

    "select only one instance of each component"
    I made a big model with many different components, some of them are more than once in the model and now I want to select the components and copy them next to the model to create a kind of library of all the different components, but I only want to select one of each component and I don't want to select every single one by hand.
    Is there maybe an already existing plugin, that can select only one instance of each component? Or can anyone help me to write that in ruby?

    "text-tag: number of instances"
    And after I copied the elements I would like to put a text tag next to them saying how many instances there are in total, of course minus the copy I just created and I don't want to do that by hand as well. So I want the entity info "solid component(65 in model)" for example as a text-tag. Is there maybe an existing plugin or can anyone help me to write that in ruby?
    And it would also be great to do that by selecting all, so it will create a text tag with the number for every single element in the selection.

    I hope you can help me with that.
    Thank you very much!

    Simon

    1 Reply Last reply Reply Quote 0
    • T Offline
      TIG Moderator
      last edited by 29 Aug 2013, 09:27

      To find components iterate the definitions...

      require('sketchup.rb')
      module TIG
      	def TIG.composer()
      		model=Sketchup.active_model
      		ents=model.entities
      		ds=[] # component definitions
      		model.definitions.each{|d|
      			next if d.image? || d.group?
      			next unless d.instances[0]
      			ds << d
      		}
      		return unless ds[0]
      		model.start_operation('Composer', true)
      		pt=model.bounds.max
      		pt.z=0
      		pt.offset!([120,0,0])
      		# first point to add instance 10' away adjust as desired
      		ds.each{|d|
      			n=d.name
      			c=d.instances.length
      			t=Geom;;Transformation.new(pt)
      			i=ents.add_instance(d, t)
      			pt.x=i.bounds.max.x+120 # point for next instance
      			ents.add_text("#{n}\nInstances=#{c}", i.bounds.max, [6,6,12])
      		}
      		model.commit_operation
      	end
      end
      

      Usage TIG.composer
      You can use this for the basis of many processes...

      TIG

      1 Reply Last reply Reply Quote 0
      • S Offline
        sb1305
        last edited by 29 Aug 2013, 12:49

        Thank you so much. That helped a lot.

        1 Reply Last reply Reply Quote 0
        • S Offline
          sb1305
          last edited by 30 Aug 2013, 08:56

          Hi TIG, so I have some more questions about the code.

          "select only one instance of the components in selection"
          The code runs for all the components in the model, right?
          How can I run it for only the ones I select?
          it would be good to have a code that only selects one instance of each component of my selection.

          "text-tag: number of instances"
          And the text tag which says how many instances there are, can I also use that separated from the copying, so that I can put a text-tag only on components that I select somewhere in my library or in the model?

          "order of components"
          And another thing, what is the order the components come in? I don't find that in the code, do I?

          Sorry for all the questions, I would really like to understand the code and work on it, but I have just started doing this.

          Thank you so much,

          Simon

          1 Reply Last reply Reply Quote 0
          • T Offline
            TIG Moderator
            last edited by 30 Aug 2013, 10:58

            @sb1305 said:

            Hi TIG, so I have some more questions about the code.

            "select only one instance of the components in selection"
            The code runs for all the components in the model, right?
            How can I run it for only the ones I select?
            it would be good to have a code that only selects one instance of each component of my selection.

            "text-tag: number of instances"
            And the text tag which says how many instances there are, can I also use that separated from the copying, so that I can put a text-tag only on components that I select somewhere in my library or in the model?

            "order of components"
            And another thing, what is the order the components come in? I don't find that in the code, do I?

            Sorry for all the questions, I would really like to understand the code and work on it, but I have just started doing this.

            Thank you so much,

            Simon
            Replace:

            ds=[] # component definitions
                  model.definitions.each{|d|
                     next if d.image? || d.group?
                     next unless d.instances[0]
                     ds << d
                  }
            

            with something to process the selection instead - a bit more convoluted!

            ss=model.selection.grep(Sketchup;;ComponentInstance)
            ds=[]
            ss.each{|e| ds << e.definition }
            ds.uniq!
            

            Now you have a 'list' of just the definitions relating to selected component-instances [.uniq! ensures there are no repeats]... Process that 'ds' 'array' as before...

            To make a text_adder() create another method [def]... In it do something like

            pt=model.bounds.max
            pt.z=0
            pt.offset!([120,0,0])
            (model.selection.grep(Sketchup;;ComponentInstance).uniq).each{|e|
              d=e.definition
              n=d.name
              c=d.instances.length
              t=Geom;;Transformation.new(pt)
              i=ents.add_instance(d, t)
              pt.x=i.bounds.max.x+120 # point for next instance
              ents.add_text("#{n}\nInstances=#{c}", i.bounds.max, [6,6,12])
            }
            

            If you want to not count the one you have in your 'Library' then change c=d.instances.length to c=d.instances.length-1 etc...
            remember to wrap it in a namespace/module as the ' composer' example, and use model_start_op...commit so it's one-step undo-able...

            The order of the components in the earlier post comes from the order in the definitions list, which is 'chronological', so if you made 'zebra' before 'aardvark' that's the order in which they are found.
            The order in a selection is not easily possible to determine, you can try picking in the desired order [holding Ctrl to add to the selection...]...
            If you want to get the results in sorted 'name' order, then you need to add in an extra step or two...The code outlined earlier...

            ss=model.selection.grep(Sketchup;;ComponentInstance)
            ds=[]
            ss.each{|e| ds << e.definition }
            ds.uniq!
            

            needs to become something like ...

            ss=model.selection.grep(Sketchup;;ComponentInstance)
            ns=[]
            ss.each{|e| ns << e.definition.name }
            ns.uniq.sort!
            ### sorted names...
            ds=[]
            ns.each{|n| ds << model.definitions[n] }
            ### NOW process 'ds' which is a list of definitions sorted by name... 
            

            You can make a similar change to the 'whole of the definitions' version too.
            Ruby's 'sort' is 'case sensitive' - you can make it case 'insensitive' using a method [wrapped] like this

            def self.sort_by(a)
              return unless a.is_a?(Array)
              return a.sort_by{|w|[w.downcase, w]}
            end
            

            You then replace the line ns.uniq.sort!
            with this:
            ns.uniq! ns=self.sort_by(ns)
            🤓

            TIG

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

            Advertisement