Author Topic: Inversion Points, 2D Circle  (Read 4177 times)

0 Members and 1 Guest are viewing this topic.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Inversion Points, 2D Circle
« on: August 19, 2020, 01:09:30 pm »
What _vince is doing with Domain Coloring (Complex Number Plotting) reminds me of Inversion Points of Circle:
Code: QB64: [Select]
  1. _TITLE "Inversion point sub" 'b+ 202-04-14
  2. '2020-04-15 Oh man! there is a way way easier way to do this!!!   yep!
  3.  
  4. CONST xmax = 1200, ymax = 700
  5. SCREEN _NEWIMAGE(xmax, ymax, 32)
  6. _SCREENMOVE 100, 40
  7.  
  8.     CIRCLE (xmax / 2, ymax / 2), 200
  9.  
  10.     mx = _MOUSEX: my = _MOUSEY
  11.     CIRCLE (mx, my), 2, &HFFF0000FF
  12.     'test new sub
  13.     inversionPoint xmax / 2, ymax / 2, 200, mx, my, Rx, Ry
  14.     CIRCLE (Rx, Ry), 2, &HFFFFFF00 'yellow circle should be on line perprendicular to 3rd click point
  15.  
  16.     _DISPLAY
  17.  
  18.  
  19. SUB inversionPoint (CX, CY, CR, X, Y, IX, IY) 'update the easy way 2020-04-15
  20.     a = _HYPOT(CX - X, CY - Y)
  21.     IF a <> 0 THEN
  22.         aPrime = CR ^ 2 / a
  23.         ang = _ATAN2(Y - CY, X - CX)
  24.         IX = CX + aPrime * COS(ang)
  25.         IY = CY + aPrime * SIN(ang)
  26.     ELSE
  27.         IX = CX: IY = CY 'because a line across diamter is inverted to itself
  28.     END IF
  29.  
  30. SUB inversionPointOrig (CX, CY, CR, X, Y, IX, IY)
  31.     dist = _HYPOT(CX - X, CY - Y)
  32.  
  33.     IF dist = CR THEN
  34.         IX = X: IY = Y
  35.     ELSEIF dist > CR THEN 'find angle of tangent line from x, y to circle radius
  36.         a = _ASIN(CR / dist)
  37.         adj = dist * COS(a)
  38.         xDist = adj * COS(a)
  39.         a = _ATAN2(CY - Y, CX - X)
  40.         IX = X + xDist * COS(a)
  41.         IY = Y + xDist * SIN(a)
  42.     ELSE 'dist < r  x, y is inertenal and need to find external
  43.         a = _ATAN2(Y - CY, X - CX) - _PI / 2 'perpendicular to X, Y and CX, CY
  44.         'need another point on the line perpendicular  at x, y
  45.         x1 = X + 100 * COS(a): y1 = Y + 100 * SIN(a)
  46.         CIRCLE (x1, y1), 2, &HFF0000FF
  47.  
  48.  
  49.         ' two points make a line find where it intersects circle
  50.         nPts = lineIntersectCircle%(X, Y, x1, y1, CX, CY, CR, ix1, iy1, ix2, iy2)
  51.  
  52.  
  53.         IF nPts = 2 THEN 'now we need 2 points to line perp to radius at ix1, ix2
  54.             CIRCLE (ix1, iy1), 2, &HFF00AA00: CIRCLE (ix2, iy2), 2, &HFF00AA00 'green circle intersect  OK
  55.  
  56.  
  57.             a = _ATAN2(CY - iy1, CX - ix1) - _PI / 2 ' the angle of tangent point to center of circle
  58.             x2 = ix1 + 100 * COS(a): y2 = iy1 + 100 * SIN(a) ' extend tangent line in some direction
  59.  
  60.             'check work
  61.             LINE (x2, y2)-(ix1, iy1), &HFF0000FF
  62.             CIRCLE (ix1, iy1), 4, &HFF0000FF ' tangent point from x, y perpendicular
  63.  
  64.             ' intersect of 2 lines
  65.             nPoints = lineIntersectLine%(CX, CY, X, Y, ix1, iy1, x2, y2, IX, IY)
  66.             IF nPoints <> 1 THEN IX = 0: IY = 0: BEEP '???? no intersect
  67.         END IF
  68.     END IF
  69.  
  70. SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept) ' fix for when x1 = x2
  71.     IF X1 = X2 THEN
  72.         slope = X1
  73.         Yintercept = Y2
  74.     ELSE
  75.         slope = (Y2 - Y1) / (X2 - X1)
  76.         Yintercept = slope * (0 - X1) + Y1
  77.     END IF
  78.  
  79. SUB PointOnLinePerp2Point (Lx1, Ly1, Lx2, Ly2, Px, Py, Rx, Ry)
  80.     '
  81.     'this sub needs  SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept) ' fix for when x1 = x2
  82.     '
  83.     'Lx1, Ly1, Lx2, Ly2     the two points that make a line
  84.     'Px, Py is point off the line
  85.     'Rx, Ry Return Point is the Point on the line perpendicular to Px, Py
  86.     slopeYintersect Lx1, Ly1, Lx2, Ly2, m, Y0
  87.     A = m ^ 2 + 1
  88.     B = 2 * (m * Y0 - m * Py - Px)
  89.     Rx = -B / (2 * A)
  90.     Ry = m * Rx + Y0
  91.  
  92. FUNCTION lineIntersectLine% (ax1, ay1, ax2, ay2, bx1, by1, bx2, by2, ix, iy)
  93.     IF ax1 = ax2 THEN 'line a is vertical
  94.         IF bx1 = bx2 THEN ' b is vertical
  95.             IF ax1 = bx1 THEN lineIntersectLine% = -1 ' if x's are same it is same vertical line
  96.             EXIT FUNCTION '
  97.         ELSE
  98.             ix = ax1
  99.             slopeYintersect bx1, by1, bx2, by2, m2, y02
  100.             iy = m2 * ix + y02
  101.             lineIntersectLine% = 1 'signal a point was found
  102.             EXIT FUNCTION
  103.         END IF
  104.     ELSE
  105.         slopeYintersect ax1, ay1, ax2, ay2, m1, y01 ' -m = a, 1 = b, y0 = c  std form
  106.     END IF
  107.     IF bx1 = bx2 THEN 'b is vertical
  108.         ix = bx1: iy = m1 * ix + y01: lineIntersectLine% = 1 'signal a point was found
  109.         EXIT FUNCTION
  110.     ELSE
  111.         slopeYintersect bx1, by1, bx2, by2, m2, y02 ' -m = a, 1 = b, y0 = c  std form
  112.     END IF
  113.     d = -m1 - -m2 ' if = 0 then parallel or equal because slopes are same
  114.     IF ABS(d) > .2 THEN 'otherwise about 0
  115.         ix = (y01 - y02) / d: iy = (-m1 * y02 - -m2 * y01) / d
  116.         lineIntersectLine% = 1 'signal one intersect point was found
  117.     ELSE 'same line or parallel? if y0 are same they are the same
  118.         IF ABS(y01 - y02) < 5 THEN lineIntersectLine% = -1 'signal same line!
  119.     END IF
  120.  
  121. ' return 0 no Intersect, 1 = tangent 1 point touch, 2 = 2 point intersect
  122. FUNCTION lineIntersectCircle% (lx1, ly1, lx2, ly2, cx, cy, r, ix1, iy1, ix2, iy2)
  123.  
  124.     'needs    SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept)
  125.  
  126.     IF lx1 <> lx2 THEN
  127.         slopeYintersect lx1, ly1, lx2, ly2, m, Y0 ' Y0 otherwise know as y Intersect
  128.  
  129.         ' https://math.stackexchange.com/questions/228841/how-do-i-calculate-the-intersections-of-a-straight-line-and-a-circle
  130.         A = m ^ 2 + 1
  131.         B = 2 * (m * Y0 - m * cy - cx)
  132.         C = cy ^ 2 - r ^ 2 + cx ^ 2 - 2 * Y0 * cy + Y0 ^ 2
  133.         D = B ^ 2 - 4 * A * C 'telling part of Quadratic formula = 0 then circle is tangent  or > 0 then 2 intersect points
  134.         IF D < 0 THEN ' no intersection
  135.             ix1 = -999: iy1 = -999: ix2 = -999: iy2 = -999: lineIntersectCircle% = 0
  136.         ELSEIF D = 0 THEN ' one point tangent
  137.             x1 = (-B + SQR(D)) / (2 * A)
  138.             y1 = m * x1 + Y0
  139.             ix1 = x1: iy1 = y1: ix2 = -999: iy2 = -999: lineIntersectCircle% = 1
  140.         ELSE '2 points
  141.             x1 = (-B + SQR(D)) / (2 * A): y1 = m * x1 + Y0
  142.             x2 = (-B - SQR(D)) / (2 * A): y2 = m * x2 + Y0
  143.             ix1 = x1: iy1 = y1: ix2 = x2: iy2 = y2: lineIntersectCircle% = 2
  144.         END IF
  145.     ELSE 'vertical line
  146.         IF r = ABS(lx1 - cx) THEN ' tangent
  147.             ix1 = lx1: iy1 = cy: ix2 = -999: iy2 = -999: lineIntersectCircle% = 1
  148.         ELSEIF r < ABS(lx1 - cx) THEN 'no intersect
  149.             ix1 = -999: iy1 = -999: ix2 = -999: iy2 = -999: lineIntersectCircle% = 0
  150.         ELSE '2 point intersect
  151.             ydist = SQR(r ^ 2 - (lx1 - cx) ^ 2)
  152.             ix1 = lx1: iy1 = cy + ydist: ix2 = lx1: iy2 = cy - ydist: lineIntersectCircle% = 2
  153.         END IF
  154.     END IF
  155.  
  156.  

