QB64.org Forum

Active Forums => Programs => Topic started by: bplus on March 14, 2020, 08:48:35 pm

Title: Intersect of 2 lines carried a step further
Post by: bplus on March 14, 2020, 08:48:35 pm
I saw this challenge at Rosetta Code and solved here:
Code: QB64: [Select]
  1. _TITLE "lineIntersectLine" 'b+ 2020-03-14 Rosetta Code
  2. '  http://rosettacode.org/wiki/Find_the_intersection_of_two_lines
  3. ' This code also tells when there is no intersect between lines handling special case of vertical lines.
  4.  
  5. PRINT "Test normal intersect:"
  6. PRINT " Line on (4, 0) and (6, 10) intersect line on (0, 3) and (10, 7)"
  7. intersect = lineIntersectLine(4, 0, 6, 10, 0, 3, 10, 7, answX, answY) ' answer should be (5 , 5)
  8. IF intersect THEN PRINT "("; ts$(answX); ", "; ts$(answY); ")" ELSE PRINT "No point intersect."
  9. PRINT "Test intersect line with 1st line vertical:"
  10. PRINT " Line on (10, 0) and (10, 20) intersect line on (0, 20) and (20, 10)"
  11. intersect = lineIntersectLine%(10, 0, 10, 20, 0, 20, 20, 10, answX, answY) 'intersect should be (10 , 15)
  12. IF intersect THEN PRINT "("; ts$(answX); ", "; ts$(answY); ")" ELSE PRINT "No point intersect."
  13. PRINT "Test intersect with 2nd line vertical:"
  14. PRINT " Line on (0, 20) and (20, 10) intersect line on (10, 0) and (10, 5)"
  15. intersect = lineIntersectLine%(0, 20, 20, 10, 10, 0, 10, 5, answX, answY) 'intersect should be (10 , 15)
  16. IF intersect THEN PRINT "("; ts$(answX); ", "; ts$(answY); ")" ELSE PRINT "No point intersect."
  17. PRINT "Test intersect with both lines vertical:"
  18. PRINT " Line on (0, 20) and (0, 10) intersect line on (10, 0) and (10, 5)"
  19. intersect = lineIntersectLine%(0, 20, 0, 10, 10, 0, 10, 5, answX, answY) 'intersect should be none
  20. IF intersect THEN PRINT "("; ts$(answX); ", "; ts$(answY); ")" ELSE PRINT "No point intersect."
  21.  
  22. ' this function needs: SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept)
  23. FUNCTION lineIntersectLine% (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  24.     IF ax1 = ax2 THEN 'line a is vertical
  25.         IF bx1 = bx2 THEN
  26.             EXIT FUNCTION 'no intersect
  27.         ELSE
  28.             ix = ax1
  29.             slopeYintersect bx1, by1, bx2, by2, m2, y02
  30.             iy = m2 * ix + y02
  31.             lineIntersectLine% = -1 'signal a point was found
  32.             EXIT FUNCTION
  33.         END IF
  34.     ELSE
  35.         slopeYintersect ax1, ay1, ax2, ay2, m1, y01 ' -m = a, 1 = b, y0 = c  std form
  36.     END IF
  37.     IF bx1 = bx2 THEN 'b is vertical
  38.         ix = bx1: iy = m1 * ix + y01: lineIntersectLine% = -1 'signal a point was found
  39.         EXIT FUNCTION
  40.     ELSE
  41.         slopeYintersect bx1, by1, bx2, by2, m2, y02 ' -m = a, 1 = b, y0 = c  std form
  42.     END IF
  43.     d = -m1 - -m2 ' if = 0 then parallel because slopes are same
  44.     IF d THEN ix = (y01 - y02) / d: iy = (-m1 * y02 - -m2 * y01) / d
  45.     lineIntersectLine% = -1 'signal a point was found
  46.  
  47. 'Slope and Y-intersect for non vertical lines,
  48. ' if x1 = x2 the line is vertical don't call this sub
  49. ' because slope calculation would cause division by 0 error.
  50. SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept) 'check x1 <> x2 first!
  51.     slope = (Y2 - Y1) / (X2 - X1): Yintercept = slope * (0 - X1) + Y1
  52.  
  53. FUNCTION ts$ (n)
  54.     ts$ = _TRIM$(STR$(INT(100 * n) / 100))
  55.  
  56.  

And then took it a step further by finding the intersect of two line segments if there is one:
Code: QB64: [Select]
  1. _TITLE "Two Line Segments Intersect" 'b+ 2020-03-14
  2. ' Just worked Rosetta Code for Line Intersect Line
  3. ' but what if we want to know if two line segments intersect?
  4. CONST xmax = 800, ymax = 600
  5. SCREEN _NEWIMAGE(xmax, ymax, 32)
  6. _DELAY .25
  7.     ax1 = xmax * RND: ay1 = ymax * RND
  8.     ax2 = xmax * RND: ay2 = ymax * RND
  9.     bx1 = xmax * RND: by1 = ymax * RND
  10.     bx2 = xmax * RND: by2 = ymax * RND
  11.     LINE (ax1, ay1)-(ax2, ay2), &HFFFF0000
  12.     LINE (bx1, by1)-(bx2, by2), &HFF0000FF
  13.     PRINT "Segments ("; ts$(ax1); ", "; ts$(ay1); ") ("; ts$(ax2); ", ";_
  14.      ts$(ay2); ") and ("; ts$(bx1); ", "; ts$(by1); ") ("; ts$(bx2); ", "; ts$(by2); ")"
  15.     intersect = twoLineSegmentsIntersect%(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  16.     IF intersect THEN
  17.         PRINT " intersect at ("; ts$(ix); ", "; ts$(iy); ")."
  18.         CIRCLE (ix, iy), 3, &HFFFFFF00
  19.     ELSE
  20.         PRINT "Do not Intersect."
  21.     END IF
  22.     INPUT "Press enter for another demo, any + enter to quit...", again$
  23.     CLS
  24. LOOP UNTIL LEN(again$)
  25.  
  26. 'This function needs: FUNCTION lineIntersectLine% (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  27. ' which in turn needs: SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept) 'check x1 <> x2 first!
  28. FUNCTION twoLineSegmentsIntersect% (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  29.     intersect = lineIntersectLine%(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  30.     IF intersect THEN 'ok we know the lines  intersect
  31.         IF ax1 < ax2 THEN aMinX = ax1: aMaxX = ax2 ELSE aMinX = ax2: aMaxX = ax1
  32.         IF bx1 < bx2 THEN bMinX = bx1: bMaxX = bx2 ELSE bMinX = bx2: bMaxX = bx1
  33.         IF (aMinX <= ix AND ix <= aMaxX) AND (bMinX <= ix AND ix <= bMaxX) THEN
  34.             twoLineSegmentsIntersect% = -1
  35.         END IF
  36.     END IF
  37.  
  38. ' this function needs: SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept)
  39. FUNCTION lineIntersectLine% (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  40.     IF ax1 = ax2 THEN 'line a is vertical
  41.         IF bx1 = bx2 THEN
  42.             EXIT FUNCTION 'no intersect
  43.         ELSE
  44.             ix = ax1
  45.             slopeYintersect bx1, by1, bx2, by2, m2, y02
  46.             iy = m2 * ix + y02
  47.             lineIntersectLine% = -1 'signal a point was found
  48.             EXIT FUNCTION
  49.         END IF
  50.     ELSE
  51.         slopeYintersect ax1, ay1, ax2, ay2, m1, y01 ' -m = a, 1 = b, y0 = c  std form
  52.     END IF
  53.     IF bx1 = bx2 THEN 'b is vertical
  54.         ix = bx1: iy = m1 * ix + y01: lineIntersectLine% = -1 'signal a point was found
  55.         EXIT FUNCTION
  56.     ELSE
  57.         slopeYintersect bx1, by1, bx2, by2, m2, y02 ' -m = a, 1 = b, y0 = c  std form
  58.     END IF
  59.     d = -m1 - -m2 ' if = 0 then parallel because slopes are same
  60.     IF d THEN ix = (y01 - y02) / d: iy = (-m1 * y02 - -m2 * y01) / d
  61.     lineIntersectLine% = -1 'signal a point was found
  62.  
  63. 'Slope and Y-intersect for non vertical lines,
  64. ' if x1 = x2 the line is vertical don't call this sub
  65. ' because slope calculation would cause division by 0 error.
  66. SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept) 'check x1 <> x2 first!
  67.     slope = (Y2 - Y1) / (X2 - X1): Yintercept = slope * (0 - X1) + Y1
  68.  
  69. FUNCTION ts$ (n)
  70.     ts$ = _TRIM$(STR$(INT(100 * n) / 100))
  71.  
  72.  
Title: Re: Intersect of 2 lines carried a step further
Post by: TempodiBasic on March 15, 2020, 04:14:25 am
Hi Bplus
I like very much all your energy....and I have difficult to follow your posts.

In the intersecting test of two line I think it is useful also in a graphic tool or in a game...
and looking at your code it seems you don't manage if the two segment are overlapped... so I test your code
and it seems to be so-
Code: QB64: [Select]
  1. _TITLE "lineIntersectLine" 'b+ 2020-03-14 Rosetta Code
  2. '  http://rosettacode.org/wiki/Find_the_intersection_of_two_lines
  3. ' This code also tells when there is no intersect between lines handling special case of vertical lines.
  4.  
  5. PRINT "Test normal intersect:"
  6. PRINT " Line on (4, 0) and (6, 10) intersect line on (0, 3) and (10, 7)"
  7. intersect = lineIntersectLine(4, 0, 6, 10, 0, 3, 10, 7, answX, answY) ' answer should be (5 , 5)
  8. IF intersect THEN PRINT "("; ts$(answX); ", "; ts$(answY); ")" ELSE PRINT "No point intersect."
  9. PRINT "Test intersect line with 1st line vertical:"
  10. PRINT " Line on (10, 0) and (10, 20) intersect line on (0, 20) and (20, 10)"
  11. intersect = lineIntersectLine%(10, 0, 10, 20, 0, 20, 20, 10, answX, answY) 'intersect should be (10 , 15)
  12. IF intersect THEN PRINT "("; ts$(answX); ", "; ts$(answY); ")" ELSE PRINT "No point intersect."
  13. PRINT "Test intersect with 2nd line vertical:"
  14. PRINT " Line on (0, 20) and (20, 10) intersect line on (10, 0) and (10, 5)"
  15. intersect = lineIntersectLine%(0, 20, 20, 10, 10, 0, 10, 5, answX, answY) 'intersect should be (10 , 15)
  16. IF intersect THEN PRINT "("; ts$(answX); ", "; ts$(answY); ")" ELSE PRINT "No point intersect."
  17. PRINT "Test intersect with both lines vertical:"
  18. PRINT " Line on (0, 20) and (0, 10) intersect line on (10, 0) and (10, 5)"
  19. intersect = lineIntersectLine%(0, 20, 0, 10, 10, 0, 10, 5, answX, answY) 'intersect should be none
  20. IF intersect THEN PRINT "("; ts$(answX); ", "; ts$(answY); ")" ELSE PRINT "No point intersect."
  21. PRINT "overlapping test TdB"
  22. PRINT " Line on (4, 0) and (6, 10) intersect line on (4, 0) and (6,10)"
  23. intersect = lineIntersectLine(4, 0, 6, 10, 4, 0, 6, 10, answX, answY) ' answer should be (5 , 5)
  24. IF intersect THEN PRINT "("; ts$(answX); ", "; ts$(answY); ")" ELSE PRINT "No point intersect."
  25.  
  26.  
  27. ' this function needs: SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept)
  28. FUNCTION lineIntersectLine% (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  29.     IF ax1 = ax2 THEN 'line a is vertical
  30.         IF bx1 = bx2 THEN
  31.             EXIT FUNCTION 'no intersect
  32.         ELSE
  33.             ix = ax1
  34.             slopeYintersect bx1, by1, bx2, by2, m2, y02
  35.             iy = m2 * ix + y02
  36.             lineIntersectLine% = -1 'signal a point was found
  37.             EXIT FUNCTION
  38.         END IF
  39.     ELSE
  40.         slopeYintersect ax1, ay1, ax2, ay2, m1, y01 ' -m = a, 1 = b, y0 = c  std form
  41.     END IF
  42.     IF bx1 = bx2 THEN 'b is vertical
  43.         ix = bx1: iy = m1 * ix + y01: lineIntersectLine% = -1 'signal a point was found
  44.         EXIT FUNCTION
  45.     ELSE
  46.         slopeYintersect bx1, by1, bx2, by2, m2, y02 ' -m = a, 1 = b, y0 = c  std form
  47.     END IF
  48.     d = -m1 - -m2 ' if = 0 then parallel because slopes are same
  49.     IF d THEN ix = (y01 - y02) / d: iy = (-m1 * y02 - -m2 * y01) / d
  50.     lineIntersectLine% = -1 'signal a point was found
  51.  
  52. 'Slope and Y-intersect for non vertical lines,
  53. ' if x1 = x2 the line is vertical don't call this sub
  54. ' because slope calculation would cause division by 0 error.
  55. SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept) 'check x1 <> x2 first!
  56.     slope = (Y2 - Y1) / (X2 - X1): Yintercept = slope * (0 - X1) + Y1
  57.  
  58. FUNCTION ts$ (n)
  59.     ts$ = _TRIM$(STR$(INT(100 * n) / 100))
  60.  
Waiting your thoughts
Title: Re: Intersect of 2 lines carried a step further
Post by: bplus on March 15, 2020, 10:56:01 am
OK I guess I did miss the case where lines (and segments) might overlap and be on the same line.

Thanks for your interest :)
Title: Re: Intersect of 2 lines carried a step further
Post by: TempodiBasic on March 15, 2020, 12:37:17 pm
Thanks to share your works, your time, your interests!
In our eucledian geometry, two segments can  share  no point, one point and all points ....so in an universal application of your function I have thought that this rare case (overlapping) may  be included. But it is a my thought. :-)
Title: Re: Intersect of 2 lines carried a step further
Post by: bplus on March 15, 2020, 01:01:01 pm
OK here is the first part of code testing for intersecting lines, corrected with TempodiBasic's test case:
There are 3 results returned now as noted in comments section of code.

Code: QB64: [Select]
  1. _TITLE "lineIntersectLine" 'b+ 2020-03-14 Rosetta Code
  2. '  http://rosettacode.org/wiki/Find_the_intersection_of_two_lines
  3. ' This code also tells when there is no intersect between lines handling special case of vertical lines.
  4.  
  5. ' 2020-03-15 overhaul this code to handle the case that all the points are on the same line.
  6. ' Return -1, if all points are on the same line
  7. ' Return 0, if no intersect
  8. ' Return 1, if the intersect is a single point (lines cross).
  9.  
  10. PRINT "Test normal intersect: answ should be: (5, 5)"
  11. printResultOfLineIntersectLine 4, 0, 6, 10, 0, 3, 10, 7
  12. PRINT "Test intersect line with 1st line vertical: answ should be: (10, 15)"
  13. printResultOfLineIntersectLine 10, 0, 10, 20, 0, 20, 20, 10
  14. PRINT "Test intersect with 2nd line vertical: answ should be: (10, 15) again."
  15. printResultOfLineIntersectLine 0, 20, 20, 10, 10, 0, 10, 5
  16. PRINT "Test intersect with both lines vertical: answ should be: No intersect."
  17. printResultOfLineIntersectLine 0, 20, 0, 10, 10, 0, 10, 5
  18. PRINT "TempodiBasic test, 4 points on same line, try 2 vertical lines, same points:"
  19. PRINT "Answer should be: Lines are the same."
  20. printResultOfLineIntersectLine 5, 10, 5, 20, 5, 10, 5, 20
  21. PRINT "Test points off same sloped line: answ should be: Lines are the same."
  22. printResultOfLineIntersectLine 2, 4, 6, 12, 10, 20, 15, 30
  23.  
  24. SUB printResultOfLineIntersectLine (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2)
  25.     PRINT "Lines on ("; ts$(ax1); ", "; ts$(ay1); ") ("; ts$(ax2); ", ";_
  26.      ts$(ay2); ") and ("; ts$(bx1); ", "; ts$(by1); ") ("; ts$(bx2); ", "; ts$(by2); ")"
  27.     intersect = lineIntersectLine%(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, answX, answY)
  28.     IF intersect = 0 THEN
  29.         PRINT "No intersection."
  30.     ELSEIF intersect = -1 THEN
  31.         PRINT "Lines are the same."
  32.     ELSEIF intersect = 1 THEN
  33.         PRINT "Lines intersect at ("; ts$(answX); ", "; ts$(answY); ")"
  34.     END IF
  35.  
  36. ' this function needs: SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept)
  37. FUNCTION lineIntersectLine% (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  38.     IF ax1 = ax2 THEN 'line a is vertical
  39.         IF bx1 = bx2 THEN ' b is vertical
  40.             IF ax1 = bx1 THEN lineIntersectLine% = -1 ' if x's are same it is same vertical line
  41.             EXIT FUNCTION '
  42.         ELSE
  43.             ix = ax1
  44.             slopeYintersect bx1, by1, bx2, by2, m2, y02
  45.             iy = m2 * ix + y02
  46.             lineIntersectLine% = 1 'signal a point was found
  47.             EXIT FUNCTION
  48.         END IF
  49.     ELSE
  50.         slopeYintersect ax1, ay1, ax2, ay2, m1, y01 ' -m = a, 1 = b, y0 = c  std form
  51.     END IF
  52.     IF bx1 = bx2 THEN 'b is vertical
  53.         ix = bx1: iy = m1 * ix + y01: lineIntersectLine% = 1 'signal a point was found
  54.         EXIT FUNCTION
  55.     ELSE
  56.         slopeYintersect bx1, by1, bx2, by2, m2, y02 ' -m = a, 1 = b, y0 = c  std form
  57.     END IF
  58.     d = -m1 - -m2 ' if = 0 then parallel or equal because slopes are same
  59.     IF d <> 0 THEN
  60.         ix = (y01 - y02) / d: iy = (-m1 * y02 - -m2 * y01) / d
  61.         lineIntersectLine% = 1 'signal one intersect point was found
  62.     ELSE 'same line or parallel? if y0 are same they are the same
  63.         IF y01 = y02 THEN lineIntersectLine% = -1 'signal same line!
  64.     END IF
  65.  
  66. 'Slope and Y-intersect for non vertical lines,
  67. ' if x1 = x2 the line is vertical don't call this sub
  68. ' because slope calculation would cause division by 0 error.
  69. SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept) 'check x1 <> x2 first!
  70.     slope = (Y2 - Y1) / (X2 - X1): Yintercept = slope * (0 - X1) + Y1
  71.  
  72. FUNCTION ts$ (n)
  73.     ts$ = _TRIM$(STR$(INT(100 * n) / 100))
  74.  
  75.  
