This commit is contained in:
Daniele Bariletti
2025-03-05 12:21:56 +01:00
4 changed files with 456 additions and 18 deletions
+51 -2
View File
@@ -79,6 +79,53 @@ static double TOL_TRAPEZOID = 50 * EPS_SMALL ; // tolleranza per casi a trapezio
typedef vector<ICRVCOMPOPOVECTOR> VICRVCOMPOPOVECTOR ;
//---------------------------------------------------------------------------
// definizione varibaile di debug
#define ENABLE_DEBUG 0
#if ENABLE_DEBUG
#include "EgtDev/Include/EGkGeoObjSave.h"
#include "EgtDev/Include/EGkGeoPoint3d.h"
#include "EgtDev/Include/EGkGeoVector3d.h"
//----------------------------------------------------------------------------
// Debug Functions
//----------------------------------------------------------------------------
void
DrawObjs( const ISURFFRPOVECTOR& vSfr, bool bSfrUniform, bool bAlphaCoverage,
const ICRVCOMPOPOVECTOR& vCompo, bool bCompoUniform, string sName)
{
// definisco i vettori per geometrie e colori
vector<IGeoObj*> VT ;
vector<Color> VC ;
// disegno le superfici
for ( int nS = 0 ; nS < int( vSfr.size()) ; ++ nS) {
if ( vSfr[nS] == nullptr || ! vSfr[nS]->IsValid())
return ;
VT.emplace_back( static_cast<IGeoObj*>( vSfr[nS]->Clone())) ;
VC.emplace_back( bAlphaCoverage ? Color( 0., 64., 0., .5) : Color( 0., 255., 0., .5)) ;
for ( int nC = 0 ; nC < vSfr[nS]->GetChunkCount() ; ++ nC) {
for ( int nL = 0 ; nL < vSfr[nS]->GetLoopCount( nC) ; ++ nL) {
PtrOwner<ICurveComposite> pCrvCompo( ConvertCurveToComposite( vSfr[nS]->GetLoop( nC, nL))) ;
for ( int nU = 0 ; nU < pCrvCompo->GetCurveCount() ; ++ nU) {
int nProp0 ; pCrvCompo->GetCurveTempProp( nU, nProp0, 0) ;
VT.emplace_back( static_cast<IGeoObj*>( pCrvCompo->GetCurve( nU)->Clone())) ;
VC.emplace_back( bSfrUniform ? WHITE : ( nProp0 == 0 ? ( bAlphaCoverage ? AQUA : BLUE) : ( bAlphaCoverage ? ORANGE : RED))) ;
}
}
}
}
// disegno le curve
for ( int nC = 0 ; nC < int( vCompo.size()) ; ++ nC) {
if ( vCompo[nC] == nullptr || ! vCompo[nC]->IsValid())
continue ;
VT.emplace_back( static_cast<IGeoObj*>( vCompo[nC]->Clone())) ;
VC.emplace_back( Color( double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, double( rand()) / RAND_MAX, 1.)) ;
}
SaveGeoObj( VT, VC, sName) ;
return ;
}
#endif
//---------------------------------------------------------------------------
static double
@@ -7374,7 +7421,7 @@ AdjustCloseEsgesForConformalGuide( ICurveComposite* pCrvCompo, const PocketParam
if ( IsNull( pMyCompo))
return false ;
CRVCVECTOR ccClass ;
if ( pSfrLimit->GetCurveClassification( *vpCrvs[i], EPS_SMALL, ccClass)) {
if ( pSfrLimit->GetCurveClassification( *vpCrvs[i], 125 * EPS_SMALL, ccClass)) {
for ( int j = 0 ; j < int( ccClass.size()) ; ++ j) {
// recupero il tratto di curva
PtrOwner<ICurveComposite> pMyCurve( ConvertCurveToComposite( vpCrvs[i]->CopyParamRange( ccClass[j].dParS, ccClass[j].dParE))) ;
@@ -8395,6 +8442,7 @@ GetConformalOffsets( const ISurfFlatRegion* pSfrChunk, const ISurfFlatRegion* pS
for ( int j = 0 ; j < int( vCrvOffs[i].size()) ; ++ j)
ModifyCurveToSmoothed( vCrvOffs[i][j], PockParam, dSmoothPar, dSmoothPar, false) ;
}
return true ;
}
@@ -8572,7 +8620,7 @@ AddConformal( ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig,
bool
CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double dStep, double dAngle,
int nType, bool bSmooth, bool bInvert, bool bAvoidOpt, bool bAllowZigZagOneWayBorders,
const Point3d& ptEndPrec, const ISurfFlatRegion* pSfrLimit, bool bAllOffs, ICRVCOMPOPOVECTOR& vCrvCompoRes)
bool bCalcFeed, const Point3d& ptEndPrec, const ISurfFlatRegion* pSfrLimit, bool bAllOffs, ICRVCOMPOPOVECTOR& vCrvCompoRes)
{
// controllo dei parametri
if ( pSfr == nullptr || ! pSfr->IsValid() ||
@@ -8594,6 +8642,7 @@ CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double
myParams.dSideStep = dStep ;
myParams.bInvert = bInvert ;
myParams.bAvoidOpt = bAvoidOpt ;
myParams.bCalcFeed = bCalcFeed ;
myParams.bAllowZigZagOneWayBorders = bAllowZigZagOneWayBorders ;
myParams.bOptOffsets = ( ! bAllOffs) ;
if ( ptEndPrec.IsValid())
BIN
View File
Binary file not shown.
+404 -16
View File
@@ -22,20 +22,27 @@
#include "/EgtDev/Include/EGkPlane3d.h"
#include "/EgtDev/Include/EGkStringUtils3d.h"
#include "/EgtDev/Include/EgtNumUtils.h"
#include "CurveComposite.h"
#include "IntersCrvCompoCrvCompo.h"
#include "/EgtDev/Extern/fist/Include/api_fist.h"
#include <algorithm>
using namespace std ;
//----------------------------------------------------------------------------
enum EarStatus{ EAS_NULL = -1, EAS_NO = 0, EAS_OK = 1} ;
enum TrgType { TRG_STD = 0, TRG_CAP = 1, TRG_NEEDLE = 2} ;
//----------------------------------------------------------------------------
static bool ChangeStartPntVector( int nNewStart, PNTVECTOR& vPi) ;
static bool MakeByFist( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr) ;
static bool RemoveFistInvalidTrg( PNTVECTOR& vPt, INTVECTOR& vTr) ;
static int CalcTriangleType( const PNTVECTOR& vPt, const INTVECTOR& vTr, int nTrg) ;
static bool FindAdjacentOnLongerEdge( PNTVECTOR& vPt, INTVECTOR& vTr, int nTrgA, int&nEdgeA, int& nTrgB, int& nEdgeB) ;
static bool FlipTrg( INTVECTOR& vTr, int nTrgA, int nTrgB, int nEdgeA, int nEdgeB) ;
static bool TestAdjacentOnEdge( INTVECTOR& vTr, int nTrgA, int nEdgeA, int nTrgTest1, int nTrgTest2, int& nTrgB, int& nEdgeB) ;
//----------------------------------------------------------------------------
static bool FORCE_EARCUT_HPP = false ;
static bool FORCE_FIST = false ;
//----------------------------------------------------------------------------
// In : PolyLine
@@ -49,8 +56,13 @@ Triangulate::Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr)
vPt.clear() ;
vTr.clear() ;
// verifico che la polilinea contenga almeno 4 punti (primo e ultimo coincidenti)
if ( PL.GetPointNbr() < 4)
if ( PL.GetPointNbr() < 4 || ! PL.IsClosed())
return false ;
// se fist ( e geometria più complessa di un quadrilatero)
if ( FORCE_FIST && PL.GetPointNbr() > 5)
return MakeByFist( {PL}, vPt, vTr) ;
// verifico che la polilinea sia chiusa e piana e calcolo il piano medio del poligono
double dArea ;
Plane3d plPlane ;
@@ -117,6 +129,11 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
// se una sola polilinea mi riconduco al caso precedente
if ( vPL.size() == 1)
return Make( vPL[0], vPt, vTr) ;
// se fist
if ( FORCE_FIST)
return MakeByFist( vPL, vPt, vTr) ;
// verifico che la polilinea esterna sia chiusa e piana e calcolo il piano medio del poligono
double dArea ;
Plane3d plExtPlane ;
@@ -134,7 +151,7 @@ Triangulate::Make( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
if ( ! vPL[i].IsClosedAndFlat( plPlane, dArea2, 50 * EPS_SMALL) ||
! AreOppositeVectorApprox( plExtPlane.GetVersN(), plPlane.GetVersN()))
return false ;
}
}
// forzo esecuzione triangolazione con earcut.hpp
if ( FORCE_EARCUT_HPP) {
@@ -238,7 +255,7 @@ Triangulate::MakeAdvanced( const POLYLINEVECTOR& vPLORIG, PNTVECTOR& vPt, INTVEC
// se non ho PolyLine, allora non faccio nulla
if ( vPLORIG.empty())
return true ;
POLYLINEVECTOR vPL ;
Vector3d vtN ;
// se non sono stati passate le info per ordinare le polyline allora le ordino
@@ -259,7 +276,7 @@ Triangulate::MakeAdvanced( const POLYLINEVECTOR& vPLORIG, PNTVECTOR& vPt, INTVEC
vPL = vPLORIG ;
vnPLIndMat = vnPLIndMatPre ;
}
// 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 ;
@@ -274,7 +291,7 @@ Triangulate::MakeAdvanced( const POLYLINEVECTOR& vPLORIG, PNTVECTOR& vPt, INTVEC
for ( int t = 0 ; t < int( vTr_tmp.size()) ; ++ t)
vTr.push_back( nSize + vTr_tmp[t]) ;
}
return true ;
}
@@ -576,7 +593,7 @@ Triangulate::MakeByEC2( const PNTVECTOR& vPt, INTVECTOR& vTr, double& dMinMinAng
// Reset earity of diagonal endpoints
vEar[vPrev[i]] = EAS_NULL ;
vEar[vNext[i]] = EAS_NULL ;
// Delete vertex v[i] by redirecting next and previous links
// Delete vertex v[i] by redirecting next and previous links
// of neighboring verts past it. Decrement vertex count
vNext[vPrev[i]] = vNext[i] ;
vPrev[vNext[i]] = vPrev[i] ;
@@ -714,7 +731,7 @@ Triangulate::MakeByEC3( const PNTVECTOR& vPt, INTVECTOR& vTr, double& dMinMinAng
// Reset earity of diagonal endpoints
vEar[vPrev[i]] = EAS_NULL ;
vEar[vNext[i]] = EAS_NULL ;
// Delete vertex v[i] by redirecting next and previous links
// Delete vertex v[i] by redirecting next and previous links
// of neighboring verts past it. Decrement vertex count
vNext[vPrev[i]] = vNext[i] ;
vPrev[vNext[i]] = vPrev[i] ;
@@ -808,7 +825,7 @@ Triangulate::TestTriangle( const PNTVECTOR& vPt, const INTVECTOR& vPol,
}
}
else {
// The ear triangle is clockwise so v[i] is not an ear
// The ear triangle is clockwise so v[i] is not an ear
bIsEar = false ;
}
@@ -1153,14 +1170,14 @@ Triangulate::GetOuterPntToJoin( const PNTVECTOR& vPt, const Point3d& ptP, int& n
break ;
}
}
// non ho trovato alcunch, errore
// non ho trovato alcunchè, errore
if ( nI == - 1)
return false ;
// se ho trovato un punto esatto del contorno, non devo fare altri controlli
if ( AreSamePointApprox( ptInt, vPt[nI]))
return true ;
// devo ora verificare che il segmento che unisce i punti non intersechi altri lati del contorno esterno
// altrimenti tengo il punto con raggio pi vicino a X_AX o Y_AX o Z_AX secondo m_nPlane
// altrimenti tengo il punto con raggio più vicino a X_AX o Y_AX o Z_AX secondo m_nPlane
int nJ = nI ;
Point3d ptPa = ptP ;
Point3d ptPb = vPt[nI] ;
@@ -1176,7 +1193,7 @@ Triangulate::GetOuterPntToJoin( const PNTVECTOR& vPt, const Point3d& ptP, int& n
double dMinTan = INFINITO ;
double dMinSqDist = SQ_INFINITO ;
for ( int i = 0 ; i < nNumPt ; ++ i) {
// salto il punto gi trovato
// salto il punto già trovato
if ( i == nJ)
continue ;
// verifico se sta nel triangolo
@@ -1212,7 +1229,7 @@ Triangulate::GetOuterPntToJoin( const PNTVECTOR& vPt, const Point3d& ptP, int& n
bool
Triangulate::PointInSector( const Point3d& ptTest, const Point3d& ptPrev, const Point3d& ptCorn, const Point3d& ptNext)
{
// la parte valida del settore a sinistra dei segmenti ptPrev --> ptCorn --> ptNext
// la parte valida del settore è a sinistra dei segmenti ptPrev --> ptCorn --> ptNext
// se corner convesso
if ( TriangleIsCCW( ptPrev, ptCorn, ptNext, 0))
return ( TriangleIsCCW( ptPrev, ptCorn, ptTest) &&
@@ -1227,13 +1244,384 @@ Triangulate::PointInSector( const Point3d& ptTest, const Point3d& ptPrev, const
bool
ChangeStartPntVector( int nNewStart, PNTVECTOR& vPi)
{
// se il nuovo inizio coincide col vecchio, non devo fare alcunch
// se il nuovo inizio coincide col vecchio, non devo fare alcunchè
if ( nNewStart == 0)
return true ;
// se il nuovo indice oltre la dimensione del vettore, errore
// se il nuovo indice è oltre la dimensione del vettore, errore
if ( nNewStart >= int( vPi.size()))
return false ;
// ciclo di aggiustamento
rotate( vPi.begin(), vPi.begin() + nNewStart, vPi.end()) ;
return true ;
}
//----------------------------------------------------------------------------
// Funzioni per triangolare usando la libreria FIST
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
int
CalcTriangleType( const PNTVECTOR& vPt, const INTVECTOR& vTr, int nTrg)
{
Vector3d vtV1 = vPt[vTr[3*nTrg + 1]] - vPt[vTr[3*nTrg]] ;
Vector3d vtV2 = vPt[vTr[3*nTrg + 2]] - vPt[vTr[3*nTrg + 1]] ;
Vector3d vtN = vtV1 ^ vtV2 ;
double dSqN = vtN.SqLen() ;
double dSqLen1 = vtV1.SqLen() ;
double dSqLen2 = vtV2.SqLen() ;
double dSqLen3 = ( vtV1 + vtV2).SqLen() ;
// un triangolo è invalido ( needle o cap) se viene scartato dai controlli di AddTriangle
if ( dSqN < SQ_EPS_ZERO || dSqN < SQ_EPS_TRIA_H * max( {dSqLen1, dSqLen2, dSqLen3})) {
if ( dSqLen1 < SQ_EPS_ZERO || dSqLen2 < SQ_EPS_ZERO || dSqLen3 < SQ_EPS_ZERO)
return TRG_NEEDLE ;
else
return TRG_CAP ;
}
else
return TRG_STD ;
}
//----------------------------------------------------------------------------
bool
FlipTrg( INTVECTOR& vTr, int nTA, int nTB, int nEA, int nEB)
{
vTr[3*nTA + nEA] = vTr[3*nTB + ( nEB + 2) % 3] ;
vTr[3*nTB + nEB] = vTr[3*nTA + ( nEA + 2) % 3] ;
return true ;
}
//----------------------------------------------------------------------------
bool
TestAdjacentOnEdge( INTVECTOR& vTr, int nTA, int nEA, int nTTest1, int nTTest2, int& nTB, int& nEB)
{
// individuo quale triangolo tra nTTest1 e nTTest2 è quello adiacente a nTA lungo il lato nEA
nTB = -1 ;
nEB = -1 ;
// recupero i vertici di nEA
int nV1 = vTr[3*nTA + nEA] ;
int nV2 = vTr[3*nTA + ( nEA + 1) % 3] ;
// verifico se è TTest1 quello adiacente
if ( vTr[3*nTTest1] == nV2 && vTr[3*nTTest1+1] == nV1) {
nEB = 0 ;
nTB = nTTest1 ;
}
else if ( vTr[3*nTTest1+1] == nV2 && vTr[3*nTTest1+2] == nV1) {
nEB = 1 ;
nTB = nTTest1 ;
}
else if ( vTr[3*nTTest1] == nV1 && vTr[3*nTTest1+2] == nV2) {
nEB = 2 ;
nTB = nTTest1 ;
}
// verifico se è TTest2 quello adiacente
else if ( vTr[3*nTTest2] == nV2 && vTr[3*nTTest2+1] == nV1) {
nEB = 0 ;
nTB = nTTest2 ;
}
else if ( vTr[3*nTTest2+1] == nV2 && vTr[3*nTTest2+2] == nV1) {
nEB = 1 ;
nTB = nTTest2 ;
}
else if ( vTr[3*nTTest2] == nV1 && vTr[3*nTTest2+2] == nV2) {
nEB = 2 ;
nTB = nTTest2 ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
FindAdjacentOnLongerEdge( PNTVECTOR& vPt, INTVECTOR& vTr, int nTA, int& nEA, int& nTB, int& nEB)
{
// recupero il lato più lungo del triangolo nTA
nEA = -1 ;
double dMaxLen = -1 ;
for ( int j = 0 ; j < 3 ; j++) {
double dCurrLen = SqDist( vPt[vTr[3*nTA + j]], vPt[vTr[3*nTA + ( j+1)%3]]) ;
if ( dCurrLen > dMaxLen) {
dMaxLen = dCurrLen ;
nEA = j ;
}
}
// cerco il triangolo nTB adiacente a nTA lungo nEA
nTB = -1 ;
nEB = -1 ;
int nV1 = vTr[3*nTA + nEA] ;
int nV2 = vTr[3*nTA + ( nEA + 1) % 3] ;
int nTria = vTr.size() / 3 ;
for ( int j = 0 ; j < nTria ; j++) {
if ( j == nTA)
continue ;
if ( vTr[3*j] == nV2 && vTr[3*j+1] == nV1) {
nEB = 0 ;
nTB = j ;
break ;
}
else if ( vTr[3*j+1] == nV2 && vTr[3*j+2] == nV1) {
nEB = 1 ;
nTB = j ;
break ;
}
else if ( vTr[3*j] == nV1 && vTr[3*j+2] == nV2) {
nEB = 2 ;
nTB = j ;
break ;
}
}
return true ;
}
//----------------------------------------------------------------------------
bool
RemoveFistInvalidTrg( PNTVECTOR& vPt, INTVECTOR& vTr)
{
// scorro tutti i triangoli alla ricerca di triangoli validi per FIST ma invalidi per le nostre tolleranze.
// I triangoli invalidi possono essere di due tipologie: cap o needle.
// 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.
int nTria = int( vTr.size()) / 3 ;
INTVECTOR vCapTria ;
INTVECTOR vNeedleTria ;
BOOLVECTOR vbIsValidTria( nTria, true) ;
bool bRemovedTrg = false ;
for ( int i = 0 ; i < nTria ; i ++) {
int nTrgType = CalcTriangleType( vPt, vTr, i) ;
if ( nTrgType == TRG_CAP) {
vbIsValidTria[i] = false ;
vCapTria.emplace_back( i) ;
}
else if ( nTrgType == TRG_NEEDLE) {
vNeedleTria.emplace_back( i) ;
}
}
// se non ci sono triangoli cap non c'è bisogno di modifiche
if ( vCapTria.empty())
return true ;
// 1) elimino i triangoli di tipo needle gestendo i vertici coincidenti
if ( ! vNeedleTria.empty()) {
bRemovedTrg = true ;
for ( int i = 0 ; i < int( vNeedleTria.size()) ; i++) {
int nT = vNeedleTria[i] ;
if ( vTr[3*nT] != vTr[3*nT+1] && vTr[3*nT] != vTr[3*nT+2] && vTr[3*nT+1] != vTr[3*nT+2]) {
// individuo i vertici coincidenti
int nOldId = -1 ;
int nNewId = -1 ;
Vector3d vtV1 = vPt[vTr[3*nT+1]] - vPt[vTr[3*nT]] ;
if ( vtV1.SqLen() < SQ_EPS_ZERO) {
// vertici coincidenti 0 e 1
nOldId = vTr[3*nT] ;
nNewId = vTr[3*nT+1] ;
}
else {
Vector3d vtV2 = vPt[vTr[3*nT+2]] - vPt[vTr[3*nT+1]] ;
if ( vtV2.SqLen() < SQ_EPS_ZERO) {
// vertici coincidenti 1 e 2
nOldId = vTr[3*nT+1] ;
nNewId = vTr[3*nT+2] ;
}
else {
// vertici coincidenti 0 e 2
nOldId = vTr[3*nT] ;
nNewId = vTr[3*nT+2] ;
}
}
// aggiorno il vettore dei triangoli unificando i vertici coincidenti
for ( int k = 0 ; k < int( vTr.size()) ; k ++) {
if ( vTr[k] == nOldId)
vTr[k] = nNewId ;
}
}
// annullo il triangolo
vTr[3*nT] = -1 ;
vTr[3*nT+1] = -1 ;
vTr[3*nT+2] = -1 ;
}
}
// 2) sistemo i triangoli di tipo cap
for ( int i = 0 ; i < int( vCapTria.size()) ; i++) {
int nTA = vCapTria[i] ;
// verifico se il triangolo è già stato resto valido ( da una catena)
if ( vbIsValidTria[nTA])
continue ;
// trovo l'adiacenza sul suo lato più lungo
int nEA = -1 ;
int nEB = -1 ;
int nTB = -1 ;
FindAdjacentOnLongerEdge( vPt, vTr, nTA, nEA, nTB, nEB) ;
if ( nTB == -1) {
// se non ha un triangolo adiacente posso annullarlo
vTr[3*nTA] = -1 ;
vTr[3*nTA+1] = -1 ;
vTr[3*nTA+2] = -1 ;
vbIsValidTria[nTA] = true ;
bRemovedTrg = true ;
continue ;
}
else if ( vbIsValidTria[nTB]) {
// se è adiacente è valido, eseguo il flip
FlipTrg( vTr, nTA, nTB, nEA, nEB) ;
vbIsValidTria[nTA] = true ;
}
else {
// se adiacente è invalido, individuo una catena di triangoli invalidi da risolvere non appena si indentifica
// adiacenza con triangolo valido
INTVECTOR vChain, vChainEdges ;
vChain.emplace_back( nTA) ;
vChainEdges.emplace_back( nEA) ;
while ( nTB != -1 && ! vbIsValidTria[nTB]) {
// aggiungo alla catena
vChain.emplace_back( nTB) ;
// calcolo il successivo
nTA = nTB ;
FindAdjacentOnLongerEdge( vPt, vTr, nTA, nEA, nTB, nEB) ;
vChainEdges.emplace_back( nEA) ;
// 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]) {
// 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) {
vChain.pop_back() ;
vChainEdges.pop_back() ;
FindAdjacentOnLongerEdge( vPt, vTr, vChain.back(), nEA, nTB, nEB) ;
vChainEdges[0] = nEA ;
}
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) ;
}
}
}
// se la catena termina su triangolo nullo, annullo tutti i triangoli della catena
if ( nTB == -1) {
bRemovedTrg = true ;
for ( int k = 0 ; k < int( vChain.size()) ; k++) {
vTr[3*vChain[k]] = -1 ;
vTr[3*vChain[k] + 1] = -1 ;
vTr[3*vChain[k] + 2] = -1 ;
vbIsValidTria[vChain[k]] = true ;
}
}
// 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) ;
vbIsValidTria[vChain.back()] = true ;
int nTrgTest1 = vChain.back() ;
int nTrgTest2 = nTB ;
for ( int i = int( vChain.size()-2) ; i >= 0 ; i--) {
// triangolo corrente
int nTA = vChain[i] ;
int nEA = vChainEdges[i] ;
// 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
FlipTrg( vTr, nTA, nTB, nEA, nEB) ;
vbIsValidTria[nTA] = true ;
// aggiorno i trg di test per lo step successivo
nTrgTest1 = nTA ;
nTrgTest2 = nTB ;
}
}
}
}
// se sono stati annullati dei triangoli, li rimuovo dal vettore
if ( bRemovedTrg) {
INTVECTOR vTrTmp ;
vTrTmp.reserve( vTr.size()) ;
for ( int i = 0 ; i < int( vTr.size()) ; i++)
if ( vTr[i] != -1)
vTrTmp.emplace_back( vTr[i]) ;
swap( vTr, vTrTmp) ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
MakeByFist( const POLYLINEVECTOR& vPL, PNTVECTOR& vPt, INTVECTOR& vTr)
{
// opzioni di triangolazione
rt_options rt_opt ;
InitDefaults( &rt_opt) ;
rt_opt.ears_top = false ;
rt_opt.ears_random = false ;
rt_opt.ears_sorted = true ;
rt_opt.ears_fancy = true ;
// creo oggetto di fist per triangolazione
global_struct fist ;
InitGlobalStruct( &fist, &rt_opt, true) ;
// allocazione ottimizzata degli array di fist
int nLoops = int( vPL.size()) ;
int nVertices = 0 ;
for ( int i = 0 ; i < nLoops ; i ++)
nVertices += ( vPL[i].GetPointNbr() - 1) ;
OptimizeMemoryAllocation( &fist, nLoops, nVertices) ;
// assegno i dati a fist
for ( int i = 0 ; i < nLoops ; i ++) {
// salvo i vertici saltando il primo punto ( coincide con l'ultimo)
Point3d pt ;
if ( ! vPL[i].GetFirstPoint( pt))
return false ;
while ( vPL[i].GetNextPoint( pt))
StoreVertex( &fist.c_vertex, pt.x, pt.y, pt.z) ;
// salvo il loop
int nPoints = vPL[i].GetPointNbr() ;
AddLoopInFace( &fist, nLoops - 1, i == 0, nPoints - 1) ;
}
StoreGroupNumber( &fist.c_list, &fist.c_vertex) ;
// eseguo triangolazione
Triangulate( &fist) ;
// recupero i vertici da fist
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 ++) {
vTr.emplace_back( fist.c_vertex.triangles[i].v1) ;
vTr.emplace_back( fist.c_vertex.triangles[i].v2) ;
vTr.emplace_back( fist.c_vertex.triangles[i].v3) ;
}
// rimuovo eventuali triangoli validi per fist ma invalidi per le nostre tolleranze
RemoveFistInvalidTrg( vPt, vTr) ;
// chiudo fist e dealloco la sua memoria
FIST_TerminateProgram( &fist) ;
return true ;
}
+1
View File
@@ -30,6 +30,7 @@
#pragma comment(lib, EGTEXTDIR "zlib/Lib/zlib" EGTLIBVER ".lib")
#pragma comment(lib, EGTEXTDIR "vroni/Lib/vroni" EGTLIBVER ".lib")
#pragma comment(lib, EGTEXTDIR "fist/Lib/fist" EGTLIBVER ".lib")
#pragma comment(lib, EGTLIBDIR "EgtGeneral" EGTLIBVER ".lib")
#pragma comment(lib, EGTLIBDIR "EgtNumKernel" EGTLIBVER ".lib")
#pragma comment(lib, EGTLIBDIR "SEgtLock" EGTLIBVER ".lib")