mirror of
https://github.com/Ttanasart-pt/Pixel-Composer.git
synced 2024-12-24 14:06:23 +01:00
Fix triangulation problem on overlapped points.
This commit is contained in:
parent
0f5c68c8c9
commit
9da78f0fe4
6 changed files with 100 additions and 57 deletions
|
@ -5,16 +5,16 @@ function polygon_simplify(points, tolerance = 4) { #region
|
|||
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 _px1 = points[(i + 1) % len].x;
|
||||
var _py1 = points[(i + 1) % len].y;
|
||||
var _px2 = points[(i + 2) % len].x;
|
||||
var _py2 = points[(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));
|
||||
if((_px0 == _px1 && _py0 == _py1) || abs(dir0 - dir1) <= tolerance)
|
||||
ds_stack_push(remSt, (i + 1) % len);
|
||||
}
|
||||
|
||||
while(!ds_stack_empty(remSt)) {
|
||||
|
@ -44,22 +44,23 @@ function polygon_points_classify(points) { #region
|
|||
var side, _side = 0;
|
||||
var convexs = [];
|
||||
var reflects = [];
|
||||
var startindex = safe_mod(maxindex - 1 + len, len);
|
||||
var startindex = (maxindex - 1 + len) % len;
|
||||
|
||||
for( var i = 0; i < len; i++ ) {
|
||||
var index = safe_mod(startindex + i, len);
|
||||
var index = (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 _px1 = points[(index + 1) % len].x;
|
||||
var _py1 = points[(index + 1) % len].y;
|
||||
var _px2 = points[(index + 2) % len].x;
|
||||
var _py2 = points[(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));
|
||||
array_push(reflects, (index + 1) % len);
|
||||
else {
|
||||
array_push(convexs, safe_mod(index + 1, len));
|
||||
array_push(convexs, (index + 1) % len);
|
||||
_side = sign(side);
|
||||
}
|
||||
}
|
||||
|
@ -83,25 +84,28 @@ function polygon_triangulate_convex(points) { #region
|
|||
return triangles;
|
||||
} #endregion
|
||||
|
||||
function polygon_triangulate(points, tolerance = 4) { #region
|
||||
points = polygon_simplify(points, tolerance);
|
||||
function polygon_triangulate(points, tolerance = 4) { #region // ear clipping
|
||||
if(array_length(points) < 3) return [ [], points ];
|
||||
|
||||
if(tolerance > 0) points = polygon_simplify(points, tolerance);
|
||||
if(array_length(points) < 3) return [ [], points ];
|
||||
|
||||
var classes = polygon_points_classify(points);
|
||||
var convexes = classes[0];
|
||||
var reflected = classes[1];
|
||||
var checkSide = classes[2];
|
||||
|
||||
if(array_length(reflected) == 0)
|
||||
return polygon_triangulate_convex(points);
|
||||
|
||||
var pointInd = array_create(array_length(points));
|
||||
for( var i = 0, n = array_length(points); i < n; i++ )
|
||||
pointInd[i] = i;
|
||||
return [ polygon_triangulate_convex(points), points ];
|
||||
|
||||
var pointInd = array_create_ext(array_length(points), function(i) /*=>*/ { return i; });
|
||||
var triangles = [];
|
||||
var repeated = 0;
|
||||
var repeated = 0;
|
||||
|
||||
//print($"Ear cutting : {array_length(points)} verticies");
|
||||
|
||||
while(array_length(pointInd) > 3) {
|
||||
if(array_length(convexes) == 0) return triangles;
|
||||
if(array_length(convexes) == 0) return [ triangles, points ];
|
||||
|
||||
var len = array_length(pointInd);
|
||||
var c0 = convexes[0];
|
||||
|
@ -117,9 +121,7 @@ function polygon_triangulate(points, tolerance = 4) { #region
|
|||
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;
|
||||
if(ind == c0 || ind == c1 || 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)) {
|
||||
|
@ -171,16 +173,16 @@ function polygon_triangulate(points, tolerance = 4) { #region
|
|||
array_push(convexes, c0);
|
||||
|
||||
if(repeated++ > len) {
|
||||
//print("mesh error")
|
||||
noti_warning("Mesh error");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(array_length(pointInd) == 3)
|
||||
array_push(triangles, [points[pointInd[0]], points[pointInd[1]], points[pointInd[2]]]);
|
||||
array_push(triangles, [ points[pointInd[0]], points[pointInd[1]], points[pointInd[2]] ]);
|
||||
|
||||
return triangles;
|
||||
return [ triangles, points ];
|
||||
} #endregion
|
||||
|
||||
function polygon_triangulate_convex_fan(points) { #region
|
||||
|
|
|
@ -26,7 +26,7 @@ function canvas_freeform_step(active, _x, _y, _s, _mx, _my, _draw) { #region
|
|||
surface_reset_target();
|
||||
|
||||
if(array_length(freeform_shape) > 3) {
|
||||
var _triangles = polygon_triangulate(freeform_shape, 1);
|
||||
var _triangles = polygon_triangulate(freeform_shape, 1)[0];
|
||||
|
||||
var temp_surface = surface_create(_dim[0], _dim[1]);
|
||||
|
||||
|
|
|
@ -46,7 +46,7 @@ function Node_Mesh_Create_Path(_x, _y, _group = noone) : Node(_x, _y, _group) co
|
|||
|
||||
var triangles = [];
|
||||
switch(_algo) {
|
||||
case 0 : triangles = polygon_triangulate(points); break;
|
||||
case 0 : triangles = polygon_triangulate(points)[0]; break;
|
||||
case 1 : triangles = polygon_triangulate_convex_fan(points); break;
|
||||
case 2 : triangles = delaunay_triangulation(points); break;
|
||||
}
|
||||
|
|
|
@ -57,13 +57,13 @@ function Node_Path(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
|
|||
];
|
||||
|
||||
#region ---- path ----
|
||||
path_loop = false;
|
||||
anchors = [];
|
||||
segments = [];
|
||||
lengths = [];
|
||||
lengthAccs = [];
|
||||
lengthTotal = 0;
|
||||
boundary = new BoundingBox();
|
||||
path_loop = false;
|
||||
anchors = [];
|
||||
segments = [];
|
||||
lengths = [];
|
||||
lengthAccs = [];
|
||||
lengthTotal = 0;
|
||||
boundary = new BoundingBox();
|
||||
|
||||
cached_pos = ds_map_create();
|
||||
#endregion
|
||||
|
@ -568,7 +568,7 @@ function Node_Path(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
|
|||
|
||||
for( var i = 0, n = array_length(segments); i < n; i++ ) { #region draw path
|
||||
var _seg = segments[i];
|
||||
var _ox = 0, _oy = 0, _nx = 0, _ny = 0, p = 0;
|
||||
var _ox = 0, _oy = 0, _nx = 0, _ny = 0, p = 0;
|
||||
|
||||
for( var j = 0, m = array_length(_seg); j < m; j++ ) {
|
||||
_nx = _x + _seg[j][0] * _s;
|
||||
|
@ -801,12 +801,13 @@ function Node_Path(_x, _y, _group = noone) : Node(_x, _y, _group) constructor {
|
|||
} #endregion
|
||||
|
||||
static updateLength = function() { #region
|
||||
boundary = new BoundingBox();
|
||||
segments = [];
|
||||
lengths = [];
|
||||
lengthAccs = [];
|
||||
lengthTotal = 0;
|
||||
boundary = new BoundingBox();
|
||||
segments = [];
|
||||
lengths = [];
|
||||
lengthAccs = [];
|
||||
lengthTotal = 0;
|
||||
|
||||
var _index = 0;
|
||||
var loop = getInputData(1);
|
||||
var sample = PREFERENCES.path_resolution;
|
||||
var ansize = ds_list_size(inputs) - input_fix_len;
|
||||
|
|
|
@ -109,12 +109,52 @@ function Node_Shape(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) con
|
|||
];
|
||||
|
||||
temp_surface = [ noone ];
|
||||
use_path = false;
|
||||
path_points = [];
|
||||
point_simp = [];
|
||||
triangles = [];
|
||||
|
||||
attribute_surface_depth();
|
||||
|
||||
static drawOverlay = function(hover, active, _x, _y, _s, _mx, _my, _snx, _sny) { #region
|
||||
var _path = getInputData(14);
|
||||
if(_path != noone && struct_has(_path, "getPointRatio")) return;
|
||||
if(use_path) {
|
||||
draw_set_text(f_p3, fa_center, fa_top);
|
||||
draw_set_color(COLORS._main_accent);
|
||||
var ox, oy, nx, ny;
|
||||
|
||||
for (var i = 0, n = array_length(point_simp); i < n; i++) {
|
||||
var p = point_simp[i];
|
||||
nx = _x + p.x * _s;
|
||||
ny = _y + p.y * _s;
|
||||
|
||||
if(i) draw_line(ox, oy, nx, ny);
|
||||
// draw_circle(nx, ny, 3, false);
|
||||
// draw_text(nx, ny + 8, i);
|
||||
|
||||
ox = nx;
|
||||
oy = ny;
|
||||
}
|
||||
|
||||
// draw_set_color(c_red);
|
||||
// for( var i = 0, n = array_length(triangles); i < n; i++ ) {
|
||||
// var tri = triangles[i];
|
||||
// var p0 = tri[0];
|
||||
// var p1 = tri[1];
|
||||
// var p2 = tri[2];
|
||||
|
||||
// var p0x = _x + p0.x * _s;
|
||||
// var p0y = _y + p0.y * _s;
|
||||
// var p1x = _x + p1.x * _s;
|
||||
// var p1y = _y + p1.y * _s;
|
||||
// var p2x = _x + p2.x * _s;
|
||||
// var p2y = _y + p2.y * _s;
|
||||
|
||||
// draw_line(p0x, p0y, p1x, p1y);
|
||||
// draw_line(p0x, p0y, p2x, p2y);
|
||||
// draw_line(p1x, p1y, p2x, p2y);
|
||||
// }
|
||||
return;
|
||||
}
|
||||
|
||||
var _type = getInputData(15);
|
||||
|
||||
|
@ -186,8 +226,9 @@ function Node_Shape(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) con
|
|||
inputs[| 15].setVisible(true);
|
||||
|
||||
_outSurf = surface_verify(_outSurf, _dim[0], _dim[1], attrDepth());
|
||||
use_path = _path != noone && struct_has(_path, "getPointRatio");
|
||||
|
||||
if(_path != noone && struct_has(_path, "getPointRatio")) { #region
|
||||
if(use_path) { #region
|
||||
inputs[| 3].setVisible(false);
|
||||
inputs[| 4].setVisible(false);
|
||||
inputs[| 5].setVisible(false);
|
||||
|
@ -201,20 +242,19 @@ function Node_Shape(_x, _y, _group = noone) : Node_Processor(_x, _y, _group) con
|
|||
if(_bg) draw_clear_alpha(0, 1);
|
||||
else DRAW_CLEAR
|
||||
|
||||
var points = [];
|
||||
var segCount = _path.getSegmentCount();
|
||||
if(segCount) {
|
||||
var quality = 8;
|
||||
var sample = quality * segCount;
|
||||
var sample = quality * segCount;
|
||||
var _step = 1 / sample;
|
||||
|
||||
for( var i = 0; i < sample; i++ ) {
|
||||
var t = i / sample;
|
||||
var pos = _path.getPointRatio(t);
|
||||
path_points = array_verify(path_points, sample);
|
||||
for( var i = 0; i < sample; i++ )
|
||||
path_points[i] = _path.getPointRatio(i * _step, array_safe_get(path_points, i, undefined));
|
||||
|
||||
array_push(points, pos);
|
||||
}
|
||||
|
||||
var triangles = polygon_triangulate(points);
|
||||
var tri = polygon_triangulate(path_points);
|
||||
triangles = tri[0];
|
||||
point_simp = tri[1];
|
||||
|
||||
draw_set_color(_color);
|
||||
draw_primitive_begin(pr_trianglelist);
|
||||
|
|
|
@ -195,7 +195,7 @@ function Node_Shape_Polygon(_x, _y, _group = noone) : Node_Processor(_x, _y, _gr
|
|||
var shapes = [];
|
||||
for( var i = 0, n = array_length(points); i < n; i++ ) {
|
||||
if(points[i].type == SHAPE_TYPE.points)
|
||||
shapes[i] = polygon_triangulate(points[i].points);
|
||||
shapes[i] = polygon_triangulate(points[i].points)[0];
|
||||
|
||||
else if(points[i].type == SHAPE_TYPE.triangles)
|
||||
shapes[i] = points[i].triangles;
|
||||
|
|
Loading…
Reference in a new issue