Author Topic: Hypnotic polygon orbits  (Read 5743 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

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.