Merge branch 'master' of https://gitlab.steamware.net/egaltech/EgtGeomKernel
This commit is contained in:
+142
-60
@@ -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 ;
|
||||
|
||||
@@ -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 ;
|
||||
}
|
||||
|
||||
@@ -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 ;
|
||||
|
||||
Binary file not shown.
@@ -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" />
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
+34
-1
@@ -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
@@ -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 ;
|
||||
}
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
@@ -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 ;
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user