This calls for an experiment in grapphing. :)
« Last Edit: August 19, 2020, 01:17:49 pm by bplus »

Offline _vince

  • Seasoned Forum Regular
  • Posts: 422
    • View Profile
Re: Inversion Points, 2D Circle
« Reply #1 on: August 19, 2020, 02:08:03 pm »
Any idea why I can't run this?  Using QB64 version 1.4 on windows

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Inversion Points, 2D Circle
« Reply #2 on: August 19, 2020, 02:45:44 pm »
Any idea why I can't run this?  Using QB64 version 1.4 on windows

Have no idea, copy paste from forum code works fine for me, but here is much briefer code with correct date and other tiny change(s). This is developed and tested in QB64 1.4 stable version in Windows 10 - 64 bit.
Code: QB64: [Select]
  1. _TITLE "Inversion point sub" 'b+ 2020-04-14
  2. '2020-04-15 Oh man! there is a way way easier way to do this!!!   yep!
  3. '2020-08-19 remove original Inversion Point code and other tiny changes
  4.  
  5. CONST xmax = 1200, ymax = 700
  6. SCREEN _NEWIMAGE(xmax, ymax, 32)
  7. _DELAY .25
  8.  
  9.     CIRCLE (xmax / 2, ymax / 2), 200
  10.     mx = _MOUSEX: my = _MOUSEY
  11.     CIRCLE (mx, my), 2, &HFFF0000FF
  12.     'test new sub
  13.     inversionPoint xmax / 2, ymax / 2, 200, mx, my, Rx, Ry
  14.     CIRCLE (Rx, Ry), 2, &HFFFFFF00 'yellow circle should be on line perprendicular to 3rd click point
  15.     _DISPLAY
  16.     _LIMIT 200
  17.  
  18. SUB inversionPoint (CX, CY, CR, X, Y, IX, IY) 'update the easy way 2020-04-15
  19.     a = _HYPOT(CX - X, CY - Y)
  20.     IF a <> 0 THEN
  21.         aPrime = CR ^ 2 / a
  22.         ang = _ATAN2(Y - CY, X - CX)
  23.         IX = CX + aPrime * COS(ang)
  24.         IY = CY + aPrime * SIN(ang)
  25.     ELSE
  26.         IX = CX: IY = CY 'because a line across diamter is inverted to itself
  27.     END IF
  28.  
  29.  
  30.  

