From 20abde05a6ef4f626fbdcebd72bd41fbb43c43f0 Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Mon, 12 Oct 2020 09:47:46 +0000 Subject: [PATCH] EgtGeomKernel 2.2j2 : - nella CurveComposite::MergeTwoCurves vengono eliminate le curve molto corte (minori di 10 volte la tolleranza lineare) - nell'offset avanzato migliorata gestione angoli interni per curve molto corte. --- CurveComposite.cpp | 177 ++++++++++++++++++++++++++------------------- CurveComposite.h | 1 - EgtGeomKernel.rc | Bin 11718 -> 11718 bytes OffsetCurve.cpp | 62 ++++++++++++---- 4 files changed, 151 insertions(+), 89 deletions(-) diff --git a/CurveComposite.cpp b/CurveComposite.cpp index 544ab31..21b9b2c 100644 --- a/CurveComposite.cpp +++ b/CurveComposite.cpp @@ -2622,54 +2622,34 @@ CurveComposite::ArcsBezierCurvesToArcsPerpExtr( double dLinTol, double dAngTolDe } //---------------------------------------------------------------------------- -bool -CurveComposite::MergeCurves( double dLinTol, double dAngTolDeg, bool bStartEnd, bool bNeedSameProp) +static int +MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dCosAngTol, bool bNeedSameProp) { - // se non ci sono almeno 2 curve, esco subito - if ( m_CrvSmplS.size() < 2) - return true ; - // controllo sui limiti di tolleranza - dLinTol = max( dLinTol, EPS_SMALL) ; - dAngTolDeg = max( dAngTolDeg, EPS_ANG_SMALL) ; - // tolleranza lineare corrente - double dCurrLinTol = dLinTol ; - // devo verificare coppie di curve - auto iterP = m_CrvSmplS.begin() ; - auto iterC = next( iterP) ; - // mentre esiste la coppia - while ( iterC != m_CrvSmplS.end()) { - // se curve unite - if ( MergeTwoCurves( *iterP, *iterC, dCurrLinTol, dAngTolDeg, bNeedSameProp)) { - // cancello l'entità precedente e la tolgo dalla lista - delete (*iterP) ; - iterC = m_CrvSmplS.erase( iterP) ; - } - // altrimenti ripristino la tolleranza - else - dCurrLinTol = dLinTol ; - // avanzo - iterP = iterC ; - iterC = next( iterC) ; - } - // se richiesto e curva chiusa devo confrontare anche ultima e prima curva - if ( bStartEnd && IsClosed()) { - if ( MergeTwoCurves( *iterP, *(m_CrvSmplS.begin()), dCurrLinTol, dAngTolDeg, bNeedSameProp)) { - // cancello l'entità precedente e la tolgo dalla lista - delete (*iterP) ; - iterC = m_CrvSmplS.erase( iterP) ; + // se precedente molto corta + double dLenP ; + if ( pCrvP->GetLength( dLenP) && dLenP < dCurrLinTol) { + // se abbastanza allineata alla successiva + Vector3d vtDirP, vtDirC ; + if ( pCrvP->GetEndDir( vtDirP) && pCrvC->GetStartDir( vtDirC) && ( vtDirP * vtDirC) >= dCosAngTol) { + Point3d ptStart ; + return ( pCrvP->GetStartPoint( ptStart) && pCrvC->ModifyStart( ptStart) ? -1 : 0) ; } } - - // imposto ricalcolo della grafica - m_OGrMgr.Reset() ; - - return true ; -} - -//---------------------------------------------------------------------------- -bool -CurveComposite::MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dAngTolDeg, bool bNeedSameProp) -{ + // se corrente molto corta + double dLenC ; + if ( pCrvC->GetLength( dLenC) && dLenC < dCurrLinTol) { + // se abbastanza allineata alla precedente + Vector3d vtDirP, vtDirC ; + if ( pCrvP->GetEndDir( vtDirP) && pCrvC->GetStartDir( vtDirC) && ( vtDirP * vtDirC) >= dCosAngTol) { + Point3d ptEnd ; + return ( pCrvC->GetEndPoint( ptEnd) && pCrvP->ModifyEnd( ptEnd) ? 1 : 0) ; + } + } + // verifico compatibilità delle proprietà + int nTprP = pCrvP->GetTempProp() ; + int nTprC = pCrvC->GetTempProp() ; + if ( bNeedSameProp && nTprP != nTprC) + return 0 ; // coefficiente deduzione tolleranza const double COEFF_TOL = 0.7 ; // se entrambe rette @@ -2680,26 +2660,20 @@ CurveComposite::MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTo Vector3d vtDirP, vtDirC ; if ( pLineP != nullptr && pLineP->GetStartDir( vtDirP) && pLineC != nullptr && pLineC->GetStartDir( vtDirC) && - ( vtDirP * vtDirC) >= cos( dAngTolDeg * DEGTORAD)) { - // recupero le proprietà - int nTprP = pLineP->GetTempProp() ; - int nTprC = pLineC->GetTempProp() ; + ( vtDirP * vtDirC) >= dCosAngTol) { // verifico se il punto di giunzione sia eliminabile DistPointLine dPL( pLineP->GetEnd(), pLineP->GetStart(), pLineC->GetEnd()) ; double dSqDist ; - if ( dPL.GetSqDist( dSqDist) && dSqDist < dCurrLinTol * dCurrLinTol && - ( ! bNeedSameProp || nTprP == nTprC)) { - // se calcolo nuova linea ok, procedo con l'unione - CurveLine NewLine ; - if ( NewLine.Set( pLineP->GetStart(), pLineC->GetEnd())) { + if ( dPL.GetSqDist( dSqDist) && dSqDist < dCurrLinTol * dCurrLinTol) { + // se modifica linea corrente ok, procedo con l'unione + if ( pLineC->ModifyStart( pLineP->GetStart())) { // diminuisco la tolleranza corrente dell'errore attuale dCurrLinTol -= COEFF_TOL * sqrt( dSqDist) ; - // se curve originali con la stessa proprietà, la riporto - if ( nTprP == nTprC) - NewLine.SetTempProp( nTprC) ; - // aggiorno la linea corrente e torno flag modifica - *pLineC = NewLine ; - return true ; + // se curve originali con proprietà diversa, la cancello + if ( nTprP != nTprC) + pLineC->SetTempProp( 0) ; + // torno flag modifica + return -1 ; } } } @@ -2714,20 +2688,20 @@ CurveComposite::MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTo Point3d ptC2Ini = pArcC->GetCenter() ; // verifico la coincidenza dei centri if ( ! AreSamePointEpsilon( ptC1Fin, ptC2Ini, dCurrLinTol)) - return false ; + return 0 ; // verifico la coincidenza dei raggi if ( abs( pArcP->GetRadius() - pArcC->GetRadius()) > dCurrLinTol) - return false ; + return 0 ; // verifico la collinearità delle normali (tenendo conto del raggio) if ( ! (( pArcP->GetNormVersor() - pArcC->GetNormVersor()) * pArcP->GetRadius()).IsSmall() && ! (( pArcP->GetNormVersor() + pArcC->GetNormVersor()) * pArcP->GetRadius()).IsSmall()) - return false ; + return 0 ; // verifico la coincidenza del senso di rotazione (verso delle normali e segno angoli al centro) if ( pArcP->GetNormVersor() * pArcC->GetNormVersor() * pArcP->GetAngCenter() * pArcC->GetAngCenter() < 0) - return false ; + return 0 ; // verifico di non superare l'angolo giro al centro if ( abs( pArcP->GetAngCenter() + pArcC->GetAngCenter()) > ANG_FULL + EPS_ANG_SMALL) - return false ; + return 0 ; // se archi piatti if ( pArcP->IsPlane() && pArcC->IsPlane()) { // se calcolo nuovo arco ok, procedo con l'unione @@ -2747,16 +2721,14 @@ CurveComposite::MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTo if ( NewArc.GetNormVersor() * pArcC->GetNormVersor() < 0) NewArc.InvertN() ; // se curve originali con la stessa proprietà, la riporto - int nTprP = pArcP->GetTempProp() ; - int nTprC = pArcC->GetTempProp() ; if ( nTprP == nTprC) NewArc.SetTempProp( nTprC) ; // aggiorno l'arco corrente e torno flag modifica *pArcC = NewArc ; - return true ; + return -1 ; } else - return false ; + return 0 ; } // verifico coincidenza pendenza sulla normale double dN = pArcP->GetNormVersor() * pArcC->GetNormVersor() ; @@ -2772,24 +2744,81 @@ CurveComposite::MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTo CurveArc NewArc ; if ( NewArc.Set2PVN( ptP1, ptP3, vtDir1, pArcC->GetNormVersor())) { // se curve originali con la stessa proprietà, la riporto - int nTprP = pArcP->GetTempProp() ; - int nTprC = pArcC->GetTempProp() ; if ( nTprP == nTprC) NewArc.SetTempProp( nTprC) ; // aggiorno l'arco corrente e torno flag modifica *pArcC = NewArc ; - return true ; + return -1 ; } else - return false ; + return 0 ; } } + // nessuna fusione - return false ; + return 0 ; } //---------------------------------------------------------------------------- bool +CurveComposite::MergeCurves( double dLinTol, double dAngTolDeg, bool bStartEnd, bool bNeedSameProp) +{ + // se non ci sono almeno 2 curve, esco subito + if ( m_CrvSmplS.size() < 2) + return true ; + // controllo sui limiti di tolleranza + dLinTol = max( dLinTol, EPS_SMALL) ; + dAngTolDeg = max( dAngTolDeg, EPS_ANG_SMALL) ; + double dCosAngTol = cos( dAngTolDeg * DEGTORAD) ; + // tolleranza lineare corrente + double dCurrLinTol = dLinTol ; + // devo verificare coppie di curve + auto iterP = m_CrvSmplS.begin() ; + auto iterC = next( iterP) ; + // mentre esiste la coppia + while ( iterC != m_CrvSmplS.end()) { + // se curve unite + switch ( MergeTwoCurves( *iterP, *iterC, dCurrLinTol, dCosAngTol, bNeedSameProp)) { + case -1 : // cancello l'entità precedente e la tolgo dalla lista + delete (*iterP) ; + iterC = m_CrvSmplS.erase( iterP) ; + break ; + case 1 : // cancello l'entità corrente e la tolgo dalla lista + delete (*iterC) ; + iterC = m_CrvSmplS.erase( iterC) ; + iterC = prev( iterC) ; + break ; + default : // ripristino la tolleranza + dCurrLinTol = dLinTol ; + break ; + } + // avanzo + iterP = iterC ; + iterC = next( iterC) ; + } + // se richiesto e curva chiusa devo confrontare anche ultima e prima curva + if ( bStartEnd && m_CrvSmplS.size() >= 2 && IsClosed()) { + iterC = m_CrvSmplS.begin() ; + switch ( MergeTwoCurves( *iterP, *iterC, dCurrLinTol, dCosAngTol, bNeedSameProp)) { + case -1 : // cancello l'entità precedente e la tolgo dalla lista + delete (*iterP) ; + m_CrvSmplS.erase( iterP) ; + break ; + case 1 : // cancello l'entità corrente e la tolgo dalla lista + delete (*iterC) ; + m_CrvSmplS.erase( iterC) ; + break ; + } + } + + // imposto ricalcolo della grafica + m_OGrMgr.Reset() ; + + return true ; +} + +//---------------------------------------------------------------------------- +static bool SplitTopBottomArcs( CurveComposite& cCompo) { int i = 0 ; diff --git a/CurveComposite.h b/CurveComposite.h index 4cb240c..9cc7acb 100644 --- a/CurveComposite.h +++ b/CurveComposite.h @@ -181,7 +181,6 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW bool AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart = true, double dLinTol = EPS_SMALL) ; bool GetIndSCurveAndLocPar( double dU, Side nS, int& nSCrv, double& dLocU) const ; bool SimpleOffsetXY( double dDist, int nType = OFF_FILLET) ; - bool MergeTwoCurves( ICurve* pCrvP, ICurve* pCrvC, double& dCurrLinTol, double dAngTolDeg, bool bNeedSameProp) ; bool IsOneCircle( Point3d& ptCen, Vector3d& vtN, double& dRad, bool& bCCW) const ; private : diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 775aa5beb62547ba8d262690640203471532e818..1445527e677e6f79b52f27d637d1c32844388173 100644 GIT binary patch delta 110 zcmX>WeJpyzA2vp#&G-4vGfl1&(wY2&Q;pGRvZAo=W*@FeEMOU1X1ItOWeJpyzA2vqA&G-4vGfl1&(wY2&Q;pGZvZAo=W*@FeEMOU1X1ItOGetEndPoint( ptP1) || ! pCrv2->GetStartPoint( ptP2)) return false ; // verifica distanza tra estremi - if ( ! AreSamePointXYEpsilon( ptP1, ptP2, 10 * EPS_SMALL)) - return false ; - // se coincidono esattamente, va bene così - if ( AreSamePointExact( ptP1, ptP2)) + if ( ! AreSamePointXYEpsilon( ptP1, ptP2, 10 * EPS_SMALL)) { + nRes = 4 ; return true ; + } + // se coincidono esattamente, va bene così + if ( AreSamePointExact( ptP1, ptP2)) { + nRes = 0 ; + return true ; + } // sono in tolleranza, ma devo ricongiungere gli estremi + nRes = 0 ; Point3d ptMid = 0.5 * ( ptP1 + ptP2) ; - return ( pCrv1->ModifyEnd( ptMid) && pCrv2->ModifyStart( ptMid)) ; + if ( ! pCrv1->ModifyEnd( ptMid)) + nRes += 1 ; + if ( ! pCrv2->ModifyStart( ptMid)) + nRes += 2 ; + return true ; } //---------------------------------------------------------------------------- bool -VerifyAndAdjustInternalAngle( ICurve* pCrv1, ICurve* pCrv2) +VerifyAndAdjustInternalAngle( ICurve* pCrv1, ICurve* pCrv2, int& nRes) { // verifica dei puntatori if ( pCrv1 == nullptr || pCrv2 == nullptr) @@ -785,8 +814,13 @@ VerifyAndAdjustInternalAngle( ICurve* pCrv1, ICurve* pCrv2) ! intCC.GetIntersPointNearTo( 1, ptMid, ptNew2)) return false ; // modifico le due curve sul punto medio di intersezione + nRes = 0 ; Point3d ptNew = 0.5 * ( ptNew1 + ptNew2) ; - return ( pCrv1->ModifyEnd( ptNew) && pCrv2->ModifyStart( ptNew)) ; + if ( ! pCrv1->ModifyEnd( ptNew)) + nRes += 1 ; + if ( ! pCrv2->ModifyStart( ptNew)) + nRes += 2 ; + return true ; } //----------------------------------------------------------------------------