sketchucation logo sketchucation
    • Login
    πŸ€‘ SketchPlus 1.3 | 44 Tools for $15 until June 20th Buy Now

    Arrange component names

    Scheduled Pinned Locked Moved Developers' Forum
    13 Posts 5 Posters 776 Views 5 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
      siim11s
      last edited by

      Hi,

      I'm fairly new to ruby so I could be missing something trivial..

      Say I have 200 or so components named as follows:

      "001 - short description"
      "002 - ..."
      "003 - ..."
      ..and so on.

      Now when I need to make a new component and place it as number "052" for example - I'd need to rename all the components that follow.

      I get the component definitions by:

      definitions = Sketchup.active_model.definitions
      component_list = []
      for d in definitions
      next if d.image?
      next if d.group?
      component_list << d
      end

      (thanks ThomThom: http://www.thomthom.net/thoughts/2012/02/definitions-and-instances-in-sketchup/)

      I then have a component_list ordered as "last modified", right?

      I can get a list with the names of the components and make the necessary changes but then I have a names_list array with no way to put the names "back" to the components in the model without changing the order in which they appear.

      I hope you understand what I'm trying to do πŸ˜„

      Maybe there is a better way, perhaps using hashes to store the component definition with the name?

      Anyway, thanks for any advice.

      /s

      //S.

      1 Reply Last reply Reply Quote 0
      • tt_suT Offline
        tt_su
        last edited by

        @siim11s said:

        I then have a component_list ordered as "last modified", right?

        The order is in no guarantied order. It doesn't change when definitions are modified.

        @siim11s said:

        I hope you understand what I'm trying to do

        I'm afraid it's a bit unclear to me.
        Are you trying to rename all definitions?
        What is the expected result?

        @siim11s said:

        Now when I need to make a new component and place it as number "052" for example - I'd need to rename all the components that follow.

        Why do you need to rename all the other components to place a new component?

        1 Reply Last reply Reply Quote 0
        • S Offline
          slbaumgartner
          last edited by

          @tt_su said:

          Why do you need to rename all the other components to place a new component?

          I'd bet that the numeric prefix has external ordering significance (like number 053 has some relation to 054) so the existing higher numbered parts have to be pushed up when a new one is inserted into the list.

          1 Reply Last reply Reply Quote 0
          • S Offline
            siim11s
            last edited by

            @tt_su said:

            The order is in no guarantied order. It doesn't change when definitions are modified.

            Ok, thanks.

            @tt_su said:

            I'm afraid it's a bit unclear to me.
            Are you trying to rename all definitions?

            Not exactly, I'm trying to insert a new component in the middle of a name-sorted list, while keeping the numbering sequence.

            @tt_su said:

            What is the expected result?

            List of components where the first 3 characters of the component name determine the component's position in the list.

            @tt_su said:

            Why do you need to rename all the other components to place a new component?

            I want to place a component in position 52 in the list, so I name it "052 - ...", but there already is a component which name starts with "052" so I need all existing component names to increase their 'index' by 1.

            Further:

            I'm working on a wooden house frame and I need a way to get the components exported in a certain order. I have numbered the 'parts' in order of 'appearance'.

            • e.g. the part you need first would be "001 - Bottom plate part - 45x95x6000". Where the "001" is the 'index' for the part and the rest is a description of it.

            So, If I at some point realise that I need to insert another piece of timber, I would create a new component. But I need to place it in a certain position in the components list (which is sorted by name). If part number 052 would be a wall stud of a certain dimension and I needed to insert a new stud of another dimension next to it I want the part to be number 051 or 053 - doesn't really matter which as long as they are close.

            If the component count at that point is 200, I'd need to increase the 'index' number for all components 053-200 by one.

            Is this any clearer?

            //S.

            1 Reply Last reply Reply Quote 0
            • S Offline
              siim11s
              last edited by

              @slbaumgartner said:

              I'd bet that the numeric prefix has external ordering significance (like number 053 has some relation to 054) so the existing higher numbered parts have to be pushed up when a new one is inserted into the list.

              Exactly : )

              //S.

              1 Reply Last reply Reply Quote 0
              • S Offline
                slbaumgartner
                last edited by

                The core issue here is to realize that there is a difference between the ordering in which items are stored in a Ruby container as they are added (which may be seemingly random - e.g. in a hash - or may be based on some optimization of the internal structure) vs the order in which they are presented by some UI or processed by code. If the order matters for the latter purposes, you should create an Array using #to_a and then sort the Array using whatever ordering rule you like.

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

                  @siim11s said:

                  @slbaumgartner said:

                  I'd bet that the numeric prefix has external ordering significance (like number 053 has some relation to 054) so the existing higher numbered parts have to be pushed up when a new one is inserted into the list.

                  Exactly : )

                  Here is some code for you to test. It seems to do what I understand you want.

                  mod = Sketchup.active_model
                  ent = mod.active_entities
                  sel = mod.selection
                  cds = mod.definitions.reject{|cd|cd.group?||cd.image?}
                  prefix=('%03d' % cds.length)
                  new=sel.first;new_name=prefix+' - '+new.definition.name
                  inp=UI.inputbox(["New Name;"],[new_name],"Rename #{new.definition.name}")
                  if inp
                   prefix,name=inp[0].split(' - ')
                   cds.each{|cd|
                    if cd.name.index(' - ')
                     p,n=cd.name.split(' - ')
                     if p.to_i >= prefix.to_i
                      cd.name=p.next+' - '+n
                     end
                    end
                   }
                   new.definition.name=inp[0]
                  end
                  
                  

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

                  http://sdmitch.blogspot.com/

                  1 Reply Last reply Reply Quote 0
                  • S Offline
                    siim11s
                    last edited by

                    @sdmitch said:

                    Here is some code for you to test. It seems to do what I understand you want.

                    Yes.. almost. Not quite the way I imagined it though.
                    It also seems to add "#1" at the end of some(?!) of the changed names.

                    I'd prefer it wasn't dependent on the " - " in the name, rather that the first 3 characters are numbers. And I'd like to be able to sort through the whole list of numbered components in the model.. looking for consistency errors and correct them if needed. But I'll try to understand it better. Thanks!

                    @slbaumgartner said:

                    The core issue here is to realize that there is a difference between the ordering in which items are stored in a Ruby container as they are added (which may be seemingly random - e.g. in a hash - or may be based on some optimization of the internal structure) vs the order in which they are presented by some UI or processed by code. If the order matters for the latter purposes, you should create an Array using #to_a and then sort the Array using whatever ordering rule you like.

                    Yes, that's where I first got stuck. I have a few Ideas I can try now, thanks for the help so far.

                    //S.

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

                      @siim11s said:

                      Yes.. almost. Not quite the way I imagined it though.
                      It also seems to add "#1" at the end of some(?!) of the changed names.

                      I'd prefer it wasn't dependent on the " - " in the name, rather that the first 3 characters are numbers. And I'd like to be able to sort through the whole list of numbered components in the model.. looking for consistency errors and correct them if needed. But I'll try to understand it better. Thanks!

                      The "#1" usually only occurs when you give the same name to two definitions which is why I don't name the selected component until the end.

                      Using the " - " seemed to be the safest option given your naming sample.

                      cdn = mod.definitions.map{|cd| cd.name}.sort
                      

                      will give you a sorted array of the definition names.

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

                      http://sdmitch.blogspot.com/

                      1 Reply Last reply Reply Quote 0
                      • M Offline
                        MSP_Greg
                        last edited by

                        Try the following (based on SDMitch's code)

                        
                        mod = Sketchup.active_model
                        ent = mod.active_entities
                        sel = mod.selection
                        cds = mod.definitions.reject{|cd|cd.group?||cd.image?}
                        prefix=('%03d' % cds.length)
                        new=sel.first;new_name=prefix+' - '+new.definition.name
                        inp=UI.inputbox(["New Name;"],[new_name],"Rename #{new.definition.name}")
                        reInc = /^(\d{3})(.+)/
                        if (reInc.match(inp[0]))
                          new.definition.name = inp[0]
                          iPre = $1.to_i
                          iCD = 0
                          cds.each { |cd|
                            if (reInc.match(cd))
                              iCD = $1.to_i + 1
                              cd.name = "%03d#{$2}" %iCD if iCD > iPre
                            end
                          }
                        end
                        
                        

                        As long as the cd name begins with three numbers...

                        Note - no testing for prefixes greater than 999, and no testing for duplicate names after the increment.

                        Greg

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

                          @msp_greg said:

                          Try the following (based on SDMitch's code)

                          
                          > mod = Sketchup.active_model
                          > ent = mod.active_entities
                          > sel = mod.selection
                          > cds = mod.definitions.reject{|cd|cd.group?||cd.image?}
                          > prefix=('%03d' % cds.length)
                          > new=sel.first;new_name=prefix+' - '+new.definition.name
                          > inp=UI.inputbox(["New Name;"],[new_name],"Rename #{new.definition.name}")
                          > reInc = /^(\d{3})(.+)/
                          > if (reInc.match(inp[0]))
                          >   new.definition.name = inp[0]
                          >   iPre = $1.to_i
                          >   iCD = 0
                          >   cds.each { |cd|
                          >     if (reInc.match(cd))
                          >       iCD = $1.to_i + 1
                          >       cd.name = "%03d#{$2}" %iCD if iCD > iPre
                          >     end
                          >   }
                          > end
                          > 
                          

                          As long as the cd name begins with three numbers...

                          Note - no testing for prefixes greater than 999, and no testing for duplicate names after the increment.

                          Greg

                          Greg,

                          Tried your code and found two problems.

                          1. if(reInc.match(cd)) needs to be if(reInc.match(cd.name))

                          2. the prefix of the new name entered gets incremented as well. the new.definition.name = inp[0] statement needs to be the last thing done in the if (reInc.match(inp[0])) section.

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

                          http://sdmitch.blogspot.com/

                          1 Reply Last reply Reply Quote 0
                          • M Offline
                            MSP_Greg
                            last edited by

                            siim11s,

                            The previous code I posted didn't allow for name collisions. Below code should allow for it. Also added a few comments...

                            
                            # reInc checks for match of three digits at beginning of string,
                            # loads digits into $1, rest of name into $2
                            reInc = /^(\d{3})(.+)/
                            
                            if (reInc.match(inp[0]))
                              # sort reverse so name colisions won't occur
                              cds.sort! { |a,b| b.name <=> a.name }
                            
                              # initialize loop variables
                              iPre = $1.to_i
                              iCD = 0
                            
                              cds.each { |cd|
                                if (reInc.match(cd.name))
                                  iCD = $1.to_i + 1
                                  # since we're reverse sorted, break when we reach low numbers
                                  break if iCD <= iPre
                                  cd.name = "%03d#{$2}" %iCD
                                end
                              }
                              new.definition.name = inp[0]
                            end
                            
                            # for testing, use below to resort & output new names
                            cds.sort! { |a,b| a.name <=> b.name }
                            cds.each { |cd| puts cd.name }
                            
                            

                            Greg

                            1 Reply Last reply Reply Quote 0
                            • M Offline
                              MSP_Greg
                              last edited by

                              SDMitch (Mitch?),

                              @sdmitch said:

                              Tried your code and found two problems.

                              1. if(reInc.match(cd)) needs to be if(reInc.match(cd.name))

                              Thanks for the catches. I edited & corrected the second post. I tested mine with a string array, not an array of cd's. Hence, no name prop.

                              @sdmitch said:

                              1. the prefix of the new name entered gets incremented as well.

                              That's why you had the new cd name assign at the end of the loop. That's why I shouldn't change code after I've tested it...

                              Thanks,

                              Greg

                              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