EgtGeomKernel :

- tentativo di miglioria alle ruled. Da debuggare.
This commit is contained in:
Daniele Bariletti
2026-02-03 16:13:07 +01:00
parent 25d53338c2
commit a1c448d8dd
2 changed files with 494 additions and 216 deletions
+385 -216
View File
@@ -45,11 +45,13 @@
#include "/EgtDev/Extern/Eigen/Dense"
#define SAVEFAILEDTRIANGULATION 0
#define SAVEISO 0
#define SAVERULEDISO 0
#define SAVEREBUILTISO 0
#define SAVERULEDISO 1
#define SAVERULEDGUIDEDISO 0
#if SAVEFAILEDTRIANGULATION || SAVEISO || SAVERULEDISO || SAVERULEDGUIDEDISO
#define SAVEMATCHCURVES 0
#if SAVEFAILEDTRIANGULATION || SAVEREBUILTISO || SAVERULEDISO || SAVERULEDGUIDEDISO || SAVEMATCHCURVES
#include "/EgtDev/Include/EGkGeoObjSave.h"
std::vector<IGeoObj*> vGeo ;
#endif
using namespace std ;
@@ -1071,10 +1073,10 @@ SurfBezier::Load( NgeReader& ngeIn)
m_bTrimmed = true ;
}
#if SAVEISO
#if SAVEREBUILTISO
ICURVEPOVECTOR vCrv ;
GetAllPatchesIsocurves( false, vCrv) ;
vector<IGeoObj*> vGeo ;
vGeo.clear() ;
for( int i = 0 ; i < ssize(vCrv) ; ++i)
vGeo.push_back( vCrv[i]->Clone()) ;
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\ruled\\rebuild\\isoCrv.nge") ;
@@ -4460,7 +4462,7 @@ ChangeStartForClosed( PolyLine& plU0, PolyLine& plU1, ICurveComposite* pCrvU0, I
}
static bool
GetEdgeSplitByAngTol( const PolyLine& PL, double dAngTol, INTVECTOR& vEdgeSplit)
GetEdgeSplitByAngTol( const PolyLine& PL, double dAngTol, BOOLVECTOR& vEdgeSplit)
{
int nPoints = PL.GetPointNbr() ;
vEdgeSplit.clear() ;
@@ -4935,30 +4937,39 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
}
}
// spezzo le curve di bezier dove è necessario aggiungere dei punti
else if ( nRuledType == RLT_B_MINDIST_PLUS ) {
else if ( nRuledType == RLT_B_MINDIST_PLUS) {
// scorro la prima curva e per ogni punto di fine sottocurva cerco il minDistPoint sull'altra curva
// in quel punto la curva verrà spezzata, a meno che non si trovi una joint già sufficientemente vicina
#if SAVEMATCHCURVES
vector<vector<IGeoObj*>> vvGeo0(4) ;
vector<vector<Color>> vvCol0(4) ;
#endif
// prima trovo le associazioni senza aggiunte di punti
bool bIsClosed0 = plU0.IsClosed() ;
bool bIsClosed1 = plU1.IsClosed() ;
CurveComposite ccPoly0 ; ccPoly0.FromPolyLine( plU0) ;
CurveComposite ccPoly1 ; ccPoly1.FromPolyLine( plU1) ;
Point3d ptP1 ; plU1.GetFirstPoint( ptP1) ;
vector<pair<Point3d,double>> vMatch1 ;
PNTUVECTOR vMatch1 ;
PNTUVECTOR vMatch1b ;
PNTVECTOR vPnt1 ; vPnt1.emplace_back( ptP1) ;
while ( plU1.GetNextPoint( ptP1, true)) {
Vector3d vtDir ; CrvU1.GetCurve( vPnt1.size() - 1)->GetEndDir( vtDir) ;
IntersCurvePlane icp( ccPoly0, ptP1, vtDir) ;
double dParam ;
Point3d ptJoint ;
DistPointCurve dpc( ptP1, CrvU0, false) ;
int nFlag = 0 ;
dpc.GetParamAtMinDistPoint( 0, dParam, nFlag) ;
dpc.GetMinDistPoint( 0, ptJoint, nFlag) ;
vMatch1b.emplace_back( ptJoint, dParam) ;
if ( icp.GetIntersCount() > 0)
icp.GetIntersPointNearTo( ptP1, ptJoint, dParam) ;
else {
DistPointCurve dpc( ptP1, CrvU0, false) ;
int nFlag = 0 ;
dpc.GetParamAtMinDistPoint( 0, dParam, nFlag) ;
dpc.GetMinDistPoint( 0, ptJoint, nFlag) ;
;
}
// capisco se il punto avrà bisogno di aggiungere uno split sull'altra curva o no
int nParam = int( dParam) ;
@@ -4972,31 +4983,44 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
//se sono troppo vicino ad uno split esistente allora non faccio nulla
if ( abs(dParam - round( dParam)) < 100 * EPS_PARAM || Dist( ptJoint, ptNearestJoint) < 50 * EPS_SMALL) {
dParam = round( dParam) ;
ptJoint = ptNearestJoint ;
}
vMatch1.push_back( pair<Point3d,double>( ptJoint, dParam)) ;
vMatch1.emplace_back( ptJoint, dParam) ;
vPnt1.emplace_back( ptP1) ;
#if SAVEMATCHCURVES
CurveLine CLa ; CLa.Set( ptP1, ptJoint) ;
vvGeo0[0].push_back( CLa.Clone()) ;
CurveLine CLb ; CLb.Set( ptP1, vMatch1b.back().first) ;
vvGeo0[1].push_back( CLb.Clone()) ;
#endif
}
plU1.GetLastPoint( ptP1) ;
vPnt1.emplace_back( ptP1) ;
Point3d ptP0 ; plU0.GetLastPoint( ptP0) ;
vMatch1.push_back( pair<Point3d,double>( ptP0, nSpanU0)) ;
vMatch1.emplace_back( ptP0, nSpanU0) ;
vMatch1b.emplace_back( ptP0, nSpanU0) ;
plU0.GetFirstPoint( ptP0) ;
vector<pair<Point3d,double>> vMatch0 ;
PNTUVECTOR vMatch0 ;
PNTUVECTOR vMatch0b ;
PNTVECTOR vPnt0 ; vPnt0.emplace_back( ptP0) ;
while ( plU0.GetNextPoint( ptP0, true)) {
double dParam ;
Point3d ptJoint ;
Vector3d vtDir ; CrvU0.GetCurve( vPnt0.size() - 1)->GetEndDir( vtDir) ;
IntersCurvePlane icp( ccPoly1, ptP0, vtDir) ;
DistPointCurve dpc( ptP0, CrvU1, false) ;
int nFlag = 0 ;
dpc.GetMinDistPoint( 0, ptJoint, nFlag) ;
dpc.GetParamAtMinDistPoint( 0, dParam, nFlag) ;
vMatch0b.emplace_back( ptJoint, dParam) ;
if ( icp.GetIntersCount() > 0) {
icp.GetIntersPointNearTo( ptP0, ptJoint, dParam) ;
}
else {
DistPointCurve dpc( ptP0, CrvU1, false) ;
int nFlag = 0 ;
dpc.GetMinDistPoint( 0, ptJoint, nFlag) ;
dpc.GetParamAtMinDistPoint( 0, dParam, nFlag) ;
;
}
// capisco se il punto avrà bisogno di aggiungere uno split sull'altra curva o no
int nParam = int( dParam) ;
@@ -5010,17 +5034,87 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
// se sono già troppo vicino ad un split esistente allora non faccio nulla
if ( abs(dParam - round( dParam)) < 100 * EPS_PARAM || Dist( ptJoint, ptNearestJoint) < 50 * EPS_SMALL) {
dParam = round( dParam) ;
ptJoint = ptNearestJoint ;
}
vMatch0.push_back( pair<Point3d,double>( ptJoint, dParam)) ;
vMatch0.emplace_back( ptJoint, dParam) ;
vPnt0.emplace_back( ptP0) ;
#if SAVEMATCHCURVES
CurveLine CLa ; CLa.Set( ptP0, ptJoint) ;
vvGeo0[2].push_back( CLa.Clone()) ;
CurveLine CLb ; CLb.Set( ptP0, vMatch0b.back().first) ;
vvGeo0[3].push_back( CLb.Clone()) ;
#endif
}
plU0.GetLastPoint( ptP0) ;
vPnt0.emplace_back( ptP0) ;
plU1.GetLastPoint( ptP1) ;
vMatch0.push_back( pair<Point3d,double>( ptP1, nSpanU1)) ;
vMatch0.emplace_back( ptP1, nSpanU1) ;
vMatch0b.emplace_back( ptP1, nSpanU1) ;
#if SAVEMATCHCURVES
vvCol0[0].resize( ssize(vvGeo0[0])) ;
fill( vvCol0[0].begin(), vvCol0[0].end(), Color( 128,128,255)) ;
vvCol0[1].resize( ssize(vvGeo0[1])) ;
fill( vvCol0[1].begin(), vvCol0[1].end(), Color( 0,128,192)) ;
vvCol0[2].resize( ssize(vvGeo0[2])) ;
fill( vvCol0[2].begin(), vvCol0[2].end(), Color( 255,128,128)) ;
vvCol0[3].resize( ssize(vvGeo0[3])) ;
fill( vvCol0[3].begin(), vvCol0[3].end(), Color( 192,128,0)) ;
SaveGeoObj( vvGeo0, vvCol0, "D:\\Temp\\bezier\\ruled\\match.nge") ;
#endif
// salvo le coppie di punti su ogni curva che indicano l'inizio e la fine di regioni di mismatch tra i valori di accoppiamento rilevati
// tramite due misure diverse della distanza
INTINTVECTOR vMismatch0 ;
INTINTVECTOR vMismatch1 ;
double dMaxDist = Dist( vPnt0[0], vPnt1[0]) / 20 ;
for( int i = 0 ; i < ssize( vMatch0) ; ++i) {
if( ! AreSamePointEpsilon( vMatch0[i].first, vMatch0b[i].first, dMaxDist)) {
int c = i + 1 ;
while( ! AreSamePointEpsilon( vMatch0[c].first, vMatch0b[c].first, dMaxDist))
++c ;
vMismatch0.emplace_back( i, c) ;
i = c ;
}
}
// faccio un merge di regioni adiacenti di mismatch
int nCurr = 0, nNext = 1 ;
while( nNext < ssize( vMismatch0)) {
if( vMismatch0[nNext].first - vMismatch0[nCurr].second < 2 + EPS_SMALL) {
vMismatch0[nCurr].second = vMismatch0[nNext].second ;
}
else {
++nCurr ;
vMismatch0[nCurr] = vMismatch0[nNext] ;
}
++nNext ;
}
vMismatch0.resize( nCurr + 1) ;
for( int i = 0 ; i < ssize( vMatch1) ; ++i) {
if( ! AreSamePointEpsilon( vMatch1[i].first, vMatch1b[i].first, dMaxDist)) {
int c = i + 1 ;
while( ! AreSamePointEpsilon( vMatch1[c].first, vMatch1b[c].first, dMaxDist))
++c ;
vMismatch1.emplace_back( i, c) ;
i = c ;
}
}
nCurr = 0, nNext = 1 ;
while( nNext < ssize( vMismatch1)) {
if( vMismatch1[nNext].first - vMismatch1[nCurr].second < 2 + EPS_SMALL) {
vMismatch1[nCurr].second = vMismatch1[nNext].second ;
}
else {
++nCurr ;
vMismatch1[nCurr] = vMismatch1[nNext] ;
}
++nNext ;
}
vMismatch1.resize( nCurr + 1) ;
// verifico la presenza di eventuali "edge" lungo le polyline ( punti di passaggio di un edge e quindi cambi bruschi di direzione della polyline)
INTVECTOR vEdgeSplit0, vEdgeSplit1 ;
BOOLVECTOR vEdgeSplit0, vEdgeSplit1 ;
double dAngTol = 55 ;
GetEdgeSplitByAngTol( plU0, dAngTol, vEdgeSplit0) ;
GetEdgeSplitByAngTol( plU1, dAngTol, vEdgeSplit1) ;
@@ -5038,12 +5132,23 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
INTINTVECTOR vPairs ;
vPairs.emplace_back( 0, 0) ;
bool bAdvance = true ;
int m0 = 0, m1 = 0 ; // contatori delle zone di mismatch
// verifico i match effettivi tra le polyline
while ( bAdvance) {
if ( c > ssize(vMatch0) - 1 || j > ssize( vMatch1) - 1) {
LOG_DBG_ERR( GetEGkLogger(), "RLT_B_MINDIST_PLUS: le due curve potrebbero non avere forme coerenti") ;
return false ;
}
// aggiorno il contatore delle eventuali zone di mismatch
if( ssize(vMismatch0) > 0) {
while( m0 < ssize(vMismatch0) && c > vMismatch0[m0].second)
++m0 ;
}
if( ssize(vMismatch1) > 0) {
while( m1 < ssize(vMismatch1) && j > vMismatch1[m1].second)
++m1 ;
}
double dParam0 = vMatch0[c].second ;
Point3d ptJoint0 = vMatch0[c].first ;
double dParam1 = vMatch1[j].second ;
@@ -5069,8 +5174,20 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
bAdvance0 = false ;
if ( j == vMatch1.size())
bAdvance1 = false ;
bool bMismatch = false ;
bool bMismatch0 = false ;
bool bMismatch1 = false ;
// controllo la presenza di eventuali zone di mismatch
if ( ssize( vMismatch0) > 0 || ssize( vMismatch1) > 0) {
if ( m0 < ssize( vMismatch0) && c >= vMismatch0[m0].first && c < vMismatch0[m0].second)
bMismatch0 = true ;
if ( m1 < ssize( vMismatch1) && j >= vMismatch1[m1].first && j < vMismatch1[m1].second)
bMismatch1 = true ;
bMismatch = (bMismatch0 && bMismatch1) || (bMismatch0 && ! bAdvance1) || (bMismatch1 && ! bAdvance0);
}
// se trovo che ho uno spigolo allora procedo con la gestione spigoli
if( vEdgeSplit0[c+1] && vEdgeSplit1[j+1]) {
else if( vEdgeSplit0[c+1] && vEdgeSplit1[j+1]) {
// se ho uno spigolo su entrambe le curve forzo l'accoppiamento
bAdvance0 = true ;
bPerfectMatch = true ;
@@ -5080,11 +5197,12 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
ptJoint1 = vPnt0[c+1] ;
}
else if ( (vEdgeSplit0[c+1] && ! bAdvance1) || (vEdgeSplit1[j+1] && ! bAdvance0)) {
// da una parte ho uno spigolo e dall'altra non posso avanzare
bAdvance0 = false ;
bAdvance1 = false ;
}
if ( bAdvance0) {
if ( bAdvance0 && ! bMismatch) {
if ( c < dLastParamMatch1 + EPS_SMALL)
++c ;
// ho match con lo start
@@ -5121,7 +5239,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
if ( bPerfectMatch)
++j ;
}
if ( bAdvance1 && ! bPerfectMatch) {
if ( bAdvance1 && ! bPerfectMatch && ! bMismatch) {
if ( j < dLastParamMatch0 + EPS_SMALL)
++j ;
// ho un match con lo start
@@ -5156,16 +5274,17 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
dLastParamMatch0 = j ;
ptLastPointMatch0 = vPnt1[j] ;
}
if ( ! bAdvance0 && ! bAdvance1) {
if ( ( ! bAdvance0 && ! bAdvance1) || bMismatch) {
// sono arrivato ad un caso di incrocio!!
//1. se sono vicino ad uno spigolo su entrambe le curve allora aggiungo dei rep
//2. sennò accoppio comunque
//1. se sono vicino ad uno spigolo su entrambe le curve allora accoppio gli spigoli e il resto lo aggiusto di conseguenza
//2. se sono in una zona di mismatch faccio il match usando la parametrizzazione sulla lunghezza dei tratti di curve interessati
//3. sennò accoppio comunque ( la coppia corrente)
bool bEdgeFoundOnSecond = false ;
if ( vEdgeSplit0[c+1] && vEdgeSplit1[j+1]) {
// questo caso non è previsto !!!!! e non mi aspetto che avvenga
LOG_DBG_ERR( GetEGkLogger(), "RLT_B_MINDIST_PLUS: a not handled mismatch was found, type 0") ;
}
if ( vEdgeSplit0[c+1]) {
if ( vEdgeSplit0[c+1] && ! bMismatch) {
++c ;
++j ;
//cerco se ho uno split anche su U1 entro una distanza che sia al massimo il doppio di quella che c'è col punto a mindist
@@ -5188,11 +5307,10 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
dLastParamMatch0 = j - 1 ;
ptLastPointMatch0 = vPnt1[j] ;
}
else {
LOG_DBG_ERR( GetEGkLogger(), "RLT_B_MINDIST_PLUS: a not handled mismatch was found, type 1") ;
}
else
bMismatch = true ;
}
else if ( vEdgeSplit1[j+1]) {
else if ( vEdgeSplit1[j+1] && ! bMismatch) {
++c ;
++j ;
//cerco se ho uno split anche su U1 entro una distanza che sia al massimo il doppio di quella che c'è col punto a mindist
@@ -5215,194 +5333,245 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
dLastParamMatch1 = c - 1 ;
ptLastPointMatch1 = vPnt0[c] ;
}
else {
LOG_DBG_ERR( GetEGkLogger(), "RLT_B_MINDIST_PLUS: a not handled mismatch was found, type 2") ;
}
else
bMismatch = true ;
}
else {
/////////OLD VRESION
++c ;
++j ;
vPairs.emplace_back( c + nSplit0, j + nSplit1) ;
dLastParamMatch1 = c ;
ptLastPointMatch1 = vPnt0[c] ;
dLastParamMatch0 = j ;
ptLastPointMatch0 = vPnt1[j] ;
if( ( ! vEdgeSplit0[c+1] && ! vEdgeSplit1[j+1]) || bMismatch) {
// non ci sono riferimenti per fare un match, quindi li cerco io
///////////OLD VRESION
//++c ;
//++j ;
//vPairs.emplace_back( c + nSplit0, j + nSplit1) ;
//dLastParamMatch1 = c ;
//ptLastPointMatch1 = vPnt0[c] ;
//dLastParamMatch0 = j ;
//ptLastPointMatch0 = vPnt1[j] ;
////// potrei avere un mismatch, senza però avere degli spigoli..
//// potrei avere un mismatch, senza però avere degli spigoli..
// // identifico la zona in cui ho il mismatch e parametrizzo localmente
// identifico la zona in cui ho il mismatch e parametrizzo localmente
// //conto quanti punti ho nel mezzo
// int c_temp = c, j_temp = j ;
// bAdvance0 = true ;
// bAdvance1 = true ;
// int nParam0, nParam1 ;
// while( bAdvance0) {
// dParam0 = vMatch0[c_temp].second ;
// nParam0 = int( round( dParam0)) ;
// dParam1 = vMatch1[nParam0].second ;
// nParam1 = int( round( dParam1)) ;
// if( abs( nParam1 - c_temp) <= 2)
// bAdvance0 = false ;
// else
// ++ c_temp ;
// }
// while( bAdvance1) {
// dParam1 = vMatch1[j_temp].second ;
// nParam1 = int( round( dParam1)) ;
// dParam0 = vMatch0[nParam1].second ;
// nParam0 = int( round( dParam0)) ;
// if( abs( nParam0 - j_temp) <= 2)
// bAdvance1 = false ;
// else
// ++ j_temp ;
// }
// // se non sono avanzato, allora mi basta accoppiare i due punti in questione
// if( c_temp == c || j_temp == j) {
// ++c ;
// ++j ;
// vPairs.emplace_back( c + nSplit0, j + nSplit1) ;
// dLastParamMatch1 = c ;
// ptLastPointMatch1 = vPnt0[c] ;
// dLastParamMatch0 = j ;
// ptLastPointMatch0 = vPnt1[j] ;
// }
// // se sono dovuto avanzare per trovare delle coppie che tornano a matchare allora ho effettivamente trovato una zona di mismatch
// else {
// // determino quale delle due coppie è il confine effettivo con la zona di mismatch e quale sarà la prima dopo il mismamtch
// dParam0 = vMatch0[c_temp].second ;
// dParam1 = vMatch1[j_temp].second ;
// bool bIntParam0 = false ;
// bool bIntParam1 = false ;
// if ( abs( dParam0 - round( dParam0)) < EPS_SMALL) {
// dParam0 = round( dParam0) ;
// bIntParam0 = true ;
// }
// if ( abs( dParam1 - round( dParam1)) < EPS_SMALL) {
// dParam1 = round( dParam1) ;
// bIntParam1 = true ;
// }
// bAdvance0 = dParam0 < j_temp + 1 + EPS_SMALL ;
// bAdvance1 = dParam1 < c_temp + 1 + EPS_SMALL ;
// PtrOwner<ICurve> pCC0 ;
// PtrOwner<ICurve> pCC1 ;
// int nPointsBetween0 = 0 ;
// int nPointsBetween1 = 0 ;
// if( bAdvance0 && bAdvance1) {
// pCC0.Set( CrvU0.CopyParamRange( dLastParamMatch1, c_temp + 1)) ;
// pCC1.Set( CrvU1.CopyParamRange( dLastParamMatch0, j_temp + 1)) ;
// nPointsBetween0 = c_temp - c ;
// nPointsBetween1 = j_temp - j ;
// }
// else if( bAdvance0){
// pCC0.Set( CrvU0.CopyParamRange( dLastParamMatch1, c_temp + 1)) ;
// pCC1.Set( CrvU1.CopyParamRange( dLastParamMatch0, dParam0)) ;
// nPointsBetween0 = c_temp - c ;
// nPointsBetween1 = int( dParam0) - ( j + 1) ;
// if ( bIntParam0)
// nPointsBetween1 -= 1 ;
// }
// else if( bAdvance1){
// pCC0.Set( CrvU0.CopyParamRange( dLastParamMatch1, dParam1)) ;
// pCC1.Set( CrvU1.CopyParamRange( dLastParamMatch0, j_temp + 1)) ;
// nPointsBetween0 = int( dParam1) - ( c + 1) ;
// nPointsBetween1 = j_temp - j ;
// if ( bIntParam1)
// nPointsBetween0 -= 1 ;
// }
//
// double dLen0 ; pCC0->GetLength( dLen0) ;
// double dLen1 ; pCC1->GetLength( dLen1) ;
// DBLVECTOR vdParamPos0 ; vdParamPos0.reserve( nPointsBetween0) ;
// DBLVECTOR vdParamPos1 ; vdParamPos1.reserve( nPointsBetween1) ;
// for ( int k = 0 ; k <= nPointsBetween0 ; ++k) {
// double dLen = 0 ; pCC0->GetLengthAtParam( k, dLen) ;
// vdParamPos0.push_back( dLen / dLen0) ;
// }
// vdParamPos0.push_back( 1) ;
// for ( int k = 0 ; k <= nPointsBetween1 ; ++k) {
// double dLen = 0 ; pCC1->GetLengthAtParam( k, dLen) ;
// vdParamPos1.push_back( dLen / dLen1) ;
// }
// vdParamPos1.push_back( 1) ;
//conto quanti punti ho nel mezzo
int c_temp, j_temp ;
if( ! bMismatch) {
c_temp = c, j_temp = j ;
bAdvance0 = true ;
bAdvance1 = true ;
int nParam0, nParam1 ;
while( bAdvance0) {
dParam0 = vMatch0[c_temp].second ;
nParam0 = int( round( dParam0)) ;
dParam1 = vMatch1[nParam0].second ;
nParam1 = int( round( dParam1)) ;
if( abs( nParam1 - c_temp) <= 2)
bAdvance0 = false ;
else
++ c_temp ;
}
while( bAdvance1) {
dParam1 = vMatch1[j_temp].second ;
nParam1 = int( round( dParam1)) ;
dParam0 = vMatch0[nParam1].second ;
nParam0 = int( round( dParam0)) ;
if( abs( nParam0 - j_temp) <= 2)
bAdvance1 = false ;
else
++ j_temp ;
}
}
else {
// cerco se ho degli spigoli nella zona di mismatch
// se ne ho definisco una regione compresa tra un estremo( start o end) e uno spigolo (presente su entrambe le curve)
INTVECTOR vnEdges0, vnEdges1 ;
for( int i = vMismatch0[m0].first ; i < vMismatch0[m0].second ; ++i) {
if ( vEdgeSplit0[i])
vnEdges0.push_back(i) ;
}
for( int i = vMismatch1[m1].first ; i < vMismatch1[m1].second ; ++i) {
if ( vEdgeSplit1[i])
vnEdges1.push_back(i) ;
}
// se ho degli edge che non matchano tra loro semplicemente tratto tutta la regione di mismatch insieme
if( ssize( vnEdges0) != ssize( vnEdges1) || ssize( vnEdges0) == 0 || ssize( vnEdges1) == 0) {
if( bMismatch0) {
c_temp = vMismatch0[m0].second ;
j_temp = int( vMatch0[c_temp].second) ;
}
else if ( bMismatch1){
j_temp = vMismatch1[m1].second ;
c_temp = int( vMatch1[j_temp].second) ;
}
}
// se ho corrispondenza tra gli edge (in numero) allora (do per scontato di accoppiarli e ) li prendo come estremi di zone da trattare separatamente
else {
// definisco gli estremi della zona da riparametrizzare
// controllo se ho già matchato parte della zona di mismatch
// cerco la coppia successiva alla corrente per determinare la zona su cui lavorare ora
for( int i = 0 ; i < ssize( vnEdges0) ; ++i) {
if( c == vnEdges0[i]) {
if( i < ssize( vnEdges0) - 1) {
c_temp = vnEdges0[i+1] ;
j_temp = vnEdges1[i+1] ;
}
else {
if ( bMismatch0) {
c_temp = vMismatch0[m0].second ;
j_temp = int( vMatch0[c_temp].second) ;
++m0 ;
}
else if( bMismatch1) {
j_temp = vMismatch1[m1].second ;
c_temp = int( vMatch1[j_temp].second) ;
++m1 ;
}
}
break ;
}
}
}
}
// se non sono avanzato, allora mi basta accoppiare i due punti in questione
if( c_temp == c || j_temp == j) {
++c ;
++j ;
vPairs.emplace_back( c + nSplit0, j + nSplit1) ;
dLastParamMatch1 = c ;
ptLastPointMatch1 = vPnt0[c] ;
dLastParamMatch0 = j ;
ptLastPointMatch0 = vPnt1[j] ;
}
// se sono dovuto avanzare per trovare delle coppie che tornano a matchare allora ho effettivamente trovato una zona di mismatch
else {
// determino quale delle due coppie è il confine effettivo con la zona di mismatch e quale sarà la prima dopo il mismamtch
dParam0 = vMatch0[c_temp].second ;
dParam1 = vMatch1[j_temp].second ;
bAdvance0 = dParam0 < j_temp + 1 + EPS_SMALL ;
bAdvance1 = dParam1 < c_temp + 1 + EPS_SMALL ;
PtrOwner<ICurve> pCC0 ;
PtrOwner<ICurve> pCC1 ;
int nPointsBetween0 = 0 ;
int nPointsBetween1 = 0 ;
if( bAdvance0 && bAdvance1) {
pCC0.Set( CrvU0.CopyParamRange( dLastParamMatch1, c_temp + 1)) ;
pCC1.Set( CrvU1.CopyParamRange( dLastParamMatch0, j_temp + 1)) ;
nPointsBetween0 = int( c_temp + 1 - floor( dLastParamMatch1) - 1) ;
nPointsBetween1 = int( j_temp + 1 - floor( dLastParamMatch0) - 1) ;
}
else if( bAdvance0){
pCC0.Set( CrvU0.CopyParamRange( dLastParamMatch1, c_temp + 1)) ;
pCC1.Set( CrvU1.CopyParamRange( dLastParamMatch0, dParam0)) ;
nPointsBetween0 = int( c_temp + 1 - floor( dLastParamMatch1) - 1) ;
nPointsBetween1 = int( ceil( dParam0) - floor( dLastParamMatch0) - 1) ;
}
else if( bAdvance1){
pCC0.Set( CrvU0.CopyParamRange( dLastParamMatch1, dParam1)) ;
pCC1.Set( CrvU1.CopyParamRange( dLastParamMatch0, j_temp + 1)) ;
nPointsBetween0 = int( ceil( dParam1) - floor( dLastParamMatch1) - 1) ;
nPointsBetween1 = int( j_temp + 1 - floor( dLastParamMatch0) - 1) ;
}
// bool bSplitToAdd = true ;
// int c0 = 1, c1 = 1 ;
// //debug
// int nCBerfore = c ;
// int nJBefore = j ;
// //debug
// while ( bSplitToAdd) {
// if ( c0 > ssize( vdParamPos0) - 1 && c1 > ssize( vdParamPos1) - 1) {
// LOG_DBG_ERR( GetEGkLogger(), "Surf Bez Ruled Guided: error 1 while reparametrizing some section") ;
// return false ;
// }
// // se ho una corrispondenza tra punti ( e non sono alla fine del tratto) allora non aggiungo split
// if ( abs( vdParamPos0[c0] - vdParamPos1[c1]) < EPS_PARAM && vdParamPos0[c0] < 1) {
// ++c0 ;
// ++c1 ;
// ++c ;
// ++j ;
// vPairs.emplace_back( c + nSplit0, j + nSplit1) ;
// }
// // se non ho corrispondenza allora aggiungo uno split sulla curva a cui manca il punto corrispondente
// else if ( vdParamPos0[c0] < vdParamPos1[c1]) {
// double dPar ; CrvU1.GetParamAtLength( dLen1 * vdParamPos0[c0], dPar) ;
// if ( abs( dPar - round( dPar)) > EPS_SMALL) {
// vdSplit1.push_back( dPar + dLastParamMatch0) ;
// nSplit1 = vdSplit1.size() ;
// }
// else if ( dPar = round( dPar) ; dPar > j){
// ++ j ;
// }
// ++c ;
// vPairs.emplace_back( c + nSplit0, j + nSplit1) ;
// ++c0 ;
// }
// else if ( vdParamPos0[c0] > vdParamPos1[c1]) {
// double dPar ; CrvU0.GetParamAtLength( dLen0 * vdParamPos1[c1], dPar) ;
// // se lo split non è in prossimità di una joint già esistente allora lo aggiungo
// if ( abs( dPar - round( dPar)) > EPS_SMALL) {
// vdSplit0.push_back( dPar + dLastParamMatch1) ;
// nSplit0 = vdSplit0.size() ;
// }
// else if ( dPar = round( dPar) ; dPar > c){
// ++ c ;
// }
// ++j ;
// vPairs.emplace_back( c + nSplit0, j + nSplit1) ;
// ++c1 ;
// }
// else {
// LOG_DBG_ERR( GetEGkLogger(), "Surf Bez Ruled Guided: error 2 while reparametrizing some section") ;
// return false ;
// }
// bSplitToAdd = ! ( c0 == ssize( vdParamPos0) - 1 && c1 == ssize( vdParamPos1) - 1) ;
// }
// // aggiorno i dati dell'ultima aggiunta
// if( bAdvance0 && ! bAdvance1) {
// ptLastPointMatch0 = vMatch0[c_temp].first ;
// dLastParamMatch0 = vMatch0[c_temp].second ;
// ptLastPointMatch1 = vPnt0[c_temp] ;
// dLastParamMatch0 = c_temp ;
// }
// else if( ! bAdvance0 && bAdvance1) {
// ptLastPointMatch0 = vPnt1[j_temp] ;
// dLastParamMatch0 = j_temp ;
// ptLastPointMatch1 = vMatch1[j_temp].first ;
// dLastParamMatch0 = vMatch1[j_temp].second ;
// }
// else {
// ptLastPointMatch0 = vPnt1[j_temp] ;
// dLastParamMatch0 = j_temp ;
// ptLastPointMatch1 = vPnt0[c_temp] ;
// dLastParamMatch0 = c_temp ;
// }
// vPairs.emplace_back( c + nSplit0, j + nSplit1) ;
// }
if( IsNull(pCC0) || ! pCC0->IsValid() || IsNull(pCC1) || ! pCC1->IsValid()) {
LOG_DBG_ERR( GetEGkLogger(), "RLT_B_MINDIST_PLUS: failed attempt to identify mismatch region, type0") ;
return false ;
}
double dLen0 ; pCC0->GetLength( dLen0) ;
double dLen1 ; pCC1->GetLength( dLen1) ;
if( nPointsBetween0 < 0 || nPointsBetween1 < 0) {
LOG_DBG_ERR( GetEGkLogger(), "RLT_B_MINDIST_PLUS: failed attempt to identify mismatch region, type1") ;
return false ;
}
DBLVECTOR vdParamPos0 ; vdParamPos0.reserve( nPointsBetween0 + 2) ;
DBLVECTOR vdParamPos1 ; vdParamPos1.reserve( nPointsBetween1 + 2) ;
for ( int k = 0 ; k <= nPointsBetween0 ; ++k) {
double dLen = 0 ; pCC0->GetLengthAtParam( k, dLen) ;
vdParamPos0.push_back( dLen / dLen0) ;
}
vdParamPos0.push_back( 1) ;
for ( int k = 0 ; k <= nPointsBetween1 ; ++k) {
double dLen = 0 ; pCC1->GetLengthAtParam( k, dLen) ;
vdParamPos1.push_back( dLen / dLen1) ;
}
vdParamPos1.push_back( 1) ;
bool bSplitToAdd = true ;
int c0 = 1, c1 = 1 ;
//debug
int nCBerfore = c ;
int nJBefore = j ;
//debug
double dLastParamMatch0Before = dLastParamMatch0 ;
double dLastParamMatch1Before = dLastParamMatch1 ;
while ( bSplitToAdd) {
if ( c0 > ssize( vdParamPos0) - 1 && c1 > ssize( vdParamPos1) - 1) {
LOG_DBG_ERR( GetEGkLogger(), "Surf Bez Ruled Guided: error 1 while reparametrizing some section") ;
return false ;
}
// se ho una corrispondenza tra punti ( e non sono alla fine del tratto) allora non aggiungo split
if ( abs( vdParamPos0[c0] - vdParamPos1[c1]) < EPS_PARAM && vdParamPos0[c0] < 1) {
++c ;
++j ;
vPairs.emplace_back( c + nSplit0, j + nSplit1) ;
ptLastPointMatch0 = vPnt0[c] ;
dLastParamMatch0 = c ;
ptLastPointMatch1 = vPnt1[j] ;
dLastParamMatch1 = j ;
++c0 ;
++c1 ;
}
// se non ho corrispondenza allora aggiungo uno split sulla curva a cui manca il punto corrispondente
else if ( vdParamPos0[c0] < vdParamPos1[c1]) {
double dPar ; pCC1->GetParamAtLength( dLen1 * vdParamPos0[c0], dPar) ;
Point3d ptMatch ; pCC1->GetPointD1D2( dPar, ICurve::Side::FROM_MINUS, ptMatch) ;
ptLastPointMatch1 = ptMatch ;
double dParamMatch ; CrvU1.GetParamAtPoint( ptMatch, dParamMatch) ;
dLastParamMatch1 = dParamMatch ;
// se lo split non è in prossimità di una joint già esistente allora lo aggiungo
if ( abs( dParamMatch - round( dParamMatch)) > EPS_SMALL) {
vdSplit1.push_back( dParamMatch) ;
nSplit1 = vdSplit1.size() ;
}
else if ( dParamMatch = round( dParamMatch) ; dParamMatch > j){
++ j ;
}
++c ;
vPairs.emplace_back( c + nSplit0, j + nSplit1) ;
ptLastPointMatch0 = vPnt0[c] ;
dLastParamMatch0 = c ;
++c0 ;
}
else if ( vdParamPos0[c0] > vdParamPos1[c1]) {
double dPar ; pCC0->GetParamAtLength( dLen0 * vdParamPos1[c1], dPar) ;
Point3d ptMatch ; pCC0->GetPointD1D2( dPar, ICurve::Side::FROM_MINUS, ptMatch) ;
ptLastPointMatch0 = ptMatch ;
double dParamMatch ; CrvU0.GetParamAtPoint( ptMatch, dParamMatch) ;
dLastParamMatch0 = dParamMatch ;
// se lo split non è in prossimità di una joint già esistente allora lo aggiungo
if ( abs( dParamMatch - round( dParamMatch)) > EPS_SMALL) {
vdSplit0.push_back( dParamMatch) ;
nSplit0 = vdSplit0.size() ;
}
else if ( dParamMatch = round( dParamMatch) ; dParamMatch > c){
++ c ;
}
++j ;
vPairs.emplace_back( c + nSplit0, j + nSplit1) ;
ptLastPointMatch1 = vPnt1[j] ;
dLastParamMatch1 = j ;
++c1 ;
}
else {
LOG_DBG_ERR( GetEGkLogger(), "Surf Bez Ruled Guided: error 2 while reparametrizing some section") ;
return false ;
}
bSplitToAdd = ! ( c0 == ssize( vdParamPos0) - 1 && c1 == ssize( vdParamPos1) - 1) ;
}
}
}
}
bAdvance = ! (c >= int(vMatch0.size()) - 1 && j >= int(vMatch1.size()) - 1) ;
@@ -5497,7 +5666,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
#if SAVERULEDISO
//debug
vector<IGeoObj*> vGeo ;
vGeo.clear() ;
ICURVEPOVECTOR vCrv ;
GetAllPatchesIsocurves( false, vCrv) ;
for( int i = 0 ; i < ssize( vCrv) ; ++i) {
@@ -6182,7 +6351,7 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c
#if SAVERULEDGUIDEDISO
//debug
vector<IGeoObj*> vGeo ;
vGeo.clear() ;
ICURVEPOVECTOR vCrvIso ;
GetAllPatchesIsocurves( false, vCrvIso) ;
for( int i = 0 ; i < ssize( vCrvIso) ; ++i) {
+109
View File
@@ -288,6 +288,115 @@ GetPointSetByAngTol( const PolyLine& PL, double dAngTol, POLYLINEVECTOR& vPL)
return true ;
}
//-----------------------------------------------------------------------------
// Funzione per spezzare una curva compo in diversi tratti in corrispondenza
// di cambi di direzione maggiori della tolleranza angolare passata
static bool
SplitCurveCompoByAngTol( const ICurveComposite* pCC, double dAngTol, ICRVCOMPOPOVECTOR& vCC)
{
int nCurves = pCC->GetCurveCount() ;
vCC.emplace_back( CreateCurveComposite()) ;
vCC.back()->AddCurve( pCC->GetCurve(0)->Clone()) ;
// Cos della tolleranza angolare massima
double dCosTol = cos( dAngTol * DEGTORAD) ;
for ( int nC = 0 ; nC < nCurves - 2; ++ nC) {
// Recupero l'angolo tra la fine della curva corrente e l'inizio della successiva
const ICurve* pCrvCurr = pCC->GetCurve( nC) ;
const ICurve* pCrvNext = pCC->GetCurve( nC + 1) ;
Vector3d vtCurrEnd ; pCrvCurr->GetEndDir( vtCurrEnd) ;
Vector3d vtNextStart ; pCrvNext->GetStartDir( vtNextStart) ;
// Calcolo il Coseno tra i due versori
double dCos = vtCurrEnd * vtNextStart ;
// Se dentro alla tolleranza, allora i punti apparterranno alla stessa curva
if ( dCos > dCosTol) {
// Aggiungo la curva
vCC.back()->AddCurve( pCrvNext->Clone()) ;
}
// Se tratto al di fuori della tolleranza, devo definire una nuova curva
else {
vCC.emplace_back( CreateCurveComposite()) ;
vCC.back()->AddCurve( pCrvNext->Clone()) ;
}
}
// Se curva originale chiusa
if ( pCC->IsClosed() && ssize( vCC) > 1) {
// Se ho più tratti, potrei riunire il primo con l'ultimo
const ICurve* pCrvFirst = pCC->GetCurve( 0) ;
const ICurve* pCrvLast = pCC->GetCurve( nCurves - 1) ;
Vector3d vtFirstStart ; pCrvFirst->GetEndDir( vtFirstStart) ;
Vector3d vtLastEnd ; pCrvLast->GetStartDir( vtLastEnd) ;
// Calcolo il Coseno tra i due versori
double dCos = vtFirstStart * vtLastEnd ;
// Se dentro alla tolleranza, allora i punti appartengono alla stessa curva
if ( dCos > dCosTol) {
// Aggiungo la curva
vCC.back()->AddCurve( Release( vCC.front())) ;
vCC.erase( vCC.begin()) ;
}
}
return true ;
}
////-----------------------------------------------------------------------------
//// Funzione che approssima la curva di bordo per la costruzione della Bezier Ruled mediante
//// Patches di curve di Bezier
//static bool
//ApproxBorder( ICurveComposite* pCrvCompo, double dLinTol, double dAngTol, double dAngTolSplit)
//{
// // N.B.:in futuro bisognerebbe fare l'approssimazione direttamente con le bezier.
//
// // Controllo dei parametri
// if ( pCrvCompo == nullptr || ! pCrvCompo->IsValid())
// return false ;
//
// // splitto la curva considerando la tolleranza angolare
// ICRVCOMPOPOVECTOR vCC ;
// SplitCurveCompoByAngTol( pCrvCompo, dAngTolSplit, vCC) ;
// #if DEBUG_BEZIER_INTERP
// VT.clear() ;
// for( int i = 0 ; i < ssize(vCC) ; ++i)
// VT.push_back( vCC[i]->Clone()) ;
// SaveGeoObj( VT, "D:\\Temp\\trimming\\AngBorderApprox.nge") ;
// VT.clear() ;
// #endif
//
// pCrvCompo->Clear() ;
//
// // Ogni PolyLine ricavata viene approssimata con un tratto di Bezier
// const double MAXLEN = 1.5 ;
// for ( ICurveComposite* pCC : vCC) {
// // Se meno di due curve, non la considero ( non dovrebbe mai capitare )
// if ( pCC->GetCurveCount() < 2)
// continue ;
// PolyArc PA ;
// if ( ! pCC->ApproxWithArcs( dLinTol, dAngTol, PA))
// return false ;
// CurveComposite CrvTemp ;
// if ( ! CrvTemp.FromPolyArc( PA) || ! CrvTemp.MergeCurves( dLinTol, dAngTol))
// return false ;
// #if DEBUG_BEZIER_INTERP
// VT.emplace_back( CrvTemp->Clone()) ;
// #endif
// // Converto in Bezier
// PtrOwner<ICurve> pCrvBz( CurveToBezierCurve( &CrvTemp)) ;
// if ( IsNull( pCrvBz) || ! pCrvBz->IsValid()) {
// LOG_ERROR( GetEGkLogger(), "Error : converrting curve to bezier") ;
// return false ;
// }
// // Aggiungo il tratto approssimato alla curva finale complessiva
// if ( ! pCrvCompo->AddCurve( Release( pCrvBz)))
// return false ;
// }
// #if DEBUG_BEZIER_INTERP
// SaveGeoObj( VT, VC, "D:\\Temp\\trimming\\bezier_edge.nge") ;
// #endif
//
// return ( pCrvCompo->IsValid()) ;
//}
//-----------------------------------------------------------------------------
// Funzione che approssima la curva di bordo per la costruzione della Bezier Ruled mediante
// Patches di curve di Bezier