mirror of
https://github.com/Ttanasart-pt/Pixel-Composer.git
synced 2024-12-26 23:17:25 +01:00
205 lines
No EOL
4.8 KiB
Text
205 lines
No EOL
4.8 KiB
Text
function polygon_simplify(points, tolerance = 4) {
|
|
var remSt = ds_stack_create();
|
|
|
|
var len = array_length(points);
|
|
for( var i = 0; i < len; i++ ) {
|
|
var _px0 = points[i].x;
|
|
var _py0 = points[i].y;
|
|
var _px1 = points[safe_mod(i + 1, len)].x;
|
|
var _py1 = points[safe_mod(i + 1, len)].y;
|
|
var _px2 = points[safe_mod(i + 2, len)].x;
|
|
var _py2 = points[safe_mod(i + 2, len)].y;
|
|
|
|
var dir0 = point_direction(_px0, _py0, _px1, _py1);
|
|
var dir1 = point_direction(_px1, _py1, _px2, _py2);
|
|
|
|
if(abs(dir0 - dir1) <= tolerance)
|
|
ds_stack_push(remSt, safe_mod(i + 1, len));
|
|
}
|
|
|
|
while(!ds_stack_empty(remSt)) {
|
|
var ind = ds_stack_pop(remSt);
|
|
array_delete(points, ind, 1);
|
|
}
|
|
|
|
ds_stack_destroy(remSt);
|
|
|
|
return points;
|
|
}
|
|
|
|
function polygon_points_classify(points) {
|
|
var len = array_length(points);
|
|
|
|
var maxx = -99999;
|
|
var maxindex = 0;
|
|
|
|
for( var i = 0; i < len; i++ ) {
|
|
var _x = points[i].x;
|
|
if(_x > maxx) {
|
|
maxx = _x;
|
|
maxindex = i;
|
|
}
|
|
}
|
|
|
|
var side, _side = 0;
|
|
var convexs = [];
|
|
var reflects = [];
|
|
var startindex = safe_mod(maxindex - 1 + len, len);
|
|
|
|
for( var i = 0; i < len; i++ ) {
|
|
var index = safe_mod(startindex + i, len);
|
|
var _px0 = points[index].x;
|
|
var _py0 = points[index].y;
|
|
var _px1 = points[safe_mod(index + 1, len)].x;
|
|
var _py1 = points[safe_mod(index + 1, len)].y;
|
|
var _px2 = points[safe_mod(index + 2, len)].x;
|
|
var _py2 = points[safe_mod(index + 2, len)].y;
|
|
|
|
var side = cross_product(_px0, _py0, _px1, _py1, _px2, _py2);
|
|
if(_side != 0 && sign(_side) != sign(side))
|
|
array_push(reflects, safe_mod(index + 1, len));
|
|
else {
|
|
array_push(convexs, safe_mod(index + 1, len));
|
|
_side = sign(side);
|
|
}
|
|
}
|
|
|
|
return [ convexs, reflects, _side ];
|
|
}
|
|
|
|
function polygon_triangulate_convex(points) {
|
|
var triangles = [];
|
|
|
|
var len = array_length(points);
|
|
var c0 = points[0];
|
|
|
|
for( var i = 0; i < len - 2; i++ ) {
|
|
var c1 = points[safe_mod(i + 1, len)];
|
|
var c2 = points[safe_mod(i + 2, len)];
|
|
|
|
array_push(triangles, [c0, c1, c2]);
|
|
}
|
|
|
|
return triangles;
|
|
}
|
|
|
|
function polygon_triangulate(points, tolerance = 4) {
|
|
points = polygon_simplify(points, tolerance);
|
|
var classes = polygon_points_classify(points);
|
|
var convexes = classes[0];
|
|
var reflected = classes[1];
|
|
var checkSide = classes[2];
|
|
var pointInd = [];
|
|
|
|
if(array_length(reflected) == 0)
|
|
return polygon_triangulate_convex(points);
|
|
|
|
for( var i = 0; i < array_length(points); i++ )
|
|
pointInd[i] = i;
|
|
|
|
var triangles = [];
|
|
var repeated = 0;
|
|
|
|
while(array_length(pointInd) > 3) {
|
|
if(array_length(convexes) == 0) return triangles;
|
|
|
|
var len = array_length(pointInd);
|
|
var c0 = convexes[0];
|
|
var c0i = array_find(pointInd, c0);
|
|
var c1 = pointInd[safe_mod(c0i - 1 + len, len)];
|
|
var c2 = pointInd[safe_mod(c0i + 1, len)];
|
|
|
|
var p0 = points[c0];
|
|
var p1 = points[c1];
|
|
var p2 = points[c2];
|
|
|
|
//check if point is ear
|
|
var isEar = true;
|
|
for( var i = 0; i < len; i++ ) {
|
|
var ind = pointInd[i];
|
|
if(ind == c0) continue;
|
|
if(ind == c1) continue;
|
|
if(ind == c2) continue;
|
|
|
|
var p = points[ind];
|
|
if(point_in_triangle(p.x, p.y, p0.x, p0.y, p1.x, p1.y, p2.x, p2.y)) {
|
|
isEar = false;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if(isEar) {
|
|
array_remove(convexes, c0);
|
|
array_remove(pointInd, c0);
|
|
|
|
array_push(triangles, [p0, p1, p2]);
|
|
len--;
|
|
|
|
if(array_exists(reflected, c1)) {
|
|
var c1i = array_find(pointInd, c1);
|
|
var c1b = safe_mod(c1i - 1 + len, len);
|
|
var c1a = safe_mod(c1i + 1, len);
|
|
|
|
var p1b = points[pointInd[c1b]];
|
|
var p1a = points[pointInd[c1a]];
|
|
|
|
var side = cross_product(p1b.x, p1b.y, p1.x, p1.y, p1a.x, p1a.y);
|
|
if(sign(side) == checkSide) {
|
|
array_remove(reflected, c1);
|
|
array_push(convexes, c1);
|
|
}
|
|
}
|
|
|
|
if(array_exists(reflected, c2)) {
|
|
var c2i = array_find(pointInd, c2);
|
|
var c2b = safe_mod(c2i - 1 + len, len);
|
|
var c2a = safe_mod(c2i + 1, len);
|
|
|
|
var p2b = points[pointInd[c2b]];
|
|
var p2a = points[pointInd[c2a]];
|
|
|
|
var side = cross_product(p2b.x, p2b.y, p2.x, p2.y, p2a.x, p2a.y);
|
|
if(sign(side) == checkSide) {
|
|
array_remove(reflected, c2);
|
|
array_push(convexes, c2);
|
|
}
|
|
}
|
|
|
|
repeated = 0;
|
|
} else {
|
|
array_remove(convexes, c0);
|
|
array_push(convexes, c0);
|
|
|
|
if(repeated++ > len) {
|
|
print("mesh error")
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
if(array_length(pointInd) == 3)
|
|
array_push(triangles, [points[pointInd[0]], points[pointInd[1]], points[pointInd[2]]]);
|
|
|
|
return triangles;
|
|
}
|
|
|
|
function polygon_triangulate_convex_fan(points) {
|
|
var triangles = [];
|
|
|
|
var amo = array_length(points);
|
|
var cx = 0;
|
|
var cy = 0;
|
|
for( var i = 0; i < amo; i++ ) {
|
|
cx += points[i].x;
|
|
cy += points[i].y;
|
|
}
|
|
|
|
cx /= amo;
|
|
cy /= amo;
|
|
|
|
var pc = new Point(cx, cy);
|
|
for( var i = 0; i < amo; i++ ) {
|
|
array_push(triangles, [ points[i], points[(i + 1) % amo], pc ]);
|
|
}
|
|
return triangles;
|
|
} |