Title: Re: Intersect of 2 lines carried a step further
Post by: TempodiBasic on March 15, 2020, 01:22:42 pm
Great Bplus
as always  you're fast, rapid and accurate!
Title: Re: Intersect of 2 lines carried a step further
Post by: bplus on March 15, 2020, 01:24:33 pm
Thanks, that was a good catch TempodiBasic. I will likely have the line segments code reworked this afternoon.
Title: Re: Intersect of 2 lines carried a step further
Post by: bplus on March 15, 2020, 10:48:25 pm
Well doing overlapping Line Segments turned out to be a bear, lots of vertical line tests because tricky case:
Code: QB64: [Select]
  1. _TITLE "Two Line Segments Intersect" 'b+ 2020-03-14
  2. ' Just worked Rosetta Code for Line Intersect Line
  3. ' but what if we want to know if two line segments intersect?
  4.  
  5. '2020-03-15 rework this code so we identify points all on same line and
  6. ' if there is overlap of line segments say the two x endpoints of the segments
  7. ' otherwise, if there is an intersect of 2 line segments say the point x, y.
  8. ' Return 0 no intersect or overlap
  9. ' Return 1 if intersect and ix, iy point of intersect
  10. ' Return -1 if segments are on same and there is overlap: ix = overlap start x, iy overlap end x
  11.  
  12. CONST xmax = 1200, ymax = 700
  13. SCREEN _NEWIMAGE(xmax, ymax, 32)
  14. _DELAY .25
  15. DIM ax1 AS INTEGER, ax2 AS INTEGER, ay1 AS INTEGER, ay2 AS INTEGER
  16. DIM bx1 AS INTEGER, bx2 AS INTEGER, by1 AS INTEGER, by2 AS INTEGER
  17.     restartA:
  18.     CLS
  19.     IF RND < .5 THEN 'throw in some vertical lines
  20.         ax1 = (xmax - 20) * RND + 10: ay1 = (ymax - 60) * RND + 50
  21.         ax2 = ax1: ay2 = (ymax - 60) * RND + 50
  22.     ELSE
  23.         ax1 = (xmax - 20) * RND + 10: ay1 = (ymax - 60) * RND + 50
  24.         ax2 = (xmax - 20) * RND + 10: ay2 = (ymax - 60) * RND + 50
  25.     END IF
  26.     IF _HYPOT(ax1 - ax2, ay1 - ay2) < 50 THEN GOTO restartA
  27.  
  28.     IF RND < .5 THEN 'get some points on same line
  29.         LOCATE 3, 80: PRINT "Blue Points are on same line as Red."
  30.         slopeYintersect ax1, ay1, ax2, ay2, slope1, Yintercept1
  31.         bx1 = (xmax - 20) * RND + 10: by1 = bx1 * slope1 + Yintercept1
  32.         bx2 = (xmax - 20) * RND + 10: by2 = bx2 * slope1 + Yintercept1
  33.     ELSE
  34.         IF RND < .5 THEN 'throw in some verticals
  35.             bx1 = (xmax - 20) * RND + 10: by1 = (ymax - 60) * RND + 50
  36.             bx2 = bx1: by2 = (ymax - 60) * RND + 50
  37.         ELSE
  38.             bx1 = (xmax - 20) * RND + 10: by1 = (ymax - 60) * RND + 50
  39.             bx2 = (xmax - 20) * RND + 10: by2 = (ymax - 60) * RND + 50
  40.         END IF
  41.     END IF
  42.     IF bx1 < 10 OR bx1 > xmax - 10 THEN GOTO restartA
  43.     IF bx2 < 10 OR bx2 > xmax - 10 THEN GOTO restartA
  44.     IF by1 < 50 OR by1 > ymax - 10 THEN GOTO restartA
  45.     IF by2 < 50 OR by2 > ymax - 10 THEN GOTO restartA
  46.     IF _HYPOT(bx1 - bx2, by1 - by2) < 50 THEN GOTO restartA
  47.  
  48.     LINE (ax1, ay1)-(ax2, ay2), &HFFFF0000
  49.     CIRCLE (ax1, ay1), 4, &HFFFF0000
  50.     CIRCLE (ax2, ay2), 4, &HFFFF0000
  51.  
  52.     LINE (bx1, by1)-(bx2, by2), &HFF0000FF
  53.     CIRCLE (bx1, by1), 4, &HFF0000FF
  54.     CIRCLE (bx2, by2), 4, &HFF0000FF
  55.  
  56.     LOCATE 1, 1
  57.     PRINT "Segments ("; ts$(ax1); ", "; ts$(ay1); ") ("; ts$(ax2); ", ";_
  58.      ts$(ay2); ") and ("; ts$(bx1); ", "; ts$(by1); ") ("; ts$(bx2); ", "; ts$(by2); ")"
  59.     intersect = twoLineSegmentsIntersect%(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  60.     IF intersect = -1 THEN
  61.         PRINT " Segments overlap between min x at "; ts$(ix); " and max x at "; ts$(iy) '< not a "y" here
  62.         LINE (ix, 0)-(iy, ymax), &H22FFFF00, BF
  63.     ELSEIF intersect = 1 THEN
  64.         PRINT " Segments intersect at ("; ts$(ix); ", "; ts$(iy); ")."
  65.         CIRCLE (ix, iy), 3, &HFFFFFF00
  66.     ELSEIF intersect = 0 THEN
  67.         PRINT " Segments do not Intersect or Overlap."
  68.     END IF
  69.     INPUT "Press enter for another demo, any + enter to quit...", again$
  70.     CLS
  71. LOOP UNTIL LEN(again$)
  72.  
  73. 'This function needs: FUNCTION lineIntersectLine% (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  74. ' which in turn needs: SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept) 'check x1 <> x2 first!
  75. FUNCTION twoLineSegmentsIntersect% (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  76.     intersect = lineIntersectLine%(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  77.     IF ax1 < ax2 THEN aMinX = ax1: aMaxX = ax2 ELSE aMinX = ax2: aMaxX = ax1
  78.     IF ay1 < ay2 THEN aMinY = ay1: aMaxY = ay2 ELSE aMinY = ay2: aMaxY = ay1
  79.     IF bx1 < bx2 THEN bMinX = bx1: bMaxX = bx2 ELSE bMinX = bx2: bMaxX = bx1
  80.     IF by1 < by2 THEN bMinY = by1: bMaxY = by2 ELSE bMinY = by2: bMaxY = by1
  81.     IF intersect = 0 THEN 'no  intersect
  82.         twoLineSegmentsIntersect% = 0
  83.     ELSEIF intersect = 1 THEN
  84.         IF ax1 = ax2 THEN 'is iy between
  85.             IF iy < aMinY OR iy > aMaxY OR ix < bMinX OR ix > bMaxX THEN twoLineSegmentsIntersect% = 0 ELSE twoLineSegmentsIntersect% = 1
  86.         ELSEIF bx1 = bx2 THEN
  87.             IF iy < bMinY OR iy > bMaxY OR ix < aMinX OR ix > aMaxX THEN twoLineSegmentsIntersect% = 0 ELSE twoLineSegmentsIntersect% = 1
  88.         ELSE
  89.             IF (aMinX <= ix AND ix <= aMaxX) AND (bMinX <= ix AND ix <= bMaxX) THEN twoLineSegmentsIntersect% = 1 ELSE twoLineSegmentsIntersect% = 0
  90.         END IF
  91.     ELSEIF intersect = -1 THEN 'segments are on same line get over lap section
  92.         IF aMinX < bMinX THEN
  93.             IF aMaxX < bMinX THEN
  94.                 twoLineSegmentsIntersect% = 0
  95.             ELSE
  96.                 twoLineSegmentsIntersect% = -1
  97.                 ix = bMinX
  98.                 IF aMaxX > bMaxX THEN iy = bMaxX ELSE iy = aMaxX
  99.             END IF
  100.         ELSE 'aMinX >= bMinX
  101.             IF aMinX > bMaxX THEN
  102.                 twoLineSegmentsIntersect% = 0
  103.             ELSE
  104.                 twoLineSegmentsIntersect% = -1
  105.                 ix = aMinX
  106.                 IF bMaxX > aMaxX THEN iy = aMaxX ELSE iy = bMaxX
  107.             END IF
  108.         END IF
  109.     END IF
  110.  
  111. ' this function needs: SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept)
  112. FUNCTION lineIntersectLine% (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  113.     IF ax1 = ax2 THEN 'line a is vertical
  114.         IF bx1 = bx2 THEN ' b is vertical
  115.             IF ax1 = bx1 THEN lineIntersectLine% = -1 ' if x's are same it is same vertical line
  116.             EXIT FUNCTION '
  117.         ELSE
  118.             ix = ax1
  119.             slopeYintersect bx1, by1, bx2, by2, m2, y02
  120.             iy = m2 * ix + y02
  121.             lineIntersectLine% = 1 'signal a point was found
  122.             EXIT FUNCTION
  123.         END IF
  124.     ELSE
  125.         slopeYintersect ax1, ay1, ax2, ay2, m1, y01 ' -m = a, 1 = b, y0 = c  std form
  126.     END IF
  127.     IF bx1 = bx2 THEN 'b is vertical
  128.         ix = bx1: iy = m1 * ix + y01: lineIntersectLine% = 1 'signal a point was found
  129.         EXIT FUNCTION
  130.     ELSE
  131.         slopeYintersect bx1, by1, bx2, by2, m2, y02 ' -m = a, 1 = b, y0 = c  std form
  132.     END IF
  133.     d = -m1 - -m2 ' if = 0 then parallel or equal because slopes are same
  134.     IF ABS(d) > .2 THEN 'otherwise about 0
  135.         ix = (y01 - y02) / d: iy = (-m1 * y02 - -m2 * y01) / d
  136.         lineIntersectLine% = 1 'signal one intersect point was found
  137.     ELSE 'same line or parallel? if y0 are same they are the same
  138.         IF ABS(y01 - y02) < 5 THEN lineIntersectLine% = -1 'signal same line!
  139.     END IF
  140.  
  141. 'Slope and Y-intersect for non vertical lines,
  142. ' if x1 = x2 the line is vertical don't call this sub
  143. ' because slope calculation would cause division by 0 error.
  144. SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept) 'check x1 <> x2 first!
  145.     slope = (Y2 - Y1) / (X2 - X1): Yintercept = slope * (0 - X1) + Y1
  146.  
  147. FUNCTION ts$ (n)
  148.     ts$ = _TRIM$(STR$(INT(100 * n) / 100))
  149.  
  150.  

Thanks to round-off errors (I think), it misses overlapping segments on occasion.
Title: Re: Intersect of 2 lines carried a step further
Post by: EricE on March 16, 2020, 02:24:54 am
Here is a solution for the case when the two lines intersect at one point.
The code uses the parametric representation of lines.

Code: QB64: [Select]
  1. PRINT "Test normal intersect:"
  2. PRINT " Line on (4, 0) and (6, 10) intersect line on (0, 3) and (10, 7)"
  3.  
  4. ' A(x1, y1), B(x2, y2),
  5. ' C(x3, y3), D(x4, y4)
  6.  
  7. DIM A(1 TO 2) AS DOUBLE
  8. DIM B(1 TO 2) AS DOUBLE
  9. DIM C(1 TO 2) AS DOUBLE
  10. DIM D(1 TO 2) AS DOUBLE
  11. DIM v1(1 TO 2) AS DOUBLE
  12. DIM v2(1 TO 2) AS DOUBLE
  13.  
  14. DIM invV(1 TO 2, 1 TO 2) AS DOUBLE
  15.  
  16. ' Intersection point
  17. DIM Xr(1 TO 2) AS DOUBLE
  18. DIM Xs(1 TO 2) AS DOUBLE
  19.  
  20. ' Test Example
  21. A(1) = 4.0
  22. A(2) = 0.0
  23. B(1) = 6.0
  24. B(2) = 10.0
  25. '---
  26. C(1) = 0.0
  27. C(2) = 3.0
  28. D(1) = 10.0
  29. D(2) = 7.0
  30.  
  31. ' directed segment AB
  32. v1(1) = B(1) - A(1)
  33. v1(2) = B(2) - A(2)
  34.  
  35. ' directed segment CD
  36. v2(1) = D(1) - C(1)
  37. v2(2) = D(2) - C(2)
  38.  
  39. ' Parametric line equations
  40. '          Xr = A + v1*r
  41. '          Xs = C + v2*s
  42. '
  43. ' Line intersection criteria
  44. '    A + v1*r = C + v2*s
  45. ' Determine scalars r, s
  46. '
  47. ' Matrix equation
  48. '         A-C = [-v1, v2]*[r, s]^t
  49. ' Define    V = [-v1, v2]
  50. '        invV = V^-1
  51. '    [r, s]^t = invV*(A - C)
  52.  
  53. ' Calculate invV([-v1, v2])
  54. '
  55. ' Compute determinant
  56. DetV = -v1(1) * v2(2) + v2(1) * v1(2)
  57. ' DetV must not be zero
  58.  
  59. invV(1, 1) = v2(2) / DetV
  60. invV(2, 1) = v1(2) / DetV
  61. invV(1, 2) = -v2(1) / DetV
  62. invV(2, 2) = -v1(1) / DetV
  63.  
  64. r = invV(1, 1) * (A(1) - C(1)) + invV(1, 2) * (A(2) - C(2))
  65. s = invV(2, 1) * (A(1) - C(1)) + invV(2, 2) * (A(2) - C(2))
  66.  
  67. ' Intersection point
  68. Xr(1) = A(1) + r * v1(1)
  69. Xr(2) = A(2) + r * v1(2)
  70.  
  71. Xs(1) = C(1) + s * v2(1)
  72. Xs(2) = C(2) + s * v2(2)
  73.  
  74. PRINT "Intersection Point:"
  75. ' (Xr(1), Xr(2)) and (Xs(1), Xs(2)) are the coordinates of the same point
  76. PRINT Xr(1), Xr(2)
  77. PRINT Xs(1), Xs(2)
  78.  
  79.  
  80.  

Title: Re: Intersect of 2 lines carried a step further
Post by: TerryRitchie on March 16, 2020, 02:39:33 am
When creating the vector engine for Widescreen Asteroids I wrote routines to detect line intersection. Here they are if you wish to use any of the code from them. It detects line intersection as well as the lines being collinear.

Plug the values into ObjIntersect() and it will return either -1 (TRUE) or 0 (FALSE)

Code: QB64: [Select]
  1.  
  2. TYPE POINTTYPE '                            X,Y point with integer precision
  3.     x AS INTEGER
  4.     y AS INTEGER
  5.  
  6.  
  7. '**********************************************************************************************************************
  8. FUNCTION ObjIntersect (p1x AS INTEGER, p1y AS INTEGER, q1x AS INTEGER, q1y AS INTEGER, p2x AS INTEGER, p2y AS INTEGER, q2x AS INTEGER, q2y AS INTEGER) ' OBJINTERSECT
  9.     '******************************************************************************************************************
  10.     '* Returns TRUE if line segments p1q1 and p2q2 intersect.                    *
  11.     '*                                                                           *
  12.     '* p1x,p1y - starting X,Y coordinates of segment 1                           *
  13.     '* q1x,q1y -   ending X,Y coordinates of segment 1                           *
  14.     '* p2x,p2y - starting X,Y coordinates of segment 2                           *
  15.     '* q2x,q2y -   ending X,Y coordinates of segment 2                           *
  16.     '*                                                                           *
  17.     '* This function was created from example code found at:                     *
  18.     '* https://www.geeksforgeeks.org/check-if-two-given-line-segments-intersect/ *
  19.     '*****************************************************************************
  20.  
  21.     DIM p1 AS POINTTYPE ' line 1 coordinate X,Y pairs
  22.     DIM q1 AS POINTTYPE
  23.     DIM p2 AS POINTTYPE ' line 2 coordinate X,Y pairs
  24.     DIM q2 AS POINTTYPE
  25.     DIM o1 AS INTEGER '   four orientations
  26.     DIM o2 AS INTEGER
  27.     DIM o3 AS INTEGER
  28.     DIM o4 AS INTEGER
  29.  
  30.     p1.x = p1x: p1.y = p1y '            line 1 start X,Y
  31.     q1.x = q1x: q1.y = q1y '            line 1   end X,Y
  32.     p2.x = p2x: p2.y = p2y '            line 2 start X,Y
  33.     q2.x = q2x: q2.y = q2y '            line 2   end X,Y
  34.     o1 = Orientation(p1, q1, p2) '      get the four orientations needed for general and special cases
  35.     o2 = Orientation(p1, q1, q2)
  36.     o3 = Orientation(p2, q2, p1)
  37.     o4 = Orientation(p2, q2, q1)
  38.     IF o1 <> o2 THEN
  39.         IF o3 <> o4 THEN '              general case
  40.             ObjIntersect = -1
  41.             EXIT FUNCTION
  42.         END IF
  43.     END IF
  44.     IF o1 = 0 THEN
  45.         IF onSegment(p1, p2, q1) THEN ' p1, q1, and p2 are colinear and p2 lies on segment p1q1
  46.             ObjIntersect = -1
  47.             EXIT FUNCTION
  48.         END IF
  49.     END IF
  50.     IF o2 = 0 THEN
  51.         IF onSegment(p1, q2, q1) THEN ' p1, q1, and q2 are colinear and q2 lies on segment p1q1
  52.             ObjIntersect = -1
  53.             EXIT FUNCTION
  54.         END IF
  55.     END IF
  56.     IF o3 = 0 THEN
  57.         IF onSegment(p2, p1, q2) THEN ' p2, q2, and p1 are colinear and p1 lies on segment p2q2
  58.             ObjIntersect = -1
  59.             EXIT FUNCTION
  60.         END IF
  61.     END IF
  62.     IF o4 = 0 THEN
  63.         IF onSegment(p2, q1, q2) THEN ' p2, q2, and q1 are colinear and q1 lies on segment p2q2
  64.             ObjIntersect = -1
  65.             EXIT FUNCTION
  66.         END IF
  67.     END IF
  68.     ObjIntersect = 0 '                  doesn't fall into any of the above cases
  69.  
  70.  
  71.  
  72. '**********************************************************************************************************************
  73. FUNCTION Orientation (p AS POINTTYPE, q AS POINTTYPE, r AS POINTTYPE) '                                     ORIENTATION
  74.     '******************************************************************************************************************
  75.     '* Returns the orientation of ordered triplet p, q, r.                       *
  76.     '* 0 = p, q, r are colinear                                                  *
  77.     '* 1 = clockwise orientation                                                 *
  78.     '* 2 = counter clockwise orientation                                         *
  79.     '*                                                                           *
  80.     '* This function was created from example code found at:                     *
  81.     '* https://www.geeksforgeeks.org/check-if-two-given-line-segments-intersect/ *
  82.     '* (FOR INTERNAL USE ONLY)                                                   *
  83.     '*****************************************************************************
  84.  
  85.     DIM Value AS INTEGER ' triplet orientation
  86.  
  87.     Value = (q.y - p.y) * (r.x - q.x) - (q.x - p.x) * (r.y - q.y) ' calculate orientation
  88.     IF Value = 0 THEN '                                             colinear
  89.         Orientation = 0
  90.     ELSEIF Value > 0 THEN '                                         clockwise
  91.         Orientation = 1
  92.     ELSE '                                                          counter clockwise
  93.         Orientation = 2
  94.     END IF
  95.  
  96.  
  97.  
  98. '**********************************************************************************************************************
  99. FUNCTION onSegment (p AS POINTTYPE, q AS POINTTYPE, r AS POINTTYPE) '                                         ONSEGMENT
  100.     '******************************************************************************************************************
  101.     '* Given 3 colinear points p, q, r, the function checks if point q lies on line segment pr. *
  102.     '*                                                                                          *
  103.     '* p, q, r - three colinear X,Y points                                                      *
  104.     '*                                                                                          *
  105.     '* This function was created from example code found at:                                    *
  106.     '* https://www.geeksforgeeks.org/check-if-two-given-line-segments-intersect/                *
  107.     '* (FOR INTERNAL USE ONLY)                                                                  *
  108.     '********************************************************************************************
  109.  
  110.     IF q.x <= ObjMax(p.x, r.x) THEN
  111.         IF q.x >= ObjMin(p.x, r.x) THEN
  112.             IF q.y <= ObjMax(p.y, r.y) THEN
  113.                 IF q.y >= ObjMin(p.y, r.y) THEN
  114.                     onSegment = -1
  115.                 END IF
  116.             END IF
  117.         END IF
  118.     END IF
  119.  
  120.  
  121.  
  122. '**********************************************************************************************************************
  123. FUNCTION ObjMax (n1 AS INTEGER, n2 AS INTEGER) '                                                                 OBJMAX
  124.     '******************************************************************************************************************
  125.     '* Returns the maximum of two numbers provided. *
  126.     '*                                              *
  127.     '* n1, n2 - the numbers to be compared          *
  128.     '************************************************
  129.  
  130.     IF n1 > n2 THEN ObjMax = n1 ELSE ObjMax = n2 ' return largest number
  131.  
  132.  
  133.  
  134. '**********************************************************************************************************************
  135. FUNCTION ObjMin (n1 AS INTEGER, n2 AS INTEGER) '                                                                 OBJMIN
  136.     '******************************************************************************************************************
  137.     '* Returns the minimum of two numbers provided. *
  138.     '*                                              *
  139.     '* n1, n2 - the numbers to be compared          *
  140.     '************************************************
  141.  
  142.     IF n1 < n2 THEN ObjMin = n1 ELSE ObjMin = n2 ' return smallest number
  143.  
  144.  
Title: Re: Intersect of 2 lines carried a step further
Post by: bplus on March 16, 2020, 10:28:54 am
Are you guys Erik and Terry talking about lines or line segments?

Lines are pretty easy, line segments are harder particularly finding the overlap zone of two segments on same line.

BTW my goal originally was to find an alternate way to determine if a triangle overlaps another by outlining the overlap area with intersect points again extending a Rosetta Code challenge from a yes/no answer to a visual representation of the overlap area.


Here is test code, see how your routines hold up ;-))
Code: QB64: [Select]
  1. _TITLE "Two Line Segments Intersect" 'b+ 2020-03-14
  2. ' Just worked Rosetta Code for Line Intersect Line
  3. ' but what if we want to know if two line segments intersect?
  4.  
  5. '2020-03-15 rework this code so we identify points all on same line and
  6. ' if there is overlap of line segments say the two x endpoints of the segments
  7. ' otherwise, if there is an intersect of 2 line segments say the point x, y.
  8. ' Return 0 no intersect or overlap
  9. ' Return 1 if intersect and ix, iy point of intersect
  10. ' Return -1 if segments are on same and there is overlap: ix = overlap start x, iy overlap end x
  11.  
  12. CONST xmax = 1200, ymax = 700
  13. SCREEN _NEWIMAGE(xmax, ymax, 32)
  14. _DELAY .25
  15. DIM ax1 AS INTEGER, ax2 AS INTEGER, ay1 AS INTEGER, ay2 AS INTEGER
  16. DIM bx1 AS INTEGER, bx2 AS INTEGER, by1 AS INTEGER, by2 AS INTEGER
  17.     restartA:
  18.     CLS
  19.     IF RND < .5 THEN 'throw in some vertical lines
  20.         ax1 = (xmax - 20) * RND + 10: ay1 = (ymax - 60) * RND + 50
  21.         ax2 = ax1: ay2 = (ymax - 60) * RND + 50
  22.     ELSE
  23.         ax1 = (xmax - 20) * RND + 10: ay1 = (ymax - 60) * RND + 50
  24.         ax2 = (xmax - 20) * RND + 10: ay2 = (ymax - 60) * RND + 50
  25.     END IF
  26.     IF _HYPOT(ax1 - ax2, ay1 - ay2) < 50 THEN GOTO restartA
  27.  
  28.     IF RND < .5 THEN 'get some points on same line
  29.         LOCATE 3, 80: PRINT "Blue Points are on same line as Red."
  30.         slopeYintersect ax1, ay1, ax2, ay2, slope1, Yintercept1  ' >>  to set up tests on same line
  31.         bx1 = (xmax - 20) * RND + 10: by1 = bx1 * slope1 + Yintercept1
  32.         bx2 = (xmax - 20) * RND + 10: by2 = bx2 * slope1 + Yintercept1
  33.     ELSE
  34.         IF RND < .5 THEN 'throw in some verticals
  35.             bx1 = (xmax - 20) * RND + 10: by1 = (ymax - 60) * RND + 50
  36.             bx2 = bx1: by2 = (ymax - 60) * RND + 50
  37.         ELSE
  38.             bx1 = (xmax - 20) * RND + 10: by1 = (ymax - 60) * RND + 50
  39.             bx2 = (xmax - 20) * RND + 10: by2 = (ymax - 60) * RND + 50
  40.         END IF
  41.     END IF
  42.     IF bx1 < 10 OR bx1 > xmax - 10 THEN GOTO restartA
  43.     IF bx2 < 10 OR bx2 > xmax - 10 THEN GOTO restartA
  44.     IF by1 < 50 OR by1 > ymax - 10 THEN GOTO restartA
  45.     IF by2 < 50 OR by2 > ymax - 10 THEN GOTO restartA
  46.     IF _HYPOT(bx1 - bx2, by1 - by2) < 50 THEN GOTO restartA
  47.  
  48.     LINE (ax1, ay1)-(ax2, ay2), &HFFFF0000
  49.     CIRCLE (ax1, ay1), 4, &HFFFF0000
  50.     CIRCLE (ax2, ay2), 4, &HFFFF0000
  51.  
  52.     LINE (bx1, by1)-(bx2, by2), &HFF0000FF
  53.     CIRCLE (bx1, by1), 4, &HFF0000FF
  54.     CIRCLE (bx2, by2), 4, &HFF0000FF
  55.  
  56.     LOCATE 1, 1
  57.     PRINT "Segments ("; ts$(ax1); ", "; ts$(ay1); ") ("; ts$(ax2); ", ";_
  58.      ts$(ay2); ") and ("; ts$(bx1); ", "; ts$(by1); ") ("; ts$(bx2); ", "; ts$(by2); ")"
  59. '==================================================++++++++++++====================
  60. '  Here is where your call to FUNCTION goes and followup with the graphing of your result
  61.  ' VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV
  62.     intersect = twoLineSegmentsIntersect%(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  63.     IF intersect = -1 THEN
  64.         PRINT " Segments overlap between min x at "; ts$(ix); " and max x at "; ts$(iy) '< not a "y" here
  65.         LINE (ix, 0)-(iy, ymax), &H22FFFF00, BF
  66.     ELSEIF intersect = 1 THEN
  67.         PRINT " Segments intersect at ("; ts$(ix); ", "; ts$(iy); ")."
  68.         CIRCLE (ix, iy), 3, &HFFFFFF00
  69.     ELSEIF intersect = 0 THEN
  70.         PRINT " Segments do not Intersect or Overlap."
  71.     END IF
  72. '============================== >>>>>>>>>>>>>>>>>>>>>>> ends interpretation of your functions results
  73.     INPUT "Press enter for another demo, any + enter to quit...", again$
  74.     CLS
  75. LOOP UNTIL LEN(again$)
  76.  
  77. 'Slope and Y-intersect for non vertical lines,
  78. ' if x1 = x2 the line is vertical don't call this sub
  79. ' because slope calculation would cause division by 0 error.
  80. SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept) 'check x1 <> x2 first!
  81.     slope = (Y2 - Y1) / (X2 - X1): Yintercept = slope * (0 - X1) + Y1
  82.  
  83. FUNCTION ts$ (n)
  84.     ts$ = _TRIM$(STR$(INT(100 * n) / 100))
  85.  
