Author Topic: Hypnotic polygon orbits  (Read 18020 times)

0 Members and 1 Guest are viewing this topic.

Offline TerryRitchie

  • Seasoned Forum Regular
  • Posts: 495
  • Semper Fidelis
    • View Profile
Re: Hypnotic polygon orbits
« Reply #15 on: February 26, 2020, 12:19:25 am »
No extra pulls. The owners won't even notice because their fish will be dead from lack of oxygen circulating through the tank.
In order to understand recursion, one must first understand recursion.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Hypnotic polygon orbits
« Reply #16 on: February 26, 2020, 02:19:22 am »
Phew, I was busting at the seams to just shut up for once about a math problem... But this reminds me of a riddle - lemme go from memory:

Suppose you're house-sitting for some up-tight rich people. You just go there to feed the fish, and that's it. They even turned the main circuit breaker off (fuse panel if you like), and locked the box. One day, you walk in to perform your duties, and absentmindedly pull the chain down on the ceiling fan. Oops, when the owners come back, the house power comes on, and so does the fan! But... based on your knowledge of fans, the pull-switch can change the speed of the motor a few times before turning it off. Taking it for certain that either three total pulls of the chain or four total pulls of the chain will leave it in the off-position, what do you do? Pull it 3 total times or 4 total times?

And as a bonus - how does that apply to this problem?

3 X 4 = 12 which is what I used as a unit rate of speed or rather 12ths as multiplier of angle.

