QB64.org Forum

Active Forums => Programs => Topic started by: FellippeHeitor on February 25, 2020, 09:19:22 am

Title: Hypnotic polygon orbits
Post by: FellippeHeitor 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/ (https://www.reddit.com/r/gifs/comments/f91c99/every_addtional_shape_adds_one_more_corner_and/)


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.  
Title: Re: Hypnotic polygon orbits
Post by: Ashish 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.  
Title: Re: Hypnotic polygon orbits
Post by: bplus 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.
Title: Re: Hypnotic polygon orbits
Post by: FellippeHeitor 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.
Title: Re: Hypnotic polygon orbits
Post by: bplus 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.
Title: Re: Hypnotic polygon orbits
Post by: bplus 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.  
Title: Re: Hypnotic polygon orbits
Post by: bplus 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.  
Title: Re: Hypnotic polygon orbits
Post by: bplus 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:
 
 

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:
 


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?
Title: Re: Hypnotic polygon orbits
Post by: FellippeHeitor on February 25, 2020, 08:58:23 pm
Lol, great investigative work, bplus. Kudos for the xtra attention to detail!
Title: Re: Hypnotic polygon orbits
Post by: bplus on February 25, 2020, 09:01:42 pm
Thanks Fellippe, but now I want that cool pattern maker found in the link. ;-)
Title: Re: Hypnotic polygon orbits
Post by: FellippeHeitor on February 25, 2020, 09:03:44 pm
Something tells me you’re not one to rest until it looks closer...
Title: Re: Hypnotic polygon orbits
Post by: bplus 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!

Title: Re: Hypnotic polygon orbits
Post by: FellippeHeitor on February 25, 2020, 09:26:47 pm
❤️
Title: Re: Hypnotic polygon orbits
Post by: bplus 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.  
Title: Re: Hypnotic polygon orbits
Post by: STxAxTIC 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?
Title: Re: Hypnotic polygon orbits
Post by: TerryRitchie 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.
Title: Re: Hypnotic polygon orbits
Post by: bplus 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.  

 

Title: Re: Hypnotic polygon orbits
Post by: johnno56 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.
Title: Re: Hypnotic polygon orbits
Post by: FellippeHeitor on February 26, 2020, 02:38:34 am
Gorgeous result, bplus! So harmonious.
Title: Re: Hypnotic polygon orbits
Post by: Ashish on February 26, 2020, 03:24:48 am
awesome bplus!
Title: Re: Hypnotic polygon orbits
Post by: Ashish 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.  
Title: Re: Hypnotic polygon orbits
Post by: Bolee 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.