BREP testing framework

This commit is contained in:
Val Erastov 2017-02-03 00:13:49 -08:00
parent 0ed5c1e9da
commit a226ce644f
71 changed files with 1137 additions and 15 deletions

View file

@ -48,6 +48,7 @@
"jwerty": "0.3.2",
"handlebars": "4.0.6",
"handlebars-loader": "1.4.0",
"json-loader": "0.5.4 ",
"jquery": "2.1.0",
"less": "2.7.1",
"libtess": "1.2.2"

View file

@ -26,6 +26,7 @@ export function Cut(app, params) {
}
const extruder = new ParametricExtruder(face, params);
console.error('normal should be explicitly passed to the extruder#extrude method. there is no way to guess normal from points of sketch!');
const cutter = combineCutters(sketch.map(s => extruder.extrude(s))) ;
BREPValidator.validateToConsole(cutter);
solid.vanish();

View file

@ -73,8 +73,8 @@ function App() {
});
}
App.prototype.addShellOnScene = function(shell) {
const sceneSolid = new BREPSceneSolid(shell);
App.prototype.addShellOnScene = function(shell, skin) {
const sceneSolid = new BREPSceneSolid(shell, undefined, skin);
this.viewer.workGroup.add(sceneSolid.cadGroup);
this.viewer.render()
};

View file

@ -4,8 +4,8 @@ import {SceneSolid, SceneFace} from './scene-object'
export class BREPSceneSolid extends SceneSolid {
constructor(shell, type) {
super(type);
constructor(shell, type, skin) {
super(type, undefined, skin);
this.shell = shell;
this.createGeometry();
}

View file

@ -7,7 +7,7 @@ import DPR from '../../utils/dpr'
export class SceneSolid {
constructor(type, id) {
constructor(type, id, skin) {
this.tCadType = type || 'SOLID';
this.cadGroup = new THREE.Object3D();
@ -22,7 +22,7 @@ export class SceneSolid {
this.mergeable = true;
this.sceneFaces = [];
this.material = createSolidMaterial();
this.material = createSolidMaterial(skin);
}
addLineToScene(a, b) {
@ -48,8 +48,8 @@ export class SceneSolid {
}
}
function createSolidMaterial() {
return new THREE.MeshPhongMaterial({
function createSolidMaterial(skin) {
return new THREE.MeshPhongMaterial(Object.assign({
vertexColors: THREE.FaceColors,
color: 0xB0C4DE,
shininess: 0,
@ -57,7 +57,7 @@ function createSolidMaterial() {
polygonOffsetFactor : 1,
polygonOffsetUnits : 2,
//side : THREE.DoubleSide
});
}, skin));
}
export class SceneFace {

View file

@ -1,6 +1,7 @@
import * as BREPPrimitives from '../brep/brep-primitives'
import * as BREPBuilder from '../brep/brep-builder'
import * as BREPBool from '../brep/operations/boolean'
import * as IO from '../brep/brep-io'
import {BREPValidator} from '../brep/brep-validator'
import {HalfEdge, Edge} from '../brep/topo/edge';
import {Loop} from '../brep/topo/loop';
@ -20,6 +21,7 @@ export default {
},
topo: {
HalfEdge, Edge, Loop, Face, Shell, Vertex
}
},
IO
}
}

41
web/app/brep/brep-io.js Normal file
View file

@ -0,0 +1,41 @@
export function toLoops(shell) {
const vertices = [];
for (let v of shell.vertices) {
vertices.push(v);
}
sortByXYZ(vertices);
const verticesIndex = new Map();
for (var i = 0; i < vertices.length; i++) {
verticesIndex.set(vertices[i], i);
}
const faces = shell.faces.map(f => {
const loops = [];
for (let l of f.loops) {
loops.push(l.halfEdges.map(e => verticesIndex.get(e.vertexA)));
}
return loops;
});
return {
format: 'LOOPS',
vertices: vertices.map(v => [v.point.x, v.point.y, v.point.z]),
faces
};
}
function sortByXYZ(vertices) {
vertices.sort((v1, v2) => {
let c = v1.point.x - v2.point.x;
if (c == 0) {
c = v1.point.y - v2.point.y;
if (c == 0) {
c = v1.point.z - v2.point.z;
}
}
return c;
});
}

View file

@ -1,9 +1,12 @@
import * as test from '../test'
import {deepMerge} from '../utils/deep-merge'
import {Matrix3} from '../../app/math/l3space'
export default {
const OPERANDS_MODE = false;
testNormalIntersection: function (env) {
const CASE = {
testSmokedSalmon: 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));
@ -14,6 +17,133 @@ export default {
env.done();
}));
}
};
def('simple.union');
def('simple.intersect');
def('simple.subtract');
def('overlap.face.intersect');
def('overlap.face.subtract');
def('overlap.face.half.intersect');
def('overlap.face.half.subtract');
def('overlap.face.edge1.intersect');
def('overlap.face.edge1.subtract');
def('overlap.face.edge1.half.intersect');
def('overlap.face.edge1.half.subtract');
def('overlap.face.edge2.intersect');
def('overlap.face.edge2.subtract');
def('overlap.face.edge2.half.intersect');
def('overlap.face.edge2.half.subtract');
def('overlap.face.inside.intersect');
def('overlap.face.inside.subtract');
def('overlap.face.inside.half.intersect');
def('overlap.face.inside.half.subtract');
def('overlap.kiss.edge.intersect');
def('overlap.kiss.edge.subtract');
def('overlap.kiss.edge.half.intersect');
def('overlap.kiss.edge.half.subtract');
def('overlap.kiss.edge4.intersect');
def('overlap.kiss.edge4.subtract');
def('overlap.kiss.edge4.half.intersect');
def('overlap.kiss.edge4.half.subtract');
def('star.intersect');
def('star.subtract');
function def(name) {
const funcName = 'test' + name.split(/\./).map(part => part.charAt(0).toUpperCase() + part.slice(1)).join('');
CASE[funcName] = function (env) {
test.modeller(env.test((win, app) => {
ddt(env, app, name);
}));
};
}
function ddt(env, app, name) {
const input = getInput(name);
const result = performOperation(app, input);
app.addShellOnScene(result);
compare(env, app, name, result);
env.done();
}
function compare(env, app, name, result) {
const out = require('./data/brep/' + name + '/out.json');
const resultData = shellToData(app.TPI.brep.IO, out.format, result);
const resultJSON = JSON.stringify(resultData).replace(/\s/g, '');
const expectedJSON = JSON.stringify(out).replace(/\s/g, '');
if (resultJSON != expectedJSON) {
console.log('EXPECTED:');
console.log(prettyJSON(out));
console.log('ACTUAL:');
console.log(prettyJSON(resultData));
env.fail('expected brep data different from actual. ^^see log above^^');
}
}
function prettyJSON(obj) {
return JSON.stringify(obj, null, 0);
}
function shellToData(io, format, shell) {
if (format == 'LOOPS') {
return io.toLoops(shell);
} else {
throw 'unsupported type: ' + format;
}
}
function getInput(name) {
const input = readInput(name);
if (input.overrides) {
const overrides = readInput(input.overrides);
return deepMerge({}, overrides, input);
}
return input;
}
function readInput(name) {
return require('./data/brep/' + name + '/in.json');
}
function materialize(tpi, def) {
if (def.type == 'EXTRUDE') {
return tpi.brep.builder.createPrism(def.base.map(p => new tpi.brep.geom.Point().set3(p)), def.height);
} else {
throw 'unsupported type: ' + def.type;
}
}
function performOperation(app, input) {
const A = materialize(app.TPI, input.A);
const B = materialize(app.TPI, input.B);
if (OPERANDS_MODE) {
app.addShellOnScene(A, {
color: 0x800080,
transparent: true,
opacity: 0.5,
});
app.addShellOnScene(B, {
color: 0xfff44f,
transparent: true,
opacity: 0.5,
});
//throw '!operands mode. turn it off!'
}
const bool = app.TPI.brep.bool;
if (input.operation == 'UNION') {
return bool.union(A, B);
} else if (input.operation == 'INTERSECT') {
return bool.intersect(A, B);
} else if (input.operation == 'SUBTRACT') {
return bool.subtract(A, B);
} else {
throw 'unknown operation: ' + input.operation;
}
}
export default CASE;

View file

@ -0,0 +1,24 @@
{
"A": {
"type": "EXTRUDE",
"base": [
[-250, -250, 250],
[ 250, -250, 250],
[ 250, 250, 250],
[-250, 250, 250]
],
"height": 500
},
"B": {
"type": "EXTRUDE",
"base": [
[-200, -200, 250],
[ 200, -200, 250],
[ 200, 250, 250],
[-200, 250, 250]
],
"height": 250
},
"operation": "INTERSECT"
}

View file

@ -0,0 +1,6 @@
{
"format": "LOOPS", "vertices": [
[-200, -200, 0], [-200, -200, 250], [-200, 250, 0], [-200, 250, 250], [200, -200, 0], [200, -200, 250], [200, 250, 0],
[200, 250, 250]
], "faces": [[[6, 2, 3, 7]], [[3, 1, 5, 7]], [[5, 1, 0, 4]], [[7, 5, 4, 6]], [[1, 3, 2, 0]], [[2, 6, 4, 0]]]
}

View file

@ -0,0 +1,24 @@
{
"A": {
"type": "EXTRUDE",
"base": [
[-250, -250, 250],
[ 250, -250, 250],
[ 250, 250, 250],
[-250, 250, 250]
],
"height": 500
},
"B": {
"type": "EXTRUDE",
"base": [
[-200, -200, 250],
[ 200, -200, 250],
[ 200, 250, 250],
[-200, 250, 250]
],
"height": 250
},
"operation": "SUBTRACT"
}

View file

@ -0,0 +1,10 @@
{
"format": "LOOPS", "vertices": [
[-250, -250, -250], [-250, -250, 250], [-250, 250, -250], [-250, 250, 250], [-200, -200, 0], [-200, -200, 250],
[-200, 250, 0], [-200, 250, 250], [200, -200, 0], [200, -200, 250], [200, 250, 0], [200, 250, 250], [250, -250, -250],
[250, -250, 250], [250, 250, -250], [250, 250, 250]
], "faces": [
[[12, 13, 1, 0]], [[14, 15, 13, 12]], [[6, 10, 11, 15, 14, 2, 3, 7]], [[0, 1, 3, 2]], [[5, 7, 3, 1, 13, 15, 11, 9]],
[[0, 2, 14, 12]], [[5, 9, 8, 4]], [[9, 11, 10, 8]], [[7, 5, 4, 6]], [[10, 6, 4, 8]]
]
}

View file

@ -0,0 +1,24 @@
{
"A": {
"type": "EXTRUDE",
"base": [
[-250, -250, 250],
[ 250, -250, 250],
[ 250, 250, 250],
[-250, 250, 250]
],
"height": 500
},
"B": {
"type": "EXTRUDE",
"base": [
[-200, -200, 250],
[ 200, -200, 250],
[ 200, 250, 250],
[-200, 250, 250]
],
"height": 500
},
"operation": "INTERSECT"
}

View file

@ -0,0 +1,6 @@
{
"format": "LOOPS", "vertices": [
[-200, -200, -250], [-200, -200, 250], [-200, 250, -250], [-200, 250, 250], [200, -200, -250], [200, -200, 250],
[200, 250, -250], [200, 250, 250]
], "faces": [[[2, 3, 7, 6]], [[3, 1, 5, 7]], [[0, 2, 6, 4]], [[0, 4, 5, 1]], [[4, 6, 7, 5]], [[2, 0, 1, 3]]]
}

View file

@ -0,0 +1,24 @@
{
"A": {
"type": "EXTRUDE",
"base": [
[-250, -250, 250],
[ 250, -250, 250],
[ 250, 250, 250],
[-250, 250, 250]
],
"height": 500
},
"B": {
"type": "EXTRUDE",
"base": [
[-200, -200, 250],
[ 200, -200, 250],
[ 200, 250, 250],
[-200, 250, 250]
],
"height": 500
},
"operation": "SUBTRACT"
}

View file

@ -0,0 +1,6 @@
{
"format": "LOOPS", "vertices": [
[0, 0, -250], [0, 0, 250], [0, 250, -250], [0, 250, 250], [250, 0, -250], [250, 0, 250], [250, 250, -250],
[250, 250, 250]
], "faces": [[[5, 4, 6, 7]], [[2, 3, 7, 6]], [[3, 1, 5, 7]], [[0, 2, 6, 4]], [[0, 4, 5, 1]], [[2, 0, 1, 3]]]
}

View file

@ -0,0 +1,24 @@
{
"A": {
"type": "EXTRUDE",
"base": [
[-250, -250, 250],
[ 250, -250, 250],
[ 250, 250, 250],
[-250, 250, 250]
],
"height": 500
},
"B": {
"type": "EXTRUDE",
"base": [
[ 0, 0, 250],
[ 250, 0, 250],
[ 250, 250, 250],
[ 0, 250, 250]
],
"height": 250
},
"operation": "INTERSECT"
}

View file

@ -0,0 +1,5 @@
{
"format": "LOOPS", "vertices": [
[0, 0, 0], [0, 0, 250], [0, 250, 0], [0, 250, 250], [250, 0, 0], [250, 0, 250], [250, 250, 0], [250, 250, 250]
], "faces": [[[4, 6, 7, 5]], [[6, 2, 3, 7]], [[3, 1, 5, 7]], [[5, 1, 0, 4]], [[1, 3, 2, 0]], [[2, 6, 4, 0]]]
}

View file

@ -0,0 +1,24 @@
{
"A": {
"type": "EXTRUDE",
"base": [
[-250, -250, 250],
[ 250, -250, 250],
[ 250, 250, 250],
[-250, 250, 250]
],
"height": 500
},
"B": {
"type": "EXTRUDE",
"base": [
[ 0, 0, 250],
[ 250, 0, 250],
[ 250, 250, 250],
[ 0, 250, 250]
],
"height": 250
},
"operation": "SUBTRACT"
}

View file

@ -0,0 +1,9 @@
{
"format": "LOOPS", "vertices": [
[-250, -250, -250], [-250, -250, 250], [-250, 250, -250], [-250, 250, 250], [0, 0, 0], [0, 0, 250], [0, 250, 0],
[0, 250, 250], [250, -250, -250], [250, -250, 250], [250, 0, 0], [250, 0, 250], [250, 250, -250], [250, 250, 0]
], "faces": [
[[8, 9, 1, 0]], [[13, 10, 11, 9, 8, 12]], [[6, 13, 12, 2, 3, 7]], [[0, 1, 3, 2]], [[5, 7, 3, 1, 9, 11]],
[[0, 2, 12, 8]], [[5, 11, 10, 4]], [[7, 5, 4, 6]], [[13, 6, 4, 10]]
]
}

View file

@ -0,0 +1,24 @@
{
"A": {
"type": "EXTRUDE",
"base": [
[-250, -250, 250],
[ 250, -250, 250],
[ 250, 250, 250],
[-250, 250, 250]
],
"height": 500
},
"B": {
"type": "EXTRUDE",
"base": [
[ 0, 0, 250],
[ 250, 0, 250],
[ 250, 250, 250],
[ 0, 250, 250]
],
"height": 500
},
"operation": "INTERSECT"
}

View file

@ -0,0 +1,6 @@
{
"format": "LOOPS", "vertices": [
[0, 0, -250], [0, 0, 250], [0, 250, -250], [0, 250, 250], [250, 0, -250], [250, 0, 250], [250, 250, -250],
[250, 250, 250]
], "faces": [[[5, 4, 6, 7]], [[2, 3, 7, 6]], [[3, 1, 5, 7]], [[0, 2, 6, 4]], [[0, 4, 5, 1]], [[2, 0, 1, 3]]]
}

View file

@ -0,0 +1,24 @@
{
"A": {
"type": "EXTRUDE",
"base": [
[-250, -250, 250],
[ 250, -250, 250],
[ 250, 250, 250],
[-250, 250, 250]
],
"height": 500
},
"B": {
"type": "EXTRUDE",
"base": [
[ 0, 0, 250],
[ 250, 0, 250],
[ 250, 250, 250],
[ 0, 250, 250]
],
"height": 500
},
"operation": "SUBTRACT"
}

View file

@ -0,0 +1,9 @@
{
"format": "LOOPS", "vertices": [
[-250, -250, -250], [-250, -250, 250], [-250, 250, -250], [-250, 250, 250], [0, 0, -250], [0, 0, 250], [0, 250, -250],
[0, 250, 250], [250, -250, -250], [250, -250, 250], [250, 0, -250], [250, 0, 250]
], "faces": [
[[8, 9, 1, 0]], [[10, 11, 9, 8]], [[7, 6, 2, 3]], [[0, 1, 3, 2]], [[5, 7, 3, 1, 9, 11]], [[6, 4, 10, 8, 0, 2]],
[[10, 4, 5, 11]], [[4, 6, 7, 5]]
]
}

View file

@ -0,0 +1,24 @@
{
"A": {
"type": "EXTRUDE",
"base": [
[-250, -250, 250],
[ 250, -250, 250],
[ 250, 250, 250],
[-250, 250, 250]
],
"height": 500
},
"B": {
"type": "EXTRUDE",
"base": [
[ 0, 0, 250],
[ 500, 0, 250],
[ 500, 500, 250],
[ 0, 500, 250]
],
"height": 250
},
"operation": "INTERSECT"
}

View file

@ -0,0 +1,5 @@
{
"format": "LOOPS", "vertices": [
[0, 0, 0], [0, 0, 250], [0, 250, 0], [0, 250, 250], [250, 0, 0], [250, 0, 250], [250, 250, 0], [250, 250, 250]
], "faces": [[[4, 6, 7, 5]], [[6, 2, 3, 7]], [[3, 1, 5, 7]], [[5, 1, 0, 4]], [[1, 3, 2, 0]], [[2, 6, 4, 0]]]
}

View file

@ -0,0 +1,24 @@
{
"A": {
"type": "EXTRUDE",
"base": [
[-250, -250, 250],
[ 250, -250, 250],
[ 250, 250, 250],
[-250, 250, 250]
],
"height": 500
},
"B": {
"type": "EXTRUDE",
"base": [
[ 0, 0, 250],
[ 500, 0, 250],
[ 500, 500, 250],
[ 0, 500, 250]
],
"height": 250
},
"operation": "SUBTRACT"
}

View file

@ -0,0 +1,9 @@
{
"format": "LOOPS", "vertices": [
[-250, -250, -250], [-250, -250, 250], [-250, 250, -250], [-250, 250, 250], [0, 0, 0], [0, 0, 250], [0, 250, 0],
[0, 250, 250], [250, -250, -250], [250, -250, 250], [250, 0, 0], [250, 0, 250], [250, 250, -250], [250, 250, 0]
], "faces": [
[[8, 9, 1, 0]], [[13, 10, 11, 9, 8, 12]], [[6, 13, 12, 2, 3, 7]], [[0, 1, 3, 2]], [[5, 7, 3, 1, 9, 11]],
[[0, 2, 12, 8]], [[5, 11, 10, 4]], [[7, 5, 4, 6]], [[13, 6, 4, 10]]
]
}

View file

@ -0,0 +1,24 @@
{
"A": {
"type": "EXTRUDE",
"base": [
[-250, -250, 250],
[ 250, -250, 250],
[ 250, 250, 250],
[-250, 250, 250]
],
"height": 500
},
"B": {
"type": "EXTRUDE",
"base": [
[-100, -100, 250],
[ 100, -100, 250],
[ 100, 100, 250],
[-100, 100, 250]
],
"height": 250
},
"operation": "INTERSECT"
}

View file

@ -0,0 +1,6 @@
{
"format": "LOOPS", "vertices": [
[-100, -100, 0], [-100, -100, 250], [-100, 100, 0], [-100, 100, 250], [100, -100, 0], [100, -100, 250], [100, 100, 0],
[100, 100, 250]
], "faces": [[[3, 1, 5, 7]], [[5, 1, 0, 4]], [[7, 5, 4, 6]], [[3, 7, 6, 2]], [[1, 3, 2, 0]], [[0, 2, 6, 4]]]
}

View file

@ -0,0 +1,24 @@
{
"A": {
"type": "EXTRUDE",
"base": [
[-250, -250, 250],
[ 250, -250, 250],
[ 250, 250, 250],
[-250, 250, 250]
],
"height": 500
},
"B": {
"type": "EXTRUDE",
"base": [
[-100, -100, 250],
[ 100, -100, 250],
[ 100, 100, 250],
[-100, 100, 250]
],
"height": 250
},
"operation": "SUBTRACT"
}

View file

@ -0,0 +1,10 @@
{
"format": "LOOPS", "vertices": [
[-250, -250, -250], [-250, -250, 250], [-250, 250, -250], [-250, 250, 250], [-100, -100, 0], [-100, -100, 250],
[-100, 100, 0], [-100, 100, 250], [100, -100, 0], [100, -100, 250], [100, 100, 0], [100, 100, 250], [250, -250, -250],
[250, -250, 250], [250, 250, -250], [250, 250, 250]
], "faces": [
[[12, 13, 1, 0]], [[14, 15, 13, 12]], [[2, 3, 15, 14]], [[0, 1, 3, 2]], [[3, 1, 13, 15], [5, 7, 11, 9]],
[[0, 2, 14, 12]], [[5, 9, 8, 4]], [[9, 11, 10, 8]], [[11, 7, 6, 10]], [[7, 5, 4, 6]], [[10, 6, 4, 8]]
]
}

View file

@ -0,0 +1,24 @@
{
"A": {
"type": "EXTRUDE",
"base": [
[-250, -250, 250],
[ 250, -250, 250],
[ 250, 250, 250],
[-250, 250, 250]
],
"height": 500
},
"B": {
"type": "EXTRUDE",
"base": [
[-100, -100, 250],
[ 100, -100, 250],
[ 100, 100, 250],
[-100, 100, 250]
],
"height": 500
},
"operation": "INTERSECT"
}

View file

@ -0,0 +1,6 @@
{
"format": "LOOPS", "vertices": [
[-100, -100, -250], [-100, -100, 250], [-100, 100, -250], [-100, 100, 250], [100, -100, -250], [100, -100, 250],
[100, 100, -250], [100, 100, 250]
], "faces": [[[3, 1, 5, 7]], [[0, 2, 6, 4]], [[0, 4, 5, 1]], [[4, 6, 7, 5]], [[6, 2, 3, 7]], [[2, 0, 1, 3]]]
}

View file

@ -0,0 +1,24 @@
{
"A": {
"type": "EXTRUDE",
"base": [
[-250, -250, 250],
[ 250, -250, 250],
[ 250, 250, 250],
[-250, 250, 250]
],
"height": 500
},
"B": {
"type": "EXTRUDE",
"base": [
[-100, -100, 250],
[ 100, -100, 250],
[ 100, 100, 250],
[-100, 100, 250]
],
"height": 500
},
"operation": "SUBTRACT"
}

View file

@ -0,0 +1,10 @@
{
"format": "LOOPS", "vertices": [
[-250, -250, -250], [-250, -250, 250], [-250, 250, -250], [-250, 250, 250], [-100, -100, -250], [-100, -100, 250],
[-100, 100, -250], [-100, 100, 250], [100, -100, -250], [100, -100, 250], [100, 100, -250], [100, 100, 250],
[250, -250, -250], [250, -250, 250], [250, 250, -250], [250, 250, 250]
], "faces": [
[[12, 13, 1, 0]], [[14, 15, 13, 12]], [[2, 3, 15, 14]], [[0, 1, 3, 2]], [[3, 1, 13, 15], [5, 7, 11, 9]],
[[0, 2, 14, 12], [6, 4, 8, 10]], [[8, 4, 5, 9]], [[10, 8, 9, 11]], [[6, 10, 11, 7]], [[4, 6, 7, 5]]
]
}

View file

@ -0,0 +1,24 @@
{
"A": {
"type": "EXTRUDE",
"base": [
[-250, -250, 250],
[ 250, -250, 250],
[ 250, 250, 250],
[-250, 250, 250]
],
"height": 500
},
"B": {
"type": "EXTRUDE",
"base": [
[ 0, 0, 250],
[ 500, 0, 250],
[ 500, 500, 250],
[ 0, 500, 250]
],
"height": 500
},
"operation": "INTERSECT"
}

View file

@ -0,0 +1,6 @@
{
"format": "LOOPS", "vertices": [
[0, 0, -250], [0, 0, 250], [0, 250, -250], [0, 250, 250], [250, 0, -250], [250, 0, 250], [250, 250, -250],
[250, 250, 250]
], "faces": [[[5, 4, 6, 7]], [[2, 3, 7, 6]], [[3, 1, 5, 7]], [[0, 2, 6, 4]], [[0, 4, 5, 1]], [[2, 0, 1, 3]]]
}

View file

@ -0,0 +1,24 @@
{
"A": {
"type": "EXTRUDE",
"base": [
[-250, -250, 250],
[ 250, -250, 250],
[ 250, 250, 250],
[-250, 250, 250]
],
"height": 500
},
"B": {
"type": "EXTRUDE",
"base": [
[ 0, 0, 250],
[ 500, 0, 250],
[ 500, 500, 250],
[ 0, 500, 250]
],
"height": 500
},
"operation": "SUBTRACT"
}

View file

@ -0,0 +1,9 @@
{
"format": "LOOPS", "vertices": [
[-250, -250, -250], [-250, -250, 250], [-250, 250, -250], [-250, 250, 250], [0, 0, -250], [0, 0, 250], [0, 250, -250],
[0, 250, 250], [250, -250, -250], [250, -250, 250], [250, 0, -250], [250, 0, 250]
], "faces": [
[[8, 9, 1, 0]], [[10, 11, 9, 8]], [[7, 6, 2, 3]], [[0, 1, 3, 2]], [[5, 7, 3, 1, 9, 11]], [[6, 4, 10, 8, 0, 2]],
[[10, 4, 5, 11]], [[4, 6, 7, 5]]
]
}

View file

@ -0,0 +1,7 @@
{
"overrides": "overlap.kiss.edge.intersect",
"B": {
"height": 250
}
}

View file

@ -0,0 +1,5 @@
{
"format": "LOOPS",
"vertices": [[-100, 100, 0], [-100, 100, 250], [100, -100, 0], [100, -100, 250], [250, 250, 0], [250, 250, 250]],
"faces": [[[1, 3, 5]], [[5, 3, 2, 4]], [[1, 5, 4, 0]], [[3, 1, 0, 2]], [[2, 0, 4]]]
}

View file

@ -0,0 +1,7 @@
{
"overrides": "overlap.kiss.edge.subtract",
"B": {
"height": 250
}
}

View file

@ -0,0 +1,6 @@
{
"format": "LOOPS", "vertices": [
[0, 0, -250], [0, 0, 250], [0, 250, -250], [0, 250, 250], [250, 0, -250], [250, 0, 250], [250, 250, -250],
[250, 250, 250]
], "faces": [[[5, 4, 6, 7]], [[2, 3, 7, 6]], [[3, 1, 5, 7]], [[0, 2, 6, 4]], [[0, 4, 5, 1]], [[2, 0, 1, 3]]]
}

View file

@ -0,0 +1,23 @@
{
"A": {
"type": "EXTRUDE",
"base": [
[-250, -250, 250],
[ 250, -250, 250],
[ 250, 250, 250],
[-250, 250, 250]
],
"height": 500
},
"B": {
"type": "EXTRUDE",
"base": [
[ 100, -100, 250],
[ 250, 250, 250],
[-100, 100, 250]
],
"height": 500
},
"operation": "INTERSECT"
}

View file

@ -0,0 +1,5 @@
{
"format": "LOOPS", "vertices": [
[-100, 100, -250], [-100, 100, 250], [100, -100, -250], [100, -100, 250], [250, 250, -250], [250, 250, 250]
], "faces": [[[1, 3, 5]], [[2, 0, 4]], [[2, 4, 5, 3]], [[4, 0, 1, 5]], [[0, 2, 3, 1]]]
}

View file

@ -0,0 +1,23 @@
{
"A": {
"type": "EXTRUDE",
"base": [
[-250, -250, 250],
[ 250, -250, 250],
[ 250, 250, 250],
[-250, 250, 250]
],
"height": 500
},
"B": {
"type": "EXTRUDE",
"base": [
[ 100, -100, 250],
[ 250, 250, 250],
[-100, 100, 250]
],
"height": 500
},
"operation": "SUBTRACT"
}

View file

@ -0,0 +1,6 @@
{
"format": "LOOPS", "vertices": [
[0, 0, -250], [0, 0, 250], [0, 250, -250], [0, 250, 250], [250, 0, -250], [250, 0, 250], [250, 250, -250],
[250, 250, 250]
], "faces": [[[5, 4, 6, 7]], [[2, 3, 7, 6]], [[3, 1, 5, 7]], [[0, 2, 6, 4]], [[0, 4, 5, 1]], [[2, 0, 1, 3]]]
}

View file

@ -0,0 +1,28 @@
{
"A": {
"type": "EXTRUDE",
"base": [
[-250, -250, 250],
[ 250, -250, 250],
[ 250, 250, 250],
[-250, 250, 250]
],
"height": 500
},
"B": {
"type": "EXTRUDE",
"base": [
[ 0, -100, 250],
[ 250, -250, 250],
[ 100, 0, 250],
[ 250, 250, 250],
[ 0, 100, 250],
[-250, 250, 250],
[-100, 0, 250],
[-250, -250, 250]
],
"height": 250
},
"operation": "INTERSECT"
}

View file

@ -0,0 +1,6 @@
{
"format": "LOOPS", "vertices": [
[0, 0, -250], [0, 0, 250], [0, 250, -250], [0, 250, 250], [250, 0, -250], [250, 0, 250], [250, 250, -250],
[250, 250, 250]
], "faces": [[[5, 4, 6, 7]], [[2, 3, 7, 6]], [[3, 1, 5, 7]], [[0, 2, 6, 4]], [[0, 4, 5, 1]], [[2, 0, 1, 3]]]
}

View file

@ -0,0 +1,28 @@
{
"A": {
"type": "EXTRUDE",
"base": [
[-250, -250, 250],
[ 250, -250, 250],
[ 250, 250, 250],
[-250, 250, 250]
],
"height": 500
},
"B": {
"type": "EXTRUDE",
"base": [
[ 0, -100, 250],
[ 250, -250, 250],
[ 100, 0, 250],
[ 250, 250, 250],
[ 0, 100, 250],
[-250, 250, 250],
[-100, 0, 250],
[-250, -250, 250]
],
"height": 250
},
"operation": "SUBTRACT"
}

View file

@ -0,0 +1,6 @@
{
"format": "LOOPS", "vertices": [
[0, 0, -250], [0, 0, 250], [0, 250, -250], [0, 250, 250], [250, 0, -250], [250, 0, 250], [250, 250, -250],
[250, 250, 250]
], "faces": [[[5, 4, 6, 7]], [[2, 3, 7, 6]], [[3, 1, 5, 7]], [[0, 2, 6, 4]], [[0, 4, 5, 1]], [[2, 0, 1, 3]]]
}

View file

@ -0,0 +1,28 @@
{
"A": {
"type": "EXTRUDE",
"base": [
[-250, -250, 250],
[ 250, -250, 250],
[ 250, 250, 250],
[-250, 250, 250]
],
"height": 500
},
"B": {
"type": "EXTRUDE",
"base": [
[ 0, -100, 250],
[ 250, -250, 250],
[ 100, 0, 250],
[ 250, 250, 250],
[ 0, 100, 250],
[-250, 250, 250],
[-100, 0, 250],
[-250, -250, 250]
],
"height": 500
},
"operation": "INTERSECT"
}

View file

@ -0,0 +1,10 @@
{
"format": "LOOPS", "vertices": [
[-250, -250, -250], [-250, -250, 250], [-250, 250, -250], [-250, 250, 250], [-100, 0, -250], [-100, 0, 250],
[0, -100, -250], [0, -100, 250], [0, 100, -250], [0, 100, 250], [100, 0, -250], [100, 0, 250], [250, -250, -250],
[250, -250, 250], [250, 250, -250], [250, 250, 250]
], "faces": [
[[1, 7, 13, 11, 15, 9, 3, 5]], [[6, 0, 4, 2, 8, 14, 10, 12]], [[6, 12, 13, 7]], [[12, 10, 11, 13]],
[[10, 14, 15, 11]], [[14, 8, 9, 15]], [[8, 2, 3, 9]], [[2, 4, 5, 3]], [[4, 0, 1, 5]], [[0, 6, 7, 1]]
]
}

View file

@ -0,0 +1,28 @@
{
"A": {
"type": "EXTRUDE",
"base": [
[-250, -250, 250],
[ 250, -250, 250],
[ 250, 250, 250],
[-250, 250, 250]
],
"height": 500
},
"B": {
"type": "EXTRUDE",
"base": [
[ 0, -100, 250],
[ 250, -250, 250],
[ 100, 0, 250],
[ 250, 250, 250],
[ 0, 100, 250],
[-250, 250, 250],
[-100, 0, 250],
[-250, -250, 250]
],
"height": 500
},
"operation": "SUBTRACT"
}

View file

@ -0,0 +1,6 @@
{
"format": "LOOPS", "vertices": [
[0, 0, -250], [0, 0, 250], [0, 250, -250], [0, 250, 250], [250, 0, -250], [250, 0, 250], [250, 250, -250],
[250, 250, 250]
], "faces": [[[5, 4, 6, 7]], [[2, 3, 7, 6]], [[3, 1, 5, 7]], [[0, 2, 6, 4]], [[0, 4, 5, 1]], [[2, 0, 1, 3]]]
}

View file

@ -0,0 +1,24 @@
{
"A": {
"type": "EXTRUDE",
"base": [
[-250, -250, 250],
[ 250, -250, 250],
[ 250, 250, 250],
[-250, 250, 250]
],
"height": 500
},
"B": {
"type": "EXTRUDE",
"base": [
[ 0, 0, 0],
[ 500, 0, 0],
[ 500, 500, 0],
[ 0, 500, 0]
],
"height": 500
},
"operation": "INTERSECT"
}

View file

@ -0,0 +1,5 @@
{
"format": "LOOPS", "vertices": [
[0, 0, -250], [0, 0, 0], [0, 250, -250], [0, 250, 0], [250, 0, -250], [250, 0, 0], [250, 250, -250], [250, 250, 0]
], "faces": [[[7, 5, 4, 6]], [[3, 7, 6, 2]], [[0, 2, 6, 4]], [[0, 4, 5, 1]], [[2, 0, 1, 3]], [[7, 3, 1, 5]]]
}

View file

@ -0,0 +1,24 @@
{
"A": {
"type": "EXTRUDE",
"base": [
[-250, -250, 250],
[ 250, -250, 250],
[ 250, 250, 250],
[-250, 250, 250]
],
"height": 500
},
"B": {
"type": "EXTRUDE",
"base": [
[ 0, 0, 0],
[ 500, 0, 0],
[ 500, 500, 0],
[ 0, 500, 0]
],
"height": 500
},
"operation": "SUBTRACT"
}

View file

@ -0,0 +1,9 @@
{
"format": "LOOPS", "vertices": [
[-250, -250, -250], [-250, -250, 250], [-250, 250, -250], [-250, 250, 250], [0, 0, -250], [0, 0, 0], [0, 250, -250],
[0, 250, 0], [250, -250, -250], [250, -250, 250], [250, 0, -250], [250, 0, 0], [250, 250, 0], [250, 250, 250]
], "faces": [
[[8, 9, 1, 0]], [[11, 12, 13, 9, 8, 10]], [[12, 7, 6, 2, 3, 13]], [[0, 1, 3, 2]], [[3, 1, 9, 13]],
[[6, 4, 10, 8, 0, 2]], [[10, 4, 5, 11]], [[4, 6, 7, 5]], [[7, 12, 11, 5]]
]
}

View file

@ -0,0 +1,24 @@
{
"A": {
"type": "EXTRUDE",
"base": [
[-250, -250, 250],
[ 250, -250, 250],
[ 250, 250, 250],
[-250, 250, 250]
],
"height": 500
},
"B": {
"type": "EXTRUDE",
"base": [
[ 0, 0, 0],
[ 500, 0, 0],
[ 500, 500, 0],
[ 0, 500, 0]
],
"height": 500
},
"operation": "UNION"
}

View file

@ -0,0 +1,11 @@
{
"format": "LOOPS", "vertices": [
[-250, -250, -250], [-250, -250, 250], [-250, 250, -250], [-250, 250, 250], [0, 0, -500], [0, 0, -250],
[0, 250, -250], [0, 250, 0], [0, 500, -500], [0, 500, 0], [250, -250, -250], [250, -250, 250], [250, 0, -250],
[250, 0, 0], [250, 250, 0], [250, 250, 250], [500, 0, -500], [500, 0, 0], [500, 500, -500], [500, 500, 0]
], "faces": [
[[10, 11, 1, 0]], [[13, 14, 15, 11, 10, 12]], [[14, 7, 6, 2, 3, 15]], [[0, 1, 3, 2]], [[3, 1, 11, 15]],
[[6, 5, 12, 10, 0, 2]], [[12, 5, 4, 16, 17, 13]], [[18, 19, 17, 16]], [[8, 9, 19, 18]], [[5, 6, 7, 9, 8, 4]],
[[7, 14, 13, 17, 19, 9]], [[4, 8, 18, 16]]
]
}

View file

@ -0,0 +1,30 @@
{
"A": {
"type": "EXTRUDE",
"base": [
[-250, -250, 250],
[ 250, -250, 250],
[ 250, 250, 250],
[-250, 250, 250]
],
"height": 500
},
"B": {
"type": "EXTRUDE",
"base": [
[ 50, 50, 250],
[ 0, 200, 250],
[ -50, 50, 250],
[-200, 0, 250],
[ -50, -50, 250],
[-200, -200, 250],
[ 0, -100, 250],
[ 200, -200, 250],
[ 50, -50, 250],
[ 200, 0, 250]
],
"height": 200
},
"operation": "INTERSECT"
}

View file

@ -0,0 +1,11 @@
{
"format": "LOOPS", "vertices": [
[-200, -200, 50], [-200, -200, 250], [-200, 0, 50], [-200, 0, 250], [-50, -50, 50], [-50, -50, 250], [-50, 50, 50],
[-50, 50, 250], [0, -100, 50], [0, -100, 250], [0, 200, 50], [0, 200, 250], [50, -50, 50], [50, -50, 250],
[50, 50, 50], [50, 50, 250], [200, -200, 50], [200, -200, 250], [200, 0, 50], [200, 0, 250]
], "faces": [
[[19, 15, 11, 7, 3, 5, 1, 9, 17, 13]], [[11, 15, 14, 10]], [[7, 11, 10, 6]], [[3, 7, 6, 2]], [[5, 3, 2, 4]],
[[1, 5, 4, 0]], [[9, 1, 0, 8]], [[17, 9, 8, 16]], [[13, 17, 16, 12]], [[19, 13, 12, 18]], [[15, 19, 18, 14]],
[[14, 18, 12, 16, 8, 0, 4, 2, 6, 10]]
]
}

View file

@ -0,0 +1,30 @@
{
"A": {
"type": "EXTRUDE",
"base": [
[-250, -250, 250],
[ 250, -250, 250],
[ 250, 250, 250],
[-250, 250, 250]
],
"height": 500
},
"B": {
"type": "EXTRUDE",
"base": [
[ 50, 50, 250],
[ 0, 200, 250],
[ -50, 50, 250],
[-200, 0, 250],
[ -50, -50, 250],
[-200, -200, 250],
[ 0, -100, 250],
[ 200, -200, 250],
[ 50, -50, 250],
[ 200, 0, 250]
],
"height": 200
},
"operation": "SUBTRACT"
}

View file

@ -0,0 +1,14 @@
{
"format": "LOOPS", "vertices": [
[-250, -250, -250], [-250, -250, 250], [-250, 250, -250], [-250, 250, 250], [-200, -200, 50], [-200, -200, 250],
[-200, 0, 50], [-200, 0, 250], [-50, -50, 50], [-50, -50, 250], [-50, 50, 50], [-50, 50, 250], [0, -100, 50],
[0, -100, 250], [0, 200, 50], [0, 200, 250], [50, -50, 50], [50, -50, 250], [50, 50, 50], [50, 50, 250],
[200, -200, 50], [200, -200, 250], [200, 0, 50], [200, 0, 250], [250, -250, -250], [250, -250, 250], [250, 250, -250],
[250, 250, 250]
], "faces": [
[[24, 25, 1, 0]], [[26, 27, 25, 24]], [[2, 3, 27, 26]], [[0, 1, 3, 2]],
[[3, 1, 25, 27], [19, 23, 17, 21, 13, 5, 9, 7, 11, 15]], [[0, 2, 26, 24]], [[19, 15, 14, 18]], [[15, 11, 10, 14]],
[[11, 7, 6, 10]], [[7, 9, 8, 6]], [[9, 5, 4, 8]], [[5, 13, 12, 4]], [[13, 21, 20, 12]], [[21, 17, 16, 20]],
[[17, 23, 22, 16]], [[23, 19, 18, 22]], [[16, 22, 18, 14, 10, 6, 8, 4, 12, 20]]
]
}

View file

@ -8,7 +8,10 @@
<div id="control-bar" class="page-row">
<button id="run-button" class="action-item" data-action="Run"><i class="fa fa-play"></i></button>
<!--<button id="pause-button"><i class="fa fa-pause"></i></button>-->
<span id="status" style="float: right">0 run / 0 passed / 0 failures</span>
<span id="status" style="float: right">
<span class="report-amount-run">0</span> run /
<span class="report-amount-passed">0</span> passed /
<span class="report-amount-failed">0</span> failed</span>
</div>
<div id="sandbox"></div>
<div class="page-row" id="test-list">

View file

@ -37,7 +37,7 @@ function scheduleTestCase(testCase, caseId) {
function scheduleTest(test, id) {
queue.push({
id,
func: test
func: test.func
});
}
@ -89,6 +89,11 @@ function pause() {
function updateIcon(dom, success) {
dom.find('.status').addClass(success ? 'status-success' : 'status-fail');
const passed = $('#test-list .status.status-success').length;
const failed = $('#test-list .status.status-fail').length;
$('.report-amount-run').text(passed + failed);
$('.report-amount-passed').text(passed);
$('.report-amount-failed').text(failed);
}
function findTestCaseById(id) {

View file

@ -32,7 +32,10 @@ export default {
function TestCase(name) {
let tests = require('./cases/' + name).default;
tests = Object.keys(tests).filter(key => key.startsWith('test')).map(key => tests[key]);
tests = Object.keys(tests).filter(key => key.startsWith('test')).map(key => ({
name: key,
func: tests[key]
}));
return {
name, tests
}

View file

@ -0,0 +1,26 @@
export function isObject(item) {
return (item && typeof item === 'object' && !Array.isArray(item));
}
/**
* Deep merge two objects.
* @param target
* @param ...sources
*/
export function deepMerge(target, ...sources) {
if (!sources.length) return target;
const source = sources.shift();
if (isObject(target) && isObject(source)) {
for (let key in source) {
if (isObject(source[key])) {
if (!target[key]) Object.assign(target, { [key]: {} });
deepMerge(target[key], source[key]);
} else {
Object.assign(target, { [key]: source[key] });
}
}
}
return deepMerge(target, ...sources);
}

View file

@ -32,6 +32,10 @@ module.exports = {
{
test: /\.html$/,
loader: 'handlebars?helperDirs[]=' + __dirname + '/web/app/ui/helpers'
},
{
test: /\.json$/,
loader: 'json'
}]
}
};