diff --git a/CDeTriaTria.cpp b/CDeTriaTria.cpp index 23a2f0a..1472bfd 100644 --- a/CDeTriaTria.cpp +++ b/CDeTriaTria.cpp @@ -109,7 +109,7 @@ CDeTriaTria( const Triangle3d& trTriaA, const Triangle3d& trTriaB) DistLineLine LineLineDistCalc( ptStA, PtEnA, ptStB, PtEnB) ; double dSqSegSegDist ; LineLineDistCalc.GetSqDist( dSqSegSegDist) ; - if ( dSqSegSegDist < EPS_SMALL * EPS_SMALL) + if ( dSqSegSegDist < SQ_EPS_SMALL) return true ; } } @@ -136,14 +136,14 @@ CDeTriaTria( const Triangle3d& trTriaA, const Triangle3d& trTriaB) vtSegFirstA /= dSegLenFirstA ; DistLineLine LineLineDistCalcFirstA( ptLineP, vtLineV, 100., trTriaA.GetP( nFirstMaxPosA), vtSegFirstA, dSegLenFirstA, false) ; double dIntParStA, dOtherParFirstA ; - LineLineDistCalcFirstA.GetParamsAtMinDistPoints( dIntParStA, dOtherParFirstA) ; + LineLineDistCalcFirstA.GetPositionsAtMinDistPoints( dIntParStA, dOtherParFirstA) ; // Limito la retta col secondo segmento trovato di A Vector3d vtSegSecondA = trTriaA.GetP( ( nSecondMaxPosA + 1) % 3) - trTriaA.GetP( nSecondMaxPosA) ; double dSegLenSecondA = vtSegSecondA.Len() ; vtSegSecondA /= dSegLenSecondA ; DistLineLine LineLineDistCalcSecondA( ptLineP, vtLineV, 100., trTriaA.GetP( nSecondMaxPosA), vtSegSecondA, dSegLenSecondA, false) ; double dIntParEnA, dOtherParSecondA ; - LineLineDistCalcSecondA.GetParamsAtMinDistPoints( dIntParEnA, dOtherParSecondA) ; + LineLineDistCalcSecondA.GetPositionsAtMinDistPoints( dIntParEnA, dOtherParSecondA) ; // Ordino i parametri lungo la retta di intersezione fra i piani if ( dIntParStA > dIntParEnA) { swap( dIntParStA, dIntParEnA) ; @@ -163,14 +163,14 @@ CDeTriaTria( const Triangle3d& trTriaA, const Triangle3d& trTriaB) vtSegFirstB /= dSegLenFirstB ; DistLineLine LineLineDistCalcFirstB( ptLineP, vtLineV, 100., trTriaB.GetP( nFirstMaxPosB), vtSegFirstB, dSegLenFirstB, false) ; double dIntParStB, dOtherParFirstB ; - LineLineDistCalcFirstB.GetParamsAtMinDistPoints( dIntParStB, dOtherParFirstB) ; + LineLineDistCalcFirstB.GetPositionsAtMinDistPoints( dIntParStB, dOtherParFirstB) ; // Limito la retta col secondo segmento trovato di B Vector3d vtSegSecondB = trTriaB.GetP( ( nSecondMaxPosB + 1) % 3) - trTriaB.GetP( nSecondMaxPosB) ; double dSegLenSecondB = vtSegSecondB.Len() ; vtSegSecondB /= dSegLenSecondB ; DistLineLine LineLineDistCalcSecondB( ptLineP, vtLineV, 100., trTriaB.GetP( nSecondMaxPosA), vtSegSecondB, dSegLenSecondB, false) ; double dIntParEnB, dOtherParSecondB ; - LineLineDistCalcSecondB.GetParamsAtMinDistPoints( dIntParEnB, dOtherParSecondB) ; + LineLineDistCalcSecondB.GetPositionsAtMinDistPoints( dIntParEnB, dOtherParSecondB) ; // Ordino i parametri lungo la retta di intersezione fra i piani if ( dIntParStB > dIntParEnB) { swap( dIntParStB, dIntParEnB) ; diff --git a/DistLineLine.cpp b/DistLineLine.cpp index a9081dc..eab126b 100644 --- a/DistLineLine.cpp +++ b/DistLineLine.cpp @@ -18,6 +18,8 @@ #include "/EgtDev/Include/EGkGeoConst.h" #include +using namespace std ; + //---------------------------------------------------------------------------- DistLineLine::DistLineLine( const Point3d& ptSt1, const Point3d& ptEn1, const Point3d& ptSt2, const Point3d& ptEn2, @@ -57,6 +59,7 @@ DistLineLine::GetSqDist( double& dSqDist) { if ( m_dSqDist < 0) return false ; + dSqDist = m_dSqDist ; return true ; } @@ -67,7 +70,10 @@ DistLineLine::GetDist( double& dDist) { if ( m_dSqDist < 0) return false ; - dDist = sqrt( m_dSqDist) ; + + if ( m_dDist < 0) + m_dDist = sqrt( m_dSqDist) ; + dDist = m_dDist ; return true ; } @@ -84,55 +90,48 @@ DistLineLine::GetMinDistPoints( Point3d& ptMinDist1, Point3d& ptMinDist2) //---------------------------------------------------------------------------- bool -DistLineLine::GetParamsAtMinDistPoints( double& dPar1, double& dPar2) +DistLineLine::GetPositionsAtMinDistPoints( double& dPos1, double& dPos2) { if ( m_dSqDist < 0) return false ; - dPar1 = m_dPar1 ; - dPar2 = m_dPar2 ; + dPos1 = m_dPos1 ; + dPos2 = m_dPos2 ; return true ; } //---------------------------------------------------------------------------- -// Calcola la distanza fra i due elemnti lineari, i punti di minima distanza e -// i loro rispettivi parametri. -// Se la coppia di punti di minima distanza non è unica ne viene scelta una -// in base a comodità di calcolo. +// Calcola la distanza fra i due elementi lineari, i punti di minima distanza e le loro posizioni. +// Se i due elementi sono paralleli i punti di minimo sono scelti secondo convenienza. void DistLineLine::Calculate( const Point3d& ptSt1, const Vector3d& vtD1, double dLen1, const Point3d& ptSt2, const Vector3d& vtD2, double dLen2, bool bIsSegment1, bool bIsSegment2) { - // Caso di elementi lineari paralleli/antiparalleli + // Se elementi paralleli o antiparalleli if ( AreSameOrOppositeVectorExact( vtD1, vtD2)) { - // Almeno un elemento è una retta - if ( ! ( bIsSegment1 && bIsSegment2)) { - // Il primo elemento è segmento, quindi deve essere una retta il secondo - if ( bIsSegment1) { - Vector3d vtStSt = ptSt1 - ptSt2 ; - double dLong = vtStSt * vtD2 ; - Vector3d vtDist = vtStSt - dLong * vtD2 ; - m_dSqDist = vtDist.SqLen() ; - m_dDist = sqrt( m_dSqDist) ; - m_dPar1 = 0 ; - m_dPar2 = dLong ; - m_ptMinDist1 = ptSt1 ; - m_ptMinDist2 = ptSt2 + dLong * vtD2 ; - } - // Il primo elemento è una retta - else { - Vector3d vtStSt = ptSt2 - ptSt1 ; - double dLong = vtStSt * vtD1 ; - Vector3d vtDist = vtStSt - dLong * vtD1 ; - m_dSqDist = vtDist.SqLen() ; - m_dDist = sqrt( m_dSqDist) ; - m_dPar1 = dLong ; - m_dPar2 = 0 ; - m_ptMinDist1 = ptSt1 + dLong * vtD1 ; - m_ptMinDist2 = ptSt2 ; - } + // Se il primo elemento è una retta infinita + if ( ! bIsSegment1) { + Vector3d vtStSt = ptSt2 - ptSt1 ; + double dLong = vtStSt * vtD1 ; + Vector3d vtDist = vtStSt - dLong * vtD1 ; + m_dSqDist = vtDist.SqLen() ; + m_dPos1 = dLong ; + m_dPos2 = 0 ; + m_ptMinDist1 = ptSt1 + dLong * vtD1 ; + m_ptMinDist2 = ptSt2 ; + } + // se altrimenti il secondo elemento è una retta infinita + else if ( ! bIsSegment2) { + Vector3d vtStSt = ptSt1 - ptSt2 ; + double dLong = vtStSt * vtD2 ; + Vector3d vtDist = vtStSt - dLong * vtD2 ; + m_dSqDist = vtDist.SqLen() ; + m_dPos1 = 0 ; + m_dPos2 = dLong ; + m_ptMinDist1 = ptSt1 ; + m_ptMinDist2 = ptSt2 + dLong * vtD2 ; } - // Entrambi gli elementi sono segmenti + // altrimenti entrambi gli elementi sono segmenti else { Point3d ptEn1 = ptSt1 + dLen1 * vtD1 ; Point3d ptEn2 = ptSt2 + dLen2 * vtD2 ; @@ -140,7 +139,7 @@ DistLineLine::Calculate( const Point3d& ptSt1, const Vector3d& vtD1, double dLen Vector3d vtStEn = ptEn2 - ptSt1 ; double dStU = vtStSt * vtD1 ; double dEnU = vtStEn * vtD1 ; - // Classifico i punti del segmento segmento in base alla loro + // Classifico i punti del secondo segmento in base alla loro // coordinata rispetto all'ordinamento generato dal primo. double dMinPar, dMaxPar ; Point3d ptMinPar, ptMaxPar ; @@ -159,70 +158,71 @@ DistLineLine::Calculate( const Point3d& ptSt1, const Vector3d& vtD1, double dLen // Possibili posizioni reciproche dei segmenti if ( dMinPar > dLen1) { m_dSqDist = SqDist( ptEn1, ptMinPar) ; - m_dDist = sqrt( m_dSqDist) ; m_ptMinDist1 = ptEn1 ; m_ptMinDist2 = ptMinPar ; - m_dPar1 = dLen1 ; - m_dPar2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ; + m_dPos1 = dLen1 ; + m_dPos2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ; } else if ( dMinPar > 0) { - m_dSqDist = std::max( vtStSt * vtStSt - dStU * dStU, 0.) ; - m_dDist = sqrt( m_dSqDist) ; + m_dSqDist = max( vtStSt * vtStSt - dStU * dStU, 0.) ; m_ptMinDist1 = ptSt1 + dMinPar * vtD1 ; m_ptMinDist2 = ptMinPar ; - m_dPar1 = dMinPar ; - m_dPar2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ; + m_dPos1 = dMinPar ; + m_dPos2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ; } else if ( dMaxPar > 0) { - m_dSqDist = std::max( vtStSt * vtStSt - dStU * dStU, 0.) ; - m_dDist = sqrt( m_dSqDist) ; + m_dSqDist = max( vtStSt * vtStSt - dStU * dStU, 0.) ; m_ptMinDist1 = ptSt1 ; m_ptMinDist2 = ptSt2 + ( ptSt1 - ptSt2) * vtD2 * vtD2 ; - m_dPar1 = 0 ; - m_dPar2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ; + m_dPos1 = 0 ; + m_dPos2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ; } else { m_dSqDist = SqDist( ptSt1, ptMaxPar) ; - m_dDist = sqrt( m_dSqDist) ; m_ptMinDist1 = ptSt1 ; m_ptMinDist2 = ptMaxPar ; - m_dPar1 = 0 ; - m_dPar2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ; + m_dPos1 = 0 ; + m_dPos2 = Clamp( ( m_ptMinDist2 - ptSt2) * vtD2, 0., dLen2) ; } } - return ; } // Caso generale - Vector3d vtDist0 = ptSt2 - ptSt1 ; - double dDist01 = vtDist0 * vtD1 ; - double dDist02 = vtDist0 * vtD2 ; - double dDotD1D2 = vtD1 * vtD2 ; - double dT1 = dDist01 + ( ( dDist01 * dDotD1D2 - dDist02) * dDotD1D2) / ( 1 - dDotD1D2 * dDotD1D2) ; - double dT2 = ( dDist01 * dDotD1D2 - dDist02) / ( 1 - dDotD1D2 * dDotD1D2) ; - double dMin1 = - INFINITO ; - double dMax1 = INFINITO ; - double dMin2 = - INFINITO ; - double dMax2 = INFINITO ; - double dSt1On2 = ( ptSt1 - ptSt2) * vtD2 ; - double dEn1On2 = ( ptSt1 + dLen1 * vtD1 - ptSt2) * vtD2 ; - if ( bIsSegment1) { - dMin1 = 0 ; - dMax1 = dLen1 ; - dMin2 = std::min( dSt1On2, dEn1On2) ; - dMax2 = std::max( dSt1On2, dEn1On2) ; + else { + // Posizioni a distanza minima tra rette illimitate + Vector3d vtStSt = ptSt2 - ptSt1 ; + double dDist01 = vtStSt * vtD1 ; + double dDist02 = vtStSt * vtD2 ; + double dDotD1D2 = vtD1 * vtD2 ; + double dT1 = dDist01 + ( ( dDist01 * dDotD1D2 - dDist02) * dDotD1D2) / ( 1 - dDotD1D2 * dDotD1D2) ; + double dT2 = ( dDist01 * dDotD1D2 - dDist02) / ( 1 - dDotD1D2 * dDotD1D2) ; + // Posizioni minime e massime sui segmenti + double dMin1 = ( bIsSegment1 ? 0 : -INFINITO) ; + double dMax1 = ( bIsSegment1 ? dLen1 : INFINITO) ; + double dMin2 = ( bIsSegment2 ? 0 : -INFINITO) ; + double dMax2 = ( bIsSegment2 ? dLen2 : INFINITO) ; + // Se entrambe le posizioni stanno nei segmenti + if ( dT1 >= dMin1 && dT1 <= dMax1 && dT2 >= dMin2 && dT2 <= dMax2) { + m_dPos1 = dT1 ; + m_dPos2 = dT2 ; + } + // se altrimenti solo la prima sta nel segmento + else if ( dT1 >= dMin1 && dT1 <= dMax1) { + m_dPos2 = Clamp( dT2, dMin2, dMax2) ; + m_dPos1 = Clamp( (( ptSt2 + m_dPos2 * vtD2) - ptSt1) * vtD1, dMin1, dMax1) ; + } + // se altrimenti solo la seconda sta nel segmento + else if ( dT2 >= dMin2 && dT2 <= dMax2) { + m_dPos1 = Clamp( dT1, dMin1, dMax1) ; + m_dPos2 = Clamp( (( ptSt1 + m_dPos1 * vtD1) - ptSt2) * vtD2, dMin2, dMax2) ; + } + // altrimenti nessuna sta nel suo segmento + else { + m_dPos1 = Clamp( dT1, dMin1, dMax1) ; + m_dPos2 = Clamp( (( ptSt1 + m_dPos1 * vtD1) - ptSt2) * vtD2, dMin2, dMax2) ; + m_dPos1 = Clamp( (( ptSt2 + m_dPos2 * vtD2) - ptSt1) * vtD1, dMin1, dMax1) ; + } + m_ptMinDist1 = ptSt1 + m_dPos1 * vtD1 ; + m_ptMinDist2 = ptSt2 + m_dPos2 * vtD2 ; + m_dSqDist = SqDist( m_ptMinDist1, m_ptMinDist2) ; } - if ( bIsSegment2) { - double dSt2On1 = ( ptSt2 - ptSt1) * vtD1 ; - double dEn2On1 = ( ptSt2 + dLen2 * vtD2 - ptSt1) * vtD1 ; - dMin1 = std::max( dMin1, std::min( dSt2On1, dEn2On1)) ; - dMax1 = std::min( dMax1, std::max( dSt2On1, dEn2On1)) ; - dMin2 = std::max( dMin2, 0.) ; - dMax2 = std::min( dMax2, dLen2) ; - } - m_dPar1 = Clamp( dT1, dMin1, dMax1) ; - m_dPar2 = Clamp( dT2, dMin2, dMax2) ; - m_ptMinDist1 = ptSt1 + m_dPar1 * vtD1 ; - m_ptMinDist2 = ptSt2 + m_dPar2 * vtD2 ; - m_dSqDist = SqDist( m_ptMinDist1, m_ptMinDist2) ; - m_dDist = sqrt( m_dSqDist) ; -} \ No newline at end of file +} diff --git a/DistLineLine.h b/DistLineLine.h index 9e204d2..ed817fb 100644 --- a/DistLineLine.h +++ b/DistLineLine.h @@ -37,17 +37,17 @@ class DistLineLine bool IsSmall( void) { return IsEpsilon( EPS_SMALL) ; } bool IsZero( void) { return IsEpsilon( EPS_ZERO) ; } bool GetMinDistPoints( Point3d& ptMinDist1, Point3d& ptMinDist2) ; - bool GetParamsAtMinDistPoints( double& dPar1, double& dPar2) ; + bool GetPositionsAtMinDistPoints( double& dPos1, double& dPos2) ; private : void Calculate( const Point3d& ptSt1, const Vector3d& vtD1, double dLen1, const Point3d& ptSt2, const Vector3d& vtD2, double dLen2, - bool bIsSegment1 = true, bool bIsSegment2 = true) ; + bool bIsSegment1, bool bIsSegment2) ; private: double m_dSqDist ; double m_dDist ; - double m_dPar1 ; - double m_dPar2 ; + double m_dPos1 ; + double m_dPos2 ; Point3d m_ptMinDist1 ; Point3d m_ptMinDist2 ; } ; diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 08e962b..1f03f6a 100644 Binary files a/EgtGeomKernel.rc and b/EgtGeomKernel.rc differ diff --git a/SurfTriMesh.cpp b/SurfTriMesh.cpp index 83cd021..ed6a5be 100644 --- a/SurfTriMesh.cpp +++ b/SurfTriMesh.cpp @@ -3180,7 +3180,7 @@ bool SurfTriMesh::InvertTriangle( int nT) { // controllo validità triangolo - if ( m_vTria[nT].nIdVert[0] == SVT_DEL) + if ( ! ExistsTriangle( nT)) return true ; // scambio di due vertici swap( m_vTria[nT].nIdVert[1], m_vTria[nT].nIdVert[2]) ; diff --git a/SurfTriMesh.h b/SurfTriMesh.h index 8cafbc1..fa8b7a5 100644 --- a/SurfTriMesh.h +++ b/SurfTriMesh.h @@ -310,6 +310,8 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW LOG_ERROR( GetEGkLogger(), "SurfTriMesh : copy error") return *this ; } bool Clear( void) ; + bool ExistsTriangle( int nT) const + { return ( nT >= 0 && nT < GetTriangleSize() && m_vTria[nT].nIdVert[0] != SVT_DEL) ; } bool GetTriangleAdjacencies( int nId, int nIdAdjTriaId[3]) const ; bool GetTriangleFlag( int nId, int& nFlag) const ; bool GetTriangleTempInt( int nId, int& nTempInt) const ; @@ -364,33 +366,13 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW bool VerifyConnection( void) const ; bool CutTriangleByPlane( int nTriaId, const Plane3d& plPlane, bool bSaveOnEq, bool& bModif) ; bool CutByTriangles( const Plane3d& plPlane, bool bSaveOnEq, bool& bModif) ; - bool CutByFacets( const Plane3d& plPlane, bool bSaveOnEq, bool& bModif) ; bool DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMATRIX& cvBoundClosedLoopVec, BOOLVECTOR& vbInOut) ; bool RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECTORMAP& Ambiguos, SurfTriMesh& Surf, bool& bModif) ; bool AmbiguosTriangleManager( TRIA3DVECTORMAP& Ambiguos, SurfTriMesh& Surf) ; bool IntersectTriMeshTriangle( SurfTriMesh& Other) ; - int VerifyLoopPlane( const PolyLine& ExtLoop, const Plane3d& plCutPlane) ; - int IntersFacetPlane( const SurfFlatRegion& Region, const Plane3d& plCutPlane, - LineFacetClassVector& IntersLinePart) ; - bool IntersFacetFacet( const SurfFlatRegion& RegionA, const PolyLine& ExtLoopA, - const SurfFlatRegion& RegionB, const PolyLine& ExtLoopB, - LineFacetClassVector& IntersLinePart) ; - bool IntersectTriMeshFacets( SurfTriMesh& Other) ; - bool RetriangulateFacetPieces( const PieceMap& NewFacet, - const INTERSEDGEMAP& EdgeInterLineMap, - const INTERSEDGEMAP& EdgeEdgeLineMap) ; - bool EdgeInteriorContactManager( const SurfTriMesh& OthSurf, - const INTERSCHAINMAP& InterInterLineMap, - const INTERSEDGEMAP& EdgeInterLineMap) ; - bool EdgeEdgeContactManager( const SurfTriMesh& OthSurf, - const INTERSCHAINMAP& InterInterLineMap, - const INTERSEDGEMAP& EdgeEdgeLineMap) ; - bool SplitFacet( const INTERSCHAINMAP& IntersLineMap, PieceMap& NewFacet); bool IdentifyParts( void) const ; - bool RemoveTJunctions( void) ; - bool RemoveCaps( void) ; - bool RemoveTripleTriangles( void) ; - bool ScanForTripleTriangles( bool& bModified) ; + bool RemoveDoubleTriangles( bool& bModified) ; + bool RemoveTJunctions( bool& bModified) ; bool FlipTriangles( int nTA, int nTB) ; bool SimplifyFacets( double dMaxEdgeLen = MAX_EDGE_LEN_STD, bool bForced = true) ; bool AddChainToChain( const Chain& ChainToAdd, PNTVECTOR& OrigChain) ; diff --git a/SurfTriMeshBooleans.cpp b/SurfTriMeshBooleans.cpp index c26b6ff..e63860d 100644 --- a/SurfTriMeshBooleans.cpp +++ b/SurfTriMeshBooleans.cpp @@ -1439,210 +1439,6 @@ SurfTriMesh::IdentifyParts( void) const return true ; } -//---------------------------------------------------------------------------- -bool -SurfTriMesh::RemoveCaps(void) -{ - INTVECTOR vIndex ; - int nTriaNum = GetTriangleSize() ; - for ( int nT = 0 ; nT < nTriaNum ; ++ nT) { - Triangle3d trTria ; - GetTriangle( nT, trTria) ; - int nMinIndex = -1 ; - double dMinSqDist = DBL_MAX ; - for ( int nV = 0 ; nV < 3 ; ++ nV) { - Point3d ptVert, ptSegSt, ptSegEn ; - ptVert = trTria.GetP( nV) ; - ptSegSt = trTria.GetP( ( nV + 1) % 3) ; - ptSegEn = trTria.GetP( ( nV + 2) % 3) ; - CurveLine cvSeg ; - cvSeg.Set( ptSegSt, ptSegEn) ; - DistPointLine DistCalculator( ptVert, cvSeg, false) ; - double dSqDist ; - DistCalculator.GetSqDist( dSqDist) ; - Vector3d vtSeg = ptSegEn - ptSegSt ; - double dSegLen = vtSeg.Len() ; - vtSeg /= dSegLen ; - double dProj = ( ptVert - ptSegSt) * vtSeg ; - if ( dSqDist < dMinSqDist && dProj > EPS_SMALL && dProj < dSegLen - EPS_SMALL) { - dMinSqDist = dSqDist ; - nMinIndex = nV ; - } - } - if ( dMinSqDist < EPS_SMALL) { - vIndex.emplace_back( nT) ; - vIndex.emplace_back( nMinIndex) ; - } - } - for ( int nPos = 0 ; nPos < int( vIndex.size()) ; nPos += 2) { - int nT = vIndex[nPos] ; - int nV = vIndex[nPos + 1] ; - int nAdjT = m_vTria[nT].nIdAdjac[( nV + 1) % 3] ; - if ( nAdjT < 0) - continue ; - int nAdjV ; - for ( nAdjV = 0 ; nAdjV < 3 ; ++ nAdjV) { - if ( m_vTria[nAdjT].nIdAdjac[nAdjV] == nT) - break ; - } - Triangle3d trTriaAdj ; - GetTriangle( nAdjT, trTriaAdj) ; - Vector3d vtLen = trTriaAdj.GetP( ( nAdjV + 1) % 3) - trTriaAdj.GetP( nAdjV) ; - if ( vtLen * vtLen > 4 * EPS_SMALL * EPS_SMALL) { - FlipTriangles( nT, nAdjT) ; - } - } - return true ; -} - -//---------------------------------------------------------------------------- -bool -SurfTriMesh::RemoveTripleTriangles() -{ - int nCounter = 1 ; - const int N_STOP = 100 ; - bool bContinue = true ; - while ( bContinue && nCounter <= N_STOP) { - ScanForTripleTriangles( bContinue) ; - } - return true ; -} - -//---------------------------------------------------------------------------- -bool -SurfTriMesh::ScanForTripleTriangles( bool& bModified) -{ - // Setto il flag come nessuna modifica eseguita - bModified = false ; - // Ciclo sui vertici - int nNumVert = GetVertexCount() ; - for ( int nV = 0 ; nV < nNumVert ; ++ nV) { - bool bCirc ; - INTVECTOR vTriaIndex ; - int nTriaNum = GetAllTriaAroundVertex( nV, vTriaIndex, bCirc) ; - // Se il vertice è condiviso da tre triangoli tutti adiacenti fra loro a due a due - if ( nTriaNum == 3 && bCirc) { - // Valuto parallelismo fra le normali - int nParallel = 0 ; - for ( int nT1 = 0 ; nT1 < 2 ; ++ nT1) { - for ( int nT2 = nT1 + 1 ; nT2 < 3 ; ++ nT2) { - if ( AreSameVectorExact( m_vTria[vTriaIndex[nT1]].vtN, m_vTria[vTriaIndex[nT2]].vtN)) { - ++ nParallel ; - } - } - } - // Se sono tutte parallele fra loro unisco i tre triangoli in uno - if ( nParallel == 3) { - // Cerco gli altri triangoli adiacenti a quelli che sostituirò con il triangolo grande. - // Cerco anche quali lati dei tre triangoli che saranno eliminati sono adiacenti a quelli esterni - INTVECTOR vVertAndAdjTria ; - for ( int nTria = 0 ; nTria < 3 ; ++ nTria) { - for ( int nVert = 0 ; nVert < 3 ; ++ nVert) { - if ( m_vTria[vTriaIndex[nTria]].nIdVert[nVert] == nV) { - vVertAndAdjTria.emplace_back( m_vTria[vTriaIndex[nTria]].nIdVert[(nVert + 1) % 3]) ; - vVertAndAdjTria.emplace_back( m_vTria[vTriaIndex[nTria]].nIdAdjac[(nVert + 1) % 3]) ; - break ; - } - } - } - // Cerco fra questi altri triangoli esterni sono adiacenti ai triangoli che eliminerò - int nAdjTriaContactEdge[3] ; - for ( int nAdjTria = 1 ; nAdjTria < 6 ; nAdjTria += 2) { - for ( int nAdjEdge = 0 ; nAdjEdge < 3 ; ++ nAdjEdge) { - if ( vVertAndAdjTria[nAdjTria] >= 0 && m_vTria[vVertAndAdjTria[nAdjTria]].nIdAdjac[nAdjEdge] == vTriaIndex[( nAdjTria - 1) / 2]) - nAdjTriaContactEdge[(nAdjTria - 1) / 2] = nAdjEdge ; - } - } - // Elimino i triangoli e salvo i loro Flag - int vnTFlag[3] ; - for ( int nTria = 0 ; nTria < 3 ; ++ nTria) { - vnTFlag[nTria] = m_vTria[vTriaIndex[nTria]].nTFlag ; - RemoveTriangle( vTriaIndex[nTria]) ; - } - // Aggiungo il nuovo triangolo con il flag - int nNewTFlag ; - if ( vnTFlag[0] == vnTFlag[1]) - nNewTFlag = vnTFlag[1] ; - else if ( vnTFlag[0] == vnTFlag[2] || vnTFlag[1] == vnTFlag[2]) - nNewTFlag = vnTFlag[2] ; - else - nNewTFlag = 0 ; - int nNewVert[3] = { vVertAndAdjTria[0], vVertAndAdjTria[2], vVertAndAdjTria[4] } ; - int nNewTriaId = AddTriangle( nNewVert, nNewTFlag) ; - if ( nNewTriaId != SVT_NULL) { - // Sistemo le adiacenze - m_vTria[nNewTriaId].nIdAdjac[0] = vVertAndAdjTria[1] ; - m_vTria[nNewTriaId].nIdAdjac[1] = vVertAndAdjTria[3] ; - m_vTria[nNewTriaId].nIdAdjac[2] = vVertAndAdjTria[5] ; - if ( vVertAndAdjTria[1] >= 0) - m_vTria[vVertAndAdjTria[1]].nIdAdjac[nAdjTriaContactEdge[0]] = nNewTriaId ; - if ( vVertAndAdjTria[3] >= 0) - m_vTria[vVertAndAdjTria[3]].nIdAdjac[nAdjTriaContactEdge[1]] = nNewTriaId ; - if ( vVertAndAdjTria[5] >= 0) - m_vTria[vVertAndAdjTria[5]].nIdAdjac[nAdjTriaContactEdge[2]] = nNewTriaId ; - // Setto il flag come modifica eseguita - bModified = true ; - } - } - } - } - return true ; -} - -//---------------------------------------------------------------------------- -bool -SurfTriMesh::FlipTriangles( int nTA, int nTB) -{ - // Verifico esistenza triangoli - int nNumTria = GetTriangleCount() ; - if ( nTA < 0 || nTA >= nNumTria || nTB < 0 || nTB >= nNumTria) - return false ; - // Verifico adiacenza triangoli - int nEdgeA ; - for ( nEdgeA = 0 ; nEdgeA < 3 ; ++ nEdgeA) { - if ( m_vTria[nTA].nIdAdjac[nEdgeA] == nTB) - break ; - } - int nEdgeB ; - for ( nEdgeB = 0 ; nEdgeB < 3 ; ++ nEdgeB) { - if ( m_vTria[nTB].nIdAdjac[nEdgeB] == nTA) - break ; - } - // Se uno è adiacente all'altro ma non viceversa, c'è un errore - if ( ( nEdgeA == 3 && nEdgeB < 3) || ( nEdgeA < 3 && nEdgeB == 3)) - return false ; - // Se non sono adiacenti, ho finito - else if ( nEdgeA == 3 && nEdgeB == 3) - return true ; - // Se non trovo i vertici del triangolo A, c'è un errorre - Point3d ptSegSt, ptSegEn, ptVertA ; - if ( ! GetVertex( m_vTria[nTA].nIdVert[nEdgeA], ptSegSt) || - ! GetVertex( m_vTria[nTA].nIdVert[( nEdgeA + 1) % 3], ptSegEn) || - ! GetVertex( m_vTria[nTA].nIdVert[( nEdgeA + 2) % 3], ptVertA)) - return false ; - // Se non trovo i vertici del triangolo B, c'è un errorre - Point3d ptVertB ; - if ( ! GetVertex( m_vTria[nTB].nIdVert[( nEdgeB + 2) % 3], ptVertB)) - return false ; - // Calcolo le proiezioni dei Vertici fuori dal segmento su quest'ultimo - Vector3d vtVec = ptSegEn - ptSegSt ; - double dLen = vtVec.Len() ; - vtVec /= dLen ; - double dProjA = ( ptVertA - ptSegSt) * vtVec ; - double dProjB = ( ptVertB - ptSegSt) * vtVec ; - // Se le proiezioni sono interne al segmento comune eseguo il flipping - if ( dProjA > EPS_SMALL && dProjA < dLen - EPS_SMALL && - dProjB > EPS_SMALL && dProjB < dLen - EPS_SMALL) { - m_vTria[nTA].nIdVert[nEdgeA] = m_vTria[nTB].nIdVert[( nEdgeB + 2) % 3] ; - m_vTria[nTB].nIdVert[nEdgeB] = m_vTria[nTA].nIdVert[( nEdgeA + 2) % 3] ; - m_vTria[nTA].nIdAdjac[nEdgeA] = m_vTria[nTB].nIdAdjac[( nEdgeB + 2) % 3] ; - m_vTria[nTA].nIdAdjac[( nEdgeA + 2) % 3] = nTB ; - m_vTria[nTB].nIdAdjac[nEdgeB] = m_vTria[nTA].nIdAdjac[( nEdgeA + 2) % 3] ; - m_vTria[nTB].nIdAdjac[( nEdgeB + 2) % 3] = nTA ; - } - return true ; -} - //---------------------------------------------------------------------------- bool SurfTriMesh::Add( const ISurfTriMesh& Other) @@ -1686,11 +1482,14 @@ SurfTriMesh::Add( const ISurfTriMesh& Other) bool bOk = ( AdjustVertices() && DoCompacting()) ; - //bOk && RemoveTripleTriangles() ; - //bOk = bOk && ( AdjustVertices() && DoCompacting()) ; + bool bModified = false ; + bOk = bOk && RemoveDoubleTriangles( bModified) ; + if ( bModified) + bOk = bOk && ( AdjustVertices() && DoCompacting()) ; - bOk = bOk && RemoveTJunctions() ; - bOk = bOk && ( AdjustVertices() && DoCompacting()) ; + bOk = bOk && RemoveTJunctions( bModified) ; + if ( bModified) + bOk = bOk && ( AdjustVertices() && DoCompacting()) ; Scale( frScalingRef, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE) ; @@ -1743,11 +1542,14 @@ SurfTriMesh::Intersect( const ISurfTriMesh& Other) bool bOk = ( AdjustVertices() && DoCompacting()) ; - //bOk && RemoveTripleTriangles() ; - //bOk = bOk && ( AdjustVertices() && DoCompacting()) ; + bool bModified = false ; + bOk = bOk && RemoveDoubleTriangles( bModified) ; + if ( bModified) + bOk = bOk && ( AdjustVertices() && DoCompacting()) ; - bOk = bOk && RemoveTJunctions() ; - bOk = bOk && ( AdjustVertices() && DoCompacting()) ; + bOk = bOk && RemoveTJunctions( bModified) ; + if ( bModified) + bOk = bOk && ( AdjustVertices() && DoCompacting()) ; Scale( frScalingRef, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE) ; @@ -1801,11 +1603,14 @@ SurfTriMesh::Subtract( const ISurfTriMesh& Other) bool bOk = ( AdjustVertices() && DoCompacting()) ; - //bOk && RemoveTripleTriangles() ; - //bOk = bOk && ( AdjustVertices() && DoCompacting()) ; + bool bModified = false ; + bOk = bOk && RemoveDoubleTriangles( bModified) ; + if ( bModified) + bOk = bOk && ( AdjustVertices() && DoCompacting()) ; - bOk = bOk && RemoveTJunctions() ; - bOk = bOk && ( AdjustVertices() && DoCompacting()) ; + bOk = bOk && RemoveTJunctions( bModified) ; + if ( bModified) + bOk = bOk && ( AdjustVertices() && DoCompacting()) ; Scale( frScalingRef, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE) ; @@ -1897,8 +1702,14 @@ SurfTriMesh::CutWithOtherSurf( const ISurfTriMesh& CutterSurf, bool bInVsOut, bo bool bOk = ( AdjustVertices() && DoCompacting()) ; - bOk = bOk && RemoveTJunctions() ; - bOk = bOk && ( AdjustVertices() && DoCompacting()) ; + bool bModified = false ; + bOk = bOk && RemoveDoubleTriangles( bModified) ; + if ( bModified) + bOk = bOk && ( AdjustVertices() && DoCompacting()) ; + + bOk = bOk && RemoveTJunctions( bModified) ; + if ( bModified) + bOk = bOk && ( AdjustVertices() && DoCompacting()) ; Scale( frScalingRef, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE) ; @@ -1919,1822 +1730,28 @@ SurfTriMesh::Repair( double dMaxEdgeLen) // Forzo aggiornamento grafica m_OGrMgr.Clear() ; - // Inserisco triangoli per rimuovere giunzioni a T - RemoveTJunctions() ; - - // Sistemo + // Aggiustamento generale if ( ! AdjustVertices() || ! DoCompacting()) return false ; + // Elimino triangoli coincidenti + bool bModified = false ; + RemoveDoubleTriangles( bModified) ; + if ( bModified) { + if ( ! AdjustVertices() || ! DoCompacting()) + return false ; + } + + // Elimino giunzioni a T, con opportuno inserimento di triangoli + RemoveTJunctions( bModified) ; + if ( bModified) { + if ( ! AdjustVertices() || ! DoCompacting()) + return false ; + } + // Ritriangolo le facce if ( ! SimplifyFacets( dMaxEdgeLen, true)) LOG_ERROR( GetEGkLogger(), "Error in SimplifyFacets of Stm::Intersect") return true ; } - -//---------------------------------------------------------------------------- -int -SurfTriMesh::VerifyLoopPlane( const PolyLine& ExtLoop, const Plane3d& plCutPlane) -{ - // Verifico il loop e il piano di taglio - if ( ExtLoop.GetPointNbr() == 0 || ! plCutPlane.IsValid()) - return FPI_ERROR ; - // Calcolo le distanze dei vertici della faccia dal piano - int nExtLoopPointNum = int( ExtLoop.GetPointNbr()) ; - DBLVECTOR vDist ; - vDist.reserve( nExtLoopPointNum) ; - Point3d ptP ; - bool bContinue = ExtLoop.GetFirstPoint( ptP) ; - while ( bContinue) { - vDist.emplace_back( DistPointPlane( ptP, plCutPlane)) ; - bContinue = ExtLoop.GetNextPoint( ptP) ; - } - // Verifico posizione della faccia rispetto al piano. - int nVertPos = 0 ; int nVertNeg = 0 ; - for ( const auto& dDist : vDist) { - if ( dDist > 0.5 * EPS_SMALL) - ++ nVertPos ; - else if ( dDist < - 0.5 * EPS_SMALL) - ++ nVertNeg ; - } - - // Tutto sul piano. - if ( nVertPos == 0 && nVertNeg == 0) - return FPI_ON ; - // Tutto dentro - else if ( nVertPos == 0) - return FPI_IN ; - // Tutto fuori - else if ( nVertNeg == 0) - return FPI_OUT ; - // Si intersecano - else - return FPI_CUT ; -} - -//---------------------------------------------------------------------------- -int -SurfTriMesh::IntersFacetPlane( const SurfFlatRegion& Region, const Plane3d& plCutPlane, - LineFacetClassVector& IntersLinePart) -{ - // Verifico la regione e il piano di taglio - if ( ! Region.IsValid() || ! plCutPlane.IsValid()) - return FPI_ERROR ; - - // Recupero il piano della regione. - Plane3d plFacetPlane ; - plFacetPlane.Set( Region.GetPlanePoint(), Region.GetNormVersor()) ; - if ( ! plFacetPlane.IsValid()) - return FPI_ERROR ; - - // Pulisco il vettore delle intersezioni - IntersLinePart.resize( 0) ; - - // Intersezione tra i piani delle due facce - Point3d ptL ; Vector3d vtL ; - int nResPP = IntersPlanePlane( plFacetPlane, plCutPlane, ptL, vtL) ; - // Sono considerate non complanari, se c'� la retta d'intersezione � errore - if ( nResPP == IPPT_NO || nResPP == IPPT_OVERLAPS) - return FPI_ERROR ; - - // Box della regione - BBox3d b3Box ; - Region.GetLocalBBox( b3Box) ; - b3Box.Expand( 10) ; - - // Limito la retta nel box contenente la regione - INTDBLVECTOR vInters ; - if ( ! IntersLineBox( ptL, vtL, 100., b3Box, vInters, false) || int( vInters.size()) < 2) - return FPI_ERROR ; - double dLen = vInters.back().second - vInters.front().second ; - Point3d ptIntLineSt = ptL + vInters.front().second * vtL ; - Point3d ptIntLineEn = ptL + vInters.back().second * vtL ; - CurveLine cvPlaneIntersLine ; - cvPlaneIntersLine.Set( ptIntLineSt, ptIntLineEn) ; - - // Classifico la linea di intersezione con la faccia - CRVCVECTOR IntersectionResults ; - bool bClassificationOk = Region.GetCurveClassification( cvPlaneIntersLine, 0.1 * EPS_SMALL, IntersectionResults) ; - // Se non trovo le intersezioni, c'� un errore. - if ( ! bClassificationOk) - return FPI_ERROR ; - - // Prendo la parte interna o sul bordo. - int nPartNum = int( IntersectionResults.size()) ; - for ( int n = 0 ; n < nPartNum ; ++ n) { - int nType = IntersectionResults[n].nClass ; - if ( nType == CRVC_IN || nType == CRVC_ON_P || nType == CRVC_ON_M) { - double dParS = dLen * IntersectionResults[n].dParS ; - double dParE = dLen * IntersectionResults[n].dParE ; - IntersLinePart.emplace_back( LineFacetClass( ptIntLineSt + dParS * vtL, ptIntLineSt + dParE * vtL, nType, nType)) ; - } - } - if ( ! IntersLinePart.empty()) - return FPI_CUT ; - - // La linea si � ridotta ad un punto, la regione � tutta dentro o tutta fuori - Point3d ptCen ; - if ( ! Region.GetChunkCentroid( 0, ptCen)) - return FPI_ERROR ; - if ( DistPointPlane( ptCen, plCutPlane) > 0) - return FPI_OUT ; - else - return FPI_IN ; -} - -//---------------------------------------------------------------------------- -bool -SurfTriMesh::IntersFacetFacet( const SurfFlatRegion& RegionA, const PolyLine& ExtLoopA, - const SurfFlatRegion& RegionB, const PolyLine& ExtLoopB, - LineFacetClassVector& IntersLinePart) -{ - IntersLinePart.resize( 0) ; - - // Determino i piani delle regioni - Plane3d plPlaneA, plPlaneB ; - plPlaneA.Set( RegionA.GetPlanePoint(), RegionA.GetNormVersor()) ; - plPlaneB.Set( RegionB.GetPlanePoint(), RegionB.GetNormVersor()) ; - - // Calcolo le distanze dei vertici della faccia A dal piano della faccia B. - int nExtLoopPointNumA = int( ExtLoopA.GetPointNbr()) ; - vector vDistA ; - vDistA.reserve( nExtLoopPointNumA) ; - Point3d ptP ; - bool bContinue = ExtLoopA.GetFirstPoint( ptP) ; - while ( bContinue) { - vDistA.emplace_back( DistPointPlane( ptP, plPlaneB)) ; - bContinue = ExtLoopA.GetNextPoint( ptP) ; - } - // Verifico posizione della faccia A rispetto al piano della faccia B. - int nVertPosA = 0 ; int nVertNegA = 0 ; - for ( const auto& dDist : vDistA) { - if ( dDist > EPS_SMALL) - ++ nVertPosA ; - else if ( dDist < - EPS_SMALL) - ++ nVertNegA ; - } - // Se la faccia A giace tutta da una parte del piano, nessuna intersezione - if ( nVertPosA == nExtLoopPointNumA || nVertNegA == nExtLoopPointNumA) - return false ; - - // Calcolo le distanze dei vertici della faccia B dal piano della faccia A. - int nExtLoopPointNumB = int( ExtLoopB.GetPointNbr()) ; - vector vDistB ; - vDistB.reserve( nExtLoopPointNumB) ; - bContinue = ExtLoopB.GetFirstPoint( ptP) ; - while ( bContinue) { - vDistB.emplace_back( DistPointPlane( ptP, plPlaneA)) ; - bContinue = ExtLoopB.GetNextPoint( ptP) ; - } - // Verifico posizione della faccia B rispetto al piano della faccia A. - int nVertPosB = 0 ; int nVertNegB = 0 ; - for ( const auto& dDist : vDistB) { - if ( dDist > EPS_SMALL) - ++ nVertPosB ; - else if ( dDist < - EPS_SMALL) - ++ nVertNegB ; - } - // Se la faccia B giace tutta da una parte del piano, nessuna intersezione - if ( nVertPosB == nExtLoopPointNumB || nVertNegB == nExtLoopPointNumB) - return false ; - - // Intersezione tra i piani delle due facce - Point3d ptL ; Vector3d vtL ; - int nResPP = IntersPlanePlane( plPlaneA, plPlaneB, ptL, vtL) ; - if ( nResPP == IPPT_NO) - return false ; - - // Se le facce sono complanari - if ( nResPP == IPPT_OVERLAPS) - return false ; - - // Box contenente entrambe le regioni - BBox3d b3Box, b3BoxB; - RegionA.GetLocalBBox( b3Box) ; - RegionB.GetLocalBBox( b3BoxB) ; - b3Box.Add(b3BoxB); - b3Box.Expand( 10); - - // Limito la retta nel box contenente le regioni - INTDBLVECTOR vInters; - if ( ! IntersLineBox(ptL, vtL, 100., b3Box, vInters, false) || int( vInters.size()) dParSA + EPS_SMALL) { - double dMinPar = max( dParSA, dParSB) ; - double dMaxPar = min( dParEA, dParEB) ; - IntersLinePart.emplace_back( LineFacetClass( ptIntLineSt + dMinPar * vtL, ptIntLineSt + dMaxPar * vtL, nTypeA, nTypeB)) ; - } - } - } - } - } - - return int( IntersLinePart.size()) > 0 ; -} - -//---------------------------------------------------------------------------- -//bool -//CreateFlatRegionFromPolyLineVector( const POLYLINEVECTOR& PolyVec, SurfFlatRegion& Region) -//{ -// bool bOk = true ; -// for ( int nL = 0 ; nL < int( PolyVec.size()) && bOk ; ++ nL) { -// CurveComposite Loop ; -// Point3d ptSt, ptEn ; -// bool bContinue = PolyVec[nL].GetFirstPoint( ptSt) && PolyVec[nL].GetNextPoint( ptEn) ; -// while ( bContinue) { -// CurveLine cvLine ; -// cvLine.Set( ptSt, ptEn) ; -// Loop.AddCurve( cvLine) ; -// ptSt = ptEn ; -// bContinue = PolyVec[nL].GetNextPoint( ptEn) ; -// } -// if ( nL == 0) -// bOk = bOk && Region.AddExtLoop( Loop) ; -// else -// bOk = bOk && Region.AddIntLoop( Loop) ; -// } -// return bOk ; -//} - -//---------------------------------------------------------------------------- -struct PositionOnPolyLine { - int nIndexInVec ; - double dPar ; - PositionOnPolyLine( int nIndex, double dParam) { - nIndexInVec = nIndex ; - dPar = dParam ; - } -} ; - -//---------------------------------------------------------------------------- -bool -SurfTriMesh::SplitFacet( const INTERSCHAINMAP& IntersLineMap, PieceMap& NewFacet) -{ - for ( auto it = IntersLineMap.begin() ; it != IntersLineMap.end() ; ++ it) { - // 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) ; - // Carico le curve per concatenarle - for ( int nCv = 0 ; nCv < int( it->second.size()); ++ nCv) { - Point3d ptSt = it->second[nCv].ptSt ; - Point3d ptEn = it->second[nCv].ptEn ; - Vector3d vtDir = ptEn - ptSt ; - vtDir.Normalize() ; - LoopCreator.AddCurve( nCv + 1, ptSt, vtDir, ptEn, vtDir) ; - } - // Recupero i concatenamenti e li divido fra chiusi e aperti. - INNCHAINVECTOR cvClosedChain ; - INNCHAINVECTOR cvOpenChain ; - INTVECTOR vIds ; - Point3d ptNearStart = ( it->second.size() > 0 ? it->second[0].ptSt : ORIG) ; - while ( LoopCreator.GetChainFromNear( ptNearStart, false, vIds)) { - IntersInnChain chTemp ; - // Aggiungo la linea alla curva composta. - for ( auto i : vIds) - chTemp.emplace_back( it->second[i - 1]) ; - // Inserisco opportunamente negli aperti o chiusi - int nCurLoopLast = int( chTemp.size()) - 1 ; - if ( nCurLoopLast > 0 && AreSamePointEpsilon( chTemp[0].ptSt, chTemp[nCurLoopLast].ptEn, 10 * EPS_SMALL)) - cvClosedChain.emplace_back( chTemp) ; - else - cvOpenChain.emplace_back( chTemp) ; - } - // Elimino la seconda copia di catene aperte doppie - for ( int nI = 0 ; nI < int( cvOpenChain.size()) - 1 ; ++ nI) { - for ( int nJ = nI + 1 ; nJ < int( cvOpenChain.size()) ; ++ nJ) { - if ( cvOpenChain[nI].size() == cvOpenChain[nJ].size()) { - bool bSame = true ; - for ( int nK = 0 ; nK < int( cvOpenChain[nI].size()) ; ++ nK) { - if ( ! AreSamePointEpsilon( cvOpenChain[nI][nK].ptSt, cvOpenChain[nJ][nK].ptSt, EPS_SMALL) || - ! AreSamePointEpsilon( cvOpenChain[nI][nK].ptEn, cvOpenChain[nJ][nK].ptEn, EPS_SMALL)) { - bSame = false ; - break ; - } - } - if ( bSame) { - cvOpenChain.erase( cvOpenChain.begin() + nJ) ; - -- nJ ; - } - } - } - } - // Elimino la seconda copia di catene chiuse doppie - for ( int nI = 0 ; nI < int( cvClosedChain.size()) - 1 ; ++ nI) { - for ( int nJ = nI + 1 ; nJ < int( cvClosedChain.size()) ; ++ nJ) { - if ( cvClosedChain[nI].size() == cvClosedChain[nJ].size()) { - bool bSame = true ; - for ( int nK = 0 ; nK < int( cvClosedChain[nI].size()) ; ++ nK) { - if ( ! AreSamePointEpsilon( cvClosedChain[nI][nK].ptSt, cvClosedChain[nJ][nK].ptSt, EPS_SMALL) || - ! AreSamePointEpsilon( cvClosedChain[nI][nK].ptEn, cvClosedChain[nJ][nK].ptEn, EPS_SMALL)) { - bSame = false ; - break ; - } - } - if ( bSame) { - cvClosedChain.erase( cvClosedChain.begin() + nJ) ; - -- nJ ; - } - } - } - } - // Recupero i loop della faccia da dividere - vector& vNewPieces = ( NewFacet.emplace( it->first, vector()).first)->second ; - vNewPieces.emplace_back(); - vNewPieces.back().nPiecePart = 1 ; - GetFacetLoops( it->first, vNewPieces.back().vPieceLoop) ; - // Divido la faccia in parti. - // Ciclo sulle catene finch� non esauriscono. - int nIterNumber = 0 ; - int nPrevLastChainNum = int( cvOpenChain.size()) ; - while ( int( cvOpenChain.size()) > 0) { - // Controllo di non essere in un loop infinito. - int nLastChainNum = int( cvOpenChain.size()) - 1 ; - if ( nPrevLastChainNum == nLastChainNum) { - cvOpenChain.insert( cvOpenChain.begin(), cvOpenChain.back()) ; - cvOpenChain.pop_back() ; - ++ nIterNumber ; - } - else { - nIterNumber = 0 ; - nPrevLastChainNum = nLastChainNum; - } - if ( nIterNumber == int( cvOpenChain.size())) { - cvOpenChain.resize( int( cvOpenChain.size()) - 1) ; - -- nLastChainNum ; - } - if ( int( cvOpenChain.size()) == 0) - break ; - // Ciclo su tutte le parti della faccia. - int nPartLoopNum = int( vNewPieces.size()) ; - for ( int nPart = 0 ; nPart < nPartLoopNum ; ++ nPart) { - // Cerco i loop su cui la catena corrente inizia e finisce. - INTVECTOR vLoopIndexes ; - // Ciclo sui loop della faccia. - for ( int nLoop = 0 ; nLoop < int( vNewPieces[nPart].vPieceLoop.size()) && int( vLoopIndexes.size()) < 2 ; ++ nLoop) { - double dPar ; - if ( GetPointParamOnPolyLine( cvOpenChain[nLastChainNum][0].ptSt, vNewPieces[nPart].vPieceLoop[nLoop], 2 * EPS_SMALL, dPar)) { - vLoopIndexes.emplace_back( nLoop) ; - if ( vLoopIndexes.size() > 1) { - swap( vLoopIndexes[0], vLoopIndexes[1]) ; - } - } - if ( GetPointParamOnPolyLine( cvOpenChain[nLastChainNum][cvOpenChain[nLastChainNum].size() - 1].ptEn, - vNewPieces[nPart].vPieceLoop[nLoop], 2 * EPS_SMALL, dPar)) { - vLoopIndexes.emplace_back( nLoop) ; - } - } - // Se non ho trovato almeno un taglio completo, vado al prossimo. - if ( int( vLoopIndexes.size()) < 2) - continue ; - // La catena finisce sul loop ove inizia. Divido la nuova parte. - if ( vLoopIndexes[0] == vLoopIndexes[1]) { - // Cambio inizio al loop iniziale. - ChangePolyLineStart( vNewPieces[nPart].vPieceLoop[vLoopIndexes[0]], cvOpenChain[nLastChainNum].back().ptEn, 2 * EPS_SMALL) ; - // Divido il loop della parte - // Loop1 - PolyLine NewLoop1 ; - // Inserisco i punti della catena nella PolyLine del nuovo loop. - for ( int m = 0 ; m < int( cvOpenChain[nLastChainNum].size()) ; ++ m) { - NewLoop1.AddUPoint( 0., cvOpenChain[nLastChainNum][m].ptSt) ; - if ( m == int( cvOpenChain[nLastChainNum].size()) - 1) - NewLoop1.AddUPoint( 0., cvOpenChain[nLastChainNum][m].ptEn) ; - } - // Spezzo il loop successivo alla catena nel punto in cui comincia la catena successiva. - PolyLine SplitLoop1, SplitLoop2 ; - SplitPolyLineAtPoint( vNewPieces[nPart].vPieceLoop[vLoopIndexes[0]], - cvOpenChain[nLastChainNum][0].ptSt, 2 * EPS_SMALL, - SplitLoop1, SplitLoop2) ; - // Aggiungo i punti precedenti il punto di frattura nella NewLoop1. - NewLoop1.Join( SplitLoop1) ; - // Loop2 - PolyLine NewLoop2 ; - NewLoop2.Join( SplitLoop2) ; - // Inserisco i punti della catena nella PolyLine del nuovo loop. - for ( int m = int( cvOpenChain[nLastChainNum].size()) - 1 ; m >= 0 ; -- m) { - NewLoop2.AddUPoint( 0., cvOpenChain[nLastChainNum][m].ptEn) ; - if ( m == 0) - NewLoop2.AddUPoint( 0., cvOpenChain[nLastChainNum][m].ptSt) ; - } - // Loop esterno coinvolto - if ( vLoopIndexes[0] == 0) { - // Creo i pezzi nuovi, i cui loop esterni sono quelli appena definiti. - FacetPiece PieceInn, PieceOut ; - PieceInn.vPieceLoop.emplace_back( NewLoop1) ; - PieceInn.nPiecePart = 1 ; - PieceOut.vPieceLoop.emplace_back( NewLoop2) ; - PieceOut.nPiecePart = - 1 ; - // Assegno i loop interni del vecchio pezzo non tagliati da catene ai nuovi. - for ( int nIL = 1 ; nIL < int( vNewPieces[nPart].vPieceLoop.size()) ; ++ nIL) { - if ( nIL == vLoopIndexes[0]) - continue ; - Point3d ptPointInnerLoop ; - vNewPieces[nPart].vPieceLoop[nIL].GetFirstPoint( ptPointInnerLoop) ; - if ( PieceInn.vPieceLoop[0].GetPointNbr() < PieceOut.vPieceLoop[0].GetPointNbr()) { - if ( IsPointInsidePolyLine( ptPointInnerLoop, PieceInn.vPieceLoop[0], EPS_SMALL)) { - PieceInn.vPieceLoop.emplace_back( vNewPieces[nPart].vPieceLoop[nIL]) ; - } - else { - PieceOut.vPieceLoop.emplace_back( vNewPieces[nPart].vPieceLoop[nIL]) ; - } - } - else { - if ( IsPointInsidePolyLine( ptPointInnerLoop, PieceOut.vPieceLoop[0], EPS_SMALL)) { - PieceOut.vPieceLoop.emplace_back( vNewPieces[nPart].vPieceLoop[nIL]) ; - } - else { - PieceInn.vPieceLoop.emplace_back( vNewPieces[nPart].vPieceLoop[nIL]) ; - } - } - } - vNewPieces.erase( vNewPieces.begin() + nPart) ; - vNewPieces.emplace_back( PieceInn) ; - vNewPieces.emplace_back( PieceOut) ; - } - // Loop esterno non coinvolto - else { - Plane3d plLoopPlane1, plLoopPlane2, plContLoopPlane; - double dArea1, dArea2, dAreaCont; - NewLoop1.IsClosedAndFlat(plLoopPlane1, dArea1); - NewLoop2.IsClosedAndFlat(plLoopPlane2, dArea2); - vNewPieces[nPart].vPieceLoop[0].IsClosedAndFlat(plContLoopPlane, dAreaCont); - Vector3d vtLoopPlaneNorm1 = plLoopPlane1.GetVersN(); - Vector3d vtContLoopPlaneNorm = plContLoopPlane.GetVersN(); - PolyLine NewLoopCCW, NewLoopCW; - bool bFirstLoopIsCounter = vtLoopPlaneNorm1 * vtContLoopPlaneNorm > EPS_SMALL; - if (bFirstLoopIsCounter) { - NewLoopCCW = NewLoop1; - NewLoopCW = NewLoop2; - } - else { - NewLoopCCW = NewLoop2; - NewLoopCW = NewLoop1; - } - // Creo il pezzo nuovo, il cui loop esterno � stato appena definito. - FacetPiece DetachedPiece; - DetachedPiece.vPieceLoop.emplace_back(NewLoopCCW); - DetachedPiece.nPiecePart = bFirstLoopIsCounter ? 1 : -1; - // Al pezzo staccato assegno i loop interni del vecchio pezzo non tagliati da catene. - for ( int nIL = 1 ; nIL < int( vNewPieces[nPart].vPieceLoop.size()) ; ++ nIL) { - if ( nIL == vLoopIndexes[0]) - continue ; - Point3d ptPointInnerLoop ; - vNewPieces[nPart].vPieceLoop[nIL].GetFirstPoint( ptPointInnerLoop) ; - if ( IsPointInsidePolyLine( ptPointInnerLoop, DetachedPiece.vPieceLoop[0], EPS_SMALL)) { - DetachedPiece.vPieceLoop.emplace_back( vNewPieces[nPart].vPieceLoop[nIL]) ; - vNewPieces[nPart].vPieceLoop.erase( vNewPieces[nPart].vPieceLoop.begin() + nIL) ; - // Cambio il numero dei loop tagliati - for ( int nIntersLoop = 0 ; nIntersLoop < int( vLoopIndexes.size()) ; ++ nIntersLoop) { - if ( vLoopIndexes[nIntersLoop] > nIL) - -- vLoopIndexes[nIntersLoop] ; - } - -- nIL ; - } - } - // Aggiungo al pezzo, da cui si stacca quello appena creato, il loop complementare a quello che appartiene al pezzo che si stacca. - /*if ( ! bFirstLoopIsCounter)*/ - vNewPieces[nPart].vPieceLoop.erase(vNewPieces[nPart].vPieceLoop.begin() + vLoopIndexes[0]); - vNewPieces[nPart].vPieceLoop.emplace_back( NewLoopCW) ; - vNewPieces[nPart].nPiecePart = bFirstLoopIsCounter ? - 1 : 1 ; - vNewPieces.emplace_back( DetachedPiece) ; - } - // Elimino la catena usata. - cvOpenChain.erase( cvOpenChain.begin() + nLastChainNum) ; - // Interrompo il ciclo sulle parti. - break ; - } - // Cerco le catene per dividere la nuova parte. - else { - INTVECTOR vChainIndex ; - vChainIndex.emplace_back( nLastChainNum) ; - while ( vLoopIndexes.back() != vLoopIndexes[0]) { - // Cambio inizio del loop corrente in modo che il punto di inizio sia il punto finale dell'ultima catena trovata. - ChangePolyLineStart( vNewPieces[nPart].vPieceLoop[vLoopIndexes.back()], cvOpenChain[vChainIndex.back()].back().ptEn, 2 * EPS_SMALL) ; - // Cerco catene che iniziano sul loop coorente - vector vChainStartingOnLoop ; - for ( int nCh = 0 ; nCh < nLastChainNum ; ++ nCh) { - double dPar ; - if ( GetPointParamOnPolyLine( cvOpenChain[nCh][0].ptSt, vNewPieces[nPart].vPieceLoop[vLoopIndexes.back()], 2 * EPS_SMALL, dPar)) { - vChainStartingOnLoop.emplace_back( PositionOnPolyLine(nCh, dPar)) ; - } - } - // Ordino le catene secondo la vicinanza lungo il loop del loro punto d'inizio al punto d'inizio del loop stesso. - sort( vChainStartingOnLoop.begin(), vChainStartingOnLoop.end(), [] ( PositionOnPolyLine Ch1, PositionOnPolyLine Ch2) { - return Ch1.dPar < Ch2.dPar ; } ) ; - // Cerco la prima catena che non termina sul loop corrente. - for ( int n = 0 ; n < int( vChainStartingOnLoop.size()) ; ++ n) { - // Indice della catena e indice del segmento finale - int nCh = vChainStartingOnLoop[n].nIndexInVec ; - int nLastLineIndex = int( cvOpenChain[nCh].size()) - 1 ; - // Ciclo sui loop - int nLoopNum = int( vNewPieces[nPart].vPieceLoop.size()) ; - bool bFound = false ; - for ( int nLoop = 0 ; nLoop < nLoopNum ; ++ nLoop) { - // Salto il loop corrente - if ( nLoop == vLoopIndexes.back()) - continue ; - double dPar ; - // La catena termina su questo loop diverso da quello corrente. - if ( GetPointParamOnPolyLine( cvOpenChain[nCh][nLastLineIndex].ptEn, vNewPieces[nPart].vPieceLoop[nLoop], 2 * EPS_SMALL, dPar)) { - // Salvo l'indice della catena e quello del loop. - vChainIndex.emplace_back( nCh) ; - vLoopIndexes.emplace_back( nLoop) ; - bFound = true ; - break ; - } - } - if ( bFound) - break ; - } - } - // Cambio inizio al loop iniziale. - ChangePolyLineStart( vNewPieces[nPart].vPieceLoop[vLoopIndexes[0]], cvOpenChain[vChainIndex.back()].back().ptEn, 2 * EPS_SMALL) ; - // Divido i loop della parte. - POLYLINEVECTOR vPolySecondPartVec ; - PolyLine NewLoop1 ; - for ( int n = 0 ; n < int( vChainIndex.size()) ; ++ n) { - // Inserisco i punti della catena nella PolyLine del nuovo loop. - for ( int m = 0 ; m < int( cvOpenChain[vChainIndex[n]].size()) ; ++ m) { - NewLoop1.AddUPoint( 0., cvOpenChain[vChainIndex[n]][m].ptSt) ; - if ( m == int( cvOpenChain[vChainIndex[n]].size()) - 1) - NewLoop1.AddUPoint( 0., cvOpenChain[vChainIndex[n]][m].ptEn) ; - } - // Spezzo il loop successivo alla catena nel punto in cui comincia la catena successiva. - PolyLine SplitLoop1, SplitLoop2 ; - SplitPolyLineAtPoint( vNewPieces[nPart].vPieceLoop[vLoopIndexes[n + 1]], - cvOpenChain[vChainIndex[( n + 1) % int( vChainIndex.size())]][0].ptSt, 2 * EPS_SMALL, - SplitLoop1, SplitLoop2) ; - // Aggiungo i punti precedenti il punto di frattura in NewLoop1. - NewLoop1.Join( SplitLoop1) ; - // Salvo la parte dopo il punto di frattura in un apposito vettore. - vPolySecondPartVec.emplace_back( SplitLoop2) ; - } - PolyLine NewLoop2 ; - for ( int n = int( vChainIndex.size()) - 1 ; n >= 0 ; -- n) { - // Aggiungo i punti successivi il punto di frattura in NewLoop2. - NewLoop2.Join( vPolySecondPartVec[n]) ; - // Inserisco i punti della catena nella PolyLine del nuovo loop. - for ( int m = int( cvOpenChain[vChainIndex[n]].size()) - 1 ; m >= 0 ; -- m) { - NewLoop2.AddUPoint( 0., cvOpenChain[vChainIndex[n]][m].ptEn) ; - if ( m == 0) - NewLoop2.AddUPoint( 0., cvOpenChain[vChainIndex[n]][m].ptSt) ; - } - } - // Controllo che il loop esterno sia interessato. - bool bExtCutted = false ; - for ( int n = 0 ; n < int( vLoopIndexes.size()) && ! bExtCutted ; ++ n) { - if ( vLoopIndexes[n] == 0) - bExtCutted = true ; - } - // Loop esterno interessato - if ( bExtCutted) { - // Creo i pezzi nuovi, i cui loop esterni sono quelli appena definiti. - FacetPiece PieceInn, PieceOut ; - PieceInn.vPieceLoop.emplace_back( NewLoop1) ; - PieceInn.nPiecePart = 1 ; - PieceOut.vPieceLoop.emplace_back( NewLoop2) ; - PieceOut.nPiecePart = - 1 ; - // Assegno i loop interni del vecchio pezzo non tagliati da catene ai nuovi. - for ( int nIL = 1 ; nIL < int( vNewPieces[nPart].vPieceLoop.size()) ; ++ nIL) { - bool bUsed = false ; - for ( int nU = 0 ; nU < int( vLoopIndexes.size()) - 1 ; ++ nU) { - if ( nIL == vLoopIndexes[nU]) { - bUsed = true ; - break ; - } - } - if ( bUsed) - continue ; - Point3d ptPointInnerLoop ; - vNewPieces[nPart].vPieceLoop[nIL].GetFirstPoint( ptPointInnerLoop) ; - if ( PieceInn.vPieceLoop[0].GetPointNbr() < PieceOut.vPieceLoop[0].GetPointNbr()) { - if ( IsPointInsidePolyLine( ptPointInnerLoop, PieceInn.vPieceLoop[0], EPS_SMALL)) { - PieceInn.vPieceLoop.emplace_back( vNewPieces[nPart].vPieceLoop[nIL]) ; - } - else { - PieceOut.vPieceLoop.emplace_back( vNewPieces[nPart].vPieceLoop[nIL]) ; - } - } - else { - if ( IsPointInsidePolyLine( ptPointInnerLoop, PieceOut.vPieceLoop[0], EPS_SMALL)) { - PieceOut.vPieceLoop.emplace_back( vNewPieces[nPart].vPieceLoop[nIL]) ; - } - else { - PieceInn.vPieceLoop.emplace_back( vNewPieces[nPart].vPieceLoop[nIL]) ; - } - } - } - // Aggiungo i due nuovi pezzi ed elimino quello da cui sono nati. - vNewPieces.erase( vNewPieces.begin() + nPart) ; - vNewPieces.emplace_back( PieceInn) ; - vNewPieces.emplace_back( PieceOut) ; - } - // Loop esterno non interessato - else { - Plane3d plLoopPlane1, plLoopPlane2, plContLoopPlane ; - double dArea1, dArea2, dAreaCont ; - NewLoop1.IsClosedAndFlat( plLoopPlane1, dArea1) ; - NewLoop2.IsClosedAndFlat( plLoopPlane2, dArea2) ; - vNewPieces[nPart].vPieceLoop[0].IsClosedAndFlat( plContLoopPlane, dAreaCont) ; - Vector3d vtLoopPlaneNorm1 = plLoopPlane1.GetVersN(); - Vector3d vtContLoopPlaneNorm = plContLoopPlane.GetVersN(); - PolyLine NewLoopCCW, NewLoopCW; - bool bFirstLoopIsCounter = vtLoopPlaneNorm1 * vtContLoopPlaneNorm > EPS_SMALL; - if ( bFirstLoopIsCounter) { - NewLoopCCW = NewLoop1 ; - NewLoopCW = NewLoop2 ; - } - else { - NewLoopCCW = NewLoop2 ; - NewLoopCW = NewLoop1 ; - } - // // Creo il pezzo nuovo, il cui loop esterno � stato appena definito. - // FacetPiece PieceInn ; - // PieceInn.vPieceLoop.emplace_back( NewLoop1) ; - // PieceInn.nPiecePart = 1 ; - // // Assegno i loop interni del vecchio pezzo non tagliati da catene ai nuovi. - // for ( int nIL = 1 ; nIL < int( vNewPieces[nPart].vPieceLoop.size()) ; ++ nIL) { - // bool bUsed = false ; - // for ( int nU = 1 ; nU < int( vLoopIndexes.size()) - 1 ; ++ nU) { - // if ( nIL == vLoopIndexes[nU]) { - // bUsed = true ; - // break ; - // } - // } - // if ( bUsed) - // continue ; - // Point3d ptPointInnerLoop ; - // vNewPieces[nPart].vPieceLoop[nIL].GetFirstPoint( ptPointInnerLoop) ; - // if ( IsPointInsidePolyLine( ptPointInnerLoop, PieceInn.vPieceLoop[0])) { - // PieceInn.vPieceLoop.emplace_back( vNewPieces[nPart].vPieceLoop[nIL]) ; - // vNewPieces[nPart].vPieceLoop.erase( vNewPieces[nPart].vPieceLoop.begin() + nIL) ; - // -- nIL ; - // } - // } - // // Aggiungo al pezzo, da cui si stacca quello appena creato, il loop complementare a quello che appartiene al nuovo pezzo. - // vNewPieces[nPart].vPieceLoop.emplace_back( NewLoop2) ; - // vNewPieces[nPart].nPiecePart = - 1 ; - // vNewPieces.emplace_back( PieceInn) ; - // Creo il pezzo nuovo, il cui loop esterno � stato appena definito. - FacetPiece DetachedPiece ; - DetachedPiece.vPieceLoop.emplace_back( NewLoopCCW) ; - DetachedPiece.nPiecePart = bFirstLoopIsCounter ? 1 : - 1 ; - // Al pezzo che si stacca assegno i loop interni del vecchio pezzo non tagliati da catene. - for ( int nIL = 1 ; nIL < int( vNewPieces[nPart].vPieceLoop.size()) ; ++ nIL) { - bool bUsed = false ; - for ( int nU = 1 ; nU < int( vLoopIndexes.size()) - 1 ; ++ nU) { - if ( nIL == vLoopIndexes[nU]) { - bUsed = true ; - break ; - } - } - if ( bUsed) - continue ; - Point3d ptPointInnerLoop ; - vNewPieces[nPart].vPieceLoop[nIL].GetFirstPoint( ptPointInnerLoop) ; - if ( IsPointInsidePolyLine( ptPointInnerLoop, DetachedPiece.vPieceLoop[0], EPS_SMALL)) { - DetachedPiece.vPieceLoop.emplace_back( vNewPieces[nPart].vPieceLoop[nIL]) ; - vNewPieces[nPart].vPieceLoop.erase( vNewPieces[nPart].vPieceLoop.begin() + nIL) ; - // Cambio il numero dei loop talgiati - for ( int nIntersLoop = 0 ; nIntersLoop < int( vLoopIndexes.size()) ; ++ nIntersLoop) { - if ( vLoopIndexes[nIntersLoop] > nIL) - -- vLoopIndexes[nIntersLoop] ; - } - -- nIL ; - } - } - // Aggiungo al pezzo, da cui si stacca quello appena creato, il loop complementare a quello che appartiene al pezzo che si stacca. - vLoopIndexes.resize(int(vLoopIndexes.size()) - 1); - sort( vLoopIndexes.begin(), vLoopIndexes.end(), [] ( int nIndex1, int nIndex2) { return nIndex1 > nIndex2 ; }) ; - for (int nLoopInd = 0; nLoopInd < int(vLoopIndexes.size()); ++nLoopInd) { - vNewPieces[nPart].vPieceLoop.erase(vNewPieces[nPart].vPieceLoop.begin() + vLoopIndexes[nLoopInd]); - } - vNewPieces[nPart].vPieceLoop.emplace_back( NewLoopCW) ; - vNewPieces[nPart].nPiecePart = bFirstLoopIsCounter ? - 1 : 1 ; - vNewPieces.emplace_back( DetachedPiece) ; - } - // Elimino catene usate. - sort( vChainIndex.begin(), vChainIndex.end(), [] ( int nIndex1, int nIndex2) { return nIndex1 > nIndex2 ; }) ; - for ( int nChInd = 0 ; nChInd < int( vChainIndex.size()) ; ++ nChInd) { - cvOpenChain.erase( cvOpenChain.begin() + vChainIndex[nChInd]) ; - } - // Interrompo il ciclo sulle parti. - break ; - } - } - } - // Assegno i loop chiusi interni alle rispettive parti di faccia. - // Ciclo sui pezzi di facet. - int nPieceNum = int( vNewPieces.size()) ; - for ( int nPieceN = 0 ; nPieceN < nPieceNum ; ++ nPieceN) { - // Ciclo sui loop interni - for ( int nInnL = 0 ; nInnL < int( cvClosedChain.size()) ; ++ nInnL) { - // Trasformo il loop interno in PolyLine. - PolyLine CurInnerLoop ; - CurInnerLoop.AddUPoint( 0., cvClosedChain[nInnL][0].ptSt) ; - for ( int nSeg = 0 ; nSeg < int( cvClosedChain[nInnL].size()) ; ++ nSeg) { - CurInnerLoop.AddUPoint( 0., cvClosedChain[nInnL][nSeg].ptEn) ; - } - Plane3d plPlane ; - double dArea ; - if ( ! CurInnerLoop.IsClosedAndFlat( plPlane, dArea) || dArea < EPS_SMALL) - continue ; - // Ciclo sui punti del loop interno. - PNTULIST& LoopList = CurInnerLoop.GetUPointList() ; - for ( auto itInn = LoopList.begin() ; itInn != LoopList.end() ; ++ itInn) { - Point3d ptInnP = itInn->first ; - Point3d ptInnNextP ; - auto itInnNext = itInn ; - ++ itInnNext ; - if ( itInnNext != LoopList.end()) - ptInnNextP = itInnNext->first ; - if ( IsPointInsidePolyLine( ptInnP, vNewPieces[nPieceN].vPieceLoop[0], EPS_SMALL) || - ( itInnNext != LoopList.end() && - IsPointInsidePolyLine( 0.5 * ( ptInnP + ptInnNextP), vNewPieces[nPieceN].vPieceLoop[0], EPS_SMALL))) { - Polygon3d AuxPolygon ; - AuxPolygon.FromPolyLine( CurInnerLoop) ; - Vector3d vtInnLoopNorm = AuxPolygon.GetVersN() ; - if ( vtFacetNorm * vtInnLoopNorm < 0.) { - // Aggiungo loop al pezzo. - vNewPieces[nPieceN].nPiecePart = 1 ; - vNewPieces[nPieceN].vPieceLoop.emplace_back( CurInnerLoop) ; - // Aggiungo nuovo pezzo. - vNewPieces.emplace_back() ; - vNewPieces.back().vPieceLoop.emplace_back( CurInnerLoop) ; - vNewPieces.back().vPieceLoop.back().Invert() ; - vNewPieces.back().nPiecePart = - 1 ; - // Cerco loop interni a quello appena aggiunto - INTVECTOR vSecondLevel ; - for ( int nSI = 1 ; nSI < int( vNewPieces[nPieceN].vPieceLoop.size()) ; ++ nSI) { - PNTULIST& SecLevLoopList = vNewPieces[nPieceN].vPieceLoop[nSI].GetUPointList() ; - for ( auto itSL = SecLevLoopList.begin() ; itSL != SecLevLoopList.end() ; ++ itSL) { - Point3d ptPntSL = itSL->first ; - if ( IsPointInsidePolyLine( ptPntSL, vNewPieces.back().vPieceLoop.back(), EPS_SMALL)) { - vSecondLevel.emplace_back( nSI) ; - break ; - } - } - } - // Aggiungo i loop al nuovo pezzo e li tolgo dal precedente. - for ( int nSI = 0 ; nSI < int( vSecondLevel.size()) ; ++ nSI) - vNewPieces.back().vPieceLoop.emplace_back( vNewPieces[nPieceN].vPieceLoop[vSecondLevel[nSI]]) ; - for ( int nSI = 0 ; nSI < int( vSecondLevel.size()) ; ++ nSI) - vNewPieces[nPieceN].vPieceLoop.erase( vNewPieces[nPieceN].vPieceLoop.begin() + vSecondLevel[nSI]) ; - break ; - } - else { - // Aggiungo loop al pezzo. - vNewPieces[nPieceN].nPiecePart = - 1 ; - vNewPieces[nPieceN].vPieceLoop.emplace_back( CurInnerLoop) ; - vNewPieces[nPieceN].vPieceLoop.back().Invert() ; - // Aggiungo nuovo pezzo. - vNewPieces.emplace_back() ; - vNewPieces.back().vPieceLoop.emplace_back( CurInnerLoop) ; - vNewPieces.back().nPiecePart = 1 ; - // Cerco loop interni a quello appena aggiunto - INTVECTOR vSecondLevel ; - for ( int nSI = 1 ; nSI < int( vNewPieces[nPieceN].vPieceLoop.size()) ; ++ nSI) { - PNTULIST& SecLevLoopList = vNewPieces[nPieceN].vPieceLoop[nSI].GetUPointList() ; - for ( auto itSL = SecLevLoopList.begin() ; itSL != SecLevLoopList.end() ; ++ itSL) { - Point3d ptPntSL = itSL->first ; - if ( IsPointInsidePolyLine( ptPntSL, vNewPieces.back().vPieceLoop.back(), EPS_SMALL)) { - vSecondLevel.emplace_back( nSI) ; - break ; - } - } - } - // Aggiungo i loop al nuovo pezzo e li tolgo dal precedente. - for ( int nSI = 0 ; nSI < int( vSecondLevel.size()) ; ++ nSI) - vNewPieces.back().vPieceLoop.emplace_back( vNewPieces[nPieceN].vPieceLoop[vSecondLevel[nSI]]) ; - for ( int nSI = 0 ; nSI < int( vSecondLevel.size()) ; ++ nSI) - vNewPieces[nPieceN].vPieceLoop.erase( vNewPieces[nPieceN].vPieceLoop.begin() + vSecondLevel[nSI]) ; - break ; - } - } - } - } - } - // Aggiungo al loop esterno i punti dei loop interni che lo toccano. - // Ciclo sui pezzi della faccia. - for ( int nPieceN = 0 ; nPieceN < nPieceNum ; ++ nPieceN) { - // Ciclo sui segmenti del loop esterno. - PNTULIST& ExtLoopList = vNewPieces[nPieceN].vPieceLoop[0].GetUPointList() ; - auto itSt = ExtLoopList.begin() ; auto itEn = itSt ; ++ itEn ; - for ( ; itEn != ExtLoopList.end(); ++itSt, ++itEn) { - Point3d ptSt = itSt->first ; - Point3d ptEn = itEn->first ; - Vector3d vtSeg = ptEn - ptSt ; - double dSegLen = vtSeg.Len() ; - vtSeg /= dSegLen ; - // Vettore dei punti dei loop interni che stanno sul segmento del loop esterno - PNTUVECTOR vPointWithOrder ; - // Ciclo sui loop interni del pezzo - int nInnerLoopNum = int( vNewPieces[nPieceN].vPieceLoop.size()) ; - for ( int nInnLoop = 1 ; nInnLoop < nInnerLoopNum ; ++ nInnLoop) { - // Ciclo sui punti del loop interno. - Point3d ptInnPoint ; - bool bIsFirst = true ; - bool bContinue = vNewPieces[nPieceN].vPieceLoop[nInnLoop].GetFirstPoint( ptInnPoint) ; - while ( bContinue) { - DistPointLine DistCalculator( ptInnPoint, ptSt, ptEn) ; - double dDist ; - DistCalculator.GetDist( dDist) ; - double dLongPos = ( ptInnPoint - ptSt) * vtSeg ; - if ( dDist < 10 * EPS_SMALL && dLongPos > 0. && dLongPos < dSegLen) { - POINTU NewPointU ; - NewPointU.first = ptInnPoint ; - NewPointU.second = dLongPos ; - if ( ! bIsFirst) - vPointWithOrder.emplace_back( NewPointU) ; - } - bIsFirst = false ; - bContinue = vNewPieces[nPieceN].vPieceLoop[nInnLoop].GetNextPoint( ptInnPoint) ; - } - } - // Riordino i punti interni sul segmento esterno in funzione della distanza dall'origine di esso - for ( int nPi = 0 ; nPi < int( vPointWithOrder.size()) - 1 ; ++ nPi) { - for ( int nPj = nPi + 1 ; nPj < int( vPointWithOrder.size()) ; ++ nPj) { - if ( vPointWithOrder[nPi].second > vPointWithOrder[nPj].second) { - swap( vPointWithOrder[nPi], vPointWithOrder[nPj]) ; - } - } - } - // Aggiungo i punti al loop esterno - for ( int nPi = 0 ; nPi < int( vPointWithOrder.size()) ; ++ nPi) { - itSt = ExtLoopList.emplace( itEn, vPointWithOrder[nPi]) ; - } - } - } - // Se non ho diviso la faccia, la elimino - if ( int( vNewPieces.size()) == 1) - NewFacet.erase( it->first) ; - } - return true ; -} - -//---------------------------------------------------------------------------- -bool -SurfTriMesh::EdgeInteriorContactManager( const SurfTriMesh& OthSurf, - const INTERSCHAINMAP& InterInterLineMap, - const INTERSEDGEMAP& EdgeInterLineMap) -{ - // Ciclo su tutte le facce. - for ( auto it = EdgeInterLineMap.begin() ; it != EdgeInterLineMap.end() ; ++ it) { - int nFacet = it->first ; - const vector& vEdgeContact = it->second ; - // Triangoli della faccia - INTVECTOR vFacetTria ; - GetAllTriaInFacet( nFacet, vFacetTria) ; - // Versore normale alla faccia. - Vector3d vtN = m_vTria[m_vFacet[nFacet]].vtN ; - // Se la faccia � stata tagliata, salto alla prossima faccia. - if ( InterInterLineMap.find( nFacet) != InterInterLineMap.end()) - continue ; - int nInOutPart = 0 ; - // Ciclo sui contatti edge-interno della faccia. - for ( const IntersEdge& Edge : vEdgeContact) { - // Estremi del segmento di contatto - Point3d ptSegSt = Edge.ptSt ; - Point3d ptSegEn = Edge.ptEn ; - Vector3d vtSegDir = ptSegEn - ptSegSt ; - double dLen = vtSegDir.Len() ; - if ( dLen < EPS_SMALL) - continue ; - vtSegDir /= dLen ; - // Cerco il tratto della frontiera della faccia su cui giace il segmento di contatto. - Vector3d vtLoopSeg ; - POLYLINEVECTOR vFacetLoop ; - GetFacetLoops( nFacet, vFacetLoop) ; - for ( int nL = 0 ; nL < int( vFacetLoop.size()) && nInOutPart == 0 ; ++ nL) { - Point3d ptLs, ptLe ; - bool bContinue = vFacetLoop[nL].GetFirstPoint( ptLs) && vFacetLoop[nL].GetNextPoint( ptLe) ; - while ( bContinue) { - DistPointLine StartPointLineDistCalc( ptLs, ptSegSt, ptSegEn, false) ; - double dDistStart ; - StartPointLineDistCalc.GetDist( dDistStart) ; - DistPointLine EndPointLineDistCalc( ptLe, ptSegSt, ptSegEn, false) ; - double dDistEnd ; - EndPointLineDistCalc.GetDist( dDistEnd) ; - double dUS = ( ptLs - ptSegSt) * vtSegDir ; - double dUE = ( ptLe - ptSegSt) * vtSegDir ; - // Segmento sovrapposto - if ( dDistStart < EPS_SMALL && dDistEnd < EPS_SMALL && dUS < dLen + EPS_SMALL && dUE > - EPS_SMALL) { - vtLoopSeg = ptLe - ptLs ; - vtLoopSeg.Normalize() ; - bContinue = false ; - } - else { - ptLs = ptLe ; - bContinue = vFacetLoop[nL].GetNextPoint( ptLe) ; - } - } - } - // Determino il valore dell'indice interno/esterno. - Vector3d vtIn = vtN ^ vtLoopSeg ; - // Ciclo sulle facce di contatto dell'altra superficie. - for ( int nOthFacet = 0 ; nOthFacet < int( Edge.vOthFacetIndex.size()) && nInOutPart == 0 ; ++ nOthFacet) { - int nOthFacetIndex = Edge.vOthFacetIndex[nOthFacet] ; - // Versore normale all'altra faccia. - Vector3d vtOthN = OthSurf.m_vTria[OthSurf.m_vFacet[nOthFacetIndex]].vtN ; - // Valore dell'indice interno/esterno. - nInOutPart = ( vtIn * vtOthN < - EPS_SMALL ? 1 : ( vtIn * vtOthN > EPS_SMALL ? - 1 : 0)) ; - } - // Ciclo sui triangoli della faccia - for ( int& nT : vFacetTria) { - // Assegno indice interno/esterno al triangolo - m_vTria[nT].nTempPart = nInOutPart ; - Triangle3d trTria ; - GetTriangle( nT, trTria) ; - trTria.Validate() ; - // Se un segmento del triangolo si sovrappone a quello di contatto, lo marco come invalicabile. - for ( int n = 0 ; n < 3 ; ++ n) { - Point3d ptTS = trTria.GetP( n) ; - Point3d ptTE = trTria.GetP( ( n + 1) % 3) ; - DistPointLine StartPointLineDistCalc( ptTS, ptSegSt, ptSegEn, false) ; - double dDistStart ; - StartPointLineDistCalc.GetDist( dDistStart) ; - DistPointLine EndPointLineDistCalc( ptTE, ptSegSt, ptSegEn, false) ; - double dDistEnd ; - EndPointLineDistCalc.GetDist( dDistEnd) ; - double dUS = ( ptTS - ptSegSt) * vtSegDir ; - double dUE = ( ptTE - ptSegSt) * vtSegDir ; - // Segmento sovrapposto - if ( dDistStart < EPS_SMALL && dDistEnd < EPS_SMALL && dUS < dLen + EPS_SMALL && dUE > - EPS_SMALL) { - m_vTria[nT].nETempFlag[n] = 1 ; - } - } - } - } - } - return true ; -} - -//---------------------------------------------------------------------------- -bool -SurfTriMesh::EdgeEdgeContactManager( const SurfTriMesh& OthSurf, - const INTERSCHAINMAP& InterInterLineMap, - const INTERSEDGEMAP& EdgeEdgeLineMap) -{ - // Ciclo su tutte le facce. - for ( auto it = EdgeEdgeLineMap.begin() ; it != EdgeEdgeLineMap.end() ; ++ it) { - int nFacet = it->first ; - const vector& vEdgeContact = it->second ; - // Triangoli della faccia - INTVECTOR vFacetTria ; - GetAllTriaInFacet( nFacet, vFacetTria) ; - // Versore normale alla faccia. - Vector3d vtN = m_vTria[m_vFacet[nFacet]].vtN ; - // Se la faccia � stata tagliata, salto alla prossima faccia. - if ( InterInterLineMap.find( nFacet) != InterInterLineMap.end()) - continue ; - int nInOutPart = 0 ; - // Ciclo sui contatti edge-interno della faccia. - for ( const IntersEdge& Edge : vEdgeContact) { - // Estremi del segmento di contatto - Point3d ptSegSt = Edge.ptSt ; - Point3d ptSegEn = Edge.ptEn ; - Vector3d vtSegDir = ptSegEn - ptSegSt ; - double dLen = vtSegDir.Len() ; - if ( dLen < EPS_SMALL) - continue ; - vtSegDir /= dLen ; - // Cerco il tratto della frontiera della faccia su cui giace il segmento di contatto. - Vector3d vtLoopSeg ; - POLYLINEVECTOR vFacetLoop ; - GetFacetLoops( nFacet, vFacetLoop) ; - for ( int nL = 0 ; nL < int( vFacetLoop.size()) && nInOutPart == 0 ; ++ nL) { - Point3d ptLs, ptLe ; - bool bContinue = vFacetLoop[nL].GetFirstPoint( ptLs) && vFacetLoop[nL].GetNextPoint( ptLe) ; - while ( bContinue) { - DistPointLine StartPointLineDistCalc( ptLs, ptSegSt, ptSegEn, false) ; - double dDistStart ; - StartPointLineDistCalc.GetDist( dDistStart) ; - DistPointLine EndPointLineDistCalc( ptLe, ptSegSt, ptSegEn, false) ; - double dDistEnd ; - EndPointLineDistCalc.GetDist( dDistEnd) ; - double dUS = ( ptLs - ptSegSt) * vtSegDir ; - double dUE = ( ptLe - ptSegSt) * vtSegDir ; - // Segmento sovrapposto - if ( dDistStart < EPS_SMALL && dDistEnd < EPS_SMALL && dUS < dLen + EPS_SMALL && dUE > - EPS_SMALL) { - vtLoopSeg = ptLe - ptLs ; - vtLoopSeg.Normalize() ; - bContinue = false ; - } - else { - ptLs = ptLe ; - bContinue = vFacetLoop[nL].GetNextPoint( ptLe) ; - } - } - } - // Determino il valore dell'indice interno/esterno. - // Vettore diretto verso l'interno della faccia. - Vector3d vtIn = vtN ^ vtLoopSeg ; - // Ciclo sulle facce di contatto dell'altra superficie. - int nOthFacet1 ; - int nOthFacet2 = - 1 ; - for ( nOthFacet1 = 0 ; nOthFacet1 < int( Edge.vOthFacetIndex.size()) - 1 && nInOutPart == 0 ; ++ nOthFacet1) { - int nOthFacetIndex1 = Edge.vOthFacetIndex[nOthFacet1] ; - Vector3d vtOthN1 = OthSurf.m_vTria[OthSurf.m_vFacet[nOthFacetIndex1]].vtN ; - for ( nOthFacet2 = nOthFacet1 + 1 ; nOthFacet2 < int( Edge.vOthFacetIndex.size()) && nInOutPart == 0 ; ++ nOthFacet2) { - int nOthFacetIndex2 = Edge.vOthFacetIndex[nOthFacet2] ; - Vector3d vtOthN2 = OthSurf.m_vTria[OthSurf.m_vFacet[nOthFacetIndex2]].vtN ; - if ( ! AreSameVectorApprox( vtOthN1, vtOthN2)) { - break ; - } - } - if ( nOthFacet2 != int( Edge.vOthFacetIndex.size())) - break ; - } - // Se l'indice interno/esterno non � stato assegnato - if ( nInOutPart == 0) { - // Se non ho trovato una coppia di facce, uso la prima. - if ( ( nOthFacet1 == int( Edge.vOthFacetIndex.size()) - 1 && nOthFacet2 == int( Edge.vOthFacetIndex.size())) || nOthFacet2 == - 1) { - ; - //int nOthFacetIndex1 = Edge.vOthFacetIndex[0] ; - //Vector3d vtOthN1 = OthSurf.m_vTria[OthSurf.m_vFacet[nOthFacetIndex1]].vtN ; - //// Valore dell'indice interno/esterno. - //nInOutPart = ( vtIn * vtOthN1 < - EPS_SMALL ? 1 : ( vtIn * vtOthN1 > EPS_SMALL ? - 1 : 0)) ; - } - // Due facce - else { - int nOthFacetIndex1 = Edge.vOthFacetIndex[nOthFacet1] ; - Vector3d vtOthN1 = OthSurf.m_vTria[OthSurf.m_vFacet[nOthFacetIndex1]].vtN ; - int nOthFacetIndex2 = Edge.vOthFacetIndex[nOthFacet2] ; - Vector3d vtOthN2 = OthSurf.m_vTria[OthSurf.m_vFacet[nOthFacetIndex2]].vtN ; - POLYLINEVECTOR vOthFacetLoop2 ; - OthSurf.GetFacetLoops( nOthFacetIndex2, vOthFacetLoop2) ; - Vector3d vtContactEdgeLoop2 ; - Point3d ptLs, ptLe ; - bool bContinue = true ; - for ( int nL = 0 ; nL < int( vOthFacetLoop2.size()) && bContinue ; ++ nL) { - bContinue = vOthFacetLoop2[nL].GetFirstPoint( ptLs) && vOthFacetLoop2[nL].GetNextPoint( ptLe) ; - while ( bContinue) { - DistPointLine StartPointLineDistCalc( ptLs, ptSegSt, ptSegEn, false) ; - double dDistStart ; - StartPointLineDistCalc.GetDist( dDistStart) ; - DistPointLine EndPointLineDistCalc( ptLe, ptSegSt, ptSegEn, false) ; - double dDistEnd ; - EndPointLineDistCalc.GetDist( dDistEnd) ; - double dUS = ( ptLs - ptSegSt) * vtSegDir ; - double dUE = ( ptLe - ptSegSt) * vtSegDir ; - // Segmento sovrapposto - if ( dDistStart < EPS_SMALL && dDistEnd < EPS_SMALL && dUS < dLen + EPS_SMALL && dUE > - EPS_SMALL) { - vtContactEdgeLoop2 = ptLe - ptLs ; - vtContactEdgeLoop2.Normalize() ; - bContinue = false ; - } - else { - ptLs = ptLe ; - bContinue = vOthFacetLoop2[nL].GetNextPoint( ptLe) ; - } - } - } - Vector3d vtInFacet2 = vtN ^ vtContactEdgeLoop2 ; - // Convesso - if ( vtInFacet2 * vtOthN1 < 0.) { - nInOutPart = vtIn * vtOthN1 < 0 && vtIn * vtOthN2 < 0 ? 1 : - 1 ; - } - // Concavo - else { - nInOutPart = vtIn * vtOthN1 > 0 && vtIn * vtOthN2 > 0 ? - 1 : 1 ; - } - } - } - // Ciclo sui triangoli della faccia - for ( int& nT : vFacetTria) { - // Assegno indice interno/esterno al triangolo - m_vTria[nT].nTempPart = nInOutPart ; - Triangle3d trTria ; - GetTriangle( nT, trTria) ; - trTria.Validate() ; - // Se un segmento del triangolo si sovrappone a quello di contatto, lo marco come invalicabile. - for ( int n = 0 ; n < 3 ; ++ n) { - Point3d ptTS = trTria.GetP( n) ; - Point3d ptTE = trTria.GetP( ( n + 1) % 3) ; - DistPointLine StartPointLineDistCalc( ptTS, ptSegSt, ptSegEn, false) ; - double dDistStart ; - StartPointLineDistCalc.GetDist( dDistStart) ; - DistPointLine EndPointLineDistCalc( ptTE, ptSegSt, ptSegEn, false) ; - double dDistEnd ; - EndPointLineDistCalc.GetDist( dDistEnd) ; - double dUS = ( ptTS - ptSegSt) * vtSegDir ; - double dUE = ( ptTE - ptSegSt) * vtSegDir ; - // Segmento sovrapposto - if ( dDistStart < EPS_SMALL && dDistEnd < EPS_SMALL && dUS < dLen + EPS_SMALL && dUE > - EPS_SMALL) { - m_vTria[nT].nETempFlag[n] = 1 ; - } - } - } - } - } - return true ; -} - -//---------------------------------------------------------------------------- -bool -SurfTriMesh::RetriangulateFacetPieces( const PieceMap& NewFacet, - const INTERSEDGEMAP& EdgeInterLineMap, - const INTERSEDGEMAP& EdgeEdgeLineMap) -{ - // Vettore degli indici delle facce - INTVECTOR vFacetIndexes ; - // Ciclo sulle facce. - for ( auto it = NewFacet.begin() ; it != NewFacet.end() ; ++ it) { - // Accedo al colore di un triangolo della faccia e cancello i triangoli della faccia. - INTVECTOR vFacetTria ; - GetAllTriaInFacet( it->first, vFacetTria) ; - for ( int& nT : vFacetTria) - RemoveTriangle( nT) ; - } - for ( auto it = NewFacet.begin() ; it != NewFacet.end() ; ++ it) { - const vector& PiecesVector = it->second ; - // Ciclo sui nuovi pezzi di faccia. - int nPartNum = int( PiecesVector.size()) ; - for ( int nPart = 0 ; nPart < nPartNum ; ++ nPart) { - PNTVECTOR vPt ; - INTVECTOR vTr ; - if ( Triangulate().Make( PiecesVector[nPart].vPieceLoop, vPt, vTr)) { - // Inserisco i nuovi triangoli - for ( int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) { - int nNewTriaVertId[3] = { vTr[n], vTr[n + 1], vTr[n + 2]} ; - int nNewId[3] = { AddVertex( vPt[nNewTriaVertId[0]]), - AddVertex( vPt[nNewTriaVertId[1]]), - AddVertex( vPt[nNewTriaVertId[2]])} ; - // Il colore passato nel secondo parametro � definito perch� il vettore delle facce ha ancora salvato l'indice di un suo triangolo e - // il triangolo � cancellato semplicente assegnadno la costante apposita VT_DEL (-2) a nIdVert[0]; ma il suo colore resta definito. - int nNewTriaNum = AddTriangle( nNewId, m_vTria[m_vFacet[it->first]].nTFlag) ; - if ( IsValidSvt( nNewTriaNum)) { - // Assegno l'indice della parte interno/esterno. - m_vTria[nNewTriaNum].nTempPart = PiecesVector[nPart].nPiecePart ; - // Indici parte interno/esterno invalicabili - m_vTria[nNewTriaNum].nETempFlag[0] = 0 ; - m_vTria[nNewTriaNum].nETempFlag[1] = 0 ; - m_vTria[nNewTriaNum].nETempFlag[2] = 0 ; - // Se la faccia ha avuto un contatto edge-interior, cerco edge invalicabili. - auto itEdgeInterEdge = EdgeInterLineMap.find( it->first) ; - auto itEdgeEdgeEdge = EdgeEdgeLineMap.find( it->first) ; - if ( itEdgeInterEdge != EdgeInterLineMap.end()) { - const vector& vEdgeContact = itEdgeInterEdge->second ; - Triangle3d trTria ; - GetTriangle( nNewTriaNum, trTria) ; - // Ciclo sui segmenti del triangolo. - for ( int n = 0 ; n < 3 ; ++ n) { - Point3d ptTS = trTria.GetP( n) ; - Point3d ptTE = trTria.GetP( ( n + 1) % 3) ; - for (int m = 0; m < int(vEdgeContact.size()) ; ++ m) { - Point3d ptEdgeSt = vEdgeContact[m].ptSt ; - Point3d ptEdgeEn = vEdgeContact[m].ptEn ; - Vector3d vtEdgeDir = ptEdgeEn - ptEdgeSt ; - double dLen = vtEdgeDir.Len() ; - if ( dLen < EPS_SMALL) - continue ; - DistPointLine StartPointLineDistCalc( ptTS, ptEdgeSt, ptEdgeEn, false) ; - double dDistStart ; - StartPointLineDistCalc.GetDist( dDistStart) ; - DistPointLine EndPointLineDistCalc( ptTE, ptEdgeSt, ptEdgeEn, false) ; - double dDistEnd ; - EndPointLineDistCalc.GetDist( dDistEnd) ; - double dUS = ( ptTS - ptEdgeSt) * vtEdgeDir ; - double dUE = ( ptTE - ptEdgeSt) * vtEdgeDir ; - // Segmento sovrapposto - if ( dDistStart < EPS_SMALL && dDistEnd < EPS_SMALL && dUS < dLen && dUE > 0) { - m_vTria[nNewTriaNum].nETempFlag[n] = 1 ; - break ; - } - } - } - } - else if ( itEdgeEdgeEdge != EdgeEdgeLineMap.end()) { - const vector& vEdgeContact = itEdgeEdgeEdge->second ; - Triangle3d trTria ; - GetTriangle( nNewTriaNum, trTria) ; - // Ciclo sui segmenti del triangolo. - for ( int n = 0 ; n < 3 ; ++ n) { - Point3d ptTS = trTria.GetP( n) ; - Point3d ptTE = trTria.GetP( ( n + 1) % 3) ; - for (int m = 0; m < int(vEdgeContact.size()) ; ++ m) { - Point3d ptEdgeSt = vEdgeContact[m].ptSt ; - Point3d ptEdgeEn = vEdgeContact[m].ptEn ; - Vector3d vtEdgeDir = ptEdgeEn - ptEdgeSt ; - double dLen = vtEdgeDir.Len() ; - if ( dLen < EPS_SMALL) - continue ; - DistPointLine StartPointLineDistCalc( ptTS, ptEdgeSt, ptEdgeEn, false) ; - double dDistStart ; - StartPointLineDistCalc.GetDist( dDistStart) ; - DistPointLine EndPointLineDistCalc( ptTE, ptEdgeSt, ptEdgeEn, false) ; - double dDistEnd ; - EndPointLineDistCalc.GetDist( dDistEnd) ; - double dUS = ( ptTS - ptEdgeSt) * vtEdgeDir ; - double dUE = ( ptTE - ptEdgeSt) * vtEdgeDir ; - // Segmento sovrapposto - if ( dDistStart < EPS_SMALL && dDistEnd < EPS_SMALL && dUS < dLen && dUE > 0) { - m_vTria[nNewTriaNum].nETempFlag[n] = 1 ; - break ; - } - } - } - } - } - } - } - } - } - return true ; -} - -//---------------------------------------------------------------------------- -bool -SurfTriMesh::IntersectTriMeshFacets( SurfTriMesh& Other) -{ - //////////////////////////////////////////////////////////////////////////////////////////////////////// - static int nTime = 0 ; - nTime ++ ; - //////////////////////////////////////////////////////////////////////////////////////////////////////// - SurfTriMesh& SurfB = Other ; - // Le superfici devono essere valide - if ( m_nStatus != OK || ! SurfB.IsValid()) - return false ; - // Unordered map dei segmenti di intersezione (contatti interno-interno) e dei contatti con edge - INTERSCHAINMAP IntersLineMapA, IntersLineMapB ; - INTERSEDGEMAP EdgeInnLineMapA, EdgeInnLineMapB ; - INTERSEDGEMAP EdgeEdgeLineMapA, EdgeEdgeLineMapB ; - // Setto il triangolo come n� fuori n� dentro - int nTriaNumA = GetTriangleSize(); - int nTriaNumB = SurfB.GetTriangleSize(); - for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) { - m_vTria[nTA].nTempPart = 0 ; - m_vTria[nTA].nETempFlag[0] = 0 ; - m_vTria[nTA].nETempFlag[1] = 0 ; - m_vTria[nTA].nETempFlag[2] = 0 ; - } - for ( int nTB = 0 ; nTB < nTriaNumB ; ++ nTB) { - SurfB.m_vTria[nTB].nTempPart = 0 ; - SurfB.m_vTria[nTB].nETempFlag[0] = 0 ; - SurfB.m_vTria[nTB].nETempFlag[1] = 0 ; - SurfB.m_vTria[nTB].nETempFlag[2] = 0 ; - } - // Ciclo sulle facce delle mesh - int nFacetNumA = GetFacetCount() ; - for ( int nFA = 0 ; nFA < nFacetNumA ; ++ nFA) { - // Dati della faccia - POLYLINEVECTOR LoopVecA ; - GetFacetLoops( nFA, LoopVecA) ; - PtrOwner pRegA( GetBasicSurfFlatRegion( GetSurfFlatRegionFromPolyLineVector( LoopVecA))) ; - if ( pRegA == nullptr) - return false ; - SurfFlatRegion RegionA = *pRegA ; - // Recupero tutti i triangoli della superficie B che cadono nel box della faccia di A. - BBox3d b3BoxA ; - RegionA.GetLocalBBox( b3BoxA) ; - INTVECTOR vNearTria ; - SurfB.GetAllTriaOverlapBox( b3BoxA, vNearTria) ; - // Determino le facce a cui appartengono i tirangoli che cadono nel box - INTVECTOR vFacetIndexesB ; - for ( int& nT : vNearTria) { - int nF = SurfB.GetFacetFromTria(nT) ; - int n ; - for ( n = 0 ; n < int( vFacetIndexesB.size()) ; ++ n) { - if ( nF == vFacetIndexesB[n]) - break ; - } - if ( n == int(vFacetIndexesB.size())) - vFacetIndexesB.emplace_back( nF) ; - } - for ( int& nFB : vFacetIndexesB) { - // Dati della faccia - POLYLINEVECTOR LoopVecB ; - SurfB.GetFacetLoops( nFB, LoopVecB) ; - PtrOwner pRegB( GetBasicSurfFlatRegion( GetSurfFlatRegionFromPolyLineVector( LoopVecB))) ; - if ( pRegB == nullptr) - return false ; - SurfFlatRegion RegionB = *pRegB ; - // Interseco le due facce - LineFacetClassVector CommonIntersection ; - // Intersezione fra le facce - if ( IntersFacetFacet( RegionA, LoopVecA[0], RegionB, LoopVecB[0], CommonIntersection)) { - // Ciclo sulle parti dell'intersezione - for ( int nPart = 0 ; nPart < int( CommonIntersection.size()) ; ++ nPart) { - // Intersezione nell'interno di entrambe le facce - if ( CommonIntersection[nPart].nTypeA == CRVC_IN && - CommonIntersection[nPart].nTypeB == CRVC_IN) { - // Salvo intersezione per la faccia A - auto itA = IntersLineMapA.find( nFA) ; - if ( itA != IntersLineMapA.end()) { - itA->second.emplace_back( IntersInnSeg( CommonIntersection[nPart].ptSt, CommonIntersection[nPart].ptEn)) ; - } - else { - IntersLineMapA.emplace( nFA, IntersInnChain( 1, IntersInnSeg( CommonIntersection[nPart].ptSt, CommonIntersection[nPart].ptEn))) ; - } - // Salvo intersezione per la faccia B - auto itB = IntersLineMapB.find( nFB) ; - if ( itB != IntersLineMapB.end()) { - itB->second.emplace_back( IntersInnSeg( CommonIntersection[nPart].ptEn, CommonIntersection[nPart].ptSt)) ; - } - else { - IntersLineMapB.emplace( nFB, IntersInnChain( 1, IntersInnSeg( CommonIntersection[nPart].ptEn, CommonIntersection[nPart].ptSt))) ; - } - } - // Intersezione all'interno della faccia A - else if ( CommonIntersection[nPart].nTypeA == CRVC_IN) { - // Salvo intersezione per la faccia A - auto itA = IntersLineMapA.find( nFA) ; - if ( itA != IntersLineMapA.end()) { - itA->second.emplace_back( IntersInnSeg( CommonIntersection[nPart].ptSt, CommonIntersection[nPart].ptEn)) ; - } - else { - IntersLineMapA.emplace( nFA, IntersInnChain( 1, IntersInnSeg( CommonIntersection[nPart].ptSt, CommonIntersection[nPart].ptEn))) ; - } - // Salvo intersezione per la faccia B - auto itB = EdgeInnLineMapB.find( nFB) ; - if ( itB != EdgeInnLineMapB.end()) { - int nE ; - for ( nE = 0 ; nE < int( itB->second.size()) ; ++ nE) { - if ( AreSamePointExact( itB->second[nE].ptSt, CommonIntersection[nPart].ptEn) && - AreSamePointExact( itB->second[nE].ptEn, CommonIntersection[nPart].ptSt)) { - itB->second[nE].vOthFacetIndex.emplace_back( nFA) ; - break ; - } - } - if ( nE == int( itB->second.size())) { - itB->second.emplace_back( IntersEdge( CommonIntersection[nPart].ptEn, CommonIntersection[nPart].ptSt, INTVECTOR( 1, nFA))) ; - } - } - else { - EdgeInnLineMapB.emplace( nFB, IntersEdgeVec( 1, IntersEdge( CommonIntersection[nPart].ptEn, CommonIntersection[nPart].ptSt, - INTVECTOR( 1, nFA)))) ; - } - } - // Intersezione all'interno della faccia B - else if ( CommonIntersection[nPart].nTypeB == CRVC_IN) { - // Salvo intersezione per la faccia A - auto itA = EdgeInnLineMapA.find( nFA) ; - if ( itA != EdgeInnLineMapA.end()) { - int nE ; - for ( nE = 0 ; nE < int( itA->second.size()) ; ++ nE) { - if ( AreSamePointExact( itA->second[nE].ptSt, CommonIntersection[nPart].ptSt) && - AreSamePointExact( itA->second[nE].ptEn, CommonIntersection[nPart].ptEn)) { - itA->second[nE].vOthFacetIndex.emplace_back( nFB) ; - break ; - } - } - if ( nE == int( itA->second.size())) { - itA->second.emplace_back( IntersEdge( CommonIntersection[nPart].ptSt, CommonIntersection[nPart].ptEn, INTVECTOR( 1, nFB))) ; - } - } - else { - EdgeInnLineMapA.emplace( nFA, IntersEdgeVec( 1, IntersEdge( CommonIntersection[nPart].ptSt, CommonIntersection[nPart].ptEn, - INTVECTOR( 1, nFB)))) ; - } - // Salvo intersezione per la faccia B - auto itB = IntersLineMapB.find( nFB) ; - if ( itB != IntersLineMapB.end()) { - itB->second.emplace_back( IntersInnSeg( CommonIntersection[nPart].ptEn, CommonIntersection[nPart].ptSt)) ; - } - else { - IntersLineMapB.emplace( nFB, IntersInnChain( 1, IntersInnSeg( CommonIntersection[nPart].ptEn, CommonIntersection[nPart].ptSt))) ; - } - } - // Intersezione sulla frontiera di entrambe le facce - else { - // Salvo intersezione per la faccia A - auto itA = EdgeEdgeLineMapA.find( nFA) ; - if ( itA != EdgeEdgeLineMapA.end()) { - int nE ; - for ( nE = 0 ; nE < int( itA->second.size()) ; ++ nE) { - if ( ( AreSamePointExact( itA->second[nE].ptSt, CommonIntersection[nPart].ptSt) && - AreSamePointExact( itA->second[nE].ptEn, CommonIntersection[nPart].ptEn)) || - ( AreSamePointExact( itA->second[nE].ptSt, CommonIntersection[nPart].ptEn) && - AreSamePointExact( itA->second[nE].ptEn, CommonIntersection[nPart].ptSt))) { - itA->second[nE].vOthFacetIndex.emplace_back( nFB) ; - break ; - } - } - if ( nE == int( itA->second.size())) { - itA->second.emplace_back( IntersEdge( CommonIntersection[nPart].ptSt, CommonIntersection[nPart].ptEn, INTVECTOR( 1, nFB))); - } - } - else { - EdgeEdgeLineMapA.emplace( nFA, IntersEdgeVec( 1, IntersEdge( CommonIntersection[nPart].ptSt, CommonIntersection[nPart].ptEn, - INTVECTOR( 1, nFB)))) ; - } - // Salvo intersezione per la faccia B - auto itB = EdgeEdgeLineMapB.find( nFB) ; - if ( itB != EdgeEdgeLineMapB.end()) { - int nE ; - for ( nE = 0 ; nE < int( itB->second.size()) ; ++ nE) { - if ( ( AreSamePointExact( itB->second[nE].ptSt, CommonIntersection[nPart].ptEn) && - AreSamePointExact( itB->second[nE].ptEn, CommonIntersection[nPart].ptSt)) || - ( AreSamePointExact( itB->second[nE].ptSt, CommonIntersection[nPart].ptSt) && - AreSamePointExact( itB->second[nE].ptEn, CommonIntersection[nPart].ptEn))) { - itB->second[nE].vOthFacetIndex.emplace_back( nFA) ; - break ; - } - } - if ( nE == int( itB->second.size())) { - itB->second.emplace_back( IntersEdge( CommonIntersection[nPart].ptEn, CommonIntersection[nPart].ptSt, INTVECTOR( 1, nFA))) ; - } - } - else { - EdgeEdgeLineMapB.emplace( nFB, IntersEdgeVec( 1, IntersEdge( CommonIntersection[nPart].ptEn, CommonIntersection[nPart].ptSt, - INTVECTOR( 1, nFA)))) ; - } - } - } - } - } - } - - // Divido le facce - PieceMap NewFacetA, NewFacetB ; - SplitFacet( IntersLineMapA, NewFacetA) ; - SurfB.SplitFacet( IntersLineMapB, NewFacetB) ; - - // Facce EdgeInn - EdgeInteriorContactManager( SurfB, IntersLineMapA, EdgeInnLineMapA) ; - SurfB.EdgeInteriorContactManager( *this, IntersLineMapB, EdgeInnLineMapB) ; - - // Facce Edge Edge - EdgeEdgeContactManager( SurfB, IntersLineMapA, EdgeEdgeLineMapA) ; - SurfB.EdgeEdgeContactManager( *this, IntersLineMapB, EdgeEdgeLineMapB) ; - - // Se non ci sono stati tagli, valuto se una � tutta interna all'altra. - if ( int( NewFacetA.size() + NewFacetB.size()) == 0) { - int nVertNum = 0 ; - Point3d ptVert ; - int nCurVert = GetFirstVertex( ptVert) ; - int nInOutNumA = 0 ; - while ( nInOutNumA == 0 && nCurVert != SVT_NULL) { - int nFacetNum = - 1 ; - double dMinDist = DBL_MAX ; - for ( int nFB = 0 ; nFB < SurfB.GetFacetCount() ; ++ nFB) { - // Loop della faccia della superficie B - POLYLINEVECTOR vFacetLoopVec ; - SurfB.GetFacetLoops( nFB, vFacetLoopVec) ; - double dDist ; - if ( DistPointFacet( ptVert, vFacetLoopVec, dDist) && dDist < dMinDist) { - dMinDist = dDist ; - nFacetNum = nFB ; - } - } - if ( nFacetNum >= 0) { - Triangle3d trTriaB ; - SurfB.GetTriangle( SurfB.m_vFacet[nFacetNum], trTriaB) ; - trTriaB.Validate() ; - if ( ( ptVert - trTriaB.GetP( 0)) * trTriaB.GetN() < - EPS_SMALL) - nInOutNumA = 1 ; - else if ( ( ptVert - trTriaB.GetP( 0)) * trTriaB.GetN() > EPS_SMALL) - nInOutNumA = - 1 ; - } - if ( nInOutNumA == 0) { - nCurVert = GetNextVertex( nVertNum, ptVert) ; - ++ nVertNum ; - } - } - // Se la superficie A non � interna valuto la posizione della superficie B. - int nInOutNumB = nInOutNumA == 1 ? - 1 : 0 ; - if ( nInOutNumB == 0) { - nVertNum = 0 ; - nCurVert = SurfB.GetFirstVertex( ptVert) ; - while ( nInOutNumB == 0 && nCurVert != SVT_NULL) { - int nFacetNum = - 1 ; - double dMinDist = DBL_MAX ; - for ( int nFA = 0 ; nFA < GetFacetCount() ; ++ nFA) { - // Loop della faccia della superficie A - POLYLINEVECTOR vFacetLoopVec ; - GetFacetLoops( nFA, vFacetLoopVec) ; - double dDist ; - if ( DistPointFacet( ptVert, vFacetLoopVec, dDist) && dDist < dMinDist) { - dMinDist = dDist ; - nFacetNum = nFA ; - } - } - if ( nFacetNum >= 0) { - Triangle3d trTriaA ; - GetTriangle( m_vFacet[nFacetNum], trTriaA) ; - trTriaA.Validate() ; - if ( ( ptVert - trTriaA.GetP( 0)) * trTriaA.GetN() < - EPS_SMALL) - nInOutNumB = 1 ; - else if ( ( ptVert - trTriaA.GetP( 0)) * trTriaA.GetN() > EPS_SMALL) - nInOutNumB = - 1 ; - - } - if ( nInOutNumB == 0) { - nCurVert = SurfB.GetNextVertex( nVertNum, ptVert) ; - ++ nVertNum ; - } - } - } - // Se la posizione della superficie A rispetto alla B non � definita e - // B � esterna ad A, allora assumiamo che siano reciprocamente esterne. - if ( nInOutNumA == 0 && nInOutNumB == - 1) - nInOutNumA = - 1 ; - // Assegno gli indici interni/esterni. - for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) { - m_vTria[nTA].nTempPart = nInOutNumA ; - } - for ( int nTB = 0 ; nTB < nTriaNumB ; ++ nTB) { - SurfB.m_vTria[nTB].nTempPart = nInOutNumB ; - } - } - -#define UseTria 0 -#if ! UseTria - // Gestisco facce sovrapposte. - // Ciclo sulle facce di A. - for ( int nFA = 0 ; nFA < nFacetNumA ; ++ nFA) { - auto itFacetA = NewFacetA.find( nFA) ; - // Faccia A divisa in pezzi. - if ( itFacetA != NewFacetA.end()) { - // Ciclo sui pezzi della faccia A. - for ( int nPieceNumA = 0 ; nPieceNumA < int( itFacetA->second.size()) ; ++ nPieceNumA) { - // Dati del pezzo di faccia di A - POLYLINEVECTOR& vPieceLoopsVecA = itFacetA->second[nPieceNumA].vPieceLoop ; - PtrOwner pRegA( GetBasicSurfFlatRegion( GetSurfFlatRegionFromPolyLineVector( vPieceLoopsVecA))) ; - if ( pRegA == nullptr) - return false ; - SurfFlatRegion RegionA = *pRegA ; - Plane3d plPlaneA ; - plPlaneA.Set( RegionA.GetPlanePoint(), RegionA.GetNormVersor()) ; - // Recupero tutti i triangoli della superficie B che cadono nel box del pezzo di faccia di A. - BBox3d b3BoxA ; - RegionA.GetLocalBBox( b3BoxA) ; - INTVECTOR vNearTria ; - SurfB.GetAllTriaOverlapBox( b3BoxA, vNearTria) ; - // Determino le facce a cui appartengono i tirangoli che cadono nel box - INTVECTOR vFacetIndexesB ; - for ( int& nT : vNearTria) { - int nF = SurfB.GetFacetFromTria( nT) ; - int n ; - for ( n = 0 ; n < int( vFacetIndexesB.size()) ; ++ n) { - if ( nF == vFacetIndexesB[n]) - break ; - } - if ( n == int( vFacetIndexesB.size())) - vFacetIndexesB.emplace_back( nF) ; - } - // Ciclo sulle facce di B - for ( int& nFB : vFacetIndexesB) { - auto itFacetB = NewFacetB.find( nFB) ; - // Faccia B divisa in pezzi - if ( itFacetB != NewFacetB.end()) { - // Ciclo sui pezzi della faccia B. - for ( int nPieceNumB = 0 ; nPieceNumB < int( itFacetB->second.size()) ; ++ nPieceNumB) { - // Dati del pezzo di faccia di B - POLYLINEVECTOR& vPieceLoopsVecB = itFacetB->second[nPieceNumB].vPieceLoop ; - PtrOwner pRegB( GetBasicSurfFlatRegion( GetSurfFlatRegionFromPolyLineVector( vPieceLoopsVecB))) ; - if ( pRegB == nullptr) - return false ; - SurfFlatRegion RegionB = *pRegB ; - Plane3d plPlaneB ; - plPlaneB.Set( RegionB.GetPlanePoint(), RegionB.GetNormVersor()) ; - // Intersezione tra i piani delle due facce: se non esiste esse sono complanari. - Point3d ptL ; Vector3d vtL ; - int nResPP = IntersPlanePlane( plPlaneA, plPlaneB, ptL, vtL) ; - if ( /*nResPP == IPPT_NO ||*/ nResPP == IPPT_OVERLAPS) { - SurfFlatRegion frIntersRegion = RegionA ; - frIntersRegion.Intersect( RegionB) ; - double dIntersRegArea ; - frIntersRegion.GetArea( dIntersRegArea) ; - // Assegno indice di parte ai pezzi. - if ( dIntersRegArea > EPS_SMALL) { - bool bCodirectedNorm = RegionA.GetNormVersor() * RegionB.GetNormVersor() > 0; - int nPartIndex = bCodirectedNorm ? 2 : - 2 ; - itFacetA->second[nPieceNumA].nPiecePart = nPartIndex; - itFacetB->second[nPieceNumB].nPiecePart = nPartIndex; - } - } - } - } - // Faccia B non divisa in pezzi - else { - // Dati della faccia - POLYLINEVECTOR vFacetLoopVecB ; - SurfB.GetFacetLoops( nFB, vFacetLoopVecB) ; - PtrOwner pRegB( GetBasicSurfFlatRegion( GetSurfFlatRegionFromPolyLineVector( vFacetLoopVecB))) ; - if ( pRegB == nullptr) - return false ; - SurfFlatRegion RegionB = *pRegB ; - Plane3d plPlaneB ; - plPlaneB.Set( RegionB.GetPlanePoint(), RegionB.GetNormVersor()) ; - // Intersezione tra i piani delle due facce: se non esiste esse sono complanari. - Point3d ptL ; Vector3d vtL ; - int nResPP = IntersPlanePlane( plPlaneA, plPlaneB, ptL, vtL) ; - if ( /*nResPP == IPPT_NO ||*/ nResPP == IPPT_OVERLAPS) { - SurfFlatRegion frIntersRegion = RegionA ; - frIntersRegion.Intersect( RegionB) ; - double dIntersRegArea ; - frIntersRegion.GetArea( dIntersRegArea) ; - // Assegno indice di parte al pezzo di faccia A e ai triangoli della faccia B. - if ( dIntersRegArea > EPS_SMALL) { - bool bCodirectedNorm = RegionA.GetNormVersor() * RegionB.GetNormVersor() > 0 ; - int nPartIndex = bCodirectedNorm ? 2 : - 2 ; - itFacetA->second[nPieceNumA].nPiecePart = nPartIndex ; - INTVECTOR vTB ; - SurfB.GetAllTriaInFacet( nFB, vTB) ; - for ( int& nTB : vTB) - SurfB.m_vTria[nTB].nTempPart = nPartIndex ; - } - } - } - } - } - } - // Faccia A non divisa in pezzi - else { - // Dati della faccia - POLYLINEVECTOR vFacetLoopsVecA ; - GetFacetLoops( nFA, vFacetLoopsVecA) ; - PtrOwner pRegA( GetBasicSurfFlatRegion( GetSurfFlatRegionFromPolyLineVector( vFacetLoopsVecA))) ; - if ( pRegA == nullptr) - return false ; - SurfFlatRegion RegionA = *pRegA ; - Plane3d plPlaneA ; - plPlaneA.Set( RegionA.GetPlanePoint(), RegionA.GetNormVersor()) ; - // Recupero tutti i triangoli della superficie B che cadono nel box del pezzo di faccia di A. - BBox3d b3BoxA ; - RegionA.GetLocalBBox( b3BoxA) ; - INTVECTOR vNearTria ; - SurfB.GetAllTriaOverlapBox( b3BoxA, vNearTria) ; - // Determino le facce a cui appartengono i tirangoli che cadono nel box - INTVECTOR vFacetIndexesB ; - for ( int& nT : vNearTria) { - int nF = SurfB.GetFacetFromTria( nT) ; - int n ; - for ( n = 0 ; n < int( vFacetIndexesB.size()) ; ++ n) { - if ( nF == vFacetIndexesB[n]) - break ; - } - if ( n == int( vFacetIndexesB.size())) - vFacetIndexesB.emplace_back( nF) ; - } - // Ciclo sulle facce di B - for ( int& nFB : vFacetIndexesB) { - auto itFacetB = NewFacetB.find( nFB) ; - // Faccia B divisa in pezzi - if ( itFacetB != NewFacetB.end()) { - for ( int nPieceNumB = 0 ; nPieceNumB < int( itFacetB->second.size()) ; ++ nPieceNumB) { - POLYLINEVECTOR& vPieceLoopsVecB = itFacetB->second[nPieceNumB].vPieceLoop ; - PtrOwner pRegB( GetBasicSurfFlatRegion( GetSurfFlatRegionFromPolyLineVector( vPieceLoopsVecB))) ; - if ( pRegB == nullptr) - return false ; - SurfFlatRegion RegionB = *pRegB ; - Plane3d plPlaneB ; - plPlaneB.Set( RegionB.GetPlanePoint(), RegionB.GetNormVersor()) ; - // Intersezione tra i piani delle due facce: se non esiste esse sono complanari. - Point3d ptL ; Vector3d vtL ; - int nResPP = IntersPlanePlane( plPlaneA, plPlaneB, ptL, vtL) ; - if ( /*nResPP == IPPT_NO ||*/ nResPP == IPPT_OVERLAPS) { - SurfFlatRegion frIntersRegion = RegionA ; - frIntersRegion.Intersect( RegionB) ; - double dIntersRegArea ; - frIntersRegion.GetArea( dIntersRegArea) ; - // Assegno indice di parte ai triangoli di A e ai pezzi di B. - if ( dIntersRegArea > EPS_SMALL) { - bool bCodirectedNorm = RegionA.GetNormVersor() * RegionB.GetNormVersor() > 0 ; - int nPartIndex = bCodirectedNorm ? 2 : - 2 ; - INTVECTOR vTA ; - GetAllTriaInFacet( nFA, vTA) ; - for ( int& nTA : vTA) - m_vTria[nTA].nTempPart = nPartIndex ; - itFacetB->second[nPieceNumB].nPiecePart = nPartIndex ; - } - } - } - } - // Faccia B non divisa in pezzi - else { - // Dati della faccia - POLYLINEVECTOR vFacetLoopVecB ; - SurfB.GetFacetLoops( nFB, vFacetLoopVecB) ; - PtrOwner pRegB( GetBasicSurfFlatRegion( GetSurfFlatRegionFromPolyLineVector( vFacetLoopVecB))) ; - if ( pRegB == nullptr) - return false ; - SurfFlatRegion RegionB = *pRegB ; - Plane3d plPlaneB ; - plPlaneB.Set( RegionB.GetPlanePoint(), RegionB.GetNormVersor()) ; - // Intersezione tra i piani delle due facce: se non esiste esse sono complanari. - Point3d ptL ; Vector3d vtL ; - int nResPP = IntersPlanePlane( plPlaneA, plPlaneB, ptL, vtL) ; - if ( /*nResPP == IPPT_NO ||*/ nResPP == IPPT_OVERLAPS) { - SurfFlatRegion frIntersRegion = RegionA ; - frIntersRegion.Intersect( RegionB) ; - double dIntersRegArea ; - frIntersRegion.GetArea( dIntersRegArea) ; - // Assegno indice di parte al pezzo di faccia A e ai triangoli della faccia B. - if ( dIntersRegArea > EPS_SMALL) { - bool bCodirectedNorm = RegionA.GetNormVersor() * RegionB.GetNormVersor() > 0 ; - int nPartIndex = bCodirectedNorm ? 2 : - 2 ; - INTVECTOR vTA ; - GetAllTriaInFacet( nFA, vTA) ; - for ( int& nTA : vTA) - m_vTria[nTA].nTempPart = nPartIndex ; - INTVECTOR vTB ; - SurfB.GetAllTriaInFacet( nFB, vTB) ; - for ( int& nTB : vTB) - SurfB.m_vTria[nTB].nTempPart = nPartIndex ; - } - } - } - } - } - } -#endif - - // Elimino i triangoli delle facce e li sostituisco con i nuovi con i loro indici - RetriangulateFacetPieces( NewFacetA, EdgeInnLineMapA, EdgeEdgeLineMapB) ; - SurfB.RetriangulateFacetPieces( NewFacetB, EdgeInnLineMapB, EdgeEdgeLineMapB) ; - - bool bOk = ( AdjustVertices() && DoCompacting() && SurfB.AdjustVertices() && SurfB.DoCompacting()) ; - -#if UseTria - // Gestione triangoli sovrapposti - if ( bOk) { - int nTriaNum2A = GetTriangleSize() ; - // Resetto e ricalcolo la HashGrid della superficie B - SurfB.ResetHashGrids3d() ; - for ( int nTA = 0 ; nTA < nTriaNum2A ; ++ nTA) { - // Se il triangolo A non � valido, continuo - Triangle3d trTriaA ; - if ( ! GetTriangle( nTA, trTriaA) || ! trTriaA.Validate( true)) - continue ; - // Box del triangolo A - BBox3d b3dTriaA ; - trTriaA.GetLocalBBox( b3dTriaA) ; - // Recupero i triangoli di B che interferiscono col box del triangolo di A - INTVECTOR vNearTria ; - SurfB.GetAllTriaOverlapBox( b3dTriaA, vNearTria) ; - for ( int nTB = 0 ; nTB < int( vNearTria.size()) ; ++ nTB) { - // Se il triangolo B non � valido, continuo - Triangle3d trTriaB ; - if ( ! SurfB.GetTriangle( vNearTria[nTB], trTriaB) || ! trTriaB.Validate( true)) - continue ; - // Se i triangoli sono sovrapposti - TRIA3DVECTOR vTriaAB ; - Point3d ptTempA, ptTempB ; - int nIntTypeAB = IntersTriaTria( trTriaA, trTriaB, ptTempA, ptTempB, vTriaAB) ; - // Verifica della correttezza del'intersezione - bool bSuccesfullInters = true ; - if ( int( vTriaAB.size()) == 1) { - Point3d ptIntTriaCentroid = vTriaAB[0].GetCentroid() ; - bSuccesfullInters = IsPointInsideTriangle( ptIntTriaCentroid, trTriaA, TriangleType::EXACT) && - IsPointInsideTriangle( ptIntTriaCentroid, trTriaB, TriangleType::EXACT) ; - } - // Se l'intersezeione � corretta e i triangoli sono sovrapposti aggiorno gli indici. -<<<<<<< HEAD - /*if ( nIntTypeAB == ITTT_OVERLAPS && bSuccesfullInters) { - bool bInvertB = trTriaA.GetN() * trTriaB.GetN() < 0. ; - m_vTria[nTA].nTempPart = ( bInvertB ? -2 : 2) ; - SurfB.m_vTria[vNearTria[nTB]].nTempPart = ( bInvertB ? - 2 : 2) ; - }*/ -======= ->>>>>>> ca83aaa249ef66937ccc16640c11d72bd2f04c55 - if ( nIntTypeAB == ITTT_OVERLAPS && bSuccesfullInters) { - m_vTria[nTA].nTempPart = 2 ; - SurfB.m_vTria[vNearTria[nTB]].nTempPart = 2 ; - } - else if ( nIntTypeAB == ITTT_COUNTER_OVERLAPS && bSuccesfullInters) { - m_vTria[nTA].nTempPart = - 2 ; - SurfB.m_vTria[vNearTria[nTB]].nTempPart = - 2 ; - } - } - } - return ( AdjustVertices() && DoCompacting() && SurfB.AdjustVertices() && SurfB.DoCompacting()) ; - } -#endif - return bOk ; -} diff --git a/SurfTriMeshCuts.cpp b/SurfTriMeshCuts.cpp index 17a0cb3..c89cde6 100644 --- a/SurfTriMeshCuts.cpp +++ b/SurfTriMeshCuts.cpp @@ -40,13 +40,10 @@ SurfTriMesh::Cut( const Plane3d& plPlane, bool bSaveOnEq) int nTriaOriCnt = GetTriangleCount() ; int nFacetOriCnt = GetFacetCount() ; - // eseguo il taglio con il metodo delle faccette o dei triangoli (per ora solo coi triangoli) + // eseguo il taglio con il metodo dei triangoli bool bModif = false ; - if ( true || ! CutByFacets( plPlane, bSaveOnEq, bModif)) { - bModif = false ; - if ( ! CutByTriangles( plPlane, bSaveOnEq, bModif)) - return false ; - } + if ( ! CutByTriangles( plPlane, bSaveOnEq, bModif)) + return false ; // se effettuate modifiche if ( bModif) { @@ -282,90 +279,6 @@ SurfTriMesh::CutTriangleByPlane( int nT, const Plane3d& plPlane, bool bSaveOnEq, return true ; } -//---------------------------------------------------------------------------- -bool -SurfTriMesh::CutByFacets( const Plane3d& plPlane, bool bSaveOnEq, bool& bModif) -{ - // Setto posizione triangoli non definita - for ( int nT = 0 ; nT < GetTriangleSize() ; ++ nT) - m_vTria[nT].nTempPart = 0 ; - - INTERSCHAINMAP IntersLineMap ; - - // Ciclo su tutte le facce. - for ( int nF = 0 ; nF < GetFacetCount() ; ++ nF) { - // Dati della faccia - POLYLINEVECTOR vLoopVec ; - GetFacetLoops( nF, vLoopVec) ; - if ( vLoopVec.empty()) - continue ; - // Verifico la posizione del loop esterno - int nIntType = VerifyLoopPlane( vLoopVec[0], plPlane) ; - // Se interseca il piano di taglio, calcolo la divisione della faccia - LineFacetClassVector IntersLinePart ; - if ( nIntType == FPI_CUT) { - PtrOwner pReg( GetBasicSurfFlatRegion( GetSurfFlatRegionFromPolyLineVector( vLoopVec))) ; - if ( IsNull( pReg) || ! pReg->IsValid()) - return false ; - nIntType = IntersFacetPlane( *pReg, plPlane, IntersLinePart) ; - } - // Gestione dei risultati - if ( nIntType == FPI_CUT) { - for ( int nPart = 0 ; nPart < int( IntersLinePart.size()) ; ++ nPart) { - // Salvo intersezione per la faccia. - auto it = IntersLineMap.find( nF) ; - if ( it != IntersLineMap.end()) { - it->second.emplace_back( IntersInnSeg( IntersLinePart[nPart].ptSt, IntersLinePart[nPart].ptEn)) ; - } - else { - IntersLineMap.emplace( nF, IntersInnChain( 1, IntersInnSeg( IntersLinePart[nPart].ptSt, IntersLinePart[nPart].ptEn))) ; - } - } - } - else if ( nIntType == FPI_ON) { - INTVECTOR vT ; - GetAllTriaInFacet( nF, vT) ; - Vector3d vtNf ; - GetFacetNormal( nF, vtNf) ; - for ( auto& nT : vT) - m_vTria[nT].nTempPart = ( vtNf * plPlane.GetVersN() > 0 ? 2 : -2) ; - } - else if ( nIntType == FPI_IN) { - INTVECTOR vT ; - GetAllTriaInFacet( nF, vT) ; - for ( auto& nT : vT) - m_vTria[nT].nTempPart = 1 ; - } - else if ( nIntType == FPI_OUT) { - INTVECTOR vT ; - GetAllTriaInFacet( nF, vT) ; - for ( auto& nT : vT) - m_vTria[nT].nTempPart = -1 ; - } - else - return false ; - } - - // Divido le facce. - PieceMap NewFacet ; - SplitFacet( IntersLineMap, NewFacet) ; - INTERSEDGEMAP EdgeInterLineMap, EdgeEdgeLineMap ; - RetriangulateFacetPieces( NewFacet, EdgeInterLineMap, EdgeEdgeLineMap) ; - - // Elimino i triangoli superflui - for ( int nT = 0 ; nT < GetTriangleSize() ; ++ nT) { - if ( m_vTria[nT].nTempPart == 0 || - m_vTria[nT].nTempPart == -1 || - m_vTria[nT].nTempPart == -2 || - ( ! bSaveOnEq && m_vTria[nT].nTempPart == 2)) { - RemoveTriangle( nT) ; - bModif = true ; - } - } - - return true ; -} - //---------------------------------------------------------------------------- // Risultato : 0=nessuna intersezione, 1=intersezione è un punto, 2=intersezione è un segmento static int diff --git a/SurfTriMeshFaceting.cpp b/SurfTriMeshFaceting.cpp index e22f0fc..678b62c 100644 --- a/SurfTriMeshFaceting.cpp +++ b/SurfTriMeshFaceting.cpp @@ -482,12 +482,14 @@ SurfTriMesh::MarchOneFacetTria( int nF, int& nT, int& nV, int nTimeStamp, // verifico appartenga alla stessa faccia if ( m_vTria[nAdjT].nIdFacet != nF) return false ; - // recupero il suo lato di adiacenza + // recupero il suo lato di adiacenza (e verifico non abbia più adiacenze con il triangolo di partenza) int nAdjS = SVT_NULL ; for ( int i = 0 ; i < 3 ; ++ i) { if ( m_vTria[nAdjT].nIdAdjac[i] == nT) { - nAdjS = i ; - break ; + if ( nAdjS == SVT_NULL) + nAdjS = i ; + else + return false ; } } if ( nAdjS == SVT_NULL) diff --git a/SurfTriMeshUtilities.cpp b/SurfTriMeshUtilities.cpp index 2aeb542..42467a3 100644 --- a/SurfTriMeshUtilities.cpp +++ b/SurfTriMeshUtilities.cpp @@ -12,17 +12,112 @@ //--------------------------- Include ---------------------------------------- #include "stdafx.h" -#include "Triangulate.h" #include "SurfTriMesh.h" +#include "CurveLine.h" +#include "Triangulate.h" #include "DistPointLine.h" +#include "DistLineLine.h" #include using namespace std ; //---------------------------------------------------------------------------- bool -SurfTriMesh::RemoveTJunctions(void) +SurfTriMesh::RemoveDoubleTriangles( bool& bModified) { + bModified = false ; + // ciclo sui triangoli + int nTriaNum = GetTriangleSize() ; + for ( int nT = 0 ; nT < nTriaNum ; ++ nT) { + // se cancellato passo al successivo + if ( m_vTria[nT].nIdVert[0] == SVT_DEL) + continue ; + // recupero i vertici dei triangoli + int nIdV[3] ; + GetTriangle( nT, nIdV) ; + // ciclo sui triangoli adiacenti + for ( int nE = 0 ; nE < 3 ; ++ nE) { + // recupero triangolo adiacente, se non esiste passo al successivo + int nAdjT = m_vTria[nT].nIdAdjac[nE] ; + if ( nAdjT == SVT_NULL || nAdjT == SVT_DEL) + continue ; + // recupero i vertici del triangolo adiacente + int nAdjIdV[3] ; + GetTriangle( nAdjT, nAdjIdV) ; + // verifico se questi vertici coincidono con quelli del triangolo di riferimento + int nCoinc = 0 ; + for ( int i = 0 ; i < 3 ; ++ i) { + for ( int j = 0 ; j < 3 ; ++ j) { + if ( nIdV[i] == nAdjIdV[j]) + ++ nCoinc ; + } + } + if ( nCoinc == 3) { + RemoveTriangle( nAdjT) ; + bModified = true ; + } + } + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +SurfTriMesh::FlipTriangles( int nTA, int nTB) +{ + // Verifico esistenza triangoli + if ( ! ExistsTriangle( nTA) || ! ExistsTriangle( nTB)) + return false ; + // Verifico adiacenza triangoli + int nEdgeA ; + for ( nEdgeA = 0 ; nEdgeA < 3 ; ++ nEdgeA) { + if ( m_vTria[nTA].nIdAdjac[nEdgeA] == nTB) + break ; + } + int nEdgeB ; + for ( nEdgeB = 0 ; nEdgeB < 3 ; ++ nEdgeB) { + if ( m_vTria[nTB].nIdAdjac[nEdgeB] == nTA) + break ; + } + // Se non sono adiacenti tra loro, impossibile flip + if ( nEdgeA == 3 && nEdgeB == 3) + return false ; + // Recupero i vertici del triangolo A + Point3d ptSegSt, ptSegEn, ptVertA ; + if ( ! GetVertex( m_vTria[nTA].nIdVert[nEdgeA], ptSegSt) || + ! GetVertex( m_vTria[nTA].nIdVert[( nEdgeA + 1) % 3], ptSegEn) || + ! GetVertex( m_vTria[nTA].nIdVert[( nEdgeA + 2) % 3], ptVertA)) + return false ; + // Recupero il vertice opposto del triangolo B + Point3d ptVertB ; + if ( ! GetVertex( m_vTria[nTB].nIdVert[( nEdgeB + 2) % 3], ptVertB)) + return false ; + // Verifico se possibile il flip (le diagonali del quadrilatero si intersecano internamente) + DistLineLine DiagDist( ptSegSt, ptSegEn, ptVertA, ptVertB) ; + if ( ! DiagDist.IsSmall()) + return false ; + double dPos1, dPos2 ; + if ( ! DiagDist.GetPositionsAtMinDistPoints( dPos1, dPos2) || + dPos1 < EPS_SMALL || dPos1 > ( ptSegEn - ptSegSt).Len() - EPS_SMALL || + dPos2 < EPS_SMALL || dPos2 > ( ptVertB - ptVertA).Len() - EPS_SMALL) + return false ; + // Eseguo il flipping + m_vTria[nTA].nIdVert[nEdgeA] = m_vTria[nTB].nIdVert[( nEdgeB + 2) % 3] ; + m_vTria[nTB].nIdVert[nEdgeB] = m_vTria[nTA].nIdVert[( nEdgeA + 2) % 3] ; + m_vTria[nTA].nIdAdjac[nEdgeA] = m_vTria[nTB].nIdAdjac[( nEdgeB + 2) % 3] ; + m_vTria[nTA].nIdAdjac[( nEdgeA + 2) % 3] = nTB ; + m_vTria[nTB].nIdAdjac[nEdgeB] = m_vTria[nTA].nIdAdjac[( nEdgeA + 2) % 3] ; + m_vTria[nTB].nIdAdjac[( nEdgeB + 2) % 3] = nTA ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +SurfTriMesh::RemoveTJunctions( bool& bModified) +{ + bModified = false ; + // Vettore di indici dei vertici sui lati del triangolo corrente unordered_map< int, INTVECTOR> TriaMap ; @@ -72,13 +167,13 @@ SurfTriMesh::RemoveTJunctions(void) } } // Riordino i vertici sul segmento - auto SortVerteces = [ this, &ptSegSt, &vtSeg]( const int nV1, const int nV2) + auto SortVertices = [ this, &ptSegSt, &vtSeg]( const int nV1, const int nV2) { Point3d ptV1, ptV2 ; GetVertex( nV1, ptV1) ; GetVertex( nV2, ptV2) ; return ( ( ptV1 - ptSegSt) * vtSeg < ( ptV2 - ptSegSt) * vtSeg) ; } ; - sort( vVertOtl.begin() + nPrevSize, vVertOtl.end(), SortVerteces) ; + sort( vVertOtl.begin() + nPrevSize, vVertOtl.end(), SortVertices) ; } // Se ci sono più di 3 vertici if ( vVertOtl.size() > 3) { @@ -107,6 +202,7 @@ SurfTriMesh::RemoveTJunctions(void) // Rimuovo il triangolo int nTFlag = m_vTria[nT].nTFlag ; RemoveTriangle( nT) ; + bModified = true ; // Aggiungo i nuovi triangoli int nLastNewTria = SVT_NULL ; // Se ci sono 4 vertici, inserisco due triangoli