QB64.org Forum

Active Forums => Programs => Topic started by: Ashish on April 28, 2020, 07:42:44 am

Title: Space Filling with Polygons
Post by: Ashish on April 28, 2020, 07:42:44 am
Hey everyone!

This program fills the space with a polygon (triangles, squares, etc) in such a way that any two polygon must not overlap/collide.
The polygon size gradually reduces and it try to fill as much space as possible.
The color of polygon also changes gradually, resulting in a beautiful pattern. :)

I took some help for concepts behind this from here - http://paulbourke.net/fractals/randomtile/

Run the program & Enjoy.

Instruction :  Enter the number of sides of the polygon you want to fill with (of course, it must greater than 2). Higher values will result
in slow speed. :)

Code: QB64: [Select]
  1. 'Space Filling with Polygon
  2. 'By Ashish
  3.  
  4. TYPE XY
  5.     x AS SINGLE
  6.     y AS SINGLE
  7.  
  8. _TITLE "Space Filling with Polygon"
  9. SCREEN _NEWIMAGE(800, 600, 32)
  10.  
  11. INPUT "Enter the number of side for a polygon (must be greater than 2) : ", x%
  12. IF x% < 3 THEN PRINT "It must be greate than 2!, taking default value of 3. Hit ENTER.": SLEEP: x% = 3
  13. polySides = x%
  14. DIM tempPoly1(polySides - 1) AS XY, tempPoly2(polySides - 1) AS XY
  15. REDIM polys(polySides - 1) AS XY
  16.  
  17.  
  18. init = 0
  19. poly_index = 0
  20. i = 1
  21. c = 1.1
  22. failed = 0
  23.     IF init = 0 THEN
  24.         r = p5random(150, 200)
  25.         ox = p5random(r, _WIDTH - r)
  26.         oy = p5random(r, _HEIGHT - r)
  27.         offAng = p5random(-_PI, _PI)
  28.         FOR j = 0 TO polySides - 1
  29.             polys(j).x = ox + COS(j * (_PI(2 / polySides)) + offAng) * r
  30.             polys(j).y = oy + SIN(j * (_PI(2 / polySides)) + offAng) * r
  31.         NEXT
  32.         clr~& = midColor(_RGB(255, 255, 0), _RGB(255, 100, 0), map(r, 200, 3, 0, 1))
  33.         drawPoly polys(), clr~&
  34.         init = 1
  35.         poly_index = poly_index + polySides
  36.     ELSE
  37.         r = 200 / (c ^ i)
  38.         ox = p5random(r, _WIDTH - r)
  39.         oy = p5random(r, _HEIGHT - r)
  40.         collided = 0
  41.         offAng = p5random(-_PI, _PI)
  42.         FOR j = 0 TO polySides - 1
  43.             tempPoly1(j).x = ox + COS(j * (_PI(2 / polySides)) + offAng) * r
  44.             tempPoly1(j).y = oy + SIN(j * (_PI(2 / polySides)) + offAng) * r
  45.         NEXT
  46.         FOR j = 0 TO UBOUND(polys) STEP polySides
  47.             FOR k = j TO j + polySides - 1
  48.                 tempPoly2(k - j) = polys(k)
  49.             NEXT
  50.             IF polyCollide(tempPoly1(), tempPoly2()) THEN collided = -1: EXIT FOR
  51.         NEXT
  52.         IF NOT collided THEN
  53.             ' _echo "yes"
  54.             REDIM _PRESERVE polys(UBOUND(polys) + polySides) AS XY
  55.             FOR j = poly_index TO poly_index + polySides - 1
  56.                 polys(j) = tempPoly1(j - poly_index)
  57.             NEXT
  58.             clr~& = midColor(_RGB(255, 255, 0), _RGB(255, 100, 0), map(r, 200, 3, 0, 1))
  59.             drawPoly tempPoly1(), clr~&
  60.             poly_index = poly_index + polySides
  61.         ELSE
  62.             failed = failed + 1
  63.             IF failed > (i * 60) THEN i = i + 1: failed = 0
  64.         END IF
  65.     END IF
  66. LOOP UNTIL r < 3
  67.  
  68. FUNCTION midColor~& (clr1 AS _UNSIGNED LONG, clr2 AS _UNSIGNED LONG, v)
  69.     midColor~& = _RGB(map(v, 0, 1, _RED(clr1), _RED(clr2)), map(v, 0, 1, _GREEN(clr1), _GREEN(clr2)), map(v, 0, 1, _BLUE(clr1), _BLUE(clr2)))
  70.  
  71. SUB drawPoly (vert() AS XY, clr AS _UNSIGNED LONG)
  72.     n = UBOUND(vert)
  73.     DIM cx, cy
  74.     FOR i = 0 TO n
  75.         LINE (vert(i).x, vert(i).y)-(vert((i + 1) MOD (n + 1)).x, vert((i + 1) MOD (n + 1)).y), clr
  76.         cx = cx + vert(i).x: cy = cy + vert(i).y
  77.     NEXT
  78.     cx = cx / (n + 1): cy = cy / (n + 1)
  79.     PAINT (cx, cy), clr, clr
  80.  
  81.  
  82. FUNCTION polyCollide (vert1() AS XY, vert2() AS XY)
  83.     DIM n1 AS INTEGER, n2 AS INTEGER
  84.     n1 = UBOUND(vert1): n2 = UBOUND(vert2)
  85.     'checking if any point of polygon 1 inside polygon 2
  86.     FOR i = 0 TO n1
  87.         IF pointInsidePoly(vert1(i), vert2()) THEN polyCollide = -1: EXIT FUNCTION
  88.     NEXT
  89.     'checking if any point of polygon 2 inside polygon 1
  90.     FOR i = 0 TO n2
  91.         IF pointInsidePoly(vert2(i), vert1()) THEN polyCollide = -1: EXIT FUNCTION
  92.     NEXT
  93.     ' checking the edge intersection
  94.     FOR i = 0 TO n1
  95.         FOR j = 0 TO n2
  96.             IF lineIntersect(vert1(i).x, vert1(i).y, vert1((i + 1) MOD (n1 + 1)).x, vert1((i + 1) MOD (n1 + 1)).y, vert2(j).x, vert2(j).y, vert2((j + 1) MOD (n2 + 1)).x, vert2((j + 1) MOD (n2 + 1)).y) THEN polyCollide = -1: EXIT FUNCTION
  97.         NEXT
  98.     NEXT
  99.  
  100. 'from paulbourke.net
  101. FUNCTION pointInsidePoly (p AS XY, polyVert() AS XY)
  102.     DIM ax1, ax2, ay1, ay2
  103.     n = UBOUND(polyVert)
  104.     FOR i = 0 TO n
  105.         ax1 = polyVert(i).x - p.x
  106.         ay1 = polyVert(i).y - p.y
  107.         ax2 = polyVert((i + 1) MOD (n + 1)).x - p.x
  108.         ay2 = polyVert((i + 1) MOD (n + 1)).y - p.y
  109.         ang = ang + angle2D(ax1, ay1, ax2, ay2)
  110.     NEXT
  111.     pointInsidePoly = (ABS(ang) >= _PI)
  112.  
  113. 'from paulbourke.net
  114. FUNCTION angle2D (x1, y1, x2, y2)
  115.     DIM theta1, theta2, ftheta
  116.     theta1 = _ATAN2(y1, x1)
  117.     theta2 = _ATAN2(y2, x2)
  118.     ftheta = theta1 - theta2
  119.     WHILE ftheta > _PI: ftheta = ftheta - _PI(2): WEND
  120.     WHILE ftheta < -_PI: ftheta = ftheta + _PI(2): WEND
  121.     angle2D = ftheta
  122.  
  123. FUNCTION lineIntersect (__x1, __y1, __x2, __y2, __x3, __y3, __x4, __y4)
  124.     DIM x1 AS INTEGER, y1 AS INTEGER, x2 AS INTEGER, y2 AS INTEGER, x3 AS INTEGER, y3 AS INTEGER, x4 AS INTEGER, y4 AS INTEGER
  125.     DIM a1, b1, c1, a2, b2, c2
  126.     DIM a1b2_minus_a2b1, b1c2_minus_b2c1, a2c1_minus_a1c2
  127.     DIM inter_x AS INTEGER, inter_y AS INTEGER
  128.  
  129.     x1 = __x1: x2 = __x2: x3 = __x3: x4 = __x4
  130.     y1 = __y1: y2 = __y2: y3 = __y3: y4 = __y4
  131.    
  132.     IF x1 > x2 THEN SWAP x1, x2
  133.     IF x3 > x4 THEN SWAP x3, x4
  134.     IF y1 > y2 THEN SWAP y1, y2
  135.     IF y3 > y4 THEN SWAP y3, y4
  136.    
  137.     a1 = __y2 - __y1: b1 = -(__x2 - __x1): c1 = (__x2 * __y1) - (__x1 * __y2)
  138.     a2 = __y4 - __y3: b2 = -(__x4 - __x3): c2 = (__x4 * __y3) - (__x3 * __y4)
  139.  
  140.     'check if lines are perfectly vertical or horizontal
  141.     IF a1 = 0 AND a2 = 0 THEN lineIntersect = (__y1 = __y3): _DEST 0: EXIT FUNCTION
  142.     IF b1 = 0 AND b2 = 0 THEN lineIntersect = (__x1 = __x3): _DEST 0: EXIT FUNCTION
  143.     IF a2 = 0 OR b2 = 0 THEN GOTO skip_component_ratio
  144.    
  145.     'check if the whole line segments coincide with each other.
  146.     IF c2 <> 0 THEN
  147.         IF (a1 / a2) = (b1 / b2) AND (b1 / b2) = (c1 / c2) THEN
  148.             lineIntersect = -1: EXIT FUNCTION
  149.         END IF
  150.     END IF
  151.     skip_component_ratio:
  152.     'check if the line segments have same slope.
  153.     IF a1 * b2 = a2 * b1 THEN
  154.         lineIntersect = (c1 = c2) 'special case, when they still coincide (as c1=c2)
  155.         EXIT FUNCTION
  156.     END IF
  157.     'check if the line do intersect between the segments.
  158.     a1b2_minus_a2b1 = (a1 * b2) - (a2 * b1): b1c2_minus_b2c1 = (b1 * c2) - (b2 * c1): a2c1_minus_a1c2 = (a2 * c1) - (a1 * c2)
  159.     inter_x = b1c2_minus_b2c1 / a1b2_minus_a2b1: inter_y = a2c1_minus_a1c2 / a1b2_minus_a2b1
  160.    
  161.     lineIntersect = ((inter_x >= x1 AND inter_x <= x2 AND inter_y >= y1 AND inter_y <= y2)) and ((inter_x >= x3 AND inter_x <= x4 AND inter_y >= y3 AND inter_y <= y4))
  162.  
  163. 'taken from p5js.bas
  164. FUNCTION map! (value!, minRange!, maxRange!, newMinRange!, newMaxRange!)
  165.     map! = ((value! - minRange!) / (maxRange! - minRange!)) * (newMaxRange! - newMinRange!) + newMinRange!
  166.  
  167. FUNCTION p5random! (mn!, mx!)
  168.     IF mn! > mx! THEN
  169.         SWAP mn!, mx!
  170.     END IF
  171.     p5random! = RND * (mx! - mn!) + mn!
  172.  


 [ This attachment cannot be displayed inline in 'Print Page' view ]  
