jsketcher/web/app/brep/brep-builder.js

144 lines
No EOL
3.9 KiB
JavaScript

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 '../cad/cad-utils';
import BBox from '../math/bbox';
import NurbsSurface from './geom/surfaces/nurbsSurface';
import {BrepSurface} from './geom/surfaces/brepSurface';
import EdgeIndex from './edgeIndex';
export default class BrepBuilder {
constructor(edgeStra) {
this._shell = new Shell();
this._face = null;
this._loop = null;
this.edgeIndex = new EdgeIndex();
}
get lastHalfEdge() {
return this._loop.halfEdges[this._loop.halfEdges.length - 1];
}
face(surface) {
this._face = new Face(surface ? surface : null);
this._shell.faces.push(this._face);
this._loop = null;
return this;
}
loop(vertices) {
if (this._loop === null) {
this._loop = this._face.outerLoop;
} else {
this._loop = new Loop();
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 = () => {
let u1 = curve.param(a.point);
curve = curve.splitByParam(u1)[1];
let u2 = curve.param(b.point);
curve = curve.splitByParam(u2)[0];
};
this.edge(a, b, curveCreate);
return this;
}
edge(a, b, curveCreate, invertedToCurve, tag) {
let he = this.edgeIndex.getHalfEdgeOrCreate(a, b, curveCreate, invertedToCurve, tag);
this._loop.halfEdges.push(he);
return this;
}
vertex(x, y, z) {
return new Vertex(new Point(x, y, z));
}
build() {
for (let face of this._shell.faces) {
for (let loop of face.loops) {
loop.link();
}
if (face.surface === null) {
face.surface = createBoundingSurface(face.outerLoop.tess());
}
}
for (let face of this._shell.faces) {
for (let he of face.edges) {
let 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, plane) {
if (!plane) {
const normal = normalOfCCWSeq(points);
const w = points[0].dot(normal);
plane = new Plane(normal, w);
}
let to2D = plane.get2DTransformation();
let points2d = points.map(p => to2D.apply(p));
return createBoundingSurfaceFrom2DPoints(points2d, plane);
}
export function createBoundingSurfaceFrom2DPoints(points2d, plane, minWidth, minHeight, offset = 0) {
let 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, plane) {
let to3D = plane.get3DTransformation();
let polygon = bBox.toPolygon();
polygon = polygon.map(p => to3D._apply(p).data());
let 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);
}