mirror of
https://github.com/xibyte/jsketcher
synced 2025-12-20 23:43:27 +01:00
BREP serialization from Shell
This commit is contained in:
parent
157f61c925
commit
e01621bf67
11 changed files with 245 additions and 104 deletions
|
|
@ -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 = [];
|
||||
|
|
|
|||
|
|
@ -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[];
|
||||
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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[];
|
||||
|
|
|
|||
|
|
@ -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[][]
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,7 @@ import {Vec3} from "math/vec";
|
|||
|
||||
export default class BrepCurve {
|
||||
|
||||
impl: any;
|
||||
impl: NurbsCurve;
|
||||
|
||||
uMin: number;
|
||||
uMax: number;
|
||||
|
|
|
|||
|
|
@ -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()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
}
|
||||
});
|
||||
|
|
|
|||
Loading…
Reference in a new issue