diff --git a/web/test/cases/brep-bool.js b/web/test/cases/brep-bool.js new file mode 100644 index 00000000..1973ffd0 --- /dev/null +++ b/web/test/cases/brep-bool.js @@ -0,0 +1,19 @@ +import * as test from '../test' +import {Matrix3} from '../../app/math/l3space' + +export default { + + testNormalIntersection: function (env) { + test.modeller(env.test((win, app) => { + const box1 = app.TPI.brep.primitives.box(500, 500, 500); + const box2 = app.TPI.brep.primitives.box(250, 250, 750, new Matrix3().translate(25, 25, 0)); + const box3 = app.TPI.brep.primitives.box(150, 600, 350, new Matrix3().translate(25, 25, -250)); + let result = app.TPI.brep.bool.subtract(box1, box2); + result = app.TPI.brep.bool.subtract(result, box3); + app.addShellOnScene(result); + env.done(); + })); + } + + +} diff --git a/web/test/cases/brep-pip.js b/web/test/cases/brep-pip.js new file mode 100644 index 00000000..5904a557 --- /dev/null +++ b/web/test/cases/brep-pip.js @@ -0,0 +1,649 @@ +import * as test from '../test' +import {Matrix3} from '../../app/math/l3space' + +export default { + + + /** + * o--------o + * | | + * *--> | | + * | | + * o--------o + */ + testPIPClassificationConvexOnlyEdgesOut: function (env) { + test.modeller(env.test((win, app) => { + const loop = createLoop(app.TPI,[ + [100, 100], + [500, 100], + [500, 500], + [100, 500] + ]); + + const result = classify(app, win, loop, [-300, 300]); + env.assertFalse(result.inside); + env.done(); + })); + }, + + /** + * o--------o + * | | + * | *--> | + * | | + * o--------o + */ + testPIPClassificationConvexOnlyEdgesIn: function (env) { + test.modeller(env.test((win, app) => { + const loop = createLoop(app.TPI,[ + [100, 100], + [500, 100], + [500, 500], + [100, 500] + ]); + + const result = classify(app, win, loop, [300, 300]); + env.assertTrue(result.inside); + env.done(); + })); + }, + + /** + * o--------o + * | | + * *--> o | + * | | + * o--------o + */ + testPIPClassificationConvexPointAndEdgeOut: function (env) { + test.modeller(env.test((win, app) => { + const loop = createLoop(app.TPI,[ + [100, 100], + [500, 100], + [500, 500], + [100, 500], + [100, 300] + ]); + + const result = classify(app, win, loop, [-300, 300]); + env.assertFalse(result.inside); + env.done(); + })); + }, + + /** + * o--------o + * | | + * o *--> | + * | | + * o--------o + */ + testPIPClassificationConvexPointAndEdgeIn: function (env) { + test.modeller(env.test((win, app) => { + const loop = createLoop(app.TPI,[ + [100, 100], + [500, 100], + [500, 500], + [100, 500], + [100, 300] + ]); + + const result = classify(app, win, loop, [300, 300]); + env.assertTrue(result.inside); + env.done(); + })); + }, + + /** + * o--------o + * | | + * *--> o o + * | | + * o--------o + */ + testPIPClassificationConvexPointAndPointOut: function (env) { + test.modeller(env.test((win, app) => { + const loop = createLoop(app.TPI,[ + [100, 100], + [500, 100], + [500, 300], + [500, 500], + [100, 500], + [100, 300] + ]); + + const result = classify(app, win, loop, [-300, 300]); + env.assertFalse(result.inside); + env.done(); + })); + }, + + /** + * o--------o + * | | + * o *--> o + * | | + * o--------o + */ + testPIPClassificationConvexPointAndPointIn: function (env) { + test.modeller(env.test((win, app) => { + const loop = createLoop(app.TPI,[ + [100, 100], + [500, 100], + [500, 300], + [500, 500], + [100, 500], + [100, 300] + ]); + + const result = classify(app, win, loop, [300, 300]); + env.assertTrue(result.inside); + env.done(); + })); + }, + + + /** + * o--------o + * | | + * *--> o-----o | + * | | + * o--------------o + */ + testPIPClassificationCollinearOut: function (env) { + test.modeller(env.test((win, app) => { + + const loop = createLoop(app.TPI,[ + [100, 100], + [500, 100], + [500, 500], + [200, 500], + [200, 300], + [100, 300] + ]); + const result = classify(app, win, loop, [-300, 300]); + env.assertFalse(result.inside); + env.done(); + })); + }, + + + /** + * o--------o + * | | + * o-----o *--> | + * | | + * o--------------o + */ + testPIPClassificationCollinearIn: function (env) { + test.modeller(env.test((win, app) => { + + const loop = createLoop(app.TPI,[ + [100, 100], + [500, 100], + [500, 500], + [200, 500], + [200, 300], + [100, 300] + ]); + const result = classify(app, win, loop, [300, 300]); + env.assertTrue(result.inside); + env.done(); + })); + }, + + /** + * o--------o + * | | + * *--> o-----o o-----o + * | | + * o--------------------o + */ + testPIPClassificationCollinear2Out: function (env) { + test.modeller(env.test((win, app) => { + + const loop = createLoop(app.TPI,[ + [100, 100], + [500, 100], + [500, 300], + [400, 300], + [400, 500], + [200, 500], + [200, 300], + [100, 300] + ]); + const result = classify(app, win, loop, [-300, 300]); + env.assertFalse(result.inside); + env.done(); + })); + }, + + + /** + * o--------o + * | | + * o-----o *--> o-----o + * | | + * o--------------------o + */ + testPIPClassificationCollinear2In: function (env) { + test.modeller(env.test((win, app) => { + + const loop = createLoop(app.TPI,[ + [100, 100], + [500, 100], + [500, 300], + [400, 300], + [400, 500], + [200, 500], + [200, 300], + [100, 300] + ]); + const result = classify(app, win, loop, [300, 300]); + env.assertTrue(result.inside); + env.done(); + })); + }, + + /** + * *--> o + * / \ + * / \ + * / \ + * / \ + * o---------o + */ + testPIPClassificationKissingVertexOut: function (env) { + test.modeller(env.test((win, app) => { + + const loop = createLoop(app.TPI,[ + [100, 100], + [500, 100], + [300, 300], + ]); + const result = classify(app, win, loop, [- 300, 300]); + env.assertFalse(result.inside); + env.done(); + })); + }, + + /** + * *--> o-----o + * / \ + * / \ + * / \ + * / \ + * o---------------o + */ + testPIPClassificationKissingVertexAndCollinearOut: function (env) { + test.modeller(env.test((win, app) => { + + const loop = createLoop(app.TPI,[ + [100, 100], + [500, 100], + [400, 300], + [200, 300], + ]); + const result = classify(app, win, loop, [- 300, 300]); + env.assertFalse(result.inside); + env.done(); + })); + }, + + /** + * *--> o o + * / \ / \ + * / \ / \ + * / \ / \ + * / o \ + * o-----------------o + */ + testPIPClassificationKissing2VerticesOut: function (env) { + test.modeller(env.test((win, app) => { + + const loop = createLoop(app.TPI,[ + [100, 100], + [500, 100], + [400, 300], + [300, 200], + [200, 300], + ]); + const result = classify(app, win, loop, [- 300, 300]); + env.assertFalse(result.inside); + env.done(); + })); + }, + + /** + * o o + * / \ / \ + * / \ / \ + * / \ / \ + * / *--> o \ + * o-----------------o + */ + testPIPClassificationKissingVertexIn: function (env) { + test.modeller(env.test((win, app) => { + + const loop = createLoop(app.TPI,[ + [100, 100], + [500, 100], + [400, 300], + [300, 200], + [200, 300], + ]); + const result = classify(app, win, loop, [200, 200]); + env.assertTrue(result.inside); + env.done(); + })); + }, + + /** + * o o + * / \ |\ + * / \ | \ + * / \ | \ + * / *--> o---o \ + * o-----------------o + */ + testPIPClassificationKissingVertexCollinearIn: function (env) { + test.modeller(env.test((win, app) => { + + const loop = createLoop(app.TPI,[ + [100, 100], + [500, 100], + [400, 300], + [400, 200], + [300, 200], + [200, 300], + ]); + const result = classify(app, win, loop, [200, 200]); + env.assertTrue(result.inside); + env.done(); + })); + }, + + /** + * o o + * / \ |\ + * / \ o | \ + * / \ / \ | \ + * / *--> o o \ + * o-----------------o + */ + testPIPClassificationKissing2VerticesIn: function (env) { + test.modeller(env.test((win, app) => { + + const loop = createLoop(app.TPI,[ + [100, 100], + [500, 100], + [400, 300], + [400, 200], + [350, 300], + [300, 200], + [200, 300], + ]); + const result = classify(app, win, loop, [200, 200]); + env.assertTrue(result.inside); + env.done(); + })); + }, + + /** + * o--------o + * | | + * * | + * | | + * o--------o + */ + testPIPClassificationOnEdgesPerp: function (env) { + test.modeller(env.test((win, app) => { + const loop = createLoop(app.TPI,[ + [100, 100], + [500, 100], + [500, 500], + [100, 500] + ]); + + const result = classify(app, win, loop, [100, 300]); + env.assertTrue(result.inside); + env.assertTrue(result.edge === loop.halfEdges[3]); + env.done(); + })); + }, + + /** + * o + * /| + * * | + * / | + * o---o + */ + testPIPClassificationOnEdgesAngled: function (env) { + test.modeller(env.test((win, app) => { + const loop = createLoop(app.TPI,[ + [100, 100], + [500, 100], + [500, 500] + ]); + + const result = classify(app, win, loop, [300, 300]); + env.assertTrue(result.inside); + env.assertTrue(result.edge === loop.halfEdges[2]); + env.done(); + })); + }, + + /** + * o---*----o + * | | + * | | + * | | + * o--------o + */ + testPIPClassificationOnEdgesCollinear: function (env) { + test.modeller(env.test((win, app) => { + const loop = createLoop(app.TPI,[ + [100, 100], + [500, 100], + [500, 500], + [100, 500] + ]); + + const result = classify(app, win, loop, [300, 500]); + env.assertTrue(result.inside); + env.assertTrue(result.edge === loop.halfEdges[2]); + env.done(); + })); + }, + + /** + * o--------o + * | | + * o-*---o o-----o + * | | + * o--------------------o + */ + testPIPClassificationOnEdgesCollinearT1: function (env) { + test.modeller(env.test((win, app) => { + const loop = createLoop(app.TPI,[ + [100, 100], + [500, 100], + [500, 300], + [400, 300], + [400, 500], + [200, 500], + [200, 300], + [100, 300] + ]); + + const result = classify(app, win, loop, [150, 300]); + env.assertTrue(result.inside); + env.assertTrue(result.edge === loop.halfEdges[6]); + env.done(); + })); + }, + + /** + * o--------o + * | | + * o-----o o---*-o + * | | + * o--------------------o + */ + testPIPClassificationOnEdgesCollinearT2: function (env) { + test.modeller(env.test((win, app) => { + const loop = createLoop(app.TPI,[ + [100, 100], + [500, 100], + [500, 300], + [400, 300], + [400, 500], + [200, 500], + [200, 300], + [100, 300] + ]); + + const result = classify(app, win, loop, [450, 300]); + env.assertTrue(result.inside); + env.assertTrue(result.edge === loop.halfEdges[2]); + env.done(); + })); + }, + + /** + * o--------o + * | | + * | | + * | | + * (*)-------o + */ + testPIPClassificationOnVertex: function (env) { + test.modeller(env.test((win, app) => { + const loop = createLoop(app.TPI,[ + [100, 100], + [500, 100], + [500, 500], + [100, 500] + ]); + + const result = classify(app, win, loop, [100, 100]); + env.assertTrue(result.inside); + env.assertTrue(result.vertex === loop.halfEdges[0].vertexA); + env.done(); + })); + }, + + /** + * o--------o + * | | + * o----(*) o-----o + * | | + * o--------------------o + */ + testPIPClassificationOnVertexT1: function (env) { + test.modeller(env.test((win, app) => { + const loop = createLoop(app.TPI,[ + [100, 100], + [500, 100], + [500, 300], + [400, 300], + [400, 500], + [200, 500], + [200, 300], + [100, 300] + ]); + + const result = classify(app, win, loop, [200, 300]); + env.assertTrue(result.inside); + env.assertTrue(result.vertex === loop.halfEdges[5].vertexB); + env.done(); + })); + }, + + /** + * o--------o + * | | + * o-----o (*)----o + * | | + * o--------------------o + */ + testPIPClassificationOnVertexT2: function (env) { + test.modeller(env.test((win, app) => { + const loop = createLoop(app.TPI,[ + [100, 100], + [500, 100], + [500, 300], + [400, 300], + [400, 500], + [200, 500], + [200, 300], + [100, 300] + ]); + + const result = classify(app, win, loop, [400, 300]); + env.assertTrue(result.inside); + env.assertTrue(result.vertex === loop.halfEdges[3].vertexA); + env.done(); + })); + }, + + /** + * o o + * / \ |\ + * / \ * | \ + * / \ / \ | \ + * / o o \ + * o-----------------o + */ + testPIPClassificationOnVertexNonConvex: function (env) { + test.modeller(env.test((win, app) => { + + const loop = createLoop(app.TPI,[ + [100, 100], + [500, 100], + [400, 300], + [400, 200], + [350, 300], + [300, 200], + [200, 300], + ]); + const result = classify(app, win, loop, [350, 300]); + env.assertTrue(result.inside); + env.assertTrue(result.vertex === loop.halfEdges[3].vertexB); + env.done(); + })); + }, + + +} + +function classify(app, win, loop, p) { + const IDENTITY = new Matrix3(); + loop.halfEdges.forEach(e => win.__DEBUG__.AddHalfEdge(e, 0xffff00)); + const pnt = point(app.TPI, p[0], p[1], 0); + const beam = pnt.copy(); + beam.x += 1700; + win.__DEBUG__.AddLine(pnt, beam); + win.__DEBUG__.AddPoint(pnt, 0xffffff); + const result = app.TPI.brep.bool.classifyPointInsideLoop(pnt, loop, IDENTITY); + win.__DEBUG__.AddPoint(pnt, result.inside ? 0x00ff00 : 0xff0000); + if (result.edge) { + win.__DEBUG__.AddHalfEdge(result.edge, 0xffffff) + } + return result; +} + + +function createLoop(tpi, points) { + const vertices = points.map(p => vertex(tpi, p[0], p[1], 0)); + return tpi.brep.builder.createPlaneLoop(vertices); +} + +function vertex(tpi, x, y, z) { + return new tpi.brep.topo.Vertex(point(tpi, x, y, z)); +} + +function point(tpi, x, y, z) { + return new tpi.brep.geom.Point(x, y, z); +} diff --git a/web/test/suites.js b/web/test/suites.js index f2b22120..ef4a4737 100644 --- a/web/test/suites.js +++ b/web/test/suites.js @@ -22,7 +22,12 @@ export default { ModellerOperations: [ ], - + + BREP: [ + TestCase('brep-bool'), + TestCase('brep-pip') + ], + }; function TestCase(name) { diff --git a/web/test/test.js b/web/test/test.js index a20c2527..86a544de 100644 --- a/web/test/test.js +++ b/web/test/test.js @@ -57,6 +57,13 @@ export class TestEnv { this.fail('assertTrue fails.', msg); } } + + assertFalse(stmt, msg) { + if (stmt) { + this.fail('assertFalse fails.', msg); + } + } + assertEquals(expected, actual, msg) { if (expected !== actual) { this.fail('assertEquals: Expected: ' + expected + ' but was ' + actual, msg); @@ -94,14 +101,18 @@ export function load(url, callback) { frame.attr('src', window.location.origin + url) } -const TEST_SKETCH_PROJECT = '$$$__test__$$$'; +const TEST_PROJECT = '$$$__test__$$$'; const STORAGE_PREFIX_SKETCH = "TCAD.projects."; export function emptySketch(callback) { - localStorage.removeItem(STORAGE_PREFIX_SKETCH + TEST_SKETCH_PROJECT); + localStorage.removeItem(STORAGE_PREFIX_SKETCH + TEST_PROJECT); sketch(callback); } export function sketch(callback) { - load('/sketcher.html#' + TEST_SKETCH_PROJECT, callback); + load('/sketcher.html#' + TEST_PROJECT, callback); +} + +export function modeller(callback) { + load('/index.html#' + TEST_PROJECT, callback); }