sketchucation logo sketchucation
    • Login
    🤑 SketchPlus 1.3 | 44 Tools for $15 until June 20th Buy Now

    [solved] taking points at intervals from a line

    Scheduled Pinned Locked Moved Developers' Forum
    16 Posts 7 Posters 873 Views 7 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.
    • K Offline
      kdasilva
      last edited by kdasilva

      Hello, I am trying to get my head around how I can collect 3DPoints from a edge my users enter for a tool

      essentially, the user draws a line on that line I want to display text at equal intervals along it. The text is not constant, it is taken from an attribute dictionary.

      What I am hung up on is splitting my edge. I am trying to use the .split method based on a fraction created by the number of attributes in the dictionary, however my math is failing me in the sense that once I do the first split, I cant seen to get another split evenly placed down the line. Is there an easier way to do this?

      For example:

      lets say the user creates a line from [0,0,0] to [100,100,0] and there are 10 attributes

      how can I get 10 Point3d's evenly spread out along this line that I can use as anchors for my text....

      Any help would be greatly appreciated!

      Cheers
      Korbin

      1 Reply Last reply Reply Quote 0
      • C Offline
        Cleverbeans
        last edited by

        To get the points you'll want the vector from Edge.start to Edge.end, then scale it by your factor and transform the start point by the scaled down vector to get you first point, then repeat on that new point until you're done. Here is some code.

        
        def even_split(edge,splits)
        	point = edge.start.position 
        	vector = point.vector_to(edge.end.position)
        	scale = Geom;;Transformation.scaling(1.0/splits)
        	vector.transform!(scale)
        	for i in 1...splits
        		point.transform!(vector)
        		edge = edge.split(point)
        	end 
        end 
        
        
        1 Reply Last reply Reply Quote 0
        • TIGT Offline
          TIG Moderator
          last edited by

          Let's call them p0 and p1
          The distance between them...
          dis=p0.distance(p1)
          Let's assume we want to find a set of points at 1/n steps
          step=dis/n
          Then process and increment
          vec=p0.vector_to(p1) pts=[p0] p=p0.clone (n-1).times{ pt=p.offset(vec, step) pts << pt p=pt.clone } pts << p1
          You now have an array 'pts' of all points including the start and end ones and all intermediate ones as required...

          TIG

          1 Reply Last reply Reply Quote 0
          • K Offline
            kdasilva
            last edited by

            @dan rathbun said:

            @kdasilva said:

            how can I get 10 Point3d's evenly spread out along this line that I can use as anchors for my text....

            Divide the line by 9

            <span class="syntaxdefault">arr</span><span class="syntaxkeyword">=[]<br /></span><span class="syntaxcomment"># load array with the txt values in order<br /></span><span class="syntaxdefault">pt  </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> edge</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">start</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">position<br />vec </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> edge</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">line<br />num </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> dict</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">size</span><span class="syntaxkeyword">-</span><span class="syntaxdefault">1<br />seg </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> vec</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">length </span><span class="syntaxkeyword">/</span><span class="syntaxdefault"> num<br />vec</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">length </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> seg<br />arr</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">each_with_index </span><span class="syntaxkeyword">{|</span><span class="syntaxdefault">e</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">i</span><span class="syntaxkeyword">|<br /></span><span class="syntaxdefault">  pt</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">offset</span><span class="syntaxkeyword">!(</span><span class="syntaxdefault">vec</span><span class="syntaxkeyword">)</span><span class="syntaxdefault"> if i</span><span class="syntaxkeyword">></span><span class="syntaxdefault">0<br />  entities</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">add_text</span><span class="syntaxkeyword">(</span><span class="syntaxdefault"> arr</span><span class="syntaxkeyword">[</span><span class="syntaxdefault">i</span><span class="syntaxkeyword">],</span><span class="syntaxdefault"> pt </span><span class="syntaxkeyword">)<br />}</span><span class="syntaxdefault"> </span>
            

            I am trying my hardest to get this to work, unfortunately I have been unsuccessful thus far.....i put in:

            def draw_vision_field
              vision_field = ["test1", "test2", "test3", "test4", "test5"]
              pt = $line.start.position
              puts pt
              vec = $line.line
              puts vec
              num = vision_field.size - 1
              puts num
              seg = vec.length / num
              puts seg
              vec.length = seg
              vision_field.each_with_index {|e,i|
                pt.offset!(vec) if i > 0
                $ents.add_text( vision_field[i], pt )
              } 
            end
            

            I just put a test array to print for now. I added the puts in order to try and debug, I am getting this error message regarding the length= function on a vector...also the last number before the word error (the vec.length /num ), weirdly enough is always 0, i removed the /num and it always prints as 2, no matter how long the line is i make)

            
            (-350507.397831", 21906.712364", 0")
            (-350507.397831", 21906.712364", 0")
            (0.131501105216966, 0.991316023943281, 0.0)
            4
            0
            Error; #<NoMethodError; undefined method `length=' for [Point3d(-350507, 21906.7, 0), Vector3d(0.131501, 0.991316, 0)];Array>
            (eval);70;in `draw_vision_field'
            (eval);55;in `draw_the_line'
            (eval);28;in `onLButtonDown'
            (eval);73
            

            also... where does the method each_with_index come from? I can't find it in the sketchup api, and I could only find each_index in the ruby-doc http://www.ruby-doc.org/core/classes/Array.html#M000232

            thanks for the help

            korbin

            1 Reply Last reply Reply Quote 0
            • K Offline
              kyyu
              last edited by

              @kdasilva said:

              <snip>
              i removed the /num and it always prints as 2, no matter how long the line is i make)
              <snip>

              You don't want to use a line. A line would have infinite length. Anyways, it's just seen as an array ( type "edge.line.class"). So the length of that array is always 2 elements in that array, which defines a line.

              You want to use the vector from the edge:

              pt1 = edge.start.position
              pt2 = edge.end.position
              vec = Geom;;Vector3d.new [(pt2.x-pt1.x), (pt2.y-pt1.y), (pt2.z-pt1.z)]
              edge_length = vec.length
              

              @kdasilva said:

              <snip>
              also... where does the method each_with_index come from? I can't find it in the sketchup api, and I could only find each_index in the ruby-doc http://www.ruby-doc.org/core/classes/Array.html#M000232

              thanks for the help

              korbin

              The sketchup api just documents, extra ruby Modules/Classes/methods for sketchup. It doesn't document the entire ruby language.

              -Kwok

              1 Reply Last reply Reply Quote 0
              • fredo6F Offline
                fredo6
                last edited by

                In general, interpolating points should be done with Geom.linear_combination
                in your case, to create nb intermediate segments ( so nb+1 points, including first and last one)

                
                def intermediate_points(pt1, pt2, nb)
                   lpt = []
                   for i in 0..nb
                      ratio = 1.0 * i / nb
                      lpt.push Geom.linear_combination(1 - ratio, pt1, ratio, pt2)
                   end
                   lpt
                end
                
                

                which you can write in a single line as well

                
                (0..nb).to_a.collect { |i| r = 1.0 * i /nb ; Geom.linear_combination(1-r, pt1, r, pt2) }
                
                

                Fredo

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

                  @kyyu said:

                  You don't want to use a line. A line would have infinite length. Anyways, it's just seen as an array ( type "edge.line.class"). So the length of that array is always 2 elements in that array, which defines a line.

                  Yes. I am sorry Korbin, meant to use the second element from the line method (got rushed.)

                  I should have written:
                  vec = edge.line[1] not vec = edge.line

                  Also within a method, you dont need to use a global variable. Pass a reference to the line into the method as an argument. The argument name becomes a local reference (var) inside the method. (Do not get in the habit of using global vars. Its poor and lazy programming.)

                  <span class="syntaxdefault">def draw_vision_field</span><span class="syntaxkeyword">(</span><span class="syntaxdefault"> edge </span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault">  ents </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> Sketchup</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">active_model</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">active_entities<br />  vision_field </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> </span><span class="syntaxkeyword">[</span><span class="syntaxstring">"test1"</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> </span><span class="syntaxstring">"test2"</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> </span><span class="syntaxstring">"test3"</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> </span><span class="syntaxstring">"test4"</span><span class="syntaxkeyword">,</span><span class="syntaxdefault"> </span><span class="syntaxstring">"test5"</span><span class="syntaxkeyword">]<br /></span><span class="syntaxdefault">  pt </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> edge</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">start</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">position<br />  puts pt<br />  vec </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> edge</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">line</span><span class="syntaxkeyword">[</span><span class="syntaxdefault">1</span><span class="syntaxkeyword">]</span><span class="syntaxdefault">       </span><span class="syntaxcomment"># fixed this <br /></span><span class="syntaxdefault">  vec</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">length </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> edge</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">length </span><span class="syntaxcomment"># added this<br /></span><span class="syntaxdefault">  puts vec<br />  num </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> vision_field</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">size </span><span class="syntaxkeyword">-</span><span class="syntaxdefault"> 1<br />  puts num<br />  seg </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> vec</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">length </span><span class="syntaxkeyword">/</span><span class="syntaxdefault"> num<br />  puts seg<br />  vec</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">length </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> seg<br />  vision_field</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">each_with_index </span><span class="syntaxkeyword">{|</span><span class="syntaxdefault">e</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">i</span><span class="syntaxkeyword">|<br /></span><span class="syntaxdefault">    pt</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">offset</span><span class="syntaxkeyword">!(</span><span class="syntaxdefault">vec</span><span class="syntaxkeyword">)</span><span class="syntaxdefault"> if i </span><span class="syntaxkeyword">></span><span class="syntaxdefault"> 0<br />    ents</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">add_text</span><span class="syntaxkeyword">(</span><span class="syntaxdefault"> vision_field</span><span class="syntaxkeyword">[</span><span class="syntaxdefault">i</span><span class="syntaxkeyword">],</span><span class="syntaxdefault"> pt </span><span class="syntaxkeyword">)<br /></span><span class="syntaxdefault">  </span><span class="syntaxkeyword">}</span><span class="syntaxdefault"> <br />end<br /></span>
                  

                  EDIT: edge.line[1] returns a unit vector, so we must add a statement to make vec the length of edge.

                  I'm not here much anymore.

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

                    @kdasilva said:

                    how can I get 10 Point3d's evenly spread out along this line that I can use as anchors for my text....

                    Divide the line by 9

                    <span class="syntaxdefault">arr</span><span class="syntaxkeyword">=[]<br /></span><span class="syntaxcomment"># load array with the txt values in order<br /></span><span class="syntaxdefault">pt  </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> edge</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">start</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">position<br />vec </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> edge</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">line</span><span class="syntaxkeyword">[</span><span class="syntaxdefault">1</span><span class="syntaxkeyword">]<br /></span><span class="syntaxdefault">vec</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">length </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> edge</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">length <br />num </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> dict</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">size</span><span class="syntaxkeyword">-</span><span class="syntaxdefault">1<br />seg </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> vec</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">length </span><span class="syntaxkeyword">/</span><span class="syntaxdefault"> num<br />vec</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">length </span><span class="syntaxkeyword">=</span><span class="syntaxdefault"> seg<br />arr</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">each_with_index </span><span class="syntaxkeyword">{|</span><span class="syntaxdefault">e</span><span class="syntaxkeyword">,</span><span class="syntaxdefault">i</span><span class="syntaxkeyword">|<br /></span><span class="syntaxdefault">  pt</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">offset</span><span class="syntaxkeyword">!(</span><span class="syntaxdefault">vec</span><span class="syntaxkeyword">)</span><span class="syntaxdefault"> if i</span><span class="syntaxkeyword">></span><span class="syntaxdefault">0<br />  entities</span><span class="syntaxkeyword">.</span><span class="syntaxdefault">add_text</span><span class="syntaxkeyword">(</span><span class="syntaxdefault"> arr</span><span class="syntaxkeyword">[</span><span class="syntaxdefault">i</span><span class="syntaxkeyword">],</span><span class="syntaxdefault"> pt </span><span class="syntaxkeyword">)<br />}</span><span class="syntaxdefault"> </span>
                    

                    EDIT: vec = edge.line[1] was vec = edge.line
                    Added: vec.length = edge.length as edge.line[1] returns a unit vector.

                    I'm not here much anymore.

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

                      @kyyu said:

                      You want to use the vector from the edge:

                      pt1 = edge.start.position
                      > pt2 = edge.end.position
                      > vec = Geom;;Vector3d.new [(pt2.x-pt1.x), (pt2.y-pt1.y), (pt2.z-pt1.z)]
                      > edge_length = vec.length
                      

                      This is what I intended, but left off the index to the 2nd element.
                      edge.line[1] returns the unit vector for the edge, so:

                      vec = edge.line[1] vec.length = edge.length

                      I'm not here much anymore.

                      1 Reply Last reply Reply Quote 0
                      • K Offline
                        kdasilva
                        last edited by

                        Wow, thanks for all the help, and that fixed it up no problem.

                        Dan - I also got rid of all of the global variables...in some cases I used class variables I hope thats not bad coding...changes to a variable in one method needed to be consistent in other methods for some parts in the tool

                        (your all definitely getting a thank you foot note in my thesis!)

                        Cheers,
                        Korbin

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

                          @kdasilva said:

                          also... where does the method each_with_index come from?

                          The method each_with_index() comes from the special mixin-module Enumerable, which is mixed into many other classes like String, Hash and Array.

                          On the Docs page for each class, it lists what other modules are "mixed-in" using the include() method, so therefore the caption Included.
                          Array_included.png

                          And for Sketchup use the v 1.8.6 docs:
                          Core: http://www.ruby-doc.org/core-1.8.6/index.html

                          The Keywords apply to all branches and versions.
                          Keywords: http://www.ruby-doc.org/docs/keywords/1.9/

                          I'm not here much anymore.

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

                            @kdasilva said:

                            ...in some cases I used class variables I hope thats not bad coding...changes to a variable in one method needed to be consistent in other methods for some parts in the tool

                            No that's proper programing.. (and what I do,) if the tool instance is a singleton instance (the only instance of the tool class that will be instantiated, which is usually the case,) ... then using class variables is fine.

                            If it's an instance of a class that will have more than one instance "live" at a time, then instance variables (beginning with only 1 @,) would be what you want to use. (That way each instance has it's own set of the variables.)

                            You can also use class constants (is place of global constants,) and local variables (in place of global variables.)

                            I'm not here much anymore.

                            1 Reply Last reply Reply Quote 0
                            • B Offline
                              bilianb
                              last edited by

                              @tig said:

                              pt=p.offset(vec, step)

                              Some help about the second argument \in API there is only one - vector\

                              Thanks

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

                                @bilianb said:

                                @tig said:

                                pt=p.offset(vec, step)

                                Some help about the second argument \in API there is only one - vector\

                                Take another look, at offset() not offset!()

                                Point3d.offset

                                I'm not here much anymore.

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

                                  point.offset() returns a new point from 'point', offset as specified BUT
                                  point.offset**!**() offsets the original 'point', as specified.

                                  TIG

                                  1 Reply Last reply Reply Quote 0
                                  • K Offline
                                    kyyu
                                    last edited by

                                    Ah, thanks for all the tips, guys! The line[1] vector will be useful, as long you are after the forward edge direction. I tried to use it yesterday, but couldn't because the polyline direction did matter in my case. And the second argument in .offset(). I didn't realize there was a second argument and was scaling my vector, instead. Actually, I only recently realized you could scale a vector by vector.length= and had been doing it a harder way, before.

                                    -Kwok

                                    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