diff --git a/SurfTriMesh.cpp b/SurfTriMesh.cpp index bd21a5a..90e5448 100644 --- a/SurfTriMesh.cpp +++ b/SurfTriMesh.cpp @@ -3301,7 +3301,7 @@ SurfTriMesh::Invert( void) bool SurfTriMesh::Cut( const Plane3d& plPlane, bool bSaveOnEq) { -#define UseTria 1 +#define UseTria 0 #if UseTria // la superficie deve essere validata if ( m_nStatus != OK) @@ -3517,7 +3517,7 @@ SurfTriMesh::Cut( const Plane3d& plPlane, bool bSaveOnEq) return true ; #else - + bool bModif = false ; // Setto i triangoli come né fuori né dentro. @@ -3539,6 +3539,21 @@ SurfTriMesh::Cut( const Plane3d& plPlane, bool bSaveOnEq) PtrOwner pReg( GetBasicSurfFlatRegion( GetSurfFlatRegionFromPolyLineVector( vLoopVec))) ; if ( IsNull( pReg)) return false ; + ////////////////////////////////////////// + BBox3d b3Box( Point3d( 653, -97.4, 4), Point3d(654,-97.3,5)); + BBox3d b3RegBox; + pReg->GetLocalBBox(b3RegBox); + if (b3Box.Overlaps(b3RegBox)) + int mimi = 0; + if (/*nF == 1349 ||*/ nF == 1350) { + /*INTVECTOR vT ; + GetAllTriaInFacet( nF, vT) ; + for ( auto& nT : vT) + m_vTria[nT].nTempPart = - 1 ; + continue;*/ + int qq = 0; + } + ////////////////////////////////////////// LineFacetClassVector IntersLinePart ; int nIntType = IntersFacetPlane( *pReg, vLoopVec[0], plPlane, IntersLinePart) ; if ( nIntType == FacetPlaneIntersType::FPI_CUT) { @@ -3551,7 +3566,7 @@ SurfTriMesh::Cut( const Plane3d& plPlane, bool bSaveOnEq) else { IntersLineMap.emplace( nF, IntersInnChain( 1, IntersInnSeg( IntersLinePart[nPart].ptSt, IntersLinePart[nPart].ptEn))) ; } - } + } } else if ( nIntType == FacetPlaneIntersType::FPI_ON) { INTVECTOR vT ; @@ -3575,12 +3590,16 @@ SurfTriMesh::Cut( const Plane3d& plPlane, bool bSaveOnEq) ; } - // Divido le facce. + // Divido e ritriangolo le facce. PieceMap NewFacet ; SplitFacet( IntersLineMap, NewFacet) ; INTERSEDGEMAP EdgeInterLineMap, EdgeEdgeLineMap ; RetriangulateFacetPieces( NewFacet, EdgeInterLineMap, EdgeEdgeLineMap) ; - + if ( ! AdjustVertices() || ! DoCompacting()) + return false ; + // Identifico le parti + IdentifyParts() ; + // Elimino i triangoli fuori dal semi-spazio d'interesse. int nNumTria = GetTriangleSize() ; for ( int nT = 0 ; nT < nNumTria ; ++ nT) if ( m_vTria[nT].nTempPart == - 1 || m_vTria[nT].nTempPart == - 2 || ( ! bSaveOnEq && m_vTria[nT].nTempPart == 2)) diff --git a/SurfTriMesh.h b/SurfTriMesh.h index bc72487..158a81a 100644 --- a/SurfTriMesh.h +++ b/SurfTriMesh.h @@ -133,6 +133,10 @@ typedef std::vector LineFacetClassVector ; //---------------------------------------------------------------------------- enum FacetPlaneIntersType { FPI_ERROR = 0, FPI_CUT = 1, FPI_INN = 2, FPI_OUT = 3, FPI_ON = 4 } ; + +//---------------------------------------------------------------------------- +enum LineClassificationWithExtPolygon { LCP_ERROR = 0, LCP_INN = 1, LCP_OUT = 2, LCP_OVERLAP = 3 } ; + //---------------------------------------------------------------------------- // Definizione strutture e contenitori // Contatti interno-interno diff --git a/SurfTriMeshBooleans.cpp b/SurfTriMeshBooleans.cpp index 6a7fcef..df54f0d 100644 --- a/SurfTriMeshBooleans.cpp +++ b/SurfTriMeshBooleans.cpp @@ -2427,11 +2427,12 @@ SurfTriMesh::Intersect( const ISurfTriMesh& Other) m_OGrMgr.Clear() ; SurfTriMesh SurfB ; SurfB.CopyFrom( &Other) ; - Frame3d frScalingRef ; - frScalingRef.Set( m_vVert[0].ptP, X_AX, Y_AX, Z_AX) ; - Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ; - SurfB.Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ; - IntersectTriMeshTriangle( SurfB) ; + //Frame3d frScalingRef ; + //frScalingRef.Set( m_vVert[0].ptP, X_AX, Y_AX, Z_AX) ; + //Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ; + //SurfB.Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ; + //IntersectTriMeshTriangle( SurfB) ; + ItersectTriMeshFacets( SurfB) ; IdentifyParts() ; SurfB.IdentifyParts() ; int nTriaNumA = GetTriangleSize() ; @@ -2453,11 +2454,11 @@ SurfTriMesh::Intersect( const ISurfTriMesh& Other) } } bool bOk = ( AdjustVertices() && DoCompacting()) ; - bOk && RemoveTripleTriangles() ; - bOk = bOk && ( AdjustVertices() && DoCompacting()) ; + //bOk && RemoveTripleTriangles() ; + //bOk = bOk && ( AdjustVertices() && DoCompacting()) ; bOk && RemoveTJunctions() ; bOk = bOk && ( AdjustVertices() && DoCompacting()) ; - Scale( frScalingRef, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE) ; + //Scale( frScalingRef, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE) ; return bOk ; } @@ -2811,6 +2812,136 @@ SurfTriMesh::IntersFacetFacet( const SurfFlatRegion& RegionA, const PolyLine& Ex // return bOk ; //} +static bool +GetLineExtPolygonClassification( const POLYLINEVECTOR& vContourVec, const Point3d& ptSt, const Point3d& ptEn, + CRVCVECTOR& vLinePart) +{ + // Se i contorni non definiscono un poligono esteso o la retta non giace sul piano di quest'ultimo, non ha senso procedere. + double dArea ; + Plane3d plPlane ; + if ( vContourVec.empty() || ! vContourVec[0].IsClosedAndFlat( plPlane, dArea) || + DistPointPlane( ptSt, plPlane) > EPS_SMALL || DistPointPlane( ptEn, plPlane) > EPS_SMALL) + return false ; + + // Pulisco il vettore delle parti. + vLinePart.clear() ; + + // Proietto tutti i punti sul piano per eliminare eventuali deviazioni. + POLYLINEVECTOR vMyContourVec ; + for ( int nC = 0 ; nC < int( vContourVec.size()) ; ++ nC) { + vMyContourVec.emplace_back() ; + Point3d ptP ; + bool bContinue = vContourVec[nC].GetFirstPoint( ptP) ; + while ( bContinue) { + vMyContourVec.back().AddUPoint( 0, ProjectPointOnPlane( ptP, plPlane)) ; + bContinue = vContourVec[nC].GetNextPoint( ptP) ; + } + } + Point3d ptMySt = ProjectPointOnPlane( ptSt, plPlane) ; + Point3d ptMyEn = ProjectPointOnPlane( ptEn, plPlane) ; + Vector3d vtLineDir = ptMyEn - ptMySt ; + double dLen = vtLineDir.Len() ; + vtLineDir /= dLen ; + + // Intersezione della linea con i contoni + ICCIVECTOR vIntInfoVec ; + CurveLine cvLine ; + cvLine.Set( ptMySt, ptMyEn) ; + for ( int nC = 0 ; nC < int( vMyContourVec.size()) ; ++ nC) { + Point3d ptSegS, ptSegE ; + bool bContinue = vMyContourVec[nC].GetFirstPoint( ptSegS) && vMyContourVec[nC].GetNextPoint( ptSegE) ; + while ( bContinue) { + vMyContourVec.back().AddUPoint( 0, ProjectPointOnPlane( ptP, plPlane)) ; + CurveLine cvSeg ; + cvSeg.Set( ptMySt, ptMyEn) ; + IntersLineLine( cvLine, cvSeg) ; + IntCrvCrvInfo aInfo ; + if ( IntersLineLine.GetIntCrvCrvInfo(aInfo)) ; + vIntInfoVec.emplace_back( aInfo) ; + ptSegS = ptSegE ; + bContinue = vMyContourVec[nC].GetNextPoint( ptSegE) ; + } + } + + // Riordino le intersezioni e unisco le parti sovrapposte. + sort( vIntInfoVec.begin(), vIntInfoVec.end(), [] ( IntCrvCrvInfo Int1, IntCrvCrvInfo Int2) { return Int1.IciA[0] < Int2.IciA[0] ; }) ; + for ( int n = 0 ; n < int( vIntInfoVec.size()) - 1 ; ++ n) { + for ( int m = n + 1 ; vIntInfoVec[n].bOverlap && m < int( vIntInfoVec.size()) ; ++ m) { + if ( vIntInfoVec[n].IciA[1] > vIntInfoVec[m].IciA[0]) { + if ( vIntInfoVec[m].bOverlap && vIntInfoVec[n].IciA[1] < vIntInfoVec[m].IciA[1]) { + vIntInfoVec[n].IciA[1] = vIntInfoVec[m].IciA[1] ; + } + vIntInfoVec.erase( vIntInfoVec.begin() + m) ; + -- m ; + } + } + } + + // Definisco le parti di linea dentro il poligono esteso. + bool bStateInside = true ; + for ( int nC = 0 ; nC < int( vMyContourVec.size()) ; ++ nC) { + bStateInside = bStateInside || IsPointInsidePolyLine( ptMySt, vMyContourVec[nC]) ; + } + if ( bStateInside) + vLinePart.emplace_back( 0, -1, LCP_ERROR) ; + for ( int n = 0 ; n < int( vIntInfoVec.size()) ; ++ n) { + // La linea è dentro. + if ( bStateInside) { + // Segno che chiudiamo una parte d'intersezione. + bStateInside = false ; + // L'intersezione corrente è un segmento. + if ( vIntInfoVec[n].bOverlap) { + // Si chiude la parte precedente e si aggiunge un segmeno + if ( vIntInfoVec[n].IciA[0] > vLinePart.back().dParS + EPS_SMALL) { + vLinePart.back().dParE = vLinePart.back().dParS ; + vLinePart.back().nClass = LCP_OVERLAP ; + vLinePart.emplace_back( vIntInfoVec[n].IciA[0], vIntInfoVec[n].IciA[1], LCP_OVERLAP) ; + } + // Si promuove l'intersezione precedente a un segmento. + else { + vLinePart.back().dParE = vIntInfoVec[n].IciA[1] ; + vLinePart.back().nClass = LCP_OVERLAP ; + } + } + // L'intersezione corrente è un punto: chiudiamo la parte precedente. + else { + vLinePart.back().dParE = vIntInfoVec[n].IciA[0] ; + vLinePart.back().nClass = LCP_INN ; + } + } + // La linea è fuori + else { + // L'intersezione corrente è un segmento. + if ( vIntInfoVec[n].bOverlap) { + // Apro e chiudo una nuova parte. + vLinePart.emplace_back( vIntInfoVec[n].IciA[0], vIntInfoVec[n].IciA[1], CRVC_ON_P) ; + } + // L'intersezione corrente è un punto: chiudiamo la parte precedente. + else { + // Segno che apro una nuova parte. + bStateInside = true ; + // Apro una nuova parte. + vLinePart.emplace_back( vIntInfoVec[n].IciA[0], - Infinito, LCP_INN) ; + } + } + } + + // Controllo che non ci siano incongruenze: se tutti gli ingressi + // e le uscite sono ordinate, dovrebbe essere tutto ok. + for ( int n = 0 ; n < int( vLinePart.size()) ; ++ n) { + if ( vLinePart[n].dParS > vLinePart[n].dParE) + return false ; + if ( n + 1 < int( vLinePart.size()) && vLinePart[n].dParE > vLinePart[n + 1].dParS) + return false ; + /*for ( int m = n + 1 ; m < int( vLinePart.size()) ; ++ m) { + if ( vLinePart[n].dParE > vLinePart[m].dParS) + return false ; + }*/ + } + + return true ; +} + //---------------------------------------------------------------------------- static bool ChangePolyLineStart( const Point3d& ptNewStart, PolyLine& Loop) @@ -3192,14 +3323,12 @@ bool SurfTriMesh::SplitFacet( const INTERSCHAINMAP& IntersLineMap, PieceMap& NewFacet) { for ( auto it = IntersLineMap.begin() ; it != IntersLineMap.end() ; ++ it) { - if (it->first == 5591) - int qqq = 0; // Normale alla faccia Vector3d vtFacetNorm ; GetFacetNormal( it->first, vtFacetNorm) ; // Creo i loop ChainCurves LoopCreator ; - LoopCreator.Init( false, 10 * EPS_SMALL, int( it->second.size()), 10) ; + LoopCreator.Init( false, 10 * EPS_SMALL, int( it->second.size()), 10 /** BOOLEAN_SCALE*/) ; // Carico le curve per concatenarle for ( int nCv = 0 ; nCv < int( it->second.size()); ++ nCv) { Point3d ptSt = it->second[nCv].ptSt ; @@ -4606,10 +4735,6 @@ SurfTriMesh::ItersectTriMeshFacets( SurfTriMesh& Other) int nFacetNumA = GetFacetCount() ; int nFacetNumB = SurfB.GetFacetCount() ; for ( int nFA = 0 ; nFA < nFacetNumA ; ++ nFA) { - ///////////////////////////////////////////////////////// - if (nFA == 129) - int mimi = 0; - ///////////////////////////////////////////////////////// // Dati della faccia POLYLINEVECTOR LoopVecA ; GetFacetLoops( nFA, LoopVecA) ; @@ -4778,22 +4903,6 @@ SurfTriMesh::ItersectTriMeshFacets( SurfTriMesh& Other) } } - ///////////////////////////////////////////////////////////////////////////////// - for ( int nFB = 0 ; nFB < nFacetNumB ; ++ nFB) { - // Dati della faccia - POLYLINEVECTOR LoopVecB ; - SurfB.GetFacetLoops( nFB, LoopVecB) ; - PtrOwner pRegB( GetBasicSurfFlatRegion( GetSurfFlatRegionFromPolyLineVector( LoopVecB))) ; - if ( pRegB == nullptr) - return false ; - SurfFlatRegion RegionB = *pRegB ; - /*Plane3d plPlaneB ;*/ - /*plPlaneB.Set( RegionB.GetPlanePoint(), RegionB.GetNormVersor()) ;*/ - if (RegionB.GetNormVersor().x > 0.99) - int m = 0; - } - ///////////////////////////////////////////////////////////////////////////////// - // Divido le facce PieceMap NewFacetA, NewFacetB ; SplitFacet( IntersLineMapA, NewFacetA) ; @@ -5010,18 +5119,6 @@ SurfTriMesh::ItersectTriMeshFacets( SurfTriMesh& Other) frIntersRegion.Intersect( RegionB) ; double dIntersRegArea ; frIntersRegion.GetArea( dIntersRegArea) ; - /*bool bOverlap = dIntersRegArea > EPS_SMALL ; - double dRegionAreaA ; - RegionA.GetArea( dRegionAreaA) ; - double dRegionAreaB ; - RegionB.GetAera( dRegionAreaB) ; - if ( ( abs( dIntersRegArea - dRegionAreaA) < EPS_SMALL && dRegionAreaA < 0.75 * dRegionAreaB) || - ( abs( dIntersRegArea - dRegionAreaB) < EPS_SMALL && dRegionAreaB < 0.75 * dRegionAreaA)) { - if ( ) - bOverlap = ; - else - bOverlap = ; - }*/ // Assegno indice di parte al pezzo di faccia A e ai triangoli della faccia B. if ( dIntersRegArea > EPS_SMALL) { bool bCodirectedNorm = plPlaneA.GetVersN() * plPlaneB.GetVersN() > 0 ; @@ -5098,10 +5195,6 @@ SurfTriMesh::ItersectTriMeshFacets( SurfTriMesh& Other) if ( n == int( vFacetIndexesB.size())) vFacetIndexesB.emplace_back( nF) ; } - ///////////////////////////////////////////////////////// - if (nFA == 129) - int mimi = 0; - ///////////////////////////////////////////////////////// // Ciclo sulle facce di B for ( int& nFB : vFacetIndexesB) { auto itFacetB = NewFacetB.find( nFB) ;