Title: Re: Intersect of 2 lines carried a step further
Post by: bplus on March 16, 2020, 11:39:02 am
The "step further" from title of this thread, I meant to get into identifying line segments as intersecting or overlapping and finding either the intersect point or area of overlap (I am happy with just x boundary points at moment) if there is any.
Title: Re: Intersect of 2 lines carried a step further
Post by: STxAxTIC on March 16, 2020, 11:45:01 am
Sorry guys, have been out for a little bit... but I like this problem - I'll see what I can work out on paper, and if fruitful, may possibly undergo the formality of writing code as well.

Looks like the important cases are already solved - so will report back if I find anything exotic.
Title: Re: Intersect of 2 lines carried a step further
Post by: bplus on March 16, 2020, 12:02:12 pm
Hey STxAxTIC, I suspect this thread subject rather exotic already ;)

I should note something important. In order to get more line segments on the same line being recognized as such in the routines, I had to loosen up the restriction of d = 0 to it being close to 0, <.2 AND I loosened up the restriction of the Y intersects being exactly the same for the 2 line segments, I allowed a difference of 5 pixels. It still doesn't catch ALL segments lying on the same line but does catch most.

I will arrow the spots in the sub:
Code: QB64: [Select]
  1. ' this function needs: SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept)
  2. FUNCTION lineIntersectLine% (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  3.     IF ax1 = ax2 THEN 'line a is vertical
  4.         IF bx1 = bx2 THEN ' b is vertical
  5.             IF ax1 = bx1 THEN lineIntersectLine% = -1 ' if x's are same it is same vertical line
  6.             EXIT FUNCTION '
  7.         ELSE
  8.             ix = ax1
  9.             slopeYintersect bx1, by1, bx2, by2, m2, y02
  10.             iy = m2 * ix + y02
  11.             lineIntersectLine% = 1 'signal a point was found
  12.             EXIT FUNCTION
  13.         END IF
  14.     ELSE
  15.         slopeYintersect ax1, ay1, ax2, ay2, m1, y01 ' -m = a, 1 = b, y0 = c  std form
  16.     END IF
  17.     IF bx1 = bx2 THEN 'b is vertical
  18.         ix = bx1: iy = m1 * ix + y01: lineIntersectLine% = 1 'signal a point was found
  19.         EXIT FUNCTION
  20.     ELSE
  21.         slopeYintersect bx1, by1, bx2, by2, m2, y02 ' -m = a, 1 = b, y0 = c  std form
  22.     END IF
  23.     d = -m1 - -m2 ' if = 0 then parallel or equal because slopes are same
  24.     IF ABS(d) > .2 THEN 'otherwise about 0 '<<<<<<<<<<<<<<<<<<<<<<<<<< loosen restriction: d = 0
  25.         ix = (y01 - y02) / d: iy = (-m1 * y02 - -m2 * y01) / d
  26.         lineIntersectLine% = 1 'signal one intersect point was found
  27.     ELSE 'same line or parallel? if y0 are same they are the same
  28.         IF ABS(y01 - y02) < 5 THEN lineIntersectLine% = -1 'signal same line! <<<<< loosen from strict:  y01 = yo2
  29.     END IF
  30.  


It was in reply #7 that I changed this FUNCTION.
Title: Re: Intersect of 2 lines carried a step further
Post by: bplus on March 16, 2020, 12:21:17 pm
Upon further thinking, determining if the 4 points are co-linear is weakest part of my coding adventure with this so far.

It might be productive to get a separate routine designed just for that purpose. Finding the x boundaries of overlap from there is pretty straight forward grunt work.
Title: Re: Intersect of 2 lines carried a step further
Post by: EricE on March 16, 2020, 01:11:40 pm
For this problem I need to know a good value for QB64's Machine Epsilon.

Edited to add:
I just started a new thread on the topic of QB64's Machine Epsilon.
https://www.qb64.org/forum/index.php?topic=2353.0 (https://www.qb64.org/forum/index.php?topic=2353.0)
Title: Re: Intersect of 2 lines carried a step further
Post by: TerryRitchie on March 16, 2020, 01:49:38 pm
Are you guys Erik and Terry talking about lines or line segments?

The code I posted works with line segments. You need to supply the start and end X,Y coordinate pairs for each line segment.
Title: Re: Intersect of 2 lines carried a step further
Post by: EricE on March 16, 2020, 02:05:35 pm
My code is for the lines containing the segments.
However, adding a simple check will tell if the two segments intersect.

Code: QB64: [Select]
  1. IF (0.0 <= r) AND (r <= 1.0) AND (0.0 <= s) AND (s <= 1.0) THEN
  2.     PRINT "Line segments intersect"
  3.     PRINT "Line segments do not intersect"
  4. <
Title: Re: Intersect of 2 lines carried a step further
Post by: bplus on March 16, 2020, 02:13:52 pm
The code I posted works with line segments. You need to supply the start and end X,Y coordinate pairs for each line segment.

Yeah I was looking over your code Terry, you are even checking if points are co-linear but 3 at a time and in a weird way ie rotation clockwise or counter? I don't see line segments turning one way or another. Otherwise I would try to test your routines in the tester code.

Quote
You need to supply the start and end X,Y coordinate pairs for each line segment.
Just what the tester code sets up unless it makes a difference which is first and which is second. Still working through the code... maybe the orientation stuff is all internal and I just need a pointType to plug the numbers there.
ObjIntersect only returns true or false for intersect and/or for overlap?
Title: Re: Intersect of 2 lines carried a step further
Post by: bplus on March 16, 2020, 02:17:01 pm
My code is for the lines containing the segments.
However, adding a simple check will tell if the two segments intersect.

Code: QB64: [Select]
  1. IF (0.0 <= r) AND (r <= 1.0) AND (0.0 <= s) AND (s <= 1.0) THEN
  2.     PRINT "Line segments intersect"
  3.     PRINT "Line segments do not intersect"
  4. <

Your code only works if D <> 0
Quote
Code: QB64: [Select]
  1. ' Compute determinant
  2. DetV = -v1(1) * v2(2) + v2(1) * v1(2)
  3. ' DetV must not be zero
Title: Re: Intersect of 2 lines carried a step further
Post by: TerryRitchie on March 16, 2020, 02:45:07 pm
Note the source cited in my code. I don't claim to have written that code myself, I converted it from the source cited. The clockwise/counter-clockwise thing has me a bit confused as well.
Title: Re: Intersect of 2 lines carried a step further
Post by: bplus on March 16, 2020, 06:50:33 pm
I have modified the twoSegmentsIntersect FUNCTION or SUB tester code. It was missing an important case of 2 segments lying on the same vertical line. Now the SUB or FUNCTION should ID either the Intersect Point or the segment Overlap boundary 2 end points (which could be the same if they only overlap at one point).

Code: QB64: [Select]
  1. _TITLE "Segments Intersect mod tester" 'b+ 2020-03-16
  2. ' Just worked Rosetta Code for Line Intersect Line
  3. ' but what if we want to know if two line segments intersect?
  4. '2020-03-14 "Two Line Segments Intersect" 'b+ 2020-03-14  start
  5. '2020-03-15 rework this code so we identify points all on same line and
  6. ' if there is overlap of line segments say the two x endpoints of the segments
  7. ' otherwise, if there is an intersect of 2 line segments say the point x, y.
  8. ' Return 0 no intersect or overlap
  9. ' Return 1 if intersect and ix, iy point of intersect
  10. ' Return -1 if segments are on same and there is overlap: ix = overlap start x, iy overlap end x
  11.  
  12. '2020-03-16 "Segments Intersect mod tester"
  13. 'mod tester for 2 segments of vertical line and found I need to add more parameters to
  14. ' FUNCTION twoLineSegmentsIntersect%  (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  15. ' mod that name and parameters to:
  16. ' FUNCTION twoSegmentsIntersect%  (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, i1x, i1y, i2x, i2y)
  17.  
  18. CONST xmax = 1200, ymax = 700
  19. SCREEN _NEWIMAGE(xmax, ymax, 32)
  20. _DELAY .25
  21. DIM ax1 AS INTEGER, ax2 AS INTEGER, ay1 AS INTEGER, ay2 AS INTEGER
  22. DIM bx1 AS INTEGER, bx2 AS INTEGER, by1 AS INTEGER, by2 AS INTEGER
  23.     restartA:
  24.     CLS
  25.     IF RND < .5 THEN 'throw in some vertical lines
  26.         LOCATE 3, 80: PRINT "Red Points are vertical."
  27.         ax1 = (xmax - 20) * RND + 10: ay1 = (ymax - 60) * RND + 50
  28.         ax2 = ax1: ay2 = (ymax - 60) * RND + 50
  29.     ELSE
  30.         LOCATE 3, 80: PRINT "Red Points are Random."
  31.         ax1 = (xmax - 20) * RND + 10: ay1 = (ymax - 60) * RND + 50
  32.         ax2 = (xmax - 20) * RND + 10: ay2 = (ymax - 60) * RND + 50
  33.     END IF
  34.     IF _HYPOT(ax1 - ax2, ay1 - ay2) < 50 THEN GOTO restartA
  35.  
  36.     IF RND < .5 THEN 'get some points on same line
  37.         LOCATE 3, 80: PRINT "Blue Points are on same line as Red."
  38.         slopeYintersect ax1, ay1, ax2, ay2, slope1, Yintercept1
  39.         bx1 = (xmax - 20) * RND + 10: by1 = bx1 * slope1 + Yintercept1
  40.         bx2 = (xmax - 20) * RND + 10: by2 = bx2 * slope1 + Yintercept1
  41.     ELSE
  42.         IF RND < .4 THEN 'throw in some verticals, we already have a doing verticals
  43.             LOCATE 3, 80: PRINT SPACE$(50)
  44.             LOCATE 3, 80: PRINT "All points vertical."
  45.             ax1 = (xmax - 20) * RND + 10: ax2 = ax1: bx1 = ax1: bx2 = ax1
  46.             ay1 = 50 + RND * 50: ay2 = ay1 + 50 + RND * 50
  47.             by1 = ay1 + 25 + RND * 50: by2 = by1 + 50 + (RND * ymax - 60 - by1)
  48.             by1 = (ymax - 60) * RND + 50: bx2 = bx1: by2 = (ymax - 60) * RND + 50
  49.         ELSE
  50.             LOCATE 4, 80: PRINT "Blue Points are Random."
  51.             bx1 = (xmax - 20) * RND + 10: by1 = (ymax - 60) * RND + 50
  52.             bx2 = (xmax - 20) * RND + 10: by2 = (ymax - 60) * RND + 50
  53.         END IF
  54.     END IF
  55.     IF bx1 < 10 OR bx1 > xmax - 10 THEN GOTO restartA
  56.     IF bx2 < 10 OR bx2 > xmax - 10 THEN GOTO restartA
  57.     IF by1 < 50 OR by1 > ymax - 10 THEN GOTO restartA
  58.     IF by2 < 50 OR by2 > ymax - 10 THEN GOTO restartA
  59.     IF _HYPOT(bx1 - bx2, by1 - by2) < 30 THEN GOTO restartA
  60.  
  61.     LINE (ax1, ay1)-(ax2, ay2), &HFFFF0000
  62.     CIRCLE (ax1, ay1), 4, &HFFFF0000
  63.     CIRCLE (ax2, ay2), 4, &HFFFF0000
  64.  
  65.     LINE (bx1, by1)-(bx2, by2), &HFF0000FF
  66.     CIRCLE (bx1, by1), 4, &HFF0000FF
  67.     CIRCLE (bx2, by2), 4, &HFF0000FF
  68.  
  69.     LOCATE 1, 1
  70.     PRINT "Segments ("; ts$(ax1); ", "; ts$(ay1); ") ("; ts$(ax2); ", ";_
  71.      ts$(ay2); ") and ("; ts$(bx1); ", "; ts$(by1); ") ("; ts$(bx2); ", "; ts$(by2); ")"
  72.  
  73.     '                    Plug in your 2 Segment Intersect SUB or FUNCTION Here
  74.     '                 and interpret reults: yellow circle around intersect point
  75.     '                and an alpha shaded box where two co-linear segments overlap
  76.     '=====================================================================================================
  77.     'intersect = twoSegmentsIntersect%(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, i1x, i1y, i2x, i2y)
  78.     'IF intersect = -1 THEN 'segments overlap on same line
  79.     '    PRINT " Segments overlap between min x at "; ts$(ix); " and max x at "; ts$(iy) '< not a "y" here
  80.     '    LINE (i1x, i1y)-(i2x, i2y), &HFFFFFFFF
  81.     'ELSEIF intersect = 1 THEN 'segments intersect at one point
  82.     '    PRINT " Segments intersect at ("; ts$(ix); ", "; ts$(iy); ")."
  83.     '    CIRCLE (ix, iy), 3, &HFFFFFFFF
  84.     'ELSEIF intersect = 0 THEN 'segments do not intersect nor overlap
  85.     '    PRINT " Segments do not Intersect or Overlap."
  86.     'END IF
  87.     '=====================================================================================================
  88.  
  89.     INPUT "Press enter for another demo, any + enter to quit...", again$
  90.     CLS
  91. LOOP UNTIL LEN(again$)
  92.  
  93. 'Slope and Y-intersect for non vertical lines,
  94. ' if x1 = x2 the line is vertical don't call this sub
  95. ' because slope calculation would cause division by 0 error.
  96. SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept) 'check x1 <> x2 first!
  97.     slope = (Y2 - Y1) / (X2 - X1): Yintercept = slope * (0 - X1) + Y1
  98.  
  99. FUNCTION ts$ (n)
  100.     ts$ = _TRIM$(STR$(INT(100 * n) / 100))
  101. ' ======================================== end tester code functions ======================================
  102.  

