From a9694e6b53a35a5b17cfe5ea76d927614110efc9 Mon Sep 17 00:00:00 2001 From: liabru Date: Tue, 12 Jan 2021 23:36:04 +0000 Subject: [PATCH] Squashed commit of the following: commit 421e56d37d738c8a97dcd01fcee858de54954efc Merge: 9c5325b 4eb61c0 Author: liabru Date: Tue Jan 12 23:33:43 2021 +0000 Merge branch 'removeDuplicatePoints' of https://github.com/tumult/matter-js into tumult-removeDuplicatePoints # Conflicts: # src/factory/Bodies.js commit 4eb61c004db49dd12767095c76c332b98432bccc Author: Jonathan Deutsch Date: Thu Jul 26 15:37:00 2018 -0700 change removeDuplicatePoints precision to default in docs commit 6c5d4065c2483a5ab74bc35242eefa62f4fa660c Author: Jonathan Deutsch Date: Thu Jul 26 14:33:39 2018 -0700 Add removeDuplicatePoints option from polygon-decomp 0.3.0 to Bodies.fromVertices() --- demo/lib/decomp.js | 66 ++++++++++++++++++++++++++++++++++++++++--- src/factory/Bodies.js | 6 +++- 2 files changed, 67 insertions(+), 5 deletions(-) diff --git a/demo/lib/decomp.js b/demo/lib/decomp.js index 61199082..ffd33bdf 100644 --- a/demo/lib/decomp.js +++ b/demo/lib/decomp.js @@ -4,6 +4,7 @@ module.exports = { quickDecomp: polygonQuickDecomp, isSimple: polygonIsSimple, removeCollinearPoints: polygonRemoveCollinearPoints, + removeDuplicatePoints: polygonRemoveDuplicatePoints, makeCCW: polygonMakeCCW }; @@ -179,6 +180,9 @@ function polygonMakeCCW(polygon){ // reverse poly if clockwise if (!isLeft(polygonAt(polygon, br - 1), polygonAt(polygon, br), polygonAt(polygon, br + 1))) { polygonReverse(polygon); + return true; + } else { + return false; } } @@ -243,6 +247,27 @@ function polygonCanSee(polygon, a,b) { return true; } +/** + * Check if two vertices in the polygon can see each other + * @method canSee2 + * @param {Number} a Vertex index 1 + * @param {Number} b Vertex index 2 + * @return {Boolean} + */ +function polygonCanSee2(polygon, a,b) { + // for each edge + for (var i = 0; i !== polygon.length; ++i) { + // ignore incident edges + if (i === a || i === b || (i + 1) % polygon.length === a || (i + 1) % polygon.length === b){ + continue; + } + if( lineSegmentsIntersect(polygonAt(polygon, a), polygonAt(polygon, b), polygonAt(polygon, i), polygonAt(polygon, i+1)) ){ + return false; + } + } + return true; +} + /** * Copy the polygon from vertex i to vertex j. * @method copy @@ -526,9 +551,12 @@ function polygonQuickDecomp(polygon, result,reflexVertices,steinerPoints,delta,m } for (var j = lowerIndex; j <= upperIndex; ++j) { - if (isLeftOn(polygonAt(poly, i - 1), polygonAt(poly, i), polygonAt(poly, j)) && isRightOn(polygonAt(poly, i + 1), polygonAt(poly, i), polygonAt(poly, j))) { + if ( + isLeftOn(polygonAt(poly, i - 1), polygonAt(poly, i), polygonAt(poly, j)) && + isRightOn(polygonAt(poly, i + 1), polygonAt(poly, i), polygonAt(poly, j)) + ) { d = sqdist(polygonAt(poly, i), polygonAt(poly, j)); - if (d < closestDist) { + if (d < closestDist && polygonCanSee2(poly, i, j)) { closestDist = d; closestIndex = j % polygon.length; } @@ -585,6 +613,23 @@ function polygonRemoveCollinearPoints(polygon, precision){ return num; } +/** + * Remove duplicate points in the polygon. + * @method removeDuplicatePoints + * @param {Number} [precision] The threshold to use when determining whether two points are the same. Use zero for best precision. + */ +function polygonRemoveDuplicatePoints(polygon, precision){ + for(var i=polygon.length-1; i>=1; --i){ + var pi = polygon[i]; + for(var j=i-1; j>=0; --j){ + if(points_eq(pi, polygon[j], precision)){ + polygon.splice(i,1); + continue; + } + } + } +} + /** * Check if two scalars are equal * @static @@ -596,9 +641,22 @@ function polygonRemoveCollinearPoints(polygon, precision){ */ function scalar_eq(a,b,precision){ precision = precision || 0; - return Math.abs(a-b) < precision; + return Math.abs(a-b) <= precision; +} + +/** + * Check if two points are equal + * @static + * @method points_eq + * @param {Array} a + * @param {Array} b + * @param {Number} [precision] + * @return {Boolean} + */ +function points_eq(a,b,precision){ + return scalar_eq(a[0],b[0],precision) && scalar_eq(a[1],b[1],precision); } },{}]},{},[1]) (1) -}); +}); \ No newline at end of file diff --git a/src/factory/Bodies.js b/src/factory/Bodies.js index 9103d5d5..fa4805ef 100644 --- a/src/factory/Bodies.js +++ b/src/factory/Bodies.js @@ -193,9 +193,10 @@ var Vector = require('../geometry/Vector'); * @param {bool} [flagInternal=false] * @param {number} [removeCollinear=0.01] * @param {number} [minimumArea=10] + * @param {number} [removeDuplicatePoints=0.01] * @return {body} */ - Bodies.fromVertices = function(x, y, vertexSets, options, flagInternal, removeCollinear, minimumArea) { + Bodies.fromVertices = function(x, y, vertexSets, options, flagInternal, removeCollinear, minimumArea, removeDuplicatePoints) { var globals = typeof global !== 'undefined' ? global : window, decomp, body, @@ -220,6 +221,7 @@ var Vector = require('../geometry/Vector'); flagInternal = typeof flagInternal !== 'undefined' ? flagInternal : false; removeCollinear = typeof removeCollinear !== 'undefined' ? removeCollinear : 0.01; minimumArea = typeof minimumArea !== 'undefined' ? minimumArea : 10; + removeDuplicatePoints = typeof removeDuplicatePoints !== 'undefined' ? removeDuplicatePoints : 0.01; if (!decomp) { Common.warn('Bodies.fromVertices: poly-decomp.js required. Could not decompose vertices. Fallback to convex hull.'); @@ -256,6 +258,8 @@ var Vector = require('../geometry/Vector'); decomp.makeCCW(concave); if (removeCollinear !== false) decomp.removeCollinearPoints(concave, removeCollinear); + if (removeDuplicatePoints !== false) + decomp.removeDuplicatePoints(concave, removeDuplicatePoints); // use the quick decomposition algorithm (Bayazit) var decomposed = decomp.quickDecomp(concave);