Author Topic: Hypnotic polygon orbits  (Read 6974 times)

0 Members and 1 Guest are viewing this topic.

This topic contains a post which is marked as Best Answer. Press here if you would like to see it.

FellippeHeitor

  • Guest
Hypnotic polygon orbits
« on: February 25, 2020, 09:19:22 am »
Inspired by this post: https://www.reddit.com/r/gifs/comments/f91c99/every_addtional_shape_adds_one_more_corner_and/

Captura de Tela 2020-02-25 às 11.37.14.png

Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(300, 300, 32)
  2. _TITLE "Polygon orbits"
  3. TYPE shapeType
  4.     n AS INTEGER
  5.     c AS _UNSIGNED LONG
  6.     x AS SINGLE
  7.     y AS SINGLE
  8.  
  9. DIM SHARED shape(1 TO 13, 1 TO 15) AS shapeType
  10.  
  11. 'draw shapes and fill shape() array with vertices
  12. FOR s = 3 TO 12
  13.     drawShape _WIDTH / 2, _HEIGHT / 2, s * 10, s, s - 2
  14.  
  15. 'save shapes image
  16. PCOPY 0, 1
  17.  
  18. 'have circles follow shapes' paths
  19.     FOR s = 1 TO 10
  20.         shape(s, 1).n = shape(s, 1).n + 1
  21.         IF shape(s, 1).n > s + 2 THEN
  22.             shape(s, 1).n = 1
  23.         END IF
  24.     NEXT
  25.     FOR i = 1 TO 100 STEP 5
  26.         PCOPY 1, 0 'restore background
  27.         DIM ret AS shapeType
  28.         FOR s = 1 TO 10
  29.             IF shape(s, 1).n < s + 2 THEN
  30.                 followPath shape(s, shape(s, 1).n).x, shape(s, shape(s, 1).n).y, shape(s, shape(s, 1).n + 1).x, shape(s, shape(s, 1).n + 1).y, i, ret
  31.             ELSE
  32.                 followPath shape(s, shape(s, 1).n).x, shape(s, shape(s, 1).n).y, shape(s, 1).x, shape(s, 1).y, i, ret
  33.             END IF
  34.             CircleFill ret.x, ret.y, 5, shape(s, 1).c
  35.         NEXT
  36.         _DISPLAY
  37.         _LIMIT 60
  38.     NEXT
  39.  
  40. SUB drawShape (x AS SINGLE, y AS SINGLE, size AS INTEGER, sides AS INTEGER, arrayIndex AS INTEGER)
  41.     'Thanks to Ashish for contributing to this sub
  42.     DIM i AS SINGLE, vertex AS INTEGER
  43.     DIM x0 AS SINGLE, y0 AS SINGLE, theta AS SINGLE
  44.     DIM thisColor AS _UNSIGNED LONG
  45.  
  46.     IF sides <> 4 THEN theta = -_PI(0.5) ELSE theta = _PI(0.25)
  47.  
  48.     thisColor = hsb(map(sides, 3, 12, 0, 360), 255, 127, 255)
  49.     shape(arrayIndex, 1).c = thisColor
  50.     FOR i = theta TO _PI(2) + theta STEP _PI(2 / sides)
  51.         x0 = x + size * COS(i)
  52.         y0 = y + size * SIN(i)
  53.         LINE (x0, y0)-(x + size * COS(i + _PI(2 / sides)), y + size * SIN(i + _PI(2 / sides))), thisColor
  54.  
  55.         vertex = vertex + 1
  56.         shape(arrayIndex, vertex).x = x0
  57.         shape(arrayIndex, vertex).y = y0
  58.     NEXT
  59.  
  60. SUB followPath (X AS INTEGER, Y AS INTEGER, X2 AS INTEGER, Y2 AS INTEGER, atStep AS INTEGER, position AS shapeType)
  61.     'This sub adapted from http://www.antonis.de/faq/progs/bline.bas
  62.     '---------
  63.     'This implementation returns position.x and position.y as coordinates
  64.     'to a point across the path between X,Y and X2,Y2
  65.     'Uses atStep to determine how far along the path the returned point stands
  66.     DIM I AS INTEGER
  67.     DIM Steep AS INTEGER
  68.     DIM E AS INTEGER
  69.     DIM SX AS INTEGER
  70.     DIM SY AS INTEGER
  71.     DIM DX AS INTEGER
  72.     DIM DY AS INTEGER
  73.     I = 0
  74.     Steep% = 0
  75.     E = 0
  76.     IF (X2 - X) > 0 THEN
  77.         SX = 1
  78.     ELSE
  79.         SX = -1
  80.     END IF
  81.     DX = ABS(X2 - X)
  82.     IF (Y2 - Y) > 0 THEN
  83.         SY = 1
  84.     ELSE
  85.         SY = -1
  86.     END IF
  87.     DY = ABS(Y2 - Y)
  88.     IF (DY > DX) THEN
  89.         Steep = 1
  90.         SWAP X, Y
  91.         SWAP DX, DY
  92.         SWAP SX, SY
  93.     END IF
  94.     E = 2 * DY - DX
  95.     FOR I = 0 TO (INT(map(atStep, 0, 100, 0, DX))) - 1
  96.         WHILE E >= 0
  97.             Y = Y + SY
  98.             E = E - 2 * DX
  99.         WEND
  100.         X = X + SX
  101.         E = E + 2 * DY
  102.     NEXT
  103.     IF Steep% = 1 THEN
  104.         position.x = Y
  105.         position.y = X
  106.     ELSE
  107.         position.x = X
  108.         position.y = Y
  109.     END IF
  110.  
  111. FUNCTION map! (value!, minRange!, maxRange!, newMinRange!, newMaxRange!)
  112.     map! = ((value! - minRange!) / (maxRange! - minRange!)) * (newMaxRange! - newMinRange!) + newMinRange!
  113.  
  114. SUB CircleFill (CX AS INTEGER, CY AS INTEGER, R AS INTEGER, C AS _UNSIGNED LONG)
  115.     'This sub from https://www.qb64.org/forum/index.php?topic=1069.0
  116.     ' CX = center x coordinate
  117.     ' CY = center y coordinate
  118.     '  R = radius
  119.     '  C = fill color
  120.     DIM Radius AS INTEGER, RadiusError AS INTEGER
  121.     DIM X AS INTEGER, Y AS INTEGER
  122.     Radius = ABS(R)
  123.     RadiusError = -Radius
  124.     X = Radius
  125.     Y = 0
  126.     IF Radius = 0 THEN PSET (CX, CY), C: EXIT SUB
  127.     LINE (CX - X, CY)-(CX + X, CY), C, BF
  128.     WHILE X > Y
  129.         RadiusError = RadiusError + Y * 2 + 1
  130.         IF RadiusError >= 0 THEN
  131.             IF X <> Y + 1 THEN
  132.                 LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  133.                 LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  134.             END IF
  135.             X = X - 1
  136.             RadiusError = RadiusError - X * 2
  137.         END IF
  138.         Y = Y + 1
  139.         LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  140.         LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  141.     WEND
  142.  
  143. FUNCTION hsb~& (__H AS _FLOAT, __S AS _FLOAT, __B AS _FLOAT, A AS _FLOAT)
  144.     DIM H AS _FLOAT, S AS _FLOAT, B AS _FLOAT
  145.  
  146.     H = __H
  147.     S = map(__S, 0, 255, 0, 1)
  148.     B = map(__B, 0, 255, 0, 1)
  149.  
  150.     IF S = 0 THEN
  151.         hsb~& = _RGBA32(B * 255, B * 255, B * 255, A)
  152.         EXIT FUNCTION
  153.     END IF
  154.  
  155.     DIM fmx AS _FLOAT, fmn AS _FLOAT
  156.     DIM fmd AS _FLOAT, iSextant AS INTEGER
  157.     DIM imx AS INTEGER, imd AS INTEGER, imn AS INTEGER
  158.  
  159.     IF B > .5 THEN
  160.         fmx = B - (B * S) + S
  161.         fmn = B + (B * S) - S
  162.     ELSE
  163.         fmx = B + (B * S)
  164.         fmn = B - (B * S)
  165.     END IF
  166.  
  167.     iSextant = INT(H / 60)
  168.  
  169.     IF H >= 300 THEN
  170.         H = H - 360
  171.     END IF
  172.  
  173.     H = H / 60
  174.     H = H - (2 * INT(((iSextant + 1) MOD 6) / 2))
  175.  
  176.     IF iSextant MOD 2 = 0 THEN
  177.         fmd = (H * (fmx - fmn)) + fmn
  178.     ELSE
  179.         fmd = fmn - (H * (fmx - fmn))
  180.     END IF
  181.  
  182.     imx = _ROUND(fmx * 255)
  183.     imd = _ROUND(fmd * 255)
  184.     imn = _ROUND(fmn * 255)
  185.  
  186.     SELECT CASE INT(iSextant)
  187.         CASE 1
  188.             hsb~& = _RGBA32(imd, imx, imn, A)
  189.         CASE 2
  190.             hsb~& = _RGBA32(imn, imx, imd, A)
  191.         CASE 3
  192.             hsb~& = _RGBA32(imn, imd, imx, A)
  193.         CASE 4
  194.             hsb~& = _RGBA32(imd, imn, imx, A)
  195.         CASE 5
  196.             hsb~& = _RGBA32(imx, imn, imd, A)
  197.         CASE ELSE
  198.             hsb~& = _RGBA32(imx, imd, imn, A)
  199.     END SELECT
  200.  
  201.  
