fix face filtering

This commit is contained in:
Val Erastov 2017-12-26 01:09:14 -07:00
parent 7b5a547755
commit 7ae9190587
7 changed files with 77 additions and 33 deletions

View file

@ -161,8 +161,8 @@ function addGlobalDebugActions(app) {
app.findAllSolidsOnScene().forEach(s => s.cadGroup.traverse(o => o.visible = false));
app.viewer.render();
},
Solids: () => {
app.findAllSolidsOnScene().forEach(s => s.cadGroup.traverse(o => o.visible = false));
ShowSolids: () => {
app.findAllSolidsOnScene().forEach(s => s.cadGroup.traverse(o => o.visible = true));
app.viewer.render();
},
Clear: () => {

View file

@ -50,6 +50,11 @@ class BRepDebug {
transferEdge(edge, face, chosenEdge) {
this.currentBooleanSession.transferedEdges.push({edge, face, chosenEdge});
}
faceFilter(connectedToAffectedFaces, allFaces) {
this.currentBooleanSession.faceFilter.connectedToAffectedFaces = connectedToAffectedFaces;
this.currentBooleanSession.faceFilter.allFaces = allFaces;
}
}
class BooleanSession {
@ -63,6 +68,10 @@ class BooleanSession {
this.transferedEdges = [];
this.mergeFacesLoopDetection = [];
this.currentLoopDetection = null;
this.faceFilter = {
connectedToAffectedFaces: null,
allFaces: null,
};
}
}

View file

@ -5,6 +5,7 @@ import ShellExplorer from './shellExplorer';
import LoopDetectionExplorer from './loopDetectionExplorer';
import Section from './section'
import {EdgeTransferExplorer} from "./edgeTransferExplorer";
import {FaceFilterExplorer} from "./faceFilterExplorer";
export default class BrepDebugger extends React.PureComponent {
@ -85,11 +86,9 @@ export default class BrepDebugger extends React.PureComponent {
<Section name='loops validation' accent>
loops validation...
</Section>
<Section name='loops filter' accent>
loops filter...
<Section name='face filter' accent>
{session.faceFilter && <FaceFilterExplorer {...session.faceFilter} group3d={brepDebugGroup} /> }
</Section>
</Section>)}
</div>
</div>;

View file

@ -0,0 +1,28 @@
import React from 'react';
import {FaceExplorer} from "./shellExplorer";
import Section from './section';
import {
getFacesViewObjects, InteractiveSection, TAB,
} from "./utils";
export function FaceFilterExplorer({connectedToAffectedFaces, allFaces, group3d}) {
connectedToAffectedFaces = connectedToAffectedFaces || [];
allFaces = allFaces || [];
let notConnectedToAffectedFaces = allFaces.filter(f => connectedToAffectedFaces.indexOf(f) === -1);
let category = 'face-filter';
let context = {connectedToAffectedFaces, notConnectedToAffectedFaces};
return <InteractiveSection name='analyzed faces' closable defaultClosed={false}
{...{viewObjectsProvider: getFacesViewObjects, topoObj: allFaces, group3d, category, context}}>
<Section name='connected to affected' tabs={TAB} accent>
{connectedToAffectedFaces.length === 0 ? '<empty>' : null }
{connectedToAffectedFaces.map((face, i) => <FaceExplorer key={i} {...{face, group3d, category, context}} />)}
</Section>
<Section name='not connected to affected' tabs={TAB} accent>
{notConnectedToAffectedFaces.length === 0 ? '<empty>' : null }
{notConnectedToAffectedFaces.map((face, i) => <FaceExplorer key={i} {...{face, group3d, category, context}} />)}
</Section>
</InteractiveSection>
}

View file

@ -1,7 +1,8 @@
import React, {Fragment as FR} from 'react';
import Section from "./section";
import {
ActiveLabel, Controls, getEdgesViewObjects, getEdgeViewObjects, getFaceViewObjects, getLoopsViewObjects,
ActiveLabel, Controls, getEdgesViewObjects, getEdgeViewObjects, getFacesViewObjects, getFaceViewObjects,
getLoopsViewObjects,
getLoopViewObjects,
getVertexViewObjects, InteractiveSection, mapIterable,
TAB
@ -11,12 +12,15 @@ export default class ShellExplorer extends React.PureComponent {
render() {
let {shell, group3d} = this.props;
let category='default';
let context = null;
let faces = shell ? shell.faces : [];
return <div className='shell-explorer'>
<Section name={`shell ${shell ? shell.refId : 'UNAVAILABLE'}`} closable>
{shell && shell.faces.map(face => <FaceExplorer key={face.refId} {...{face, group3d}} category='default' context={null} />)}
</Section>
</div>;
return <InteractiveSection name={`shell ${shell ? shell.refId : 'UNAVAILABLE'}`} closable defaultClosed={false}
{...{viewObjectsProvider: getFacesViewObjects, topoObj: faces, group3d, category, context}}>
{faces.map(face => <FaceExplorer key={face.refId} {...{face, group3d, category, context}} />)}
</InteractiveSection>;
}
}

View file

@ -3,6 +3,10 @@ import {AQUA, BLACK, BLUE, cycleColor, DETECTED_EDGE, DISCARDED_EDGE, GREEN, RED
import {distanceAB3} from "../../../math/math";
import Section from "./section";
export function getFacesViewObjects(group3d, category, context, out, faces) {
forEach(faces, getFaceViewObjects.bind(null, group3d, category, context, out));
}
export function getFaceViewObjects(group3d, category, context, out, face) {
return getLoopsViewObjects(group3d, category, context, out, face.loops);
}
@ -137,6 +141,14 @@ export function getInitColor(category, obj, context) {
return BLACK;
}
}
case 'face-filter': {
let {connectedToAffectedFaces, notConnectedToAffectedFaces} = context;
if (connectedToAffectedFaces.indexOf(obj.loop.face) > -1) {
return WHITE;
} else {
return BLACK;
}
}
default:
switch (obj.constructor.name) {
case 'HalfEdge': return SALMON;

View file

@ -137,7 +137,6 @@ export function BooleanAlgorithm( shellA, shellB, type ) {
faces = filterFaces(faces, shellA, shellB, type !== TYPE.UNION);
const result = new Shell();
faces.forEach(face => {
face.shell = result;
@ -403,6 +402,7 @@ function mergeFaces(facesA, facesB, opType) {
let detectedLoops = detectLoops(originFace.surface, graph);
for (let loop of detectedLoops) {
for (let edge of loop.halfEdges) {
EdgeSolveData.setPriority(edge, 1);
discardedEdges.delete(edge);
}
}
@ -561,39 +561,40 @@ function filterFaces(faces, a, b, isIntersection) {
if (FILTER_STRATEGY === FILTER_STRATEGIES.RAY_CAST) {
return filterByRayCast(faces, a, b, isIntersection);
} else if (FILTER_STRATEGY === FILTER_STRATEGIES.NEW_EDGES) {
return filterFacesByNewEdges(faces, a, b, isIntersection);
return filterFacesByNewEdges(faces);
} else {
throw 'unsupported';
}
}
function filterFacesByNewEdges(faces) {
function isFaceContainNewEdge(face) {
function doesFaceContainNewEdge(face) {
for (let e of face.edges) {
if (getPriority(e) > 0) {
if (getPriority(e) > 0 || getPriority(e.twin()) > 0) {
return true;
}
}
return false;
}
const validFaces = new Set(faces);
const result = new Set();
const resultSet = new Set();
for (let face of faces) {
// __DEBUG__.Clear();
// __DEBUG__.AddFace(face);
traverseFaces(face, validFaces, (it) => {
if (result.has(it) || isFaceContainNewEdge(it)) {
result.add(face);
traverseFaces(face, (it) => {
if (resultSet.has(it) || doesFaceContainNewEdge(it)) {
resultSet.add(face);
return true;
}
});
}
const result = Array.from(resultSet)
BREP_DEBUG.faceFilter(result, faces);
return result;
}
function traverseFaces(face, validFaces, callback) {
function traverseFaces(face, callback) {
const stack = [face];
const seen = new Set();
while (stack.length !== 0) {
@ -603,14 +604,9 @@ function traverseFaces(face, validFaces, callback) {
if (callback(face) === true) {
return;
}
if (!validFaces.has(face)) continue;
for (let loop of face.loops) {
for (let halfEdge of loop.halfEdges) {
for (let twin of halfEdge.twins()) {
if (validFaces.has(twin.loop.face)) {
stack.push(twin.loop.face)
}
}
stack.push(halfEdge.twin().loop.face);
}
}
}
@ -822,10 +818,6 @@ function transferEdges(faceSource, faceDest, operationType) {
continue;
}
if (edgeCollinearToFace(edge, faceDest)) {
//not coincide with an edge
if (!faceDest.rayCast(edge.edge.curve.middlePoint()).strictInside) {
continue;
}
let validEdge = chooseValidEdge(edge, faceDest, operationType);
BREP_DEBUG.transferEdge(edge, faceDest, validEdge);
let twin = validEdge.twin();