EgtGeomKernel :

- corretta la funzione per il trim di sup. di Bezier con piani, in zone di salto per periodicità e in caso di tagli multipli.
This commit is contained in:
Daniele Bariletti
2024-02-26 09:48:02 +01:00
parent 4bada73c83
commit 3a623996d2
+159 -178
View File
@@ -36,6 +36,7 @@
#include "/EgtDev/Extern/Eigen/Dense"
#include "/EgtDev/Include/EGkCurveComposite.h"
#include "/EgtDev/Include/EGkGeoObjSave.h"
#include <limits>
using namespace std ;
@@ -1647,6 +1648,22 @@ SurfBezier::AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR&
return true ;
}
typedef tuple<int,int,int> TRINT ;
//static bool operator==(TRINT& ta, TRINT& tb)
//{
// return get<0>(ta) == get<0>(tb) && get<1>(ta) == get<1>(tb) && get<2>(ta) == get<2>(tb) ;
//}
template<>
struct hash<TRINT> {
std::size_t operator()(const TRINT& t) const
{
// Compute individual hash values for first, second and third and combine them using XOR and bit shifting:
return ((hash<int>()(get<0>(t))) ^ (hash<int>()(get<1>(t)) << 1) >> 1) ^ (hash<int>()(get<2>(t)) << 1) ;
}
};
//----------------------------------------------------------------------------
bool
SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq)
@@ -1772,12 +1789,12 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq)
}
AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed) ;
}
////debug
//vector<IGeoObj*> vGeoObj ;
//for ( int i = 0 ; i < int(vpCCOpen.size()); ++i )
// vGeoObj.emplace_back(static_cast<IGeoObj*>( vpCCOpen[i]->Clone())) ;
//SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\sphere_openCuts_beforeJoint.nge") ;
////debug
//debug
vector<IGeoObj*> vGeoObj ;
for ( int i = 0 ; i < int(vpCCOpen.size()); ++i )
vGeoObj.emplace_back(static_cast<IGeoObj*>( vpCCOpen[i]->Clone())) ;
SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\sphere_openCuts_beforeJoint.nge") ;
//debug
if ( int( vpCCOpen.size()) != 0) {
// devo verificare se devo giuntare la prima curva aperta con l'ultima
Point3d ptStartOpen, ptEndOpen ;
@@ -1790,188 +1807,162 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq)
}
}
// creo il nuovo bordo usando i loop aperti
//POLYLINEMATRIX vPolygons ;
//comincio a creare la superficie aggiungendo i tagli aperti ai bordi attualmente esistenti
SurfFlatRegionByContours sfrContour ;
if ( int(vpCCOpen.size()) != 0 ) {
//Tree Tree(Point3d( 0, 0, 0), Point3d( m_nSpanU * SBZ_TREG_COEFF, m_nSpanV * SBZ_TREG_COEFF)) ;
//POLYLINEVECTOR vPL ;
//for ( int i = 0 ; i < int(vpCCOpen.size()); ++i ) {
// PolyLine pl ;
// vpCCOpen[i]->ApproxWithLines( LIN_TOL_FINE, ANG_TOL_STD_DEG, ICurveComposite::APL_STD, pl) ;
// vPL.emplace_back( pl) ;
//}
//Tree.AddCutsToRoot( vPL) ;
//////debug
////vector<IGeoObj*> vGeoObj ;
////for ( int k = 0 ; k < int( vPL.size()) ; ++ k) {
//// PtrOwner<ICurveComposite> pCrv( CreateCurveComposite()) ;
//// pCrv->FromPolyLine( vPL[k]) ;
//// vGeoObj.emplace_back( static_cast<IGeoObj*>(Release( pCrv))) ;
////}
////SaveGeoObj( vGeoObj, "D:\\Temp\\inters\\sphere_openCuts.nge") ;
//////debug
//Tree.CreateCellContour( vPolygons) ;
// qui devo aggiungere tutto del codice nuovo per ricostruire in altro modo il nuovo bordo della superficie
// recupero la regione attuale
PtrOwner<ISurfFlatRegion> pNewTrim( GetTrimRegion()->Clone()) ;
unordered_map<TRINT,ICCIVECTOR> mInters ;
// costruisco la mappa delle intersezioni
PtrOwner<ISurfFlatRegion> pNewTrim( CreateBasicSurfFlatRegion()) ;
if ( m_bTrimmed)
pNewTrim.Set( GetTrimRegion()->Clone()) ;
else
pNewTrim.Set( GetSurfFlatRegionRectangle( SBZ_TREG_COEFF * m_nSpanU, SBZ_TREG_COEFF * m_nSpanV)) ;
//debug
PtrOwner<ISurfFlatRegion> pSrfCopy( pNewTrim->Clone()) ;
SaveGeoObj( Release(pSrfCopy), "D:\\Temp\\inters\\sphere_actualTrimRegion.nge") ;
//debug
////debug
//PtrOwner<ICurve> pCrvCopy( pNewTrim->GetLoop(0,0)) ;
//SaveGeoObj( Release(pCrvCopy), "D:\\Temp\\inters\\sphere_actualTrimRegionEdge.nge") ;
////debug
for ( int c = 0 ; c < pNewTrim->GetChunkCount() ; ++c) {
for ( int l = 0 ; l < pNewTrim->GetLoopCount( c) ; ++l) {
for ( int t = 0 ; t < int( vpCCOpen.size()); ++t) {
PtrOwner<ICurve> pLoop( pNewTrim->GetLoop( c, l)) ;
// prima curva è il loop, seconda curva è il loop
IntersCurveCurve icc( *pLoop, *vpCCOpen[t]) ;
if ( icc.GetIntersCount() != 0) {
ICCIVECTOR vICC ;
for ( int i = 0 ; i < int( icc.GetIntersCount()); ++i) {
IntCrvCrvInfo iccInfo ;
icc.GetIntCrvCrvInfo( i, iccInfo) ;
vICC.emplace_back( iccInfo) ;
}
mInters.insert( pair<TRINT,ICCIVECTOR>( TRINT(c,l,t), vICC)) ;
}
}
}
}
// vettore di flag che mi indica quali tagli aperti sono stati aggiunti al nuovo bordo
BOOLVECTOR vbAdded( vpCCOpen.size()) ;
fill(vbAdded.begin(), vbAdded.end(), false) ;
PtrOwner<ICurveComposite> pCCNewEdge( CreateCurveComposite()) ;
PtrOwner<ICurveLine> pCL( CreateCurveLine()) ;
bool bAddedAll = false ;
int nFirstIntersChunck = -1 ;
int nFirstIntersLoop = -1 ;
//bool bAddedAll = false ;
TRINT tiFirstInters ;
double dParamFirstInters = -1 ;
// parto aggiungendo il primo taglio
int nNewToAdd = 0 ;
//while ( ! bAddedAll) {
bool bFirstCurveOfEdge = true ;
while ( nNewToAdd != -1) {
// aggiungo il taglio
PtrOwner<ICurveComposite> pLastCC( vpCCOpen[nNewToAdd]->Clone()) ;
//PtrOwner<ICurveComposite> pLastCC( vpCCOpen[nNewToAdd]->Clone()) ;
pCCNewEdge->AddCurve( Release( vpCCOpen[nNewToAdd])) ;
// aggiorno la lista degli aggiunti
vbAdded[nNewToAdd] = true ;
// ora devo trovare la sua intersezione con un edge
// visto che scorro tutto ogni volta posso almeno evitare il conto se incontro l'edge da cui avevo già trovato lo start
int nChunkE = -1 ;
int nLoopE = -1 ;
int nChunkS = -1 ;
int nLoopS = -1 ;
// scorro tutti i chunk e tutti i loop per trovare l'intersezione
int nInters = 0 ; // per ogni loop devo trovare due intersezioni, una di partenza e una di arrivo
IntCrvCrvInfo iccInfo0 ;
IntCrvCrvInfo iccInfo1 ;
bool bStartInters0 = false ;
for ( int c = 0 ; c < pNewTrim->GetChunkCount() ; ++c) {
for ( int l = 0 ; l < pNewTrim->GetLoopCount( c) ; ++l) {
if ( c == nChunkS && l == nLoopS)
continue ;
PtrOwner<ICurve> pLoop( pNewTrim->GetLoop( c, l)) ;
IntersCurveCurve icc( *pLastCC, *pLoop) ;
if ( icc.GetIntersCount() == 0)
continue ;
if ( icc.GetIntersCount() == 1){
if ( nInters == 0) {
icc.GetIntCrvCrvInfo( 0, iccInfo0) ;
// do per scontato di avere solo intersezioni all'inizio o alla fine del taglio
if ( iccInfo0.IciA->dU < EPS_SMALL ) {
nChunkS = c ;
nLoopS = l ;
bStartInters0 = true ;
}
else {
nChunkE = c ;
nLoopE = l ;
bStartInters0 = false ;
}
}
else if ( nInters == 1) {
icc.GetIntCrvCrvInfo( 1, iccInfo1) ;
// do per scontato di avere solo intersezioni all'inizio o alla fine del taglio
if ( iccInfo0.IciA->dU < EPS_SMALL ) {
nChunkS = c ;
nLoopS = l ;
}
else {
nChunkE = c ;
nLoopE = l ;
// di questo taglio mi salvo il chunk e loop di start e end
TRINT tiStart, tiEnd ;
for (const auto& pair : mInters) {
if ( get<2>(pair.first) == nNewToAdd ) {
for (int p = 0 ; p < int(pair.second.size()) ; ++p) {
if ( pair.second[p].IciB->dU < EPS_SMALL) {
tiStart = pair.first ;
if ( bFirstCurveOfEdge){
// salvo l'inizio del taglio che è la prima curva di questa curva compo
tiFirstInters = pair.first ;
dParamFirstInters = pair.second[p].IciA->dU ; // parametro di intersezione sul loop
bFirstCurveOfEdge = false ;
}
}
else
return false ;
++nInters ;
tiEnd = pair.first ;
}
else if (icc.GetIntersCount() == 2) {
icc.GetIntCrvCrvInfo( 0, iccInfo0) ;
// do per scontato di avere solo intersezioni all'inizio o alla fine del taglio
if ( iccInfo0.IciA->dU < EPS_SMALL ) {
nChunkS = c ;
nLoopS = l ;
bStartInters0 = true ;
}
else {
nChunkE = c ;
nLoopE = l ;
bStartInters0 = false ;
}
icc.GetIntCrvCrvInfo( 1, iccInfo1) ;
// do per scontato di avere solo intersezioni all'inizio o alla fine del taglio
if ( iccInfo1.IciA->dU < EPS_SMALL ) {
nChunkS = c ;
nLoopS = l ;
}
else {
nChunkE = c ;
nLoopE = l ;
}
++nInters ;
++nInters ;
}
// quando ho trovato due intersezioni esco
if ( nInters == 2)
break ;
}
// quando ho trovato due intersezioni esco
if ( nInters == 2)
break ;
}
// se ho appena aggiunto il primo taglio mi salvo il suo start che mi indicherà dove terminare la ricostruzione del bordo
if ( nNewToAdd == 0 ) {
nFirstIntersChunck = nChunkS ;
nFirstIntersLoop = nLoopS ;
dParamFirstInters = bStartInters0 ? iccInfo0.IciB->dU : iccInfo1.IciB->dU ;
}
// devo trovare fino a che punto seguire il loop che ho trovato come prosecuzione del taglio corrente
// devo quindi trovare la prossima intersezione con un taglio
ICCIVECTOR vICCI ;
PtrOwner<ICurve> pLoop( pNewTrim->GetLoop( nChunkE, nLoopE)) ;
for ( int t = 0 ; t < int( vpCCOpen.size()); ++t) {
IntersCurveCurve icc( *pLoop, *vpCCOpen[t]) ;
if ( icc.GetIntersCount() == 0)
continue ;
else if ( icc.GetIntersCount() == 1) {
vICCI.emplace_back() ;
icc.GetIntCrvCrvInfo( 0, vICCI.back()) ;
}
int nInters = -1 ;
double dNextCut = numeric_limits<double>::infinity() ;
double dEndCurrentCut ;
for ( int i = 0 ; i < int( mInters[tiEnd].size()); ++i) {
// se ho trovato l'intersezione con la fine del taglio corrente, salvo il parametro sul loop
if ( mInters[tiEnd][0].IciB->dU > EPS_SMALL)
dEndCurrentCut = mInters[tiEnd][0].IciA->dU ;
}
// se non trovo nessuna altra intersezione prima della fine del loop allora devo ripetere tutto cercando a partire dall'inizio del loop
for ( const auto& pair : mInters) {
if ( get<0>(pair.first) == get<0>(tiEnd) && get<1>(pair.first) == get<1>(tiEnd)) {
for ( int i = 0 ; i < int(pair.second.size()); ++i ) {
// se trovo una nuova intersezione che incontro prima di quella che mi ero salvato precedentemente allora
// mi salvo questa nuova che ho trovato
if ( pair.second[i].IciA->dU < dNextCut && pair.second[i].IciA->dU > dEndCurrentCut) {
dNextCut = pair.second[i].IciA->dU ;
nInters = get<2>(pair.first) ;
}
}
}
}
bool bRestart = false ;
if ( nInters == -1) {
bRestart = true ;
dNextCut = numeric_limits<double>::infinity() ;
for ( const auto& pair : mInters) {
if ( get<0>(pair.first) == get<0>(tiEnd) && get<1>(pair.first) == get<1>(tiEnd)) {
for ( int i = 0 ; i < int(pair.second.size()); ++i ) {
// se trovo una nuova intersezione che incontro prima di quella che mi ero salvato precedentemente allora
// mi salvo questa nuova che ho trovato
if ( pair.second[i].IciA->dU < dNextCut) {
dNextCut = pair.second[i].IciA->dU ;
nInters = get<2>(pair.first) ;
}
}
}
}
}
PtrOwner<ICurve> pLoopTrimmed( pNewTrim->GetLoop( get<0>(tiEnd), get<1>(tiEnd))) ;
// trimmo il loop che ho trovato come prosecuzione del taglio corrente e la aggiungo al taglio
pLoop->TrimStartAtParam(bStartInters0 ? iccInfo0.IciB->dU : iccInfo1.IciB->dU) ;
pLoop->TrimEndAtParam() ;
// se arrivo fino alla fine del loop devo ricominciare a seguire il loop fino ad un'intersezione?
PtrOwner<ICurve> pLoop2( pNewTrim->GetLoop( nChunkE, nLoopE)) ;
pLoop->TrimEndAtParam() ;// appiccico un pezzo dall'inizio
// trovo il prossimo taglio ancora da aggiungere
nNewToAdd = -1 ;
for ( int b = 0 ; b < int(vbAdded.size()) ; ++b ) {
if ( ! vbAdded[b]) {
nNewToAdd = b ;
//vbAdded[b] = true ;
break ;
pLoopTrimmed->TrimEndAtParam( dNextCut) ;
// se non sono ripassato per lo start del loop mi basta aggiungere il pezzo di loop che ho trimmato
if ( ! bRestart) {
pLoopTrimmed->TrimStartAtParam( dEndCurrentCut) ;
pCCNewEdge->AddCurve( Release( pLoopTrimmed)) ;
}
else {
// prima di aggiungere il pezzo che ho identificato devo aggiungere quello che dal parametro corrente mi fa
// andare al punto finale e quindi tornare al punto iniziale
PtrOwner<ICurve> pLoopTrimmed0( pNewTrim->GetLoop( get<0>(tiEnd), get<1>(tiEnd))) ;
pLoopTrimmed0->TrimStartAtParam( dEndCurrentCut) ;
pCCNewEdge->AddCurve( Release(pLoopTrimmed0)) ;
// e poi aggiungo il tratto che ho identificato per arrivare al prossimo taglio
pCCNewEdge->AddCurve( Release(pLoopTrimmed)) ;
}
// se il prossimo taglio identificato è quello da cui sono partito allora aggiungo il bordo ricostruito fino a questo momento
// alla flat region e comincio a costruire un altro bordo
// altrimenti continuo ad aggiungere curve al bordo corrente
if ( nInters == get<2>(tiFirstInters) ) {
pCCNewEdge->Close() ;
sfrContour.AddCurve( Release( pCCNewEdge)) ;
pCCNewEdge.Set( CreateBasicCurveComposite()) ;
bFirstCurveOfEdge = true ;
// trovo il prossimo taglio ancora da aggiungere
nNewToAdd = -1 ;
for ( int b = 0 ; b < int(vbAdded.size()) ; ++b ) {
if ( ! vbAdded[b]) {
nNewToAdd = b ;
//vbAdded[b] = true ;
break ;
}
}
}
//// controllo se ho aggiunto tutti i tagli
//bAddedAll = true ;
//for ( int b = 0 ; b < int( vbAdded.size()) ; ++b ) {
// bAddedAll = bAddedAll && vbAdded[b] ;
//}
else
nNewToAdd = nInters;
}
}
@@ -1992,19 +1983,6 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq)
pNewStm->GetLoops( vPLTria) ;
}
SurfFlatRegionByContours sfrContour ;
// aggiungo i tagli sul bordo
for ( int i = 0 ; i < int( vPolygons.size()); ++i ) {
for ( int j = 0 ; j < int( vPolygons[i].size()); ++j) {
PtrOwner<ICurveComposite> pCC( CreateCurveComposite()) ;
pCC->FromPolyLine( vPolygons[i][j]) ;
////debug
//PtrOwner<ICurveComposite> pCrvCopy( pCC->Clone()) ;
//SaveGeoObj( Release(pCrvCopy), "D:\\Temp\\inters\\sphere_trim_curve2D.nge") ;
////debug
sfrContour.AddCurve( Release( pCC)) ;
}
}
// aggiungo i loop chiusi
for ( int i = 0 ; i < int( vpCCClosed.size()); ++i )
sfrContour.AddCurve( Release( vpCCClosed[i])) ;
@@ -2076,10 +2054,10 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq)
// 1. se il punto è sopra il piano ed era dentro una curva CCW
// 2. se il punto è sotto il piano ed era interno ad una curva CW
//debug
PtrOwner<ISurfFlatRegion> pSrfFR_Copy( pSFR->Clone()) ;
SaveGeoObj( Release(pSrfFR_Copy), "D:\\Temp\\inters\\failed_trim.nge", GDB_SV_BIN) ;
//debug
////debug
//PtrOwner<ISurfFlatRegion> pSrfFR_Copy( pSFR->Clone()) ;
//SaveGeoObj( Release(pSrfFR_Copy), "D:\\Temp\\inters\\failed_trim.nge", GDB_SV_BIN) ;
////debug
// la SetTrimRegion controlla se avevo trim precedenti ed eventualmente fa l'intersezione con lo spazio esistente
if ( ( dDist > 0 && bPos) || ( dDist < 0 && ! bPos)) {
@@ -2211,9 +2189,12 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in
}
}
}
// questa è ancora da sviluppare //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// devo anche tener conto della possibilità che i lati siano collassati in poli
//if ( m_vbPole[0])
// ;
if ( m_vbPole[0] ) {
;
}
// se l'intersezione era su un vertice restituisco le coordinate parametriche del vertice
if ( nIL == 3 ) {
if ( AreSamePointApprox(ptI, vPT[0]))