« Last Edit: February 25, 2020, 09:37:59 am by FellippeHeitor »

Offline Ashish

  • Forum Resident
  • Posts: 630
  • Never Give Up!
    • View Profile
Re: Hypnotic polygon orbits
« Reply #1 on: February 25, 2020, 09:34:05 am »
Hi.. here my version
Code: QB64: [Select]
  1. SCREEN _NEWIMAGE(700, 700, 32)
  2.  
  3. TYPE vec2
  4.     x AS SINGLE
  5.     y AS SINGLE
  6.  
  7. TYPE part
  8.     pos AS vec2
  9.     src AS INTEGER
  10.     dest AS INTEGER
  11.  
  12. DIM SHARED particle_path(11, 13) AS vec2
  13. DIM SHARED particle(10) AS part
  14.  
  15. FOR i = 3 TO 13
  16.     COLOR hsb~&((i - 3) * 17, 255, 128, 255)
  17.     drawShape 350, 350, 60 + 25 * (i - 3), i
  18.     particle(i - 3).pos = particle_path(i - 3, 0)
  19.     particle(i - 3).src = 0
  20.     particle(i - 3).dest = 1
  21. pic& = _COPYIMAGE(0)
  22. speed = 0.04
  23. v = 0
  24. w~& = _RGB(255, 255, 255)
  25.     CLS
  26.     _PUTIMAGE , pic&
  27.     v = v + speed
  28.     FOR i = 0 TO UBOUND(particle)
  29.         CircleFill particle(i).pos.x, particle(i).pos.y, 5, w~&
  30.         particle(i).pos.x = map(v, 0, 1, particle_path(i, particle(i).src).x, particle_path(i, particle(i).dest).x)
  31.         particle(i).pos.y = map(v, 0, 1, particle_path(i, particle(i).src).y, particle_path(i, particle(i).dest).y)
  32.         IF v >= 1 THEN
  33.             particle(i).src = particle(i).dest
  34.             IF particle(i).dest = (i + 3) - 1 THEN
  35.                 particle(i).dest = 0
  36.             ELSE
  37.                 particle(i).dest = particle(i).dest + 1
  38.             END IF
  39.         END IF
  40.     NEXT
  41.     IF v >= 1 THEN v = 0
  42.     _LIMIT 60
  43.     _DISPLAY
  44.  
  45. SUB drawShape (x, y, s, n)
  46.     IF n <> 4 THEN theta = -_PI(0.5) ELSE theta = _PI(0.25)
  47.     c = 0
  48.     FOR i = theta TO _PI(2) + theta STEP _PI(2 / n)
  49.         x0 = x + s * COS(i)
  50.         y0 = y + s * SIN(i)
  51.         particle_path((n - 3), c).x = x0
  52.         particle_path((n - 3), c).y = y0
  53.         LINE (x0, y0)-(x + s * COS(i + _PI(2 / n)), y + s * SIN(i + _PI(2 / n)))
  54.         c = c + 1
  55.     NEXT
  56.  
  57.  
  58. 'method adapted form http://stackoverflow.com/questions/4106363/converting-rgb-to-hsb-colors
  59. FUNCTION hsb~& (__H AS _FLOAT, __S AS _FLOAT, __B AS _FLOAT, A AS _FLOAT)
  60.     DIM H AS _FLOAT, S AS _FLOAT, B AS _FLOAT
  61.  
  62.     H = map(__H, 0, 255, 0, 360)
  63.     S = map(__S, 0, 255, 0, 1)
  64.     B = map(__B, 0, 255, 0, 1)
  65.  
  66.     IF S = 0 THEN
  67.         hsb~& = _RGBA32(B * 255, B * 255, B * 255, A)
  68.         EXIT FUNCTION
  69.     END IF
  70.  
  71.     DIM fmx AS _FLOAT, fmn AS _FLOAT
  72.     DIM fmd AS _FLOAT, iSextant AS INTEGER
  73.     DIM imx AS INTEGER, imd AS INTEGER, imn AS INTEGER
  74.  
  75.     IF B > .5 THEN
  76.         fmx = B - (B * S) + S
  77.         fmn = B + (B * S) - S
  78.     ELSE
  79.         fmx = B + (B * S)
  80.         fmn = B - (B * S)
  81.     END IF
  82.  
  83.     iSextant = INT(H / 60)
  84.  
  85.     IF H >= 300 THEN
  86.         H = H - 360
  87.     END IF
  88.  
  89.     H = H / 60
  90.     H = H - (2 * INT(((iSextant + 1) MOD 6) / 2))
  91.  
  92.     IF iSextant MOD 2 = 0 THEN
  93.         fmd = (H * (fmx - fmn)) + fmn
  94.     ELSE
  95.         fmd = fmn - (H * (fmx - fmn))
  96.     END IF
  97.  
  98.     imx = _ROUND(fmx * 255)
  99.     imd = _ROUND(fmd * 255)
  100.     imn = _ROUND(fmn * 255)
  101.  
  102.     SELECT CASE INT(iSextant)
  103.         CASE 1
  104.             hsb~& = _RGBA32(imd, imx, imn, A)
  105.         CASE 2
  106.             hsb~& = _RGBA32(imn, imx, imd, A)
  107.         CASE 3
  108.             hsb~& = _RGBA32(imn, imd, imx, A)
  109.         CASE 4
  110.             hsb~& = _RGBA32(imd, imn, imx, A)
  111.         CASE 5
  112.             hsb~& = _RGBA32(imx, imn, imd, A)
  113.         CASE ELSE
  114.             hsb~& = _RGBA32(imx, imd, imn, A)
  115.     END SELECT
  116.  
  117.  
  118.  
  119. FUNCTION map! (value!, minRange!, maxRange!, newMinRange!, newMaxRange!)
  120.     map! = ((value! - minRange!) / (maxRange! - minRange!)) * (newMaxRange! - newMinRange!) + newMinRange!
  121.  
  122. SUB CircleFill (x AS LONG, y AS LONG, R AS LONG, C AS _UNSIGNED LONG)
  123.     DIM x0 AS SINGLE, y0 AS SINGLE
  124.     DIM e AS SINGLE
  125.  
  126.     x0 = R
  127.     y0 = 0
  128.     e = -R
  129.     DO WHILE y0 < x0
  130.         IF e <= 0 THEN
  131.             y0 = y0 + 1
  132.             LINE (x - x0, y + y0)-(x + x0, y + y0), C, BF
  133.             LINE (x - x0, y - y0)-(x + x0, y - y0), C, BF
  134.             e = e + 2 * y0
  135.         ELSE
  136.             LINE (x - y0, y - x0)-(x + y0, y - x0), C, BF
  137.             LINE (x - y0, y + x0)-(x + y0, y + x0), C, BF
  138.             x0 = x0 - 1
  139.             e = e - 2 * x0
  140.         END IF
  141.     LOOP
  142.     LINE (x - R, y)-(x + R, y), C, BF
  143.  
  144.  
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 bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Hypnotic polygon orbits
« Reply #2 on: February 25, 2020, 09:37:18 am »
Wow! They are also spiral and turn into n-perpeller like, oh that's only in the link to video.

