diff --git a/OffsetAux.cpp b/OffsetAux.cpp index 9b5c30e..195bdd3 100644 --- a/OffsetAux.cpp +++ b/OffsetAux.cpp @@ -16,9 +16,17 @@ #include "CurveArc.h" #include "CurveLine.h" #include "GeoConst.h" +#include "/EgtDev/Include/EGkIntervals.h" +#include "/EgtDev/Include/EGkIntersCurves.h" +#include "/EgtDev/Include/EGkChainCurves.h" using namespace std ; +//---------------------------------------------------------------------------- +static bool IsFillet( const ICurve* pCrv, double dDist) ; +static bool ModifyFillet( ICurve* pCrv, double dDist, int nType, ICurveComposite& ccAux) ; +static bool AdjustIntersections( ICRVCOMPOPVECTOR& CrvList) ; + //---------------------------------------------------------------------------- bool IdentifyFillets( ICurveComposite* pCrvCo, double dDist) @@ -52,36 +60,76 @@ IsFillet( const ICurve* pCrv, double dDist) //---------------------------------------------------------------------------- bool -AdjustCurveFillets( ICurveComposite* pCrvCo, double dDist, int nType) +AdjustCurveFillets( ICURVEPOVECTOR& vOffset, double dDist, int nType) { - ICURVEPLIST CrvLst ; - PtrOwner pCrv( pCrvCo->RemoveFirstOrLastCurve( false)) ; - while ( ! IsNull( pCrv)) { - // se identificato come fillet lo trasformo in smusso o estensione - if ( pCrv->GetTempParam() > EPS_SMALL) { - CurveComposite ccTemp ; - ModifyFillet( pCrv, dDist, nType, ccTemp) ; - // metto in lista le curve risultanti - if ( ccTemp.GetCurveCount() > 0) { - PtrOwner pCrv2( ccTemp.RemoveFirstOrLastCurve( false)) ; - while ( ! IsNull( pCrv2)) { - CrvLst.push_back( Release( pCrv2)) ; - pCrv2.Set( ccTemp.RemoveFirstOrLastCurve( false)) ; - } + if ( vOffset.empty()) + return true ; + + // suddivido le curve di offset individuando i fillet e isolandoli dagli altri tratti + ICRVCOMPOPVECTOR vCrvs ; + for ( int i = 0 ; i < int( vOffset.size()) ; i ++) { + CurveComposite* pCompo = GetBasicCurveComposite( vOffset[i]) ; + if ( pCompo == nullptr) + return false ; + bool bNewCrv = true ; + PtrOwner pCrv( pCompo->RemoveFirstOrLastCurve(false)) ; + while ( ! IsNull( pCrv)) { + if ( pCrv->GetTempParam() > EPS_SMALL) { + // se fillet calcolo il nuovo raccordo + CurveComposite* ccTemp = CreateBasicCurveComposite() ; + ModifyFillet( pCrv, dDist, nType, *ccTemp) ; + // assegno temp param per identificarlo nei conti successivi + ccTemp->SetTempParam( 1) ; + vCrvs.push_back( ccTemp) ; + bNewCrv = true ; } + else { + // aggiungo la curva + if ( bNewCrv) { + bNewCrv = false ; + CurveComposite* pCompo = ConvertCurveToBasicComposite( Release( pCrv)) ; + if ( pCompo == nullptr) + return false ; + vCrvs.push_back( pCompo) ; + } + else + vCrvs.back()->AddCurve( Release( pCrv)) ; + } + // passo alla curva successiva + pCrv.Set( pCompo->RemoveFirstOrLastCurve( false)) ; } - // altrimenti salvo in lista - else - CrvLst.push_back( Release( pCrv)) ; - // passo alla curva successiva - pCrv.Set( pCrvCo->RemoveFirstOrLastCurve( false)) ; } - // rimetto le curve nella composita - for ( auto pCrv : CrvLst) { - pCrvCo->AddCurve( pCrv) ; + vOffset.clear() ; + + // gestione delle intersezioni + if ( ! AdjustIntersections( vCrvs)) + return false ; + + // concateno i tratti ottenuti + ChainCurves ChainCrv ; + ChainCrv.Init( false, 2 * EPS_SMALL, vCrvs.size()) ; + for ( int i = 0 ; i < int( vCrvs.size()); ++ i) { + Point3d ptS, ptE ; + Vector3d vtS, vtE ; + vCrvs[i]->GetStartPoint( ptS) ; + vCrvs[i]->GetEndPoint( ptE) ; + vCrvs[i]->GetStartDir( vtS) ; + vCrvs[i]->GetEndDir( vtE) ; + ChainCrv.AddCurve( i + 1, ptS, vtS, ptE, vtE) ; + } + // recupero i concatenamenti + Point3d ptRef ; vCrvs[0]->GetStartPoint( ptRef) ; + INTVECTOR vIds ; + while ( ChainCrv.GetChainFromNear( ptRef, false, vIds)) { + PtrOwner pCompo( CreateBasicCurveComposite()) ; + if ( IsNull( pCompo)) + return false ; + for ( auto i : vIds) + pCompo->AddCurve( vCrvs[i-1]) ; + pCompo->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG) ; + pCompo->GetEndPoint( ptRef) ; + vOffset.emplace_back( Release( pCompo)) ; } - // unisco tratti allineati - pCrvCo->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG) ; return true ; } @@ -175,3 +223,79 @@ ModifyFillet( ICurve* pCrv, double dDist, int nType, ICurveComposite& ccAux) } return false ; } + +//---------------------------------------------------------------------------- +bool +AdjustIntersections( ICRVCOMPOPVECTOR& vCrvs) +{ + // sistema le curve nel vettore vCrvs eliminando le parti coinvolte nelle intersezioni + + vector vIntervals( vCrvs.size()) ; + INTVECTOR vFillets ; + for ( int i = 0 ; i < int( vCrvs.size()) ; i ++) { + // salvo i parametri della curva + double dParS, dParE ; + vCrvs[i]->GetDomain( dParS, dParE) ; + vIntervals[i].Set( dParS, dParE) ; + // verifico se raccordo + if ( vCrvs[i]->GetTempParam() > EPS_SMALL) + vFillets.emplace_back( i) ; + } + + // verifico se i raccordi intersecano le altre curve + bool bInters = false ; + for ( int i = 0 ; i < int( vFillets.size()) ; i ++) { + int nIdx = vFillets[i] ; + for ( int j = 0 ; j < int( vCrvs.size()) ; j ++) { + if ( j == nIdx) + continue ; + + IntersCurveCurve intCC( *vCrvs[nIdx], *vCrvs[j]) ; + int nCnt = intCC.GetIntersCount() ; + if ( nCnt > 1) { + // aggiorno gli intervalli della curva sottraendo la parte coinvolta dall'intersezione + for ( int k = 0 ; k < nCnt - 1 ; k = k+2) { + IntCrvCrvInfo iccInfo1, iccInfo2 ; + intCC.GetIntCrvCrvInfo( k, iccInfo1) ; + // verifico non sia intersezione nell'estremo iniziale o sovrapposizione + if ( iccInfo1.IciA[0].dU < EPS_SMALL || iccInfo1.bOverlap) { + k-- ; + continue ; + } + intCC.GetIntCrvCrvInfo( k+1, iccInfo2) ; + + vIntervals[nIdx].Subtract( iccInfo1.IciA[0].dU, iccInfo2.IciA[0].dU) ; + vIntervals[j].Subtract( iccInfo1.IciB[0].dU, iccInfo2.IciB[0].dU) ; + bInters = true ; + } + } + } + } + + if ( ! bInters) + return true ; + + // aggiorno le curve eliminando i tratti coinvolti nelle intersezioni + for ( int i = 0 ; i < int( vIntervals.size()) ; i++) { + if ( vIntervals[i].GetCount() > 1) { + PtrOwner pCompo( CloneBasicCurveComposite( vCrvs[i])) ; + if ( IsNull( pCompo)) + return false ; + double dParS, dParE ; + vIntervals[i].GetFirst( dParS, dParE) ; + vCrvs[i]->TrimStartEndAtParam( dParS, dParE) ; + while ( vIntervals[i].GetNext( dParS, dParE)) { + CurveComposite* pCrv = ConvertCurveToBasicComposite( pCompo->CopyParamRange( dParS, dParE)) ; + if ( pCrv == nullptr) + return false ; + vCrvs.emplace_back( pCrv) ; + } + } + else { + double dParS, dParE ; + vIntervals[i].GetFirst( dParS, dParE) ; + vCrvs[i]->TrimStartEndAtParam( dParS, dParE) ; + } + } + return true ; +} diff --git a/OffsetAux.h b/OffsetAux.h index 488af20..48c205e 100644 --- a/OffsetAux.h +++ b/OffsetAux.h @@ -16,6 +16,4 @@ //---------------------------------------------------------------------------- bool IdentifyFillets( ICurveComposite* pCrvCo, double dDist) ; -bool IsFillet( const ICurve* pCrv, double dDist) ; -bool AdjustCurveFillets( ICurveComposite* pCrvCo, double dDist, int nType) ; -bool ModifyFillet( ICurve* pCrv, double dDist, int nType, ICurveComposite& ccAux) ; +bool AdjustCurveFillets( ICURVEPOVECTOR& vCrvs, double dDist, int nType) ; \ No newline at end of file diff --git a/OffsetCurve.cpp b/OffsetCurve.cpp index b52168a..7e2a50d 100644 --- a/OffsetCurve.cpp +++ b/OffsetCurve.cpp @@ -674,12 +674,20 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType) } // nono passo : se con smusso o estensione, sostituisco i fillet con questi + // NB questa parte non è gestita in modo efficiente perchè dovrebbe essere sempre disabilitata. + // Le funzioni sono state ottimizzate per lavorare con voronoi if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0) { - for ( auto iIter = m_CrvLst.begin() ; iIter != m_CrvLst.end() ; ++ iIter) { - CurveComposite* pCrvCo = GetBasicCurveComposite( *iIter) ; - IdentifyFillets( pCrvCo, dDist) ; - AdjustCurveFillets( pCrvCo, dDist, nType) ; - } + ICURVEPOVECTOR vCrvs ; + vCrvs.reserve( m_CrvLst.size()) ; + for ( auto pCrv : m_CrvLst) { + IdentifyFillets( GetCurveComposite( pCrv), dDist) ; + vCrvs.emplace_back( pCrv) ; + } + if ( ! AdjustCurveFillets( vCrvs, dDist, nType)) + return false ; + m_CrvLst.clear() ; + for ( int j = 0 ; j < int( vCrvs.size()) ; j ++) + m_CrvLst.emplace_back( Release( vCrvs[j])) ; } } diff --git a/Voronoi.cpp b/Voronoi.cpp index 81a304b..8321f49 100644 --- a/Voronoi.cpp +++ b/Voronoi.cpp @@ -625,16 +625,12 @@ Voronoi::CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType) if ( vResult[i]->IsClosed()) AdjustOffsetStart( vResult[i]) ; - // sistemo i raccordi - if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0) { + // identifico 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) ; + vResult[i]->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG, true, true) ; // aggiungo al vettore finale vOffs.emplace_back( Release( vResult[i])) ; } @@ -642,6 +638,17 @@ Voronoi::CalcOffset( ICURVEPOVECTOR& vOffs, double dOffs, int nType) delete( pCrv) ; } + // aggiusto i raccordi + if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0) + if ( ! AdjustCurveFillets( vOffs, dOffs, nType)) { + vOffs.clear() ; + return false ; + } + + // porto nel frame globale + for ( int i = 0 ; i < int( vOffs.size()) ; i++) + vOffs[i]->ToGlob( m_Frame) ; + return true ; } @@ -820,7 +827,7 @@ Voronoi::CalcSpecialPointOffset( PNTVECTVECTOR& vResult, double dOffs) Point3d ptTemp ; Vector3d vtDir ; if ( ! pCrv->GetParamAtPoint( pt, dPar, 100 * EPS_SMALL) || ! pCrv->GetPointD1D2( dPar, ICurve::FROM_MINUS, ptTemp, &vtDir)) - return false ; + return false ; vtDir.Normalize() ; vResult.emplace_back( pt, vtDir) ; @@ -863,11 +870,10 @@ Voronoi::CalcFatCurve( ICURVEPOVECTOR& vCrvs, double dOffs, bool bSquareEnds, bo if ( dOffs > EPS_SMALL) pCrvOffs->Invert() ; - // sistemo i raccordi + // identifico i raccordi da modificare if ( bClosed && bSquareMids) { // se curva è chiusa tutti i raccordi rispondono a bSquareMids - IdentifyFillets( pCrvOffs, dOffs) ; - AdjustCurveFillets( pCrvOffs, dOffs, ICurve::OFF_EXTEND) ; + IdentifyFillets( pCrvOffs, dOffs) ; } else if ( ! bClosed && ( bSquareMids || bSquareEnds)) { // se curva è aperta devo distinguere i raccordi interni da quelli relativi agli estremi e @@ -880,17 +886,25 @@ Voronoi::CalcFatCurve( ICURVEPOVECTOR& vCrvs, double dOffs, bool bSquareEnds, bo else pCrvOffs->SetCurveTempParam( j, 0) ; } - AdjustCurveFillets( pCrvOffs, dOffs, ICurve::OFF_EXTEND) ; } - // porto nel frame globale - pCrvOffs->ToGlob( m_Frame) ; // unisco le parti allineate pCrvOffs->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG, true, true) ; // aggiungo al vettore finale vCrvs.emplace_back( pCrvOffs) ; } - + + // sistemo i raccordi + if ( bSquareMids || bSquareEnds) + if ( ! AdjustCurveFillets( vCrvs, dOffs, ICurve::OFF_EXTEND)) { + vCrvs.clear() ; + return false ; + } + + // porto nel frame globale + for ( int i = 0 ; i < int( vCrvs.size()) ; i++) + vCrvs[i]->ToGlob( m_Frame) ; + return true ; }