BREP validator

This commit is contained in:
Val Erastov 2017-01-12 00:40:56 -08:00
parent 15300e225a
commit 28d341735a
4 changed files with 160 additions and 6 deletions

View file

@ -18,6 +18,7 @@ import '../../css/app3d.less'
import * as BREPPrimitives from '../brep/brep-primitives'
import * as BREPBool from '../brep/operations/boolean'
import {BREPValidator} from '../brep/brep-validator'
import {SceneSolid} from '../brep/viz/scene-solid'
function App() {
@ -82,6 +83,8 @@ App.prototype.BREPTestImpl = function() {
const box1 = BREPPrimitives.box(500, 500, 500);
const box2 = BREPPrimitives.box(500, 500, 500, new Matrix3().translate(250, 250, 250));
BREPValidator.validateToConsole(box1);
//box1.faces = [box1.faces[2]];
//box2.faces = [box2.faces[5]];

View file

@ -17,18 +17,20 @@ export function createPrism(basePoints, height) {
const lidNormal = normal.multiply(-1);
const offVector = lidNormal.multiply(height);
const lidSegments = [];
iterateSegments(basePoints.map(p => p.plus(offVector)), (a, b) => lidSegments.push({a, b}));
const lidLoop = new Loop();
//iterateSegments(basePoints.map(p => new Vertex(p.plus(offVector))), (a, b) => lidSegments.push({a, b}));
const lidPoints = basePoints.map(p => p.plus(offVector)).reverse();
const lidLoop = createPlaneLoop(lidPoints.map(p => new Vertex(p)));
const shell = new Shell();
const n = baseLoop.halfEdges.length;
for (let i = 0; i < n; i++) {
let lidIdx = n - 2 - i;
if (lidIdx == -1) {
lidIdx = n - 1;
}
const baseHalfEdge = baseLoop.halfEdges[i];
const lidSegment = lidSegments[i];
const lidHalfEdge = createHalfEdge(lidLoop, new Vertex(lidSegment.b), new Vertex(lidSegment.a));
const lidHalfEdge = lidLoop.halfEdges[lidIdx];
const wallPolygon = [baseHalfEdge.vertexB, baseHalfEdge.vertexA, lidHalfEdge.vertexB, lidHalfEdge.vertexA];
const wallLoop = createPlaneLoop(wallPolygon);

View file

@ -0,0 +1,146 @@
import Vector from '../math/vector'
import * as math from '../math/math'
export class BREPValidator {
constructor() {
this.errors = [];
}
validateShell(shell) {
for (let face of shell.faces) {
this.validateFace(face);
}
}
validateFace(face) {
if (face !== face.outerLoop.face) {
this.addError(new LoopRefersToWrongFace(face.outerLoop, face));
}
this.validateLoop(face.outerLoop);
}
validateLoop(loop) {
const halfEdges = loop.halfEdges;
const n = halfEdges.length;
if (n == 0) {
return;
}
for (let i = 0; i < n; i ++) {
const j = (i + 1) % n;
const curr = halfEdges[i];
const next = halfEdges[j];
if (curr.loop !== loop) {
this.addError(new HalfEdgeRefersToWrongLoop(loop, curr));
}
if (curr.vertexB !== next.vertexA) {
this.addError(new VerticesOfHalfEdgeArentConnected(curr, next));
}
if (curr.next != next) {
this.addError(new HalfEdgeNextPointerIncorrect(curr, next));
}
if (next.prev != curr) {
this.addError(new HalfEdgePrevPointerIncorrect(next, curr));
}
const twin = curr.twin();
if (twin.vertexB != curr.vertexA) {
this.addError(new TwinStartVertexIncorrect(curr, twin));
}
if (twin.vertexA != curr.vertexB) {
this.addError(new TwinEndVertexIncorrect(curr, twin));
}
}
}
addError(validationError) {
this.errors.push(validationError);
}
}
BREPValidator.validateToConsole = function(shell) {
const brepValidator = new BREPValidator();
brepValidator.validateShell(shell);
for (let brepError of brepValidator.errors) {
console.log(brepError.message());
}
};
class VerticesOfHalfEdgeArentConnected {
constructor(loop, halfEdge1, halfEdge2) {
this.loop = loop;
this.halfEdge1 = halfEdge1;
this.halfEdge2 = halfEdge2;
}
message() {
return 'starting point of the following half edge should identically the same as ending of a half edge';
}
}
class HalfEdgeRefersToWrongLoop {
constructor(loop, face) {
this.loop = loop;
this.face = face;
}
message() {
return 'half edge refers to different loop it belongs to';
}
}
class LoopRefersToWrongFace {
constructor(loop, halfEdge) {
this.loop = loop;
this.halfEdge = halfEdge;
}
message() {
return 'loop refers to different face it belongs to';
}
}
class HalfEdgeNextPointerIncorrect {
constructor(halfEdge, nextHalfEdge) {
this.halfEdge = halfEdge;
this.nextHalfEdge = nextHalfEdge;
}
message() {
return "half edge's next pointer doesn't refer to real next half edge";
}
}
class HalfEdgePrevPointerIncorrect {
constructor(halfEdge, prevHalfEdge) {
this.halfEdge = halfEdge;
this.prevHalfEdge = prevHalfEdge;
}
message() {
return "half edge's prev pointer doesn't refer to prior half edge";
}
}
class TwinStartVertexIncorrect {
constructor(halfEdge, twin) {
this.halfEdge = halfEdge;
this.twin = twin;
}
message() {
return "a twin has incorrect start vertex, should be identical to the end vertex of the half edge";
}
}
class TwinEndVertexIncorrect {
constructor(halfEdge, twin) {
this.halfEdge = halfEdge;
this.twin = twin;
}
message() {
return "a twin has incorrect end vertex, should be identical to the start vertex of the half edge";
}
}

View file

@ -30,6 +30,9 @@ export function union( shell1, shell2 ) {
//if (shell2.faces.indexOf(face) != -1) {
// continue;
//}
if (face.debugName == 'lid') {
__DEBUG__.Clear();
}
const edges = face.outerLoop.halfEdges.concat(faceData.newEdges);
//edges.forEach(e => __DEBUG__.AddLine(e.vertexA.point, e.vertexB.point));
while (true) {