Title: Re: Intersect of 2 lines carried a step further
Post by: bplus on March 16, 2020, 09:57:49 pm
OK I think I got it, running without error over 100 tests:
Code: QB64: [Select]
  1. _TITLE "Segments Intersect revised 2020-03-16:  White Circles are Intersects White Lines are Overlaps" 'b+ 2020-03-16
  2. ' Just worked Rosetta Code for Line Intersect Line
  3. ' but what if we want to know if two line segments intersect?
  4. '2020-03-14 "Two Line Segments Intersect" 'b+ 2020-03-14  start
  5. '2020-03-15 rework this code so we identify points all on same line and
  6. ' if there is overlap of line segments say the two x endpoints of the segments
  7. ' otherwise, if there is an intersect of 2 line segments say the point x, y.
  8. ' Return 0 no intersect or overlap
  9. ' Return 1 if intersect and ix, iy point of intersect
  10. ' Return -1 if segments are on same and there is overlap: ix = overlap start x, iy overlap end x
  11.  
  12. '2020-03-16 "Segments Intersect mod tester"  >>> just post testing code
  13. 'mod tester for 2 segments of vertical line and found I need to add more parameters to
  14. ' FUNCTION twoLineSegmentsIntersect%  (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  15. ' mod that name and parameters to:
  16. ' FUNCTION twoSegmentsIntersect%  (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix1, iy1, ix2, iy2)
  17.  
  18. '2020-03-16 Segments Intersect revised 2020-03-16
  19. ' OK now get the new FUNCTION working
  20. ' ah! I had to tighten down D from >.2 to >.05 but loosen y-axis intersect
  21.  
  22. CONST xmax = 1200, ymax = 700
  23. SCREEN _NEWIMAGE(xmax, ymax, 32)
  24. _DELAY .25
  25. DIM ax1 AS INTEGER, ax2 AS INTEGER, ay1 AS INTEGER, ay2 AS INTEGER
  26. DIM bx1 AS INTEGER, bx2 AS INTEGER, by1 AS INTEGER, by2 AS INTEGER
  27.     restartA:
  28.     CLS
  29.     IF RND < .3 THEN 'throw in some vertical lines
  30.         LOCATE 3, 80: PRINT "Red Points are vertical."
  31.         ax1 = (xmax - 20) * RND + 10: ay1 = (ymax - 60) * RND + 50
  32.         ax2 = ax1: ay2 = (ymax - 60) * RND + 50
  33.     ELSE
  34.         LOCATE 3, 80: PRINT "Red Points are Random."
  35.         ax1 = (xmax - 20) * RND + 10: ay1 = (ymax - 60) * RND + 50
  36.         ax2 = (xmax - 20) * RND + 10: ay2 = (ymax - 60) * RND + 50
  37.     END IF
  38.     IF _HYPOT(ax1 - ax2, ay1 - ay2) < 50 THEN GOTO restartA
  39.  
  40.     IF RND < .6 THEN 'get some points on same line
  41.         LOCATE 3, 80: PRINT "Blue Points are on same line as Red."
  42.         slopeYintersect ax1, ay1, ax2, ay2, slope1, Yintercept1
  43.         bx1 = (xmax - 20) * RND + 10: by1 = bx1 * slope1 + Yintercept1
  44.         bx2 = (xmax - 20) * RND + 10: by2 = bx2 * slope1 + Yintercept1
  45.     ELSE
  46.         IF RND < .4 THEN 'throw in some verticals, we already have a doing verticals
  47.             LOCATE 3, 80: PRINT SPACE$(50)
  48.             LOCATE 3, 80: PRINT "All points vertical."
  49.             ax1 = (xmax - 20) * RND + 10: ax2 = ax1: bx1 = ax1: bx2 = ax1
  50.             ay1 = 50 + RND * 50: ay2 = ay1 + 50 + RND * 50
  51.             by1 = ay1 + 25 + RND * 50: by2 = by1 + 50 + (RND * ymax - 60 - by1)
  52.             by1 = (ymax - 60) * RND + 50: bx2 = bx1: by2 = (ymax - 60) * RND + 50
  53.         ELSE
  54.             LOCATE 4, 80: PRINT "Blue Points are Random."
  55.             bx1 = (xmax - 20) * RND + 10: by1 = (ymax - 60) * RND + 50
  56.             bx2 = (xmax - 20) * RND + 10: by2 = (ymax - 60) * RND + 50
  57.         END IF
  58.     END IF
  59.     IF bx1 < 10 OR bx1 > xmax - 10 THEN GOTO restartA
  60.     IF bx2 < 10 OR bx2 > xmax - 10 THEN GOTO restartA
  61.     IF by1 < 50 OR by1 > ymax - 10 THEN GOTO restartA
  62.     IF by2 < 50 OR by2 > ymax - 10 THEN GOTO restartA
  63.     IF _HYPOT(bx1 - bx2, by1 - by2) < 30 THEN GOTO restartA
  64.  
  65.     LINE (ax1, ay1)-(ax2, ay2), &HFFFF0000
  66.     CIRCLE (ax1, ay1), 4, &HFFFF0000
  67.     CIRCLE (ax2, ay2), 4, &HFFFF0000
  68.  
  69.     LINE (bx1, by1)-(bx2, by2), &HFF0000FF
  70.     CIRCLE (bx1, by1), 4, &HFF0000FF
  71.     CIRCLE (bx2, by2), 4, &HFF0000FF
  72.  
  73.     LOCATE 1, 1
  74.     PRINT "Segments ("; ts$(ax1); ", "; ts$(ay1); ") ("; ts$(ax2); ", ";_
  75.      ts$(ay2); ") and ("; ts$(bx1); ", "; ts$(by1); ") ("; ts$(bx2); ", "; ts$(by2); ")"
  76.  
  77.     '                    Plug in your 2 Segment Intersect SUB or FUNCTION Here
  78.     '                 and interpret reults: yellow circle around intersect point
  79.     '                and an alpha shaded box where two co-linear segments overlap
  80.     '=====================================================================================================
  81.     intersect = twoSegmentsIntersect%(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix1, iy1, ix2, iy2)
  82.     IF intersect = -1 THEN 'segments overlap on same line
  83.         PRINT " Segments overlap between: ("; ts$(ix1); ", "; ts$(iy1); ") and ("; ts$(ix2); ", "; ts$(iy2); ")"
  84.         LINE (ix1, iy1)-(ix2, iy2), &HFFFFFFFF
  85.     ELSEIF intersect = 1 THEN 'segments intersect at one point
  86.         PRINT " Segments intersect: ("; ts$(ix1); ", "; ts$(iy1); ")"
  87.         CIRCLE (ix1, iy1), 3, &HFFFFFFFF
  88.     ELSEIF intersect = 0 THEN 'segments do not intersect nor overlap
  89.         PRINT " Segments do not Intersect or Overlap."
  90.     END IF
  91.     '=====================================================================================================
  92.  
  93.     INPUT "Press enter for another demo, any + enter to quit...", again$
  94.     CLS
  95. LOOP UNTIL LEN(again$)
  96.  
  97. 'Slope and Y-intersect for non vertical lines,
  98. ' if x1 = x2 the line is vertical don't call this sub
  99. ' because slope calculation would cause division by 0 error.
  100. SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept) 'check x1 <> x2 first!
  101.     slope = (Y2 - Y1) / (X2 - X1): Yintercept = slope * (0 - X1) + Y1
  102.  
  103. FUNCTION ts$ (n)
  104.     ts$ = _TRIM$(STR$(INT(100 * n) / 100))
  105. ' ======================================== end tester code functions ======================================
  106.  
  107.  
  108. 'This function needs: FUNCTION lineIntersectLine% (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  109. ' which in turn needs: SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept) 'check x1 <> x2 first!
  110. FUNCTION twoSegmentsIntersect% (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix1, iy1, ix2, iy2)
  111.     intersect = lineIntersectLine%(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  112.     IF ax1 < ax2 THEN aMinX = ax1: aMaxX = ax2 ELSE aMinX = ax2: aMaxX = ax1
  113.     IF ay1 < ay2 THEN aMinY = ay1: aMaxY = ay2 ELSE aMinY = ay2: aMaxY = ay1
  114.     IF bx1 < bx2 THEN bMinX = bx1: bMaxX = bx2 ELSE bMinX = bx2: bMaxX = bx1
  115.     IF by1 < by2 THEN bMinY = by1: bMaxY = by2 ELSE bMinY = by2: bMaxY = by1
  116.     IF intersect = 0 THEN 'no  intersect
  117.         twoSegmentsIntersect% = 0
  118.     ELSEIF intersect = 1 THEN 'segments intersect at one point
  119.         IF ax1 = ax2 THEN 'is iy between
  120.             IF iy < aMinY OR iy > aMaxY OR ix < bMinX OR ix > bMaxX THEN
  121.                 twoSegmentsIntersect% = 0
  122.             ELSE
  123.                 ix1 = ix: iy1 = iy: twoSegmentsIntersect% = 1
  124.             END IF
  125.         ELSEIF bx1 = bx2 THEN
  126.             IF iy < bMinY OR iy > bMaxY OR ix < aMinX OR ix > aMaxX THEN
  127.                 twoSegmentsIntersect% = 0
  128.             ELSE
  129.                 ix1 = ix: iy1 = iy: twoSegmentsIntersect% = 1
  130.             END IF
  131.         ELSE
  132.             IF (aMinX <= ix AND ix <= aMaxX) AND (bMinX <= ix AND ix <= bMaxX) THEN
  133.                 ix1 = ix: iy1 = iy: twoSegmentsIntersect% = 1
  134.             ELSE
  135.                 twoSegmentsIntersect% = 0
  136.             END IF
  137.         END IF
  138.     ELSEIF intersect = -1 THEN 'segments are on same line get over lap section
  139.         'first check if both are on vertical line
  140.         IF ax1 = ax2 THEN 'and we know both are same line  we have two vertical segemnts, do they over lap?
  141.             ix1 = ax1: ix2 = ax1
  142.             IF aMinY < bMinY THEN
  143.                 IF aMaxY < bMinY THEN
  144.                     twoSegmentsIntersect% = 0
  145.                 ELSE
  146.                     twoSegmentsIntersect% = -1: iy1 = bMinY
  147.                     IF aMaxY > bMaxY THEN
  148.                         iy2 = bMaxY
  149.                     ELSE
  150.                         iy2 = aMaxY
  151.                     END IF
  152.                 END IF
  153.             ELSE 'bMinY <= aMinY
  154.                 IF bMaxY < aMinY THEN
  155.                     twoSegmentsIntersect% = 0
  156.                 ELSE
  157.                     twoSegmentsIntersect% = -1: iy1 = aMinY
  158.                     IF bMaxY > aMaxY THEN
  159.                         iy2 = aMaxY
  160.                     ELSE
  161.                         iy2 = bMaxY
  162.                     END IF
  163.                 END IF
  164.             END IF
  165.         ELSE 'the same line is not vertical
  166.             IF aMinX < bMinX THEN
  167.                 IF aMaxX < bMinX THEN
  168.                     twoSegmentsIntersect% = 0
  169.                 ELSE
  170.                     twoSegmentsIntersect% = -1: ix1 = bMinX
  171.                     IF bx1 = bMinX THEN iy1 = by1 ELSE iy1 = by2
  172.                     IF aMaxX > bMaxX THEN
  173.                         ix2 = bMaxX
  174.                         IF bx1 = bMaxX THEN iy2 = by1 ELSE iy2 = by2
  175.                     ELSE
  176.                         ix2 = aMaxX
  177.                         IF ax1 = aMaxX THEN iy2 = ay1 ELSE iy2 = ay2
  178.                     END IF
  179.                 END IF
  180.             ELSE 'aMinX >= bMinX
  181.                 IF aMinX > bMaxX THEN
  182.                     twoSegmentsIntersect% = 0
  183.                 ELSE
  184.                     twoSegmentsIntersect% = -1: ix1 = aMinX
  185.                     IF ax1 = aMinX THEN iy1 = ay1 ELSE iy1 = ay2
  186.                     IF bMaxX > aMaxX THEN
  187.                         ix2 = aMaxX
  188.                         IF ax1 = aMaxX THEN iy2 = ay1 ELSE iy2 = ay2
  189.                     ELSE
  190.                         ix2 = bMaxX
  191.                         IF bx1 = bMaxX THEN iy2 = by1 ELSE iy2 = by2
  192.                     END IF
  193.                 END IF
  194.             END IF
  195.         END IF
  196.     END IF
  197.  
  198. ' this function needs: SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept)
  199. FUNCTION lineIntersectLine% (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  200.     IF ax1 = ax2 THEN 'line a is vertical
  201.         IF bx1 = bx2 THEN ' b is vertical
  202.             IF ax1 = bx1 THEN lineIntersectLine% = -1 ' if x's are same it is same vertical line
  203.             EXIT FUNCTION '
  204.         ELSE
  205.             ix = ax1
  206.             slopeYintersect bx1, by1, bx2, by2, m2, y02
  207.             iy = m2 * ix + y02
  208.             lineIntersectLine% = 1 'signal a point was found
  209.             EXIT FUNCTION
  210.         END IF
  211.     ELSE
  212.         slopeYintersect ax1, ay1, ax2, ay2, m1, y01 ' -m = a, 1 = b, y0 = c  std form
  213.     END IF
  214.     IF bx1 = bx2 THEN 'b is vertical
  215.         ix = bx1: iy = m1 * ix + y01: lineIntersectLine% = 1 'signal a point was found
  216.         EXIT FUNCTION
  217.     ELSE
  218.         slopeYintersect bx1, by1, bx2, by2, m2, y02 ' -m = a, 1 = b, y0 = c  std form
  219.     END IF
  220.     d = -m1 - -m2 ' if = 0 then parallel or equal because slopes are same
  221.     IF ABS(d) > .05 THEN 'otherwise about 0 <<< tighten down from .2 to .05
  222.         ix = (y01 - y02) / d: iy = (-m1 * y02 - -m2 * y01) / d
  223.         lineIntersectLine% = 1 'signal one intersect point was found
  224.     ELSE 'same line or parallel? if y0 (y-axis interssect) are same they are the same
  225.         IF ABS(y01 - y02) < 15 THEN lineIntersectLine% = -1 'signal same line!  <<< loosen more! 5 to 15
  226.     END IF
  227.  

Best answer so far, if anyone can cut down the size of twoSegmentIntersect%() Function...?


2020-03-18 Update: I have tested the twoSegmentIntersect%() Function in "Two Triangles Overlap" see below and found the Overlap signal was coming up with allot of false positives, so there is plenty of room for improvement yet remaining.
Title: Re: Intersect of 2 lines carried a step further
Post by: STxAxTIC on March 17, 2020, 06:30:51 pm
I worked something useful out on paper - if I can just get a darn second to sit and crystallize it I'll meet you at the end bplus!
Title: Re: Intersect of 2 lines carried a step further
Post by: STxAxTIC on March 17, 2020, 08:31:04 pm
I just heard "her" car pull in so I gotta go but here's what I have buddy. Hope it adds to something!

Drag line with mouse 1

Rotate with mouse wheel

All cases covered except parallel, which is easy

Code: QB64: [Select]
  1.  
  2. TYPE Vector
  3.     x AS DOUBLE
  4.     y AS DOUBLE
  5.  
  6. TYPE LineSegment
  7.     b AS Vector
  8.     alpha1 AS DOUBLE
  9.     alpha2 AS DOUBLE
  10.     ang AS DOUBLE
  11.     t AS Vector
  12.     p1 AS Vector
  13.     p2 AS Vector
  14.  
  15. DIM SHARED Segments(2) AS LineSegment
  16.  
  17. Segments(1).b.x = 0
  18. Segments(1).b.y = 0
  19. Segments(1).alpha1 = -150
  20. Segments(1).alpha2 = 150
  21. Segments(1).ang = 0
  22. CALL CalcLine(1)
  23.  
  24. Segments(2).b.x = 0
  25. Segments(2).b.y = 50
  26. Segments(2).alpha1 = -150
  27. Segments(2).alpha2 = 150
  28. Segments(2).ang = ATN(1)
  29. CALL CalcLine(2)
  30.  
  31.  
  32.         x = _MOUSEX
  33.         y = _MOUSEY
  34.         IF ((x > 0) AND (x < _WIDTH) AND (y > 0) AND (y < _HEIGHT)) THEN
  35.             IF _MOUSEBUTTON(1) THEN
  36.                 x = _MOUSEX
  37.                 y = _MOUSEY
  38.                 Segments(1).b.x = (x - _WIDTH / 2)
  39.                 Segments(1).b.y = (-y + _HEIGHT / 2)
  40.                 CALL CalcLine(1)
  41.             END IF
  42.             IF _MOUSEWHEEL > 0 THEN
  43.                 Segments(1).ang = Segments(1).ang + ATN(1) / 10
  44.                 CALL CalcLine(1)
  45.             END IF
  46.             IF _MOUSEWHEEL < 0 THEN
  47.                 Segments(1).ang = Segments(1).ang - ATN(1) / 10
  48.                 CALL CalcLine(1)
  49.             END IF
  50.         END IF
  51.     LOOP
  52.  
  53.     CLS
  54.     CALL cline(Segments(1).p1.x, Segments(1).p1.y, Segments(1).p2.x, Segments(1).p2.y, 15)
  55.     CALL cline(Segments(2).p1.x, Segments(2).p1.y, Segments(2).p2.x, Segments(2).p2.y, 14)
  56.  
  57.     ''' Intersection calculation
  58.     DIM db AS Vector
  59.     db.x = Segments(2).b.x - Segments(1).b.x
  60.     db.y = Segments(2).b.y - Segments(1).b.y
  61.     qj = DotProduct(db, Segments(1).t)
  62.     ql = DotProduct(db, Segments(2).t)
  63.     p = DotProduct(Segments(1).t, Segments(2).t)
  64.     pp = p * p
  65.     IF (pp < 1) THEN
  66.         alphaj = (qj - p * ql) / (1 - pp)
  67.         alphal = (p * qj - ql) / (1 - pp) ' This is actually redundant (along with anything depending on it.)
  68.         IF ((alphaj > Segments(1).alpha1) AND (alphaj < Segments(1).alpha2)) THEN
  69.             IF ((alphal > Segments(2).alpha1) AND (alphal < Segments(2).alpha2)) THEN
  70.                 CALL ccircle(Segments(1).b.x + alphaj * Segments(1).t.x, Segments(1).b.y + alphaj * Segments(1).t.y, 5, 15)
  71.                 CALL ccircle(Segments(2).b.x + alphal * Segments(2).t.x, Segments(2).b.y + alphal * Segments(2).t.y, 5, 15)
  72.             END IF
  73.         END IF
  74.     ELSE
  75.         ' Parallel case.
  76.     END IF
  77.     '''
  78.  
  79.     _DISPLAY
  80.     _LIMIT 60
  81.  
  82.  
  83. SUB CalcLine (i AS INTEGER)
  84.     Segments(i).t.x = COS(Segments(i).ang)
  85.     Segments(i).t.y = SIN(Segments(i).ang)
  86.     Segments(i).p1.x = Segments(i).b.x + Segments(i).alpha1 * Segments(i).t.x
  87.     Segments(i).p1.y = Segments(i).b.y + Segments(i).alpha1 * Segments(i).t.y
  88.     Segments(i).p2.x = Segments(i).b.x + Segments(i).alpha2 * Segments(i).t.x
  89.     Segments(i).p2.y = Segments(i).b.y + Segments(i).alpha2 * Segments(i).t.y
  90.  
  91. FUNCTION DotProduct (a AS Vector, b AS Vector)
  92.     DotProduct = a.x * b.x + a.y * b.y
  93.  
  94. SUB cline (x1 AS DOUBLE, y1 AS DOUBLE, x2 AS DOUBLE, y2 AS DOUBLE, col AS _UNSIGNED LONG)
  95.     LINE (_WIDTH / 2 + x1, -y1 + _HEIGHT / 2)-(_WIDTH / 2 + x2, -y2 + _HEIGHT / 2), col
  96.  
  97. SUB ccircle (x1 AS DOUBLE, y1 AS DOUBLE, rad AS DOUBLE, col AS _UNSIGNED LONG)
  98.     CIRCLE (_WIDTH / 2 + x1, -y1 + _HEIGHT / 2), rad, col
  99.  
  100. SUB cpset (x1 AS DOUBLE, y1 AS DOUBLE, col AS _UNSIGNED LONG)
  101.     PSET (_WIDTH / 2 + x1, -y1 + _HEIGHT / 2), col
  102.  
  103. SUB cpaint (x1 AS DOUBLE, y1 AS DOUBLE, col1 AS _UNSIGNED LONG, col2 AS _UNSIGNED LONG)
  104.     PAINT (_WIDTH / 2 + x1, -y1 + _HEIGHT / 2), col1, col2
  105.  
  106. SUB cprintstring (y AS DOUBLE, a AS STRING)
  107.     _PRINTSTRING (_WIDTH / 2 - (LEN(a) * 8) / 2, -y + _HEIGHT / 2), a
  108.  
Title: Re: Intersect of 2 lines carried a step further
Post by: bplus on March 17, 2020, 10:41:21 pm
Dang I had intersections done in the first OP, that's easy. Find when and where they overlap (on the same line) too, draw that line segment. That was like 75% of my subroutine and 90% of my time. That's what TempodiBasic pointed out.

Dang but those lines looked sharp and clean, oh it's the angle.

Here is the challenging case (that I have solved) determine if 2 line segments are sitting on the same line or do they lay on different lines that intersect, if they overlap, say the 2 endpoints that contain the overlap, if they intersect say the intersect point, or say they neither intersect nor overlap.
Title: Re: Intersect of 2 lines carried a step further
Post by: STxAxTIC on March 17, 2020, 11:31:44 pm
You got it man - I swear next time I sit down I'll finish my math up there - it'll stay tight, promise.
Title: Re: Intersect of 2 lines carried a step further
Post by: bplus on March 18, 2020, 12:32:28 am
Oh rats and nutz and worse@!

Turns out all I really needed was intersect, at least with completely random triangles. It is rare occasion two line segments actually do line up on exact line. Here is basically what I was going after, and intersect handles it nicely:

Code: QB64: [Select]
  1. _TITLE "Two Triangles Overlap is Outlined in White dots" 'b+ 2020-03-18
  2. ' Just worked Rosetta Code for Line Intersect Line
  3. ' but what if we want to know if two line segments intersect?
  4. '2020-03-14 "Two Line Segments Intersect" 'b+ 2020-03-14  start
  5. '2020-03-15 rework this code so we identify points all on same line and
  6. ' if there is overlap of line segments say the two x endpoints of the segments
  7. ' otherwise, if there is an intersect of 2 line segments say the point x, y.
  8. ' Return 0 no intersect or overlap
  9. ' Return 1 if intersect and ix, iy point of intersect
  10. ' Return -1 if segments are on same and there is overlap: ix = overlap start x, iy overlap end x
  11.  
  12. '2020-03-16 "Segments Intersect mod tester"  >>> just post testing code
  13. 'mod tester for 2 segments of vertical line and found I need to add more parameters to
  14. ' FUNCTION twoLineSegmentsIntersect%  (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  15. ' mod that name and parameters to:
  16. ' FUNCTION twoSegmentsIntersect%  (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix1, iy1, ix2, iy2)
  17.  
  18. '2020-03-16 Segments Intersect revised 2020-03-16
  19. ' OK now get the new FUNCTION working
  20. ' ah! I had to tighten down D from >.2 to >.05 but loosen y-axis intersect
  21.  
  22. '2020-03-18 apply routines to two triangles
  23. ' modified FUNCTION twoSegmentsIntersect% (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix1, iy1)
  24. ' to do only intersect. This code proved, Segments Intersect revised 2020-03-16, was faulty.
  25.  
  26. CONST xmax = 800, ymax = 600
  27. SCREEN _NEWIMAGE(xmax, ymax, 32)
  28. _DELAY .25
  29. DIM ax1 AS INTEGER, ax2 AS INTEGER, ay1 AS INTEGER, ay2 AS INTEGER, ax3 AS INTEGER, ay3 AS INTEGER
  30. DIM bx1 AS INTEGER, bx2 AS INTEGER, by1 AS INTEGER, by2 AS INTEGER, bx3 AS INTEGER, by3 AS INTEGER
  31.     ax1 = (xmax - 20) * RND + 10: ay1 = (ymax - 20) * RND + 10
  32.     ax2 = (xmax - 20) * RND + 10: ay2 = (ymax - 20) * RND + 10
  33.     ax3 = (xmax - 20) * RND + 10: ay3 = (ymax - 20) * RND + 10
  34.     bx1 = (xmax - 20) * RND + 10: by1 = (ymax - 20) * RND + 10
  35.     bx2 = (xmax - 20) * RND + 10: by2 = (ymax - 20) * RND + 10
  36.     bx3 = (xmax - 20) * RND + 10: by3 = (ymax - 20) * RND + 10
  37.     'tri a
  38.     LINE (ax1, ay1)-(ax2, ay2), &HFFFF0000
  39.     LINE (ax2, ay2)-(ax3, ay3), &HFFFF0000
  40.     LINE (ax3, ay3)-(ax1, ay1), &HFFFF0000
  41.     'tri b
  42.     LINE (bx1, by1)-(bx2, by2), &HFF0000FF
  43.     LINE (bx2, by2)-(bx3, by3), &HFF0000FF
  44.     LINE (bx3, by3)-(bx1, by1), &HFF0000FF
  45.  
  46.     dista2a3 = _HYPOT(ax2 - ax3, ay2 - ay3)
  47.     adx = (ax3 - ax2) / dista2a3: ady = (ay3 - ay2) / dista2a3
  48.     distb2b3 = _HYPOT(bx2 - bx3, by2 - by3)
  49.     bdx = (bx3 - bx2) / distb2b3: bdy = (by3 - by2) / distb2b3
  50.  
  51.     FOR i = 0 TO dista2a3
  52.         x1 = ax2 + adx * i: y1 = ay2 + ady * i
  53.         sect = twoSegmentsIntersect%(ax1, ay1, x1, y1, bx1, by1, bx2, by2, ix1, iy1)
  54.         IF sect THEN PSET (ix1, iy1)
  55.         sect = twoSegmentsIntersect%(ax1, ay1, x1, y1, bx3, by3, bx2, by2, ix1, iy1)
  56.         IF sect THEN PSET (ix1, iy1)
  57.         sect = twoSegmentsIntersect%(ax1, ay1, x1, y1, bx1, by1, bx3, by3, ix1, iy1)
  58.         IF sect = 1 THEN PSET (ix1, iy1)
  59.     NEXT
  60.  
  61.     FOR i = 0 TO distb2b3
  62.         x1 = bx2 + bdx * i: y1 = by2 + bdy * i
  63.         sect = twoSegmentsIntersect%(bx1, by1, x1, y1, ax1, ay1, ax2, ay2, ix1, iy1)
  64.         IF sect = 1 THEN PSET (ix1, iy1)
  65.         sect = twoSegmentsIntersect%(bx1, by1, x1, y1, ax3, ay3, ax2, ay2, ix1, iy1)
  66.         IF sect THEN PSET (ix1, iy1)
  67.         sect = twoSegmentsIntersect%(bx1, by1, x1, y1, ax1, ay1, ax3, ay3, ix1, iy1)
  68.         IF sect = 1 THEN PSET (ix1, iy1)
  69.     NEXT
  70.  
  71.     INPUT "Press enter for another demo, any + enter to quit...", again$
  72.     CLS
  73. LOOP UNTIL LEN(again$)
  74.  
  75. 'Slope and Y-intersect for non vertical lines,
  76. ' if x1 = x2 the line is vertical don't call this sub
  77. ' because slope calculation would cause division by 0 error.
  78. SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept) 'check x1 <> x2 first!
  79.     slope = (Y2 - Y1) / (X2 - X1): Yintercept = slope * (0 - X1) + Y1
  80.  
  81. ' ======================================== end tester code functions ======================================
  82.  
  83. 'This function needs: FUNCTION lineIntersectLine% (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  84. ' which in turn needs: SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept) 'check x1 <> x2 first!
  85. FUNCTION twoSegmentsIntersect% (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix1, iy1)
  86.     intersect = lineIntersectLine%(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  87.     IF ax1 < ax2 THEN aMinX = ax1: aMaxX = ax2 ELSE aMinX = ax2: aMaxX = ax1
  88.     IF ay1 < ay2 THEN aMinY = ay1: aMaxY = ay2 ELSE aMinY = ay2: aMaxY = ay1
  89.     IF bx1 < bx2 THEN bMinX = bx1: bMaxX = bx2 ELSE bMinX = bx2: bMaxX = bx1
  90.     IF by1 < by2 THEN bMinY = by1: bMaxY = by2 ELSE bMinY = by2: bMaxY = by1
  91.     IF intersect = 0 THEN 'no  intersect
  92.         twoSegmentsIntersect% = 0
  93.     ELSEIF intersect = 1 THEN 'segments intersect at one point
  94.         IF ax1 = ax2 THEN 'is iy between
  95.             IF iy < aMinY OR iy > aMaxY OR ix < bMinX OR ix > bMaxX THEN
  96.                 twoSegmentsIntersect% = 0
  97.             ELSE
  98.                 ix1 = ix: iy1 = iy: twoSegmentsIntersect% = 1
  99.             END IF
  100.         ELSEIF bx1 = bx2 THEN
  101.             IF iy < bMinY OR iy > bMaxY OR ix < aMinX OR ix > aMaxX THEN
  102.                 twoSegmentsIntersect% = 0
  103.             ELSE
  104.                 ix1 = ix: iy1 = iy: twoSegmentsIntersect% = 1
  105.             END IF
  106.         ELSE
  107.             IF (aMinX <= ix AND ix <= aMaxX) AND (bMinX <= ix AND ix <= bMaxX) THEN
  108.                 ix1 = ix: iy1 = iy: twoSegmentsIntersect% = 1
  109.             END IF
  110.         END IF
  111.     END IF
  112.  
  113. ' this function needs: SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept)
  114. FUNCTION lineIntersectLine% (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  115.     IF ax1 = ax2 THEN 'line a is vertical
  116.         IF bx1 = bx2 THEN ' b is vertical
  117.             IF ax1 = bx1 THEN lineIntersectLine% = -1 ' if x's are same it is same vertical line
  118.             EXIT FUNCTION '
  119.         ELSE
  120.             ix = ax1
  121.             slopeYintersect bx1, by1, bx2, by2, m2, y02
  122.             iy = m2 * ix + y02
  123.             lineIntersectLine% = 1 'signal a point was found
  124.             EXIT FUNCTION
  125.         END IF
  126.     ELSE
  127.         slopeYintersect ax1, ay1, ax2, ay2, m1, y01 ' -m = a, 1 = b, y0 = c  std form
  128.     END IF
  129.     IF bx1 = bx2 THEN 'b is vertical
  130.         ix = bx1: iy = m1 * ix + y01: lineIntersectLine% = 1 'signal a point was found
  131.         EXIT FUNCTION
  132.     ELSE
  133.         slopeYintersect bx1, by1, bx2, by2, m2, y02 ' -m = a, 1 = b, y0 = c  std form
  134.     END IF
  135.     d = -m1 - -m2 ' if = 0 then parallel or equal because slopes are same
  136.     IF d THEN 'otherwise about 0 <<< tighten down from .2 to .05
  137.         ix = (y01 - y02) / d: iy = (-m1 * y02 - -m2 * y01) / d
  138.         lineIntersectLine% = 1 'signal one intersect point was found
  139.     END IF
  140.  

  [ This attachment cannot be displayed inline in 'Print Page' view ]  

Using the overlap signal from the code in Best Answer was getting some really screwy lines, messing up the outlines way, way more than helping with anything. Phooey all that effort... oh well.
Title: Re: Intersect of 2 lines carried a step further
Post by: STxAxTIC on March 18, 2020, 07:26:51 am
Alrighty - so I'm (in a rush as usual) trying to piece together if there are any remaining questions. Would you say this question is fully cooked now? FWIW the intersection calculations are way simpler with vectors, and only one IF statement is technically needed. (The two CIRCLE statements put two copies of the same circle in the same place so this code can basically be cut in half again for the minimalist approach.)

Code: QB64: [Select]
  1.     DIM db AS Vector
  2.     db.x = Segments(2).b.x - Segments(1).b.x
  3.     db.y = Segments(2).b.y - Segments(1).b.y
  4.     qj = DotProduct(db, Segments(1).t)
  5.     ql = DotProduct(db, Segments(2).t)
  6.     p = DotProduct(Segments(1).t, Segments(2).t)
  7.     pp = p * p
  8.     IF (pp < 1) THEN
  9.         alphaj = (qj - p * ql) / (1 - pp)
  10.         alphal = (p * qj - ql) / (1 - pp) ' This is actually redundant (along with anything depending on it.)
  11.         IF ((alphaj > Segments(1).alpha1) AND (alphaj < Segments(1).alpha2)) THEN
  12.             IF ((alphal > Segments(2).alpha1) AND (alphal < Segments(2).alpha2)) THEN
  13.                 CALL ccircle(Segments(1).b.x + alphaj * Segments(1).t.x, Segments(1).b.y + alphaj * Segments(1).t.y, 5, 15)
  14.                 CALL ccircle(Segments(2).b.x + alphal * Segments(2).t.x, Segments(2).b.y + alphal * Segments(2).t.y, 5, 15)
  15.             END IF
  16.         END IF
  17.     ELSE
  18.         ' Parallel case.
  19.     END IF
Title: Re: Intersect of 2 lines carried a step further
Post by: bplus on March 18, 2020, 11:05:51 am
Alrighty - so I'm (in a rush as usual) trying to piece together if there are any remaining questions. Would you say this question is fully cooked now? FWIW the intersection calculations are way simpler with vectors, and only one IF statement is technically needed. (The two CIRCLE statements put two copies of the same circle in the same place so this code can basically be cut in half again for the minimalist approach.)

Code: QB64: [Select]
  1.     DIM db AS Vector
  2.     db.x = Segments(2).b.x - Segments(1).b.x
  3.     db.y = Segments(2).b.y - Segments(1).b.y
  4.     qj = DotProduct(db, Segments(1).t)
  5.     ql = DotProduct(db, Segments(2).t)
  6.     p = DotProduct(Segments(1).t, Segments(2).t)
  7.     pp = p * p
  8.     IF (pp < 1) THEN
  9.         alphaj = (qj - p * ql) / (1 - pp)
  10.         alphal = (p * qj - ql) / (1 - pp) ' This is actually redundant (along with anything depending on it.)
  11.         IF ((alphaj > Segments(1).alpha1) AND (alphaj < Segments(1).alpha2)) THEN
  12.             IF ((alphal > Segments(2).alpha1) AND (alphal < Segments(2).alpha2)) THEN
  13.                 CALL ccircle(Segments(1).b.x + alphaj * Segments(1).t.x, Segments(1).b.y + alphaj * Segments(1).t.y, 5, 15)
  14.                 CALL ccircle(Segments(2).b.x + alphal * Segments(2).t.x, Segments(2).b.y + alphal * Segments(2).t.y, 5, 15)
  15.             END IF
  16.         END IF
  17.     ELSE
  18.         ' Parallel case.
  19.     END IF

If you put your code into a sub routine (SUB or FUNCTION) I will test it in my code tester app but your "simple" thing has need of two Types at least and at least 2 supplemental helper routines, maybe just one DotProduct (and how many supplements might that have?) because I am NOT looking for drawing, just a FUNCTION that returns True if there is an Intersect and gives the intersect point (ix, iy) say.

If you can by-pass the case of vertical lines when the Determinate = 0 without more code to cover that case I am all eyes because that's what takes up the majority of my Intersect FUNCTION.

Hmm... if just going for Intersect maybe I can combine LineIntersect with SegmentIntersect but seems both might come in handy in app.

What's your DotProduct Function, I might be able to put it all together in a tester. I will call my Point Type XY and segments will just be two points. BUT first guarantee you have vertical line cases covered ;-))

Not cooked at all! Nobody has tested another's code and approved. The code I have quoted above is obviously pulled out of some other context and is incomplete to run.


Update: Oh I see the context! (Reply #24) from first code, OK I will work up test for my own satisfaction anyway. ;)
Title: Re: Intersect of 2 lines carried a step further
Post by: STxAxTIC on March 18, 2020, 11:30:55 am
Sorry my posting context has been so fleeting - my usual verboseness is missing.

So I define lines as a parameterized vector:

vec(y) = vec(b) + alpha * hat(t)

Where vec(y) is any location on the line, vec(b) is the lines origin, alpha is a dimensionless parameter that scales the lines unit tangent vector, vec(t). You can see where I convert this to XY coordinates in a sub.

As for multiple alignments, etc etc - it's all very easy in this framework. The simple question of intersections simply solves vec(y_a) = vec(y_b) for two lines a and b.

Will make nice notes on it in time. Lemme know where the cutting edge is, I'll try to keep near you.
Title: Re: Intersect of 2 lines carried a step further
Post by: bplus on March 18, 2020, 02:00:19 pm
For two overlapping triangles, I think I know how to cover the case should 2 line segments line up perfect PLUS make the entire outline better. But if the triangle should overlap along 2 sides... ;-))
Title: Re: Intersect of 2 lines carried a step further
Post by: STxAxTIC on March 18, 2020, 02:15:46 pm
Oh god let's not talk about triangles yet. Are we onto that though? Lines are done?
Title: Re: Intersect of 2 lines carried a step further
Post by: TempodiBasic on March 18, 2020, 03:34:10 pm
great geometry knowledge!
Quote
But if the triangle should overlap along 2 sides... ;-))

