diff --git a/CurveAux.cpp b/CurveAux.cpp index 02080c2..d6c1fe9 100644 --- a/CurveAux.cpp +++ b/CurveAux.cpp @@ -130,7 +130,7 @@ MoveParamToAvoidTg( double& dU, ICurve::Side nSide, const ICurve& Curve) if ( Curve.GetPointD1D2( dU, nSide, ptPos, &vtDer1)) { double dDer1 = vtDer1.LenXY() ; if ( dDer1 > EPS_ZERO) - dDeltaU = 10 * EPS_SMALL / dDer1 ; + dDeltaU = 2 * EPS_SMALL / dDer1 ; } // cerco di spostarmi per evitare eventuali problemi di tangenza diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 8304a11..ab97224 100644 Binary files a/EgtGeomKernel.rc and b/EgtGeomKernel.rc differ diff --git a/IntersCurveCurve.cpp b/IntersCurveCurve.cpp index 5d7c83c..51751a5 100644 --- a/IntersCurveCurve.cpp +++ b/IntersCurveCurve.cpp @@ -471,18 +471,49 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO double dStartPar, dEndPar ; if ( pCurve == nullptr || ! pCurve->GetDomain( dStartPar, dEndPar)) return false ; + // elimino intersezioni senza attraversamento che giacciono in intervalli di sovrapposizione + ICCIVECTOR InfoCorr ; + InfoCorr.reserve( Info.size()) ; + for ( size_t i = 0 ; i < Info.size() ; ++ i) { + // se intersezione puntuale senza attraversamento + if ( ! Info[i].bOverlap && Info[i].IciA[0].nPrevTy == Info[i].IciA[0].nNextTy) { + // confronto con le intersezioni con sovrapposizione + bool bToSkip = false ; + for ( size_t j = 0 ; j < Info.size() ; ++ j) { + // se coincide o puntuale + if ( j == i || ! Info[j].bOverlap) + continue ; + // determino l'intervallo parametrico tenendo conto di eventuale avvolgimento attorno all'inizio + double dU1 = Info[j].IciA[0].dU ; + double dU2 = Info[j].IciA[1].dU ; + if ( dU2 < dU1 && pCurve->IsClosed()) + dU2 += dEndPar ; + // se cade nell'intervallo è da saltare + if ( Info[i].IciA[0].dU >= dU1 && Info[i].IciA[0].dU <= dU2) { + bToSkip = true ; + break ; + } + } + if ( bToSkip) + continue ; + } + // salvo dati intersezione + InfoCorr.emplace_back( Info[i]) ; + } + // aggiorno numero di intersezioni da considerare + nNumInters = int( InfoCorr.size()) ; // recupero la classificazione all'inizio della curva int nLastTy = ICCT_NULL ; double dCurrPar = dStartPar ; // se è chiusa, recupero come finisce if ( pCurve->IsClosed()) { - if ( ! Info[nNumInters-1].bOverlap) - nLastTy = Info[nNumInters-1].IciA[0].nNextTy ; + if ( ! InfoCorr[nNumInters-1].bOverlap) + nLastTy = InfoCorr[nNumInters-1].IciA[0].nNextTy ; else { - nLastTy = Info[nNumInters-1].IciA[1].nNextTy ; + nLastTy = InfoCorr[nNumInters-1].IciA[1].nNextTy ; // se attraversa il punto di giunzione (parametro di fine minore di quello di inizio) - if ( Info[nNumInters-1].IciA[1].dU < Info[nNumInters-1].IciA[0].dU) { - dCurrPar = Info[nNumInters-1].IciA[1].dU ; + if ( InfoCorr[nNumInters-1].IciA[1].dU < InfoCorr[nNumInters-1].IciA[0].dU) { + dCurrPar = InfoCorr[nNumInters-1].IciA[1].dU ; dEndPar = dCurrPar ; } } @@ -490,36 +521,36 @@ IntersCurveCurve::CalcCurveClassification( const ICurve* pCurve, const ICCIVECTO // costruisco il vettore delle classificazioni for ( int i = 0 ; i < nNumInters ; ++ i) { // se è definito un tratto precedente - if ( Info[i].IciA[0].dU > dCurrPar + EPS_PARAM) { + if ( InfoCorr[i].IciA[0].dU > dCurrPar + EPS_PARAM) { // verifico che la definizione sul tratto sia omogenea e valida - int nPrevTy = Info[i].IciA[0].nPrevTy ; + int nPrevTy = InfoCorr[i].IciA[0].nPrevTy ; if ( ( nLastTy != ICCT_NULL && nPrevTy != nLastTy) || nPrevTy == ICCT_NULL || nPrevTy == ICCT_ON) return false ; // assegno i dati CrvClass segClass ; segClass.dParS = dCurrPar ; - segClass.dParE = Info[i].IciA[0].dU ; + segClass.dParE = InfoCorr[i].IciA[0].dU ; segClass.nClass = (( nPrevTy == ICCT_IN) ? CRVC_IN : CRVC_OUT) ; ccClass.push_back( segClass) ; // salvo dati correnti - dCurrPar = Info[i].IciA[0].dU ; - nLastTy = Info[i].IciA[0].nNextTy ; + dCurrPar = InfoCorr[i].IciA[0].dU ; + nLastTy = InfoCorr[i].IciA[0].nNextTy ; } // altrimenti, salvo il tipo else - nLastTy = Info[i].IciA[0].nNextTy ; + nLastTy = InfoCorr[i].IciA[0].nNextTy ; // se è definito un tratto in sovrapposizione - if ( Info[i].bOverlap) { + if ( InfoCorr[i].bOverlap) { // assegno i dati CrvClass segClass ; segClass.dParS = dCurrPar ; - segClass.dParE = Info[i].IciA[1].dU ; - segClass.nClass = ( Info[i].bCBOverEq ? CRVC_ON_P : CRVC_ON_M) ; + segClass.dParE = InfoCorr[i].IciA[1].dU ; + segClass.nClass = ( InfoCorr[i].bCBOverEq ? CRVC_ON_P : CRVC_ON_M) ; ccClass.push_back( segClass) ; // salvo dati correnti - dCurrPar = Info[i].IciA[1].dU ; - nLastTy = Info[i].IciA[1].nNextTy ; + dCurrPar = InfoCorr[i].IciA[1].dU ; + nLastTy = InfoCorr[i].IciA[1].nNextTy ; } } // eventuale tratto finale rimasto diff --git a/SurfFlatRegion.cpp b/SurfFlatRegion.cpp index 6a67476..8d00421 100644 --- a/SurfFlatRegion.cpp +++ b/SurfFlatRegion.cpp @@ -962,13 +962,12 @@ SurfFlatRegion::GetAuxSurf( void) const return nullptr ; pLoop = GetMyLoop( i, ++j) ; } - // porto le polilinee in globale al riferimento intrinseco - for ( auto& PL : vPL) - PL.ToGlob( m_frF) ; // creo, setto la superficie trimesh ed elimino punti ripetuti PtrOwner pChSTM( CreateBasicSurfTriMesh()) ; if ( IsNull( pChSTM) || ! pChSTM->CreateByRegion( vPL) || ! pChSTM->DoCompacting()) return nullptr ; + // porto la trimesh in globale al riferimento intrinseco + pChSTM->ToGlob( m_frF) ; // inserisco questa trimesh in quella complessiva pSTM->DoSewing( *Get( pChSTM)) ; } diff --git a/SurfTriMesh.cpp b/SurfTriMesh.cpp index cd63341..3d42312 100644 --- a/SurfTriMesh.cpp +++ b/SurfTriMesh.cpp @@ -600,6 +600,187 @@ SurfTriMesh::GetTriangleSmoothNormal( int nT, int nV, Vector3d& vtN) const return true ; } +//---------------------------------------------------------------------------- +bool +SurfTriMesh::GetLoops( POLYLINEVECTOR& vPL) const +{ + // aggiorno timestamp dei triangoli + ++ m_nTimeStamp ; + for ( auto& Tria : m_vTria) + Tria.nTemp = m_nTimeStamp ; + // incremento time stamp + ++ m_nTimeStamp ; + // ciclo sui triangoli + for ( int nT = 0 ; nT < int( m_vTria.size()) ; ++ nT) { + // se triangolo non ancora visitato + if ( m_vTria[nT].nTemp != m_nTimeStamp) { + // determino i triangoli adiacenti + int nAdjT[3] ; + for ( int j = 0 ; j < 3 ; ++ j) + nAdjT[j] = m_vTria[nT].nIdAdjac[j] ; + // se tutti e tre i lati sono di contorno + if ( nAdjT[0] == SVT_NULL && + nAdjT[1] == SVT_NULL && + nAdjT[2] == SVT_NULL) { + // ho trovato un loop + vPL.emplace_back() ; + vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ; + vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ; + vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ; + vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ; + // marco il triangolo come verificato + m_vTria[nT].nTemp = m_nTimeStamp ; + } + // se i due lati 0 e 1 sono di contorno + else if ( nAdjT[0] == SVT_NULL && + nAdjT[1] == SVT_NULL) { + // ho trovato l'inizio di un loop + vPL.emplace_back() ; + vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ; + vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ; + vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ; + // marco il triangolo come verificato + m_vTria[nT].nTemp = m_nTimeStamp ; + // cammino lungo il loop fino a chiuderlo + if ( ! MarchAlongLoop( nT, 2, m_nTimeStamp, vPL.back())) + return false ; + } + // se i due lati 1 e 2 sono di contorno + else if ( nAdjT[1] == SVT_NULL && + nAdjT[2] == SVT_NULL) { + // ho trovato l'inizio di un loop + vPL.emplace_back() ; + vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ; + vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ; + vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ; + // marco il triangolo come verificato + m_vTria[nT].nTemp = m_nTimeStamp ; + // cammino lungo il loop fino a chiuderlo + if ( ! MarchAlongLoop( nT, 0, m_nTimeStamp, vPL.back())) + return false ; + } + // se i due lati 2 e 0 sono di contorno + else if ( nAdjT[2] == SVT_NULL && + nAdjT[0] == SVT_NULL) { + // ho trovato l'inizio di un loop + vPL.emplace_back() ; + vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ; + vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ; + vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ; + // marco il triangolo come verificato + m_vTria[nT].nTemp = m_nTimeStamp ; + // cammino lungo il loop fino a chiuderlo + if ( ! MarchAlongLoop( nT, 1, m_nTimeStamp, vPL.back())) + return false ; + } + // se il lato 0 è di contorno + else if ( nAdjT[0] == SVT_NULL) { + // ho trovato l'inizio di un loop + vPL.emplace_back() ; + vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ; + vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ; + // marco il triangolo come verificato + m_vTria[nT].nTemp = m_nTimeStamp ; + // cammino lungo il loop fino a chiuderlo + if ( ! MarchAlongLoop( nT, 1, m_nTimeStamp, vPL.back())) + return false ; + } + // se il lato 1 è di contorno + else if ( nAdjT[1] == SVT_NULL) { + // ho trovato l'inizio di un loop + vPL.emplace_back() ; + vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ; + vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ; + // marco il triangolo come verificato + m_vTria[nT].nTemp = m_nTimeStamp ; + // cammino lungo il loop fino a chiuderlo + if ( ! MarchAlongLoop( nT, 2, m_nTimeStamp, vPL.back())) + return false ; + } + // se il lato 2 è di contorno + else if ( nAdjT[2] == SVT_NULL) { + // ho trovato l'inizio di un loop + vPL.emplace_back() ; + vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ; + vPL.back().AddUPoint( nT, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ; + // marco il triangolo come verificato + m_vTria[nT].nTemp = m_nTimeStamp ; + // cammino lungo il loop fino a chiuderlo + if ( ! MarchAlongLoop( nT, 0, m_nTimeStamp, vPL.back())) + return false ; + } + // altrimenti non c'è contorno + else { + // marco il triangolo come verificato + m_vTria[nT].nTemp = m_nTimeStamp ; + } + } + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +SurfTriMesh::MarchAlongLoop( int nT, int nV, int nTimeStamp, PolyLine& PL) const +{ + // mi muovo lungo il loop, un triangolo alla volta + bool bEnd = false ; + while ( ! bEnd) { + if ( ! MarchOneTria( nT, nV, nTimeStamp, PL, bEnd)) + return false ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +SurfTriMesh::MarchOneTria( int& nT, int& nV, int nTimeStamp, + PolyLine& PL, bool& bEnd) const +{ + // verifico esistenza triangolo adiacente, sul lato dopo il vertice + if ( m_vTria[nT].nIdAdjac[nV] == SVT_NULL) + return false ; + int nAdjT = m_vTria[nT].nIdAdjac[nV] ; + // recupero il suo lato di adiacenza + 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) + return false ; + // vertice di fine adiacenza e indice del successivo lato + int nAdjV = Next( nAdjS) ; + // verifico se il lato successivo è un bordo + int nNextT = m_vTria[nAdjT].nIdAdjac[nAdjV] ; + if ( nNextT == SVT_NULL) { + // se già recuperato + if ( m_vTria[nAdjT].nTemp == nTimeStamp) { + bEnd = true ; + return true ; + } + // dichiaro triangolo analizzato + m_vTria[nAdjT].nTemp = nTimeStamp ; + // aggiungo il lato al loop + nAdjV = Next( nAdjV) ; + PL.AddUPoint( nAdjT, m_vVert[m_vTria[nAdjT].nIdVert[nAdjV]].ptP) ; + // verifico anche il successivo + nNextT = m_vTria[nAdjT].nIdAdjac[nAdjV] ; + if ( nNextT == SVT_NULL) { + // aggiungo il lato al loop + nAdjV = Next( nAdjV) ; + PL.AddUPoint( nAdjT, m_vVert[m_vTria[nAdjT].nIdVert[nAdjV]].ptP) ; + } + } + // devo passare al triangolo adiacente + nT = nAdjT ; + nV = nAdjV ; + return true ; +} + //---------------------------------------------------------------------------- SurfTriMesh* SurfTriMesh::Clone( void) const diff --git a/SurfTriMesh.h b/SurfTriMesh.h index 7944404..6aab84f 100644 --- a/SurfTriMesh.h +++ b/SurfTriMesh.h @@ -162,6 +162,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW virtual bool GetVertexSmoothNormal( int nV, int nT, Vector3d& vtN) const ; virtual bool GetTriangleBoundaryEdges( int nId, TriFlags3d& TFlags) const ; virtual bool GetTriangleSmoothNormals( int nId, TriNormals3d& TNrms) const ; + virtual bool GetLoops( POLYLINEVECTOR& vPL) const ; virtual int GetFacetCount( void) const ; virtual int GetFacetSize( void) const { return int( m_vFacet.size()) ; } @@ -216,6 +217,8 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW int NextIndAroundVertex( int nInd, int nSize, bool bCirc) const ; int PrevIndAroundVertex( int nInd, int nSize, bool bCirc) const ; bool GetTriangleSmoothNormal( int nT, int nV, Vector3d& vtN) const ; + bool MarchAlongLoop( int nT, int nV, int nTimeStamp, PolyLine& PL) const ; + bool MarchOneTria( int& nT, int& nV, int nTimeStamp, PolyLine& PL, bool& bEnd) const ; bool VerifyPolylinesForTwoCurves( const PolyLine& PL1, const PolyLine& PL2) const ; bool VeryfyPolylineForRevolution( const PolyLine& PL, const Point3d& ptAx, const Vector3d& vtAx) const ; bool AddBiTriangle( const int nIdVert[4]) ; @@ -225,8 +228,8 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW bool UpdateTriaFaceting( int nRefT, int nFacet, const Plane3d& plPlane, int nT) ; bool SetFacet( int nInd, int nT) ; bool VerifyAdjacTriaFacet( int nT, INTVECTOR& vT) const ; - bool MarchAlongLoop( int nF, int nT, int nV, int nTimeStamp, PolyLine& PL) const ; - bool MarchOneTria( int nF, int& nT, int& nV, int nTimeStamp, PolyLine& PL, bool& bEnd) const ; + bool MarchAlongFacetLoop( int nF, int nT, int nV, int nTimeStamp, PolyLine& PL) const ; + bool MarchOneFacetTria( int nF, int& nT, int& nV, int nTimeStamp, PolyLine& PL, bool& bEnd) const ; private : ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto diff --git a/SurfTriMeshFaceting.cpp b/SurfTriMeshFaceting.cpp index f5238a5..925c17c 100644 --- a/SurfTriMeshFaceting.cpp +++ b/SurfTriMeshFaceting.cpp @@ -338,7 +338,7 @@ SurfTriMesh::GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const // marco il triangolo come verificato m_vTria[nT].nTemp = m_nTimeStamp ; // cammino lungo il loop fino a chiuderlo - if ( ! MarchAlongLoop( nF, nT, 2, m_nTimeStamp, vPL.back())) + if ( ! MarchAlongFacetLoop( nF, nT, 2, m_nTimeStamp, vPL.back())) return false ; } // se i due lati 1 e 2 sono di contorno @@ -352,7 +352,7 @@ SurfTriMesh::GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const // marco il triangolo come verificato m_vTria[nT].nTemp = m_nTimeStamp ; // cammino lungo il loop fino a chiuderlo - if ( ! MarchAlongLoop( nF, nT, 0, m_nTimeStamp, vPL.back())) + if ( ! MarchAlongFacetLoop( nF, nT, 0, m_nTimeStamp, vPL.back())) return false ; } // se i due lati 2 e 0 sono di contorno @@ -366,7 +366,7 @@ SurfTriMesh::GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const // marco il triangolo come verificato m_vTria[nT].nTemp = m_nTimeStamp ; // cammino lungo il loop fino a chiuderlo - if ( ! MarchAlongLoop( nF, nT, 1, m_nTimeStamp, vPL.back())) + if ( ! MarchAlongFacetLoop( nF, nT, 1, m_nTimeStamp, vPL.back())) return false ; } // se il lato 0 è di contorno @@ -378,7 +378,7 @@ SurfTriMesh::GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const // marco il triangolo come verificato m_vTria[nT].nTemp = m_nTimeStamp ; // cammino lungo il loop fino a chiuderlo - if ( ! MarchAlongLoop( nF, nT, 1, m_nTimeStamp, vPL.back())) + if ( ! MarchAlongFacetLoop( nF, nT, 1, m_nTimeStamp, vPL.back())) return false ; } // se il lato 1 è di contorno @@ -390,7 +390,7 @@ SurfTriMesh::GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const // marco il triangolo come verificato m_vTria[nT].nTemp = m_nTimeStamp ; // cammino lungo il loop fino a chiuderlo - if ( ! MarchAlongLoop( nF, nT, 2, m_nTimeStamp, vPL.back())) + if ( ! MarchAlongFacetLoop( nF, nT, 2, m_nTimeStamp, vPL.back())) return false ; } // se il lato 2 è di contorno @@ -402,7 +402,7 @@ SurfTriMesh::GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const // marco il triangolo come verificato m_vTria[nT].nTemp = m_nTimeStamp ; // cammino lungo il loop fino a chiuderlo - if ( ! MarchAlongLoop( nF, nT, 0, m_nTimeStamp, vPL.back())) + if ( ! MarchAlongFacetLoop( nF, nT, 0, m_nTimeStamp, vPL.back())) return false ; } // altrimenti non c'è contorno @@ -442,12 +442,12 @@ SurfTriMesh::GetFacetLoops( int nF, POLYLINEVECTOR& vPL) const //---------------------------------------------------------------------------- bool -SurfTriMesh::MarchAlongLoop( int nF, int nT, int nV, int nTimeStamp, PolyLine& PL) const +SurfTriMesh::MarchAlongFacetLoop( int nF, int nT, int nV, int nTimeStamp, PolyLine& PL) const { // mi muovo lungo il loop, un triangolo alla volta bool bEnd = false ; while ( ! bEnd) { - if ( ! MarchOneTria( nF, nT, nV, nTimeStamp, PL, bEnd)) + if ( ! MarchOneFacetTria( nF, nT, nV, nTimeStamp, PL, bEnd)) return false ; } return true ; @@ -455,8 +455,8 @@ SurfTriMesh::MarchAlongLoop( int nF, int nT, int nV, int nTimeStamp, PolyLine& P //---------------------------------------------------------------------------- bool -SurfTriMesh::MarchOneTria( int nF, int& nT, int& nV, int nTimeStamp, - PolyLine& PL, bool& bEnd) const +SurfTriMesh::MarchOneFacetTria( int nF, int& nT, int& nV, int nTimeStamp, + PolyLine& PL, bool& bEnd) const { // verifico esistenza triangolo adiacente, sul lato dopo il vertice if ( m_vTria[nT].nIdAdjac[nV] == SVT_NULL)