diff --git a/ArcXxTgArc.cpp b/ArcXxTgArc.cpp index 64e7c12..22510c1 100644 --- a/ArcXxTgArc.cpp +++ b/ArcXxTgArc.cpp @@ -76,7 +76,7 @@ GetCircleCenTgArc( const Point3d& ptCen, const ICurveArc& crvArc, const Point3d& // creo l'arco PtrOwner pCrvArc( CreateCurveArc()) ; - if ( ! IsValid( pCrvArc)) + if ( IsNull( pCrvArc)) return nullptr ; // costruisco la circonferenza corrispondente alla soluzione scelta @@ -141,7 +141,7 @@ GetArcCenTgArcPnt( const Point3d& ptCen, const ICurveArc& crvArc, // creo l'arco PtrOwner pCrvArc( CreateCurveArc()) ; - if ( ! IsValid( pCrvArc)) + if ( IsNull( pCrvArc)) return nullptr ; // posso costruire l'arco solo nel riferimento intrinseco e poi portarlo in quello standard @@ -209,7 +209,7 @@ GetArcPntDirTgArc( const Point3d& ptP, double dDirStartDeg, const ICurveArc& crv // calcolo arco spostando il punto iniziale di + raggio in direzione ortogonale Point3d ptP1 = ptP + vtOrtho * crvArc.GetRadius() ; PtrOwner pCrv1( GetArc2PD( ptP1, crvArc.GetCenter(), dDirStartDeg)) ; - bool bOk1 = IsValid( pCrv1) ; + bool bOk1 = ( ! IsNull( pCrv1)) ; // compenso lo spostamento bOk1 = bOk1 && pCrv1->Offset( crvArc.GetRadius(), ICurve::OFF_RIGHT) ; // verifico se il punto di tangenza sta sull'arco @@ -220,7 +220,7 @@ GetArcPntDirTgArc( const Point3d& ptP, double dDirStartDeg, const ICurveArc& crv // calcolo arco spostando il punto iniziale di - raggio in direzione ortogonale Point3d ptP2 = ptP - vtOrtho * crvArc.GetRadius() ; PtrOwner pCrv2( GetArc2PD( ptP2, crvArc.GetCenter(), dDirStartDeg)) ; - bool bOk2 = IsValid( pCrv2) ; + bool bOk2 = ( ! IsNull( pCrv2)) ; // compenso lo spostamento bOk2 = bOk2 && pCrv2->Offset( crvArc.GetRadius(), ICurve::OFF_LEFT) ; // verifico se il punto di tangenza sta sull'arco diff --git a/BiArcs.cpp b/BiArcs.cpp index 790063f..ece737b 100644 --- a/BiArcs.cpp +++ b/BiArcs.cpp @@ -13,11 +13,13 @@ //--------------------------- Include ---------------------------------------- #include "stdafx.h" +#include "BiArcs.h" +#include "CurveArc.h" #include "/EgtDev/Include/EGkAngle.h" -#include "/EgtDev/Include/EgkBiArcs.h" #include "/EgtDev/Include/EgkCurveLine.h" #include "/EgtDev/Include/EgkCurveComposite.h" #include "/EgtDev/Include/EgkArcXxTgArc.h" +#include "/EgtDev/Include/EGkDistPointCurve.h" #include "/EgtDev/Include/EgtPointerOwner.h" using namespace std ; @@ -32,7 +34,7 @@ GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir { // calcolo la curva dove giacciono i punti di giunzione tra i due archi del biarco PtrOwner pJCrv( CalcJCurve( ptP0, dDir0Deg, ptP1, dDir1Deg)) ; - if ( ! ::IsValid( pJCrv)) + if ( IsNull( pJCrv)) return nullptr ; // limito il parametro nell'intervallo 0 - 1 @@ -48,7 +50,7 @@ GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir // preparo la curva composita per i biarchi PtrOwner pBiArc( CreateCurveComposite()) ; - if ( ! IsValid( pBiArc)) + if ( IsNull( pBiArc)) return nullptr ; // calcolo la curva dal punto iniziale alla giunzione @@ -79,22 +81,79 @@ GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir //---------------------------------------------------------------------------- ICurve* -GetBiArc( const PolyLine& PL, double dU0, double dDir0Deg, double dU1, double dDir1Deg) +GetBiArc( const ICurve& Crv, const PolyLine& PL, double& dDist) { - // recupero i punti estremi della parte di interesse della polilinea - //double dU ; - //Point3d ptP, ptP0, ptP1 ; - //for ( bool bFound = PL.GetFirstUPoint( dU, &ptP) ; - // bFound ; - // bFound = PL.GetNextUPoint( dU, &ptP)) { - - //} + // calcolo punti e direzioni estremi + double dU ; + Point3d ptP0, ptP1 ; + Vector3d vtDir ; + double dDir0Deg, dDir1Deg ; + if ( ! PL.GetFirstU( dU) || ! Crv.GetPointTang( dU, ICurve::FROM_PLUS, ptP0, vtDir)) + return false ; + vtDir.ToSpherical( nullptr, nullptr, &dDir0Deg) ; + if ( ! PL.GetLastU( dU) || ! Crv.GetPointTang( dU, ICurve::FROM_MINUS, ptP1, vtDir)) + return false ; + vtDir.ToSpherical( nullptr, nullptr, &dDir1Deg) ; // calcolo la curva dove giacciono i punti di giunzione tra i due archi del biarco - //PtrOwner pJCrv( CalcJCurve( ptP0, dDir0Deg, ptP1, dDir1Deg)) ; - //if ( ! ::IsValid( pJCrv)) - // return nullptr ; + PtrOwner pJCrv( CalcJCurve( ptP0, dDir0Deg, ptP1, dDir1Deg)) ; + if ( IsNull( pJCrv)) + return nullptr ; + // calcolo le intersezioni tra la curva delle giunzioni (segmento o arco) e la polilinea + PtrOwner pBiArc ; + if ( pJCrv->GetType() == CRV_LINE) { + pBiArc.Set( GetBiArc( ptP0, dDir0Deg, ptP1, dDir1Deg, 0.5)) ; + } + else { + CurveArc* pArc = GetBasicCurveArc( Get( pJCrv)) ; + if ( pArc == nullptr) + return nullptr ; + double dU = - 1 ; + double dRad = pArc->GetRadius() ; + double dSqRad = dRad * dRad ; + Point3d ptCen = pArc->GetCenter() ; + Point3d ptIni, ptFin ; + for ( bool bLine = PL.GetFirstLine( ptIni, ptFin) ; + bLine ; + bLine = PL.GetNextLine( ptIni, ptFin)) { + double dSqDistIni = SqDistXY( ptIni, ptCen) ; + double dSqDistFin = SqDistXY( ptFin, ptCen) ; + if ( ( dSqDistIni > dSqRad && dSqDistFin < dSqRad) || + ( dSqDistIni < dSqRad && dSqDistFin > dSqRad)) { + double dDiffIni = DistXY( ptIni, ptCen) - dRad ; + double dDiffFin = DistXY( ptFin, ptCen) - dRad ; + Point3d ptMid = Media( ptIni, ptFin, fabs( dDiffIni) / ( fabs( dDiffIni) + fabs( dDiffFin))) ; + int nPos ; + double dTmp ; + if ( pArc->CalcPointParamPosiz( ptMid, dTmp, nPos)) { + if ( nPos != ICurve::PP_START && nPos != ICurve::PP_END && + fabs( dTmp - 0.5) < fabs( dU - 0.5)) + dU = dTmp ; + } + } + } + if ( dU < 0) + dU = 0.5 ; + pBiArc.Set( GetBiArc( ptP0, dDir0Deg, ptP1, dDir1Deg, dU)) ; + } - return nullptr ; + // se biarco non trovato, errore + if ( IsNull( pBiArc)) + return nullptr ; + + // determino la massima distanza tra la curva e il biarco + Point3d ptP ; + double dSqDist = 0 ; + for ( bool bPnt = PL.GetFirstPoint( ptP) ; + bPnt ; + bPnt = PL.GetNextPoint( ptP)) { + DistPointCurve dstPC( ptP, *Get( pBiArc)) ; + double dSqDistPC ; + if ( dstPC.GetSqDist( dSqDistPC) && dSqDistPC > dSqDist) + dSqDist = dSqDistPC ; + } + dDist = sqrt( dSqDist) ; + + return Release( pBiArc) ; } //---------------------------------------------------------------------------- @@ -111,7 +170,7 @@ CalcJCurve( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dD // se rotazione nulla, allora segmento di retta tra i due punti if ( fabs( dAngDeg) < EPS_ANG_SMALL) { PtrOwner pLine( CreateCurveLine()) ; - if ( ! ::IsValid( pLine) || ! pLine->Set( ptP0, ptP1)) + if ( IsNull( pLine) || ! pLine->Set( ptP0, ptP1)) return nullptr ; // inverto per avere parametrizzazione crescente allontanandosi da Dir0 e avvicinandosi a Dir1 pLine->Invert() ; @@ -133,7 +192,7 @@ CalcJCurve( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dD double dRad, dAngStart ; vtStart.ToSpherical( &dRad, nullptr, &dAngStart) ; PtrOwner pArc( CreateCurveArc()) ; - if ( ! ::IsValid( pArc) || ! pArc->SetXY( ptCen, dRad, dAngStart, dAngDeg, ( ptP1.z - ptP0.z))) + if ( IsNull( pArc) || ! pArc->SetXY( ptCen, dRad, dAngStart, dAngDeg, ( ptP1.z - ptP0.z))) return nullptr ; double dDirStartDeg = dAngStart + ( dAngDeg > 0 ? ANG_RIGHT : - ANG_RIGHT) ; // determinazione regione tra le curve estreme in cui contenere l'arco (tramite angoli su start) diff --git a/BiArcs.h b/BiArcs.h new file mode 100644 index 0000000..2ce110e --- /dev/null +++ b/BiArcs.h @@ -0,0 +1,20 @@ +//---------------------------------------------------------------------------- +// EgalTech 2014-2014 +//---------------------------------------------------------------------------- +// File : BiArcs.h Data : 18.08.14 Versione : 1.5h5 +// Contenuto : Dichiarazione funzioni locali per calcolo biarchi. +// +// +// +// Modifiche : 18.08.14 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +#pragma once + +#include "/EgtDev/Include/EgkBiArcs.h" + +//----------------------------------------------------------------------------- +ICurve* GetBiArc( const ICurve& Crv, const PolyLine& PL, double& dDist) ; + diff --git a/CurveArc.cpp b/CurveArc.cpp index 910e7e2..fe3e683 100644 --- a/CurveArc.cpp +++ b/CurveArc.cpp @@ -935,7 +935,7 @@ CurveArc::CopyParamRange( double dUStart, double dUEnd) const } // creo l'arco copia PtrOwner pCopy( Clone()) ; - if ( ! ::IsValid( pCopy)) + if ( IsNull( pCopy)) return nullptr ; // eseguo il trim if ( ! pCopy->TrimStartEndAtParam( dUStart, dUEnd)) diff --git a/CurveAux.cpp b/CurveAux.cpp index 898094f..2ebe51d 100644 --- a/CurveAux.cpp +++ b/CurveAux.cpp @@ -95,19 +95,24 @@ GetPointTang( const ICurve& crvC, double dU, ICurve::Side nS, Point3d& ptPos, Ve { if ( ! crvC.GetPointD1D2( dU, nS, ptPos, &vtTang)) return false ; - if ( vtTang.Normalize()) + if ( vtTang.Normalize( EPS_ZERO)) return true ; // nel caso la derivata prima sia nulla, utilizziamo la seconda Vector3d vtDummy ; if ( ! crvC.GetPointD1D2( dU, nS, ptPos, &vtDummy, &vtTang)) return false ; - if ( ! vtTang.Normalize()) - return false ; - // per il verso, lo confrontiamo con quello della derivata prima un poco discosta + double dUmod = dU + ( nS == ICurve::FROM_MINUS ? -1 : +1) * 100 * EPS_PARAM ; Point3d ptDummy ; + // se anche la derivata seconda è nulla, provo a spostarmi di poco + if ( ! vtTang.Normalize( EPS_ZERO)) { + if ( ! crvC.GetPointD1D2( dUmod, nS, ptDummy, &vtDummy, &vtTang)) + return false ; + if ( ! vtTang.Normalize( EPS_ZERO)) + return false ; + } + // per il verso, lo confrontiamo con quello della derivata prima un poco discosta Vector3d vtD1near ; - dU += ( nS == ICurve::FROM_MINUS ? -1 : +1) * 100 * EPS_PARAM ; - if ( ! crvC.GetPointD1D2( dU, nS, ptDummy, &vtD1near)) + if ( ! crvC.GetPointD1D2( dUmod, nS, ptDummy, &vtD1near)) return false ; if ( ( vtTang * vtD1near) < 0) vtTang.Invert() ; @@ -223,7 +228,7 @@ ArcToBezierCurve( const ICurve* pCrv) if ( fabs( pArc->GetAngCenter()) <= BEZARC_ANG_CEN_MAX) { // creo la curva di Bezier PtrOwner pCrvBez( CreateCurveBezier()) ; - if ( ! IsValid( pCrvBez)) + if ( IsNull( pCrvBez)) return nullptr ; if ( ! pCrvBez->FromArc( *pArc)) return nullptr ; @@ -235,7 +240,7 @@ ArcToBezierCurve( const ICurve* pCrv) else { // creo la curva composita PtrOwner pCrvCompo( CreateCurveComposite()) ; - if ( ! IsValid( pCrvCompo)) + if ( IsNull( pCrvCompo)) return nullptr ; if ( ! pCrvCompo->AddCurve( *pArc) || ! pCrvCompo->ArcsToBezierCurves()) @@ -290,7 +295,7 @@ NurbsToBezierCurve( const CNurbsData& cnData) if ( nInt == 1) { // creo la curva di Bezier PtrOwner pCrvBez( CreateCurveBezier()) ; - if ( ! IsValid( pCrvBez)) + if ( IsNull( pCrvBez)) return nullptr ; // la inizializzo if ( ! pCrvBez->Init( cnData.nDeg, cnData.bRat)) @@ -305,13 +310,16 @@ NurbsToBezierCurve( const CNurbsData& cnData) return nullptr ; } } + // se non è una curva ma un punto, la invalido + if ( pCrvBez->IsAPoint()) + pCrvBez->Init( cnData.nDeg, cnData.bRat) ; // restituisco la curva return Release( pCrvBez) ; } // altrimenti è equivalente ad una curva composita, la creo PtrOwner pCrvCompo( CreateCurveComposite()) ; - if ( ! IsValid( pCrvCompo)) + if ( IsNull( pCrvCompo)) return nullptr ; // vettore dei punti di controllo della curva di Bezier @@ -339,6 +347,7 @@ NurbsToBezierCurve( const CNurbsData& cnData) vAlfa.resize( cnData.nDeg - 1) ; int a = cnData.nDeg - 1 ; int b = cnData.nDeg ; + bool bPrevRejected = false ; // ciclo while ( b < nU - 1) { int i = b ; @@ -372,8 +381,15 @@ NurbsToBezierCurve( const CNurbsData& cnData) // costruisco la curva di Bezier e la inserisco nella curva composita PtrOwner pCrvBez( CreateCurveBezier()) ; - if ( ! IsValid( pCrvBez)) + if ( IsNull( pCrvBez)) return nullptr ; + // se precedente saltata + if ( bPrevRejected) { + // prendo l'ultimo punto della curva composita per garantire la continuità + Point3d ptEnd ; + if ( pCrvCompo->GetEndPoint( ptEnd)) + vBC[0] = ptEnd ; + } // la inizializzo if ( ! pCrvBez->Init( cnData.nDeg, cnData.bRat)) return nullptr ; @@ -389,9 +405,17 @@ NurbsToBezierCurve( const CNurbsData& cnData) return nullptr ; } } - // la aggiungo alla curva composita - if ( ! pCrvCompo->AddCurve( Release( pCrvBez))) - return nullptr ; + // se è una vera curva, la aggiungo alla curva composita + if ( ! pCrvBez->IsAPoint()) { + if ( ! pCrvCompo->AddCurve( Release( pCrvBez))) + return nullptr ; + bPrevRejected = false ; + } + // altrimenti è un punto, la cancello + else { + pCrvBez.Reset() ; + bPrevRejected = true ; + } // inizializzazioni per la prossima curva di Bezier if ( b < nU - 1) { diff --git a/CurveBezier.cpp b/CurveBezier.cpp index 59b6bfd..425a577 100644 --- a/CurveBezier.cpp +++ b/CurveBezier.cpp @@ -16,6 +16,7 @@ #include "CurveBezier.h" #include "CurveComposite.h" #include "DistPointCrvBezier.h" +#include "BiArcs.h" #include "GeoConst.h" #include "DistPointLine.h" #include "GeoObjFactory.h" @@ -234,6 +235,22 @@ CurveBezier::FromArc( const ICurveArc& crArc) return true ; } +//---------------------------------------------------------------------------- +bool +CurveBezier::IsAPoint( void) const +{ + // verifico lo stato + if ( m_nStatus != OK) + return false ; + // ciclo sui punti + for ( int i = 1 ; i <= m_nDeg ; ++ i) { + if ( ! AreSamePointApprox( m_aPtCtrl[0], m_aPtCtrl[i])) + return false ; + } + + return true ; +} + //---------------------------------------------------------------------------- const Point3d& CurveBezier::GetControlPoint( int nInd, bool* pbOk) const @@ -1143,88 +1160,6 @@ CurveBezier::GetParamAtLength( double dLen, double& dU) const return bOk ; } -//---------------------------------------------------------------------------- -bool -CurveBezier::FlatOrSplit( int nLev, const CurveBezier& crvBez, double dParStart, double dParEnd, - double dLinTol, double dAngTolDeg, PolyLine& PL) const -{ - const int MAX_LEV = 10 ; - int i ; - double dMaxSqDist ; - double dSqDist ; - double dAngDeg ; - double dPolLen ; - double dLen ; - Point3d ptLast ; - Vector3d vtDirI ; - Vector3d vtDirF ; - Vector3d vtDir ; - - - // se raggiunto il massimo livello di recursione ... - if ( nLev >= MAX_LEV) { - // 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 - PL.GetLastPoint( ptLast) ; - if ( SqDist( ptLast, crvBez.m_aPtCtrl[m_nDeg]) > ( dLinTol * dLinTol)) - PL.AddUPoint( dParEnd, crvBez.m_aPtCtrl[m_nDeg]) ; - return true ; - } - - // massima distanza al quadrato dei punti di controllo intermedi dalla linea tra primo e ultimo - dMaxSqDist = 0 ; - DirDist( crvBez.m_aPtCtrl[0], crvBez.m_aPtCtrl[m_nDeg], vtDir, dLen) ; - for ( i = 1 ; i < m_nDeg ; i ++) { - DistPointLine dstPL( crvBez.m_aPtCtrl[i], crvBez.m_aPtCtrl[0], vtDir, dLen) ; - if ( dstPL.GetSqDist( dSqDist) && dSqDist > dMaxSqDist) - dMaxSqDist = dSqDist ; - } - - // se distanza entro tolleranza - if ( dMaxSqDist <= ( dLinTol * dLinTol)) { - // deviazione angolare tra primo e ultimo tratto del poligono di controllo (grado >= 1) - vtDirI = crvBez.m_aPtCtrl[1] - crvBez.m_aPtCtrl[0] ; - vtDirF = crvBez.m_aPtCtrl[m_nDeg] - crvBez.m_aPtCtrl[m_nDeg-1] ; - vtDirI.GetAngle( vtDirF, dAngDeg) ; - // se deviazione angolare entro tolleranza oppure lunghezza poligono controllo entro tolleranza - if ( fabs( dAngDeg) <= dAngTolDeg || - ( crvBez.GetControlPolygonLength( dPolLen) && dPolLen <= dLinTol)) { - // considero la curva piatta (inserisco il punto se abbastanza lontano dal precedente) ed esco - PL.GetLastPoint( ptLast) ; - if ( SqDist( ptLast, crvBez.m_aPtCtrl[m_nDeg]) > ( dLinTol * dLinTol)) - PL.AddUPoint( dParEnd, crvBez.m_aPtCtrl[m_nDeg]) ; - return true ; - } - } - - // curva da dividere - { - double dParDiv ; - double dParMid ; - CurveBezier crvBez1 ; - // se prima suddivisione e c'è singolarità, divido su questa - if ( nLev == 0 && GetSingularParam( dParDiv) > 0) - ; - // altrimenti divido a metà - else - dParDiv = 0.5 ; - dParMid = dParDiv * ( dParStart + dParEnd) ; - // prima metà - crvBez1 = crvBez ; - crvBez1.TrimEndAtParam( dParDiv) ; - if ( ! FlatOrSplit( nLev + 1, crvBez1, dParStart, dParMid, dLinTol, dAngTolDeg, PL)) - return false ; - // seconda metà - crvBez1 = crvBez ; - crvBez1.TrimStartAtParam( dParDiv) ; - if ( ! FlatOrSplit( nLev + 1, crvBez1, dParMid, dParEnd, dLinTol, dAngTolDeg, PL)) - return false ; - } - - return true ; -} - //---------------------------------------------------------------------------- bool CurveBezier::IsPointOn( const Point3d& ptP, double dTol) const @@ -1265,6 +1200,92 @@ CurveBezier::ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) c // se è stato inserito un solo punto, aggiungo il finale if ( PL.GetPointNbr() == 1) return PL.AddUPoint( 1, m_aPtCtrl[m_nDeg]) ; + // altrimenti, se l'ultimo punto non coincide con il finale lo sostituisco (distano al max di dLinTol) + else { + Point3d ptLast ; + PL.GetLastPoint( ptLast) ; + if ( ! AreSamePointApprox( ptLast, m_aPtCtrl[m_nDeg])) { + PL.EraseLastUPoint() ; + return PL.AddUPoint( 1, m_aPtCtrl[m_nDeg]) ; + } + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +CurveBezier::FlatOrSplit( int nLev, const CurveBezier& crvBez, double dParStart, double dParEnd, + double dLinTol, double dAngTolDeg, PolyLine& PL) const +{ + // se raggiunto il massimo livello di recursione ... + const int MAX_LEV = 10 ; + if ( nLev >= MAX_LEV) { + // 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 + Point3d ptLast ; + PL.GetLastPoint( ptLast) ; + if ( SqDist( ptLast, crvBez.m_aPtCtrl[m_nDeg]) > ( dLinTol * dLinTol)) + PL.AddUPoint( dParEnd, crvBez.m_aPtCtrl[m_nDeg]) ; + return true ; + } + + // massima distanza al quadrato dei punti di controllo intermedi dalla linea tra primo e ultimo + double dMaxSqDist = 0 ; + double dLen ; + Vector3d vtDir ; + DirDist( crvBez.m_aPtCtrl[0], crvBez.m_aPtCtrl[m_nDeg], vtDir, dLen) ; + for ( int i = 1 ; i < m_nDeg ; i ++) { + DistPointLine dstPL( crvBez.m_aPtCtrl[i], crvBez.m_aPtCtrl[0], vtDir, dLen) ; + double dSqDist ; + if ( dstPL.GetSqDist( dSqDist) && dSqDist > dMaxSqDist) + dMaxSqDist = dSqDist ; + } + + // se distanza entro tolleranza + if ( dMaxSqDist <= ( dLinTol * dLinTol)) { + // deviazione angolare tra primo e ultimo tratto del poligono di controllo (grado >= 1) + Vector3d vtDirI = crvBez.m_aPtCtrl[1] - crvBez.m_aPtCtrl[0] ; + Vector3d vtDirF = crvBez.m_aPtCtrl[m_nDeg] - crvBez.m_aPtCtrl[m_nDeg-1] ; + double dAngDeg ; + vtDirI.GetAngle( vtDirF, dAngDeg) ; + // se deviazione angolare entro tolleranza oppure lunghezza poligono controllo entro tolleranza + double dPolLen ; + if ( fabs( dAngDeg) <= dAngTolDeg || + ( crvBez.GetControlPolygonLength( dPolLen) && dPolLen <= dLinTol)) { + // considero la curva piatta (inserisco il punto se abbastanza lontano dal precedente) ed esco + Point3d ptLast ; + PL.GetLastPoint( ptLast) ; + if ( SqDist( ptLast, crvBez.m_aPtCtrl[m_nDeg]) > ( dLinTol * dLinTol)) + PL.AddUPoint( dParEnd, crvBez.m_aPtCtrl[m_nDeg]) ; + return true ; + } + } + + // curva da dividere + { + double dParDiv ; + double dParMid ; + CurveBezier crvBez1 ; + // se prima suddivisione e c'è singolarità, divido su questa + if ( nLev == 0 && GetSingularParam( dParDiv) > 0) + ; + // altrimenti divido a metà + else + dParDiv = 0.5 ; + dParMid = dParDiv * ( dParStart + dParEnd) ; + // prima metà + crvBez1 = crvBez ; + crvBez1.TrimEndAtParam( dParDiv) ; + if ( ! FlatOrSplit( nLev + 1, crvBez1, dParStart, dParMid, dLinTol, dAngTolDeg, PL)) + return false ; + // seconda metà + crvBez1 = crvBez ; + crvBez1.TrimStartAtParam( dParDiv) ; + if ( ! FlatOrSplit( nLev + 1, crvBez1, dParMid, dParEnd, dLinTol, dAngTolDeg, PL)) + return false ; + } return true ; } @@ -1273,10 +1294,107 @@ CurveBezier::ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL) c bool CurveBezier::ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) const { - // pulisco la polilinea + // pulisco il poliarco PA.Clear() ; - return false ; + // costruisco una approssimazione lineare + PolyLine PL ; + if ( ! ApproxWithLines( dLinTol, dAngTolDeg, PL)) + return false ; + + // approssimo la curva per approssimazioni successive mediante bisezione + return BiArcOrSplit( 0, PL, dLinTol, dAngTolDeg, PA) ; +} + +//---------------------------------------------------------------------------- +bool +CurveBezier::BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAngTolDeg, PolyArc& PA) const +{ + const int MAX_LEV = 10 ; + + // se non chiusa + if ( ! PL.IsClosed()) { + + PtrOwner pCrv ; + double dMaxDist ; + + // se la polilinea ha più di 2 punti + if ( PL.GetPointNbr() > 2) { + // costruisco un biarco sulla polilinea (secondo metodo di Z. Sir) + pCrv.Set( GetBiArc( *this, PL, dMaxDist)) ; + if ( IsNull( pCrv)) + return false ; + } + // se la polilinea è formata da 2 punti + else if ( PL.GetPointNbr() == 2) { + // se molto vicini, esco + double dLen ; + if ( PL.GetLength( dLen) && dLen < EPS_SMALL) + return true ; + // costruisco la retta che li unisce + PtrOwner pCC( CreateCurveComposite()) ; + if ( IsNull( pCC)) + return false ; + if ( ! pCC->FromPolyLine( PL)) + return false ; + pCrv.Set( Release( pCC)) ; + dMaxDist = 0 ; + } + // se la polilinea ha un solo punto, esco + else + return true ; + + // se raggiunto il massimo livello di recursione, forzo l'accettazione del biarco + if ( nLev >= MAX_LEV) { + dMaxDist = 0 ; + // segnalo situazione per debug + LOG_DBG_ERR( GetEGkLogger(), "ERROR : Exceeded recursions") + } + + // se lunghezza abbastanza picccola, forzo l'accettazione della curva + double dLen ; + if ( PL.GetApproxLength( dLen) && dLen < 10 * EPS_SMALL) + dMaxDist = 0 ; + + // se in tolleranza + if ( dMaxDist <= dLinTol) { + // lo inserisco nel poliarco ed esco + PolyArc PA2 ; + if ( ! pCrv->ApproxWithArcs( dLinTol, dAngTolDeg, PA2)) + return false ; + if ( ! PA.Join( PA2)) + return false ; + return true ; + } + } + + // se raggiunto il massimo livello di recursione, errore + if ( nLev >= MAX_LEV) { + // segnalo situazione per debug + LOG_DBG_ERR( GetEGkLogger(), "ERROR : Exceeded recursions") + return false ; + } + + // spezzo l'intervallo in due parti + double dParMid ; + // se prima suddivisione e c'è singolarità, divido su questa + if ( nLev == 0 && GetSingularParam( dParMid) > 0) + ; + // altrimenti divido a metà + else { + double dParStart, dParEnd ; + if ( ! PL.GetFirstU( dParStart) || ! PL.GetLastU( dParEnd)) + return false ; + dParMid = 0.5 * ( dParStart + dParEnd) ; + } + PolyLine PL2 ; + if ( ! PL.Split( dParMid, PL2)) + return false ; + // prima metà + if ( ! BiArcOrSplit( nLev + 1, PL, dLinTol, dAngTolDeg, PA)) + return false ; + // seconda metà + return BiArcOrSplit( nLev + 1, PL2, dLinTol, dAngTolDeg, PA) ; } //---------------------------------------------------------------------------- @@ -1302,7 +1420,7 @@ CurveBezier::CopyParamRange( double dUStart, double dUEnd) const } // creo la curva di Bezier copia PtrOwner pCopy( Clone()) ; - if ( ! ::IsValid( pCopy)) + if ( IsNull( pCopy)) return nullptr ; // eseguo il trim if ( ! pCopy->TrimStartEndAtParam( dUStart, dUEnd)) diff --git a/CurveBezier.h b/CurveBezier.h index d396dfc..3005556 100644 --- a/CurveBezier.h +++ b/CurveBezier.h @@ -111,6 +111,7 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW { return m_nDeg ; } virtual bool IsRational( void) const { return m_bRat ; } + virtual bool IsAPoint( void) const ; 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 ; @@ -141,6 +142,7 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW double& dUIni, double& dUFin) const ; bool FlatOrSplit( int nLev, const CurveBezier& crvBez, double dParStart, double dParEnd, double dLinTol, double dAngTolDeg, PolyLine& PL) const ; + bool BiArcOrSplit( int nLev, PolyLine& PL, double dLinTol, double dAngTolDeg, PolyArc& PA) const ; bool ToPowerBase( PolynomialPoint3d& pol3P) const ; bool ToPowerBase( PolynomialPoint3d& pol3Num, Polynomial& polDen) const ; diff --git a/CurveByInterp.cpp b/CurveByInterp.cpp index f8eed51..3ebb065 100644 --- a/CurveByInterp.cpp +++ b/CurveByInterp.cpp @@ -62,7 +62,7 @@ CurveByInterp::GetCurve( int nMethod, int nType) if ( nType == BIARCS) { // creo la curva composita PtrOwner pCrvCompo( CreateCurveComposite()) ; - if ( ! IsValid( pCrvCompo)) + if ( IsNull( pCrvCompo)) return nullptr ; // ciclo sugli intervalli for ( int i = 1 ; i < int( m_vPnt.size()) ; ++ i) { @@ -82,13 +82,13 @@ CurveByInterp::GetCurve( int nMethod, int nType) if ( nType == CUBIC_BEZIERS) { // creo la curva composita PtrOwner pCrvCompo( CreateCurveComposite()) ; - if ( ! IsValid( pCrvCompo)) + if ( IsNull( pCrvCompo)) return nullptr ; // ciclo sugli intervalli for ( int i = 1 ; i < int( m_vPnt.size()) ; ++ i) { // creo una curva di Bezier cubica per ogni intervallo PtrOwner pCBez( CreateCurveBezier()) ; - if ( ! IsValid( pCBez)) + if ( IsNull( pCBez)) return false ; pCBez->Init( 3, false) ; pCBez->SetControlPoint( 0, m_vPnt[i-1]) ; diff --git a/CurveComposite.cpp b/CurveComposite.cpp index a9d010e..99791d7 100644 --- a/CurveComposite.cpp +++ b/CurveComposite.cpp @@ -149,7 +149,7 @@ CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart, double dLinT { // prendo la proprietà del puntatore PtrOwner pCrv( pSmplCrv) ; - if ( ! ::IsValid( pCrv)) + if ( IsNull( pCrv)) return false ; // verifico lo stato @@ -253,7 +253,7 @@ CurveComposite::FromSplit( const ICurve& cCrv, int nParts) dStartLen = dEndLen ; dEndLen = dTotLen * i / (double) nParts ; PtrOwner pSmplCrv( GetCurve( cCrv.Clone())) ; - if ( ! ::IsValid( pSmplCrv)) + if ( IsNull( pSmplCrv)) return false ; if ( ! pSmplCrv->TrimEndAtLen( dEndLen) || ! pSmplCrv->TrimStartAtLen( dStartLen)) @@ -289,7 +289,7 @@ CurveComposite::FromPolyLine( const PolyLine& PL) continue ; // creo il segmento di retta PtrOwner pCrvLine( CreateCurveLine()) ; - if ( ! ::IsValid( pCrvLine)) + if ( IsNull( pCrvLine)) return false ; // assegno i punti estremi if ( ! pCrvLine->Set( ptIni, ptFin)) @@ -329,7 +329,7 @@ CurveComposite::FromPolyArc( const PolyArc& PA) if ( fabs( dBulge) < EPS_SMALL) { // creo la retta PtrOwner pCrvLine( CreateBasicCurveLine()) ; - if ( ! ::IsValid( pCrvLine)) + if ( IsNull( pCrvLine)) return false ; // setto la linea if ( ! pCrvLine->Set( ptIni, ptFin)) @@ -342,7 +342,7 @@ CurveComposite::FromPolyArc( const PolyArc& PA) else { // creo l'arco PtrOwner pCrvArc( CreateBasicCurveArc()) ; - if ( ! ::IsValid( pCrvArc)) + if ( IsNull( pCrvArc)) return false ; // setto l'arco if ( ! pCrvArc->Set2PNB( ptIni, ptFin, PA.GetExtrusion(), dBulge)) @@ -386,7 +386,7 @@ CurveComposite::PolygonCenterCorner( int nSides, const Point3d& ptCen, const Poi } // creo il segmento di retta PtrOwner pCrvLine( CreateBasicCurveLine()) ; - if ( ! ::IsValid( pCrvLine)) + if ( IsNull( pCrvLine)) return false ; // assegno i punti estremi if ( ! pCrvLine->Set( ptStart, ptEnd)) @@ -1058,7 +1058,6 @@ CurveComposite::ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL return false ; // eseguo approssimazione - bool bFirst = true ; double dStartPar = 0 ; PolyLine PLSmpl ; PCRVSMPL_DEQUE::const_iterator Iter ; @@ -1067,15 +1066,8 @@ CurveComposite::ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL 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) ; - } + if ( ! PL.Join( PLSmpl, dStartPar)) + return false ; // incremento inizio parametro per prossima curva semplice dStartPar += 1 ; } @@ -1095,7 +1087,6 @@ CurveComposite::ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) return false ; // eseguo approssimazione - bool bFirst = true ; double dStartPar = 0 ; PolyArc PASmpl ; PCRVSMPL_DEQUE::const_iterator Iter ; @@ -1104,15 +1095,8 @@ CurveComposite::ApproxWithArcs( double dLinTol, double dAngTolDeg, PolyArc& PA) if ( ! (*Iter)->ApproxWithArcs( dLinTol, dAngTolDeg, PASmpl)) return false ; // la accodo opportunamente a quella della curva composita - if ( bFirst) { - PA.Splice( PASmpl) ; - bFirst = false ; - } - else { - PA.EraseLastUPoint() ; - PASmpl.AddOffsetToU( dStartPar) ; - PA.Splice( PASmpl) ; - } + if ( ! PA.Join( PASmpl, dStartPar)) + return false ; // incremento inizio parametro per prossima curva semplice dStartPar += 1 ; } @@ -1143,7 +1127,7 @@ CurveComposite::CopyParamRange( double dUStart, double dUEnd) const int nIdEnd = static_cast( ceil( dUEnd)) ; // creo la curva composita copia PtrOwner pCopy( new CurveComposite()) ; - if ( ! ::IsValid( pCopy)) + if ( IsNull( pCopy)) return nullptr ; // eseguo la copia delle sole curve semplici necessarie for ( int i = nIdStart ; i < nIdEnd ; ++ i) { @@ -1883,7 +1867,7 @@ CurveComposite::ArcsToBezierCurves( void) if ( fabs( pArc->GetAngCenter()) <= BEZARC_ANG_CEN_MAX + EPS_ANG_SMALL) { // creo la curva di Bezier PtrOwner pCrvBez( CreateBasicCurveBezier()) ; - if ( ! ::IsValid( pCrvBez)) + if ( IsNull( pCrvBez)) return false ; if ( ! pCrvBez->FromArc( *pArc)) return false ; diff --git a/CurveLine.cpp b/CurveLine.cpp index b450d58..515164e 100644 --- a/CurveLine.cpp +++ b/CurveLine.cpp @@ -465,7 +465,7 @@ CurveLine::CopyParamRange( double dUStart, double dUEnd) const return nullptr ; // creo la linea copia PtrOwner pCopy( Clone()) ; - if ( ! ::IsValid( pCopy)) + if ( IsNull( pCopy)) return nullptr ; // eseguo il trim if ( ! pCopy->TrimStartEndAtParam( dUStart, dUEnd)) diff --git a/DistPointCurve.cpp b/DistPointCurve.cpp index c02785a..5bd1b2b 100644 --- a/DistPointCurve.cpp +++ b/DistPointCurve.cpp @@ -58,7 +58,7 @@ DistPointCurve::LineCalculate( const Point3d& ptP, const ICurve& Curve, bool bIs { DistPointLine dstPtLn( ptP, *GetCurveLine( &Curve), bIsSegment) ; - if ( dstPtLn.m_dSqDist > 0) { + if ( dstPtLn.m_dSqDist >= 0) { m_dDist = sqrt( dstPtLn.m_dSqDist) ; m_Info.push_back( MinDistPCInfo( MDPCI_NORMAL, dstPtLn.m_dParam, dstPtLn.m_ptMinDist)) ; } diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 2c0006b..06bb921 100644 Binary files a/EgtGeomKernel.rc and b/EgtGeomKernel.rc differ diff --git a/EgtGeomKernel.vcxproj b/EgtGeomKernel.vcxproj index bf9c44a..04cd493 100644 --- a/EgtGeomKernel.vcxproj +++ b/EgtGeomKernel.vcxproj @@ -354,6 +354,7 @@ copy $(TargetPath) \EgtProg\Dll64 + diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters index f677f16..f36c784 100644 --- a/EgtGeomKernel.vcxproj.filters +++ b/EgtGeomKernel.vcxproj.filters @@ -545,6 +545,9 @@ File di intestazione\Include + + File di intestazione + diff --git a/FontNfe.cpp b/FontNfe.cpp index 702c128..d25c84d 100644 --- a/FontNfe.cpp +++ b/FontNfe.cpp @@ -79,7 +79,7 @@ NfeFont::SetCurrFont( const string& sFont, int nWeight, bool bItalic, return false ; // recupero i parametri generali del font (devono essere nel gruppo 1) PtrOwner pIter( CreateGdbIterator( m_pGDB)) ; - if ( ! IsValid( pIter)) + if ( IsNull( pIter)) return false ; if ( ! pIter->GoTo( 1)) return false ; @@ -160,7 +160,7 @@ NfeFont::GetXBox( const string& sText, int nInsPos, bool bCapOrBound, BBox3d& b3 // creo un iteratore PtrOwner pIter( CreateGdbIterator( m_pGDB)) ; - if ( ! IsValid( pIter)) + if ( IsNull( pIter)) return false ; // calcolo i fattori di scala @@ -227,7 +227,7 @@ NfeFont::GetOutline( const string& sText, int nInsPos, ICURVEPLIST& lstPC) // creo un iteratore PtrOwner pIter( CreateGdbIterator( m_pGDB)) ; - if ( ! IsValid( pIter)) + if ( IsNull( pIter)) return false ; // calcolo i fattori di scala @@ -316,7 +316,7 @@ NfeFont::ApproxWithLines( const string& sText, int nInsPos, double dLinTol, doub // creo un iteratore PtrOwner pIter( CreateGdbIterator( m_pGDB)) ; - if ( ! IsValid( pIter)) + if ( IsNull( pIter)) return false ; // calcolo i fattori di scala diff --git a/FontOs.cpp b/FontOs.cpp index 785d05e..86d9a65 100644 --- a/FontOs.cpp +++ b/FontOs.cpp @@ -425,7 +425,7 @@ OsFont::GetCharOutline( unsigned int nChar, double& dAdvance, ICURVEPLIST& lstPC if ( dwSize == GDI_ERROR) return false ; PtrOwner pBuffer( new char[dwSize]) ; - if ( ! ::IsValid( pBuffer)) + if ( IsNull( pBuffer)) return false ; // recupero l'outline DWORD dErr = GetGlyphOutlineW( m_hDC, nChar, GGO_NATIVE, &gm, dwSize, ::Get( pBuffer), &mat) ; @@ -446,7 +446,7 @@ OsFont::GetCharOutline( unsigned int nChar, double& dAdvance, ICURVEPLIST& lstPC // creo curva composita PtrOwner pCCompo( CreateCurveComposite()) ; - if ( ! ::IsValid( pCCompo)) + if ( IsNull( pCCompo)) return false ; // posizionamento sul punto iniziale @@ -539,7 +539,7 @@ OsFont::AddLineToCompo( ICurveComposite* pCCompo, const Point3d& ptStart, const // creo retta, la imposto e la inserisco nella curva composita PtrOwner pCLine( CreateCurveLine()) ; - if ( ! ::IsValid( pCLine)) + if ( IsNull( pCLine)) return false ; if ( ! pCLine->Set( ptStart, ptEnd)) return false ; @@ -560,7 +560,7 @@ OsFont::AddCBezierQuadToCompo( ICurveComposite* pCCompo, // creo curva di Bezier quadratica, la imposto e la inserisco nella curva composita PtrOwner pCBezier( CreateCurveBezier()) ; - if ( ! ::IsValid( pCBezier)) + if ( IsNull( pCBezier)) return false ; if ( ! pCBezier->Init( 2, false) || ! pCBezier->SetControlPoint( 0, ptStart) || diff --git a/GdbExecutor.cpp b/GdbExecutor.cpp index 45f8ba5..85bd734 100644 --- a/GdbExecutor.cpp +++ b/GdbExecutor.cpp @@ -633,7 +633,7 @@ GdbExecutor::CurveLineMake( const STRVECTOR& vsParams) return false ; // creo la linea PtrOwner pCrvLine( CreateCurveLine()) ; - if ( ! IsValid( pCrvLine)) + if ( IsNull( pCrvLine)) return false ; // setto la linea if ( ! pCrvLine->Set( ptStart, ptEnd)) @@ -667,7 +667,7 @@ GdbExecutor::CurveLineVersorLength( const STRVECTOR& vsParams) return false ; // creo la linea PtrOwner pCrvLine( CreateCurveLine()) ; - if ( ! IsValid( pCrvLine)) + if ( IsNull( pCrvLine)) return false ; // setto la linea if ( ! pCrvLine->SetPVL( ptStart, vtDir, dLen)) @@ -701,7 +701,7 @@ GdbExecutor::CurveLineDirLength( const STRVECTOR& vsParams) return false ; // creo la linea PtrOwner pCrvLine( CreateCurveLine()) ; - if ( ! IsValid( pCrvLine)) + if ( IsNull( pCrvLine)) return false ; // setto la linea if ( ! pCrvLine->SetPDL( ptStart, dDirAngDeg, dLen)) @@ -799,7 +799,7 @@ GdbExecutor::CurveLineTgTwoArcs( const STRVECTOR& vsParams) return false ; // porto il secondo arco nel riferimento del primo PtrOwner pArc2Loc( CreateCurveArc()) ; - if ( ! IsValid( pArc2Loc)) + if ( IsNull( pArc2Loc)) return false ; pArc2Loc->CopyFrom( pArc2) ; pArc2Loc->LocToLoc( frArc2, frArc1) ; @@ -863,7 +863,7 @@ GdbExecutor::CurveLineMinPointCurve( const STRVECTOR& vsParams) ptEnd.LocToLoc( frCurve, frPoint) ; // creo la linea PtrOwner pCrvLine( CreateCurveLine()) ; - if ( ! IsValid( pCrvLine)) + if ( IsNull( pCrvLine)) return false ; // setto la linea if ( ! pCrvLine->Set( ptStart, ptEnd)) @@ -966,7 +966,7 @@ GdbExecutor::CurveCircleMake( const STRVECTOR& vsParams) return false ; // creo l'arco PtrOwner pCrvArc( CreateCurveArc()) ; - if ( ! IsValid( pCrvArc)) + if ( IsNull( pCrvArc)) return false ; // setto l'arco if ( ! pCrvArc->Set( ptCen, vtN, dRad)) @@ -996,7 +996,7 @@ GdbExecutor::CurveCirclePlaneXY( const STRVECTOR& vsParams) return false ; // creo l'arco PtrOwner pCrvArc( CreateCurveArc()) ; - if ( ! IsValid( pCrvArc)) + if ( IsNull( pCrvArc)) return false ; // setto l'arco if ( ! pCrvArc->SetXY( ptCen, dRad)) @@ -1042,7 +1042,7 @@ GdbExecutor::CurveArcMake( const STRVECTOR& vsParams) return false ; // creo l'arco PtrOwner pCrvArc( CreateCurveArc()) ; - if ( ! IsValid( pCrvArc)) + if ( IsNull( pCrvArc)) return false ; // setto l'arco if ( ! pCrvArc->Set( ptCen, vtN, dRad, vtS, dAngCenDeg, dDeltaZ)) @@ -1084,7 +1084,7 @@ GdbExecutor::CurveArcPlaneXY( const STRVECTOR& vsParams) return false ; // creo l'arco PtrOwner pCrvArc( CreateCurveArc()) ; - if ( ! IsValid( pCrvArc)) + if ( IsNull( pCrvArc)) return false ; // setto l'arco if ( ! pCrvArc->SetXY( ptCen, dRad, dAngIniDeg, dAngCenDeg, dDeltaZ)) @@ -1118,7 +1118,7 @@ GdbExecutor::CurveArcCircle3P( const STRVECTOR& vsParams, bool bCirc) return false ; // creo l'arco PtrOwner pCrvArc( CreateCurveArc()) ; - if ( ! IsValid( pCrvArc)) + if ( IsNull( pCrvArc)) return false ; // setto l'arco if ( ! pCrvArc->Set3P( ptP0, ptP1, ptP2, bCirc)) @@ -1187,7 +1187,7 @@ GdbExecutor::CurveArc2PRS( const STRVECTOR& vsParams) bCCW = false ; // creo l'arco PtrOwner pCrvArc( CreateCurveArc()) ; - if ( ! IsValid( pCrvArc)) + if ( IsNull( pCrvArc)) return false ; // setto l'arco if ( ! pCrvArc->Set2PRS( ptPi, ptPf, dRad, bCCW)) @@ -1221,7 +1221,7 @@ GdbExecutor::CurveArcC2P( const STRVECTOR& vsParams) return false ; // creo l'arco PtrOwner pCrvArc( CreateCurveArc()) ; - if ( ! IsValid( pCrvArc)) + if ( IsNull( pCrvArc)) return false ; // setto l'arco if ( ! pCrvArc->SetC2P( ptCen, ptPi, ptNearPf)) @@ -1487,7 +1487,7 @@ GdbExecutor::ExecuteCurveBez( const string& sCmd2, const STRVECTOR& vsParams) { // creo la curva di Bezier PtrOwner pCrvBez( CreateCurveBezier()) ; - if ( ! IsValid( pCrvBez)) + if ( IsNull( pCrvBez)) return false ; // per cancellazione eventuale arco di origine bool bErase = false ; @@ -1578,6 +1578,10 @@ GdbExecutor::ExecuteCurveBez( const string& sCmd2, const STRVECTOR& vsParams) else return false ; + // se curva nulla (ovvero ridotta a punto), errore + if ( pCrvBez->IsAPoint()) + return false ; + // inserisco la curva di Bezier nel DB if ( AddGeoObj( vsParams[0], vsParams[1], Release( pCrvBez))) { // se richiesto, cancello eventuale arco di origine @@ -1650,7 +1654,7 @@ GdbExecutor::CurveCompoMake( const STRVECTOR& vsParams) { // creo la curva composita PtrOwner pCrvCompo( CreateCurveComposite()) ; - if ( ! IsValid( pCrvCompo)) + if ( IsNull( pCrvCompo)) return false ; // 3 o 4 parametri bool bErase ; @@ -1689,7 +1693,7 @@ GdbExecutor::CurveCompoMake( const STRVECTOR& vsParams) else { // creo una copia della curva (da buttare alla fine) PtrOwner pModCrv( pCrv->Clone()) ; - if ( ! IsValid( pModCrv)) + if ( IsNull( pModCrv)) return false ; // eseguo la trasformazione pModCrv->ToGlob( frSou) ; @@ -1732,7 +1736,7 @@ GdbExecutor::CurveCompoFromPoints( const STRVECTOR& vsParams) return false ; // creo la curva composita PtrOwner pCrvCompo( CreateCurveComposite()) ; - if ( ! IsValid( pCrvCompo)) + if ( IsNull( pCrvCompo)) return false ; // inserisco i segmenti che uniscono i punti if ( ! pCrvCompo->FromPolyLine( PL)) @@ -1758,7 +1762,7 @@ GdbExecutor::CurveCompoFromPointBulges( const STRVECTOR& vsParams) return false ; // creo la curva composita PtrOwner pCrvCompo( CreateCurveComposite()) ; - if ( ! IsValid( pCrvCompo)) + if ( IsNull( pCrvCompo)) return false ; // inserisco i segmenti che uniscono i punti if ( ! pCrvCompo->FromPolyArc( PA)) @@ -1810,7 +1814,7 @@ GdbExecutor::CurveCompoFromPointInterpolation( const STRVECTOR& vsParams) crvByInterp.AddPoint( ptP) ; crvByInterp.End() ; PtrOwner pCrv( crvByInterp.GetCurve( nMethod, nType)) ; - if ( ! ::IsValid( pCrv)) + if ( IsNull( pCrv)) return false ; // inserisco la curva composita nel DB return AddGeoObj( vsParams[0], vsParams[1], ::Release( pCrv)) ; @@ -1843,7 +1847,7 @@ GdbExecutor::CurveCompoFromCurveApproximation( const STRVECTOR& vsParams) return false ; // eseguo l'approssimazione PtrOwner pCC( CreateCurveComposite()) ; - if ( ! IsValid( pCC)) + if ( IsNull( pCC)) return false ; if ( nType == 1) { // con linee PolyLine PL ; @@ -1876,7 +1880,7 @@ GdbExecutor::CurveCompoFromSplit( const STRVECTOR& vsParams) // creo la curva composita PtrOwner pCrvCompo( CreateCurveComposite()) ; - if ( ! IsValid( pCrvCompo)) + if ( IsNull( pCrvCompo)) return false ; // salvo nome curva originale per eventuale cancellazione @@ -1944,7 +1948,7 @@ GdbExecutor::CurveCompoFromPolygon( const STRVECTOR& vsParams, int nType) return false ; // creo la curva composita PtrOwner pCrvCompo( CreateCurveComposite()) ; - if ( ! IsValid( pCrvCompo)) + if ( IsNull( pCrvCompo)) return false ; // costruisco il poligono switch ( nType) { @@ -2001,7 +2005,7 @@ GdbExecutor::CurveCompoFromBiarc( const STRVECTOR& vsParams) return false ; // costruisco il biarco PtrOwner pBiArc( GetBiArc( ptP1, dDir1, ptP2, dDir2, dPar)) ; - if ( ! ::IsValid( pBiArc)) + if ( IsNull( pBiArc)) return false ; // inserisco la curva nel DB return AddGeoObj( vsParams[0], vsParams[1], Release( pBiArc)) ; @@ -2334,7 +2338,7 @@ GdbExecutor::SurfTriMeshByContour( const STRVECTOR& vsParams) return false ; // creo la superficie PtrOwner pSTM( CreateSurfTriMesh()) ; - if ( ! IsValid( pSTM)) + if ( IsNull( pSTM)) return false ; // costruisco la triangolazione if ( ! pSTM->CreateByFlatContour( PL)) @@ -2370,7 +2374,7 @@ GdbExecutor::SurfTriMeshByExtrusion( const STRVECTOR& vsParams) return false ; // creo la superficie PtrOwner pSTM( CreateSurfTriMesh()) ; - if ( ! IsValid( pSTM)) + if ( IsNull( pSTM)) return false ; // costruisco l'estrusione if ( ! pSTM->CreateByExtrusion( PL, vtExtr)) @@ -2408,7 +2412,7 @@ GdbExecutor::SurfTriMeshByTwoPaths( const STRVECTOR& vsParams) return false ; // creo la superficie PtrOwner pSTM( CreateSurfTriMesh()) ; - if ( ! IsValid( pSTM)) + if ( IsNull( pSTM)) return false ; // costruisco la rigata tra le due curve if ( ! pSTM->CreateByTwoCurves( PL1, PL2)) @@ -2476,7 +2480,7 @@ GdbExecutor::SurfTriMeshByScrewing( bool bMove, const STRVECTOR& vsParams) double dStepRotDeg = sqrt( 8 * dLinTol / dMaxRad) * RADTODEG ; // creo la superficie PtrOwner pSTM( CreateSurfTriMesh()) ; - if ( ! IsValid( pSTM)) + if ( IsNull( pSTM)) return false ; // costruisco la rivoluzione if ( ! pSTM->CreateByScrewing( PL, ptAx, vtAx, dAngRotDeg, dStepRotDeg, dMove)) @@ -2508,7 +2512,7 @@ GdbExecutor::GetPolyLineFromCurve( int nId, const Frame3d& frDest, double dLinTo else { // creo una copia della curva (da buttare alla fine) PtrOwner pModCrv( pCrv->Clone()) ; - if ( ! IsValid( pModCrv)) + if ( IsNull( pModCrv)) return false ; // eseguo la trasformazione pModCrv->LocToLoc( frCrv, frDest) ; @@ -2542,7 +2546,7 @@ GdbExecutor::GetPolyArcFromCurve( int nId, const Frame3d& frDest, double dLinTol else { // creo una copia della curva (da buttare alla fine) PtrOwner pModCrv( pCrv->Clone()) ; - if ( ! IsValid( pModCrv)) + if ( IsNull( pModCrv)) return false ; // eseguo la trasformazione pModCrv->LocToLoc( frCrv, frDest) ; @@ -2710,7 +2714,7 @@ GdbExecutor::TextSimple( const STRVECTOR& vsParams) return false ; // creo il testo PtrOwner pTXT( CreateExtText()) ; - if ( ! IsValid( pTXT)) + if ( IsNull( pTXT)) return false ; // lo riempio if ( ! pTXT->Set( sText, ptP, dAngRotDeg, dH)) @@ -2785,7 +2789,7 @@ GdbExecutor::TextComplete( const STRVECTOR& vsParams) nInsPos = ETXT_IPBR ; // creo il testo PtrOwner pTXT( CreateExtText()) ; - if ( ! IsValid( pTXT)) + if ( IsNull( pTXT)) return false ; // lo riempio if ( ! pTXT->Set( sText, ptP, dAngRotDeg, vsParams[5], nW, bItl, dH, dRat, dAddAdv, nInsPos)) @@ -3291,7 +3295,7 @@ GdbExecutor::GetPointParam( const string& sParam, const Frame3d& frPnt, Point3d& PtrOwner crvTrans( nullptr) ; if ( ! AreSameFrame( frEnt, frEnt2)) { crvTrans.Set( pCrv2->Clone()) ; - if ( ! ::IsValid( crvTrans)) + if ( IsNull( crvTrans)) return false ; crvTrans->LocToLoc( frEnt2, frEnt) ; pCrv2 = ::Get( crvTrans) ; @@ -4888,7 +4892,7 @@ GdbExecutor::CurveCopyByParamRange( const STRVECTOR& vsParams) return false ; // copio la parte di curva che interessa e la porto nel riferimento del gruppo destinazione PtrOwner pCopy( pCrv->CopyParamRange( dUStart, dUEnd)) ; - if ( ! ::IsValid( pCopy)) + if ( IsNull( pCopy)) return false ; pCopy->LocToLoc( frCrv, frDest) ; // la inserisco nel gruppo @@ -4926,7 +4930,7 @@ GdbExecutor::CurveCopyBySplitClass( const STRVECTOR& vsParams) PtrOwner crvTrans ; if ( ! AreSameFrame( frCrv, frCloCrv)) { crvTrans.Set( pCloCrv->Clone()) ; - if ( ! ::IsValid( crvTrans)) + if ( IsNull( crvTrans)) return false ; crvTrans->LocToLoc( frCloCrv, frCrv) ; pCloCrv = ::Get( crvTrans) ; @@ -4965,7 +4969,7 @@ GdbExecutor::CurveCopyBySplitClass( const STRVECTOR& vsParams) continue ; // copio la parte di curva che interessa e la porto nel riferimento del gruppo PtrOwner pSplit( pCrv->CopyParamRange( ccClass[i].dParS, ccClass[i].dParE)) ; - if ( ! ::IsValid( pSplit)) + if ( IsNull( pSplit)) continue ; pSplit->LocToLoc( frCrv, frGrp[nGrp]) ; // la inserisco nel gruppo @@ -5033,7 +5037,7 @@ GdbExecutor::CurveCopyByChain( const STRVECTOR& vsParams) while ( chainC.GetChainFromNear( ptNearStart, vIds)) { // creo una curva composita PtrOwner pCrvCompo( CreateCurveComposite()) ; - if ( ! IsValid( pCrvCompo)) + if ( IsNull( pCrvCompo)) return false ; // recupero le curve semplici e le inserisco nella curva composita INTVECTOR::iterator Iter ; @@ -5049,7 +5053,7 @@ GdbExecutor::CurveCopyByChain( const STRVECTOR& vsParams) return false ; // copio la curva PtrOwner pCopCrv( pCrv->Clone()) ; - if ( ! IsValid( pCopCrv)) + if ( IsNull( pCopCrv)) return false ; // se necessario, la inverto if ( bInvert) @@ -5186,7 +5190,7 @@ GdbExecutor::ExecuteOutTextIcci( const string& sCmd2, const STRVECTOR& vsParams) PtrOwner crvTrans ; if ( ! AreSameFrame( frEnt1, frEnt2)) { crvTrans.Set( pCrv2->Clone()) ; - if ( ! ::IsValid( crvTrans)) + if ( IsNull( crvTrans)) return false ; crvTrans->LocToLoc( frEnt2, frEnt1) ; pCrv2 = ::Get( crvTrans) ; @@ -5255,7 +5259,7 @@ GdbExecutor::ExecuteOutTextIcci( const string& sCmd2, const STRVECTOR& vsParams) return false ; // creo il testo PtrOwner pTXT( CreateExtText()) ; - if ( ! IsValid( pTXT)) + if ( IsNull( pTXT)) return false ; // lo riempio if ( ! pTXT->Set( sText, ptText, 0, dH)) diff --git a/GeomDB.cpp b/GeomDB.cpp index e77b98c..244d272 100644 --- a/GeomDB.cpp +++ b/GeomDB.cpp @@ -412,7 +412,7 @@ GeomDB::InsertGeoObj( int nId, int nRefId, int nSonBeforeAfter, IGeoObj* pGeoObj if ( ExistsObj( nId)) return GDB_ID_NULL ; // verifico validità oggetto Geo - if ( ! IsValid( pRPGeoObj) || ! pRPGeoObj->IsValid()) + if ( IsNull( pRPGeoObj) || ! pRPGeoObj->IsValid()) return GDB_ID_NULL ; // alloco oggetto Gdb GdbGeo* pGdbGeo = new(nothrow) GdbGeo ; @@ -676,7 +676,7 @@ GeomDB::Copy( int nIdSou, int nIdDest, int nRefId, int nSonBeforeAfter, bool bGl // eseguo la copia PtrOwner pGdODest( pGdOSou->Clone( nIdDest, m_IdManager)) ; - if ( ! ::IsValid( pGdODest)) + if ( IsNull( pGdODest)) return GDB_ID_NULL ; // se in globale diff --git a/IntersCurveCurve.cpp b/IntersCurveCurve.cpp index d4da256..2e8a41d 100644 --- a/IntersCurveCurve.cpp +++ b/IntersCurveCurve.cpp @@ -269,7 +269,7 @@ IntersCurveCurve::GetIntersPointNearTo( int nCrv, const Point3d& ptNear, Point3d swap( dUStartTrim, dUEndTrim) ; } PtrOwner pCrv( m_pCurve[nCrv]->CopyParamRange( dUStartTrim, dUEndTrim)) ; - if ( ! ::IsValid( pCrv)) + if ( IsNull( pCrv)) continue ; // cerco il punto int nFlag ; diff --git a/LinePntTgCurve.cpp b/LinePntTgCurve.cpp index b7d4e04..118ff48 100644 --- a/LinePntTgCurve.cpp +++ b/LinePntTgCurve.cpp @@ -92,7 +92,7 @@ GetLinePointTgArc( const Point3d& ptP, const ICurveArc& crvArc, const Point3d& p // creo la linea PtrOwner pCrvLine( CreateCurveLine()) ; - if ( ! IsValid( pCrvLine)) + if ( IsNull( pCrvLine)) return nullptr ; // costruisco la linea corrispondente alla soluzione scelta diff --git a/LineTgTwoArcs.cpp b/LineTgTwoArcs.cpp index 85784da..6ce8724 100644 --- a/LineTgTwoArcs.cpp +++ b/LineTgTwoArcs.cpp @@ -86,7 +86,7 @@ GetLineTgTwoArcs( const ICurveArc& crvArc1, const Point3d& ptNear1, // creo la linea PtrOwner pCrvLine( CreateCurveLine()) ; - if ( ! IsValid( pCrvLine)) + if ( IsNull( pCrvLine)) return nullptr ; // costruisco la linea corrispondente alla soluzione scelta diff --git a/PolyArc.cpp b/PolyArc.cpp index 3f61b01..545c295 100644 --- a/PolyArc.cpp +++ b/PolyArc.cpp @@ -246,8 +246,20 @@ PolyArc::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) //---------------------------------------------------------------------------- bool -PolyArc::Splice( PolyArc& PA) +PolyArc::Join( PolyArc& PA, double dOffsetPar) { + // se l'altro poliarco non contiene alcunchè, esco con ok + if ( PA.m_nCount == 0) + return true ; + // verifico che l'ultimo punto di questo poliarco coincida con il primo dell'altro + if ( m_nCount > 0 && ! AreSamePointApprox( m_lUPointBs.back().ptP, PA.m_lUPointBs.front().ptP)) + return false ; + // cancello l'ultimo di questo + EraseLastUPoint() ; + // aggiungo eventuale offset all'altro + if ( fabs( dOffsetPar) > EPS_PARAM) + PA.AddOffsetToU( dOffsetPar) ; + // sposto i punti dall'altra polilinea a questa e aggiorno i contatori m_lUPointBs.splice( m_lUPointBs.end(), PA.m_lUPointBs) ; m_nCount += PA.GetPointNbr() ; PA.m_nCount = 0 ; @@ -255,6 +267,32 @@ PolyArc::Splice( PolyArc& PA) return true ; } +//---------------------------------------------------------------------------- +bool +PolyArc::Split( double dU, PolyArc& PA) +{ + // pulisco la polilinea destinazione + PA.Clear() ; + // ricerca del punto in cui dividere + UPNTBLIST::const_iterator iter ; + iter = m_lUPointBs.begin() ; + while ( iter != m_lUPointBs.end() && iter->dU < ( dU + EPS_PARAM)) + ++ iter ; + if ( iter == m_lUPointBs.end()) + return false ; + // sposto i punti nell'altra polilinea + PA.m_lUPointBs.splice( PA.m_lUPointBs.end(), m_lUPointBs, iter, m_lUPointBs.end()) ; + PA.m_nCount = int( PA.m_lUPointBs.size()) ; + m_nCount -= PA.m_nCount ; + // prepongo l'ultimo punto rimasto + PA.m_lUPointBs.push_front( m_lUPointBs.back()) ; + ++ PA.m_nCount ; + // annullo l'iteratore corrente + m_iter = m_lUPointBs.end() ; + + return true ; +} + //---------------------------------------------------------------------------- bool PolyArc::GetFirstUPoint( double* pdPar, Point3d* pptP, double* pdBulge, bool bNotLast) const diff --git a/PolyLine.cpp b/PolyLine.cpp index 66a053a..c77b0e2 100644 --- a/PolyLine.cpp +++ b/PolyLine.cpp @@ -207,8 +207,20 @@ PolyLine::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) //---------------------------------------------------------------------------- bool -PolyLine::Splice( PolyLine& PL) +PolyLine::Join( PolyLine& PL, double dOffsetPar) { + // se l'altra polilinea non contiene alcunchè, esco con ok + if ( PL.m_nCount == 0) + return true ; + // verifico che l'ultimo punto di questa polilinea coincida con il primo dell'altra + if ( m_nCount > 0 && ! AreSamePointApprox( m_lUPoints.back().second, PL.m_lUPoints.front().second)) + return false ; + // cancello l'ultimo di questa + EraseLastUPoint() ; + // aggiungo eventuale offset all'altra + if ( fabs( dOffsetPar) > EPS_PARAM) + PL.AddOffsetToU( dOffsetPar) ; + // sposto i punti dall'altra polilinea a questa e aggiorno i contatori m_lUPoints.splice( m_lUPoints.end(), PL.m_lUPoints) ; m_nCount += PL.GetPointNbr() ; PL.m_nCount = 0 ; @@ -216,6 +228,32 @@ PolyLine::Splice( PolyLine& PL) return true ; } +//---------------------------------------------------------------------------- +bool +PolyLine::Split( double dU, PolyLine& PL) +{ + // pulisco la polilinea destinazione + PL.Clear() ; + // ricerca del punto in cui dividere + UPNTLIST::const_iterator iter ; + iter = m_lUPoints.begin() ; + while ( iter != m_lUPoints.end() && iter->first < ( dU + EPS_PARAM)) + ++ iter ; + if ( iter == m_lUPoints.end()) + return false ; + // sposto i punti nell'altra polilinea + PL.m_lUPoints.splice( PL.m_lUPoints.end(), m_lUPoints, iter, m_lUPoints.end()) ; + PL.m_nCount = int( PL.m_lUPoints.size()) ; + m_nCount -= PL.m_nCount ; + // prepongo l'ultimo punto rimasto + PL.m_lUPoints.push_front( m_lUPoints.back()) ; + ++ PL.m_nCount ; + // annullo l'iteratore corrente + m_iter = m_lUPoints.end() ; + + return true ; +} + //---------------------------------------------------------------------------- bool PolyLine::IsClosed( void) const