Fix triangulation problem on overlapped points.

This commit is contained in:
Tanasart 2024-05-05 15:29:43 +07:00
parent 0f5c68c8c9
commit 9da78f0fe4
6 changed files with 100 additions and 57 deletions

View file

@ -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

View file

@ -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]);

View file

@ -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;
}

View file

@ -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;

View file

@ -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);

View file

@ -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;