https://it.wikipedia.org/wiki/Criteri_di_congruenza_dei_triangoli (https://it.wikipedia.org/wiki/Criteri_di_congruenza_dei_triangoli)
https://www.youtube.com/watch?v=xaXV-RVpXgo (https://www.youtube.com/watch?v=xaXV-RVpXgo)

Math & Logic can be useful
Title: Re: Intersect of 2 lines carried a step further
Post by: bplus on March 18, 2020, 03:47:40 pm
Oh god let's not talk about triangles yet. Are we onto that though? Lines are done?

Ha! my plan from the start was to use this segment intersect stuff to do overlapping triangles. It's what got me started on this segment intersect adventure in the first place.
https://www.qb64.org/forum/index.php?topic=2342.msg115768#msg115768
Quote
BTW my goal originally was to find an alternate way to determine if a triangle overlaps another by outlining the overlap area with intersect points again extending a Rosetta Code challenge from a yes/no answer to a visual representation of the overlap area.
and here you see I am succeeding! with only LineSegmentIntersect
https://www.qb64.org/forum/index.php?topic=2342.msg115824#msg115824

Title: Re: Intersect of 2 lines carried a step further
Post by: TempodiBasic on March 18, 2020, 04:44:18 pm
Great Bplus...
and I may see another application of your code .... in a graphic world... let's think to a 3D engine with _Maptriangle....
in perspective is it possible?