Program output for the input value of 3, i.e. for a triangle.
Title: Re: Space Filling with Polygons
Post by: Dav on April 28, 2020, 09:11:42 am
Nice one, Ashish!

- Dav
Title: Re: Space Filling with Polygons
Post by: FellippeHeitor on April 28, 2020, 09:18:35 am
Doritos!
Title: Re: Space Filling with Polygons
Post by: TerryRitchie on April 28, 2020, 11:19:32 am
Nacho cheese, please.
Title: Re: Space Filling with Polygons
Post by: bplus on April 28, 2020, 12:22:06 pm
Nice one!

I remember doing circle fills with images awhile back. That was a Coding Challenge or Coding Train session with that crazy YouTube guy, Daniel Shiffman.
Title: Re: Space Filling with Polygons
Post by: TempodiBasic on April 28, 2020, 07:33:03 pm
Hi Ashish
what fine colors in this geometric application!
Cool!  [ This attachment cannot be displayed inline in 'Print Page' view ]  
Title: Re: Space Filling with Polygons
Post by: Ashish on April 28, 2020, 11:24:04 pm
@Dav @FellippeHeitor  @TerryRitchie @bplus @TempodiBasic
Thank you for trying this!

Ok, here is a new MOD. Now, it draws the polygon with shaded effect. To get variation, you can change value of polygonSides.

Code: QB64: [Select]
  1. 'Space Filling with Polygon
  2. 'By Ashish
  3.  
  4. TYPE gl_vertex_type
  5.     'position of vertex
  6.     x AS SINGLE
  7.     y AS SINGLE
  8.     'center
  9.     cx AS SINGLE
  10.     cy AS SINGLE
  11.     'color of the vertex to be used
  12.     r AS SINGLE
  13.     g AS SINGLE
  14.     b AS SINGLE
  15.  
  16. _TITLE "Space Filling with Polygon [MOD:SHADED SHAPE]"
  17. SCREEN _NEWIMAGE(800, 600, 32)
  18.  
  19. DIM SHARED init, polySides
  20. 'warning : polySides must always be greater than 2
  21. polySides = 3 'change its value to get different polygons
  22. DIM tempPoly1(polySides - 1) AS gl_vertex_type, tempPoly2(polySides - 1) AS gl_vertex_type
  23. REDIM SHARED polys(polySides - 1) AS gl_vertex_type
  24.  
  25.  
  26. init = 0
  27. poly_index = 0
  28. i = 1
  29. c = 1.05
  30. failed = 0
  31.     IF init = 0 THEN
  32.         r = p5random(150, 200)
  33.         ox = p5random(r, _WIDTH - r)
  34.         oy = p5random(r, _HEIGHT - r)
  35.         offAng = p5random(-_PI, _PI)
  36.         clr~& = midColor(_RGB(255, 255, 0), _RGB(255, 100, 0), map(r, 200, 3, 0, 1))
  37.         red = map(_RED(clr~&), 0, 255, 0, 1): green = map(_GREEN(clr~&), 0, 255, 0, 1): blue = map(_BLUE(clr~&), 0, 255, 0, 1)
  38.         FOR j = 0 TO polySides - 1
  39.             polys(j).x = ox + COS(j * (_PI(2 / polySides)) + offAng) * r
  40.             polys(j).y = oy + SIN(j * (_PI(2 / polySides)) + offAng) * r
  41.             polys(j).cx = ox: polys(j).cy = oy
  42.             polys(j).r = red: polys(j).g = green: polys(j).b = blue
  43.         NEXT
  44.         init = -1
  45.         poly_index = poly_index + polySides
  46.     ELSE
  47.         r = 200 / (c ^ i)
  48.         ox = p5random(r, _WIDTH - r)
  49.         oy = p5random(r, _HEIGHT - r)
  50.         collided = 0
  51.         offAng = p5random(-_PI, _PI)
  52.         FOR j = 0 TO polySides - 1
  53.             tempPoly1(j).x = ox + COS(j * (_PI(2 / polySides)) + offAng) * r
  54.             tempPoly1(j).y = oy + SIN(j * (_PI(2 / polySides)) + offAng) * r
  55.         NEXT
  56.         FOR j = 0 TO UBOUND(polys) STEP polySides
  57.             FOR k = j TO j + polySides - 1
  58.                 tempPoly2(k - j) = polys(k)
  59.             NEXT
  60.             IF polyCollide(tempPoly1(), tempPoly2()) THEN collided = -1: EXIT FOR
  61.         NEXT
  62.         IF NOT collided THEN
  63.             REDIM _PRESERVE polys(UBOUND(polys) + polySides) AS gl_vertex_type
  64.             clr~& = midColor(_RGB(255, 255, 0), _RGB(255, 100, 0), map(r, 200, 3, 0, 1))
  65.             red = map(_RED(clr~&), 0, 255, 0, 1): green = map(_GREEN(clr~&), 0, 255, 0, 1): blue = map(_BLUE(clr~&), 0, 255, 0, 1)
  66.             FOR j = poly_index TO poly_index + polySides - 1
  67.                 polys(j) = tempPoly1(j - poly_index)
  68.                 polys(j).cx = ox: polys(j).cy = oy
  69.                 polys(j).r = red: polys(j).g = green: polys(j).b = blue
  70.             NEXT
  71.             poly_index = poly_index + polySides
  72.         ELSE
  73.             failed = failed + 1
  74.             IF failed > (i * 60) THEN i = i + 1: failed = 0
  75.         END IF
  76.     END IF
  77. LOOP UNTIL r < 3
  78.  
  79.  
  80. SUB _GL ()
  81.     IF NOT init THEN EXIT SUB
  82.     _glMatrixMode _GL_MODELVIEW
  83.  
  84.     'set the gl screen so that it can work normal screen coordinates
  85.     _glTranslatef -1, 1, 0
  86.     _glScalef 1 / 400, -1 / 300, 1
  87.      
  88.     'to get shaded effect, we will divide polygon into smaller triangles from center of polygon in a cyclic way.
  89.     FOR n = 0 TO UBOUND(polys) STEP polySides
  90.         _glPushMatrix
  91.         _glTranslatef polys(n).cx, polys(n).cy, 0
  92.         _glBegin _GL_TRIANGLES
  93.         FOR j = n TO n + polySides - 1
  94.             _glColor3f 0, 0, 0
  95.             _glVertex2i 0, 0
  96.             _glColor3f polys(n).r, polys(n).g, polys(n).b
  97.             _glVertex2i polys(j).x - polys(n).cx, polys(j).y - polys(j).cy
  98.             IF (j + 1) MOD (n + polySides) = 0 THEN _glVertex2i polys(n).x - polys(n).cx, polys(n).y - polys(j).cy ELSE _glVertex2i polys(j + 1).x - polys(n).cx, polys(j + 1).y - polys(j).cy
  99.         NEXT
  100.         _glEnd
  101.         _glPopMatrix
  102.     NEXT
  103.  
  104. FUNCTION midColor~& (clr1 AS _UNSIGNED LONG, clr2 AS _UNSIGNED LONG, v)
  105.     midColor~& = _RGB(map(v, 0, 1, _RED(clr1), _RED(clr2)), map(v, 0, 1, _GREEN(clr1), _GREEN(clr2)), map(v, 0, 1, _BLUE(clr1), _BLUE(clr2)))
  106.  
  107. FUNCTION polyCollide (vert1() AS gl_vertex_type, vert2() AS gl_vertex_type)
  108.     DIM n1 AS INTEGER, n2 AS INTEGER
  109.     n1 = UBOUND(vert1): n2 = UBOUND(vert2)
  110.     'checking if any point of polygon 1 inside polygon 2
  111.     FOR i = 0 TO n1
  112.         IF pointInsidePoly(vert1(i), vert2()) THEN polyCollide = -1: EXIT FUNCTION
  113.     NEXT
  114.     'checking if any point of polygon 2 inside polygon 1
  115.     FOR i = 0 TO n2
  116.         IF pointInsidePoly(vert2(i), vert1()) THEN polyCollide = -1: EXIT FUNCTION
  117.     NEXT
  118.     ' checking the edge intersection
  119.     FOR i = 0 TO n1
  120.         FOR j = 0 TO n2
  121.             IF lineIntersect(vert1(i).x, vert1(i).y, vert1((i + 1) MOD (n1 + 1)).x, vert1((i + 1) MOD (n1 + 1)).y, vert2(j).x, vert2(j).y, vert2((j + 1) MOD (n2 + 1)).x, vert2((j + 1) MOD (n2 + 1)).y) THEN polyCollide = -1: EXIT FUNCTION
  122.         NEXT
  123.     NEXT
  124.  
  125. 'from paulbourke.net
  126. FUNCTION pointInsidePoly (p AS gl_vertex_type, polyVert() AS gl_vertex_type)
  127.     DIM ax1, ax2, ay1, ay2
  128.     n = UBOUND(polyVert)
  129.     FOR i = 0 TO n
  130.         ax1 = polyVert(i).x - p.x
  131.         ay1 = polyVert(i).y - p.y
  132.         ax2 = polyVert((i + 1) MOD (n + 1)).x - p.x
  133.         ay2 = polyVert((i + 1) MOD (n + 1)).y - p.y
  134.         ang = ang + angle2D(ax1, ay1, ax2, ay2)
  135.     NEXT
  136.     pointInsidePoly = (ABS(ang) >= _PI)
  137.  
  138. 'from paulbourke.net
  139. FUNCTION angle2D (x1, y1, x2, y2)
  140.     DIM theta1, theta2, ftheta
  141.     theta1 = _ATAN2(y1, x1)
  142.     theta2 = _ATAN2(y2, x2)
  143.     ftheta = theta1 - theta2
  144.     WHILE ftheta > _PI: ftheta = ftheta - _PI(2): WEND
  145.     WHILE ftheta < -_PI: ftheta = ftheta + _PI(2): WEND
  146.     angle2D = ftheta
  147.  
  148. FUNCTION lineIntersect (__x1, __y1, __x2, __y2, __x3, __y3, __x4, __y4)
  149.     DIM x1 AS INTEGER, y1 AS INTEGER, x2 AS INTEGER, y2 AS INTEGER, x3 AS INTEGER, y3 AS INTEGER, x4 AS INTEGER, y4 AS INTEGER
  150.     DIM a1, b1, c1, a2, b2, c2
  151.     DIM a1b2_minus_a2b1, b1c2_minus_b2c1, a2c1_minus_a1c2
  152.     DIM inter_x AS INTEGER, inter_y AS INTEGER
  153.  
  154.     x1 = __x1: x2 = __x2: x3 = __x3: x4 = __x4
  155.     y1 = __y1: y2 = __y2: y3 = __y3: y4 = __y4
  156.    
  157.     IF x1 > x2 THEN SWAP x1, x2
  158.     IF x3 > x4 THEN SWAP x3, x4
  159.     IF y1 > y2 THEN SWAP y1, y2
  160.     IF y3 > y4 THEN SWAP y3, y4
  161.    
  162.     a1 = __y2 - __y1: b1 = -(__x2 - __x1): c1 = (__x2 * __y1) - (__x1 * __y2)
  163.     a2 = __y4 - __y3: b2 = -(__x4 - __x3): c2 = (__x4 * __y3) - (__x3 * __y4)
  164.  
  165.     'check if lines are perfectly vertical or horizontal
  166.     IF a1 = 0 AND a2 = 0 THEN lineIntersect = (__y1 = __y3): _DEST 0: EXIT FUNCTION
  167.     IF b1 = 0 AND b2 = 0 THEN lineIntersect = (__x1 = __x3): _DEST 0: EXIT FUNCTION
  168.     IF a2 = 0 OR b2 = 0 THEN GOTO skip_component_ratio
  169.    
  170.     'check if the whole line segments coincide with each other.
  171.     IF c2 <> 0 THEN
  172.         IF (a1 / a2) = (b1 / b2) AND (b1 / b2) = (c1 / c2) THEN
  173.             lineIntersect = -1: EXIT FUNCTION
  174.         END IF
  175.     END IF
  176.     skip_component_ratio:
  177.     'check if the line segments have same slope.
  178.     IF a1 * b2 = a2 * b1 THEN
  179.         lineIntersect = (c1 = c2) 'special case, when they still coincide (as c1=c2)
  180.         EXIT FUNCTION
  181.     END IF
  182.     'check if the line do intersect between the segments.
  183.     a1b2_minus_a2b1 = (a1 * b2) - (a2 * b1): b1c2_minus_b2c1 = (b1 * c2) - (b2 * c1): a2c1_minus_a1c2 = (a2 * c1) - (a1 * c2)
  184.     inter_x = b1c2_minus_b2c1 / a1b2_minus_a2b1: inter_y = a2c1_minus_a1c2 / a1b2_minus_a2b1
  185.    
  186.     lineIntersect = ((inter_x >= x1 AND inter_x <= x2 AND inter_y >= y1 AND inter_y <= y2)) AND ((inter_x >= x3 AND inter_x <= x4 AND inter_y >= y3 AND inter_y <= y4))
  187.  
  188. 'taken from p5js.bas
  189. FUNCTION map! (value!, minRange!, maxRange!, newMinRange!, newMaxRange!)
  190.     map! = ((value! - minRange!) / (maxRange! - minRange!)) * (newMaxRange! - newMinRange!) + newMinRange!
  191.  
  192. FUNCTION p5random! (mn!, mx!)
  193.     IF mn! > mx! THEN
  194.         SWAP mn!, mx!
  195.     END IF
  196.     p5random! = RND * (mx! - mn!) + mn!
  197.  


 [ This attachment cannot be displayed inline in 'Print Page' view ]  
