bool ManifoldManager::additionTest(Delaunay3::Cell_handle &cell) { bool additionManifold; int numV = 0; int numFound = 0; for (int curVertexId = 0; curVertexId < 4; ++curVertexId) { if (cell->vertex(curVertexId)->info().isUsed() > 0) { numFound++; } } numV = numFound; int numE = 0; for (int curEdgeId1 = 0; curEdgeId1 < 4; ++curEdgeId1) { for (int curEdgeId2 = curEdgeId1 + 1; curEdgeId2 < 4; ++curEdgeId2) { bool intersectionFound = false; Delaunay3::Edge curEdge(cell, curEdgeId1, curEdgeId2); Delaunay3::Cell_circulator cellCirc = dt_.incident_cells(curEdge, cell); Delaunay3::Cell_circulator cellCircInit = dt_.incident_cells(curEdge, cell); do { if (cellCirc->info().iskeptManifold()) { intersectionFound = true; } cellCirc++; } while (cellCirc != cellCircInit); if (intersectionFound) { numE++; } } } int numF = 0; for (int curNeighId = 0; curNeighId < 4; ++curNeighId) { bool intersectionFound = false; if (cell->neighbor(curNeighId)->info().iskeptManifold()) { intersectionFound = true; } if (intersectionFound) { numF++; } } if ((numV == 0 && numE == 0 && numF == 0) || (numV == 3 && numE == 3 && numF == 1) || (numV == 4 && numE == 5 && numF == 2) || (numV == 4 && numE == 6 && numF == 3) || (numV == 4 && numE == 6 && numF == 4)) { additionManifold = true; } else { additionManifold = false; } return additionManifold; }
bool ManifoldManager::subtractionTest(Delaunay3::Cell_handle &i) { bool subtractionManifold; int numV = 0; int numFound = 0; bool iskeptManif = i->info().iskeptManifold(); for (int curVertexId = 0; curVertexId < 4; ++curVertexId) { if (i->vertex(curVertexId)->info().isNotUsed()) { numFound++; } } numV = numFound; int numE = 0; for (int curEdgeId1 = 0; curEdgeId1 < 4; ++curEdgeId1) { for (int curEdgeId2 = curEdgeId1 + 1; curEdgeId2 < 4; ++curEdgeId2) { bool intersectionFound = false; Delaunay3::Edge curEdge(i, curEdgeId1, curEdgeId2); Delaunay3::Cell_circulator cellCirc = dt_.incident_cells(curEdge, i); Delaunay3::Cell_circulator cellCircInit = dt_.incident_cells(curEdge, i); do { if (cellCirc->info().iskeptManifold() != iskeptManif) { intersectionFound = true; } cellCirc++; } while (cellCirc != cellCircInit && intersectionFound == false); if (intersectionFound) { numE++; } } } /*COUNT NUM Facets in the intersection between tet cell and the current manifold*/ int numF = 0; for (int curNeighId = 0; curNeighId < 4; ++curNeighId) { bool intersectionFound = false; if (i->neighbor(curNeighId)->info().iskeptManifold() != iskeptManif) { numF++; } } if ((numV == 0 && numE == 0 && numF == 0) || (numV == 3 && numE == 3 && numF == 1) || (numV == 4 && numE == 5 && numF == 2) || (numV == 4 && numE == 6 && numF == 3) || (numV == 4 && numE == 6 && numF == 4)) { subtractionManifold = true; } else { subtractionManifold = false; } return subtractionManifold; }
// Build a 2D convex hull of the set of points. // This essentially giftwraps the points as it walks around the perimeter. int Convex2D( Vector2D const *pPoints, int nPoints, int *indices, int nMaxIndices ) { int nIndices = 0; bool touched[512]; int indexMap[512]; if( nPoints == 0 ) return 0; // If we don't collapse the points into a unique set, we can loop around forever // and max out nMaxIndices. nPoints = FindUniquePoints( pPoints, nPoints, indexMap, ARRAYSIZE( indexMap ), 0.1f ); memset( touched, 0, nPoints*sizeof(touched[0]) ); // Find the (lower) left side. int i; int iBest = 0; for( i=1; i < nPoints; i++ ) { if( pPoints[indexMap[i]].x < pPoints[indexMap[iBest]].x || (pPoints[indexMap[i]].x == pPoints[indexMap[iBest]].x && pPoints[indexMap[i]].y < pPoints[indexMap[iBest]].y) ) { iBest = i; } } touched[iBest] = true; indices[0] = indexMap[iBest]; nIndices = 1; Vector2D curEdge( 0, 1 ); // Wind around clockwise. while( 1 ) { Vector2D const *pStartPoint = &pPoints[ indices[nIndices-1] ]; float flEdgeAngle = atan2( curEdge.y, curEdge.x ); int iMinAngle = -1; float flMinAngle = 5000; for( i=0; i < nPoints; i++ ) { Vector2D vTo = pPoints[indexMap[i]] - *pStartPoint; float flDistToSqr = vTo.LengthSqr(); if ( flDistToSqr <= 0.1f ) continue; // Get the angle from the edge to this point. float flAngle = atan2( vTo.y, vTo.x ); flAngle = AngleOffset( flEdgeAngle, flAngle ); if( fabs( flAngle - flMinAngle ) < 0.00001f ) { float flDistToTestSqr = pStartPoint->DistToSqr( pPoints[iMinAngle] ); // If the angle is the same, pick the point farthest away. // unless the current one is closing the face loop if ( iMinAngle != indices[0] && flDistToSqr > flDistToTestSqr ) { flMinAngle = flAngle; iMinAngle = indexMap[i]; } } else if( flAngle < flMinAngle ) { flMinAngle = flAngle; iMinAngle = indexMap[i]; } } if( iMinAngle == -1 ) { // Couldn't find a point? Assert( false ); break; } else if( iMinAngle == indices[0] ) { // Finished. break; } else { // Add this point. if( nIndices >= nMaxIndices ) break; for ( int jj = 0; jj < nIndices; jj++ ) { // if this assert hits, this routine is broken and is generating a spiral // rather than a closed polygon - basically an edge overlap of some kind Assert(indices[jj] != iMinAngle ); } indices[nIndices] = iMinAngle; ++nIndices; } curEdge = pPoints[indices[nIndices-1]] - pPoints[indices[nIndices-2]]; } return nIndices; }
bool ManifoldManager::singleTetTest(Delaunay3::Cell_handle &cell) { bool iskeptManif = cell->info().iskeptManifold(); /*COUNT NUM VERTICES in the intersection between tet cell and the current manifold*/ int numV = 0; for (int curVertexId = 0; curVertexId < 4; ++curVertexId) { std::vector<Delaunay3::Cell_handle> incidentCells; dt_.incident_cells(cell->vertex(curVertexId), std::back_inserter(incidentCells)); auto it = incidentCells.begin(); bool found = false; while (it != incidentCells.end() && found == false) { if ((*it)->info().iskeptManifold() != iskeptManif) { found = true; } it++; } if (found) { numV++; } } /*COUNT NUM Edges in the intersection between tet cell and the current manifold*/ int numE = 0; for (int curEdgeId1 = 0; curEdgeId1 < 4; ++curEdgeId1) { for (int curEdgeId2 = curEdgeId1 + 1; curEdgeId2 < 4; ++curEdgeId2) { bool intersectionFound = false; Delaunay3::Edge curEdge(cell, curEdgeId1, curEdgeId2); Delaunay3::Cell_circulator cellCirc = dt_.incident_cells(curEdge, cell); Delaunay3::Cell_circulator cellCircInit = dt_.incident_cells(curEdge, cell); do { if (cellCirc->info().iskeptManifold() != iskeptManif) { intersectionFound = true; } cellCirc++; } while (cellCirc != cellCircInit && intersectionFound == false); if (intersectionFound) { numE++; } } } /*COUNT NUM Facets in the intersection between tet cell and the current manifold*/ int numF = 0; for (int curNeighId = 0; curNeighId < 4; ++curNeighId) { bool intersectionFound = false; if (cell->neighbor(curNeighId)->info().iskeptManifold() != iskeptManif) { numF++; } } if ((numV == 0 && numE == 0 && numF == 0) || (numV == 3 && numE == 3 && numF == 1) || (numV == 4 && numE == 5 && numF == 2) || (numV == 4 && numE == 6 && numF == 3) || (numV == 4 && numE == 6 && numF == 4)) { return true; } else { return false; } }