Thanks  to read
Title: Re: Intersect of 2 lines carried a step further
Post by: bplus on March 18, 2020, 05:03:14 pm
Here is even better demo of Outlining Overlapping Triangles. It does everything I wanted it to do, beautiful!
Code: QB64: [Select]
  1. _TITLE "Two Triangles Overlap is Outlined in White dots" 'b+ 2020-03-18
  2. ' Just worked Rosetta Code for Line Intersect Line
  3. ' but what if we want to know if two line segments intersect?
  4. '2020-03-14 "Two Line Segments Intersect" 'b+ 2020-03-14  start
  5. '2020-03-15 rework this code so we identify points all on same line and
  6. ' if there is overlap of line segments say the two x endpoints of the segments
  7. ' otherwise, if there is an intersect of 2 line segments say the point x, y.
  8. ' Return 0 no intersect or overlap
  9. ' Return 1 if intersect and ix, iy point of intersect
  10. ' Return -1 if segments are on same and there is overlap: ix = overlap start x, iy overlap end x
  11.  
  12. '2020-03-16 "Segments Intersect mod tester"  >>> just post testing code
  13. 'mod tester for 2 segments of vertical line and found I need to add more parameters to
  14. ' FUNCTION twoLineSegmentsIntersect%  (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  15. ' mod that name and parameters to:
  16. ' FUNCTION twoSegmentsIntersect%  (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix1, iy1, ix2, iy2)
  17.  
  18. '2020-03-16 Segments Intersect revised 2020-03-16
  19. ' OK now get the new FUNCTION working
  20. ' ah! I had to tighten down D from >.2 to >.05 but loosen y-axis intersect
  21.  
  22. '2020-03-18 apply routines to two triangles
  23. ' modified FUNCTION twoSegmentsIntersect% (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix1, iy1)
  24. ' to do only intersect. This code proved, Segments Intersect revised 2020-03-16, was faulty.
  25.  
  26. '2020-03-18 a more exactling test of triangle overlaps with line segments over lapping
  27. ' purposely to the random triangles already tested and working well.
  28.  
  29.  
  30. CONST xmax = 800, ymax = 600
  31. SCREEN _NEWIMAGE(xmax, ymax, 32)
  32. _DELAY .25
  33. DIM ax1 AS INTEGER, ax2 AS INTEGER, ay1 AS INTEGER, ay2 AS INTEGER, ax3 AS INTEGER, ay3 AS INTEGER
  34. DIM bx1 AS INTEGER, bx2 AS INTEGER, by1 AS INTEGER, by2 AS INTEGER, bx3 AS INTEGER, by3 AS INTEGER
  35.  
  36. DO 'main testing loop sets up two triangles to test overlap area
  37.     lCnt = lCnt + 1 'loop counter to control some purposeful test triangles
  38.     IF lCnt MOD 4 = 0 THEN 'purpose overlap vertical lines
  39.         cText 400, 580, 32, &HFF0088FF, "Two Triangles with Common Vertical Segment"
  40.         ax1 = 400: ay1 = 20
  41.         ax2 = 400: ay2 = 570
  42.         ax3 = (xmax - 20) * RND + 10: ay3 = (ymax - 20) * RND + 10
  43.         bx1 = 400: by1 = 200
  44.         bx2 = 400: by2 = 450
  45.         bx3 = (xmax - 20) * RND + 10: by3 = (ymax - 20) * RND + 10
  46.  
  47.     ELSEIF lCnt MOD 4 = 1 THEN 'purpose overlap horizontal line
  48.         cText 400, 580, 32, &HFF008800, "Two Triangles with Common Horizontal Segment"
  49.         ax1 = 10: ay1 = 300
  50.         ax2 = 400: ay2 = 300
  51.         ax3 = (xmax - 20) * RND + 10: ay3 = (ymax - 20) * RND + 10
  52.         bx1 = 125: by1 = 300
  53.         bx2 = 700: by2 = 300
  54.         bx3 = (xmax - 20) * RND + 10: by3 = by3 = (ymax - 20) * RND + 10
  55.  
  56.     ELSEIF lCnt MOD 4 = 2 THEN 'purpose overlap 1/5 triangle
  57.         cText 400, 580, 32, &HFFFF8800, "Two Triangles with Common 45 Degree Segment"
  58.         ax1 = 100: ay1 = 100
  59.         ax2 = 400: ay2 = 400
  60.         ax3 = (xmax - 20) * RND + 10: ay3 = (ymax - 20) * RND + 10
  61.         bx1 = 50: by1 = 50
  62.         bx2 = 500: by2 = 500
  63.         bx3 = (xmax - 20) * RND + 10: by3 = (ymax - 20) * RND + 10
  64.  
  65.     ELSEIF lCnt MOD 4 = 3 THEN ' completely random triangles
  66.         cText 400, 580, 32,  &HFF0000FF, "Two Completely Random Triangles"
  67.         ax1 = (xmax - 20) * RND + 10: ay1 = (ymax - 20) * RND + 10
  68.         ax2 = (xmax - 20) * RND + 10: ay2 = (ymax - 20) * RND + 10
  69.         ax3 = (xmax - 20) * RND + 10: ay3 = (ymax - 20) * RND + 10
  70.         bx1 = (xmax - 20) * RND + 10: by1 = (ymax - 20) * RND + 10
  71.         bx2 = (xmax - 20) * RND + 10: by2 = (ymax - 20) * RND + 10
  72.         bx3 = (xmax - 20) * RND + 10: by3 = (ymax - 20) * RND + 10
  73.     END IF
  74.     'tri a
  75.     LINE (ax1, ay1)-(ax2, ay2), &HFFFF0000
  76.     LINE (ax2, ay2)-(ax3, ay3), &HFFFF0000
  77.     LINE (ax3, ay3)-(ax1, ay1), &HFFFF0000
  78.     'tri b
  79.     LINE (bx1, by1)-(bx2, by2), &HFF0000FF
  80.     LINE (bx2, by2)-(bx3, by3), &HFF0000FF
  81.     LINE (bx3, by3)-(bx1, by1), &HFF0000FF
  82.  
  83.     dista2a3 = _HYPOT(ax2 - ax3, ay2 - ay3)
  84.     adx = (ax3 - ax2) / dista2a3: ady = (ay3 - ay2) / dista2a3
  85.     FOR i = 0 TO dista2a3
  86.         x1 = ax2 + adx * i: y1 = ay2 + ady * i
  87.         sect = twoSegmentsIntersect%(ax1, ay1, x1, y1, bx1, by1, bx2, by2, ix1, iy1)
  88.         IF sect THEN PSET (ix1, iy1)
  89.         sect = twoSegmentsIntersect%(ax1, ay1, x1, y1, bx3, by3, bx2, by2, ix1, iy1)
  90.         IF sect THEN PSET (ix1, iy1)
  91.         sect = twoSegmentsIntersect%(ax1, ay1, x1, y1, bx1, by1, bx3, by3, ix1, iy1)
  92.         IF sect = 1 THEN PSET (ix1, iy1)
  93.     NEXT
  94.  
  95.     dista1a3 = _HYPOT(ax1 - ax3, ay1 - ay3)
  96.     adx = (ax3 - ax1) / dista1a3: ady = (ay3 - ay1) / dista1a3
  97.     FOR i = 0 TO dista1a3
  98.         x1 = ax1 + adx * i: y1 = ay1 + ady * i
  99.         sect = twoSegmentsIntersect%(ax2, ay2, x1, y1, bx1, by1, bx2, by2, ix1, iy1)
  100.         IF sect THEN PSET (ix1, iy1)
  101.         sect = twoSegmentsIntersect%(ax2, ay2, x1, y1, bx3, by3, bx2, by2, ix1, iy1)
  102.         IF sect THEN PSET (ix1, iy1)
  103.         sect = twoSegmentsIntersect%(ax2, ay2, x1, y1, bx1, by1, bx3, by3, ix1, iy1)
  104.         IF sect = 1 THEN PSET (ix1, iy1)
  105.     NEXT
  106.  
  107.     dista1a2 = _HYPOT(ax1 - ax2, ay1 - ay2)
  108.     adx = (ax2 - ax1) / dista1a2: ady = (ay2 - ay1) / dista1a2
  109.     FOR i = 0 TO dista1a2
  110.         x1 = ax1 + adx * i: y1 = ay1 + ady * i
  111.         sect = twoSegmentsIntersect%(ax3, ay3, x1, y1, bx1, by1, bx2, by2, ix1, iy1)
  112.         IF sect THEN PSET (ix1, iy1)
  113.         sect = twoSegmentsIntersect%(ax3, ay3, x1, y1, bx3, by3, bx2, by2, ix1, iy1)
  114.         IF sect THEN PSET (ix1, iy1)
  115.         sect = twoSegmentsIntersect%(ax3, ay3, x1, y1, bx1, by1, bx3, by3, ix1, iy1)
  116.         IF sect = 1 THEN PSET (ix1, iy1)
  117.     NEXT
  118.  
  119.     distb2b3 = _HYPOT(bx2 - bx3, by2 - by3)
  120.     bdx = (bx3 - bx2) / distb2b3: bdy = (by3 - by2) / distb2b3
  121.     FOR i = 0 TO distb2b3
  122.         x1 = bx2 + bdx * i: y1 = by2 + bdy * i
  123.         sect = twoSegmentsIntersect%(bx1, by1, x1, y1, ax1, ay1, ax2, ay2, ix1, iy1)
  124.         IF sect = 1 THEN PSET (ix1, iy1)
  125.         sect = twoSegmentsIntersect%(bx1, by1, x1, y1, ax3, ay3, ax2, ay2, ix1, iy1)
  126.         IF sect THEN PSET (ix1, iy1)
  127.         sect = twoSegmentsIntersect%(bx1, by1, x1, y1, ax1, ay1, ax3, ay3, ix1, iy1)
  128.         IF sect = 1 THEN PSET (ix1, iy1)
  129.     NEXT
  130.  
  131.     distb1b3 = _HYPOT(bx1 - bx3, by1 - by3)
  132.     bdx = (bx3 - bx1) / distb1b3: bdy = (by3 - by1) / distb1b3
  133.     FOR i = 0 TO distb1b3
  134.         x1 = bx1 + bdx * i: y1 = by1 + bdy * i
  135.         sect = twoSegmentsIntersect%(bx2, by2, x1, y1, ax1, ay1, ax2, ay2, ix1, iy1)
  136.         IF sect THEN PSET (ix1, iy1)
  137.         sect = twoSegmentsIntersect%(bx2, by2, x1, y1, ax3, ay3, ax2, ay2, ix1, iy1)
  138.         IF sect THEN PSET (ix1, iy1)
  139.         sect = twoSegmentsIntersect%(bx2, by2, x1, y1, ax1, ay1, ax3, ay3, ix1, iy1)
  140.         IF sect = 1 THEN PSET (ix1, iy1)
  141.     NEXT
  142.  
  143.     distb1b2 = _HYPOT(bx1 - bx2, by1 - by2)
  144.     bdx = (bx2 - bx1) / distb1b2: bdy = (by2 - by1) / distb1b2
  145.     FOR i = 0 TO distb1b2
  146.         x1 = bx1 + bdx * i: y1 = by1 + bdy * i
  147.         sect = twoSegmentsIntersect%(bx3, by3, x1, y1, ax1, ay1, ax2, ay2, ix1, iy1)
  148.         IF sect THEN PSET (ix1, iy1)
  149.         sect = twoSegmentsIntersect%(bx3, by3, x1, y1, ax3, ay3, ax2, ay2, ix1, iy1)
  150.         IF sect THEN PSET (ix1, iy1)
  151.         sect = twoSegmentsIntersect%(bx3, by3, x1, y1, ax1, ay1, ax3, ay3, ix1, iy1)
  152.         IF sect = 1 THEN PSET (ix1, iy1)
  153.     NEXT
  154.  
  155.     INPUT "Press enter for another demo, any + enter to quit...", again$
  156.     CLS
  157. LOOP UNTIL LEN(again$)
  158.  
  159. 'Slope and Y-intersect for non vertical lines,
  160. ' if x1 = x2 the line is vertical don't call this sub
  161. ' because slope calculation would cause division by 0 error.
  162. SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept) 'check x1 <> x2 first!
  163.     slope = (Y2 - Y1) / (X2 - X1): Yintercept = slope * (0 - X1) + Y1
  164.  
  165. ' ======================================== end tester code functions ======================================
  166.  
  167. 'This function needs: FUNCTION lineIntersectLine% (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  168. ' which in turn needs: SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept) 'check x1 <> x2 first!
  169. FUNCTION twoSegmentsIntersect% (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix1, iy1)
  170.     intersect = lineIntersectLine%(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  171.     IF ax1 < ax2 THEN aMinX = ax1: aMaxX = ax2 ELSE aMinX = ax2: aMaxX = ax1
  172.     IF ay1 < ay2 THEN aMinY = ay1: aMaxY = ay2 ELSE aMinY = ay2: aMaxY = ay1
  173.     IF bx1 < bx2 THEN bMinX = bx1: bMaxX = bx2 ELSE bMinX = bx2: bMaxX = bx1
  174.     IF by1 < by2 THEN bMinY = by1: bMaxY = by2 ELSE bMinY = by2: bMaxY = by1
  175.     IF intersect = 0 THEN 'no  intersect
  176.         twoSegmentsIntersect% = 0
  177.     ELSEIF intersect = 1 THEN 'segments intersect at one point
  178.         IF ax1 = ax2 THEN 'is iy between
  179.             IF iy < aMinY OR iy > aMaxY OR ix < bMinX OR ix > bMaxX THEN
  180.                 twoSegmentsIntersect% = 0
  181.             ELSE
  182.                 ix1 = ix: iy1 = iy: twoSegmentsIntersect% = 1
  183.             END IF
  184.         ELSEIF bx1 = bx2 THEN
  185.             IF iy < bMinY OR iy > bMaxY OR ix < aMinX OR ix > aMaxX THEN
  186.                 twoSegmentsIntersect% = 0
  187.             ELSE
  188.                 ix1 = ix: iy1 = iy: twoSegmentsIntersect% = 1
  189.             END IF
  190.         ELSE
  191.             IF (aMinX <= ix AND ix <= aMaxX) AND (bMinX <= ix AND ix <= bMaxX) THEN
  192.                 ix1 = ix: iy1 = iy: twoSegmentsIntersect% = 1
  193.             END IF
  194.         END IF
  195.     END IF
  196.  
  197. ' this function needs: SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept)
  198. FUNCTION lineIntersectLine% (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  199.     IF ax1 = ax2 THEN 'line a is vertical
  200.         IF bx1 = bx2 THEN ' b is vertical
  201.             IF ax1 = bx1 THEN lineIntersectLine% = -1 ' if x's are same it is same vertical line
  202.             EXIT FUNCTION '
  203.         ELSE
  204.             ix = ax1
  205.             slopeYintersect bx1, by1, bx2, by2, m2, y02
  206.             iy = m2 * ix + y02
  207.             lineIntersectLine% = 1 'signal a point was found
  208.             EXIT FUNCTION
  209.         END IF
  210.     ELSE
  211.         slopeYintersect ax1, ay1, ax2, ay2, m1, y01 ' -m = a, 1 = b, y0 = c  std form
  212.     END IF
  213.     IF bx1 = bx2 THEN 'b is vertical
  214.         ix = bx1: iy = m1 * ix + y01: lineIntersectLine% = 1 'signal a point was found
  215.         EXIT FUNCTION
  216.     ELSE
  217.         slopeYintersect bx1, by1, bx2, by2, m2, y02 ' -m = a, 1 = b, y0 = c  std form
  218.     END IF
  219.     d = -m1 - -m2 ' if = 0 then parallel or equal because slopes are same
  220.     IF d THEN 'otherwise about 0 <<< tighten down from .2 to .05
  221.         ix = (y01 - y02) / d: iy = (-m1 * y02 - -m2 * y01) / d
  222.         lineIntersectLine% = 1 'signal one intersect point was found
  223.     END IF
  224.  
  225. 'center the text at x, y with given height and color
  226. SUB cText (x, y, textHeight, K AS _UNSIGNED LONG, txt$)
  227.     DIM fg AS _UNSIGNED LONG, cur&, I&, mult, xlen
  228.     fg = _DEFAULTCOLOR
  229.     'screen snapshot
  230.     cur& = _DEST
  231.     I& = _NEWIMAGE(8 * LEN(txt$), 16, 32)
  232.     _DEST I&
  233.     COLOR K, _RGBA32(0, 0, 0, 0)
  234.     _PRINTSTRING (0, 0), txt$
  235.     mult = textHeight / 16
  236.     xlen = LEN(txt$) * 8 * mult
  237.     _PUTIMAGE (x - .5 * xlen, y - .5 * textHeight)-STEP(xlen, textHeight), I&, cur&
  238.     COLOR fg
  239.     _FREEIMAGE I&
  240.  
  241.  

 


It's taking about 60+ lines of code to figure intersect point of two line segments.
Title: Re: Intersect of 2 lines carried a step further
Post by: TempodiBasic on March 18, 2020, 08:52:05 pm
Very Impressive Bplus
  [ This attachment cannot be displayed inline in 'Print Page' view ]  
Thanks to share the code

Title: Re: Intersect of 2 lines carried a step further
Post by: STxAxTIC on March 21, 2020, 03:43:32 pm
Nice one bplus.

While I didn't bother with triangles, I wrote up the case of intersecting lines and wrote out the requirements for overlapping segments. Jst for academic completeness...

EDIT - removed third page - it was bullshit

Title: Re: Intersect of 2 lines carried a step further
Post by: bplus on March 21, 2020, 04:03:04 pm
Nice one bplus.

While I didn't bother with triangles, I wrote up the case of intersecting lines and wrote out the requirements for overlapping segments. Jst for academic completeness...



Thanks STxAxTIC, you know I've a feeling your code is way shorter than mine and theoretically accomplish the same thing. It is so abstract for me, I couldn't translate it into something I could use for the app. If you wouldn't mind I'd prefer simple brevity of a Segment Intersect SUB set up as I have and returns True if Intersect with the ix, iy point named in value. Can it be written without the segment Type and maintain it's brevity? If I am asking you to commit a Physic's sin? pretend I never asked. :)
Title: Re: Intersect of 2 lines carried a step further
Post by: STxAxTIC on March 21, 2020, 04:07:12 pm
Aw man bplus no worries - I mean, these works really do accomplish the same thing, and my notation is undoubtedly stylized for the thick-skinned. My real thoughts on the matter are that you've got this ground covered. I hesitated to make the code into a sub because there are an ambiguous number of return values and QB64 is funny about that.

However - because the conversion from mine to yours is straightforward enough, I could easily work this into a SUB of some kind that returns the intersection points and flags perfect overlapping, or even overlapping to a threshold. I'll whip it up just so we have two floating around, but I get the sense you got there first 100% and I'm in your shadow on this one.
Title: Re: Intersect of 2 lines carried a step further
Post by: bplus on March 21, 2020, 04:21:29 pm
Aw man bplus no worries - I mean, these works really do accomplish the same thing, and my notation is undoubtedly stylized for the thick-skinned. My real thoughts on the matter are that you've got this ground covered. I hesitated to make the code into a sub because there are an ambiguous number of return values and QB64 is funny about that.

However - because the conversion from mine to yours is straightforward enough, I could easily work this into a SUB of some kind that returns the intersection points and flags perfect overlapping, or even overlapping to a threshold. I'll whip it up just so we have two floating around, but I get the sense you got there first 100% and I'm in your shadow on this one.

Just a reminder, I've realized, at least for this particular application, I don't need to know about overlap, count that as 0 or false Intersect, please don't bother with that difficult case. Just a straight and simple intersect will do it for me for this.

For Bonus, you could try the overlap case too, I used -1 for overlap, 1 for Intersect, 0 for neither Intersect nor Overlap, but then you need 2 points and more tricky code. It's likely to come in handy down the line. I never did nail down overlap and this application proved it to me.

Those triangle overlaps are drawn only from tons of intersects.
Title: Re: Intersect of 2 lines carried a step further
Post by: STxAxTIC on March 21, 2020, 05:54:27 pm
Heya bplus,

So this code has the intersections and the overlaps perfectly calculated - the overlap threshold is set high for demo purposes. If you rotate the line with the mouse wheel you can see it in action.

Next thing would be to turn this into a SUB. Gonna let this cook for a minute before I change it again.

Code: QB64: [Select]
  1.  
  2. TYPE Vector
  3.     x AS DOUBLE
  4.     y AS DOUBLE
  5.  
  6. TYPE LineSegment
  7.     b AS Vector
  8.     alpha1 AS DOUBLE
  9.     alpha2 AS DOUBLE
  10.     ang AS DOUBLE
  11.     t AS Vector
  12.     p1 AS Vector
  13.     p2 AS Vector
  14.  
  15. DIM SHARED Segments(2) AS LineSegment
  16.  
  17. Segments(1).b.x = 0
  18. Segments(1).b.y = 0
  19. Segments(1).alpha1 = -50
  20. Segments(1).alpha2 = 50
  21. Segments(1).ang = 0
  22. CALL CalcLine(1)
  23.  
  24. Segments(2).b.x = 0
  25. Segments(2).b.y = 50
  26. Segments(2).alpha1 = -100
  27. Segments(2).alpha2 = 100
  28. Segments(2).ang = ATN(1)
  29. CALL CalcLine(2)
  30.  
  31.  
  32.         x = _MOUSEX
  33.         y = _MOUSEY
  34.         IF ((x > 0) AND (x < _WIDTH) AND (y > 0) AND (y < _HEIGHT)) THEN
  35.             IF _MOUSEBUTTON(1) THEN
  36.                 x = _MOUSEX
  37.                 y = _MOUSEY
  38.                 Segments(1).b.x = (x - _WIDTH / 2)
  39.                 Segments(1).b.y = (-y + _HEIGHT / 2)
  40.                 CALL CalcLine(1)
  41.             END IF
  42.             IF _MOUSEWHEEL > 0 THEN
  43.                 Segments(1).ang = Segments(1).ang + ATN(1) / 10
  44.                 CALL CalcLine(1)
  45.             END IF
  46.             IF _MOUSEWHEEL < 0 THEN
  47.                 Segments(1).ang = Segments(1).ang - ATN(1) / 10
  48.                 CALL CalcLine(1)
  49.             END IF
  50.         END IF
  51.     LOOP
  52.  
  53.     CLS
  54.     CALL cline(Segments(1).p1.x, Segments(1).p1.y, Segments(1).p2.x, Segments(1).p2.y, 15)
  55.     CALL cline(Segments(2).p1.x, Segments(2).p1.y, Segments(2).p2.x, Segments(2).p2.y, 14)
  56.  
  57.     ''' Intersection calculation
  58.     DIM db AS Vector
  59.     db.x = Segments(2).b.x - Segments(1).b.x
  60.     db.y = Segments(2).b.y - Segments(1).b.y
  61.     qj = DotProduct(db, Segments(1).t)
  62.     ql = DotProduct(db, Segments(2).t)
  63.     p = DotProduct(Segments(1).t, Segments(2).t)
  64.     pp = p * p
  65.     IF (pp < 1) THEN
  66.         alphaj = (qj - p * ql) / (1 - pp)
  67.         alphal = (p * qj - ql) / (1 - pp)
  68.         IF ((alphaj > Segments(1).alpha1) AND (alphaj < Segments(1).alpha2)) THEN
  69.             IF ((alphal > Segments(2).alpha1) AND (alphal < Segments(2).alpha2)) THEN
  70.                 CALL ccircle(Segments(1).b.x + alphaj * Segments(1).t.x, Segments(1).b.y + alphaj * Segments(1).t.y, 3, 13)
  71.                 CALL ccircle(Segments(2).b.x + alphal * Segments(2).t.x, Segments(2).b.y + alphal * Segments(2).t.y, 5, 15)
  72.             END IF
  73.         END IF
  74.     ELSE ' Parallel case
  75.         DIM dbhat AS Vector
  76.         dbmag = SQR(db.x * db.x + db.y * db.y)
  77.         dbhat.x = db.x / dbmag
  78.         dbhat.y = db.y / dbmag
  79.         thresh = DotProduct(dbhat, Segments(1).t)
  80.         IF (1 - thresh * thresh < 0.01) THEN ' Overlap case
  81.             t1t2 = DotProduct(Segments(1).t, Segments(2).t)
  82.             alphaj1 = Segments(2).alpha1 * t1t2 + DotProduct(Segments(1).t, db)
  83.             alphaj2 = Segments(2).alpha2 * t1t2 + DotProduct(Segments(1).t, db)
  84.             IF ((alphaj1 > Segments(1).alpha1) AND (alphaj1 < Segments(1).alpha2)) THEN
  85.                 CALL ccircle(Segments(1).b.x + alphaj1 * Segments(1).t.x, Segments(1).b.y + alphaj1 * Segments(1).t.y, 3, 13)
  86.                 CALL ccircle(Segments(2).b.x + Segments(2).alpha1 * Segments(2).t.x, Segments(2).b.y + Segments(2).alpha1 * Segments(2).t.y, 4, 14)
  87.             END IF
  88.             IF ((alphaj2 > Segments(1).alpha1) AND (alphaj2 < Segments(1).alpha2)) THEN
  89.                 CALL ccircle(Segments(1).b.x + alphaj2 * Segments(1).t.x, Segments(1).b.y + alphaj2 * Segments(1).t.y, 3, 13)
  90.                 CALL ccircle(Segments(2).b.x + Segments(2).alpha2 * Segments(2).t.x, Segments(2).b.y + Segments(2).alpha2 * Segments(2).t.y, 4, 14)
  91.             END IF
  92.             alphal1 = Segments(1).alpha1 * t1t2 - DotProduct(Segments(2).t, db)
  93.             alphal2 = Segments(1).alpha2 * t1t2 - DotProduct(Segments(2).t, db)
  94.             IF ((alphal1 > Segments(2).alpha1) AND (alphal1 < Segments(2).alpha2)) THEN
  95.                 CALL ccircle(Segments(2).b.x + alphal1 * Segments(2).t.x, Segments(2).b.y + alphal1 * Segments(2).t.y, 3, 13)
  96.                 CALL ccircle(Segments(1).b.x + Segments(1).alpha1 * Segments(1).t.x, Segments(1).b.y + Segments(1).alpha1 * Segments(1).t.y, 5, 15)
  97.             END IF
  98.             IF ((alphal2 > Segments(2).alpha1) AND (alphal2 < Segments(2).alpha2)) THEN
  99.                 CALL ccircle(Segments(2).b.x + alphal2 * Segments(2).t.x, Segments(2).b.y + alphal2 * Segments(2).t.y, 3, 13)
  100.                 CALL ccircle(Segments(1).b.x + Segments(1).alpha2 * Segments(1).t.x, Segments(1).b.y + Segments(1).alpha2 * Segments(1).t.y, 5, 15)
  101.             END IF
  102.         END IF
  103.     END IF
  104.     '''
  105.  
  106.     _DISPLAY
  107.     _LIMIT 60
  108.  
  109.  
  110. SUB CalcLine (i AS INTEGER)
  111.     Segments(i).t.x = COS(Segments(i).ang)
  112.     Segments(i).t.y = SIN(Segments(i).ang)
  113.     Segments(i).p1.x = Segments(i).b.x + Segments(i).alpha1 * Segments(i).t.x
  114.     Segments(i).p1.y = Segments(i).b.y + Segments(i).alpha1 * Segments(i).t.y
  115.     Segments(i).p2.x = Segments(i).b.x + Segments(i).alpha2 * Segments(i).t.x
  116.     Segments(i).p2.y = Segments(i).b.y + Segments(i).alpha2 * Segments(i).t.y
  117.  
  118. FUNCTION DotProduct (a AS Vector, b AS Vector)
  119.     DotProduct = a.x * b.x + a.y * b.y
  120.  
  121. SUB cline (x1 AS DOUBLE, y1 AS DOUBLE, x2 AS DOUBLE, y2 AS DOUBLE, col AS _UNSIGNED LONG)
  122.     LINE (_WIDTH / 2 + x1, -y1 + _HEIGHT / 2)-(_WIDTH / 2 + x2, -y2 + _HEIGHT / 2), col
  123.  
  124. SUB ccircle (x1 AS DOUBLE, y1 AS DOUBLE, rad AS DOUBLE, col AS _UNSIGNED LONG)
  125.     CIRCLE (_WIDTH / 2 + x1, -y1 + _HEIGHT / 2), rad, col
  126.  
  127. SUB cpset (x1 AS DOUBLE, y1 AS DOUBLE, col AS _UNSIGNED LONG)
  128.     PSET (_WIDTH / 2 + x1, -y1 + _HEIGHT / 2), col
  129.  
  130. SUB cpaint (x1 AS DOUBLE, y1 AS DOUBLE, col1 AS _UNSIGNED LONG, col2 AS _UNSIGNED LONG)
  131.     PAINT (_WIDTH / 2 + x1, -y1 + _HEIGHT / 2), col1, col2
  132.  
  133. SUB cprintstring (y AS DOUBLE, a AS STRING)
  134.     _PRINTSTRING (_WIDTH / 2 - (LEN(a) * 8) / 2, -y + _HEIGHT / 2), a
  135.  
Title: Re: Intersect of 2 lines carried a step further
Post by: STxAxTIC on March 22, 2020, 02:09:38 am
This version will do triangles and more. Detects all intersections *and* overlaps in all lines to an adjustable threshold. See screenshot

Code: QB64: [Select]
  1.  
  2. TYPE Vector
  3.     x AS DOUBLE
  4.     y AS DOUBLE
  5.  
  6. TYPE LineSegment
  7.     b AS Vector
  8.     alpha1 AS DOUBLE
  9.     alpha2 AS DOUBLE
  10.     ang AS DOUBLE
  11.     t AS Vector
  12.     p1 AS Vector
  13.     p2 AS Vector
  14.  
  15. DIM SHARED Segments(100) AS LineSegment
  16. DIM SHARED NumSegments AS INTEGER
  17.  
  18. NumSegments = 0
  19.  
  20. NumSegments = NumSegments + 1
  21. Segments(NumSegments).b.x = 0
  22. Segments(NumSegments).b.y = 0
  23. Segments(NumSegments).alpha1 = -150
  24. Segments(NumSegments).alpha2 = 150
  25. Segments(NumSegments).ang = ATN(1)
  26. CALL CalibrateLine(NumSegments)
  27.  
  28. NumSegments = NumSegments + 1
  29. Segments(NumSegments).b.x = 0
  30. Segments(NumSegments).b.y = 50
  31. Segments(NumSegments).alpha1 = -100
  32. Segments(NumSegments).alpha2 = 100
  33. Segments(NumSegments).ang = ATN(1)
  34. CALL CalibrateLine(NumSegments)
  35.  
  36. NumSegments = NumSegments + 1
  37. Segments(NumSegments).b.x = 0
  38. Segments(NumSegments).b.y = 50
  39. Segments(NumSegments).alpha1 = -100
  40. Segments(NumSegments).alpha2 = 100
  41. Segments(NumSegments).ang = -ATN(1)
  42. CALL CalibrateLine(NumSegments)
  43.  
  44. FOR k = 1 TO 15
  45.     NumSegments = NumSegments + 1
  46.     Segments(NumSegments).b.x = 1 * _WIDTH * (RND - .5)
  47.     Segments(NumSegments).b.y = 1 * _HEIGHT * (RND - .5)
  48.     Segments(NumSegments).alpha1 = -100 - RND * 100
  49.     Segments(NumSegments).alpha2 = 100 + RND * 100
  50.     Segments(NumSegments).ang = RND * 4 * ATN(1)
  51.     CALL CalibrateLine(NumSegments)
  52.  
  53.  
  54.         x = _MOUSEX
  55.         y = _MOUSEY
  56.         IF ((x > 0) AND (x < _WIDTH) AND (y > 0) AND (y < _HEIGHT)) THEN
  57.             IF _MOUSEBUTTON(1) THEN
  58.                 x = _MOUSEX
  59.                 y = _MOUSEY
  60.                 Segments(1).b.x = (x - _WIDTH / 2)
  61.                 Segments(1).b.y = (-y + _HEIGHT / 2)
  62.                 CALL CalibrateLine(1)
  63.             END IF
  64.             IF _MOUSEWHEEL > 0 THEN
  65.                 Segments(1).ang = Segments(1).ang + ATN(1) / 10
  66.                 CALL CalibrateLine(1)
  67.             END IF
  68.             IF _MOUSEWHEEL < 0 THEN
  69.                 Segments(2).ang = Segments(2).ang + ATN(1) / 10
  70.                 CALL CalibrateLine(2)
  71.             END IF
  72.         END IF
  73.     LOOP
  74.  
  75.     CLS
  76.     FOR k = 1 TO NumSegments
  77.         CALL cline(Segments(k).p1.x, Segments(k).p1.y, Segments(k).p2.x, Segments(k).p2.y, 15)
  78.     NEXT
  79.  
  80.     FOR k = 1 TO NumSegments
  81.         FOR j = k + 1 TO NumSegments
  82.  
  83.             ''' Intersection calculation
  84.             Seg1 = k
  85.             Seg2 = j
  86.  
  87.             DIM db AS Vector
  88.             db.x = Segments(Seg2).b.x - Segments(Seg1).b.x
  89.             db.y = Segments(Seg2).b.y - Segments(Seg1).b.y
  90.             qj = DotProduct(db, Segments(Seg1).t)
  91.             ql = DotProduct(db, Segments(Seg2).t)
  92.             p = DotProduct(Segments(Seg1).t, Segments(Seg2).t)
  93.             pp = p * p
  94.             IF (pp < 1) THEN ' Non-parallel case
  95.                 alphaj = (qj - p * ql) / (1 - pp)
  96.                 alphal = (p * qj - ql) / (1 - pp)
  97.                 IF ((alphaj > Segments(Seg1).alpha1) AND (alphaj < Segments(Seg1).alpha2)) THEN
  98.                     IF ((alphal > Segments(Seg2).alpha1) AND (alphal < Segments(Seg2).alpha2)) THEN
  99.                         CALL ccircle(Segments(Seg1).b.x + alphaj * Segments(Seg1).t.x, Segments(Seg1).b.y + alphaj * Segments(Seg1).t.y, 3, 13)
  100.                         CALL ccircle(Segments(Seg2).b.x + alphal * Segments(Seg2).t.x, Segments(Seg2).b.y + alphal * Segments(Seg2).t.y, 5, 15)
  101.                     END IF
  102.                 END IF
  103.             ELSE ' Parallel case
  104.                 DIM dbhat AS Vector
  105.                 dbmag = SQR(db.x * db.x + db.y * db.y)
  106.                 dbhat.x = db.x / dbmag
  107.                 dbhat.y = db.y / dbmag
  108.                 thresh = DotProduct(dbhat, Segments(Seg1).t)
  109.                 IF (1 - thresh * thresh < 0.001) THEN ' Overlap case
  110.                     t1t2 = DotProduct(Segments(Seg1).t, Segments(Seg2).t)
  111.                     alphaj1 = Segments(Seg2).alpha1 * t1t2 + DotProduct(Segments(Seg1).t, db)
  112.                     alphaj2 = Segments(Seg2).alpha2 * t1t2 + DotProduct(Segments(Seg1).t, db)
  113.                     x1 = 0
  114.                     y1 = 0
  115.                     x2 = 0
  116.                     y2 = 0
  117.                     IF ((alphaj1 > Segments(Seg1).alpha1) AND (alphaj1 < Segments(Seg1).alpha2)) THEN
  118.                         xx = Segments(Seg1).b.x + alphaj1 * Segments(Seg1).t.x
  119.                         yy = Segments(Seg1).b.y + alphaj1 * Segments(Seg1).t.y
  120.                         IF (x1 = 0) THEN x1 = xx ELSE x2 = xx
  121.                         IF (y1 = 0) THEN y1 = yy ELSE y2 = yy
  122.                         CALL ccircle(xx, yy, 3, 13)
  123.                         'CALL ccircle(Segments(Seg2).b.x + Segments(Seg2).alpha1 * Segments(Seg2).t.x, Segments(Seg2).b.y + Segments(Seg2).alpha1 * Segments(Seg2).t.y, 4, 14)
  124.                     END IF
  125.                     IF ((alphaj2 > Segments(Seg1).alpha1) AND (alphaj2 < Segments(Seg1).alpha2)) THEN
  126.                         xx = Segments(Seg1).b.x + alphaj2 * Segments(Seg1).t.x
  127.                         yy = Segments(Seg1).b.y + alphaj2 * Segments(Seg1).t.y
  128.                         IF (x1 = 0) THEN x1 = xx ELSE x2 = xx
  129.                         IF (y1 = 0) THEN y1 = yy ELSE y2 = yy
  130.                         CALL ccircle(xx, yy, 3, 13)
  131.                         'CALL ccircle(Segments(Seg2).b.x + Segments(Seg2).alpha2 * Segments(Seg2).t.x, Segments(Seg2).b.y + Segments(Seg2).alpha2 * Segments(Seg2).t.y, 4, 14)
  132.                     END IF
  133.                     alphal1 = Segments(Seg1).alpha1 * t1t2 - DotProduct(Segments(Seg2).t, db)
  134.                     alphal2 = Segments(Seg1).alpha2 * t1t2 - DotProduct(Segments(Seg2).t, db)
  135.                     IF ((alphal1 > Segments(Seg2).alpha1) AND (alphal1 < Segments(Seg2).alpha2)) THEN
  136.                         xx = Segments(Seg2).b.x + alphal1 * Segments(Seg2).t.x
  137.                         yy = Segments(Seg2).b.y + alphal1 * Segments(Seg2).t.y
  138.                         IF (x1 = 0) THEN x1 = xx ELSE x2 = xx
  139.                         IF (y1 = 0) THEN y1 = yy ELSE y2 = yy
  140.                         CALL ccircle(xx, yy, 3, 15)
  141.                         'CALL ccircle(Segments(Seg1).b.x + Segments(Seg1).alpha1 * Segments(Seg1).t.x, Segments(Seg1).b.y + Segments(Seg1).alpha1 * Segments(Seg1).t.y, 5, 15)
  142.                     END IF
  143.                     IF ((alphal2 > Segments(Seg2).alpha1) AND (alphal2 < Segments(Seg2).alpha2)) THEN
  144.                         xx = Segments(Seg2).b.x + alphal2 * Segments(Seg2).t.x
  145.                         yy = Segments(Seg2).b.y + alphal2 * Segments(Seg2).t.y
  146.                         IF (x1 = 0) THEN x1 = xx ELSE x2 = xx
  147.                         IF (y1 = 0) THEN y1 = yy ELSE y2 = yy
  148.                         CALL ccircle(xx, yy, 3, 15)
  149.                         'CALL ccircle(Segments(Seg1).b.x + Segments(Seg1).alpha2 * Segments(Seg1).t.x, Segments(Seg1).b.y + Segments(Seg1).alpha2 * Segments(Seg1).t.y, 5, 15)
  150.                     END IF
  151.                     IF (x1 OR x2 OR y1 OR y2) THEN
  152.                         CALL cline(x1, y1, x2, y2, 13)
  153.                     END IF
  154.                 END IF
  155.             END IF
  156.             '''
  157.  
  158.         NEXT
  159.     NEXT
  160.  
  161.     _DISPLAY
  162.     _LIMIT 60
  163.  
  164.  
  165. SUB CalibrateLine (i AS INTEGER)
  166.     Segments(i).t.x = COS(Segments(i).ang)
  167.     Segments(i).t.y = SIN(Segments(i).ang)
  168.     Segments(i).p1.x = Segments(i).b.x + Segments(i).alpha1 * Segments(i).t.x
  169.     Segments(i).p1.y = Segments(i).b.y + Segments(i).alpha1 * Segments(i).t.y
  170.     Segments(i).p2.x = Segments(i).b.x + Segments(i).alpha2 * Segments(i).t.x
  171.     Segments(i).p2.y = Segments(i).b.y + Segments(i).alpha2 * Segments(i).t.y
  172.  
  173. FUNCTION DotProduct (a AS Vector, b AS Vector)
  174.     DotProduct = a.x * b.x + a.y * b.y
  175.  
  176. SUB cline (x1 AS DOUBLE, y1 AS DOUBLE, x2 AS DOUBLE, y2 AS DOUBLE, col AS _UNSIGNED LONG)
  177.     LINE (_WIDTH / 2 + x1, -y1 + _HEIGHT / 2)-(_WIDTH / 2 + x2, -y2 + _HEIGHT / 2), col
  178.  
  179. SUB ccircle (x1 AS DOUBLE, y1 AS DOUBLE, rad AS DOUBLE, col AS _UNSIGNED LONG)
  180.     CIRCLE (_WIDTH / 2 + x1, -y1 + _HEIGHT / 2), rad, col
  181.  
  182. SUB cpset (x1 AS DOUBLE, y1 AS DOUBLE, col AS _UNSIGNED LONG)
  183.     PSET (_WIDTH / 2 + x1, -y1 + _HEIGHT / 2), col
  184.  
  185. SUB cpaint (x1 AS DOUBLE, y1 AS DOUBLE, col1 AS _UNSIGNED LONG, col2 AS _UNSIGNED LONG)
  186.     PAINT (_WIDTH / 2 + x1, -y1 + _HEIGHT / 2), col1, col2
  187.  
  188. SUB cprintstring (y AS DOUBLE, a AS STRING)
  189.     _PRINTSTRING (_WIDTH / 2 - (LEN(a) * 8) / 2, -y + _HEIGHT / 2), a
  190.  
Title: Re: Intersect of 2 lines carried a step further
Post by: bplus on March 22, 2020, 10:12:44 am
Well no segment intersect function in sight except from bplus. OK ;-))

