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

Geom.intersect_line_line question

Scheduled Pinned Locked Moved Developers' Forum
15 Posts 4 Posters 557 Views
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.
  • B Offline
    Brett McAllister
    last edited by 22 Mar 2011, 08:13

    model = Sketchup.active_model
    entities = model.entities
    
    dpoint_1=[-3.989142.m, 3.877123.m, -0.m]
    dpoint_2=[-3.989142.m, -3.647636.m, -0.m]
    curve_array=[[-3.989142.m, 3.877123.m, -0.m],[-4.457867.m, 3.358428.m, -0.m],[-4.853319.m, 2.781918.m, -0.m],
    [-5.16845.m, 2.157867.m, -0.m],[-5.397644.m, 1.4974.m, -0.m],[-5.536815.m, 0.812289.m, -0.m],
    [-5.583482.m, 0.114744.m, -0.m],[-5.536815.m, -0.582801.m, -0.m],[-5.397644.m, -1.267913.m, -0.m],
    [-5.16845.m, -1.92838.m, -0.m],[-4.853319.m, -2.55243.m, -0.m],[-4.457867.m, -3.128941.m, -0.m],[-3.989142.m, -3.647636.m, -0.m]]
    curve_center=[-0.347015.m, 0.114744.m, -0.m]
    center= [-5.583482.m, 0.114744.m, -0.m]
    offset1_vec =center.vector_to dpoint_1
    offset2_vec =center.vector_to dpoint_2
    offset1 = center.offset offset1_vec,(0.2.m)
    offset2 = center.offset offset2_vec,(0.2.m)
    line1_vector = center.vector_to curve_center 
    line2_vector = center.vector_to curve_center 
    line1 = [offset1,line1_vector]
    line2 = [offset2,line2_vector]	
    
    entities.add_curve(curve_array)
    entities.add_cline(offset1,line1_vector)
    entities.add_cline(offset2,line2_vector)
    curve_array_length =(curve_array.length)-1
    
    curve_array_length.times do |point|
    line = [curve_array.at(point),curve_array.at(point +1) ]	
    pt1 = Geom.intersect_line_line(line, line1)
    pt2 = Geom.intersect_line_line(line, line2)
    puts "pt1;#{pt1}"
    puts "pt2;#{pt1}"
    end
    

    Hi Guys

    Just wondering why the above code sample returns an intersection with each code block iteration.
    If it was working correctly it should return 2 point3d's instead every line comparison is showing up as an intersection?
    I am sure there must be something basic that I have missed.
    Some times another set of eyes works wonders.

    Cheers Brett

    1 Reply Last reply Reply Quote 0
    • T Offline
      TIG Moderator
      last edited by 22 Mar 2011, 09:42

      It is working correctly.
      A 'line' *isn'*t an 'edge'.
      An 'edge' has a 'line' - a 'line' is simply an array of a point and a vector = [point, vector] which stretches infinitely.
      So if you have an edge intersecting a coplanar curve its line will intersect with the line of every edge in the curve, unless a curve-edge is exactly parallel with the intersecting edge - as then their lines will never intersect...
      I think what you actually want is to test for an edge intersecting other edges...
      First you narrow it down to the list of intersection-points you are getting - make an array of them as you collect them.
      Now iterate again through these points and check if they actually fall 'on' the 'intersecting-edge' itself rather than just its 'line'.
      To do this write a simple sub-method inside your main code...

      def is_point_on_edge?(point,edge)
        dis=edge.length
        spt=edge.start.position
        ept=edge.end.position
        if point.distance(spt)<=dis and point.distance(ept)<=dis
          return true
        else
          return false
        end
      end
      

      to use it simply use it inside a block iterating the points
      intersecting_points << point if is_point_on_edge?(point,edge)
      The test is true if the edges intersect at a vertex - Note how this could return two identical points for a start or end when that is the intersection point as a vertex is still 'on' the edge - after making the array of points [0/1/2/3/4 long (with possible duplicates at vertices) for an 'arc', but for a 'curve' that could zigzag this could be any number as it's edges pass across the intersecting edge...]you can then simply test for equality of any of them in the intersecting_points array and keep just one if so...
      is_point_on_edge? assumes you already established that 'point' is on 'edge.line' - you could readily combine the two tests into one if you wanted to... πŸ€“

      TIG

      1 Reply Last reply Reply Quote 0
      • B Offline
        Brett McAllister
        last edited by 22 Mar 2011, 18:54

        Thanks for the reply and suggestion Tig.
        For some reason I thought if you use two point3d's to form a line, you created a line segment, instead of an infinite line.
        The dangers of coding when your tired.

        Regards

        Brett

        1 Reply Last reply Reply Quote 0
        • T Offline
          TIG Moderator
          last edited by 22 Mar 2011, 19:53

          @brett mcallister said:

          Thanks for the reply and suggestion Tig.
          For some reason I thought if you use two point3d's to form a line, you created a line segment, instead of an infinite line.
          The dangers of coding when your tired.

          Regards

          Brett

          When you specify an edge by two points [confusingly it IS referred to as a 'line' in entities.add_line(pt0,pt1) πŸ˜’ ] then what you get IS an edge [or a 'line-segment' as you call it]... BUT when you get that edge's 'line' with edge.line then it becomes as infinitely long 'thing' - a vector through a fixed point... that could intersect with other 'lines' - to get 'physical' intersections of edges use a method like I outlined..........

          TIG

          1 Reply Last reply Reply Quote 0
          • H Offline
            honkinberry
            last edited by 5 Apr 2013, 20:21

            Here's my confusion with the Geom.intersect_line_line --
            when I'm processing a large file, that seems to be a huge amount of additional processing, with it always assuming the two lines are infinite.
            In particular,

            
            Geom.intersect_line_line(edge1.line,edge2.line)
            
            

            I can appreciate why it treats them as infinite, but what about this:

            
            Geom.intersect_line_line(edge1.vertices,edge2.vertices)
            
            

            If it's going to accept the vertices as parameters, why can't it treat them as fixed length?

            Put that on my wishlist.

            --J

            1 Reply Last reply Reply Quote 0
            • T Offline
              TIG Moderator
              last edited by 5 Apr 2013, 21:51

              A 3 item array, and the special kinds of arrays - i.e. a point and a vector both have xyz values.
              Many of Sketchup tools also accept a vertex as if it were a point, doing the vertex.position conversion for you.
              You can confuse Sketchup by passing something other than a the correct 'types' as a 'line' and thereby having it think it is one.
              A 'line' is a two item array containing a point and a vector [or the equivalent arrays for these].
              Every edge has a 'line' consisting of its start vertex position [point] and the vector from that point to its end vertex position.
              A 'line' in geometry is considered infinite.
              So two 'lines' might intersect and return a point, but that intersection-point may well not be on either of the edges that own those 'lines'...
              An edge has two vertices - so edge.vertices is effectively returning an array of two xyz arrays [vertex, vertex].
              This array of two vertices could be confused as the [point, vector] needed to define that 'line' BUT the second element is a NOT a vector, or anything equivalent to the edge's vector, so the result will be wrong !
              If you want to intersect the 'lines' of two edges and find out if its intersection-point [if successful] is physically on one [or both] of those two edges then there are several examples of code to do that. Rick Wilson did one to check if such a point was between the two points defined by the edge's start.position and end.position - i.e. it was on the edge, will additional flags for ignoring/accepting if the point were exactly at a start/end position...
              You don't have the right kind of arrays passed from two 'edge.vertices' to get a meaningful intersection with another pair of 'edge.vertices' - there is no vector information in there - that's why edge.line was invented ! It is relatively straightforward to get the two edges' lines, see if they intersect, and then see if the intersection-point falls on neither, one or two of the edges, even checking for start/end-point being coincident with it as valid or not...

              TIG

              1 Reply Last reply Reply Quote 0
              • H Offline
                honkinberry
                last edited by 5 Apr 2013, 22:27

                Thanks for clarifying a bit.
                It's just difficult for the likes of me, coming from a strong background in the CAD realm (AutoCAD and Revit).
                In AutoCAD, you have intersect(p1, p2, p3, p4, INF), where INF is the flag to treat the line segments as infinite.
                Further, you can very quickly build a selection of all objects within certain bounds.
                So coming from that experience, it just feels like I'm having to needlessly iterate through all entities in a model to perform some simple intersection checking.
                I've got a routine that does exactly what you describe, but with 1,500 edges in a model (which seems like a ridiculously small set), checking them all against each other just seems to take too long.

                --J

                1 Reply Last reply Reply Quote 0
                • thomthomT Offline
                  thomthom
                  last edited by 6 Apr 2013, 00:46

                  @honkinberry said:

                  I've got a routine that does exactly what you describe, but with 1,500 edges in a model (which seems like a ridiculously small set), checking them all against each other just seems to take too long.

                  What is that routine? Ruby is slow and it behaves in strange ways that I've often find surprising ways to optimize code. If you have a snippet we can have a look and have a stab at it.

                  Thomas Thomassen β€” SketchUp Monkey & Coding addict
                  List of my plugins and link to the CookieWare fund

                  1 Reply Last reply Reply Quote 0
                  • H Offline
                    honkinberry
                    last edited by 9 Apr 2013, 22:58

                    So given an array of edges 'elist' (imported from AutoCAD), I'm checking for intersections.

                    
                    elist.each do |e1|
                    	# so given this line, we look for intersections, to amend [p1,p2] to [p1,px,pn,p2]
                    	p1 = e1.start.position
                    	p2 = e1.end.position
                    	plist = [p1,p2]
                    	line1 = e1.line # [point . vector]
                    
                    	# for this line segment, compare to all other edges
                    	elist.each do |e2|
                    		if ( e1 != e2 ) # only if not the same edge of course
                    			line2 = e2.line # [point . vector]
                    			v1 = line1[1] # vector
                    			v2 = line2[1] # vector
                    					
                    			if ( v1 != v2 ) # if vectors are differnet, they aren't parallel
                    				int = Geom.intersect_line_line(line1,line2) # but assumes infinite!
                    				if ( int ) # make sure it's on both lines, and not an endpoint of line1
                    					z1 = e2.start.position
                    					z2 = e2.end.position
                    
                    					if ( !plist.include?(int) ) # not end point or already found
                    						if ( pointonline(int,p1,p2) ) # and on line1
                    							if ( pointonline(int,z1,z2) ) # and on line2
                    								# so adding our intersection to line 1
                    								plist << int
                    							end # if co-linear2
                    						end # if co-linear1
                    					end # if not end point
                    				end # if intersection
                    			end # if not parallel
                    
                    		end # if not same segment
                    	end # subloop
                    
                    	# ... do stuff with amended plist ...
                    end # entity loop
                    
                    

                    Missing is a standard helper function 'pointonline' which checks if given point falls on the given line segment.
                    Given about 1,500 edges, it seems it can easily take 30 seconds, which just feels far too long for my taste.
                    Many thanks if you have any tips to optimize it!

                    --J

                    1 Reply Last reply Reply Quote 0
                    • T Offline
                      TIG Moderator
                      last edited by 10 Apr 2013, 08:40

                      As I thought I explained...
                      Rick Wilson already made a function called something like
                      point.between_points?(pt1, pt2, cond)
                      So to see if a point on a an edge use that passing the edge.start.position and edge.end.position as the arguments - returns true or false: the ' cond' determines if the point that is 'exactly on' the edge's start/end is be be regarded as 'between' the given points...

                      I posted an example of this three years ago!
                      http://sketchucation.com/forums/viewtopic.php?p=243509#p243509

                      Note that changing/adding-to the built-in API class methods is probably not the best way to do it... BUT you can easily use the principal to make your own equivalent of this method, wrapped in your own module/class/methods...

                      TIG

                      1 Reply Last reply Reply Quote 0
                      • thomthomT Offline
                        thomthom
                        last edited by 10 Apr 2013, 11:41

                        Here's my version of it: https://bitbucket.org/thomthom/tt-library-2/src/56b237cae78615e19712faf22980293879916793/TT_Lib2/point3d.rb?at=Version%202.8#cl-28

                        Thomas Thomassen β€” SketchUp Monkey & Coding addict
                        List of my plugins and link to the CookieWare fund

                        1 Reply Last reply Reply Quote 0
                        • H Offline
                          honkinberry
                          last edited by 10 Apr 2013, 17:09

                          Sorry, guess I wasn't clear.
                          I have the pointonline function, and yes, that's easy, hence why I didn't bother including it.
                          My issue, is that in a model with 1,500 edges, the afore posted routine takes over 30 seconds to complete.
                          What I was hoping to do, was to optimize that routine if possible. As near as I can tell, I have to iterate through all edges, and compare each to all other edges, perform an intersect_line_line, and then check if that point falls on both edges. Correct?
                          I tried adding some basic coordinate validation, checking the X and Y coordinates of each edge end point first, to see if an intersection might be possible, but just took even more processing time.
                          I'm about to check the exact processing hit for each of the key tests, to see what is the big hangup, but thought I'd post what I have so far to see if there's any thing that jumps out as slow.

                          --J

                          1 Reply Last reply Reply Quote 0
                          • thomthomT Offline
                            thomthom
                            last edited by 10 Apr 2013, 17:17

                            Yea, Ruby is so slow that extra checks might just make it slower. Perhaps you can use the BoundingBox class?

                            In general, try to make the API methods to the most work as then it's performed in C++.

                            Thomas Thomassen β€” SketchUp Monkey & Coding addict
                            List of my plugins and link to the CookieWare fund

                            1 Reply Last reply Reply Quote 0
                            • H Offline
                              honkinberry
                              last edited by 10 Apr 2013, 18:52

                              I've tried a few variations now.
                              added a BoundingBox intersection testing, and if that hits, then do an intersect_line_line.
                              That ends up taking about 10% more time.
                              Then on a whim, I even removed the Vector checking, that saves time.
                              So no matter what I try, indeed, it seems the fastest is to get to the intersect_line_line as quickly as possible, as that's even faster than comparing the vectors first.

                              The really unfortunate part, now, is that I've found in trying to add a progress bar at the status line, that just seems to add a huge amount of time to the operation. I'd rather have a spinning pinwheel for 30 seconds than a progress bar for 2 minutes. I guess I could try optimizing the progress bar function, it looks like it's updating the status bar text every iteration, regardless of whether the percentage has changed.

                              Thanks as always for the tips!

                              --J

                              1 Reply Last reply Reply Quote 0
                              • thomthomT Offline
                                thomthom
                                last edited by 10 Apr 2013, 21:15

                                Then it sounds like moving to an Ruby C Extension is what might give real performance improvements.

                                Thomas Thomassen β€” SketchUp Monkey & Coding addict
                                List of my plugins and link to the CookieWare fund

                                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