Boolean op are undeffined when one of the two meshes are a no closed mesh (without holes).

I put a test to check the input meshes before do any thing. If one mesh have holes a error code is returned.
This commit is contained in:
Marc Freixas 2005-11-30 17:35:54 +00:00
parent b7a4a6c837
commit 738d3e4ae3
5 changed files with 91 additions and 64 deletions

@ -146,7 +146,7 @@ void BOP_mergeVertexs(BOP_Mesh *mesh, unsigned int firstFace);
* @param facesB set of faces from object B
*/
void BOP_Face2Face(BOP_Mesh *mesh, BOP_Faces *facesA, BOP_Faces *facesB)
{
{
for(unsigned int idxFaceA=0;idxFaceA<facesA->size();idxFaceA++) {
BOP_Face *faceA = (*facesA)[idxFaceA];
MT_Plane3 planeA = faceA->getPlane();
@ -160,28 +160,28 @@ void BOP_Face2Face(BOP_Mesh *mesh, BOP_Faces *facesA, BOP_Faces *facesB)
idxFaceB<facesB->size() && (faceA->getTAG() != BROKEN) && (faceA->getTAG() != PHANTOM);) {
BOP_Face *faceB = (*facesB)[idxFaceB];
if ((faceB->getTAG() != BROKEN) && (faceB->getTAG() != PHANTOM)) {
BOP_BBox boxB(mesh->getVertex(faceB->getVertex(0))->getPoint(),
mesh->getVertex(faceB->getVertex(1))->getPoint(),
mesh->getVertex(faceB->getVertex(2))->getPoint());
if (boxA.intersect(boxB)) {
BOP_BBox boxB(mesh->getVertex(faceB->getVertex(0))->getPoint(),
mesh->getVertex(faceB->getVertex(1))->getPoint(),
mesh->getVertex(faceB->getVertex(2))->getPoint());
if (boxA.intersect(boxB)) {
MT_Plane3 planeB = faceB->getPlane();
if (BOP_containsPoint(planeB,p1) &&
BOP_containsPoint(planeB,p2) &&
BOP_containsPoint(planeB,p3)) {
if (BOP_orientation(planeB,planeA)>0) {
BOP_intersectCoplanarFaces(mesh,facesB,faceA,faceB,false);
}
}
else {
BOP_intersectNonCoplanarFaces(mesh,facesA,facesB,faceA,faceB);
}
}
MT_Plane3 planeB = faceB->getPlane();
if (BOP_containsPoint(planeB,p1) &&
BOP_containsPoint(planeB,p2) &&
BOP_containsPoint(planeB,p3)) {
if (BOP_orientation(planeB,planeA)>0) {
BOP_intersectCoplanarFaces(mesh,facesB,faceA,faceB,false);
}
}
else {
BOP_intersectNonCoplanarFaces(mesh,facesA,facesB,faceA,faceB);
}
}
}
if (faceB->getTAG()==BROKEN){
facesB->erase(facesB->begin()+idxFaceB);
facesB->erase(facesB->begin()+idxFaceB);
}else
idxFaceB++;
idxFaceB++;
}
}

@ -92,9 +92,9 @@ BoolOpState BOP_performBooleanOperation(BoolOpType opType,
CSG_VertexIteratorDescriptor obBVertices,
CSG_InterpolateUserFaceVertexDataFunc interpFunc)
{
#ifdef DEBUG
#ifdef DEBUG
cout << "BEGIN BOP_performBooleanOperation" << endl;
#endif
#endif
// Set invert flags depending on boolean operation type:
// INTERSECTION: A^B = and(A,B)
@ -121,6 +121,9 @@ BoolOpState BOP_performBooleanOperation(BoolOpType opType,
// Add B-mesh into C-mesh
BOP_addMesh(&meshC, &meshBFacesId, &materials, obBProps, obBFaces, obBVertices, invertMeshB);
if (!meshC.isClosedMesh())
return BOP_NO_SOLID;
// Perform the intersection boolean operation.
BoolOpState result = BOP_intersectionBoolOp(&meshC, &meshAFacesId, &meshBFacesId,
invertMeshA, invertMeshB);
@ -128,9 +131,9 @@ BoolOpState BOP_performBooleanOperation(BoolOpType opType,
// Invert the output mesh if is required
*outputMesh = BOP_exportMesh(&meshC, &materials, outputProps, invertMeshC);
#ifdef DEBUG
#ifdef DEBUG
cout << "END BOP_performBooleanOperation" << endl;
#endif
#endif
return result;
}
@ -151,13 +154,13 @@ BoolOpState BOP_intersectionBoolOp(BOP_Mesh* meshC,
bool invertMeshA,
bool invertMeshB)
{
#ifdef DEBUG
#ifdef DEBUG
BOP_Chrono chrono;
float t = 0.0f;
float c = 0.0f;
chrono.start();
cout << "---" << endl;
#endif
#endif
// Create BSPs trees for mesh A & B
BOP_BSPTree bspA;
@ -168,10 +171,10 @@ BoolOpState BOP_intersectionBoolOp(BOP_Mesh* meshC,
bspB.addMesh(meshC, *facesB);
bspB.computeBox();
#ifdef DEBUG
#ifdef DEBUG
c = chrono.stamp(); t += c;
cout << "Create BSP " << c << endl;
#endif
#endif
unsigned int numVertices = meshC->getNumVertexs();
@ -184,54 +187,54 @@ BoolOpState BOP_intersectionBoolOp(BOP_Mesh* meshC,
if ((0.25*facesB->size()) > bspA.getDeep())
BOP_meshFilter(meshC, facesB, &bspA);
#ifdef DEBUG
#ifdef DEBUG
c = chrono.stamp(); t += c;
cout << "mesh Filter " << c << endl;
#endif
#endif
// Face 2 Face
BOP_Face2Face(meshC,facesA,facesB);
#ifdef DEBUG
#ifdef DEBUG
c = chrono.stamp(); t += c;
cout << "Face2Face " << c << endl;
#endif
#endif
// BSP classification
BOP_meshClassify(meshC,facesA,&bspB);
BOP_meshClassify(meshC,facesB,&bspA);
#ifdef DEBUG
#ifdef DEBUG
c = chrono.stamp(); t += c;
cout << "Classification " << c << endl;
#endif
#endif
// Process overlapped faces
BOP_removeOverlappedFaces(meshC,facesA,facesB);
#ifdef DEBUG
#ifdef DEBUG
c = chrono.stamp(); t += c;
cout << "Remove overlap " << c << endl;
#endif
#endif
// Sew two meshes
BOP_sew(meshC,facesA,facesB);
#ifdef DEBUG
#ifdef DEBUG
c = chrono.stamp(); t += c;
cout << "Sew " << c << endl;
#endif
#endif
// Merge faces
BOP_Merge::getInstance().mergeFaces(meshC,numVertices);
#ifdef DEBUG
#ifdef DEBUG
c = chrono.stamp(); t += c;
cout << "Merge faces " << c << endl;
cout << "Total " << t << endl;
// Test integrity
meshC->testMesh();
#endif
#endif
return BOP_OK;
}

@ -553,6 +553,23 @@ BOP_Index BOP_Mesh::replaceVertexIndex(BOP_Index oldIndex, BOP_Index newIndex)
return newIndex;
}
bool BOP_Mesh::isClosedMesh()
{
for(unsigned int i=0; i<m_edges.size(); i++) {
BOP_Edge *edge = m_edges[i];
BOP_Indexs faces = edge->getFaces();
unsigned int count = 0;
const BOP_IT_Indexs facesEnd = faces.end();
for(BOP_IT_Indexs it = faces.begin();it!=facesEnd;it++) {
if (m_faces[*it]->getTAG()!=BROKEN)
count++;
}
if ((count%2)!=0) return false;
}
return true;
}
/** ***************************************************************************

@ -82,6 +82,7 @@ public:
unsigned int getNumVertexs(BOP_TAG tag);
unsigned int getNumFaces(BOP_TAG tag);
BOP_Index replaceVertexIndex(BOP_Index oldIndex, BOP_Index newIndex);
bool isClosedMesh();
// Debug functions
void print();

@ -103,15 +103,15 @@ CSG_DescibeOperands(
/**
* Compute the boolean operation, UNION, INTERSECION or DIFFERENCE
*/
int
int
CSG_PerformBooleanOperation(
CSG_BooleanOperation *operation,
CSG_OperationType op_type,
CSG_FaceIteratorDescriptor obAFaces,
CSG_VertexIteratorDescriptor obAVertices,
CSG_FaceIteratorDescriptor obBFaces,
CSG_VertexIteratorDescriptor obBVertices,
CSG_InterpolateUserFaceVertexDataFunc interp_func
CSG_BooleanOperation *operation,
CSG_OperationType op_type,
CSG_FaceIteratorDescriptor obAFaces,
CSG_VertexIteratorDescriptor obAVertices,
CSG_FaceIteratorDescriptor obBFaces,
CSG_VertexIteratorDescriptor obBVertices,
CSG_InterpolateUserFaceVertexDataFunc interp_func
){
if (operation == NULL) return 0;
BSP_MeshInfo * mesh_info = static_cast<BSP_MeshInfo *>(operation->CSG_info);
@ -128,33 +128,39 @@ CSG_PerformBooleanOperation(
switch( op_type ) {
case e_csg_union:
boolType = BOP_UNION;
break;
boolType = BOP_UNION;
break;
case e_csg_difference:
boolType = BOP_DIFFERENCE;
break;
boolType = BOP_DIFFERENCE;
break;
default:
boolType = BOP_INTERSECTION;
break;
boolType = BOP_INTERSECTION;
break;
}
BoolOpState boolOpResult;
try {
BOP_performBooleanOperation( boolType,
mesh_info->output_descriptor,
(BSP_CSGMesh**) &(mesh_info->output_mesh),
mesh_info->obB_descriptor,
obBFaces,
obBVertices,
mesh_info->obA_descriptor,
obAFaces,
obAVertices,
interp_func );
boolOpResult= BOP_performBooleanOperation( boolType,
mesh_info->output_descriptor,
(BSP_CSGMesh**) &(mesh_info->output_mesh),
mesh_info->obB_descriptor,
obBFaces,
obBVertices,
mesh_info->obA_descriptor,
obAFaces,
obAVertices,
interp_func );
}
catch(...) {
return 0;
}
return success;
switch (boolOpResult) {
case BOP_OK: return 1;
case BOP_NO_SOLID: return -2;
case BOP_ERROR: return 0;
default: return 1;
}
}
int