diff --git a/CurveArc.cpp b/CurveArc.cpp index 1d5a55e..8ccca6d 100644 --- a/CurveArc.cpp +++ b/CurveArc.cpp @@ -288,7 +288,7 @@ CurveArc::GetLength( double& dLen) const //---------------------------------------------------------------------------- bool -CurveArc::ApproxWithLines( double dLinTol, double dAngTolDeg, UPNTVECTOR& vUPoints) const +CurveArc::ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) const { int i ; int nStep ; @@ -321,9 +321,6 @@ CurveArc::ApproxWithLines( double dLinTol, double dAngTolDeg, UPNTVECTOR& vUPoin // sistemo lo step (per il numero intero di passi) dAngStepDeg = m_dAngCenDeg / nStep ; - // riservo lo spazio necessario nel vettore di punti - vUPoints.reserve( nStep + 1) ; - // versori di riferimento nel piano dell'arco vtA1 = m_VtS ; vtA2 = m_VtN ^ m_VtS ; @@ -334,7 +331,7 @@ CurveArc::ApproxWithLines( double dLinTol, double dAngTolDeg, UPNTVECTOR& vUPoin // primo punto ptPos = m_PtCen + vtA1 * m_dRad ; - vUPoints.push_back( UPOINT( 0, ptPos)) ; + PL.AddUPoint( 0, ptPos) ; // ciclo per i punti successivi for ( i = 1 ; i <= nStep ; ++ i) { @@ -349,7 +346,7 @@ CurveArc::ApproxWithLines( double dLinTol, double dAngTolDeg, UPNTVECTOR& vUPoin ptPos = m_PtCen + vtA1 * m_dRad ; if ( fabs( m_dDeltaN) > EPS_ZERO) ptPos = ptPos + ( dU * m_dDeltaN) * m_VtN ; - vUPoints.push_back( UPOINT( dU, ptPos)) ; + PL.AddUPoint( dU, ptPos) ; } return true ; diff --git a/CurveArc.h b/CurveArc.h index 8717981..10f7555 100644 --- a/CurveArc.h +++ b/CurveArc.h @@ -52,6 +52,7 @@ class CurveArc : public ICurveArc virtual bool GetPointTangNormCurv( double dU, Point3d& ptPos, Vector3d& vtT, Vector3d& vtN, double& dCurv) const { return ::GetPointTangNormCurv( *this, dU, ptPos, vtT, vtN, dCurv) ; } virtual bool Reverse( void) ; + virtual bool ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) const ; virtual bool TrimStartAtParam( double dUTrim) ; virtual bool TrimEndAtParam( double dUTrim) ; virtual bool TrimStartAtLen( double dLenTrim) ; @@ -76,15 +77,14 @@ class CurveArc : public ICurveArc { return m_dAngCenDeg ; } virtual double GetDeltaN( void) const { return m_dDeltaN ; } - virtual bool ApproxWithLines( double dLinTol, double dAngTolDeg, UPNTVECTOR& vUPoints) const ; public : CurveArc( void) ; - inline const CurveArc& operator =( const CurveArc& caSrc) - { if ( &caSrc != this) - Set( caSrc.m_PtCen, caSrc.m_VtN, caSrc.m_dRad, - caSrc.m_VtS, caSrc.m_dAngCenDeg, caSrc.m_dDeltaN) ; - return *this ; } + const CurveArc& operator =( const CurveArc& caSrc) + { if ( &caSrc != this) + Set( caSrc.m_PtCen, caSrc.m_VtN, caSrc.m_dRad, + caSrc.m_VtS, caSrc.m_dAngCenDeg, caSrc.m_dDeltaN) ; + return *this ; } private : bool Validate( void) ; diff --git a/CurveBezier.cpp b/CurveBezier.cpp index 04b5b02..a43f63c 100644 --- a/CurveBezier.cpp +++ b/CurveBezier.cpp @@ -725,7 +725,7 @@ CurveBezier::GetParamAtLength( double dLen, double& dU) const //---------------------------------------------------------------------------- bool CurveBezier::FlatOrSplit( int nLev, const CurveBezier& crvBez, double dParStart, double dParEnd, - double dLinTol, double dAngTolDeg, UPNTVECTOR& vUPoints) const + double dLinTol, double dAngTolDeg, PolyLine& PL) const { const int MAX_LEV = 10 ; int i ; @@ -733,6 +733,7 @@ CurveBezier::FlatOrSplit( int nLev, const CurveBezier& crvBez, double dParStart, double dSqDist ; double dAngDeg ; double dPolLen ; + Point3d ptLast ; Vector3d vtDirI ; Vector3d vtDirF ; DistPointLine dstPL ; @@ -743,8 +744,9 @@ CurveBezier::FlatOrSplit( int nLev, const CurveBezier& crvBez, double dParStart, // segnalo situazione per debug LOG_DBG_ERR( GetEGkLogger(), "ERROR : Exceeded recursions") // considero la curva piatta (inserisco il punto se abbastanza lontano dal precedente) ed esco - if ( SqDist( vUPoints.back().second, crvBez.m_aPtCtrl[m_nDeg]) > ( dLinTol * dLinTol)) - vUPoints.push_back( UPOINT( dParEnd, crvBez.m_aPtCtrl[m_nDeg])) ; + PL.GetLastPoint( ptLast) ; + if ( SqDist( ptLast, crvBez.m_aPtCtrl[m_nDeg]) > ( dLinTol * dLinTol)) + PL.AddUPoint( dParEnd, crvBez.m_aPtCtrl[m_nDeg]) ; return true ; } @@ -768,8 +770,9 @@ CurveBezier::FlatOrSplit( int nLev, const CurveBezier& crvBez, double dParStart, if ( fabs( dAngDeg) <= dAngTolDeg || ( crvBez.GetControlPolygonLength( dPolLen) && dPolLen <= dLinTol)) { // considero la curva piatta (inserisco il punto se abbastanza lontano dal precedente) ed esco - if ( SqDist( vUPoints.back().second, crvBez.m_aPtCtrl[m_nDeg]) > ( dLinTol * dLinTol)) - vUPoints.push_back( UPOINT( dParEnd, crvBez.m_aPtCtrl[m_nDeg])) ; + PL.GetLastPoint( ptLast) ; + if ( SqDist( ptLast, crvBez.m_aPtCtrl[m_nDeg]) > ( dLinTol * dLinTol)) + PL.AddUPoint( dParEnd, crvBez.m_aPtCtrl[m_nDeg]) ; return true ; } } @@ -783,12 +786,12 @@ CurveBezier::FlatOrSplit( int nLev, const CurveBezier& crvBez, double dParStart, // prima metà crvBez1 = crvBez ; crvBez1.TrimEndAtParam( 0.5) ; - if ( ! FlatOrSplit( nLev + 1, crvBez1, dParStart, dParMid, dLinTol, dAngTolDeg, vUPoints)) + if ( ! FlatOrSplit( nLev + 1, crvBez1, dParStart, dParMid, dLinTol, dAngTolDeg, PL)) return false ; // seconda metà crvBez1 = crvBez ; crvBez1.TrimStartAtParam( 0.5) ; - if ( ! FlatOrSplit( nLev + 1, crvBez1, dParMid, dParEnd, dLinTol, dAngTolDeg, vUPoints)) + if ( ! FlatOrSplit( nLev + 1, crvBez1, dParMid, dParEnd, dLinTol, dAngTolDeg, PL)) return false ; } @@ -797,20 +800,16 @@ CurveBezier::FlatOrSplit( int nLev, const CurveBezier& crvBez, double dParStart, //---------------------------------------------------------------------------- bool -CurveBezier::ApproxWithLines( double dLinTol, double dAngTolDeg, UPNTVECTOR& vUPoints) const +CurveBezier::ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) const { - const int VP_DIM = 64 ; - - // la curva deve essere validata if ( m_nStatus != OK) return false ; // se di primo grado, basta inserire gli estremi if ( m_nDeg == 1) { - vUPoints.reserve( 2) ; - vUPoints.push_back( UPOINT( 0, m_aPtCtrl[0])) ; - vUPoints.push_back( UPOINT( 1, m_aPtCtrl[m_nDeg])) ; + PL.AddUPoint( 0, m_aPtCtrl[0]) ; + PL.AddUPoint( 1, m_aPtCtrl[m_nDeg]) ; return true ; } @@ -818,18 +817,15 @@ CurveBezier::ApproxWithLines( double dLinTol, double dAngTolDeg, UPNTVECTOR& vUP dLinTol = max( dLinTol, LIN_TOL_MIN) ; dAngTolDeg = max( dAngTolDeg, ANG_TOL_MIN_DEG) ; - // riservo uno spazio standard nel vettore di punti - vUPoints.reserve( VP_DIM) ; - // inserisco il punto iniziale - vUPoints.push_back( UPOINT( 0, m_aPtCtrl[0])) ; + PL.AddUPoint( 0, m_aPtCtrl[0]) ; // verifico se va divisa - FlatOrSplit( 0, *this, PAR_START, PAR_END, dLinTol, dAngTolDeg, vUPoints) ; + FlatOrSplit( 0, *this, PAR_START, PAR_END, dLinTol, dAngTolDeg, PL) ; // se è stato inserito un solo punto, aggiungo il finale - if ( vUPoints.size() == 1) - vUPoints.push_back( UPOINT( 1, m_aPtCtrl[m_nDeg])) ; + if ( PL.GetPointNbr() == 1) + PL.AddUPoint( 1, m_aPtCtrl[m_nDeg]) ; return true ; } diff --git a/CurveBezier.h b/CurveBezier.h index bf2e5b3..fe9ee30 100644 --- a/CurveBezier.h +++ b/CurveBezier.h @@ -54,6 +54,7 @@ class CurveBezier : public ICurveBezier virtual bool GetPointTangNormCurv( double dU, Point3d& ptPos, Vector3d& vtT, Vector3d& vtN, double& dCurv) const { return ::GetPointTangNormCurv( *this, dU, ptPos, vtT, vtN, dCurv) ; } virtual bool Reverse( void) ; + virtual bool ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) const ; virtual bool TrimStartAtParam( double dUTrim) ; virtual bool TrimEndAtParam( double dUTrim) ; virtual bool TrimStartAtLen( double dLenTrim) ; @@ -71,19 +72,18 @@ class CurveBezier : public ICurveBezier virtual const Point3d& GetControlPoint( int nInd, bool* pbOk = NULL) const ; virtual double GetControlWeight( int nInd, bool* pbOk = NULL) const ; virtual bool GetControlPolygonLength( double& dLen) const ; - virtual bool ApproxWithLines( double dLinTol, double dAngTolDeg, UPNTVECTOR& vUPoints) const ; public : CurveBezier( void) ; - inline const CurveBezier& operator =( const CurveBezier& cbSrc) - { if ( &cbSrc != this && Init( cbSrc.m_nDeg, cbSrc.m_bRat)) { - for ( int i = 0 ; i <= m_nDeg ; ++ i) { - m_aPtCtrl[i] = cbSrc.m_aPtCtrl[i] ; - if ( cbSrc.m_bRat) - m_aWeCtrl[i] = cbSrc.m_aWeCtrl[i] ; - } - } - return *this ; } + const CurveBezier& operator =( const CurveBezier& cbSrc) + { if ( &cbSrc != this && Init( cbSrc.m_nDeg, cbSrc.m_bRat)) { + for ( int i = 0 ; i <= m_nDeg ; ++ i) { + m_aPtCtrl[i] = cbSrc.m_aPtCtrl[i] ; + if ( cbSrc.m_bRat) + m_aWeCtrl[i] = cbSrc.m_aWeCtrl[i] ; + } + } + return *this ; } private : bool Validate( void) ; @@ -93,7 +93,7 @@ class CurveBezier : public ICurveBezier bool GetSegmentParam( double dLen, double& dCurrLen, double& dSegLen, double& dUIni, double& dUFin) const ; bool FlatOrSplit( int nLev, const CurveBezier& crvBez, double dParStart, double dParEnd, - double dLinTol, double dAngTolDeg, UPNTVECTOR& vUPoints) const ; + double dLinTol, double dAngTolDeg, PolyLine& PL) const ; private : enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ; diff --git a/CurveComposite.cpp b/CurveComposite.cpp index d8f4f40..00760a7 100644 --- a/CurveComposite.cpp +++ b/CurveComposite.cpp @@ -383,6 +383,40 @@ CurveComposite::GetLength( double& dLen) const return true ; } +//---------------------------------------------------------------------------- +bool +CurveComposite::ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) const +{ + bool bFirst ; + double dStartPar ; + Point3d ptP ; + PolyLine PLSmpl ; + PCRVSMPL_LIST::const_iterator Iter ; + + + bFirst = true ; + dStartPar = 0 ; + for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) { + // recupero approssimazione per curva semplice + if ( ! (*Iter)->ApproxWithLines( dLinTol, dAngTolDeg, PLSmpl)) + return false ; + // la accodo opportunamente a quella della curva composita + if ( bFirst) { + PL.Splice( PLSmpl) ; + bFirst = false ; + } + else { + PLSmpl.EraseFirstUPoint() ; + PLSmpl.AddOffsetToU( dStartPar) ; + PL.Splice( PLSmpl) ; + } + // incremento inizio parametro per prossima curva semplice + dStartPar += 1 ; + } + + return true ; +} + //---------------------------------------------------------------------------- bool CurveComposite::Reverse( void) @@ -798,3 +832,16 @@ CurveComposite::GetNextCurve( void) const else return nullptr ; } + +//---------------------------------------------------------------------------- +bool +CurveComposite::IsParamAtJoint( double dU) const +{ + // se all'inizio, alla fine o lontano dagli interi + if ( fabs( dU) < EPS_ZERO || + fabs( dU - m_nCounter) < EPS_ZERO || + fabs( dU - (int) ( dU + EPS_ZERO)) > EPS_ZERO) + return false ; + else + return true ; +} diff --git a/CurveComposite.h b/CurveComposite.h index 4183b91..0a8a67a 100644 --- a/CurveComposite.h +++ b/CurveComposite.h @@ -56,6 +56,7 @@ class CurveComposite : public ICurveComposite virtual bool GetPointTangNormCurv( double dU, Point3d& ptPos, Vector3d& vtT, Vector3d& vtN, double& dCurv) const { return ::GetPointTangNormCurv( *this, dU, ptPos, vtT, vtN, dCurv) ; } virtual bool Reverse( void) ; + virtual bool ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) const ; virtual bool TrimStartAtParam( double dUTrim) ; virtual bool TrimEndAtParam( double dUTrim) ; virtual bool TrimStartAtLen( double dLenTrim) ; @@ -67,17 +68,18 @@ class CurveComposite : public ICurveComposite virtual int GetCurveNumber( void) const { return m_nCounter ; } virtual const ICurve* GetFirstCurve( void) const ; virtual const ICurve* GetNextCurve( void) const ; + virtual bool IsParamAtJoint( double dU) const ; public : CurveComposite( void) ; - inline const CurveComposite& operator =( const CurveComposite& ccSrc) - { if ( &ccSrc != this) { - Clear() ; - PCRVSMPL_LIST::const_iterator Iter ; - for ( Iter = ccSrc.m_CrvSmplS.begin() ; Iter != ccSrc.m_CrvSmplS.end() ; ++Iter) - AddCurve( **Iter) ; - } - return *this ; } + const CurveComposite& operator =( const CurveComposite& ccSrc) + { if ( &ccSrc != this) { + Clear() ; + PCRVSMPL_LIST::const_iterator Iter ; + for ( Iter = ccSrc.m_CrvSmplS.begin() ; Iter != ccSrc.m_CrvSmplS.end() ; ++Iter) + AddCurve( **Iter) ; + } + return *this ; } private : bool Validate( void) ; diff --git a/CurveLine.cpp b/CurveLine.cpp index e71010a..1a456d1 100644 --- a/CurveLine.cpp +++ b/CurveLine.cpp @@ -204,16 +204,15 @@ CurveLine::GetLength( double& dLen) const //---------------------------------------------------------------------------- bool -CurveLine::ApproxWithLines( double dLinTol, double dAngTolDeg, UPNTVECTOR& vUPoints) const +CurveLine::ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) const { // la curva deve essere validata if ( m_nStatus != OK) return false ; // inserisco gli estremi - vUPoints.reserve( 2) ; - vUPoints.push_back( UPOINT( 0, m_PtStart)) ; - vUPoints.push_back( UPOINT( 1, m_PtEnd)) ; + PL.AddUPoint( 0, m_PtStart) ; + PL.AddUPoint( 1, m_PtEnd) ; return true ; } diff --git a/CurveLine.h b/CurveLine.h index 298ae74..ddb347c 100644 --- a/CurveLine.h +++ b/CurveLine.h @@ -52,6 +52,7 @@ class CurveLine : public ICurveLine virtual bool GetPointTangNormCurv( double dU, Point3d& ptPos, Vector3d& vtT, Vector3d& vtN, double& dCurv) const { return ::GetPointTangNormCurv( *this, dU, ptPos, vtT, vtN, dCurv) ; } virtual bool Reverse( void) ; + virtual bool ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) const ; virtual bool TrimStartAtParam( double dUTrim) ; virtual bool TrimEndAtParam( double dUTrim) ; virtual bool TrimStartAtLen( double dLenTrim) ; @@ -63,14 +64,13 @@ class CurveLine : public ICurveLine { return m_PtStart ; } virtual const Point3d& GetEnd( void) const { return m_PtEnd ; } - virtual bool ApproxWithLines( double dLinTol, double dAngTolDeg, UPNTVECTOR& vUPoints) const ; public : CurveLine( void) ; - inline const CurveLine& operator =( const CurveLine& clSrc) - { if ( &clSrc != this) - Set( clSrc.m_PtStart, clSrc.m_PtEnd) ; - return *this ; } + const CurveLine& operator =( const CurveLine& clSrc) + { if ( &clSrc != this) + Set( clSrc.m_PtStart, clSrc.m_PtEnd) ; + return *this ; } private : bool Validate( void) ; diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index a4aaac6..6ffa6a2 100644 Binary files a/EgtGeomKernel.rc and b/EgtGeomKernel.rc differ diff --git a/EgtGeomKernel.vcxproj b/EgtGeomKernel.vcxproj index 26d11b6..80726d7 100644 --- a/EgtGeomKernel.vcxproj +++ b/EgtGeomKernel.vcxproj @@ -138,6 +138,7 @@ copy $(TargetPath) \EgtProg\Dll + Create Create @@ -164,6 +165,7 @@ copy $(TargetPath) \EgtProg\Dll + diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters index c0d1ade..85827a5 100644 --- a/EgtGeomKernel.vcxproj.filters +++ b/EgtGeomKernel.vcxproj.filters @@ -96,6 +96,9 @@ File di origine\Base + + File di origine\Base + @@ -230,6 +233,9 @@ File di intestazione + + File di intestazione + diff --git a/OutScl.cpp b/OutScl.cpp index 4ec4f7b..146dd41 100644 --- a/OutScl.cpp +++ b/OutScl.cpp @@ -276,6 +276,35 @@ OutScl::CircleCR( const Point3d& ptCen, double dRad) return true ; } +//---------------------------------------------------------------------------- +bool +OutScl::ArcCurvOrTgOrNone( const Point3d& ptFin, const Vector3d& vtT, const Vector3d& vtN, double dCurv) +{ + bool bCCW ; + double dAngCenDeg ; + Point3d ptCen ; + + + // curvatura + if ( fabs( dCurv) > EPS_ZERO) { + // tratto di arco + ptCen = ptFin + vtN / dCurv ; + bCCW = ( vtT ^ vtN).z > 0 ; + dAngCenDeg = ( bCCW ? 1 : -1) * 4 * dCurv * RADTODEG ; + ArcCPA( ptCen, ptFin, dAngCenDeg) ; + // raggio + Line2P( ptFin, ptCen) ; + } + // altrimenti, tangente + else if ( ! vtT.IsSmall()) + Line2P( ptFin - vtT, ptFin + vtT) ; + // altrimenti cerchietto + else + CircleCR( ptFin, 1) ; + + return true ; +} + //---------------------------------------------------------------------------- bool OutScl::PutCurve( const IGeoObj* pCurve, int nFlag) @@ -312,34 +341,31 @@ OutScl::PutCurveLine( const ICurveLine& CrvLine) bool OutScl::PutCurveArc( const ICurveArc& CrvArc, int nFlag) { - int i ; - double dU ; - double dCurv ; - Point3d ptFin ; - Vector3d vtT ; - Vector3d vtN ; - UPNTVECTOR vUPoints ; + bool bFound ; + double dU ; + double dCurv ; + Point3d ptIni ; + Point3d ptFin ; + Vector3d vtT ; + Vector3d vtN ; + PolyLine PL ; // ciclo sui segmenti Remark( "CurveArc") ; - CrvArc.ApproxWithLines( 0.1, 5, vUPoints) ; - for ( i = 1 ; i < (int) vUPoints.size() ; ++ i) { - Line2P( vUPoints[i-1].second, vUPoints[i].second) ; + CrvArc.ApproxWithLines( 0.1, 5, PL) ; + for ( bFound = PL.GetFirstLine( ptIni, ptFin) ; bFound ; bFound = PL.GetNextLine( ptIni, ptFin)) { + Line2P( ptIni, ptFin) ; } // se richieste derivate e curvature if ( ( nFlag & 1) != 0) { // ciclo per disegnare le derivate Remark( "ArcTangents+Der2") ; - for ( i = 0 ; i < (int) vUPoints.size() ; ++ i) { - // ricavo il punto - dU = vUPoints[i].first ; + for ( bFound = PL.GetFirstU( dU) ; bFound ; bFound = PL.GetNextU( dU)) { + // ricavo il punto, la tangente, la normale e la curvatura CrvArc.GetPointTangNormCurv( dU, ptFin, vtT, vtN, dCurv) ; - // tangente - Line2P( ptFin - vtT, ptFin + vtT) ; - // curvatura - if ( fabs( dCurv) > EPS_ZERO) - Line2P( ptFin, ptFin + vtN / dCurv) ; + // curvatura o tangente o niente + ArcCurvOrTgOrNone( ptFin, vtT, vtN, dCurv) ; } } @@ -350,16 +376,14 @@ OutScl::PutCurveArc( const ICurveArc& CrvArc, int nFlag) bool OutScl::PutCurveBez( const ICurveBezier& CrvBez, int nFlag) { - bool bCCW ; - int i ; - double dU ; - double dCurv ; - double dAngCenDeg ; - Point3d ptFin ; - Point3d ptCen ; - Vector3d vtT ; - Vector3d vtN ; - UPNTVECTOR vUPoints ; + bool bFound ; + double dU ; + double dCurv ; + Point3d ptIni ; + Point3d ptFin ; + Vector3d vtT ; + Vector3d vtN ; + PolyLine PL ; // se richiesto anche il poligono di controllo @@ -368,34 +392,19 @@ OutScl::PutCurveBez( const ICurveBezier& CrvBez, int nFlag) // ciclo per disegnare i segmenti Remark( "BezierCurve") ; - CrvBez.ApproxWithLines( 0.1, 5, vUPoints) ; - for ( i = 1 ; i < (int) vUPoints.size() ; ++ i) { - Line2P( vUPoints[i-1].second, vUPoints[i].second) ; + CrvBez.ApproxWithLines( 0.1, 5, PL) ; + for ( bFound = PL.GetFirstLine( ptIni, ptFin) ; bFound ; bFound = PL.GetNextLine( ptIni, ptFin)) { + Line2P( ptIni, ptFin) ; } // se richieste derivate e curvature if ( ( nFlag & 1) != 0) { // ciclo per disegnare le derivate e le curvature Remark( "BezierTangents+Der2") ; - for ( i = 0 ; i < (int) vUPoints.size() ; ++ i) { - // ricavo il punto - dU = vUPoints[i].first ; + for ( bFound = PL.GetFirstU( dU) ; bFound ; bFound = PL.GetNextU( dU)) { + // ricavo il punto, la tangente, la normale e la curvatura CrvBez.GetPointTangNormCurv( dU, ptFin, vtT, vtN, dCurv) ; - // curvatura - if ( fabs( dCurv) > EPS_ZERO) { - // tratto di arco - ptCen = ptFin + vtN / dCurv ; - bCCW = ( vtT ^ vtN).z > 0 ; - dAngCenDeg = ( bCCW ? 1 : -1) * 4 * dCurv * RADTODEG ; - ArcCPA( ptCen, ptFin, dAngCenDeg) ; - // raggio - Line2P( ptFin, ptCen) ; - } - // altrimenti, tangente - else if ( ! vtT.IsSmall()) - Line2P( ptFin - vtT, ptFin + vtT) ; - // altrimenti cerchietto - else - CircleCR( ptFin, 1) ; + // curvatura o tangente o niente + ArcCurvOrTgOrNone( ptFin, vtT, vtN, dCurv) ; } } @@ -413,11 +422,11 @@ OutScl::PutPolygBez( const ICurveBezier& CrvBez) // ciclo per disegnare il poligono di controllo Remark( "BezierPolygon") ; - for ( i = 0 ; i <= CrvBez.GetDegree() ; ++ i) { + ptIni = CrvBez.GetControlPoint( 0) ; + for ( i = 1 ; i <= CrvBez.GetDegree() ; ++ i) { ptFin = CrvBez.GetControlPoint( i) ; - // dopo il primo, disegno - if ( i > 0) - Line2P( ptIni, ptFin) ; + // disegno + Line2P( ptIni, ptFin) ; // nuovo iniziale prende i valori del finale ptIni = ptFin ; } @@ -429,27 +438,39 @@ OutScl::PutPolygBez( const ICurveBezier& CrvBez) bool OutScl::PutCurveCompo( const ICurveComposite& CrvCompo, int nFlag) { - const ICurve* pCrvSmpl ; + bool bFound ; + double dU ; + double dCurv ; + Point3d ptIni ; + Point3d ptFin ; + Vector3d vtT ; + Vector3d vtN ; + PolyLine PL ; - pCrvSmpl = CrvCompo.GetFirstCurve() ; - while ( pCrvSmpl != nullptr) { - // scrittura comandi SCL - Remark( "CurveComposite") ; - // secondo il tipo - switch ( pCrvSmpl->GetType()) { - case CRV_LINE : - PutCurveLine( *::GetCurveLine( pCrvSmpl)) ; - break ; - case CRV_ARC : - PutCurveArc( *::GetCurveArc( pCrvSmpl), nFlag) ; - break ; - case CRV_BEZ : - PutCurveBez( *::GetCurveBezier( pCrvSmpl), nFlag) ; - break ; + // ciclo per disegnare i segmenti + Remark( "CurveComposite") ; + CrvCompo.ApproxWithLines( 0.1, 5, PL) ; + for ( bFound = PL.GetFirstLine( ptIni, ptFin) ; bFound ; bFound = PL.GetNextLine( ptIni, ptFin)) { + Line2P( ptIni, ptFin) ; + } + // se richieste derivate e curvature + if ( ( nFlag & 1) != 0) { + // ciclo per disegnare le derivate e le curvature + Remark( "CompositeTangents+Der2") ; + for ( bFound = PL.GetFirstU( dU) ; bFound ; bFound = PL.GetNextU( dU)) { + // ricavo il punto, la tangente, la normale e la curvatura + CrvCompo.GetPointTangNormCurv( dU, ptFin, vtT, vtN, dCurv) ; + // curvatura o tangente o niente + ArcCurvOrTgOrNone( ptFin, vtT, vtN, dCurv) ; + // se alla giunzione tra due curve semplici, calcolo anche appena dopo + if ( CrvCompo.IsParamAtJoint( dU)) { + // ricavo il punto, la tangente, la normale e la curvatura + CrvCompo.GetPointTangNormCurv( dU + EPS_ZERO, ptFin, vtT, vtN, dCurv) ; + // curvatura o tangente o niente + ArcCurvOrTgOrNone( ptFin, vtT, vtN, dCurv) ; + } } - // passo alla successiva - pCrvSmpl = CrvCompo.GetNextCurve() ; } return true ; diff --git a/OutScl.h b/OutScl.h index b218bbb..f3c82de 100644 --- a/OutScl.h +++ b/OutScl.h @@ -50,6 +50,7 @@ class OutScl bool Arc3P( const Point3d& ptP1, const Point3d& ptP2, const Point3d& ptP3) ; bool ArcCPA( const Point3d& ptCen, const Point3d& ptMed, double dAngCenDeg) ; bool CircleCR( const Point3d& ptCen, double dRad) ; + bool ArcCurvOrTgOrNone( const Point3d& ptFin, const Vector3d& vtT, const Vector3d& vtN, double dCurv) ; private : std::ofstream m_ofFile ; diff --git a/PolyLine.cpp b/PolyLine.cpp new file mode 100644 index 0000000..0669d2b --- /dev/null +++ b/PolyLine.cpp @@ -0,0 +1,177 @@ +//---------------------------------------------------------------------------- +// EgalTech 2013-2013 +//---------------------------------------------------------------------------- +// File : DistPointLine.cpp Data : 22.12.13 Versione : 1.4l3 +// Contenuto : Implementazione dell'oggetto PolyLine. +// +// +// +// Modifiche : 22.12.13 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "\EgtDev\Include\EGkPolyLine.h" + + +//---------------------------------------------------------------------------- +PolyLine::PolyLine( void) +{ + m_nCount = 0 ; + m_iter = m_lUPoints.end() ; +} + +//---------------------------------------------------------------------------- +PolyLine::~PolyLine( void) +{ +} + +//---------------------------------------------------------------------------- +bool +PolyLine::AddUPoint( double dPar, const Point3d& ptP) +{ + try { + m_lUPoints.push_back( UPOINT( dPar, ptP)) ; + } + catch (...) { + return false ; + } + + m_nCount ++ ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +PolyLine::EraseFirstUPoint( void) +{ + if ( m_lUPoints.begin() == m_lUPoints.end()) + return false ; + + m_lUPoints.pop_front() ; + m_nCount -- ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +PolyLine::AddOffsetToU( double dOffset) +{ + UPNTLIST::iterator iter ; + + + for ( iter = m_lUPoints.begin() ; iter != m_lUPoints.end() ; ++ iter) + iter->first += dOffset ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +PolyLine::Splice( PolyLine& PL) +{ + m_lUPoints.splice( m_lUPoints.end(), PL.m_lUPoints) ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +PolyLine::GetFirstUPoint( double* pdPar, Point3d* pptP) +{ + m_iter = m_lUPoints.begin() ; + if ( m_iter == m_lUPoints.end()) + return false ; + + if ( pdPar != nullptr) + *pdPar = m_iter->first ; + if ( pptP != nullptr) + *pptP = m_iter->second ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +PolyLine::GetNextUPoint( double* pdPar, Point3d* pptP) +{ + ++ m_iter ; + if ( m_iter == m_lUPoints.end()) + return false ; + + if ( pdPar != nullptr) + *pdPar = m_iter->first ; + if ( pptP != nullptr) + *pptP = m_iter->second ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +PolyLine::GetLastUPoint( double* pdPar, Point3d* pptP) +{ + if ( m_lUPoints.begin() == m_lUPoints.end()) + return false ; + + if ( pdPar != nullptr) + *pdPar = m_lUPoints.back().first ; + if ( pptP != nullptr) + *pptP = m_lUPoints.back().second ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +PolyLine::GetFirstULine( double* pdIni, Point3d* pptIni, double* pdFin, Point3d* pptFin) +{ + // parametro e punto iniziali + m_iter = m_lUPoints.begin() ; + if ( m_iter == m_lUPoints.end()) + return false ; + if ( pdIni != nullptr) + *pdIni = m_iter->first ; + if ( pptIni != nullptr) + *pptIni = m_iter->second ; + + // parametro e punto finali + ++ m_iter ; + if ( m_iter == m_lUPoints.end()) + return false ; + if ( pdFin != nullptr) + *pdFin = m_iter->first ; + if ( pptFin != nullptr) + *pptFin = m_iter->second ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +PolyLine::GetNextULine( double* pdIni, Point3d* pptIni, double* pdFin, Point3d* pptFin) +{ + // parametro e punto iniziali (è il precedente finale) + if ( m_iter == m_lUPoints.end()) + return false ; + if ( pdIni != nullptr) + *pdIni = m_iter->first ; + if ( pptIni != nullptr) + *pptIni = m_iter->second ; + + // parametro e punto finali + ++ m_iter ; + if ( m_iter == m_lUPoints.end()) + return false ; + if ( pdFin != nullptr) + *pdFin = m_iter->first ; + if ( pptFin != nullptr) + *pptFin = m_iter->second ; + + return true ; +} +