mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-14 20:33:30 +01:00
nurbs boolean
This commit is contained in:
parent
9983904a70
commit
6dc0f99746
9 changed files with 217 additions and 81 deletions
55
web/app/3d/craft/brep/wizards/revolve.js
Normal file
55
web/app/3d/craft/brep/wizards/revolve.js
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
import {CURRENT_SELECTION as S} from './wizard'
|
||||
import {PreviewWizard, SketchBasedPreviewer} from './preview-wizard'
|
||||
import {TriangulatePolygons} from '../../../triangulation'
|
||||
import Vector from '../../../../math/vector'
|
||||
|
||||
|
||||
const METADATA = [
|
||||
['angle' , 'number', 5, {min: -360, max: 360, step: 10}],
|
||||
['pivot' , 'sketch' , S ]
|
||||
];
|
||||
|
||||
export class RevolveWizard extends PreviewWizard {
|
||||
constructor(app, initialState) {
|
||||
super(app, 'REVOLVE', METADATA, initialState)
|
||||
}
|
||||
|
||||
createPreviewObject(app, params) {
|
||||
return CUT_PREVIEWER.create(app, params);
|
||||
}
|
||||
|
||||
uiLabel(name) {
|
||||
if ('value' == name) return 'depth';
|
||||
return super.uiLabel(name);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
export class ExtrudePreviewer extends SketchBasedPreviewer {
|
||||
|
||||
createImpl(app, params, sketch, face) {
|
||||
const triangles = [];
|
||||
|
||||
sketch.
|
||||
|
||||
for (let d of encloseDetails) {
|
||||
const base = d.basePath.points;
|
||||
const lid = d.lidPath.points;
|
||||
const n = base.length;
|
||||
for (let p = n - 1, q = 0; q < n; p = q ++) {
|
||||
triangles.push([ base[p], base[q], lid[q] ]);
|
||||
triangles.push([ lid[q], lid[p], base[p] ]);
|
||||
}
|
||||
|
||||
function collectOnSurface(points, normal) {
|
||||
TriangulatePolygons([points], normal, (v) => v.toArray(), (arr) => new Vector().set3(arr))
|
||||
.forEach(tr => triangles.push(tr));
|
||||
}
|
||||
collectOnSurface(base, d.baseSurface.normal);
|
||||
collectOnSurface(lid, d.lidSurface.normal);
|
||||
}
|
||||
return triangles;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -112,20 +112,27 @@ export class Wizard {
|
|||
});
|
||||
return new Field(radio, () => radio.getValue(), (v) => radio.setValue(v));
|
||||
} else if (type == 'face') {
|
||||
const face = new tk.Text(label, initValue);
|
||||
face.input.on('change', () => this.onUIChange(name));
|
||||
return Field.fromInput(face, undefined, (faceId) => {
|
||||
if (faceId === CURRENT_SELECTION) {
|
||||
let selection = this.app.viewer.selectionMgr.selection[0];
|
||||
return selection ? selection.id : '';
|
||||
} else {
|
||||
return faceId;
|
||||
}
|
||||
});
|
||||
return selectionWidget(name, label, initValue, this.app.viewer.selectionMgr);
|
||||
} else if (type == 'sketch.segment') {
|
||||
return selectionWidget(name, label, initValue, this.app.viewer.sketchSelectionMgr);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function selectionWidget(name, label, initValue, selectionManager) {
|
||||
const obj = new tk.Text(label, initValue);
|
||||
obj.input.on('change', () => this.onUIChange(name));
|
||||
return Field.fromInput(obj, undefined, (objId) => {
|
||||
if (objId === CURRENT_SELECTION) {
|
||||
let selection = selectionManager.selection[0];
|
||||
return selection ? selection.id : '';
|
||||
} else {
|
||||
return objId;
|
||||
}
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function FaceSelectionListener() {
|
||||
this.callbacks = [];
|
||||
}
|
||||
|
|
|
|||
|
|
@ -226,7 +226,9 @@ const USE_APPROX_FOR = new Set();
|
|||
const USE_NURBS_FOR = new Set();
|
||||
USE_NURBS_FOR.add('Arc');
|
||||
USE_NURBS_FOR.add('Circle');
|
||||
|
||||
//USE_NURBS_FOR.add('Ellipse');
|
||||
//USE_NURBS_FOR.add('EllipticalArc');
|
||||
//USE_NURBS_FOR.add('BezierCurve');
|
||||
|
||||
export class Contour {
|
||||
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ import * as Operations from '../craft/operations'
|
|||
import Menu from '../menu/menu'
|
||||
import {ExtrudeWizard, CutWizard} from '../craft/brep/wizards/cut-extrude'
|
||||
|
||||
import {RevolveWizard} from '../craft/mesh/wizards/revolve'
|
||||
import {RevolveWizard} from '../craft/brep/wizards/revolve'
|
||||
import {PlaneWizard} from '../craft/brep/wizards/plane'
|
||||
import {BoxWizard} from '../craft/brep/wizards/box'
|
||||
import {SphereWizard} from '../craft/mesh/wizards/sphere'
|
||||
|
|
|
|||
|
|
@ -48,7 +48,7 @@ export function createPrism(basePoints, height) {
|
|||
}
|
||||
|
||||
|
||||
export function enclose(basePath, lidPath, baseSurface, lidSurface, onWallF) {
|
||||
export function enclose(basePath, lidPath, baseSurface, lidSurface) {
|
||||
|
||||
if (basePath.points.length != lidPath.points.length) {
|
||||
throw 'illegal arguments';
|
||||
|
|
@ -125,6 +125,13 @@ export function enclose(basePath, lidPath, baseSurface, lidSurface, onWallF) {
|
|||
return shell;
|
||||
}
|
||||
|
||||
export function revolve(basePath, baseSurface) {
|
||||
const baseLoop = new Loop();
|
||||
|
||||
const shell = new Shell();
|
||||
new verb.geom.RevolvedSurface( prof, [0,0,0], [1,0,0], 2* Math.PI);
|
||||
}
|
||||
|
||||
function createTwin(halfEdge) {
|
||||
const twin = new HalfEdge();
|
||||
twin.vertexA = halfEdge.vertexB;
|
||||
|
|
|
|||
|
|
@ -85,11 +85,30 @@ export class NurbsSurface {
|
|||
this.verb = verbSurface;
|
||||
}
|
||||
|
||||
isCognateCurve(curve) {
|
||||
return curve.constructor.name == 'NurbsCurve';
|
||||
}
|
||||
|
||||
toNurbs() {
|
||||
return this;
|
||||
}
|
||||
|
||||
coplanarUnsignedForSameClass(other, tolerance) {
|
||||
throw 'not implemented'
|
||||
coplanarUnsignedForSameClass(other, tol) {
|
||||
//throw 'not implemented'
|
||||
return false;
|
||||
}
|
||||
|
||||
intersectForSameClass(other, tol) {
|
||||
const curves = verb.geom.Intersect.surfaces(this.verb, other.verb, tol);
|
||||
return curves.map(curve => new NurbsCurve(curve));
|
||||
}
|
||||
|
||||
classifyCognateCurve(line, tol) {
|
||||
const parallel = math.areEqual(line.v.dot(this.normal), 0, tol);
|
||||
const pointOnPlane = math.areEqual(this.normal.dot(line.p0), this.w, tol);
|
||||
return {
|
||||
hit: !parallel || pointOnPlane,
|
||||
parallel
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -3,7 +3,7 @@ import {Point} from '../point'
|
|||
import {Line} from './line'
|
||||
import {Matrix3, AXIS, BasisForPlane} from '../../../math/l3space'
|
||||
import * as math from '../../../math/math'
|
||||
|
||||
|
||||
export class Plane extends Surface {
|
||||
|
||||
constructor(normal, w) {
|
||||
|
|
@ -12,22 +12,23 @@ export class Plane extends Surface {
|
|||
this.w = w;
|
||||
}
|
||||
|
||||
isCognateCurve(curve) {
|
||||
return curve.constructor.name == 'Line';
|
||||
}
|
||||
|
||||
calculateBasis() {
|
||||
return BasisForPlane(this.normal);
|
||||
}
|
||||
|
||||
|
||||
basis() {
|
||||
if (!this._basis) {
|
||||
this._basis = this.calculateBasis();
|
||||
}
|
||||
return this._basis;
|
||||
}
|
||||
|
||||
intersect(other) {
|
||||
if (other.isPlane) {
|
||||
return new Line.fromTwoPlanesIntersection(this, other);
|
||||
}
|
||||
return super.intersect();
|
||||
|
||||
intersectForSameClass(other) {
|
||||
return new Line.fromTwoPlanesIntersection(this, other);
|
||||
}
|
||||
|
||||
translate(vector) {
|
||||
|
|
@ -40,14 +41,18 @@ export class Plane extends Surface {
|
|||
|
||||
get2DTransformation() {
|
||||
if (!this.__2dTr) {
|
||||
this.__2dTr = this.get3DTransformation().invert();
|
||||
this.__2dTr = this.get3DTransformation().invert();
|
||||
}
|
||||
return this.__2dTr;
|
||||
}
|
||||
|
||||
get3DTransformation() {
|
||||
if (!this.__3dTr) {
|
||||
this.__3dTr = new Matrix3().setBasis(this.basis());
|
||||
const basis = new Matrix3().setBasis(this.basis());
|
||||
const translate = new Matrix3();
|
||||
translate.tz = this.w
|
||||
this.__3dTr = basis.combine(translate);
|
||||
// this.__3dTr.tz = this.w;
|
||||
}
|
||||
return this.__3dTr;
|
||||
}
|
||||
|
|
@ -69,7 +74,7 @@ export class Plane extends Surface {
|
|||
}
|
||||
return this.__parametricForm;
|
||||
}
|
||||
|
||||
|
||||
toUV(point) {
|
||||
return this.get2DTransformation().apply(point);
|
||||
}
|
||||
|
|
@ -81,10 +86,19 @@ export class Plane extends Surface {
|
|||
domainU() {
|
||||
return [Number.MIN_VALUE, Number.MAX_VALUE];
|
||||
}
|
||||
|
||||
|
||||
domainV() {
|
||||
return [Number.MIN_VALUE, Number.MAX_VALUE];
|
||||
}
|
||||
|
||||
classifyCognateCurve(line, tol) {
|
||||
const parallel = math.areEqual(line.v.dot(this.normal), 0, tol);
|
||||
const pointOnPlane = math.areEqual(this.normal.dot(line.p0), this.w, tol);
|
||||
return {
|
||||
hit: !parallel || pointOnPlane,
|
||||
parallel
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Plane.prototype.isPlane = true;
|
||||
|
|
@ -100,4 +114,4 @@ class ParametricPlane {
|
|||
equation(u, v) {
|
||||
return this.r0 + this.r1.multiply(u) + this.r2.multiply(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -4,27 +4,39 @@ export class Surface {
|
|||
constructor() {
|
||||
|
||||
}
|
||||
|
||||
intersect(other) {
|
||||
return this.toNurbs.intersect(other.toNurbs());
|
||||
};
|
||||
|
||||
toNurbs() {
|
||||
//--------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
classifyCognateCurve(curve, tol) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
classifyCurve(curve, tol) {
|
||||
if (this.isCognateCurve(curve)) {
|
||||
return this.classifyCognateCurve(curve, tol)
|
||||
}
|
||||
return this.toNurbs().classifyCognateCurve(curve.toNurbs(), tol);
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
intersectForSameClass() {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
intersect(other, tol) {
|
||||
if (this.isSameClass(other)) {
|
||||
return this.intersectForSameClass(other, tol)
|
||||
}
|
||||
return this.toNurbs().intersectForSameClass(other.toNurbs(), tol);
|
||||
};
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
coplanarUnsignedForSameClass(other, tol) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
equalsUnsignedForSameClass(other, tol) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
isSameClass(other) {
|
||||
return this.constructor.name == other.constructor.name;
|
||||
}
|
||||
|
||||
coplanarUnsigned(other, tol) {
|
||||
if (this.isSameClass(other)) {
|
||||
return this.coplanarUnsignedForSameClass(other, tol)
|
||||
|
|
@ -32,11 +44,31 @@ export class Surface {
|
|||
return this.toNurbs().coplanarUnsignedForSameClass(other.toNurbs());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
equalsForSameClass(other, tol) {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
equals(other, tol) {
|
||||
if (this.isSameClass(other)) {
|
||||
return this.equalsForSameClass(other, tol)
|
||||
}
|
||||
return this.toNurbs().equalsForSameClass(other.toNurbs());
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------------------------------------------------------
|
||||
|
||||
toNurbs() {
|
||||
throw 'not implemented';
|
||||
}
|
||||
|
||||
isSameClass(other) {
|
||||
return this.constructor.name == other.constructor.name;
|
||||
}
|
||||
|
||||
isCognateCurve(curve) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
Surface.prototype.isPlane = false;
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@ 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_SQ = TOLERANCE * TOLERANCE;
|
||||
export const TOLERANCE_HALF = TOLERANCE * 0.5;
|
||||
|
||||
const DEBUG = {
|
||||
|
|
@ -70,7 +70,7 @@ export function BooleanAlgorithm( shell1, shell2, type ) {
|
|||
|
||||
initSolveData(shell1, facesData);
|
||||
initSolveData(shell2, facesData);
|
||||
|
||||
|
||||
markOverlappingFaces(shell1, shell2);
|
||||
intersectFaces(shell1, shell2, type !== TYPE.UNION);
|
||||
|
||||
|
|
@ -86,7 +86,7 @@ export function BooleanAlgorithm( shell1, shell2, type ) {
|
|||
for (let faceData of facesData) {
|
||||
initGraph(faceData);
|
||||
}
|
||||
|
||||
|
||||
facesData = facesData.filter(fd => fd.merged !== true);
|
||||
|
||||
const allFaces = [];
|
||||
|
|
@ -140,7 +140,7 @@ function detectLoops(face) {
|
|||
}
|
||||
const loop = new Loop();
|
||||
loop.face = face;
|
||||
let surface = EdgeSolveData.get(edge).transferedSurface;
|
||||
let surface = EdgeSolveData.get(edge).transferedSurface;
|
||||
if (!surface) {
|
||||
surface = face.surface;
|
||||
}
|
||||
|
|
@ -170,7 +170,7 @@ function detectLoops(face) {
|
|||
}
|
||||
}
|
||||
return loops;
|
||||
}
|
||||
}
|
||||
|
||||
function initGraph(faceData) {
|
||||
faceData.vertexToEdge.clear();
|
||||
|
|
@ -180,11 +180,11 @@ function initGraph(faceData) {
|
|||
}
|
||||
|
||||
function sew(allFaces) {
|
||||
|
||||
|
||||
const sewed = new Set();
|
||||
const sewedFaces = [];
|
||||
const analyzedNeighbors = new Map();
|
||||
FACES:
|
||||
FACES:
|
||||
for (let face of allFaces) {
|
||||
if (DEBUG.SEWING) {
|
||||
__DEBUG__.Clear();
|
||||
|
|
@ -197,7 +197,7 @@ function sew(allFaces) {
|
|||
if (DEBUG.SEWING) {
|
||||
__DEBUG__.AddHalfEdge(h1);
|
||||
}
|
||||
|
||||
|
||||
if (sewed.has(h1)) {
|
||||
continue;
|
||||
}
|
||||
|
|
@ -205,7 +205,7 @@ function sew(allFaces) {
|
|||
if (neighborhood.all.length == 1) {
|
||||
continue FACES;
|
||||
}
|
||||
|
||||
|
||||
let h2;
|
||||
if (neighborhood.all.length == 2 && neighborhood.side2.length == 1) {
|
||||
h2 = neighborhood.side2[0];
|
||||
|
|
@ -223,7 +223,7 @@ function sew(allFaces) {
|
|||
if (sewed.has(h2)) {
|
||||
throw 'illegal state. already sewed'
|
||||
}
|
||||
|
||||
|
||||
const edge = new Edge(h1.edge.curve);
|
||||
|
||||
edge.halfEdge1 = h1;
|
||||
|
|
@ -243,7 +243,7 @@ function edgeV(edge) {
|
|||
}
|
||||
|
||||
function neighborhoodAnalysis(neighborhood, analized) {
|
||||
|
||||
|
||||
function encloses(e1, e2, testeeE) {
|
||||
const f1 = e1.loop.face;
|
||||
const f2 = e2.loop.face;
|
||||
|
|
@ -263,7 +263,7 @@ function neighborhoodAnalysis(neighborhood, analized) {
|
|||
const testAngle = leftTurningMeasure(t1, t3, normal);
|
||||
return testAngle > angle;
|
||||
}
|
||||
|
||||
|
||||
let paired = new Set();
|
||||
for (let e1 of neighborhood.side1) {
|
||||
SIDE_2:
|
||||
|
|
@ -274,7 +274,7 @@ function neighborhoodAnalysis(neighborhood, analized) {
|
|||
continue;
|
||||
}
|
||||
if (encloses(e1, e2, t)) {
|
||||
continue SIDE_2;
|
||||
continue SIDE_2;
|
||||
}
|
||||
}
|
||||
analized.set(e1, e2);
|
||||
|
|
@ -283,21 +283,21 @@ function neighborhoodAnalysis(neighborhood, analized) {
|
|||
paired.add(e2);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
for (let e of neighborhood.all) {
|
||||
if (!paired.has(e)) {
|
||||
analized.set(e, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function findNeighborhood(allFaces, skipFace, forEdge) {
|
||||
const result = {
|
||||
side1: [forEdge],
|
||||
side2: [],
|
||||
all: [forEdge]
|
||||
};
|
||||
|
||||
|
||||
for (let face of allFaces) {
|
||||
if (face == skipFace) continue;
|
||||
for (let e of face.edges) {
|
||||
|
|
@ -355,7 +355,7 @@ function markOverlapping(face1, face2) {
|
|||
}
|
||||
|
||||
function mergeOverlappingFaces(shell1, shell2) {
|
||||
const merged = new Set();
|
||||
const merged = new Set();
|
||||
for (let face1 of shell1.faces) {
|
||||
if (merged.has(face1)) continue;
|
||||
const data1 = face1.data[MY];
|
||||
|
|
@ -378,11 +378,11 @@ function mergeOverlappingFaces(shell1, shell2) {
|
|||
|
||||
function doMergeOverlappingFaces(face1, face2, keepNew) {
|
||||
const data2 = face2.data[MY];
|
||||
|
||||
|
||||
let allEdges = [];
|
||||
for (let e of face1.edges) {
|
||||
allEdges.push(e);
|
||||
}
|
||||
}
|
||||
for (let e of face2.edges) {
|
||||
const coi = findCoincidentEdge(e, allEdges);
|
||||
if (coi == null) {
|
||||
|
|
@ -414,7 +414,7 @@ function doMergeOverlappingFaces(face1, face2, keepNew) {
|
|||
nullifyOppositeEdges(allEdges);
|
||||
allEdges = allEdges.filter(e => e != null);
|
||||
sort(allEdges);
|
||||
squash(face1, allEdges);
|
||||
squash(face1, allEdges);
|
||||
data2.merged = true;
|
||||
}
|
||||
|
||||
|
|
@ -476,9 +476,9 @@ function merge(face, newEdges) {
|
|||
allEdges.push(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nullifyOppositeEdges(newEdges);
|
||||
|
||||
|
||||
for (let e of newEdges) {
|
||||
if (e == null) continue;
|
||||
const existingEdge = findCoincidentEdge(e, allEdges);
|
||||
|
|
@ -488,9 +488,9 @@ function merge(face, newEdges) {
|
|||
EdgeSolveData.createIfEmpty(existingEdge).newEdgeFlag = true
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
nullifyOppositeEdges(allEdges);
|
||||
|
||||
|
||||
allEdges = allEdges.filter(e => e != null);
|
||||
//put new edges to the tail
|
||||
bringNewEdgesToTheTail(allEdges);
|
||||
|
|
@ -515,7 +515,7 @@ function nullifyOppositeEdges(edges) {
|
|||
if (i == j) continue;
|
||||
if (edges[j] == null) continue;
|
||||
if (areEdgesOpposite(edges[i], edges[j])) {
|
||||
edges[i] = null;
|
||||
edges[i] = null;
|
||||
edges[j] = null;
|
||||
continue main;
|
||||
}
|
||||
|
|
@ -629,7 +629,7 @@ export function loopsToFaces(originFace, loops, out) {
|
|||
return originSurface;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function createFaces(nestedLoop, surface, level) {
|
||||
if (!nestedLoop.loop.isCCW(surface)) {
|
||||
surface = invertSurface(surface);
|
||||
|
|
@ -651,7 +651,7 @@ export function loopsToFaces(originFace, loops, out) {
|
|||
newFace.innerLoops.push(child.loop);
|
||||
} else {
|
||||
createFaces(child, surface, level + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -706,7 +706,7 @@ function initSolveData(shell, facesData) {
|
|||
for (let he of face.edges) {
|
||||
EdgeSolveData.clear(he);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function cleanUpSolveData(shell) {
|
||||
|
|
@ -736,7 +736,7 @@ function leftTurningMeasure(v1, v2, normal) {
|
|||
measure = -(2 + measure);
|
||||
}
|
||||
measure -= 1;//shift to the zero
|
||||
|
||||
|
||||
//make it positive all the way
|
||||
return -measure;
|
||||
}
|
||||
|
|
@ -762,11 +762,11 @@ function intersectFaces(shell1, shell2, inverseCrossEdgeDirection) {
|
|||
continue;
|
||||
}
|
||||
const curve = face1.surface.intersect(face2.surface);
|
||||
|
||||
|
||||
const nodes = [];
|
||||
collectNodesOfIntersectionOfFace(face2, face1, nodes);
|
||||
collectNodesOfIntersectionOfFace(face1, face2, nodes);
|
||||
|
||||
|
||||
const newEdges = [];
|
||||
const direction = face1.surface.normal.cross(face2.surface.normal);
|
||||
if (inverseCrossEdgeDirection) {
|
||||
|
|
@ -816,7 +816,7 @@ function filterNodes(nodes) {
|
|||
if (node2.vertex == node1.vertex) {
|
||||
if (node1.normal + node2.normal == 0) {
|
||||
nodes[i] = null
|
||||
}
|
||||
}
|
||||
nodes[j] = null
|
||||
}
|
||||
}
|
||||
|
|
@ -885,7 +885,7 @@ function split(nodes, result, onCurve, direction) {
|
|||
const halfEdge1 = new HalfEdge();
|
||||
halfEdge1.vertexA = inNode.vertex;
|
||||
halfEdge1.vertexB = outNode.vertex;
|
||||
|
||||
|
||||
const halfEdge2 = new HalfEdge();
|
||||
halfEdge2.vertexB = halfEdge1.vertexA;
|
||||
halfEdge2.vertexA = halfEdge1.vertexB;
|
||||
|
|
@ -908,7 +908,7 @@ function split(nodes, result, onCurve, direction) {
|
|||
edge.halfEdge2 = halfEdgeSameDir;
|
||||
halfEdgeNegativeDir.edge = edge;
|
||||
halfEdgeSameDir.edge = edge;
|
||||
|
||||
|
||||
//check for corner case when to faces only intersects in edges
|
||||
if (!containsEdges(result, edge)) {
|
||||
result.push(edge);
|
||||
|
|
@ -931,7 +931,7 @@ function isSameEdge(e1, e2) {
|
|||
|
||||
|
||||
function splitEdgeByVertex(originHalfEdge, vertex, splittingFace) {
|
||||
|
||||
|
||||
function splitHalfEdge(h) {
|
||||
const newEdge = new HalfEdge();
|
||||
newEdge.vertexA = vertex;
|
||||
|
|
@ -946,20 +946,20 @@ function splitEdgeByVertex(originHalfEdge, vertex, splittingFace) {
|
|||
if (orig.vertexA == vertex || orig.vertexB == vertex) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
const newOrig = splitHalfEdge(orig);
|
||||
const newTwin = splitHalfEdge(twin);
|
||||
|
||||
|
||||
BREPBuilder.linkHalfEdges(orig.edge, orig, newTwin);
|
||||
BREPBuilder.linkHalfEdges(new Edge(orig.edge.curve), twin, newOrig);
|
||||
|
||||
|
||||
orig.loop.halfEdges.splice(orig.loop.halfEdges.indexOf(orig) + 1, 0, newOrig);
|
||||
twin.loop.halfEdges.splice(twin.loop.halfEdges.indexOf(twin) + 1, 0, newTwin);
|
||||
|
||||
newOrig.loop = orig.loop;
|
||||
newTwin.loop = twin.loop;
|
||||
|
||||
|
||||
EdgeSolveData.transfer(orig, newOrig);
|
||||
EdgeSolveData.transfer(twin, newTwin);
|
||||
|
||||
|
|
@ -1009,7 +1009,7 @@ function intersectFaceWithEdge(face, edge, result) {
|
|||
const ab = edge.vertexB.point.minus(p0);
|
||||
const length = ab.length();
|
||||
const v = ab._multiply(1 / length);
|
||||
|
||||
|
||||
if (math.areEqual(edge.edge.curve.v.dot(face.surface.normal), 0, TOLERANCE)) {
|
||||
if (math.areEqual(face.surface.normal.dot(edge.vertexA.point), face.surface.w, TOLERANCE)) {
|
||||
classifyAndAdd(edge.vertexA.point, true, false);
|
||||
|
|
|
|||
Loading…
Reference in a new issue