Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| bd90fc2b59 | |||
| 5800093e53 | |||
| 65daddfced | |||
| 95915b16e5 | |||
| 46b91bb49d | |||
| 751ea085a6 | |||
| 15ed754512 |
+3
-3
@@ -119,12 +119,12 @@ IntersTriaTria( const Triangle3d& trTria1, const Triangle3d& trTria2, Point3d& p
|
||||
Point3d ptSt1, ptEn1 ;
|
||||
int nRes1 = IntersCoplanarLineTria( ptL, vtL, 100.0, trTria1, ptSt1, ptEn1, false) ;
|
||||
|
||||
// limito la liena di intersezione con il secondo triangolo
|
||||
// limito la linea di intersezione con il secondo triangolo
|
||||
Point3d ptSt2, ptEn2 ;
|
||||
int nRes2 = IntersCoplanarLineTria( ptL, vtL, 100.0, trTria2, ptSt2, ptEn2, false) ;
|
||||
|
||||
// eseguo classificazione
|
||||
double dIntStU, dIntEnU;
|
||||
double dIntStU, dIntEnU ;
|
||||
int nIntType = FindTriaTriaIntersType( trTria1, trTria2, ptL, vtL,
|
||||
( ptSt1 - ptL) * vtL, ( ptEn1 - ptL) * vtL,
|
||||
( ptSt2 - ptL) * vtL, ( ptEn2 - ptL) * vtL,
|
||||
@@ -234,7 +234,7 @@ int
|
||||
FindTriaTriaIntersType( const Triangle3d& trTria1, const Triangle3d& trTria2, const Point3d& ptLineSt, const Vector3d& vtLineDir,
|
||||
double dStU1, double dEnU1, double dStU2, double dEnU2, int nRes1, int nRes2, double& dIntStU, double& dIntEnU)
|
||||
{
|
||||
// Controllo su validit� input
|
||||
// Controllo su validità input
|
||||
if ( ! ( trTria1.IsValid() && trTria2.IsValid() && vtLineDir.IsNormalized()))
|
||||
return ITTT_NO ;
|
||||
// Casi
|
||||
|
||||
+114
-37
@@ -26,6 +26,7 @@
|
||||
#include <algorithm>
|
||||
#include <thread>
|
||||
#include <future>
|
||||
#include <EgtDev/Include/EGkIntersCurves.h>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
@@ -800,56 +801,132 @@ bool
|
||||
CalcRegionPolyLines( const CICURVEPVECTOR& vpCurve, double dLinTol,
|
||||
POLYLINEVECTOR& vPL, Vector3d& vtN)
|
||||
{
|
||||
// se non ho curve, non faccio nulla
|
||||
if ( int( vpCurve.size()) == 0)
|
||||
return true ;
|
||||
|
||||
// calcolo le polilinee che approssimano le curve
|
||||
POLYLINEVECTOR vPLtmp ;
|
||||
vPLtmp.resize( vpCurve.size()) ;
|
||||
vPL.resize( vpCurve.size()) ;
|
||||
for ( int i = 0 ; i < int( vpCurve.size()) ; ++ i) {
|
||||
if ( ! vpCurve[i]->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPLtmp[i]))
|
||||
if ( ! vpCurve[i]->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPL[i]))
|
||||
return false ;
|
||||
}
|
||||
// ne calcolo l'area e genero un ordine in senso decrescente
|
||||
typedef pair<int,double> INDAREA ; // coppia indice, area
|
||||
typedef vector<INDAREA> INDAREAVECTOR ; // vettore di coppie indice, area
|
||||
INDAREAVECTOR vArea ;
|
||||
vArea.reserve( vPLtmp.size()) ;
|
||||
Vector3d vtN0 ;
|
||||
for ( int i = 0 ; i < int( vPLtmp.size()) ; ++ i) {
|
||||
// verifico chiusura, calcolo piano medio e area
|
||||
|
||||
// ricavo versore normale
|
||||
Plane3d plPlane ; double dArea ;
|
||||
if ( ! vPL[0].IsClosedAndFlat( plPlane, dArea, 50 * EPS_SMALL))
|
||||
return false ;
|
||||
vtN = plPlane.GetVersN() ;
|
||||
|
||||
typedef std::pair<int,double> INDAREA ;
|
||||
std::vector<INDAREA> m_vArea ;
|
||||
// calcolo piano medio e area delle curve
|
||||
m_vArea.reserve( vPL.size()) ;
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
|
||||
// calcolo piano medio e area
|
||||
Plane3d plPlane ;
|
||||
double dArea ;
|
||||
if ( ! vPLtmp[i].IsClosedAndFlat( plPlane, dArea, 50 * EPS_SMALL))
|
||||
if ( ! vPL[i].IsClosedAndFlat( plPlane, dArea))
|
||||
return false ;
|
||||
// imposto la normale del primo contorno come riferimento
|
||||
if ( i == 0)
|
||||
vtN0 = plPlane.GetVersN() ;
|
||||
// verifico che le normali siano molto vicine
|
||||
if ( ! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), vtN0))
|
||||
if ( ! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), vtN))
|
||||
return false ;
|
||||
// assegno il segno all'area secondo il verso della normale
|
||||
if ( ( plPlane.GetVersN() * vtN0) > 0)
|
||||
vArea.emplace_back( i, dArea) ;
|
||||
if ( ( plPlane.GetVersN() * vtN) > 0)
|
||||
m_vArea.emplace_back( i, dArea) ;
|
||||
else
|
||||
vArea.emplace_back( i, - dArea) ;
|
||||
m_vArea.emplace_back( i, - dArea) ;
|
||||
}
|
||||
sort( vArea.begin(), vArea.end(),
|
||||
// ordino in senso decrescente sull'area
|
||||
sort( m_vArea.begin(), m_vArea.end(),
|
||||
[]( const INDAREA& a, const INDAREA& b) { return ( abs( a.second) > abs( b.second)) ; }) ;
|
||||
// sposto le polilinee nel vettore da restituire secondo l'ordine
|
||||
vPL.clear() ;
|
||||
vPL.resize( vPLtmp.size()) ;
|
||||
bool bCCW = true ;
|
||||
for ( int i = 0 ; i < int( vPLtmp.size()) ; ++ i) {
|
||||
// scambio
|
||||
swap( vPL[i], vPLtmp[vArea[i].first]) ;
|
||||
// verifico senso di rotazione del contorno esterno
|
||||
if ( i == 0)
|
||||
bCCW = ( vArea[i].second > 0) ;
|
||||
// aggiusto gli altri contorni
|
||||
else {
|
||||
if ( ( bCCW && vArea[i].second > 0) || ( ! bCCW && vArea[i].second < 0))
|
||||
vPL[i].Invert() ;
|
||||
}
|
||||
|
||||
// dalle PolyLine passo alle curve nel piano XY ( prendo la prima come riferimento, trascuro le Z delle successive)
|
||||
Frame3d frRef ; frRef.Set( ORIG, vtN) ;
|
||||
if ( ! frRef.IsValid())
|
||||
return false ;
|
||||
ICRVCOMPOPOVECTOR vCrvCompo( int( vPL.size())) ;
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
|
||||
vCrvCompo[i].Set( CreateCurveComposite()) ;
|
||||
vCrvCompo[i]->FromPolyLine( vPL[i]) ;
|
||||
vCrvCompo[i]->ToLoc( frRef) ;
|
||||
}
|
||||
// restituisco la normale positiva alla regione
|
||||
vtN = ( bCCW ? vtN0 : - vtN0) ;
|
||||
|
||||
// creo una matrice di interi ; ogni riga corrisponde ad un chunk, dove in posizione 0 c'è il loop esterno e nelle
|
||||
// successive i loop interni
|
||||
INTMATRIX vnPLIndMat ;
|
||||
|
||||
// vettore di indici per ordinare le PolyLine
|
||||
INTVECTOR vPL_IndOrder ; vPL_IndOrder.resize( int( vPL.size())) ;
|
||||
for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i)
|
||||
vPL_IndOrder[i] = m_vArea[i].first ;
|
||||
|
||||
// aggiungo le diverse curve
|
||||
bool bFirstCrv ;
|
||||
Plane3d plExtLoop ;
|
||||
double dAreaExtLoop = 0. ;
|
||||
do {
|
||||
bFirstCrv = true ;
|
||||
for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i) {
|
||||
// recupero indice di percorso e verifico sia valido
|
||||
int j = m_vArea[i].first ;
|
||||
if ( j < 0)
|
||||
continue ;
|
||||
// lo inserisco come esterno...
|
||||
if ( bFirstCrv) {
|
||||
vnPLIndMat.push_back({ j}) ;
|
||||
m_vArea[i].first = -1 ;
|
||||
dAreaExtLoop = m_vArea[i].second ;
|
||||
// inverto se necessario
|
||||
if ( m_vArea[i].second < EPS_SMALL) {
|
||||
vPL[j].Invert() ;
|
||||
vCrvCompo[j]->Invert() ;
|
||||
dAreaExtLoop *= -1 ;
|
||||
}
|
||||
bFirstCrv = false ;
|
||||
}
|
||||
// ... altrimenti verifico se il loop è interno o no
|
||||
else {
|
||||
// il loop è interno se è sia interno al loop esterno della riga di vnPLIndMat e allo stesso tempo
|
||||
// esterno a tutti i loop già inseriti nella riga attuale.
|
||||
// verifica rispetto loop esterno
|
||||
IntersCurveCurve ccInt( *vCrvCompo[vnPLIndMat.back().front()], *vCrvCompo[j]) ;
|
||||
CRVCVECTOR ccClass ;
|
||||
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
|
||||
! ccInt.GetCurveClassification( 1, EPS_SMALL, ccClass) ||
|
||||
ccClass.empty() || ccClass[0].nClass != CRVC_IN)
|
||||
continue ;
|
||||
// verifica rispetto ai loop interni
|
||||
bool bOk = true ;
|
||||
for ( int k = 1 ; k < int( vnPLIndMat.back().size()) ; ++ k) {
|
||||
IntersCurveCurve ccInt2( *vCrvCompo[vnPLIndMat.back()[k]], *vCrvCompo[j]) ;
|
||||
CRVCVECTOR ccClass2 ;
|
||||
if ( ccInt2.GetCrossOrOverlapIntersCount() > 0 ||
|
||||
! ccInt2.GetCurveClassification( 1, EPS_SMALL, ccClass2) ||
|
||||
ccClass2.empty() || ccClass2[0].nClass != CRVC_IN) {
|
||||
bOk = false ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
if ( bOk) {
|
||||
// inserisco nella matrice
|
||||
vnPLIndMat.back().push_back( j) ;
|
||||
m_vArea[i].first = -1 ;
|
||||
// inverto se necessario
|
||||
if ( m_vArea[i].second * dAreaExtLoop > 0.) {
|
||||
vPL[j].Invert() ;
|
||||
vCrvCompo[j]->Invert() ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while ( ! bFirstCrv) ;
|
||||
|
||||
// ordino le PolyLine per area
|
||||
POLYLINEVECTOR vPL_tmp ;
|
||||
for ( int i = 0 ; i < int( vPL_IndOrder.size()) ; ++ i)
|
||||
vPL_tmp.push_back( vPL[ vPL_IndOrder[i]]) ;
|
||||
swap( vPL, vPL_tmp) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
+2
-2
@@ -31,7 +31,7 @@
|
||||
#include "/EgtDev/Include/EGkSfrCreate.h"
|
||||
#include "/EgtDev/Include/EgtPointerOwner.h"
|
||||
#include <new>
|
||||
#include <set>
|
||||
#include <set>
|
||||
|
||||
using namespace std ;
|
||||
|
||||
@@ -1960,7 +1960,7 @@ SurfTriMesh::CreateByRegion( const POLYLINEVECTOR& vPL)
|
||||
PNTVECTOR vPnt ;
|
||||
INTVECTOR vTria ;
|
||||
Triangulate Tri ;
|
||||
if ( ! Tri.Make( vPL, vPnt, vTria))
|
||||
if ( ! Tri.MakeAdvanced( vPL, vPnt, vTria))
|
||||
return false ;
|
||||
|
||||
// inizializzo la superficie
|
||||
|
||||
+196
-126
@@ -35,6 +35,7 @@
|
||||
#include "/EgtDev/Include/EGkPolygon3d.h"
|
||||
#include "/EgtDev/Include/EgtPerfCounter.h"
|
||||
#include "/EgtDev/Include/EGnStringUtils.h"
|
||||
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
@@ -52,9 +53,10 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA
|
||||
if ( vnDegVec[nC] > 0)
|
||||
++ nExistNotDeg ;
|
||||
}
|
||||
|
||||
// Divido il loop di partenza in sotto-loop
|
||||
int nIterationCount = 0 ;
|
||||
while ( cvOpenChain.size() > 0) {
|
||||
while ( cvOpenChain.size() > 0) { // per ogni catena aperta...
|
||||
bool bLoopSplitted = false ;
|
||||
int nLastOpenLoopN = int( cvOpenChain.size()) - 1 ;
|
||||
if ( vnDegVec[nLastOpenLoopN] == 1) {
|
||||
@@ -63,13 +65,24 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA
|
||||
int nLastOpenLoopPoint = max( int( cvOpenChain[nLastOpenLoopN].size()) - 1, 0) ;
|
||||
Point3d ptOpenLoopStP = cvOpenChain[nLastOpenLoopN][0].ptSt ;
|
||||
Point3d ptOpenLoopEnP = cvOpenChain[nLastOpenLoopN][nLastOpenLoopPoint].ptEn ;
|
||||
// costruisco il primo e il secondo loop che si generano
|
||||
// NB. il loop esterno è chiuso, mentre la catena aperta
|
||||
// è la successione dei tratti lineari dovuti ai triangoli dell'altra superficie
|
||||
PNTVECTOR Loop1, Loop2 ;
|
||||
// cambio il punto iniziale del loop di bordo se non coincide già con ptStart della catena aperta
|
||||
bool bChangedStart = ChangeStart( ptOpenLoopStP, cvBoundClosedLoopVec[nLoop]) ;
|
||||
// splitto
|
||||
bool bSplitted = SplitAtPoint( ptOpenLoopEnP, cvBoundClosedLoopVec[nLoop], Loop1, Loop2) ;
|
||||
if ( ! ( bChangedStart && bSplitted) ||
|
||||
( nLastOpenLoopPoint == 0 && ( Loop1.size() == 2 || Loop2.size() == 2)))
|
||||
continue ;
|
||||
continue ; // la catena aperta non è interna al loop chiuso attuale
|
||||
|
||||
// il loop 1 segue sempre la direzione della catena, il loop 2 ha dentro la catena invertita
|
||||
// Ho sempre che il loop 1 è sempre interno ( la direzione della catena è determinata
|
||||
// dalla normale dei triangoli che la formano; avendo chimatao la chian senza ammettere inversioni, sono
|
||||
// curve tutte concordi ) e il loop 2 che è esterno
|
||||
bLoopSplitted = true ;
|
||||
// ricostrusico i due loop mediante concatenazione
|
||||
Chain cvCounterChain ;
|
||||
for ( int nPt = int( cvOpenChain[nLastOpenLoopN].size()) - 1 ; nPt >= 0 ; -- nPt) {
|
||||
IntSegment CurSeg ;
|
||||
@@ -181,7 +194,7 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA
|
||||
// elimino i punti superflui prima
|
||||
for ( int i = 0 ; i < nCvFirst ; ++ i)
|
||||
cvBoundClosedLoopVec[nLoop].erase( cvBoundClosedLoopVec[nLoop].begin()) ;
|
||||
// verifico se questo punto � dalla parte valida o no
|
||||
// verifico se questo punto è dalla parte valida o no
|
||||
bool bC12 = ( ( ptM12 - ptProva) * vtVecProva < 0) ;
|
||||
vbInOut[nLoop] = bC12 ;
|
||||
}
|
||||
@@ -192,7 +205,7 @@ SurfTriMesh::DecomposeLoop( CHAINVECTOR& cvOpenChain, INTVECTOR& vnDegVec, PNTMA
|
||||
// elimino i punti superflui intermedi
|
||||
for ( int i = nCvFirst + 2 ; i < nCvSecond ; ++ i)
|
||||
cvBoundClosedLoopVec[nLoop].erase( cvBoundClosedLoopVec[nLoop].begin() + nCvFirst + 2) ;
|
||||
// verifico se questo punto � dalla parte valida o no
|
||||
// verifico se questo punto è dalla parte valida o no
|
||||
bool bC21 = ( ( ptM21 - ptProva) * vtVecProva < 0) ;
|
||||
vbInOut[nLoop] = bC21 ;
|
||||
}
|
||||
@@ -234,9 +247,13 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
// La superficie deve essere valida
|
||||
if ( ! Surf.IsValid())
|
||||
return false ;
|
||||
// Ritriangolarizzo i triangoli
|
||||
|
||||
// itero sulla unorderd_map
|
||||
for ( auto it = LoopLines.begin() ; it != LoopLines.end() ; ++ it) {
|
||||
|
||||
// itero sulle catene ( secondo parametro della mappa)
|
||||
for ( int nS1 = 0 ; nS1 < int( it->second.size()) - 1 ; ++ nS1) {
|
||||
// tolgo i tratti degeneri ad un punto
|
||||
for ( int nS2 = nS1 + 1 ; nS2 < int( it->second.size()) ; ++ nS2) {
|
||||
if ( AreSamePointApprox( it->second[nS1].ptSt, it->second[nS2].ptEn) &&
|
||||
AreSamePointApprox( it->second[nS1].ptEn, it->second[nS2].ptSt) &&
|
||||
@@ -248,22 +265,21 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// se non resta nulla, allora passo alla mappa successiva
|
||||
if ( int( it->second.size()) == 0)
|
||||
continue ;
|
||||
|
||||
// Se il triangolo è stato sottoposto a ritriangolazione, le sue componenti sono classificabili come dentro-fuori.
|
||||
// Lo tolgo dall'insieme dei triangoli ambigui (intersezione edge-edge)
|
||||
else {
|
||||
auto itS = Ambiguos.find( it->first) ;
|
||||
if ( itS != Ambiguos.end()) {
|
||||
Ambiguos.erase( itS) ;
|
||||
}
|
||||
}
|
||||
auto itS = Ambiguos.find( it->first) ;
|
||||
if ( itS != Ambiguos.end())
|
||||
Ambiguos.erase( itS) ;
|
||||
|
||||
// Creo i loop
|
||||
// CREAZIONE DEI LOOP ---------------------------------------------
|
||||
// Chain
|
||||
ChainCurves LoopCreator ;
|
||||
LoopCreator.Init( false, 2 * EPS_SMALL, int( it->second.size()), 10 * BOOLEAN_SCALE) ;
|
||||
// Carico le curve per concatenarle
|
||||
// Recupero le curve ( gli estremi dei tratti lineari) per concatenarle
|
||||
for ( int nCv = 0 ; nCv < int( it->second.size()); ++ nCv) {
|
||||
Point3d ptSt = it->second[nCv].ptSt ;
|
||||
Point3d ptEn = it->second[nCv].ptEn ;
|
||||
@@ -277,15 +293,14 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
CHAINVECTOR vChain ;
|
||||
while ( LoopCreator.GetChainFromNear( ptNearStart, false, vIds)) {
|
||||
Chain chTemp ;
|
||||
for ( auto i : vIds) {
|
||||
// Aggiungo la linea alla curva composta.
|
||||
for ( auto i : vIds) // Aggiungo la linea alla curva composta
|
||||
chTemp.emplace_back( it->second[i - 1]) ;
|
||||
}
|
||||
|
||||
vChain.emplace_back( chTemp) ;
|
||||
}
|
||||
// Lavoro su loop e catene per regolarizzarle
|
||||
int nChainCnt = int( vChain.size()) ;
|
||||
// unisco eventuali catene estreme che sono parte di una stessa catena
|
||||
// Unisco eventuali catene estreme che sono parte di una stessa catena
|
||||
if ( nChainCnt > 1) {
|
||||
if ( AreSamePointApprox( vChain[0].front().ptSt, vChain[nChainCnt - 1].back().ptEn)) {
|
||||
vChain[0].insert( vChain[0].begin(), vChain[nChainCnt - 1].begin(), vChain[nChainCnt - 1].end()) ;
|
||||
@@ -298,7 +313,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
-- nChainCnt ;
|
||||
}
|
||||
}
|
||||
// semplifico catene formate da punti degeneri
|
||||
// Semplifico catene formate da punti degeneri
|
||||
for ( int nCh = 0 ; nCh < nChainCnt ; ++ nCh) {
|
||||
if ( vChain[nCh].size() == 2 && ( vChain[nCh][0].bDegenerate || vChain[nCh][1].bDegenerate)) {
|
||||
vChain[nCh][0].ptEn = vChain[nCh][1].ptEn ;
|
||||
@@ -377,6 +392,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Chiudo i loop costruiti a partire dalle catene
|
||||
for ( int nC = 0 ; nC < nChainCnt ; ++ nC) {
|
||||
int nChainLastSegPos = int( vChain[nC].size()) - 1 ;
|
||||
@@ -463,7 +479,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
Surf.m_vTria[nNewAloneTriaNum].nETempFlag[0] = 0 ;
|
||||
Surf.m_vTria[nNewAloneTriaNum].nETempFlag[1] = 0 ;
|
||||
Surf.m_vTria[nNewAloneTriaNum].nETempFlag[2] = 0 ;
|
||||
Surf.m_vTria[nNewAloneTriaNum].nTempPart = nDist[nAloneVert] ;
|
||||
Surf.m_vTria[nNewAloneTriaNum].nTempPart = nDist[nAloneVert] ;
|
||||
bModif = true ;
|
||||
}
|
||||
int nNewCoupleId1[3] = { Surf.AddVertex( ptIntSt), Surf.AddVertex( trTria.GetP( ( nAloneVert + 1) % 3)), Surf.AddVertex( trTria.GetP( ( nAloneVert + 2) % 3)) } ;
|
||||
@@ -472,7 +488,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
Surf.m_vTria[nNewCoupleTriaNum1].nETempFlag[0] = 0 ;
|
||||
Surf.m_vTria[nNewCoupleTriaNum1].nETempFlag[1] = 0 ;
|
||||
Surf.m_vTria[nNewCoupleTriaNum1].nETempFlag[2] = 0 ;
|
||||
Surf.m_vTria[nNewCoupleTriaNum1].nTempPart = - nDist[nAloneVert] ;
|
||||
Surf.m_vTria[nNewCoupleTriaNum1].nTempPart = - nDist[nAloneVert] ;
|
||||
bModif = true ;
|
||||
}
|
||||
int nNewCoupleId2[3] = { Surf.AddVertex( ptIntSt), Surf.AddVertex( trTria.GetP( ( nAloneVert + 2) % 3)), Surf.AddVertex( ptIntEn) } ;
|
||||
@@ -481,27 +497,32 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
Surf.m_vTria[nNewCoupleTriaNum2].nETempFlag[0] = 0 ;
|
||||
Surf.m_vTria[nNewCoupleTriaNum2].nETempFlag[1] = 0 ;
|
||||
Surf.m_vTria[nNewCoupleTriaNum2].nETempFlag[2] = 0 ;
|
||||
Surf.m_vTria[nNewCoupleTriaNum2].nTempPart = - nDist[nAloneVert] ;
|
||||
Surf.m_vTria[nNewCoupleTriaNum2].nTempPart = - nDist[nAloneVert] ;
|
||||
bModif = true ;
|
||||
}
|
||||
continue ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// -------------------------------------------------------------------------------------------
|
||||
|
||||
// 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.
|
||||
|
||||
// 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.
|
||||
PNTVECTOR cvFirstLoop ;
|
||||
cvFirstLoop.emplace_back( trTria.GetP( 0)) ;
|
||||
cvFirstLoop.emplace_back( trTria.GetP( 1)) ;
|
||||
cvFirstLoop.emplace_back( trTria.GetP( 2)) ;
|
||||
|
||||
PNTMATRIX cvBoundClosedLoopVec;
|
||||
// creo una matrice di punti ; ogni riga corrisponde ad una sequenza di punti che indentificano un loop
|
||||
PNTMATRIX cvBoundClosedLoopVec ;
|
||||
cvBoundClosedLoopVec.emplace_back( cvFirstLoop) ;
|
||||
|
||||
// vettore per indicare se il loop è interno/esterno all'altra superficie
|
||||
BOOLVECTOR vbInOut ;
|
||||
vbInOut.push_back( true) ;
|
||||
|
||||
// Divido il loop usando le catene
|
||||
if ( ! DecomposeLoop( cvOpenChain, vnDegVec, cvBoundClosedLoopVec, vbInOut)) {
|
||||
if ( cvBoundClosedLoopVec.size() == 1 && cvOpenChain.size() == 2) {
|
||||
@@ -556,7 +577,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
Surf.m_vTria[it->first].nTempPart = 0 ;
|
||||
continue ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// Rimuovo il triangolo corrente
|
||||
int nOldTriaCol = Surf.m_vTria[it->first].nTFlag ;
|
||||
Surf.RemoveTriangle( it->first) ;
|
||||
@@ -564,14 +585,14 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
POLYLINEVECTOR vplPolyVec ;
|
||||
vplPolyVec.resize( cvBoundClosedLoopVec.size()) ;
|
||||
for ( int nLoop = 0 ; nLoop < int( vplPolyVec.size()) ; ++ nLoop) {
|
||||
for ( int nLine = 0 ; nLine < int( cvBoundClosedLoopVec[nLoop].size()) ; ++ nLine) {
|
||||
for ( int nLine = 0 ; nLine < int( cvBoundClosedLoopVec[nLoop].size()) ; ++ nLine)
|
||||
vplPolyVec[nLoop].AddUPoint( 0., cvBoundClosedLoopVec[nLoop][nLine]) ;
|
||||
}
|
||||
|
||||
vplPolyVec[nLoop].AddUPoint( 0., cvBoundClosedLoopVec[nLoop][0]) ;
|
||||
|
||||
// Assegno ai loop trovati i rispettivi interni
|
||||
// Assumo che i loop interni a uno dei loop creati fino ad'ora siano tutti sullo stesso livello.
|
||||
// Il caso generale si risolve con una struttura ad albero in cui il nodi corrispondente a un
|
||||
// Il caso generale si risolve con una struttura ad albero in cui il nodi corrispondente a un
|
||||
// loop è figlio del nodo corrispondente al loop che lo contiene.
|
||||
INTVECTOR vInnerLoop ;
|
||||
for ( int nCLI = 0 ; nCLI < int( cvClosedChain.size()) ; ++ nCLI) {
|
||||
@@ -692,7 +713,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
break ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ( vInnerLoop.size() == 0 || bDouble) {
|
||||
// Eseguo triangolazione
|
||||
PNTVECTOR vPt ;
|
||||
@@ -710,7 +731,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
Surf.m_vTria[nNewTriaNum].nETempFlag[1] = 0 ;
|
||||
Surf.m_vTria[nNewTriaNum].nETempFlag[2] = 0 ;
|
||||
if ( vbInOut[nLoop])
|
||||
Surf.m_vTria[nNewTriaNum].nTempPart = 1 ;
|
||||
Surf.m_vTria[nNewTriaNum].nTempPart = 1 ;
|
||||
else
|
||||
Surf.m_vTria[nNewTriaNum].nTempPart = - 1 ;
|
||||
bModif = true ;
|
||||
@@ -719,33 +740,32 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
}
|
||||
}
|
||||
else {
|
||||
// se ho più loop, essi descrivono un poligono di n-lati
|
||||
POLYLINEVECTOR vPolygons ;
|
||||
vPolygons.emplace_back( vplPolyVec[nLoop]) ;
|
||||
for ( int nL = 0 ; nL < int( vInnerLoop.size()) ; ++ nL) {
|
||||
// per ognuno di essi, ricavo la PolyLine dai punti
|
||||
PolyLine CurLoop ;
|
||||
for ( int nV = 0 ; nV < int( cvClosedChain[vInnerLoop[nL]].size()) ; ++ nV) {
|
||||
for ( int nV = 0 ; nV < int( cvClosedChain[vInnerLoop[nL]].size()) ; ++ nV)
|
||||
CurLoop.AddUPoint( 0., cvClosedChain[vInnerLoop[nL]][nV].ptSt) ;
|
||||
}
|
||||
|
||||
CurLoop.AddUPoint( 0., cvClosedChain[vInnerLoop[nL]][0].ptSt) ;
|
||||
vPolygons.emplace_back( CurLoop) ;
|
||||
}
|
||||
|
||||
// poligono
|
||||
Polygon3d pgPol ;
|
||||
pgPol.FromPolyLine(vPolygons[1]) ;
|
||||
pgPol.FromPolyLine( vPolygons[1]) ;
|
||||
|
||||
// controllo direzioni delle normali
|
||||
bool bCodirectedNormals = trTria.GetN() * pgPol.GetVersN() > 0. ;
|
||||
if ( bCodirectedNormals) {
|
||||
for ( int nL = 1 ; nL < int( vPolygons.size()) ; ++ nL) {
|
||||
vPolygons[nL].Invert() ;
|
||||
}
|
||||
}
|
||||
|
||||
// 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 ;
|
||||
++ itEn ;
|
||||
for ( ; itSt != ExternLoopList.end() && itEn != ExternLoopList.end() ; ++ itSt, ++ itEn) {
|
||||
// Estremi del segmento corrente del loop esterno e scorrispondente vettore
|
||||
Point3d ptSt = itSt->first ;
|
||||
@@ -761,7 +781,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
Point3d ptInnPoint ;
|
||||
bool bIsFirst = true ;
|
||||
bool bContinue = vPolygons[nInnPoly].GetFirstPoint( ptInnPoint) ;
|
||||
while ( bContinue) {
|
||||
while ( bContinue) {
|
||||
DistPointLine DistCalculator( ptInnPoint, ptSt, ptEn) ;
|
||||
double dDist ;
|
||||
DistCalculator.GetDist( dDist) ;
|
||||
@@ -788,13 +808,14 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
// Aggiungo i punti al loop esterno
|
||||
for ( int nPi = 0 ; nPi < int( vPointWithOrder.size()) ; ++ nPi) {
|
||||
itSt = ExternLoopList.emplace( itEn, vPointWithOrder[nPi]) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PNTVECTOR vPt ;
|
||||
INTVECTOR vTr ;
|
||||
if ( Triangulate().Make( vPolygons, vPt, vTr)) {
|
||||
// Inserisco i nuovi triangoli
|
||||
// classifico i loop e ricavo la triangolazione di essi mediante classificazione
|
||||
if ( Triangulate().MakeAdvanced( vPolygons, 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] = { Surf.AddVertex( vPt[nNewTriaVertId[0]]),
|
||||
@@ -817,7 +838,7 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
// Divido i loop che si autointercettano
|
||||
int nInitialLoopNum = int( vPolygons.size()) ;
|
||||
for ( int nL = 1 ; nL < nInitialLoopNum ; ++ nL) {
|
||||
// Lista dei punti della PolyLine Loop corrente
|
||||
// Lista dei punti della PolyLine Loop corrente
|
||||
PNTULIST& LoopPointList = vPolygons[nL].GetUPointList() ;
|
||||
// Ciclo sui segmenti
|
||||
auto itSt2 = LoopPointList.begin() ;
|
||||
@@ -928,26 +949,24 @@ SurfTriMesh::RetriangulationForBooleanOperation( CHAINMAP& LoopLines, TRIA3DVECT
|
||||
}
|
||||
}
|
||||
}
|
||||
for ( int nL = 1 ; nL < int( vPolygons.size()) ; ++ nL) {
|
||||
vPolygons[nL].Invert() ;
|
||||
if ( Triangulate().Make( vPolygons[nL], 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] = { Surf.AddVertex( vPt[nNewTriaVertId[0]]),
|
||||
Surf.AddVertex( vPt[nNewTriaVertId[1]]),
|
||||
Surf.AddVertex( vPt[nNewTriaVertId[2]])} ;
|
||||
int nNewTriaNum = Surf.AddTriangle( nNewId, nOldTriaCol) ;
|
||||
if ( IsValidSvt( nNewTriaNum)) {
|
||||
Surf.m_vTria[nNewTriaNum].nETempFlag[0] = 0 ;
|
||||
Surf.m_vTria[nNewTriaNum].nETempFlag[1] = 0 ;
|
||||
Surf.m_vTria[nNewTriaNum].nETempFlag[2] = 0 ;
|
||||
if ( bCodirectedNormals)
|
||||
Surf.m_vTria[nNewTriaNum].nTempPart = 1 ;
|
||||
else
|
||||
Surf.m_vTria[nNewTriaNum].nTempPart = -1 ;
|
||||
bModif = true ;
|
||||
}
|
||||
vPolygons.erase( vPolygons.begin()) ;
|
||||
if ( Triangulate().MakeAdvanced( vPolygons, 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] = { Surf.AddVertex( vPt[nNewTriaVertId[0]]),
|
||||
Surf.AddVertex( vPt[nNewTriaVertId[1]]),
|
||||
Surf.AddVertex( vPt[nNewTriaVertId[2]])} ;
|
||||
int nNewTriaNum = Surf.AddTriangle( nNewId, nOldTriaCol) ;
|
||||
if ( IsValidSvt( nNewTriaNum)) {
|
||||
Surf.m_vTria[nNewTriaNum].nETempFlag[0] = 0 ;
|
||||
Surf.m_vTria[nNewTriaNum].nETempFlag[1] = 0 ;
|
||||
Surf.m_vTria[nNewTriaNum].nETempFlag[2] = 0 ;
|
||||
if ( bCodirectedNormals)
|
||||
Surf.m_vTria[nNewTriaNum].nTempPart = 1 ;
|
||||
else
|
||||
Surf.m_vTria[nNewTriaNum].nTempPart = -1 ;
|
||||
bModif = true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1088,18 +1107,23 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
{
|
||||
bool bModif = false ;
|
||||
SurfTriMesh& SurfB = Other ;
|
||||
|
||||
// Le superfici devono essere valide
|
||||
if ( m_nStatus != OK || ! SurfB.IsValid())
|
||||
return false ;
|
||||
|
||||
// Unordered map dei segmenti di intersezione
|
||||
CHAINMAP LineMapA ;
|
||||
CHAINMAP LineMapB ;
|
||||
|
||||
// Unordered map dei triangoli ambigui (intersezione edge-edge)
|
||||
TRIA3DVECTORMAP AmbiguosA ;
|
||||
TRIA3DVECTORMAP AmbiguosB ;
|
||||
|
||||
// Ciclo sui triangoli delle mesh
|
||||
int nTriaNumA = GetTriangleSize() ;
|
||||
int nTriaNumB = SurfB.GetTriangleSize() ;
|
||||
|
||||
// Setto il triangolo come né fuori né dentro
|
||||
for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) {
|
||||
m_vTria[nTA].nTempPart = 0 ;
|
||||
@@ -1113,55 +1137,58 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
SurfB.m_vTria[nTB].nETempFlag[1] = 0 ;
|
||||
SurfB.m_vTria[nTB].nETempFlag[2] = 0 ;
|
||||
}
|
||||
|
||||
// Resetto e ricalcolo la HashGrid della superficie B
|
||||
SurfB.ResetHashGrids3d() ;
|
||||
|
||||
// Scorro i triangoli della superficie A
|
||||
for ( int nTA = 0 ; nTA < nTriaNumA ; ++ 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) ;
|
||||
|
||||
// I 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
|
||||
Triangle3d trTriaB ;
|
||||
if ( ! SurfB.GetTriangle( vNearTria[nTB], trTriaB) || ! trTriaB.Validate( true))
|
||||
continue ;
|
||||
|
||||
// Interseco i triangoli
|
||||
Point3d ptSegSt, ptSegEn ;
|
||||
TRIA3DVECTOR vTria ;
|
||||
int nIntType = IntersTriaTria( trTriaA, trTriaB, ptSegSt, ptSegEn, vTria) ;
|
||||
if ( nIntType == ITTT_EDGE_EDGE_SEG ||
|
||||
nIntType == ITTT_EDGE_INT ||
|
||||
nIntType == ITTT_INT_EDGE ||
|
||||
nIntType == ITTT_INT_INT_SEG) {
|
||||
// Assegno i dati di intersezione
|
||||
|
||||
// se l'intersezione è identificabile con un segmento...
|
||||
if ( nIntType == ITTT_EDGE_EDGE_SEG || nIntType == ITTT_EDGE_INT ||
|
||||
nIntType == ITTT_INT_EDGE || nIntType == ITTT_INT_INT_SEG) {
|
||||
|
||||
// Assegno i dati di intersezione per la superficie A
|
||||
IntSegment CurInters ;
|
||||
if ( nIntType == ITTT_EDGE_EDGE_SEG || nIntType == ITTT_EDGE_INT ||
|
||||
nIntType == ITTT_INT_EDGE || nIntType == ITTT_INT_INT_SEG) {
|
||||
CurInters.ptSt = ptSegSt ;
|
||||
CurInters.ptEn = ptSegEn ;
|
||||
CurInters.bDegenerate = false ;
|
||||
}
|
||||
else {
|
||||
CurInters.ptSt = ptSegSt ;
|
||||
CurInters.ptEn = ptSegSt ;
|
||||
CurInters.bDegenerate = true ;
|
||||
}
|
||||
CurInters.vtOuter = trTriaB.GetN() ;
|
||||
CurInters.ptSt = ptSegSt ; // punto iniziale del segmento
|
||||
CurInters.ptEn = ptSegEn ; // punto finale del segmento
|
||||
CurInters.bDegenerate = false ; // segmento non degenere
|
||||
CurInters.vtOuter = trTriaB.GetN() ; // perpendicolare alla tangente ( oritentata )
|
||||
CurInters.vtOuter -= ( ( CurInters.vtOuter * trTriaA.GetN()) * trTriaA.GetN()) ;
|
||||
CurInters.vtOuter.Normalize() ;
|
||||
// Salvo intersezione per superficie A
|
||||
bool bIntOnEndgeA = false ;
|
||||
if ( nIntType != ITTT_EDGE_EDGE_SEG && nIntType != ITTT_EDGE_INT) {
|
||||
// controllo se tale segmento non è già contenuto
|
||||
auto itA = LineMapA.find( nTA) ;
|
||||
if ( itA != LineMapA.end()) {
|
||||
if ( itA != LineMapA.end())
|
||||
itA->second.emplace_back( CurInters) ;
|
||||
}
|
||||
else {
|
||||
Chain chTemp ;
|
||||
chTemp.emplace_back( CurInters) ;
|
||||
@@ -1171,6 +1198,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
else
|
||||
bIntOnEndgeA = true ;
|
||||
|
||||
// Inverto i dati del segmento per intersezione con superficie B
|
||||
swap( CurInters.ptSt, CurInters.ptEn) ;
|
||||
CurInters.vtOuter = trTriaA.GetN() ;
|
||||
CurInters.vtOuter -= ( ( CurInters.vtOuter * trTriaB.GetN()) * trTriaB.GetN()) ;
|
||||
@@ -1179,10 +1207,10 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
// Salvo intersezione per superficie B
|
||||
bool bIntOnEndgeB = false ;
|
||||
if ( nIntType != ITTT_EDGE_EDGE_SEG && nIntType != ITTT_INT_EDGE) {
|
||||
// controllo se tale segmento non è già contenuto
|
||||
auto itB = LineMapB.find( vNearTria[nTB]) ;
|
||||
if ( itB != LineMapB.end()) {
|
||||
if ( itB != LineMapB.end())
|
||||
itB->second.emplace_back( CurInters) ;
|
||||
}
|
||||
else {
|
||||
Chain chTemp ;
|
||||
chTemp.emplace_back( CurInters) ;
|
||||
@@ -1191,8 +1219,10 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
}
|
||||
else
|
||||
bIntOnEndgeB = true ;
|
||||
// Intersezione edge-interno
|
||||
|
||||
// caso di Intersezione edge-interno ( per superificie A con B)
|
||||
if ( bIntOnEndgeA && ! bIntOnEndgeB) {
|
||||
// calcolo la massima distanza e il tratto ad essa associato
|
||||
double dMaxDist = 0. ;
|
||||
int nSegMaxDist = - 1 ;
|
||||
for ( int nVA = 0 ; nVA < 3 ; ++ nVA) {
|
||||
@@ -1203,7 +1233,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
}
|
||||
}
|
||||
if ( nSegMaxDist >= 0) {
|
||||
// Cerco qual'è il segmento di contatto per dichiararlo come invalicabile
|
||||
// Cerco qual è il segmento di contatto per dichiararlo come invalicabile
|
||||
int nVA ;
|
||||
for ( nVA = 0 ; nVA < 3 ; ++ nVA) {
|
||||
if ( abs( ( trTriaA.GetP( nVA) - trTriaB.GetP( 0)) * trTriaB.GetN()) < EPS_SMALL &&
|
||||
@@ -1215,8 +1245,9 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
m_vTria[nTA].nETempFlag[nVA] = m_vTria[nTA].nTempPart ;
|
||||
}
|
||||
}
|
||||
// Intersezione interno-edge
|
||||
// caso di Intersezione interno-edge ( per superficie A con B)
|
||||
else if ( ! bIntOnEndgeA && bIntOnEndgeB) {
|
||||
// calcolo la massima distanza e il tratto ad essa associato
|
||||
double dMaxDist = 0. ;
|
||||
int nSegMaxDist = - 1 ;
|
||||
for ( int nVB = 0 ; nVB < 3 ; ++ nVB) {
|
||||
@@ -1227,7 +1258,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
}
|
||||
}
|
||||
if ( nSegMaxDist >= 0) {
|
||||
// Cerco qual'è il segmento di contatto per dichiararlo come invalicabile
|
||||
// Cerco qual è il segmento di contatto per dichiararlo come invalicabile
|
||||
int nVB ;
|
||||
for ( nVB = 0 ; nVB < 3 ; ++ nVB) {
|
||||
if ( abs( ( trTriaB.GetP( nVB) - trTriaA.GetP(0)) * trTriaA.GetN()) < EPS_SMALL &&
|
||||
@@ -1266,11 +1297,11 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Ritriangolarizzo i triangoli delle superfici
|
||||
RetriangulationForBooleanOperation( LineMapA, AmbiguosA, *this, bModif) ;
|
||||
RetriangulationForBooleanOperation( LineMapB, AmbiguosB, SurfB, bModif) ;
|
||||
|
||||
|
||||
// Se i triangoli delle superfici non si intersecano, una delle due è totalmente interna o esterna all'altra.
|
||||
// non mi basta fare un controllo sulle bbox perché non so come sono orientate le superfici e che potrebbero anche non essere chiuse
|
||||
bool bRetriangulated = true ;
|
||||
@@ -1309,7 +1340,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
if ( ( ptFirstV - trTriaB.GetP(0)) * trTriaB.GetN() < - EPS_SMALL) {
|
||||
if ( nInOutNum == 0)
|
||||
nInOutNum = 1 ;
|
||||
else if (nInOutNum == -1) {
|
||||
else if ( nInOutNum == -1) {
|
||||
bSame = false ;
|
||||
break ;
|
||||
}
|
||||
@@ -1317,7 +1348,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
else if ( ( ptFirstV - trTriaB.GetP(0)) * trTriaB.GetN() > EPS_SMALL) {
|
||||
if ( nInOutNum == 0)
|
||||
nInOutNum = -1 ;
|
||||
else if (nInOutNum == 1) {
|
||||
else if ( nInOutNum == 1) {
|
||||
bSame = false ;
|
||||
break ;
|
||||
}
|
||||
@@ -1325,23 +1356,23 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
}
|
||||
// se le informazioni date dalle normali dei triangoli non sono concordi valuto il triangolo più vicino
|
||||
// e ricalcolo l'informazione che mi dà la sua normale
|
||||
if ( ! bSame ) {
|
||||
if ( ! bSame) {
|
||||
Point3d ptBar_tot ;
|
||||
for (int nTriaNum : vnTriaNum) {
|
||||
SurfB.GetTriangle( nTriaNum, trTriaB) ;
|
||||
ptBar_tot += trTriaB.GetCentroid();
|
||||
}
|
||||
ptBar_tot /= (int)vnTriaNum.size() ;
|
||||
for (int nTriaNum : vnTriaNum) {
|
||||
ptBar_tot /= int( vnTriaNum.size()) ;
|
||||
for ( int nTriaNum : vnTriaNum) {
|
||||
SurfB.GetTriangle( nTriaNum, trTriaB) ;
|
||||
Point3d ptInters1, ptInters2 ;
|
||||
int nInters = IntersLineTria(ptFirstV, ptBar_tot, trTriaB, ptInters1, ptInters2, true) ;
|
||||
if (nInters == ILTT_NO)
|
||||
int nInters = IntersLineTria( ptFirstV, ptBar_tot, trTriaB, ptInters1, ptInters2, true) ;
|
||||
if ( nInters == ILTT_NO)
|
||||
continue ;
|
||||
else if ( nInters == ILTT_IN ) {
|
||||
if ( ( ptFirstV - trTriaB.GetP(0)) * trTriaB.GetN() < - EPS_SMALL)
|
||||
else if ( nInters == ILTT_IN) {
|
||||
if ( ( ptFirstV - trTriaB.GetP( 0)) * trTriaB.GetN() < - EPS_SMALL)
|
||||
nInOutNum = 1 ;
|
||||
else if ( ( ptFirstV - trTriaB.GetP(0)) * trTriaB.GetN() > EPS_SMALL)
|
||||
else if ( ( ptFirstV - trTriaB.GetP( 0)) * trTriaB.GetN() > EPS_SMALL)
|
||||
nInOutNum = -1 ;
|
||||
break ;
|
||||
}
|
||||
@@ -1355,9 +1386,10 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
++ nVertNum ;
|
||||
}
|
||||
}
|
||||
for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) {
|
||||
|
||||
for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA)
|
||||
m_vTria[nTA].nTempPart = nInOutNum ;
|
||||
}
|
||||
|
||||
nVertNum = 0 ;
|
||||
nCurVert = SurfB.GetFirstVertex( ptFirstV) ;
|
||||
nInOutNum = 0 ;
|
||||
@@ -1374,7 +1406,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
DistCalculator.GetDist( dDist) ;
|
||||
// potrei trovare più triangolo equidistanti, li salvo tutti
|
||||
if ( DistPointTriangle( ptFirstV, trTriaA).GetDist( dDist)) {
|
||||
if ( abs(dDist - dMinDist) < EPS_SMALL)
|
||||
if ( abs( dDist - dMinDist) < EPS_SMALL)
|
||||
vnTriaNum.push_back( nTA) ;
|
||||
else if ( dDist < dMinDist){
|
||||
vnTriaNum.clear() ;
|
||||
@@ -1392,7 +1424,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
if ( ( ptFirstV - trTriaA.GetP(0)) * trTriaA.GetN() < - EPS_SMALL) {
|
||||
if ( nInOutNum == 0)
|
||||
nInOutNum = 1 ;
|
||||
else if (nInOutNum == -1) {
|
||||
else if ( nInOutNum == -1) {
|
||||
bSame = false ;
|
||||
break ;
|
||||
}
|
||||
@@ -1400,7 +1432,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
else if ( ( ptFirstV - trTriaA.GetP(0)) * trTriaA.GetN() > EPS_SMALL) {
|
||||
if ( nInOutNum == 0)
|
||||
nInOutNum = -1 ;
|
||||
else if (nInOutNum == 1) {
|
||||
else if ( nInOutNum == 1) {
|
||||
bSame = false ;
|
||||
break ;
|
||||
}
|
||||
@@ -1408,23 +1440,23 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
}
|
||||
// se le informazioni date dalle normali dei triangoli non sono concordi valuto il triangolo più vicino
|
||||
// e ricalcolo l'informazione che mi dà la sua normale
|
||||
if ( ! bSame ) {
|
||||
if ( ! bSame) {
|
||||
Point3d ptBar_tot ;
|
||||
for (int nTriaNum : vnTriaNum) {
|
||||
for ( int nTriaNum : vnTriaNum) {
|
||||
GetTriangle( nTriaNum, trTriaA) ;
|
||||
ptBar_tot += trTriaA.GetCentroid();
|
||||
}
|
||||
ptBar_tot /= (int)vnTriaNum.size() ;
|
||||
for (int nTriaNum : vnTriaNum) {
|
||||
ptBar_tot /= int( vnTriaNum.size()) ;
|
||||
for ( int nTriaNum : vnTriaNum) {
|
||||
GetTriangle( nTriaNum, trTriaA) ;
|
||||
Point3d ptInters1, ptInters2 ;
|
||||
int nInters = IntersLineTria(ptFirstV, ptBar_tot, trTriaA, ptInters1, ptInters2, true) ;
|
||||
if (nInters == ILTT_NO)
|
||||
int nInters = IntersLineTria( ptFirstV, ptBar_tot, trTriaA, ptInters1, ptInters2, true) ;
|
||||
if ( nInters == ILTT_NO)
|
||||
continue ;
|
||||
else if ( nInters == ILTT_IN ) {
|
||||
if ( ( ptFirstV - trTriaA.GetP(0)) * trTriaA.GetN() < - EPS_SMALL)
|
||||
else if ( nInters == ILTT_IN) {
|
||||
if ( ( ptFirstV - trTriaA.GetP( 0)) * trTriaA.GetN() < - EPS_SMALL)
|
||||
nInOutNum = 1 ;
|
||||
else if ( ( ptFirstV - trTriaA.GetP(0)) * trTriaA.GetN() > EPS_SMALL)
|
||||
else if ( ( ptFirstV - trTriaA.GetP( 0)) * trTriaA.GetN() > EPS_SMALL)
|
||||
nInOutNum = -1 ;
|
||||
break ;
|
||||
}
|
||||
@@ -1438,9 +1470,8 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
++ nVertNum ;
|
||||
}
|
||||
}
|
||||
for ( int nTB = 0 ; nTB < nTriaNumB ; ++ nTB) {
|
||||
for ( int nTB = 0 ; nTB < nTriaNumB ; ++ nTB)
|
||||
SurfB.m_vTria[nTB].nTempPart = nInOutNum ;
|
||||
}
|
||||
}
|
||||
|
||||
// Se c'è stata una ritriangolazione di almeno un triangolo, NON siamo nel caso di tutto dentro o tutto fuori.
|
||||
@@ -1449,11 +1480,15 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
AmbiguosTriangleManager( AmbiguosA, *this) ;
|
||||
AmbiguosTriangleManager( AmbiguosB, SurfB) ;
|
||||
}
|
||||
|
||||
|
||||
bool bContinue = true ;
|
||||
// Se avvenuta modifica, aggiorno tutto
|
||||
if ( bModif)
|
||||
bContinue = ( AdjustVertices() && DoCompacting() && SurfB.AdjustVertices() && SurfB.DoCompacting()) ;
|
||||
|
||||
SaveGeoObj( this, "C:\\Users\\riccardo.elitropi\\Desktop\\SurfA.nge") ;
|
||||
SaveGeoObj( SurfB.Clone(), "C:\\Users\\riccardo.elitropi\\Desktop\\SurfB.nge") ;
|
||||
|
||||
// Triangoli sovrapposti
|
||||
if ( bContinue) {
|
||||
int nTriaNum2A = GetTriangleSize() ;
|
||||
@@ -1491,7 +1526,7 @@ SurfTriMesh::IntersectTriMeshTriangle( SurfTriMesh& Other)
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -1620,48 +1655,83 @@ SurfTriMesh::Intersect( const ISurfTriMesh& Other)
|
||||
return true ;
|
||||
}
|
||||
|
||||
// Surf A è la superficie attuale ( this), SurfB è l'altra
|
||||
SurfTriMesh SurfB ;
|
||||
SurfB.CopyFrom( &Other) ;
|
||||
|
||||
// scalo la superficie
|
||||
Frame3d frScalingRef ;
|
||||
frScalingRef.Set( m_vVert[0].ptP, X_AX, Y_AX, Z_AX) ;
|
||||
Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ;
|
||||
SurfB.Scale( frScalingRef, BOOLEAN_SCALE, BOOLEAN_SCALE, BOOLEAN_SCALE) ;
|
||||
|
||||
// ritriangolo le due superfici mediante ogni intersezione Triangolo-Triangolo
|
||||
IntersectTriMeshTriangle( SurfB) ;
|
||||
|
||||
// assegno un medesimo indice ai triangoli che non interferiscono con altri
|
||||
IdentifyParts() ;
|
||||
SurfB.IdentifyParts() ;
|
||||
|
||||
// rimozione dei triangoli di A con proprietà -1 e -2
|
||||
int nTriaNumA = GetTriangleSize() ;
|
||||
for ( int nTA = 0 ; nTA < nTriaNumA ; ++ nTA) {
|
||||
if ( m_vTria[nTA].nTempPart == - 1 || m_vTria[nTA].nTempPart == - 2)
|
||||
RemoveTriangle( nTA) ;
|
||||
}
|
||||
|
||||
// aggiunta dei triangoli di B con proprietà +1
|
||||
int nPrevMaxTFlag = m_nMaxTFlag ;
|
||||
int nTriaNumB = SurfB.GetTriangleSize() ;
|
||||
for ( int nTB = 0 ; nTB < nTriaNumB ; ++ nTB) {
|
||||
if ( SurfB.m_vTria[nTB].nTempPart == 1) {
|
||||
int nNewVert[3] ;
|
||||
for ( int nV = 0 ; nV < 3 ; ++ nV) {
|
||||
for ( int nV = 0 ; nV < 3 ; ++ nV)
|
||||
nNewVert[nV] = AddVertex( SurfB.m_vVert[SurfB.m_vTria[nTB].nIdVert[nV]].ptP) ;
|
||||
}
|
||||
|
||||
if ( nPrevMaxTFlag == m_nMaxTFlag)
|
||||
++ m_nMaxTFlag ;
|
||||
AddTriangle( nNewVert, m_nMaxTFlag) ;
|
||||
}
|
||||
}
|
||||
|
||||
// sistemazioni varie
|
||||
bool 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()) ;
|
||||
|
||||
// rimuovo tutte le parti esterne all'intersezione
|
||||
int nParts = GetPartCount() ;
|
||||
if ( nParts > 1) {
|
||||
for ( int i = 0 ; i < nParts ; ++ i) {
|
||||
// recupero i triangoli della stessa Part
|
||||
INTVECTOR vTriaPart ;
|
||||
for ( int j = 0 ; j < int( m_vTria.size()) ; ++ j)
|
||||
if ( m_vTria[j].nPart == i)
|
||||
vTriaPart.push_back( j) ;
|
||||
// controllo se il loro box interferisce con il box della superficie B
|
||||
bool bErasePart = true ;
|
||||
for ( int j = 0 ; j < int( vTriaPart.size()) && bErasePart ; ++ j) {
|
||||
// Se il triangolo A non è valido, continuo
|
||||
Triangle3d Tria ;
|
||||
if ( ! GetTriangle( j, Tria) || ! Tria.Validate( true))
|
||||
continue ;
|
||||
// Box del triangolo A
|
||||
BBox3d b3dTriaA ; Tria.GetLocalBBox( b3dTriaA) ;
|
||||
// Recupero i triangoli di B che interferiscono col box del triangolo di A
|
||||
INTVECTOR vNearTria ; SurfB.GetAllTriaOverlapBox( b3dTriaA, vNearTria) ;
|
||||
bErasePart = int( vNearTria.size() == 0) ;
|
||||
}
|
||||
if ( bErasePart)
|
||||
RemovePart( i) ;
|
||||
}
|
||||
}
|
||||
|
||||
// scalo alle dimensioni originali
|
||||
Scale( frScalingRef, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE, 1. / BOOLEAN_SCALE) ;
|
||||
|
||||
if ( ! SimplifyFacets())
|
||||
|
||||
@@ -531,7 +531,7 @@ SurfTriMesh::AddChainToChain( const Chain& ChainToAdd, PNTVECTOR& OrigChain)
|
||||
if ( AreSamePointApprox( OrigChain[nLastOrig], ChainToAdd[0].ptSt)) {
|
||||
for ( int nPt = 1 ; nPt <= nLastToAdd ; ++ nPt) {
|
||||
if ( nPt == nLastToAdd) {
|
||||
if ( ! AreSamePointApprox(OrigChain[0], ChainToAdd[nPt].ptSt))
|
||||
if ( ! AreSamePointApprox( OrigChain[0], ChainToAdd[nPt].ptSt))
|
||||
OrigChain.emplace_back( ChainToAdd[nPt].ptSt) ;
|
||||
}
|
||||
else if ( nPt == 1) {
|
||||
|
||||
+138
@@ -21,6 +21,8 @@
|
||||
#include "/EgtDev/Include/EGkPlane3d.h"
|
||||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
#include "CurveComposite.h"
|
||||
#include "IntersCrvCompoCrvCompo.h"
|
||||
#include <algorithm>
|
||||
|
||||
using namespace std ;
|
||||
@@ -218,6 +220,142 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
return true ;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------------------------
|
||||
bool
|
||||
Triangulate::MakeAdvanced( const POLYLINEVECTOR& vPLORIG, PNTVECTOR& vPt, INTVECTOR& vTr)
|
||||
{
|
||||
vPt.clear() ;
|
||||
vTr.clear() ;
|
||||
// se non ho PolyLine, allora non faccio nulla
|
||||
if ( int( vPLORIG.size()) == 0)
|
||||
return true ;
|
||||
|
||||
// copio il vettore di PolyLine
|
||||
POLYLINEVECTOR vPL ;
|
||||
for ( int i = 0 ; i < int( vPLORIG.size()) ; ++ i)
|
||||
vPL.push_back( vPLORIG[i]) ;
|
||||
|
||||
typedef std::pair<int,double> INDAREA ;
|
||||
std::vector<INDAREA> m_vArea ;
|
||||
// calcolo piano medio e area delle curve
|
||||
m_vArea.reserve( vPL.size()) ;
|
||||
Vector3d vtN0 ;
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
|
||||
// calcolo piano medio e area
|
||||
Plane3d plPlane ;
|
||||
double dArea ;
|
||||
if ( ! vPL[i].IsClosedAndFlat( plPlane, dArea))
|
||||
return false ;
|
||||
// imposto la normale del primo contorno come riferimento
|
||||
if ( i == 0)
|
||||
vtN0 = plPlane.GetVersN() ;
|
||||
// verifico che le normali siano molto vicine
|
||||
if ( ! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), vtN0))
|
||||
return false ;
|
||||
// assegno il segno all'area secondo il verso della normale
|
||||
if ( ( plPlane.GetVersN() * vtN0) > 0)
|
||||
m_vArea.emplace_back( i, dArea) ;
|
||||
else
|
||||
m_vArea.emplace_back( i, - dArea) ;
|
||||
}
|
||||
// ordino in senso decrescente sull'area
|
||||
sort( m_vArea.begin(), m_vArea.end(),
|
||||
[]( const INDAREA& a, const INDAREA& b) { return ( abs( a.second) > abs( b.second)) ; }) ;
|
||||
|
||||
// dalle PolyLine passo alle curve nel piano XY ( prendo la prima come riferimento, trascuro le Z delle successive)
|
||||
Frame3d frRef ; frRef.Set( ORIG, vtN0) ;
|
||||
if ( ! frRef.IsValid())
|
||||
return false ;
|
||||
ICRVCOMPOPOVECTOR vCrvCompo( int( vPL.size())) ;
|
||||
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
|
||||
vCrvCompo[i].Set( CreateCurveComposite()) ;
|
||||
vCrvCompo[i]->FromPolyLine( vPL[i]) ;
|
||||
vCrvCompo[i]->ToLoc( frRef) ;
|
||||
}
|
||||
|
||||
// creo una matrice di interi ; ogni riga corrisponde ad un chunk, dove in posizione 0 c'è il loop esterno e nelle
|
||||
// successive i loop interni
|
||||
INTMATRIX vnPLIndMat ;
|
||||
|
||||
// aggiungo le diverse curve
|
||||
bool bFirstCrv ;
|
||||
Plane3d plExtLoop ;
|
||||
double dAreaExtLoop = 0. ;
|
||||
do {
|
||||
bFirstCrv = true ;
|
||||
for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i) {
|
||||
// recupero indice di percorso e verifico sia valido
|
||||
int j = m_vArea[i].first ;
|
||||
if ( j < 0)
|
||||
continue ;
|
||||
// lo inserisco come esterno...
|
||||
if ( bFirstCrv) {
|
||||
vnPLIndMat.push_back({ j}) ;
|
||||
m_vArea[i].first = -1 ;
|
||||
dAreaExtLoop = m_vArea[i].second ;
|
||||
// inverto se necessario
|
||||
if ( m_vArea[i].second < EPS_SMALL) {
|
||||
vPL[j].Invert() ;
|
||||
vCrvCompo[j]->Invert() ;
|
||||
dAreaExtLoop *= -1 ;
|
||||
}
|
||||
bFirstCrv = false ;
|
||||
}
|
||||
// ... altrimenti verifico se il loop è interno o no
|
||||
else {
|
||||
// il loop è interno se è sia interno al loop esterno della riga di vnPLIndMat e allo stesso tempo
|
||||
// esterno a tutti i loop già inseriti nella riga attuale.
|
||||
// verifica rispetto loop esterno
|
||||
IntersCurveCurve ccInt( *vCrvCompo[vnPLIndMat.back().front()], *vCrvCompo[j]) ;
|
||||
CRVCVECTOR ccClass ;
|
||||
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
|
||||
! ccInt.GetCurveClassification( 1, EPS_SMALL, ccClass) ||
|
||||
ccClass.empty() || ccClass[0].nClass != CRVC_IN)
|
||||
continue ;
|
||||
// verifica rispetto ai loop interni
|
||||
bool bOk = true ;
|
||||
for ( int k = 1 ; k < int( vnPLIndMat.back().size()) ; ++ k) {
|
||||
IntersCurveCurve ccInt2( *vCrvCompo[vnPLIndMat.back()[k]], *vCrvCompo[j]) ;
|
||||
CRVCVECTOR ccClass2 ;
|
||||
if ( ccInt2.GetCrossOrOverlapIntersCount() > 0 ||
|
||||
! ccInt2.GetCurveClassification( 1, EPS_SMALL, ccClass2) ||
|
||||
ccClass2.empty() || ccClass2[0].nClass != CRVC_IN) {
|
||||
bOk = false ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
if ( bOk) {
|
||||
// inserisco nella matrice
|
||||
vnPLIndMat.back().push_back( j) ;
|
||||
m_vArea[i].first = -1 ;
|
||||
// inverto se necessario
|
||||
if ( m_vArea[i].second * dAreaExtLoop > 0.) {
|
||||
vPL[j].Invert() ;
|
||||
vCrvCompo[j]->Invert() ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} while ( ! bFirstCrv) ;
|
||||
|
||||
// chiamo la Triangolazione per ogni riga della matrice ( quindi su ogni "Chunk")
|
||||
for ( int i = 0 ; i < int( vnPLIndMat.size()) ; ++ i) {
|
||||
PNTVECTOR vPt_tmp ; INTVECTOR vTr_tmp ;
|
||||
POLYLINEVECTOR vPL_tmp ;
|
||||
for ( int j = 0 ; j < int( vnPLIndMat[i].size()) ; ++ j)
|
||||
vPL_tmp.push_back( vPL[vnPLIndMat[i][j]]) ;
|
||||
if ( ! Make( vPL_tmp, vPt_tmp, vTr_tmp))
|
||||
return false ;
|
||||
int nSize = int( vPt.size()) ;
|
||||
for ( int p = 0 ; p < int( vPt_tmp.size()) ; ++ p)
|
||||
vPt.push_back( vPt_tmp[p]) ;
|
||||
for ( int t = 0 ; t < int( vTr_tmp.size()) ; ++ t)
|
||||
vTr.push_back( nSize + vTr_tmp[t]) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Triangulate the CCW n-gon specified by the vertices vPt (Pt[n] != Pt[0])
|
||||
// Ear Clipping algorithm from mapbox
|
||||
|
||||
@@ -22,6 +22,7 @@ class Triangulate
|
||||
public :
|
||||
bool Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr) ;
|
||||
bool Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr) ;
|
||||
bool MakeAdvanced( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr) ;
|
||||
|
||||
private :
|
||||
bool MakeByEC_HPP( const PolyLine& PL, bool bCCW, PNTVECTOR& vPt, INTVECTOR& vTr) ;
|
||||
|
||||
Reference in New Issue
Block a user