Move your mouse around edge of circle to see drawing on both inside and out.

Mouse is blue, Inversion Points of mouse position is yellow.
Inversion Point.PNG
* Inversion Point.PNG (Filesize: 34.75 KB, Dimensions: 1204x720, Views: 238)
« Last Edit: August 19, 2020, 02:58:24 pm by bplus »

Offline _vince

  • Seasoned Forum Regular
  • Posts: 422
    • View Profile
Re: Inversion Points, 2D Circle
« Reply #3 on: August 19, 2020, 04:47:54 pm »
this one works, nice

Offline loudar

  • Newbie
  • Posts: 73
  • improve it bit by bit.
    • View Profile
Re: Inversion Points, 2D Circle
« Reply #4 on: August 19, 2020, 04:55:40 pm »
waves and stuff!
Anmerkung 2020-08-19 225516.png
* Anmerkung 2020-08-19 225516.png (Filesize: 23.13 KB, Dimensions: 1200x726, Views: 193)
Check out what I do besides coding: http://loudar.myportfolio.com/

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Inversion Points, 2D Circle
« Reply #5 on: August 19, 2020, 05:44:06 pm »
I inverted a checkerboard in a circle in the middle of it:
Code: QB64: [Select]
  1. _TITLE "Checkerboard mod Inverse" ' b+ 2020-08-19
  2. SCREEN _NEWIMAGE(700, 700, 32)
  3. _DELAY .25
  4.  
  5. ' using const so the code can be more readable < great idea!
  6. CONST GOLD = &HFFFF9900, BLACK = &HFF000000, RED = &HFFFF0000, SQ = 35
  7. LINE (0 * SQ + .5 * SQ - 4, 0 * SQ + .5 * SQ - 4)-STEP(19 * SQ + 8, 19 * SQ + 8), GOLD, BF
  8. n = 0
  9. FOR y = 0 TO 18
  10.     FOR x = 0 TO 18
  11.         n = (n + 1) MOD 2
  12.         IF n MOD 2 THEN colore& = RED ELSE colore& = BLACK
  13.         LINE (x * SQ + .5 * SQ + 2, y * SQ + .5 * SQ + 2)-STEP(SQ - 4, SQ - 4), colore&, BF
  14.     NEXT
  15.     'n = (n + 1) MOD 2 '< for even amount of squares in a row
  16. fcirc 350, 350, 250, &HFF000000
  17. FOR y = -1000 TO 1700
  18.     FOR x = -1000 TO 1700
  19.         IF _HYPOT(x - 350, y - 350) >= 250 THEN
  20.             inversionPoint 350, 350, 250, x, y, ix, iy
  21.             IF x > 0 AND x < 700 AND y > 0 AND y < 700 THEN
  22.                 c = POINT(x, y)
  23.                 PSET (ix, iy), c
  24.             ELSE
  25.                 PSET (ix, iy), &HFF000000
  26.             END IF
  27.         END IF
  28.     NEXT
  29.  
  30. SUB inversionPoint (CX, CY, CR, X, Y, IX, IY) 'update the easy way 2020-04-15
  31.     a = _HYPOT(CX - X, CY - Y)
  32.     IF a <> 0 THEN
  33.         aPrime = CR ^ 2 / a
  34.         ang = _ATAN2(Y - CY, X - CX)
  35.         IX = CX + aPrime * COS(ang)
  36.         IY = CY + aPrime * SIN(ang)
  37.     ELSE
  38.         IX = CX: IY = CY 'because a line across diamter is inverted to itself
  39.     END IF
  40.  
  41. SUB fcirc (CX AS INTEGER, CY AS INTEGER, R AS INTEGER, C AS _UNSIGNED LONG)
  42.     DIM Radius AS INTEGER, RadiusError AS INTEGER
  43.     DIM X AS INTEGER, Y AS INTEGER
  44.     Radius = ABS(R): RadiusError = -Radius: X = Radius: Y = 0
  45.     IF Radius = 0 THEN PSET (CX, CY), C: EXIT SUB
  46.     LINE (CX - X, CY)-(CX + X, CY), C, BF
  47.     WHILE X > Y
  48.         RadiusError = RadiusError + Y * 2 + 1
  49.         IF RadiusError >= 0 THEN
  50.             IF X <> Y + 1 THEN
  51.                 LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  52.                 LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  53.             END IF
  54.             X = X - 1
  55.             RadiusError = RadiusError - X * 2
  56.         END IF
  57.         Y = Y + 1
  58.         LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  59.         LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  60.     WEND
  61.  
  62.  

Checkerboard with Inversion Mod.PNG
* Checkerboard with Inversion Mod.PNG (Filesize: 55.48 KB, Dimensions: 706x731, Views: 236)
« Last Edit: August 19, 2020, 05:45:28 pm by bplus »