Fellippe your lineup of regular polys is off, yours too neat ;-) in link notice how all polys lineup at the bottom segment and the triangle overlaps the square at top point... that might help keep colored disks in pattern. They also start lineup straight down.

Still pretty cool.

FellippeHeitor

  • Guest
Re: Hypnotic polygon orbits
« Reply #3 on: February 25, 2020, 09:39:34 am »
Just "fixed" the square to be hacky too.

To fix the rest I'd probably need an adaptive theta in drawShape() for each number of sides.
« Last Edit: February 25, 2020, 09:41:52 am by FellippeHeitor »

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Hypnotic polygon orbits
« Reply #4 on: February 25, 2020, 03:31:54 pm »
This might help get your alignment started on the right foot.
Code: QB64: [Select]
  1. _TITLE "Polygon Orbits" '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 = 700, ymax = 700, side = 100, center = 350, P1 = _PI: P2 = _PI(2): PD2 = _PI(.5)
  6.  
  7. SCREEN _NEWIMAGE(xmax, ymax, 32)
  8. _SCREENMOVE 300, 20
  9. PSET (center, center)
  10. FOR n = 3 TO 12
  11.     a = P2 / n
  12.     ' 1/2 *side = r*sin(1/2*a)
  13.     r = .5 * side / SIN(a / 2)
  14.     x1 = center + r * COS(a / 2 + PD2)
  15.     y1 = center + r * SIN(a / 2 + PD2)
  16.     'PSET (x1, y1)   'OK ?
  17.     x2 = x1 + side * COS(0)
  18.     y2 = y1 + side * SIN(0)
  19.     'PSET (x2, y2) ' OK?
  20.     LINE (x1, y1)-(x2, y2) 'OK!
  21.  

