> show canvas only <


/* built with Studio Sketchpad: 
 *   https://sketchpad.cc
 * 
 * observe the evolution of this sketch: 
 *   https://studio.sketchpad.cc/sp/pad/view/ro.8CBmQLCilSm/rev.3198
 * 
 * authors: 
 *   Steven

 * license (unless otherwise specified): 
 *   creative commons attribution-share alike 3.0 license.
 *   https://creativecommons.org/licenses/by-sa/3.0/ 
 */ 



// Steven de Brouwer <[email protected]>
// Still work in progress... the result is already awesome!
// Nice to be featured! Thank you!
//
// Feel free to copy, but:
// (C)redits 2016 Steven <[email protected]>
//
// Press Q to clear the canvas

int i = 0;
color lineColor = #707070;
float dtheta = 2*Math.PI * 3/360; // degrees

var Polygons = new Array();

boolean frist = true;
void deb(string tekst) { console.log(tekst); }

void drawPoly(p, c) {
    var n = p.length>>1;
    if (n<=1) {return;}
    for(var i=0; i<n-1; i++)
    {
        stroke(c);
        line(p[2*i+0],p[2*i+1],p[2*i+2],p[2*i+3]);
    }
    if (n>2) {
        i=n-1;
        line(p[2*i+0],p[2*i+1],p[0],p[1]);
    }
    stroke(lineColor);
}

void setup() {
    size(500, 500); 
    smooth();
    frameRate(5);
    strokeWeight(1);
    stroke(lineColor);
    rectMode(CORNERS);
    fill(0, 102, 153);
    setUp();
}

void draw() {  // this is run repeatedly. 
    if ( frist ) {
        frist = false;
    }
    if ( mousePressed ){
        var x = mouseX;
        var y = mouseY;
        found = -1;
        for (i = 0; i < Polygons.length; i++) {
            if (PolyK.ContainsPoint(Polygons[i], x, y)) {
                found = i;
            }
        }
        if (found >= 0) {
            if (PolyK.GetArea(Polygons[found]) < 10000) { // 5000
                fillPoly(found, x, y);
            } else {
                splitPoly(found, x, y);
            }
        }
    }
}

void fillPoly(f, x, y) {
    var poly = Polygons[f].slice();
    //drawPoly(poly, #FF0000);
    n = poly.length>>1
    maxi=200;
    var plusOrMinus = Math.random() < 0.5 ? -1 : 1;
    plusOrMinus += n;
    //deb("plusOrMinus = "+plusOrMinus );

    var isc = PolyK.ClosestEdge(poly, x, y);
    e1 = isc.edge;
    while (n > 2 && maxi>0) {
        e2 = (e1 + plusOrMinus ) % n;
        //deb("e1="+e1+", e2="+e2);
        e1 *= 2;
        e2 *= 2;
        
        theta = angle(poly[e1+0], poly[e1+1], poly[e2+0], poly[e2+1]);
        dx = Math.cos(theta+dtheta); dy = Math.sin(theta+dtheta);
        if ( ! PolyK.ContainsPoint(poly, poly[e1+0]+dx, poly[e1+1]+dy)) {
            dx = Math.cos(theta-dtheta); dy = Math.sin(theta-dtheta);
        }
        //deb("dx="+dx+", dy="+dy+", theta="+theta);
        ray = PolyK.Raycast(poly, poly[e1+0]+dx, poly[e1+1]+dy, dx, dy);

        //if (ray == null  || 2*ray.edge == e1) {
        //    dx = Math.cos(theta-dtheta); dy = Math.sin(theta-dtheta);                                
        //    ray = PolyK.Raycast(poly, poly[e1+0]+dx, poly[e1+1]+dy, dx, dy);
        //}
        if (ray == null) { return; }

//        if (ray.edge == e2) {
            line(poly[e1+0], poly[e1+1], poly[e1+0]+dx*ray.dist, poly[e1+1]+dy*ray.dist);
            poly[e2+0] = poly[e1+0] + dx*ray.dist;
            poly[e2+1] = poly[e1+1] + dy*ray.dist;
//        }
        maxi = maxi-1;
        e1 = e1>>1;
        e1 = (e1 + plusOrMinus ) % n;
        //n = 0;
    }
    //drawPoly(poly, #00FF00);
}

void splitPoly(f, x, y) {
    float r = random(-89, 89);
    float a = tan(radians(r)); // y=ax+b
    float b = y-(a*x);
    xL=     -5; yL=(a*xL) + b;
    xR=width+5; yR=(a*xR) + b;
    PolyDuo = PolyK.Slice( Polygons[f] , xL,yL , xR,yR );
    Polygons.splice(found,   1, PolyDuo[0]);
    Polygons.splice(found+1, 0, PolyDuo[1]);
    drawPoly(PolyDuo[0], lineColor);
    //drawPoly(Polygons[f], #00FF00);
    //drawPoly(PolyDuo[1], lineColor);
}

void keyPressed() {
    // deb("keyCode="+keyCode);
    // q=81, c=67
    if (keyCode == 81) { setUp(); } // clear canvas
}
void setUp() {
    background(255);
    Polygons = [];
    polyscreen = [10,10, width-10,10, width-10,height-10, 10,height-10];
    //drawPoly(polyscreen, #FF0F0F);
    drawPoly(polyscreen, lineColor);
    Polygons.push(polyscreen);
}

function angle(cx, cy, ex, ey) {
    return Math.atan2(ey - cy, ex - cx); // range (-PI, PI]
    //theta *= 180 / Math.PI; // rads to degs, range (-180, 180]
    //if (theta < 0) theta = 360 + theta; // range [0, 360)
    //return theta;
}