/*
**  Usage:
**      triangles = polygon_to_triangles(polygon);
**
**  Description:
**      Takes a list of points defining the boundary of a polygon
**      and returns a list of triangles in the same shape.
**
**  Arguments:
**      polygon      ds_list containing XY coordinate pairs defining
**                   the shape of a polygon
**
**  Returns:
**      triangles    ds_list containing triplets of XY coordinate pairs
**
**  Dependencies:
**      is_clockwise()
**      lines_intersect()
**      point_in_triangle()
**
**  Notes:
**      The polygon points are given and returned in traditional
**      counter-clockwise order. Polygons are closed figures, the
**      first point in the polygon will also be considered the last
**      point in the polygon. Polygons must be simple, which means
**      they can not have edges that cross each other. The number
**      of triangles created is (n-2) where n is the number of
**      points in the polygon.
**
**  Example:
**      in:  polygon = [ 100,100,  100,200,  200,200,  200,100 ]
**           (a square polygon: four coordinate pairs)
**
**      out: triangles = [ 100,100,  100,200,  200,100,   (1st triplet)
**                         100,200,  200,200,  200,100 ]  (2nd triplet)
**           (two triangles: two triplet sets of coordinate pairs)
**
**  copyright (c) 2006, John Leffingwell
**  www.planetxot.com
*/

var polygon, polygonSize, triangles, points, polyX, polyY, good;
var i, j, n, p, A, B, C, x0, y0, x1, y1, x2, y2, x3, y3, x4, y4;
polygon = argument[0];
polygonSize = ds_list_size(polygon) div 2;
triangles = ds_list_create();
points = ds_list_create();
polyX = ds_list_create();
polyY = ds_list_create();
i = 0;
repeat (polygonSize) {
    ds_list_add(polyX, ds_list_find_value(polygon, i));
    ds_list_add(polyY, ds_list_find_value(polygon, i+1));
    i += 2;
}
// 1. For (n - 3) vertices
n = polygonSize;
for (n = polygonSize; n > 3; n -= 1) {
    //  a. Select first point (random)
    ds_list_clear(points);
    for (p = 0; p < n; p += 1) ds_list_add(points, p);
    repeat (p) {
        i = floor(random(ds_list_size(points)));
        A = ds_list_find_value(points, i);
        ds_list_delete(points, i);
        //  b. Pick the next two points
        B = (A + 1) mod n;
        C = (A + 2) mod n;
        //  c. Make a triangle with the selected points
        x0 = ds_list_find_value(polyX, A);
        y0 = ds_list_find_value(polyY, A);
        x1 = ds_list_find_value(polyX, B);
        y1 = ds_list_find_value(polyY, B);
        x2 = ds_list_find_value(polyX, C);
        y2 = ds_list_find_value(polyY, C);
        //  d. If triangle is counter-clockwise...
        if (not is_clockwise(x0, y0, x1, y1, x2, y2)) {
            good = true;
            //  ...and if triangle has no vertices within it...
            for (i = 0; i < n; i += 1) {
                if ((i != A) && (i != B) && (i != C)) {
                    x3 = ds_list_find_value(polyX, i);
                    y3 = ds_list_find_value(polyY, i);
                    if (point_in_triangle(x0, y0, x1, y1, x2, y2, x3, y3)) { good = false; break; }
                    //  ...and if the new edge has no other edges crossing it...
                    j = (i + 1) mod n;
                    if ((j != A) && (j != B) && (j != C)) {
                        x4 = ds_list_find_value(polyX, j);
                        y4 = ds_list_find_value(polyY, j);
                        if (lines_intersect(x0, y0, x2, y2, x3, y3, x4, y4)) { good = false; break; }
                    }
                }
            }
            //  e.  ...then add the triangle to list and remove the shared outside edge point
            if (good) {
                ds_list_add(triangles, x0);
                ds_list_add(triangles, y0);
                ds_list_add(triangles, x1);
                ds_list_add(triangles, y1);
                ds_list_add(triangles, x2);
                ds_list_add(triangles, y2);
                ds_list_delete(polyX, B);
                ds_list_delete(polyY, B);
                break;
            }
        }
    }
}
//  2. There are only three vertices left, so add the final triangle to the list
ds_list_add(triangles, ds_list_find_value(polyX, 0));
ds_list_add(triangles, ds_list_find_value(polyY, 0));
ds_list_add(triangles, ds_list_find_value(polyX, 1));
ds_list_add(triangles, ds_list_find_value(polyY, 1));
ds_list_add(triangles, ds_list_find_value(polyX, 2));
ds_list_add(triangles, ds_list_find_value(polyY, 2));
//  3. Clean up
ds_list_destroy(polyX);
ds_list_destroy(polyY);
ds_list_destroy(points);
return triangles;