PIP for NURBS

This commit is contained in:
Val Erastov 2017-04-13 17:49:03 -07:00 committed by xibyte
parent cad474b100
commit 13f2f8f6ee
11 changed files with 415 additions and 78 deletions

View file

@ -24,9 +24,14 @@ function addGlobalDebugActions(app) {
app.viewer.render(); app.viewer.render();
}, },
AddSegment: (a, b, color) => { AddSegment: (a, b, color) => {
debugGroup.add(createLine(a, b, color)); __DEBUG__.AddPolyLine([a, b], color);
debugGroup.add(createPoint(a, 0x000088)); },
debugGroup.add(createPoint(b, 0x880000)); AddPolyLine: (points, color) => {
for (let i = 1; i < points.length; ++i) {
debugGroup.add(createLine(points[i - 1], points[i], color));
}
debugGroup.add(createPoint(points[0], 0x000088));
debugGroup.add(createPoint(points[points.length - 1], 0x880000));
app.viewer.render(); app.viewer.render();
}, },
AddPoint: (coordinates, or, vector, andColorAtTheEnd) => { AddPoint: (coordinates, or, vector, andColorAtTheEnd) => {
@ -55,7 +60,12 @@ function addGlobalDebugActions(app) {
app.viewer.render(); app.viewer.render();
}, },
AddHalfEdge: (he, color) => { AddHalfEdge: (he, color) => {
window.__DEBUG__.AddSegment(he.vertexA.point, he.vertexB.point, color); const points = [he.vertexA.point];
if (he.edge && he.edge.curve) {
he.edge.curve.approximate(10, he.vertexA.point, he.vertexB.point, points);
}
points.push(he.vertexB.point);
window.__DEBUG__.AddPolyLine(points, color);
}, },
AddFace: (face, color) => { AddFace: (face, color) => {
for (let e of face.edges) __DEBUG__.AddHalfEdge(e, color); for (let e of face.edges) __DEBUG__.AddHalfEdge(e, color);

View file

@ -149,6 +149,30 @@ export function triangulateToThree(shell, geom) {
} }
//view.setFaceColor(sceneFace, utils.isSmoothPiece(group.shared) ? 0xFF0000 : null); //view.setFaceColor(sceneFace, utils.isSmoothPiece(group.shared) ? 0xFF0000 : null);
} }
} else if (brepFace.surface.constructor.name == 'NurbsSurface1') {
const off = geom.vertices.length;
const contours = [];
for (let loop of brepFace.loops) {
const points = [];
for (let he of loop.halfEdges) {
points.push(he.vertexA.point);
he.edge.curve.approximate(10, he.vertexA.point, he.vertexB.point, points);
}
const verb = brepFace.surface.verb;
const uvs = points.map(point => verb.closestParam(point.data()));
uvs.forEach(uv => uv.push(0)); // add z coord
contours.push(uvs);
//....TODO
for (let i = 0; i < tessedUVs.length; i += 3 ) {
var a = new Vector().set3(tessedUVs[i]);
var b = new Vector().set3(tessedUVs[i + 1]);
var c = new Vector().set3(tessedUVs[i + 2]);
const normalOrNormals = normalOfCCWSeq([a, b, c]).three();
const face = new THREE.Face3(off, off + 1, off + 2, normalOrNormals);
addFace(face);
}
}
} else if (brepFace.surface.constructor.name == 'NurbsSurface') { } else if (brepFace.surface.constructor.name == 'NurbsSurface') {
const off = geom.vertices.length; const off = geom.vertices.length;
const tess = brepFace.surface.verb.tessellate({maxDepth: 3}); const tess = brepFace.surface.verb.tessellate({maxDepth: 3});

View file

@ -9,6 +9,8 @@ import {Face} from '../brep/topo/face';
import {Shell} from '../brep/topo/shell'; import {Shell} from '../brep/topo/shell';
import {Vertex} from '../brep/topo/vertex'; import {Vertex} from '../brep/topo/vertex';
import {Point} from '../brep/geom/point'; import {Point} from '../brep/geom/point';
import {NurbsCurve} from '../brep/geom/impl/nurbs';
import {Plane} from '../brep/geom/impl/plane';
export default { export default {
brep: { brep: {
@ -17,7 +19,7 @@ export default {
bool: BREPBool, bool: BREPBool,
validator: BREPValidator, validator: BREPValidator,
geom: { geom: {
Point Point, NurbsCurve, Plane
}, },
topo: { topo: {
HalfEdge, Edge, Loop, Face, Shell, Vertex HalfEdge, Edge, Loop, Face, Shell, Vertex

View file

@ -186,12 +186,14 @@ export function invertLoop(loop) {
linkSegments(loop.halfEdges); linkSegments(loop.halfEdges);
} }
export function createPlaneLoop(vertices) { export function createPlaneLoop(vertices, curves) {
const loop = new Loop(); const loop = new Loop();
iterateSegments(vertices, (a, b) => { iterateSegments(vertices, (a, b, i) => {
createHalfEdge(loop, a, b) const halfEdge = createHalfEdge(loop, a, b);
halfEdge.edge = new Edge(curves[i] ? curves[i] : Line.fromSegment(a.point, b.point));
return halfEdge;
}); });
linkSegments(loop.halfEdges); linkSegments(loop.halfEdges);

View file

@ -2,7 +2,6 @@
export class Curve { export class Curve {
constructor() { constructor() {
this.isLine = false;
} }
intersectCurve(curve) { intersectCurve(curve) {
@ -20,7 +19,7 @@ export class Curve {
approximate(resolution, from, to, path) { approximate(resolution, from, to, path) {
} }
} }
Curve.prototype.isLine = false;
export class CompositeCurve { export class CompositeCurve {

View file

@ -4,7 +4,6 @@ export class Line extends Curve {
constructor(p0, v) { constructor(p0, v) {
super(); super();
this.isLine = true;
this.p0 = p0; this.p0 = p0;
this.v = v; this.v = v;
this._pointsCache = new Map(); this._pointsCache = new Map();
@ -56,6 +55,8 @@ export class Line extends Curve {
offset() {}; offset() {};
} }
Line.prototype.isLine = true;
Line.fromTwoPlanesIntersection = function(plane1, plane2) { Line.fromTwoPlanesIntersection = function(plane1, plane2) {
const n1 = plane1.normal; const n1 = plane1.normal;
const n2 = plane2.normal; const n2 = plane2.normal;

View file

@ -1,6 +1,7 @@
import verb from 'verb-nurbs' import verb from 'verb-nurbs'
import {Matrix3} from '../../../math/l3space' import {Matrix3} from '../../../math/l3space'
import Vector from '../../../math/vector' import * as math from '../../../math/math'
import {Point} from '../point'
export class NurbsCurve { export class NurbsCurve {
@ -31,7 +32,7 @@ export class NurbsCurve {
const step = this.verb.paramAtLength(length / resolution); const step = this.verb.paramAtLength(length / resolution);
u += step; u += step;
for (;u < endU; u += step) { for (;u < endU; u += step) {
out.push(new Vector().set3(this.verb.point(u))); out.push(new Point().set3(this.verb.point(u)));
} }
if (reverse) { if (reverse) {
for (let i = off, j = out.length - 1; i != j; ++i, --j) { for (let i = off, j = out.length - 1; i != j; ++i, --j) {
@ -41,8 +42,48 @@ export class NurbsCurve {
} }
} }
} }
approximateU(resolution, paramFrom, paramTo, consumer) {
let u = paramFrom;
let endU = paramTo;
let step = this.verb.paramAtLength(resolution);
if (u > endU) {
step *= -1;
}
u += step;
for (;step > 0 ? u < endU : u > endU; u += step) {
consumer(u);
}
}
tangentAtPoint(point) {
return new Point().set3(this.verb.tangent(this.verb.closestParam(point.data())));
}
closestDistanceToPoint(point) {
const closest = this.verb.closestPoint(point.data());
return math.distance3(point.x, point.y, point.z, closest[0], closest[1], closest[2]);
}
tangent(point) {
return new Point().set3(this.verb.tangent( this.verb.closestParam(point.data() )));
}
intersect(other, tolerance) {
return verb.geom.Intersect.curves(this.verb, other.verb, tolerance).map(i => new Point().set3(i.point0));
}
static createByPoints(points, degeree) {
points = points.map(p => p.data());
return new NurbsCurve(new verb.geom.NurbsCurve.byPoints(points, degeree));
}
} }
NurbsCurve.prototype.createLinearNurbs = function(a, b) {
return new NurbsCurve(new verb.geom.Line(a.data(), b.data()));
};
export class NurbsSurface { export class NurbsSurface {
constructor(verbSurface) { constructor(verbSurface) {

View file

@ -1,4 +1,5 @@
import {Surface} from '../surface' import {Surface} from '../surface'
import {Point} from '../point'
import {Line} from './line' import {Line} from './line'
import {Matrix3, AXIS, BasisForPlane} from '../../../math/l3space' import {Matrix3, AXIS, BasisForPlane} from '../../../math/l3space'
import * as math from '../../../math/math' import * as math from '../../../math/math'
@ -38,11 +39,17 @@ export class Plane extends Surface {
} }
get2DTransformation() { get2DTransformation() {
return this.get3DTransformation().invert(); if (!this.__2dTr) {
this.__2dTr = this.get3DTransformation().invert();
}
return this.__2dTr;
} }
get3DTransformation() { get3DTransformation() {
return new Matrix3().setBasis(this.basis()); if (!this.__3dTr) {
this.__3dTr = new Matrix3().setBasis(this.basis());
}
return this.__3dTr;
} }
coplanarUnsigned(other, tol) { coplanarUnsigned(other, tol) {
@ -58,8 +65,27 @@ export class Plane extends Surface {
} }
toParametricForm() { toParametricForm() {
const basis = BasisForPlane(this.normal); if (!this.__parametricForm) {
return new ParametricPlane(this.normal.multiply(this.w), basis.x, basis.y); const basis = BasisForPlane(this.normal);
this.__parametricForm = new ParametricPlane(this.normal.multiply(this.w), basis.x, basis.y);
}
return this.__parametricForm;
}
toUV(point) {
return this.get2DTransformation().apply(point);
}
fromUV(u, v) {
return this.get3DTransformation()._apply(new Point(u, v, 0));
}
domainU() {
return [Number.MIN_VALUE, Number.MAX_VALUE];
}
domainV() {
return [Number.MIN_VALUE, Number.MAX_VALUE];
} }
} }

View file

@ -667,7 +667,6 @@ export function loopsToFaces(originFace, loops, out) {
} }
function getNestedLoops(face, brepLoops) { function getNestedLoops(face, brepLoops) {
const tr = face.surface.get2DTransformation();
function NestedLoop(loop) { function NestedLoop(loop) {
this.loop = loop; this.loop = loop;
this.nesting = []; this.nesting = [];
@ -677,7 +676,7 @@ function getNestedLoops(face, brepLoops) {
const loops = brepLoops.map(loop => new NestedLoop(loop)); const loops = brepLoops.map(loop => new NestedLoop(loop));
function contains(loop, other) { function contains(loop, other) {
for (let point of other.asPolygon()) { for (let point of other.asPolygon()) {
if (!classifyPointInsideLoop(tr.apply(point), loop, tr).inside) { if (!classifyPointInsideLoop(point, loop, face.surface).inside) {
return false; return false;
} }
} }
@ -1076,9 +1075,9 @@ function classifyPointToFace(point, face) {
} }
return result; return result;
} }
const tr = face.surface.get2DTransformation();
const point2d = tr.apply(point); const uvPt = face.surface.toUV(point);
const outer = classifyPointInsideLoop(point2d, face.outerLoop, tr); const outer = classifyPointInsideLoop(point, face.outerLoop, face.surface, uvPt);
if (outer.inside) { if (outer.inside) {
if (outer.vertex || outer.edge) { if (outer.vertex || outer.edge) {
@ -1087,7 +1086,7 @@ function classifyPointToFace(point, face) {
} }
for (let innerLoop of face.innerLoops) { for (let innerLoop of face.innerLoops) {
const inner = classifyPointInsideLoop(point2d, innerLoop, tr); const inner = classifyPointInsideLoop(point, innerLoop, face.surface, uvPt);
if (inner.vertex || inner.edge) { if (inner.vertex || inner.edge) {
return inner; return inner;
} }
@ -1209,7 +1208,7 @@ class FaceSolveData {
} }
} }
export function classifyPointInsideLoop( inPt, loop, tr ) { export function classifyPointInsideLoop( pt, loop, surface, uvPt ) {
function VertexResult(vertex) { function VertexResult(vertex) {
this.inside = true; this.inside = true;
@ -1221,20 +1220,37 @@ export function classifyPointInsideLoop( inPt, loop, tr ) {
this.edge = edge; this.edge = edge;
} }
const _2dCoords = new Map(); if (!uvPt) {
uvPt = surface.toUV(pt);
}
function isLine(edge) {
return !edge.edge || !edge.edge.curve || edge.edge.curve.isLine;
}
const uvCoords = new Map();
for( let edge of loop.halfEdges ) { for( let edge of loop.halfEdges ) {
const p = tr.apply(edge.vertexA.point); const uv = surface.toUV(edge.vertexA.point);
if (math.areEqual(inPt.y, p.y, TOLERANCE) && math.areEqual(inPt.x, p.x, TOLERANCE)) { if (math.areEqual(uvPt.y, uv.y, TOLERANCE) && math.areEqual(uvPt.x, uv.x, TOLERANCE)) {
return new VertexResult(edge.vertexA); return new VertexResult(edge.vertexA);
} }
_2dCoords.set(edge.vertexA, p); uvCoords.set(edge.vertexA, uv);
} }
const grads = []; const grads = [];
for( let edge of loop.halfEdges ) { for( let edge of loop.halfEdges ) {
const a = _2dCoords.get(edge.vertexA); const a = uvCoords.get(edge.vertexA);
const b = _2dCoords.get(edge.vertexB); const b = uvCoords.get(edge.vertexB);
const dy = b.y - a.y; let dy;
if (isLine(edge)) {
dy = b.y - a.y;
} else {
const tangent = edge.edge.curve.tangent(edge.vertexA.point);
dy = surface.toUV(tangent).y;
if (edge.edge.invertedToCurve) {
dy *= -1;
}
}
if (math.areEqual(dy, 0, TOLERANCE)) { if (math.areEqual(dy, 0, TOLERANCE)) {
grads.push(0) grads.push(0)
} else if (dy > 0) { } else if (dy > 0) {
@ -1264,6 +1280,7 @@ export function classifyPointInsideLoop( inPt, loop, tr ) {
const skip = new Set(); const skip = new Set();
let ray = null;
let inside = false; let inside = false;
for( let i = 0; i < loop.halfEdges.length; ++i) { for( let i = 0; i < loop.halfEdges.length; ++i) {
@ -1271,11 +1288,11 @@ export function classifyPointInsideLoop( inPt, loop, tr ) {
var shouldBeSkipped = skip.has(edge.vertexA) || skip.has(edge.vertexB); var shouldBeSkipped = skip.has(edge.vertexA) || skip.has(edge.vertexB);
const a = _2dCoords.get(edge.vertexA); const a = uvCoords.get(edge.vertexA);
const b = _2dCoords.get(edge.vertexB); const b = uvCoords.get(edge.vertexB);
const aEq = math.areEqual(inPt.y, a.y, TOLERANCE); const aEq = math.areEqual(uvPt.y, a.y, TOLERANCE);
const bEq = math.areEqual(inPt.y, b.y, TOLERANCE); const bEq = math.areEqual(uvPt.y, b.y, TOLERANCE);
if (aEq) { if (aEq) {
skip.add(edge.vertexA); skip.add(edge.vertexA);
@ -1287,50 +1304,98 @@ export function classifyPointInsideLoop( inPt, loop, tr ) {
if (math.areVectorsEqual(a, b, TOLERANCE)) { if (math.areVectorsEqual(a, b, TOLERANCE)) {
console.error('unable to classify invalid polygon'); console.error('unable to classify invalid polygon');
} }
var edgeLowPt = a;
var edgeHighPt = b;
var edgeDx = edgeHighPt.x - edgeLowPt.x; if (isLine(edge)) {
var edgeDy = edgeHighPt.y - edgeLowPt.y; let edgeLowPt = a;
let edgeHighPt = b;
if (aEq && bEq) {
if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) || let edgeDx = edgeHighPt.x - edgeLowPt.x;
( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) ) { let edgeDy = edgeHighPt.y - edgeLowPt.y;
return new EdgeResult(edge);
} else { if (aEq && bEq) {
if ( ( ( edgeHighPt.x <= uvPt.x ) && ( uvPt.x <= edgeLowPt.x ) ) ||
( ( edgeLowPt.x <= uvPt.x ) && ( uvPt.x <= edgeHighPt.x ) ) ) {
return new EdgeResult(edge);
} else {
continue;
}
}
if (shouldBeSkipped) {
continue; continue;
} }
}
if ( edgeDy < 0 ) {
if (shouldBeSkipped) { edgeLowPt = b; edgeDx = - edgeDx;
continue; edgeHighPt = a; edgeDy = - edgeDy;
} }
if (!aEq && !bEq && ( uvPt.y < edgeLowPt.y || uvPt.y > edgeHighPt.y ) ) {
if ( edgeDy < 0 ) {
edgeLowPt = b; edgeDx = - edgeDx;
edgeHighPt = a; edgeDy = - edgeDy;
}
if (!aEq && !bEq && ( inPt.y < edgeLowPt.y || inPt.y > edgeHighPt.y ) ) {
continue;
}
if (bEq) {
if (grads[i] * nextGrad(i) < 0) {
continue; continue;
} }
} else if (aEq) {
if (grads[i] * prevGrad(i) < 0) { if (bEq) {
if (grads[i] * nextGrad(i) < 0) {
continue;
}
} else if (aEq) {
if (grads[i] * prevGrad(i) < 0) {
continue;
}
}
let perpEdge = edgeDx * (uvPt.y - edgeLowPt.y) - edgeDy * (uvPt.x - edgeLowPt.x);
if ( math.areEqual(perpEdge, 0, TOLERANCE) ) return new EdgeResult(edge); // uvPt is on contour ?
if ( perpEdge < 0 ) {
continue; continue;
} }
} inside = ! inside; // true intersection left of uvPt
} else {
if (aEq && bEq) {
if (math.areEqual(edge.edge.curve.closestDistanceToPoint(pt), 0, TOLERANCE)) {
return new EdgeResult(edge);
} else {
continue;
}
}
let perpEdge = edgeDx * (inPt.y - edgeLowPt.y) - edgeDy * (inPt.x - edgeLowPt.x); if (shouldBeSkipped) {
if ( math.areEqual(perpEdge, 0, TOLERANCE) ) return new EdgeResult(edge); // inPt is on contour ? continue;
if ( perpEdge < 0 ) { }
continue;
if (bEq) {
if (grads[i] * nextGrad(i) < 0) {
continue;
}
} else if (aEq) {
if (grads[i] * prevGrad(i) < 0) {
continue;
}
}
if (math.areEqual(edge.edge.curve.closestDistanceToPoint(pt), 0, TOLERANCE)) {
return new EdgeResult(edge);
}
if (ray == null) {
let rayEnd = pt.copy();
//fixme!!
rayEnd.x = 1000000;//surface.fromUV(surface.domainU()[1]).x;
ray = edge.edge.curve.createLinearNurbs(pt, rayEnd);
}
const hits = edge.edge.curve.intersect(ray);
for (let hit of hits) {
//if ray just touches
const onlyTouches = math.areEqual(edge.edge.curve.tangent(hit).normalize().y, 0, TOLERANCE);
if (!onlyTouches) {
inside = ! inside;
}
}
} }
inside = ! inside; // true intersection left of inPt
} }
return {inside}; return {inside};

View file

@ -15,9 +15,9 @@ Vector.prototype.set = function(x, y, z) {
}; };
Vector.prototype.set3 = function(data) { Vector.prototype.set3 = function(data) {
this.x = data[0]; this.x = data[0] || 0;
this.y = data[1]; this.y = data[1] || 0;
this.z = data[2]; this.z = data[2] || 0;
return this; return this;
}; };

View file

@ -1,5 +1,5 @@
import * as test from '../test' import * as test from '../test'
import {Matrix3} from '../../app/math/l3space' import {AXIS} from '../../app/math/l3space'
export default { export default {
@ -639,6 +639,167 @@ export default {
})); }));
}, },
/**
* o--------o
* | \
* *--> | )
* | /
* o--------o
*/
testPIPClassification1NurbsOut: function (env) {
test.modeller(env.test((win, app) => {
const loop = createLoop(app.TPI,[
[100, 100],
[500, 100],
[500, 500],
[100, 500]
], [,['nurbs', [500, 100], [700, 250], [500, 500] ]]);
const result = classify(app, win, loop, [-300, 300]);
env.assertFalse(result.inside);
env.done();
}));
},
/**
* o--------o
* | \
* *--> | )
* | /
* o--------o
*/
testPIPClassification1NurbsIn: function (env) {
test.modeller(env.test((win, app) => {
const loop = createLoop(app.TPI,[
[100, 100],
[500, 100],
[500, 500],
[100, 500]
], [,['nurbs', [500, 100], [700, 250], [500, 500] ]]);
const result = classify(app, win, loop, [300, 300]);
env.assertTrue(result.inside);
env.done();
}));
},
/**
* *-->
*
* . ' .
* / \
* o o
* | |
* | |
* | |
* o--------o
*/
testPIPClassificationCloseToNurbsOut: function (env) {
test.modeller(env.test((win, app) => {
const loop = createLoop(app.TPI,[
[100, 100],
[500, 100],
[500, 500],
[100, 500]
], [,,['nurbs', [500, 500], [250, 750], [100, 500] ]]);
const result = classify(app, win, loop, [-300, 780]);
env.assertFalse(result.inside);
env.done();
}));
},
/**
* *-->
* . ' .
* / \
* o o
* | |
* | |
* | |
* o--------o
*/
testPIPClassificationTouchesNurbsOut: function (env) {
test.modeller(env.test((win, app) => {
const loop = createLoop(app.TPI,[
[100, 100],
[500, 100],
[500, 500],
[100, 500]
], [,,['nurbs', [500, 500], [250, 750], [100, 500] ]]);
const result = classify(app, win, loop, [-300, 750]);
env.assertFalse(result.inside);
env.done();
}));
},
/**
*
* *--> . ' .
* / \
* o o
* | |
* | |
* | |
* o--------o
*/
testPIPClassificationThroughNurbsOut: function (env) {
test.modeller(env.test((win, app) => {
const loop = createLoop(app.TPI,[
[100, 100],
[500, 100],
[500, 500],
[100, 500]
], [,,['nurbs', [500, 500], [250, 750], [100, 500] ]]);
const result = classify(app, win, loop, [-300, 650]);
env.assertFalse(result.inside);
env.done();
}));
},
/**
*
* . ' .
* / *-> \
* o o
* | |
* | |
* | |
* o--------o
*/
testPIPClassificationCrossesNurbsIn: function (env) {
test.modeller(env.test((win, app) => {
const loop = createLoop(app.TPI,[
[100, 100],
[500, 100],
[500, 500],
[100, 500]
], [,,['nurbs', [500, 500], [250, 750], [100, 500] ]]);
const result = classify(app, win, loop, [300, 650]);
env.assertTrue(result.inside);
env.done();
}));
},
/**
* o--------o
* \ \
* *--> ) )
* / /
* o--------o
*/
testPIPClassification2NurbsOut: function (env) {
test.modeller(env.test((win, app) => {
const loop = createLoop(app.TPI,[
[100, 100],
[500, 100],
[500, 500],
[100, 500]
], [,['nurbs', [500, 100], [700, 250], [500, 500]], , ['nurbs', [100, 500], [250, 250], [100, 100]]]);
const result = classify(app, win, loop, [-300, 300]);
env.assertFalse(result.inside);
env.done();
}));
},
testPIPClassification_TR_OUT_TR_INNER: function (env) { testPIPClassification_TR_OUT_TR_INNER: function (env) {
test.modeller(env.test((win, app) => { test.modeller(env.test((win, app) => {
const loop = createLoop(app.TPI,[ const loop = createLoop(app.TPI,[
@ -660,14 +821,13 @@ export default {
} }
function classify(app, win, loop, p) { function classify(app, win, loop, p) {
const IDENTITY = new Matrix3();
loop.halfEdges.forEach(e => win.__DEBUG__.AddHalfEdge(e, 0xffff00)); loop.halfEdges.forEach(e => win.__DEBUG__.AddHalfEdge(e, 0xffff00));
const pnt = point(app.TPI, p[0], p[1], 0); const pnt = point(app.TPI, p[0], p[1], 0);
const beam = pnt.copy(); const beam = pnt.copy();
beam.x += 1700; beam.x += 1700;
win.__DEBUG__.AddLine(pnt, beam); win.__DEBUG__.AddLine(pnt, beam);
win.__DEBUG__.AddPoint(pnt, 0xffffff); win.__DEBUG__.AddPoint(pnt, 0xffffff);
const result = app.TPI.brep.bool.classifyPointInsideLoop(pnt, loop, IDENTITY); const result = app.TPI.brep.bool.classifyPointInsideLoop(pnt, loop, new app.TPI.brep.geom.Plane(AXIS.Z, 0));
win.__DEBUG__.AddPoint(pnt, result.inside ? 0x00ff00 : 0xff0000); win.__DEBUG__.AddPoint(pnt, result.inside ? 0x00ff00 : 0xff0000);
if (result.edge) { if (result.edge) {
win.__DEBUG__.AddHalfEdge(result.edge, 0xffffff) win.__DEBUG__.AddHalfEdge(result.edge, 0xffffff)
@ -676,9 +836,16 @@ function classify(app, win, loop, p) {
} }
function createLoop(tpi, points) { function createLoop(tpi, points, curves) {
curves = curves || [];
const vertices = points.map(p => vertex(tpi, p[0], p[1], 0)); const vertices = points.map(p => vertex(tpi, p[0], p[1], 0));
return tpi.brep.builder.createPlaneLoop(vertices); return tpi.brep.builder.createPlaneLoop(vertices, curves.map(c => {
if (c && c[0] == 'nurbs') {
const points = c.slice(1).map(p => new tpi.brep.geom.Point().set3(p) );
return tpi.brep.geom.NurbsCurve.createByPoints(points, 2);
}
return undefined;
}));
} }
function vertex(tpi, x, y, z) { function vertex(tpi, x, y, z) {