_TITLE "Enclose a random set of points then Voronoi to border"  
nPoints = 13 '<<<<<<<<<<< actually less points makes for more interesting shapes!
 
        'test circle points, supposed to be most difficult
        'toggle comments this whole block to try random dots or dots on a circle
 
        'ca = _PI(2 / (nPoints - 1))
        'IF i = 1 THEN 'need one off the border for painting interior
        '    p(i).x = xmax / 2: p(i).y = ymax / 2
        'ELSE
        '    p(i).x = xmax / 2 + 200 * COS(ca * i)
        '    p(i).y = ymax / 2 + 200 * SIN(ca * i)
        'END IF
        p
(i
).x 
= INT(RND * (xmax 
- 20)) + 10        p
(i
).y 
= INT(RND * (ymax 
- 20)) + 10 
 
        fcirc p(i).x, p(i).y, 2, p(i).K
    qSort 1, nPoints, p()
    curPoint = 1
    plot
    'main event: going from farthest left to right find points that contiain interior with convex polygon
    'This loop does the top section
        lowestAngle 
= _PI(2): saveI 
= 0        FOR i 
= curPoint 
+ 1 TO nPoints
             testAngle 
= _ATAN2(p
(i
).y 
- p
(curPoint
).y
, p
(i
).x 
- p
(curPoint
).x
)            IF testAngle 
< lowestAngle 
THEN lowestAngle 
= testAngle: saveI 
= i
             p(curPoint).connectX = p(saveI).x: p(curPoint).connectY = p(saveI).y
            curPoint = saveI
        plot
 
    'main even part 2: going back right to left find the points that contain the interior with a convex ploygon
    'This loop does the bottom section
    curPoint = nPoints
        lowestAngle 
= _PI(2): saveI 
= 0            testAngle 
= _ATAN2(p
(curPoint
).y 
- p
(i
).y
, p
(curPoint
).x 
- p
(i
).x
)            IF testAngle 
< lowestAngle 
THEN lowestAngle 
= testAngle: saveI 
= i
             p(curPoint).connectX = p(saveI).x: p(curPoint).connectY = p(saveI).y
            curPoint = saveI
        plot
 
    'note: if a dot happens to sit on the border the paint is going to leak blue
    ' FIXED dots are on separate Bg image
 
    ' find an interior point (not connected) and paint from there
 
    'the blue paint is to tell us which points to Voronoi
    maxD = xmax + ymax
    FOR x 
= p
(1).x 
TO p
(nPoints
).x
             IF POINT(x
, y
) = _RGB32(0, 0, 255) THEN 'a Voronoi point to color the same as closest point                 d = maxD
                FOR i 
= 1 TO nPoints 
'looking for closet point to x, y                     IF a 
+ b 
< d 
THEN d 
= a 
+ b: kkl 
= i
                 PSET (x
, y
), p
(kkl
).K 
'set x, y the same as closets point color  
    _PUTIMAGE , dotsBg&
, 0 'dots were causing Paints to bleed         'note x can not = 0
        IF p
(i
).connectX 
THEN thic p
(i
).x
, p
(i
).y
, p
(i
).connectX
, p
(i
).connectY
, 1, _RGB32(255, 255, 255)  
'now scan or sort on x
    Hi = finish: Lo = start
    Middle = a((Lo + Hi) / 2).x 'find middle of array
            Lo = Lo + 1: Hi = Hi - 1
    IF Hi 
> start 
THEN qSort start
, Hi
, a
()     IF Lo 
< finish 
THEN qSort Lo
, finish
, a
()  
    t2 = thick / 2
    x3 
= x1 
+ t2 
* COS(a 
+ pd2
)    y3 
= y1 
+ t2 
* SIN(a 
+ pd2
)    x4 
= x1 
+ t2 
* COS(a 
- pd2
)    y4 
= y1 
+ t2 
* SIN(a 
- pd2
)    x5 
= x2 
+ t2 
* COS(a 
+ pd2
)    y5 
= y2 
+ t2 
* SIN(a 
+ pd2
)    x6 
= x2 
+ t2 
* COS(a 
- pd2
)    y6 
= y2 
+ t2 
* SIN(a 
- pd2
)    ftri x6, y6, x4, y4, x3, y3, K
    ftri x3, y3, x5, y5, x6, y6, K
 
 
 
    RadiusError = -Radius
    X = Radius
    Y = 0
 
 
    ' Draw the middle span here so we don't draw it twice in the main loop,
    ' which would be a problem with blending turned on.
    LINE (CX 
- X
, CY
)-(CX 
+ X
, CY
), C
, BF
  
        RadiusError = RadiusError + Y * 2 + 1
                LINE (CX 
- Y
, CY 
- X
)-(CX 
+ Y
, CY 
- X
), C
, BF
                 LINE (CX 
- Y
, CY 
+ X
)-(CX 
+ Y
, CY 
+ X
), C
, BF
             X = X - 1
            RadiusError = RadiusError - X * 2
        Y = Y + 1
        LINE (CX 
- X
, CY 
- Y
)-(CX 
+ X
, CY 
- Y
), C
, BF
         LINE (CX 
- X
, CY 
+ Y
)-(CX 
+ X
, CY 
+ Y
), C
, BF