For this:
Code: QB64: [Select]
  1. _TITLE "Polygon Orbits 2" 'b+ 2020-02-25
  2. ' Fellippe's post 2020-02-25 https://www.qb64.org/forum/index.php?topic=2234.msg114766#msg114766
  3. ' Inspired by this post: https://www.reddit.com/r/gifs/comments/f91c99/every_addtional_shape_adds_one_more_corner_and/
  4.  
  5. CONST xmax = 550, ymax = 550, side = 100, center = 275, P1 = _PI, P2 = P1 * 2, PD2 = P1 * .5
  6. DIM SHARED poly$(3 TO 15) 'point strings we will turn into arrays as needed
  7. DIM SHARED c(3 TO 15) AS _UNSIGNED LONG 'colors
  8. c(3) = &HFF550000: c(4) = &HFFAA0000: c(5) = &HFFFF0000: c(6) = &HFFDD4400: c(7) = &HFF888800: c(8) = &HFFFF8800
  9. c(9) = &HFF00FF00: c(10) = &HFF00FF88: c(11) = &HFF00FFFF: c(12) = &HFF0088FF: c(13) = &HFF0000FF: c(14) = &HF88F0088: c(15) = &HFF330033
  10. DIM SHARED rate(3 TO 15), radii(3 TO 15), a 'for dots
  11.  
  12. SCREEN _NEWIMAGE(xmax, ymax, 32)
  13. _SCREENMOVE 300, 20
  14. DIM i, n, isoA, isoA2, turn, r, x1, y1, currA, x2, y2
  15. FOR i = 3 TO 15
  16.     rate(i) = (16 - i) / 12 'rate as angle mult that disc will move in circle
  17. FOR n = 3 TO 15
  18.     a = P2 / n '                  central angle
  19.     isoA = (P1 - a) / 2 '         angle of one iso triangle at base
  20.     isoA2 = isoA * 2 '            2 iso's is interior angle at each node
  21.     turn = P1 - isoA2 '           for turtle drawing, turn this much at each point
  22.     r = .5 * side / SIN(a / 2) ' << so  << 1/2 * side = r * sin(1/2 * a)
  23.     radii(n) = r
  24.     x1 = center + r * COS(a / 2 + PD2): y1 = center + r * SIN(a / 2 + PD2)
  25.     poly$(n) = STR$(x1) + "," + STR$(y1) 'our first point for polygon
  26.     currA = P1 'turtle draw the rest of the poly and save the points
  27.     FOR i = 2 TO n + 1
  28.         currA = currA + turn
  29.         x2 = x1 + side * COS(currA): y2 = y1 + side * SIN(currA)
  30.         LINE (x1, y1)-(x2, y2)
  31.         x1 = x2: y1 = y2
  32.         poly$(n) = poly$(n) + "," + STR$(x1) + "," + STR$(y1)
  33.     NEXT
  34. WHILE _KEYDOWN(27) = 0
  35.     CLS
  36.     drawPolys
  37.     a = a + _PI(2 / 120)
  38.     _DISPLAY
  39.     _LIMIT 30
  40.  
  41. SUB drawPolys
  42.     DIM n, i, Px, Py, dist, Rx, Ry, r, g, b
  43.     FOR n = 15 TO 3 STEP -1
  44.         'here is where we want our dot but we have to place on a line segment between two closest points to Px, Py
  45.         Px = center + radii(n) * COS(rate(n) * a + PD2)
  46.         Py = center + radii(n) * SIN(rate(n) * a + PD2)
  47.         REDIM pts(0)
  48.         Split poly$(n), ",", pts()
  49.         REDIM min(1), save(1)
  50.         min(0) = 1000: min(1) = 1100: save(0) = -1: save(1) = -2 'dummy
  51.         FOR i = 0 TO UBOUND(pts) STEP 2
  52.             IF i < 2 * n - 1 THEN
  53.                 dist = SQR((Px - pts(i)) ^ 2 + (Py - pts(i + 1)) ^ 2)
  54.                 IF dist <= min(0) THEN
  55.                     min(1) = min(0): min(0) = dist: save(1) = save(0): save(0) = i
  56.                 ELSEIF dist <= min(1) THEN
  57.                     min(1) = dist: save(1) = i
  58.                 END IF
  59.             END IF
  60.             IF i = 0 THEN
  61.                 PSET (pts(0), pts(1)), c(n)
  62.             ELSE
  63.                 LINE -(pts(i), pts(i + 1)), c(n)
  64.             END IF
  65.         NEXT
  66.         'now we have the two closest points of poly to px, py find Rx, RY on that line closest to Px, Py
  67.         IF ABS(pts(save(0)) - pts(save(1))) < .001 THEN ' have perpendicular line so get Rx, RY directly
  68.             Rx = pts(save(0)): Ry = Py
  69.         ELSE
  70.             PointOnLinePerp2Point pts(save(0)), pts(save(0) + 1), pts(save(1)), pts(save(1) + 1), Px, Py, Rx, Ry
  71.         END IF
  72.         r = _RED32(c(n)): g = _GREEN32(c(n)): b = _BLUE32(c(n))
  73.         FOR i = 9 TO 0 STEP -1
  74.             fcirc Rx, Ry, i, midInk(r, g, b, 255, 255, 255, (9 - i) / 9)
  75.         NEXT
  76.     NEXT
  77.  
  78. SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept) ' fix for when x1 = x2
  79.     IF X1 = X2 THEN
  80.         slope = X1
  81.         Yintercept = Y2
  82.     ELSE
  83.         slope = (Y2 - Y1) / (X2 - X1)
  84.         Yintercept = slope * (0 - X1) + Y1
  85.     END IF
  86.  
  87. SUB PointOnLinePerp2Point (Lx1, Ly1, Lx2, Ly2, Px, Py, Rx, Ry)
  88.     '
  89.     'this sub needs  SUB slopeYintersect (X1, Y1, X2, Y2, slope, Yintercept) ' fix for when x1 = x2
  90.     '
  91.     'Lx1, Ly1, Lx2, Ly2     the two points that make a line
  92.     'Px, Py is point off the line
  93.     'Rx, Ry Return Point is the Point on the line perpendicular to Px, Py
  94.     DIM m, Y0, AA, B
  95.     slopeYintersect Lx1, Ly1, Lx2, Ly2, m, Y0
  96.     AA = m ^ 2 + 1
  97.     B = 2 * (m * Y0 - m * Py - Px)
  98.     Rx = -B / (2 * AA)
  99.     Ry = m * Rx + Y0
  100.  
  101. FUNCTION midInk~& (r1%, g1%, b1%, r2%, g2%, b2%, fr##)
  102.     midInk~& = _RGB32(r1% + (r2% - r1%) * fr##, g1% + (g2% - g1%) * fr##, b1% + (b2% - b1%) * fr##)
  103.  
  104. 'this sub modified for splitting into an single array!!!
  105. SUB Split (SplitMeString AS STRING, delim AS STRING, loadMeArray())
  106.     DIM curpos AS LONG, arrpos AS LONG, LD AS LONG, dpos AS LONG 'fix use the Lbound the array already has
  107.     curpos = 1: arrpos = LBOUND(loadMeArray): LD = LEN(delim)
  108.     dpos = INSTR(curpos, SplitMeString, delim)
  109.     DO UNTIL dpos = 0
  110.         loadMeArray(arrpos) = VAL(MID$(SplitMeString, curpos, dpos - curpos))
  111.         arrpos = arrpos + 1
  112.         IF arrpos > UBOUND(loadMeArray) THEN REDIM _PRESERVE loadMeArray(LBOUND(loadMeArray) TO UBOUND(loadMeArray) + 1000)
  113.         curpos = dpos + LD
  114.         dpos = INSTR(curpos, SplitMeString, delim)
  115.     LOOP
  116.     loadMeArray(arrpos) = VAL(MID$(SplitMeString, curpos))
  117.     REDIM _PRESERVE loadMeArray(LBOUND(loadMeArray) TO arrpos) 'get the ubound correct
  118.  
  119. SUB fcirc (CX AS INTEGER, CY AS INTEGER, R AS INTEGER, C AS _UNSIGNED LONG)
  120.     DIM Radius AS INTEGER, RadiusError AS INTEGER
  121.     DIM X AS INTEGER, Y AS INTEGER
  122.     Radius = ABS(R): RadiusError = -Radius: X = Radius: Y = 0
  123.     IF Radius = 0 THEN PSET (CX, CY), C: EXIT SUB
  124.     LINE (CX - X, CY)-(CX + X, CY), C, BF
  125.     WHILE X > Y
  126.         RadiusError = RadiusError + Y * 2 + 1
  127.         IF RadiusError >= 0 THEN
  128.             IF X <> Y + 1 THEN
  129.                 LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  130.                 LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  131.             END IF
  132.             X = X - 1
  133.             RadiusError = RadiusError - X * 2
  134.         END IF
  135.         Y = Y + 1
  136.         LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  137.         LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  138.     WEND
  139.  

 
Polygon Orbits 2.PNG

« Last Edit: February 26, 2020, 02:44:12 am by bplus »

Offline johnno56

  • Forum Resident
  • Posts: 1270
  • Live long and prosper.
    • View Profile
Re: Hypnotic polygon orbits
« Reply #17 on: February 26, 2020, 02:37:07 am »
Cool.

Noticed that every time the "outer" object completes a semi-orbit all the other object aligns... Cool.
Logic is the beginning of wisdom.

FellippeHeitor

  • Guest
Re: Hypnotic polygon orbits
« Reply #18 on: February 26, 2020, 02:38:34 am »
Gorgeous result, bplus! So harmonious.

Offline Ashish

  • Forum Resident
  • Posts: 630
  • Never Give Up!
    • View Profile
Re: Hypnotic polygon orbits
« Reply #19 on: February 26, 2020, 03:24:48 am »
awesome bplus!
if (Me.success) {Me.improve()} else {Me.tryAgain()}


My Projects - https://github.com/AshishKingdom?tab=repositories
OpenGL tutorials - https://ashishkingdom.github.io/OpenGL-Tutorials

Marked as best answer by on Today at 05:48:29 am

Offline Ashish

  • Forum Resident
  • Posts: 630
  • Never Give Up!
    • View Profile
Re: Hypnotic polygon orbits
« Reply #20 on: February 26, 2020, 04:30:39 am »
  • Undo Best Answer
  • Here's my version....It is not as good as yours bplus. ;) something buggy in angular speed...
    Code: QB64: [Select]
    1. _TITLE "Hypnotic Polygon Orbits [Ashish's Version]"
    2. SCREEN _NEWIMAGE(400, 400, 32)
    3.  
    4. TYPE vec2
    5.     x AS SINGLE
    6.     y AS SINGLE
    7.  
    8. TYPE part
    9.     pos AS vec2
    10.     src AS INTEGER
    11.     dest AS INTEGER
    12.     v AS SINGLE
    13.     angSpeed AS SINGLE
    14.  
    15. DIM SHARED particle_path(11, 13) AS vec2
    16. DIM SHARED particle(10) AS part
    17.  
    18. vel = 3
    19. FOR i = 3 TO 13
    20.     COLOR hsb~&((i - 3) * 17, 255, 128, 255)
    21.     drawShape 200, 200, 30 + 15 * (i - 3), i
    22.     '   particle(i - 3).angSpeed = vel / (25 * (i - 2))  'angular speed. will calculated by v = w*r -> w = v/r and v is constant.
    23.     particle(i - 3).angSpeed = 0.05 * (ABS(i - 14) / 12)
    24.     particle(i - 3).v = 0.5 '    align at the middle
    25.     IF i MOD 2 = 1 THEN
    26.         particle(i - 3).pos = particle_path(i - 3, (i - 1) / 2) '((i+1)/2)-1
    27.         particle(i - 3).src = (i - 1) / 2
    28.         particle(i - 3).dest = particle(i - 3).src + 1
    29.     END IF
    30.     IF i MOD 4 = 0 THEN
    31.         particle(i - 3).pos = particle_path(i - 3, (i - 4) / 4) '((i)/4)-1
    32.         particle(i - 3).src = (i - 4) / 4
    33.         particle(i - 3).dest = particle(i - 3).src + 1
    34.     END IF
    35. particle(3).pos = particle_path(3, 4) 'hack, I just need to care about initial condition
    36. particle(3).src = 4
    37. particle(3).dest = 5
    38. particle(7).pos = particle_path(7, 7)
    39. particle(7).src = 7
    40. particle(7).dest = 8
    41.  
    42.  
    43. pic& = _COPYIMAGE(0)
    44. w~& = _RGB32(255)
    45.  
    46.     CLS
    47.     _PUTIMAGE , pic&
    48.     FOR i = 0 TO UBOUND(particle)
    49.         particle(i).pos.x = map(particle(i).v, 0, 1, particle_path(i, particle(i).src).x, particle_path(i, particle(i).dest).x)
    50.         particle(i).pos.y = map(particle(i).v, 0, 1, particle_path(i, particle(i).src).y, particle_path(i, particle(i).dest).y)
    51.         CircleFill particle(i).pos.x, particle(i).pos.y, 3, w~&
    52.         IF particle(i).v >= 1 THEN
    53.             particle(i).src = particle(i).dest
    54.             IF particle(i).dest = (i + 3) - 1 THEN
    55.                 particle(i).dest = 0
    56.             ELSE
    57.                 particle(i).dest = particle(i).dest + 1
    58.             END IF
    59.             particle(i).v = 0
    60.         END IF
    61.         particle(i).v = particle(i).v + particle(i).angSpeed
    62.     NEXT
    63.  
    64.     _LIMIT 60
    65.     _DISPLAY
    66.  
    67.  
    68. SUB drawShape (x, y, s, n)
    69.     IF n MOD 2 = 1 THEN theta = -_PI(0.5) ELSE theta = _PI(1 / n)
    70.     IF n = 6 OR n = 10 THEN theta = _PI(1 / 2 * n)
    71.     c = 0
    72.     FOR i = theta TO _PI(2) + theta STEP _PI(2 / n)
    73.         x0 = x + s * COS(i)
    74.         y0 = y + s * SIN(i)
    75.         particle_path((n - 3), c).x = x0
    76.         particle_path((n - 3), c).y = y0
    77.         LINE (x0, y0)-(x + s * COS(i + _PI(2 / n)), y + s * SIN(i + _PI(2 / n)))
    78.         c = c + 1
    79.     NEXT
    80.  
    81.  
    82. 'method adapted form http://stackoverflow.com/questions/4106363/converting-rgb-to-hsb-colors
    83. FUNCTION hsb~& (__H AS _FLOAT, __S AS _FLOAT, __B AS _FLOAT, A AS _FLOAT)
    84.     DIM H AS _FLOAT, S AS _FLOAT, B AS _FLOAT
    85.  
    86.     H = map(__H, 0, 255, 0, 360)
    87.     S = map(__S, 0, 255, 0, 1)
    88.     B = map(__B, 0, 255, 0, 1)
    89.  
    90.     IF S = 0 THEN
    91.         hsb~& = _RGBA32(B * 255, B * 255, B * 255, A)
    92.         EXIT FUNCTION
    93.     END IF
    94.  
    95.     DIM fmx AS _FLOAT, fmn AS _FLOAT
    96.     DIM fmd AS _FLOAT, iSextant AS INTEGER
    97.     DIM imx AS INTEGER, imd AS INTEGER, imn AS INTEGER
    98.  
    99.     IF B > .5 THEN
    100.         fmx = B - (B * S) + S
    101.         fmn = B + (B * S) - S
    102.     ELSE
    103.         fmx = B + (B * S)
    104.         fmn = B - (B * S)
    105.     END IF
    106.  
    107.     iSextant = INT(H / 60)
    108.  
    109.     IF H >= 300 THEN
    110.         H = H - 360
    111.     END IF
    112.  
    113.     H = H / 60
    114.     H = H - (2 * INT(((iSextant + 1) MOD 6) / 2))
    115.  
    116.     IF iSextant MOD 2 = 0 THEN
    117.         fmd = (H * (fmx - fmn)) + fmn
    118.     ELSE
    119.         fmd = fmn - (H * (fmx - fmn))
    120.     END IF
    121.  
    122.     imx = _ROUND(fmx * 255)
    123.     imd = _ROUND(fmd * 255)
    124.     imn = _ROUND(fmn * 255)
    125.  
    126.     SELECT CASE INT(iSextant)
    127.         CASE 1
    128.             hsb~& = _RGBA32(imd, imx, imn, A)
    129.         CASE 2
    130.             hsb~& = _RGBA32(imn, imx, imd, A)
    131.         CASE 3
    132.             hsb~& = _RGBA32(imn, imd, imx, A)
    133.         CASE 4
    134.             hsb~& = _RGBA32(imd, imn, imx, A)
    135.         CASE 5
    136.             hsb~& = _RGBA32(imx, imn, imd, A)
    137.         CASE ELSE
    138.             hsb~& = _RGBA32(imx, imd, imn, A)
    139.     END SELECT
    140.  
    141.  
    142.  
    143. FUNCTION map! (value!, minRange!, maxRange!, newMinRange!, newMaxRange!)
    144.     map! = ((value! - minRange!) / (maxRange! - minRange!)) * (newMaxRange! - newMinRange!) + newMinRange!
    145.  
    146. SUB CircleFill (x AS LONG, y AS LONG, R AS LONG, C AS _UNSIGNED LONG)
    147.     DIM x0 AS SINGLE, y0 AS SINGLE
    148.     DIM e AS SINGLE
    149.  
    150.     x0 = R
    151.     y0 = 0
    152.     e = -R
    153.     DO WHILE y0 < x0
    154.         IF e <= 0 THEN
    155.             y0 = y0 + 1
    156.             LINE (x - x0, y + y0)-(x + x0, y + y0), C, BF
    157.             LINE (x - x0, y - y0)-(x + x0, y - y0), C, BF
    158.             e = e + 2 * y0
    159.         ELSE
    160.             LINE (x - y0, y - x0)-(x + y0, y - x0), C, BF
    161.             LINE (x - y0, y + x0)-(x + y0, y + x0), C, BF
    162.             x0 = x0 - 1
    163.             e = e - 2 * x0
    164.         END IF
    165.     LOOP
    166.     LINE (x - R, y)-(x + R, y), C, BF
    167.  
    « Last Edit: February 26, 2020, 10:21:43 am by Ashish »
    if (Me.success) {Me.improve()} else {Me.tryAgain()}


    My Projects - https://github.com/AshishKingdom?tab=repositories
    OpenGL tutorials - https://ashishkingdom.github.io/OpenGL-Tutorials

    Offline Bolee

    • Newbie
    • Posts: 4
      • View Profile
    Re: Hypnotic polygon orbits
    « Reply #21 on: February 17, 2021, 05:36:59 am »
    Wow I like the pattern.

    There is also something called an ULAM SPIRAL  where you can set the type of polygon and then it spirals (a bit like your pattern but spiraling). I saw it on the freebasic site years ago. It was also on Rosetta code.