From d4fe4c108b46810399b3e8d0c3b9e2189f7e44a9 Mon Sep 17 00:00:00 2001 From: Mysterix Date: Thu, 1 May 2014 21:33:16 +0200 Subject: [PATCH 01/18] Solving multiple shapes display order with new function addOrdered --- js/isomer.js | 29 +++++++++++++++++++++++++++++ 1 file changed, 29 insertions(+) diff --git a/js/isomer.js b/js/isomer.js index 0ff509a..debf5bc 100644 --- a/js/isomer.js +++ b/js/isomer.js @@ -82,6 +82,35 @@ Isomer.prototype.add = function (item, baseColor) { } }; +/** + * Adds an array of shapes to the scene, sorting their faces globally + * so that they are displayed in the right order + * + * Input is given as an array of {shape: yourShape, color: yourColor} + */ + +Isomer.prototype.addOrdered = function (item) { + var Point = Isomer.Point; + var observer = new Point(-10, -10, 10); + var pathList = []; + var index = 0; + + for (var i = 0; i < item.length; i++) { + for(var j = 0 ; j < item[i].shape.paths.length ; j++){ + pathList[index] = { + path: item[i].shape.paths[j], + color: item[i].color, + distance: item[i].shape._pathDistances(item[i].shape.paths[j], observer) + }; + index++; + } + } + pathList.sort(function(pathA, pathB){return (pathB.distance.averageDistance - pathA.distance.averageDistance)}); + + for (var i = 0 ; i < pathList.length ; i++) { + this._addPath(pathList[i].path, pathList[i].color); + } +}; /** * Adds a path to the scene From 6c7169737eff1ef03cd7769ac166a54e6c5625fd Mon Sep 17 00:00:00 2001 From: Mysterix Date: Fri, 2 May 2014 19:07:49 +0200 Subject: [PATCH 02/18] Revert "Solving multiple shapes display order with new function addOrdered" This reverts commit d4fe4c108b46810399b3e8d0c3b9e2189f7e44a9. --- js/isomer.js | 29 ----------------------------- 1 file changed, 29 deletions(-) diff --git a/js/isomer.js b/js/isomer.js index debf5bc..0ff509a 100644 --- a/js/isomer.js +++ b/js/isomer.js @@ -82,35 +82,6 @@ Isomer.prototype.add = function (item, baseColor) { } }; -/** - * Adds an array of shapes to the scene, sorting their faces globally - * so that they are displayed in the right order - * - * Input is given as an array of {shape: yourShape, color: yourColor} - */ - -Isomer.prototype.addOrdered = function (item) { - var Point = Isomer.Point; - var observer = new Point(-10, -10, 10); - var pathList = []; - var index = 0; - - for (var i = 0; i < item.length; i++) { - for(var j = 0 ; j < item[i].shape.paths.length ; j++){ - pathList[index] = { - path: item[i].shape.paths[j], - color: item[i].color, - distance: item[i].shape._pathDistances(item[i].shape.paths[j], observer) - }; - index++; - } - } - pathList.sort(function(pathA, pathB){return (pathB.distance.averageDistance - pathA.distance.averageDistance)}); - - for (var i = 0 ; i < pathList.length ; i++) { - this._addPath(pathList[i].path, pathList[i].color); - } -}; /** * Adds a path to the scene From 7371c166ab63c7289df713d92bec5f71d8bd0aa0 Mon Sep 17 00:00:00 2001 From: Mysterix Date: Fri, 2 May 2014 19:20:17 +0200 Subject: [PATCH 03/18] Solves issue #9 : paths ordering and shapes ordering --- js/isomer.js | 26 ++++++++++++++++++++++++++ js/path.js | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 59 insertions(+) diff --git a/js/isomer.js b/js/isomer.js index 0ff509a..318fd3a 100644 --- a/js/isomer.js +++ b/js/isomer.js @@ -82,6 +82,32 @@ Isomer.prototype.add = function (item, baseColor) { } }; +/** + * Adds an array of {shape: yourShape, color: yourColor} to the scene, + * ordered so that distant faces are displayed first + * */ +Isomer.prototype.addOrdered = function (item) { // array of {shape:, color:} + var Point = Isomer.Point; + var observer = new Point(-10, -10, 10); + var pathList = []; + var index = 0; + + for (var i = 0; i < item.length; i++) { + for(var j = 0 ; j < item[i].shape.paths.length ; j++){ + pathList[index] = { + path: item[i].shape.paths[j], + color: item[i].color + }; + index++; + } + } + pathList.sort(function(pathA, pathB){return (pathA.closerThan(pathB, observer))?1:-1;}); + + for (var i = 0 ; i < pathList.length ; i++) { + this._addPath(pathList[i].path, pathList[i].color); + } +}; + /** * Adds a path to the scene diff --git a/js/path.js b/js/path.js index 3f0f2bc..270cd37 100644 --- a/js/path.js +++ b/js/path.js @@ -88,6 +88,39 @@ }; + /** + * If pathB ("this") is closer from the observer than pathA, it must be drawn after. + * It is closer if one of its vertices and the observer are on the same side of the plane defined by pathA. + */ + Path.prototype.closerThan = function(pathA, observer) { + var i = 0; + // the plane containing pathA is defined by the three points A, B, C + var AB = Vector.fromTwoPoints(pathA.points[0], pathA.points[1]); + var AC = Vector.fromTwoPoints(pathA.points[0], pathA.points[2]); + var n = Vector.crossProduct(AB, AC); + + var OA = Vector.fromTwoPoints(Point.ORIGIN, pathA.points[0]); + var OU = Vector.fromTwoPoints(Point.ORIGIN, observer); //U = user = observer + + // Plane defined by pathA such as ax + by + zc = d + // Here d = nx*x + ny*y + nz*z = n.OA + var d = Vector.dotProduct(n, OA); + + var observerPosition = Vector.dotProduct(n, OU) - d; + + for (i = 0; i < this.points.length; i++) { + var OP = Vector.fromTwoPoints(Point.ORIGIN, this.points[i]); + var pPosition = Vector.dotProduct(n, OP) - d; + if(observerPosition * pPosition > 0){ //same sign = same side + return 1; + } + } + + return 0; + + }; + + /** * Some paths to play with */ From 017910ce330ff187a70898b55a6ecd185833bbc9 Mon Sep 17 00:00:00 2001 From: Mysterix Date: Sat, 3 May 2014 00:48:30 +0200 Subject: [PATCH 04/18] More complex way to find closer path --- js/isomer.js | 18 +++++++++++++++--- js/path.js | 20 ++++++++++++-------- 2 files changed, 27 insertions(+), 11 deletions(-) diff --git a/js/isomer.js b/js/isomer.js index 318fd3a..831b5c7 100644 --- a/js/isomer.js +++ b/js/isomer.js @@ -91,17 +91,29 @@ Isomer.prototype.addOrdered = function (item) { // array of {shape:, color:} var observer = new Point(-10, -10, 10); var pathList = []; var index = 0; - for (var i = 0; i < item.length; i++) { for(var j = 0 ; j < item[i].shape.paths.length ; j++){ pathList[index] = { path: item[i].shape.paths[j], - color: item[i].color + color: item[i].color, + nbCloser: 0 }; index++; } } - pathList.sort(function(pathA, pathB){return (pathA.closerThan(pathB, observer))?1:-1;}); + + for (var i = 0 ; i < pathList.length ; i++) { + for (var j = 0 ; j < i ; j++) { + var cmpPath = pathList[i].path.closerThan(pathList[j].path, observer); + var cmpPath2 = pathList[i].path.depth() - pathList[j].path.depth(); + if(cmpPath > 0 || (cmpPath == 0 && cmpPath2 > 0)){ + pathList[i].nbCloser++; + } else { + pathList[j].nbCloser++; + } + } + } + pathList.sort(function(pathA, pathB){return (pathB.nbCloser - pathA.nbCloser);}); for (var i = 0 ; i < pathList.length ; i++) { this._addPath(pathList[i].path, pathList[i].color); diff --git a/js/path.js b/js/path.js index 270cd37..f8df684 100644 --- a/js/path.js +++ b/js/path.js @@ -93,30 +93,34 @@ * It is closer if one of its vertices and the observer are on the same side of the plane defined by pathA. */ Path.prototype.closerThan = function(pathA, observer) { - var i = 0; + var result = pathA._countCloserThan(this, observer) - this._countCloserThan(pathA, observer); + return result; + } + + Path.prototype._countCloserThan = function(pathA, observer) { + var Vector = Isomer.Vector; + var i = 0; // the plane containing pathA is defined by the three points A, B, C var AB = Vector.fromTwoPoints(pathA.points[0], pathA.points[1]); var AC = Vector.fromTwoPoints(pathA.points[0], pathA.points[2]); var n = Vector.crossProduct(AB, AC); - + var OA = Vector.fromTwoPoints(Point.ORIGIN, pathA.points[0]); var OU = Vector.fromTwoPoints(Point.ORIGIN, observer); //U = user = observer // Plane defined by pathA such as ax + by + zc = d // Here d = nx*x + ny*y + nz*z = n.OA var d = Vector.dotProduct(n, OA); - var observerPosition = Vector.dotProduct(n, OU) - d; - + var result = 0; for (i = 0; i < this.points.length; i++) { var OP = Vector.fromTwoPoints(Point.ORIGIN, this.points[i]); var pPosition = Vector.dotProduct(n, OP) - d; - if(observerPosition * pPosition > 0){ //same sign = same side - return 1; + if(observerPosition * pPosition >= 0){ + result++; } } - - return 0; + return (result / this.points.length); }; From 2a155aff4c18562c0689817f6ebc71494e3eb40f Mon Sep 17 00:00:00 2001 From: Mysterix Date: Sun, 4 May 2014 17:26:52 +0200 Subject: [PATCH 05/18] Only sort intersecting polygones (slow but correct) --- js/isomer.js | 153 ++++++++++++++++++++++++++++++++++++++++++++++----- js/path.js | 21 ++++++- 2 files changed, 159 insertions(+), 15 deletions(-) diff --git a/js/isomer.js b/js/isomer.js index 831b5c7..a9df799 100644 --- a/js/isomer.js +++ b/js/isomer.js @@ -88,39 +88,164 @@ Isomer.prototype.add = function (item, baseColor) { * */ Isomer.prototype.addOrdered = function (item) { // array of {shape:, color:} var Point = Isomer.Point; - var observer = new Point(-10, -10, 10); + //var observer = new Point(-10, -10, 10); + var observer = new Point(-10, -10, 10000); var pathList = []; var index = 0; for (var i = 0; i < item.length; i++) { for(var j = 0 ; j < item[i].shape.paths.length ; j++){ pathList[index] = { path: item[i].shape.paths[j], - color: item[i].color, - nbCloser: 0 + color: item[i].color }; index++; } } + + + + //pathList = [pathList[0], pathList[8], ]; + //pathList = [pathList[5],pathList[29]]; + //pathList[7],pathList[8],pathList[9],pathList[10],pathList[11]]; + + //pathList = [pathList[1], pathList[2],]; + //pathList[10],pathList[11]]; + console.log(pathList[0].path.points); + console.log(pathList[1].path.points); - for (var i = 0 ; i < pathList.length ; i++) { - for (var j = 0 ; j < i ; j++) { - var cmpPath = pathList[i].path.closerThan(pathList[j].path, observer); - var cmpPath2 = pathList[i].path.depth() - pathList[j].path.depth(); - if(cmpPath > 0 || (cmpPath == 0 && cmpPath2 > 0)){ - pathList[i].nbCloser++; + + console.log("0->1 " + pathList[0].path._countCloserThan(pathList[1].path, observer)); + console.log("1->0 " + pathList[1].path._countCloserThan(pathList[0].path, observer)); + console.log("conclude " + pathList[0].path.closerThan(pathList[1].path, observer)); + + + // topological sort + + var drawnPath = []; + var drawBefore = []; + for (var i = 0 ; i < pathList.length ; i++){ + drawnPath[i] = 0; + drawBefore[i] = []; + } + for (var i = 0 ; i < pathList.length ; i++){ + for (var j = 0 ; j < i ; j++){ + if(this._hasIntersection(pathList[i].path, pathList[j].path)){ + var cmpPath = pathList[i].path.closerThan(pathList[j].path, observer); + if(cmpPath < 0){ + drawBefore[i][drawBefore[i].length] = j; + } + if(cmpPath > 0){ + drawBefore[j][drawBefore[j].length] = i; + } } else { - pathList[j].nbCloser++; + //console.log("no intesect : " + i + " " + j); } - } + } + } + for (var i = 0 ; i < pathList.length ; i++){ + console.log(i); + console.log(drawBefore[i]); } - pathList.sort(function(pathA, pathB){return (pathB.nbCloser - pathA.nbCloser);}); - for (var i = 0 ; i < pathList.length ; i++) { - this._addPath(pathList[i].path, pathList[i].color); + var drawThisTurn = 1; + var index = 0; + while(drawThisTurn == 1){ + console.log("turn " + index); + index++; + drawThisTurn = 0; + for (var i = 0 ; i < pathList.length ; i++){ + if(drawnPath[i] == 0){ + var canDraw = 1; + for (var j = 0 ; j < drawBefore[i].length ; j++){ + if(drawnPath[drawBefore[i][j]] == 0){canDraw = 0;} + } + if(canDraw == 1){ + this._addPath(pathList[i].path, pathList[i].color); + drawThisTurn = 1; + drawnPath[i] = 1; + } + } + } + } + console.log(drawnPath); + }; +//+ Jonas Raoni Soares Silva +//@ http://jsfromhell.com/math/is-point-in-poly [rev. #0] +function isPointInPoly(poly, pt){ + for(var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i) + ((poly[i].y <= pt.y && pt.y < poly[j].y) || (poly[j].y <= pt.y && pt.y < poly[i].y)) + && (pt.x < (poly[j].x - poly[i].x) * (pt.y - poly[i].y) / (poly[j].y - poly[i].y) + poly[i].x) + && (c = !c); + return c; +} + + +/** + * Does pathA has intersection with pathB ? + * Naïve approach done first : approximate the paths with a rectangle + * Then more complex method + */ +Isomer.prototype._hasIntersection = function(pathA, pathB) { + var pointsA = pathA.points.map(this._translatePoint.bind(this)); + var pointsB = pathB.points.map(this._translatePoint.bind(this)); + var i, j; + + var AminX = pointsA[0].x; + var AminY = pointsA[0].y; + var AmaxX = AminX; + var AmaxY = AminY; + var BminX = pointsB[0].x; + var BminY = pointsB[0].y; + var BmaxX = BminX; + var BmaxY = BminY; + for(i = 0 ; i < pointsA.length ; i++){ + AminX = Math.min(AminX, pointsA[i].x); + AminY = Math.min(AminY, pointsA[i].y); + AmaxX = Math.max(AmaxX, pointsA[i].x); + AmaxY = Math.max(AmaxY, pointsA[i].y); + } + for(i = 0 ; i < pointsB.length ; i++){ + BminX = Math.min(BminX, pointsB[i].x); + BminY = Math.min(BminY, pointsB[i].y); + BmaxX = Math.max(BmaxX, pointsB[i].x); + BmaxY = Math.max(BmaxY, pointsB[i].y); + } + + //console.log([AminX, AmaxX, BminX, BmaxX, AminY, AmaxY, BminY, BmaxY]); + + if(((AminX <= BminX && BminX <= AmaxX) || (BminX <= AminX && AminX <= BmaxX)) && + ((AminY <= BminY && BminY <= AmaxY) || (BminY <= AminY && AminY <= BmaxY))) { + // now let's be more specific + // console.log("points A pointsB polyA polyB"); + //console.log(pointsA); + //console.log(pointsB); + var polyA = pointsA.slice(); + var polyB = pointsB.slice(); + polyA.push(pointsA[0]); + polyB.push(pointsB[0]); + //console.log(polyA); + //console.log(polyB); + for(i = Math.min(Math.floor(AminX), Math.floor(BminX)) ; i < Math.max(Math.ceil(AmaxX), Math.ceil(BmaxX)) ; i++){ + for(j = Math.min(Math.floor(AminY), Math.floor(BminY)) ; j < Math.max(Math.ceil(AmaxY), Math.ceil(BmaxY)) ; j++){ + if(isPointInPoly(polyA, {x:i, y:j}) && isPointInPoly(polyB, {x:i, y:j})){ + //console.log("return 1"); + return 1; + } + } + } + //console.log("return 00"); + return 0; + } else { + //console.log("return 0"); + return 0; + } + +}; + /** * Adds a path to the scene */ diff --git a/js/path.js b/js/path.js index f8df684..5395cc3 100644 --- a/js/path.js +++ b/js/path.js @@ -94,16 +94,26 @@ */ Path.prototype.closerThan = function(pathA, observer) { var result = pathA._countCloserThan(this, observer) - this._countCloserThan(pathA, observer); + //console.log(result); return result; } Path.prototype._countCloserThan = function(pathA, observer) { + //console.log("counting"); var Vector = Isomer.Vector; var i = 0; + + //console.log("pathA"); + //console.log(pathA); // the plane containing pathA is defined by the three points A, B, C var AB = Vector.fromTwoPoints(pathA.points[0], pathA.points[1]); var AC = Vector.fromTwoPoints(pathA.points[0], pathA.points[2]); var n = Vector.crossProduct(AB, AC); + // console.log("AB AC n A d n.OU :"); + // console.log(AB); + // console.log(AC); + // console.log(n); + // console.log(pathA.points[0]); var OA = Vector.fromTwoPoints(Point.ORIGIN, pathA.points[0]); var OU = Vector.fromTwoPoints(Point.ORIGIN, observer); //U = user = observer @@ -111,18 +121,27 @@ // Plane defined by pathA such as ax + by + zc = d // Here d = nx*x + ny*y + nz*z = n.OA var d = Vector.dotProduct(n, OA); + // console.log(d); var observerPosition = Vector.dotProduct(n, OU) - d; + // console.log(Vector.dotProduct(n, OU)); var result = 0; for (i = 0; i < this.points.length; i++) { var OP = Vector.fromTwoPoints(Point.ORIGIN, this.points[i]); + // console.log("OP"); + // console.log(OP); var pPosition = Vector.dotProduct(n, OP) - d; - if(observerPosition * pPosition >= 0){ + // console.log(Vector.dotProduct(n, OP)); + // console.log(i+" prod = "+(observerPosition * pPosition)); + if(observerPosition * pPosition >= -0.01){ result++; } } + //console.log("__" + (result / this.points.length)); return (result / this.points.length); }; + + /** From a455b3fa531c51e2687eb87c1aa0bd04c724c252 Mon Sep 17 00:00:00 2001 From: Mysterix Date: Sun, 4 May 2014 19:23:50 +0200 Subject: [PATCH 06/18] Intersection : perf improvement --- js/isomer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/js/isomer.js b/js/isomer.js index a9df799..16157fc 100644 --- a/js/isomer.js +++ b/js/isomer.js @@ -229,8 +229,8 @@ Isomer.prototype._hasIntersection = function(pathA, pathB) { polyB.push(pointsB[0]); //console.log(polyA); //console.log(polyB); - for(i = Math.min(Math.floor(AminX), Math.floor(BminX)) ; i < Math.max(Math.ceil(AmaxX), Math.ceil(BmaxX)) ; i++){ - for(j = Math.min(Math.floor(AminY), Math.floor(BminY)) ; j < Math.max(Math.ceil(AmaxY), Math.ceil(BmaxY)) ; j++){ + for(i = Math.max(Math.floor(AminX), Math.floor(BminX)) ; i < Math.min(Math.ceil(AmaxX), Math.ceil(BmaxX)) ; i++){ + for(j = Math.max(Math.floor(AminY), Math.floor(BminY)) ; j < Math.min(Math.ceil(AmaxY), Math.ceil(BmaxY)) ; j++){ if(isPointInPoly(polyA, {x:i, y:j}) && isPointInPoly(polyB, {x:i, y:j})){ //console.log("return 1"); return 1; From 19e14d0419ec64deafa9dd05d0b96dbb51bb3a4a Mon Sep 17 00:00:00 2001 From: Mysterix Date: Sun, 4 May 2014 23:09:38 +0200 Subject: [PATCH 07/18] Dot product very very closed to 0 caused some problems --- js/isomer.js | 65 +++++++++++++++++++++++++++++++++++++--------------- js/path.js | 35 +++++++++++++++++----------- 2 files changed, 68 insertions(+), 32 deletions(-) diff --git a/js/isomer.js b/js/isomer.js index 16157fc..f99bfe2 100644 --- a/js/isomer.js +++ b/js/isomer.js @@ -96,7 +96,8 @@ Isomer.prototype.addOrdered = function (item) { // array of {shape:, color:} for(var j = 0 ; j < item[i].shape.paths.length ; j++){ pathList[index] = { path: item[i].shape.paths[j], - color: item[i].color + color: item[i].color, + drawn: 0 }; index++; } @@ -104,27 +105,46 @@ Isomer.prototype.addOrdered = function (item) { // array of {shape:, color:} - //pathList = [pathList[0], pathList[8], ]; + /* pathList = [ + //pathList[0], + pathList[1], + //pathList[2], + //pathList[3], + //pathList[4], + // pathList[5],pathList[6],pathList[7],pathList[8],pathList[9], + //pathList[10],pathList[11], + //pathList[12], + //pathList[13], + pathList[14], + //pathList[15], + //pathList[16],pathList[17],pathList[18],pathList[19], + // pathList[20],pathList[21],pathList[22],pathList[23],pathList[24], + //pathList[25], + //pathList[26], + //pathList[27] + + ];*/ //pathList = [pathList[5],pathList[29]]; //pathList[7],pathList[8],pathList[9],pathList[10],pathList[11]]; //pathList = [pathList[1], pathList[2],]; //pathList[10],pathList[11]]; - console.log(pathList[0].path.points); - console.log(pathList[1].path.points); + //console.log(pathList[0].path.points); + //console.log(pathList[2].path.points); - console.log("0->1 " + pathList[0].path._countCloserThan(pathList[1].path, observer)); - console.log("1->0 " + pathList[1].path._countCloserThan(pathList[0].path, observer)); - console.log("conclude " + pathList[0].path.closerThan(pathList[1].path, observer)); - + //console.log("0->2 " + pathList[0].path._countCloserThan(pathList[2].path, observer)); + //console.log("2->0 " + pathList[2].path._countCloserThan(pathList[0].path, observer)); + //console.log("conclude " + pathList[0].path.closerThan(pathList[2].path, observer)); - // topological sort + // console.log("0->1 " + pathList[0].path._countCloserThan(pathList[1].path, observer)); + // console.log("1->0 " + pathList[1].path._countCloserThan(pathList[0].path, observer)); + // console.log("conclude " + pathList[0].path.closerThan(pathList[1].path, observer)); + + // topological sort - var drawnPath = []; var drawBefore = []; for (var i = 0 ; i < pathList.length ; i++){ - drawnPath[i] = 0; drawBefore[i] = []; } for (var i = 0 ; i < pathList.length ; i++){ @@ -154,21 +174,29 @@ Isomer.prototype.addOrdered = function (item) { // array of {shape:, color:} index++; drawThisTurn = 0; for (var i = 0 ; i < pathList.length ; i++){ - if(drawnPath[i] == 0){ + if(pathList[i].drawn == 0){ var canDraw = 1; for (var j = 0 ; j < drawBefore[i].length ; j++){ - if(drawnPath[drawBefore[i][j]] == 0){canDraw = 0;} + if(pathList[drawBefore[i][j]].drawn == 0){canDraw = 0;} } if(canDraw == 1){ this._addPath(pathList[i].path, pathList[i].color); drawThisTurn = 1; - drawnPath[i] = 1; + pathList[i].drawn = 1; } } } } - console.log(drawnPath); + //purge + //could be done more in a smarter order, that's why drawn is is an element of pathList[] and not a separate array + for (var i = 0 ; i < pathList.length ; i++){ + if(pathList[i].drawn == 0){ + console.log("purging : "+i); + this._addPath(pathList[i].path, pathList[i].color); + } + } + }; @@ -193,7 +221,7 @@ Isomer.prototype._hasIntersection = function(pathA, pathB) { var pointsA = pathA.points.map(this._translatePoint.bind(this)); var pointsB = pathB.points.map(this._translatePoint.bind(this)); var i, j; - + //console.log("_hasIntersection"); var AminX = pointsA[0].x; var AminY = pointsA[0].y; var AmaxX = AminX; @@ -229,8 +257,9 @@ Isomer.prototype._hasIntersection = function(pathA, pathB) { polyB.push(pointsB[0]); //console.log(polyA); //console.log(polyB); - for(i = Math.max(Math.floor(AminX), Math.floor(BminX)) ; i < Math.min(Math.ceil(AmaxX), Math.ceil(BmaxX)) ; i++){ - for(j = Math.max(Math.floor(AminY), Math.floor(BminY)) ; j < Math.min(Math.ceil(AmaxY), Math.ceil(BmaxY)) ; j++){ + // Parse common rectangle to find intersection. For better performance, we can monte-carlo this. + for(i = Math.floor(Math.max(AminX, BminX)) + 1 ; i <= Math.ceil(Math.min(AmaxX, BmaxX)) - 1 ; i++){ + for(j = Math.floor(Math.max(AminY, BminY)) + 1 ; j <= Math.ceil(Math.min(AmaxY, BmaxY)) - 1 ; j++){ if(isPointInPoly(polyA, {x:i, y:j}) && isPointInPoly(polyB, {x:i, y:j})){ //console.log("return 1"); return 1; diff --git a/js/path.js b/js/path.js index 5395cc3..d7315ae 100644 --- a/js/path.js +++ b/js/path.js @@ -109,11 +109,11 @@ var AB = Vector.fromTwoPoints(pathA.points[0], pathA.points[1]); var AC = Vector.fromTwoPoints(pathA.points[0], pathA.points[2]); var n = Vector.crossProduct(AB, AC); - // console.log("AB AC n A d n.OU :"); - // console.log(AB); - // console.log(AC); - // console.log(n); - // console.log(pathA.points[0]); + //console.log("AB AC n A d n.OU :"); + //console.log(AB); + //console.log(AC); + //console.log(n); + //console.log(pathA.points[0]); var OA = Vector.fromTwoPoints(Point.ORIGIN, pathA.points[0]); var OU = Vector.fromTwoPoints(Point.ORIGIN, observer); //U = user = observer @@ -121,24 +121,31 @@ // Plane defined by pathA such as ax + by + zc = d // Here d = nx*x + ny*y + nz*z = n.OA var d = Vector.dotProduct(n, OA); - // console.log(d); + //console.log(d); var observerPosition = Vector.dotProduct(n, OU) - d; - // console.log(Vector.dotProduct(n, OU)); + //console.log(Vector.dotProduct(n, OU)); var result = 0; + var result0 = 0; for (i = 0; i < this.points.length; i++) { var OP = Vector.fromTwoPoints(Point.ORIGIN, this.points[i]); - // console.log("OP"); - // console.log(OP); + //console.log("OP"); + //console.log(OP); var pPosition = Vector.dotProduct(n, OP) - d; - // console.log(Vector.dotProduct(n, OP)); - // console.log(i+" prod = "+(observerPosition * pPosition)); - if(observerPosition * pPosition >= -0.01){ + //console.log(Vector.dotProduct(n, OP)); + //console.log(i+" prod = "+(observerPosition * pPosition)); + if(observerPosition * pPosition > 0){ result++; + } + if(observerPosition * pPosition >= -0.000000001 && observerPosition * pPosition <= 0){ + result0++; } } //console.log("__" + (result / this.points.length)); - return (result / this.points.length); - + if(result == 0){ + return 0; + } else { + return ((result + result0) / this.points.length); + } }; From be8b04d23804fe233e56daf0c331c54fac9538bc Mon Sep 17 00:00:00 2001 From: Mysterix Date: Tue, 6 May 2014 21:21:45 +0200 Subject: [PATCH 08/18] Corrected the observer position (if observer has a meaning with isometric) --- js/isomer.js | 5 ++--- js/path.js | 4 ++-- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/js/isomer.js b/js/isomer.js index f99bfe2..0a5f7ec 100644 --- a/js/isomer.js +++ b/js/isomer.js @@ -89,7 +89,7 @@ Isomer.prototype.add = function (item, baseColor) { Isomer.prototype.addOrdered = function (item) { // array of {shape:, color:} var Point = Isomer.Point; //var observer = new Point(-10, -10, 10); - var observer = new Point(-10, -10, 10000); + var observer = new Point(-10, -10, 20); var pathList = []; var index = 0; for (var i = 0; i < item.length; i++) { @@ -124,8 +124,7 @@ Isomer.prototype.addOrdered = function (item) { // array of {shape:, color:} //pathList[27] ];*/ - //pathList = [pathList[5],pathList[29]]; - //pathList[7],pathList[8],pathList[9],pathList[10],pathList[11]]; + //pathList = [pathList[1],pathList[3]]; //pathList = [pathList[1], pathList[2],]; //pathList[10],pathList[11]]; diff --git a/js/path.js b/js/path.js index d7315ae..1defb64 100644 --- a/js/path.js +++ b/js/path.js @@ -133,10 +133,10 @@ var pPosition = Vector.dotProduct(n, OP) - d; //console.log(Vector.dotProduct(n, OP)); //console.log(i+" prod = "+(observerPosition * pPosition)); - if(observerPosition * pPosition > 0){ + if(observerPosition * pPosition >= 0.000000001){ //careful with rounding approximations result++; } - if(observerPosition * pPosition >= -0.000000001 && observerPosition * pPosition <= 0){ + if(observerPosition * pPosition >= -0.000000001 && observerPosition * pPosition < 0.000000001){ result0++; } } From b6c590e8e670909d35f3285382aaa7290b61c529 Mon Sep 17 00:00:00 2001 From: Mysterix Date: Thu, 8 May 2014 00:22:12 +0200 Subject: [PATCH 09/18] Faster 2d-polygon intersection method --- js/isomer.js | 65 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 51 insertions(+), 14 deletions(-) diff --git a/js/isomer.js b/js/isomer.js index 0a5f7ec..8d63d76 100644 --- a/js/isomer.js +++ b/js/isomer.js @@ -148,6 +148,7 @@ Isomer.prototype.addOrdered = function (item) { // array of {shape:, color:} } for (var i = 0 ; i < pathList.length ; i++){ for (var j = 0 ; j < i ; j++){ + //console.log("i:"+i+",j:"+j+"hasIntesect:"+this._hasIntersection(pathList[i].path, pathList[j].path)); if(this._hasIntersection(pathList[i].path, pathList[j].path)){ var cmpPath = pathList[i].path.closerThan(pathList[j].path, observer); if(cmpPath < 0){ @@ -202,6 +203,7 @@ Isomer.prototype.addOrdered = function (item) { // array of {shape:, color:} //+ Jonas Raoni Soares Silva //@ http://jsfromhell.com/math/is-point-in-poly [rev. #0] +//see also http://jsperf.com/ispointinpath-boundary-test-speed/2 function isPointInPoly(poly, pt){ for(var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i) ((poly[i].y <= pt.y && pt.y < poly[j].y) || (poly[j].y <= pt.y && pt.y < poly[i].y)) @@ -213,8 +215,8 @@ function isPointInPoly(poly, pt){ /** * Does pathA has intersection with pathB ? - * Naïve approach done first : approximate the paths with a rectangle - * Then more complex method + * Naïve approach done first : approximate the polygons with a rectangle + * Then more complex method : see if edges cross, or one contained in the other */ Isomer.prototype._hasIntersection = function(pathA, pathB) { var pointsA = pathA.points.map(this._translatePoint.bind(this)); @@ -247,28 +249,63 @@ Isomer.prototype._hasIntersection = function(pathA, pathB) { if(((AminX <= BminX && BminX <= AmaxX) || (BminX <= AminX && AminX <= BmaxX)) && ((AminY <= BminY && BminY <= AmaxY) || (BminY <= AminY && AminY <= BmaxY))) { // now let's be more specific - // console.log("points A pointsB polyA polyB"); - //console.log(pointsA); - //console.log(pointsB); var polyA = pointsA.slice(); var polyB = pointsB.slice(); polyA.push(pointsA[0]); polyB.push(pointsB[0]); //console.log(polyA); //console.log(polyB); - // Parse common rectangle to find intersection. For better performance, we can monte-carlo this. - for(i = Math.floor(Math.max(AminX, BminX)) + 1 ; i <= Math.ceil(Math.min(AmaxX, BmaxX)) - 1 ; i++){ - for(j = Math.floor(Math.max(AminY, BminY)) + 1 ; j <= Math.ceil(Math.min(AmaxY, BmaxY)) - 1 ; j++){ - if(isPointInPoly(polyA, {x:i, y:j}) && isPointInPoly(polyB, {x:i, y:j})){ - //console.log("return 1"); - return 1; + // see if edges cross, or one contained in the other + var crossing = 0; + + + var deltaAX = []; + var deltaAY = []; + var deltaBX = []; + var deltaBY = []; + var rA = []; + var rB = []; + for(i = 0 ; i <= polyA.length - 2 ; i++){ + deltaAX[i] = polyA[i+1].x - polyA[i].x; + deltaAY[i] = polyA[i+1].y - polyA[i].y; + //equation written as deltaY.x - deltaX.y + r = 0 + rA[i] = deltaAX[i] * polyA[i].y - deltaAY[i] * polyA[i].x; + } + for(i = 0 ; i <= polyB.length - 2 ; i++){ + deltaBX[i] = polyB[i+1].x - polyB[i].x; + deltaBY[i] = polyB[i+1].y - polyB[i].y; + rB[i] = deltaBX[i] * polyB[i].y - deltaBY[i] * polyB[i].x; + } + + + crossExam: + for(i = 0 ; i <= polyA.length - 2 ; i++){ + for(j = 0 ; j <= polyB.length - 2 ; j++){ + if( deltaAX[i] * deltaBY[j] != deltaAY[i] * deltaBX[j]){ + //case when vectors are colinear, or one polygon included in the other, is covered after + //two segments cross each other if and only if the points of the first are on each side of the line defined by the second and vice-versa + if((deltaAY[i] * polyB[j].x - deltaAX[i] * polyB[j].y + rA[i]) * (deltaAY[i] * polyB[j+1].x - deltaAX[i] * polyB[j+1].y + rA[i]) < -0.000000001 && + (deltaBY[j] * polyA[i].x - deltaBX[j] * polyA[i].y + rB[j]) * (deltaBY[j] * polyA[i+1].x - deltaBX[j] * polyA[i+1].y + rB[j]) < -0.000000001){ + crossing = 1; + break crossExam; + } } } } - //console.log("return 00"); - return 0; + + for(i = 0 ; i <= polyA.length - 2 ; i++){ + if(isPointInPoly(polyB, {x:polyA[i].x, y:polyA[i].y})){ + crossing = 1; + } + } + for(i = 0 ; i <= polyB.length - 2 ; i++){ + if(isPointInPoly(polyA, {x:polyB[i].x, y:polyB[i].y})){ + crossing = 1; + } + } + + return crossing; } else { - //console.log("return 0"); return 0; } From 092ec9facb26fc5ca12a0938eb2cadff968d3d43 Mon Sep 17 00:00:00 2001 From: Mysterix Date: Thu, 8 May 2014 18:31:42 +0200 Subject: [PATCH 10/18] Optimization and code cleaning. --- js/isomer.js | 83 ++++++++-------------------------------------------- js/path.js | 17 +---------- 2 files changed, 13 insertions(+), 87 deletions(-) diff --git a/js/isomer.js b/js/isomer.js index 8d63d76..7b0e34c 100644 --- a/js/isomer.js +++ b/js/isomer.js @@ -86,9 +86,8 @@ Isomer.prototype.add = function (item, baseColor) { * Adds an array of {shape: yourShape, color: yourColor} to the scene, * ordered so that distant faces are displayed first * */ -Isomer.prototype.addOrdered = function (item) { // array of {shape:, color:} +Isomer.prototype.addOrdered = function (item) { var Point = Isomer.Point; - //var observer = new Point(-10, -10, 10); var observer = new Point(-10, -10, 20); var pathList = []; var index = 0; @@ -96,49 +95,13 @@ Isomer.prototype.addOrdered = function (item) { // array of {shape:, color:} for(var j = 0 ; j < item[i].shape.paths.length ; j++){ pathList[index] = { path: item[i].shape.paths[j], + polygon: item[i].shape.paths[j].points.map(this._translatePoint.bind(this)), color: item[i].color, drawn: 0 }; index++; } } - - - - /* pathList = [ - //pathList[0], - pathList[1], - //pathList[2], - //pathList[3], - //pathList[4], - // pathList[5],pathList[6],pathList[7],pathList[8],pathList[9], - //pathList[10],pathList[11], - //pathList[12], - //pathList[13], - pathList[14], - //pathList[15], - //pathList[16],pathList[17],pathList[18],pathList[19], - // pathList[20],pathList[21],pathList[22],pathList[23],pathList[24], - //pathList[25], - //pathList[26], - //pathList[27] - - ];*/ - //pathList = [pathList[1],pathList[3]]; - - //pathList = [pathList[1], pathList[2],]; - //pathList[10],pathList[11]]; - //console.log(pathList[0].path.points); - //console.log(pathList[2].path.points); - - - //console.log("0->2 " + pathList[0].path._countCloserThan(pathList[2].path, observer)); - //console.log("2->0 " + pathList[2].path._countCloserThan(pathList[0].path, observer)); - //console.log("conclude " + pathList[0].path.closerThan(pathList[2].path, observer)); - - // console.log("0->1 " + pathList[0].path._countCloserThan(pathList[1].path, observer)); - // console.log("1->0 " + pathList[1].path._countCloserThan(pathList[0].path, observer)); - // console.log("conclude " + pathList[0].path.closerThan(pathList[1].path, observer)); // topological sort @@ -148,8 +111,7 @@ Isomer.prototype.addOrdered = function (item) { // array of {shape:, color:} } for (var i = 0 ; i < pathList.length ; i++){ for (var j = 0 ; j < i ; j++){ - //console.log("i:"+i+",j:"+j+"hasIntesect:"+this._hasIntersection(pathList[i].path, pathList[j].path)); - if(this._hasIntersection(pathList[i].path, pathList[j].path)){ + if(this._hasIntersection(pathList[i].polygon, pathList[j].polygon)){ var cmpPath = pathList[i].path.closerThan(pathList[j].path, observer); if(cmpPath < 0){ drawBefore[i][drawBefore[i].length] = j; @@ -157,20 +119,12 @@ Isomer.prototype.addOrdered = function (item) { // array of {shape:, color:} if(cmpPath > 0){ drawBefore[j][drawBefore[j].length] = i; } - } else { - //console.log("no intesect : " + i + " " + j); } } } - for (var i = 0 ; i < pathList.length ; i++){ - console.log(i); - console.log(drawBefore[i]); - } - var drawThisTurn = 1; var index = 0; while(drawThisTurn == 1){ - console.log("turn " + index); index++; drawThisTurn = 0; for (var i = 0 ; i < pathList.length ; i++){ @@ -186,18 +140,14 @@ Isomer.prototype.addOrdered = function (item) { // array of {shape:, color:} } } } - } //purge //could be done more in a smarter order, that's why drawn is is an element of pathList[] and not a separate array for (var i = 0 ; i < pathList.length ; i++){ if(pathList[i].drawn == 0){ - console.log("purging : "+i); this._addPath(pathList[i].path, pathList[i].color); } } - - }; @@ -214,13 +164,11 @@ function isPointInPoly(poly, pt){ /** - * Does pathA has intersection with pathB ? + * Does polygonA has intersection with polygonB ? * Naïve approach done first : approximate the polygons with a rectangle * Then more complex method : see if edges cross, or one contained in the other */ -Isomer.prototype._hasIntersection = function(pathA, pathB) { - var pointsA = pathA.points.map(this._translatePoint.bind(this)); - var pointsB = pathB.points.map(this._translatePoint.bind(this)); +Isomer.prototype._hasIntersection = function(pointsA, pointsB) { var i, j; //console.log("_hasIntersection"); var AminX = pointsA[0].x; @@ -244,8 +192,6 @@ Isomer.prototype._hasIntersection = function(pathA, pathB) { BmaxY = Math.max(BmaxY, pointsB[i].y); } - //console.log([AminX, AmaxX, BminX, BmaxX, AminY, AmaxY, BminY, BmaxY]); - if(((AminX <= BminX && BminX <= AmaxX) || (BminX <= AminX && AminX <= BmaxX)) && ((AminY <= BminY && BminY <= AmaxY) || (BminY <= AminY && AminY <= BmaxY))) { // now let's be more specific @@ -253,12 +199,8 @@ Isomer.prototype._hasIntersection = function(pathA, pathB) { var polyB = pointsB.slice(); polyA.push(pointsA[0]); polyB.push(pointsB[0]); - //console.log(polyA); - //console.log(polyB); - // see if edges cross, or one contained in the other - var crossing = 0; - - + + // see if edges cross, or one contained in the other var deltaAX = []; var deltaAY = []; var deltaBX = []; @@ -281,13 +223,12 @@ Isomer.prototype._hasIntersection = function(pathA, pathB) { crossExam: for(i = 0 ; i <= polyA.length - 2 ; i++){ for(j = 0 ; j <= polyB.length - 2 ; j++){ - if( deltaAX[i] * deltaBY[j] != deltaAY[i] * deltaBX[j]){ + if(deltaAX[i] * deltaBY[j] != deltaAY[i] * deltaBX[j]){ //case when vectors are colinear, or one polygon included in the other, is covered after //two segments cross each other if and only if the points of the first are on each side of the line defined by the second and vice-versa if((deltaAY[i] * polyB[j].x - deltaAX[i] * polyB[j].y + rA[i]) * (deltaAY[i] * polyB[j+1].x - deltaAX[i] * polyB[j+1].y + rA[i]) < -0.000000001 && (deltaBY[j] * polyA[i].x - deltaBX[j] * polyA[i].y + rB[j]) * (deltaBY[j] * polyA[i+1].x - deltaBX[j] * polyA[i+1].y + rB[j]) < -0.000000001){ - crossing = 1; - break crossExam; + return 1; } } } @@ -295,16 +236,16 @@ Isomer.prototype._hasIntersection = function(pathA, pathB) { for(i = 0 ; i <= polyA.length - 2 ; i++){ if(isPointInPoly(polyB, {x:polyA[i].x, y:polyA[i].y})){ - crossing = 1; + return 1; } } for(i = 0 ; i <= polyB.length - 2 ; i++){ if(isPointInPoly(polyA, {x:polyB[i].x, y:polyB[i].y})){ - crossing = 1; + return 1; } } - return crossing; + return 0; } else { return 0; } diff --git a/js/path.js b/js/path.js index 1defb64..c365626 100644 --- a/js/path.js +++ b/js/path.js @@ -94,26 +94,17 @@ */ Path.prototype.closerThan = function(pathA, observer) { var result = pathA._countCloserThan(this, observer) - this._countCloserThan(pathA, observer); - //console.log(result); return result; } Path.prototype._countCloserThan = function(pathA, observer) { - //console.log("counting"); var Vector = Isomer.Vector; var i = 0; - //console.log("pathA"); - //console.log(pathA); // the plane containing pathA is defined by the three points A, B, C var AB = Vector.fromTwoPoints(pathA.points[0], pathA.points[1]); var AC = Vector.fromTwoPoints(pathA.points[0], pathA.points[2]); var n = Vector.crossProduct(AB, AC); - //console.log("AB AC n A d n.OU :"); - //console.log(AB); - //console.log(AC); - //console.log(n); - //console.log(pathA.points[0]); var OA = Vector.fromTwoPoints(Point.ORIGIN, pathA.points[0]); var OU = Vector.fromTwoPoints(Point.ORIGIN, observer); //U = user = observer @@ -121,18 +112,12 @@ // Plane defined by pathA such as ax + by + zc = d // Here d = nx*x + ny*y + nz*z = n.OA var d = Vector.dotProduct(n, OA); - //console.log(d); var observerPosition = Vector.dotProduct(n, OU) - d; - //console.log(Vector.dotProduct(n, OU)); var result = 0; var result0 = 0; for (i = 0; i < this.points.length; i++) { var OP = Vector.fromTwoPoints(Point.ORIGIN, this.points[i]); - //console.log("OP"); - //console.log(OP); var pPosition = Vector.dotProduct(n, OP) - d; - //console.log(Vector.dotProduct(n, OP)); - //console.log(i+" prod = "+(observerPosition * pPosition)); if(observerPosition * pPosition >= 0.000000001){ //careful with rounding approximations result++; } @@ -140,7 +125,7 @@ result0++; } } - //console.log("__" + (result / this.points.length)); + if(result == 0){ return 0; } else { From 43e3e05a42007d03e248307ed752483c920d2c42 Mon Sep 17 00:00:00 2001 From: Mysterix Date: Sun, 11 May 2014 13:37:57 +0200 Subject: [PATCH 11/18] Isomer.p.add now adds paths to be drawn to an array that can be sorted --- js/isomer.js | 61 ++++++++++++++++++++++++++++++++++------------------ 1 file changed, 40 insertions(+), 21 deletions(-) diff --git a/js/isomer.js b/js/isomer.js index fd2aee9..7334418 100644 --- a/js/isomer.js +++ b/js/isomer.js @@ -36,6 +36,11 @@ function Isomer(canvasId, options) { */ this.colorDifference = 0.20; this.lightColor = options.lightColor || new Color(255, 255, 255); + + /** + * List of {path, color, shapeName} to draw + */ + this.paths = []; } /** @@ -69,43 +74,57 @@ Isomer.prototype._translatePoint = function (point) { * * This method also accepts arrays */ -Isomer.prototype.add = function (item, baseColor) { +Isomer.prototype.add = function (item, baseColor, name) { if (Object.prototype.toString.call(item) == '[object Array]') { for (var i = 0; i < item.length; i++) { this.add(item[i], baseColor); } } else if (item instanceof Path) { - this._addPath(item, baseColor); + this.paths[this.paths.length] = {shape:item, color:baseColor, shapeName:(name||'')}; } else if (item instanceof Shape) { - /* Fetch paths ordered by distance to prevent overlaps */ var paths = item.orderedPaths(); for (var i in paths) { - this._addPath(paths[i], baseColor); + this.paths[this.paths.length] = {shape:paths[i], color:baseColor, shapeName:(name||'')}; } } }; /** - * Adds an array of {shape: yourShape, color: yourColor} to the scene, + * Draws the content of this.paths + * By default, sorts all the paths + */ +Isomer.prototype.draw = function(sortPath){ + var sort = (typeof sortPath === 'number') ? sortPath : 1; + if(sortPath == 1){ + this.sortPaths(); + } + for (var i in this.paths){ + this._addPath(this.paths[i].path, this.paths[i].color); + } +} + + +/** + * Sorts the paths contained in this.paths, * ordered so that distant faces are displayed first * */ -Isomer.prototype.addOrdered = function (item) { +Isomer.prototype.sortPaths = function () { var Point = Isomer.Point; var observer = new Point(-10, -10, 20); var pathList = []; - var index = 0; - for (var i = 0; i < item.length; i++) { - for(var j = 0 ; j < item[i].shape.paths.length ; j++){ - pathList[index] = { - path: item[i].shape.paths[j], - polygon: item[i].shape.paths[j].points.map(this._translatePoint.bind(this)), - color: item[i].color, - drawn: 0 - }; - index++; - } + for (var i = 0; i < this.paths.length; i++) { + var currentPath = this.paths[i]; + pathList[index] = { + path: currentPath.path, + polygon: currentPath.path.points.map(this._translatePoint.bind(this)), + color: currentPath.color, + drawn: 0, + shapeName: currentPath.shapeName + + }; } - + this.paths.length = 0; + // topological sort var drawBefore = []; @@ -137,7 +156,7 @@ Isomer.prototype.addOrdered = function (item) { if(pathList[drawBefore[i][j]].drawn == 0){canDraw = 0;} } if(canDraw == 1){ - this._addPath(pathList[i].path, pathList[i].color); + this.add(pathList[i].path, pathList[i].color, pathList[i].shapeName); drawThisTurn = 1; pathList[i].drawn = 1; } @@ -148,8 +167,8 @@ Isomer.prototype.addOrdered = function (item) { //could be done more in a smarter order, that's why drawn is is an element of pathList[] and not a separate array for (var i = 0 ; i < pathList.length ; i++){ if(pathList[i].drawn == 0){ - this._addPath(pathList[i].path, pathList[i].color); - } + this.add(pathList[i].path, pathList[i].color, pathList[i].shapeName); + } } }; From 3aa9d74e465d95ad4aad94d0989d857ec8572837 Mon Sep 17 00:00:00 2001 From: Mysterix Date: Sun, 11 May 2014 15:06:48 +0200 Subject: [PATCH 12/18] Bugfix --- js/isomer.js | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/js/isomer.js b/js/isomer.js index 7334418..12896a1 100644 --- a/js/isomer.js +++ b/js/isomer.js @@ -80,23 +80,25 @@ Isomer.prototype.add = function (item, baseColor, name) { this.add(item[i], baseColor); } } else if (item instanceof Path) { - this.paths[this.paths.length] = {shape:item, color:baseColor, shapeName:(name||'')}; + this.paths[this.paths.length] = {path:item, color:baseColor, shapeName:(name||'')}; } else if (item instanceof Shape) { var paths = item.orderedPaths(); for (var i in paths) { - this.paths[this.paths.length] = {shape:paths[i], color:baseColor, shapeName:(name||'')}; + this.paths[this.paths.length] = {path:paths[i], color:baseColor, shapeName:(name||'')}; } } }; /** * Draws the content of this.paths - * By default, sorts all the paths + * By default, does not sort the paths between shapes */ Isomer.prototype.draw = function(sortPath){ - var sort = (typeof sortPath === 'number') ? sortPath : 1; - if(sortPath == 1){ + var sortValid = (typeof sortPath === 'number') ? sortPath : 0; + if(sortValid == 1){ + console.log(this.paths); this.sortPaths(); + console.log(this.paths); } for (var i in this.paths){ this._addPath(this.paths[i].path, this.paths[i].color); @@ -114,7 +116,7 @@ Isomer.prototype.sortPaths = function () { var pathList = []; for (var i = 0; i < this.paths.length; i++) { var currentPath = this.paths[i]; - pathList[index] = { + pathList[i] = { path: currentPath.path, polygon: currentPath.path.points.map(this._translatePoint.bind(this)), color: currentPath.color, From b6227a09923a1cc4ec31bf4172e59c1673d7e050 Mon Sep 17 00:00:00 2001 From: Mysterix Date: Sun, 11 May 2014 15:32:01 +0200 Subject: [PATCH 13/18] Clean logs --- js/isomer.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/js/isomer.js b/js/isomer.js index 12896a1..c2b7fb1 100644 --- a/js/isomer.js +++ b/js/isomer.js @@ -96,9 +96,7 @@ Isomer.prototype.add = function (item, baseColor, name) { Isomer.prototype.draw = function(sortPath){ var sortValid = (typeof sortPath === 'number') ? sortPath : 0; if(sortValid == 1){ - console.log(this.paths); this.sortPaths(); - console.log(this.paths); } for (var i in this.paths){ this._addPath(this.paths[i].path, this.paths[i].color); From d24b7d376952c1a598b56435d742b50226aea3d1 Mon Sep 17 00:00:00 2001 From: Mysterix Date: Sun, 11 May 2014 18:18:29 +0200 Subject: [PATCH 14/18] For backward-compatibility, option expertMode in add --- js/isomer.js | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) diff --git a/js/isomer.js b/js/isomer.js index c2b7fb1..7aff219 100644 --- a/js/isomer.js +++ b/js/isomer.js @@ -72,19 +72,29 @@ Isomer.prototype._translatePoint = function (point) { /** * Adds a shape or path to the scene * - * This method also accepts arrays + * This method also accepts arrays. + * By default or if expertMode=0, shapes are drawn */ -Isomer.prototype.add = function (item, baseColor, name) { +Isomer.prototype.add = function (item, baseColor, expertMode, name) { + var expertModeValid = (typeof expertMode === 'number') ? expertMode : 0; if (Object.prototype.toString.call(item) == '[object Array]') { for (var i = 0; i < item.length; i++) { - this.add(item[i], baseColor); + this.add(item[i], baseColor, expertModeValid, name); } } else if (item instanceof Path) { - this.paths[this.paths.length] = {path:item, color:baseColor, shapeName:(name||'')}; + if(expertModeValid == 1){ + this.paths[this.paths.length] = {path:item, color:baseColor, shapeName:(name||'')}; + } else { + this._addPath(item, baseColor); + } } else if (item instanceof Shape) { var paths = item.orderedPaths(); for (var i in paths) { - this.paths[this.paths.length] = {path:paths[i], color:baseColor, shapeName:(name||'')}; + if(expertModeValid == 1){ + this.paths[this.paths.length] = {path:paths[i], color:baseColor, shapeName:(name||'')}; + } else { + this._addPath(paths[i], baseColor); + } } } }; @@ -156,7 +166,7 @@ Isomer.prototype.sortPaths = function () { if(pathList[drawBefore[i][j]].drawn == 0){canDraw = 0;} } if(canDraw == 1){ - this.add(pathList[i].path, pathList[i].color, pathList[i].shapeName); + this.add(pathList[i].path, pathList[i].color, 1, pathList[i].shapeName); drawThisTurn = 1; pathList[i].drawn = 1; } @@ -167,7 +177,7 @@ Isomer.prototype.sortPaths = function () { //could be done more in a smarter order, that's why drawn is is an element of pathList[] and not a separate array for (var i = 0 ; i < pathList.length ; i++){ if(pathList[i].drawn == 0){ - this.add(pathList[i].path, pathList[i].color, pathList[i].shapeName); + this.add(pathList[i].path, pathList[i].color, 1, pathList[i].shapeName); } } }; From 4245b729de054cab91cc8f6aa408163ebfee2df7 Mon Sep 17 00:00:00 2001 From: Mysterix Date: Sun, 11 May 2014 18:29:06 +0200 Subject: [PATCH 15/18] Word was written in french --- js/isomer.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/js/isomer.js b/js/isomer.js index 7aff219..fdb5955 100644 --- a/js/isomer.js +++ b/js/isomer.js @@ -197,7 +197,7 @@ function isPointInPoly(poly, pt){ /** * Does polygonA has intersection with polygonB ? - * Naïve approach done first : approximate the polygons with a rectangle + * Naive approach done first : approximate the polygons with a rectangle * Then more complex method : see if edges cross, or one contained in the other */ Isomer.prototype._hasIntersection = function(pointsA, pointsB) { From 813d5879feb00309c211740dfb4e005162887747 Mon Sep 17 00:00:00 2001 From: Mysterix Date: Sun, 11 May 2014 21:38:52 +0200 Subject: [PATCH 16/18] Cleaning code (booleans) --- js/isomer.js | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/js/isomer.js b/js/isomer.js index fdb5955..4b369c2 100644 --- a/js/isomer.js +++ b/js/isomer.js @@ -76,13 +76,13 @@ Isomer.prototype._translatePoint = function (point) { * By default or if expertMode=0, shapes are drawn */ Isomer.prototype.add = function (item, baseColor, expertMode, name) { - var expertModeValid = (typeof expertMode === 'number') ? expertMode : 0; + var expertModeValid = !!expertMode; if (Object.prototype.toString.call(item) == '[object Array]') { for (var i = 0; i < item.length; i++) { this.add(item[i], baseColor, expertModeValid, name); } } else if (item instanceof Path) { - if(expertModeValid == 1){ + if(expertModeValid){ this.paths[this.paths.length] = {path:item, color:baseColor, shapeName:(name||'')}; } else { this._addPath(item, baseColor); @@ -90,7 +90,7 @@ Isomer.prototype.add = function (item, baseColor, expertMode, name) { } else if (item instanceof Shape) { var paths = item.orderedPaths(); for (var i in paths) { - if(expertModeValid == 1){ + if(expertModeValid){ this.paths[this.paths.length] = {path:paths[i], color:baseColor, shapeName:(name||'')}; } else { this._addPath(paths[i], baseColor); @@ -104,8 +104,8 @@ Isomer.prototype.add = function (item, baseColor, expertMode, name) { * By default, does not sort the paths between shapes */ Isomer.prototype.draw = function(sortPath){ - var sortValid = (typeof sortPath === 'number') ? sortPath : 0; - if(sortValid == 1){ + var sortValid = !!sortPath; + if(sortValid){ this.sortPaths(); } for (var i in this.paths){ @@ -166,7 +166,7 @@ Isomer.prototype.sortPaths = function () { if(pathList[drawBefore[i][j]].drawn == 0){canDraw = 0;} } if(canDraw == 1){ - this.add(pathList[i].path, pathList[i].color, 1, pathList[i].shapeName); + this.add(pathList[i].path, pathList[i].color, true, pathList[i].shapeName); drawThisTurn = 1; pathList[i].drawn = 1; } @@ -177,7 +177,7 @@ Isomer.prototype.sortPaths = function () { //could be done more in a smarter order, that's why drawn is is an element of pathList[] and not a separate array for (var i = 0 ; i < pathList.length ; i++){ if(pathList[i].drawn == 0){ - this.add(pathList[i].path, pathList[i].color, 1, pathList[i].shapeName); + this.add(pathList[i].path, pathList[i].color, true, pathList[i].shapeName); } } }; @@ -202,7 +202,6 @@ function isPointInPoly(poly, pt){ */ Isomer.prototype._hasIntersection = function(pointsA, pointsB) { var i, j; - //console.log("_hasIntersection"); var AminX = pointsA[0].x; var AminY = pointsA[0].y; var AmaxX = AminX; @@ -251,8 +250,6 @@ Isomer.prototype._hasIntersection = function(pointsA, pointsB) { rB[i] = deltaBX[i] * polyB[i].y - deltaBY[i] * polyB[i].x; } - - crossExam: for(i = 0 ; i <= polyA.length - 2 ; i++){ for(j = 0 ; j <= polyB.length - 2 ; j++){ if(deltaAX[i] * deltaBY[j] != deltaAY[i] * deltaBX[j]){ @@ -260,7 +257,7 @@ Isomer.prototype._hasIntersection = function(pointsA, pointsB) { //two segments cross each other if and only if the points of the first are on each side of the line defined by the second and vice-versa if((deltaAY[i] * polyB[j].x - deltaAX[i] * polyB[j].y + rA[i]) * (deltaAY[i] * polyB[j+1].x - deltaAX[i] * polyB[j+1].y + rA[i]) < -0.000000001 && (deltaBY[j] * polyA[i].x - deltaBX[j] * polyA[i].y + rB[j]) * (deltaBY[j] * polyA[i+1].x - deltaBX[j] * polyA[i+1].y + rB[j]) < -0.000000001){ - return 1; + return true; } } } @@ -268,18 +265,18 @@ Isomer.prototype._hasIntersection = function(pointsA, pointsB) { for(i = 0 ; i <= polyA.length - 2 ; i++){ if(isPointInPoly(polyB, {x:polyA[i].x, y:polyA[i].y})){ - return 1; + return true; } } for(i = 0 ; i <= polyB.length - 2 ; i++){ if(isPointInPoly(polyA, {x:polyB[i].x, y:polyB[i].y})){ - return 1; + return true; } } - return 0; + return false; } else { - return 0; + return false; } }; From 49d81f6e6bc997ecfc99c47b93f88e47e584b8b2 Mon Sep 17 00:00:00 2001 From: Mysterix Date: Tue, 24 Mar 2015 22:06:09 +0100 Subject: [PATCH 17/18] Cleaning code (indentation) --- js/isomer.js | 170 +++++++++++++++++++++++++-------------------------- js/path.js | 78 +++++++++++------------ 2 files changed, 124 insertions(+), 124 deletions(-) diff --git a/js/isomer.js b/js/isomer.js index 4b369c2..9704e4a 100644 --- a/js/isomer.js +++ b/js/isomer.js @@ -93,7 +93,7 @@ Isomer.prototype.add = function (item, baseColor, expertMode, name) { if(expertModeValid){ this.paths[this.paths.length] = {path:paths[i], color:baseColor, shapeName:(name||'')}; } else { - this._addPath(paths[i], baseColor); + this._addPath(paths[i], baseColor); } } } @@ -133,48 +133,48 @@ Isomer.prototype.sortPaths = function () { }; } - this.paths.length = 0; + this.paths.length = 0; // topological sort var drawBefore = []; for (var i = 0 ; i < pathList.length ; i++){ - drawBefore[i] = []; + drawBefore[i] = []; } for (var i = 0 ; i < pathList.length ; i++){ for (var j = 0 ; j < i ; j++){ - if(this._hasIntersection(pathList[i].polygon, pathList[j].polygon)){ - var cmpPath = pathList[i].path.closerThan(pathList[j].path, observer); - if(cmpPath < 0){ - drawBefore[i][drawBefore[i].length] = j; - } - if(cmpPath > 0){ - drawBefore[j][drawBefore[j].length] = i; - } - } - } + if(this._hasIntersection(pathList[i].polygon, pathList[j].polygon)){ + var cmpPath = pathList[i].path.closerThan(pathList[j].path, observer); + if(cmpPath < 0){ + drawBefore[i][drawBefore[i].length] = j; + } + if(cmpPath > 0){ + drawBefore[j][drawBefore[j].length] = i; + } + } + } } var drawThisTurn = 1; var index = 0; while(drawThisTurn == 1){ - index++; - drawThisTurn = 0; - for (var i = 0 ; i < pathList.length ; i++){ - if(pathList[i].drawn == 0){ - var canDraw = 1; - for (var j = 0 ; j < drawBefore[i].length ; j++){ - if(pathList[drawBefore[i][j]].drawn == 0){canDraw = 0;} - } - if(canDraw == 1){ - this.add(pathList[i].path, pathList[i].color, true, pathList[i].shapeName); - drawThisTurn = 1; - pathList[i].drawn = 1; - } - } - } + index++; + drawThisTurn = 0; + for (var i = 0 ; i < pathList.length ; i++){ + if(pathList[i].drawn == 0){ + var canDraw = 1; + for (var j = 0 ; j < drawBefore[i].length ; j++){ + if(pathList[drawBefore[i][j]].drawn == 0){canDraw = 0;} + } + if(canDraw == 1){ + this.add(pathList[i].path, pathList[i].color, true, pathList[i].shapeName); + drawThisTurn = 1; + pathList[i].drawn = 1; + } + } + } } //purge - //could be done more in a smarter order, that's why drawn is is an element of pathList[] and not a separate array + //could be done more in a smarter order, that's why drawn is an element of pathList[] and not a separate array for (var i = 0 ; i < pathList.length ; i++){ if(pathList[i].drawn == 0){ this.add(pathList[i].path, pathList[i].color, true, pathList[i].shapeName); @@ -187,11 +187,11 @@ Isomer.prototype.sortPaths = function () { //@ http://jsfromhell.com/math/is-point-in-poly [rev. #0] //see also http://jsperf.com/ispointinpath-boundary-test-speed/2 function isPointInPoly(poly, pt){ - for(var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i) - ((poly[i].y <= pt.y && pt.y < poly[j].y) || (poly[j].y <= pt.y && pt.y < poly[i].y)) - && (pt.x < (poly[j].x - poly[i].x) * (pt.y - poly[i].y) / (poly[j].y - poly[i].y) + poly[i].x) - && (c = !c); - return c; + for(var c = false, i = -1, l = poly.length, j = l - 1; ++i < l; j = i) + ((poly[i].y <= pt.y && pt.y < poly[j].y) || (poly[j].y <= pt.y && pt.y < poly[i].y)) + && (pt.x < (poly[j].x - poly[i].x) * (pt.y - poly[i].y) / (poly[j].y - poly[i].y) + poly[i].x) + && (c = !c); + return c; } @@ -213,68 +213,68 @@ Isomer.prototype._hasIntersection = function(pointsA, pointsB) { for(i = 0 ; i < pointsA.length ; i++){ AminX = Math.min(AminX, pointsA[i].x); AminY = Math.min(AminY, pointsA[i].y); - AmaxX = Math.max(AmaxX, pointsA[i].x); + AmaxX = Math.max(AmaxX, pointsA[i].x); AmaxY = Math.max(AmaxY, pointsA[i].y); } for(i = 0 ; i < pointsB.length ; i++){ BminX = Math.min(BminX, pointsB[i].x); BminY = Math.min(BminY, pointsB[i].y); - BmaxX = Math.max(BmaxX, pointsB[i].x); + BmaxX = Math.max(BmaxX, pointsB[i].x); BmaxY = Math.max(BmaxY, pointsB[i].y); } if(((AminX <= BminX && BminX <= AmaxX) || (BminX <= AminX && AminX <= BmaxX)) && ((AminY <= BminY && BminY <= AmaxY) || (BminY <= AminY && AminY <= BmaxY))) { // now let's be more specific - var polyA = pointsA.slice(); - var polyB = pointsB.slice(); - polyA.push(pointsA[0]); - polyB.push(pointsB[0]); - - // see if edges cross, or one contained in the other - var deltaAX = []; - var deltaAY = []; - var deltaBX = []; - var deltaBY = []; - var rA = []; - var rB = []; - for(i = 0 ; i <= polyA.length - 2 ; i++){ - deltaAX[i] = polyA[i+1].x - polyA[i].x; - deltaAY[i] = polyA[i+1].y - polyA[i].y; - //equation written as deltaY.x - deltaX.y + r = 0 - rA[i] = deltaAX[i] * polyA[i].y - deltaAY[i] * polyA[i].x; - } - for(i = 0 ; i <= polyB.length - 2 ; i++){ - deltaBX[i] = polyB[i+1].x - polyB[i].x; - deltaBY[i] = polyB[i+1].y - polyB[i].y; - rB[i] = deltaBX[i] * polyB[i].y - deltaBY[i] * polyB[i].x; - } - - for(i = 0 ; i <= polyA.length - 2 ; i++){ - for(j = 0 ; j <= polyB.length - 2 ; j++){ - if(deltaAX[i] * deltaBY[j] != deltaAY[i] * deltaBX[j]){ - //case when vectors are colinear, or one polygon included in the other, is covered after - //two segments cross each other if and only if the points of the first are on each side of the line defined by the second and vice-versa - if((deltaAY[i] * polyB[j].x - deltaAX[i] * polyB[j].y + rA[i]) * (deltaAY[i] * polyB[j+1].x - deltaAX[i] * polyB[j+1].y + rA[i]) < -0.000000001 && - (deltaBY[j] * polyA[i].x - deltaBX[j] * polyA[i].y + rB[j]) * (deltaBY[j] * polyA[i+1].x - deltaBX[j] * polyA[i+1].y + rB[j]) < -0.000000001){ - return true; - } - } - } - } - - for(i = 0 ; i <= polyA.length - 2 ; i++){ - if(isPointInPoly(polyB, {x:polyA[i].x, y:polyA[i].y})){ - return true; - } - } - for(i = 0 ; i <= polyB.length - 2 ; i++){ - if(isPointInPoly(polyA, {x:polyB[i].x, y:polyB[i].y})){ - return true; - } - } - - return false; + var polyA = pointsA.slice(); + var polyB = pointsB.slice(); + polyA.push(pointsA[0]); + polyB.push(pointsB[0]); + + // see if edges cross, or one contained in the other + var deltaAX = []; + var deltaAY = []; + var deltaBX = []; + var deltaBY = []; + var rA = []; + var rB = []; + for(i = 0 ; i <= polyA.length - 2 ; i++){ + deltaAX[i] = polyA[i+1].x - polyA[i].x; + deltaAY[i] = polyA[i+1].y - polyA[i].y; + //equation written as deltaY.x - deltaX.y + r = 0 + rA[i] = deltaAX[i] * polyA[i].y - deltaAY[i] * polyA[i].x; + } + for(i = 0 ; i <= polyB.length - 2 ; i++){ + deltaBX[i] = polyB[i+1].x - polyB[i].x; + deltaBY[i] = polyB[i+1].y - polyB[i].y; + rB[i] = deltaBX[i] * polyB[i].y - deltaBY[i] * polyB[i].x; + } + + for(i = 0 ; i <= polyA.length - 2 ; i++){ + for(j = 0 ; j <= polyB.length - 2 ; j++){ + if(deltaAX[i] * deltaBY[j] != deltaAY[i] * deltaBX[j]){ + //case when vectors are colinear, or one polygon included in the other, is covered after + //two segments cross each other if and only if the points of the first are on each side of the line defined by the second and vice-versa + if((deltaAY[i] * polyB[j].x - deltaAX[i] * polyB[j].y + rA[i]) * (deltaAY[i] * polyB[j+1].x - deltaAX[i] * polyB[j+1].y + rA[i]) < -0.000000001 && + (deltaBY[j] * polyA[i].x - deltaBX[j] * polyA[i].y + rB[j]) * (deltaBY[j] * polyA[i+1].x - deltaBX[j] * polyA[i+1].y + rB[j]) < -0.000000001){ + return true; + } + } + } + } + + for(i = 0 ; i <= polyA.length - 2 ; i++){ + if(isPointInPoly(polyB, {x:polyA[i].x, y:polyA[i].y})){ + return true; + } + } + for(i = 0 ; i <= polyB.length - 2 ; i++){ + if(isPointInPoly(polyA, {x:polyB[i].x, y:polyB[i].y})){ + return true; + } + } + + return false; } else { return false; } diff --git a/js/path.js b/js/path.js index 22fc33c..739a67c 100644 --- a/js/path.js +++ b/js/path.js @@ -87,50 +87,50 @@ Path.prototype.depth = function () { return total / (this.points.length || 1); }; - /** - * If pathB ("this") is closer from the observer than pathA, it must be drawn after. - * It is closer if one of its vertices and the observer are on the same side of the plane defined by pathA. - */ - Path.prototype.closerThan = function(pathA, observer) { - var result = pathA._countCloserThan(this, observer) - this._countCloserThan(pathA, observer); - return result; - } +/** + * If pathB ("this") is closer from the observer than pathA, it must be drawn after. + * It is closer if one of its vertices and the observer are on the same side of the plane defined by pathA. + */ +Path.prototype.closerThan = function(pathA, observer) { + var result = pathA._countCloserThan(this, observer) - this._countCloserThan(pathA, observer); + return result; +} - Path.prototype._countCloserThan = function(pathA, observer) { - var Vector = Isomer.Vector; - var i = 0; +Path.prototype._countCloserThan = function(pathA, observer) { + var Vector = Isomer.Vector; + var i = 0; - // the plane containing pathA is defined by the three points A, B, C - var AB = Vector.fromTwoPoints(pathA.points[0], pathA.points[1]); - var AC = Vector.fromTwoPoints(pathA.points[0], pathA.points[2]); - var n = Vector.crossProduct(AB, AC); + // the plane containing pathA is defined by the three points A, B, C + var AB = Vector.fromTwoPoints(pathA.points[0], pathA.points[1]); + var AC = Vector.fromTwoPoints(pathA.points[0], pathA.points[2]); + var n = Vector.crossProduct(AB, AC); - var OA = Vector.fromTwoPoints(Point.ORIGIN, pathA.points[0]); - var OU = Vector.fromTwoPoints(Point.ORIGIN, observer); //U = user = observer - - // Plane defined by pathA such as ax + by + zc = d - // Here d = nx*x + ny*y + nz*z = n.OA - var d = Vector.dotProduct(n, OA); - var observerPosition = Vector.dotProduct(n, OU) - d; - var result = 0; - var result0 = 0; - for (i = 0; i < this.points.length; i++) { - var OP = Vector.fromTwoPoints(Point.ORIGIN, this.points[i]); - var pPosition = Vector.dotProduct(n, OP) - d; - if(observerPosition * pPosition >= 0.000000001){ //careful with rounding approximations - result++; - } - if(observerPosition * pPosition >= -0.000000001 && observerPosition * pPosition < 0.000000001){ - result0++; - } + var OA = Vector.fromTwoPoints(Point.ORIGIN, pathA.points[0]); + var OU = Vector.fromTwoPoints(Point.ORIGIN, observer); //U = user = observer + + // Plane defined by pathA such as ax + by + zc = d + // Here d = nx*x + ny*y + nz*z = n.OA + var d = Vector.dotProduct(n, OA); + var observerPosition = Vector.dotProduct(n, OU) - d; + var result = 0; + var result0 = 0; + for (i = 0; i < this.points.length; i++) { + var OP = Vector.fromTwoPoints(Point.ORIGIN, this.points[i]); + var pPosition = Vector.dotProduct(n, OP) - d; + if(observerPosition * pPosition >= 0.000000001){ //careful with rounding approximations + result++; } - - if(result == 0){ - return 0; - } else { - return ((result + result0) / this.points.length); + if(observerPosition * pPosition >= -0.000000001 && observerPosition * pPosition < 0.000000001){ + result0++; } - }; + } + + if(result == 0){ + return 0; + } else { + return ((result + result0) / this.points.length); + } +}; From bc320b6a346544e5def02d6725ecd082aa7e7fc8 Mon Sep 17 00:00:00 2001 From: Mysterix Date: Tue, 24 Mar 2015 22:24:23 +0100 Subject: [PATCH 18/18] List of elements to draw is now called scene instead of paths --- js/isomer.js | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/js/isomer.js b/js/isomer.js index 9704e4a..5bd9bc7 100644 --- a/js/isomer.js +++ b/js/isomer.js @@ -40,7 +40,7 @@ function Isomer(canvasId, options) { /** * List of {path, color, shapeName} to draw */ - this.paths = []; + this.scene = []; } /** @@ -83,7 +83,7 @@ Isomer.prototype.add = function (item, baseColor, expertMode, name) { } } else if (item instanceof Path) { if(expertModeValid){ - this.paths[this.paths.length] = {path:item, color:baseColor, shapeName:(name||'')}; + this.scene[this.scene.length] = {path:item, color:baseColor, shapeName:(name||'')}; } else { this._addPath(item, baseColor); } @@ -91,7 +91,7 @@ Isomer.prototype.add = function (item, baseColor, expertMode, name) { var paths = item.orderedPaths(); for (var i in paths) { if(expertModeValid){ - this.paths[this.paths.length] = {path:paths[i], color:baseColor, shapeName:(name||'')}; + this.scene[this.scene.length] = {path:paths[i], color:baseColor, shapeName:(name||'')}; } else { this._addPath(paths[i], baseColor); } @@ -100,7 +100,7 @@ Isomer.prototype.add = function (item, baseColor, expertMode, name) { }; /** - * Draws the content of this.paths + * Draws the content of this.scene * By default, does not sort the paths between shapes */ Isomer.prototype.draw = function(sortPath){ @@ -108,22 +108,22 @@ Isomer.prototype.draw = function(sortPath){ if(sortValid){ this.sortPaths(); } - for (var i in this.paths){ - this._addPath(this.paths[i].path, this.paths[i].color); + for (var i in this.scene){ + this._addPath(this.scene[i].path, this.scene[i].color); } } /** - * Sorts the paths contained in this.paths, + * Sorts the paths contained in this.scene, * ordered so that distant faces are displayed first * */ Isomer.prototype.sortPaths = function () { var Point = Isomer.Point; var observer = new Point(-10, -10, 20); var pathList = []; - for (var i = 0; i < this.paths.length; i++) { - var currentPath = this.paths[i]; + for (var i = 0; i < this.scene.length; i++) { + var currentPath = this.scene[i]; pathList[i] = { path: currentPath.path, polygon: currentPath.path.points.map(this._translatePoint.bind(this)), @@ -133,7 +133,7 @@ Isomer.prototype.sortPaths = function () { }; } - this.paths.length = 0; + this.scene.length = 0; // topological sort