This commit is contained in:
Dario Sassi
2024-07-15 18:51:13 +02:00
16 changed files with 3766 additions and 613 deletions
+142 -60
View File
@@ -411,14 +411,51 @@ CopyThickness( const ICurve* pSouCrv, ICurve* pDestCrv)
return true ;
}
//----------------------------------------------------------------------------
ICurve*
CurveToBezierCurve( const ICurve* pCrv, bool bDeg3OrDeg2, bool bForceRat)
{
PtrOwner<ICurve> pBezierForm ;
switch ( pCrv->GetType()) {
case CRV_LINE :{
const ICurveLine* pCrvLine = static_cast<const ICurveLine*>( pCrv) ;
pBezierForm.Set( LineToBezierCurve( pCrvLine, bDeg3OrDeg2, bForceRat)) ;
break ;
}
case CRV_ARC : {
const ICurveArc* pCrvArc = static_cast<const ICurveArc*>( pCrv) ;
pBezierForm.Set( ArcToBezierCurve( pCrvArc, bDeg3OrDeg2)) ;
break ;
}
case CRV_COMPO : {
const ICurveComposite* pCrvCompo = static_cast<const ICurveComposite*>( pCrv) ;
pBezierForm.Set( CompositeToBezierCurve( pCrvCompo, bDeg3OrDeg2, bForceRat)) ;
break ;
}
case CRV_BEZIER : {
const ICurveBezier* pCrvBezier = static_cast<const ICurveBezier*>( pCrv) ;
pBezierForm.Set( BezierToBasicBezierCurve( pCrvBezier, bDeg3OrDeg2, bForceRat)) ;
break ;
}
default :
return nullptr ;
break ;
}
return Release( pBezierForm) ;
}
//----------------------------------------------------------------------------
ICurveBezier*
LineToBezierCurve( const ICurveLine* pCrvLine)
LineToBezierCurve( const ICurveLine* pCrvLine, bool bDeg3OrDeg2, bool bForceRat)
{
PtrOwner<ICurveBezier> pCrvBezier( CreateCurveBezier()) ;
// rendo tutte le curve di grado 2 e razionali così posso convertire anche archi e avere tutte curve dello stesso grado e razionali
pCrvBezier->Init( 2, true) ;
int nDeg = bDeg3OrDeg2 ? 3 : 2 ;
pCrvBezier->Init( nDeg, true) ;
pCrvBezier->FromLine( *pCrvLine) ;
if ( bForceRat)
pCrvBezier->MakeRational() ;
return Release( pCrvBezier) ;
}
@@ -426,31 +463,35 @@ LineToBezierCurve( const ICurveLine* pCrvLine)
ICurve*
ArcToBezierCurve( const ICurve* pCrv, bool bDeg3OrDeg2)
{
// una spirale non può essere forzata al grado 2
// verifico sia un arco
const CurveArc* pArc = GetBasicCurveArc( pCrv) ;
if ( pArc == nullptr)
return nullptr ;
// se angolo al centro sotto il limite, basta una curva
if ( ( abs( pArc->GetAngCenter()) < BEZARC_ANG_CEN_MAX + EPS_ANG_SMALL && abs( pArc->GetDeltaN()) < EPS_ZERO && ! bDeg3OrDeg2) ||
( abs( pArc->GetAngCenter()) < BEZARC_ANG_CEN_MAX + EPS_ANG_SMALL && bDeg3OrDeg2)) {
if ( abs( pArc->GetAngCenter()) < BEZARC_ANG_CEN_MAX + EPS_ANG_SMALL) {
// creo la curva di Bezier equivalente all'arco
PtrOwner<CurveBezier> pCrvBez( CreateBasicCurveBezier()) ;
PtrOwner<ICurveBezier> pCrvBez( CreateBasicCurveBezier()) ;
if ( IsNull( pCrvBez) || ! pCrvBez->FromArc( *pArc))
return nullptr ;
// se l'arco era piano ed è richiesta una curva di grado 3 allora aumento una volta il grado
if ( bDeg3OrDeg2 && abs( pArc->GetDeltaN()) < EPS_ZERO)
pCrvBez.Set( BezierIncreaseDegree( pCrvBez)) ;
// restituisco la curva
return Release( pCrvBez) ;
}
// altrimenti curva composita di Bezier
else {
// creo la curva composita
PtrOwner<CurveComposite> pCrvCompo( CreateBasicCurveComposite()) ;
PtrOwner<ICurveComposite> pCrvCompo( CreateBasicCurveComposite()) ;
if ( IsNull( pCrvCompo))
return nullptr ;
// inserisco nella CC le curve di Bezier equivalenti alle parti dell'arco
int nParts = (int) ceil( abs( pArc->GetAngCenter()) / ( BEZARC_ANG_CEN_MAX + EPS_ANG_SMALL)) ;
if ( ! bDeg3OrDeg2 && abs( pArc->GetDeltaN()) > EPS_ZERO)
nParts *= 2 ;
//if ( ! bDeg3OrDeg2 && abs( pArc->GetDeltaN()) > EPS_ZERO)
// nParts *= 2 ;
nParts = max( nParts, 2) ;
for ( int i = 0 ; i < nParts ; ++ i) {
// copio l'arco originale
@@ -458,9 +499,12 @@ ArcToBezierCurve( const ICurve* pCrv, bool bDeg3OrDeg2)
// lo limito alla parte di interesse
cArc.TrimStartEndAtParam( i / double( nParts), ( i + 1) / double( nParts)) ;
// creo la curva di Bezier equivalente
PtrOwner<CurveBezier> pCrvBez( CreateBasicCurveBezier()) ;
PtrOwner<ICurveBezier> pCrvBez( CreateBasicCurveBezier()) ;
if ( IsNull( pCrvBez) || ! pCrvBez->FromArc( cArc))
return nullptr ;
// se l'arco era piano ed è richiesta una curva di grado 3 allora aumento una volta il grado
if ( bDeg3OrDeg2 && abs( pArc->GetDeltaN()) < EPS_ZERO)
pCrvBez.Set( BezierIncreaseDegree( pCrvBez)) ;
// aggiungo la curva di Bezier a quella composita
if ( ! pCrvCompo->AddCurve( Release( pCrvBez)))
return nullptr ;
@@ -475,7 +519,7 @@ ArcToBezierCurve( const ICurve* pCrv, bool bDeg3OrDeg2)
//----------------------------------------------------------------------------
ICurve*
CompositeToBezierCurve( const ICurveComposite* pCC)
CompositeToBezierCurve( const ICurveComposite* pCC, bool bDeg3OrDeg2, bool bForceRat)
{
// converto tutte le curve in bezier razionali di grado 2
PtrOwner<ICurveComposite> pCCBezier( CreateCurveComposite()) ;
@@ -491,14 +535,14 @@ CompositeToBezierCurve( const ICurveComposite* pCC)
}
else if ( pCC->GetCurve(i)->GetType() == CRV_LINE) {
const CurveLine* crLine = GetBasicCurveLine( pCC->GetCurve(i)) ;
ICurve* pCrvBezier = LineToBezierCurve( crLine) ;
ICurve* pCrvBezier = LineToBezierCurve( crLine, bDeg3OrDeg2, bForceRat) ;
if ( pCrvBezier == nullptr)
return nullptr ;
pCrvNew.Set( pCrvBezier) ;
}
else if ( pCC->GetCurve(i)->GetType() == CRV_BEZIER ) {
const CurveBezier* crvBezier = GetBasicCurveBezier( pCC->GetCurve(i)) ;
ICurve* pCrvBezier = BezierToBasicBezierCurve( crvBezier) ;
ICurve* pCrvBezier = BezierToBasicBezierCurve( crvBezier, bDeg3OrDeg2, bForceRat) ;
if ( pCrvBezier == nullptr)
return nullptr ;
pCrvNew.Set( pCrvBezier) ;
@@ -511,7 +555,7 @@ CompositeToBezierCurve( const ICurveComposite* pCC)
//----------------------------------------------------------------------------
ICurve*
BezierToBasicBezierCurve( const ICurveBezier* pCrvBezier)
BezierToBasicBezierCurve( const ICurveBezier* pCrvBezier, bool bDeg3OrDeg2, bool bForceRat)
{
// resta da calcolare un errore sull'approssimazione oppure usare la tecnica di spezzare la curva originale in sottocurve e approssimarle con bezier cubiche
// per ridurre molto l'errore
@@ -521,34 +565,26 @@ BezierToBasicBezierCurve( const ICurveBezier* pCrvBezier)
int nDeg = pCrvBezier->GetDegree() ;
bool bRat = pCrvBezier->IsRational() ;
// se la curva è già nella forma giusta la restituisco
if ( nDeg == 2 && bRat)
int nDegWanted = bDeg3OrDeg2 ? 3 : 2 ;
if ( nDeg == nDegWanted && ( ( ! bRat && ! bForceRat) || bRat))
return Release( pCrvNew) ;
// sennò la riduco di grado fino al 2
PtrOwner<ICurveBezier> pBasicBezier ( CreateCurveBezier()) ;
pBasicBezier->Init( 2, true) ;
double dW = 1 ;
if ( nDeg == 1) {
Point3d ptStart = pCrvBezier->GetControlPoint( 0) ;
Point3d ptEnd = pCrvBezier->GetControlPoint( 1) ;
pBasicBezier->SetControlPoint( 0, ptStart, dW) ;
pBasicBezier->SetControlPoint( 1, 0.5 * (ptStart + ptEnd), dW) ;
pBasicBezier->SetControlPoint( 2, ptEnd, dW) ;
return Release( pBasicBezier) ;
// sennò mi porto al grado giusto
if ( nDeg < nDegWanted) {
while ( nDeg < nDegWanted)
pCrvNew.Set( BezierIncreaseDegree( pCrvNew)) ;
}
while ( nDeg > 2 ) {
pCrvNew.Set( BezierDecreaseDegree( pCrvNew, 1)) ;
if ( IsNull( pCrvNew) || ! pCrvNew->IsValid())
return nullptr ;
-- nDeg ;
}
for ( int i = 0 ; i < 3 ; ++i) {
Point3d ptCopy = pCrvNew->GetControlPoint( i) ;
if ( bRat)
dW = pCrvNew->GetControlWeight( i) ;
pBasicBezier->SetControlPoint( i, ptCopy, dW) ;
else if ( nDeg > nDegWanted) {
while ( nDeg > nDegWanted) {
pCrvNew.Set( BezierDecreaseDegree( pCrvNew, 1)) ;
if ( IsNull( pCrvNew) || ! pCrvNew->IsValid())
return nullptr ;
-- nDeg ;
}
}
if ( bForceRat)
pCrvNew->MakeRational() ;
return Release( pBasicBezier) ;
return Release( pCrvNew) ;
}
ICurveBezier*
@@ -576,15 +612,19 @@ BezierIncreaseDegree(const ICurveBezier* pCrvBezier)
double dWcurr ;
for ( double i = 1 ; i < nDeg ; ++i) {
ptCtrlCurr = pCrvBezier->GetControlPoint( int( i)) ;
Point3d ptNew = ( i / nDeg) * ptCtrlPrev + ( 1 - i / ( nDeg)) * ptCtrlCurr ;
double dAlpha = i / nDeg ;
if ( bRat) {
dWcurr = pCrvBezier->GetControlWeight( int( i)) ;
double dWnew = ( i / nDeg) * dWprev + ( 1 - i / ( nDeg)) * dWcurr ;
double dWnew = dAlpha * dWprev + ( 1 - dAlpha) * dWcurr ;
Point3d ptNew = dAlpha * ptCtrlPrev * dWprev + ( 1 - dAlpha) * ptCtrlCurr * dWcurr;
ptNew /= dWnew ;
pNewBezier->SetControlPoint( int( i), ptNew, dWnew) ;
dWprev = dWnew ;
dWprev = dWcurr ;
}
else
else {
Point3d ptNew = dAlpha * ptCtrlPrev + ( 1 - dAlpha) * ptCtrlCurr ;
pNewBezier->SetControlPoint( int( i), ptNew) ;
}
ptCtrlPrev = ptCtrlCurr ;
}
// salvo l'ultimo punto
@@ -628,30 +668,37 @@ BezierDecreaseDegree(const ICurveBezier* pCrvBezier, double dTol)
double dAlpha = i / ( nDeg + 1) ;
// old è riferito alla curva originale
Point3d ptOld = pCrvBezier->GetControlPoint( int( i)) ;
ptCtrlCurr = ( ptOld + (- dAlpha * ptCtrlPrev)) / ( 1 - dAlpha) ;
if ( bRat) {
double dWold = pCrvBezier->GetControlWeight( int( i)) ;
dWcurr = ( dWold + (- dAlpha * dWprev)) / ( 1 - dAlpha) ;
ptCtrlCurr = ( ptOld * dWold + (- dAlpha * ptCtrlPrev * dWprev)) / ( 1 - dAlpha) ;
ptCtrlCurr /= dWcurr ;
pNewBezier->SetControlPoint( int( i), ptCtrlCurr, dWcurr) ;
dWprev = dWcurr ;
}
else
else {
ptCtrlCurr = ( ptOld + (- dAlpha * ptCtrlPrev)) / ( 1 - dAlpha) ;
pNewBezier->SetControlPoint( int( i), ptCtrlCurr) ;
}
ptCtrlPrev = ptCtrlCurr ;
}
// risolvo il punto di mezzo per il caso nDeg pari
if ( ( nDeg + 1) % 2 == 0) { // pari
double dAlpha = r / ( nDeg + 1.) ;
Point3d ptOld = pCrvBezier->GetControlPoint( r) ;
ptCtrlCurr = ( ptOld + (- dAlpha * ptCtrlPrev)) / ( 1 - dAlpha) ;
if ( bRat) {
double dWold = pCrvBezier->GetControlWeight( r) ;
dWcurr = ( dWold + (- dAlpha * dWprev)) / ( 1 - dAlpha) ;
ptCtrlCurr = ( ptOld * dWold + (- dAlpha * ptCtrlPrev * dWprev)) / ( 1 - dAlpha) ;
ptCtrlCurr /= dWcurr ;
pNewBezier->SetControlPoint( r, ptCtrlCurr, dWcurr) ;
dWprev = dWcurr ;
}
else
else {
ptCtrlCurr = ( ptOld + (- dAlpha * ptCtrlPrev)) / ( 1 - dAlpha) ;
pNewBezier->SetControlPoint( r, ptCtrlCurr) ;
}
}
// salvo l'ultimo punto
ptCtrlCurr = pCrvBezier->GetControlPoint( nDeg + 1) ;
@@ -668,15 +715,18 @@ BezierDecreaseDegree(const ICurveBezier* pCrvBezier, double dTol)
for ( double i = nDeg - 1 ; i > r ; --i) {
double dAlpha = ( i + 1) / ( nDeg + 1) ;
Point3d ptOld = pCrvBezier->GetControlPoint( int( i) + 1) ;
ptCtrlCurr = ( ptOld + ( - ( 1 - dAlpha) * ptCtrlPrev)) / dAlpha ;
if ( bRat) {
double dWold = pCrvBezier->GetControlWeight( int( i) + 1) ;
dWcurr = ( dWold - ( ( 1 - dAlpha) * dWprev)) / dAlpha ;
ptCtrlCurr = ( ptOld * dWold + ( - ( 1 - dAlpha) * ptCtrlPrev * dWprev)) / dAlpha ;
ptCtrlCurr /= dWcurr ;
pNewBezier->SetControlPoint( int( i), ptCtrlCurr, dWcurr) ;
dWprev = dWcurr ;
}
else
else {
ptCtrlCurr = ( ptOld + ( - ( 1 - dAlpha) * ptCtrlPrev)) / dAlpha ;
pNewBezier->SetControlPoint( int( i), ptCtrlCurr) ;
}
ptCtrlPrev = ptCtrlCurr ;
}
// risolvo il punto di mezzo per il caso nDeg dispari
@@ -687,29 +737,37 @@ BezierDecreaseDegree(const ICurveBezier* pCrvBezier, double dTol)
double dAlpha = r / ( nDeg + 1.) ;
ptCtrlPrev = pNewBezier->GetControlPoint( r - 1) ;
Point3d ptOld = pCrvBezier->GetControlPoint( r) ;
Point3d ptL = ( ptOld + ( - dAlpha * ptCtrlPrev)) / ( 1 - dAlpha) ;
Point3d ptL ;
double dWL = 1 ;
if ( bRat) {
dWprev = pNewBezier->GetControlWeight( r - 1) ;
double dWold =pCrvBezier->GetControlWeight( r) ;
dWL = ( dWold - ( dAlpha * dWprev)) / ( 1 - dAlpha) ;
ptL = ( ptOld * dWold + ( - dAlpha * ptCtrlPrev * dWprev)) / ( 1 - dAlpha) ;
}
else
ptL = ( ptOld + ( - dAlpha * ptCtrlPrev)) / ( 1 - dAlpha) ;
// punto di destra
dAlpha = ( r + 1.) / ( nDeg + 1.) ;
ptCtrlPrev = pNewBezier->GetControlPoint( r + 1) ;
ptOld = pCrvBezier->GetControlPoint( r + 1) ;
double dWR = 1 ;
Point3d ptR ;
if ( bRat) {
dWprev = pNewBezier->GetControlWeight( r + 1) ;
double dWold =pCrvBezier->GetControlWeight( r + 1) ;
dWR = ( dWold - ( ( 1 - dAlpha) * dWprev)) / dAlpha ;
ptR = ( ptOld * dWold + ( - ( 1 - dAlpha) * ptCtrlPrev * dWprev)) / dAlpha ;
}
Point3d ptR = ( ptOld + ( - ( 1 - dAlpha) * ptCtrlPrev)) / dAlpha ;
else
ptR = ( ptOld + ( - ( 1 - dAlpha) * ptCtrlPrev)) / dAlpha ;
// calcolo il punto di mezzo e lo aggiungo
Point3d ptNew = ( ptL + ptR) / 2 ;
double dWnew = ( dWL + dWR) / 2 ;
if ( bRat)
if ( bRat) {
double dWnew = ( dWL + dWR) / 2 ;
ptNew /= dWnew ;
pNewBezier->SetControlPoint( r, ptNew, dWnew) ;
}
else
pNewBezier->SetControlPoint( r, ptNew) ;
dErr = Dist( ptL, ptR) ;
@@ -815,15 +873,16 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
if ( ! bRepeated || (bRepeated && AreSamePointApprox( cnData.vCP[0],cnData.vCP[cnData.nDeg]))){
// salvo il vettore dei nodi in caso mi accorga di avere tra le mani una curva unclamped
DBLVECTOR vU = cnData.vU ;
// se il primo e l'ultimo punto non coincidono allora aggiungo il primo punto in fondo al vettore dei punti di controllo
if ( ! AreSamePointApprox( cnData.vCP[0], cnData.vCP.back()) ) {
cnData.vCP.push_back( cnData.vCP[0]) ;
if ( cnData.bRat)
cnData.vW.push_back( cnData.vW[0]) ;
}
// se effettivamente ho dei nodi in più da togliere allora li tolgo
if ( int( cnData.vU.size()) != int(cnData.vCP.size()) + cnData.nDeg - 1) {
// devo poi anche togliere i nodi di troppo // presuppongo che la convenzione sia che i nodi di troppo sono alla fine del vettore dei nodi
// se effettivamente ho dei nodi in più da togliere allora li tolgo ed eventualmente aggiungo punti di controllo
if ( int(cnData.vU.size()) > int(cnData.vCP.size()) + cnData.nDeg - 1 ) {
// se il primo e l'ultimo punto non coincidono allora aggiungo il primo punto in fondo al vettore dei punti di controllo
if ( ! AreSamePointApprox( cnData.vCP[0], cnData.vCP.back())) {
bFirstAddedAtEnd = true ;
cnData.vCP.push_back( cnData.vCP[0]) ;
if ( cnData.bRat)
cnData.vW.push_back( cnData.vW[0]) ;
}
// devo poi anche togliere i nodi di troppo // presuppongo che la convenzione sia che i nodi di troppo siano alla fine del vettore dei nodi
cnData.vU = DBLVECTOR( cnData.vU.begin(), cnData.vU.end() - cnData.nDeg) ;
// controllo eventualmente anche i nodi extra
// se ne ho due in più ne tolgo uno in cima e uno in fondo
@@ -922,9 +981,20 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
// trovo il nodo di cui aumentare la molteplicità e ne calcolo la molteplicità
int b = nU - nDeg - 1 + 1 ;
int i = b ;
//int c = b ;
while ( b > 0 && abs( cnData.vU[b] - cnData.vU[b - 1]) < EPS_ZERO)
-- b ;
int mult = min( i - b + 1, nDeg) ; // mi aspetto che sia 1, ma comunque sarà < nDeg
//while ( i > 0 && abs( cnData.vU[i] - cnData.vU[i - 1]) < EPS_ZERO)
// -- i ;
//int mult = min( b - i + 1, nDeg) ; // mi aspetto che sia 1, ma comunque sarà < nDeg
//// devo controllare anche i nodi successivi!
//while ( c < nU - 1 && abs( cnData.vU[c + 1] - cnData.vU[c]) < EPS_ZERO)
// ++ c ;
//int mult = min( c - i + 1, nDeg) ; // mi aspetto che sia 1, ma comunque sarà < nDeg
// recupero i punti da modificare
if ( ! cnData.bRat) {
for ( int i = 0 ; i <= nDeg - mult ; ++ i)
@@ -986,9 +1056,20 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
// aumento la molteplicità del punto u_p-1
b = nDeg - 1 ;
i = b ;
//c = b ;
while ( b > 0 && abs( cnData.vU[b] - cnData.vU[b - 1]) < EPS_ZERO)
-- b ;
mult = min( i - b + 1, nDeg) ; // mi aspetto che sia 1, ma comunque sarà < cnData.nDeg
//while ( i > 0 && abs( cnData.vU[i] - cnData.vU[i - 1]) < EPS_ZERO)
// -- i ;
//mult = min( b - i + 1, nDeg) ; // mi aspetto che sia 1, ma comunque sarà < cnData.nDeg
//// devo controllare anche i nodi successivi!
//while ( c < nU -1 && abs(cnData.vU[c + 1] - cnData.vU[c]) < EPS_ZERO )
// ++ c ;
//mult = min( c - i + 1, nDeg) ; // mi aspetto che sia 1, ma comunque sarà < cnData.nDeg
// recupero i punti da modificare
if ( ! cnData.bRat) {
for ( int i = 0 ; i <= nDeg - mult ; ++ i)
@@ -1161,6 +1242,7 @@ NurbsToBezierCurve( const CNurbsData& cnData)
int a = cnData.nDeg - 1 ;
int b = cnData.nDeg ;
bool bPrevRejected = false ;
//algoritmo A5.6 di Piegl e Tiller
// ciclo
while ( b < nU - 1) {
int i = b ;
+40
View File
@@ -141,6 +141,32 @@ CurveBezier::SetControlPoint( int nInd, const Point3d& ptCtrl, double dW)
return true ;
}
//----------------------------------------------------------------------------
bool
CurveBezier::SetControlWeight( int nInd, double dW)
{
// verifico validità, razionalità e indice
if ( m_nStatus != OK || ! m_bRat || nInd < 0 || nInd > m_nDeg)
return false ;
// verifico che il peso non sia nullo o negativo
if ( dW < EPS_SMALL)
return false ;
// assegno il valore e il peso
m_vWeCtrl[nInd] = dW ;
// annullo analisi presenza singolarità
m_dParSing = - 2 ;
// imposto ricalcolo Voronoi
ResetVoronoiObject() ;
// imposto ricalcolo della grafica
m_OGrMgr.Reset() ;
return true ;
}
//----------------------------------------------------------------------------
bool
CurveBezier::FromArc( const ICurveArc& crArc)
@@ -2208,3 +2234,17 @@ CurveBezier::ResetVoronoiObject() const
delete m_pVoronoiObj ;
m_pVoronoiObj = nullptr ;
}
//----------------------------------------------------------------------------
bool
CurveBezier::MakeRational( void)
{
if ( m_bRat)
return true ;
// creo il vettore dei pesi e li setto tutti a 1
m_vWeCtrl.assign( m_nDeg + 1, 1) ;
// aggiorno il flag rational
m_bRat = true ;
return true ;
}
+2
View File
@@ -137,6 +137,7 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
bool Init( int nDeg, bool bIsRational) override ;
bool SetControlPoint( int nInd, const Point3d& ptCtrl) override ;
bool SetControlPoint( int nInd, const Point3d& ptCtrl, double dW) override ;
bool SetControlWeight( int nInd, double dW) override ;
bool FromArc( const ICurveArc& crArc) override ;
bool FromLine( const ICurveLine& crLine) override ;
int GetDegree( void) const override
@@ -148,6 +149,7 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW
double GetControlWeight( int nInd, bool* pbOk = NULL) const override ;
bool GetControlPolygonLength( double& dLen) const override ;
int GetSingularParam( double& dPar) const override ;
bool MakeRational( void) override ;
public : // IGeoObjRW
int GetNgeId( void) const override ;
BIN
View File
Binary file not shown.
+2
View File
@@ -320,9 +320,11 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
<ClCompile Include="IntersPlaneVolZmap.cpp" />
<ClCompile Include="IntersLineSurfBez.cpp" />
<ClCompile Include="PolygonElevation.cpp" />
<ClCompile Include="ProjectCurveSurfBez.cpp" />
<ClCompile Include="Quaternion.cpp" />
<ClCompile Include="RotationMinimizingFrame.cpp" />
<ClCompile Include="RotationXplaneFrame.cpp" />
<ClCompile Include="SbzFromCurves.cpp" />
<ClCompile Include="SbzStandard.cpp" />
<ClCompile Include="Voronoi.cpp" />
<ClInclude Include="..\Include\EGkCDeClosedSurfTmClosedSurfTm.h" />
+6
View File
@@ -540,6 +540,12 @@
<ClCompile Include="CAvSilhouetteSurfTm.cpp">
<Filter>File di origine\GeoCollisionAvoid</Filter>
</ClCompile>
<ClCompile Include="ProjectCurveSurfBez.cpp">
<Filter>File di origine\GeoProject</Filter>
</ClCompile>
<ClCompile Include="SbzFromCurves.cpp">
<Filter>File di origine\GeoCreate</Filter>
</ClCompile>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
+55
View File
@@ -0,0 +1,55 @@
//----------------------------------------------------------------------------
// EgalTech 2024-2024
//----------------------------------------------------------------------------
// File : ProjectCurveSurfBez.cpp Data : 07.05.24 Versione : 2.6e3
// Contenuto : Implementazione funzioni proiezione curve su superficie Bezier.
//
//
//
// Modifiche : 07.05.24 DB Creazione modulo.
//
//
//----------------------------------------------------------------------------
//--------------------------- Include ----------------------------------------
#include "stdafx.h"
#include "/EgtDev/Include/EGkProjectCurveSurfTm.h"
#include "/EgtDev/Include/EGkSurfBezier.h"
using namespace std ;
//----------------------------------------------------------------------------
bool
ProjectCurveOnSurfBez( const ICurve& crCrv, const ISurfBezier& surfBez, const Vector3d& vtDir, double dLinTol, double dMaxSegmLen,
PNT5AXVECTOR& vPt5ax)
{
const ISurfTriMesh* pAuxSurf = surfBez.GetAuxSurf() ;
return ProjectCurveOnSurfTm( crCrv, *pAuxSurf, vtDir, dLinTol, dMaxSegmLen, vPt5ax) ;
}
//----------------------------------------------------------------------------
bool
ProjectCurveOnSurfBez( const ICurve& crCrv, const ISurfBezier& surfBez, const IGeoPoint3d& gpRef,
double dLinTol, double dMaxSegmLen, PNT5AXVECTOR& vPt5ax)
{
const ISurfTriMesh* pAuxSurf = surfBez.GetAuxSurf() ;
return ProjectCurveOnSurfTm( crCrv, *pAuxSurf, gpRef, dLinTol, dMaxSegmLen, vPt5ax) ;
}
//----------------------------------------------------------------------------
bool
ProjectCurveOnSurfBez( const ICurve& crCrv, const ISurfBezier& surfBez, const ICurve& crRef,
double dLinTol, double dMaxSegmLen, PNT5AXVECTOR& vPt5ax)
{
const ISurfTriMesh* pAuxSurf = surfBez.GetAuxSurf() ;
return ProjectCurveOnSurfTm( crCrv, *pAuxSurf, crRef, dLinTol, dMaxSegmLen, vPt5ax) ;
}
//----------------------------------------------------------------------------
bool
ProjectCurveOnSurfBez( const ICurve& crCrv, const ISurfBezier& surfBez, const ISurfTriMesh& tmRef,
double dLinTol, double dMaxSegmLen, PNT5AXVECTOR& vPt5ax)
{
const ISurfTriMesh* pAuxSurf = surfBez.GetAuxSurf() ;
return ProjectCurveOnSurfTm( crCrv, *pAuxSurf, tmRef, dLinTol, dMaxSegmLen, vPt5ax) ;
}
+1155
View File
File diff suppressed because it is too large Load Diff
+34 -1
View File
@@ -17,12 +17,13 @@
#include "SurfTriMesh.h"
#include "SurfBezier.h"
#include "/EgtDev/Include/EGkSbzStandard.h"
#include "/EgtDev/Include/EGkSbzFromCurves.h"
using namespace std ;
//-------------------------------------------------------------------------------
ISurfBezier*
CreateBezierSphere( const Point3d& ptCenter, double dR)
GetSurfBezierSphere( const Point3d& ptCenter, double dR)
{
// creo una superficie di Bezier di grado 2 con 45 punti di controllo
PtrOwner<ISurfBezier> pSrfBez( CreateSurfBezier()) ;
@@ -78,3 +79,35 @@ CreateBezierSphere( const Point3d& ptCenter, double dR)
return Release( pSrfBez) ;
}
////-------------------------------------------------------------------------------
//ISurfBezier*
//GetSurfBezierCone( const Point3d& ptCenter, double dRadius, const Vector3d& dHeight)
//{
// // le dimensioni devono essere significative
// if ( dRadius < EPS_SMALL || abs( dHeight) < EPS_SMALL)
// return nullptr ;
// // creo la circonferenza di base
// CurveArc cArc ;
// cArc.Set( ORIG, Z_AX, dRadius) ;
// if ( dHeight < 0)
// cArc.Invert() ;
// // punto di vertice
// Point3d ptTip( 0, 0, dHeight) ;
// // creo la superficie laterale del cono
// PtrOwner<ISurfBezier> pSbz( GetSurfBezierRuled( ptTip, &cArc)) ;
// if ( IsNull( pSbz))
// return nullptr ;
//
// //// creo la superficie di base e la inverto
// //PtrOwner<ISurfTriMesh> pSTM1( GetSurfTriMeshByFlatContour( &cArc, dLinTol)) ;
// //if ( IsNull( pSTM1))
// // return nullptr ;
// //pSTM1->Invert() ;
// //// la unisco alla superficie del fianco
// //if ( ! pSTM->DoSewing( *pSTM1))
// // return nullptr ;
//
// // restituisco la superficie
// return Release( pSbz) ;
//}
+136 -1
View File
@@ -571,4 +571,139 @@ SurfFlatRegionByContours::GetUnusedCurveTempProps( INTVECTOR& vId)
vId.push_back( pCrv->GetTempProp()) ;
}
return ( ! vId.empty()) ;
}
}
//-------------------------------------------------------------------------------
bool
CalcRegionPolyLines( const CICURVEPVECTOR& vpCurve, double dLinTol,
POLYLINEVECTOR& vPL, Vector3d& vtN)
{
// se non ho curve, non faccio nulla
if ( int( vpCurve.size()) == 0)
return true ;
// calcolo le polilinee che approssimano le curve
vPL.resize( vpCurve.size()) ;
for ( int i = 0 ; i < int( vpCurve.size()) ; ++ i) {
if ( ! vpCurve[i]->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPL[i]))
return false ;
}
// ricavo versore normale
Plane3d plPlane ; double dArea ;
if ( ! vPL[0].IsClosedAndFlat( plPlane, dArea, 50 * EPS_SMALL))
return false ;
vtN = plPlane.GetVersN() ;
typedef std::pair<int,double> INDAREA ;
std::vector<INDAREA> m_vArea ;
// calcolo piano medio e area delle curve
m_vArea.reserve( vPL.size()) ;
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
// calcolo piano medio e area
Plane3d plPlane ;
double dArea ;
if ( ! vPL[i].IsClosedAndFlat( plPlane, dArea))
return false ;
// verifico che le normali siano molto vicine
if ( ! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), vtN))
return false ;
// assegno il segno all'area secondo il verso della normale
if ( ( plPlane.GetVersN() * vtN) > 0)
m_vArea.emplace_back( i, dArea) ;
else
m_vArea.emplace_back( i, - dArea) ;
}
// ordino in senso decrescente sull'area
sort( m_vArea.begin(), m_vArea.end(),
[]( const INDAREA& a, const INDAREA& b) { return ( abs( a.second) > abs( b.second)) ; }) ;
// dalle PolyLine passo alle curve nel piano XY ( prendo la prima come riferimento, trascuro le Z delle successive)
Frame3d frRef ; frRef.Set( ORIG, vtN) ;
if ( ! frRef.IsValid())
return false ;
ICRVCOMPOPOVECTOR vCrvCompo( int( vPL.size())) ;
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
vCrvCompo[i].Set( CreateCurveComposite()) ;
vCrvCompo[i]->FromPolyLine( vPL[i]) ;
vCrvCompo[i]->ToLoc( frRef) ;
}
// creo una matrice di interi ; ogni riga corrisponde ad un chunk, dove in posizione 0 c'è il loop esterno e nelle
// successive i loop interni
INTMATRIX vnPLIndMat ;
// vettore di indici per ordinare le PolyLine
INTVECTOR vPL_IndOrder ; vPL_IndOrder.resize( int( vPL.size())) ;
for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i)
vPL_IndOrder[i] = m_vArea[i].first ;
// aggiungo le diverse curve
bool bFirstCrv ;
Plane3d plExtLoop ;
double dAreaExtLoop = 0. ;
do {
bFirstCrv = true ;
for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i) {
// recupero indice di percorso e verifico sia valido
int j = m_vArea[i].first ;
if ( j < 0)
continue ;
// lo inserisco come esterno...
if ( bFirstCrv) {
vnPLIndMat.push_back({ j}) ;
m_vArea[i].first = -1 ;
dAreaExtLoop = m_vArea[i].second ;
// inverto se necessario
if ( m_vArea[i].second < EPS_SMALL) {
vPL[j].Invert() ;
vCrvCompo[j]->Invert() ;
dAreaExtLoop *= -1 ;
}
bFirstCrv = false ;
}
// ... altrimenti verifico se il loop è interno o no
else {
// il loop è interno se è sia interno al loop esterno della riga di vnPLIndMat e allo stesso tempo
// esterno a tutti i loop già inseriti nella riga attuale.
// verifica rispetto loop esterno
IntersCurveCurve ccInt( *vCrvCompo[vnPLIndMat.back().front()], *vCrvCompo[j]) ;
CRVCVECTOR ccClass ;
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt.GetCurveClassification( 1, EPS_SMALL, ccClass) ||
ccClass.empty() || ccClass[0].nClass != CRVC_IN)
continue ;
// verifica rispetto ai loop interni
bool bOk = true ;
for ( int k = 1 ; k < int( vnPLIndMat.back().size()) ; ++ k) {
IntersCurveCurve ccInt2( *vCrvCompo[vnPLIndMat.back()[k]], *vCrvCompo[j]) ;
CRVCVECTOR ccClass2 ;
if ( ccInt2.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt2.GetCurveClassification( 1, EPS_SMALL, ccClass2) ||
ccClass2.empty() || ccClass2[0].nClass != CRVC_IN) {
bOk = false ;
break ;
}
}
if ( bOk) {
// inserisco nella matrice
vnPLIndMat.back().push_back( j) ;
m_vArea[i].first = -1 ;
// inverto se necessario
if ( m_vArea[i].second * dAreaExtLoop > 0.) {
vPL[j].Invert() ;
vCrvCompo[j]->Invert() ;
}
}
}
}
} while ( ! bFirstCrv) ;
// ordino le PolyLine per area
POLYLINEVECTOR vPL_tmp ;
for ( int i = 0 ; i < int( vPL_IndOrder.size()) ; ++ i)
vPL_tmp.push_back( vPL[ vPL_IndOrder[i]]) ;
swap( vPL, vPL_tmp) ;
return true ;
}
-139
View File
@@ -31,10 +31,6 @@
using namespace std ;
//-------------------------------------------------------------------------------
static bool CalcRegionPolyLines( const CICURVEPVECTOR& vpCurve, double dLinTol,
POLYLINEVECTOR& vPL, Vector3d& vtN) ;
//-------------------------------------------------------------------------------
ISurfTriMesh*
GetSurfTriMeshByFlatContour( const ICurve* pCurve, double dLinTol)
@@ -1433,138 +1429,3 @@ GetSurfTriMeshRuled( const ICurve* pCurve1, const ICurve* pCurve2, int nType, do
// restituisco la superficie
return Release( pSTM) ;
}
//-------------------------------------------------------------------------------
bool
CalcRegionPolyLines( const CICURVEPVECTOR& vpCurve, double dLinTol,
POLYLINEVECTOR& vPL, Vector3d& vtN)
{
// se non ho curve, non faccio nulla
if ( int( vpCurve.size()) == 0)
return true ;
// calcolo le polilinee che approssimano le curve
vPL.resize( vpCurve.size()) ;
for ( int i = 0 ; i < int( vpCurve.size()) ; ++ i) {
if ( ! vpCurve[i]->ApproxWithLines( dLinTol, ANG_TOL_STD_DEG, ICurve::APL_SPECIAL, vPL[i]))
return false ;
}
// ricavo versore normale
Plane3d plPlane ; double dArea ;
if ( ! vPL[0].IsClosedAndFlat( plPlane, dArea, 50 * EPS_SMALL))
return false ;
vtN = plPlane.GetVersN() ;
typedef std::pair<int,double> INDAREA ;
std::vector<INDAREA> m_vArea ;
// calcolo piano medio e area delle curve
m_vArea.reserve( vPL.size()) ;
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
// calcolo piano medio e area
Plane3d plPlane ;
double dArea ;
if ( ! vPL[i].IsClosedAndFlat( plPlane, dArea))
return false ;
// verifico che le normali siano molto vicine
if ( ! AreSameOrOppositeVectorApprox( plPlane.GetVersN(), vtN))
return false ;
// assegno il segno all'area secondo il verso della normale
if ( ( plPlane.GetVersN() * vtN) > 0)
m_vArea.emplace_back( i, dArea) ;
else
m_vArea.emplace_back( i, - dArea) ;
}
// ordino in senso decrescente sull'area
sort( m_vArea.begin(), m_vArea.end(),
[]( const INDAREA& a, const INDAREA& b) { return ( abs( a.second) > abs( b.second)) ; }) ;
// dalle PolyLine passo alle curve nel piano XY ( prendo la prima come riferimento, trascuro le Z delle successive)
Frame3d frRef ; frRef.Set( ORIG, vtN) ;
if ( ! frRef.IsValid())
return false ;
ICRVCOMPOPOVECTOR vCrvCompo( int( vPL.size())) ;
for ( int i = 0 ; i < int( vPL.size()) ; ++ i) {
vCrvCompo[i].Set( CreateCurveComposite()) ;
vCrvCompo[i]->FromPolyLine( vPL[i]) ;
vCrvCompo[i]->ToLoc( frRef) ;
}
// creo una matrice di interi ; ogni riga corrisponde ad un chunk, dove in posizione 0 c'è il loop esterno e nelle
// successive i loop interni
INTMATRIX vnPLIndMat ;
// vettore di indici per ordinare le PolyLine
INTVECTOR vPL_IndOrder ; vPL_IndOrder.resize( int( vPL.size())) ;
for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i)
vPL_IndOrder[i] = m_vArea[i].first ;
// aggiungo le diverse curve
bool bFirstCrv ;
Plane3d plExtLoop ;
double dAreaExtLoop = 0. ;
do {
bFirstCrv = true ;
for ( int i = 0 ; i < int( m_vArea.size()) ; ++ i) {
// recupero indice di percorso e verifico sia valido
int j = m_vArea[i].first ;
if ( j < 0)
continue ;
// lo inserisco come esterno...
if ( bFirstCrv) {
vnPLIndMat.push_back({ j}) ;
m_vArea[i].first = -1 ;
dAreaExtLoop = m_vArea[i].second ;
// inverto se necessario
if ( m_vArea[i].second < EPS_SMALL) {
vPL[j].Invert() ;
vCrvCompo[j]->Invert() ;
dAreaExtLoop *= -1 ;
}
bFirstCrv = false ;
}
// ... altrimenti verifico se il loop è interno o no
else {
// il loop è interno se è sia interno al loop esterno della riga di vnPLIndMat e allo stesso tempo
// esterno a tutti i loop già inseriti nella riga attuale.
// verifica rispetto loop esterno
IntersCurveCurve ccInt( *vCrvCompo[vnPLIndMat.back().front()], *vCrvCompo[j]) ;
CRVCVECTOR ccClass ;
if ( ccInt.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt.GetCurveClassification( 1, EPS_SMALL, ccClass) ||
ccClass.empty() || ccClass[0].nClass != CRVC_IN)
continue ;
// verifica rispetto ai loop interni
bool bOk = true ;
for ( int k = 1 ; k < int( vnPLIndMat.back().size()) ; ++ k) {
IntersCurveCurve ccInt2( *vCrvCompo[vnPLIndMat.back()[k]], *vCrvCompo[j]) ;
CRVCVECTOR ccClass2 ;
if ( ccInt2.GetCrossOrOverlapIntersCount() > 0 ||
! ccInt2.GetCurveClassification( 1, EPS_SMALL, ccClass2) ||
ccClass2.empty() || ccClass2[0].nClass != CRVC_IN) {
bOk = false ;
break ;
}
}
if ( bOk) {
// inserisco nella matrice
vnPLIndMat.back().push_back( j) ;
m_vArea[i].first = -1 ;
// inverto se necessario
if ( m_vArea[i].second * dAreaExtLoop > 0.) {
vPL[j].Invert() ;
vCrvCompo[j]->Invert() ;
}
}
}
}
} while ( ! bFirstCrv) ;
// ordino le PolyLine per area
POLYLINEVECTOR vPL_tmp ;
for ( int i = 0 ; i < int( vPL_IndOrder.size()) ; ++ i)
vPL_tmp.push_back( vPL[ vPL_IndOrder[i]]) ;
swap( vPL, vPL_tmp) ;
return true ;
}
+1548 -184
View File
File diff suppressed because it is too large Load Diff
+9
View File
@@ -137,6 +137,12 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
// se la superficie è trimmata restituisce i loop dello spazio parametrico in forma di linee spezzate
bool GetLoops( ICRVCOMPOPOVECTOR& vCC, bool bLineOrBezier, int nEdge = -1) const override ;
bool IsPlanar( void) const override ;
bool CreateByFlatContour( const PolyLine& PL) override ;
bool CreateByRegion( const POLYLINEVECTOR& vPL) override ;
bool CreateByExtrusion( const ICurve* pCurve, const Vector3d& vtExtr, bool bDeg3OrDeg2 = false) override ;
bool CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const Vector3d& vtAx, double dAngRotDeg, double dMove) override ;
bool CreateByPointCurve( const Point3d& pt, const ICurve* pCurve) override ;
bool CreateByTwoCurves( const ICurve* pCurve1, const ICurve* pCurve2, int nType) override ;
public : // IGeoObjRW
int GetNgeId( void) const override ;
@@ -189,11 +195,14 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
double GetCurveOnVApproxLen( double dU) const ;
// funzione che proietta nello spazio parametrico un trim derivante da un taglio con un piano, categorizzandolo come aperto o chiuso ( nel parametrico)
bool AddCurveCompoToCuts( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed, double dToler = EPS_SMALL, const Plane3d* pPlCut = nullptr) const ;
ISurfFlatRegion* CreateTrimRegionFromCuts( ICRVCOMPOPOVECTOR& vpCCOpen, ICRVCOMPOPOVECTOR& vpCCClosed) const ;
// restituisce il singolo edge della superficie non trimmata
ICurveComposite* GetSingleEdge3D( bool bLineOrBezier, int nEdge) const ;
bool UpdateEdgesFromTree( Tree& tr) const ;
// funzione che calcola se gli edge sono collassati in poli
bool CalcPoles( void) ;
bool FindMatchByParam( const PolyLine& pl0, const PolyLine& pl1, INTVECTOR& vMatch, int& nLong) const ;
bool ParametrizeByLen( const ICurveComposite* pCurve0, const ICurveComposite* pCurve1, DBLVECTOR& vParam0, DBLVECTOR& vParam1) const ;
private :
ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto
+4
View File
@@ -2715,6 +2715,8 @@ VeryfyPolylineForRevolution( const PolyLine& PL, const Point3d& ptAx, const Vect
ptPc.z = 0 ;
++ nSeg ;
// verifico distanza
// se la curva è chiusa oppure è vicina all'asse ( entro EPS_SMALL), ma non ho che sono start o end ad essere sull'asse
// allora dovrò rimaneggiare la polyline
if ( DistPointLine( ORIG, ptPp, ptPc).IsSmall()) {
if ( bClosed ||
( ! ( nSeg == 1 && AreSamePointApprox( ORIG, ptPp)) &&
@@ -2833,10 +2835,12 @@ SurfTriMesh::CreateByScrewing( const PolyLine& PL, const Point3d& ptAx, const Ve
// verifico che la polilinea non attraversi l'asse di rivoluzione o lo tocchi in punti interni
PolyLine MyPL = PL ;
// commented for debug
if ( ! VeryfyPolylineForRevolution( MyPL, ptAx, vtAx) && ! AdjustPolylineForRevolution( MyPL, ptAx, vtAx)) {
LOG_ERROR( GetEGkLogger(), "StmCreateByRevolution : polyline inside meets axis")
return false ;
}
// commented for debug
// imposto ricalcolo
m_nStatus = ERR ;
+607 -210
View File
File diff suppressed because it is too large Load Diff
+26 -18
View File
@@ -155,7 +155,7 @@ class Cell
~Cell( void) {}
Cell( void)
: m_nId( -1),m_nTop ( -2), m_nBottom( -2), m_nLeft( -2), m_nRight ( -2), m_nParent( -2), m_nDepth( 0),
m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_nFlag2( 0), m_nRightEdgeIn( -1), m_bOnLeftEdge( false), m_bOnTopEdge( false),
m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_nFlag2( 0), m_nRightEdgeIn( -1), m_bOnLeftEdge( false), m_bOnTopEdge( false), m_nVertToErase( -1),
m_ptPbl( ORIG), m_ptPtr( SBZ_TREG_COEFF, SBZ_TREG_COEFF, 0), m_bProcessed( false), m_bSplitVert( true)
{
Point3d ptTr ( 1 * SBZ_TREG_COEFF, 1 * SBZ_TREG_COEFF) ;
@@ -163,7 +163,7 @@ class Cell
}
Cell( const Point3d& ptBL, const Point3d& ptTR)
: m_nId( -1),m_nTop ( -2), m_nBottom( -2), m_nLeft( -2), m_nRight ( -2), m_nParent( -2), m_nDepth( 0),
m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_nFlag2( 0), m_nRightEdgeIn( -1), m_bOnLeftEdge( false), m_bOnTopEdge( false),
m_nChild1( -2), m_nChild2( -2), m_nFlag( -1), m_nFlag2( 0), m_nRightEdgeIn( -1), m_bOnLeftEdge( false), m_bOnTopEdge( false), m_nVertToErase( -1),
m_ptPbl( ptBL), m_ptPtr( ptTR), m_bProcessed( false), m_bSplitVert( true) {}
bool IsSame( const Cell& cOtherCell) const
{ return ( m_nId == cOtherCell.m_nId) ; }
@@ -185,9 +185,9 @@ class Cell
{ return Point3d( m_ptPtr.x, m_ptPbl.y); }
double GetSplitValue( void) const
{ return m_dSplit ; }
bool IsSplitVert( void) const // se true la cella verrebbe splittata verticalmente, senn orizzontalmente
bool IsSplitVert( void) const // se true la cella verrebbe splittata verticalmente, sennò orizzontalmente
{ return m_bSplitVert ; }
bool IsLeaf( void) const // flag che indica se la cella ha figli o se una foglia
bool IsLeaf( void) const // flag che indica se la cella ha figli o se è una foglia
{ return ( m_nChild1 == -2 && m_nChild2 == -2) ; }
bool IsProcessed( void) const // flag che indica se tutti i figli della cella, se ce ne sono, sono stati processati
{ return m_bProcessed ; }
@@ -217,6 +217,7 @@ class Cell
bool m_bOnTopEdge ; // flag che indica se la cella è sul lato top ( per superfici chiuse sul parametro V)
std::vector<Inters> m_vInters ; // vettore delle intersezioni della cella con i loop di trim
// ogni elemento del vettore è l'insieme dei punti che caratterizza un attraversamento della cella
int m_nVertToErase ; // vertice da eliminare dal poligono della cella, in caso di lato sovrapposto ad un lato di polo
private :
Point3d m_ptPbl ; // punto bottom left
@@ -235,12 +236,17 @@ class Tree
Tree( const Point3d ptBl, const Point3d ptTr) ; // creatore da usare solo nel caso in cui si voglia aggiungere tagli ad un'unica cella e del risultato ottenere il contorno
bool SetSurf( const SurfBezier* pSrfBz, bool bSplitPatches = true, const Point3d& ptMin = ORIG, const Point3d& ptMax = ORIG) ;
bool GetIndependentTrees( BIPNTVECTOR& vTrees) ; // calcolo la suddivisione della superficie solo sulle singole bbox dei loop di trim ( unendo quelli vicini)
bool BuildTree( double dLinTol = LIN_TOL_STD, double dSideMin = 1, double dSideMax = INFINITO) ; // dSideMax il massimo per la dimensione maggiore di un triangolo della trimesh
// dSideMin lunghezza minima del lato di una cella nello spazio reale
bool BuildTree( double dLinTol = LIN_TOL_STD, double dSideMin = 1, double dSideMax = INFINITO) ; // dSideMax è il massimo per la dimensione maggiore di un triangolo della trimesh
// dSideMin è lunghezza minima del lato di una cella nello spazio reale
bool BuildTree_test( double dLinTol = LIN_TOL_STD, double dSideMin = 1, double dSideMax = INFINITO) ;
bool GetPolygons( POLYLINEMATRIX& vPolygons) ;
bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells = {}) ; // restituisce il poligono corrispondente ad ogni cella foglia dell'albero
// ad ogni poligono sono stati aggiunti tutti i vertici dei vicini posizionati sui suoi lati
bool GetPolygons( POLYLINEMATRIX& vvPolygons) ;
bool GetPolygons( POLYLINEMATRIX& vvPolygons, POLYLINEMATRIX& vvPolygons3d) ;
bool GetPolygons( POLYLINEMATRIX& vPolygons, bool bForTriangulation, POLYLINEMATRIX& vvPolygons3d) ;
bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, bool bForTriangulation, POLYLINEVECTOR& vPolygons3d, INTVECTOR vCells = {}) ; // restituisce il poligono corrispondente ad ogni cella foglia dell'albero
// ad ogni poligono sono stati aggiunti tutti i vertici dei vicini posizionati sui suoi lati
// se richiesti per la triangolazione ad alcuni poligoni potrebbero venire tolti dei punti per evitare errori dovuti ad eventuali poli sui bordi del parametrico
bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, POLYLINEVECTOR& vPolygons3d) ;
bool GetPolygonsBasic( POLYLINEVECTOR& vPolygons, INTVECTOR vCells = {}) ;
bool GetLeaves ( std::vector<Cell>& vLeaves) const ; // restituisce gli indici delle foglie nell'albero
bool GetEdges3D ( POLYLINEMATRIX& mPLEdges) ; // restituisce gli edge 3D come polyline
bool GetSplitLoops( POLYLINEVECTOR& vPl) const // funzione che restituisce i loop splitatti ai confini delle celle
@@ -256,8 +262,8 @@ class Tree
private :
bool LimitLoop( PolyLine& pl, POLYLINEVECTOR& vPl, BOOLVECTOR& vbOrientation) const ; // funzione che limita i loop di trim allo spazio parametrico
bool Split( int nId, double dSplitValue) ; // funzione di split di una cella al parametro indicato nella direzione data da bVert
bool Split( int nId) ; // funzione di split di una cella dell'albero a met nella direzione data da bVert
void Balance( void) ; // creo rami in modo che tutte tutte le foglie abbiano come adiacenti foglie ad una profondit di +- 1
bool Split( int nId) ; // funzione di split di una cella dell'albero a metà nella direzione data da bVert
void Balance( void) ; // creo rami in modo che tutte tutte le foglie abbiano come adiacenti foglie ad una profondità di +- 1
int GetHeightLeaves( int nId, INTVECTOR& vnLeaves, int d = 0) const ; // altezza del subtree a partire dal nodo nId
int GetDepth( int nId, int nRef) const ; // livello del nodo nId
void GetTopNeigh( int nId, INTVECTOR& vTopNeighs) const ; // restituisce le celle foglie che sono adiacenti al lato top
@@ -268,17 +274,18 @@ class Tree
void ResetTree( void) ; // resetto m_bProcessed a false per tutti i nodi dell'albero
INTVECTOR FindCell( const Point3d& ptToAssign, const CurveLine& cl, bool bRecurs = false) const ; // dato un punto, trova la cella foglia a cui appartiene
INTVECTOR FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells, bool bRecurs = false) const ; // dato un punto, trova la cella foglia a cui appartiene
bool TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) ; // tracing dei loop e labelling delle celle
bool FindInters( int& nId, const CurveLine& clTrim, PNTVECTOR& vptInters, bool bFirstInters = true) ; // trova le intersezioni tra una cella e una linea di trim
bool TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons) ; // tracing dei loop e labelling delle celle
bool FindInters( int& nId, const CurveLine& clTrim, const PolyLine& plPolygon, PNTVECTOR& vptInters, bool bFirstInters = true) ; // trova le intersezioni tra una cella e una linea di trim
// resituisce l'id della cella verso cui la curva di trim esce e il vettore delle intersezioni per la cella successiva con il primo punto
bool CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, INTVECTOR& vToCheck, int& nPoly, INTVECTOR& vnParentChunk, const PolyLine& plCell) ; // crea i poligoni della cella passata. richiede anche la funzione CreateIslandAndHoles per completare i poligoni.
bool CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, int& nPoly, INTVECTOR& vnParentChunk) ; // ai poligoni generati da CreatePolygonsCell aggiunge i loop che creano isole o buchi all'interno della singola cella
bool CreateCellPolygons( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vPolygons3d, INTVECTOR& vToCheck, int& nPoly, INTVECTOR& vnParentChunk, const PolyLine& plCell, const PolyLine& plCell3d) ; // crea i poligoni della cella passata. richiede anche la funzione CreateIslandAndHoles per completare i poligoni.
bool CreateIslandAndHoles( int nLeafId, POLYLINEMATRIX& vPolygons, POLYLINEMATRIX& vvPolygons3d, int& nPoly, INTVECTOR& vnParentChunk, bool bForTriangulation) ; // ai poligoni generati da CreatePolygonsCell aggiunge i loop che creano isole o buchi all'interno della singola cella
bool CheckIfBefore( const PolyLine& pl, int nEdge) const ; // controllo se ptEnd è prima di ptStart sul lato nEdge rispetto al senso antiorario
bool CheckIfBefore( const Inters& inA) const ; // controlla se l'ingresso è prima dell'uscita in senso antiorario a partire da ptTR.
bool CheckIfBefore( int nEdge1, const Point3d& ptP1, int nEdge2, const Point3d& ptP2) const ; // verifico quale punto viene prima tra pt1 e pt2 a partire da ptTR girando in senso CCW (punto 1 su edge 1 e punto 2 su edge 2, rispetto al lato 3)
bool CheckIfBefore( int nEdge, const Point3d& ptP1, const Point3d& ptP2, int nEdge2 = -1) const ; // sul lato nEdge controllo se ptP1 viene prima di ptP2.
bool AreSameEdge( int nEdge1, int nEdge2) const ; // indica se i due edge sono lo stesso. Un vertice adiacente ad un edge viene considerato uguale a questo edge
bool AddVertex( int nId, const PNTMATRIX& vEdgeVertex, PolyLine& plTrimmedPoly, int& c, const Point3d& ptToAdd) const ; // aggiunge un punto ad un poligono in una cella, premurandosi di aggiungere eventualmente vertici o punti di celle vicine di cui tenere conto
bool AddVertex( int nId, const PNTMATRIX& vEdgeVertex, const PNTMATRIX& vEdgeVertex3d, PolyLine& plTrimmedPoly, int& c,
const Point3d& ptToAdd, PolyLine& plTrimmedPoly3d, bool ForTriangulation) const ; // aggiunge un punto ad un poligono in una cella, premurandosi di aggiungere eventualmente vertici o punti di celle vicine di cui tenere conto
bool SetRightEdgeIn( int nId) ; // categorizza la cella in base all'edge destro per poter poi definire m_nFlag
bool CategorizeCell( int nId) ; // categorizza la cella in base al flag m_nFlag (dentro, fuori, intersecata)
bool CheckIfBetween( const Inters& inA, const Inters& inB) const ; // / controllo se inB è compreso tra l'end e lo start di inA (in senso CCW)
@@ -310,8 +317,9 @@ class Tree
int m_nSpanU ; // numero di span lungo il parametro U
int m_nSpanV ; // numero di span lungo il parametro V
POLYLINEMATRIX m_vPolygons ; // matrice dei poligoni del tree
std::map<int,Cell> m_mTree ; // mappa che contiene tutti i nodi e le foglie dell'albero. -2 puntatore Null e -1 root
std::map<int,PNTVECTOR> m_mVert ; // mappa che contiene tutti i vertici 3d delle celle del tree. L'Id lo stesso che la cella ha in m_mTree
POLYLINEMATRIX m_vPolygons3d ; // matrice dei poligoni3d del tree
std::map<int,Cell> m_mTree ; // mappa che contiene tutti i nodi e le foglie dell'albero. -2 è puntatore Null e -1 è root
std::map<int,PNTVECTOR> m_mVert ; // mappa che contiene tutti i vertici 3d delle celle del tree. L'Id è lo stesso che la cella ha in m_mTree. I punti sono nell'ordine P00, P10, P11, P01
INTVECTOR m_vnLeaves ; // vettore delle foglie
INTVECTOR m_vnParents ; // vettore delle celle ottenute dalla divisione preliminare in singole patch
bool m_bTestMode ; // bool che indica se la test mode è attiva