From 2c6ebdadca049a1bfe8c9d12b68a5d185ced558b Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Mon, 30 Mar 2020 11:04:20 +0000 Subject: [PATCH] EgtGeomKernel : - correzioni, migliorie e d estensioni alle superfici di Bezier - in Release cambiate opzioni di ottimizzazione da /Ox a /O2. --- Bernstein.h | 1 - CurveBezier.cpp | 197 ++++++++++------- CurveBezier.h | 2 + EgtGeomKernel.vcxproj | 5 +- EgtGeomKernel.vcxproj.filters | 3 + StmFromTriangleSoup.cpp | 38 ++++ SurfBezier.cpp | 388 +++++++++++++++++++++++++++------- SurfBezier.h | 15 +- deCasteljau.h | 85 ++++++++ stdafx.cpp | 4 +- 10 files changed, 575 insertions(+), 163 deletions(-) create mode 100644 deCasteljau.h diff --git a/Bernstein.h b/Bernstein.h index 85bf2f2..5e81dfc 100644 --- a/Bernstein.h +++ b/Bernstein.h @@ -14,7 +14,6 @@ #pragma once //--------------------------- Include ---------------------------------------- -#include "stdafx.h" #include "/EgtDev/Include/EgtNumCollection.h" //---------------------------------------------------------------------------- diff --git a/CurveBezier.cpp b/CurveBezier.cpp index 9e23f8d..e3537bf 100644 --- a/CurveBezier.cpp +++ b/CurveBezier.cpp @@ -25,6 +25,7 @@ #include "NgeReader.h" #include "PolynomialPoint3d.h" #include "Bernstein.h" +#include "deCasteljau.h" #include "/EgtDev/Include/EGkCurveArc.h" #include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EGkUiUnits.h" @@ -57,11 +58,11 @@ CurveBezier::~CurveBezier( void) bool CurveBezier::Init( int nDeg, bool bIsRational) { - // verifico validità grado + // verifico validità grado if ( nDeg < 1 || nDeg > MAXDEG) return false ; - // imposto grado, flag di razionale e singolarità non studiata + // imposto grado, flag di razionale e singolarità non studiata m_nDeg = nDeg ; m_bRat = bIsRational ; m_dParSing = - 2 ; @@ -84,7 +85,7 @@ CurveBezier::Init( int nDeg, bool bIsRational) bool CurveBezier::SetControlPoint( int nInd, const Point3d& ptCtrl) { - // verifico validità indice + // verifico validità indice if ( m_nStatus != OK || m_bRat || nInd < 0 || nInd > m_nDeg) return false ; @@ -95,7 +96,7 @@ CurveBezier::SetControlPoint( int nInd, const Point3d& ptCtrl) if ( m_bRat) m_vWeCtrl[nInd] = 1 ; - // annullo analisi presenza singolarità + // annullo analisi presenza singolarità m_dParSing = - 2 ; // imposto ricalcolo della grafica @@ -108,7 +109,7 @@ CurveBezier::SetControlPoint( int nInd, const Point3d& ptCtrl) bool CurveBezier::SetControlPoint( int nInd, const Point3d& ptCtrl, double dW) { - // verifico validità, razionalità e indice + // verifico validità, razionalità e indice if ( m_nStatus != OK || ! m_bRat || nInd < 0 || nInd > m_nDeg) return false ; @@ -120,7 +121,7 @@ CurveBezier::SetControlPoint( int nInd, const Point3d& ptCtrl, double dW) m_vPtCtrl[nInd] = ptCtrl ; m_vWeCtrl[nInd] = dW ; - // annullo analisi presenza singolarità + // annullo analisi presenza singolarità m_dParSing = - 2 ; // imposto ricalcolo della grafica @@ -215,7 +216,7 @@ CurveBezier::IsAPoint( void) const const Point3d& CurveBezier::GetControlPoint( int nInd, bool* pbOk) const { - // verifico validità e indice + // verifico validità e indice if ( m_nStatus != OK || nInd < 0 || nInd > m_nDeg) { if ( pbOk != NULL) *pbOk = false ; @@ -231,7 +232,7 @@ CurveBezier::GetControlPoint( int nInd, bool* pbOk) const double CurveBezier::GetControlWeight( int nInd, bool* pbOk) const { - // verifico validità, razionalità e indice + // verifico validità, razionalità e indice if ( m_nStatus != OK || ! m_bRat || nInd < 0 || nInd > m_nDeg) { if ( pbOk != NULL) *pbOk = false ; @@ -452,7 +453,7 @@ CurveBezier::GetLocalBBox( BBox3d& b3Loc, int nFlag) const b3Loc.Add( ptTemp) ; } } - // se c'è estrusione, devo tenerne conto + // se c'è estrusione, devo tenerne conto if ( ! m_VtExtr.IsSmall() && abs( m_dThick) > EPS_SMALL) { Point3d ptMinExtr = b3Loc.GetMin() + m_VtExtr * m_dThick ; Point3d ptMaxExtr = b3Loc.GetMax() + m_VtExtr * m_dThick ; @@ -470,7 +471,7 @@ CurveBezier::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const // verifico lo stato if ( m_nStatus != OK) return false ; - // verifico validità del frame + // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; // assegno il box nel riferimento @@ -496,7 +497,7 @@ CurveBezier::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const b3Ref.Add( ptTemp) ; } } - // se c'è estrusione, devo tenerne conto + // se c'è estrusione, devo tenerne conto if ( ! m_VtExtr.IsSmall() && abs( m_dThick) > EPS_SMALL) { Vector3d vtFrExtr = m_VtExtr ; vtFrExtr.ToGlob( frRef) ; @@ -525,7 +526,7 @@ CurveBezier::IsFlat( Plane3d& plPlane, double dToler) const if ( ! shPL.AddUPoint( dU, GetControlPoint( i))) return false ; } - // recupero dati sulla planarità + // recupero dati sulla planarità int nRank ; Point3d ptCen ; Vector3d vtDir ; @@ -597,7 +598,7 @@ CurveBezier::GetMidPoint( Point3d& ptMid) const // verifico lo stato if ( m_nStatus != OK) return false ; - // determino il valore del parametro a metà lunghezza + // determino il valore del parametro a metà lunghezza double dLen, dMid ; if ( ! GetLength( dLen) || ! GetParamAtLength( 0.5 * dLen, dMid)) return false ; @@ -634,7 +635,7 @@ CurveBezier::GetMidDir( Vector3d& vtDir) const // verifico lo stato if ( m_nStatus != OK) return false ; - // determino il valore del parametro a metà lunghezza + // determino il valore del parametro a metà lunghezza double dLen, dMid ; if ( ! GetLength( dLen) || ! GetParamAtLength( 0.5 * dLen, dMid)) return false ; @@ -787,7 +788,7 @@ CurveBezier::GetSingularParam( double& dPar) const if ( m_dParSing < -1.5) CalcSingularParam() ; - // se esiste singolarità + // se esiste singolarità if ( m_dParSing > 0 && m_dParSing < 1) { dPar = m_dParSing ; return 1 ; @@ -801,15 +802,15 @@ CurveBezier::GetSingularParam( double& dPar) const bool CurveBezier::CalcSingularParam( void) const { - // non si considerano singolarità agli estremi ( non creano problemi) + // non si considerano singolarità agli estremi ( non creano problemi) - // le curve di grado 1 non possono avere singolarità + // le curve di grado 1 non possono avere singolarità if ( m_nDeg <= 1) { m_dParSing = -1 ; return true ; } - // le curve di grado 2 possono avere singolarità solo se i punti sono allineati con ordine P0 P2 P1 + // le curve di grado 2 possono avere singolarità solo se i punti sono allineati con ordine P0 P2 P1 if ( m_nDeg == 2) { Vector3d vtV1 = m_vPtCtrl[1] - m_vPtCtrl[0] ; Vector3d vtV2 = m_vPtCtrl[2] - m_vPtCtrl[1] ; @@ -849,7 +850,7 @@ CurveBezier::CalcSingularParam( void) const pol3P.AdjustDegree() ; } - // calcolo gli zeri della componente più importante della derivata + // calcolo gli zeri della componente più importante della derivata DBLVECTOR vdRoot ; int nZ = pol3P.FindMainComponentRoots( vdRoot) ; // scarto gli zeri fuori dall'intervallo aperto 0-1 e quelli ripetuti @@ -867,13 +868,13 @@ CurveBezier::CalcSingularParam( void) const } } - // non ci sono singolarità + // non ci sono singolarità m_dParSing = -1 ; return true ; } //---------------------------------------------------------------------------- -// i coefficienti sono ordinati dalla potenza più bassa alla più alta +// i coefficienti sono ordinati dalla potenza più bassa alla più alta // se razionale, ritorna la sola forma monomiale del numeratore //---------------------------------------------------------------------------- bool @@ -910,8 +911,8 @@ CurveBezier::ToPowerBase( PolynomialPoint3d& pol3P) const } //---------------------------------------------------------------------------- -// i coefficienti sono ordinati dalla potenza più bassa alla più alta -// se polinomiale, la forma monomiale del denominatore è un 1 +// i coefficienti sono ordinati dalla potenza più bassa alla più alta +// se polinomiale, la forma monomiale del denominatore è un 1 //---------------------------------------------------------------------------- bool CurveBezier::ToPowerBase( PolynomialPoint3d& pol3Num, Polynomial& polDen) const @@ -976,6 +977,37 @@ CurveBezier::GetControlPolygonLength( double& dLen) const return true ; } +//---------------------------------------------------------------------------- +bool +CurveBezier::GetApproxLength( double& dLen) const +{ + // la curva deve essere valida + if ( m_nStatus != OK) + return false ; + // se ridotta ad un punto + if ( IsAPoint()) { + dLen = 0 ; + return true ; + } + // se grado 1 + if ( m_nDeg == 1) { + dLen = Dist( m_vPtCtrl[0], m_vPtCtrl[m_nDeg]) ; + return true ; + } + // la divido in due metà + CurveBezier crvBez1 = *this ; + crvBez1.TrimEndAtParam( 0.5) ; + double dCordLen1 = Dist( crvBez1.m_vPtCtrl[0], crvBez1.m_vPtCtrl[m_nDeg]) ; + double dCtrlLen1 ; crvBez1.GetControlPolygonLength( dCtrlLen1) ; + CurveBezier crvBez2 = *this ; + crvBez2.TrimStartAtParam( 0.5) ; + double dCordLen2 = Dist( crvBez2.m_vPtCtrl[0], crvBez2.m_vPtCtrl[m_nDeg]) ; + double dCtrlLen2 ; crvBez2.GetControlPolygonLength( dCtrlLen2) ; + // applico la formula di Gravesen (Graphics Gems V) + dLen = ( 2 * ( dCordLen1 + dCordLen2) + ( m_nDeg - 1) * ( dCtrlLen1 + dCtrlLen2)) / ( m_nDeg + 1) ; + return true ; +} + //---------------------------------------------------------------------------- bool CurveBezier::GetLength( double& dLen) const @@ -1016,18 +1048,18 @@ CurveBezier::GetSegmentLength( int nLev, double dU0, double dU1, double dU2, double dUMid ; Point3d ptMid ; - // prima metà + // prima metà dUMid = 0.5 * ( dU0 + dU1) ; GetPointD1D2( dUMid, ptMid) ; double dD3 = GetSegmentLength( nLev +1, dU0, dUMid, dU1, ptP0, ptMid, ptP1) ; - // seconda metà + // seconda metà dUMid = 0.5 * ( dU1 + dU2) ; GetPointD1D2( dUMid, ptMid) ; double dD4 = GetSegmentLength( nLev + 1, dU1, dUMid, dU2, ptP1, ptMid, ptP2) ; - // la lunghezza è la somma delle due + // la lunghezza è la somma delle due return ( dD3 + dD4) ; } @@ -1191,6 +1223,31 @@ CurveBezier::GetLengthAtPoint( const Point3d& ptP, double& dLen, double dTol) co return GetLengthAtParam( dU, dLen) ; } +//---------------------------------------------------------------------------- +bool +CurveBezier::ApproxWithLines( int nStep, PolyLine& PL) const +{ + // pulisco la polilinea + PL.Clear() ; + + // la curva deve essere validata + if ( m_nStatus != OK) + return false ; + + // calcolo i punti richiesti + double dStep = 1.0 / nStep ; + for ( int i = 0 ; i <= nStep ; ++ i) { + double dU = i * dStep ; + Point3d ptPos ; + if ( GetPointD1D2( dU, ptPos)) + PL.AddUPoint( dU, ptPos) ; + else + return false ; + } + + return true ; +} + //---------------------------------------------------------------------------- bool CurveBezier::ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, PolyLine& PL) const @@ -1221,7 +1278,7 @@ CurveBezier::ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, Poly Vector3d vtExtr = ( m_VtExtr.IsSmall() ? Z_AX : m_VtExtr) ; if ( ! PL.ApproxOnSide( vtExtr, ( nType == APL_LEFT), dLinTol)) return false ; - // se necessario, sistemo per convessità dalla parte ammessa + // se necessario, sistemo per convessità dalla parte ammessa if ( nType == APL_RIGHT_CONVEX || nType == APL_LEFT_CONVEX) { if ( ! PL.MakeConvex( vtExtr, ( nType == APL_LEFT_CONVEX))) return false ; @@ -1237,7 +1294,7 @@ CurveBezier::ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, Poly if ( ! FlatOrSplit( 0, *this, 0, 1, dLinTol, dAngTolDeg, PL)) return false ; - // se è stato inserito un solo punto, aggiungo il finale + // se è stato inserito un solo punto, aggiungo il finale if ( PL.GetPointNbr() == 1) return PL.AddUPoint( 1, m_vPtCtrl[m_nDeg]) ; // altrimenti, se l'ultimo punto non coincide con il finale lo sostituisco (distano al max di dLinTol) @@ -1308,19 +1365,19 @@ CurveBezier::FlatOrSplit( int nLev, const CurveBezier& crvBez, double dParStart, double dParDiv ; double dParMid ; CurveBezier crvBez1 ; - // se prima suddivisione e c'è singolarità, divido su questa + // se prima suddivisione e c'è singolarità, divido su questa if ( nLev == 0 && GetSingularParam( dParDiv) > 0) ; - // altrimenti divido a metà + // altrimenti divido a metà else dParDiv = 0.5 ; dParMid = dParDiv * ( dParStart + dParEnd) ; - // prima metà + // prima metà crvBez1 = crvBez ; crvBez1.TrimEndAtParam( dParDiv) ; if ( ! FlatOrSplit( nLev + 1, crvBez1, dParStart, dParMid, dLinTol, dAngTolDeg, PL)) return false ; - // seconda metà + // seconda metà crvBez1 = crvBez ; crvBez1.TrimStartAtParam( dParDiv) ; if ( ! FlatOrSplit( nLev + 1, crvBez1, dParMid, dParEnd, dLinTol, dAngTolDeg, PL)) @@ -1351,7 +1408,7 @@ CurveBezier::ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) con PA.ToGlob( frExtr) ; return bOk ; } - // l'estrusione è secondo Z+, pertanto sono già nel piano XY + // l'estrusione è secondo Z+, pertanto sono già nel piano XY else return ApproxWithArcsXY( dLinTol, dAngTolDeg, PA) ; } @@ -1386,7 +1443,7 @@ CurveBezier::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAngTo PtrOwner pCrv ; double dMaxDist ; - // se la polilinea ha più di 2 punti + // se la polilinea ha più di 2 punti if ( PL.GetPointNbr() > 2) { // calcolo punti e direzioni agli estremi della polilinea usando la curva di Bezier double dU ; @@ -1404,7 +1461,7 @@ CurveBezier::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAngTo if ( IsNull( pCrv)) return false ; } - // se la polilinea è formata da 2 punti + // se la polilinea è formata da 2 punti else if ( PL.GetPointNbr() == 2) { // se molto vicini, esco double dLen ; @@ -1463,10 +1520,10 @@ CurveBezier::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAngTo // spezzo l'intervallo in due parti double dParMid ; - // se prima suddivisione e c'è singolarità, divido su questa + // se prima suddivisione e c'è singolarità, divido su questa if ( nLev == 0 && GetSingularParam( dParMid) > 0) ; - // altrimenti divido a metà + // altrimenti divido a metà else { double dParStart, dParEnd ; if ( ! PL.GetFirstU( dParStart) || ! PL.GetLastU( dParEnd)) @@ -1476,10 +1533,10 @@ CurveBezier::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAngTo PolyLine PL2 ; if ( ! PL.Split( dParMid, PL2)) return false ; - // prima metà + // prima metà if ( ! BiArcOrSplit( nLev + 1, PL, dLinTol, dAngTolDeg, PA)) return false ; - // seconda metà + // seconda metà return BiArcOrSplit( nLev + 1, PL2, dLinTol, dAngTolDeg, PA) ; } @@ -1493,7 +1550,7 @@ CurveBezier::CopyParamRange( double dUStart, double dUEnd) const return nullptr ; // se il parametro start supera quello di end if ( dUStart > dUEnd - EPS_PARAM) { - // se curva aperta, il trim la cancella completamente quindi non resta alcunchè + // se curva aperta, il trim la cancella completamente quindi non resta alcunché if ( ! IsClosed()) return nullptr ; // se curva chiusa, il trim si avvolge attorno al punto di giunzione @@ -1575,24 +1632,14 @@ CurveBezier::TrimStartAtParam( double dUTrim) if ( m_nStatus != OK) return false ; - // se devo togliere dall'inizio o prima non tolgo niente - if ( dUTrim <= 0) - return true ; - // se devo togliere a partire dalla fine o dopo non rimane niente - if ( dUTrim >= 1) - return false ; // eseguo il trim (algoritmo di de Casteljau) - for ( int k = 1 ; k <= m_nDeg ; k ++) { - for ( int i = 0 ; i <= m_nDeg - k ; i ++) { - if ( ! m_bRat) { - m_vPtCtrl[i] = ( 1 - dUTrim) * m_vPtCtrl[i] + dUTrim * m_vPtCtrl[i+1] ; - } - else { - m_vPtCtrl[i] = ( 1 - dUTrim) * m_vWeCtrl[i] * m_vPtCtrl[i] + dUTrim * m_vWeCtrl[i+1] * m_vPtCtrl[i+1] ; - m_vWeCtrl[i] = ( 1 - dUTrim) * m_vWeCtrl[i] + dUTrim * m_vWeCtrl[i+1] ; - m_vPtCtrl[i] = m_vPtCtrl[i] * ( 1 / m_vWeCtrl[i]) ; - } - } + if ( ! m_bRat) { + if ( ! deCastTrimStart( dUTrim, m_nDeg, m_vPtCtrl)) + return false ; + } + else { + if ( ! deCastRatTrimStart( dUTrim, m_nDeg, m_vPtCtrl, m_vWeCtrl)) + return false ; } // con i controlli sopra fatti rimane validata, ma la grafica va ricalcolata @@ -1609,24 +1656,14 @@ CurveBezier::TrimEndAtParam( double dUTrim) if ( m_nStatus != OK) return false ; - // se devo togliere a partire dall'inizio o prima non rimane niente - if ( dUTrim < EPS_PARAM) - return false ; - // se devo togliere dalla fine o dopo non tolgo niente - if ( dUTrim > 1 - EPS_PARAM) - return true ; // eseguo il trim (algoritmo di de Casteljau) - for ( int k = 1 ; k <= m_nDeg ; k ++) { - for ( int i = m_nDeg ; i >= k ; i --) { - if ( ! m_bRat) { - m_vPtCtrl[i] = ( 1 - dUTrim) * m_vPtCtrl[i-1] + dUTrim * m_vPtCtrl[ i] ; - } - else { - m_vPtCtrl[i] = ( 1 - dUTrim) * m_vWeCtrl[i-1] * m_vPtCtrl[i-1] + dUTrim * m_vWeCtrl[ i] * m_vPtCtrl[ i] ; - m_vWeCtrl[i] = ( 1 - dUTrim) * m_vWeCtrl[i-1] + dUTrim * m_vWeCtrl[ i] ; - m_vPtCtrl[i] = m_vPtCtrl[i] * ( 1 / m_vWeCtrl[i]) ; - } - } + if ( ! m_bRat) { + if ( ! deCastTrimEnd( dUTrim, m_nDeg, m_vPtCtrl)) + return false ; + } + else { + if ( ! deCastRatTrimEnd( dUTrim, m_nDeg, m_vPtCtrl, m_vWeCtrl)) + return false ; } // con i controlli sopra fatti rimane validata, ma la grafica va ricalcolata @@ -1808,7 +1845,7 @@ CurveBezier::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, if ( m_nStatus != OK) return false ; - // verifico validità dell'asse di rotazione + // verifico validità dell'asse di rotazione if ( vtAx.IsSmall()) return false ; @@ -1879,7 +1916,7 @@ CurveBezier::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) if ( m_nStatus != OK) return false ; - // verifico validità del piano di specchiatura + // verifico validità del piano di specchiatura if ( vtNorm.IsSmall()) return false ; @@ -1903,7 +1940,7 @@ CurveBezier::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& if ( m_nStatus != OK) return false ; - // verifico validità dei parametri + // verifico validità dei parametri if ( vtNorm.IsSmall() || vtDir.IsSmall()) return false ; @@ -1932,7 +1969,7 @@ CurveBezier::ToGlob( const Frame3d& frRef) if ( m_nStatus != OK) return false ; - // verifico validità del frame + // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; @@ -1956,7 +1993,7 @@ CurveBezier::ToLoc( const Frame3d& frRef) if ( m_nStatus != OK) return false ; - // verifico validità del frame + // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; @@ -1980,7 +2017,7 @@ CurveBezier::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) if ( m_nStatus != OK) return false ; - // verifico validità dei frame + // verifico validità dei frame if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR) return false ; diff --git a/CurveBezier.h b/CurveBezier.h index e5189cd..325b5e6 100644 --- a/CurveBezier.h +++ b/CurveBezier.h @@ -155,6 +155,8 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW { if ( ! CopyFrom( cbSrc)) LOG_ERROR( GetEGkLogger(), "CurveBezier : copy error") return *this ; } + bool ApproxWithLines( int nStep, PolyLine& PL) const ; + bool GetApproxLength( double& dLen) const ; private : bool CopyFrom( const CurveBezier& cbSrc) ; diff --git a/EgtGeomKernel.vcxproj b/EgtGeomKernel.vcxproj index 3456cb9..223d544 100644 --- a/EgtGeomKernel.vcxproj +++ b/EgtGeomKernel.vcxproj @@ -173,7 +173,7 @@ copy $(TargetPath) \EgtProg\DllD64 Level3 Use - Full + MaxSpeed true true WIN32;_WINDOWS;I_AM_EGK;NDEBUG;%(PreprocessorDefinitions) @@ -220,7 +220,7 @@ copy $(TargetPath) \EgtProg\Dll32 Level3 Use - Full + MaxSpeed true true WIN32;_WINDOWS;I_AM_EGK;NDEBUG;%(PreprocessorDefinitions) @@ -283,6 +283,7 @@ copy $(TargetPath) \EgtProg\Dll64 + diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters index 1077060..33a2bf8 100644 --- a/EgtGeomKernel.vcxproj.filters +++ b/EgtGeomKernel.vcxproj.filters @@ -414,6 +414,9 @@ File di origine\Geo + + File di intestazione + diff --git a/StmFromTriangleSoup.cpp b/StmFromTriangleSoup.cpp index 9f4ac36..c1863a7 100644 --- a/StmFromTriangleSoup.cpp +++ b/StmFromTriangleSoup.cpp @@ -74,6 +74,44 @@ StmFromTriangleSoup::AddTriangle( const Triangle3d& Tria) return true ; } +//---------------------------------------------------------------------------- +bool +StmFromTriangleSoup::AddTriangle( const Point3d& ptP0, const Point3d& ptP1, const Point3d& ptP2) +{ + // verifico inizializzazione + if ( m_pSTM == nullptr) + return false ; + // ciclo sui tre vertici + int nIdV[3] ; + if ( ( nIdV[0] = AddVertex( ptP0)) == SVT_NULL) + return false ; + if ( ( nIdV[1] = AddVertex( ptP1)) == SVT_NULL) + return false ; + if ( ( nIdV[2] = AddVertex( ptP2)) == SVT_NULL) + return false ; + // se i vertici sono tutti diversi tra loro, inserisco il triangolo + if ( nIdV[0] != nIdV[1] && nIdV[0] != nIdV[2] && nIdV[1] != nIdV[2]) { + if ( m_pSTM->AddTriangle( nIdV) == SVT_NULL) + return false ; + } + return true ; +} + +//---------------------------------------------------------------------------- +int +StmFromTriangleSoup::AddVertex( const Point3d& ptP) +{ + // verifico se già presente + int nId ; + if ( m_VertGrid.Find( ptP, 2 * EPS_SMALL, nId)) + return nId ; + // aggiungo il vertice + if ( ( nId = m_pSTM->AddVertex( ptP)) == SVT_NULL) + return SVT_NULL ; + m_VertGrid.InsertPoint( ptP, nId) ; + return nId ; +} + //---------------------------------------------------------------------------- bool StmFromTriangleSoup::End( void) diff --git a/SurfBezier.cpp b/SurfBezier.cpp index 27022a3..a81f98c 100644 --- a/SurfBezier.cpp +++ b/SurfBezier.cpp @@ -18,9 +18,13 @@ #include "NgeWriter.h" #include "NgeReader.h" #include "Bernstein.h" +#include "CurveBezier.h" +#include "CurveComposite.h" +#include "/EgtDev/Include/EGkStmFromTriangleSoup.h" #include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EGkUiUnits.h" #include "/EgtDev/Include/EgtNumUtils.h" +#include "/EgtDev/Include/EgtPointerOwner.h" using namespace std ; @@ -29,7 +33,7 @@ GEOOBJ_REGISTER( SRF_BEZIER, NGE_S_BEZ, SurfBezier) ; //---------------------------------------------------------------------------- SurfBezier::SurfBezier(void) - : m_pSTM( nullptr), m_nStatus( TO_VERIFY), m_nDegU(), m_nDegV(), m_bRat( false), m_nTempProp( 0) + : m_pSTM( nullptr), m_nStatus( TO_VERIFY), m_nDegU(), m_nDegV(), m_bRat( false), m_bTrimmed( false), m_nTempProp( 0) { } @@ -52,6 +56,7 @@ SurfBezier::Init( int nDegU, int nDegV, bool bIsRational) m_nDegU = nDegU ; m_nDegV = nDegV ; m_bRat = bIsRational ; + m_bTrimmed = false ; // dimensiono i vettori dei punti e dei pesi m_vPtCtrl.assign( GetDim(), ORIG) ; @@ -115,7 +120,7 @@ SurfBezier::SetControlPoint( int nInd, const Point3d& ptCtrl, double dW) //---------------------------------------------------------------------------- bool -SurfBezier::GetInfo( int& nDegU, int& nDegV, bool& bIsRat) const +SurfBezier::GetInfo( int& nDegU, int& nDegV, bool& bIsRat, bool& bTrimmed) const { // verifico validità superficie if ( m_nStatus != OK) @@ -124,6 +129,7 @@ SurfBezier::GetInfo( int& nDegU, int& nDegV, bool& bIsRat) const nDegU = m_nDegU ; nDegV = m_nDegV ; bIsRat = m_bRat ; + bTrimmed = m_bTrimmed ; return true ; } @@ -535,6 +541,8 @@ SurfBezier::Dump( string& sOut, bool bMM, const char* szNewLine) const sOut += "Area=" + ToString( GetAreaInUiUnits( dArea, bMM),1) + szNewLine ; // parametri : flag razionale sOut += ( m_bRat ? "Rat " : "Int ") ; + // flag trimmata + sOut += ( m_bTrimmed ? "Trim " : "Full ") ; // gradi in U e V sOut += "DegU=" + ToString( m_nDegU) + " DegV=" + ToString( m_nDegV) + szNewLine ; // ciclo sui punti di controllo ( con pesi se razionale) @@ -562,6 +570,9 @@ SurfBezier::Save( NgeWriter& ngeOut) const // flag razionale if ( ! ngeOut.WriteBool( m_bRat, ";")) return false ; + // flag trimmata + if ( ! ngeOut.WriteBool( m_bTrimmed, ";")) + return false ; // gradi if ( ! ngeOut.WriteInt( m_nDegU, ",") || ! ngeOut.WriteInt( m_nDegV, ";", true)) @@ -593,6 +604,10 @@ SurfBezier::Load( NgeReader& ngeIn) bool bIsRat ; if ( ! ngeIn.ReadBool( bIsRat, ";")) return false ; + // recupero il flag trimmata + bool bTrimmed ; + if ( ! ngeIn.ReadBool( bTrimmed, ";")) + return false ; // recupero i gradi int nDegU, nDegV ; if ( ! ngeIn.ReadInt( nDegU, ",") || @@ -647,20 +662,45 @@ SurfBezier::Validate( void) bool SurfBezier::GetLocalBBox( BBox3d& b3Loc, int nFlag) const { - // assegno il box in locale - if ( ! GetAuxSurf()) - return false ; - return m_pSTM->GetLocalBBox( b3Loc, nFlag) ; + // basta approssimato + if ( ( nFlag & BBF_EXACT) == 0) { + for ( int i = 0 ; i < GetDim() ; ++ i) { + Point3d ptTemp = m_vPtCtrl[i] ; + b3Loc.Add( ptTemp) ; + } + return true ; + } + // deve essere preciso + else { + // verifico esistenza trimesh associata + if ( ! GetAuxSurf()) + return false ; + // calcolo il box della trimesh + return m_pSTM->GetLocalBBox( b3Loc, nFlag) ; + } } //---------------------------------------------------------------------------- bool SurfBezier::GetBBox( const Frame3d& frRef, BBox3d& b3Ref, int nFlag) const { - // assegno il box nel riferimento - if ( ! GetAuxSurf()) - return false ; - return m_pSTM->GetBBox( frRef, b3Ref, nFlag) ; + // basta approssimato + if ( ( nFlag & BBF_EXACT) == 0) { + for ( int i = 0 ; i < GetDim() ; ++ i) { + Point3d ptTemp = m_vPtCtrl[i] ; + ptTemp.ToGlob( frRef) ; + b3Ref.Add( ptTemp) ; + } + return true ; + } + // deve essere preciso + else { + // verifico esistenza trimesh associata + if ( ! GetAuxSurf()) + return false ; + // calcolo il box della trimesh + return m_pSTM->GetBBox( frRef, b3Ref, nFlag) ; + } } //---------------------------------------------------------------------------- @@ -898,6 +938,202 @@ SurfBezier::Invert( void) return true ; } +//---------------------------------------------------------------------------- +int +SurfBezier::GetSteps( int nDeg, double dLen, int nQuality) const +{ + const double dCoeff[] = { 0, 1, 2, 2.4, 2.8, 3, 3, 3, 3, 3, 3, 3} ; + nDeg = Clamp( nDeg, 0, MAXDEG) ; + nQuality = Clamp( nQuality, 1, 3) ; + double dMult = sqrt( max( dLen, 10.)) ; + return int( nQuality * dMult * dCoeff[nDeg]) ; +} + +//---------------------------------------------------------------------------- +CurveBezier* +SurfBezier::GetCurveOnU( double dV) const +{ + // controlli + if ( dV < - EPS_PARAM || dV > 1 + EPS_PARAM) + return false ; + dV = Clamp( dV, 0., 1.) ; + + // se forma polinomiale (o integrale) + if ( ! m_bRat) { + // preparazione della curva di Bezier + PtrOwner pCbz( CreateBasicCurveBezier()) ; + if ( IsNull( pCbz) || ! pCbz->Init( m_nDegU, false)) + return nullptr ; + // calcolo dei polinomi di Bernstein per V di grado opportuno + DBLVECTOR vBernV( m_nDegV + 1) ; + GetAllBernstein( dV, m_nDegV, vBernV) ; + // calcolo dei punti di controllo della curva + for ( int i = 0 ; i <= m_nDegU ; ++ i) { + Point3d ptP = ORIG ; + for ( int j = 0 ; j <= m_nDegV ; ++ j) + ptP += vBernV[j] * m_vPtCtrl[GetInd( i, j)] ; + pCbz->SetControlPoint( i, ptP) ; + } + return Release( pCbz) ; + } + // altrimenti forma razionale + else { + // preparazione della curva di Bezier + PtrOwner pCbz( CreateBasicCurveBezier()) ; + if ( IsNull( pCbz) || ! pCbz->Init( m_nDegU, true)) + return nullptr ; + // calcolo dei polinomi di Bernstein per V di grado opportuno + DBLVECTOR vBernV( m_nDegV + 1) ; + GetAllBernstein( dV, m_nDegV, vBernV) ; + // calcolo dei punti di controllo della curva + PNTVECTOR vPtWCtrl( GetDim()) ; + for ( int i = 0 ; i < GetDim() ; ++ i) + vPtWCtrl[i] = m_vWeCtrl[i] * m_vPtCtrl[i] ; + for ( int i = 0 ; i <= m_nDegU ; ++ i) { + Point3d ptP = ORIG ; + double dW = 0 ; + for ( int j = 0 ; j <= m_nDegV ; ++ j) { + ptP += vBernV[j] * vPtWCtrl[GetInd( i, j)] ; + dW += vBernV[j] * m_vWeCtrl[GetInd( i, j)] ; + } + double dInvW = 1 / ( ( dW > EPS_ZERO) ? dW : EPS_ZERO) ; + pCbz->SetControlPoint( i, ptP * dInvW, dW) ; + } + return Release( pCbz) ; + } +} + +//---------------------------------------------------------------------------- +CurveBezier* +SurfBezier::GetCurveOnV( double dU) const +{ + // controlli + if ( dU < - EPS_PARAM || dU > 1 + EPS_PARAM) + return false ; + dU = Clamp( dU, 0., 1.) ; + + // se forma polinomiale (o integrale) + if ( ! m_bRat) { + // preparazione della curva di Bezier + PtrOwner pCbz( CreateBasicCurveBezier()) ; + if ( IsNull( pCbz) || ! pCbz->Init( m_nDegV, false)) + return nullptr ; + // calcolo dei polinomi di Bernstein per U di grado opportuno + DBLVECTOR vBernU( m_nDegU + 1) ; + GetAllBernstein( dU, m_nDegU, vBernU) ; + // calcolo dei punti di controllo della curva + for ( int j = 0 ; j <= m_nDegV ; ++ j) { + Point3d ptP = ORIG ; + for ( int i = 0 ; i <= m_nDegU ; ++ i) + ptP += vBernU[i] * m_vPtCtrl[GetInd( i, j)] ; + pCbz->SetControlPoint( j, ptP) ; + } + return Release( pCbz) ; + } + // altrimenti forma razionale + else { + // preparazione della curva di Bezier + PtrOwner pCbz( CreateBasicCurveBezier()) ; + if ( IsNull( pCbz) || ! pCbz->Init( m_nDegV, true)) + return nullptr ; + // calcolo dei polinomi di Bernstein per U di grado opportuno + DBLVECTOR vBernU( m_nDegU + 1) ; + GetAllBernstein( dU, m_nDegU, vBernU) ; + // calcolo dei punti di controllo della curva + PNTVECTOR vPtWCtrl( GetDim()) ; + for ( int i = 0 ; i < GetDim() ; ++ i) + vPtWCtrl[i] = m_vWeCtrl[i] * m_vPtCtrl[i] ; + for ( int j = 0 ; j <= m_nDegV ; ++ j) { + Point3d ptP = ORIG ; + double dW = 0 ; + for ( int i = 0 ; i <= m_nDegU ; ++ i) { + ptP += vBernU[i] * vPtWCtrl[GetInd( i, j)] ; + dW += vBernU[i] * m_vWeCtrl[GetInd( i, j)] ; + } + double dInvW = 1 / ( ( dW > EPS_ZERO) ? dW : EPS_ZERO) ; + pCbz->SetControlPoint( j, ptP * dInvW, dW) ; + } + return Release( pCbz) ; + } +} + +//---------------------------------------------------------------------------- +ICurve* +SurfBezier::GetLoop( int nLoop) const +{ + // Se superficie completa, basta concatenare le 4 isoparametriche di bordo + if ( ! m_bTrimmed) { + // Esiste solo il loop esterno + if ( nLoop |= 0) + return nullptr ; + // Loop + PtrOwner pLoop( CreateBasicCurveComposite()) ; + // prima curva U=0 + PtrOwner pCbzU0( GetCurveOnU( 0)) ; + if ( ! IsNull( pCbzU0) && ! pCbzU0->IsAPoint()) + pLoop->AddCurve( Release( pCbzU0)) ; + // seconda curva V=1 + PtrOwner pCbzV1( GetCurveOnV( 1)) ; + if ( ! IsNull( pCbzV1) && ! pCbzV1->IsAPoint()) + pLoop->AddCurve( Release( pCbzV1)) ; + // terza curva U=1 invertita + PtrOwner pCbzU1( GetCurveOnU( 1)) ; + if ( ! IsNull( pCbzU1) && ! pCbzU1->IsAPoint()) { + pCbzU1->Invert() ; + pLoop->AddCurve( Release( pCbzU1)) ; + } + // quarta curva V=0 invertita + PtrOwner pCbzV0( GetCurveOnV( 0)) ; + if ( ! IsNull( pCbzV0) && ! pCbzV0->IsAPoint()) { + pCbzV0->Invert() ; + pLoop->AddCurve( Release( pCbzV0)) ; + } + // se loop chiuso lo restituisco, altrimenti errore + return ( pLoop->IsClosed() ? Release( pLoop) : nullptr) ; + } + // altrimenti trimmata, per ora non gestita + else + return nullptr ; +} + +//---------------------------------------------------------------------------- +bool +SurfBezier::GetCurveOnU( double dV, int nStep, PolyLine& plCrvU) const +{ + plCrvU.Clear() ; + if ( dV < - EPS_PARAM || dV > 1 + EPS_PARAM) + return false ; + dV = Clamp( dV, 0., 1.) ; + PtrOwner pCbz( GetCurveOnU( dV)) ; + if ( IsNull( pCbz)) + return false ; + if ( nStep <= 0) { + double dLenU = 0 ; + pCbz->GetApproxLength( dLenU) ; + nStep = GetSteps( m_nDegU, dLenU, 2) ; + } + return pCbz->ApproxWithLines( nStep, plCrvU) ; +} + +//---------------------------------------------------------------------------- +bool +SurfBezier::GetCurveOnV( double dU, int nStep, PolyLine& plCrvV) const +{ + plCrvV.Clear() ; + if ( dU < - EPS_PARAM || dU > 1 + EPS_PARAM) + return false ; + dU = Clamp( dU, 0., 1.) ; + PtrOwner pCbz( GetCurveOnV( dU)) ; + if ( IsNull( pCbz)) + return false ; + if ( nStep <= 0) { + double dLenV = 0 ; + pCbz->GetApproxLength( dLenV) ; + nStep = GetSteps( m_nDegV, dLenV, 2) ; + } + return pCbz->ApproxWithLines( nStep, plCrvV) ; +} + //---------------------------------------------------------------------------- bool SurfBezier::GetControlCurveOnU( int nIndV, PolyLine& plCtrlU) const @@ -918,54 +1154,32 @@ SurfBezier::GetControlCurveOnV( int nIndU, PolyLine& plCtrlV) const plCtrlV.Clear() ; if ( nIndU < 0 || nIndU > m_nDegU) return false ; - for ( int i = 0 ; i <= m_nDegV ; ++ i) - plCtrlV.AddUPoint( double( i) / m_nDegV, m_vPtCtrl[GetInd( nIndU, i)]) ; + for ( int j = 0 ; j <= m_nDegV ; ++ j) + plCtrlV.AddUPoint( double( j) / m_nDegV, m_vPtCtrl[GetInd( nIndU, j)]) ; return true ; } //---------------------------------------------------------------------------- -bool -SurfBezier::GetCurveOnU( double dV, PolyLine& plCtrlU) const +double +SurfBezier::GetCurveOnUApproxLen( double dV) const { - plCtrlU.Clear() ; - if ( dV < - EPS_PARAM || dV > 1 + EPS_PARAM) - return false ; - dV = Clamp( dV, 0., 1.) ; - int nStepU = 20 * m_nDegU ; - double dStepU = 1.0 / nStepU ; - for ( int i = 0 ; i <= nStepU ; ++ i) { - double dU = i * dStepU ; - Point3d ptPos ; - if ( GetPointD1D2( dU, dV, ptPos)) - plCtrlU.AddUPoint( dU, ptPos) ; - else - return false ; - } - - return true ; + PtrOwner pCbz( GetCurveOnU( dV)) ; + double dLen ; + if ( IsNull( pCbz) || ! pCbz->GetApproxLength( dLen)) + return 0 ; + return dLen ; } //---------------------------------------------------------------------------- -bool -SurfBezier::GetCurveOnV( double dU, PolyLine& plCtrlV) const +double +SurfBezier::GetCurveOnVApproxLen( double dU) const { - plCtrlV.Clear() ; - if ( dU < - EPS_PARAM || dU > 1 + EPS_PARAM) - return false ; - dU = Clamp( dU, 0., 1.) ; - int nStepV = 20 * m_nDegV ; - double dStepV = 1.0 / nStepV ; - for ( int j = 0 ; j <= nStepV ; ++ j) { - double dV = j * dStepV ; - Point3d ptPos ; - if ( GetPointD1D2( dU, dV, ptPos)) - plCtrlV.AddUPoint( dV, ptPos) ; - else - return false ; - } - - return true ; + PtrOwner pCbz( GetCurveOnV( dU)) ; + double dLen ; + if ( IsNull( pCbz) || ! pCbz->GetApproxLength( dLen)) + return 0 ; + return dLen ; } //---------------------------------------------------------------------------- @@ -980,41 +1194,65 @@ SurfBezier::GetAuxSurf( void) const // se già calcolata, la restituisco if ( m_pSTM != nullptr) return m_pSTM ; - // la creo - PtrOwner pSTM( CreateBasicSurfTriMesh()) ; - if ( IsNull( pSTM)) - return nullptr ; - // prima isoparametrica + // costruttore della superficie + StmFromTriangleSoup stmSoup ; + stmSoup.Start() ; + // definisco il numero degli step in U e in V + double dMaxLenU = 0 ; + for ( int j = 0 ; j <= m_nDegV ; ++ j) + dMaxLenU = max( dMaxLenU, GetCurveOnUApproxLen( double( j) / m_nDegV)) ; + int nStepU = GetSteps( m_nDegU, dMaxLenU, 2) ; + double dMaxLenV = 0 ; + for ( int i = 0 ; i <= m_nDegU ; ++ i) + dMaxLenV = max( dMaxLenV, GetCurveOnVApproxLen( double( i) / m_nDegU)) ; + int nStepV = GetSteps( m_nDegV, dMaxLenV, 2) ; + // prima curva isoparametrica (potrebbe essere un solo punto) PolyLine PL1 ; - GetCurveOnU( 0, PL1) ; + GetCurveOnU( 0, nStepU, PL1) ; + bool bSingle1 = ( PL1.GetPointNbr() == 1) ; // ciclo sulle isoparametriche - int nStrip = 20 * m_nDegV ; - for ( int i = 1 ; i <= nStrip ; ++ i) { - // altra isoparametrica + for ( int i = 1 ; i <= nStepV ; ++ i) { + // seconda curva isoparametrica (con tanti punti quanti la prima, oppure uno solo) + double dV = double( i) / nStepV ; PolyLine PL2 ; - GetCurveOnU( double( i) / nStrip, PL2) ; - // creo la trimesh tra le due isoparametriche - PtrOwner pSt12( CreateBasicSurfTriMesh()) ; - if ( IsNull( pSt12)) - return nullptr ; - if ( PL1.GetPointNbr() == 1) { - Point3d ptP ; PL1.GetFirstPoint( ptP) ; - pSt12->CreateByPointCurve( ptP, PL2) ; - pSt12->Invert() ; + GetCurveOnU( dV, nStepU, PL2) ; + bool bSingle2 = ( PL2.GetPointNbr() == 1) ; + // inserisco i triangoli della striscia nel costruttore della TriMesh + Point3d ptP1c, ptP2c ; + Point3d ptP1n, ptP2n ; + bool bNext = PL1.GetFirstPoint( ptP1c) && PL2.GetFirstPoint( ptP2c) ; + if ( bNext) { + if ( bSingle1 && bSingle2) + bNext = false ; + if ( bSingle1) + ptP1n = ptP1c ; + else + bNext = bNext && PL1.GetNextPoint( ptP1n) ; + if ( bSingle2) + ptP2n = ptP2c ; + else + bNext = bNext && PL2.GetNextPoint( ptP2n) ; } - else if ( PL2.GetPointNbr() == 1) { - Point3d ptP ; PL2.GetFirstPoint( ptP) ; - pSt12->CreateByPointCurve( ptP, PL1) ; + while ( bNext) { + // eventuale primo triangolo (con base sui correnti e vertice su P2 successivo) + if ( ! AreSamePointApprox( ptP1c, ptP2c)) + stmSoup.AddTriangle( ptP2c, ptP1c, ptP2n) ; + // eventuale secondo triangolo (con vertice su P1 corrente e base sui successivi) + if ( ! AreSamePointApprox( ptP1n, ptP2n)) + stmSoup.AddTriangle( ptP1c, ptP1n, ptP2n) ; + // passo alla successiva coppia + ptP1c = ptP1n ; + ptP2c = ptP2n ; + bNext = ( bSingle1 || PL1.GetNextPoint( ptP1n)) && ( bSingle2 || PL2.GetNextPoint( ptP2n)) ; } - else - pSt12->CreateByTwoCurves( PL1, PL2, ISurfTriMesh::RLT_ISOPAR) ; - // inserisco questa trimesh in quella complessiva - pSTM->DoSewing( *pSt12) ; // salvo isoparametrica PL2 in PL1 PL1.GetUPointList().swap( PL2.GetUPointList()) ; + bSingle1 = bSingle2 ; } - // la salvo - m_pSTM = Release( pSTM) ; + // la completo + stmSoup.End() ; + // la salvo + m_pSTM = GetBasicSurfTriMesh( stmSoup.GetSurf()) ; return m_pSTM ; } diff --git a/SurfBezier.h b/SurfBezier.h index 5e57f6f..a50bfb8 100644 --- a/SurfBezier.h +++ b/SurfBezier.h @@ -16,6 +16,7 @@ #include "ObjGraphicsMgr.h" #include "DllMain.h" #include "GeoObjRW.h" +#include "CurveBezier.h" #include "SurfTriMesh.h" #include "/EgtDev/Include/EGkSurfBezier.h" #include "/EgtDev/Include/EGkGeoCollection.h" @@ -79,7 +80,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool SetControlPoint( int nIndU, int nIndV, const Point3d& ptCtrl, double dW) override { return SetControlPoint( GetInd( nIndU, nIndV), ptCtrl, dW) ; } bool SetControlPoint( int nInd, const Point3d& ptCtrl, double dW) override ; - bool GetInfo( int& nDegU, int& nDegV, bool& bIsRat) const override ; + bool GetInfo( int& nDegU, int& nDegV, bool& bIsRat, bool& bTrimmed) const override ; const Point3d& GetControlPoint( int nIndU, int nIndV, bool* pbOk) const override { return GetControlPoint( GetInd( nIndU, nIndV), pbOk) ; } const Point3d& GetControlPoint( int nInd, bool* pbOk) const override ; @@ -93,10 +94,11 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW bool GetPointNrmD1D2( double dU, double dV, Point3d& ptPos, Vector3d& vtN, Vector3d* pvtDerU = nullptr, Vector3d* pvtDerV = nullptr, Vector3d* pvtDerUU = nullptr, Vector3d* pvtDerVV = nullptr, Vector3d* pvtDerUV = nullptr) const override ; + CurveBezier* GetCurveOnU( double dV) const override ; + CurveBezier* GetCurveOnV( double dU) const override ; + ICurve* GetLoop( int nLoop) const override ; // nLoop 0-based (1°esterno, successivi interni) bool GetControlCurveOnU( int nIndV, PolyLine& plCtrlU) const override ; bool GetControlCurveOnV( int nIndU, PolyLine& plCtrlV) const override ; - bool GetCurveOnU( double dV, PolyLine& plCtrlU) const override ; - bool GetCurveOnV( double dU, PolyLine& plCtrlV) const override ; const ISurfTriMesh* GetAuxSurf( void) const override ; public : // IGeoObjRW @@ -116,6 +118,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW private : enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ; + enum ParDir { ON_U = 1, ON_V = 2} ; static const int MAXDEG = 11 ; private : @@ -130,6 +133,11 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW int GetDim( void) const { return ( m_nDegU + 1) * ( m_nDegV + 1) ; } void ResetAuxSurf( void) const ; + int GetSteps( int nDeg, double dLen, int nQuality) const ; + bool GetCurveOnU( double dV, int nStep, PolyLine& plCrvU) const ; + bool GetCurveOnV( double dU, int nStep, PolyLine& plCrvV) const ; + double GetCurveOnUApproxLen( double dV) const ; + double GetCurveOnVApproxLen( double dU) const ; private : ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto @@ -138,6 +146,7 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW int m_nDegU ; // grado in U int m_nDegV ; // grado in V bool m_bRat ; // flag di razionale/polinomiale + bool m_bTrimmed ; // flag per presenza regione di trim PNTVECTOR m_vPtCtrl ; // vettore dei punti di controllo DBLVECTOR m_vWeCtrl ; // vettore dei pesi di controllo int m_nTempProp ; // proprietà temporanea diff --git a/deCasteljau.h b/deCasteljau.h new file mode 100644 index 0000000..82d5641 --- /dev/null +++ b/deCasteljau.h @@ -0,0 +1,85 @@ +//---------------------------------------------------------------------------- +// EgalTech 2020-2020 +//---------------------------------------------------------------------------- +// File : deCasteljau.h Data : 29.03.20 Versione : 2.2c3 +// Contenuto : Applicazioni dell'algoritmo di de Casteljau. +// +// +// +// Modifiche : 29.03.20 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +#pragma once + +//--------------------------- Include ---------------------------------------- +#include "/EgtDev/Include/EGkGeoCollection.h" + +//---------------------------------------------------------------------------- +inline bool +deCastTrimStart( double dPar, int nDeg, PNTVECTOR& vPtCtrl) +{ + if ( dPar < EPS_PARAM) + return true ; + if ( dPar > 1 - EPS_PARAM) + return false ; + for ( int k = 1 ; k <= nDeg ; ++ k) { + for ( int i = 0 ; i <= nDeg - k ; ++ i) { + vPtCtrl[i] = ( 1 - dPar) * vPtCtrl[i] + dPar * vPtCtrl[i+1] ; + } + } + return true ; +} + +//---------------------------------------------------------------------------- +inline bool +deCastRatTrimStart( double dPar, int nDeg, PNTVECTOR& vPtCtrl, DBLVECTOR& vWeCtrl) +{ + if ( dPar < EPS_PARAM) + return true ; + if ( dPar > 1 - EPS_PARAM) + return false ; + for ( int k = 1 ; k <= nDeg ; ++ k) { + for ( int i = 0 ; i <= nDeg - k ; ++ i) { + vPtCtrl[i] = ( 1 - dPar) * vWeCtrl[i] * vPtCtrl[i] + dPar * vWeCtrl[i+1] * vPtCtrl[i+1] ; + vWeCtrl[i] = ( 1 - dPar) * vWeCtrl[i] + dPar * vWeCtrl[i+1] ; + vPtCtrl[i] = vPtCtrl[i] * ( 1 / vWeCtrl[i]) ; + } + } + return true ; +} + +//---------------------------------------------------------------------------- +inline bool +deCastTrimEnd( double dPar, int nDeg, PNTVECTOR& vPtCtrl) +{ + if ( dPar < EPS_PARAM) + return false ; + if ( dPar > 1 - EPS_PARAM) + return true ; + for ( int k = 1 ; k <= nDeg ; ++ k) { + for ( int i = nDeg ; i >= k ; -- i) { + vPtCtrl[i] = ( 1 - dPar) * vPtCtrl[i-1] + dPar * vPtCtrl[ i] ; + } + } + return true ; +} + +//---------------------------------------------------------------------------- +inline bool +deCastRatTrimEnd( double dPar, int nDeg, PNTVECTOR& vPtCtrl, DBLVECTOR& vWeCtrl) +{ + if ( dPar < EPS_PARAM) + return false ; + if ( dPar > 1 - EPS_PARAM) + return true ; + for ( int k = 1 ; k <= nDeg ; ++ k) { + for ( int i = nDeg ; i >= k ; -- i) { + vPtCtrl[i] = ( 1 - dPar) * vWeCtrl[i-1] * vPtCtrl[i-1] + dPar * vWeCtrl[ i] * vPtCtrl[ i] ; + vWeCtrl[i] = ( 1 - dPar) * vWeCtrl[i-1] + dPar * vWeCtrl[ i] ; + vPtCtrl[i] = vPtCtrl[i] * ( 1 / vWeCtrl[i]) ; + } + } + return true ; +} diff --git a/stdafx.cpp b/stdafx.cpp index 6826075..31131c2 100644 --- a/stdafx.cpp +++ b/stdafx.cpp @@ -1,6 +1,6 @@ // stdafx.cpp : file di origine che include solo le inclusioni standard -// EgtGeometry.pch sarà l'intestazione precompilata -// stdafx.obj conterrà le informazioni sui tipi precompilati +// EgtGeometry.pch sarà l'intestazione precompilata +// stdafx.obj conterrà le informazioni sui tipi precompilati #include "stdafx.h"