From 7ff04eb47dd3905a08f9e07ab0f9b33baecbb472 Mon Sep 17 00:00:00 2001 From: Val Erastov Date: Fri, 10 Feb 2017 21:48:29 -0800 Subject: [PATCH] brep debug framework / fix volumes --- web/app/3d/debug.js | 39 +++++++++++-- web/app/3d/modeler-app.js | 4 +- web/app/3d/scene/brep-scene-object.js | 73 ++++++++++++++++-------- web/app/3d/scene/scene-object.js | 2 +- web/app/brep/operations/boolean.js | 4 +- web/app/brep/topo/shell.js | 14 ++++- web/app/utils/dpr.js | 3 +- web/test/cases/brep-bool-wizard-based.js | 14 +++++ 8 files changed, 116 insertions(+), 37 deletions(-) diff --git a/web/app/3d/debug.js b/web/app/3d/debug.js index a348dee1..233121a3 100644 --- a/web/app/3d/debug.js +++ b/web/app/3d/debug.js @@ -1,4 +1,7 @@ import {checkForSelectedFaces} from './actions/action-helpers' +import {triangulateToThree} from './scene/brep-scene-object' +import {createSolidMaterial} from './scene/scene-object' +import DPR from '../utils/dpr' export const DEBUG = true; @@ -12,7 +15,9 @@ export function AddDebugSupport(app) { function addGlobalDebugActions(app) { const debugGroup = new THREE.Object3D(); + const debugVolumeGroup = new THREE.Object3D(); app.viewer.workGroup.add(debugGroup); + app.viewer.workGroup.add(debugVolumeGroup); window.__DEBUG__ = { AddLine: (a, b) => { debugGroup.add(createLine(a, b)); @@ -39,27 +44,53 @@ function addGlobalDebugActions(app) { }, AddVolume: (shell, color) => { color = color || 0xffffff; - app.addShellOnScene(shell, { + const geometry = new THREE.Geometry(); + triangulateToThree(shell, geometry); + const mesh = new THREE.Mesh(geometry, createSolidMaterial({ color, transparent: true, opacity: 0.5, - }).__debug__ = true; + })); + debugVolumeGroup.add(mesh); + window.__DEBUG__.AddWireframe(shell, color); + app.viewer.render(); + }, + AddWireframe: (shell, color) => { + color = color || 0xffffff; + const visited = new Set(); + for (let e of shell.edges) { + var lg = new THREE.Geometry(); + lg.vertices.push(e.halfEdge1.vertexA.point.three()); + lg.vertices.push(e.halfEdge2.vertexA.point.three()); + const line = new THREE.Line(lg, new THREE.LineBasicMaterial({color, linewidth: 3/DPR})); + debugVolumeGroup.add(line); + } + app.viewer.render(); }, HideSolids: () => { app.findAllSolidsOnScene().forEach(s => s.cadGroup.traverse(o => o.visible = false)); app.viewer.render(); }, Clear: () => { - while (debugGroup.children.length) debugGroup.remove(debugGroup.children[0]); + clearGroup(debugGroup); app.viewer.render(); }, ClearVolumes: () => { - app.findAllSolidsOnScene().filter(s => s.__debug__ === true).forEach(s => s.vanish()); + clearGroup(debugVolumeGroup); app.viewer.render(); } } } +function clearGroup(g) { + while (g.children.length) { + const o = g.children[0]; + o.material.dispose(); + o.geometry.dispose(); + g.remove(o); + } +} + function createLine(a, b, color) { color = color || 0xFA8072; const debugLineMaterial = new THREE.LineBasicMaterial({color, linewidth: 3}); diff --git a/web/app/3d/modeler-app.js b/web/app/3d/modeler-app.js index 8f029b4e..188d3cde 100644 --- a/web/app/3d/modeler-app.js +++ b/web/app/3d/modeler-app.js @@ -76,8 +76,8 @@ function App() { App.prototype.addShellOnScene = function(shell, skin) { const sceneSolid = new BREPSceneSolid(shell, undefined, skin); - this.viewer.workGroup.add(sceneSolid.cadGroup); - this.viewer.render() + //this.viewer.workGroup.add(sceneSolid.cadGroup); + this.viewer.render(); return sceneSolid; }; diff --git a/web/app/3d/scene/brep-scene-object.js b/web/app/3d/scene/brep-scene-object.js index 04357267..199e1a1b 100644 --- a/web/app/3d/scene/brep-scene-object.js +++ b/web/app/3d/scene/brep-scene-object.js @@ -21,33 +21,15 @@ export class BREPSceneSolid extends SceneSolid { } createFaces() { - let off = 0; - let gIdx = 0; const geom = this.mesh.geometry; - for (let brepFace of this.shell.faces) { - const sceneFace = new BREPSceneFace(brepFace, this); + const groups = triangulateToThree(this.shell, geom); + for (let g of groups) { + const sceneFace = new BREPSceneFace(g.brepFace, this); this.sceneFaces.push(sceneFace); - const polygons = triangulate(brepFace); - for (let p = 0; p < polygons.length; ++p) { - const poly = polygons[p]; - const vLength = poly.length; - if (vLength < 3) continue; - const firstVertex = poly[0]; - geom.vertices.push(threeV(firstVertex)); - geom.vertices.push(threeV(poly[1])); - const normal = threeV(brepFace.surface.normal); - for (let i = 2; i < vLength; i++) { - geom.vertices.push(threeV(poly[i])); - const a = off; - const b = i - 1 + off; - const c = i + off; - const face = sceneFace.createMeshFace(a, b, c); - face.normal = normal; - face.materialIndex = gIdx ++; - geom.faces.push(face); - } - //view.setFaceColor(sceneFace, utils.isSmoothPiece(group.shared) ? 0xFF0000 : null); - off = geom.vertices.length; + for (let i = g.groupStart; i < g.groupEnd; i ++) { + const face = geom.faces[i]; + sceneFace.meshFaces.push(face); + face.__TCAD_SceneFace = this; } } geom.mergeVertices(); @@ -119,4 +101,45 @@ function triangulate(face) { } +export function triangulateToThree(shell, geom) { + const result = []; + let off = 0; + let gIdx = 0; + for (let brepFace of shell.faces) { + const polygons = triangulate(brepFace); + const groupStart = geom.faces.length; + for (let p = 0; p < polygons.length; ++p) { + const poly = polygons[p]; + const vLength = poly.length; + if (vLength < 3) continue; + const firstVertex = poly[0]; + geom.vertices.push(threeV(firstVertex)); + geom.vertices.push(threeV(poly[1])); + const normal = threeV(brepFace.surface.normal); + for (let i = 2; i < vLength; i++) { + geom.vertices.push(threeV(poly[i])); + const a = off; + const b = i - 1 + off; + const c = i + off; + const face = new THREE.Face3(a, b, c); + face.normal = normal; + face.materialIndex = gIdx ++; + geom.faces.push(face); + } + //view.setFaceColor(sceneFace, utils.isSmoothPiece(group.shared) ? 0xFF0000 : null); + off = geom.vertices.length; + } + result.push(new FaceGroup(brepFace, groupStart, geom.faces.length)); + } + return result; +} + +class FaceGroup { + constructor(brepFace, groupStart, groupEnd) { + this.brepFace = brepFace; + this.groupStart = groupStart; + this.groupEnd = groupEnd; + } +} + function threeV(v) {return new THREE.Vector3( v.x, v.y, v.z )} diff --git a/web/app/3d/scene/scene-object.js b/web/app/3d/scene/scene-object.js index 6499e93d..0e927ead 100644 --- a/web/app/3d/scene/scene-object.js +++ b/web/app/3d/scene/scene-object.js @@ -48,7 +48,7 @@ export class SceneSolid { } } -function createSolidMaterial(skin) { +export function createSolidMaterial(skin) { return new THREE.MeshPhongMaterial(Object.assign({ vertexColors: THREE.FaceColors, color: 0xB0C4DE, diff --git a/web/app/brep/operations/boolean.js b/web/app/brep/operations/boolean.js index b76977e7..a79d6527 100644 --- a/web/app/brep/operations/boolean.js +++ b/web/app/brep/operations/boolean.js @@ -14,8 +14,8 @@ export const TOLERANCE_SQ = TOLERANCE * TOLERANCE; export const TOLERANCE_HALF = TOLERANCE * 0.5; const DEBUG = { - OPERANDS_MODE: true, - LOOP_DETECTION: true, + OPERANDS_MODE: false, + LOOP_DETECTION: false, FACE_FACE_INTERSECTION: false, FACE_EDGE_INTERSECTION: false, SEWING: false, diff --git a/web/app/brep/topo/shell.js b/web/app/brep/topo/shell.js index 59a09f7f..a6d5a935 100644 --- a/web/app/brep/topo/shell.js +++ b/web/app/brep/topo/shell.js @@ -5,6 +5,7 @@ export class Shell extends TopoObject { super(); this.faces = []; this.defineIterable('vertices', () => verticesGenerator(this)); + this.defineIterable('edges', () => edges(this)) } } @@ -19,4 +20,15 @@ export function* verticesGenerator(shell) { } } } - \ No newline at end of file + +export function* edges(shell) { + const visited = new Set(); + for (let face of shell.faces) { + for (let halfEdge of face.edges) { + if (!visited.has(halfEdge.edge)) { + visited.add(halfEdge.edge); + yield halfEdge.edge; + } + } + } +} diff --git a/web/app/utils/dpr.js b/web/app/utils/dpr.js index 70d0cf33..20f1cf26 100644 --- a/web/app/utils/dpr.js +++ b/web/app/utils/dpr.js @@ -1,2 +1 @@ -const DPR = (window.devicePixelRatio) ? window.devicePixelRatio : 1; -export default DPR; \ No newline at end of file +export default (window.devicePixelRatio) ? window.devicePixelRatio : 1; diff --git a/web/test/cases/brep-bool-wizard-based.js b/web/test/cases/brep-bool-wizard-based.js index 37f24e30..65c41ee9 100644 --- a/web/test/cases/brep-bool-wizard-based.js +++ b/web/test/cases/brep-bool-wizard-based.js @@ -30,7 +30,21 @@ export default { assertScene(app, env, {"format":"LOOPS","vertices":[[-250,-250,-250],[-250,-250,250],[-250,57.176503480539594,-250],[-250,57.176503480539594,-45.42896723585416],[-250,250,-45.42896723585416],[-250,250,250],[-154.2442837314632,-250,-17.236467236467238],[-154.2442837314632,-250,173.69055445978523],[-154.2442837314632,250,-17.236467236467238],[-154.2442837314632,250,173.69055445978523],[148.94075535101177,-250,-17.236467236467238],[148.94075535101177,-250,173.69055445978523],[148.94075535101177,250,-17.236467236467238],[148.94075535101177,250,173.69055445978523],[200,-250,5.818373610536707],[200,-250,250],[200,-40.45650878155793,5.818373610536707],[200,-40.45650878155793,250],[250,-250,-250],[250,-250,5.818373610536696],[250,-40.45650878155794,250],[250,-40.45650878155793,5.818373610536707],[250,57.176503480539594,-250],[250,57.176503480539594,-45.42896723585416],[250,250,-45.42896723585416],[250,250,250]],"faces":[[[14,15,1,0,18,19],[6,7,11,10]],[[21,19,18,22,23,24,25,20]],[[25,24,4,5],[9,8,12,13]],[[4,3,2,0,1,5]],[[15,17,20,25,5,1]],[[0,2,22,18]],[[6,10,12,8]],[[7,6,8,9]],[[11,7,9,13]],[[10,11,13,12]],[[4,24,23,3]],[[3,23,22,2]],[[14,19,21,16]],[[20,17,16,21]],[[17,15,14,16]]]}); env.done(); })); + }, + + test_TR_OUT_TR_KISS: function(env) { + test.emptyModeller(env.test((win, app) => { + app.actionManager.actions['BOX'].invoke(app); + app.ui.registeredWizard.okClick(); + setSketch(win, app, '0:2', {"layers":[{"name":"sketch","data":[{"id":34,"_class":"TCAD.TWO.Segment","points":[[28,[29,199.9768703670335],[30,225.00201188826748]],[31,[32,208.9483140098693],[33,-207.18004219340503]]],"children":[34]},{"id":41,"_class":"TCAD.TWO.Segment","points":[[35,[36,208.9483140098693],[37,-207.18004219340503]],[38,[39,291.47622363115545],[40,28.544413377534887]]],"children":[41]},{"id":48,"_class":"TCAD.TWO.Segment","points":[[42,[43,291.47622363115545],[44,28.544413377534887]],[45,[46,199.9768703670335],[47,225.00201188826748]]],"children":[48]}]}]} ); + cut(app, '0:2', 500); + setSketch(win, app, '0:3', {"layers":[{"name":"sketch","data":[{"id":34,"_class":"TCAD.TWO.Segment","points":[[28,[29,-250],[30,250]],[31,[32,-169.15430109914888],[33,24.438723388262304]]],"children":[34]},{"id":41,"_class":"TCAD.TWO.Segment","points":[[35,[36,-169.15430109914888],[37,24.438723388262304]],[38,[39,-44.56473088447832],[40,170.1126824084925]]],"children":[41]},{"id":48,"_class":"TCAD.TWO.Segment","points":[[42,[43,-44.56473088447832],[44,170.1126824084925]],[45,[46,-250],[47,250]]],"children":[48]}]}]}); + cut(app, '0:3', 500); + assertScene(app, env, {"format":"LOOPS","vertices":[[-250,-250,-250],[-250,-250,250],[-250,57.176503480539594,-250],[-250,57.176503480539594,-45.42896723585416],[-250,250,-45.42896723585416],[-250,250,250],[-154.2442837314632,-250,-17.236467236467238],[-154.2442837314632,-250,173.69055445978523],[-154.2442837314632,250,-17.236467236467238],[-154.2442837314632,250,173.69055445978523],[148.94075535101177,-250,-17.236467236467238],[148.94075535101177,-250,173.69055445978523],[148.94075535101177,250,-17.236467236467238],[148.94075535101177,250,173.69055445978523],[200,-250,5.818373610536707],[200,-250,250],[200,-40.45650878155793,5.818373610536707],[200,-40.45650878155793,250],[250,-250,-250],[250,-250,5.818373610536696],[250,-40.45650878155794,250],[250,-40.45650878155793,5.818373610536707],[250,57.176503480539594,-250],[250,57.176503480539594,-45.42896723585416],[250,250,-45.42896723585416],[250,250,250]],"faces":[[[14,15,1,0,18,19],[6,7,11,10]],[[21,19,18,22,23,24,25,20]],[[25,24,4,5],[9,8,12,13]],[[4,3,2,0,1,5]],[[15,17,20,25,5,1]],[[0,2,22,18]],[[6,10,12,8]],[[7,6,8,9]],[[11,7,9,13]],[[10,11,13,12]],[[4,24,23,3]],[[3,23,22,2]],[[14,19,21,16]],[[20,17,16,21]],[[17,15,14,16]]]}); + env.done(); + })); } + }; function cut(app, faceId, depth) {