The bottom segments are all aligned and parallel to bottom of screen.

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Hypnotic polygon orbits
« Reply #5 on: February 25, 2020, 04:49:38 pm »
Use turtle drawing to finish the polys and save the point positions:
Code: QB64: [Select]
  1. 'OPTION _EXPLICIT
  2. _TITLE "Polygon Orbits" 'b+ 2020-02-25
  3. ' Fellippe's post 2020-02-25 https://www.qb64.org/forum/index.php?topic=2234.msg114766#msg114766
  4. ' Inspired by this post: https://www.reddit.com/r/gifs/comments/f91c99/every_addtional_shape_adds_one_more_corner_and/
  5.  
  6. CONST xmax = 700, ymax = 700, side = 170, center = 350, P1 = _PI: P2 = _PI(2): PD2 = _PI(.5)
  7.  
  8. SCREEN _NEWIMAGE(xmax, ymax, 32)
  9. _SCREENMOVE 300, 20
  10.  
  11. DIM SHARED poly$(3 TO 12) 'point strings we will turn into arrays as needed
  12. PSET (center, center)
  13. FOR n = 3 TO 12
  14.     a = P2 / n
  15.     isoA = (P1 - a) / 2
  16.     isoA2 = isoA * 2
  17.     turn = P1 - isoA2 'for turtle drawing
  18.  
  19.     ' 1/2 *side = r*sin(1/2*a)
  20.     r = .5 * side / SIN(a / 2)
  21.     x1 = center + r * COS(a / 2 + PD2)
  22.     y1 = center + r * SIN(a / 2 + PD2)
  23.     'PSET (x1, y1)   'OK ?
  24.     'x2 = x1 + side * COS(0)
  25.     'y2 = y1 + side * SIN(0)
  26.     'PSET (x2, y2) ' OK?
  27.     'LINE (x1, y1)-(x2, y2) 'OK!
  28.     poly$(n) = STR$(x1) + "," + STR$(y1) 'our first point for polygon
  29.     currA = P1 'turtle draw the rest of the poly and save the points
  30.     FOR ring = 2 TO n + 1
  31.         currA = currA + turn
  32.         x2 = x1 + side * COS(currA)
  33.         y2 = y1 + side * SIN(currA)
  34.         LINE (x1, y1)-(x2, y2)
  35.         x1 = x2: y1 = y2
  36.         poly$(n) = poly$(n) + STR$(x1) + "," + STR$(y1)
  37.     NEXT
  38.  

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Hypnotic polygon orbits
« Reply #6 on: February 25, 2020, 05:58:22 pm »
OK, just need to add the circles
Code: QB64: [Select]
  1. _TITLE "Polygon Orbits" '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 = 700, ymax = 700, side = 170, center = 350, P1 = _PI, P2 = P1 * 2, PD2 = P1 * .5
  6. DIM SHARED poly$(3 TO 12) 'point strings we will turn into arrays as needed
  7. DIM SHARED c(3 TO 12) AS _UNSIGNED LONG 'colors
  8. c(3) = Red: c(4) = CrayolaOrange: c(5) = LaserLemon: c(6) = Lime: c(7) = MediumSpringGreen
  9. c(8) = Aqua: c(9) = Periwinkle: c(10) = NavyBlue: c(11) = MediumBlue: c(12) = RedViolet
  10.  
  11. SCREEN _NEWIMAGE(xmax, ymax, 32)
  12. _SCREENMOVE 300, 20
  13. DIM n, a, isoA, isoA2, turn, r, x1, y1, currA, ring, x2, y2
  14.  
  15. 'PSET (center, center)
  16. FOR n = 3 TO 12
  17.     a = P2 / n
  18.     isoA = (P1 - a) / 2
  19.     isoA2 = isoA * 2
  20.     turn = P1 - isoA2 'for turtle drawing
  21.  
  22.     ' 1/2 *side = r*sin(1/2*a)
  23.     r = .5 * side / SIN(a / 2)
  24.     x1 = center + r * COS(a / 2 + PD2)
  25.     y1 = center + r * SIN(a / 2 + PD2)
  26.     'PSET (x1, y1)   'OK ?
  27.     'x2 = x1 + side * COS(0)
  28.     'y2 = y1 + side * SIN(0)
  29.     'PSET (x2, y2) ' OK?
  30.     'LINE (x1, y1)-(x2, y2) 'OK!
  31.     poly$(n) = STR$(x1) + "," + STR$(y1) 'our first point for polygon
  32.     currA = P1 'turtle draw the rest of the poly and save the points
  33.     FOR ring = 2 TO n + 1
  34.         currA = currA + turn
  35.         x2 = x1 + side * COS(currA)
  36.         y2 = y1 + side * SIN(currA)
  37.         LINE (x1, y1)-(x2, y2)
  38.         x1 = x2: y1 = y2
  39.         poly$(n) = poly$(n) + "," + STR$(x1) + "," + STR$(y1)
  40.     NEXT
  41. drawPolys
  42.  
  43. SUB drawPolys
  44.     DIM n, i, x1, y1, x2, y2, w$
  45.     FOR n = 3 TO 12
  46.         REDIM pts$(0)
  47.         Split poly$(n), ",", pts$()
  48.         'FOR i = 0 TO UBOUND(pts$) - 1 STEP 2
  49.         '    PRINT pts$(i), pts$(i + 1)
  50.         'NEXT
  51.         PSET (VAL(pts$(0)), VAL(pts$(1))), c(n)
  52.         FOR i = 2 TO UBOUND(pts$) STEP 2
  53.             x1 = VAL(pts$(i)): y1 = VAL(pts$((i + 1)))
  54.             LINE -(x1, y1), c(n)
  55.         NEXT
  56.     NEXT
  57.  
  58. SUB Split (SplitMeString AS STRING, delim AS STRING, loadMeArray() AS STRING)
  59.     DIM curpos AS LONG, arrpos AS LONG, LD AS LONG, dpos AS LONG 'fix use the Lbound the array already has
  60.     curpos = 1: arrpos = LBOUND(loadMeArray): LD = LEN(delim)
  61.     dpos = INSTR(curpos, SplitMeString, delim)
  62.     DO UNTIL dpos = 0
  63.         loadMeArray(arrpos) = MID$(SplitMeString, curpos, dpos - curpos)
  64.         arrpos = arrpos + 1
  65.         IF arrpos > UBOUND(loadMeArray) THEN REDIM _PRESERVE loadMeArray(LBOUND(loadMeArray) TO UBOUND(loadMeArray) + 1000) AS STRING
  66.         curpos = dpos + LD
  67.         dpos = INSTR(curpos, SplitMeString, delim)
  68.     LOOP
  69.     loadMeArray(arrpos) = MID$(SplitMeString, curpos)
  70.     REDIM _PRESERVE loadMeArray(LBOUND(loadMeArray) TO arrpos) AS STRING 'get the ubound correct
  71.  
  72.  
  73. SUB fcirc (CX AS INTEGER, CY AS INTEGER, R AS INTEGER, C AS _UNSIGNED LONG)
  74.     DIM Radius AS INTEGER, RadiusError AS INTEGER
  75.     DIM X AS INTEGER, Y AS INTEGER
  76.     Radius = ABS(R): RadiusError = -Radius: X = Radius: Y = 0
  77.     IF Radius = 0 THEN PSET (CX, CY), C: EXIT SUB
  78.     LINE (CX - X, CY)-(CX + X, CY), C, BF
  79.     WHILE X > Y
  80.         RadiusError = RadiusError + Y * 2 + 1
  81.         IF RadiusError >= 0 THEN
  82.             IF X <> Y + 1 THEN
  83.                 LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  84.                 LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  85.             END IF
  86.             X = X - 1
  87.             RadiusError = RadiusError - X * 2
  88.         END IF
  89.         Y = Y + 1
  90.         LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  91.         LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  92.     WEND
  93.  
  94.  
  95.  

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Hypnotic polygon orbits
« Reply #7 on: February 25, 2020, 08:54:39 pm »
Piss, I get the same misalignment you guys got:
Code: QB64: [Select]
  1. _TITLE "Polygon Orbits" '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 = 700, ymax = 700, side = 130, center = 350, 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 node, frac 'frac for moving disks between nodes
  11. SCREEN _NEWIMAGE(xmax, ymax, 32)
  12. _SCREENMOVE 300, 20
  13. DIM n, a, isoA, isoA2, turn, r, x1, y1, currA, ring, x2, y2
  14. FOR n = 3 TO 15
  15.     a = P2 / n '                  central angle
  16.     isoA = (P1 - a) / 2 '         angle of one iso triangle at base
  17.     isoA2 = isoA * 2 '            2 iso's is interior angle at each node
  18.     turn = P1 - isoA2 '           for turtle drawing, turn this much at each point
  19.     r = .5 * side / SIN(a / 2) ' << so  << 1/2 * side = r * sin(1/2 * a)
  20.     x1 = center + r * COS(a / 2 + PD2): y1 = center + r * SIN(a / 2 + PD2)
  21.     poly$(n) = STR$(x1) + "," + STR$(y1) 'our first point for polygon
  22.     currA = P1 'turtle draw the rest of the poly and save the points
  23.     FOR ring = 2 TO n + 1
  24.         currA = currA + turn
  25.         x2 = x1 + side * COS(currA): y2 = y1 + side * SIN(currA)
  26.         LINE (x1, y1)-(x2, y2)
  27.         x1 = x2: y1 = y2
  28.         poly$(n) = poly$(n) + "," + STR$(x1) + "," + STR$(y1)
  29.     NEXT
  30. frac = 4
  31. WHILE _KEYDOWN(27) = 0
  32.     CLS
  33.     frac = frac + 1
  34.     IF frac = 10 THEN frac = 0: node = node + 1
  35.     drawPolys
  36.     _DISPLAY
  37.     _LIMIT 30
  38.  
  39. SUB drawPolys
  40.     DIM n, i, x1, y1, x2, y2, target, lastNode, midx, midy
  41.     FOR n = 3 TO 15
  42.         REDIM pts$(0)
  43.         Split poly$(n), ",", pts$()
  44.         PSET (VAL(pts$(0)), VAL(pts$(1))), c(n)
  45.         FOR i = 2 TO UBOUND(pts$) STEP 2
  46.             x1 = VAL(pts$(i)): y1 = VAL(pts$((i + 1)))
  47.             LINE -(x1, y1), c(n)
  48.         NEXT
  49.         target = node MOD n: lastNode = target - 1
  50.         IF lastNode < 0 THEN lastNode = n - 1
  51.         x1 = VAL(pts$(2 * lastNode)): y1 = VAL(pts$(2 * lastNode + 1))
  52.         x2 = VAL(pts$(2 * target)): y2 = VAL(pts$(2 * target + 1))
  53.         midx = x1 + (x2 - x1) * frac / 10: midy = y1 + (y2 - y1) * frac / 10
  54.         fcirc midx, midy, 9, c(n)
  55.     NEXT
  56.  
  57. SUB Split (SplitMeString AS STRING, delim AS STRING, loadMeArray() AS STRING)
  58.     DIM curpos AS LONG, arrpos AS LONG, LD AS LONG, dpos AS LONG 'fix use the Lbound the array already has
  59.     curpos = 1: arrpos = LBOUND(loadMeArray): LD = LEN(delim)
  60.     dpos = INSTR(curpos, SplitMeString, delim)
  61.     DO UNTIL dpos = 0
  62.         loadMeArray(arrpos) = MID$(SplitMeString, curpos, dpos - curpos)
  63.         arrpos = arrpos + 1
  64.         IF arrpos > UBOUND(loadMeArray) THEN REDIM _PRESERVE loadMeArray(LBOUND(loadMeArray) TO UBOUND(loadMeArray) + 1000) AS STRING
  65.         curpos = dpos + LD
  66.         dpos = INSTR(curpos, SplitMeString, delim)
  67.     LOOP
  68.     loadMeArray(arrpos) = MID$(SplitMeString, curpos)
  69.     REDIM _PRESERVE loadMeArray(LBOUND(loadMeArray) TO arrpos) AS STRING 'get the ubound correct
  70.  
  71. SUB fcirc (CX AS INTEGER, CY AS INTEGER, R AS INTEGER, C AS _UNSIGNED LONG)
  72.     DIM Radius AS INTEGER, RadiusError AS INTEGER
  73.     DIM X AS INTEGER, Y AS INTEGER
  74.     Radius = ABS(R): RadiusError = -Radius: X = Radius: Y = 0
  75.     IF Radius = 0 THEN PSET (CX, CY), C: EXIT SUB
  76.     LINE (CX - X, CY)-(CX + X, CY), C, BF
  77.     WHILE X > Y
  78.         RadiusError = RadiusError + Y * 2 + 1
  79.         IF RadiusError >= 0 THEN
  80.             IF X <> Y + 1 THEN
  81.                 LINE (CX - Y, CY - X)-(CX + Y, CY - X), C, BF
  82.                 LINE (CX - Y, CY + X)-(CX + Y, CY + X), C, BF
  83.             END IF
  84.             X = X - 1
  85.             RadiusError = RadiusError - X * 2
  86.         END IF
  87.         Y = Y + 1
  88.         LINE (CX - X, CY - Y)-(CX + X, CY - Y), C, BF
  89.         LINE (CX - X, CY + Y)-(CX + X, CY + Y), C, BF
  90.     WEND
  91.  

