mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-06 08:25:19 +01:00
151 lines
No EOL
4.3 KiB
TypeScript
151 lines
No EOL
4.3 KiB
TypeScript
import {Plane} from 'geom/impl/plane';
|
|
import {Point} from 'geom/point';
|
|
import {Shell} from './topo/shell';
|
|
import {Face} from './topo/face';
|
|
import {Loop} from './topo/loop';
|
|
import {Vertex} from './topo/vertex';
|
|
import {normalOfCCWSeq} from '../../web/app/cad/cad-utils';
|
|
import BBox from 'math/bbox';
|
|
import NurbsSurface from 'geom/surfaces/nurbsSurface';
|
|
import {BrepSurface} from 'geom/surfaces/brepSurface';
|
|
import EdgeIndex from './edgeIndex';
|
|
import {HalfEdge} from "brep/topo/edge";
|
|
import Vector from "math/vector";
|
|
|
|
export default class BrepBuilder {
|
|
_shell: Shell;
|
|
_face: Face;
|
|
_loop: Loop;
|
|
edgeIndex: EdgeIndex;
|
|
|
|
constructor() {
|
|
this._shell = new Shell();
|
|
this._face = null;
|
|
this._loop = null;
|
|
this.edgeIndex = new EdgeIndex();
|
|
}
|
|
|
|
get lastHalfEdge(): HalfEdge {
|
|
return this._loop.halfEdges[this._loop.halfEdges.length - 1];
|
|
}
|
|
|
|
face(surface?: BrepSurface): BrepBuilder {
|
|
this._face = new Face(surface ? surface : null);
|
|
this._shell.faces.push(this._face);
|
|
this._loop = null;
|
|
return this;
|
|
}
|
|
|
|
loop(vertices?: Vertex[]): BrepBuilder {
|
|
if (this._loop === null) {
|
|
this._loop = this._face.outerLoop;
|
|
} else {
|
|
this._loop = new Loop(null);
|
|
this._face.innerLoops.push(this._loop);
|
|
}
|
|
this._loop.face = this._face;
|
|
if (vertices) {
|
|
for (let i = 0; i < vertices.length; ++i) {
|
|
this.edge(vertices[i], vertices[(i + 1) % vertices.length]);
|
|
}
|
|
}
|
|
return this;
|
|
}
|
|
|
|
edgeTrim(a, b, curve) {
|
|
const curveCreate = () => {
|
|
const u1 = curve.param(a.point);
|
|
curve = curve.splitByParam(u1)[1];
|
|
const u2 = curve.param(b.point);
|
|
curve = curve.splitByParam(u2)[0];
|
|
};
|
|
this.edge(a, b, curveCreate);
|
|
return this;
|
|
}
|
|
|
|
edge(a, b, curveCreate?, invertedToCurve?, tag?): BrepBuilder {
|
|
const he = this.edgeIndex.getHalfEdgeOrCreate(a, b, curveCreate, invertedToCurve, tag);
|
|
this._loop.halfEdges.push(he);
|
|
return this;
|
|
}
|
|
|
|
vertex(x: number, y: number, z: number): Vertex {
|
|
return new Vertex(new Point(x, y, z));
|
|
}
|
|
|
|
build(): Shell {
|
|
for (const face of this._shell.faces) {
|
|
face.shell = this._shell;
|
|
for (const loop of face.loops) {
|
|
loop.link();
|
|
}
|
|
if (face.surface === null) {
|
|
face.surface = createBoundingSurface(face.outerLoop.tess());
|
|
}
|
|
}
|
|
for (const face of this._shell.faces) {
|
|
for (const he of face.edges) {
|
|
const twin = he.twin();
|
|
if (twin.loop === null) {
|
|
const nullFace = new Face(face.surface);
|
|
nullFace.outerLoop.halfEdges.push(twin);
|
|
nullFace.outerLoop.link();
|
|
}
|
|
}
|
|
}
|
|
return this._shell;
|
|
}
|
|
}
|
|
|
|
export function createBoundingSurface(points: Vector[], plane?: Plane): BrepSurface {
|
|
if (!plane) {
|
|
const normal = normalOfCCWSeq(points);
|
|
const w = points[0].dot(normal);
|
|
plane = new Plane(normal, w);
|
|
}
|
|
const to2D = plane.get2DTransformation();
|
|
const points2d = points.map(p => to2D.apply(p));
|
|
|
|
return createBoundingSurfaceFrom2DPoints(points2d, plane);
|
|
}
|
|
|
|
export function createBoundingSurfaceFrom2DPoints(points2d: Vector[], plane: Plane, minWidth?: number, minHeight?: number, offset = 0): BrepSurface {
|
|
const bBox = new BBox();
|
|
points2d.forEach(p => bBox.checkPoint(p));
|
|
|
|
if (minWidth && bBox.width() < minWidth) {
|
|
bBox.checkBounds( minWidth * 0.5, 0);
|
|
bBox.checkBounds(- minWidth * 0.5, 0);
|
|
}
|
|
if (minHeight && bBox.height() < minHeight) {
|
|
bBox.checkBounds(0, minHeight * 0.5);
|
|
bBox.checkBounds(0, - minHeight * 0.5);
|
|
}
|
|
|
|
if (offset !== 0) {
|
|
bBox.maxX += offset * 0.5;
|
|
bBox.minX -= offset * 0.5;
|
|
bBox.maxY += offset * 0.5;
|
|
bBox.minY -= offset * 0.5;
|
|
}
|
|
|
|
return createBoundingSurfaceFromBBox(bBox, plane);
|
|
}
|
|
|
|
export function createBoundingSurfaceFromBBox(bBox: BBox, plane: Plane): BrepSurface {
|
|
const to3D = plane.get3DTransformation();
|
|
let polygon = bBox.toPolygon() as Vector[];
|
|
polygon = polygon.map(p => to3D._apply(p).data());
|
|
|
|
const planeNurbs = verb.geom.NurbsSurface.byKnotsControlPointsWeights( 1, 1, [0,0,1,1], [0,0,1,1],
|
|
[ [ polygon[3], polygon[2]] ,
|
|
[ polygon[0], polygon[1] ] ] );
|
|
|
|
const nurbs = new NurbsSurface(planeNurbs);
|
|
|
|
// __DEBUG__.AddNurbs(nurbs);
|
|
// __DEBUG__.AddSurfaceNormal(nurbs);
|
|
|
|
return new BrepSurface(nurbs);
|
|
|
|
} |