BREP serialization from Shell

This commit is contained in:
Val Erastov (xibyte) 2020-10-05 01:27:26 -07:00
parent 157f61c925
commit e01621bf67
11 changed files with 245 additions and 104 deletions

View file

@ -10,10 +10,14 @@ import NullSurface from 'geom/surfaces/nullSurface';
import BBox from 'math/bbox';
import NurbsCurve from 'geom/curves/nurbsCurve';
import BrepCurve from 'geom/curves/brepCurve';
import {BrepOutputData, EdgeData, FaceData} from "engine/data/brepOutputData";
import {BrepOutputData} from "engine/data/brepOutputData";
import {ProductionInfo} from "engine/productionInfo";
import {Tessellation1D} from "engine/tessellation";
import {Shell} from "brep/topo/shell";
import {BrepInputData} from "engine/data/brepInputData";
import {Vertex} from "brep/topo/vertex";
import {Edge} from "brep/topo/edge";
import {ParametricSurface} from "geom/surfaces/parametricSurface";
//Extensions for topo objects
declare module '../topo/shell' {
@ -63,6 +67,7 @@ export function readBrep(data: BrepOutputData) {
for (let faceData of data.faces) {
bb.face();
// @ts-ignore
let nonDirect = faceData.surface.direct === false; // left handed coordinate system for planes
let inverted = faceData.inverted !== nonDirect;
bb._face.data.tessellation = {
@ -143,81 +148,86 @@ function readCurve(curve) {
}
// export function writeBrep(shell: Shell): BrepOutputData {
//
// const brepData: BrepOutputData = {
// faces: []
// };
//
// for (let f of shell.faces) {
// const faceData: FaceData = {
// surface: writeSurface(f.surface),
// inverted: f.surface.inverted,
// loops: []
// };
//
// brepData.faces.push(faceData);
//
// for (let l of f.loops) {
// const loop = [];
// faceData.loops.push(loop);
//
//
//
// for (let he of l.halfEdges) {
// const vs = [he.vertexA, he.vertexB];
// if (he.inverted) {
// vs.reverse();
// }
// const [a, b] = vs;
// const curve = he.edge.curve;
// const edgeData: EdgeData = {
// a: a.point.toArray(),
// b: b.point.toArray(),
//
// inverted: he.inverted,
// curveBounds: curve.domain,
//
// curve: writeCurve(curve)
//
// };
// loop.push(edgeData);
// }
//
// }
// }
// return brepData;
// }
//
//
// function writeSurface(surface: BrepSurface) {
// const impl = surface.impl;
// if (impl instanceof NurbsSurface) {
// const {
// degreeU,
// degreeV,
// controlPoints,
// knotsU,
// knotsV,
// weights
// } = impl.data;
// return {
//
// TYPE: "B-SPLINE",
//
// direct: surface.mirrored,
//
// degU: degreeU,
// degV: degreeV,
// knotsU: number[],
// knotsV: number[],
// weights: number[][],
// cp: controlPoints
// }
// } else {
// throw 'only nurbs';
// }
// }
export function writeBrep(shell: Shell): BrepInputData {
const brepData: BrepInputData = {
vertices: {},
curves: {},
surfaces: {},
edges: {},
faces: []
};
const surfaces = new Map<ParametricSurface, string>();
const curves = new Map<BrepCurve, string>();
const verts = new Map<Vertex, string>();
const edges = new Map<Edge, string>();
let vid = 0;
for (let v of shell.vertices) {
const id = 'v' + (vid++);
brepData.vertices[id] = v.point.data();
verts.set(v, id);
}
let cid = 0;
for (let e of shell.edges) {
e.curve.impl.asCurveBSplineData()
let curveId = curves.get(e.curve);
if (!curveId) {
curveId = 'c' + (cid++);
brepData.curves[curveId] = e.curve.impl.asCurveBSplineData();
curves.set(e.curve, curveId);
}
const a = verts.get(e.halfEdge1.vertexA);
const b = verts.get(e.halfEdge1.vertexB);
const edgeId = a + '_' + b;
brepData.edges[edgeId] = {
a, b,
curve: curveId
}
edges.set(e, edgeId);
}
let sid = 0;
for (let face of shell.faces) {
let surfaceId = surfaces.get(face.surface.impl);
if (!surfaceId) {
surfaceId = 's' + (sid++);
brepData.surfaces[surfaceId] = {
... (face.surface.impl as NurbsSurface).asSurfaceBSplineData()
}
//direct needed only for planes
//direct: face.surface.mirrored ? false : undefined
surfaces.set(face.surface.impl, surfaceId);
}
}
for (let face of shell.faces) {
const loops = [];
for (let loop of face.loops) {
loops.push(loop.halfEdges.map(he => edges.get(he.edge)));
}
brepData.faces.push({
surface: surfaces.get(face.surface.impl),
inverted: face.surface.inverted,
loops
})
}
return brepData;
}
export function normalizetessellationData(tessellation, inverted, surfaceNormal) {
let tess = [];

View file

@ -1,7 +1,19 @@
import {SurfaceData} from "./surfaceData";
import {CurveData} from "./curveData";
import {Vec3} from "math/vec";
import {SurfaceType} from "engine/data/brepOutputData";
export interface BrepInputFaceData {
surface?: string;
loops: string[][];
inverted?: boolean;
}
export interface BrepInputEdgeData {
a: string;
b: string;
curve?: string;
}
export interface BrepInputData {
@ -14,22 +26,14 @@ export interface BrepInputData {
},
surfaces?: {
[id: string]: SurfaceData;
[id: string]: SurfaceType;
};
edges: {
[id: string]: {
a: string;
b: string;
curve?: string;
inverted?: boolean;
};
[id: string]: BrepInputEdgeData;
};
faces: {
surface?: string;
loops: string[][];
}[];
faces: BrepInputFaceData[];
}

View file

@ -15,13 +15,15 @@ export interface BrepOutputData {
}
export type SurfaceType = SurfacePlaneData | SurfaceBSplineData | SurfaceUnknownData;
export interface FaceData {
ref: number;
ptr: Handle;
surface: SurfacePlaneData | SurfaceBSplineData | SurfaceUnknownData;
surface: SurfaceType;
inverted: boolean;
tess?: Tessellation2D<Vec3>;
productionInfo: ProductionInfo;

View file

@ -9,7 +9,12 @@ export interface CurveData {
export interface CurveBSplineData extends CurveData {
TYPE: "B-SPLINE";
deg: number;
degree?: number;
//backward compat
deg?: number;
knots: number[];
weights: number[];
cp: Vec3[];

View file

@ -3,9 +3,6 @@ import {Vec3} from "math/vec";
export interface SurfaceData {
TYPE: string;
direct: boolean;
}
export interface SurfacePlaneData extends SurfaceData {
@ -16,17 +13,23 @@ export interface SurfacePlaneData extends SurfaceData {
origin: Vec3;
direct?: boolean;
}
export interface SurfaceBSplineData extends SurfaceData {
TYPE: "B-SPLINE",
TYPE: "B-SPLINE"
degU: number
degV: number
knotsU: number[],
knotsV: number[],
weights: number[][],
degreeU?: number
degreeV?: number
//backward compat
degU?: number
degV?: number
knotsU: number[]
knotsV: number[]
weights: number[][]
cp: Vec3[][]
}

View file

@ -13,7 +13,7 @@ import {Vec3} from "math/vec";
export default class BrepCurve {
impl: any;
impl: NurbsCurve;
uMin: number;
uMax: number;

View file

@ -4,6 +4,7 @@ import {ParametricCurve} from "./parametricCurve";
import {Matrix3x4Data} from "math/matrix";
import {Vec3} from "math/vec";
import {NurbsCurveData} from "geom/curves/nurbsCurveData";
import {CurveBSplineData} from "engine/data/curveData";
//in fact the sketcher format
@ -98,4 +99,14 @@ export default class NurbsCurve implements ParametricCurve {
weights: this.verb.weights()
}
}
asCurveBSplineData(): CurveBSplineData {
return {
TYPE: "B-SPLINE",
degree: this.verb.degree(),
knots: this.verb.knots(),
cp: this.verb.controlPoints(),
weights: this.verb.weights()
}
}
}

View file

@ -7,6 +7,7 @@ import {ParametricCurve} from "../curves/parametricCurve";
import {Matrix3x4Data} from "math/matrix";
import {Vec3} from "math/vec";
import {NurbsSurfaceData} from "geom/surfaces/nurbsSurfaceData";
import {SurfaceBSplineData} from "engine/data/surfaceData";
export default class NurbsSurface implements ParametricSurface {
@ -84,6 +85,17 @@ export default class NurbsSurface implements ParametricSurface {
throw 'unimplemented';
}
asSurfaceBSplineData(): SurfaceBSplineData {
return {
TYPE: "B-SPLINE",
degreeU: this.verb.degreeU(),
degreeV: this.verb.degreeV(),
knotsU: this.verb.knotsU(),
knotsV: this.verb.knotsV(),
weights: this.verb.weights(),
cp: this.verb.controlPoints()
}
}
}
const surTess = verb.eval.Tess.rationalSurfaceAdaptive;

View file

@ -10,6 +10,7 @@ import {toLoops} from 'brep/io/brepLoopsFormat';
import curveTess from 'geom/impl/curve/curve-tess';
import {LOG_FLAGS} from './logFlags';
import {state} from "lstream";
import {BufferGeometry, BufferAttribute, Float32BufferAttribute, Int32BufferAttribute} from 'three';
const BREP_DEBUG_WINDOW_VISIBLE$ = state(false);
@ -194,7 +195,7 @@ function addGlobalDebugActions({viewer, cadScene, cadRegistry}) {
for (let i = 0; i < triangles.length; ++i) {
let off = geometry.vertices.length;
let tr = triangles[i], normales;
if (Array.isArray(tr)) {
if (Array.isArray(tr[0][0])) {
normales = tr[1];
tr = tr[0];
if (normales.find(n => n[0] === null || n[1] === null || n[2] === null)) {
@ -215,6 +216,39 @@ function addGlobalDebugActions({viewer, cadScene, cadRegistry}) {
debugVolumeGroup.add(mesh);
viewer.render();
},
AddFacesTessellation: (faces) => {
const dump = [];
faces.forEach(face => {
for (let i = 0; i < face.indices.length; i += 3) {
const a = (face.indices[i + 0] - 1) * 3;
const b = (face.indices[i + 1] - 1) * 3;
const c = (face.indices[i + 2] - 1) * 3;
dump.push([
[
face.positions[a + 0],
face.positions[a + 1],
face.positions[a + 2]
],
[
face.positions[b + 0],
face.positions[b + 1],
face.positions[b + 2]
],
[
face.positions[c + 0],
face.positions[c + 1],
face.positions[c + 2]
],
]);
}
})
__DEBUG__.AddTessDump(dump);
viewer.render();
},
HideSolids: () => {
cadRegistry.getAllShells().forEach(s => s.ext.view.mesh.traverse(o => o.visible = false));
viewer.render();

View file

@ -5,6 +5,8 @@ import {MVertex} from './mvertex';
import CSys from 'math/csys';
import {state, StateStream} from "lstream";
import {Matrix3x4} from "math/matrix";
import {Shell} from "brep/topo/shell";
import {TopoObject} from "brep/topo/topo-object";
export class MShell extends MObject {
@ -41,9 +43,9 @@ export class MShell extends MObject {
export class MBrepShell extends MShell {
brepShell: any;
brepShell: Shell;
csys: CSys;
brepRegistry: Map<string, MObject>;
brepRegistry: Map<TopoObject, MObject>;
constructor(shell, csys) {
super();

View file

@ -12,6 +12,9 @@ import {Vec3} from "math/vec";
import {ApplicationContext} from "context";
import {readShellEntityFromJson} from "./scene/wrappers/entityIO";
import {DEG_RAD} from "math/commons";
import {DEFLECTION, E0_TOLERANCE} from "./craft/e0/common";
import {readBrep, writeBrep} from "brep/io/brepIO";
import {PRIMITIVE_TYPES} from "engine/data/primitiveData";
export function runSandbox(ctx: ApplicationContext) {
@ -325,10 +328,65 @@ export function runSandbox(ctx: ApplicationContext) {
const mBrepShell = readShellEntityFromJson(data);
services.exposure.addOnScene(mBrepShell);
const serialized = writeBrep(mBrepShell.brepShell);
console.log(serialized);
let fromSerialization = ctx.craftEngine.modellingEngine.loadModel(serialized);
const mBrepShell2 = readShellEntityFromJson(data);
services.exposure.addOnScene(mBrepShell2);
}
function testTess() {
let direction = [0, 0, 100];
let sketch = [[
{
TYPE: PRIMITIVE_TYPES.SEGMENT,
a: [0, 0, 0],
b: [100, 0, 0],
},
{
TYPE: PRIMITIVE_TYPES.SEGMENT,
a: [100, 0, 0],
b: [100, 100, 0],
},
{
TYPE: PRIMITIVE_TYPES.SEGMENT,
a: [100, 100, 0],
b: [0, 100, 0],
},
{
TYPE: PRIMITIVE_TYPES.SEGMENT,
a: [0, 100, 0],
b: [0, 0, 0],
},
]]
let data = ctx.craftEngine.modellingEngine.extrude({
vector: direction,
sketch: sketch,
tolerance: E0_TOLERANCE,
deflection: DEFLECTION
})
let brep = readBrep(data);
let tess = ctx.craftEngine.modellingEngine.tessellate({
model: data.ptr,
deflection: DEFLECTION
})
__DEBUG__.AddFacesTessellation(tess.faces)
console.dir(tess.faces)
// const mBrepShell = readShellEntityFromJson(data);
// services.exposure.addOnScene(mBrepShell);
}
// cylinderAndPlaneIntersect();
// curvesIntersect();
@ -347,7 +405,7 @@ export function runSandbox(ctx: ApplicationContext) {
// window.voxelTest = voxelTest;
ctx.streams.lifecycle.projectLoaded.attach(ready => {
if (ready) {
testLoadBrep()
testLoadBrep();
}
});