Author Topic: Hypnotic polygon orbits  (Read 6975 times)

0 Members and 1 Guest are viewing this topic.

Marked as best answer by on Yesterday at 06:48:57 pm

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 »
  • Undo Best Answer
  • 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

    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 »
    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.