mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-07 17:04:58 +01:00
nurbs curve-curve intersection
This commit is contained in:
parent
496cf22ba9
commit
9f168e563a
4 changed files with 223 additions and 28 deletions
|
|
@ -92,27 +92,32 @@ App.prototype.scratchCode = function() {
|
|||
|
||||
const box3 = app.TPI.brep.primitives.box(150, 600, 350, new Matrix3().translate(25, 25, -250));
|
||||
// let result = app.TPI.brep.bool.union(box1, box2);
|
||||
// let result = app.TPI.brep.bool.subtract(box1, box2);
|
||||
// result = app.TPI.brep.bool.subtract(result, box3);
|
||||
let result = app.TPI.brep.bool.subtract(box1, box2);
|
||||
result = app.TPI.brep.bool.subtract(result, box3);
|
||||
// app.addShellOnScene(box1);
|
||||
// app.addShellOnScene(result);
|
||||
app.addShellOnScene(result);
|
||||
|
||||
|
||||
let curve1 = new NurbsCurve(new verb.geom.NurbsCurve({"degree":6,"controlPoints":[[150,149.99999999999997,-249.99999999999994,1],[108.33333333333051,150.00000000000907,-250.00000000001975,1],[66.6666666666712,149.99999999998562,-249.99999999996987,1],[24.99999999999545,150.00000000001364,-250.00000000002711,1],[-16.66666666666362,149.99999999999145,-249.9999999999837,1],[-58.33333333333436,150.0000000000029,-250.00000000000531,1],[-99.99999999999997,150,-250,1]],"knots":[0,0,0,0,0,0,0,1,1,1,1,1,1,1]}));
|
||||
let curve2 = new NurbsCurve(new verb.geom.NurbsCurve({"degree":9,"controlPoints":[[100,-250,-250,1],[99.9999999999927,-194.44444444444687,-250.00000000000028,1],[100.00000000002228,-138.8888888888811,-249.99999999999838,1],[99.99999999995923,-83.33333333334777,-250.00000000000287,1],[100.00000000005268,-27.77777777775936,-249.99999999999744,1],[99.9999999999493,27.777777777760704,-250.0000000000008,1],[100.00000000003591,83.33333333334477,-250.00000000000063,1],[99.99999999998269,138.88888888888374,-249.99999999999966,1],[100.00000000000443,194.44444444444562,-249.99999999999986,1],[100,250,-250,1]],"knots":[0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1]}));
|
||||
// let curve1 = new NurbsCurve(new verb.geom.NurbsCurve({"degree":6,"controlPoints":[[150,149.99999999999997,-249.99999999999994,1],[108.33333333333051,150.00000000000907,-250.00000000001975,1],[66.6666666666712,149.99999999998562,-249.99999999996987,1],[24.99999999999545,150.00000000001364,-250.00000000002711,1],[-16.66666666666362,149.99999999999145,-249.9999999999837,1],[-58.33333333333436,150.0000000000029,-250.00000000000531,1],[-99.99999999999997,150,-250,1]],"knots":[0,0,0,0,0,0,0,1,1,1,1,1,1,1]}));
|
||||
// let curve2 = new NurbsCurve(new verb.geom.NurbsCurve({"degree":9,"controlPoints":[[100,-250,-250,1],[99.9999999999927,-194.44444444444687,-250.00000000000028,1],[100.00000000002228,-138.8888888888811,-249.99999999999838,1],[99.99999999995923,-83.33333333334777,-250.00000000000287,1],[100.00000000005268,-27.77777777775936,-249.99999999999744,1],[99.9999999999493,27.777777777760704,-250.0000000000008,1],[100.00000000003591,83.33333333334477,-250.00000000000063,1],[99.99999999998269,138.88888888888374,-249.99999999999966,1],[100.00000000000443,194.44444444444562,-249.99999999999986,1],[100,250,-250,1]],"knots":[0,0,0,0,0,0,0,0,0,0,1,1,1,1,1,1,1,1,1,1]}));
|
||||
|
||||
__DEBUG__.AddCurve(curve1);
|
||||
__DEBUG__.AddCurve(curve2);
|
||||
// var p1 = [-50,0,0], p2 = [100,0,0], p3 = [100,100,0], p4 = [0,100,0], p5 = [50, 50, 0];
|
||||
// var pts = [p1, p2, p3, p4, p5];
|
||||
// let curve1 = new NurbsCurve(verb.geom.NurbsCurve.byPoints( pts, 3 ));
|
||||
//
|
||||
// var p1a = [-50,0,0], p2a = [50,-10,0], p3a = [150,50,0], p4a = [30,100,0], p5a = [50, 120, 0];
|
||||
// var ptsa = [p1a, p2a, p3a, p4a, p5a];
|
||||
// let curve2 = new NurbsCurve(verb.geom.NurbsCurve.byPoints( ptsa, 3 ));
|
||||
//
|
||||
// __DEBUG__.AddCurve(curve1);
|
||||
// __DEBUG__.AddCurve(curve2);
|
||||
|
||||
|
||||
// let curves = surface.intersectSurface(box1.faces[0].surface);
|
||||
// const curve = box1.faces[0].outerLoop.halfEdges[0].edge.curve;
|
||||
let points = curve1.intersectCurve(curve2);
|
||||
for (let p of points) {
|
||||
__DEBUG__.AddPoint(p.p0);
|
||||
}
|
||||
|
||||
|
||||
// let points = curve1.intersectCurve(curve2);
|
||||
// for (let p of points) {
|
||||
// __DEBUG__.AddPoint(p.p0);
|
||||
// }
|
||||
|
||||
app.viewer.render();
|
||||
};
|
||||
|
|
|
|||
|
|
@ -3,6 +3,7 @@ import * as math from '../../../math/math'
|
|||
import {Point} from '../point'
|
||||
import {Surface} from "../surface";
|
||||
import Vector from "../../../math/vector";
|
||||
import * as vec from "../../../math/vec";
|
||||
import {Curve} from "../curve";
|
||||
|
||||
export class NurbsCurve extends Curve {
|
||||
|
|
@ -76,7 +77,7 @@ export class NurbsCurve extends Curve {
|
|||
isecOn(other, this, 0);
|
||||
isecOn(other, this, 1);
|
||||
|
||||
verb.geom.Intersect.curves(this.verb, other.verb, tol).forEach( i => add({
|
||||
verb_curve_isec(this.verb, other.verb, tol).forEach( i => add({
|
||||
u0: i.u0,
|
||||
u1: i.u1,
|
||||
p0: i.point0,
|
||||
|
|
@ -86,10 +87,11 @@ export class NurbsCurve extends Curve {
|
|||
i.p0 = pt(i.p0);
|
||||
i.p1 = pt(i.p1);
|
||||
});
|
||||
return isecs.filter(({u0, u1}) => {
|
||||
return Math.abs(this.tangentAtParam(u0).dot(other.tangentAtParam(u1))) <= tol;
|
||||
isecs = isecs.filter(({u0, u1}) => {
|
||||
let collinearFactor = Math.abs(this.tangentAtParam(u0).dot(other.tangentAtParam(u1)));
|
||||
return !math.areEqual(collinearFactor, 1, tol);
|
||||
});
|
||||
|
||||
return isecs;
|
||||
}
|
||||
|
||||
static createByPoints(points, degeree) {
|
||||
|
|
@ -146,7 +148,7 @@ export class NurbsSurface extends Surface {
|
|||
}
|
||||
|
||||
intersectSurfaceForSameClass(other, tol) {
|
||||
const curves = verb_isec(this.verb, other.verb);
|
||||
const curves = verb_surface_isec(this.verb, other.verb, tol);
|
||||
let inverted = this.inverted !== other.inverted;
|
||||
return curves.map(curve => new NurbsCurve(inverted ? curve.reverse() : curve));
|
||||
}
|
||||
|
|
@ -180,15 +182,13 @@ function pt(data) {
|
|||
return new Point().set3(data);
|
||||
}
|
||||
|
||||
|
||||
function verb_isec(nurbs1, nurbs2) {
|
||||
const tol = 1e-3
|
||||
function verb_surface_isec(nurbs1, nurbs2, tol) {
|
||||
const surface0 = nurbs1.asNurbs();
|
||||
const surface1 = nurbs2.asNurbs();
|
||||
var tess1 = verb.eval.Tess.rationalSurfaceAdaptive(surface0);
|
||||
var tess2 = verb.eval.Tess.rationalSurfaceAdaptive(surface1);
|
||||
var resApprox = verb.eval.Intersect.meshes(tess1,tess2);
|
||||
var exactPls = resApprox.map(function(pl) {
|
||||
const tess1 = verb.eval.Tess.rationalSurfaceAdaptive(surface0);
|
||||
const tess2 = verb.eval.Tess.rationalSurfaceAdaptive(surface1);
|
||||
const resApprox = verb.eval.Intersect.meshes(tess1,tess2);
|
||||
const exactPls = resApprox.map(function(pl) {
|
||||
return pl.map(function(inter) {
|
||||
return verb.eval.Intersect.surfacesAtPointWithEstimate(surface0,surface1,inter.uv0,inter.uv1,tol);
|
||||
});
|
||||
|
|
@ -199,3 +199,70 @@ function verb_isec(nurbs1, nurbs2) {
|
|||
}), x.length - 1);
|
||||
}).map(cd => new verb.geom.NurbsCurve(cd));
|
||||
}
|
||||
|
||||
function verb_curve_isec(curve1, curve2, tol) {
|
||||
|
||||
let result = [];
|
||||
let segs1 = curve1.tessellate();
|
||||
let segs2 = curve2.tessellate();
|
||||
|
||||
for (let i = 0; i < segs1.length - 1; i++) {
|
||||
let a1 = segs1[i];
|
||||
let b1 = segs1[i + 1];
|
||||
for (let j = 0; j < segs2.length - 1; j++) {
|
||||
let a2 = segs2[j];
|
||||
let b2 = segs2[j + 1];
|
||||
|
||||
//TODO: minimize
|
||||
let isec = intersectSegs(a1, b1, a2, b2, tol);
|
||||
if (isec !== null) {
|
||||
let {u1, u2, point1, point2, l1, l2} = isec;
|
||||
result.push({
|
||||
u0: curve1.closestParam(point1),
|
||||
u1: curve2.closestParam(point2),
|
||||
point0: point1,
|
||||
point1: point2
|
||||
});
|
||||
if (math.areEqual(u1, l1, tol )) {
|
||||
i ++;
|
||||
}
|
||||
if (math.areEqual(u2, l2, tol )) {
|
||||
j ++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
export function lineLineIntersection(p1, p2, v1, v2) {
|
||||
let zAx = vec.cross(v1, v2);
|
||||
const n1 = vec._normalize(vec.cross(zAx, v1));
|
||||
const n2 = vec._normalize(vec.cross(zAx, v2));
|
||||
return {
|
||||
u1: vec.dot(n2, vec.sub(p2, p1)) / vec.dot(n2, v1),
|
||||
u2: vec.dot(n1, vec.sub(p1, p2)) / vec.dot(n1, v2),
|
||||
}
|
||||
}
|
||||
|
||||
function intersectSegs(a1, b1, a2, b2, tol) {
|
||||
let v1 = vec.sub(b1, a1);
|
||||
let v2 = vec.sub(b2, a2);
|
||||
let l1 = vec.length(v1);
|
||||
let l2 = vec.length(v2);
|
||||
vec._div(v1, l1);
|
||||
vec._div(v2, l2);
|
||||
|
||||
let {u1, u2} = lineLineIntersection(a1, a2, v1, v2);
|
||||
let point1 = vec.add(a1, vec.mul(v1, u1));
|
||||
let point2 = vec.add(a2, vec.mul(v2, u2));
|
||||
let p2p = vec.lengthSq(vec.sub(point1, point2));
|
||||
let eq = (a, b) => math.areEqual(a, b, tol);
|
||||
if (u1 !== Infinity && u2 !== Infinity && math.areEqual(p2p, 0, tol*tol) &&
|
||||
((u1 >0 && u1 < l1) || eq(u1, 0) || eq(u1, l1)) &&
|
||||
((u2 >0 && u2 < l2) || eq(u2, 0) || eq(u2, l2))
|
||||
) {
|
||||
return {point1, point2, u1, u2, l1, l2}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -7,8 +7,8 @@ import {Vertex} from '../topo/vertex';
|
|||
import Vector from '../../math/vector';
|
||||
import * as math from '../../math/math';
|
||||
|
||||
export const TOLERANCE = 1e-8;
|
||||
export const TOLERANCE_SQ = TOLERANCE * TOLERANCE;
|
||||
export const TOLERANCE = 1e-3;
|
||||
export const TOLERANCE_SQ = TOLERANCE * TOLERANCE;
|
||||
export const TOLERANCE_HALF = TOLERANCE * 0.5;
|
||||
|
||||
const DEBUG = {
|
||||
|
|
@ -448,6 +448,7 @@ function collectNodesOfIntersection(curve, loop, nodes) {
|
|||
function intersectCurveWithEdge(curve, edge, result) {
|
||||
__DEBUG__.AddCurve(curve, 0xffffff);
|
||||
__DEBUG__.AddHalfEdge(edge, 0xff00ff);
|
||||
console.log(1)
|
||||
const points = edge.edge.curve.intersectCurve(curve, TOLERANCE);
|
||||
for (let point of points) {
|
||||
const {u0, u1} = point;
|
||||
|
|
|
|||
122
web/app/math/vec.js
Normal file
122
web/app/math/vec.js
Normal file
|
|
@ -0,0 +1,122 @@
|
|||
export function __mul(v, scalar, out) {
|
||||
out[0] = scalar * v[0];
|
||||
out[1] = scalar * v[1];
|
||||
out[2] = scalar * v[2];
|
||||
return out;
|
||||
}
|
||||
|
||||
export function _mul(v, scalar) {
|
||||
return __mul(v, scalar, v);
|
||||
}
|
||||
|
||||
export function mul(v, scalar) {
|
||||
return __mul(v, scalar, []);
|
||||
}
|
||||
|
||||
export function __div(v, scalar, out) {
|
||||
out[0] = v[0] / scalar;
|
||||
out[1] = v[1] / scalar;
|
||||
out[2] = v[2] / scalar;
|
||||
return out;
|
||||
}
|
||||
|
||||
export function _div(v, scalar) {
|
||||
return __div(v, scalar, v);
|
||||
}
|
||||
|
||||
export function div(v, scalar) {
|
||||
return __div(v, scalar, []);
|
||||
}
|
||||
|
||||
|
||||
export function __add(v1, v2, out) {
|
||||
out[0] = v1[0] + v2[0];
|
||||
out[1] = v1[1] + v2[1];
|
||||
out[2] = v1[2] + v2[2];
|
||||
return out;
|
||||
}
|
||||
|
||||
export function _add(v1, v2) {
|
||||
return __add(v1, v2, v1);
|
||||
}
|
||||
|
||||
export function add(v1, v2) {
|
||||
return __add(v1, v2, []);
|
||||
}
|
||||
|
||||
export function __sub(v1, v2, out) {
|
||||
out[0] = v1[0] - v2[0];
|
||||
out[1] = v1[1] - v2[1];
|
||||
out[2] = v1[2] - v2[2];
|
||||
return out;
|
||||
}
|
||||
|
||||
export function _sub(v1, v2) {
|
||||
return __sub(v1, v2, v1);
|
||||
}
|
||||
|
||||
export function sub(v1, v2) {
|
||||
return __sub(v1, v2, []);
|
||||
}
|
||||
|
||||
|
||||
export function __negate(v, out) {
|
||||
out[0] = - v[0];
|
||||
out[1] = - v[1];
|
||||
out[2] = - v[2];
|
||||
return out;
|
||||
}
|
||||
|
||||
export function _negate(v) {
|
||||
return __negate(v, v);
|
||||
}
|
||||
|
||||
export function negate(v) {
|
||||
return __negate(v, []);
|
||||
}
|
||||
|
||||
|
||||
export function dot(v1, v2) {
|
||||
return v1[0] * v2[0] + v1[1] * v2[1] + v1[2] * v2[2];
|
||||
}
|
||||
|
||||
export function __cross(v1, v2, out) {
|
||||
out[0] = v1[1] * v2[2] - v1[2] * v2[1];
|
||||
out[1] = v1[2] * v2[0] - v1[0] * v2[2];
|
||||
out[2] = v1[0] * v2[1] - v1[1] * v2[0];
|
||||
return out;
|
||||
}
|
||||
|
||||
export function _cross(v1, v2) {
|
||||
return __cross(v1, v2);
|
||||
}
|
||||
|
||||
export function cross(v1, v2) {
|
||||
return __cross(v1, v2, []);
|
||||
}
|
||||
|
||||
|
||||
export function __normalize(v, out) {
|
||||
const mag = length(v);
|
||||
if (mag === 0.0) {
|
||||
out[0] = out[1] = out[2] = 0;
|
||||
}
|
||||
return __div(v, mag, out)
|
||||
}
|
||||
|
||||
export function _normalize(v) {
|
||||
return __normalize(v, v);
|
||||
}
|
||||
|
||||
export function normalize(v) {
|
||||
return __normalize(v, []);
|
||||
}
|
||||
|
||||
|
||||
export function lengthSq(v) {
|
||||
return dot(v, v);
|
||||
}
|
||||
|
||||
export function length(v) {
|
||||
return Math.sqrt(lengthSq(v));
|
||||
}
|
||||
Loading…
Reference in a new issue