And do you know why?

WE are going down each line segment at the same rate, stop the motion at any time and every dot is the same distance between the nodes:
 
Polygon Orbit.PNG
 

But that's not how the code from the link is drawing the disks, stop the motion there and the disks are anywhere along each line segment between nodes:
 
OK these disc aren't at the same place on the line segments.PNG


We've been lied to my friends, the title in the link says the dots move at the same speed. They don't! Just watch the outside dot and the next one in and compare their speeds going round.

So... how do we change our code to have the disks move in the way to form the cool patterns that are found in the link?
« Last Edit: February 25, 2020, 09:00:38 pm by bplus »

FellippeHeitor

  • Guest
Re: Hypnotic polygon orbits
« Reply #8 on: February 25, 2020, 08:58:23 pm »
Lol, great investigative work, bplus. Kudos for the xtra attention to detail!

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Hypnotic polygon orbits
« Reply #9 on: February 25, 2020, 09:01:42 pm »
Thanks Fellippe, but now I want that cool pattern maker found in the link. ;-)

FellippeHeitor

  • Guest
Re: Hypnotic polygon orbits
« Reply #10 on: February 25, 2020, 09:03:44 pm »
Something tells me you’re not one to rest until it looks closer...

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Hypnotic polygon orbits
« Reply #11 on: February 25, 2020, 09:19:27 pm »
Well it shouldn't take more than the rest of the night, maybe less?


