Author Topic: Intersect of 2 lines carried a step further  (Read 15797 times)

0 Members and 1 Guest are viewing this topic.

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Intersect of 2 lines carried a step further
« Reply #30 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.
You're not done when it works, you're done when it's right.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Intersect of 2 lines carried a step further
« Reply #31 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... ;-))

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Intersect of 2 lines carried a step further
« Reply #32 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?
You're not done when it works, you're done when it's right.

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: Intersect of 2 lines carried a step further
« Reply #33 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://www.youtube.com/watch?v=xaXV-RVpXgo

Math & Logic can be useful
Programming isn't difficult, only it's  consuming time and coffee

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Intersect of 2 lines carried a step further
« Reply #34 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

« Last Edit: March 18, 2020, 05:16:59 pm by bplus »

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: Intersect of 2 lines carried a step further
« Reply #35 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
Programming isn't difficult, only it's  consuming time and coffee

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Intersect of 2 lines carried a step further
« Reply #36 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.  

 
Two Overlapping Triangles Common Vertical Segment.PNG


It's taking about 60+ lines of code to figure intersect point of two line segments.
« Last Edit: March 18, 2020, 05:20:34 pm by bplus »

Offline TempodiBasic

  • Forum Resident
  • Posts: 1792
    • View Profile
Re: Intersect of 2 lines carried a step further
« Reply #37 on: March 18, 2020, 08:52:05 pm »
Very Impressive Bplus
 
Intersecting triangles Bplus.jpg

Thanks to share the code

Programming isn't difficult, only it's  consuming time and coffee

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Intersect of 2 lines carried a step further
« Reply #38 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

ss1.png
* ss1.png (Filesize: 54.33 KB, Dimensions: 646x513, Views: 273)
ss2.png
* ss2.png (Filesize: 25.95 KB, Dimensions: 659x318, Views: 302)
« Last Edit: March 21, 2020, 05:56:57 pm by STxAxTIC »
You're not done when it works, you're done when it's right.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Intersect of 2 lines carried a step further
« Reply #39 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. :)

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Intersect of 2 lines carried a step further
« Reply #40 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.
You're not done when it works, you're done when it's right.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Intersect of 2 lines carried a step further
« Reply #41 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.
« Last Edit: March 21, 2020, 04:23:38 pm by bplus »

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Intersect of 2 lines carried a step further
« Reply #42 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.  
You're not done when it works, you're done when it's right.

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Intersect of 2 lines carried a step further
« Reply #43 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.  
ss.png
* ss.png (Filesize: 11.6 KB, Dimensions: 640x480, Views: 268)
You're not done when it works, you're done when it's right.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Intersect of 2 lines carried a step further
« Reply #44 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.
« Last Edit: March 22, 2020, 10:21:17 am by bplus »