mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-07 08:53:25 +01:00
PIP for NURBS
This commit is contained in:
parent
cad474b100
commit
13f2f8f6ee
11 changed files with 415 additions and 78 deletions
|
|
@ -24,9 +24,14 @@ function addGlobalDebugActions(app) {
|
|||
app.viewer.render();
|
||||
},
|
||||
AddSegment: (a, b, color) => {
|
||||
debugGroup.add(createLine(a, b, color));
|
||||
debugGroup.add(createPoint(a, 0x000088));
|
||||
debugGroup.add(createPoint(b, 0x880000));
|
||||
__DEBUG__.AddPolyLine([a, b], color);
|
||||
},
|
||||
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();
|
||||
},
|
||||
AddPoint: (coordinates, or, vector, andColorAtTheEnd) => {
|
||||
|
|
@ -55,7 +60,12 @@ function addGlobalDebugActions(app) {
|
|||
app.viewer.render();
|
||||
},
|
||||
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) => {
|
||||
for (let e of face.edges) __DEBUG__.AddHalfEdge(e, color);
|
||||
|
|
|
|||
|
|
@ -149,6 +149,30 @@ export function triangulateToThree(shell, geom) {
|
|||
}
|
||||
//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') {
|
||||
const off = geom.vertices.length;
|
||||
const tess = brepFace.surface.verb.tessellate({maxDepth: 3});
|
||||
|
|
|
|||
|
|
@ -9,6 +9,8 @@ import {Face} from '../brep/topo/face';
|
|||
import {Shell} from '../brep/topo/shell';
|
||||
import {Vertex} from '../brep/topo/vertex';
|
||||
import {Point} from '../brep/geom/point';
|
||||
import {NurbsCurve} from '../brep/geom/impl/nurbs';
|
||||
import {Plane} from '../brep/geom/impl/plane';
|
||||
|
||||
export default {
|
||||
brep: {
|
||||
|
|
@ -17,7 +19,7 @@ export default {
|
|||
bool: BREPBool,
|
||||
validator: BREPValidator,
|
||||
geom: {
|
||||
Point
|
||||
Point, NurbsCurve, Plane
|
||||
},
|
||||
topo: {
|
||||
HalfEdge, Edge, Loop, Face, Shell, Vertex
|
||||
|
|
|
|||
|
|
@ -186,12 +186,14 @@ export function invertLoop(loop) {
|
|||
linkSegments(loop.halfEdges);
|
||||
}
|
||||
|
||||
export function createPlaneLoop(vertices) {
|
||||
export function createPlaneLoop(vertices, curves) {
|
||||
|
||||
const loop = new Loop();
|
||||
|
||||
iterateSegments(vertices, (a, b) => {
|
||||
createHalfEdge(loop, a, b)
|
||||
iterateSegments(vertices, (a, b, i) => {
|
||||
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);
|
||||
|
|
|
|||
|
|
@ -2,7 +2,6 @@
|
|||
export class Curve {
|
||||
|
||||
constructor() {
|
||||
this.isLine = false;
|
||||
}
|
||||
|
||||
intersectCurve(curve) {
|
||||
|
|
@ -20,7 +19,7 @@ export class Curve {
|
|||
approximate(resolution, from, to, path) {
|
||||
}
|
||||
}
|
||||
|
||||
Curve.prototype.isLine = false;
|
||||
|
||||
export class CompositeCurve {
|
||||
|
||||
|
|
|
|||
|
|
@ -4,7 +4,6 @@ export class Line extends Curve {
|
|||
|
||||
constructor(p0, v) {
|
||||
super();
|
||||
this.isLine = true;
|
||||
this.p0 = p0;
|
||||
this.v = v;
|
||||
this._pointsCache = new Map();
|
||||
|
|
@ -56,6 +55,8 @@ export class Line extends Curve {
|
|||
offset() {};
|
||||
}
|
||||
|
||||
Line.prototype.isLine = true;
|
||||
|
||||
Line.fromTwoPlanesIntersection = function(plane1, plane2) {
|
||||
const n1 = plane1.normal;
|
||||
const n2 = plane2.normal;
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
import verb from 'verb-nurbs'
|
||||
import {Matrix3} from '../../../math/l3space'
|
||||
import Vector from '../../../math/vector'
|
||||
import * as math from '../../../math/math'
|
||||
import {Point} from '../point'
|
||||
|
||||
export class NurbsCurve {
|
||||
|
||||
|
|
@ -31,7 +32,7 @@ export class NurbsCurve {
|
|||
const step = this.verb.paramAtLength(length / resolution);
|
||||
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) {
|
||||
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 {
|
||||
|
||||
constructor(verbSurface) {
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
import {Surface} from '../surface'
|
||||
import {Point} from '../point'
|
||||
import {Line} from './line'
|
||||
import {Matrix3, AXIS, BasisForPlane} from '../../../math/l3space'
|
||||
import * as math from '../../../math/math'
|
||||
|
|
@ -38,11 +39,17 @@ export class Plane extends Surface {
|
|||
}
|
||||
|
||||
get2DTransformation() {
|
||||
return this.get3DTransformation().invert();
|
||||
if (!this.__2dTr) {
|
||||
this.__2dTr = this.get3DTransformation().invert();
|
||||
}
|
||||
return this.__2dTr;
|
||||
}
|
||||
|
||||
get3DTransformation() {
|
||||
return new Matrix3().setBasis(this.basis());
|
||||
if (!this.__3dTr) {
|
||||
this.__3dTr = new Matrix3().setBasis(this.basis());
|
||||
}
|
||||
return this.__3dTr;
|
||||
}
|
||||
|
||||
coplanarUnsigned(other, tol) {
|
||||
|
|
@ -58,8 +65,27 @@ export class Plane extends Surface {
|
|||
}
|
||||
|
||||
toParametricForm() {
|
||||
const basis = BasisForPlane(this.normal);
|
||||
return new ParametricPlane(this.normal.multiply(this.w), basis.x, basis.y);
|
||||
if (!this.__parametricForm) {
|
||||
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];
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -667,7 +667,6 @@ export function loopsToFaces(originFace, loops, out) {
|
|||
}
|
||||
|
||||
function getNestedLoops(face, brepLoops) {
|
||||
const tr = face.surface.get2DTransformation();
|
||||
function NestedLoop(loop) {
|
||||
this.loop = loop;
|
||||
this.nesting = [];
|
||||
|
|
@ -677,7 +676,7 @@ function getNestedLoops(face, brepLoops) {
|
|||
const loops = brepLoops.map(loop => new NestedLoop(loop));
|
||||
function contains(loop, other) {
|
||||
for (let point of other.asPolygon()) {
|
||||
if (!classifyPointInsideLoop(tr.apply(point), loop, tr).inside) {
|
||||
if (!classifyPointInsideLoop(point, loop, face.surface).inside) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
@ -1076,9 +1075,9 @@ function classifyPointToFace(point, face) {
|
|||
}
|
||||
return result;
|
||||
}
|
||||
const tr = face.surface.get2DTransformation();
|
||||
const point2d = tr.apply(point);
|
||||
const outer = classifyPointInsideLoop(point2d, face.outerLoop, tr);
|
||||
|
||||
const uvPt = face.surface.toUV(point);
|
||||
const outer = classifyPointInsideLoop(point, face.outerLoop, face.surface, uvPt);
|
||||
|
||||
if (outer.inside) {
|
||||
if (outer.vertex || outer.edge) {
|
||||
|
|
@ -1087,7 +1086,7 @@ function classifyPointToFace(point, face) {
|
|||
}
|
||||
|
||||
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) {
|
||||
return inner;
|
||||
}
|
||||
|
|
@ -1209,7 +1208,7 @@ class FaceSolveData {
|
|||
}
|
||||
}
|
||||
|
||||
export function classifyPointInsideLoop( inPt, loop, tr ) {
|
||||
export function classifyPointInsideLoop( pt, loop, surface, uvPt ) {
|
||||
|
||||
function VertexResult(vertex) {
|
||||
this.inside = true;
|
||||
|
|
@ -1221,20 +1220,37 @@ export function classifyPointInsideLoop( inPt, loop, tr ) {
|
|||
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 ) {
|
||||
const p = tr.apply(edge.vertexA.point);
|
||||
if (math.areEqual(inPt.y, p.y, TOLERANCE) && math.areEqual(inPt.x, p.x, TOLERANCE)) {
|
||||
const uv = surface.toUV(edge.vertexA.point);
|
||||
if (math.areEqual(uvPt.y, uv.y, TOLERANCE) && math.areEqual(uvPt.x, uv.x, TOLERANCE)) {
|
||||
return new VertexResult(edge.vertexA);
|
||||
}
|
||||
_2dCoords.set(edge.vertexA, p);
|
||||
uvCoords.set(edge.vertexA, uv);
|
||||
}
|
||||
|
||||
const grads = [];
|
||||
for( let edge of loop.halfEdges ) {
|
||||
const a = _2dCoords.get(edge.vertexA);
|
||||
const b = _2dCoords.get(edge.vertexB);
|
||||
const dy = b.y - a.y;
|
||||
const a = uvCoords.get(edge.vertexA);
|
||||
const b = uvCoords.get(edge.vertexB);
|
||||
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)) {
|
||||
grads.push(0)
|
||||
} else if (dy > 0) {
|
||||
|
|
@ -1264,6 +1280,7 @@ export function classifyPointInsideLoop( inPt, loop, tr ) {
|
|||
|
||||
const skip = new Set();
|
||||
|
||||
let ray = null;
|
||||
let inside = false;
|
||||
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);
|
||||
|
||||
const a = _2dCoords.get(edge.vertexA);
|
||||
const b = _2dCoords.get(edge.vertexB);
|
||||
const a = uvCoords.get(edge.vertexA);
|
||||
const b = uvCoords.get(edge.vertexB);
|
||||
|
||||
const aEq = math.areEqual(inPt.y, a.y, TOLERANCE);
|
||||
const bEq = math.areEqual(inPt.y, b.y, TOLERANCE);
|
||||
const aEq = math.areEqual(uvPt.y, a.y, TOLERANCE);
|
||||
const bEq = math.areEqual(uvPt.y, b.y, TOLERANCE);
|
||||
|
||||
if (aEq) {
|
||||
skip.add(edge.vertexA);
|
||||
|
|
@ -1287,50 +1304,98 @@ export function classifyPointInsideLoop( inPt, loop, tr ) {
|
|||
if (math.areVectorsEqual(a, b, TOLERANCE)) {
|
||||
console.error('unable to classify invalid polygon');
|
||||
}
|
||||
|
||||
var edgeLowPt = a;
|
||||
var edgeHighPt = b;
|
||||
|
||||
var edgeDx = edgeHighPt.x - edgeLowPt.x;
|
||||
var edgeDy = edgeHighPt.y - edgeLowPt.y;
|
||||
|
||||
if (aEq && bEq) {
|
||||
if ( ( ( edgeHighPt.x <= inPt.x ) && ( inPt.x <= edgeLowPt.x ) ) ||
|
||||
( ( edgeLowPt.x <= inPt.x ) && ( inPt.x <= edgeHighPt.x ) ) ) {
|
||||
return new EdgeResult(edge);
|
||||
} else {
|
||||
if (isLine(edge)) {
|
||||
let edgeLowPt = a;
|
||||
let edgeHighPt = b;
|
||||
|
||||
let edgeDx = edgeHighPt.x - edgeLowPt.x;
|
||||
let edgeDy = edgeHighPt.y - edgeLowPt.y;
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
if (shouldBeSkipped) {
|
||||
continue;
|
||||
}
|
||||
|
||||
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) {
|
||||
|
||||
if ( edgeDy < 0 ) {
|
||||
edgeLowPt = b; edgeDx = - edgeDx;
|
||||
edgeHighPt = a; edgeDy = - edgeDy;
|
||||
}
|
||||
if (!aEq && !bEq && ( uvPt.y < edgeLowPt.y || uvPt.y > edgeHighPt.y ) ) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
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 ( math.areEqual(perpEdge, 0, TOLERANCE) ) return new EdgeResult(edge); // inPt is on contour ?
|
||||
if ( perpEdge < 0 ) {
|
||||
continue;
|
||||
if (shouldBeSkipped) {
|
||||
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};
|
||||
|
|
|
|||
|
|
@ -15,9 +15,9 @@ Vector.prototype.set = function(x, y, z) {
|
|||
};
|
||||
|
||||
Vector.prototype.set3 = function(data) {
|
||||
this.x = data[0];
|
||||
this.y = data[1];
|
||||
this.z = data[2];
|
||||
this.x = data[0] || 0;
|
||||
this.y = data[1] || 0;
|
||||
this.z = data[2] || 0;
|
||||
return this;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,5 @@
|
|||
import * as test from '../test'
|
||||
import {Matrix3} from '../../app/math/l3space'
|
||||
import {AXIS} from '../../app/math/l3space'
|
||||
|
||||
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) {
|
||||
test.modeller(env.test((win, app) => {
|
||||
const loop = createLoop(app.TPI,[
|
||||
|
|
@ -660,14 +821,13 @@ export default {
|
|||
}
|
||||
|
||||
function classify(app, win, loop, p) {
|
||||
const IDENTITY = new Matrix3();
|
||||
loop.halfEdges.forEach(e => win.__DEBUG__.AddHalfEdge(e, 0xffff00));
|
||||
const pnt = point(app.TPI, p[0], p[1], 0);
|
||||
const beam = pnt.copy();
|
||||
beam.x += 1700;
|
||||
win.__DEBUG__.AddLine(pnt, beam);
|
||||
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);
|
||||
if (result.edge) {
|
||||
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));
|
||||
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) {
|
||||
|
|
|
|||
Loading…
Reference in a new issue