EgtGeomKernel 2.7f1 :
- migliorie e piccole correzioni varie nelle trimesh ( booleane, chiusura).
This commit is contained in:
@@ -3309,8 +3309,6 @@ MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAn
|
||||
CurveArc NewArc ;
|
||||
if ( NewArc.Set3P( ptP1, ptP2, ptP3, bCirc)) {
|
||||
// se vicino a circonferenza arco per 3 punti potrebbe non dare il risultato desiderato quindi faccio controllo su raggio e centro
|
||||
double dDist = Dist( NewArc.GetCenter(), ptC1Fin) ;
|
||||
double dDelta = abs( NewArc.GetRadius() - pArcP->GetRadius()) ;
|
||||
if ( Dist( NewArc.GetCenter(), ptC1Fin) > 2 * dCurrLinTol || abs( NewArc.GetRadius() - pArcP->GetRadius()) > 2 * dCurrLinTol)
|
||||
return 0 ;
|
||||
|
||||
|
||||
Binary file not shown.
+5
-5
@@ -19,10 +19,10 @@
|
||||
void
|
||||
PolygonPlane::AddPoint( const Point3d& ptP)
|
||||
{
|
||||
// se è il primo punto (parto da -1 perchè verrà contato alla chiusura)
|
||||
// se è il primo punto (parto da -1 perchè verrà contato alla chiusura)
|
||||
if ( m_nPntNbr == -1) {
|
||||
// inizializzazioni
|
||||
m_dLenN = 0 ;
|
||||
m_dLenN = -1 ;
|
||||
m_vtN = V_NULL ;
|
||||
m_ptMid = ORIG ;
|
||||
m_dSXy = 0 ; m_dSXz = 0 ;
|
||||
@@ -60,16 +60,16 @@ PolygonPlane::AddPoint( const Point3d& ptP)
|
||||
bool
|
||||
PolygonPlane::Finalize( void)
|
||||
{
|
||||
// almeno 3 punti (il triangolo è il poligono con minimo numero di lati)
|
||||
// almeno 3 punti (il triangolo è il poligono con minimo numero di lati)
|
||||
if ( m_nPntNbr + 1 < 3)
|
||||
return false ;
|
||||
// se il poligono non è stato chiuso, aggiungo calcolo per ultimo lato
|
||||
// se il poligono non è stato chiuso, aggiungo calcolo per ultimo lato
|
||||
if ( ! AreSamePointExact( m_ptFirst, m_ptLast)) {
|
||||
// aggiungo il primo punto per far eseguire i conti sul lato di chiusura
|
||||
AddPoint( m_ptFirst) ;
|
||||
}
|
||||
// se non effettuato, eseguo il calcolo finale
|
||||
if ( m_dLenN < EPS_SMALL) {
|
||||
if ( m_dLenN < 0) {
|
||||
// lunghezza della normale (doppio dell'area del poligono)
|
||||
m_dLenN = m_vtN.Len() ;
|
||||
if ( m_dLenN < SQ_EPS_SMALL)
|
||||
|
||||
+59
-21
@@ -3044,7 +3044,7 @@ SurfTriMesh::AddBiTriangle( const int nIdVert[4])
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::DoCompacting( double dTol)
|
||||
{
|
||||
{
|
||||
// imposto ricalcolo
|
||||
m_nStatus = ERR ;
|
||||
m_OGrMgr.Reset() ;
|
||||
@@ -3085,6 +3085,7 @@ SurfTriMesh::DoCompacting( double dTol)
|
||||
int nVIdSize = int( vVId.size()) ;
|
||||
|
||||
// sistemo gli indici dei vertici nei triangoli
|
||||
INTVECTOR vInvalidIds ;
|
||||
for ( int nId = 0 ; nId < GetTriangleSize() ; ++ nId) {
|
||||
// salto i triangoli cancellati
|
||||
if ( m_vTria[nId].nIdVert[0] == SVT_DEL)
|
||||
@@ -3101,15 +3102,51 @@ SurfTriMesh::DoCompacting( double dTol)
|
||||
// aggiorno il triangolo
|
||||
m_vTria[nId].nIdVert[0] = vVId[vOId[0]] ;
|
||||
m_vTria[nId].nIdVert[1] = vVId[vOId[1]] ;
|
||||
m_vTria[nId].nIdVert[2] = vVId[vOId[2]] ;
|
||||
// se due vertici coincidono o la normale non è calcolabile, cancello il triangolo
|
||||
if ( m_vTria[nId].nIdVert[0] == m_vTria[nId].nIdVert[1] ||
|
||||
m_vTria[nId].nIdVert[0] == m_vTria[nId].nIdVert[2] ||
|
||||
m_vTria[nId].nIdVert[1] == m_vTria[nId].nIdVert[2] ||
|
||||
! CalcTriangleNormal( nId))
|
||||
RemoveTriangle( nId) ;
|
||||
m_vTria[nId].nIdVert[2] = vVId[vOId[2]] ;
|
||||
|
||||
// verifico se triangolo da rimuovere per vertici coincidenti
|
||||
bool bRemove = false ;
|
||||
int nTAdj1 = SVT_NULL, nTAdj2 = SVT_NULL ;
|
||||
if ( m_vTria[nId].nIdVert[0] == m_vTria[nId].nIdVert[1]) {
|
||||
nTAdj1 = m_vTria[nId].nIdAdjac[1] ;
|
||||
nTAdj2 = m_vTria[nId].nIdAdjac[2] ;
|
||||
bRemove = true ;
|
||||
}
|
||||
else if ( m_vTria[nId].nIdVert[0] == m_vTria[nId].nIdVert[2]) {
|
||||
nTAdj1 = m_vTria[nId].nIdAdjac[0] ;
|
||||
nTAdj2 = m_vTria[nId].nIdAdjac[1] ;
|
||||
bRemove = true ;
|
||||
}
|
||||
else if ( m_vTria[nId].nIdVert[1] == m_vTria[nId].nIdVert[2]) {
|
||||
nTAdj1 = m_vTria[nId].nIdAdjac[0] ;
|
||||
nTAdj2 = m_vTria[nId].nIdAdjac[2] ;
|
||||
bRemove = true ;
|
||||
}
|
||||
if ( bRemove) {
|
||||
// sistemo le contro adiacenze
|
||||
if ( nTAdj1 != SVT_NULL) {
|
||||
for ( int j = 0 ; j < 3 ; ++ j)
|
||||
if ( m_vTria[nTAdj1].nIdAdjac[j] == nId)
|
||||
m_vTria[nTAdj1].nIdAdjac[j] = nTAdj2 ;
|
||||
}
|
||||
if ( nTAdj2 != SVT_NULL) {
|
||||
for ( int j = 0 ; j < 3 ; ++ j)
|
||||
if ( m_vTria[nTAdj2].nIdAdjac[j] == nId)
|
||||
m_vTria[nTAdj2].nIdAdjac[j] = nTAdj1 ;
|
||||
}
|
||||
// rimuovo il triangolo
|
||||
RemoveTriangle( nId) ;
|
||||
}
|
||||
|
||||
// verifico se il triangolo va rimosso per normale non calcolabile
|
||||
else if ( ! CalcTriangleNormal( nId))
|
||||
vInvalidIds.emplace_back( nId) ;
|
||||
}
|
||||
|
||||
// elimino triangoli invalidi ( con gestione speciale per evitare T-junctions)
|
||||
if ( ! vInvalidIds.empty())
|
||||
RemoveInvalidTriangles( vInvalidIds) ;
|
||||
|
||||
// compatto il vettore dei vertici
|
||||
if ( ! PackVertices())
|
||||
return false ;
|
||||
@@ -3346,22 +3383,23 @@ SurfTriMesh::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, double
|
||||
bMirror = ( bMirror ? ( dCoeffY > 0) : ( dCoeffY < 0)) ;
|
||||
bMirror = ( bMirror ? ( dCoeffZ > 0) : ( dCoeffZ < 0)) ;
|
||||
|
||||
// aggiorno le facce
|
||||
for ( int i = 0 ; i < GetTriangleSize() ; ++ i) {
|
||||
if ( m_vTria[i].nIdVert[0] != SVT_DEL) {
|
||||
// se c'è mirror, devo invertire la faccia
|
||||
if ( bMirror)
|
||||
InvertTriangle( i) ;
|
||||
// aggiorno la normale
|
||||
if ( ! CalcTriangleNormal( i)) {
|
||||
// elimino il triangolo
|
||||
RemoveTriangle( i) ;
|
||||
}
|
||||
}
|
||||
// se c'è mirror, devo invertire le facce
|
||||
if ( bMirror) {
|
||||
for ( int i = 0 ; i < GetTriangleSize() ; ++ i)
|
||||
if ( m_vTria[i].nIdVert[0] != SVT_DEL)
|
||||
InvertTriangle( i) ;
|
||||
}
|
||||
|
||||
// rimuovo i triangoli resi invalidi dalla scalatura
|
||||
bool bOk = DoCompacting() ;
|
||||
|
||||
return DoCompacting() ;
|
||||
// rimuovo i triangoli doppi
|
||||
bool bModified = false ;
|
||||
bOk = bOk && RemoveDoubleTriangles( bModified) ;
|
||||
if ( bModified)
|
||||
bOk = bOk && ( AdjustVertices() && DoCompacting()) ;
|
||||
|
||||
return bOk ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
@@ -440,6 +440,10 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
|
||||
bool DistPointFacet( const Point3d& ptP, const POLYLINEVECTOR& vPolyVec, double& dPointFacetDist) ;
|
||||
bool ChangeStart( const Point3d& ptNewStart, PNTVECTOR& Loop) ;
|
||||
bool SplitAtPoint( const Point3d& ptStop, const PNTVECTOR& Loop, PNTVECTOR& Loop1, PNTVECTOR& Loop2) ;
|
||||
bool AdjustLoop( PNTULIST& PointList, double dMaxEdgeLen, int nF, bool& bModif) const ;
|
||||
bool RemoveInvalidTriangles( const INTVECTOR& vIds) ;
|
||||
bool FindAdjacentOnLongerEdge( int nT, int& nEdge, int& nAdjTrg) const ;
|
||||
|
||||
|
||||
private :
|
||||
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
|
||||
|
||||
+42
-83
@@ -502,9 +502,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
}
|
||||
}
|
||||
}
|
||||
// -------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
|
||||
// Creo il loop chiuso padre di tutti, il perimetro del triangolo. Questo viene diviso in sotto-loop
|
||||
// chiusi mediante quelli aperti. I loop chiusi trovati precedentemente sono interni a uno dei
|
||||
// sotto-loop chiusi di cui è formato il perimetro.
|
||||
@@ -704,16 +702,18 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
}
|
||||
}
|
||||
}
|
||||
// Elimino loop interni non validi
|
||||
bool bDouble = true ;
|
||||
// Verifico se i loop interni sono validi
|
||||
bool bAllInvalid = true ;
|
||||
for ( int nInnLoop = 0 ; nInnLoop < int( vInnerLoop.size()) ; ++ nInnLoop) {
|
||||
if ( cvClosedChain[vInnerLoop[nInnLoop]].size() > 2) {
|
||||
bDouble = false ;
|
||||
// se chain formata da tre segmenti significa che si tratta di due linee sovrapposte ( il terzo tratto è quello aggiunto
|
||||
// per forzare la chiusura)
|
||||
if ( cvClosedChain[vInnerLoop[nInnLoop]].size() > 3) {
|
||||
bAllInvalid = false ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
if ( vInnerLoop.empty() || bDouble) {
|
||||
if ( vInnerLoop.empty() || bAllInvalid) {
|
||||
// Eseguo triangolazione
|
||||
PNTVECTOR vPt ;
|
||||
INTVECTOR vTr ;
|
||||
@@ -753,63 +753,20 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
vPolygons.emplace_back( CurLoop) ;
|
||||
}
|
||||
|
||||
// poligono
|
||||
Polygon3d pgPol ;
|
||||
pgPol.FromPolyLine( vPolygons[1]) ;
|
||||
|
||||
// controllo direzioni delle normali
|
||||
bool bCodirectedNormals = trTria.GetN() * pgPol.GetVersN() > 0. ;
|
||||
|
||||
// Aggiungo al loop esterno i punti dei loop interni che si trovano su di esso
|
||||
PNTULIST& ExternLoopList = vPolygons[0].GetUPointList() ;
|
||||
// Ciclo sui segmenti del loop esterno
|
||||
auto itSt = ExternLoopList.begin() ;
|
||||
auto itEn = itSt ;
|
||||
++ itEn ;
|
||||
for ( ; itSt != ExternLoopList.end() && itEn != ExternLoopList.end() ; ++ itSt, ++ itEn) {
|
||||
// Estremi del segmento corrente del loop esterno e scorrispondente vettore
|
||||
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
|
||||
for ( int nInnPoly = 1 ; nInnPoly < int( vPolygons.size()) ; ++ nInnPoly) {
|
||||
// Ciclo sui punti dei loop interni
|
||||
Point3d ptInnPoint ;
|
||||
bool bIsFirst = true ;
|
||||
bool bContinue = vPolygons[nInnPoly].GetFirstPoint( ptInnPoint) ;
|
||||
while ( bContinue) {
|
||||
DistPointLine DistCalculator( ptInnPoint, ptSt, ptEn) ;
|
||||
double dDist ;
|
||||
DistCalculator.GetDist( dDist) ;
|
||||
double dLongPos = ( ptInnPoint - ptSt) * vtSeg ;
|
||||
if ( dDist < EPS_SMALL && dLongPos > 0. && dLongPos < dSegLen) {
|
||||
POINTU NewPointU ;
|
||||
NewPointU.first = ptInnPoint ;
|
||||
NewPointU.second = dLongPos ;
|
||||
if ( ! bIsFirst)
|
||||
vPointWithOrder.emplace_back( NewPointU) ;
|
||||
}
|
||||
bIsFirst = false ;
|
||||
bContinue = vPolygons[nInnPoly].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 = ExternLoopList.emplace( itEn, vPointWithOrder[nPi]) ;
|
||||
}
|
||||
// controllo la direzione della normale del triangolo con quella del poligono di area maggiore
|
||||
// ( per gestire eventuali inscatolamenti)
|
||||
Vector3d vtPoly = V_NULL ;
|
||||
double dMaxArea = -1 ;
|
||||
for ( int i = 1 ; i < int( vPolygons.size()) ; i ++) {
|
||||
Plane3d plPoly ;
|
||||
double dAreaPoly ;
|
||||
vPolygons[i].IsClosedAndFlat( plPoly, dAreaPoly) ;
|
||||
if ( dAreaPoly > dMaxArea) {
|
||||
vtPoly = plPoly.GetVersN() ;
|
||||
dMaxArea = dAreaPoly ;
|
||||
}
|
||||
}
|
||||
bool bCodirectedNormals = trTria.GetN() * vtPoly > 0. ;
|
||||
|
||||
PNTVECTOR vPt ;
|
||||
INTVECTOR vTr ;
|
||||
@@ -836,6 +793,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
}
|
||||
|
||||
// Divido i loop che si autointercettano
|
||||
// TO DO : da verificare. Questa porzione di codice non dovrebbe andare prima della triangolazione?
|
||||
int nInitialLoopNum = int( vPolygons.size()) ;
|
||||
for ( int nL = 1 ; nL < nInitialLoopNum ; ++ nL) {
|
||||
// Lista dei punti della PolyLine Loop corrente
|
||||
@@ -883,11 +841,11 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
itSt2 = LoopPointList.emplace( itEn2, vAddingPointWithOrder[nPi]) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Spezzo i loop autointersecantesi
|
||||
POLYLINEVECTOR vAuxPolygons ;
|
||||
vAuxPolygons.emplace_back( vPolygons[nL]) ;
|
||||
|
||||
|
||||
bool bSplitted = true ;
|
||||
while ( bSplitted) {
|
||||
bSplitted = false ;
|
||||
@@ -956,16 +914,13 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
vPolygons.erase( vPolygons.begin() + i) ;
|
||||
else
|
||||
++ i ;
|
||||
|
||||
}
|
||||
|
||||
bool bCordirectedNormals_intLoop = bCodirectedNormals ;
|
||||
// eventuale inversione della prima curva ( che determina il verso della triangolazione) per averla orientata
|
||||
// come il triangolo
|
||||
if ( ! vPolygons.empty()) {
|
||||
Polygon3d pgPol ;
|
||||
pgPol.FromPolyLine( vPolygons[0]) ;
|
||||
// controllo direzioni delle normali
|
||||
bCordirectedNormals_intLoop = trTria.GetN() * pgPol.GetVersN() > 0. ;
|
||||
if ( ! bCordirectedNormals_intLoop)
|
||||
if ( trTria.GetN() * pgPol.GetVersN() < 0.)
|
||||
vPolygons[0].Invert() ;
|
||||
}
|
||||
|
||||
@@ -981,7 +936,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
Surf.m_vTria[nNewTriaNum].nETempFlag[0] = 0 ;
|
||||
Surf.m_vTria[nNewTriaNum].nETempFlag[1] = 0 ;
|
||||
Surf.m_vTria[nNewTriaNum].nETempFlag[2] = 0 ;
|
||||
if ( bCordirectedNormals_intLoop)
|
||||
if ( bCodirectedNormals)
|
||||
Surf.m_vTria[nNewTriaNum].nTempShell = 1 ;
|
||||
else
|
||||
Surf.m_vTria[nNewTriaNum].nTempShell = -1 ;
|
||||
@@ -1123,7 +1078,7 @@ SurfTriMesh::AmbiguosTriangleManager( TRIA3DVECTORMAP& Ambiguos, SurfTriMesh& Su
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
{
|
||||
{
|
||||
bool bModif = false ;
|
||||
SurfTriMesh& SurfB = Other ;
|
||||
|
||||
@@ -1176,7 +1131,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
INTVECTOR vNearTria ;
|
||||
SurfB.GetAllTriaOverlapBox( b3dTriaA, vNearTria) ;
|
||||
|
||||
// I scorro tutti i triangoli di B che intersecano il box di A
|
||||
// Scorro tutti i triangoli di B che intersecano il box di A
|
||||
for ( int nTB = 0 ; nTB < int( vNearTria.size()) ; ++ nTB) {
|
||||
|
||||
// Se il triangolo B non è valido, continuo
|
||||
@@ -1365,7 +1320,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
// Triangoli sovrapposti
|
||||
if ( bContinue) {
|
||||
int nTriaNum2A = GetTriangleSize() ;
|
||||
// Resetto e ricalcolo la HashGrid della superficie B
|
||||
// Resetto e ricalcolo la HashGrid della superficie B
|
||||
SurfB.ResetHashGrids3d() ;
|
||||
for ( int nTA = 0 ; nTA < nTriaNum2A ; ++ nTA) {
|
||||
// Se il triangolo A non è valido, continuo
|
||||
@@ -1375,15 +1330,19 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
// Box del triangolo A
|
||||
BBox3d b3dTriaA ;
|
||||
trTriaA.GetLocalBBox( b3dTriaA) ;
|
||||
// Recupero i triangoli di B che interferiscono col box del triangolo di A
|
||||
// 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
|
||||
// Se il triangolo B non è valido, continuo
|
||||
Triangle3d trTriaB ;
|
||||
if ( ! SurfB.GetTriangle( vNearTria[nTB], trTriaB) || ! trTriaB.Validate( true))
|
||||
continue ;
|
||||
// Se i triangoli sono sovrapposti
|
||||
// Se sono già stati classificati entrambi come sovrapposti continuo
|
||||
if ( abs( m_vTria[nTA].nTempShell) == 2 && abs( SurfB.m_vTria[vNearTria[nTB]].nTempShell) == 2)
|
||||
continue ;
|
||||
|
||||
// Se i triangoli sono sovrapposti
|
||||
TRIA3DVECTOR vTriaAB ;
|
||||
Point3d ptTempA, ptTempB ;
|
||||
int nIntTypeAB = IntersTriaTria( trTriaA, trTriaB, ptTempA, ptTempB, vTriaAB) ;
|
||||
@@ -1475,7 +1434,7 @@ SurfTriMesh::Add( const ISurfTriMesh& Other)
|
||||
// tengo una copia di B ( la superficie B viene modificata durante la ritriangolazione )
|
||||
SurfTriMesh SurfA_cl ;
|
||||
SurfA_cl.CopyFrom( this) ;
|
||||
|
||||
|
||||
// ritriangolo le due superfici mediante ogni intersezione Triangolo-Triangolo
|
||||
IntersectTriMeshTriangle( SurfB) ;
|
||||
|
||||
@@ -1625,12 +1584,12 @@ SurfTriMesh::Intersect( const ISurfTriMesh& Other)
|
||||
AddTriangle( nNewVert, m_nMaxTFlag) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// sistemazioni varie
|
||||
bool bOk = ( AdjustVertices() && DoCompacting()) ;
|
||||
bool bModified = false ;
|
||||
bOk = bOk && RemoveDoubleTriangles( bModified) ;
|
||||
if ( bModified)
|
||||
bOk = bOk && RemoveDoubleTriangles( bModified) ;
|
||||
if ( bModified)
|
||||
bOk = bOk && ( AdjustVertices() && DoCompacting()) ;
|
||||
bOk = bOk && RemoveTJunctions( bModified) ;
|
||||
if ( bModified)
|
||||
|
||||
+192
-25
@@ -17,7 +17,6 @@
|
||||
#include "Triangulate.h"
|
||||
#include "/EgtDev/Include/EGkDistPointLine.h"
|
||||
#include "/EgtDev/Include/EGkDistLineLine.h"
|
||||
#include <unordered_map>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
@@ -35,6 +34,7 @@ SurfTriMesh::RemoveDoubleTriangles( bool& bModified)
|
||||
// recupero i vertici dei triangoli
|
||||
int nIdV[3] ;
|
||||
GetTriangle( nT, nIdV) ;
|
||||
bool bToRemove = false ;
|
||||
// ciclo sui triangoli adiacenti
|
||||
for ( int nE = 0 ; nE < 3 ; ++ nE) {
|
||||
// recupero triangolo adiacente, se non esiste passo al successivo
|
||||
@@ -53,10 +53,14 @@ SurfTriMesh::RemoveDoubleTriangles( bool& bModified)
|
||||
}
|
||||
}
|
||||
if ( nCoinc == 3) {
|
||||
RemoveTriangle( nAdjT) ;
|
||||
// se i vertici coincidono rimuovo entrambi i triangoli
|
||||
bToRemove = true ;
|
||||
bModified = true ;
|
||||
RemoveTriangle( nAdjT) ;
|
||||
}
|
||||
}
|
||||
if ( bToRemove)
|
||||
RemoveTriangle( nT) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
@@ -86,8 +90,8 @@ SurfTriMesh::FlipTriangles( int nTA, int nTB)
|
||||
// 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))
|
||||
! 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 ;
|
||||
@@ -98,17 +102,37 @@ SurfTriMesh::FlipTriangles( int nTA, int nTB)
|
||||
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 ;
|
||||
if ( ! DiagDist.GetPositionsAtMinDistPoints( dPos1, dPos2))
|
||||
return false ;
|
||||
if ( 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[nTA].nIdAdjac[( nEdgeA + 2) % 3] = nTB ;
|
||||
m_vTria[nTB].nIdAdjac[( nEdgeB + 2) % 3] = nTA ;
|
||||
|
||||
// sistemo anche le contro-adiacenze
|
||||
int nTC = m_vTria[nTA].nIdAdjac[nEdgeA] ;
|
||||
if ( nTC != SVT_NULL) {
|
||||
for ( int i = 0 ; i < 3 ; i++)
|
||||
if ( m_vTria[nTC].nIdAdjac[i] == nTB) {
|
||||
m_vTria[nTC].nIdAdjac[i] = nTA ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
int nTD = m_vTria[nTB].nIdAdjac[nEdgeB] ;
|
||||
if ( nTD != SVT_NULL) {
|
||||
for ( int i = 0 ; i < 3 ; i++)
|
||||
if ( m_vTria[nTD].nIdAdjac[i] == nTA) {
|
||||
m_vTria[nTD].nIdAdjac[i] = nTB ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -150,6 +174,8 @@ SurfTriMesh::RemoveTJunctions( bool& bModified)
|
||||
if ( dSegLen < EPS_SMALL)
|
||||
continue ;
|
||||
vtSeg /= dSegLen ;
|
||||
int nV1 = m_vTria[nT].nIdVert[nSeg] ;
|
||||
int nV2 = m_vTria[nT].nIdVert[Next( nSeg)] ;
|
||||
// Ciclo sui triangoli vicini
|
||||
for ( int nI = 0 ; nI < int( vNearTria.size()) ; ++ nI) {
|
||||
// Salto il triangolo se è quello di riferimento
|
||||
@@ -157,6 +183,9 @@ SurfTriMesh::RemoveTJunctions( bool& bModified)
|
||||
continue ;
|
||||
// Cerco i vertici che stanno sul lato del triangolo
|
||||
for ( int nVert = 0 ; nVert < 3 ; ++ nVert) {
|
||||
int nCurrVert = m_vTria[vNearTria[nI]].nIdVert[nVert] ;
|
||||
if ( nCurrVert == nV1 || nCurrVert == nV2)
|
||||
continue ;
|
||||
Point3d ptVert ;
|
||||
if ( ! GetVertex( m_vTria[vNearTria[nI]].nIdVert[nVert], ptVert))
|
||||
continue ;
|
||||
@@ -307,16 +336,44 @@ ChooseGoodStartPoint( PNTULIST& PointList)
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
AdjustLoop( PNTULIST& PointList, double dMaxEdgeLen, bool& bModif)
|
||||
// -------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::AdjustLoop( PNTULIST& PointList, double dMaxEdgeLen, int nF, bool& bModif) const
|
||||
{
|
||||
// Ciclo sui punti del loop
|
||||
auto itLast = PointList.begin() ;
|
||||
for ( auto it = next( itLast) ; it != PointList.end() ; ++ it) {
|
||||
|
||||
// Se dal punto corrente inizia un segmento adiacente a un'altra faccia
|
||||
if ( itLast->second != it->second) {
|
||||
|
||||
// bisogna fermarsi per analizzare il tratto corrente alla ricerca di punti allineati se dal punto corrente
|
||||
// inizia un tratto adiacente ad un'altra faccia oppure se il punto corrente non verrà eliminato dal loop
|
||||
// della faccia adiacente
|
||||
bool bAnalyze = ( itLast->second != it->second) ;
|
||||
if ( ! bAnalyze && itLast->second != - 1) {
|
||||
// recupero i loop della faccia adiacente
|
||||
POLYLINEVECTOR LoopVec ;
|
||||
GetFacetLoops( int( itLast->second), LoopVec) ;
|
||||
bool bFound = false ;
|
||||
for ( int i = 0 ; i < int( LoopVec.size()) && ! bFound ; i ++) {
|
||||
const PNTULIST& PointListAdj = LoopVec[i].GetUPointList() ;
|
||||
for ( auto itAdj = PointListAdj.begin() ; itAdj != prev( PointListAdj.end()) && ! bFound ; ++ itAdj) {
|
||||
// cerco il punto corrente sul loop della faccia adiacente
|
||||
if ( itAdj->second == nF && AreSamePointApprox( it->first, itAdj->first)) {
|
||||
bFound = true ;
|
||||
auto itPrev = ( itAdj == PointListAdj.begin() ? prev( prev( PointListAdj.end())) : prev( itAdj)) ;
|
||||
auto itNext = next( itAdj) ;
|
||||
DistPointLine PointLineDistCalc( itAdj->first, itPrev->first, itNext->first) ;
|
||||
double dDist ;
|
||||
if ( PointLineDistCalc.GetDist( dDist) && dDist > 50 * EPS_SMALL)
|
||||
// se il punto non è allineato al precedente e al successivo non verrà rimosso dal loop della faccia adiacente,
|
||||
// quindi non deve essere rimosso dal loop corrente altrimenti si genererebbe una T-Junction. Quindi posso
|
||||
// interrompere e analizzare il tratto trovato fino ad ora
|
||||
bAnalyze = true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ( bAnalyze) {
|
||||
// Raccolgo i punti in una polyline
|
||||
PolyLine PL ;
|
||||
int nPar = -1 ;
|
||||
@@ -433,8 +490,8 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced)
|
||||
// Ciclo sulle facce della mesh per trovare quelle da ritriangolare
|
||||
unordered_map< int, pair< PNTVECTOR, INTVECTOR>> FacetMap ;
|
||||
for ( int nF = 0 ; nF < nFacetCnt ; ++ nF) {
|
||||
|
||||
// Recupero i loop della faccia (il parametro indica la faccia adiacente)
|
||||
|
||||
// Recupero i loop della faccia ( il parametro indica la faccia adiacente)
|
||||
POLYLINEVECTOR LoopVec ;
|
||||
GetFacetLoops( nF, LoopVec) ;
|
||||
|
||||
@@ -451,7 +508,7 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced)
|
||||
|
||||
// Sistemo il loop
|
||||
bool bModif = false ;
|
||||
if ( ! AdjustLoop( PointList, dMaxEdgeLen, bModif))
|
||||
if ( ! AdjustLoop( PointList, dMaxEdgeLen, nF, bModif))
|
||||
return false ;
|
||||
if ( bModif)
|
||||
bToRetriangulate = true ;
|
||||
@@ -483,8 +540,8 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced)
|
||||
FacetMap.emplace( nF, make_pair( vPt, vTr)) ;
|
||||
}
|
||||
// Se non riesco a triangolare anche solo questa faccia, interrompo tutto
|
||||
else
|
||||
return false ;
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -502,17 +559,17 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced)
|
||||
// Cancello i triangoli
|
||||
for ( int nT : vDelTria)
|
||||
RemoveTriangle( nT) ;
|
||||
|
||||
|
||||
// Applico le nuove triangolazioni delle facce
|
||||
for ( auto itF = FacetMap.begin() ; itF != FacetMap.end() ; ++ itF) {
|
||||
const PNTVECTOR& vPt = itF->second.first ;
|
||||
const INTVECTOR& vTr = itF->second.second ;
|
||||
// Inserisco i nuovi triangoli
|
||||
// Inserisco i nuovi triangoli
|
||||
bool bFirstTria = true ;
|
||||
for ( int n = 0 ; n < int( vTr.size()) - 2 ; n += 3) {
|
||||
int nNewId[3] = { AddVertex( vPt[vTr[n]]),
|
||||
AddVertex( vPt[vTr[n + 1]]),
|
||||
AddVertex( vPt[vTr[n + 2]])} ;
|
||||
AddVertex( vPt[vTr[n + 1]]),
|
||||
AddVertex( vPt[vTr[n + 2]])} ;
|
||||
auto itCol = ColorMap.find( itF->first) ;
|
||||
int nTFlag = ( itCol != ColorMap.end() ? itCol->second : 0) ;
|
||||
int nNewTriaId = AddTriangle( nNewId, nTFlag) ;
|
||||
@@ -525,7 +582,7 @@ SurfTriMesh::SimplifyFacets( double dMaxEdgeLen, bool bForced)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// dichiaro necessità ricalcolo della grafica e di hashgrids3d
|
||||
m_OGrMgr.Reset() ;
|
||||
ResetHashGrids3d() ;
|
||||
@@ -722,3 +779,113 @@ SurfTriMesh::SplitAtPoint( const Point3d& ptStop, const PNTVECTOR& Loop, PNTVECT
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::FindAdjacentOnLongerEdge( int nT, int& nEdge, int& nAdjTrg) const
|
||||
{
|
||||
// recupero il lato più lungo del triangolo
|
||||
double dLen0 = SqDist( m_vVert[m_vTria[nT].nIdVert[0]].ptP, m_vVert[m_vTria[nT].nIdVert[1]].ptP) ;
|
||||
double dLen1 = SqDist( m_vVert[m_vTria[nT].nIdVert[1]].ptP, m_vVert[m_vTria[nT].nIdVert[2]].ptP) ;
|
||||
double dLen2 = SqDist( m_vVert[m_vTria[nT].nIdVert[2]].ptP, m_vVert[m_vTria[nT].nIdVert[0]].ptP) ;
|
||||
nEdge = -1 ;
|
||||
if ( dLen0 > dLen1 && dLen0 > dLen2)
|
||||
nEdge = 0 ;
|
||||
else if ( dLen1 > dLen2)
|
||||
nEdge = 1 ;
|
||||
else
|
||||
nEdge = 2 ;
|
||||
|
||||
// recupero il triangolo adiacente sul lato più lungo
|
||||
nAdjTrg = m_vTria[nT].nIdAdjac[nEdge] ;
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
SurfTriMesh::RemoveInvalidTriangles( const INTVECTOR& vIds)
|
||||
{
|
||||
// al momento gestito solo per trimesh con adiacenze definite, eventualmente da estendere.
|
||||
// Analoga a RemoveFistInvalidTrg in Triangulate.cpp
|
||||
// TO DO da capire e gestire casi in cui flip lascia triangoli invalidi
|
||||
|
||||
unordered_map<int, bool> InvalidMap ;
|
||||
for ( auto nId : vIds)
|
||||
InvalidMap[nId] = true ;
|
||||
|
||||
for ( int i = 0 ; i < int( vIds.size()) ; i++) {
|
||||
|
||||
int nTA = vIds[i] ;
|
||||
if ( ! InvalidMap[nTA])
|
||||
continue ;
|
||||
|
||||
// recupero il triangolo adiacente sul suo lato più lungo
|
||||
int nTB, nEdgeA ;
|
||||
FindAdjacentOnLongerEdge( nTA, nEdgeA, nTB) ;
|
||||
|
||||
// se adiacente è nullo posso rimuovere tranquillamente il triangolo senza creare TJunctions
|
||||
if ( nTB == SVT_NULL) {
|
||||
RemoveTriangle( nTA) ;
|
||||
continue ;
|
||||
}
|
||||
// se adiacente è valido posso fare il flip per rendere valido nTA
|
||||
else if ( ! InvalidMap[nTB]) {
|
||||
FlipTriangles( nTA, nTB) ;
|
||||
InvalidMap[nTA] = false ;
|
||||
}
|
||||
// se adiacente è invalido creo una catena da risolvere non appena si trova un triangolo valido
|
||||
else {
|
||||
INTVECTOR vChain = {nTA} ;
|
||||
INTVECTOR vChainEdges = {nEdgeA} ;
|
||||
int nTCurr = nTB ;
|
||||
|
||||
while ( nTCurr != SVT_NULL && InvalidMap[nTCurr]) {
|
||||
|
||||
// calcolo il successivo
|
||||
int nTOther, nEdgeCurr ;
|
||||
FindAdjacentOnLongerEdge( nTCurr, nEdgeCurr, nTOther) ;
|
||||
|
||||
if ( nTOther == vChain.back()) {
|
||||
// se ho trovato un'adiacenza ambigua ( ovvero due triangoli invalidi adiacenti sui loro lati più lunghi)
|
||||
// flip dei due triangoli per modificare il lato più lungo e togliere adiacenza ambigua
|
||||
FlipTriangles( nTCurr, nTOther) ;
|
||||
if ( vChain.size() > 1) {
|
||||
vChain.pop_back() ;
|
||||
vChainEdges.pop_back() ;
|
||||
// individuo il nuovo adiacente all'ultimo triangolo della catena dopo aver fatto flip
|
||||
nTOther = m_vTria[vChain.back()].nIdAdjac[vChainEdges.back()] ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
vChain.emplace_back( nTCurr) ;
|
||||
vChainEdges.emplace_back( nEdgeCurr) ;
|
||||
}
|
||||
// aggiorno per iterazione successiva
|
||||
nTCurr = nTOther ;
|
||||
}
|
||||
|
||||
// se la catena termina su triangolo nullo, posso rimuovere tutti i triangoli della catena
|
||||
if ( nTCurr == SVT_NULL) {
|
||||
for ( int k = 0 ; k < int( vChain.size()) ; k++) {
|
||||
RemoveTriangle( vChain[k]) ;
|
||||
InvalidMap[vChain[k]] = false ;
|
||||
}
|
||||
}
|
||||
// se catena termina su un triangolo valido, applico il flip a cascata a partire dall'ultimo triangolo invalido trovato
|
||||
else {
|
||||
FlipTriangles( vChain.back(), nTCurr) ;
|
||||
InvalidMap[vChain.back()] = false ;
|
||||
for ( int i = int( vChain.size()) - 2 ; i >= 0 ; i--) {
|
||||
int nTA = vChain[i] ;
|
||||
if ( ! InvalidMap[nTA])
|
||||
continue ;
|
||||
// eseguo il flip con il triangolo adiacente sul suo lato più lungo
|
||||
int nTOther = m_vTria[nTA].nIdAdjac[vChainEdges[i]] ;
|
||||
FlipTriangles( nTA, nTOther) ;
|
||||
InvalidMap[nTA] = false ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
+30
-33
@@ -1385,6 +1385,7 @@ RemoveFistInvalidTrg( PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
// I triangoli cap se eliminati danno origine a T-junctions, quindi devono essere gestiti opportunamente con dei flip.
|
||||
// I triangoli needle se eliminati non sono problematici, ma i loro vertici coincidenti vanno gestiti opportunamente nel
|
||||
// calcolo delle adiacenze dei triangoli cap.
|
||||
// TO DO da capire e gestire casi in cui flip lascia triangoli invalidi
|
||||
|
||||
int nTria = int( vTr.size()) / 3 ;
|
||||
INTVECTOR vCapTria ;
|
||||
@@ -1482,46 +1483,40 @@ RemoveFistInvalidTrg( PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
INTVECTOR vChain, vChainEdges ;
|
||||
vChain.emplace_back( nTA) ;
|
||||
vChainEdges.emplace_back( nEA) ;
|
||||
|
||||
while ( nTB != -1 && ! vbIsValidTria[nTB]) {
|
||||
// aggiungo alla catena
|
||||
vChain.emplace_back( nTB) ;
|
||||
int nTCurr = nTB ;
|
||||
int nEOther ;
|
||||
while ( nTCurr != -1 && ! vbIsValidTria[nTCurr]) {
|
||||
|
||||
// calcolo il successivo
|
||||
nTA = nTB ;
|
||||
FindAdjacentOnLongerEdge( vPt, vTr, nTA, nEA, nTB, nEB) ;
|
||||
vChainEdges.emplace_back( nEA) ;
|
||||
int nTOther, nECurr ;
|
||||
FindAdjacentOnLongerEdge( vPt, vTr, nTCurr, nECurr, nTOther, nEOther) ;
|
||||
|
||||
// verifico di non aver trovato un'adiacenza ambigua ( ovvero due triangoli invalidi adiacenti sui loro lati più lunghi)
|
||||
// e quindi di non essere entrato in un loop
|
||||
if ( nTB == vChain[vChain.size()-2]) {
|
||||
if ( nTOther == vChain.back()) {
|
||||
// se ho trovato un'adiacenza ambigua ( ovvero due triangoli invalidi adiacenti sui loro lati più lunghi)
|
||||
// flip dei due triangoli per modificare il lato più lungo e togliere adiacenza ambigua
|
||||
FlipTrg( vTr, nTA, nTB, nEA, nEB) ;
|
||||
// aggiorno per iterazione successiva
|
||||
if ( vChain.size() == 2) {
|
||||
FlipTrg( vTr, nTCurr, nTOther, nECurr, nEOther) ;
|
||||
if ( vChain.size() > 1) {
|
||||
vChain.pop_back() ;
|
||||
vChainEdges.pop_back() ;
|
||||
FindAdjacentOnLongerEdge( vPt, vTr, vChain.back(), nEA, nTB, nEB) ;
|
||||
vChainEdges[0] = nEA ;
|
||||
// individuo il nuovo adiacente all'ultimo triangolo della catena tra i due appena flippati
|
||||
TestAdjacentOnEdge( vTr, vChain.back(), vChainEdges.back(), nTCurr, nTOther, nTB, nEB) ;
|
||||
nTOther = nTB ;
|
||||
}
|
||||
else {
|
||||
// elimino gli ultimi due triangoli che sono appena stati flippati e ricalcolo adiacenza del triangolo
|
||||
// precedente
|
||||
vChain.pop_back() ;
|
||||
vChain.pop_back() ;
|
||||
vChainEdges.pop_back() ;
|
||||
vChainEdges.pop_back() ;
|
||||
int nTTest1 = nTA ;
|
||||
int nTTest2 = nTB ;
|
||||
TestAdjacentOnEdge( vTr, vChain.back(), vChainEdges.back(), nTTest1, nTTest2, nTB, nEB) ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
vChain.emplace_back( nTCurr) ;
|
||||
vChainEdges.emplace_back( nECurr) ;
|
||||
}
|
||||
// aggiorno per iterazione successiva
|
||||
nTCurr = nTOther ;
|
||||
}
|
||||
|
||||
// se la catena termina su triangolo nullo, annullo tutti i triangoli della catena
|
||||
if ( nTB == -1) {
|
||||
if ( nTCurr == -1) {
|
||||
bRemovedTrg = true ;
|
||||
for ( int k = 0 ; k < int( vChain.size()) ; k++) {
|
||||
if ( vbIsValidTria[vChain[k]])
|
||||
continue ;
|
||||
vTr[3*vChain[k]] = -1 ;
|
||||
vTr[3*vChain[k] + 1] = -1 ;
|
||||
vTr[3*vChain[k] + 2] = -1 ;
|
||||
@@ -1530,14 +1525,16 @@ RemoveFistInvalidTrg( PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
}
|
||||
// se catena termina su un triangolo valido, applico il flip a cascata a partire dall'ultimo triangolo invalido
|
||||
else {
|
||||
FlipTrg( vTr, vChain.back(), nTB, vChainEdges.back(), nEB) ;
|
||||
FlipTrg( vTr, vChain.back(), nTCurr, vChainEdges.back(), nEOther) ;
|
||||
vbIsValidTria[vChain.back()] = true ;
|
||||
int nTrgTest1 = vChain.back() ;
|
||||
int nTrgTest2 = nTB ;
|
||||
for ( int i = int( vChain.size()-2) ; i >= 0 ; i--) {
|
||||
int nTrgTest2 = nTCurr ;
|
||||
for ( int j = int( vChain.size()-2) ; j >= 0 ; j--) {
|
||||
// triangolo corrente
|
||||
int nTA = vChain[i] ;
|
||||
int nEA = vChainEdges[i] ;
|
||||
int nTA = vChain[j] ;
|
||||
if ( vbIsValidTria[nTA])
|
||||
continue ;
|
||||
int nEA = vChainEdges[j] ;
|
||||
// devo trovare il nuovo adiacente dopo il flip dei successivi nella catena
|
||||
TestAdjacentOnEdge( vTr, nTA, nEA, nTrgTest1, nTrgTest2, nTB, nEB) ;
|
||||
// flip per rendere valido il triangolo corrente
|
||||
@@ -1608,7 +1605,7 @@ MakeByFist( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
vPt.reserve( fist.c_vertex.num_vertices) ;
|
||||
for ( int i = 0 ; i < fist.c_vertex.num_vertices ; i ++)
|
||||
vPt.emplace_back( fist.c_vertex.vertices[i].x, fist.c_vertex.vertices[i].y, fist.c_vertex.vertices[i].z) ;
|
||||
|
||||
|
||||
// recupero i triangoli da fist
|
||||
vTr.reserve( 3 * fist.c_vertex.num_triangles) ;
|
||||
for ( int i = 0 ; i < fist.c_vertex.num_triangles ; i ++) {
|
||||
|
||||
Reference in New Issue
Block a user