From 34c1df0bb70c3661c8598d8f554ac7276b54bb3f Mon Sep 17 00:00:00 2001 From: Val Erastov Date: Mon, 25 Dec 2017 16:55:24 -0700 Subject: [PATCH] unit tests for enclosures --- web/app/3d/tpi.js | 6 +- web/app/brep/operations/boolean.js | 27 +++--- web/app/brep/topo/face.js | 12 +-- web/test/cases/brep-enclose.js | 138 +++++++++++++++++++++++++++++ web/test/suites.js | 3 +- 5 files changed, 166 insertions(+), 20 deletions(-) create mode 100644 web/test/cases/brep-enclose.js diff --git a/web/app/3d/tpi.js b/web/app/3d/tpi.js index e2f54e98..94ee4671 100644 --- a/web/app/3d/tpi.js +++ b/web/app/3d/tpi.js @@ -1,5 +1,5 @@ import * as BREPPrimitives from '../brep/brep-primitives' -import BrepBuilder from '../brep/brep-builder' +import BrepBuilder, {createBoundingNurbs} from '../brep/brep-builder' import {createPrism} from '../brep/brep-enclose' import * as BREPBool from '../brep/operations/boolean' import * as IO from '../brep/brep-io' @@ -10,7 +10,7 @@ import {Face} from '../brep/topo/face'; import {Shell} from '../brep/topo/shell'; import {Vertex} from '../brep/topo/vertex'; import {Point} from '../brep/geom/point'; -import {NurbsCurve} from '../brep/geom/impl/nurbs'; +import {NurbsCurve, NurbsSurface} from '../brep/geom/impl/nurbs'; import {Plane} from '../brep/geom/impl/plane'; import pip from "./tess/pip"; @@ -23,7 +23,7 @@ export default { pip, validator: BREPValidator, geom: { - Point, NurbsCurve, Plane + Point, NurbsCurve, Plane, NurbsSurface, createBoundingNurbs }, topo: { HalfEdge, Edge, Loop, Face, Shell, Vertex diff --git a/web/app/brep/operations/boolean.js b/web/app/brep/operations/boolean.js index 4437c4e8..17c4011f 100644 --- a/web/app/brep/operations/boolean.js +++ b/web/app/brep/operations/boolean.js @@ -1028,18 +1028,23 @@ export function isCurveEntersEnclose(curve, a, b, checkCoincidence) { let inVec = a.tangentAtEnd(); let outVec = b.tangentAtStart(); - if (checkCoincidence) { - if (veq(outVec, testee)) { - return true; - } else if (veqNeg(outVec, testee)) { - return false; - } else if (veq(inVec, testee)) { - return false; - } else if (veqNeg(inVec, testee)) { - return true; - } + let coiIn = veqNeg(inVec, testee); + let coiOut = veq(outVec, testee); + + if (coiIn && coiOut) { + return undefined; } - return isInsideEnclose(normal, testee, inVec, outVec); + + let negated = coiIn || coiOut; + if (negated) { + testee = testee.negate(); + } + + let insideEnclose = isInsideEnclose(normal, testee, inVec, outVec); + if (negated) { + insideEnclose = !insideEnclose; + } + return insideEnclose; } export function isCurveEntersEdgeAtPoint(curve, edge, point) { diff --git a/web/app/brep/topo/face.js b/web/app/brep/topo/face.js index 0028ec64..00acd424 100644 --- a/web/app/brep/topo/face.js +++ b/web/app/brep/topo/face.js @@ -86,11 +86,13 @@ export class Face extends TopoObject { let dist = pt.distanceToSquared(v.point); if (result === null || dist < result.dist) { let inside = !isCurveEntersEnclose(ray, a, b, true); - result = { - dist, - inside, - strictInside: inside, - }; + if (inside !== undefined) { + result = { + dist, + inside, + strictInside: inside, + }; + } } } } diff --git a/web/test/cases/brep-enclose.js b/web/test/cases/brep-enclose.js new file mode 100644 index 00000000..2601f72e --- /dev/null +++ b/web/test/cases/brep-enclose.js @@ -0,0 +1,138 @@ +import * as test from '../test' + +export default { + + + /** + * *--> o<-------o + * | + * | + * |/ + * o + */ + testEncloseClassificationCoiInNeg: function (env) { + test.modeller(env.test((win, app) => { + doTest(env, win, app, [100, 100], [10, 100], [10, 10], [-100, 100], [100, 100], true); + })); + }, + + /** + * <--- o<-------o + * | + * | + * |/ + * o + */ + testEncloseClassificationCoiInPos: function (env) { + test.modeller(env.test((win, app) => { + doTest(env, win, app, [100, 100], [10, 100], [10, 10], [100, 100], [-100, 100], false); + })); + }, + + /** + * ^ + * | + * o<-------o + * | + * | + * |/ + * o + */ + testEncloseClassificationCoiOutNeg: function (env) { + test.modeller(env.test((win, app) => { + doTest(env, win, app, [100, 100], [10, 100], [10, 10], [10, 0], [10, 200], false); + })); + }, + + /** + * | + * \/ + * o<-------o + * | + * | + * |/ + * o + */ + testEncloseClassificationCoiOutPos: function (env) { + test.modeller(env.test((win, app) => { + doTest(env, win, app, [100, 100], [10, 100], [10, 10], [10, 200], [10, 0], true); + })); + }, + + /** * + * \ + * \ + * o<-------o + * | + * | + * |/ + * o + */ + testEncloseClassificationEntersAngle: function (env) { + test.modeller(env.test((win, app) => { + doTest(env, win, app, [100, 100], [10, 100], [10, 10], [0, 110], [1000, -890], true); + })); + }, + + /** + * \ + * \ + * o<-------o + * |\ + * | \ + * |/ * + * o + */ + testEncloseClassificationLeavesAngle: function (env) { + test.modeller(env.test((win, app) => { + doTest(env, win, app, [100, 100], [10, 100], [10, 10], [1000, -890], [0, 110], false); + })); + }, + +} + +function doTest(env, win, app, encA, encB, encC, curveA, curveB, expected) { + let [a, b] = createEnclosure(app.TPI, encA, encB, encC); + let curve = createCurve(app.TPI, curveA, curveB); + + let result = app.TPI.brep.bool.isCurveEntersEnclose(curve, a, b); + + draw(win, curve, a, b, result); + env.assertTrue(result === expected); + env.done(); +} + +function draw(win, curve, a, b, result) { + win.__DEBUG__.AddCurve(curve, result ? 0x00ff00 : 0xff0000); + win.__DEBUG__.AddHalfEdge(a); + win.__DEBUG__.AddHalfEdge(b); +} + +function createEnclosure(tpi, a, b, c) { + + a = new tpi.brep.topo.Vertex(pt(tpi, a)); + b = new tpi.brep.topo.Vertex(pt(tpi, b)); + c = new tpi.brep.topo.Vertex(pt(tpi, c)); + + let e1 = createEdge(tpi, a, b); + let e2 = createEdge(tpi, b, c); + + let loop = new tpi.brep.topo.Loop(); + loop.halfEdges.push(e1, e2); + loop.link(); + let face = new tpi.brep.topo.Face(new tpi.brep.geom.createBoundingNurbs([ + a.point, b.point, c.point + ])); + loop.face = face; + return [e1, e2]; +} + +function createEdge(tpi, a, b) { + return new tpi.brep.topo.Edge(tpi.brep.geom.NurbsCurve.createLinearNurbs(a.point, b.point), a, b).halfEdge1; +} + +function createCurve(tpi, a, b) { + return tpi.brep.geom.NurbsCurve.createLinearNurbs(pt(tpi,a), pt(tpi,b)); +} + +const pt = (tpi, arr) => new tpi.brep.geom.Point().set3(arr); diff --git a/web/test/suites.js b/web/test/suites.js index 99967f92..1663f270 100644 --- a/web/test/suites.js +++ b/web/test/suites.js @@ -26,7 +26,8 @@ export default { BREP: [ TestCase('brep-bool'), TestCase('brep-bool-wizard-based'), - TestCase('brep-pip') + TestCase('brep-pip'), + TestCase('brep-enclose') ], };