|
@@ -4,6 +4,193 @@
|
|
|
|
|
|
THREE.ShapeUtils = {
|
|
|
|
|
|
+ triangulate: ( function () {
|
|
|
+
|
|
|
+ /**
|
|
|
+ * This code is a quick port of code written in C++ which was submitted to
|
|
|
+ * flipcode.com by John W. Ratcliff // July 22, 2000
|
|
|
+ * See original code and more information here:
|
|
|
+ * http://www.flipcode.com/archives/Efficient_Polygon_Triangulation.shtml
|
|
|
+ *
|
|
|
+ * ported to actionscript by Zevan Rosser
|
|
|
+ * www.actionsnippet.com
|
|
|
+ *
|
|
|
+ * ported to javascript by Joshua Koo
|
|
|
+ * http://www.lab4games.net/zz85/blog
|
|
|
+ *
|
|
|
+ */
|
|
|
+
|
|
|
+ // calculate area of the contour polygon
|
|
|
+
|
|
|
+ function area( contour ) {
|
|
|
+
|
|
|
+ var n = contour.length;
|
|
|
+ var a = 0.0;
|
|
|
+
|
|
|
+ for ( var p = n - 1, q = 0; q < n; p = q ++ ) {
|
|
|
+
|
|
|
+ a += contour[ p ].x * contour[ q ].y - contour[ q ].x * contour[ p ].y;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return a * 0.5;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ THREE.ShapeUtils.area = area;
|
|
|
+
|
|
|
+ function snip( contour, u, v, w, n, verts ) {
|
|
|
+
|
|
|
+ var p;
|
|
|
+ var ax, ay, bx, by;
|
|
|
+ var cx, cy, px, py;
|
|
|
+
|
|
|
+ ax = contour[ verts[ u ] ].x;
|
|
|
+ ay = contour[ verts[ u ] ].y;
|
|
|
+
|
|
|
+ bx = contour[ verts[ v ] ].x;
|
|
|
+ by = contour[ verts[ v ] ].y;
|
|
|
+
|
|
|
+ cx = contour[ verts[ w ] ].x;
|
|
|
+ cy = contour[ verts[ w ] ].y;
|
|
|
+
|
|
|
+ if ( Number.EPSILON > ( ( ( bx - ax ) * ( cy - ay ) ) - ( ( by - ay ) * ( cx - ax ) ) ) ) return false;
|
|
|
+
|
|
|
+ var aX, aY, bX, bY, cX, cY;
|
|
|
+ var apx, apy, bpx, bpy, cpx, cpy;
|
|
|
+ var cCROSSap, bCROSScp, aCROSSbp;
|
|
|
+
|
|
|
+ aX = cx - bx; aY = cy - by;
|
|
|
+ bX = ax - cx; bY = ay - cy;
|
|
|
+ cX = bx - ax; cY = by - ay;
|
|
|
+
|
|
|
+ for ( p = 0; p < n; p ++ ) {
|
|
|
+
|
|
|
+ px = contour[ verts[ p ] ].x;
|
|
|
+ py = contour[ verts[ p ] ].y;
|
|
|
+
|
|
|
+ if ( ( ( px === ax ) && ( py === ay ) ) ||
|
|
|
+ ( ( px === bx ) && ( py === by ) ) ||
|
|
|
+ ( ( px === cx ) && ( py === cy ) ) ) continue;
|
|
|
+
|
|
|
+ apx = px - ax; apy = py - ay;
|
|
|
+ bpx = px - bx; bpy = py - by;
|
|
|
+ cpx = px - cx; cpy = py - cy;
|
|
|
+
|
|
|
+ // see if p is inside triangle abc
|
|
|
+
|
|
|
+ aCROSSbp = aX * bpy - aY * bpx;
|
|
|
+ cCROSSap = cX * apy - cY * apx;
|
|
|
+ bCROSScp = bX * cpy - bY * cpx;
|
|
|
+
|
|
|
+ if ( ( aCROSSbp >= - Number.EPSILON ) && ( bCROSScp >= - Number.EPSILON ) && ( cCROSSap >= - Number.EPSILON ) ) return false;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ return true;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ // takes in an contour array and returns
|
|
|
+
|
|
|
+ return function ( contour, indices ) {
|
|
|
+
|
|
|
+ var n = contour.length;
|
|
|
+
|
|
|
+ if ( n < 3 ) return null;
|
|
|
+
|
|
|
+ var result = [],
|
|
|
+ verts = [],
|
|
|
+ vertIndices = [];
|
|
|
+
|
|
|
+ /* we want a counter-clockwise polygon in verts */
|
|
|
+
|
|
|
+ var u, v, w;
|
|
|
+
|
|
|
+ if ( area( contour ) > 0.0 ) {
|
|
|
+
|
|
|
+ for ( v = 0; v < n; v ++ ) verts[ v ] = v;
|
|
|
+
|
|
|
+ } else {
|
|
|
+
|
|
|
+ for ( v = 0; v < n; v ++ ) verts[ v ] = ( n - 1 ) - v;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ var nv = n;
|
|
|
+
|
|
|
+ /* remove nv - 2 vertices, creating 1 triangle every time */
|
|
|
+
|
|
|
+ var count = 2 * nv; /* error detection */
|
|
|
+
|
|
|
+ for ( v = nv - 1; nv > 2; ) {
|
|
|
+
|
|
|
+ /* if we loop, it is probably a non-simple polygon */
|
|
|
+
|
|
|
+ if ( ( count -- ) <= 0 ) {
|
|
|
+
|
|
|
+ //** Triangulate: ERROR - probable bad polygon!
|
|
|
+
|
|
|
+ //throw ( "Warning, unable to triangulate polygon!" );
|
|
|
+ //return null;
|
|
|
+ // Sometimes warning is fine, especially polygons are triangulated in reverse.
|
|
|
+ console.warn( 'THREE.ShapeUtils: Unable to triangulate polygon! in triangulate()' );
|
|
|
+
|
|
|
+ if ( indices ) return vertIndices;
|
|
|
+ return result;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ /* three consecutive vertices in current polygon, <u,v,w> */
|
|
|
+
|
|
|
+ u = v; if ( nv <= u ) u = 0; /* previous */
|
|
|
+ v = u + 1; if ( nv <= v ) v = 0; /* new v */
|
|
|
+ w = v + 1; if ( nv <= w ) w = 0; /* next */
|
|
|
+
|
|
|
+ if ( snip( contour, u, v, w, nv, verts ) ) {
|
|
|
+
|
|
|
+ var a, b, c, s, t;
|
|
|
+
|
|
|
+ /* true names of the vertices */
|
|
|
+
|
|
|
+ a = verts[ u ];
|
|
|
+ b = verts[ v ];
|
|
|
+ c = verts[ w ];
|
|
|
+
|
|
|
+ /* output Triangle */
|
|
|
+
|
|
|
+ result.push( [ contour[ a ],
|
|
|
+ contour[ b ],
|
|
|
+ contour[ c ] ] );
|
|
|
+
|
|
|
+
|
|
|
+ vertIndices.push( [ verts[ u ], verts[ v ], verts[ w ] ] );
|
|
|
+
|
|
|
+ /* remove v from the remaining polygon */
|
|
|
+
|
|
|
+ for ( s = v, t = v + 1; t < nv; s ++, t ++ ) {
|
|
|
+
|
|
|
+ verts[ s ] = verts[ t ];
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ nv --;
|
|
|
+
|
|
|
+ /* reset error detection counter */
|
|
|
+
|
|
|
+ count = 2 * nv;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ if ( indices ) return vertIndices;
|
|
|
+ return result;
|
|
|
+
|
|
|
+ }
|
|
|
+
|
|
|
+ } )(),
|
|
|
+
|
|
|
triangulateShape: function ( contour, holes ) {
|
|
|
|
|
|
function point_in_segment_2D_colin( inSegPt1, inSegPt2, inOtherPt ) {
|
|
@@ -454,7 +641,7 @@ THREE.ShapeUtils = {
|
|
|
// remove holes by cutting paths to holes and adding them to the shape
|
|
|
var shapeWithoutHoles = removeHoles( contour, holes );
|
|
|
|
|
|
- var triangles = THREE.FontUtils.Triangulate( shapeWithoutHoles, false ); // True returns indices for points of spooled shape
|
|
|
+ var triangles = THREE.ShapeUtils.triangulate( shapeWithoutHoles, false ); // True returns indices for points of spooled shape
|
|
|
//console.log( "triangles",triangles, triangles.length );
|
|
|
|
|
|
// check all face vertices against all points map
|
|
@@ -485,7 +672,7 @@ THREE.ShapeUtils = {
|
|
|
|
|
|
isClockWise: function ( pts ) {
|
|
|
|
|
|
- return THREE.FontUtils.Triangulate.area( pts ) < 0;
|
|
|
+ return THREE.ShapeUtils.area( pts ) < 0;
|
|
|
|
|
|
},
|
|
|
|