From 964647d7e6b15162f8297cfb93776ee139c8e4ff Mon Sep 17 00:00:00 2001 From: SaraP Date: Fri, 30 Aug 2024 14:49:47 +0200 Subject: [PATCH] =?UTF-8?q?EgtGeomKernel=202.6h3=20:=20-=20estensione=20de?= =?UTF-8?q?l=20calcolo=20degli=20offset=20con=20Voronoi=20al=20caso=20di?= =?UTF-8?q?=20pi=C3=B9=20curve=20scollegate=20tra=20loro.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- EgtGeomKernel.rc | Bin 11710 -> 11710 bytes Voronoi.cpp | 306 ++++++++++++++++------------------------------- Voronoi.h | 10 +- 3 files changed, 106 insertions(+), 210 deletions(-) diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index c8ab857bb15506675dc10edef317bcd3e4d4293f..8ddb8912ca78c2a598b70c9d74bba23ed84dcfe8 100644 GIT binary patch delta 238 zcmdlNy)SyhI%aiGhCGIJh8%`ehGHOAV9;O)W+-7u1ma8}FBB-731Uy?R&U)L$1;bB z(RlN3HbrJec1_cHUhESkLCPN8BDnkm89}HwAf_cT0PijeT z{=m$}%xJXvyqqG4`lwjSxVewp10r;uY4S3`JfN_k6i~QJ7*lvJ3$os9QmsEYnTvVZ lClone()) ; } - bool bClosed = m_vpCrvs[0]->IsClosed() ; - // calcolo offset ICRVCOMPOPLIST OffsList ; if ( ! CalcVroniOffset( OffsList, abs( dOffs))) @@ -614,39 +608,34 @@ Voronoi::CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType) // sistemo le curve di offset calcolate con vroni for ( auto pCrv : OffsList) { - // seleziono le curve di offset corrette in base al segno dell'offset - if ( bClosed) - AdjustClosedOffsetCurve( *pCrv, dOffs) ; - else - AdjustOpenOffsetCurve( *pCrv, dOffs) ; - - if ( pCrv->IsValid()) { - // eventuale inversione - if ( dOffs > EPS_SMALL) - pCrv->Invert() ; - - // sistemo i raccordi - if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0) { - IdentifyFillets( pCrv, dOffs) ; - AdjustCurveFillets( pCrv, dOffs, nType) ; - } + // seleziono le porzioni dell'offset che si trovano dal lato richiesto + ICRVCOMPOPOVECTOR vResult = AdjustOffsetCurves( pCrv, dOffs) ; + + for ( int i = 0 ; i < int( vResult.size()) ; ++ i) { - if ( bClosed) { - // forzo chiusura della curva per evitare piccole imprecisioni - pCrv->Close() ; - // sistemo il punto di inizio - AdjustOffsetStart( *pCrv) ; - } - - // porto nel frame globale - pCrv->ToGlob( m_Frame) ; - // unisco le parti allineate - pCrv->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG, true, true) ; - // aggiungo al vettore finale - vOffs.emplace_back( pCrv) ; + // eventuale inversione + if ( dOffs > EPS_SMALL) + vResult[i]->Invert() ; + + // sistemo il punto di inizio + if ( vResult[i]->IsClosed()) + AdjustOffsetStart( vResult[i]) ; + + // sistemo i raccordi + if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0) { + IdentifyFillets( vResult[i], dOffs) ; + AdjustCurveFillets( vResult[i], dOffs, nType) ; + } + + // porto nel frame globale + vResult[i]->ToGlob( m_Frame) ; + // unisco le parti allineate + vResult[i]->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG, true, true) ; + // aggiungo al vettore finale + vOffs.emplace_back( Release( vResult[i])) ; } - else - delete pCrv ; + // dealloco curva + delete( pCrv) ; } return true ; @@ -717,14 +706,6 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs) if ( ! IsValid()) return false ; - int nOrigCrvCnt = 1 ; - if ( m_vpCrvs[0]->GetType() == CRV_COMPO) { - const CurveComposite * pOrigCompo = GetBasicCurveComposite( m_vpCrvs[0]) ; - if ( pOrigCompo == nullptr) - return false ; - nOrigCrvCnt = pOrigCompo->GetCurveCount() ; - } - try { // reset di eventuali offset precedenti m_vroni->apiResetOffsetData() ; @@ -772,9 +753,17 @@ Voronoi::CalcVroniOffset( ICRVCOMPOPLIST& OffsList, double dOffs) int nCurrCrvId = pCrvOffs->GetCurveCount() - 1 ; pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigCrv + 1, 0) ; pCrvOffs->SetCurveTempProp( nCurrCrvId, nOrigLoop, 1) ; - // verifico se è raccordo relativo agli estremi della curva - if ( nOrigCrv == -1 && ( nOrigPnt == 0 || nOrigPnt == nOrigCrvCnt)) - pCrvOffs->SetCurveTempParam( nCurrCrvId, 1.0, 0) ; + // verifico se è una giunzione, ovvero un raccordo relativo agli estremi di una curva ( con distinzione fra curva + // aperta e chiusa) + if ( nOrigCrv == -1) { + int nOrigCrvCnt = 1 ; + if ( m_vpCrvs[nOrigLoop]->GetType() == CRV_COMPO) + nOrigCrvCnt = GetBasicCurveComposite( m_vpCrvs[nOrigLoop])->GetCurveCount() ; + if ( nOrigPnt == 0 || nOrigPnt == nOrigCrvCnt) { + double dParam = m_vpCrvs[nOrigLoop]->IsClosed() ? VRONI_JUNCTION_CLOSED : VRONI_JUNCTION_OPEN ; + pCrvOffs->SetCurveTempParam( nCurrCrvId, dParam, 0) ; + } + } } } @@ -814,169 +803,76 @@ Voronoi::UpdateVoronoi( double dOffs) } //---------------------------------------------------------------------------- -bool -Voronoi::VerifyCurvesValidityForOffset() -{ - if ( m_vpCrvs.size() == 1) - return true ; - - // se ho più curve, devono essere tutte chiuse - for ( auto pCrv : m_vpCrvs) { - if ( ! pCrv->IsClosed()) - return false ; - } - - // verifico se gli orientamenti delle curve sono coerenti - DBLVECTOR vArea( m_vpCrvs.size()) ; - double dRefArea = 0.0 ; - for ( int i = 0 ; i < ( int)m_vpCrvs.size() ; i ++) { - m_vpCrvs[i]->GetAreaXY( vArea[i]) ; - if ( abs( vArea[i]) > abs( dRefArea)) - dRefArea = vArea[i] ; - } - bool bRefCCW = ( dRefArea > EPS_SMALL) ; - - for ( int i = 0 ; i < ( int)vArea.size() ; i++) { - - // se curva con orientamento principale verifico sia esterna a tutte le altre curve con orientamento principale - if ( vArea[i] * dRefArea > EPS_SMALL) { - for ( int j = 0 ; j < ( int)vArea.size() ; j++) { - if ( j != i && vArea[i] * vArea[j] > EPS_SMALL) { - IntersCurveCurve ccInt( *m_vpCrvs[i], *m_vpCrvs[j]) ; - int nRes = ccInt.GetRegionCurveClassification() ; - if ( nRes == CCREGC_NULL || nRes == CCREGC_SAME || nRes == CCREGC_INTERS) - return false ; - if ( ( bRefCCW && nRes == CCREGC_IN1) || ( ! bRefCCW && nRes == CCREGC_IN2)) { - // se è interna ad una curva con orientamento principale, verifico sia esterna ad almeno una curva con orientamento - // diverso dal principale - bool bFound = false ; - for ( int k = 0 ; k < ( int)vArea.size() ; k++) { - if ( k != i && vArea[i] * vArea[k] < EPS_SMALL) { - IntersCurveCurve ccInt( *m_vpCrvs[i], *m_vpCrvs[k]) ; - int nRes = ccInt.GetRegionCurveClassification() ; - if ( ( bRefCCW && nRes == CCREGC_OUT) || ( ! bRefCCW && nRes == CCREGC_IN1)) { - bFound = true ; - break ; - } - } - } - if ( ! bFound) - return false ; - } - } - } - } - - // se curva con orientamento diverso dal principale verifico sia contenuta in una curva con orientamento principale - else if ( vArea[i] * dRefArea < - EPS_SMALL) { - bool bInside = false ; - for ( int j = 0 ; j < ( int)vArea.size() ; j++) { - if ( j != i && vArea[j] * dRefArea > EPS_SMALL) { - IntersCurveCurve ccInt( *m_vpCrvs[i], *m_vpCrvs[j]) ; - int nRes = ccInt.GetRegionCurveClassification() ; - if ( ( bRefCCW && nRes == CCREGC_IN1) || ( ! bRefCCW && nRes == CCREGC_OUT)) { - bInside = true ; - break ; - } - } - } - if ( ! bInside) - return false ; - } - } - - return true ; -} - -//---------------------------------------------------------------------------- -bool -Voronoi::AdjustClosedOffsetCurve( ICurveComposite& pCompo, double dOffs) -{ - int nSideRef = dOffs < EPS_SMALL ? MDS_LEFT : MDS_RIGHT ; - int nSide = GetOffsetCurveSide( pCompo, 0) ; - if ( nSide != nSideRef) - // se lato errato, tutta la curva va cancellata - pCompo.Clear() ; - - return true ; -} - -//---------------------------------------------------------------------------- -bool -Voronoi::AdjustOpenOffsetCurve( ICurveComposite& pCompo, double dOffs) +ICRVCOMPOPOVECTOR +Voronoi::AdjustOffsetCurves( const ICurveComposite* pCompo, double dOffs) const { + ICRVCOMPOPOVECTOR vResult ; int nSideRef = dOffs < EPS_SMALL ? MDS_LEFT : MDS_RIGHT ; - // recupero i raccordi relativi agli estremi della curva aperta - INTVECTOR vJunctions ; - for ( int i = 0 ; i < pCompo.GetCurveCount() ; i++) { - double dParTmp ; - pCompo.GetCurveTempParam( i, dParTmp) ; - if ( dParTmp > EPS_SMALL) - vJunctions.push_back( i) ; + // verifico se presenti giunzioni + bool bJunctions = false ; + for ( int i = 0 ; i < pCompo->GetCurveCount() ; i ++) { + double dParam ; pCompo->GetCurveTempParam( i, dParam) ; + if ( abs( dParam - VRONI_JUNCTION_OPEN) < EPS_SMALL) { + bJunctions = true ; + break ; + } } - if ( vJunctions.size() == 0) { - // verifico se si trova dal lato corretto + if ( ! bJunctions) { + // controllo la curva complessiva int nSide = GetOffsetCurveSide( pCompo, 0) ; - if ( nSide != nSideRef) - // se lato errato, tutta la curva va cancellata - pCompo.Clear() ; + if ( nSide == nSideRef) + vResult.emplace_back( pCompo->Clone()) ; } - else if ( vJunctions.size() == 2) { - // recupero i due tratti di curva - PtrOwner pCompo1( ConvertCurveToBasicComposite( pCompo.CopyParamRange( vJunctions[0] + 1, vJunctions[1]))) ; - PtrOwner pCompo2( ConvertCurveToBasicComposite( pCompo.CopyParamRange( vJunctions[1] + 1, vJunctions[0]))) ; - pCompo.Clear() ; - if ( ! IsNull( pCompo1) && pCompo1->IsValid()) { - int nSide = GetOffsetCurveSide( *pCompo1, 0) ; - if ( nSide == nSideRef) - pCompo.CopyFrom( pCompo1) ; - else if ( ! IsNull( pCompo2) && pCompo2->IsValid()) - pCompo.CopyFrom( pCompo2) ; - } - else if ( ! IsNull( pCompo2) && pCompo2->IsValid()) { - int nSide = GetOffsetCurveSide( *pCompo2, 0) ; - if ( nSide == nSideRef) - pCompo.CopyFrom( pCompo2) ; - } - } - else { - // mi posiziono dopo la junction - pCompo.ChangeStartPoint( vJunctions[0] + 1) ; - delete( pCompo.RemoveFirstOrLastCurve()) ; - // verifico validità della curva - int nSide = GetOffsetCurveSide( pCompo, 0) ; - if ( nSide == nSideRef) { - // scorro fino alla prima curva non valida ed elimino la curva da quel punto fino alla fine - for ( int i = 1 ; i < pCompo.GetCurveCount() ; i++) { + else { + // scorro la curva eliminando le giunzioni relative a curve aperte e le sottocurve che si trovano dal lato sbagliato + PtrOwner pCompoCurr( CreateBasicCurveComposite()) ; + for ( int i = 0 ; i < pCompo->GetCurveCount() ; i ++) { + bool bKeep = true ; + double dParTmp ; pCompo->GetCurveTempParam( i, dParTmp) ; + if ( abs( dParTmp - VRONI_JUNCTION_OPEN) < EPS_SMALL) + bKeep = false ; + else { int nSide = GetOffsetCurveSide( pCompo, i) ; - if ( nSide != nSideRef) - pCompo.TrimEndAtParam( i) ; - } - } - else { - // elimino finchè non trovo una curva valida - while( nSide != nSideRef && pCompo.IsValid()) { - delete( pCompo.RemoveFirstOrLastCurve( false)) ; - if ( pCompo.IsValid()) - nSide = GetOffsetCurveSide( pCompo, 0) ; - } - } - } + bKeep = ( nSide == nSideRef) ; + } - return true ; + if ( bKeep) + pCompoCurr->AddCurve( pCompo->GetCurve( i)->Clone()) ; + else { + // salvo la curva ottenuta fino ad ora e resetto per i prossimi tratti validi + if ( pCompoCurr->IsValid()) { + vResult.emplace_back( Release( pCompoCurr)) ; + pCompoCurr.Set( CreateBasicCurveComposite()) ; + } + } + } + // salvo eventuale ultima curva + if ( pCompoCurr->IsValid()) + vResult.emplace_back( Release( pCompoCurr)) ; + + // verifico se posso concatenare prima e ultima curva + if ( vResult.size() > 1) { + Point3d ptStart ; vResult.front()->GetStartPoint( ptStart) ; + Point3d ptEnd ; vResult.back()->GetEndPoint( ptEnd) ; + if ( AreSamePointApprox( ptStart, ptEnd) && vResult.front()->AddCurve( vResult.back()->Clone(), false)) + vResult.pop_back() ; + } + } + + return vResult ; } //--------------------------------------------------------------------------- int -Voronoi::GetOffsetCurveSide( const ICurveComposite& pOffs, int nCrv) +Voronoi::GetOffsetCurveSide( const ICurveComposite* pOffs, int nCrv) const { - Point3d ptM ; pOffs.GetCurve( nCrv)->GetMidPoint( ptM) ; + Point3d ptM ; pOffs->GetCurve( nCrv)->GetMidPoint( ptM) ; // recupero curva e sottocurva di riferimento - int nOrigSubCrv ; pOffs.GetCurveTempProp( nCrv, nOrigSubCrv) ; - int nOrigCrv ; pOffs.GetCurveTempProp( nCrv, nOrigCrv, 1) ; + int nOrigSubCrv ; pOffs->GetCurveTempProp( nCrv, nOrigSubCrv) ; + int nOrigCrv ; pOffs->GetCurveTempProp( nCrv, nOrigCrv, 1) ; const ICurve* pCrvRef = m_vpCrvs[nOrigCrv] ; if ( nOrigSubCrv != 0 && m_vpCrvs[nOrigCrv]->GetType() == CRV_COMPO) { const CurveComposite* pCompoOrig = GetBasicCurveComposite( m_vpCrvs[nOrigCrv]) ; @@ -992,19 +888,19 @@ Voronoi::GetOffsetCurveSide( const ICurveComposite& pOffs, int nCrv) //--------------------------------------------------------------------------- bool -Voronoi::AdjustOffsetStart( ICurveComposite& pCrv) +Voronoi::AdjustOffsetStart( ICurveComposite* pCrv) const { - for ( int i = 0 ; i < pCrv.GetCurveCount() ; i++) { - // cerco il tratto associato alla prima curva originale - int nProp ; pCrv.GetCurveTempProp( i, nProp) ; - if ( nProp == 1) { - pCrv.ChangeStartPoint( i) ; + for ( int i = 0 ; i < pCrv->GetCurveCount() ; i++) { + // cerco il tratto associato alla prima sottocurva originale + int nOrigCrv ; pCrv->GetCurveTempProp( i, nOrigCrv) ; + if ( nOrigCrv == 1) { + pCrv->ChangeStartPoint( i) ; break ; } - // oppure un raccordo di junction - double dParam ; pCrv.GetCurveTempParam( i, dParam) ; - if ( abs( dParam - 1) < EPS_SMALL) { - pCrv.ChangeStartPoint( i + 1) ; + // oppure associato ad una giunzione + double dParam ; pCrv->GetCurveTempParam( i, dParam) ; + if ( abs( dParam - VRONI_JUNCTION_CLOSED) < EPS_SMALL) { + pCrv->ChangeStartPoint( i + 1) ; break ; } } diff --git a/Voronoi.h b/Voronoi.h index 502cf91..b8876c0 100644 --- a/Voronoi.h +++ b/Voronoi.h @@ -25,6 +25,8 @@ static const bool USE_VORONOI = true ; static const int VORONOI_STD_BOUND = 3 ; static const double VRONI_OFFS_TOL = 1e-9 ; +static const double VRONI_JUNCTION_OPEN = 1.0 ; +static const double VRONI_JUNCTION_CLOSED = 2.0 ; //-------------------------- Forward Definitions ------------------------------- class ISurfFlatRegion ; @@ -77,11 +79,9 @@ class Voronoi bool CalcVoronoi( int nBound = VORONOI_STD_BOUND) ; bool CalcVroniOffset( ICRVCOMPOPLIST& vOffs, double dOffs) ; bool UpdateVoronoi( double dOffs) ; - bool VerifyCurvesValidityForOffset( void) ; - bool AdjustOpenOffsetCurve( ICurveComposite& pCompo, double dOffs) ; - bool AdjustClosedOffsetCurve( ICurveComposite& pCompo, double dOffs) ; - bool AdjustOffsetStart( ICurveComposite& pCompo) ; - int GetOffsetCurveSide( const ICurveComposite& pOffs, int nCrv) ; + ICRVCOMPOPOVECTOR AdjustOffsetCurves( const ICurveComposite* pCompo, double dOffs) const ; + bool AdjustOffsetStart( ICurveComposite* pCompo) const ; + int GetOffsetCurveSide( const ICurveComposite* pOffs, int nCrv) const ; ICurve* GetBisectorCurve( int i) ; private :