diff --git a/src/libtess.js/dict/Dict.js b/src/libtess.js/dict/Dict.js index 7cec28fa2e..b4e9fa8c7b 100644 --- a/src/libtess.js/dict/Dict.js +++ b/src/libtess.js/dict/Dict.js @@ -35,18 +35,21 @@ // require libtess /*global libtess */ + // TODO(bckenny): better typing for DictKey? actually libtess.ActiveRegion /** @typedef {Object} */ libtess.dictKey; // TODO(bckenny): better typing for all of this, really. no need not to eg use tess as frame directly + + /** * [Dict description] * * @constructor - * @param {Object} frame [description] - * @param {function(Object, Object, Object): boolean} leq [description] + * @param {Object} frame [description]. + * @param {function(Object, Object, Object): boolean} leq [description]. */ libtess.Dict = function(frame, leq) { /** @@ -72,29 +75,31 @@ libtess.Dict = function(frame, leq) { this.leq_ = /** @type {function(Object, libtess.dictKey, libtess.dictKey): boolean} */(leq); }; + /** * [deleteDict description] */ libtess.Dict.prototype.deleteDict = function() { // TODO(bckenny): unnecessary, I think. // for (var node = libtess.head.next; node !== libtess.head; node = node.next) { - // memFree(node); + // memFree(node); // } // memFree(dict); - + // NOTE(bckenny): nulled at callsite (sweep.doneEdgeDict_) }; + /** * [insertBefore description] - * @param {libtess.DictNode} node [description] - * @param {Object} key [description] - * @return {libtess.DictNode} [description] + * @param {libtess.DictNode} node [description]. + * @param {Object} key [description]. + * @return {libtess.DictNode} [description]. */ libtess.Dict.prototype.insertBefore = function(node, key) { do { node = node.prev; - } while(node.key !== null && !this.leq_(this.frame, node.key, key)); + } while (node.key !== null && !this.leq_(this.frame, node.key, key)); var newNode = new libtess.DictNode(); @@ -107,19 +112,21 @@ libtess.Dict.prototype.insertBefore = function(node, key) { return newNode; }; + /** * [insert description] - * @param {Object} key [description] - * @return {libtess.DictNode} [description] + * @param {Object} key [description]. + * @return {libtess.DictNode} [description]. */ libtess.Dict.prototype.insert = function(key) { // NOTE(bckenny): from a macro in dict.h/dict-list.h return this.insertBefore(this.head, key); }; + /** * [deleteNode description] - * @param {libtess.DictNode} node [description] + * @param {libtess.DictNode} node [description]. */ libtess.Dict.prototype.deleteNode = function(node) { // NOTE(bckenny): nulled at callsite (sweep.deleteRegion_) @@ -128,36 +135,39 @@ libtess.Dict.prototype.deleteNode = function(node) { // memFree( node ); TODO(bckenny) }; + /** * Search returns the node with the smallest key greater than or equal * to the given key. If there is no such key, returns a node whose * key is null. Similarly, max(d).getSucc() has a null key, etc. * - * @param {Object} key [description] - * @return {libtess.DictNode} [description] + * @param {Object} key [description]. + * @return {libtess.DictNode} [description]. */ libtess.Dict.prototype.search = function(key) { var node = this.head; do { node = node.next; - } while(node.key !== null && !this.leq_(this.frame, key, node.key)); + } while (node.key !== null && !this.leq_(this.frame, key, node.key)); return node; }; + /** * [getMin description] - * @return {libtess.DictNode} [description] + * @return {libtess.DictNode} [description]. */ libtess.Dict.prototype.getMin = function() { // NOTE(bckenny): from a macro in dict.h/dict-list.h return this.head.next; }; + /** * [getMax description] - * @return {libtess.DictNode} [description] + * @return {libtess.DictNode} [description]. */ libtess.Dict.prototype.getMax = function() { // NOTE(bckenny): from a macro in dict.h/dict-list.h diff --git a/src/libtess.js/dict/DictNode.js b/src/libtess.js/dict/DictNode.js index 12f7b5ca4d..5782f82b55 100644 --- a/src/libtess.js/dict/DictNode.js +++ b/src/libtess.js/dict/DictNode.js @@ -38,6 +38,8 @@ // TODO(bckenny): better typing for DictKey? + + /** * [DictNode description] * @constructor @@ -55,7 +57,7 @@ libtess.DictNode = function() { * @type {libtess.DictNode} */ this.next = null; - + /** * [prev description] * @type {libtess.DictNode} @@ -63,26 +65,29 @@ libtess.DictNode = function() { this.prev = null; }; + /** * [getKey description] - * @return {libtess.dictKey} [description] + * @return {libtess.dictKey} [description]. */ libtess.DictNode.prototype.getKey = function() { return this.key; }; + /** * [getSucc description] - * @return {libtess.DictNode} [description] + * @return {libtess.DictNode} [description]. */ libtess.DictNode.prototype.getSucc = function() { // TODO(bckenny): unabreviated naming? return this.next; }; + /** * [getPred description] - * @return {libtess.DictNode} [description] + * @return {libtess.DictNode} [description]. */ libtess.DictNode.prototype.getPred = function() { // TODO(bckenny): unabreviated naming? diff --git a/src/libtess.js/geom.js b/src/libtess.js/geom.js index dfc13a6453..1b95dad007 100644 --- a/src/libtess.js/geom.js +++ b/src/libtess.js/geom.js @@ -45,28 +45,31 @@ libtess.geom = function() { }; + /** * [vertEq description] * - * @param {libtess.GluVertex} u [description] - * @param {libtess.GluVertex} v [description] - * @return {boolean} [description] + * @param {libtess.GluVertex} u [description]. + * @param {libtess.GluVertex} v [description]. + * @return {boolean} [description]. */ libtess.geom.vertEq = function(u, v) { return u.s === v.s && u.t === v.t; }; + /** * Returns true if u is lexicographically <= v. * - * @param {libtess.GluVertex} u [description] - * @param {libtess.GluVertex} v [description] + * @param {libtess.GluVertex} u [description]. + * @param {libtess.GluVertex} v [description]. * @return {boolean} */ libtess.geom.vertLeq = function(u, v) { return (u.s < v.s) || (u.s === v.s && u.t <= v.t); }; + /** * Given three vertices u,v,w such that geom.vertLeq(u,v) && geom.vertLeq(v,w), * evaluates the t-coord of the edge uw at the s-coord of the vertex v. @@ -78,16 +81,16 @@ libtess.geom.vertLeq = function(u, v) { * let r be the negated result (this evaluates (uw)(v.s)), then * r is guaranteed to satisfy MIN(u.t,w.t) <= r <= MAX(u.t,w.t). * - * @param {libtess.GluVertex} u [description] - * @param {libtess.GluVertex} v [description] - * @param {libtess.GluVertex} w [description] - * @return {number} double + * @param {libtess.GluVertex} u [description]. + * @param {libtess.GluVertex} v [description]. + * @param {libtess.GluVertex} w [description]. + * @return {number} double. */ libtess.geom.edgeEval = function(u, v, w) { var gapL, gapR; libtess.assert(libtess.geom.vertLeq(u, v) && libtess.geom.vertLeq(v, w)); - + gapL = v.s - u.s; gapR = w.s - v.s; @@ -103,21 +106,22 @@ libtess.geom.edgeEval = function(u, v, w) { return 0; }; + /** * Returns a number whose sign matches geom.edgeEval(u,v,w) but which * is cheaper to evaluate. Returns > 0, == 0 , or < 0 * as v is above, on, or below the edge uw. * - * @param {libtess.GluVertex} u [description] - * @param {libtess.GluVertex} v [description] - * @param {libtess.GluVertex} w [description] - * @return {number} double + * @param {libtess.GluVertex} u [description]. + * @param {libtess.GluVertex} v [description]. + * @param {libtess.GluVertex} w [description]. + * @return {number} double. */ libtess.geom.edgeSign = function(u, v, w) { var gapL, gapR; libtess.assert(libtess.geom.vertLeq(u, v) && libtess.geom.vertLeq(v, w)); - + gapL = v.s - u.s; gapR = w.s - v.s; @@ -129,18 +133,20 @@ libtess.geom.edgeSign = function(u, v, w) { return 0; }; + /** * Version of VertLeq with s and t transposed. * Returns true if u is lexicographically <= v. * - * @param {libtess.GluVertex} u [description] - * @param {libtess.GluVertex} v [description] + * @param {libtess.GluVertex} u [description]. + * @param {libtess.GluVertex} v [description]. * @return {boolean} */ libtess.geom.transLeq = function(u, v) { return (u.t < v.t) || (u.t === v.t && u.s <= v.s); }; + /** * Version of geom.edgeEval with s and t transposed. * Given three vertices u,v,w such that geom.transLeq(u,v) && geom.transLeq(v,w), @@ -153,16 +159,16 @@ libtess.geom.transLeq = function(u, v) { * let r be the negated result (this evaluates (uw)(v.t)), then * r is guaranteed to satisfy MIN(u.s,w.s) <= r <= MAX(u.s,w.s). * - * @param {libtess.GluVertex} u [description] - * @param {libtess.GluVertex} v [description] - * @param {libtess.GluVertex} w [description] - * @return {number} double + * @param {libtess.GluVertex} u [description]. + * @param {libtess.GluVertex} v [description]. + * @param {libtess.GluVertex} w [description]. + * @return {number} double. */ libtess.geom.transEval = function(u, v, w) { var gapL, gapR; libtess.assert(libtess.geom.transLeq(u, v) && libtess.geom.transLeq(v, w)); - + gapL = v.t - u.t; gapR = w.t - v.t; @@ -178,22 +184,23 @@ libtess.geom.transEval = function(u, v, w) { return 0; }; + /** * Version of geom.edgeSign with s and t transposed. * Returns a number whose sign matches geom.transEval(u,v,w) but which * is cheaper to evaluate. Returns > 0, == 0 , or < 0 * as v is above, on, or below the edge uw. * - * @param {libtess.GluVertex} u [description] - * @param {libtess.GluVertex} v [description] - * @param {libtess.GluVertex} w [description] - * @return {number} double + * @param {libtess.GluVertex} u [description]. + * @param {libtess.GluVertex} v [description]. + * @param {libtess.GluVertex} w [description]. + * @return {number} double. */ libtess.geom.transSign = function(u, v, w) { var gapL, gapR; libtess.assert(libtess.geom.transLeq(u, v) && libtess.geom.transLeq(v, w)); - + gapL = v.t - u.t; gapR = w.t - v.t; @@ -205,37 +212,41 @@ libtess.geom.transSign = function(u, v, w) { return 0; }; + /** * [edgeGoesLeft description] * - * @param {libtess.GluHalfEdge} e [description] - * @return {boolean} [description] + * @param {libtess.GluHalfEdge} e [description]. + * @return {boolean} [description]. */ libtess.geom.edgeGoesLeft = function(e) { return libtess.geom.vertLeq(e.dst(), e.org); }; + /** * [edgeGoesRight description] * - * @param {libtess.GluHalfEdge} e [description] - * @return {boolean} [description] + * @param {libtess.GluHalfEdge} e [description]. + * @return {boolean} [description]. */ libtess.geom.edgeGoesRight = function(e) { return libtess.geom.vertLeq(e.org, e.dst()); }; + /** * [vertL1dist description] * - * @param {libtess.GluVertex} u [description] - * @param {libtess.GluVertex} v [description] - * @return {number} [description] + * @param {libtess.GluVertex} u [description]. + * @param {libtess.GluVertex} v [description]. + * @return {number} [description]. */ libtess.geom.vertL1dist = function(u, v) { return Math.abs(u.s - v.s) + Math.abs(u.t - v.t); }; + /** * For almost-degenerate situations, the results are not reliable. * Unless the floating-point arithmetic can be performed without @@ -243,15 +254,16 @@ libtess.geom.vertL1dist = function(u, v) { * on some degenerate inputs, so the client must have some way to * handle this situation. * - * @param {libtess.GluVertex} u [description] - * @param {libtess.GluVertex} v [description] - * @param {libtess.GluVertex} w [description] + * @param {libtess.GluVertex} u [description]. + * @param {libtess.GluVertex} v [description]. + * @param {libtess.GluVertex} w [description]. * @return {boolean} */ libtess.geom.vertCCW = function(u, v, w) { - return (u.s*(v.t - w.t) + v.s*(w.t - u.t) + w.s*(u.t - v.t)) >= 0; + return (u.s * (v.t - w.t) + v.s * (w.t - u.t) + w.s * (u.t - v.t)) >= 0; }; + /** * Given parameters a,x,b,y returns the value (b*x+a*y)/(a+b), * or (x+y)/2 if a==b==0. It requires that a,b >= 0, and enforces @@ -262,11 +274,11 @@ libtess.geom.vertCCW = function(u, v, w) { * even when a and b differ greatly in magnitude. * * @private - * @param {number} a [description] - * @param {number} x [description] - * @param {number} b [description] - * @param {number} y [description] - * @return {number} [description] + * @param {number} a [description]. + * @param {number} x [description]. + * @param {number} b [description]. + * @param {number} y [description]. + * @return {number} [description]. */ libtess.geom.interpolate_ = function(a, x, b, y) { //(a = (a < 0) ? 0 : a, b = (b < 0) ? 0 : b, ((a <= b) ? ((b == 0) ? ((x+y) / 2) : (x + (y-x) * (a/(a+b)))) : (y + (x-y) * (b/(a+b))))) @@ -275,25 +287,26 @@ libtess.geom.interpolate_ = function(a, x, b, y) { if (a <= b) { if (b === 0) { - return (x+y) / 2; + return (x + y) / 2; } else { - return x + (y-x) * (a/(a+b)); + return x + (y - x) * (a / (a + b)); } } else { - return y + (x-y) * (b/(a+b)); + return y + (x - y) * (b / (a + b)); } }; + /** * Given edges (o1,d1) and (o2,d2), compute their point of intersection. * The computed point is guaranteed to lie in the intersection of the * bounding rectangles defined by each edge. * - * @param {libtess.GluVertex} o1 [description] - * @param {libtess.GluVertex} d1 [description] - * @param {libtess.GluVertex} o2 [description] - * @param {libtess.GluVertex} d2 [description] - * @param {libtess.GluVertex} v output + * @param {libtess.GluVertex} o1 [description]. + * @param {libtess.GluVertex} d1 [description]. + * @param {libtess.GluVertex} o2 [description]. + * @param {libtess.GluVertex} d2 [description]. + * @param {libtess.GluVertex} v output. */ libtess.geom.edgeIntersect = function(o1, d1, o2, d2, v) { /* This is certainly not the most efficient way to find the intersection @@ -305,7 +318,7 @@ libtess.geom.edgeIntersect = function(o1, d1, o2, d2, v) { */ var z1, z2; var tmp; - + if (!libtess.geom.vertLeq(o1, d1)) { // Swap(o1, d1); tmp = o1; @@ -337,14 +350,14 @@ libtess.geom.edgeIntersect = function(o1, d1, o2, d2, v) { // Interpolate between o2 and d1 z1 = libtess.geom.edgeEval(o1, o2, d1); z2 = libtess.geom.edgeEval(o2, d1, d2); - if (z1+z2 < 0) { z1 = -z1; z2 = -z2; } + if (z1 + z2 < 0) { z1 = -z1; z2 = -z2; } v.s = libtess.geom.interpolate_(z1, o2.s, z2, d1.s); } else { // Interpolate between o2 and d2 z1 = libtess.geom.edgeSign(o1, o2, d1); z2 = -libtess.geom.edgeSign(o1, d2, d1); - if (z1+z2 < 0) { z1 = -z1; z2 = -z2; } + if (z1 + z2 < 0) { z1 = -z1; z2 = -z2; } v.s = libtess.geom.interpolate_(z1, o2.s, z2, d2.s); } @@ -380,14 +393,14 @@ libtess.geom.edgeIntersect = function(o1, d1, o2, d2, v) { // Interpolate between o2 and d1 z1 = libtess.geom.transEval(o1, o2, d1); z2 = libtess.geom.transEval(o2, d1, d2); - if (z1+z2 < 0) { z1 = -z1; z2 = -z2; } + if (z1 + z2 < 0) { z1 = -z1; z2 = -z2; } v.t = libtess.geom.interpolate_(z1, o2.t, z2, d1.t); } else { // Interpolate between o2 and d2 z1 = libtess.geom.transSign(o1, o2, d1); z2 = -libtess.geom.transSign(o1, d2, d1); - if (z1+z2 < 0) { z1 = -z1; z2 = -z2; } + if (z1 + z2 < 0) { z1 = -z1; z2 = -z2; } v.t = libtess.geom.interpolate_(z1, o2.t, z2, d2.t); } }; diff --git a/src/libtess.js/libtess.js b/src/libtess.js/libtess.js index b515a3b739..ccf47c5a83 100644 --- a/src/libtess.js/libtess.js +++ b/src/libtess.js/libtess.js @@ -32,13 +32,15 @@ * @author Brendan Kenny */ + /** * Base namespace. */ var libtess = libtess || {}; + /** - * @define {boolean} [DEBUG description] + * @define {boolean} [DEBUG description]. */ libtess.DEBUG = false; @@ -55,6 +57,7 @@ libtess.assert = function(condition, opt_message) { } }; + /** * [sweepDebugEvent description] * @param {libtess.GluTesselator} tess @@ -64,6 +67,7 @@ libtess.sweepDebugEvent = function(tess) { // sweep event updated }; + /** * [GLU_TESS_MAX_COORD description] * @type {number} @@ -72,6 +76,7 @@ libtess.sweepDebugEvent = function(tess) { libtess.GLU_TESS_MAX_COORD = 1e150; // NOTE(bckenny): from glu.pl generator + /** * [TRUE_PROJECT description] * TODO(bckenny): see alg-outline for description @@ -80,6 +85,7 @@ libtess.GLU_TESS_MAX_COORD = 1e150; */ libtess.TRUE_PROJECT = false; + /** * We cache vertex data for single-contour polygons so that we can * try a quick-and-dirty decomposition first. @@ -88,6 +94,7 @@ libtess.TRUE_PROJECT = false; */ libtess.TESS_MAX_CACHE = 100; + /** * [GLU_TESS_DEFAULT_TOLERANCE description] * @type {number} @@ -95,6 +102,7 @@ libtess.TESS_MAX_CACHE = 100; */ libtess.GLU_TESS_DEFAULT_TOLERANCE = 0.0; + /** * The begin/end calls must be properly nested. We keep track of * the current state to enforce the ordering. @@ -108,6 +116,7 @@ libtess.tessState = { T_IN_CONTOUR: 2 }; + /** * The input contours parition the plane into regions. A winding * rule determines which of these regions are inside the polygon. @@ -139,6 +148,7 @@ libtess.windingRule = { GLU_TESS_WINDING_ABS_GEQ_TWO: 100134 }; + /** * The type of primitive return from a "begin" callback. GL_LINE_LOOP is only * returned when GLU_TESS_BOUNDARY_ONLY is true. Values of enum match WebGL @@ -155,6 +165,7 @@ libtess.primitiveType = { GL_TRIANGLE_FAN: 6 }; + /** * The types of errors provided to error callback. * @enum {number} @@ -170,6 +181,7 @@ libtess.errorType = { GLU_TESS_NEED_COMBINE_CALLBACK: 100156 }; + /** * GLU enums necessary for this project. * see enumglu.spec @@ -203,9 +215,11 @@ libtess.gluEnum = { GLU_TESS_COMBINE_DATA: 100111 }; + /** @typedef {number} */ libtess.PQHandle; + // TODO(bckenny): better typing on key? /** @typedef {Object} */ libtess.PQKey; diff --git a/src/libtess.js/libtess/CachedVertex.js b/src/libtess.js/libtess/CachedVertex.js index 1632ad3ccb..82e6665dca 100644 --- a/src/libtess.js/libtess/CachedVertex.js +++ b/src/libtess.js/libtess/CachedVertex.js @@ -35,6 +35,8 @@ // require libtess /*global libtess */ + + /** * Cached vertex data for single-countour polygons for quick-and-dirty * decomposition. @@ -47,7 +49,7 @@ libtess.CachedVertex = function() { */ this.coords = [0, 0, 0]; // TODO(bckenny): better way to init? - + /** * [data description] * @type {Object} diff --git a/src/libtess.js/libtess/GluTesselator.js b/src/libtess.js/libtess/GluTesselator.js index 218953a7ff..634f248a32 100644 --- a/src/libtess.js/libtess/GluTesselator.js +++ b/src/libtess.js/libtess/GluTesselator.js @@ -47,6 +47,8 @@ // TODO(bckenny): create more javascript-y API, e.g. make gluTessEndPolygon async, // don't require so many temp objects created + + /** * [GluTesselator description] * @@ -97,13 +99,13 @@ libtess.GluTesselator = function() { */ this.normal = [0, 0, 0]; // TODO(bckenny): better way to init these arrays? - + /** * unit vector in s-direction (debugging) * @type {Array.} */ this.sUnit = [0, 0, 0]; - + /** * unit vector in t-direction (debugging) * @type {Array.} @@ -270,7 +272,7 @@ libtess.GluTesselator = function() { */ this.emptyCache = false; // TODO(bckenny): possibly rename to be clear it's a boolean - + /** * number of cached vertices * @type {number} @@ -289,6 +291,7 @@ libtess.GluTesselator = function() { } }; + /** * Destory the tesselator object. See README. */ @@ -298,10 +301,11 @@ libtess.GluTesselator.prototype.gluDeleteTess = function() { // memFree(tess); TODO(bckenny) }; + /** * Set properties for control over tesselation. See README. - * @param {libtess.gluEnum} which [description] - * @param {number|boolean} value [description] + * @param {libtess.gluEnum} which [description]. + * @param {number|boolean} value [description]. */ libtess.GluTesselator.prototype.gluTessProperty = function(which, value) { // TODO(bckenny): split into more setters? @@ -342,10 +346,11 @@ libtess.GluTesselator.prototype.gluTessProperty = function(which, value) { this.callErrorOrErrorData(libtess.gluEnum.GLU_INVALID_VALUE); }; + /** * Returns tessellator property - * @param {libtess.gluEnum} which [description] - * @return {number|boolean} [description] + * @param {libtess.gluEnum} which [description]. + * @return {number|boolean} [description]. */ libtess.GluTesselator.prototype.gluGetTessProperty = function(which) { // TODO(bckenny): as above, split into more getters? and improve on switch statement @@ -373,10 +378,11 @@ libtess.GluTesselator.prototype.gluGetTessProperty = function(which) { default: this.callErrorOrErrorData(libtess.gluEnum.GLU_INVALID_ENUM); break; - } - return false; + } + return false; }; + /** * Lets the user supply the polygon normal, if known. All input data * is projected into a plane perpendicular to the normal before @@ -386,9 +392,9 @@ libtess.GluTesselator.prototype.gluGetTessProperty = function(which) { * you know that all polygons lie in the x-y plane, call * "tess.gluTessNormal(0.0, 0.0, 1.0)" before rendering any polygons. * - * @param {number} x [description] - * @param {number} y [description] - * @param {number} z [description] + * @param {number} x [description]. + * @param {number} y [description]. + * @param {number} z [description]. */ libtess.GluTesselator.prototype.gluTessNormal = function(x, y, z) { this.normal[0] = x; @@ -396,17 +402,18 @@ libtess.GluTesselator.prototype.gluTessNormal = function(x, y, z) { this.normal[2] = z; }; + /** * Specify callbacks. See README. A null or undefined opt_fn removes current callback. * - * @param {libtess.gluEnum} which [description] - * @param {?function()=} opt_fn [description] + * @param {libtess.gluEnum} which [description]. + * @param {?function()=} opt_fn [description]. */ libtess.GluTesselator.prototype.gluTessCallback = function(which, opt_fn) { var fn = !opt_fn ? null : opt_fn; // TODO(bckenny): better opt_fn typing? - switch(which) { + switch (which) { case libtess.gluEnum.GLU_TESS_BEGIN: this.callBegin_ = /** @type {function(libtess.primitiveType)} */ (fn); return; @@ -473,12 +480,13 @@ libtess.GluTesselator.prototype.gluTessCallback = function(which, opt_fn) { } }; + /** * Specify a vertex and associated data. Must be within calls to * beginContour/endContour. See README. * - * @param {Array.} coords [description] - * @param {Object} data [description] + * @param {Array.} coords [description]. + * @param {Object} data [description]. */ libtess.GluTesselator.prototype.gluTessVertex = function(coords, data) { var tooLarge = false; @@ -523,9 +531,10 @@ libtess.GluTesselator.prototype.gluTessVertex = function(coords, data) { this.addVertex_(clamped, data); }; + /** * [gluTessBeginPolygon description] - * @param {Object} data Client data for current polygon + * @param {Object} data Client data for current polygon. */ libtess.GluTesselator.prototype.gluTessBeginPolygon = function(data) { this.requireState_(libtess.tessState.T_DORMANT); @@ -538,6 +547,7 @@ libtess.GluTesselator.prototype.gluTessBeginPolygon = function(data) { this.polygonData_ = data; }; + /** * [gluTessBeginContour description] */ @@ -555,6 +565,7 @@ libtess.GluTesselator.prototype.gluTessBeginContour = function() { } }; + /** * [gluTessEndContour description] */ @@ -563,6 +574,7 @@ libtess.GluTesselator.prototype.gluTessEndContour = function() { this.state = libtess.tessState.T_IN_POLYGON; }; + /** * [gluTessEndPolygon description] */ @@ -644,6 +656,7 @@ libtess.GluTesselator.prototype.gluTessEndPolygon = function() { this.mesh = null; }; + /** * Return the tessellator to its original dormant state. * @private @@ -657,10 +670,11 @@ libtess.GluTesselator.prototype.makeDormant_ = function() { this.mesh = null; }; + /** * [requireState_ description] * @private - * @param {libtess.tessState} state [description] + * @param {libtess.tessState} state [description]. */ libtess.GluTesselator.prototype.requireState_ = function(state) { if (this.state !== state) { @@ -668,10 +682,11 @@ libtess.GluTesselator.prototype.requireState_ = function(state) { } }; + /** * [gotoState_ description] * @private - * @param {libtess.tessState} newState [description] + * @param {libtess.tessState} newState [description]. */ libtess.GluTesselator.prototype.gotoState_ = function(newState) { while (this.state !== newState) { @@ -711,11 +726,12 @@ libtess.GluTesselator.prototype.gotoState_ = function(newState) { } }; + /** * [addVertex_ description] * @private - * @param {Array.} coords [description] - * @param {Object} data [description] + * @param {Array.} coords [description]. + * @param {Object} data [description]. */ libtess.GluTesselator.prototype.addVertex_ = function(coords, data) { var e = this.lastEdge_; @@ -736,7 +752,7 @@ libtess.GluTesselator.prototype.addVertex_ = function(coords, data) { e.org.coords[0] = coords[0]; e.org.coords[1] = coords[1]; e.org.coords[2] = coords[2]; - + // The winding of an edge says how the winding number changes as we // cross from the edge''s right face to its left face. We add the // vertices in such an order that a CCW contour will add +1 to @@ -747,11 +763,12 @@ libtess.GluTesselator.prototype.addVertex_ = function(coords, data) { this.lastEdge_ = e; }; + /** * [cacheVertex_ description] * @private - * @param {Array.} coords [description] - * @param {Object} data [description] + * @param {Array.} coords [description]. + * @param {Object} data [description]. */ libtess.GluTesselator.prototype.cacheVertex_ = function(coords, data) { var v = this.cache[this.cacheCount]; @@ -763,6 +780,7 @@ libtess.GluTesselator.prototype.cacheVertex_ = function(coords, data) { ++this.cacheCount; }; + /** * [emptyCache_ description] * @private @@ -780,13 +798,14 @@ libtess.GluTesselator.prototype.emptyCache_ = function() { this.emptyCache = false; }; + // TODO(bckenny): all following conditional callbacks could be simplified // TODO(bckenny): using null for now, but may rework // TODO(bckenny): should add documentation that references in callback are volatile (or make a copy) // see README callback descriptions /** * [callBeginOrBeginData description] - * @param {libtess.primitiveType} type [description] + * @param {libtess.primitiveType} type [description]. */ libtess.GluTesselator.prototype.callBeginOrBeginData = function(type) { if (this.callBeginData_) { @@ -797,9 +816,10 @@ libtess.GluTesselator.prototype.callBeginOrBeginData = function(type) { } }; + /** * [callVertexOrVertexData description] - * @param {Object} data [description] + * @param {Object} data [description]. */ libtess.GluTesselator.prototype.callVertexOrVertexData = function(data) { if (this.callVertexData_) { @@ -810,9 +830,10 @@ libtess.GluTesselator.prototype.callVertexOrVertexData = function(data) { } }; + /** * [callEdgeFlagOrEdgeFlagData description] - * @param {boolean} flag [description] + * @param {boolean} flag [description]. */ libtess.GluTesselator.prototype.callEdgeFlagOrEdgeFlagData = function(flag) { if (this.callEdgeFlagData_) { @@ -823,6 +844,7 @@ libtess.GluTesselator.prototype.callEdgeFlagOrEdgeFlagData = function(flag) { } }; + /** * [callEndOrEndData description] */ @@ -835,12 +857,13 @@ libtess.GluTesselator.prototype.callEndOrEndData = function() { } }; + /** * [callCombineOrCombineData description] - * @param {Array.} coords [description] - * @param {Array.} data [description] - * @param {Array.} weight [description] - * @return {Object} Interpolated vertex + * @param {Array.} coords [description]. + * @param {Array.} data [description]. + * @param {Array.} weight [description]. + * @return {Object} Interpolated vertex. */ libtess.GluTesselator.prototype.callCombineOrCombineData = function(coords, data, weight) { @@ -860,10 +883,11 @@ libtess.GluTesselator.prototype.callCombineOrCombineData = return interpData; }; + // TODO(bckenny): combine the enums in libtess /** * [callErrorOrErrorData description] - * @param {(libtess.errorType|libtess.gluEnum)} errno [description] + * @param {(libtess.errorType|libtess.gluEnum)} errno [description]. */ libtess.GluTesselator.prototype.callErrorOrErrorData = function(errno) { if (this.callErrorData_) { diff --git a/src/libtess.js/mesh.js b/src/libtess.js/mesh.js index bba7ca7124..9ed7c5fc5e 100644 --- a/src/libtess.js/mesh.js +++ b/src/libtess.js/mesh.js @@ -48,12 +48,13 @@ libtess.mesh = function() { /****************** Basic Edge Operations **********************/ + /** * makeEdge creates one edge, two vertices, and a loop (face). * The loop consists of the two new half-edges. * - * @param {libtess.GluMesh} mesh [description] - * @return {libtess.GluHalfEdge} [description] + * @param {libtess.GluMesh} mesh [description]. + * @return {libtess.GluHalfEdge} [description]. */ libtess.mesh.makeEdge = function(mesh) { // TODO(bckenny): probably move to GluMesh, but needs Make* methods with it @@ -62,12 +63,13 @@ libtess.mesh.makeEdge = function(mesh) { // complete edge with vertices and face (see mesh.makeEdgePair_) libtess.mesh.makeVertex_(e, mesh.vHead); - libtess.mesh.makeVertex_(e.sym, mesh.vHead ); + libtess.mesh.makeVertex_(e.sym, mesh.vHead); libtess.mesh.makeFace_(e, mesh.fHead); return e; }; + /** * meshSplice(eOrg, eDst) is the basic operation for changing the * mesh connectivity and topology. It changes the mesh so that @@ -92,8 +94,8 @@ libtess.mesh.makeEdge = function(mesh) { * If eDst == eOrg.oNext, the new vertex will have a single edge. * If eDst == eOrg.oPrev(), the old vertex will have a single edge. * - * @param {libtess.GluHalfEdge} eOrg [description] - * @param {libtess.GluHalfEdge} eDst [description] + * @param {libtess.GluHalfEdge} eOrg [description]. + * @param {libtess.GluHalfEdge} eDst [description]. */ libtess.mesh.meshSplice = function(eOrg, eDst) { // TODO: more descriptive name? @@ -135,6 +137,7 @@ libtess.mesh.meshSplice = function(eOrg, eDst) { } }; + /** * deleteEdge(eDel) removes the edge eDel. There are several cases: * if (eDel.lFace != eDel.rFace()), we join two loops into one; the loop @@ -146,7 +149,7 @@ libtess.mesh.meshSplice = function(eOrg, eDst) { * plus a few calls to memFree, but this would allocate and delete * unnecessary vertices and faces. * - * @param {libtess.GluHalfEdge} eDel [description] + * @param {libtess.GluHalfEdge} eDel [description]. */ libtess.mesh.deleteEdge = function(eDel) { var eDelSym = eDel.sym; @@ -160,7 +163,7 @@ libtess.mesh.deleteEdge = function(eDel) { libtess.mesh.killFace_(eDel.lFace, eDel.rFace()); } - if (eDel.oNext === eDel ) { + if (eDel.oNext === eDel) { libtess.mesh.killVertex_(eDel.org, null); } else { @@ -178,7 +181,7 @@ libtess.mesh.deleteEdge = function(eDel) { // Claim: the mesh is now in a consistent state, except that eDel.org // may have been deleted. Now we disconnect eDel.dst(). - if (eDelSym.oNext === eDelSym ) { + if (eDelSym.oNext === eDelSym) { libtess.mesh.killVertex_(eDelSym.org, null); libtess.mesh.killFace_(eDelSym.lFace, null); @@ -199,13 +202,14 @@ libtess.mesh.deleteEdge = function(eDel) { * operations above. They are provided for convenience and efficiency. */ + /** * addEdgeVertex(eOrg) creates a new edge eNew such that * eNew == eOrg.lNext, and eNew.dst() is a newly created vertex. * eOrg and eNew will have the same left face. * - * @param {libtess.GluHalfEdge} eOrg [description] - * @return {libtess.GluHalfEdge} [description] + * @param {libtess.GluHalfEdge} eOrg [description]. + * @return {libtess.GluHalfEdge} [description]. */ libtess.mesh.addEdgeVertex = function(eOrg) { // TODO(bckenny): why is it named this? @@ -219,20 +223,21 @@ libtess.mesh.addEdgeVertex = function(eOrg) { // Set the vertex and face information eNew.org = eOrg.dst(); - libtess.mesh.makeVertex_(eNewSym, eNew.org ); + libtess.mesh.makeVertex_(eNewSym, eNew.org); eNew.lFace = eNewSym.lFace = eOrg.lFace; return eNew; }; + /** * splitEdge(eOrg) splits eOrg into two edges eOrg and eNew, * such that eNew == eOrg.lNext. The new vertex is eOrg.dst() == eNew.org. * eOrg and eNew will have the same left face. * - * @param {libtess.GluHalfEdge} eOrg [description] - * @return {!libtess.GluHalfEdge} [description] + * @param {libtess.GluHalfEdge} eOrg [description]. + * @return {!libtess.GluHalfEdge} [description]. */ libtess.mesh.splitEdge = function(eOrg) { var tempHalfEdge = libtess.mesh.addEdgeVertex(eOrg); @@ -252,6 +257,7 @@ libtess.mesh.splitEdge = function(eOrg) { return eNew; }; + /** * connect(eOrg, eDst) creates a new edge from eOrg.dst() * to eDst.org, and returns the corresponding half-edge eNew. @@ -263,9 +269,9 @@ libtess.mesh.splitEdge = function(eOrg) { * If (eOrg.lNext == eDst), the old face is reduced to a single edge. * If (eOrg.lNext.lNext == eDst), the old face is reduced to two edges. * - * @param {libtess.GluHalfEdge} eOrg [description] - * @param {libtess.GluHalfEdge} eDst [description] - * @return {!libtess.GluHalfEdge} [description] + * @param {libtess.GluHalfEdge} eOrg [description]. + * @param {libtess.GluHalfEdge} eDst [description]. + * @return {!libtess.GluHalfEdge} [description]. */ libtess.mesh.connect = function(eOrg, eDst) { var joiningLoops = false; @@ -292,13 +298,14 @@ libtess.mesh.connect = function(eOrg, eDst) { if (!joiningLoops) { // We split one loop into two -- the new loop is eNew.lFace - libtess.mesh.makeFace_(eNew, eOrg.lFace ); + libtess.mesh.makeFace_(eNew, eOrg.lFace); } return eNew; }; /******************** Other Operations **********************/ + /** * zapFace(fZap) destroys a face and removes it from the * global face list. All edges of fZap will have a null pointer as their @@ -307,7 +314,7 @@ libtess.mesh.connect = function(eOrg, eDst) { * An entire mesh can be deleted by zapping its faces, one at a time, * in any order. Zapped faces cannot be used in further mesh operations! * - * @param {libtess.GluFace} fZap [description] + * @param {libtess.GluFace} fZap [description]. */ libtess.mesh.zapFace = function(fZap) { var eStart = fZap.anEdge; @@ -343,7 +350,7 @@ libtess.mesh.zapFace = function(fZap) { } libtess.mesh.killEdge_(e); } - } while(e !== eStart); + } while (e !== eStart); // delete from circular doubly-linked list var fPrev = fZap.prev; @@ -355,13 +362,14 @@ libtess.mesh.zapFace = function(fZap) { // TODO(bckenny): probably null at callsite }; + /** * meshUnion() forms the union of all structures in * both meshes, and returns the new mesh (the old meshes are destroyed). * - * @param {libtess.GluMesh} mesh1 [description] - * @param {libtess.GluMesh} mesh2 [description] - * @return {libtess.GluMesh} [description] + * @param {libtess.GluMesh} mesh1 [description]. + * @param {libtess.GluMesh} mesh2 [description]. + * @return {libtess.GluMesh} [description]. */ libtess.mesh.meshUnion = function(mesh1, mesh2) { // TODO(bceknny): probably move to GluMesh method @@ -400,9 +408,10 @@ libtess.mesh.meshUnion = function(mesh1, mesh2) { return mesh1; }; + /** * deleteMesh(mesh) will free all storage for any valid mesh. - * @param {libtess.GluMesh} mesh [description] + * @param {libtess.GluMesh} mesh [description]. */ libtess.mesh.deleteMesh = function(mesh) { // TODO(bckenny): unnecessary, I think. @@ -412,6 +421,7 @@ libtess.mesh.deleteMesh = function(mesh) { /************************ Utility Routines ************************/ + /** * Creates a new pair of half-edges which form their own loop. * No vertex or face structures are allocated, but these must be assigned @@ -420,8 +430,8 @@ libtess.mesh.deleteMesh = function(mesh) { * TODO(bckenny): warning about eNext strictly being first of pair? (see code) * * @private - * @param {libtess.GluHalfEdge} eNext [description] - * @return {libtess.GluHalfEdge} [description] + * @param {libtess.GluHalfEdge} eNext [description]. + * @return {libtess.GluHalfEdge} [description]. */ libtess.mesh.makeEdgePair_ = function(eNext) { var e = new libtess.GluHalfEdge(); @@ -430,7 +440,7 @@ libtess.mesh.makeEdgePair_ = function(eNext) { // TODO(bckenny): how do we ensure this? see above comment in jsdoc // Make sure eNext points to the first edge of the edge pair // if (eNext->Sym < eNext ) { eNext = eNext->Sym; } - + // NOTE(bckenny): check this for bugs in current implementation! // Insert in circular doubly-linked list before eNext. @@ -452,6 +462,7 @@ libtess.mesh.makeEdgePair_ = function(eNext) { return e; }; + /** * splice_ is best described by the Guibas/Stolfi paper or the * CS348a notes. Basically, it modifies the mesh so that @@ -460,8 +471,8 @@ libtess.mesh.makeEdgePair_ = function(eNext) { * For more explanation see mesh.meshSplice below. * * @private - * @param {libtess.GluHalfEdge} a [description] - * @param {libtess.GluHalfEdge} b [description] + * @param {libtess.GluHalfEdge} a [description]. + * @param {libtess.GluHalfEdge} b [description]. */ libtess.mesh.splice_ = function(a, b) { var aONext = a.oNext; @@ -473,6 +484,7 @@ libtess.mesh.splice_ = function(a, b) { b.oNext = aONext; }; + /** * makeVertex_(eOrig, vNext) attaches a new vertex and makes it the * origin of all edges in the vertex loop to which eOrig belongs. "vNext" gives @@ -483,8 +495,8 @@ libtess.mesh.splice_ = function(a, b) { * NOTE: unlike original, acutally allocates new vertex. * * @private - * @param {libtess.GluHalfEdge} eOrig [description] - * @param {libtess.GluVertex} vNext [description] + * @param {libtess.GluHalfEdge} eOrig [description]. + * @param {libtess.GluVertex} vNext [description]. */ libtess.mesh.makeVertex_ = function(eOrig, vNext) { // insert in circular doubly-linked list before vNext @@ -502,9 +514,10 @@ libtess.mesh.makeVertex_ = function(eOrig, vNext) { do { e.org = vNew; e = e.oNext; - } while(e !== eOrig); + } while (e !== eOrig); }; + /** * makeFace_(eOrig, fNext) attaches a new face and makes it the left * face of all edges in the face loop to which eOrig belongs. "fNext" gives @@ -515,8 +528,8 @@ libtess.mesh.makeVertex_ = function(eOrig, vNext) { * NOTE: unlike original, acutally allocates new face. * * @private - * @param {libtess.GluHalfEdge} eOrig [description] - * @param {libtess.GluFace} fNext [description] + * @param {libtess.GluHalfEdge} eOrig [description]. + * @param {libtess.GluFace} fNext [description]. */ libtess.mesh.makeFace_ = function(eOrig, fNext) { // insert in circular doubly-linked list before fNext @@ -536,15 +549,16 @@ libtess.mesh.makeFace_ = function(eOrig, fNext) { do { e.lFace = fNew; e = e.lNext; - } while(e !== eOrig); + } while (e !== eOrig); }; + /** * killEdge_ destroys an edge (the half-edges eDel and eDel.sym), * and removes from the global edge list. * * @private - * @param {libtess.GluHalfEdge} eDel [description] + * @param {libtess.GluHalfEdge} eDel [description]. */ libtess.mesh.killEdge_ = function(eDel) { // TODO(bckenny): in this case, no need to worry(?), but check when checking mesh.makeEdgePair_ @@ -561,13 +575,14 @@ libtess.mesh.killEdge_ = function(eDel) { // TODO(bckenny): need to null at callsites? }; + /** * killVertex_ destroys a vertex and removes it from the global * vertex list. It updates the vertex loop to point to a given new vertex. * * @private - * @param {libtess.GluVertex} vDel [description] - * @param {libtess.GluVertex} newOrg [description] + * @param {libtess.GluVertex} vDel [description]. + * @param {libtess.GluVertex} newOrg [description]. */ libtess.mesh.killVertex_ = function(vDel, newOrg) { var eStart = vDel.anEdge; @@ -577,7 +592,7 @@ libtess.mesh.killVertex_ = function(vDel, newOrg) { do { e.org = newOrg; e = e.oNext; - } while(e !== eStart); + } while (e !== eStart); // delete from circular doubly-linked list var vPrev = vDel.prev; @@ -589,13 +604,14 @@ libtess.mesh.killVertex_ = function(vDel, newOrg) { // TODO(bckenny): need to null at callsites? }; + /** * killFace_ destroys a face and removes it from the global face * list. It updates the face loop to point to a given new face. * * @private - * @param {libtess.GluFace} fDel [description] - * @param {libtess.GluFace} newLFace [description] + * @param {libtess.GluFace} fDel [description]. + * @param {libtess.GluFace} newLFace [description]. */ libtess.mesh.killFace_ = function(fDel, newLFace) { var eStart = fDel.anEdge; @@ -605,7 +621,7 @@ libtess.mesh.killFace_ = function(fDel, newLFace) { do { e.lFace = newLFace; e = e.lNext; - } while(e !== eStart); + } while (e !== eStart); // delete from circular doubly-linked list var fPrev = fDel.prev; diff --git a/src/libtess.js/mesh/GluFace.js b/src/libtess.js/mesh/GluFace.js index 4fd834ad86..76ee91f854 100644 --- a/src/libtess.js/mesh/GluFace.js +++ b/src/libtess.js/mesh/GluFace.js @@ -36,14 +36,16 @@ // requre libtess.GluHalfEdge /*global libtess */ + + /** * Each face has a pointer to the next and previous faces in the * circular list, and a pointer to a half-edge with this face as * the left face (null if this is the dummy header). There is also * a field "data" for client data. * - * @param {libtess.GluFace=} opt_nextFace [description] - * @param {libtess.GluFace=} opt_prevFace [description] + * @param {libtess.GluFace=} opt_nextFace [description]. + * @param {libtess.GluFace=} opt_prevFace [description]. * @constructor */ libtess.GluFace = function(opt_nextFace, opt_prevFace) { @@ -66,7 +68,7 @@ libtess.GluFace = function(opt_nextFace, opt_prevFace) { * @type {libtess.GluHalfEdge} */ this.anEdge = null; - + /** * room for client's data * @type {Object} @@ -78,13 +80,13 @@ libtess.GluFace = function(opt_nextFace, opt_prevFace) { * @type {libtess.GluFace} */ this.trail = null; - + /** * Flag for conversion to strips. * @type {boolean} */ this.marked = false; - + /** * This face is in the polygon interior. * @type {boolean} diff --git a/src/libtess.js/mesh/GluHalfEdge.js b/src/libtess.js/mesh/GluHalfEdge.js index 25c947add3..28bf8d1bb8 100644 --- a/src/libtess.js/mesh/GluHalfEdge.js +++ b/src/libtess.js/mesh/GluHalfEdge.js @@ -38,6 +38,8 @@ // require libtess.ActiveRegion /*global libtess */ + + /** * The fundamental data structure is the "half-edge". Two half-edges * go together to make an edge, but they point in opposite directions. @@ -63,12 +65,12 @@ * e.sym stores a pointer in the opposite direction, thus it is * always true that e.sym.next.sym.next === e. * - * @param {libtess.GluHalfEdge=} opt_nextEdge [description] + * @param {libtess.GluHalfEdge=} opt_nextEdge [description]. * @constructor */ libtess.GluHalfEdge = function(opt_nextEdge) { // TODO(bckenny): are these the right defaults? (from gl_meshNewMesh requirements) - + /** * doubly-linked list (prev==sym->next) * @type {!libtess.GluHalfEdge} @@ -108,7 +110,7 @@ libtess.GluHalfEdge = function(opt_nextEdge) { // Internal data (keep hidden) // NOTE(bckenny): can't be private, though... - + /** * a region with this upper edge (see sweep.js) * @type {libtess.ActiveRegion} @@ -126,65 +128,73 @@ libtess.GluHalfEdge = function(opt_nextEdge) { // TODO(bckenny): using methods as aliases for sym connections for now. // not sure about this approach. getters? renames? + /** * [rFace description] - * @return {libtess.GluFace} [description] + * @return {libtess.GluFace} [description]. */ libtess.GluHalfEdge.prototype.rFace = function() { return this.sym.lFace; }; + /** * [dst description] - * @return {libtess.GluVertex} [description] + * @return {libtess.GluVertex} [description]. */ libtess.GluHalfEdge.prototype.dst = function() { return this.sym.org; }; + /** * [oPrev description] - * @return {libtess.GluHalfEdge} [description] + * @return {libtess.GluHalfEdge} [description]. */ libtess.GluHalfEdge.prototype.oPrev = function() { return this.sym.lNext; }; + /** * [lPrev description] - * @return {libtess.GluHalfEdge} [description] + * @return {libtess.GluHalfEdge} [description]. */ libtess.GluHalfEdge.prototype.lPrev = function() { return this.oNext.sym; }; + /** * [dPrev description] - * @return {libtess.GluHalfEdge} [description] + * @return {libtess.GluHalfEdge} [description]. */ libtess.GluHalfEdge.prototype.dPrev = function() { return this.lNext.sym; }; + /** * [rPrev description] - * @return {libtess.GluHalfEdge} [description] + * @return {libtess.GluHalfEdge} [description]. */ libtess.GluHalfEdge.prototype.rPrev = function() { return this.sym.oNext; }; + /** * [dNext description] - * @return {libtess.GluHalfEdge} [description] + * @return {libtess.GluHalfEdge} [description]. */ libtess.GluHalfEdge.prototype.dNext = function() { return this.rPrev().sym; }; + /** * [rNext description] - * @return {libtess.GluHalfEdge} [description] + * @return {libtess.GluHalfEdge} [description]. */ libtess.GluHalfEdge.prototype.rNext = function() { return this.oPrev().sym; diff --git a/src/libtess.js/mesh/GluMesh.js b/src/libtess.js/mesh/GluMesh.js index c1c9df099e..78c6a18660 100644 --- a/src/libtess.js/mesh/GluMesh.js +++ b/src/libtess.js/mesh/GluMesh.js @@ -37,6 +37,8 @@ // require libtess.GluVertex /*global libtess */ + + /** * Creates a new mesh with no edges, no vertices, * and no loops (what we usually call a "face"). @@ -61,7 +63,7 @@ libtess.GluMesh = function() { * @type {libtess.GluHalfEdge} */ this.eHead = new libtess.GluHalfEdge(); - + /** * and its symmetric counterpart * @type {libtess.GluHalfEdge} @@ -73,6 +75,7 @@ libtess.GluMesh = function() { this.eHeadSym.sym = this.eHead; }; + // TODO(bckenny): #ifndef NDEBUG /** * Checks mesh for self-consistency. @@ -85,7 +88,7 @@ libtess.GluMesh.prototype.checkMesh = function() { var fHead = this.fHead; var vHead = this.vHead; var eHead = this.eHead; - + var e; // faces @@ -101,7 +104,7 @@ libtess.GluMesh.prototype.checkMesh = function() { libtess.assert(e.oNext.sym.lNext === e); libtess.assert(e.lFace === f); e = e.lNext; - } while(e !== f.anEdge); + } while (e !== f.anEdge); } libtess.assert(f.prev === fPrev && f.anEdge === null && f.data === null); @@ -118,7 +121,7 @@ libtess.GluMesh.prototype.checkMesh = function() { libtess.assert(e.oNext.sym.lNext === e); libtess.assert(e.org === v); e = e.oNext; - } while(e !== v.anEdge); + } while (e !== v.anEdge); } libtess.assert(v.prev === vPrev && v.anEdge === null && v.data === null); diff --git a/src/libtess.js/mesh/GluVertex.js b/src/libtess.js/mesh/GluVertex.js index f1ea05199b..64d49833f6 100644 --- a/src/libtess.js/mesh/GluVertex.js +++ b/src/libtess.js/mesh/GluVertex.js @@ -35,14 +35,16 @@ // requre libtess.GluHalfEdge /*global libtess */ + + /** * Each vertex has a pointer to next and previous vertices in the * circular list, and a pointer to a half-edge with this vertex as * the origin (null if this is the dummy header). There is also a * field "data" for client data. * - * @param {libtess.GluVertex=} opt_nextVertex [description] - * @param {libtess.GluVertex=} opt_prevVertex [description] + * @param {libtess.GluVertex=} opt_nextVertex [description]. + * @param {libtess.GluVertex=} opt_prevVertex [description]. * @constructor */ libtess.GluVertex = function(opt_nextVertex, opt_prevVertex) { @@ -65,7 +67,7 @@ libtess.GluVertex = function(opt_nextVertex, opt_prevVertex) { * @type {libtess.GluHalfEdge} */ this.anEdge = null; - + /** * The client's data. * @type {Object} diff --git a/src/libtess.js/normal.js b/src/libtess.js/normal.js index 81554ad15b..5bd16880be 100644 --- a/src/libtess.js/normal.js +++ b/src/libtess.js/normal.js @@ -40,6 +40,7 @@ libtess.normal = function() { }; + // TODO(bckenny): NOTE: /* The "feature merging" is not intended to be complete. There are * special cases where edges are nearly parallel to the sweep line @@ -62,6 +63,7 @@ libtess.normal = function() { */ libtess.normal.S_UNIT_X_ = 1.0; + /** * @type {number} * @private @@ -69,15 +71,16 @@ libtess.normal.S_UNIT_X_ = 1.0; */ libtess.normal.S_UNIT_Y_ = 0.0; + /** * projectPolygon determines the polygon normal * and projects vertices onto the plane of the polygon. * - * @param {libtess.GluTesselator} tess [description] + * @param {libtess.GluTesselator} tess [description]. */ libtess.normal.projectPolygon = function(tess) { var computedNormal = false; - + var norm = [0, 0, 0]; norm[0] = tess.normal[0]; // TODO(bckenny): better way to init these? norm[1] = tess.normal[1]; @@ -97,8 +100,8 @@ libtess.normal.projectPolygon = function(tess) { libtess.normal.normalize_(norm); sUnit[i] = 0; - sUnit[(i+1)%3] = libtess.normal.S_UNIT_X_; - sUnit[(i+2)%3] = libtess.normal.S_UNIT_Y_; + sUnit[(i + 1) % 3] = libtess.normal.S_UNIT_X_; + sUnit[(i + 2) % 3] = libtess.normal.S_UNIT_Y_; // Now make it exactly perpendicular var w = libtess.normal.dot_(sUnit, norm); @@ -108,20 +111,20 @@ libtess.normal.projectPolygon = function(tess) { libtess.normal.normalize_(sUnit); // Choose tUnit so that (sUnit,tUnit,norm) form a right-handed frame - tUnit[0] = norm[1]*sUnit[2] - norm[2]*sUnit[1]; - tUnit[1] = norm[2]*sUnit[0] - norm[0]*sUnit[2]; - tUnit[2] = norm[0]*sUnit[1] - norm[1]*sUnit[0]; + tUnit[0] = norm[1] * sUnit[2] - norm[2] * sUnit[1]; + tUnit[1] = norm[2] * sUnit[0] - norm[0] * sUnit[2]; + tUnit[2] = norm[0] * sUnit[1] - norm[1] * sUnit[0]; libtess.normal.normalize_(tUnit); } else { // Project perpendicular to a coordinate axis -- better numerically sUnit[i] = 0; - sUnit[(i+1)%3] = libtess.normal.S_UNIT_X_; - sUnit[(i+2)%3] = libtess.normal.S_UNIT_Y_; - + sUnit[(i + 1) % 3] = libtess.normal.S_UNIT_X_; + sUnit[(i + 2) % 3] = libtess.normal.S_UNIT_Y_; + tUnit[i] = 0; - tUnit[(i+1)%3] = (norm[i] > 0) ? -libtess.normal.S_UNIT_Y_ : libtess.normal.S_UNIT_Y_; - tUnit[(i+2)%3] = (norm[i] > 0) ? libtess.normal.S_UNIT_X_ : -libtess.normal.S_UNIT_X_; + tUnit[(i + 1) % 3] = (norm[i] > 0) ? -libtess.normal.S_UNIT_Y_ : libtess.normal.S_UNIT_Y_; + tUnit[(i + 2) % 3] = (norm[i] > 0) ? libtess.normal.S_UNIT_X_ : -libtess.normal.S_UNIT_X_; } // Project the vertices onto the sweep plane @@ -136,24 +139,26 @@ libtess.normal.projectPolygon = function(tess) { } }; + /** * Dot product. * @private - * @param {Array.} u [description] - * @param {Array.} v [description] - * @return {number} [description] + * @param {Array.} u [description]. + * @param {Array.} v [description]. + * @return {number} [description]. */ libtess.normal.dot_ = function(u, v) { - return u[0]*v[0] + u[1]*v[1] + u[2]*v[2]; + return u[0] * v[0] + u[1] * v[1] + u[2] * v[2]; }; + /** * Normalize vector v * @private - * @param {Array.} v [description] + * @param {Array.} v [description]. */ libtess.normal.normalize_ = function(v) { - var len = v[0]*v[0] + v[1]*v[1] + v[2]*v[2]; + var len = v[0] * v[0] + v[1] * v[1] + v[2] * v[2]; libtess.assert(len > 0); len = Math.sqrt(len); @@ -162,10 +167,11 @@ libtess.normal.normalize_ = function(v) { v[2] /= len; }; + /** * Returns the index of the longest component of vector v. * @private - * @param {Array.} v [description] + * @param {Array.} v [description]. * @return {number} The index of the longest component. */ libtess.normal.longAxis_ = function(v) { @@ -181,12 +187,13 @@ libtess.normal.longAxis_ = function(v) { return i; }; + /** * [computeNormal description] * * @private - * @param {libtess.GluTesselator} tess [description] - * @param {Array.} norm [description] + * @param {libtess.GluTesselator} tess [description]. + * @param {Array.} norm [description]. */ libtess.normal.computeNormal_ = function(tess, norm) { // TODO(bckenny): better way to init these @@ -238,10 +245,10 @@ libtess.normal.computeNormal_ = function(tess, norm) { d2[0] = v.coords[0] - v2.coords[0]; d2[1] = v.coords[1] - v2.coords[1]; d2[2] = v.coords[2] - v2.coords[2]; - tNorm[0] = d1[1]*d2[2] - d1[2]*d2[1]; - tNorm[1] = d1[2]*d2[0] - d1[0]*d2[2]; - tNorm[2] = d1[0]*d2[1] - d1[1]*d2[0]; - var tLen2 = tNorm[0]*tNorm[0] + tNorm[1]*tNorm[1] + tNorm[2]*tNorm[2]; + tNorm[0] = d1[1] * d2[2] - d1[2] * d2[1]; + tNorm[1] = d1[2] * d2[0] - d1[0] * d2[2]; + tNorm[2] = d1[0] * d2[1] - d1[1] * d2[0]; + var tLen2 = tNorm[0] * tNorm[0] + tNorm[1] * tNorm[1] + tNorm[2] * tNorm[2]; if (tLen2 > maxLen2) { maxLen2 = tLen2; norm[0] = tNorm[0]; @@ -257,11 +264,12 @@ libtess.normal.computeNormal_ = function(tess, norm) { } }; + /** * [checkOrientation description] * * @private - * @param {libtess.GluTesselator} tess [description] + * @param {libtess.GluTesselator} tess [description]. */ libtess.normal.checkOrientation_ = function(tess) { // When we compute the normal automatically, we choose the orientation @@ -274,7 +282,7 @@ libtess.normal.checkOrientation_ = function(tess) { do { area += (e.org.s - e.dst().s) * (e.org.t + e.dst().t); e = e.lNext; - } while(e !== f.anEdge); + } while (e !== f.anEdge); } if (area < 0) { diff --git a/src/libtess.js/priorityq/PQHandleElem.js b/src/libtess.js/priorityq/PQHandleElem.js index 56481318e0..39289f1eda 100644 --- a/src/libtess.js/priorityq/PQHandleElem.js +++ b/src/libtess.js/priorityq/PQHandleElem.js @@ -37,6 +37,8 @@ // TODO(bckenny): more specific typing on key + + /** * [PQHandleElem description] * @constructor @@ -49,7 +51,7 @@ libtess.PQHandleElem = function() { * @type {libtess.PQKey} */ this.key = null; - + /** * [node description] * @type {libtess.PQHandle} @@ -57,14 +59,15 @@ libtess.PQHandleElem = function() { this.node = 0; }; + /** * Allocate a PQHandleElem array of size size. If oldArray is not null, its * contents are copied to the beginning of the new array. The rest of the array * is filled with new PQHandleElems. * - * @param {?Array.} oldArray [description] - * @param {number} size [description] - * @return {Array.} [description] + * @param {?Array.} oldArray [description]. + * @param {number} size [description]. + * @return {Array.} [description]. */ libtess.PQHandleElem.realloc = function(oldArray, size) { var newArray = new Array(size); diff --git a/src/libtess.js/priorityq/PQNode.js b/src/libtess.js/priorityq/PQNode.js index 35189c23f2..ecbe2b40c5 100644 --- a/src/libtess.js/priorityq/PQNode.js +++ b/src/libtess.js/priorityq/PQNode.js @@ -38,6 +38,8 @@ // TODO(bckenny): maybe just have these created inline as literals // (or unboxed directly - PQHandle is just an array index number) + + /** * [PQNode description] * @constructor @@ -50,14 +52,15 @@ libtess.PQNode = function() { this.handle = 0; }; + /** * Allocate a PQNode array of size size. If oldArray is not null, its contents * are copied to the beginning of the new array. The rest of the array is * filled with new PQNodes. * - * @param {?Array.} oldArray [description] - * @param {number} size [description] - * @return {Array.} [description] + * @param {?Array.} oldArray [description]. + * @param {number} size [description]. + * @return {Array.} [description]. */ libtess.PQNode.realloc = function(oldArray, size) { var newArray = new Array(size); diff --git a/src/libtess.js/priorityq/PriorityQ.js b/src/libtess.js/priorityq/PriorityQ.js index 0928bbad3b..428b12fec0 100644 --- a/src/libtess.js/priorityq/PriorityQ.js +++ b/src/libtess.js/priorityq/PriorityQ.js @@ -39,10 +39,12 @@ // TODO(bckenny): preallocating arrays may actually be hurting us in sort // performance (esp if theres some undefs in there) + + /** * [PriorityQ description] * @constructor - * @param {function(Object, Object): boolean} leq [description] + * @param {function(Object, Object): boolean} leq [description]. */ libtess.PriorityQ = function(leq) { /** @@ -51,21 +53,21 @@ libtess.PriorityQ = function(leq) { * @type {Array.} */ this.keys_ = libtess.PriorityQ.prototype.PQKeyRealloc_(null, libtess.PriorityQ.INIT_SIZE_); - + /** * Array of indexes into this.keys_ * @private * @type {Array.} */ this.order_ = null; - + /** * [size description] * @private * @type {number} */ this.size_ = 0; - + /** * [max_ description] * @private @@ -97,6 +99,7 @@ libtess.PriorityQ = function(leq) { this.heap_ = new libtess.PriorityQHeap(this.leq_); }; + /** * [INIT_SIZE_ description] * @private @@ -105,6 +108,7 @@ libtess.PriorityQ = function(leq) { */ libtess.PriorityQ.INIT_SIZE_ = 32; + /** * [deleteQ description] */ @@ -117,6 +121,7 @@ libtess.PriorityQ.prototype.deleteQ = function() { // NOTE(bckenny): nulled at callsite (sweep.donePriorityQ_) }; + /** * [init description] */ @@ -154,16 +159,17 @@ libtess.PriorityQ.prototype.init = function() { var p = 0; var r = p + this.size_ - 1; for (i = p; i < r; ++i) { - libtess.assert(this.leq_(this.keys_[this.order_[i+1]], this.keys_[this.order_[i]])); + libtess.assert(this.leq_(this.keys_[this.order_[i + 1]], this.keys_[this.order_[i]])); } } // #endif }; + /** * [insert description] - * @param {libtess.PQKey} keyNew [description] - * @return {libtess.PQHandle} [description] + * @param {libtess.PQKey} keyNew [description]. + * @return {libtess.PQHandle} [description]. */ libtess.PriorityQ.prototype.insert = function(keyNew) { // NOTE(bckenny): originally returned LONG_MAX as alloc failure signal. no longer does. @@ -181,18 +187,19 @@ libtess.PriorityQ.prototype.insert = function(keyNew) { this.keys_[curr] = keyNew; // Negative handles index the sorted array. - return -(curr+1); + return -(curr + 1); }; + /** * Allocate a PQKey array of size size. If oldArray is not null, its * contents are copied to the beginning of the new array. The rest of the array * is filled with nulls. * * @private - * @param {?Array.} oldArray [description] - * @param {number} size [description] - * @return {Array.<(?libtess.PQKey)>} [description] + * @param {?Array.} oldArray [description]. + * @param {number} size [description]. + * @return {Array.<(?libtess.PQKey)>} [description]. */ libtess.PriorityQ.prototype.PQKeyRealloc_ = function(oldArray, size) { // TODO(bckenny): double check return type. can we have ? there? @@ -213,12 +220,13 @@ libtess.PriorityQ.prototype.PQKeyRealloc_ = function(oldArray, size) { return newArray; }; + /** * [keyLessThan_ description] * @private - * @param {number} x [description] - * @param {number} y [description] - * @return {boolean} [description] + * @param {number} x [description]. + * @param {number} y [description]. + * @return {boolean} [description]. */ libtess.PriorityQ.prototype.keyLessThan_ = function(x, y) { // NOTE(bckenny): was macro LT @@ -227,12 +235,13 @@ libtess.PriorityQ.prototype.keyLessThan_ = function(x, y) { return !this.leq_(keyY, keyX); }; + /** * [keyGreaterThan_ description] * @private - * @param {number} x [description] - * @param {number} y [description] - * @return {boolean} [description] + * @param {number} x [description]. + * @param {number} y [description]. + * @return {boolean} [description]. */ libtess.PriorityQ.prototype.keyGreaterThan_ = function(x, y) { // NOTE(bckenny): was macro GT @@ -241,16 +250,17 @@ libtess.PriorityQ.prototype.keyGreaterThan_ = function(x, y) { return !this.leq_(keyX, keyY); }; + /** * [extractMin description] - * @return {libtess.PQKey} [description] + * @return {libtess.PQKey} [description]. */ libtess.PriorityQ.prototype.extractMin = function() { if (this.size_ === 0) { return this.heap_.extractMin(); } - var sortMin = this.keys_[this.order_[this.size_-1]]; + var sortMin = this.keys_[this.order_[this.size_ - 1]]; if (!this.heap_.isEmpty()) { var heapMin = this.heap_.minimum(); if (this.leq_(heapMin, sortMin)) { @@ -260,21 +270,22 @@ libtess.PriorityQ.prototype.extractMin = function() { do { --this.size_; - } while(this.size_ > 0 && this.keys_[this.order_[this.size_-1]] === null); + } while (this.size_ > 0 && this.keys_[this.order_[this.size_ - 1]] === null); return sortMin; }; + /** * [minimum description] - * @return {libtess.PQKey} [description] + * @return {libtess.PQKey} [description]. */ libtess.PriorityQ.prototype.minimum = function() { if (this.size_ === 0) { return this.heap_.minimum(); } - var sortMin = this.keys_[this.order_[this.size_-1]]; + var sortMin = this.keys_[this.order_[this.size_ - 1]]; if (!this.heap_.isEmpty()) { var heapMin = this.heap_.minimum(); if (this.leq_(heapMin, sortMin)) { @@ -285,29 +296,31 @@ libtess.PriorityQ.prototype.minimum = function() { return sortMin; }; + /** * [isEmpty description] - * @return {boolean} [description] + * @return {boolean} [description]. */ libtess.PriorityQ.prototype.isEmpty = function() { return (this.size_ === 0) && this.heap_.isEmpty(); }; + /** * [remove description] - * @param {libtess.PQHandle} curr [description] + * @param {libtess.PQHandle} curr [description]. */ libtess.PriorityQ.prototype.remove = function(curr) { if (curr >= 0) { this.heap_.remove(curr); return; } - curr = -(curr+1); + curr = -(curr + 1); libtess.assert(curr < this.max_ && this.keys_[curr] !== null); this.keys_[curr] = null; - while(this.size_ > 0 && this.keys_[this.order_[this.size_-1]] === null) { + while (this.size_ > 0 && this.keys_[this.order_[this.size_ - 1]] === null) { --this.size_; } }; diff --git a/src/libtess.js/priorityq/PriorityQHeap.js b/src/libtess.js/priorityq/PriorityQHeap.js index 5f05516b43..f4e738530f 100644 --- a/src/libtess.js/priorityq/PriorityQHeap.js +++ b/src/libtess.js/priorityq/PriorityQHeap.js @@ -39,10 +39,12 @@ // TODO(bckenny): keys appear to always be GluVertex in this case? + + /** * [PriorityQHeap description] * @constructor - * @param {function(libtess.PQKey, libtess.PQKey): boolean} leq [description] + * @param {function(libtess.PQKey, libtess.PQKey): boolean} leq [description]. */ libtess.PriorityQHeap = function(leq) { /** @@ -102,11 +104,12 @@ libtess.PriorityQHeap = function(leq) { * @type {function(libtess.PQKey, libtess.PQKey): boolean} */ this.leq_ = leq; - + // so that minimum returns null this.nodes_[1].handle = 1; }; + /** * [INIT_SIZE_ description] * @private @@ -115,6 +118,7 @@ libtess.PriorityQHeap = function(leq) { */ libtess.PriorityQHeap.INIT_SIZE_ = 32; + /** * [deleteHeap description] */ @@ -125,19 +129,21 @@ libtess.PriorityQHeap.prototype.deleteHeap = function() { // NOTE(bckenny): nulled at callsite in PriorityQ.deleteQ }; + /** * Initializing ordering of the heap. Must be called before any method other than * insert is called to ensure correctness when removing or querying. */ libtess.PriorityQHeap.prototype.init = function() { // This method of building a heap is O(n), rather than O(n lg n). - for(var i = this.size_; i >= 1; --i) { + for (var i = this.size_; i >= 1; --i) { this.floatDown_(i); } this.initialized_ = true; }; + /** * Insert a new key into the heap. * @param {libtess.PQKey} keyNew The key to insert. @@ -147,7 +153,7 @@ libtess.PriorityQHeap.prototype.insert = function(keyNew) { var curr = ++this.size_; // if the heap overflows, double its size. - if ((curr*2) > this.max_) { + if ((curr * 2) > this.max_) { this.max_ *= 2; this.nodes_ = libtess.PQNode.realloc(this.nodes_, this.max_ + 1); this.handles_ = libtess.PQHandleElem.realloc(this.handles_, this.max_ + 1); @@ -172,6 +178,7 @@ libtess.PriorityQHeap.prototype.insert = function(keyNew) { return free; }; + /** * @return {boolean} Whether the heap is empty. */ @@ -179,19 +186,21 @@ libtess.PriorityQHeap.prototype.isEmpty = function() { return this.size_ === 0; }; + /** * Returns the minimum key in the heap. If the heap is empty, null will be * returned. - * @return {libtess.PQKey} [description] + * @return {libtess.PQKey} [description]. */ libtess.PriorityQHeap.prototype.minimum = function() { return this.handles_[this.nodes_[1].handle].key; }; + /** * Removes the minimum key from the heap and returns it. If the heap is empty, * null will be returned. - * @return {libtess.PQKey} [description] + * @return {libtess.PQKey} [description]. */ libtess.PriorityQHeap.prototype.extractMin = function() { var n = this.nodes_; @@ -207,7 +216,7 @@ libtess.PriorityQHeap.prototype.extractMin = function() { h[hMin].node = this.freeList_; this.freeList_ = hMin; - if (--this.size_ > 0 ) { + if (--this.size_ > 0) { this.floatDown_(1); } } @@ -215,9 +224,10 @@ libtess.PriorityQHeap.prototype.extractMin = function() { return min; }; + /** * Remove key associated with handle hCurr (returned from insert) from heap. - * @param {libtess.PQHandle} hCurr [description] + * @param {libtess.PQHandle} hCurr [description]. */ libtess.PriorityQHeap.prototype.remove = function(hCurr) { var n = this.nodes_; @@ -230,7 +240,7 @@ libtess.PriorityQHeap.prototype.remove = function(hCurr) { h[n[curr].handle].node = curr; if (curr <= --this.size_) { - if (curr <= 1 || this.leq_(h[n[curr>>1].handle].key, h[n[curr].handle].key)) { + if (curr <= 1 || this.leq_(h[n[curr >> 1].handle].key, h[n[curr].handle].key)) { this.floatDown_(curr); } else { this.floatUp_(curr); @@ -242,21 +252,22 @@ libtess.PriorityQHeap.prototype.remove = function(hCurr) { this.freeList_ = hCurr; }; + /** * [floatDown_ description] * @private - * @param {libtess.PQHandle} curr [description] + * @param {libtess.PQHandle} curr [description]. */ libtess.PriorityQHeap.prototype.floatDown_ = function(curr) { var n = this.nodes_; var h = this.handles_; var hCurr = n[curr].handle; - for( ;; ) { + for (;; ) { // The children of node i are nodes 2i and 2i+1. // set child to the index of the child with the minimum key var child = curr << 1; - if (child < this.size_ && this.leq_(h[n[child+1].handle].key, h[n[child].handle].key)) { + if (child < this.size_ && this.leq_(h[n[child + 1].handle].key, h[n[child].handle].key)) { ++child; } @@ -274,17 +285,18 @@ libtess.PriorityQHeap.prototype.floatDown_ = function(curr) { } }; + /** * [floatUp_ description] * @private - * @param {libtess.PQHandle} curr [description] + * @param {libtess.PQHandle} curr [description]. */ libtess.PriorityQHeap.prototype.floatUp_ = function(curr) { var n = this.nodes_; var h = this.handles_; var hCurr = n[curr].handle; - for( ;; ) { + for (;; ) { var parent = curr >> 1; var hParent = n[parent].handle; if (parent === 0 || this.leq_(h[hParent].key, h[hCurr].key)) { diff --git a/src/libtess.js/render.js b/src/libtess.js/render.js index b360b654c1..7c5914b10c 100644 --- a/src/libtess.js/render.js +++ b/src/libtess.js/render.js @@ -46,6 +46,7 @@ libtess.render = function() { }; + /** * [SIGN_INCONSISTENT_ description] * @type {number} @@ -54,6 +55,7 @@ libtess.render = function() { */ libtess.render.SIGN_INCONSISTENT_ = 2; + /** * render.renderMesh(tess, mesh) takes a mesh and breaks it into triangle * fans, strips, and separate triangles. A substantial effort is made @@ -62,18 +64,18 @@ libtess.render.SIGN_INCONSISTENT_ = 2; * * The rendering output is provided as callbacks (see the api). * - * @param {libtess.GluTesselator} tess [description] - * @param {libtess.GluMesh} mesh [description] + * @param {libtess.GluTesselator} tess [description]. + * @param {libtess.GluMesh} mesh [description]. */ libtess.render.renderMesh = function(tess, mesh) { // Make a list of separate triangles so we can render them all at once tess.lonelyTriList = null; var f; - for(f = mesh.fHead.next; f !== mesh.fHead; f = f.next) { + for (f = mesh.fHead.next; f !== mesh.fHead; f = f.next) { f.marked = false; } - for(f = mesh.fHead.next; f !== mesh.fHead; f = f.next) { + for (f = mesh.fHead.next; f !== mesh.fHead; f = f.next) { // We examine all faces in an arbitrary order. Whenever we find // an unprocessed face F, we output a group of faces including F // whose size is maximum. @@ -94,8 +96,8 @@ libtess.render.renderMesh = function(tess, mesh) { * contour for each face marked "inside". The rendering output is * provided as callbacks (see the api). * - * @param {libtess.GluTesselator} tess [description] - * @param {libtess.GluMesh} mesh [description] + * @param {libtess.GluTesselator} tess [description]. + * @param {libtess.GluMesh} mesh [description]. */ libtess.render.renderBoundary = function(tess, mesh) { for (var f = mesh.fHead.next; f !== mesh.fHead; f = f.next) { @@ -113,6 +115,7 @@ libtess.render.renderBoundary = function(tess, mesh) { } }; + /** * render.renderCache(tess) takes a single contour and tries to render it * as a triangle fan. This handles convex polygons, as well as some @@ -121,8 +124,8 @@ libtess.render.renderBoundary = function(tess, mesh) { * Returns true if the polygon was successfully rendered. The rendering * output is provided as callbacks (see the api). * - * @param {libtess.GluTesselator} tess [description] - * @return {boolean} [description] + * @param {libtess.GluTesselator} tess [description]. + * @return {boolean} [description]. */ libtess.render.renderCache = function(tess) { if (tess.cacheCount < 3) { @@ -150,7 +153,7 @@ libtess.render.renderCache = function(tess) { } // make sure we do the right thing for each winding rule - switch(tess.windingRule) { + switch (tess.windingRule) { case libtess.windingRule.GLU_TESS_WINDING_ODD: case libtess.windingRule.GLU_TESS_WINDING_NONZERO: break; @@ -180,11 +183,11 @@ libtess.render.renderCache = function(tess) { tess.callVertexOrVertexData(tess.cache[v0].data); if (sign > 0) { - for (vc = v0+1; vc < vn; ++vc) { + for (vc = v0 + 1; vc < vn; ++vc) { tess.callVertexOrVertexData(tess.cache[vc].data); } } else { - for(vc = vn-1; vc > v0; --vc) { + for (vc = vn - 1; vc > v0; --vc) { tess.callVertexOrVertexData(tess.cache[vc].data); } } @@ -196,18 +199,19 @@ libtess.render.renderCache = function(tess) { /** * Returns true if face has been marked temporarily. * @private - * @param {libtess.GluFace} f [description] - * @return {boolean} [description] + * @param {libtess.GluFace} f [description]. + * @return {boolean} [description]. */ libtess.render.marked_ = function(f) { // NOTE(bckenny): originally macro return (!f.inside || f.marked); }; + /** * [freeTrail description] * @private - * @param {libtess.GluFace} t [description] + * @param {libtess.GluFace} t [description]. */ libtess.render.freeTrail_ = function(t) { // NOTE(bckenny): originally macro @@ -217,22 +221,23 @@ libtess.render.freeTrail_ = function(t) { } }; + /** * eOrig.lFace is the face we want to render. We want to find the size * of a maximal fan around eOrig.org. To do this we just walk around * the origin vertex as far as possible in both directions. * @private - * @param {libtess.GluHalfEdge} eOrig [description] - * @return {libtess.FaceCount} [description] + * @param {libtess.GluHalfEdge} eOrig [description]. + * @return {libtess.FaceCount} [description]. */ libtess.render.maximumFan_ = function(eOrig) { // TODO(bckenny): probably have dest FaceCount passed in (see renderMaximumFaceGroup) var newFace = new libtess.FaceCount(0, null, libtess.render.renderFan_); - + var trail = null; var e; - for(e = eOrig; !libtess.render.marked_(e.lFace); e = e.oNext) { + for (e = eOrig; !libtess.render.marked_(e.lFace); e = e.oNext) { // NOTE(bckenny): AddToTrail(e.lFace, trail) macro e.lFace.trail = trail; trail = e.lFace; @@ -240,7 +245,7 @@ libtess.render.maximumFan_ = function(eOrig) { ++newFace.size; } - for(e = eOrig; !libtess.render.marked_(e.rFace()); e = e.oPrev()) { + for (e = eOrig; !libtess.render.marked_(e.rFace()); e = e.oPrev()) { // NOTE(bckenny): AddToTrail(e.rFace(), trail) macro e.rFace().trail = trail; trail = e.rFace(); @@ -254,6 +259,7 @@ libtess.render.maximumFan_ = function(eOrig) { return newFace; }; + /** * Here we are looking for a maximal strip that contains the vertices * eOrig.org, eOrig.dst(), eOrig.lNext.dst() (in that order or the @@ -265,8 +271,8 @@ libtess.render.maximumFan_ = function(eOrig) { * We walk the strip starting on a side with an even number of triangles; * if both side have an odd number, we are forced to shorten one side. * @private - * @param {libtess.GluHalfEdge} eOrig [description] - * @return {libtess.FaceCount} [description] + * @param {libtess.GluHalfEdge} eOrig [description]. + * @return {libtess.FaceCount} [description]. */ libtess.render.maximumStrip_ = function(eOrig) { // TODO(bckenny): probably have dest FaceCount passed in (see renderMaximumFaceGroup) @@ -335,14 +341,15 @@ libtess.render.maximumStrip_ = function(eOrig) { return newFace; }; + /** * Render as many CCW triangles as possible in a fan starting from * edge "e". The fan *should* contain exactly "size" triangles * (otherwise we've goofed up somewhere). * @private - * @param {libtess.GluTesselator} tess [description] - * @param {libtess.GluHalfEdge} e [description] - * @param {number} size [description] + * @param {libtess.GluTesselator} tess [description]. + * @param {libtess.GluHalfEdge} e [description]. + * @param {number} size [description]. */ libtess.render.renderFan_ = function(tess, e, size) { tess.callBeginOrBeginData(libtess.primitiveType.GL_TRIANGLE_FAN); @@ -360,14 +367,15 @@ libtess.render.renderFan_ = function(tess, e, size) { tess.callEndOrEndData(); }; + /** * Render as many CCW triangles as possible in a strip starting from * edge e. The strip *should* contain exactly "size" triangles * (otherwise we've goofed up somewhere). * @private - * @param {libtess.GluTesselator} tess [description] - * @param {libtess.GluHalfEdge} e [description] - * @param {number} size [description] + * @param {libtess.GluTesselator} tess [description]. + * @param {libtess.GluHalfEdge} e [description]. + * @param {number} size [description]. */ libtess.render.renderStrip_ = function(tess, e, size) { tess.callBeginOrBeginData(libtess.primitiveType.GL_TRIANGLE_STRIP); @@ -393,13 +401,14 @@ libtess.render.renderStrip_ = function(tess, e, size) { tess.callEndOrEndData(); }; + /** * Just add the triangle to a triangle list, so we can render all * the separate triangles at once. * @private - * @param {libtess.GluTesselator} tess [description] - * @param {libtess.GluHalfEdge} e [description] - * @param {number} size [description] + * @param {libtess.GluTesselator} tess [description]. + * @param {libtess.GluHalfEdge} e [description]. + * @param {number} size [description]. */ libtess.render.renderTriangle_ = function(tess, e, size) { libtess.assert(size === 1); @@ -409,6 +418,7 @@ libtess.render.renderTriangle_ = function(tess, e, size) { e.lFace.marked = true; }; + /** * We want to find the largest triangle fan or strip of unmarked faces * which includes the given face fOrig. There are 3 possible fans @@ -417,8 +427,8 @@ libtess.render.renderTriangle_ = function(tess, e, size) { * is to try all of these, and take the primitive which uses the most * triangles (a greedy approach). * @private - * @param {libtess.GluTesselator} tess [description] - * @param {libtess.GluFace} fOrig [description] + * @param {libtess.GluTesselator} tess [description]. + * @param {libtess.GluFace} fOrig [description]. */ libtess.render.renderMaximumFaceGroup_ = function(tess, fOrig) { var e = fOrig.anEdge; @@ -460,12 +470,13 @@ libtess.render.renderMaximumFaceGroup_ = function(tess, fOrig) { max.render(tess, max.eStart, max.size); }; + /** * Now we render all the separate triangles which could not be * grouped into a triangle fan or strip. * @private - * @param {libtess.GluTesselator} tess [description] - * @param {libtess.GluFace} head [description] + * @param {libtess.GluTesselator} tess [description]. + * @param {libtess.GluFace} head [description]. */ libtess.render.renderLonelyTriangles_ = function(tess, head) { // TODO(bckenny): edgeState needs to be boolean, but != on first call @@ -476,7 +487,7 @@ libtess.render.renderLonelyTriangles_ = function(tess, head) { tess.callBeginOrBeginData(libtess.primitiveType.GL_TRIANGLES); - for(; f !== null; f = f.trail) { + for (; f !== null; f = f.trail) { // Loop once for each edge (there will always be 3 edges) var e = f.anEdge; do { @@ -499,6 +510,7 @@ libtess.render.renderLonelyTriangles_ = function(tess, head) { tess.callEndOrEndData(); }; + /** * If check==false, we compute the polygon normal and place it in norm[]. * If check==true, we check that each triangle in the fan from v0 has a @@ -507,10 +519,10 @@ libtess.render.renderLonelyTriangles_ = function(tess, head) { * are degenerate return 0; otherwise (no consistent orientation) return * render.SIGN_INCONSISTENT_. * @private - * @param {libtess.GluTesselator} tess [description] - * @param {Array.} norm [description] - * @param {boolean} check [description] - * @return {number} int + * @param {libtess.GluTesselator} tess [description]. + * @param {Array.} norm [description]. + * @param {boolean} check [description]. + * @return {number} int. */ libtess.render.computeNormal_ = function(tess, norm, check) { /* Find the polygon normal. It is important to get a reasonable @@ -537,7 +549,7 @@ libtess.render.computeNormal_ = function(tess, norm, check) { var vc = v0 + 1; var vert0 = tess.cache[v0]; var vertc = tess.cache[vc]; - + var xc = vertc.coords[0] - vert0.coords[0]; var yc = vertc.coords[1] - vert0.coords[1]; var zc = vertc.coords[2] - vert0.coords[2]; @@ -554,11 +566,11 @@ libtess.render.computeNormal_ = function(tess, norm, check) { // Compute (vp - v0) cross (vc - v0) var n = [0, 0, 0]; // TODO(bckenny): better init? - n[0] = yp*zc - zp*yc; - n[1] = zp*xc - xp*zc; - n[2] = xp*yc - yp*xc; + n[0] = yp * zc - zp * yc; + n[1] = zp * xc - xp * zc; + n[2] = xp * yc - yp * xc; - var dot = n[0]*norm[0] + n[1]*norm[1] + n[2]*norm[2]; + var dot = n[0] * norm[0] + n[1] * norm[1] + n[2] * norm[2]; if (!check) { // Reverse the contribution of back-facing triangles to get // a reasonable normal for self-intersecting polygons (see above) diff --git a/src/libtess.js/render/FaceCount.js b/src/libtess.js/render/FaceCount.js index 4bdaa03a3f..1d5d5a9f69 100644 --- a/src/libtess.js/render/FaceCount.js +++ b/src/libtess.js/render/FaceCount.js @@ -39,15 +39,17 @@ // TODO(bckenny): Used only in private functions of render.js + + /** * This structure remembers the information we need about a primitive * to be able to render it later, once we have determined which * primitive is able to use the most triangles. * * @constructor - * @param {number} size [description] - * @param {libtess.GluHalfEdge} eStart [description] - * @param {!function(libtess.GluTesselator, libtess.GluHalfEdge, number)} renderFunction [description] + * @param {number} size [description]. + * @param {libtess.GluHalfEdge} eStart [description]. + * @param {!function(libtess.GluTesselator, libtess.GluHalfEdge, number)} renderFunction [description]. */ libtess.FaceCount = function(size, eStart, renderFunction) { /** diff --git a/src/libtess.js/sweep.js b/src/libtess.js/sweep.js index ba361670ad..09ecd838b5 100644 --- a/src/libtess.js/sweep.js +++ b/src/libtess.js/sweep.js @@ -74,6 +74,7 @@ libtess.sweep = function() { }; + /** * Make the sentinel coordinates big enough that they will never be * merged with real input features. (Even with the largest possible @@ -85,6 +86,7 @@ libtess.sweep = function() { */ libtess.sweep.SENTINEL_COORD_ = 4 * libtess.GLU_TESS_MAX_COORD; + /** * Because vertices at exactly the same location are merged together * before we process the sweep event, some degenerate cases can't occur. @@ -98,6 +100,7 @@ libtess.sweep.SENTINEL_COORD_ = 4 * libtess.GLU_TESS_MAX_COORD; */ libtess.sweep.TOLERANCE_NONZERO_ = false; + /** * computeInterior(tess) computes the planar arrangement specified * by the given contours, and further subdivides this arrangement @@ -105,7 +108,7 @@ libtess.sweep.TOLERANCE_NONZERO_ = false; * to the polygon, according to the rule given by tess.windingRule. * Each interior region is guaranteed be monotone. * - * @param {libtess.GluTesselator} tess [description] + * @param {libtess.GluTesselator} tess [description]. */ libtess.sweep.computeInterior = function(tess) { tess.fatalError = false; @@ -121,12 +124,12 @@ libtess.sweep.computeInterior = function(tess) { // TODO(bckenny): don't need the cast if pq's key is better typed var v; while ((v = /** @type {libtess.GluVertex} */(tess.pq.extractMin())) !== null) { - for ( ;; ) { + for (;; ) { var vNext = /** @type {libtess.GluVertex} */(tess.pq.minimum()); if (vNext === null || !libtess.geom.vertEq(vNext, v)) { break; } - + /* Merge together all vertices at exactly the same location. * This is more efficient than processing them one at a time, * simplifies the code (see connectLeftDegenerate), and is also @@ -161,13 +164,12 @@ libtess.sweep.computeInterior = function(tess) { }; - /** * When we merge two edges into one, we need to compute the combined * winding of the new edge. * @private - * @param {libtess.GluHalfEdge} eDst [description] - * @param {libtess.GluHalfEdge} eSrc [description] + * @param {libtess.GluHalfEdge} eDst [description]. + * @param {libtess.GluHalfEdge} eSrc [description]. */ libtess.sweep.addWinding_ = function(eDst, eSrc) { // NOTE(bckenny): from AddWinding macro @@ -175,6 +177,7 @@ libtess.sweep.addWinding_ = function(eDst, eSrc) { eDst.sym.winding += eSrc.sym.winding; }; + /** * Both edges must be directed from right to left (this is the canonical * direction for the upper edge of each region). @@ -187,10 +190,10 @@ libtess.sweep.addWinding_ = function(eDst, eSrc) { * we sort the edges by slope (they would otherwise compare equally). * * @private - * @param {libtess.GluTesselator} tess [description] - * @param {libtess.ActiveRegion} reg1 [description] - * @param {libtess.ActiveRegion} reg2 [description] - * @return {boolean} [description] + * @param {libtess.GluTesselator} tess [description]. + * @param {libtess.ActiveRegion} reg1 [description]. + * @param {libtess.ActiveRegion} reg2 [description]. + * @return {boolean} [description]. */ libtess.sweep.edgeLeq_ = function(tess, reg1, reg2) { var event = tess.event; @@ -221,11 +224,12 @@ libtess.sweep.edgeLeq_ = function(tess, reg1, reg2) { return (t1 >= t2); }; + /** * [deleteRegion_ description] * @private - * @param {libtess.GluTesselator} tess [description] - * @param {libtess.ActiveRegion} reg [description] + * @param {libtess.GluTesselator} tess [description]. + * @param {libtess.ActiveRegion} reg [description]. */ libtess.sweep.deleteRegion_ = function(tess, reg) { if (reg.fixUpperEdge) { @@ -244,11 +248,12 @@ libtess.sweep.deleteRegion_ = function(tess, reg) { // TODO(bckenny): may need to null at callsite }; + /** * Replace an upper edge which needs fixing (see connectRightVertex). * @private - * @param {libtess.ActiveRegion} reg [description] - * @param {libtess.GluHalfEdge} newEdge [description] + * @param {libtess.ActiveRegion} reg [description]. + * @param {libtess.GluHalfEdge} newEdge [description]. */ libtess.sweep.fixUpperEdge_ = function(reg, newEdge) { libtess.assert(reg.fixUpperEdge); @@ -259,11 +264,12 @@ libtess.sweep.fixUpperEdge_ = function(reg, newEdge) { newEdge.activeRegion = reg; }; + /** * Find the region above the uppermost edge with the same origin. * @private - * @param {libtess.ActiveRegion} reg [description] - * @return {libtess.ActiveRegion} [description] + * @param {libtess.ActiveRegion} reg [description]. + * @return {libtess.ActiveRegion} [description]. */ libtess.sweep.topLeftRegion_ = function(reg) { var org = reg.eUp.org; @@ -284,11 +290,12 @@ libtess.sweep.topLeftRegion_ = function(reg) { return reg; }; + /** * Find the region above the uppermost edge with the same destination. * @private - * @param {libtess.ActiveRegion} reg [description] - * @return {libtess.ActiveRegion} [description] + * @param {libtess.ActiveRegion} reg [description]. + * @return {libtess.ActiveRegion} [description]. */ libtess.sweep.topRightRegion_ = function(reg) { var dst = reg.eUp.dst(); @@ -300,6 +307,7 @@ libtess.sweep.topRightRegion_ = function(reg) { return reg; }; + /** * Add a new active region to the sweep line, *somewhere* below "regAbove" * (according to where the new edge belongs in the sweep-line dictionary). @@ -307,9 +315,9 @@ libtess.sweep.topRightRegion_ = function(reg) { * Winding number and "inside" flag are not updated. * * @private - * @param {libtess.GluTesselator} tess [description] - * @param {libtess.ActiveRegion} regAbove [description] - * @param {libtess.GluHalfEdge} eNewUp [description] + * @param {libtess.GluTesselator} tess [description]. + * @param {libtess.ActiveRegion} regAbove [description]. + * @param {libtess.GluHalfEdge} eNewUp [description]. */ libtess.sweep.addRegionBelow_ = function(tess, regAbove, eNewUp) { var regNew = new libtess.ActiveRegion(); @@ -321,15 +329,16 @@ libtess.sweep.addRegionBelow_ = function(tess, regAbove, eNewUp) { return regNew; }; + /** * [isWindingInside_ description] * @private - * @param {libtess.GluTesselator} tess [description] - * @param {number} n int - * @return {boolean} [description] + * @param {libtess.GluTesselator} tess [description]. + * @param {number} n int. + * @return {boolean} [description]. */ libtess.sweep.isWindingInside_ = function(tess, n) { - switch(tess.windingRule) { + switch (tess.windingRule) { case libtess.windingRule.GLU_TESS_WINDING_ODD: return ((n & 1) !== 0); case libtess.windingRule.GLU_TESS_WINDING_NONZERO: @@ -347,17 +356,19 @@ libtess.sweep.isWindingInside_ = function(tess, n) { return false; }; + /** * [computeWinding_ description] * @private - * @param {libtess.GluTesselator} tess [description] - * @param {libtess.ActiveRegion} reg [description] + * @param {libtess.GluTesselator} tess [description]. + * @param {libtess.ActiveRegion} reg [description]. */ libtess.sweep.computeWinding_ = function(tess, reg) { reg.windingNumber = reg.regionAbove().windingNumber + reg.eUp.winding; reg.inside = libtess.sweep.isWindingInside_(tess, reg.windingNumber); }; + /** * Delete a region from the sweep line. This happens when the upper * and lower chains of a region meet (at a vertex on the sweep line). @@ -366,8 +377,8 @@ libtess.sweep.computeWinding_ = function(tess, reg) { * changing, this face may not have even existed until now). * * @private - * @param {libtess.GluTesselator} tess [description] - * @param {libtess.ActiveRegion} reg [description] + * @param {libtess.GluTesselator} tess [description]. + * @param {libtess.ActiveRegion} reg [description]. */ libtess.sweep.finishRegion_ = function(tess, reg) { // TODO(bckenny): may need to null reg at callsite @@ -380,6 +391,7 @@ libtess.sweep.finishRegion_ = function(tess, reg) { libtess.sweep.deleteRegion_(tess, reg); }; + /** * We are given a vertex with one or more left-going edges. All affected * edges should be in the edge dictionary. Starting at regFirst.eUp, @@ -393,10 +405,10 @@ libtess.sweep.finishRegion_ = function(tess, reg) { * same as in the dictionary. * * @private - * @param {libtess.GluTesselator} tess [description] - * @param {libtess.ActiveRegion} regFirst [description] - * @param {libtess.ActiveRegion} regLast [description] - * @return {libtess.GluHalfEdge} [description] + * @param {libtess.GluTesselator} tess [description]. + * @param {libtess.ActiveRegion} regFirst [description]. + * @param {libtess.ActiveRegion} regLast [description]. + * @return {libtess.GluHalfEdge} [description]. */ libtess.sweep.finishLeftRegions_ = function(tess, regFirst, regLast) { var regPrev = regFirst; @@ -439,6 +451,7 @@ libtess.sweep.finishLeftRegions_ = function(tess, regFirst, regLast) { return ePrev; }; + /** * Purpose: insert right-going edges into the edge dictionary, and update * winding numbers and mesh connectivity appropriately. All right-going @@ -450,12 +463,12 @@ libtess.sweep.finishLeftRegions_ = function(tess, regFirst, regLast) { * should be null. * * @private - * @param {libtess.GluTesselator} tess [description] - * @param {libtess.ActiveRegion} regUp [description] - * @param {libtess.GluHalfEdge} eFirst [description] - * @param {libtess.GluHalfEdge} eLast [description] - * @param {libtess.GluHalfEdge} eTopLeft [description] - * @param {boolean} cleanUp [description] + * @param {libtess.GluTesselator} tess [description]. + * @param {libtess.ActiveRegion} regUp [description]. + * @param {libtess.GluHalfEdge} eFirst [description]. + * @param {libtess.GluHalfEdge} eLast [description]. + * @param {libtess.GluHalfEdge} eTopLeft [description]. + * @param {boolean} cleanUp [description]. */ libtess.sweep.addRightEdges_ = function(tess, regUp, eFirst, eLast, eTopLeft, cleanUp) { var firstTime = true; @@ -477,7 +490,7 @@ libtess.sweep.addRightEdges_ = function(tess, regUp, eFirst, eLast, eTopLeft, cl var regPrev = regUp; var ePrev = eTopLeft; var reg; - for( ;; ) { + for (;; ) { reg = regPrev.regionBelow(); e = reg.eUp.sym; if (e.org !== ePrev.org) { @@ -515,14 +528,15 @@ libtess.sweep.addRightEdges_ = function(tess, regUp, eFirst, eLast, eTopLeft, cl } }; + /** * [callCombine_ description] * @private - * @param {libtess.GluTesselator} tess [description] - * @param {libtess.GluVertex} isect [description] - * @param {Array.} data [description] - * @param {Array.} weights [description] - * @param {boolean} needed [description] + * @param {libtess.GluTesselator} tess [description]. + * @param {libtess.GluVertex} isect [description]. + * @param {Array.} data [description]. + * @param {Array.} weights [description]. + * @param {boolean} needed [description]. */ libtess.sweep.callCombine_ = function(tess, isect, data, weights, needed) { // Copy coord data in case the callback changes it. @@ -549,13 +563,14 @@ libtess.sweep.callCombine_ = function(tess, isect, data, weights, needed) { } }; + /** * Two vertices with idential coordinates are combined into one. * e1.org is kept, while e2.org is discarded. * @private - * @param {libtess.GluTesselator} tess [description] - * @param {libtess.GluHalfEdge} e1 [description] - * @param {libtess.GluHalfEdge} e2 [description] + * @param {libtess.GluTesselator} tess [description]. + * @param {libtess.GluHalfEdge} e1 [description]. + * @param {libtess.GluHalfEdge} e2 [description]. */ libtess.sweep.spliceMergeVertices_ = function(tess, e1, e2) { // TODO(bckenny): better way to init these? save them? @@ -568,6 +583,7 @@ libtess.sweep.spliceMergeVertices_ = function(tess, e1, e2) { libtess.mesh.meshSplice(e1, e2); }; + /** * Find some weights which describe how the intersection vertex is * a linear combination of org and dst. Each of the two edges @@ -576,11 +592,11 @@ libtess.sweep.spliceMergeVertices_ = function(tess, e1, e2) { * relative distance to "isect". * * @private - * @param {libtess.GluVertex} isect [description] - * @param {libtess.GluVertex} org [description] - * @param {libtess.GluVertex} dst [description] - * @param {Array.} weights [description] - * @param {number} weightIndex Index into weights for first weight to supply + * @param {libtess.GluVertex} isect [description]. + * @param {libtess.GluVertex} org [description]. + * @param {libtess.GluVertex} dst [description]. + * @param {Array.} weights [description]. + * @param {number} weightIndex Index into weights for first weight to supply. */ libtess.sweep.vertexWeights_ = function(isect, org, dst, weights, weightIndex) { // TODO(bckenny): think through how we can use L1dist here and be correct for coords @@ -594,22 +610,23 @@ libtess.sweep.vertexWeights_ = function(isect, org, dst, weights, weightIndex) { var i1 = weightIndex + 1; weights[i0] = 0.5 * t2 / (t1 + t2); weights[i1] = 0.5 * t1 / (t1 + t2); - isect.coords[0] += weights[i0]*org.coords[0] + weights[i1]*dst.coords[0]; - isect.coords[1] += weights[i0]*org.coords[1] + weights[i1]*dst.coords[1]; - isect.coords[2] += weights[i0]*org.coords[2] + weights[i1]*dst.coords[2]; + isect.coords[0] += weights[i0] * org.coords[0] + weights[i1] * dst.coords[0]; + isect.coords[1] += weights[i0] * org.coords[1] + weights[i1] * dst.coords[1]; + isect.coords[2] += weights[i0] * org.coords[2] + weights[i1] * dst.coords[2]; }; + /** * We've computed a new intersection point, now we need a "data" pointer * from the user so that we can refer to this new vertex in the * rendering callbacks. * @private - * @param {libtess.GluTesselator} tess [description] - * @param {libtess.GluVertex} isect [description] - * @param {libtess.GluVertex} orgUp [description] - * @param {libtess.GluVertex} dstUp [description] - * @param {libtess.GluVertex} orgLo [description] - * @param {libtess.GluVertex} dstLo [description] + * @param {libtess.GluTesselator} tess [description]. + * @param {libtess.GluVertex} isect [description]. + * @param {libtess.GluVertex} orgUp [description]. + * @param {libtess.GluVertex} dstUp [description]. + * @param {libtess.GluVertex} orgLo [description]. + * @param {libtess.GluVertex} dstLo [description]. */ libtess.sweep.getIntersectData_ = function(tess, isect, orgUp, dstUp, orgLo, dstLo) { // TODO(bckenny): called for every intersection event, should these be from a pool? @@ -633,6 +650,7 @@ libtess.sweep.getIntersectData_ = function(tess, isect, orgUp, dstUp, orgLo, dst libtess.sweep.callCombine_(tess, isect, data, weights, true); }; + /** * Check the upper and lower edge of regUp, to make sure that the * eUp.org is above eLo, or eLo.org is below eUp (depending on which @@ -659,9 +677,9 @@ libtess.sweep.getIntersectData_ = function(tess, isect, orgUp, dstUp, orgLo, dst * Basically this is a combinatorial solution to a numerical problem. * * @private - * @param {libtess.GluTesselator} tess [description] - * @param {libtess.ActiveRegion} regUp [description] - * @return {boolean} [description] + * @param {libtess.GluTesselator} tess [description]. + * @param {libtess.ActiveRegion} regUp [description]. + * @return {boolean} [description]. */ libtess.sweep.checkForRightSplice_ = function(tess, regUp) { // TODO(bckenny): fully learn how these two checks work @@ -703,6 +721,7 @@ libtess.sweep.checkForRightSplice_ = function(tess, regUp) { return true; }; + /** * Check the upper and lower edge of regUp to make sure that the * eUp.dst() is above eLo, or eLo.dst() is below eUp (depending on which @@ -722,9 +741,9 @@ libtess.sweep.checkForRightSplice_ = function(tess, regUp) { * other edge. * * @private - * @param {libtess.GluTesselator} tess description] - * @param {libtess.ActiveRegion} regUp [description] - * @return {boolean} [description] + * @param {libtess.GluTesselator} tess description]. + * @param {libtess.ActiveRegion} regUp [description]. + * @return {boolean} [description]. */ libtess.sweep.checkForLeftSplice_ = function(tess, regUp) { var regLo = regUp.regionBelow(); @@ -760,6 +779,7 @@ libtess.sweep.checkForLeftSplice_ = function(tess, regUp) { return true; }; + /** * Check the upper and lower edges of the given region to see if * they intersect. If so, create the intersection and add it @@ -770,9 +790,9 @@ libtess.sweep.checkForLeftSplice_ = function(tess, regUp) { * checked for intersections, and possibly regUp has been deleted. * * @private - * @param {libtess.GluTesselator} tess [description] - * @param {libtess.ActiveRegion} regUp [description] - * @return {boolean} [description] + * @param {libtess.GluTesselator} tess [description]. + * @param {libtess.ActiveRegion} regUp [description]. + * @return {boolean} [description]. */ libtess.sweep.checkForIntersect_ = function(tess, regUp) { var regLo = regUp.regionBelow(); @@ -787,7 +807,7 @@ libtess.sweep.checkForIntersect_ = function(tess, regUp) { libtess.assert(!libtess.geom.vertEq(dstLo, dstUp)); libtess.assert(libtess.geom.edgeSign(dstUp, tess.event, orgUp) <= 0); - libtess.assert(libtess.geom.edgeSign(dstLo, tess.event, orgLo) >= 0 ); + libtess.assert(libtess.geom.edgeSign(dstLo, tess.event, orgLo) >= 0); libtess.assert(orgUp !== tess.event && orgLo !== tess.event); libtess.assert(!regUp.fixUpperEdge && !regLo.fixUpperEdge); @@ -814,10 +834,10 @@ libtess.sweep.checkForIntersect_ = function(tess, regUp) { } // At this point the edges intersect, at least marginally - libtess.sweepDebugEvent( tess ); + libtess.sweepDebugEvent(tess); libtess.geom.edgeIntersect(dstUp, orgUp, dstLo, orgLo, isect); - + // The following properties are guaranteed: libtess.assert(Math.min(orgUp.t, dstUp.t) <= isect.t); libtess.assert(isect.t <= Math.max(orgLo.t, dstLo.t)); @@ -926,6 +946,7 @@ libtess.sweep.checkForIntersect_ = function(tess, regUp) { return false; }; + /** * When the upper or lower edge of any region changes, the region is * marked "dirty". This routine walks through all the dirty regions @@ -934,13 +955,13 @@ libtess.sweep.checkForIntersect_ = function(tess, regUp) { * new dirty regions can be created as we make changes to restore * the invariants. * @private - * @param {libtess.GluTesselator} tess [description] - * @param {libtess.ActiveRegion} regUp [description] + * @param {libtess.GluTesselator} tess [description]. + * @param {libtess.ActiveRegion} regUp [description]. */ libtess.sweep.walkDirtyRegions_ = function(tess, regUp) { var regLo = regUp.regionBelow(); - for ( ;; ) { + for (;; ) { // Find the lowest dirty region (we walk from the bottom up). while (regLo.dirty) { regUp = regLo; @@ -1013,6 +1034,7 @@ libtess.sweep.walkDirtyRegions_ = function(tess, regUp) { } }; + /** * Purpose: connect a "right" vertex vEvent (one where all edges go left) * to the unprocessed portion of the mesh. Since there are no right-going @@ -1045,9 +1067,9 @@ libtess.sweep.walkDirtyRegions_ = function(tess, regUp) { * closest one, in which case we won't need to make any changes. * * @private - * @param {libtess.GluTesselator} tess [description] - * @param {libtess.ActiveRegion} regUp [description] - * @param {libtess.GluHalfEdge} eBottomLeft [description] + * @param {libtess.GluTesselator} tess [description]. + * @param {libtess.ActiveRegion} regUp [description]. + * @param {libtess.GluHalfEdge} eBottomLeft [description]. */ libtess.sweep.connectRightVertex_ = function(tess, regUp, eBottomLeft) { var eTopLeft = eBottomLeft.oNext; @@ -1096,14 +1118,15 @@ libtess.sweep.connectRightVertex_ = function(tess, regUp, eBottomLeft) { libtess.sweep.walkDirtyRegions_(tess, regUp); }; + /** * The event vertex lies exacty on an already-processed edge or vertex. * Adding the new vertex involves splicing it into the already-processed * part of the mesh. * @private - * @param {libtess.GluTesselator} tess [description] - * @param {libtess.ActiveRegion} regUp [description] - * @param {libtess.GluVertex} vEvent [description] + * @param {libtess.GluTesselator} tess [description]. + * @param {libtess.ActiveRegion} regUp [description]. + * @param {libtess.GluVertex} vEvent [description]. */ libtess.sweep.connectLeftDegenerate_ = function(tess, regUp, vEvent) { var e = regUp.eUp; @@ -1114,7 +1137,7 @@ libtess.sweep.connectLeftDegenerate_ = function(tess, regUp, vEvent) { libtess.sweep.spliceMergeVertices_(tess, e, vEvent.anEdge); return; } - + if (!libtess.geom.vertEq(e.dst(), vEvent)) { // General case -- splice vEvent into edge e which passes through it libtess.mesh.splitEdge(e.sym); @@ -1126,7 +1149,7 @@ libtess.sweep.connectLeftDegenerate_ = function(tess, regUp, vEvent) { } libtess.mesh.meshSplice(vEvent.anEdge, e); - + // recurse libtess.sweep.sweepEvent_(tess, vEvent); return; @@ -1144,7 +1167,7 @@ libtess.sweep.connectLeftDegenerate_ = function(tess, regUp, vEvent) { if (reg.fixUpperEdge) { // Here e.dst() has only a single fixable edge going right. // We can delete it since now we have some real right-going edges. - + // there are some left edges too libtess.assert(eTopLeft !== eTopRight); libtess.sweep.deleteRegion_(tess, reg); // TODO(bckenny): something to null? @@ -1161,6 +1184,7 @@ libtess.sweep.connectLeftDegenerate_ = function(tess, regUp, vEvent) { libtess.sweep.addRightEdges_(tess, regUp, eTopRight.oNext, eLast, eTopLeft, true); }; + /** * Connect a "left" vertex (one where both edges go right) * to the processed portion of the mesh. Let R be the active region @@ -1177,8 +1201,8 @@ libtess.sweep.connectLeftDegenerate_ = function(tess, regUp, vEvent) { * - merging with an already-processed portion of U or L * * @private - * @param {libtess.GluTesselator} tess [description] - * @param {libtess.GluVertex} vEvent [description] + * @param {libtess.GluTesselator} tess [description]. + * @param {libtess.GluVertex} vEvent [description]. */ libtess.sweep.connectLeftVertex_ = function(tess, vEvent) { // TODO(bckenny): tmp only used for sweep. better to keep tmp across calls? @@ -1228,17 +1252,18 @@ libtess.sweep.connectLeftVertex_ = function(tess, vEvent) { } }; + /** * Does everything necessary when the sweep line crosses a vertex. * Updates the mesh and the edge dictionary. * @private - * @param {libtess.GluTesselator} tess [description] - * @param {libtess.GluVertex} vEvent [description] + * @param {libtess.GluTesselator} tess [description]. + * @param {libtess.GluVertex} vEvent [description]. */ libtess.sweep.sweepEvent_ = function(tess, vEvent) { tess.event = vEvent; // for access in edgeLeq_ // TODO(bckenny): wuh? - libtess.sweepDebugEvent( tess ); - + libtess.sweepDebugEvent(tess); + /* Check if this vertex is the right endpoint of an edge that is * already in the dictionary. In this case we don't need to waste * time searching for the location to insert new edges. @@ -1279,12 +1304,13 @@ libtess.sweep.sweepEvent_ = function(tess, vEvent) { } }; + /** * We add two sentinel edges above and below all other edges, * to avoid special cases at the top and bottom. * @private - * @param {libtess.GluTesselator} tess [description] - * @param {number} t [description] + * @param {libtess.GluTesselator} tess [description]. + * @param {number} t [description]. */ libtess.sweep.addSentinel_ = function(tess, t) { var reg = new libtess.ActiveRegion(); @@ -1306,11 +1332,12 @@ libtess.sweep.addSentinel_ = function(tess, t) { reg.nodeUp = tess.dict.insert(reg); }; + /** * We maintain an ordering of edge intersections with the sweep line. * This order is maintained in a dynamic dictionary. * @private - * @param {libtess.GluTesselator} tess [description] + * @param {libtess.GluTesselator} tess [description]. */ libtess.sweep.initEdgeDict_ = function(tess) { // TODO(bckenny): need to cast edgeLeq_? @@ -1321,10 +1348,11 @@ libtess.sweep.initEdgeDict_ = function(tess) { libtess.sweep.addSentinel_(tess, libtess.sweep.SENTINEL_COORD_); }; + /** * [doneEdgeDict_ description] * @private - * @param {libtess.GluTesselator} tess [description] + * @param {libtess.GluTesselator} tess [description]. */ libtess.sweep.doneEdgeDict_ = function(tess) { var fixedEdges = 0; @@ -1346,10 +1374,11 @@ libtess.sweep.doneEdgeDict_ = function(tess) { tess.dict = null; }; + /** * Remove zero-length edges, and contours with fewer than 3 vertices. * @private - * @param {libtess.GluTesselator} tess [description] + * @param {libtess.GluTesselator} tess [description]. */ libtess.sweep.removeDegenerateEdges_ = function(tess) { var eHead = tess.mesh.eHead; @@ -1358,7 +1387,7 @@ libtess.sweep.removeDegenerateEdges_ = function(tess) { for (var e = eHead.next; e !== eHead; e = eNext) { eNext = e.next; var eLNext = e.lNext; - + if (libtess.geom.vertEq(e.org, e.dst()) && e.lNext.lNext !== e) { // Zero-length edge, contour has at least 3 edges libtess.sweep.spliceMergeVertices_(tess, eLNext, e); // deletes e.org @@ -1376,7 +1405,7 @@ libtess.sweep.removeDegenerateEdges_ = function(tess) { libtess.mesh.deleteEdge(eLNext); } - if (e === eNext || e === eNext.sym ) { + if (e === eNext || e === eNext.sym) { eNext = eNext.next; } libtess.mesh.deleteEdge(e); @@ -1384,11 +1413,12 @@ libtess.sweep.removeDegenerateEdges_ = function(tess) { } }; + /** * Construct priority queue and insert all vertices into it, which determines * the order in which vertices cross the sweep line. * @private - * @param {libtess.GluTesselator} tess [description] + * @param {libtess.GluTesselator} tess [description]. */ libtess.sweep.initPriorityQ_ = function(tess) { // TODO(bckenny): libtess.geom.vertLeq needs cast? @@ -1405,10 +1435,11 @@ libtess.sweep.initPriorityQ_ = function(tess) { pq.init(); }; + /** * [donePriorityQ_ description] * @private - * @param {libtess.GluTesselator} tess [description] + * @param {libtess.GluTesselator} tess [description]. */ libtess.sweep.donePriorityQ_ = function(tess) { // TODO(bckenny): probably don't need deleteQ. check that function for comment @@ -1416,6 +1447,7 @@ libtess.sweep.donePriorityQ_ = function(tess) { tess.pq = null; }; + /** * Delete any degenerate faces with only two edges. walkDirtyRegions() * will catch almost all of these, but it won't catch degenerate faces @@ -1431,7 +1463,7 @@ libtess.sweep.donePriorityQ_ = function(tess) { * will sometimes be keeping a pointer to that edge. * * @private - * @param {libtess.GluMesh} mesh [description] + * @param {libtess.GluMesh} mesh [description]. */ libtess.sweep.removeDegenerateFaces_ = function(mesh) { var fNext; diff --git a/src/libtess.js/sweep/ActiveRegion.js b/src/libtess.js/sweep/ActiveRegion.js index 21e424a7f7..56773028b0 100644 --- a/src/libtess.js/sweep/ActiveRegion.js +++ b/src/libtess.js/sweep/ActiveRegion.js @@ -41,6 +41,8 @@ // TODO(bckenny): apparently only visible outside of sweep for debugging routines. // find out if we can hide + + /** * For each pair of adjacent edges crossing the sweep line, there is * an ActiveRegion to represent the region between them. The active @@ -75,13 +77,13 @@ libtess.ActiveRegion = function() { * @type {boolean} */ this.inside = false; - + /** * marks fake edges at t = +/-infinity * @type {boolean} */ this.sentinel = false; - + /** * Marks regions where the upper or lower edge has changed, but we haven't * checked whether they intersect yet. @@ -97,18 +99,20 @@ libtess.ActiveRegion = function() { this.fixUpperEdge = false; }; + /** * [regionBelow description] - * @return {libtess.ActiveRegion} [description] + * @return {libtess.ActiveRegion} [description]. */ libtess.ActiveRegion.prototype.regionBelow = function() { // TODO(bckenny): better typing? or is cast unavoidable return /** @type {libtess.ActiveRegion} */ (this.nodeUp.getPred().getKey()); }; + /** * [regionAbove description] - * @return {libtess.ActiveRegion} [description] + * @return {libtess.ActiveRegion} [description]. */ libtess.ActiveRegion.prototype.regionAbove = function() { // TODO(bckenny): better typing? or is cast unavoidable diff --git a/src/libtess.js/tessmono.js b/src/libtess.js/tessmono.js index 1e78abf1dd..270b59f307 100644 --- a/src/libtess.js/tessmono.js +++ b/src/libtess.js/tessmono.js @@ -42,6 +42,7 @@ libtess.tessmono = function() { }; + /** * tessellateMonoRegion(face) tessellates a monotone region * (what else would it do??). The region must consist of a single @@ -52,7 +53,7 @@ libtess.tessmono = function() { * Tessellation consists of adding interior edges (actually pairs of * half-edges), to split the region into non-overlapping triangles. * @private - * @param {libtess.GluFace} face [description] + * @param {libtess.GluFace} face [description]. */ libtess.tessmono.tessellateMonoRegion_ = function(face) { /* The basic idea is explained in Preparata and Shamos (which I don''t @@ -84,7 +85,7 @@ libtess.tessmono.tessellateMonoRegion_ = function(face) { for (; libtess.geom.vertLeq(up.dst(), up.org); up = up.lPrev()) { } for (; libtess.geom.vertLeq(up.org, up.dst()); up = up.lNext) { } - + var lo = up.lPrev(); var tempHalfEdge; @@ -95,7 +96,7 @@ libtess.tessmono.tessellateMonoRegion_ = function(face) { // are CW, given that the upper and lower chains are truly monotone. while (lo.lNext !== up && (libtess.geom.edgeGoesLeft(lo.lNext) || libtess.geom.edgeSign(lo.org, lo.dst(), lo.lNext.dst()) <= 0)) { - + tempHalfEdge = libtess.mesh.connect(lo.lNext, lo); lo = tempHalfEdge.sym; } @@ -105,7 +106,7 @@ libtess.tessmono.tessellateMonoRegion_ = function(face) { // lo.org is on the left. We can make CCW triangles from up.dst(). while (lo.lNext !== up && (libtess.geom.edgeGoesRight(up.lPrev()) || libtess.geom.edgeSign(up.dst(), up.org, up.lPrev().org) >= 0)) { - + tempHalfEdge = libtess.mesh.connect(up, up.lPrev()); up = tempHalfEdge.sym; } @@ -122,12 +123,13 @@ libtess.tessmono.tessellateMonoRegion_ = function(face) { } }; + /** * tessellateInterior(mesh) tessellates each region of * the mesh which is marked "inside" the polygon. Each such region * must be monotone. * - * @param {libtess.GluMesh} mesh [description] + * @param {libtess.GluMesh} mesh [description]. */ libtess.tessmono.tessellateInterior = function(mesh) { var next; @@ -140,13 +142,14 @@ libtess.tessmono.tessellateInterior = function(mesh) { } }; + /** * discardExterior(mesh) zaps (ie. sets to null) all faces * which are not marked "inside" the polygon. Since further mesh operations * on null faces are not allowed, the main purpose is to clean up the * mesh so that exterior loops are not represented in the data structure. * - * @param {libtess.GluMesh} mesh [description] + * @param {libtess.GluMesh} mesh [description]. */ libtess.tessmono.discardExterior = function(mesh) { var next; @@ -159,6 +162,7 @@ libtess.tessmono.discardExterior = function(mesh) { } }; + /** * setWindingNumber(mesh, value, keepOnlyBoundary) resets the * winding numbers on all edges so that regions marked "inside" the @@ -168,7 +172,7 @@ libtess.tessmono.discardExterior = function(mesh) { * If keepOnlyBoundary is true, it also deletes all edges which do not * separate an interior region from an exterior one. * - * @param {libtess.GluMesh} mesh [description] + * @param {libtess.GluMesh} mesh [description]. * @param {number} value Winding number to set (int). */ libtess.tessmono.setWindingNumber = function(mesh, value, keepOnlyBoundary) { @@ -179,7 +183,7 @@ libtess.tessmono.setWindingNumber = function(mesh, value, keepOnlyBoundary) { if (e.rFace().inside !== e.lFace.inside) { // This is a boundary edge (one side is interior, one is exterior). e.winding = (e.lFace.inside) ? value : -value; - + } else { // Both regions are interior, or both are exterior. if (!keepOnlyBoundary) {