From 5013fc2b6ceb1887d0bdf38b7d0e3ee04c1b39f6 Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Wed, 10 Apr 2024 16:17:39 +0200 Subject: [PATCH] EgtGeomKernel : - funzioni MakeUniform e OnWhichEdge per Bezier spostate da converter e exch3dm a metodi della classe Bezier. --- SurfBezier.cpp | 172 +++++++++++++++++++++++++++++++++++++++++++++++++ SurfBezier.h | 2 + 2 files changed, 174 insertions(+) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 3f2e6bf..04b59e5 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -3176,4 +3176,176 @@ SurfBezier::GetSingleEdge3D( bool bLineOrBezier, int nEdge) const } } return pCrvCompo ; +} + +//---------------------------------------------------------------------------- +bool +SurfBezier::MakeUniform( ISurfFlatRegion** sfr, DBLVECTOR& vU0, DBLVECTOR& vV0, double dScaleU, double dScaleV, bool& bRescaled, bool bRetry) const +{ + // la superficie in input arriva già scalata + bool bRescaledU = false ; + bool bRescaledV = false ; + int nSpanU = 1, nSpanV = 1 ; + PtrOwner sfr_rescaled( CreateSurfFlatRegion()) ; + for ( int nDir = 0 ; nDir <= 1 ; ++ nDir) { + // vettore dei nodi + DBLVECTOR vU ; + int nExtraKnots = 0 ; + + if ( nDir == 0) { + if ( m_nDegU > 1) { + nExtraKnots = m_nDegU - 1 ; + } + for ( int i = nExtraKnots ; i < int( vU0.size()) - nExtraKnots ; ++i ) { + double dKnot = vU0[i] * SBZ_TREG_COEFF ; + // lo aggiungo solo se è diverso dal precedente + if ( i == nExtraKnots || dKnot > vU.back() + EPS_SMALL || dKnot < vU.back() - EPS_SMALL) + vU.push_back( dKnot) ; + } + } + else if ( nDir == 1 ) { + if ( m_nDegV > 1) { + nExtraKnots = m_nDegV - 1 ; + } + for ( int i = nExtraKnots ; i < int( vV0.size()) - nExtraKnots ; ++i ) { + double dKnot = vV0[i] * SBZ_TREG_COEFF ; + // lo aggiungo solo se è diverso dal precedente + if ( i == nExtraKnots || dKnot > vU.back() + EPS_SMALL || dKnot < vU.back() - EPS_SMALL) + vU.push_back( dKnot) ; + } + } + + nDir == 0 ? nSpanU = (int)vU.size() - 1 : nSpanV = (int)vU.size() - 1 ; + // controllo se il vettore dei nodi è uniforme + int a = 0, b = 1 ; + double d0 = abs( vU[b] - vU[a]), d1 = d0 ; + // il vettore è uniforme quando la distanza tra nodi consecutivi è sempre zero o un valore costante + while ( b < (int)vU.size() && ( ( d1 < d0 + EPS_SMALL && d1 > d0 - EPS_SMALL) || d1 < EPS_SMALL)) { + a = b ; + ++b ; + if ( b < (int)vU.size()) + d1 = abs( vU[b] - vU[a]) ; + } + if ( b != (int)vU.size()) { + nDir == 0 ? bRescaledU = true : bRescaledV = true ; + sfr_rescaled.Set( CreateSurfFlatRegion()) ; + if ( IsNull( sfr_rescaled)) + return false ; + for ( int p = 0 ; p < (int)vU.size() - 1 ; ++p) { + PtrOwner pSfr_copy( (*sfr)->Clone()) ; + if ( IsNull( pSfr_copy)) + return false ; + double dLenStrip = abs( vU[p+1] - vU[p]) ; + if ( dLenStrip < EPS_SMALL) + continue ; + // creo la maschera per tagliare la superficie originale e ottenere una striscia + PtrOwner pSfrTrim( CreateSurfFlatRegion()) ; + + // ricavo la maschera del trim, con cui poi farò l'intersezione con la sfr iniziale + Vector3d vtTrim ; + if ( nDir == 0) { + pSfrTrim.Set( GetSurfFlatRegionRectangle( dLenStrip, dScaleV + 2)) ; + vtTrim.Set( abs(vU[p] - vU.front()), - 1, 0) ; + } + else{ + pSfrTrim.Set( GetSurfFlatRegionRectangle( dScaleU + 2, dLenStrip)) ; + vtTrim.Set( - 1, abs(vU[p] - vU.front()), 0) ; + } + pSfrTrim->Translate( vtTrim) ; + + if ( ! pSfr_copy->Intersect( *pSfrTrim)) + return false ; + + // aggiungo la nuova striscia solo se è valida + if ( pSfr_copy->IsValid() ) { + if ( nDir == 0) + pSfr_copy->Scale( GLOB_FRM, SBZ_TREG_COEFF / dLenStrip, 1, 1) ; + else + pSfr_copy->Scale( GLOB_FRM, 1, SBZ_TREG_COEFF / dLenStrip, 1) ; + + // prima di riunire la striscia al resto devo traslarla sul bordo destro della superificie che sto ricostruendo + + Point3d pt ; + nDir == 0 ? pt.Set( abs(vU[p] - vU.front()), 0, 0) : pt.Set( 0,abs(vU[p] - vU.front()), 0) ; + if ( nDir == 0) + pt.Scale( GLOB_FRM, SBZ_TREG_COEFF / dLenStrip, 1, 1) ; + else + pt.Scale( GLOB_FRM, 1, SBZ_TREG_COEFF / dLenStrip, 1) ; + + Vector3d vtJoin ; + if ( nDir == 0) + vtJoin.Set( p * SBZ_TREG_COEFF - pt.x, 0, 0) ; + else + vtJoin.Set( 0, p * SBZ_TREG_COEFF - pt.y, 0) ; + pSfr_copy->Translate( vtJoin) ; + // se sto ritentando MakeUniform, allora faccio anche OFFSET e controOFFSET + if ( bRetry) + pSfr_copy->Offset( 10*EPS_SMALL,ICurve::OFF_FILLET) ; // OFFSET + if ( sfr_rescaled->IsValid()) { + if ( ! sfr_rescaled->Add( *pSfr_copy)) + return false ; + } + else + sfr_rescaled.Set( pSfr_copy) ; + } + } + if ( nDir == 0) { + dScaleU = ((int)vU.size() - 1) * SBZ_TREG_COEFF ; + if ( sfr_rescaled->IsValid()) { + if ( bRetry) + sfr_rescaled->Offset( -10*EPS_SMALL,ICurve::OFF_FILLET) ; //contro OFFSET + *sfr = Release( sfr_rescaled) ; + } + } + else + dScaleV = ((int)vU.size() - 1) * SBZ_TREG_COEFF ; + } + } + + if ( ! IsNull( sfr_rescaled) && sfr_rescaled->IsValid()) { + if ( bRetry) + sfr_rescaled->Offset( -10*EPS_SMALL,ICurve::OFF_FILLET) ; // contro OFFSET + *sfr = Release( sfr_rescaled) ; + } + + if ( ! bRescaledU && ! bRescaledV) + ( *sfr)->Scale( GLOB_FRM, nSpanU / dScaleU * SBZ_TREG_COEFF, nSpanV / dScaleV * SBZ_TREG_COEFF, 1) ; + else if ( bRescaledU && ! bRescaledV) + ( *sfr)->Scale( GLOB_FRM, 1, nSpanV / dScaleV * SBZ_TREG_COEFF, 1) ; + else if ( ! bRescaledU && bRescaledV) + ( *sfr)->Scale( GLOB_FRM, nSpanU / dScaleU * SBZ_TREG_COEFF, 1, 1) ; + + bRescaled = bRescaledU || bRescaledV ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +SurfBezier::OnWhichEdge( double u0, double u1, double v0, double v1, int& nEdge, Point3d ptToAssign) const +{ + Point3d ptTR( u1, v1) ; + Point3d ptTl( u0, v1) ; + Point3d ptBL( u0, v0) ; + Point3d ptBr( u1, v0) ; + + double dEps = 0.1 ; + if ( AreSamePointEpsilon( ptToAssign, ptTR, dEps)) + nEdge = 7 ; + else if ( AreSamePointEpsilon( ptToAssign, ptTl, dEps)) + nEdge = 4 ; + else if ( AreSamePointEpsilon( ptToAssign, ptBL, dEps)) + nEdge = 5 ; + else if ( AreSamePointEpsilon( ptToAssign, ptBr, dEps)) + nEdge = 6 ; + else if ( ptToAssign.x > ptBL.x - dEps && ptToAssign.x < ptTR.x + dEps && abs( ptToAssign.y - ptTR.y) < dEps) + nEdge = 0 ; + else if ( ptToAssign.y > ptBL.y - dEps && ptToAssign.y < ptTR.y + dEps && abs( ptToAssign.x - ptBL.x) < dEps) + nEdge = 1 ; + else if ( ptToAssign.x > ptBL.x - dEps && ptToAssign.x < ptTR.x + dEps && abs( ptToAssign.y - ptBL.y) < dEps) + nEdge = 2 ; + else if ( ptToAssign.y > ptBL.y - dEps && ptToAssign.y < ptTR.y + dEps && abs( ptToAssign.x - ptTR.x) < dEps) + nEdge = 3 ; + else + return false ; + return true ; } \ No newline at end of file diff --git a/SurfBezier.h b/SurfBezier.h index 56bc818..148699c 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -138,6 +138,8 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW // funzione che restituisce gli edge della superficie o in forma di linea spezzata o in forma di curva di Bezier // 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 MakeUniform( ISurfFlatRegion** sfr, DBLVECTOR& vU, DBLVECTOR& vV, double dScaleU, double dScaleV, bool& bRescaled, bool bRetry) const override ; + bool OnWhichEdge( double u0, double u1, double v0, double v1, int& nEdge, Point3d ptToAssign) const override ; public : // IGeoObjRW int GetNgeId( void) const override ;