EgtGeomKernel :

- correzioni al cut di una superficie Bezier.
This commit is contained in:
Daniele Bariletti
2024-03-01 11:37:12 +01:00
parent 7a2af0b5f2
commit 96ea6bc73e
4 changed files with 231 additions and 92 deletions
+1
View File
@@ -256,4 +256,5 @@ FilterLineSurfBzInters( const ILSBIVECTOR& vInfo, INTDBLVECTOR& vInters)
// passo alla successiva
++ j ;
}
return true ;
}
+221 -86
View File
@@ -36,6 +36,7 @@
#include "/EgtDev/Extern/Eigen/Dense"
#include "/EgtDev/Include/EGkCurveComposite.h"
#include <limits>
#include "/EgtDev/Include/EGkGeoObjSave.h"
using namespace std ;
@@ -1620,15 +1621,8 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC) const
const ICurve* pCrv0 = pCC->GetCurve( 0) ;
PolyLine pl ;
Point3d pt3D, pt2D ; pCrv0->GetStartPoint( pt3D) ;
DistPointSurfTm distPtStm0( pt3D, *GetAuxSurf()) ;
// aggiungo il primo punto
int nTriaIndex ; distPtStm0.GetMinDistTriaIndex( nTriaIndex) ;
// passo anche i riferimenti del prossimo punto
Point3d pt3DEnd ; pCrv0->GetEndPoint( pt3DEnd) ;
DistPointSurfTm distPtStm0End( pt3DEnd, *GetAuxSurf()) ;
int nTriaIndexNext = -1 ;
distPtStm0End.GetMinDistTriaIndex( nTriaIndexNext) ;
if ( ! UnprojectPointFromStm(nTriaIndex, pt3D, pt2D, 5, pt3DEnd, nTriaIndexNext))
if ( ! UnprojectPoint(pt3D, pt2D, pt3DEnd))
return nullptr ;
//if ( ! UnprojectPointFromStm(nTriaIndex, pt3D, pt2D)) {
// Point3d pt3DEnd ; pCrv0->GetEndPoint( pt3DEnd) ;
@@ -1641,17 +1635,13 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC) const
//}
pl.AddUPoint( 0, pt2D) ;
// aggiungo tutti i successivi
int nTriaIndexPrev = nTriaIndex ;
for ( int i = 0 ; i < int( pCC->GetCurveCount()) ; ++i) {
const ICurve* pCrv = pCC->GetCurve( i) ;
Point3d pt3DPrev = pt3D ;
pCrv->GetEndPoint( pt3D) ;
DistPointSurfTm distPtStm( pt3D, *GetAuxSurf()) ;
distPtStm.GetMinDistTriaIndex( nTriaIndex) ;
if ( ! UnprojectPointFromStm( nTriaIndex, pt3D, pt2D, 5, pt3DPrev, nTriaIndexPrev))
if ( ! UnprojectPoint( pt3D, pt2D, pt3DPrev))
return nullptr ;
pl.AddUPoint( i, pt2D) ;
nTriaIndexPrev = nTriaIndex ;
}
PtrOwner<ICurveComposite> pCC2D ( CreateCurveComposite()) ;
pCC2D->FromPolyLine( pl) ;
@@ -1660,8 +1650,12 @@ SurfBezier::UnprojectCurveFromStm( const ICurveComposite* pCC) const
//----------------------------------------------------------------------------
bool
SurfBezier::AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, double dToler)
SurfBezier::AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, ICRVCOMPOPOVECTOR& vpCC3D, double dToler)
{
//debug
vpCC3D.emplace_back( pCrvCompo->Clone()) ;
//debug
// se lunghezza curva inferiore a 5 volte la tolleranza, la ignoro e sposto il punto finale nel punto di fine della curva che sto ignorando
double dCrvLen ;
if ( ! pCrvCompo->GetLength( dCrvLen) || dCrvLen < 5. * dToler)
@@ -1717,6 +1711,11 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq)
// le curve 3d le trasformo in curve 2d e le aggiungo alle curve di trim
// accorpo eventuali triangoli adiacenti ed estraggo i loop delle regioni ottenute; questi vengono poi portati in 2d e aggiunti alle curve di trim
////debug
//PtrOwner<ISurfFlatRegion> pSFRTrim ( GetTrimRegion()->Clone()) ;
//SaveGeoObj( Release(pSFRTrim), "D:\\Temp\\inters\\original_trim.nge", GDB_SV_BIN) ;
////debug
PNTVECTOR vPnt ;
BIPNTVECTOR vBPnt ;
TRIA3DVECTOR vTria ;
@@ -1731,6 +1730,16 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq)
//////i tagli multipli////////////////////////////////////////////////
IntersPlaneSurfTm( plPlane, *GetAuxSurf(), vPnt, vBPnt, vTria) ;
////debug
//vector<IGeoObj*> vGeoObj3 ;
//for ( int i = 0 ; i < int(m_vCCEdge.size()); ++i ) {
// if ( ! m_vCCEdge[i]->IsValid())
// continue ;
// vGeoObj3.emplace_back(static_cast<IGeoObj*>( m_vCCEdge[i]->Clone())) ;
//}
//SaveGeoObj( vGeoObj3, "D:\\Temp\\inters\\Edge3D.nge") ;
////debug
// concateno le curve 3d
ChainCurves chainC ;
double dToler = EPS_SMALL ;
@@ -1750,6 +1759,9 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq)
// separo tra loop chiusi, interni allo spazio parametrico e loop passanti che tagliano lo spazio intersecando i bordi
ICRVCOMPOPOVECTOR vpCCOpen ;
ICRVCOMPOPOVECTOR vpCCClosed ;
//debug
ICRVCOMPOPOVECTOR vpCC3D ;
//debug
while ( chainC.GetChainFromNear( ptNear, false, vId)) {
// creo una curva composita
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
@@ -1798,23 +1810,53 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq)
else if ( icc3.GetIntersCount() != 0)
icc3.GetIntCrvCrvInfo( 0, iccInfo) ;
if ( i == 48 ) {
//debug
vector<IGeoObj*> vGeoObj5 ;
vGeoObj5.emplace_back(static_cast<IGeoObj*>( pLine->Clone())) ;
vGeoObj5.emplace_back(static_cast<IGeoObj*>( m_vCCEdge[1]->GetCurve(12)->Clone())) ;
SaveGeoObj( vGeoObj5, "D:\\Temp\\inters\\inters3D_error.nge") ;
//debug
}
ICurveLine* pCLPart1 ( CreateCurveLine()) ;
// spezzo la linea che avrei dovuto inserire, facendola finire dove ho l'intersezione con un edge della cella root
Vector3d vtDir ; pLine->GetStartDir( vtDir) ;
Point3d ptBeforeTheEdge = iccInfo.IciA[0].ptI - vtDir * EPS_SMALL * EPS_SMALL ;
pCLPart1->Set( ptStart, ptBeforeTheEdge) ;
pCrvCompo->AddCurve( pCLPart1, true, dToler) ;
bAdded = false ;
AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed) ;
pCrvCompo->Clear() ;
// comincio a costruire una nuova curva partendo oltre l'edge che ho appena attraversato
// probabilmente mi conviene spostare di poco il punto in modo da aiutare la funzione di Unproject
//ICurveLine* pCLPart2 ( CreateCurveLine()) ;
Point3d ptBeyondTheEdge = iccInfo.IciA[0].ptI + vtDir * EPS_SMALL * EPS_SMALL;
//pCLPart2->Set( ptBeyondTheEdge, ptEnd) ;
//bAdded = bAdded && pCrvCompo->AddCurve( pCLPart2, true, dToler) ;
ptNear = ptBeyondTheEdge ;
bPrevLineThroughEdge = true ;
// se l'intersezione non coincide con l'inizio o la fine allora spezzo la curva, salvando quella creata fino ad ora e cominciandone una nuova
// a partire dall'intersezione
if ( ! AreSamePointApprox( ptStart, ptBeforeTheEdge) && ! AreSamePointApprox( ptEnd, ptBeforeTheEdge)) {
pCLPart1->Set( ptStart, ptBeforeTheEdge) ;
pCrvCompo->AddCurve( pCLPart1, true, dToler) ;
bAdded = false ;
if ( ! AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed, vpCC3D))
return false ;
pCrvCompo->Clear() ;
// comincio a costruire una nuova curva partendo oltre l'edge che ho appena attraversato
// probabilmente mi conviene spostare di poco il punto in modo da aiutare la funzione di Unproject
//ICurveLine* pCLPart2 ( CreateCurveLine()) ;
Point3d ptBeyondTheEdge = iccInfo.IciA[0].ptI + vtDir * EPS_SMALL * EPS_SMALL;
//pCLPart2->Set( ptBeyondTheEdge, ptEnd) ;
//bAdded = bAdded && pCrvCompo->AddCurve( pCLPart2, true, dToler) ;
ptNear = ptBeyondTheEdge ;
bPrevLineThroughEdge = true ;
--i ;
}
else if ( AreSamePointApprox( ptStart, ptBeforeTheEdge)) {
// se l'intersezione era all'inizio allora aggiungo e basta
bAdded = bAdded && pCrvCompo->AddCurve( pLine, true, dToler) ;
ptNear = ( bAdded ? ptEnd : ptStart) ;
}
else if ( AreSamePointApprox( ptEnd, ptBeforeTheEdge)) {
// se invece era alla fine, aggiungo, ma devo comunque spezzare, salvando la curva attuale e cominciarne una nuova
// indipendente dall'interesezione
bAdded = bAdded && pCrvCompo->AddCurve( pLine, true, dToler) ;
if ( ! AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed, vpCC3D))
return false ;
pCrvCompo->Clear() ;
ptNear = ( bAdded ? ptEnd : ptStart) ;
}
}
}
// sennò procedo normalmente aggiungendo il punto
@@ -1824,36 +1866,75 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq)
bPrevLineThroughEdge = false ;
}
}
AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed) ;
if ( ! AddCurveCompoToCuts( pCrvCompo, vpCCOpen, vpCCClosed, vpCC3D))
return false ;
}
////debug
//vector<IGeoObj*> vGeoObj4 ;
//for ( int i = 0 ; i < int(vpCC3D.size()); ++i )
// vGeoObj4.emplace_back(static_cast<IGeoObj*>( vpCC3D[i]->Clone())) ;
//SaveGeoObj( vGeoObj4, "D:\\Temp\\inters\\inters3D.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
//// devo verificare se devo giuntare la prima curva aperta con l'ultima
//Point3d ptStartOpen, ptEndOpen ;
//vpCCOpen.front()->GetStartPoint( ptStartOpen) ;
//vpCCOpen.back()->GetEndPoint( ptEndOpen) ;
//if ( AreSamePointApprox(ptStartOpen, ptEndOpen) ) {
// vpCCOpen.back()->AddCurve( vpCCOpen.front()) ;
// Release( vpCCOpen[0]) ;
// vpCCOpen.erase( vpCCOpen.begin()) ;
//}
// devo controllare se devo giuntare queste curve aperte tra loro
Point3d ptStartOpen, ptEndOpen ;
vpCCOpen.front()->GetStartPoint( ptStartOpen) ;
vpCCOpen.back()->GetEndPoint( ptEndOpen) ;
if ( AreSamePointApprox(ptStartOpen, ptEndOpen) ) {
vpCCOpen.back()->AddCurve( vpCCOpen.front()) ;
Release( vpCCOpen[0]) ;
vpCCOpen.erase( vpCCOpen.begin()) ;
for ( int c = int(vpCCOpen.size()) ; c > 0 ; --c ) {
// controllo se la fine di questa curva coincide con lo start di un'altra
}
}
////debug
//vector<IGeoObj*> vGeoObj2 ;
//for ( int i = 0 ; i < int(vpCCOpen.size()); ++i )
// vGeoObj2.emplace_back(static_cast<IGeoObj*>( vpCCOpen[i]->Clone())) ;
//SaveGeoObj( vGeoObj2, "D:\\Temp\\inters\\sphere_openCuts_AfterJoint.nge") ;
////debug
//comincio a creare la superficie aggiungendo i tagli aperti ai bordi attualmente esistenti
SurfFlatRegionByContours sfrContour ;
if ( int(vpCCOpen.size()) != 0 ) {
// qui devo aggiungere tutto del codice nuovo per ricostruire in altro modo il nuovo bordo della superficie
// recupero la regione attuale
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
// costruisco la mappa delle intersezioni, trovando tutte le intersezioni tra i trim e i loop dei vari chunk della falr region
unordered_map<TRINT,ICCIVECTOR> mInters ;
//chunk
for ( int c = 0 ; c < pNewTrim->GetChunkCount() ; ++c) {
// loop
for ( int l = 0 ; l < pNewTrim->GetLoopCount( c) ; ++l) {
bool bHasSomeIntersection = false ;
// trim
for ( int t = 0 ; t < int( vpCCOpen.size()); ++t) {
PtrOwner<ICurve> pLoop( pNewTrim->GetLoop( c, l)) ;
// prima curva è il loop, seconda curva è il loop
@@ -1866,8 +1947,12 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq)
vICC.emplace_back( iccInfo) ;
}
mInters.insert( pair<TRINT,ICCIVECTOR>( TRINT(c,l,t), vICC)) ;
bHasSomeIntersection = true ;
}
}
// se un trim non fa intersezioni allora c'è qualcosa di sbagliato
if ( ! bHasSomeIntersection)
return false ;
}
}
@@ -2102,6 +2187,11 @@ 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
// la SetTrimRegion controlla se avevo trim precedenti ed eventualmente fa l'intersezione con lo spazio esistente
if ( ( dDist > 0 && bPos) || ( dDist < 0 && ! bPos)) {
if ( ! SetTrimRegion( *pSFR, false) || ! m_pTrimReg->IsValid())
@@ -2112,6 +2202,11 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq)
return false ;
}
////debug
//PtrOwner<ISurfFlatRegion> pSrfFR_Copy( GetTrimRegion()->Clone()) ;
//SaveGeoObj( Release(pSrfFR_Copy), "D:\\Temp\\inters\\after_trimUpdate.nge", GDB_SV_BIN) ;
////debug
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
@@ -2122,20 +2217,29 @@ SurfBezier::Cut( const Plane3d& plPlane, bool bSaveOnEq)
bool
SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL) const
{
return UnprojectPointFromStm( nT, ptI, ptSP, nIL, Point3d(-1,-1,-1), -1) ;
return UnprojectPointFromStm( nT, ptI, ptSP, nIL, Point3d(-1,-1,-1)) ;
}
//----------------------------------------------------------------------------
bool
SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL, const Point3d& ptIPrevOrNext, int nTPrev) const
SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL, const Point3d& ptIPrevOrNext) const
{
// dato un punto sulla trimesh ausiliaria, ne ricavo le coordinate parametriche
const ISurfTriMesh* pSurfTm = GetAuxSurf() ;
int nTriaIndex = nT ;
if ( nT == -1) {
DistPointSurfTm distPtStm0( ptI, *pSurfTm) ;
distPtStm0.GetMinDistTriaIndex( nTriaIndex) ;
}
// aggiungo il primo punto
// devo subito capire se sono in un polo o no
// se sono in polo e mi hanno passato un punto precedente allora devo prendere il triangolo di quel punto
bool bIsPole = false ;
int nInters = 0 ;
INTVECTOR vInters ;
// se il vettore dei poli non è stato riempito vuol dire che quando è stata creata la superficie non è stata chiamata la funzione CalcPoles
if ( int( m_vbPole.size()) == 0)
return false ;
if ( m_vbPole[0] || m_vbPole[1] || m_vbPole[2] || m_vbPole[3]) {
for ( int c = 0 ; c < 4 ; ++c) {
if ( ! m_vCCEdge[c]->IsValid()) {
@@ -2169,17 +2273,23 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in
// return false ;
// visto che sono in un polo devo verificare di aver ricevuto il triangolo giusto
// mi sposto verso il punto successivo o precedente e ricalcolo il triangolo di appartenenza
// se è stato passato il punto successivo o precedente mi sposto verso quello e ricalcolo il triangolo di appartenenza
if ( AreSamePointExact( ptIPrevOrNext, Point3d(-1,-1,-1))){ // controllo che non sia quello definito di default
DistPointSurfTm dPtStm( ptIPrevOrNext, *pSurfTm) ;
double dDist = INFINITO ; dPtStm.GetDist( dDist) ;
if ( dDist > 0.1)
return false ;
}
Point3d ptI2 = ptI + ( ptIPrevOrNext - ptI) * EPS_SMALL ;
// ricalcolo il triangolo di appartenenza
DistPointSurfTm dPtStm( ptI2, *pSurfTm) ;
dPtStm.GetMinDistTriaIndex( nT) ;
dPtStm.GetMinDistTriaIndex( nTriaIndex) ;
}
}
// recupero i dati dei vertici del triangolo che fa intersezione
int nVert[3] ;
pSurfTm->GetTriangle( nT, nVert) ;
pSurfTm->GetTriangle( nTriaIndex, nVert) ;
PNTVECTOR vPtPa(3) ;
pSurfTm->GetVertexParam( nVert[0], vPtPa[0].x,vPtPa[0].y) ;
pSurfTm->GetVertexParam( nVert[1], vPtPa[1].x,vPtPa[1].y) ;
@@ -2211,7 +2321,7 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in
vtDir.Normalize() ;
// se la dimensione maggiore è grande come la dimensione dello spazio parametrico allora potrebbe essere che le coordinate parametriche di un vertice
// siano da correggere per periodicità
if ( m_bClosedU && abs(vtDir.x) > abs( vtDir.y) && dDist > dParamL * 0.95 ) {
if ( m_bClosedU && abs(vtDir.x) > abs( vtDir.y) && dDist > dParamL * 0.5 ) {
// trovo se dei punti del triangolo sono sul bordo dello spazio parametrico
BOOLVECTOR vbOn(3) ;
for ( int p = 0 ; p < 3; ++p ) {
@@ -2250,7 +2360,7 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in
}
}
}
else if ( m_bClosedV && abs(vtDir.y) > abs(vtDir.x) && dDist > dParamH * 0.95) {
else if ( m_bClosedV && abs(vtDir.y) > abs(vtDir.x) && dDist > dParamH * 0.5) {
BOOLVECTOR vbOn(3) ;
for ( int p = 0 ; p < 3; ++p ) {
if ( ! m_vCCEdge[0]->IsValid()) {
@@ -2395,64 +2505,89 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in
//----------------------------------------------------------------------------
bool
SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam) const
SurfBezier::UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d& ptIPrev) const
{
// dato il punto pt3D sulla superficie di Bezier si cercano le coordinate parametriche ( ptParam) , iterativamente con Newton
// trovato un primo candidato ptParam, ne calcolo l'immagine sulla superficie ( ptBez) e ne calcolo la distanza con il punto pt3D
// ripeto cercando di avvicinarmi il più possibile
// per trovare il primo punto trovo il triangolo della trimesh ausiliaria più vicino e il punto più vicino
DistPointSurfTm dptSurfTm( pt3D, *GetAuxSurf()) ;
int nTriaIndex ; dptSurfTm.GetMinDistTriaIndex( nTriaIndex) ;
Point3d ptI ; dptSurfTm.GetMinDistPoint( ptI) ;
if ( ! UnprojectPointFromStm( nTriaIndex, ptI, ptParam))
if ( ! UnprojectPointFromStm( -1, ptI, ptParam, 5, ptIPrev))
return false ;
Point3d ptBez ;
GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez) ;
// usando un algoritmo di newton cerco di avvicinarmi il più possibile al punto
double dDistNew = Dist( pt3D, ptBez) ;
double dDistPre = dDistNew ;
double dDistPre ;
double dDist0, dDist1;
int nCount = 0 ;
double dh = EPS_SMALL ;
// metodo di newton in più dimensioni
// vario sia il parametro U che il parametro V e verifico se la distanza dalla retta diminuisce per scostamenti positivi o negativi.
while ( dDistNew > EPS_SMALL && nCount < 100) {
dDistPre = dDistNew ;
Point3d ptIBzNew1 ;
GetPointD1D2( ( ptParam.x + dh) / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew1) ;
dDistNew = Dist( pt3D, ptIBzNew1) ;
double dfdU = ( dDistNew - dDistPre) / dh ;
Point3d ptIBzNew2 ;
GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ( ptParam.y + dh) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew2) ;
dDistNew = Dist( pt3D, ptIBzNew2) ;
double dfdV = ( dDistNew - dDistPre) / dh ;
//// opzione 0
////scelgo h1 e h2 separatamente e in modo da annullare f(x)
//// opzione 1
//// valore fisso
//double dr = EPS_SMALL ;
//if ( dDistPre > 1)
// dr = 1 ;
//else if ( dDistPre > 0.1)
// dr = 0.1 ;
//else if ( dDistPre > 0.01)
// dr = 0.01 ;
//// opzione 2
//// valore direttamente vincolato
//double dr = dDistPre ;
//// opzione 3
//// valuto la deformazione locale in base allo spostamento del punto sulla bezier // non serve
//double dh1 = Dist( ptIBz, ptIBzNew1) ;
//double dh2 = Dist( ptIBz, ptIBzNew2) ;
// potrei valutare il nuovo spostamento in base all'ultima variazione di dDist
// potrei anche vedere se sto uscendo dal triangolo ( definito nello spazio parametrico)
// mi avvicino cercando di annullare la distanza in un colpo solo
double dr = - dDistPre / ( dfdU + dfdV) ;
GetPointD1D2(( ptParam.x + dr * dfdU) / SBZ_TREG_COEFF, ( ptParam.y + dr * dfdV) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez) ;
bool bRetry = false ;
double dApproach = 0.01 ;
bool bDesperate = false ;
double dAng = 1 ;
double dr = 5 ;
double dfdU, dfdV ;
while ( dDistNew > 3 * EPS_SMALL && nCount < 100) {
if ( ! bRetry) {
dDistPre = dDistNew ;
// derivata in U
Point3d ptIBzNew1 ;
GetPointD1D2( ( ptParam.x + dh) / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew1) ;
dDist0 = Dist( pt3D, ptIBzNew1) ;
dfdU = ( dDist0 - dDistPre) / dh ;
// derivata in V
Point3d ptIBzNew2 ;
GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ( ptParam.y + dh) / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptIBzNew2) ;
dDist1 = Dist( pt3D, ptIBzNew2) ;
dfdV = ( dDist1 - dDistPre) / dh ;
}
// calcolo le nuove coordinate
Vector3d vtDir ;
double dASum = abs(dfdU) + abs(dfdV) ;
double dSSum = sqrt( pow(dfdU,2) + pow( dfdV,2)) ;
vtDir.Set( - dfdU, - dfdV, 0) ;
if ( ! vtDir.Normalize() )
vtDir.Set( - dfdU / dSSum, - dfdV / dSSum, 0) ;
dr = dDistPre / dASum ;
// in modalità Retry riduco lo spostamento
vtDir *= dr * ( bRetry ? 0.1 : 0.5) ;
if ( bDesperate) {
// in depserate mode riduco lo spostamento e comincio a cambiare progressivamente la direzione oscillando tra destra e sinistra della direzione "naturale"
vtDir *= 0.5 ;
dAng *= -1.25 ;
// riduco ulteriormente lo spostamento dopo qualche giro in desperate mode
if ( abs( dAng) > 5)
vtDir *= 0.5 ;
vtDir.Rotate( Z_AX, dAng) ;
}
ptParam += vtDir ;
// calcolo la nuova distanza tra il punto di partenza e quello che sto trovando con le coordinate attuali
GetPointD1D2( ptParam.x / SBZ_TREG_COEFF, ptParam.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, ptBez) ;
dDistNew = Dist( pt3D, ptBez) ;
dApproach = dDistPre - dDistNew ;
// se ho peggiorato la situazione rispetto allo step precedente torno indietro e vado in Retry mode
if ( dApproach < EPS_ZERO) {
if ( bRetry)
bDesperate = true ; // entro in desperate mode
ptParam -= vtDir ;
bRetry = true ;
// se ho già fatto 9 giri in desperate mode allora esco
if ( abs( dAng) > 8)
break ;
}
else {
bRetry = false ;
bDesperate = false ;
dAng = 1 ;
}
++nCount ;
}
return nCount != 99 ;
return nCount != 100 || (dDistNew < dDistPre ? dDistNew : dDistPre) < 10 * EPS_SMALL ;
}
//----------------------------------------------------------------------------
@@ -2477,8 +2612,8 @@ SurfBezier::CalcPoles( void)
if ( ! bPole0 && ! bPole1)
break ;
}
m_vbPole[1] = bPole0 ;
m_vbPole[3] = bPole1 ;
m_vbPole[1] = bPole0 ; // u = 0 corrisponde all'edge 1
m_vbPole[3] = bPole1 ; // u = 1 corrisponde all'edge 3
// controllo l'edge 1 e 3 per vedere se tutti i punti dell'edge sono coincidenti
Point3d ptV0, ptV1 ;
Point3d ptP01 = GetControlPoint( ( m_nDegU * m_nSpanU + 1) * ( m_nDegV * m_nSpanV), &bOk) ;
@@ -2492,8 +2627,8 @@ SurfBezier::CalcPoles( void)
if ( ! bPole0 && ! bPole1)
break ;
}
m_vbPole[0] = bPole0 ;
m_vbPole[2] = bPole1 ;
m_vbPole[0] = bPole1 ; // v = 1 corrisponde all'edge 0
m_vbPole[2] = bPole0 ; // v = 0 corrisponde all'edge 2
return true ;
}
+3 -3
View File
@@ -114,8 +114,8 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
bool GetLeaves( std::vector<std::tuple<int, Point3d, Point3d>>& vLeaves) const override ;
bool GetTriangles2D( std::vector<std::tuple<int,Point3d, Point3d, Point3d>>& vTria2D) const override ;
bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL = 5) const override ;
bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL, const Point3d& ptIPrev, int nTPrev = -1) const override ; // a nIL si può passare 5 come valore di default
bool UnprojectPoint( const Point3d& pt3D, Point3d& ptParam) const override ;
bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL, const Point3d& ptIPrev) const override ; // a nIL si può passare 5 come valore di default
bool UnprojectPoint( const Point3d& pt3D, Point3d& ptParam, const Point3d& ptIPrev) const override ;
ICurveComposite* UnprojectCurveFromStm( const ICurveComposite* pCC) const override ;
bool Cut( const Plane3d& plPlane, bool bSaveOnEq = false) override ;
bool CalcPoles( void) override ;
@@ -166,7 +166,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
bool GetCurveOnV( double dU, int nStep, PolyLine& plCrvV) const ;
double GetCurveOnUApproxLen( double dV) const ;
double GetCurveOnVApproxLen( double dU) const ;
bool AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, double dToler = EPS_SMALL) ;
bool AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, ICRVCOMPOPOVECTOR& vpCC3D, double dToler = EPS_SMALL) ;
private :
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
+6 -3
View File
@@ -3616,7 +3616,8 @@ Tree::GetEdge3D( POLYLINEVECTOR& vPLEdges)
++ nPtCount ;
// scorro fino alla fine di quel lato
while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[1][c]).GetBottomLeft())) {
vPLEdges.back().AddUPoint( nPtCount, pt) ;
m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ;
vPLEdges.back().AddUPoint( nPtCount, pt3d) ;
++ nPtCount ;
}
vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[1][c])[0]) ;
@@ -3630,7 +3631,8 @@ Tree::GetEdge3D( POLYLINEVECTOR& vPLEdges)
++ nPtCount ;
// scorro fino alla fine di quel lato
while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[2][c]).GetBottomRight())) {
vPLEdges.back().AddUPoint( nPtCount, pt) ;
m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ;
vPLEdges.back().AddUPoint( nPtCount, pt3d) ;
++ nPtCount ;
}
vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[2][c])[1]) ;
@@ -3644,7 +3646,8 @@ Tree::GetEdge3D( POLYLINEVECTOR& vPLEdges)
++ nPtCount ;
// scorro fino alla fine di quel lato
while ( mPL[i][c].GetNextPoint( pt) && ! AreSamePointApprox(pt, m_mTree.at(vEdges[3][c]).GetTopRight())) {
vPLEdges.back().AddUPoint( nPtCount, pt) ;
m_pSrfBz->GetPointD1D2( pt.x / SBZ_TREG_COEFF, pt.y / SBZ_TREG_COEFF, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, pt3d) ;
vPLEdges.back().AddUPoint( nPtCount, pt3d) ;
++ nPtCount ;
}
vPLEdges.back().AddUPoint( nPtCount, m_mVert.at(vEdges[3][c])[2]) ;