Update:
Ha! I am just now reading the comments,

Quote
Well there's definitely something fucky going on with the gif to make it look like this.

I got 27729 nodes before complete alignment again at the start line pointing down. But then I recounted the number of concentric polygons, oh 13 not 10, I had to insert 3 more rings and find 3 more colors, that's when I switched color systems from $color:32 names to hexadecimal, easier to make rainbow set. So 13 X 27720 = 360,360 nodes to cross before alignment as it starts what this guy calculates in first comment posted there.

All those comments were great!

« Last Edit: February 25, 2020, 09:37:40 pm by bplus »

FellippeHeitor

  • Guest
Re: Hypnotic polygon orbits
« Reply #12 on: February 25, 2020, 09:26:47 pm »
❤️

Offline bplus

  • Global Moderator
  • Forum Resident
  • Posts: 8053
  • b = b + ...
    • View Profile
Re: Hypnotic polygon orbits
« Reply #13 on: February 25, 2020, 11:04:53 pm »
Look familiar?
Code: QB64: [Select]
  1. _TITLE "Orbit Patterns" 'b+ started 2020-02-25
  2. 'can we find speeds for disks going in  orbits around center st they form patterns
  3.  
  4. CONST xmax = 700, ymax = 700, center = 350, P1 = _PI, P2 = P1 * 2, PD2 = P1 * .5
  5. SCREEN _NEWIMAGE(xmax, ymax, 32)
  6. _SCREENMOVE 300, 20
  7. DIM rate(1 TO 20)
  8. FOR i = 1 TO 20
  9.     rate(i) = (21 - i) / 12
  10. WHILE _KEYDOWN(27) = 0
  11.     CLS
  12.     FOR r = 10 TO 200 STEP 10
  13.         i = INT(r / 10)
  14.         x = center + r * COS(rate(i) * a)
  15.         y = center + r * SIN(rate(i) * a)
  16.         CIRCLE (x, y), 5
  17.     NEXT
  18.     a = a + _PI(2 / 120)
  19.     _DISPLAY
  20.     _LIMIT 30
  21.  
  22.  

Offline STxAxTIC

  • Library Staff
  • Forum Resident
  • Posts: 1091
  • he lives
    • View Profile
Re: Hypnotic polygon orbits
« Reply #14 on: February 25, 2020, 11:32:19 pm »
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?
You're not done when it works, you're done when it's right.