second approach to face merging

This commit is contained in:
Val Erastov 2015-01-14 02:25:20 -08:00
parent e8e27493f0
commit 6fb0e58483
4 changed files with 2269 additions and 6 deletions

View file

@ -121,6 +121,52 @@ TCAD.utils.equal = function(v1, v2) {
return TCAD.utils.areEqual(v1, v2, TCAD.TOLERANCE);
};
TCAD.utils.isPointInsidePolygon = function( inPt, inPolygon ) {
var EPSILON = TCAD.TOLERANCE;
var polyLen = inPolygon.length;
// inPt on polygon contour => immediate success or
// toggling of inside/outside at every single! intersection point of an edge
// with the horizontal line through inPt, left of inPt
// not counting lowerY endpoints of edges and whole edges on that line
var inside = false;
for( var p = polyLen - 1, q = 0; q < polyLen; p = q ++ ) {
var edgeLowPt = inPolygon[ p ];
var edgeHighPt = inPolygon[ q ];
var edgeDx = edgeHighPt.x - edgeLowPt.x;
var edgeDy = edgeHighPt.y - edgeLowPt.y;
if ( Math.abs(edgeDy) > EPSILON ) { // not parallel
if ( edgeDy < 0 ) {
edgeLowPt = inPolygon[ q ]; edgeDx = - edgeDx;
edgeHighPt = inPolygon[ p ]; edgeDy = - edgeDy;
}
if ( ( inPt.y < edgeLowPt.y ) || ( inPt.y > edgeHighPt.y ) ) continue;
if ( inPt.y == edgeLowPt.y ) {
if ( inPt.x == edgeLowPt.x ) return true; // inPt is on contour ?
// continue; // no intersection or edgeLowPt => doesn't count !!!
} else {
var perpEdge = edgeDy * (inPt.x - edgeLowPt.x) - edgeDx * (inPt.y - edgeLowPt.y);
if ( perpEdge == 0 ) return true; // inPt is on contour ?
if ( perpEdge < 0 ) continue;
inside = ! inside; // true intersection left of inPt
}
} else { // parallel or colinear
if ( inPt.y != edgeLowPt.y ) continue; // parallel
// egde lies on the same horizontal line as inPt
if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) ||
( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) ) return true; // inPt: Point on contour !
// continue;
}
}
return inside;
}
TCAD.utils.sketchToPolygons = function(geom) {
var dict = {};
@ -282,7 +328,7 @@ TCAD.Solid = function(polygons, material) {
continue;
}
pushVertices(poly.shell);
for ( var h = 0; h < poly.holes; ++ h ) {
for ( var h = 0; h < poly.holes.length; ++ h ) {
pushVertices(poly.holes[ h ]);
}
var polyFace = new TCAD.SketchFace(this, poly);
@ -392,6 +438,13 @@ TCAD.Polygon = function(shell, holes, normal) {
normal = TCAD.geom.normalOfCCWSeq(shell);
} else {
shell = TCAD.utils.fixCCW(shell, normal);
if (holes.length > 0) {
var neg = normal.negate();
for (var h = 0; h < holes.length; ++h) {
holes[h] = TCAD.utils.fixCCW(holes[h], neg);
}
}
}
this.normal = normal;
@ -448,6 +501,11 @@ TCAD.Polygon.prototype.to2D = function() {
TCAD.Polygon.prototype.triangulate = function() {
function triangulateShape( contour, holes ) {
var myTriangulator = new PNLTRI.Triangulator();
return myTriangulator.triangulate_polygon( [ contour ].concat(holes) );
}
var i, h;
var f2d = this.to2D();
@ -459,7 +517,8 @@ TCAD.Polygon.prototype.triangulate = function() {
f2d.holes[h][i] = f2d.holes[h][i].three();
}
}
return THREE.Shape.utils.triangulateShape( f2d.shell, f2d.holes );
return triangulateShape( f2d.shell, f2d.holes );
// return THREE.Shape.utils.triangulateShape( f2d.shell, f2d.holes );
};

View file

@ -415,14 +415,121 @@ TCAD.craft.cut = function(app, face, faces, height) {
var cut = CSG.fromPolygons(work).subtract(CSG.fromPolygons(cutter));
face.polygon.__face = undefined;
return TCAD.craft._mergeCSGPolygons(cut.polygons).map(function(path) {
return new TCAD.Polygon(path.vertices, [], path.normal);
});
function sortPaths() {
function pInP(p1, p2) {
var notEqPoints = [];
for (var i = 0; i < p1.length; ++i) {
var v1 = p1[i];
for (var j = 0; j < p2.length; ++j) {
var v2 = p2[j];
if (!v1.equals(v2)) {
notEqPoints.push(v1);
break;
}
}
}
if (notEqPoints.length == 0) {
return true;
}
for (var i = 0; i < notEqPoints.length; ++i) {
var v = notEqPoints[i];
if (!TCAD.utils.isPointInsidePolygon(v, p2)) {
return false;
}
}
return true;
}
function sortPaths(paths3D) {
paths = paths3D.map(function(path) {
return {
vertices : new TCAD.Polygon(path.vertices, [], path.normal).to2D().shell,
normal : path.normal
}
});
var index = [];
for (var pi = 0; pi < paths.length; ++pi) {
index[pi] = [];
paths3D[pi].holes = [];
}
for (var pi = 0; pi < paths.length; ++pi) {
var path = paths[pi];
depth = path.vertices[0].dot(path.normal);
for (var piTest = 0; piTest < paths.length; ++piTest) {
var pathTest = paths[piTest];
if (piTest === pi) continue;
if (!pathTest.normal.equals(path.normal)) continue;
depthTest = pathTest.vertices[0].dot(pathTest.normal);
if (!TCAD.utils.equal(depthTest, depth)) continue;
if (pInP(pathTest.vertices, path.vertices)) {
index[piTest].push(pi);
}
}
}
function collect(master, level) {
var success = false;
for (var i = 0; i < index.length; ++i) {
var masters = index[i];
if (level != masters.length) continue;
for (var j = 0; j < masters.length; ++j) {
var m = masters[j];
if (m === master) {
paths3D[m].holes.push(paths3D[i])
success = true;
}
}
}
return success;
}
for (var success = true, level = 1;
level < paths3D.length && success;
level ++, success = false) {
for (var i = 0; i < index.length; ++i) {
var masters = index[i];
if (masters.length == level - 1) {
if (collect(i, level)) {
success = true;
}
}
}
}
function separate(path, separated) {
separated.push(path);
for (var i = 0; i < path.holes.length; ++i) {
var hole = path.holes[i];
for (var j = 0; j < hole.holes.length; ++j) {
var inner = hole.holes[j];
separate(inner, separated)
}
}
}
var separated = [];
for (var i = 0; i < index.length; ++i) {
var masters = index[i];
if (masters.length == 0) {
separate(paths3D[i], separated);
}
}
return separated;
}
var merged = TCAD.craft._mergeCSGPolygons(cut.polygons);
var sorted = sortPaths(merged);
return sorted.map(function(path) {
return new TCAD.Polygon(path.vertices, path.holes.map(function(path){return path.vertices}), path.normal);
});
// return cut.polygons.map(function(e) {
// return new TCAD.Polygon(e.vertices.map(

View file

@ -14,6 +14,7 @@
<script src="lib/three/OrbitControls.js"></script>
<script src="lib/dat.gui.min.js"></script>
<script src="lib/csg.js"></script>
<script src="lib/pnltri.js"></script>
<script src="app/main.js"></script>
<script src="app/ctrl.js"></script>
<script src="app/viewer.js"></script>

2096
web/lib/pnltri.js Normal file

File diff suppressed because it is too large Load diff