Title: Re: Space Filling with Polygons
Post by: bplus on April 29, 2020, 11:43:03 am
Cool!

@Ashish, if you try squares maybe you could put images in them? Wouldn't that make things interesting?
Title: Re: Space Filling with Polygons
Post by: Pete on April 29, 2020, 04:48:29 pm
Doritos!

@Fell: Speak English!

@ Ashish: Yep, it's all that, and a bag of chips, but I tried the latest code, and all I got was the bag of chips.. all shaded triangles, not shaded pentagons. What? Edit: Oh, I see, I found the place you mentioned to change the number of sides. Cool!

Pete
Title: Re: Space Filling with Polygons
Post by: bplus on April 29, 2020, 08:50:54 pm
Hey a little mod :)
Code: QB64: [Select]
  1. 'Space Filling with Polygon
  2. 'By Ashish
  3. 'b+ copy and mod 2020-04-29   https://www.qb64.org/forum/index.php?topic=2515.msg117572#msg117572
  4. TYPE XY
  5.     x AS SINGLE
  6.     y AS SINGLE
  7.  
  8. _TITLE "Space Filling with Polygon"
  9. SCREEN _NEWIMAGE(800, 600, 32)
  10. _DELAY .25
  11. 'INPUT "Enter the number of side for a polygon (must be greater than 2) : ", x%
  12. 'IF x% < 3 THEN PRINT "It must be greate than 2!, taking default value of 3. Hit ENTER.": SLEEP: x% = 3
  13.  
  14.  
  15. ' b+ loads an image and takes some measurements
  16. ih& = _LOADIMAGE("Templar.png")
  17. IF ih& = -1 THEN PRINT "Sorry image did not load.": SLEEP: END
  18. DIM SHARED wi, hi
  19. wi = _WIDTH(ih&): hi = _HEIGHT(ih&)
  20.  
  21. polySides = 4
  22. DIM tempPoly1(polySides - 1) AS XY, tempPoly2(polySides - 1) AS XY
  23. REDIM polys(polySides - 1) AS XY
  24.  
  25. init = 0
  26. poly_index = 0
  27. i = 1
  28. c = 1.1
  29. failed = 0
  30. FOR y = 0 TO 600
  31.     midInk 0, 0, 255, 255, 255, 0, y / 600
  32.     LINE (0, y)-(800, y)
  33.     IF init = 0 THEN
  34.         r = p5random(150, 200)
  35.         ox = p5random(r, _WIDTH - r)
  36.         oy = p5random(r, _HEIGHT - r)
  37.         offAng = p5random(-_PI, _PI)
  38.         FOR j = 0 TO polySides - 1
  39.             polys(j).x = ox + COS(j * (_PI(2 / polySides)) + offAng) * r
  40.             polys(j).y = oy + SIN(j * (_PI(2 / polySides)) + offAng) * r
  41.         NEXT
  42.         clr~& = midColor(_RGB(255, 255, 0), _RGB(255, 100, 0), map(r, 200, 3, 0, 1))
  43.         drawPoly polys(), clr~&
  44.         init = 1
  45.         poly_index = poly_index + polySides
  46.     ELSE
  47.         r = 200 / (c ^ i)
  48.         ox = p5random(r, _WIDTH - r)
  49.         oy = p5random(r, _HEIGHT - r)
  50.         collided = 0
  51.         offAng = p5random(-_PI, _PI)
  52.         FOR j = 0 TO polySides - 1
  53.             tempPoly1(j).x = ox + COS(j * (_PI(2 / polySides)) + offAng) * r
  54.             tempPoly1(j).y = oy + SIN(j * (_PI(2 / polySides)) + offAng) * r
  55.         NEXT
  56.         FOR j = 0 TO UBOUND(polys) STEP polySides
  57.             FOR k = j TO j + polySides - 1
  58.                 tempPoly2(k - j) = polys(k)
  59.             NEXT
  60.             IF polyCollide(tempPoly1(), tempPoly2()) THEN collided = -1: EXIT FOR
  61.         NEXT
  62.         IF NOT collided THEN
  63.             ' _echo "yes"
  64.             REDIM _PRESERVE polys(UBOUND(polys) + polySides) AS XY
  65.             FOR j = poly_index TO poly_index + polySides - 1
  66.                 polys(j) = tempPoly1(j - poly_index)
  67.             NEXT
  68.             clr~& = midColor(_RGB(255, 255, 0), _RGB(255, 100, 0), map(r, 200, 3, 0, 1))
  69.             drawPoly tempPoly1(), clr~&
  70.             poly_index = poly_index + polySides
  71.         ELSE
  72.             failed = failed + 1
  73.             IF failed > (i * 60) THEN i = i + 1: failed = 0
  74.         END IF
  75.     END IF
  76. LOOP UNTIL r < 1
  77.  
  78. FUNCTION midColor~& (clr1 AS _UNSIGNED LONG, clr2 AS _UNSIGNED LONG, v)
  79.     midColor~& = _RGB(map(v, 0, 1, _RED(clr1), _RED(clr2)), map(v, 0, 1, _GREEN(clr1), _GREEN(clr2)), map(v, 0, 1, _BLUE(clr1), _BLUE(clr2)))
  80.  
  81. SUB drawPoly (vert() AS XY, clr AS _UNSIGNED LONG)
  82.     'n = UBOUND(vert)
  83.     'DIM cx, cy
  84.     'FOR i = 0 TO n
  85.     '    LINE (vert(i).x, vert(i).y)-(vert((i + 1) MOD (n + 1)).x, vert((i + 1) MOD (n + 1)).y), clr
  86.     '    cx = cx + vert(i).x: cy = cy + vert(i).y
  87.     'NEXT
  88.     'cx = cx / (n + 1): cy = cy / (n + 1)
  89.     'PAINT (cx, cy), clr, clr
  90.  
  91.     cx = (vert(0).x + vert(2).x) / 2 'find the center, radius and tilt
  92.     cy = (vert(0).y + vert(2).y) / 2
  93.     r = SQR(2) * _HYPOT(cx - vert(0).x, cy - vert(0).y) 'mult bty SQR(2) locating sq top left corner from
  94.     a = _ATAN2(vert(0).y - cy, vert(0).x - cx) - _PI / 4 'subtract 45 degrees because square is off by that
  95.     RotoZoom3 cx, cy, ih&, r / wi, r / hi, a
  96.  
  97.  
  98. FUNCTION polyCollide (vert1() AS XY, vert2() AS XY)
  99.     DIM n1 AS INTEGER, n2 AS INTEGER
  100.     n1 = UBOUND(vert1): n2 = UBOUND(vert2)
  101.     'checking if any point of polygon 1 inside polygon 2
  102.     FOR i = 0 TO n1
  103.         IF pointInsidePoly(vert1(i), vert2()) THEN polyCollide = -1: EXIT FUNCTION
  104.     NEXT
  105.     'checking if any point of polygon 2 inside polygon 1
  106.     FOR i = 0 TO n2
  107.         IF pointInsidePoly(vert2(i), vert1()) THEN polyCollide = -1: EXIT FUNCTION
  108.     NEXT
  109.     ' checking the edge intersection
  110.     FOR i = 0 TO n1
  111.         FOR j = 0 TO n2
  112.             IF lineIntersect(vert1(i).x, vert1(i).y, vert1((i + 1) MOD (n1 + 1)).x, vert1((i + 1) MOD (n1 + 1)).y, vert2(j).x, vert2(j).y, vert2((j + 1) MOD (n2 + 1)).x, vert2((j + 1) MOD (n2 + 1)).y) THEN polyCollide = -1: EXIT FUNCTION
  113.         NEXT
  114.     NEXT
  115.  
  116. 'from paulbourke.net
  117. FUNCTION pointInsidePoly (p AS XY, polyVert() AS XY)
  118.     DIM ax1, ax2, ay1, ay2
  119.     n = UBOUND(polyVert)
  120.     FOR i = 0 TO n
  121.         ax1 = polyVert(i).x - p.x
  122.         ay1 = polyVert(i).y - p.y
  123.         ax2 = polyVert((i + 1) MOD (n + 1)).x - p.x
  124.         ay2 = polyVert((i + 1) MOD (n + 1)).y - p.y
  125.         ang = ang + angle2D(ax1, ay1, ax2, ay2)
  126.     NEXT
  127.     pointInsidePoly = (ABS(ang) >= _PI)
  128.  
  129. 'from paulbourke.net
  130. FUNCTION angle2D (x1, y1, x2, y2)
  131.     DIM theta1, theta2, ftheta
  132.     theta1 = _ATAN2(y1, x1)
  133.     theta2 = _ATAN2(y2, x2)
  134.     ftheta = theta1 - theta2
  135.     WHILE ftheta > _PI: ftheta = ftheta - _PI(2): WEND
  136.     WHILE ftheta < -_PI: ftheta = ftheta + _PI(2): WEND
  137.     angle2D = ftheta
  138.  
  139. FUNCTION lineIntersect (__x1, __y1, __x2, __y2, __x3, __y3, __x4, __y4)
  140.     DIM x1 AS INTEGER, y1 AS INTEGER, x2 AS INTEGER, y2 AS INTEGER, x3 AS INTEGER, y3 AS INTEGER, x4 AS INTEGER, y4 AS INTEGER
  141.     DIM a1, b1, c1, a2, b2, c2
  142.     DIM a1b2_minus_a2b1, b1c2_minus_b2c1, a2c1_minus_a1c2
  143.     DIM inter_x AS INTEGER, inter_y AS INTEGER
  144.  
  145.     x1 = __x1: x2 = __x2: x3 = __x3: x4 = __x4
  146.     y1 = __y1: y2 = __y2: y3 = __y3: y4 = __y4
  147.  
  148.     IF x1 > x2 THEN SWAP x1, x2
  149.     IF x3 > x4 THEN SWAP x3, x4
  150.     IF y1 > y2 THEN SWAP y1, y2
  151.     IF y3 > y4 THEN SWAP y3, y4
  152.  
  153.     a1 = __y2 - __y1: b1 = -(__x2 - __x1): c1 = (__x2 * __y1) - (__x1 * __y2)
  154.     a2 = __y4 - __y3: b2 = -(__x4 - __x3): c2 = (__x4 * __y3) - (__x3 * __y4)
  155.  
  156.     'check if lines are perfectly vertical or horizontal
  157.     IF a1 = 0 AND a2 = 0 THEN lineIntersect = (__y1 = __y3): _DEST 0: EXIT FUNCTION
  158.     IF b1 = 0 AND b2 = 0 THEN lineIntersect = (__x1 = __x3): _DEST 0: EXIT FUNCTION
  159.     IF a2 = 0 OR b2 = 0 THEN GOTO skip_component_ratio
  160.  
  161.     'check if the whole line segments coincide with each other.
  162.     IF c2 <> 0 THEN
  163.         IF (a1 / a2) = (b1 / b2) AND (b1 / b2) = (c1 / c2) THEN
  164.             lineIntersect = -1: EXIT FUNCTION
  165.         END IF
  166.     END IF
  167.     skip_component_ratio:
  168.     'check if the line segments have same slope.
  169.     IF a1 * b2 = a2 * b1 THEN
  170.         lineIntersect = (c1 = c2) 'special case, when they still coincide (as c1=c2)
  171.         EXIT FUNCTION
  172.     END IF
  173.     'check if the line do intersect between the segments.
  174.     a1b2_minus_a2b1 = (a1 * b2) - (a2 * b1): b1c2_minus_b2c1 = (b1 * c2) - (b2 * c1): a2c1_minus_a1c2 = (a2 * c1) - (a1 * c2)
  175.     inter_x = b1c2_minus_b2c1 / a1b2_minus_a2b1: inter_y = a2c1_minus_a1c2 / a1b2_minus_a2b1
  176.  
  177.     lineIntersect = ((inter_x >= x1 AND inter_x <= x2 AND inter_y >= y1 AND inter_y <= y2)) AND ((inter_x >= x3 AND inter_x <= x4 AND inter_y >= y3 AND inter_y <= y4))
  178.  
  179. 'taken from p5js.bas
  180. FUNCTION map! (value!, minRange!, maxRange!, newMinRange!, newMaxRange!)
  181.     map! = ((value! - minRange!) / (maxRange! - minRange!)) * (newMaxRange! - newMinRange!) + newMinRange!
  182.  
  183. FUNCTION p5random! (mn!, mx!)
  184.     IF mn! > mx! THEN
  185.         SWAP mn!, mx!
  186.     END IF
  187.     p5random! = RND * (mx! - mn!) + mn!
  188.  
  189. ' b+ added some helpers =====================================================================================
  190.  
  191. SUB RotoZoom3 (X AS LONG, Y AS LONG, Image AS LONG, xScale AS SINGLE, yScale AS SINGLE, radianRotation AS SINGLE) ' 0 at end means no scaling of x or y
  192.     DIM px(3) AS SINGLE: DIM py(3) AS SINGLE
  193.     DIM W&, H&, sinr!, cosr!, i&, x2&, y2&
  194.     W& = _WIDTH(Image&): H& = _HEIGHT(Image&)
  195.     px(0) = -W& / 2: py(0) = -H& / 2: px(1) = -W& / 2: py(1) = H& / 2
  196.     px(2) = W& / 2: py(2) = H& / 2: px(3) = W& / 2: py(3) = -H& / 2
  197.     sinr! = SIN(-radianRotation): cosr! = COS(-radianRotation)
  198.     FOR i& = 0 TO 3
  199.         x2& = xScale * (px(i&) * cosr! + sinr! * py(i&)) + X: y2& = yScale * (py(i&) * cosr! - px(i&) * sinr!) + Y
  200.         px(i&) = x2&: py(i&) = y2&
  201.     NEXT
  202.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, H& - 1)-(W& - 1, H& - 1), Image TO(px(0), py(0))-(px(1), py(1))-(px(2), py(2))
  203.     _MAPTRIANGLE _SEAMLESS(0, 0)-(W& - 1, 0)-(W& - 1, H& - 1), Image TO(px(0), py(0))-(px(3), py(3))-(px(2), py(2))
  204.  
  205. SUB midInk (r1%, g1%, b1%, r2%, g2%, b2%, fr##)
  206.     COLOR _RGB32(r1% + (r2% - r1%) * fr##, g1% + (g2% - g1%) * fr##, b1% + (b2% - b1%) * fr##)
  207.  
  208.  

 


and zip with bas, exe and png
Title: Re: Space Filling with Polygons
Post by: bplus on April 29, 2020, 09:55:32 pm
Here I try swapping color with the image:

Code: QB64: [Select]
  1. 'Space Filling with Polygon
  2. 'By Ashish
  3. 'b+ copy and mod 2020-04-29   https://www.qb64.org/forum/index.php?topic=2515.msg117572#msg117572
  4. 'b+ mod 2 color changing
  5. TYPE XY
  6.     x AS SINGLE
  7.     y AS SINGLE
  8.  
  9. _TITLE "Space Filling with Polygon"
  10. SCREEN _NEWIMAGE(800, 600, 32)
  11. _DELAY .25
  12. 'INPUT "Enter the number of side for a polygon (must be greater than 2) : ", x%
  13. 'IF x% < 3 THEN PRINT "It must be greate than 2!, taking default value of 3. Hit ENTER.": SLEEP: x% = 3
  14.  
  15.  
  16. ' b+ loads an image and takes some measurements
  17. ih& = _LOADIMAGE("Templar.png")
  18. IF ih& = -1 THEN PRINT "Sorry image did not load.": SLEEP: END
  19. DIM SHARED wi, hi
  20. wi = _WIDTH(ih&): hi = _HEIGHT(ih&)
  21. DIM SHARED rStart, origClr AS _UNSIGNED LONG
  22. 'what is it's color
  23.  
  24. _PUTIMAGE , ih&, 0
  25. origClr = POINT(10, 300)
  26. PRINT origClr
  27. 'END
  28.  
  29.  
  30. polySides = 4
  31. DIM tempPoly1(polySides - 1) AS XY, tempPoly2(polySides - 1) AS XY
  32. REDIM polys(polySides - 1) AS XY
  33.  
  34. init = 0
  35. poly_index = 0
  36. i = 1
  37. c = 1.1
  38. failed = 0
  39. FOR y = 0 TO 600
  40.     LINE (0, y)-(800, y), midInk(0, 0, 255, 255, 255, 0, y / 600)
  41.     IF init = 0 THEN
  42.         r = p5random(150, 200)
  43.         rStart = r
  44.         ox = p5random(r, _WIDTH - r)
  45.         oy = p5random(r, _HEIGHT - r)
  46.         offAng = p5random(-_PI, _PI)
  47.         FOR j = 0 TO polySides - 1
  48.             polys(j).x = ox + COS(j * (_PI(2 / polySides)) + offAng) * r
  49.             polys(j).y = oy + SIN(j * (_PI(2 / polySides)) + offAng) * r
  50.         NEXT
  51.         'clr~& = midColor(_RGB(255, 255, 0), _RGB(255, 100, 0), map(r, 200, 3, 0, 1))
  52.         drawPoly polys(), midInk~&(0, 128, 0, 255, 0, 255, (rStart - r) / rStart)
  53.         init = 1
  54.         poly_index = poly_index + polySides
  55.     ELSE
  56.         r = 200 / (c ^ i)
  57.         ox = p5random(r, _WIDTH - r)
  58.         oy = p5random(r, _HEIGHT - r)
  59.         collided = 0
  60.         offAng = p5random(-_PI, _PI)
  61.         FOR j = 0 TO polySides - 1
  62.             tempPoly1(j).x = ox + COS(j * (_PI(2 / polySides)) + offAng) * r
  63.             tempPoly1(j).y = oy + SIN(j * (_PI(2 / polySides)) + offAng) * r
  64.         NEXT
  65.         FOR j = 0 TO UBOUND(polys) STEP polySides
  66.             FOR k = j TO j + polySides - 1
  67.                 tempPoly2(k - j) = polys(k)
  68.             NEXT
  69.             IF polyCollide(tempPoly1(), tempPoly2()) THEN collided = -1: EXIT FOR
  70.         NEXT
  71.         IF NOT collided THEN
  72.             ' _echo "yes"
  73.             REDIM _PRESERVE polys(UBOUND(polys) + polySides) AS XY
  74.             FOR j = poly_index TO poly_index + polySides - 1
  75.                 polys(j) = tempPoly1(j - poly_index)
  76.             NEXT
  77.             clr~& = midColor(_RGB(255, 255, 0), _RGB(255, 100, 0), map(r, 200, 3, 0, 1))
  78.             drawPoly tempPoly1(), midInk~&(0, 128, 0, 255, 0, 255, (rStart - r) / rStart)
  79.             poly_index = poly_index + polySides
  80.         ELSE
  81.             failed = failed + 1
  82.             IF failed > (i * 60) THEN i = i + 1: failed = 0
  83.         END IF
  84.     END IF
  85. LOOP UNTIL r < 4
  86.  
  87. FUNCTION midColor~& (clr1 AS _UNSIGNED LONG, clr2 AS _UNSIGNED LONG, v)
  88.     midColor~& = _RGB(map(v, 0, 1, _RED(clr1), _RED(clr2)), map(v, 0, 1, _GREEN(clr1), _GREEN(clr2)), map(v, 0, 1, _BLUE(clr1), _BLUE(clr2)))
  89.  
  90. SUB drawPoly (vert() AS XY, clr AS _UNSIGNED LONG)
  91.     'n = UBOUND(vert)
  92.     'DIM cx, cy
  93.     'FOR i = 0 TO n
  94.     '    LINE (vert(i).x, vert(i).y)-(vert((i + 1) MOD (n + 1)).x, vert((i + 1) MOD (n + 1)).y), clr
  95.     '    cx = cx + vert(i).x: cy = cy + vert(i).y
  96.     'NEXT
  97.     'cx = cx / (n + 1): cy = cy / (n + 1)
  98.     'PAINT (cx, cy), clr, clr
  99.  
  100.     cx = (vert(0).x + vert(2).x) / 2 'find the center, radius and tilt
  101.     cy = (vert(0).y + vert(2).y) / 2
  102.     r = SQR(2) * _HYPOT(cx - vert(0).x, cy - vert(0).y) 'mult bty SQR(2) locating sq top left corner from
  103.     a = _ATAN2(vert(0).y - cy, vert(0).x - cx) - _PI / 4 'subtract 45 degrees because square is off by that
  104.     new& = swapColor&(ih&, origClr, clr)
  105.     RotoZoom3 cx, cy, new&, r / wi, r / hi, a
  106.     _FREEIMAGE new&
  107.  
  108.  
  109. FUNCTION polyCollide (vert1() AS XY, vert2() AS XY)
  110.     DIM n1 AS INTEGER, n2 AS INTEGER
  111.     n1 = UBOUND(vert1): n2 = UBOUND(vert2)
  112.     'checking if any point of polygon 1 inside polygon 2
  113.     FOR i = 0 TO n1
  114.         IF pointInsidePoly(vert1(i), vert2()) THEN polyCollide = -1: EXIT FUNCTION
  115.     NEXT
  116.     'checking if any point of polygon 2 inside polygon 1
  117.     FOR i = 0 TO n2
  118.         IF pointInsidePoly(vert2(i), vert1()) THEN polyCollide = -1: EXIT FUNCTION
  119.     NEXT
  120.     ' checking the edge intersection
  121.     FOR i = 0 TO n1
  122.         FOR j = 0 TO n2
  123.             IF lineIntersect(vert1(i).x, vert1(i).y, vert1((i + 1) MOD (n1 + 1)).x, vert1((i + 1) MOD (n1 + 1)).y, vert2(j).x, vert2(j).y, vert2((j + 1) MOD (n2 + 1)).x, vert2((j + 1) MOD (n2 + 1)).y) THEN polyCollide = -1: EXIT FUNCTION
  124.         NEXT
  125.     NEXT
  126.  
  127. 'from paulbourke.net
  128. FUNCTION pointInsidePoly (p AS XY, polyVert() AS XY)
  129.     DIM ax1, ax2, ay1, ay2
  130.     n = UBOUND(polyVert)
  131.     FOR i = 0 TO n
  132.         ax1 = polyVert(i).x - p.x
  133.         ay1 = polyVert(i).y - p.y
  134.         ax2 = polyVert((i + 1) MOD (n + 1)).x - p.x
  135.         ay2 = polyVert((i + 1) MOD (n + 1)).y - p.y
  136.         ang = ang + angle2D(ax1, ay1, ax2, ay2)
  137.     NEXT
  138.     pointInsidePoly = (ABS(ang) >= _PI)
  139.  
  140. 'from paulbourke.net
  141. FUNCTION angle2D (x1, y1, x2, y2)
  142.     DIM theta1, theta2, ftheta
  143.     theta1 = _ATAN2(y1, x1)
  144.     theta2 = _ATAN2(y2, x2)
  145.     ftheta = theta1 - theta2
  146.     WHILE ftheta > _PI: ftheta = ftheta - _PI(2): WEND
  147.     WHILE ftheta < -_PI: ftheta = ftheta + _PI(2): WEND
  148.     angle2D = ftheta
  149.  
  150. FUNCTION lineIntersect (__x1, __y1, __x2, __y2, __x3, __y3, __x4, __y4)
  151.     DIM x1 AS INTEGER, y1 AS INTEGER, x2 AS INTEGER, y2 AS INTEGER, x3 AS INTEGER, y3 AS INTEGER, x4 AS INTEGER, y4 AS INTEGER
  152.     DIM a1, b1, c1, a2, b2, c2
  153.     DIM a1b2_minus_a2b1, b1c2_minus_b2c1, a2c1_minus_a1c2
  154.     DIM inter_x AS INTEGER, inter_y AS INTEGER
  155.  
  156.     x1 = __x1: x2 = __x2: x3 = __x3: x4 = __x4
  157.     y1 = __y1: y2 = __y2: y3 = __y3: y4 = __y4
  158.  
  159.     IF x1 > x2 THEN SWAP x1, x2
  160.     IF x3 > x4 THEN SWAP x3, x4
  161.     IF y1 > y2 THEN SWAP y1, y2
  162.     IF y3 > y4 THEN SWAP y3, y4
  163.  
  164.     a1 = __y2 - __y1: b1 = -(__x2 - __x1): c1 = (__x2 * __y1) - (__x1 * __y2)
  165.     a2 = __y4 - __y3: b2 = -(__x4 - __x3): c2 = (__x4 * __y3) - (__x3 * __y4)
  166.  
  167.     'check if lines are perfectly vertical or horizontal
  168.     IF a1 = 0 AND a2 = 0 THEN lineIntersect = (__y1 = __y3): _DEST 0: EXIT FUNCTION
  169.     IF b1 = 0 AND b2 = 0 THEN lineIntersect = (__x1 = __x3): _DEST 0: EXIT FUNCTION
  170.     IF a2 = 0 OR b2 = 0 THEN GOTO skip_component_ratio
  171.  
  172.     'check if the whole line segments coincide with each other.
  173.     IF c2 <> 0 THEN
  174.         IF (a1 / a2) = (b1 / b2) AND (b1 / b2) = (c1 / c2) THEN
  175.             lineIntersect = -1: EXIT FUNCTION
  176.         END IF
  177.     END IF
  178.     skip_component_ratio:
  179.     'check if the line segments have same slope.
  180.     IF a1 * b2 = a2 * b1 THEN
  181.         lineIntersect = (c1 = c2) 'special case, when they still coincide (as c1=c2)
  182.         EXIT FUNCTION
  183.     END IF
  184.     'check if the line do intersect between the segments.
  185.     a1b2_minus_a2b1 = (a1 * b2) - (a2 * b1): b1c2_minus_b2c1 = (b1 * c2) - (b2 * c1): a2c1_minus_a1c2 = (a2 * c1) - (a1 * c2)
  186.     inter_x = b1c2_minus_b2c1 / a1b2_minus_a2b1: inter_y = a2c1_minus_a1c2 / a1b2_minus_a2b1
  187.  
  188.     lineIntersect = ((inter_x >= x1 AND inter_x <= x2 AND inter_y >= y1 AND inter_y <= y2)) AND ((inter_x >= x3 AND inter_x <= x4 AND inter_y >= y3 AND inter_y <= y4))
  189.  
  190. 'taken from p5js.bas
  191. FUNCTION map! (value!, minRange!, maxRange!, newMinRange!, newMaxRange!)
  192.     map! = ((value! - minRange!) / (maxRange! - minRange!)) * (newMaxRange! - newMinRange!) + newMinRange!
  193.  
  194. FUNCTION p5random! (mn!, mx!)
  195.     IF mn! > mx! THEN
  196.         SWAP mn!, mx!
  197.     END IF
  198.     p5random! = RND * (mx! - mn!) + mn!
  199.  
  200. ' b+ added some helpers =====================================================================================
  201.  
  202. SUB RotoZoom3 (X AS LONG, Y AS LONG, Image AS LONG, xScale AS SINGLE, yScale AS SINGLE, radianRotation AS SINGLE) ' 0 at end means no scaling of x or y
  203.     DIM px(3) AS SINGLE: DIM py(3) AS SINGLE
  204.     DIM W&, H&, sinr!, cosr!, i&, x2&, y2&
  205.     W& = _WIDTH(Image&): H& = _HEIGHT(Image&)
  206.     px(0) = -W& / 2: py(0) = -H& / 2: px(1) = -W& / 2: py(1) = H& / 2
  207.     px(2) = W& / 2: py(2) = H& / 2: px(3) = W& / 2: py(3) = -H& / 2
  208.     sinr! = SIN(-radianRotation): cosr! = COS(-radianRotation)
  209.     FOR i& = 0 TO 3
  210.         x2& = xScale * (px(i&) * cosr! + sinr! * py(i&)) + X: y2& = yScale * (py(i&) * cosr! - px(i&) * sinr!) + Y
  211.         px(i&) = x2&: py(i&) = y2&
  212.     NEXT
  213.     _MAPTRIANGLE _SEAMLESS(0, 0)-(0, H& - 1)-(W& - 1, H& - 1), Image TO(px(0), py(0))-(px(1), py(1))-(px(2), py(2))
  214.     _MAPTRIANGLE _SEAMLESS(0, 0)-(W& - 1, 0)-(W& - 1, H& - 1), Image TO(px(0), py(0))-(px(3), py(3))-(px(2), py(2))
  215.  
  216. FUNCTION midInk~& (r1%, g1%, b1%, r2%, g2%, b2%, fr##)
  217.     midInk~& = _RGB32(r1% + (r2% - r1%) * fr##, g1% + (g2% - g1%) * fr##, b1% + (b2% - b1%) * fr##)
  218.  
  219. ' create new Image Handle for an image copy with a color changed from original image, returns new Handle&
  220. 'https://www.qb64.org/forum/index.php?topic=2451.0
  221. ' from Petr to Craz1000
  222. FUNCTION swapColor& (oldHandle&, oldcolor~&, newcolor~&)
  223.     DIM m AS _MEM, c AS _UNSIGNED LONG
  224.     swapColor& = _COPYIMAGE(oldHandle&, 32)
  225.     m = _MEMIMAGE(swapColor)
  226.     DO UNTIL a& = m.SIZE - 4
  227.         a& = a& + 4
  228.         c~& = _MEMGET(m, m.OFFSET + a&, _UNSIGNED LONG)
  229.         IF c~& = oldcolor~& THEN _MEMPUT m, m.OFFSET + a&, newcolor~&
  230.     LOOP
  231.     _MEMFREE m
  232.  
  233.  

Same png as in zip above.
Title: Re: Space Filling with Polygons
Post by: Ashish on April 30, 2020, 08:41:14 am
@bplus
Cool! I liked your MOD!
Title: Re: Space Filling with Polygons
Post by: bplus on April 30, 2020, 11:40:56 am
@Ashish

And I like this demo because you are getting in closer with the polygons than you could with circles with the polygons drawn within. ie could almost do same thing with a circle fill and then embed any regular poly within the circles but they could not get as close as they do here, some side by side.
Title: Re: Space Filling with Polygons
Post by: Ashish on April 30, 2020, 12:14:43 pm
@bplus
Yeah, thanks for giving the idea
Here we gooo...!!

Code: QB64: [Select]
  1. 'Space Filling with Polygon
  2. 'By Ashish
  3. 'MOD : RESTRICTED AREA
  4. 'circle is situated at the center of the screen
  5.  
  6. TYPE gl_vertex_type
  7.     'position of vertex
  8.     x AS SINGLE
  9.     y AS SINGLE
  10.     'center
  11.     cx AS SINGLE
  12.     cy AS SINGLE
  13.     'color of the vertex to be used
  14.     r AS SINGLE
  15.     g AS SINGLE
  16.     b AS SINGLE
  17.  
  18. _TITLE "Space Filling with Polygon [MOD:RESTRICTED AREA]"
  19. SCREEN _NEWIMAGE(800, 600, 32)
  20.  
  21. DIM SHARED init, polySides
  22. 'warning : polySides must always be greater than 2
  23. polySides = 3 'change its value to get different polygons
  24. DIM tempPoly1(polySides - 1) AS gl_vertex_type, tempPoly2(polySides - 1) AS gl_vertex_type
  25. REDIM SHARED polys(polySides - 1) AS gl_vertex_type
  26.  
  27.  
  28. init = 0
  29. poly_index = 0
  30. i = 1
  31. c = 1.05
  32. failed = 0
  33.         search_new_place:
  34.     IF init = 0 THEN
  35.         r = p5random(100, 150)
  36.         ox = p5random(r, _WIDTH - r)
  37.         oy = p5random(r, _HEIGHT - r)
  38.         offAng = p5random(-_PI, _PI)
  39.         clr~& = midColor(_RGB(255, 255, 0), _RGB(255, 100, 0), map(r, 150, 3, 0, 1))
  40.         red = map(_RED(clr~&), 0, 255, 0, 1): green = map(_GREEN(clr~&), 0, 255, 0, 1): blue = map(_BLUE(clr~&), 0, 255, 0, 1)
  41.         FOR j = 0 TO polySides - 1
  42.             polys(j).x = ox+COS(j * (_PI(2 / polySides)) + offAng) * r
  43.             polys(j).y = oy+SIN(j * (_PI(2 / polySides)) + offAng) * r
  44.                         if not insideCircle(polys(j),400,300,300) then  goto search_new_place
  45.                        
  46.             polys(j).cx = ox: polys(j).cy = oy
  47.             polys(j).r = red: polys(j).g = green: polys(j).b = blue
  48.         NEXT
  49.         init = -1
  50.         poly_index = poly_index + polySides
  51.     ELSE
  52.         r = 120 / (c ^ i)
  53.         ox = p5random(r, _WIDTH - r)
  54.         oy = p5random(r, _HEIGHT - r)
  55.         collided = 0
  56.         offAng = p5random(-_PI, _PI)
  57.         FOR j = 0 TO polySides - 1
  58.             tempPoly1(j).x = ox + COS(j * (_PI(2 / polySides)) + offAng) * r
  59.             tempPoly1(j).y = oy + SIN(j * (_PI(2 / polySides)) + offAng) * r
  60.                         if not insideCircle(tempPoly1(j),400,300,300) then goto search_new_place
  61.         NEXT
  62.         FOR j = 0 TO UBOUND(polys) STEP polySides
  63.             FOR k = j TO j + polySides - 1
  64.                 tempPoly2(k - j) = polys(k)
  65.             NEXT
  66.             IF polyCollide(tempPoly1(), tempPoly2()) THEN collided = -1: EXIT FOR
  67.         NEXT
  68.         IF NOT collided THEN
  69.             REDIM _PRESERVE polys(UBOUND(polys) + polySides) AS gl_vertex_type
  70.             clr~& = midColor(_RGB(255, 255, 0), _RGB(255, 100, 0), map(r, 120, 3, 0, 1))
  71.             red = map(_RED(clr~&), 0, 255, 0, 1): green = map(_GREEN(clr~&), 0, 255, 0, 1): blue = map(_BLUE(clr~&), 0, 255, 0, 1)
  72.             FOR j = poly_index TO poly_index + polySides - 1
  73.                 polys(j) = tempPoly1(j - poly_index)
  74.                 polys(j).cx = ox: polys(j).cy = oy
  75.                 polys(j).r = red: polys(j).g = green: polys(j).b = blue
  76.             NEXT
  77.             poly_index = poly_index + polySides
  78.         ELSE
  79.             failed = failed + 1
  80.             IF failed > (i * 60) THEN i = i + 1: failed = 0
  81.         END IF
  82.     END IF
  83. LOOP UNTIL r < 3
  84.  
  85.  
  86. SUB _GL ()
  87.     IF NOT init THEN EXIT SUB
  88.         _glEnable _GL_TEXTURE_2D
  89.     _glMatrixMode _GL_MODELVIEW
  90.  
  91.     'set the gl screen so that it can work normal screen coordinates
  92.     _glTranslatef -1, 1, 0
  93.     _glScalef 1 / 400, -1 / 300, 1
  94.      
  95.     'to get shaded effect, we will divide polygon into smaller triangles from center of polygon in a cyclic way.
  96.     FOR n = 0 TO UBOUND(polys) STEP polySides
  97.         _glPushMatrix
  98.         _glTranslatef polys(n).cx, polys(n).cy, 0
  99.         _glBegin _GL_TRIANGLES
  100.         FOR j = n TO n + polySides - 1
  101.             _glColor3f 0, 0, 0
  102.             _glVertex2i 0, 0
  103.             _glColor3f polys(n).r, polys(n).g, polys(n).b
  104.             _glVertex2i polys(j).x - polys(n).cx, polys(j).y - polys(j).cy
  105.             IF (j + 1) MOD (n + polySides) = 0 THEN _glVertex2i polys(n).x - polys(n).cx, polys(n).y - polys(j).cy ELSE _glVertex2i polys(j + 1).x - polys(n).cx, polys(j + 1).y - polys(j).cy
  106.         NEXT
  107.         _glEnd
  108.         _glPopMatrix
  109.     NEXT
  110.  
  111. function insideCircle (p as gl_vertex_type, cx, cy, rad)
  112.     insideCircle = (sqr((cx-p.x)^2+(cy-p.y)^2)<=rad)
  113.  
  114. FUNCTION midColor~& (clr1 AS _UNSIGNED LONG, clr2 AS _UNSIGNED LONG, v)
  115.     midColor~& = _RGB(map(v, 0, 1, _RED(clr1), _RED(clr2)), map(v, 0, 1, _GREEN(clr1), _GREEN(clr2)), map(v, 0, 1, _BLUE(clr1), _BLUE(clr2)))
  116.  
  117. FUNCTION polyCollide (vert1() AS gl_vertex_type, vert2() AS gl_vertex_type)
  118.     DIM n1 AS INTEGER, n2 AS INTEGER
  119.     n1 = UBOUND(vert1): n2 = UBOUND(vert2)
  120.     'checking if any point of polygon 1 inside polygon 2
  121.     FOR i = 0 TO n1
  122.         IF pointInsidePoly(vert1(i), vert2()) THEN polyCollide = -1: EXIT FUNCTION
  123.     NEXT
  124.     'checking if any point of polygon 2 inside polygon 1
  125.     FOR i = 0 TO n2
  126.         IF pointInsidePoly(vert2(i), vert1()) THEN polyCollide = -1: EXIT FUNCTION
  127.     NEXT
  128.     ' checking the edge intersection
  129.     FOR i = 0 TO n1
  130.         FOR j = 0 TO n2
  131.             IF lineIntersect(vert1(i).x, vert1(i).y, vert1((i + 1) MOD (n1 + 1)).x, vert1((i + 1) MOD (n1 + 1)).y, vert2(j).x, vert2(j).y, vert2((j + 1) MOD (n2 + 1)).x, vert2((j + 1) MOD (n2 + 1)).y) THEN polyCollide = -1: EXIT FUNCTION
  132.         NEXT
  133.     NEXT
  134.  
  135. 'from paulbourke.net
  136. FUNCTION pointInsidePoly (p AS gl_vertex_type, polyVert() AS gl_vertex_type)
  137.     DIM ax1, ax2, ay1, ay2
  138.     n = UBOUND(polyVert)
  139.     FOR i = 0 TO n
  140.         ax1 = polyVert(i).x - p.x
  141.         ay1 = polyVert(i).y - p.y
  142.         ax2 = polyVert((i + 1) MOD (n + 1)).x - p.x
  143.         ay2 = polyVert((i + 1) MOD (n + 1)).y - p.y
  144.         ang = ang + angle2D(ax1, ay1, ax2, ay2)
  145.     NEXT
  146.     pointInsidePoly = (ABS(ang) >= _PI)
  147.  
  148. 'from paulbourke.net
  149. FUNCTION angle2D (x1, y1, x2, y2)
  150.     DIM theta1, theta2, ftheta
  151.     theta1 = _ATAN2(y1, x1)
  152.     theta2 = _ATAN2(y2, x2)
  153.     ftheta = theta1 - theta2
  154.     WHILE ftheta > _PI: ftheta = ftheta - _PI(2): WEND
  155.     WHILE ftheta < -_PI: ftheta = ftheta + _PI(2): WEND
  156.     angle2D = ftheta
  157.  
  158. FUNCTION lineIntersect (__x1, __y1, __x2, __y2, __x3, __y3, __x4, __y4)
  159.     DIM x1 AS INTEGER, y1 AS INTEGER, x2 AS INTEGER, y2 AS INTEGER, x3 AS INTEGER, y3 AS INTEGER, x4 AS INTEGER, y4 AS INTEGER
  160.     DIM a1, b1, c1, a2, b2, c2
  161.     DIM a1b2_minus_a2b1, b1c2_minus_b2c1, a2c1_minus_a1c2
  162.     DIM inter_x AS INTEGER, inter_y AS INTEGER
  163.  
  164.     x1 = __x1: x2 = __x2: x3 = __x3: x4 = __x4
  165.     y1 = __y1: y2 = __y2: y3 = __y3: y4 = __y4
  166.    
  167.     IF x1 > x2 THEN SWAP x1, x2
  168.     IF x3 > x4 THEN SWAP x3, x4
  169.     IF y1 > y2 THEN SWAP y1, y2
  170.     IF y3 > y4 THEN SWAP y3, y4
  171.    
  172.     a1 = __y2 - __y1: b1 = -(__x2 - __x1): c1 = (__x2 * __y1) - (__x1 * __y2)
  173.     a2 = __y4 - __y3: b2 = -(__x4 - __x3): c2 = (__x4 * __y3) - (__x3 * __y4)
  174.  
  175.     'check if lines are perfectly vertical or horizontal
  176.     IF a1 = 0 AND a2 = 0 THEN lineIntersect = (__y1 = __y3): _DEST 0: EXIT FUNCTION
  177.     IF b1 = 0 AND b2 = 0 THEN lineIntersect = (__x1 = __x3): _DEST 0: EXIT FUNCTION
  178.     IF a2 = 0 OR b2 = 0 THEN GOTO skip_component_ratio
  179.    
  180.     'check if the whole line segments coincide with each other.
  181.     IF c2 <> 0 THEN
  182.         IF (a1 / a2) = (b1 / b2) AND (b1 / b2) = (c1 / c2) THEN
  183.             lineIntersect = -1: EXIT FUNCTION
  184.         END IF
  185.     END IF
  186.     skip_component_ratio:
  187.     'check if the line segments have same slope.
  188.     IF a1 * b2 = a2 * b1 THEN
  189.         lineIntersect = (c1 = c2) 'special case, when they still coincide (as c1=c2)
  190.         EXIT FUNCTION
  191.     END IF
  192.     'check if the line do intersect between the segments.
  193.     a1b2_minus_a2b1 = (a1 * b2) - (a2 * b1): b1c2_minus_b2c1 = (b1 * c2) - (b2 * c1): a2c1_minus_a1c2 = (a2 * c1) - (a1 * c2)
  194.     inter_x = b1c2_minus_b2c1 / a1b2_minus_a2b1: inter_y = a2c1_minus_a1c2 / a1b2_minus_a2b1
  195.    
  196.     lineIntersect = ((inter_x >= x1 AND inter_x <= x2 AND inter_y >= y1 AND inter_y <= y2)) AND ((inter_x >= x3 AND inter_x <= x4 AND inter_y >= y3 AND inter_y <= y4))
  197.  
  198. 'taken from p5js.bas
  199. FUNCTION map! (value!, minRange!, maxRange!, newMinRange!, newMaxRange!)
  200.     map! = ((value! - minRange!) / (maxRange! - minRange!)) * (newMaxRange! - newMinRange!) + newMinRange!
  201.  
  202. FUNCTION p5random! (mn!, mx!)
  203.     IF mn! > mx! THEN
  204.         SWAP mn!, mx!
  205.     END IF
  206.     p5random! = RND * (mx! - mn!) + mn!
  207.  



  [ This attachment cannot be displayed inline in 'Print Page' view ]  
Title: Re: Space Filling with Polygons
Post by: bplus on April 30, 2020, 12:34:20 pm
@Ashish,

Cool! but can you use this very code (with slight mod) to fill a big triangle with triangles and maybe squares pentagons, hexagons.... but at least triangles?
Title: Re: Space Filling with Polygons
Post by: Ashish on May 01, 2020, 12:23:26 am
@Ashish,

Cool! but can you use this very code (with slight mod) to fill a big triangle with triangles and maybe squares pentagons, hexagons.... but at least triangles?
Oh.. So this is what you mean @bplus . Ok
Here new MOD. Now, you need to specify the shape in which you are going to do space filling and then you have to specify the shape
which is to be used for filling the area.
That is, you can now have triangles inside Pentagon, or Squares in inside triangles, etc.

Code: QB64: [Select]
  1. 'Space Filling with Polygon
  2. 'By Ashish
  3. 'MOD : RESTRICTED AREA
  4.  
  5. TYPE XY
  6.     x AS SINGLE
  7.     y AS SINGLE
  8.  
  9. _TITLE "Space Filling with Polygon [MOD : RESTRICTED AREA]"
  10. SCREEN _NEWIMAGE(800, 700, 32)
  11.  
  12. INPUT "Enter the number of side for polygon in which SPACE FILLING has to be done : ", a%
  13. IF a% < 3 THEN PRINT "It must be greate than 2!, taking default value of 3. Hit ENTER.": SLEEP: a% = 3
  14. INPUT "Enter the number of side for a polygon to fill in (must be greater than 2) : ", x%
  15. IF x% < 3 THEN PRINT "It must be greate than 2!, taking default value of 3. Hit ENTER.": SLEEP: x% = 3
  16. polySides = x%
  17. DIM tempPoly1(polySides - 1) AS XY, tempPoly2(polySides - 1) AS XY
  18. REDIM polys(polySides - 1) AS XY
  19.  
  20. Dim ShapeArea(a% - 1) as XY
  21. for j = 0 to ubound(ShapeArea)
  22.         ShapeArea(j).x = 400 + COS(j * (_PI(2 / a%))) * 350
  23.     ShapeArea(j).y = 350 + SIN(j * (_PI(2 / a%))) * 350
  24. ' drawPoly ShapeArea(), _RGB(255,255,255)
  25. init = 0
  26. poly_index = 0
  27. i = 1
  28. c = 1.1
  29. failed = 0
  30.         start:
  31.     IF init = 0 THEN
  32.         r = p5random(150, 200)
  33.         ox = p5random(r, _WIDTH - r)
  34.         oy = p5random(r, _HEIGHT - r)
  35.         offAng = p5random(-_PI, _PI)
  36.         FOR j = 0 TO polySides - 1
  37.             polys(j).x = ox + COS(j * (_PI(2 / polySides)) + offAng) * r
  38.             polys(j).y = oy + SIN(j * (_PI(2 / polySides)) + offAng) * r
  39.                         if not pointInsidePoly(polys(j), ShapeArea()) then goto start
  40.         NEXT
  41.         clr~& = midColor(_RGB(255, 255, 0), _RGB(255, 100, 0), map(r, 200, 3, 0, 1))
  42.         drawPoly polys(), clr~&
  43.         init = 1
  44.         poly_index = poly_index + polySides
  45.     ELSE
  46.         r = 200 / (c ^ i)
  47.         ox = p5random(r, _WIDTH - r)
  48.         oy = p5random(r, _HEIGHT - r)
  49.         collided = 0
  50.         offAng = p5random(-_PI, _PI)
  51.         FOR j = 0 TO polySides - 1
  52.             tempPoly1(j).x = ox + COS(j * (_PI(2 / polySides)) + offAng) * r
  53.             tempPoly1(j).y = oy + SIN(j * (_PI(2 / polySides)) + offAng) * r
  54.                         if not pointInsidePoly(tempPoly1(j), ShapeArea()) then goto start
  55.         NEXT
  56.         FOR j = 0 TO UBOUND(polys) STEP polySides
  57.             FOR k = j TO j + polySides - 1
  58.                 tempPoly2(k - j) = polys(k)
  59.             NEXT
  60.             IF polyCollide(tempPoly1(), tempPoly2()) THEN collided = -1: EXIT FOR
  61.         NEXT
  62.         IF NOT collided THEN
  63.             ' _echo "yes"
  64.             REDIM _PRESERVE polys(UBOUND(polys) + polySides) AS XY
  65.             FOR j = poly_index TO poly_index + polySides - 1
  66.                 polys(j) = tempPoly1(j - poly_index)
  67.             NEXT
  68.             clr~& = midColor(_RGB(255, 255, 0), _RGB(255, 100, 0), map(r, 200, 3, 0, 1))
  69.             drawPoly tempPoly1(), clr~&
  70.             poly_index = poly_index + polySides
  71.         ELSE
  72.             failed = failed + 1
  73.             IF failed > (i * 60) THEN i = i + 1: failed = 0
  74.         END IF
  75.     END IF
  76. LOOP UNTIL r < 3
  77.  
  78. FUNCTION midColor~& (clr1 AS _UNSIGNED LONG, clr2 AS _UNSIGNED LONG, v)
  79.     midColor~& = _RGB(map(v, 0, 1, _RED(clr1), _RED(clr2)), map(v, 0, 1, _GREEN(clr1), _GREEN(clr2)), map(v, 0, 1, _BLUE(clr1), _BLUE(clr2)))
  80.  
  81. SUB drawPoly (vert() AS XY, clr AS _UNSIGNED LONG)
  82.     n = UBOUND(vert)
  83.     DIM cx, cy
  84.     FOR i = 0 TO n
  85.         LINE (vert(i).x, vert(i).y)-(vert((i + 1) MOD (n + 1)).x, vert((i + 1) MOD (n + 1)).y), clr
  86.         cx = cx + vert(i).x: cy = cy + vert(i).y
  87.     NEXT
  88.     cx = cx / (n + 1): cy = cy / (n + 1)
  89.     PAINT (cx, cy), clr, clr
  90.  
  91.  
  92. FUNCTION polyCollide (vert1() AS XY, vert2() AS XY)
  93.     DIM n1 AS INTEGER, n2 AS INTEGER
  94.     n1 = UBOUND(vert1): n2 = UBOUND(vert2)
  95.     'checking if any point of polygon 1 inside polygon 2
  96.     FOR i = 0 TO n1
  97.         IF pointInsidePoly(vert1(i), vert2()) THEN polyCollide = -1: EXIT FUNCTION
  98.     NEXT
  99.     'checking if any point of polygon 2 inside polygon 1
  100.     FOR i = 0 TO n2
  101.         IF pointInsidePoly(vert2(i), vert1()) THEN polyCollide = -1: EXIT FUNCTION
  102.     NEXT
  103.     ' checking the edge intersection
  104.     FOR i = 0 TO n1
  105.         FOR j = 0 TO n2
  106.             IF lineIntersect(vert1(i).x, vert1(i).y, vert1((i + 1) MOD (n1 + 1)).x, vert1((i + 1) MOD (n1 + 1)).y, vert2(j).x, vert2(j).y, vert2((j + 1) MOD (n2 + 1)).x, vert2((j + 1) MOD (n2 + 1)).y) THEN polyCollide = -1: EXIT FUNCTION
  107.         NEXT
  108.     NEXT
  109.  
  110. 'from paulbourke.net
  111. FUNCTION pointInsidePoly (p AS XY, polyVert() AS XY)
  112.     DIM ax1, ax2, ay1, ay2
  113.     n = UBOUND(polyVert)
  114.     FOR i = 0 TO n
  115.         ax1 = polyVert(i).x - p.x
  116.         ay1 = polyVert(i).y - p.y
  117.         ax2 = polyVert((i + 1) MOD (n + 1)).x - p.x
  118.         ay2 = polyVert((i + 1) MOD (n + 1)).y - p.y
  119.         ang = ang + angle2D(ax1, ay1, ax2, ay2)
  120.     NEXT
  121.     pointInsidePoly = (ABS(ang) >= _PI)
  122.  
  123. 'from paulbourke.net
  124. FUNCTION angle2D (x1, y1, x2, y2)
  125.     DIM theta1, theta2, ftheta
  126.     theta1 = _ATAN2(y1, x1)
  127.     theta2 = _ATAN2(y2, x2)
  128.     ftheta = theta1 - theta2
  129.     WHILE ftheta > _PI: ftheta = ftheta - _PI(2): WEND
  130.     WHILE ftheta < -_PI: ftheta = ftheta + _PI(2): WEND
  131.     angle2D = ftheta
  132.  
  133. FUNCTION lineIntersect (__x1, __y1, __x2, __y2, __x3, __y3, __x4, __y4)
  134.     DIM x1 AS INTEGER, y1 AS INTEGER, x2 AS INTEGER, y2 AS INTEGER, x3 AS INTEGER, y3 AS INTEGER, x4 AS INTEGER, y4 AS INTEGER
  135.     DIM a1, b1, c1, a2, b2, c2
  136.     DIM a1b2_minus_a2b1, b1c2_minus_b2c1, a2c1_minus_a1c2
  137.     DIM inter_x AS INTEGER, inter_y AS INTEGER
  138.  
  139.     x1 = __x1: x2 = __x2: x3 = __x3: x4 = __x4
  140.     y1 = __y1: y2 = __y2: y3 = __y3: y4 = __y4
  141.    
  142.     IF x1 > x2 THEN SWAP x1, x2
  143.     IF x3 > x4 THEN SWAP x3, x4
  144.     IF y1 > y2 THEN SWAP y1, y2
  145.     IF y3 > y4 THEN SWAP y3, y4
  146.    
  147.     a1 = __y2 - __y1: b1 = -(__x2 - __x1): c1 = (__x2 * __y1) - (__x1 * __y2)
  148.     a2 = __y4 - __y3: b2 = -(__x4 - __x3): c2 = (__x4 * __y3) - (__x3 * __y4)
  149.  
  150.     'check if lines are perfectly vertical or horizontal
  151.     IF a1 = 0 AND a2 = 0 THEN lineIntersect = (__y1 = __y3): _DEST 0: EXIT FUNCTION
  152.     IF b1 = 0 AND b2 = 0 THEN lineIntersect = (__x1 = __x3): _DEST 0: EXIT FUNCTION
  153.     IF a2 = 0 OR b2 = 0 THEN GOTO skip_component_ratio
  154.    
  155.     'check if the whole line segments coincide with each other.
  156.     IF c2 <> 0 THEN
  157.         IF (a1 / a2) = (b1 / b2) AND (b1 / b2) = (c1 / c2) THEN
  158.             lineIntersect = -1: EXIT FUNCTION
  159.         END IF
  160.     END IF
  161.     skip_component_ratio:
  162.     'check if the line segments have same slope.
  163.     IF a1 * b2 = a2 * b1 THEN
  164.         lineIntersect = (c1 = c2) 'special case, when they still coincide (as c1=c2)
  165.         EXIT FUNCTION
  166.     END IF
  167.     'check if the line do intersect between the segments.
  168.     a1b2_minus_a2b1 = (a1 * b2) - (a2 * b1): b1c2_minus_b2c1 = (b1 * c2) - (b2 * c1): a2c1_minus_a1c2 = (a2 * c1) - (a1 * c2)
  169.     inter_x = b1c2_minus_b2c1 / a1b2_minus_a2b1: inter_y = a2c1_minus_a1c2 / a1b2_minus_a2b1
  170.    
  171.     lineIntersect = ((inter_x >= x1 AND inter_x <= x2 AND inter_y >= y1 AND inter_y <= y2)) and ((inter_x >= x3 AND inter_x <= x4 AND inter_y >= y3 AND inter_y <= y4))
  172.  
  173. 'taken from p5js.bas
  174. FUNCTION map! (value!, minRange!, maxRange!, newMinRange!, newMaxRange!)
  175.     map! = ((value! - minRange!) / (maxRange! - minRange!)) * (newMaxRange! - newMinRange!) + newMinRange!
  176.  
  177. FUNCTION p5random! (mn!, mx!)
  178.     IF mn! > mx! THEN
  179.         SWAP mn!, mx!
  180.     END IF
  181.     p5random! = RND * (mx! - mn!) + mn!
  182.  



 [ This attachment cannot be displayed inline in 'Print Page' view ]  

Squares inside pentagon


  [ This attachment cannot be displayed inline in 'Print Page' view ]  

Pentagons inside triangle
Title: Re: Space Filling with Polygons
Post by: bplus on May 01, 2020, 02:48:24 am
@Ashish,

Nailed it! :)
Title: Re: Space Filling with Polygons
Post by: _vince on May 01, 2020, 06:35:48 am
Nice pattern guys ;-) ;-)

Here is my experiment
Code: [Select]
defdbl a-z
const sw = 1024
const sh = 768
pi = 4*atn(1)

screen _newimage(sw, sh, 32)
line (0,0)-(sw,sh),_rgb(0,0,0),bf

a = sh
bplus sw/2, sh/2, a, 0, _rgb(50,0,0), _rgb(0,0,0)
c = 1.5
n = 7
for i=2 to n
        a = sh/(i^(c*c))
        for j=0 to 2000
                x = sw/2 - a*(i^(c*c))/2 + a*(i^(c*c))*rnd
                y = sh/2 - a*(i^(c*c))/2 + a*(i^(c*c))*rnd
                rot = 2*pi*rnd'*(i - 1)
                bplus x, y, a, rot, _rgb(50 + (i-1)*205/n,0,0), _rgb(50,0,0)
        next
next

sleep
system

sub bplus (x0, y0, a, rot, cc as _integer64, cp as _integer64)
        p = 50/400
        q = 20/400

        dim img as long
        img = _newimage(a, a, 32)

        _dest img
        line (0,0)-(a,a),cp,bf
        for y=0 to a - 1
        for x=0 to a - 1
                if (((x + p*a)^2 + (y - a/2)^2) > a*a*(q + 0.5)^2) and (((x - a - p*a)^2 + (y - a/2)^2) > a*a*(q + 0.5)^2) or (((y + p*a)^2 + (x - a/2)^2) > a*a*(q + 0.5)^2) and (((y - a - p*a)^2 + (x - a/2)^2) > a*a*(q + 0.5)^2) then pset (x, y), cc
        next
        next

        dim tl as long, tr as long, bl as long, br as long
        dim r as integer, g as integer, b as integer

        yes = 1
        a2 = a*(sqr(2) - 0.5)
        _dest 0
        for y=-a2 to a + a2
        for x=-a2 to a + a2
                xx = (x - a/2)*cos(rot) - (y - a/2)*sin(rot) + a/2
                yy = (x - a/2)*sin(rot) + (y - a/2)*cos(rot) + a/2

                if (xx >= 0 and xx < a-1 and yy >= 0 and yy < a-1) then
                        _source img
                        if point (xx, yy) <> cp then
                                _source 0
                                if point(x0 - a/2 + x, y0 - a/2 + y) <> cp then yes = 0
                        end if
                end if
        next
        next

        if yes then
                _dest 0
                for y=-a2 to a + a2
                for x=-a2 to a + a2
                        xx = (x - a/2)*cos(rot) - (y - a/2)*sin(rot) + a/2
                        yy = (x - a/2)*sin(rot) + (y - a/2)*cos(rot) + a/2

                        if (xx >= 0 and xx < a-1 and yy >= 0 and yy < a-1) then
                                _source img
                                if int(xx) > a-1 or int(yy) > a-1 then tl = cp else tl = point(int(xx), int(yy))
                                if int(xx) > a-1 or int(yy) > a-1 or int(xx)+1 > a-1 then tr = cp else tr = point(int(xx) + 1, int(yy))
                                if int(xx) > a-1 or int(yy) > a-1 or int(yy)+1 > a-1 then bl = cp else bl = point(int(xx), int(yy) + 1)
                                if int(xx) > a-1 or int(yy) > a-1 or int(xx)+1 > a-1 or int(yy)+1 > a-1 then br = cp else br = point(int(xx) + 1, int(yy) + 1)

                                dx = xx - int(xx)
                                dy = yy - int(yy)

                                r = _round((1 - dy)*((1 - dx)*  _red(tl) + dx*  _red(tr)) + dy*((1 - dx)*  _red(bl) + dx*  _red(br)))
                                g = _round((1 - dy)*((1 - dx)*_green(tl) + dx*_green(tr)) + dy*((1 - dx)*_green(bl) + dx*_green(br)))
                                b = _round((1 - dy)*((1 - dx)* _blue(tl) + dx* _blue(tr)) + dy*((1 - dx)* _blue(bl) + dx* _blue(br)))

                                if point (xx, yy) <> cp then pset (x0 - a/2 + x, y0 - a/2 + y), _rgb(r,g,b)
                        end if
                next
                next
        end if

        _freeimage img
end sub
Title: Re: Space Filling with Polygons
Post by: Ashish on May 01, 2020, 08:52:12 am
Hi _vince, that screenshots is awesome! :D
But, your program is running slowly. Is this my PC fault or your program do lot of calculations?
Title: Re: Space Filling with Polygons
Post by: _vince on May 01, 2020, 09:09:00 am
It's not really optimized, it does pixel by pixel overlap detection.  I let it run and came back an hour later for a slightly bigger picture but not as pretty as I was hoping