OK Terry had one that said True or False for Intersect but does not name the point values.

OK Well I will take another crack at making a shorter one after snakeBrain.
Title: Re: Intersect of 2 lines carried a step further
Post by: STxAxTIC on March 22, 2020, 10:51:25 am
This can be made into a sub now that it's done, of course.

You gotta see where i was coming from though - to ask for a SUB before this milestone would be asking for premature optimization.

Now that we're on this, what kind of outputs do you want the sub to give? Just a true/false? Pish posh right? Because what about the actual intersection points?
Title: Re: Intersect of 2 lines carried a step further
Post by: bplus on March 22, 2020, 04:42:46 pm
This can be made into a sub now that it's done, of course.

You gotta see where i was coming from though - to ask for a SUB before this milestone would be asking for premature optimization.

Now that we're on this, what kind of outputs do you want the sub to give? Just a true/false? Pish posh right? Because what about the actual intersection points?

https://www.qb64.org/forum/index.php?topic=2342.msg115971#msg115971
https://www.qb64.org/forum/index.php?topic=2342.msg115974#msg115974

FUNCTION SegIntersect%(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
Return True or -1 if intersect with i point at ix, iy
Return 0 if overlap or no intersect.

Purpose of sub as you've already figured out is for outlining intersect boundaries of 2D objects.
Title: Re: Intersect of 2 lines carried a step further
Post by: STxAxTIC on March 22, 2020, 04:52:36 pm
Yeah - I suppose we have to work around QB64 only outputting one thing per function. I can make this into a SUB prolly - but there may have to be some hacky helper functions.

The real problem arises from the overly cartesian mindset brought on by the QB64 coordinate system. Grumble grumble... get to work...
Title: Re: Intersect of 2 lines carried a step further
Post by: bplus on March 22, 2020, 05:09:20 pm
Yeah - I suppose we have to work around QB64 only outputting one thing per function. I can make this into a SUB prolly - but there may have to be some hacky helper functions.

The real problem arises from the overly cartesian mindset brought on by the QB64 coordinate system. Grumble grumble... get to work...

Remember all parameters are passed by reference so what goes in still comes out SUB or FUNCTION and is available to main code (as long as you are careful with Type). I have 2 helpers total 67 lines, I'm thinking that can be beat easily. I have allot of code dealing with slopes when 0 is denominator, if you use Standard Form you might be able to get around that. QB64 coordinate system has no effect on the math, it's just one quadrant that's upside down in our subjective vision.

Title: Re: Intersect of 2 lines carried a step further
Post by: STxAxTIC on March 22, 2020, 05:12:47 pm
QB64 coordinate system has no effect on the math, it's just one quadrant that's upside down in our subjective vision.

Deeply wrong sadly - the QB64 coordinate systems all violate the right hand rule. All depths must be thought of as negative depths (in screen). All cross products are backwards. All line integrals are backwards. Green's theorems become wonky. Everything sucks, it's counter intuitive, yall are simply used to it. I'm trying to drive home the fact that this isn't subjective - this isn't one of those things where my yellow is your green. The coordinate systems are objectively ill-chosen. But hey, what else is new in computing?

EDIT:

Not to mention, it makes Trig COMPLETELY UPSIDE DOWN and only helps to stifle the learning around here, trust me.
Title: Re: Intersect of 2 lines carried a step further
Post by: STxAxTIC on March 23, 2020, 06:26:28 am
Alrighty, here's about 90% of what you asked for. The intersection calculation sub takes endpoints as its inputs, but outputs nothing right now. I figure if you want it to return specific stuff, the road should be easy, very easy, to travel from here.

The Segments() array is still there, basically for show. The LineSegment UDT is crucial though. This code already became a mess doing what you asked - I wouldn't imagine doing this without vector notation.

Anyway, here's the compromise:

(Control it with the mouse)

Code: QB64: [Select]
  1.  
  2. TYPE Vector
  3.     x AS DOUBLE
  4.     y AS DOUBLE
  5.  
  6. TYPE LineSegment
  7.     '                  Endpoint definition:
  8.     p1 AS Vector '     Endpoint 1
  9.     p2 AS Vector '     Endpoint 2
  10.     '                  Parameterized definition:
  11.     b AS Vector '      Origin vector
  12.     alpha1 AS DOUBLE ' End-parameter 1
  13.     alpha2 AS DOUBLE ' End-parameter 2
  14.     ang AS DOUBLE '    Orientation angle
  15.     t AS Vector '      Tangent (unit) vector
  16.  
  17. DIM SHARED Segments(100) AS LineSegment
  18. DIM SHARED NumSegments AS INTEGER
  19. NumSegments = 0
  20.  
  21. '' Example: Define a line using parameters (calculates endpoints anyway):
  22. 'NumSegments = NumSegments + 1
  23. 'Segments(NumSegments).b.x = 0
  24. 'Segments(NumSegments).b.y = 0
  25. 'Segments(NumSegments).alpha1 = 0
  26. 'Segments(NumSegments).alpha2 = 100
  27. 'Segments(NumSegments).ang = ATN(0)
  28. 'Segments(NumSegments).t.x = COS(Segments(NumSegments).ang)
  29. 'Segments(NumSegments).t.y = SIN(Segments(NumSegments).ang)
  30. 'CALL CalcEndpoints(NumSegments)
  31.  
  32. '' Example: Define a line using endpoints (calculates parameters anyway):
  33. 'NumSegments = NumSegments + 1
  34. 'Segments(NumSegments).p1.x = 0
  35. 'Segments(NumSegments).p1.y = 0
  36. 'Segments(NumSegments).p2.x = 100
  37. 'Segments(NumSegments).p2.y = 0
  38.  
  39. ' Main lines and shapes
  40.  
  41. NumSegments = NumSegments + 1
  42. Segments(NumSegments).p1.x = -100
  43. Segments(NumSegments).p1.y = -100
  44. Segments(NumSegments).p2.x = 100
  45. Segments(NumSegments).p2.y = -100
  46.  
  47. NumSegments = NumSegments + 1
  48. Segments(NumSegments).p1.x = -200
  49. Segments(NumSegments).p1.y = -100
  50. Segments(NumSegments).p2.x = 200
  51. Segments(NumSegments).p2.y = -100
  52.  
  53. NumSegments = NumSegments + 1
  54. Segments(NumSegments).p1.x = 200
  55. Segments(NumSegments).p1.y = -100
  56. Segments(NumSegments).p2.x = 0
  57. Segments(NumSegments).p2.y = 200
  58.  
  59. NumSegments = NumSegments + 1
  60. Segments(NumSegments).p1.x = 0
  61. Segments(NumSegments).p1.y = 200
  62. Segments(NumSegments).p2.x = -200
  63. Segments(NumSegments).p2.y = -100
  64.  
  65. NumSegments = NumSegments + 1
  66. Segments(NumSegments).p1.x = -200
  67. Segments(NumSegments).p1.y = -200
  68. Segments(NumSegments).p2.x = 200
  69. Segments(NumSegments).p2.y = 200
  70.  
  71. NumSegments = NumSegments + 1
  72. Segments(NumSegments).p1.x = 200
  73. Segments(NumSegments).p1.y = -200
  74. Segments(NumSegments).p2.x = -200
  75. Segments(NumSegments).p2.y = 200
  76.  
  77. ' Main loop
  78.  
  79.     ' User input
  80.         x = _MOUSEX
  81.         y = _MOUSEY
  82.         IF ((x > 0) AND (x < _WIDTH) AND (y > 0) AND (y < _HEIGHT)) THEN
  83.             IF (_MOUSEBUTTON(1)) THEN
  84.                 CALL CalcParameters(1)
  85.                 x = _MOUSEX
  86.                 y = _MOUSEY
  87.                 Segments(1).b.x = INT((x - _WIDTH / 2))
  88.                 Segments(1).b.y = INT((-y + _HEIGHT / 2))
  89.                 CALL CalcEndpoints(1)
  90.             END IF
  91.             IF (_MOUSEWHEEL > 0) THEN
  92.                 CALL CalcParameters(1)
  93.                 Segments(1).ang = Segments(1).ang + ATN(1) / 10
  94.                 Segments(1).t.x = COS(Segments(1).ang)
  95.                 Segments(1).t.y = SIN(Segments(1).ang)
  96.                 CALL CalcEndpoints(1)
  97.             END IF
  98.             IF (_MOUSEWHEEL < 0) THEN
  99.                 CALL CalcParameters(1)
  100.                 Segments(1).ang = Segments(1).ang - ATN(1) / 10
  101.                 Segments(1).t.x = COS(Segments(1).ang)
  102.                 Segments(1).t.y = SIN(Segments(1).ang)
  103.                 CALL CalcEndpoints(1)
  104.             END IF
  105.         END IF
  106.     LOOP
  107.  
  108.     ' Graphics
  109.     CLS
  110.     FOR k = 1 TO NumSegments
  111.         CALL cline(Segments(k).p1.x, Segments(k).p1.y, Segments(k).p2.x, Segments(k).p2.y, 15)
  112.     NEXT
  113.  
  114.     ' Intersections loop
  115.     FOR k = 1 TO NumSegments
  116.         FOR j = k + 1 TO NumSegments
  117.             a1x = Segments(k).p1.x
  118.             a1y = Segments(k).p1.y
  119.             a2x = Segments(k).p2.x
  120.             a2y = Segments(k).p2.y
  121.             b1x = Segments(j).p1.x
  122.             b1y = Segments(j).p1.y
  123.             b2x = Segments(j).p2.x
  124.             b2y = Segments(j).p2.y
  125.             CALL CalcIntersections(a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y)
  126.         NEXT
  127.     NEXT
  128.  
  129.     _DISPLAY
  130.     _LIMIT 60
  131.  
  132.  
  133. SUB CalcIntersections (a1x, a1y, a2x, a2y, b1x, b1y, b2x, b2y)
  134.     ' Requires UDT LineSegment
  135.     ' Requires FUNCTION DotProduct
  136.  
  137.     DIM s1 AS LineSegment
  138.     DIM s2 AS LineSegment
  139.  
  140.     s1.p1.x = a1x
  141.     s1.p1.y = a1y
  142.     s1.p2.x = a2x
  143.     s1.p2.y = a2y
  144.     s1.ang = ATN((s1.p2.y - s1.p1.y) / (s1.p2.x - s1.p1.x))
  145.     s1.b.x = .5 * (s1.p1.x + s1.p2.x)
  146.     s1.b.y = .5 * (s1.p1.y + s1.p2.y)
  147.     s1.alpha1 = -.5 * _HYPOT(s1.p2.x - s1.p1.x, s1.p2.y - s1.p1.y)
  148.     s1.alpha2 = .5 * _HYPOT(s1.p2.x - s1.p1.x, s1.p2.y - s1.p1.y)
  149.     s1.t.x = COS(s1.ang)
  150.     s1.t.y = SIN(s1.ang)
  151.  
  152.     s2.p1.x = b1x
  153.     s2.p1.y = b1y
  154.     s2.p2.x = b2x
  155.     s2.p2.y = b2y
  156.     s2.ang = ATN((s2.p2.y - s2.p1.y) / (s2.p2.x - s2.p1.x))
  157.     s2.b.x = .5 * (s2.p1.x + s2.p2.x)
  158.     s2.b.y = .5 * (s2.p1.y + s2.p2.y)
  159.     s2.alpha1 = -.5 * _HYPOT(s2.p2.x - s2.p1.x, s2.p2.y - s2.p1.y)
  160.     s2.alpha2 = .5 * _HYPOT(s2.p2.x - s2.p1.x, s2.p2.y - s2.p1.y)
  161.     s2.t.x = COS(s2.ang)
  162.     s2.t.y = SIN(s2.ang)
  163.  
  164.     DIM db AS Vector
  165.     db.x = s2.b.x - s1.b.x
  166.     db.y = s2.b.y - s1.b.y
  167.     qj = DotProduct(db, s1.t)
  168.     ql = DotProduct(db, s2.t)
  169.     p = DotProduct(s1.t, s2.t)
  170.     pp = p * p
  171.     IF (pp < 1) THEN ' Non-parallel case
  172.         alphaj = (qj - p * ql) / (1 - pp)
  173.         alphal = (p * qj - ql) / (1 - pp)
  174.         IF ((alphaj > s1.alpha1) AND (alphaj < s1.alpha2)) THEN
  175.             IF ((alphal > s2.alpha1) AND (alphal < s2.alpha2)) THEN
  176.                 CALL ccircle(s1.b.x + alphaj * s1.t.x, s1.b.y + alphaj * s1.t.y, 3, 13)
  177.                 CALL ccircle(s2.b.x + alphal * s2.t.x, s2.b.y + alphal * s2.t.y, 5, 15)
  178.             END IF
  179.         END IF
  180.     ELSE ' Parallel case
  181.         LOCATE 5, 5: PRINT pp
  182.         DIM dbhat AS Vector
  183.         dbmag = SQR(db.x * db.x + db.y * db.y)
  184.         IF (dbmag <> 0) THEN
  185.             dbhat.x = db.x / dbmag
  186.             dbhat.y = db.y / dbmag
  187.             thresh = DotProduct(dbhat, s1.t)
  188.         END IF
  189.         IF ((1 - thresh * thresh < 0.001) OR (dbmag = 0)) THEN ' Overlap detection
  190.             t1t2 = DotProduct(s1.t, s2.t)
  191.             alphaj1 = s2.alpha1 * t1t2 + DotProduct(s1.t, db)
  192.             alphaj2 = s2.alpha2 * t1t2 + DotProduct(s1.t, db)
  193.             x1 = 0
  194.             y1 = 0
  195.             x2 = 0
  196.             y2 = 0
  197.             IF ((alphaj1 >= s1.alpha1) AND (alphaj1 <= s1.alpha2)) THEN
  198.                 xx = s1.b.x + alphaj1 * s1.t.x
  199.                 yy = s1.b.y + alphaj1 * s1.t.y
  200.                 IF (x1 = 0) THEN x1 = xx ELSE x2 = xx
  201.                 IF (y1 = 0) THEN y1 = yy ELSE y2 = yy
  202.                 CALL ccircle(xx, yy, 3, 13)
  203.                 'CALL ccircle(s2.b.x + s2.alpha1 * s2.t.x, s2.b.y + s2.alpha1 * s2.t.y, 4, 14)
  204.             END IF
  205.             IF ((alphaj2 >= s1.alpha1) AND (alphaj2 <= s1.alpha2)) THEN
  206.                 xx = s1.b.x + alphaj2 * s1.t.x
  207.                 yy = s1.b.y + alphaj2 * s1.t.y
  208.                 IF (x1 = 0) THEN x1 = xx ELSE x2 = xx
  209.                 IF (y1 = 0) THEN y1 = yy ELSE y2 = yy
  210.                 CALL ccircle(xx, yy, 3, 13)
  211.                 'CALL ccircle(s2.b.x + s2.alpha2 * s2.t.x, s2.b.y + s2.alpha2 * s2.t.y, 4, 14)
  212.             END IF
  213.             alphal1 = s1.alpha1 * t1t2 - DotProduct(s2.t, db)
  214.             alphal2 = s1.alpha2 * t1t2 - DotProduct(s2.t, db)
  215.             IF ((alphal1 >= s2.alpha1) AND (alphal1 <= s2.alpha2)) THEN
  216.                 xx = s2.b.x + alphal1 * s2.t.x
  217.                 yy = s2.b.y + alphal1 * s2.t.y
  218.                 IF (x1 = 0) THEN x1 = xx ELSE x2 = xx
  219.                 IF (y1 = 0) THEN y1 = yy ELSE y2 = yy
  220.                 CALL ccircle(xx, yy, 3, 15)
  221.                 'CALL ccircle(s1.b.x + s1.alpha1 * s1.t.x, s1.b.y + s1.alpha1 * s1.t.y, 5, 15)
  222.             END IF
  223.             IF ((alphal2 >= s2.alpha1) AND (alphal2 <= s2.alpha2)) THEN
  224.                 xx = s2.b.x + alphal2 * s2.t.x
  225.                 yy = s2.b.y + alphal2 * s2.t.y
  226.                 IF (x1 = 0) THEN x1 = xx ELSE x2 = xx
  227.                 IF (y1 = 0) THEN y1 = yy ELSE y2 = yy
  228.                 CALL ccircle(xx, yy, 3, 15)
  229.                 'CALL ccircle(s1.b.x + s1.alpha2 * s1.t.x, s1.b.y + s1.alpha2 * s1.t.y, 5, 15)
  230.             END IF
  231.             IF (x1 OR x2 OR y1 OR y2) THEN ' Overlap occurred
  232.                 CALL cline(x1, y1, x2, y2, 13)
  233.             END IF
  234.         END IF
  235.     END IF
  236.  
  237.  
  238. SUB CalcEndpoints (i AS INTEGER)
  239.     Segments(i).p1.x = Segments(i).b.x + Segments(i).alpha1 * Segments(i).t.x
  240.     Segments(i).p1.y = Segments(i).b.y + Segments(i).alpha1 * Segments(i).t.y
  241.     Segments(i).p2.x = Segments(i).b.x + Segments(i).alpha2 * Segments(i).t.x
  242.     Segments(i).p2.y = Segments(i).b.y + Segments(i).alpha2 * Segments(i).t.y
  243.  
  244. SUB CalcParameters (i AS INTEGER)
  245.     Segments(i).ang = ATN((Segments(i).p2.y - Segments(i).p1.y) / (Segments(i).p2.x - Segments(i).p1.x))
  246.     Segments(i).b.x = .5 * (Segments(i).p1.x + Segments(i).p2.x)
  247.     Segments(i).b.y = .5 * (Segments(i).p1.y + Segments(i).p2.y)
  248.     Segments(i).alpha1 = -.5 * _HYPOT(Segments(i).p2.x - Segments(i).p1.x, Segments(i).p2.y - Segments(i).p1.y)
  249.     Segments(i).alpha2 = .5 * _HYPOT(Segments(i).p2.x - Segments(i).p1.x, Segments(i).p2.y - Segments(i).p1.y)
  250.     Segments(i).t.x = COS(Segments(i).ang)
  251.     Segments(i).t.y = SIN(Segments(i).ang)
  252.  
  253. FUNCTION DotProduct (a AS Vector, b AS Vector)
  254.     DotProduct = a.x * b.x + a.y * b.y
  255.  
  256. SUB cline (x1 AS DOUBLE, y1 AS DOUBLE, x2 AS DOUBLE, y2 AS DOUBLE, col AS _UNSIGNED LONG)
  257.     LINE (_WIDTH / 2 + x1, -y1 + _HEIGHT / 2)-(_WIDTH / 2 + x2, -y2 + _HEIGHT / 2), col
  258.  
  259. SUB ccircle (x1 AS DOUBLE, y1 AS DOUBLE, rad AS DOUBLE, col AS _UNSIGNED LONG)
  260.     CIRCLE (_WIDTH / 2 + x1, -y1 + _HEIGHT / 2), rad, col
  261.  
  262. SUB cpset (x1 AS DOUBLE, y1 AS DOUBLE, col AS _UNSIGNED LONG)
  263.     PSET (_WIDTH / 2 + x1, -y1 + _HEIGHT / 2), col
  264.  
  265. SUB cpaint (x1 AS DOUBLE, y1 AS DOUBLE, col1 AS _UNSIGNED LONG, col2 AS _UNSIGNED LONG)
  266.     PAINT (_WIDTH / 2 + x1, -y1 + _HEIGHT / 2), col1, col2
  267.  
  268. SUB cprintstring (y AS DOUBLE, a AS STRING)
  269.     _PRINTSTRING (_WIDTH / 2 - (LEN(a) * 8) / 2, -y + _HEIGHT / 2), a
  270.  
Title: Re: Intersect of 2 lines carried a step further
Post by: bplus on March 23, 2020, 01:41:33 pm
Quote
Not to mention, it makes Trig COMPLETELY UPSIDE DOWN and only helps to stifle the learning around here, trust me.

Sorry man, didn't think this would turn into such a chore. Can't get there from here, not without going around the whole world first, yikes I think you are way past 67 LOC (245 - 141 + Dot Product = 100+ LOC) and still no FUNCTION in sight.

The trig is right on for an "upside down" 1st quadrant, angles increase as you go clockwise just as a "right side up" math quadrant goes counter clockwise with increasing angle. What is NOT consistent is the CIRCLE SUB built into QB64, those start and end angles for arcs are wrong for an "upside down" first quadrant.

A proper WINDOW command let's you "right" the coordinates and put the origin wherever your heart desires but CIRCLE will still be inconsistent.

One WINDOW command and a CIRCLE SUB of your own will save you all those supplemental procedures you keep adding to "fix" the coordinate system.

... but it's 6 of 1 half dozen of another, use WINDOW and you have PSET and LINE but not MOUSE but there is a command to fix that (see wiki WINDOW) but not sure how _PRINTSTRING and such will do.
Title: Re: Intersect of 2 lines carried a step further
Post by: bplus on March 24, 2020, 10:10:40 pm
Oh yeah! From 56 lines of code down to 32 and the 2 supplemental subs are useful too without line segments intersect.

Here is what I've whittle it down to, to get the intersect point of two line segments:
Code: QB64: [Select]
  1. ' For segments intersect first we need to know if lines do and for that we need to knoww stuff
  2. ' about the line from the segment given.
  3.  
  4. '  Return 0 if x = x2 and line is perpendicular otherwise return -1, slope = M and yIntersect = Y0
  5. FUNCTION slopeY0% (X, Y, X2, Y2, M, Y0)
  6.     IF X = X2 THEN EXIT FUNCTION ELSE slopeY0% = -1: M = (Y2 - Y) / (X2 - X): Y0 = -X * M + Y
  7.  
  8. ' Return 1, ix, iy if lines intersect, Return -1 if they overlap, return 0 if neither.
  9. ' This function needs:
  10. '  Return 0 if x = x2 and line is perpendicular otherwise return -1, slope = M and yIntersect = Y0
  11. ' FUNCTION slopeY0% (X, Y, X2, Y2, M, Y0)
  12. FUNCTION lineIntersectLine% (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  13.     DIM ai, bi, aM, bM, aY0, bY0, d
  14.     ai = slopeY0%(ax1, ay1, ax2, ay2, aM, aY0) '                        here's the scoop on line a
  15.     bi = slopeY0%(bx1, by1, bx2, by2, bM, bY0) '                         here's the dope on line b
  16.     IF ai = 0 AND bi = 0 THEN '                              both are perpendicular how bout that!
  17.         IF ax1 = bx1 THEN lineIntersectLine% = -1 '             whole line overlaps more amazing!!
  18.     ELSEIF ai = 0 AND bi THEN '                         a is perpendicular and b is not so ix = ax
  19.         ix = ax1: iy = bM * ix + bY0: lineIntersectLine% = 1 '            signal a point was found
  20.     ELSEIF ai AND bi = 0 THEN '                         b is perpendicular and a is not so ix = bx
  21.         ix = bx1: iy = aM * ix + aY0: lineIntersectLine% = 1 '            signal a point was found
  22.     ELSE
  23.         d = -aM + bM '                       if = 0 then parallel or equal because slopes are same
  24.         IF d = 0 THEN '                                                 lines a and b are parallel
  25.             IF aY0 = bY0 THEN lineIntersectLine% = -1 ' the same Y0 means signal overlapping lines
  26.         ELSE '                           get values of ix, iy intersect point and signal intersect
  27.             ix = (aY0 - bY0) / d: iy = (-aM * bY0 + bM * aY0) / d: lineIntersectLine% = 1
  28.         END IF
  29.     END IF
  30.  
  31. ' Return 1, ix, iy if line segments intersect, Return 0 if they don't
  32. ' This function needs:
  33. '  Return 0 if x = x2 and line is perpendicular otherwise return -1, slope = M and yIntersect = Y0
  34. '  FUNCTION slopeY0% (X, Y, X2, Y2, M, Y0)
  35. '  Return 1, ix, iy if lines intersect, Return -1 if they overlap, return 0 if neither.
  36. '  FUNCTION lineIntersectLine% (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  37. FUNCTION twoSegmentsIntersect% (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  38.     DIM intersect AS INTEGER, a1, a2, near0 '                                       default SINGLE
  39.     intersect = lineIntersectLine%(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  40.     near0 = _PI(2 / 360)
  41.     IF intersect = 1 THEN
  42.         a1 = _ATAN2(ay1 - iy, ax1 - ix): a2 = _ATAN2(ay2 - iy, ax2 - ix)
  43.         IF ABS(a1 - a2) < near0 THEN EXIT SUB
  44.         a1 = _ATAN2(by1 - iy, bx1 - ix): a2 = _ATAN2(by2 - iy, bx2 - ix)
  45.         IF ABS(a1 - a2) < near0 THEN EXIT SUB
  46.         twoSegmentsIntersect% = 1
  47.     END IF
  48.  

Here is the overlap of two triangles again with the procedures plugged into this test application:
Code: QB64: [Select]
  1. _TITLE "Two Triangles Overlap v2 2020-03-24" 'b+ 2020-03-24
  2. ' Just worked Rosetta Code for Line Intersect Line
  3. ' but what if we want to know if two line segments intersect?
  4. '2020-03-14 "Two Line Segments Intersect" 'b+ 2020-03-14  start
  5. '2020-03-15 rework this code so we identify points all on same line and
  6. ' if there is overlap of line segments say the two x endpoints of the segments
  7. ' otherwise, if there is an intersect of 2 line segments say the point x, y.
  8. ' Return 0 no intersect or overlap
  9. ' Return 1 if intersect and ix, iy point of intersect
  10. ' Return -1 if segments are on same and there is overlap: ix = overlap start x, iy overlap end x
  11.  
  12. '2020-03-16 "Segments Intersect mod tester"  >>> just post testing code
  13. 'mod tester for 2 segments of vertical line and found I need to add more parameters to
  14. ' FUNCTION twoLineSegmentsIntersect%  (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  15. ' mod that name and parameters to:
  16. ' FUNCTION twoSegmentsIntersect%  (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix1, iy1, ix2, iy2)
  17.  
  18. '2020-03-16 Segments Intersect revised 2020-03-16
  19. ' OK now get the new FUNCTION working
  20. ' ah! I had to tighten down D from >.2 to >.05 but loosen y-axis intersect
  21.  
  22. '2020-03-18 apply routines to two triangles
  23. ' modified FUNCTION twoSegmentsIntersect% (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix1, iy1)
  24. ' to do only intersect. This code proved, Segments Intersect revised 2020-03-16, was faulty.
  25.  
  26. '2020-03-18 a more exactling test of triangle overlaps with line segments over lapping
  27. ' purposely to the random triangles already tested and working well.
  28.  
  29. ' 2020-03-24     Two Triangles Overlap v2 2020-03-24
  30. ' Can I tighten up the code for getting the Intersect of 2 Line Segments?
  31. ' beat 3 + 26 + 27 = 56 lines of code in 3 procedures?
  32. ' Oh yes!!! now have 3 + 18 + 11 = 32 lines of code
  33. ' lineIntersectLine% cut 8 lines of code :)
  34. ' twoSegmentsIntersect cut 16 lines of cutting from 27 lines to 11!
  35.  
  36. CONST xmax = 800, ymax = 600
  37. SCREEN _NEWIMAGE(xmax, ymax, 32)
  38. _DELAY .25
  39. DIM ax1 AS INTEGER, ax2 AS INTEGER, ay1 AS INTEGER, ay2 AS INTEGER
  40. DIM ax3 AS INTEGER, ay3 AS INTEGER, bx1 AS INTEGER, bx2 AS INTEGER
  41. DIM by1 AS INTEGER, by2 AS INTEGER, bx3 AS INTEGER, by3 AS INTEGER
  42. DIM lCnt, dista2a3, adx, ady, ix1, i, x1, y1, sect, iy1, dista1a3
  43. DIM dista1a2, distb2b3, bdx, bdy, distb1b3, distb1b2, again$
  44.  
  45. DO 'main testing loop sets up two triangles to test overlap area
  46.     lCnt = lCnt + 1 'loop counter to control some purposeful test triangles
  47.     IF lCnt MOD 4 = 0 THEN 'purpose overlap vertical lines
  48.         cText 400, 580, 32, &HFF0088FF, "Two Triangles with Common Vertical Segment"
  49.         ax1 = 400: ay1 = 20
  50.         ax2 = 400: ay2 = 570
  51.         ax3 = (xmax - 20) * RND + 10: ay3 = (ymax - 20) * RND + 10
  52.         bx1 = 400: by1 = 200
  53.         bx2 = 400: by2 = 450
  54.         bx3 = (xmax - 20) * RND + 10: by3 = (ymax - 20) * RND + 10
  55.  
  56.     ELSEIF lCnt MOD 4 = 1 THEN 'purpose overlap horizontal line
  57.         cText 400, 580, 32, &HFF008800, "Two Triangles with Common Horizontal Segment"
  58.         ax1 = 10: ay1 = 300
  59.         ax2 = 400: ay2 = 300
  60.         ax3 = (xmax - 20) * RND + 10: ay3 = (ymax - 20) * RND + 10
  61.         bx1 = 125: by1 = 300
  62.         bx2 = 700: by2 = 300
  63.         bx3 = (xmax - 20) * RND + 10: by3 = by3 = (ymax - 20) * RND + 10
  64.  
  65.     ELSEIF lCnt MOD 4 = 2 THEN 'purpose overlap 1/5 triangle
  66.         cText 400, 580, 32, &HFFFF8800, "Two Triangles with Common 45 Degree Segment"
  67.         ax1 = 100: ay1 = 100
  68.         ax2 = 400: ay2 = 400
  69.         ax3 = (xmax - 20) * RND + 10: ay3 = (ymax - 20) * RND + 10
  70.         bx1 = 50: by1 = 50
  71.         bx2 = 500: by2 = 500
  72.         bx3 = (xmax - 20) * RND + 10: by3 = (ymax - 20) * RND + 10
  73.  
  74.     ELSEIF lCnt MOD 4 = 3 THEN ' completely random triangles
  75.         cText 400, 580, 32, &HFF0000FF, "Two Completely Random Triangles"
  76.         ax1 = (xmax - 20) * RND + 10: ay1 = (ymax - 20) * RND + 10
  77.         ax2 = (xmax - 20) * RND + 10: ay2 = (ymax - 20) * RND + 10
  78.         ax3 = (xmax - 20) * RND + 10: ay3 = (ymax - 20) * RND + 10
  79.         bx1 = (xmax - 20) * RND + 10: by1 = (ymax - 20) * RND + 10
  80.         bx2 = (xmax - 20) * RND + 10: by2 = (ymax - 20) * RND + 10
  81.         bx3 = (xmax - 20) * RND + 10: by3 = (ymax - 20) * RND + 10
  82.     END IF
  83.     'tri a
  84.     LINE (ax1, ay1)-(ax2, ay2), &HFFFF0000
  85.     LINE (ax2, ay2)-(ax3, ay3), &HFFFF0000
  86.     LINE (ax3, ay3)-(ax1, ay1), &HFFFF0000
  87.     'tri b
  88.     LINE (bx1, by1)-(bx2, by2), &HFF0000FF
  89.     LINE (bx2, by2)-(bx3, by3), &HFF0000FF
  90.     LINE (bx3, by3)-(bx1, by1), &HFF0000FF
  91.  
  92.     dista2a3 = _HYPOT(ax2 - ax3, ay2 - ay3)
  93.     adx = (ax3 - ax2) / dista2a3: ady = (ay3 - ay2) / dista2a3
  94.     FOR i = 0 TO dista2a3
  95.         x1 = ax2 + adx * i: y1 = ay2 + ady * i
  96.         sect = twoSegmentsIntersect%(ax1, ay1, x1, y1, bx1, by1, bx2, by2, ix1, iy1)
  97.         IF sect THEN PSET (ix1, iy1)
  98.         sect = twoSegmentsIntersect%(ax1, ay1, x1, y1, bx3, by3, bx2, by2, ix1, iy1)
  99.         IF sect THEN PSET (ix1, iy1)
  100.         sect = twoSegmentsIntersect%(ax1, ay1, x1, y1, bx1, by1, bx3, by3, ix1, iy1)
  101.         IF sect = 1 THEN PSET (ix1, iy1)
  102.     NEXT
  103.  
  104.     dista1a3 = _HYPOT(ax1 - ax3, ay1 - ay3)
  105.     adx = (ax3 - ax1) / dista1a3: ady = (ay3 - ay1) / dista1a3
  106.     FOR i = 0 TO dista1a3
  107.         x1 = ax1 + adx * i: y1 = ay1 + ady * i
  108.         sect = twoSegmentsIntersect%(ax2, ay2, x1, y1, bx1, by1, bx2, by2, ix1, iy1)
  109.         IF sect THEN PSET (ix1, iy1)
  110.         sect = twoSegmentsIntersect%(ax2, ay2, x1, y1, bx3, by3, bx2, by2, ix1, iy1)
  111.         IF sect THEN PSET (ix1, iy1)
  112.         sect = twoSegmentsIntersect%(ax2, ay2, x1, y1, bx1, by1, bx3, by3, ix1, iy1)
  113.         IF sect = 1 THEN PSET (ix1, iy1)
  114.     NEXT
  115.  
  116.     dista1a2 = _HYPOT(ax1 - ax2, ay1 - ay2)
  117.     adx = (ax2 - ax1) / dista1a2: ady = (ay2 - ay1) / dista1a2
  118.     FOR i = 0 TO dista1a2
  119.         x1 = ax1 + adx * i: y1 = ay1 + ady * i
  120.         sect = twoSegmentsIntersect%(ax3, ay3, x1, y1, bx1, by1, bx2, by2, ix1, iy1)
  121.         IF sect THEN PSET (ix1, iy1)
  122.         sect = twoSegmentsIntersect%(ax3, ay3, x1, y1, bx3, by3, bx2, by2, ix1, iy1)
  123.         IF sect THEN PSET (ix1, iy1)
  124.         sect = twoSegmentsIntersect%(ax3, ay3, x1, y1, bx1, by1, bx3, by3, ix1, iy1)
  125.         IF sect = 1 THEN PSET (ix1, iy1)
  126.     NEXT
  127.  
  128.     distb2b3 = _HYPOT(bx2 - bx3, by2 - by3)
  129.     bdx = (bx3 - bx2) / distb2b3: bdy = (by3 - by2) / distb2b3
  130.     FOR i = 0 TO distb2b3
  131.         x1 = bx2 + bdx * i: y1 = by2 + bdy * i
  132.         sect = twoSegmentsIntersect%(bx1, by1, x1, y1, ax1, ay1, ax2, ay2, ix1, iy1)
  133.         IF sect = 1 THEN PSET (ix1, iy1)
  134.         sect = twoSegmentsIntersect%(bx1, by1, x1, y1, ax3, ay3, ax2, ay2, ix1, iy1)
  135.         IF sect THEN PSET (ix1, iy1)
  136.         sect = twoSegmentsIntersect%(bx1, by1, x1, y1, ax1, ay1, ax3, ay3, ix1, iy1)
  137.         IF sect = 1 THEN PSET (ix1, iy1)
  138.     NEXT
  139.  
  140.     distb1b3 = _HYPOT(bx1 - bx3, by1 - by3)
  141.     bdx = (bx3 - bx1) / distb1b3: bdy = (by3 - by1) / distb1b3
  142.     FOR i = 0 TO distb1b3
  143.         x1 = bx1 + bdx * i: y1 = by1 + bdy * i
  144.         sect = twoSegmentsIntersect%(bx2, by2, x1, y1, ax1, ay1, ax2, ay2, ix1, iy1)
  145.         IF sect THEN PSET (ix1, iy1)
  146.         sect = twoSegmentsIntersect%(bx2, by2, x1, y1, ax3, ay3, ax2, ay2, ix1, iy1)
  147.         IF sect THEN PSET (ix1, iy1)
  148.         sect = twoSegmentsIntersect%(bx2, by2, x1, y1, ax1, ay1, ax3, ay3, ix1, iy1)
  149.         IF sect = 1 THEN PSET (ix1, iy1)
  150.     NEXT
  151.  
  152.     distb1b2 = _HYPOT(bx1 - bx2, by1 - by2)
  153.     bdx = (bx2 - bx1) / distb1b2: bdy = (by2 - by1) / distb1b2
  154.     FOR i = 0 TO distb1b2
  155.         x1 = bx1 + bdx * i: y1 = by1 + bdy * i
  156.         sect = twoSegmentsIntersect%(bx3, by3, x1, y1, ax1, ay1, ax2, ay2, ix1, iy1)
  157.         IF sect = 1 THEN PSET (ix1, iy1)
  158.         sect = twoSegmentsIntersect%(bx3, by3, x1, y1, ax3, ay3, ax2, ay2, ix1, iy1)
  159.         IF sect = 1 THEN PSET (ix1, iy1)
  160.         sect = twoSegmentsIntersect%(bx3, by3, x1, y1, ax1, ay1, ax3, ay3, ix1, iy1)
  161.         IF sect = 1 THEN PSET (ix1, iy1)
  162.     NEXT
  163.  
  164.     INPUT "Press enter for another demo, any + enter to quit...", again$
  165.     CLS
  166. LOOP UNTIL LEN(again$)
  167.  
  168. 'center the text at x, y with given height and color
  169. SUB cText (x, y, textHeight, K AS _UNSIGNED LONG, txt$)
  170.     DIM fg AS _UNSIGNED LONG, cur&, I&, mult, xlen
  171.     fg = _DEFAULTCOLOR
  172.     'screen snapshot
  173.     cur& = _DEST
  174.     I& = _NEWIMAGE(8 * LEN(txt$), 16, 32)
  175.     _DEST I&
  176.     COLOR K, _RGBA32(0, 0, 0, 0)
  177.     _PRINTSTRING (0, 0), txt$
  178.     mult = textHeight / 16
  179.     xlen = LEN(txt$) * 8 * mult
  180.     _PUTIMAGE (x - .5 * xlen, y - .5 * textHeight)-STEP(xlen, textHeight), I&, cur&
  181.     COLOR fg
  182.     _FREEIMAGE I&
  183.  
  184. ' ======================================== end tester code functions ===========================98
  185.  
  186. ' For segments intersect first we need to know if lines do and for that we need to knoww stuff
  187. ' about the line from the segment given.
  188.  
  189. '  Return 0 if x = x2 and line is perpendicular otherwise return -1, slope = M and yIntersect = Y0
  190. FUNCTION slopeY0% (X, Y, X2, Y2, M, Y0)
  191.     IF X = X2 THEN EXIT FUNCTION ELSE slopeY0% = -1: M = (Y2 - Y) / (X2 - X): Y0 = -X * M + Y
  192.  
  193. ' Return 1, ix, iy if lines intersect, Return -1 if they overlap, return 0 if neither.
  194. ' This function needs:
  195. '  Return 0 if x = x2 and line is perpendicular otherwise return -1, slope = M and yIntersect = Y0
  196. ' FUNCTION slopeY0% (X, Y, X2, Y2, M, Y0)
  197. FUNCTION lineIntersectLine% (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  198.     DIM ai, bi, aM, bM, aY0, bY0, d
  199.     ai = slopeY0%(ax1, ay1, ax2, ay2, aM, aY0) '                        here's the scoop on line a
  200.     bi = slopeY0%(bx1, by1, bx2, by2, bM, bY0) '                         here's the dope on line b
  201.     IF ai = 0 AND bi = 0 THEN '                              both are perpendicular how bout that!
  202.         IF ax1 = bx1 THEN lineIntersectLine% = -1 '             whole line overlaps more amazing!!
  203.     ELSEIF ai = 0 AND bi THEN '                         a is perpendicular and b is not so ix = ax
  204.         ix = ax1: iy = bM * ix + bY0: lineIntersectLine% = 1 '            signal a point was found
  205.     ELSEIF ai AND bi = 0 THEN '                         b is perpendicular and a is not so ix = bx
  206.         ix = bx1: iy = aM * ix + aY0: lineIntersectLine% = 1 '            signal a point was found
  207.     ELSE
  208.         d = -aM + bM '                       if = 0 then parallel or equal because slopes are same
  209.         IF d = 0 THEN '                                                 lines a and b are parallel
  210.             IF aY0 = bY0 THEN lineIntersectLine% = -1 ' the same Y0 means signal overlapping lines
  211.         ELSE '                           get values of ix, iy intersect point and signal intersect
  212.             ix = (aY0 - bY0) / d: iy = (-aM * bY0 + bM * aY0) / d: lineIntersectLine% = 1
  213.         END IF
  214.     END IF
  215.  
  216. ' Return 1, ix, iy if line segments intersect, Return 0 if they don't
  217. ' This function needs:
  218. '  Return 0 if x = x2 and line is perpendicular otherwise return -1, slope = M and yIntersect = Y0
  219. '  FUNCTION slopeY0% (X, Y, X2, Y2, M, Y0)
  220. '  Return 1, ix, iy if lines intersect, Return -1 if they overlap, return 0 if neither.
  221. '  FUNCTION lineIntersectLine% (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  222. FUNCTION twoSegmentsIntersect% (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  223.     DIM intersect AS INTEGER, a1, a2, near0 '                                       default SINGLE
  224.     intersect = lineIntersectLine%(ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  225.     near0 = _PI(2 / 360)
  226.     IF intersect = 1 THEN
  227.         a1 = _ATAN2(ay1 - iy, ax1 - ix): a2 = _ATAN2(ay2 - iy, ax2 - ix)
  228.         IF ABS(a1 - a2) < near0 THEN EXIT SUB
  229.         a1 = _ATAN2(by1 - iy, bx1 - ix): a2 = _ATAN2(by2 - iy, bx2 - ix)
  230.         IF ABS(a1 - a2) < near0 THEN EXIT SUB
  231.         twoSegmentsIntersect% = 1
  232.     END IF
  233.  

The shortcut for line segments was made when I realized if a line does not cross the intersect point BOTH it's points will lie on the same side and have the same angle from the intersect point whereas if the segment crossed the intersect point there would be a 180 degree difference between the angles from the intersect point.
Title: Re: Intersect of 2 lines carried a step further
Post by: TempodiBasic on March 25, 2020, 06:31:22 am
Hi guys
I'm following fascinated your math graphic thread!
Starting from the search of a point of contact between two segments, you have arrived to show IF , WHERE and HOW two triangles ( so 2 plane objects) interacts between and what part of each them is  envolved in the contact.
Cool!
I think applications of this one into  Graphic function, Collision detection,  3D rendering and so go on ( for example, AI, MAP editing)!

Thanks to share!
Title: Re: Intersect of 2 lines carried a step further
Post by: bplus on March 25, 2020, 11:48:56 am
Thanks TempodiBasic, I think you've got the significance. :)

I don't know if this will be practical but we'll see.