From d76beb09eee8ee52ed28a6e988283cec37740b6f Mon Sep 17 00:00:00 2001 From: Daniele Bariletti Date: Mon, 16 Mar 2026 17:01:48 +0100 Subject: [PATCH] EgtGeomKernel : - correzione alla GetChainedCurves - aggiunto parametro alla GetSide della DistPointCurve - migliorie alla IntersCurveCurve. --- CurveAux.cpp | 15 ++- DistPointCurve.cpp | 10 +- IntersCrvCompoCrvCompo.cpp | 191 +++++++++++++++++++++++++++++++------ IntersCrvCompoCrvCompo.h | 2 + 4 files changed, 183 insertions(+), 35 deletions(-) diff --git a/CurveAux.cpp b/CurveAux.cpp index 43c1f53..1aaceff 100644 --- a/CurveAux.cpp +++ b/CurveAux.cpp @@ -2656,12 +2656,21 @@ GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert) INTVECTOR vIds ; Point3d ptStart = ORIG ; while ( chainCrv.GetChainFromNear( ptStart, false, vIds)) { - ICurveComposite* pFirstCrv = vCrv[abs(vIds[0]) - 1] ; + int nFirst = vIds[0] ; + bool bInvert = false ; + if ( nFirst < 0) + bInvert = true ; + nFirst = abs( nFirst) - 1 ; + if ( bInvert) + vCrv[nFirst]->Invert() ; + ICurveComposite* pFirstCrv = vCrv[nFirst] ; for ( int nId : vIds) { - bool bInvert = false ; + bInvert = false ; if ( nId < 0) bInvert = true ; nId = abs( nId) - 1 ; + if ( nId == nFirst) + continue ; if ( bInvert) vCrv[nId]->Invert() ; if ( ! pFirstCrv->AddCurve( Release( vCrv[nId]), true, dChainTol)) @@ -2670,7 +2679,7 @@ GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert) pFirstCrv->GetEndPoint( ptStart) ; } // elimino gli elementi del vettore che non contengono più curve - int c = ssize( vCrv) ; + int c = ssize( vCrv) - 1 ; while ( c > -1) { if ( IsNull( vCrv[c])) vCrv.erase( vCrv.begin() + c) ; diff --git a/DistPointCurve.cpp b/DistPointCurve.cpp index c5dad76..d01af4c 100644 --- a/DistPointCurve.cpp +++ b/DistPointCurve.cpp @@ -211,13 +211,13 @@ DistPointCurve::GetParamAtMinDistPoint( double dNearParam, double& dParam, int& //---------------------------------------------------------------------------- bool -DistPointCurve::GetSideAtMinDistPoint( int nInd, const Vector3d& vtN, int& nSide) const +DistPointCurve::GetSideAtMinDistPoint( int nInd, const Vector3d& vtN, int& nSide, double dTol) const { if ( m_dDist < 0 || nInd < 0 || nInd >= (int) m_Info.size()) return false ; // se distanza nulla, il punto giace sulla curva - if ( m_dDist <= EPS_SMALL) { + if ( m_dDist <= dTol) { nSide = MDS_ON ; return true ; } @@ -259,7 +259,7 @@ DistPointCurve::GetSideAtMinDistPoint( int nInd, const Vector3d& vtN, int& nSide // determino il lato di giacitura del punto double dSide = vtRef * ( m_ptP - ptQ) ; - if ( abs( dSide) < EPS_SMALL) + if ( abs( dSide) < dTol) nSide = MDS_ON ; else if ( dSide > 0) nSide = MDS_LEFT ; @@ -270,7 +270,7 @@ DistPointCurve::GetSideAtMinDistPoint( int nInd, const Vector3d& vtN, int& nSide //---------------------------------------------------------------------------- bool -DistPointCurve::GetSideAtMinDistPoint( double dNearParam, const Vector3d& vtN, int& nSide) const +DistPointCurve::GetSideAtMinDistPoint( double dNearParam, const Vector3d& vtN, int& nSide, double dTol) const { if ( m_dDist < 0 || m_Info.empty()) return false ; @@ -286,7 +286,7 @@ DistPointCurve::GetSideAtMinDistPoint( double dNearParam, const Vector3d& vtN, i } } // mi sono ricondotto al caso precedente - return GetSideAtMinDistPoint( nInd, vtN, nSide) ; + return GetSideAtMinDistPoint( nInd, vtN, nSide, dTol) ; } //---------------------------------------------------------------------------- diff --git a/IntersCrvCompoCrvCompo.cpp b/IntersCrvCompoCrvCompo.cpp index 2b2a9fd..cab38d8 100644 --- a/IntersCrvCompoCrvCompo.cpp +++ b/IntersCrvCompoCrvCompo.cpp @@ -34,7 +34,6 @@ static bool CalcATypeFromDisk( const ICurve& CurveA, double dUA, ICurve::Side nS const ICurve& CurveB, double dUB, int& nType) ; static bool CalcATypeFromDisk2( const ICurve& CurveA, double dUA, ICurve::Side nSideA, const ICurve& CurveB, double dUB1, double dUB2, int& nType) ; -static bool CalcSide( const IntCrvCrvInfo& Icci1, const IntCrvCrvInfo& Icci2, const ICurve* pThisCrv, const ICurve* pOtherCrv, bool bCrvAOrB, int& nType) ; //---------------------------------------------------------------------------- IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA, @@ -784,12 +783,13 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA, if ( m_nNumInters > 1) { bool bCoherent = true ; INTVECTOR vIncoherenceWithPrev ; + INTVECTOR vNewOverlap ; // salvo eventuali incoerenze col precedente for ( int i = bCrvAClosed ? 0 : 1 ; i < m_nNumInters ; ++i) { int j = i == 0 ? m_nNumInters - 1 : i - 1 ; int kj = m_Info[j].bOverlap ? 1 : 0 ; - if ( m_Info[j].IciA[kj].nNextTy != m_Info[i].IciA[0].nPrevTy && - m_Info[j].IciA[kj].nNextTy != ICCT_SPK && m_Info[i].IciA[0].nPrevTy != ICCT_SPK) { + if ( (m_Info[j].IciA[kj].nNextTy == ICCT_NULL || m_Info[i].IciA[0].nPrevTy == ICCT_NULL || m_Info[j].IciA[kj].nNextTy != m_Info[i].IciA[0].nPrevTy) && + m_Info[j].IciA[kj].nNextTy != ICCT_SPK && m_Info[i].IciA[0].nPrevTy != ICCT_SPK) { vIncoherenceWithPrev.push_back( i) ; bCoherent = false ; } @@ -800,16 +800,21 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA, int j = i == 0 ? m_nNumInters - 1 : i - 1 ; int kj = m_Info[j].bOverlap ? 1 : 0 ; int nType = 0 ; - CalcSide( m_Info[j], m_Info[i], &CCompoA, &CCompoB, true, nType) ; - if ( nType == MDS_LEFT) - nType = ICCT_IN ; - else if ( nType == MDS_RIGHT) - nType = ICCT_OUT ; - m_Info[i].IciA[0].nPrevTy = nType ; - m_Info[j].IciA[kj].nNextTy = nType ; + CalcSide( j, i, &CCompoA, &CCompoB, true, nType) ; + if ( nType != ICCT_ON) { + m_Info[i].IciA[0].nPrevTy = nType ; + m_Info[j].IciA[kj].nNextTy = nType ; + } + else + vNewOverlap.push_back( i) ; } } + // faccio il merge se ho trasformato delle intersezioni in overlap + for ( int i : vNewOverlap) + MergeNewOverlap( i, true) ; + + vNewOverlap.clear() ; stable_sort( m_Info.begin(), m_Info.end(), SortGreaterB) ; bCoherent = true ; vIncoherenceWithPrev.clear() ; @@ -817,7 +822,7 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA, for ( int i = bCrvBClosed ? 0 : 1 ; i < m_nNumInters ; ++i) { int j = i == 0 ? m_nNumInters - 1 : i - 1 ; int kj = m_Info[j].bOverlap ? 1 : 0 ; - if ( m_Info[j].IciB[kj].nNextTy != m_Info[i].IciB[0].nPrevTy && + if ( ( m_Info[j].IciB[kj].nNextTy == ICCT_NULL || m_Info[i].IciB[0].nPrevTy == ICCT_NULL || m_Info[j].IciB[kj].nNextTy != m_Info[i].IciB[0].nPrevTy) && m_Info[j].IciB[kj].nNextTy != ICCT_SPK && m_Info[i].IciB[0].nPrevTy != ICCT_SPK) { vIncoherenceWithPrev.push_back( i) ; bCoherent = false ; @@ -829,15 +834,19 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA, int j = i == 0 ? m_nNumInters - 1 : i - 1 ; int kj = m_Info[j].bOverlap ? 1 : 0 ; int nType = 0 ; - CalcSide( m_Info[j], m_Info[i], &CCompoB, &CCompoA, false, nType) ; - if ( nType == MDS_LEFT) - nType = ICCT_IN ; - else if ( nType == MDS_RIGHT) - nType = ICCT_OUT ; - m_Info[i].IciB[0].nPrevTy = nType ; - m_Info[j].IciB[kj].nNextTy = nType ; + CalcSide( j, i, &CCompoB, &CCompoA, false, nType) ; + if ( nType != ICCT_ON) { + m_Info[i].IciB[0].nPrevTy = nType ; + m_Info[j].IciB[kj].nNextTy = nType ; + } + else + vNewOverlap.push_back( i) ; } } + + // faccio il merge se ho trasformato delle intersezioni in overlap + for ( int i : vNewOverlap) + MergeNewOverlap( i, false) ; } else { // posso completare A guardando B e viceversa @@ -849,34 +858,162 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA, } //---------------------------------------------------------------------------- -static bool -CalcSide( const IntCrvCrvInfo& Icci1, const IntCrvCrvInfo& Icci2,const ICurve* pThisCrv, const ICurve* pOtherCrv, bool bCrvAOrB, int& nType) +bool +IntersCrvCompoCrvCompo::CalcSide( int j, int i,const ICurve* pThisCrv, const ICurve* pOtherCrv, bool bCrvAOrB, int& nType) { + const IntCrvCrvInfo& Icci1 = m_Info[j] ; + const IntCrvCrvInfo& Icci2 = m_Info[i] ; // calcolo tra l'intersezione 1 e 2 se la curva sta dentro o fuori int kj = Icci1.bOverlap ? 1 : 0 ; double dU = 0 ; + bool bPrevIsBefore = true ; if ( bCrvAOrB) { // se precedente minore del successivo faccio la media if ( Icci1.IciA[kj].dU < Icci2.IciA[0].dU) - dU = (Icci2.IciA[0].dU + Icci1.IciA[kj].dU) / 2 ; + dU = ( Icci2.IciA[0].dU + Icci1.IciA[kj].dU) / 2 ; // altrimenti guardo tra lo start e il successivo - else - dU = (Icci2.IciA[0].dU + 0.) / 2 ; + else { + bPrevIsBefore = false ; + dU = ( Icci2.IciA[0].dU + 0.) / 2 ; + if ( dU < EPS_SMALL) { + double dStart, dEnd ; + pThisCrv->GetDomain( dStart, dEnd) ; + double dUNew = dEnd - Icci1.IciA[kj].dU / 2 ; + if ( dUNew > dU) + dU = dUNew ; + } + } } else { // se precedente minore del successivo faccio la media if ( Icci1.IciB[kj].dU < Icci2.IciB[0].dU) - dU = (Icci2.IciB[0].dU + Icci1.IciB[kj].dU) / 2 ; + dU = ( Icci2.IciB[0].dU + Icci1.IciB[kj].dU) / 2 ; // altrimenti guardi tra lo start e il successivo - else - dU = (Icci2.IciB[0].dU + 0.) / 2 ; + else { + bPrevIsBefore = false ; + dU = ( Icci2.IciB[0].dU + 0.) / 2 ; + if ( dU < EPS_SMALL) { + double dStart, dEnd ; + pThisCrv->GetDomain( dStart, dEnd) ; + double dUNew = dEnd - Icci1.IciB[kj].dU / 2 ; + if ( dUNew > dU) + dU = dUNew ; + } + } } Point3d ptTest ; pThisCrv->GetPointD1D2( dU, ICurve::FROM_MINUS, ptTest) ; DistPointCurve dpc( ptTest, *pOtherCrv) ; - dpc.GetSideAtMinDistPoint( 0, Z_AX, nType) ; + dpc.GetSideAtMinDistPoint( 0, Z_AX, nType, EPS_ZERO) ; + if ( nType == MDS_LEFT) + nType = ICCT_IN ; + else if ( nType == MDS_RIGHT) + nType = ICCT_OUT ; + // se lo trovo sulla curva controllo se posso definire un tratto overlap + if ( nType == MDS_ON) { + double dFactor = 1./3. ; + DBLVECTOR vdU(2) ; + bool bIsOn = false ; + if ( bCrvAOrB) { + if ( bPrevIsBefore) { + vdU[0] = ( 1 - dFactor) * Icci2.IciA[0].dU + dFactor * Icci1.IciA[kj].dU ; + vdU[1] = ( 1 - 2 * dFactor) * Icci2.IciA[0].dU + 2 * dFactor * Icci1.IciA[kj].dU ; + } + else if ( Icci2.IciA[0].dU > 2 * EPS_SMALL){ + vdU[0] = ( Icci2.IciA[0].dU + 0.) * dFactor ; + vdU[1] = ( Icci2.IciA[0].dU + 0.) * 2 * dFactor ; + } + else + bIsOn = true ; + } + else { + if ( bPrevIsBefore) { + vdU[0] = ( 1 - dFactor) * Icci2.IciB[0].dU + dFactor * Icci1.IciB[kj].dU ; + vdU[1] = ( 1 - 2 * dFactor) * Icci2.IciB[0].dU + 2 * dFactor * Icci1.IciB[kj].dU ; + } + else if ( Icci2.IciB[0].dU > 2 * EPS_SMALL) { + vdU[0] = ( Icci2.IciB[0].dU + 0.) * dFactor ; + vdU[1] = ( Icci2.IciB[0].dU + 0.) * 2 * dFactor ; + } + else + bIsOn = true ; + } + if ( ! bIsOn) { + bIsOn = true ; + for ( int k = 0 ; k < ssize(vdU) && bIsOn ; ++k) { + Point3d ptTest2 ; pThisCrv->GetPointD1D2( vdU[k], ICurve::FROM_MINUS, ptTest2) ; + DistPointCurve dpc2( ptTest2, *pOtherCrv) ; + dpc2.GetSideAtMinDistPoint( 0, Z_AX, nType, EPS_ZERO) ; + if ( nType != MDS_ON) + bIsOn = false ; + } + } + if ( bIsOn) { + m_Info[i].bOverlap = true ; + Vector3d vtDirThis, vtDirOther ; + Point3d ptCommon ; + double dUThis = 0 ; + if ( bCrvAOrB) + dUThis = m_Info[i].IciA[0].dU ; + else + dUThis = m_Info[i].IciB[0].dU ; + pThisCrv->GetPointD1D2( dUThis, ICurve::Side::FROM_MINUS, ptCommon, &vtDirThis) ; + double dUOther = 0 ; pOtherCrv->GetParamAtPoint( ptCommon, dUOther) ; + pOtherCrv->GetPointD1D2( dUOther, ICurve::Side::FROM_MINUS, ptCommon, &vtDirOther) ; + m_Info[i].bCBOverEq = vtDirThis * vtDirOther > 0 ; + if ( m_Info[i].bCBOverEq) { + m_Info[i].IciA[1] = m_Info[i].IciA[0] ; + m_Info[i].IciB[1] = m_Info[i].IciB[0] ; + m_Info[i].IciA[0] = m_Info[j].IciA[kj] ; + m_Info[i].IciB[0] = m_Info[j].IciB[kj] ; + m_Info[i].IciA[1].nPrevTy = ICCT_ON ; + m_Info[i].IciB[1].nPrevTy = ICCT_ON ; + m_Info[i].IciA[0].nNextTy = ICCT_ON ; + m_Info[i].IciB[0].nNextTy = ICCT_ON ; + } + else { + if ( bCrvAOrB) { + m_Info[i].IciA[1] = m_Info[i].IciA[0] ; + m_Info[i].IciA[0] = m_Info[j].IciA[kj] ; + m_Info[i].IciA[1].nPrevTy = ICCT_ON ; + m_Info[i].IciA[0].nNextTy = ICCT_ON ; + m_Info[i].IciB[1] = m_Info[j].IciB[kj] ; + m_Info[i].IciB[0].nPrevTy = ICCT_ON ; + m_Info[i].IciB[1].nNextTy = ICCT_ON ; + } + else { + m_Info[i].IciB[1] = m_Info[i].IciB[0] ; + m_Info[i].IciB[0] = m_Info[j].IciB[kj] ; + m_Info[i].IciB[1].nPrevTy = ICCT_ON ; + m_Info[i].IciB[0].nNextTy = ICCT_ON ; + m_Info[i].IciA[1] = m_Info[j].IciA[kj] ; + m_Info[i].IciA[0].nPrevTy = ICCT_ON ; + m_Info[i].IciA[1].nNextTy = ICCT_ON ; + } + } + nType = ICCT_ON ; + } + } + return true ; } +//---------------------------------------------------------------------------- +bool +IntersCrvCompoCrvCompo::MergeNewOverlap( int i, bool bCrvAOrB) +{ + // faccio il merge col precedente + int j = i == 0 ? m_nNumInters - 1 : i - 1 ; + if ( m_Info[j].bOverlap) { + m_Info[i].IciA[0] = m_Info[j].IciA[0] ; + m_Info[i].IciB[0] = m_Info[j].IciB[0] ; + } + m_Info.erase( m_Info.begin() + j) ; + -- j ; + -- m_nNumInters ; + return true ; +} + + //---------------------------------------------------------------------------- bool IntersCrvCompoCrvCompo::IntersSimpleCurves( const ICurve& CurveA, int nA, const ICurve& CurveB, int nB, diff --git a/IntersCrvCompoCrvCompo.h b/IntersCrvCompoCrvCompo.h index ee5d0ff..f0ebc03 100644 --- a/IntersCrvCompoCrvCompo.h +++ b/IntersCrvCompoCrvCompo.h @@ -43,6 +43,8 @@ class IntersCrvCompoCrvCompo bool bAutoInters, bool bClosed, int nCurvesNbr) ; bool EraseCurrentInfo( int& nIndCurr, int& nIndOther) ; bool EraseOtherInfo( int& nIndCurr, int& nIndOther) ; + bool CalcSide( int j, int i,const ICurve* pThisCrv, const ICurve* pOtherCrv, bool bCrvAOrB, int& nType) ; + bool MergeNewOverlap( int i, bool bCrvAOrB) ; private : bool m_bOverlaps ;