EgtGeomKernel :

- miglioramenti e correzioni alle rigate con le bezier.
This commit is contained in:
Daniele Bariletti
2026-02-16 12:45:50 +01:00
parent 8db1765505
commit da7ebd6f61
+128 -31
View File
@@ -48,7 +48,7 @@
#define SAVEREBUILTISO 0
#define SAVERULEDISO 1
#define SAVERULEDGUIDEDISO 0
#define SAVEMATCHCURVES 0
#define SAVEMATCHCURVES 1
#if SAVEFAILEDTRIANGULATION || SAVEREBUILTISO || SAVERULEDISO || SAVERULEDGUIDEDISO || SAVEMATCHCURVES
#include "/EgtDev/Include/EGkGeoObjSave.h"
std::vector<IGeoObj*> vGeo ;
@@ -4511,6 +4511,60 @@ GetEdgeSplitByAngTol( const PolyLine& PL, double dAngTol, BOOLVECTOR& vEdgeSplit
return true ;
}
static bool
GetEdgeSplitByAngTol( const ICurveComposite* pCC, double dAngTol, BOOLVECTOR& vEdgeSplit)
{
int nCrvs = pCC->GetCurveCount() ;
vEdgeSplit.clear() ;
vEdgeSplit.resize( nCrvs) ;
fill( vEdgeSplit.begin(), vEdgeSplit.end(), false) ;
bool bClosed = pCC->IsClosed() ;
Vector3d vtTanCurr = V_INVALID, vtTanNext = V_INVALID ;
// cos della tolleranza angolare massima
double dCosTol = cos( dAngTol * DEGTORAD) ;
for ( int nC = 0 ; nC < nCrvs ; ++ nC) {
const ICurve* pSubCrvCurr = pCC->GetCurve( nC) ;
int nNext = nC < nCrvs - 1 ? nC + 1 : 0 ;
const ICurve* pSubCrvNext = pCC->GetCurve( nNext) ;
pSubCrvCurr->GetEndDir( vtTanCurr) ; vtTanCurr.Normalize() ;
pSubCrvNext->GetStartDir( vtTanNext) ; vtTanNext.Normalize() ;
// Calcolo il Coseno tra i due versori
double dCos = vtTanCurr * vtTanNext ;
// Se oltre la tolleranza allora ho incontrato un edge
if ( dCos < dCosTol)
vEdgeSplit[nC] = true ;
}
if ( ! bClosed)
vEdgeSplit[nCrvs - 1] = false ;
return true ;
}
//----------------------------------------------------------------------------
static bool
AdjustParamFromApprox( const PolyLine& plApprox, double& dParam)
{
// il parametro in ingresso è riferito al numero di linee della polilinea
// questa variabile verrà sostituita con il valore del parametro corrispondente alla curva che è stata approssimata dalla polilinea
int nCrv = int( dParam) ;
if ( nCrv > plApprox.GetPointNbr())
return false ;
double dParamPrev = 0 ;
plApprox.GetFirstU( dParamPrev) ;
int c = 0 ;
while ( c < nCrv) {
plApprox.GetNextU( dParamPrev) ;
++c ;
}
double dParamNext = 0 ;
plApprox.GetNextU( dParamNext) ;
double dFactor = dParam - nCrv ;
dParam = dFactor * dParamNext + ( 1 - dFactor) * dParamPrev ;
return true ;
}
//----------------------------------------------------------------------------
bool
SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int nRuledType)
@@ -4947,11 +5001,18 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
vector<vector<Color>> vvCol0(4) ;
#endif
// approssimo le curve con delle polyline per il calcolo delle distanze
PolyLine plApproxU0, plApproxU1 ;
double dLinTol = 10 * EPS_SMALL ;
double dAngTol = 5 ;
CrvU0.ApproxWithLines( dLinTol, dAngTol, ICurve::APL_STD, plApproxU0) ;
CrvU1.ApproxWithLines( dLinTol, dAngTol, ICurve::APL_STD, plApproxU1) ;
// 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) ;
CurveComposite ccPoly0 ; ccPoly0.FromPolyLine( plApproxU0) ;
CurveComposite ccPoly1 ; ccPoly1.FromPolyLine( plApproxU1) ;
Point3d ptP1 ; plU1.GetFirstPoint( ptP1) ;
PNTUVECTOR vMatch1 ;
PNTUVECTOR vMatch1b ;
@@ -4962,13 +5023,23 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
double dParam ;
Point3d ptJoint ;
DistPointCurve dpc( ptP1, CrvU0, false) ;
DistPointCurve dpc( ptP1, ccPoly0, false) ;
int nFlag = 0 ;
dpc.GetParamAtMinDistPoint( 0, dParam, nFlag) ;
AdjustParamFromApprox( plApproxU0, dParam) ;
dpc.GetMinDistPoint( 0, ptJoint, nFlag) ;
vMatch1b.emplace_back( ptJoint, dParam) ;
if ( icp.GetIntersCount() > 0)
double dParamMinDist = dParam ;
Point3d ptMinDist = ptJoint ;
if ( icp.GetIntersCount() > 0) {
icp.GetIntersPointNearTo( ptP1, ptJoint, dParam) ;
AdjustParamFromApprox( plApproxU0, dParam) ;
if ( Dist( ptP1, ptJoint) > 2 * Dist( ptP1, ptMinDist)) {
ptJoint = ptMinDist ;
dParam = dParamMinDist ;
}
}
else {
;
}
@@ -5011,14 +5082,22 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
Vector3d vtDir ; CrvU0.GetCurve( vPnt0.size() - 1)->GetEndDir( vtDir) ;
IntersCurvePlane icp( ccPoly1, ptP0, vtDir) ;
DistPointCurve dpc( ptP0, CrvU1, false) ;
DistPointCurve dpc( ptP0, ccPoly1, false) ;
int nFlag = 0 ;
dpc.GetMinDistPoint( 0, ptJoint, nFlag) ;
dpc.GetParamAtMinDistPoint( 0, dParam, nFlag) ;
AdjustParamFromApprox( plApproxU1, dParam) ;
vMatch0b.emplace_back( ptJoint, dParam) ;
double dParamMinDist = dParam ;
Point3d ptMinDist = ptJoint ;
if ( icp.GetIntersCount() > 0) {
icp.GetIntersPointNearTo( ptP0, ptJoint, dParam) ;
AdjustParamFromApprox( plApproxU1, dParam) ;
if ( Dist( ptP0, ptJoint) > 2 * Dist( ptP0, ptMinDist)) {
ptJoint = ptMinDist ;
dParam = dParamMinDist ;
}
}
else {
;
@@ -5068,7 +5147,8 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
// tramite due misure diverse della distanza
INTINTVECTOR vMismatch0 ;
INTINTVECTOR vMismatch1 ;
double dMaxDist = Dist( vPnt0[0], vPnt1[0]) / 20 ;
//double dMaxDist = Dist( vPnt0[0], vPnt1[0]) / 20 ;
double dMaxDist = Dist( vPnt0[0], vPnt1[0]) / 3 ;
for( int i = 0 ; i < ssize( vMatch0) ; ++i) {
if( ! AreSamePointEpsilon( vMatch0[i].first, vMatch0b[i].first, dMaxDist)) {
int c = i + 1 ;
@@ -5116,9 +5196,9 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
// verifico la presenza di eventuali "edge" lungo le polyline ( punti di passaggio di un edge e quindi cambi bruschi di direzione della polyline)
BOOLVECTOR vEdgeSplit0, vEdgeSplit1 ;
double dAngTol = 55 ;
GetEdgeSplitByAngTol( plU0, dAngTol, vEdgeSplit0) ;
GetEdgeSplitByAngTol( plU1, dAngTol, vEdgeSplit1) ;
double dAngTolSplit = 55 ;
GetEdgeSplitByAngTol( &CrvU0, dAngTolSplit, vEdgeSplit0) ;
GetEdgeSplitByAngTol( &CrvU1, dAngTolSplit, vEdgeSplit1) ;
int c = 0 ;
double dLastParamMatch0 = 0 ;
@@ -5135,18 +5215,20 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
bool bAdvance = true ;
int m0 = 0, m1 = 0 ; // contatori delle zone di mismatch
// verifico i match effettivi tra le polyline
while ( bAdvance) {
int nPairs = 0 ;
while ( bAdvance && ssize( vPairs) > nPairs) {
nPairs = ssize( vPairs) ;
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)
if( ssize( vMismatch0) > 0) {
while( m0 < ssize( vMismatch0) - 1 && c > vMismatch0[m0].second)
++m0 ;
}
if( ssize(vMismatch1) > 0) {
while( m1 < ssize(vMismatch1) && j > vMismatch1[m1].second)
if( ssize( vMismatch1) > 0) {
while( m1 < ssize( vMismatch1) - 1 && j > vMismatch1[m1].second)
++m1 ;
}
@@ -5165,9 +5247,12 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
// capisco con quale delle due polyline avanzo
bool bAdvance0 = dParam0 < j + 1 + EPS_SMALL ;
bool bAdvance1 = dParam1 < c + 1 + EPS_SMALL ;
// controllo se ho un match biunivoco
bool bPerfectMatch = abs( dParam0 - round( dParam0)) < EPS_SMALL && round( dParam0) == j + 1 &&
abs( dParam1 - round( dParam1)) < EPS_SMALL && round( dParam1) == c + 1 ;
// controllo se ho un match biunivoco ( controllo parametri e punti)
bool bPerfectMatch = ( abs( dParam0 - round( dParam0)) < 10 * EPS_SMALL && round( dParam0) == j + 1 &&
abs( dParam1 - round( dParam1)) < 10 * EPS_SMALL && round( dParam1) == c + 1) ||
( AreSamePointEpsilon( vPnt0[c+1], ptJoint1, 100 * EPS_SMALL) && AreSamePointEpsilon( vPnt1[j+1], ptJoint0, 100 * EPS_SMALL)) ;
if ( bPerfectMatch)
bAdvance0 = true ;
int nSplit1 = vdSplit1.size() ;
int nSplit0 = vdSplit0.size() ;
// se con una polyline sono arrivato alla fine non posso più avanzare
@@ -5188,7 +5273,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
bMismatch = (bMismatch0 && bMismatch1) || (bMismatch0 && ! bAdvance1) || (bMismatch1 && ! bAdvance0);
}
// se trovo che ho uno spigolo allora procedo con la gestione spigoli
else if( vEdgeSplit0[c+1] && vEdgeSplit1[j+1]) {
if ( vEdgeSplit0[c] && vEdgeSplit1[j]) {
// se ho uno spigolo su entrambe le curve forzo l'accoppiamento
bAdvance0 = true ;
bPerfectMatch = true ;
@@ -5197,7 +5282,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
ptJoint0 = vPnt1[j+1] ;
ptJoint1 = vPnt0[c+1] ;
}
else if ( (vEdgeSplit0[c+1] && ! bAdvance1) || (vEdgeSplit1[j+1] && ! bAdvance0)) {
else if ( ( vEdgeSplit0[c] && ! bAdvance1) || (vEdgeSplit1[j] && ! bAdvance0)) {
// da una parte ho uno spigolo e dall'altra non posso avanzare
bAdvance0 = false ;
bAdvance1 = false ;
@@ -5220,8 +5305,8 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
}
else {
// ho un match con una joint esistente
if ( dParam0 - int( dParam0) < EPS_SMALL) {
if ( dParam0 > dLastParamMatch0)
if ( abs( dParam0 - round( dParam0)) < EPS_SMALL) {
if ( dParam0 > dLastParamMatch0 + EPS_SMALL)
vPairs.emplace_back( c + nSplit0, j + nSplit1 + 1) ;
else
vPairs.emplace_back( c + nSplit0, j + nSplit1) ;
@@ -5257,8 +5342,8 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
}
else {
// ho un match con una joint esistente
if ( dParam1 - int( dParam1) < EPS_SMALL) {
if ( dParam1 > dLastParamMatch1)
if ( abs( dParam1 - round( dParam1)) < EPS_SMALL) {
if ( dParam1 > dLastParamMatch1 + EPS_SMALL)
vPairs.emplace_back( c + nSplit0 + 1, j + nSplit1) ;
else
vPairs.emplace_back( c + nSplit0, j + nSplit1) ;
@@ -5281,11 +5366,11 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
//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]) {
if ( vEdgeSplit0[c] && vEdgeSplit1[j]) {
// 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] && ! bMismatch) {
if ( vEdgeSplit0[c] && ! 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
@@ -5308,10 +5393,13 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
dLastParamMatch0 = j - 1 ;
ptLastPointMatch0 = vPnt1[j] ;
}
else
else {
bMismatch = true ;
--c ;
--j ;
}
}
else if ( vEdgeSplit1[j+1] && ! bMismatch) {
else if ( vEdgeSplit1[j] && ! 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
@@ -5334,11 +5422,14 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
dLastParamMatch1 = c - 1 ;
ptLastPointMatch1 = vPnt0[c] ;
}
else
else {
bMismatch = true ;
--c ;
--j ;
}
}
if( ( ! vEdgeSplit0[c+1] && ! vEdgeSplit1[j+1]) || bMismatch) {
if( ( ! vEdgeSplit0[c] && ! vEdgeSplit1[j]) || bMismatch) {
// non ci sono riferimenti per fare un match, quindi li cerco io
///////////OLD VRESION
@@ -5357,7 +5448,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
// identifico la zona in cui ho il mismatch e parametrizzo localmente
//conto quanti punti ho nel mezzo
int c_temp, j_temp ;
int c_temp = c, j_temp = j ;
if( ! bMismatch) {
c_temp = c, j_temp = j ;
bAdvance0 = true ;
@@ -5435,6 +5526,12 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
}
}
}
if ( j_temp == ssize( vMatch1))
--j_temp ;
if ( c_temp == ssize( vMatch0))
-- c_temp ;
// se non sono avanzato, allora mi basta accoppiare i due punti in questione
if( c_temp == c || j_temp == j) {
++c ;