EtgGeomKernel :

- primo tentativo.
This commit is contained in:
Daniele Bariletti
2025-11-04 14:37:34 +01:00
parent 3bf2972089
commit 1219e9bd80
+313 -167
View File
@@ -42,6 +42,7 @@
#include "/EgtDev/Include/EGkIntervals.h"
#define EIGEN_NO_IO
#include "/EgtDev/Extern/Eigen/Dense"
#include "/EgtDev/Include/EGkGeoObjSave.h"
using namespace std ;
@@ -4380,6 +4381,55 @@ ChangeStartForClosed( PolyLine& plU0, PolyLine& plU1, ICurveComposite* pCrvU0, I
return true ;
}
static bool
GetEdgeSplitByAngTol( const PolyLine& PL, double dAngTol, INTVECTOR& vEdgeSplit)
{
int nPoints = PL.GetPointNbr() ;
vEdgeSplit.clear() ;
vEdgeSplit.resize( nPoints) ;
fill( vEdgeSplit.begin(), vEdgeSplit.end(), false) ;
bool bClosed = PL.IsClosed() ;
// Recupero l'insieme di punti associati alla PolyLine
PNTVECTOR vPoints ; vPoints.reserve( nPoints) ;
Point3d ptCurr = P_INVALID ;
// aggiungo come primo punto il penultimo punto della polyline in modo da analizzare direttamente anche la chiusura ( se è una polyline chiusa)
PL.GetLastPoint( ptCurr) ;
PL.GetPrevPoint( ptCurr) ;
vPoints.emplace_back( ptCurr) ;
bool bFound = PL.GetFirstPoint( ptCurr) ;
while ( bFound) {
vPoints.emplace_back( ptCurr) ;
bFound = PL.GetNextPoint( ptCurr) ;
}
Vector3d vtTanCurr = V_INVALID, vtTanNext = V_INVALID ;
// cos della tolleranza angolare massima
double dCosTol = cos( dAngTol * DEGTORAD) ;
for ( int nP = 0 ; nP < nPoints - 2 ; ++ nP) {
// Recupero il punto corrente e i due punti successivi
Point3d& ptCurr = vPoints[nP] ;
Point3d& ptNext = vPoints[nP + 1] ;
Point3d& ptNextNext = vPoints[nP + 2] ;
// Recupero i versori tangenti definiti dai tre punti ( ptCurr|ptNext e ptNext|ptNextNext)
if ( nP == 0) {
vtTanCurr = ptNext - ptCurr ;
vtTanCurr.Normalize() ;
}
else
vtTanCurr = vtTanNext ;
vtTanNext = ptNextNext - ptNext ; 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[nP] = true ;
}
if( ! bClosed)
vEdgeSplit[0] = false ;
return true ;
}
//----------------------------------------------------------------------------
bool
SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int nRuledType)
@@ -4842,6 +4892,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
bool bIsClosed1 = plU1.IsClosed() ;
Point3d ptP1 ; plU1.GetFirstPoint( ptP1) ;
vector<pair<Point3d,double>> vMatch1 ;
PNTVECTOR vPnt1 ; vPnt1.emplace_back( ptP1) ;
while ( plU1.GetNextPoint( ptP1, true)) {
DistPointCurve dpc( ptP1, CrvU0, false) ;
int nFlag = 0 ;
@@ -4862,9 +4913,11 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
}
vMatch1.push_back( pair<Point3d,double>( ptJoint, dParam)) ;
vPnt1.emplace_back( ptP1) ;
}
Point3d ptP0 ; plU0.GetFirstPoint( ptP0) ;
vector<pair<Point3d,double>> vMatch0 ;
PNTVECTOR vPnt0 ; vPnt0.emplace_back( ptP0) ;
while ( plU0.GetNextPoint( ptP0, true)) {
DistPointCurve dpc( ptP0, CrvU1, false) ;
int nFlag = 0 ;
@@ -4884,163 +4937,247 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
dParam = round( dParam) ;
}
vMatch0.push_back( pair<Point3d,double>( ptJoint, dParam)) ;
vPnt0.emplace_back( ptP0) ;
}
// 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 ;
GetEdgeSplitByAngTol( plU0, 15, vEdgeSplit0) ;
GetEdgeSplitByAngTol( plU1, 15, vEdgeSplit1) ;
int nAtStart1 = 0 ; // match ripetuti dalla curva U0 allo start della curva U1
int nAtEnd1 = 0 ;
plU0.GetFirstPoint( ptP0) ;
int c = 0 ;
int nRep0 = 0 ; // match interni consecutivi uguali di punti della curva U0 con punti della curva U1
int nRep1 = 0 ;
double dLastParamMatch = 0 ;
Point3d ptLastPointMatch = ptP0 ;
double dLastParamMatch0 = 0 ;
plU0.GetFirstPoint( ptP0) ;
Point3d ptLastPointMatch0 = ptP0 ;
BOOLVECTOR vbRep0( nSpanU0) ;
INTVECTOR vnAddedOrNextIsRep0 ; // 0 non Rep, 1 Rep, 2 Next is Rep ;
DBLVECTOR vdSplit0 ;
fill( vbRep0.begin(), vbRep0.end(), false) ;
while ( plU0.GetNextPoint( ptP0, true)) {
// devo salvarmi se matcho più punti con lo start o l'end della curva totale
double dParam = vMatch0[c].second ;
Point3d ptJoint = vMatch0[c].first ; // nuovo punto che si vorrebbe aggiungere sulla curva U1
if( bIsClosed1 && dParam > nSpanU1 - EPS_SMALL)
dParam = 0 ;
vMatch0[c].second = dParam ;
// ho match con lo start
if ( dParam < EPS_SMALL) {
++nAtStart1 ;
vbRep0[c] = true ;
++c ;
continue ;
}
// ho un match con l'end
else if ( dParam > nSpanU1 - EPS_SMALL ) {
vbRep0[c] = nAtEnd1 == 0 ? false : true ;
vbRep0.back() = true ;
++ nAtEnd1 ;
++c ;
continue ;
}
if ( dParam <= dLastParamMatch || AreSamePointApprox( ptJoint, ptLastPointMatch)) {
dParam = dLastParamMatch ;
vbRep0[c] = true ;
++ nRep0 ;
++c ;
continue ;
}
else {
dLastParamMatch = dParam ;
ptLastPointMatch = ptJoint ;
// ho un match con una joint esistente
if( dParam - int( dParam) < EPS_SMALL) {
++c ;
continue ;
}
vdSplit0.push_back( dParam) ;
// verifico se ho un match per questo punto
// in tal caso vuol dire che sto creando una ripetizione nRep1
int nCase = 0 ;
for ( int j = 0 ; j < int( vMatch1.size()) ; ++j) {
if ( abs(vMatch1[j].second - (c + 1)) < EPS_SMALL) {
// devo però verificare che non ci sia un match successivo, perché in quel caso non ho una ripetizione
bool bFoundMatch = false ;
for ( int z = int( round(vMatch1[j].second)) ; z < int( vMatch0.size()) ; ++z) {
if ( abs( vMatch0[z].second - ( j + 1 )) < EPS_SMALL ) {
bFoundMatch = true ;
break ;
}
}
if ( ! bFoundMatch) {
++nRep1 ;
// capisco se il punto è rep o se lo è il suo successivo
if( j + 1 < dParam)
nCase = 1 ;
else
nCase = 2 ;
}
break ;
}
}
vnAddedOrNextIsRep0.push_back( nCase) ;
}
++c ;
}
int nAtStart0 = 0 ;
int nAtEnd0 = 0 ;
int j = 0 ;
double dLastParamMatch1 = 0 ;
plU1.GetFirstPoint( ptP1) ;
c = 0 ;
dLastParamMatch = 0 ;
ptLastPointMatch = ptP1 ;
Point3d ptLastPointMatch1 = ptP1 ;
INTVECTOR vnAddedOrNextIsRep1 ; // 0 non Rep, 1 Rep, 2 Next is Rep ;
DBLVECTOR vdSplit1 ;
BOOLVECTOR vbRep1( plU1.GetPointNbr() - 1) ;
fill( vbRep1.begin(), vbRep1.end(), false) ;
while ( plU1.GetNextPoint( ptP1, true)) {
double dParam = vMatch1[c].second ;
Point3d ptJoint = vMatch1[c].first ;
if ( bIsClosed0 && dParam > nSpanU0 - EPS_SMALL)
dParam = 0 ;
// ho un match con lo start
if ( dParam < EPS_SMALL) {
++nAtStart0 ;
vbRep1[c] = true ;
++c ;
continue ;
bool bAdvance = true ;
// verifico i match effettivi tra le polyline
while( bAdvance) {
double dParam0 = vMatch0[c].second ;
Point3d ptJoint0 = vMatch0[c].first ;
double dParam1 = vMatch1[j].second ;
Point3d ptJoint1 = vMatch1[j].first ;
if( bIsClosed1 && dParam0 > nSpanU1 - EPS_SMALL) {
dParam0 = 0 ;
vMatch0[c].second = dParam0 ;
}
// ho un match con l'end
else if ( dParam > nSpanU0 - EPS_SMALL ) {
vbRep1[c] = nAtEnd0 == 0 ? false : true ;
vbRep1.back() = true ;
++ nAtEnd0 ;
++c ;
continue ;
if( bIsClosed0 && dParam1 > nSpanU0 - EPS_SMALL) {
dParam1 = 0 ;
vMatch1[j].second = dParam1 ;
}
if ( dParam <= dLastParamMatch || AreSamePointApprox( ptJoint, ptLastPointMatch)) {
dParam = dLastParamMatch ;
vbRep1[c] = true ;
++ nRep1 ;
++c ;
continue ;
}
else {
dLastParamMatch = dParam ;
ptLastPointMatch = ptJoint ;
// ho un match con una joint esistente
if( dParam - int( dParam) < EPS_SMALL) {
// capisco con quale delle due polyline avanzo
bool bAdvance0 = dParam0 < j + 1 + EPS_SMALL ;
bool bAdvance1 = dParam1 < c + 1 + EPS_SMALL ;
if ( bAdvance0) {
// ho match con lo start
if ( dParam0 < EPS_SMALL) {
++nAtStart1 ;
vbRep0[c] = true ;
++c ;
continue ;
}
vdSplit1.push_back( dParam) ;
// verifico se ho un match per questo punto
// in tal caso vuol dire che sto creando una ripetizione nRep0
int nCase = 0 ;
for ( int j = 0 ; j < int( vMatch0.size()) ; ++j) {
if ( abs(vMatch0[j].second - (c + 1)) < EPS_SMALL) {
// devo però verificare che non ci sia un match successivo, perché in quel caso non ho una ripetizione
bool bFoundMatch = false ;
for ( int z = int( round(vMatch0[j].second)) ; z < int( vMatch1.size()) ; ++z) {
if ( abs( vMatch1[z].second - ( j + 1 )) < EPS_SMALL ) {
bFoundMatch = true ;
// ho un match con l'end
else if ( dParam0 > nSpanU1 - EPS_SMALL ) {
vbRep0[c] = nAtEnd1 == 0 ? false : true ;
vbRep0.back() = true ;
++ nAtEnd1 ;
++c ;
continue ;
}
if ( dParam0 <= dLastParamMatch0 || AreSamePointApprox( ptJoint0, ptLastPointMatch0)) {
dParam0 = dLastParamMatch0 ;
vbRep0[c] = true ;
++ nRep0 ;
++c ;
continue ;
}
else {
dLastParamMatch0 = dParam0 ;
ptLastPointMatch0 = ptJoint0 ;
// ho un match con una joint esistente
if( dParam0 - int( dParam0) < EPS_SMALL) {
;
}
// altrimenti lo aggiungo
else {
vdSplit0.push_back( dParam0) ;
// verifico se ho un match per questo punto
// in tal caso vuol dire che sto creando una ripetizione nRep1
int nCase = 0 ;
for ( int k = 0 ; k < int( vMatch1.size()) ; ++k) {
if ( abs(vMatch1[k].second - (c + 1)) < EPS_SMALL) {
// devo però verificare che non ci sia un match successivo, perché in quel caso non ho una ripetizione
bool bFoundMatch = false ;
for ( int z = int( round(vMatch1[k].second)) ; z < int( vMatch0.size()) ; ++z) {
if ( abs( vMatch0[z].second - ( k + 1 )) < EPS_SMALL ) {
bFoundMatch = true ;
break ;
}
}
if ( ! bFoundMatch) {
++nRep1 ;
// capisco se il punto è rep o se lo è il suo successivo
if( j + 1 < dParam0)
nCase = 1 ;
else
nCase = 2 ;
}
break ;
}
}
if ( ! bFoundMatch) {
++nRep0 ;
// capisco se il punto è rep o se lo è il suo successivo
if( j + 1 < dParam)
nCase = 1 ;
else
nCase = 2 ;
}
break ;
vnAddedOrNextIsRep0.push_back( nCase) ;
}
}
vnAddedOrNextIsRep1.push_back( nCase) ;
++c ;
}
++c ;
if ( bAdvance1) {
// ho un match con lo start
if ( dParam1 < EPS_SMALL) {
++nAtStart0 ;
vbRep1[j] = true ;
++j ;
continue ;
}
// ho un match con l'end
else if ( dParam1 > nSpanU0 - EPS_SMALL ) {
vbRep1[j] = nAtEnd0 == 0 ? false : true ;
vbRep1.back() = true ;
++ nAtEnd0 ;
++j ;
continue ;
}
if ( dParam1 <= dLastParamMatch1 || AreSamePointApprox( ptJoint1, ptLastPointMatch1)) {
dParam1 = dLastParamMatch1 ;
vbRep1[j] = true ;
++ nRep1 ;
++j ;
continue ;
}
else {
dLastParamMatch1 = dParam1 ;
ptLastPointMatch1 = ptJoint1 ;
// ho un match con una joint esistente
if( dParam1 - int( dParam1) < EPS_SMALL) {
;
}
//altrimenti lo aggiungo
else {
vdSplit1.push_back( dParam1) ;
// verifico se ho un match per questo punto
// in tal caso vuol dire che sto creando una ripetizione nRep0
int nCase = 0 ;
for ( int k = 0 ; k < int( vMatch0.size()) ; ++k) {
if ( abs(vMatch0[k].second - (j + 1)) < EPS_SMALL) {
// devo però verificare che non ci sia un match successivo, perché in quel caso non ho una ripetizione
bool bFoundMatch = false ;
for ( int z = int( round(vMatch0[k].second)) ; z < int( vMatch1.size()) ; ++z) {
if ( abs( vMatch1[z].second - ( k + 1 )) < EPS_SMALL ) {
bFoundMatch = true ;
break ;
}
}
if ( ! bFoundMatch) {
++nRep0 ;
// capisco se il punto è rep o se lo è il suo successivo
if( k + 1 < dParam1)
nCase = 1 ;
else
nCase = 2 ;
}
break ;
}
}
vnAddedOrNextIsRep1.push_back( nCase) ;
}
}
++j ;
}
if( ! bAdvance0 && ! bAdvance1) {
// sono arrivato ad un caso di incrocio!!
//1. verifico se sono vicino ad uno spigolo su entrambe le curve
//2. verifico se calcolando i punti bonus con i piani risolvo
//3. sennò aggiungo qualche rep
bool bEdgeFoundOnSecond = false ;
if( vEdgeSplit0[c+1] && vEdgeSplit1[j+1]) {
// questo caso non è previsto !!!!!
;
}
if( vEdgeSplit0[c+1]) {
//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
double dDist = 0 ;
double dMaxDist = Dist( vPnt0[c+1], vMatch0[c].first) * 2 ;
int j_temp = j + 1 ;
while( dDist < dMaxDist) {
if ( vEdgeSplit1[j_temp]) {
bEdgeFoundOnSecond = true ;
break ;
}
++j_temp ;
dDist = Dist( vPnt0[c+1], vPnt1[j_temp]) ;
}
if( bEdgeFoundOnSecond) {
// collego i due punti in cui ho il passaggio di un edge e tutti i punti che restano non accoppiati li metto come Rep
for( int i = j_temp ; i > j ; --i)
vbRep1[i] = true ;
j = j_temp ;
dLastParamMatch0 = j ;
ptLastPointMatch0 = vPnt1[j] ;
}
}
if( vEdgeSplit1[j+1]) {
//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
double dDist = 0 ;
double dMaxDist = Dist( vPnt1[j+1], vMatch1[j].first) * 2 ;
int c_temp = c + 1 ;
while( dDist < dMaxDist) {
if ( vEdgeSplit0[c_temp]) {
bEdgeFoundOnSecond = true ;
break ;
}
++c_temp ;
dDist = Dist( vPnt1[j+1], vPnt0[c_temp]) ;
}
if( bEdgeFoundOnSecond) {
// collego i due punti in cui ho il passaggio di un edge e tutti i punti che restano non accoppiati li metto come Rep
for( int i = c_temp ; i > c ; --i)
vbRep0[i] = true ;
c = c_temp ;
dLastParamMatch1 = c ;
ptLastPointMatch1 = vPnt0[c] ;
}
}
bool bPlaneDist = false ;
if( ! bEdgeFoundOnSecond) {
// provo col piano b: cerco degli accoppiamenti usando i piani anziché il mindist
;
}
if( ! bPlaneDist) {
// cerco di capire come settare i punti Rep
;
}
}
bAdvance = c < int(vMatch0.size()) - 1 || j < int(vMatch1.size()) - 1 ;
}
// applico effettivamente gli split e aggiungo gli elementi ai vettori vbRep
@@ -5096,44 +5233,42 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
}
}
//debug
INTVECTOR vCorresp0 ;
INTVECTOR vCorresp1 ;
vCorresp0.push_back( 0) ;
vCorresp1.push_back( 0) ;
plU0.GetFirstPoint(ptP0) ;
int cc = 0 ;
while( plU0.GetNextPoint(ptP0)) {
bool bFound = false ;
while( ! bFound) {
Point3d ptEnd ; CrvU0.GetCurve(cc)->GetEndPoint( ptEnd) ;
if( AreSamePointApprox( ptP0, ptEnd)) {
vCorresp0.push_back( cc + 1) ;
bFound = true ;
}
++cc ;
}
}
plU1.GetFirstPoint(ptP1) ;
cc = 0 ;
while( plU1.GetNextPoint(ptP1)) {
bool bFound = false ;
while( ! bFound) {
Point3d ptEnd ; CrvU1.GetCurve(cc)->GetEndPoint( ptEnd) ;
if( AreSamePointApprox( ptP1, ptEnd)) {
vCorresp1.push_back( cc + 1) ;
bFound = true ;
}
++cc ;
}
}
//debug
nSpanU0 = CrvU0.GetCurveCount() ;
nSpanU1 = CrvU1.GetCurveCount() ;
//aggiusto i vettori delle ripetizioni in modo in modo che non arrivino mai ad essere contemporaneamente true
int nAddedSpan = 0 ;
int nCrv0 = 0 ;
int nCrv1 = 0 ;
while ( nAddedSpan < nSpanU0 + nAtStart0 + nAtEnd0 + nRep1) {
if ( nCrv0 >= nSpanU0)
nCrv0 = nSpanU0 - 1;
if ( nCrv1 >= nSpanU1)
nCrv1 = nSpanU1 - 1;
bool bRep0 = vbRep0[nCrv0] ;
bool bRep1 = vbRep1[nCrv1] ;
if ( bRep0 && bRep1 ) {
vbRep0[nCrv0] = false ;
bRep0 = false ;
vbRep1[nCrv1] = false ;
bRep1 = false ;
-- nRep0 ;
-- nRep1 ;
}
if ( ! bRep0 || nCrv1 == nSpanU1 - 1)
++ nCrv1 ;
if ( ! bRep1 || nCrv0 == nSpanU0 - 1)
++ nCrv0 ;
++nAddedSpan ;
}
// se non sono arrivato all'ultima curva su U0 o U1 vuol dire che ho creato delle ripetizioni che non ho contato prima
if( nCrv1 < nSpanU1) {
nRep1 += nSpanU1 - nCrv1 ;
for ( int z = int( vbRep1.size() - 1) ; z >= nCrv1 ; --z)
vbRep1[z] = true ;
}
if( nCrv0 < nSpanU0) {
nRep0 += nSpanU0 - nCrv0 ;
for ( int z = int( vbRep0.size() - 1) ; z >= nCrv0 ; --z)
vbRep0[z] = true ;
}
// trovo il numero di span che dovrà avere la superficie
// ( numero di sottocurve che compongono la U0 + tutte le ripetizioni dei match di punti della curva U1 con i punti di U0)
@@ -5147,9 +5282,9 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
Init( nDegU, nDegV, nSpanU, nSpanV, bRat) ;
// aggiungo i punti di controllo scorrendo in contemporanea le due curve
nAddedSpan = 0 ;
nCrv0 = 0 ;
nCrv1 = 0 ;
int nAddedSpan = 0 ;
int nCrv0 = 0 ;
int nCrv1 = 0 ;
bool bLast0 = false ;
bool bLast1 = false ;
@@ -5194,6 +5329,17 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
++ nAddedSpan ;
}
//debug
ICURVEPOVECTOR vCrv ;
GetAllPatchesIsocurves( false, vCrv) ;
vector<IGeoObj*> vGeo ;
for( int i = 0 ; i < int(vCrv.size()); ++i)
vGeo.push_back( vCrv[i]) ;
vector<Color> vCol( vGeo.size()) ;
fill( vCol.begin(), vCol.end(), Color( 255, 0 ,128)) ;
SaveGeoObj( vGeo, vCol, "D:/Temp/bezier/ruled/isoCurves.nge") ;
//debug
return bOk ;
}
else if ( RLT_B_LENPAR ) {