diff --git a/BBox3d.cpp b/BBox3d.cpp index 8ae2e19..14ee845 100644 --- a/BBox3d.cpp +++ b/BBox3d.cpp @@ -217,20 +217,39 @@ BBox3d::ToLoc( const Frame3d& frRef) bool BBox3d::Encloses( const Point3d& ptP) const { - return ( ptP.x >= m_ptMin.x && ptP.x <= m_ptMax.x && - ptP.y >= m_ptMin.y && ptP.y <= m_ptMax.y && - ptP.z >= m_ptMin.z && ptP.z <= m_ptMax.z) ; + return ( ptP.x > m_ptMin.x - EPS_SMALL && ptP.x < m_ptMax.x + EPS_SMALL && + ptP.y > m_ptMin.y - EPS_SMALL && ptP.y < m_ptMax.y + EPS_SMALL && + ptP.z > m_ptMin.z - EPS_SMALL && ptP.z < m_ptMax.z + EPS_SMALL) ; +} + +//---------------------------------------------------------------------------- +bool +BBox3d::EnclosesXY( const Point3d& ptP) const +{ + return ( ptP.x > m_ptMin.x - EPS_SMALL && ptP.x < m_ptMax.x + EPS_SMALL && + ptP.y > m_ptMin.y - EPS_SMALL && ptP.y < m_ptMax.y + EPS_SMALL) ; } //---------------------------------------------------------------------------- bool BBox3d::Overlaps( const BBox3d& b3B) const { - if ( m_ptMax.x < b3B.m_ptMin.x || m_ptMin.x > b3B.m_ptMax.x) + if ( m_ptMax.x < b3B.m_ptMin.x - EPS_SMALL || m_ptMin.x > b3B.m_ptMax.x + EPS_SMALL) return false ; - if ( m_ptMax.y < b3B.m_ptMin.y || m_ptMin.y > b3B.m_ptMax.y) + if ( m_ptMax.y < b3B.m_ptMin.y - EPS_SMALL || m_ptMin.y > b3B.m_ptMax.y + EPS_SMALL) return false ; - if ( m_ptMax.z < b3B.m_ptMin.z || m_ptMin.z > b3B.m_ptMax.z) + if ( m_ptMax.z < b3B.m_ptMin.z - EPS_SMALL || m_ptMin.z > b3B.m_ptMax.z + EPS_SMALL) + return false ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +BBox3d::OverlapsXY( const BBox3d& b3B) const +{ + if ( m_ptMax.x < b3B.m_ptMin.x - EPS_SMALL || m_ptMin.x > b3B.m_ptMax.x + EPS_SMALL) + return false ; + if ( m_ptMax.y < b3B.m_ptMin.y - EPS_SMALL || m_ptMin.y > b3B.m_ptMax.y + EPS_SMALL) return false ; return true ; } @@ -240,11 +259,30 @@ bool BBox3d::FindIntersection( const BBox3d& b3B, BBox3d& b3Int) const { // verifico direttamente la sovrapposizione - if ( m_ptMax.x < b3B.m_ptMin.x || m_ptMin.x > b3B.m_ptMax.x) + if ( m_ptMax.x < b3B.m_ptMin.x - EPS_SMALL || m_ptMin.x > b3B.m_ptMax.x + EPS_SMALL) return false ; - if ( m_ptMax.y < b3B.m_ptMin.y || m_ptMin.y > b3B.m_ptMax.y) + if ( m_ptMax.y < b3B.m_ptMin.y - EPS_SMALL || m_ptMin.y > b3B.m_ptMax.y + EPS_SMALL) return false ; - if ( m_ptMax.z < b3B.m_ptMin.z || m_ptMin.z > b3B.m_ptMax.z) + if ( m_ptMax.z < b3B.m_ptMin.z - EPS_SMALL || m_ptMin.z > b3B.m_ptMax.z + EPS_SMALL) + return false ; + // calcolo il box intersezione + b3Int.m_ptMin.x = (( m_ptMin.x >= b3B.m_ptMin.x) ? m_ptMin.x : b3B.m_ptMin.x) ; + b3Int.m_ptMin.y = (( m_ptMin.y >= b3B.m_ptMin.y) ? m_ptMin.y : b3B.m_ptMin.y) ; + b3Int.m_ptMin.z = (( m_ptMin.z >= b3B.m_ptMin.z) ? m_ptMin.z : b3B.m_ptMin.z) ; + b3Int.m_ptMax.x = (( m_ptMax.x <= b3B.m_ptMax.x) ? m_ptMax.x : b3B.m_ptMax.x) ; + b3Int.m_ptMax.y = (( m_ptMax.y <= b3B.m_ptMax.y) ? m_ptMax.y : b3B.m_ptMax.y) ; + b3Int.m_ptMax.z = (( m_ptMax.z <= b3B.m_ptMax.z) ? m_ptMax.z : b3B.m_ptMax.z) ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +BBox3d::FindIntersectionXY( const BBox3d& b3B, BBox3d& b3Int) const +{ + // verifico direttamente la sovrapposizione + if ( m_ptMax.x < b3B.m_ptMin.x - EPS_SMALL || m_ptMin.x > b3B.m_ptMax.x + EPS_SMALL) + return false ; + if ( m_ptMax.y < b3B.m_ptMin.y - EPS_SMALL || m_ptMin.y > b3B.m_ptMax.y + EPS_SMALL) return false ; // calcolo il box intersezione b3Int.m_ptMin.x = (( m_ptMin.x >= b3B.m_ptMin.x) ? m_ptMin.x : b3B.m_ptMin.x) ; @@ -275,3 +313,19 @@ BBox3d::SqDistFromPoint( const Point3d& ptP) const dSqDist += ( ptP.z - m_ptMax.z) * ( ptP.z - m_ptMax.z) ; return dSqDist ; } + +//---------------------------------------------------------------------------- +double +BBox3d::SqDistFromPointXY( const Point3d& ptP) const +{ + double dSqDist = 0 ; + if ( ptP.x < m_ptMin.x) + dSqDist += ( m_ptMin.x - ptP.x) * ( m_ptMin.x - ptP.x) ; + else if ( ptP.x > m_ptMax.x) + dSqDist += ( ptP.x - m_ptMax.x) * ( ptP.x - m_ptMax.x) ; + if ( ptP.y < m_ptMin.y) + dSqDist += ( m_ptMin.y - ptP.y) * ( m_ptMin.y - ptP.y) ; + else if ( ptP.y > m_ptMax.y) + dSqDist += ( ptP.y - m_ptMax.y) * ( ptP.y - m_ptMax.y) ; + return dSqDist ; +} diff --git a/CurveArc.cpp b/CurveArc.cpp index f875f4e..594fcea 100644 --- a/CurveArc.cpp +++ b/CurveArc.cpp @@ -592,7 +592,7 @@ CurveArc::Validate( void) } // eseguo il controllo m_nStatus = ( ( m_VtN.IsNormalized() && m_VtS.IsNormalized() && - AreOrthoNear( m_VtN, m_VtS) && + AreOrthoApprox( m_VtN, m_VtS) && m_dRad > EPS_ZERO && fabs( m_dAngCenDeg) > EPS_ANG_ZERO) ? OK : ERR) ; } diff --git a/CurveArc.h b/CurveArc.h index 2acb6f5..07edc48 100644 --- a/CurveArc.h +++ b/CurveArc.h @@ -67,6 +67,12 @@ class CurveArc : public ICurveArc, public IGeoObjRW { return GetDir( 0.5, vtDir) ; } virtual bool GetDomain( double& dStart, double& dEnd) const { dStart = 0 ; dEnd = 1 ; return ( m_nStatus == OK) ; } + virtual bool IsValidParam( double dPar, Side nSide) const + { return ::IsValidParam( *this, dPar, nSide) ; } + virtual bool IsStartParam( double dPar) const + { return ::IsStartParam( *this, dPar) ; } + virtual bool IsEndParam( double dPar) const + { return ::IsEndParam( *this, dPar) ; } virtual bool GetLength( double& dLen) const ; virtual bool GetLengthAtParam( double dU, double& dLen) const ; virtual bool GetParamAtLength( double dLen, double& dU) const ; diff --git a/CurveAux.cpp b/CurveAux.cpp index dc6fba1..39df948 100644 --- a/CurveAux.cpp +++ b/CurveAux.cpp @@ -26,9 +26,56 @@ IsClosed( const ICurve& crvC) { Point3d ptStart ; Point3d ptEnd ; + return ( crvC.GetStartPoint( ptStart) && crvC.GetEndPoint( ptEnd) && AreSamePointApprox( ptStart, ptEnd)) ; +} +//---------------------------------------------------------------------------- +bool +IsValidParam( const ICurve& crvC, double dPar, ICurve::Side nSide) +{ + // recupero l'intervallo di validità del parametro + double dStart, dEnd ; + if ( ! crvC.GetDomain( dStart, dEnd)) + return false ; + // il parametro deve stare nei limiti + if ( dPar < dStart - EPS_PARAM || dPar > dEnd + EPS_PARAM) + return false ; + // se curva chiusa non sono necessari altri controlli + if ( crvC.IsClosed()) + return true ; + // per curve aperte non posso studiare la curva prima dell'inizio e dopo la fine + if ( ( dPar < dStart + EPS_PARAM && nSide == ICurve::FROM_MINUS) || + ( dPar > dEnd - EPS_PARAM && nSide == ICurve::FROM_PLUS)) + return false ; + return true ; +} - return ( crvC.GetStartPoint( ptStart) && crvC.GetEndPoint( ptEnd) && AreSamePointNear( ptStart, ptEnd)) ; +//---------------------------------------------------------------------------- +bool +IsStartParam( const ICurve& crvC, double dPar) +{ + // recupero l'intervallo di validità del parametro + double dStart, dEnd ; + if ( ! crvC.GetDomain( dStart, dEnd)) + return false ; + // se il parametro non è nell'intorno dell'inizio + if ( fabs( dPar - dStart) > EPS_PARAM) + return false ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +IsEndParam( const ICurve& crvC, double dPar) +{ + // recupero l'intervallo di validità del parametro + double dStart, dEnd ; + if ( ! crvC.GetDomain( dStart, dEnd)) + return false ; + // se il parametro non è nell'intorno della fine + if ( fabs( dPar - dEnd) > EPS_PARAM) + return false ; + return true ; } //---------------------------------------------------------------------------- diff --git a/CurveAux.h b/CurveAux.h index 5e6219a..b49d86d 100644 --- a/CurveAux.h +++ b/CurveAux.h @@ -17,6 +17,9 @@ //---------------------------------------------------------------------------- bool IsClosed( const ICurve& crvC) ; +bool IsValidParam( const ICurve& crvC, double dPar, ICurve::Side nSide) ; +bool IsStartParam( const ICurve& crvC, double dPar) ; +bool IsEndParam( const ICurve& crvC, double dPar) ; bool GetTang( const ICurve& crvC, double dU, ICurve::Side nS, Vector3d& vtTang) ; bool GetPointTang( const ICurve& crvC, double dU, ICurve::Side nS, Point3d& ptPos, Vector3d& vtTang) ; bool GetPointDiffGeom( const ICurve& crvC, double dU, ICurve::Side nS, CrvPointDiffGeom& oDiffG) ; diff --git a/CurveBezier.h b/CurveBezier.h index 04d9b72..f994750 100644 --- a/CurveBezier.h +++ b/CurveBezier.h @@ -69,6 +69,12 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW { return ::GetTang( *this, 0.5, FROM_MINUS, vtDir) ; } virtual bool GetDomain( double& dStart, double& dEnd) const { dStart = 0 ; dEnd = 1 ; return ( m_nStatus == OK) ; } + virtual bool IsValidParam( double dPar, Side nSide) const + { return ::IsValidParam( *this, dPar, nSide) ; } + virtual bool IsStartParam( double dPar) const + { return ::IsStartParam( *this, dPar) ; } + virtual bool IsEndParam( double dPar) const + { return ::IsEndParam( *this, dPar) ; } virtual bool GetLength( double& dLen) const ; virtual bool GetLengthAtParam( double dU, double& dLen) const ; virtual bool GetParamAtLength( double dLen, double& dU) const ; diff --git a/CurveComposite.cpp b/CurveComposite.cpp index 346a59e..36a4c70 100644 --- a/CurveComposite.cpp +++ b/CurveComposite.cpp @@ -19,11 +19,11 @@ #include "GeoObjFactory.h" #include "NgeWriter.h" #include "NgeReader.h" -#include "/EgtDev/Include/EGnStringUtils.h" -#include "/EgtDev/Include/EgtPointerOwner.h" +#include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EGkCurveLine.h" #include "/EgtDev/Include/EGkCurveArc.h" #include "/EgtDev/Include/EGkCurveBezier.h" +#include "/EgtDev/Include/EgtPointerOwner.h" #include using namespace std ; @@ -48,7 +48,7 @@ bool CurveComposite::Clear( void) { // ciclo di pulizia - PCRVSMPL_LIST::iterator Iter ; + PCRVSMPL_DEQUE::iterator Iter ; for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) delete (*Iter) ; @@ -167,13 +167,13 @@ CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart) // se inserita alla fine if ( bEndOrStart) { // verifico sia in continuità con il finale attuale - if ( ! AreSamePointNear( ptStart, m_PtEnd)) + if ( ! AreSamePointApprox( ptStart, m_PtEnd)) return false ; } // altrimenti inserita all'inizio else { // verifico sia in continuità con l'iniziale attuale - if ( ! AreSamePointNear( ptEnd, m_PtStart)) + if ( ! AreSamePointApprox( ptEnd, m_PtStart)) return false ; } } @@ -196,7 +196,7 @@ CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart) m_PtStart = ptStart ; // aggiorno il flag di curva chiusa - m_bClosed = ( AreSamePointNear( m_PtStart, m_PtEnd)) ; + m_bClosed = ( AreSamePointApprox( m_PtStart, m_PtEnd)) ; // aggiorno lo stato m_nStatus = OK ; @@ -262,7 +262,7 @@ CurveComposite::FromPointVector( const PNTVECTOR& vPnt) int iPrev = 0 ; for ( int i = 1 ; i < int( vPnt.size()) ; ++ i) { // se i punti della coppia coincidono, passo alla coppia successiva - if ( AreSamePointNear( vPnt[iPrev], vPnt[i])) + if ( AreSamePointApprox( vPnt[iPrev], vPnt[i])) continue ; // creo il segmento di retta PtrOwner pCrvLine( CreateCurveLine()) ; @@ -299,7 +299,7 @@ CurveComposite::FromPointBulgeVector( const UPNTVECTOR& vUPnt, const Vector3d& v int iPrev = 0 ; for ( int i = 1 ; i < int( vUPnt.size()) ; ++i) { // se i punti della coppia coincidono, passo alla coppia successiva - if ( AreSamePointNear( vUPnt[iPrev].second, vUPnt[i].second)) + if ( AreSamePointApprox( vUPnt[iPrev].second, vUPnt[i].second)) continue ; // se retta if ( fabs( vUPnt[i-1].first) < EPS_SMALL) { @@ -359,7 +359,7 @@ CurveComposite::PolygonCenterCorner( int nSides, const Point3d& ptCen, const Poi ptEnd.Rotate( ptCen, Z_AX, dCosAng, dSinAng) ; // se primo lato, verifico che la lunghezza sia superiore al minimo if ( i == 1) { - if ( AreSamePointNear( ptStart, ptEnd)) + if ( AreSamePointApprox( ptStart, ptEnd)) return false ; } // creo il segmento di retta @@ -416,7 +416,7 @@ CurveComposite::PolygonSide( int nSides, const Point3d& ptStart, const Point3d& if ( nSides < 3) return false ; // verifico che la lunghezza sia superiore al minimo - if ( AreSamePointNear( ptStart, ptEnd)) + if ( AreSamePointApprox( ptStart, ptEnd)) return false ; // calcolo la posizione del centro @@ -464,7 +464,7 @@ CurveComposite::Copy( const CurveComposite& ccSrc) if ( &ccSrc == this) return true ; Clear() ; - PCRVSMPL_LIST::const_iterator Iter ; + PCRVSMPL_DEQUE::const_iterator Iter ; for ( Iter = ccSrc.m_CrvSmplS.begin() ; Iter != ccSrc.m_CrvSmplS.end() ; ++Iter) { if ( ! AddCurve( **Iter)) return false ; @@ -492,9 +492,12 @@ bool CurveComposite::Dump( string& sOut, const char* szNewLine) const { // se curva aperta o chiusa - sOut += ( IsClosed() ? "Closed" : "Open") ; + sOut += ( IsClosed() ? "Closed" : "Open") + string( szNewLine) ; + // punti iniziale e finale + sOut += "PS(" + ToString( m_PtStart, 3) + ")" + szNewLine ; + sOut += "PE(" + ToString( m_PtEnd, 3) + ")" + szNewLine ; // numero di curve - sOut += " CrvNbr=" + ToString( m_nCounter) + szNewLine ; + sOut += "CrvNbr=" + ToString( m_nCounter) + szNewLine ; // ciclo sulle curve componenti int i = 0 ; const ICurve* pCrvSmpl = GetFirstCurve() ; @@ -647,12 +650,11 @@ bool CurveComposite::Validate( void) { if ( m_nStatus == TO_VERIFY) { - int nCount ; Point3d ptPrevEnd ; Point3d ptStart ; - PCRVSMPL_LIST::const_iterator Iter ; // ciclo su tutte le curve - nCount = 0 ; + int nCount = 0 ; + PCRVSMPL_DEQUE::const_iterator Iter ; for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) { // verifico validità della curva e sua semplicità if ( ! (*Iter)->IsValid() || (*Iter)->GetType() == CRV_COMPO) { @@ -664,7 +666,7 @@ CurveComposite::Validate( void) // verifico continuità con la precedente (se non è la prima) if ( nCount > 1) { (*Iter)->GetStartPoint( ptStart) ; - if ( ! AreSamePointNear( ptPrevEnd, ptStart)) { + if ( ! AreSamePointApprox( ptPrevEnd, ptStart)) { m_nStatus = ERR ; return false ; } @@ -678,7 +680,7 @@ CurveComposite::Validate( void) if ( m_nStatus == OK) { m_CrvSmplS.front()->GetStartPoint( m_PtStart) ; m_CrvSmplS.back()->GetEndPoint( m_PtEnd) ; - m_bClosed = ( AreSamePointNear( m_PtStart, m_PtEnd)) ; + m_bClosed = ( AreSamePointApprox( m_PtStart, m_PtEnd)) ; } else m_bClosed = false ; @@ -747,6 +749,47 @@ CurveComposite::GetDomain( double& dStart, double& dEnd) const return true ; } +//---------------------------------------------------------------------------- +bool +CurveComposite::GetIndSCurveAndLocPar( double dU, Side nS, int& nSCrv, double& dLocU) const +{ + // verifico che il parametro non sia troppo fuori dai limiti + if ( dU < - 100 * EPS_PARAM || dU > m_nCounter + 100 * EPS_PARAM) + return false ; + + // il parametro U deve essere compreso tra 0 e m_nCounter (le curve chiuse sono cicliche) + if ( dU < ( 0 + EPS_PARAM)) { + // se chiusa e voglio valutare prima dell'inizio devo valutare prima della fine + if ( m_bClosed && nS == ICurve::FROM_MINUS) + dU = m_nCounter ; + // altrimenti posso valutare solo dopo l'inizio + else { + dU = 0 ; + nS = ICurve::FROM_PLUS ; + } + } + else if ( dU > ( m_nCounter - EPS_PARAM)) { + // se chiusa e voglio valutare dopo la fine devo valutare dopo l'inizio + if ( m_bClosed && nS == ICurve::FROM_PLUS) + dU = 0 ; + // altrimenti posso valutare solo prima della fine + else { + dU = m_nCounter ; + nS = ICurve::FROM_MINUS ; + } + } + + // determino la curva di appartenenza e il valore locale (ovvero nella curva) del parametro + nSCrv = static_cast( dU) ; + dLocU = dU - nSCrv ; + if ( fabs( dLocU) < EPS_PARAM && nSCrv > 0 && nS == ICurve::FROM_MINUS) { + -- nSCrv ; + dLocU += 1 ; + } + + return true ; +} + //---------------------------------------------------------------------------- bool CurveComposite::GetPointD1D2( double dU, Side nS, Point3d& ptPos, Vector3d* pvtDer1, Vector3d* pvtDer2) const @@ -755,29 +798,14 @@ CurveComposite::GetPointD1D2( double dU, Side nS, Point3d& ptPos, Vector3d* pvtD if ( m_nStatus != OK) return false ; - // il parametro U deve essere compreso tra 0 e m_nCounter - if ( dU < ( 0 + EPS_PARAM)) { - dU = 0 ; - nS = ICurve::FROM_PLUS ; - } - else if ( dU > ( m_nCounter - EPS_PARAM)) { - dU = m_nCounter ; - nS = ICurve::FROM_MINUS ; - } + // determino la curva di appartenenza e il valore locale del parametro + int nC ; + double dUc ; + if ( ! GetIndSCurveAndLocPar( dU, nS, nC, dUc)) + return false ; - // determino la curva di appartenenza e faccio eseguire il calcolo - PCRVSMPL_LIST::const_iterator Iter ; - for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) { - // ogni curva semplice ha parametro compreso tra 0 e 1 - // se nella parametrizzazione della curva semplice, oppure all'estremo superiore e dal basso - if ( dU < ( 1 - EPS_ZERO) || - ( fabs( dU - 1) < EPS_ZERO && nS == ICurve::FROM_MINUS)) - return (*Iter)->GetPointD1D2( dU, ICurve::FROM_MINUS, ptPos, pvtDer1, pvtDer2) ; - else - dU -= 1 ; - } - - return false ; + // eseguo il calcolo sulla curva semplice + return m_CrvSmplS[nC]->GetPointD1D2( dUc, ICurve::FROM_MINUS, ptPos, pvtDer1, pvtDer2) ; } //---------------------------------------------------------------------------- @@ -790,7 +818,7 @@ CurveComposite::GetLength( double& dLen) const // ciclo di calcolo dLen = 0 ; - PCRVSMPL_LIST::const_iterator Iter ; + PCRVSMPL_DEQUE::const_iterator Iter ; for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) { double dLenCrvSmpl ; if ( (*Iter)->GetLength( dLenCrvSmpl)) @@ -817,7 +845,7 @@ CurveComposite::GetLengthAtParam( double dU, double& dLen) const // ciclo di calcolo dLen = 0 ; double dUToGo = dU ; - PCRVSMPL_LIST::const_iterator Iter ; + PCRVSMPL_DEQUE::const_iterator Iter ; for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) { // dominio parametrico della curva semplice double dParStart, dParEnd ; @@ -866,7 +894,7 @@ CurveComposite::GetParamAtLength( double dLen, double& dU) const // ciclo di calcolo dU = 0 ; double dLenToGo = dLen ; - PCRVSMPL_LIST::const_iterator Iter ; + PCRVSMPL_DEQUE::const_iterator Iter ; for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) { // lunghezza della curva semplice double dCrvLen ; @@ -922,7 +950,7 @@ CurveComposite::ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL bool bFirst = true ; double dStartPar = 0 ; PolyLine PLSmpl ; - PCRVSMPL_LIST::const_iterator Iter ; + PCRVSMPL_DEQUE::const_iterator Iter ; for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) { // recupero approssimazione per curva semplice if ( ! (*Iter)->ApproxWithLines( dLinTol, dAngTolDeg, PLSmpl)) @@ -953,12 +981,12 @@ CurveComposite::Invert( void) return false ; // inverto le singole curve - PCRVSMPL_LIST::iterator Iter ; + PCRVSMPL_DEQUE::iterator Iter ; for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) (*Iter)->Invert() ; // inverto l'ordine della lista - m_CrvSmplS.reverse() ; + reverse( m_CrvSmplS.begin(), m_CrvSmplS.end()) ; // scambio punti iniziale e finale swap( m_PtStart, m_PtEnd) ; @@ -975,7 +1003,7 @@ CurveComposite::TrimStartAtParam( double dUTrim) { // ciclo sulle diverse curve dall'inizio double dUToTrim = dUTrim ; - PCRVSMPL_LIST::iterator Iter ; + PCRVSMPL_DEQUE::iterator Iter ; for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ;) { // dominio parametrico della curva semplice double dParStart, dParEnd ; @@ -999,13 +1027,13 @@ CurveComposite::TrimStartAtParam( double dUTrim) if ( m_nCounter == 0) return false ; (*Iter)->GetStartPoint( m_PtStart) ; - m_bClosed = ( AreSamePointNear( m_PtStart, m_PtEnd)) ; + m_bClosed = ( AreSamePointApprox( m_PtStart, m_PtEnd)) ; break ; } // altrimenti superata lunghezza ancora da tagliare (taglio già fatto al test sopra) else { (*Iter)->GetStartPoint( m_PtStart) ; - m_bClosed = ( AreSamePointNear( m_PtStart, m_PtEnd)) ; + m_bClosed = ( AreSamePointApprox( m_PtStart, m_PtEnd)) ; break ; } } @@ -1023,7 +1051,7 @@ CurveComposite::TrimEndAtParam( double dUTrim) // ciclo sulle diverse curve dalla fine bool bToErase = false ; double dUToTrim = dUTrim ; - PCRVSMPL_LIST::iterator Iter ; + PCRVSMPL_DEQUE::iterator Iter ; for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ;) { // dominio parametrico della curva semplice double dParStart, dParEnd ; @@ -1046,7 +1074,7 @@ CurveComposite::TrimEndAtParam( double dUTrim) else if ( dUToTrim > - EPS_PARAM) { // imposto punto finale e verifico curva chiusa (*Iter)->GetEndPoint( m_PtEnd) ; - m_bClosed = ( AreSamePointNear( m_PtStart, m_PtEnd)) ; + m_bClosed = ( AreSamePointApprox( m_PtStart, m_PtEnd)) ; // passo alla entità successiva ++ Iter ; // dichiaro ingresso in zona da cancellare @@ -1062,7 +1090,7 @@ CurveComposite::TrimEndAtParam( double dUTrim) } // imposto punto finale e verifica curva chiusa (*Iter)->GetEndPoint( m_PtEnd) ; - m_bClosed = ( AreSamePointNear( m_PtStart, m_PtEnd)) ; + m_bClosed = ( AreSamePointApprox( m_PtStart, m_PtEnd)) ; // passo alla entità successiva ++ Iter ; // dichiaro ingresso in zona da cancellare @@ -1083,19 +1111,22 @@ CurveComposite::TrimStartEndAtParam( double dUStartTrim, double dUEndTrim) // verifico che i trim non cancellino interamente la curva if ( dUStartTrim > dUEndTrim - EPS_PARAM) return false ; + // per parametro start : determino la curva di appartenenza e il valore locale del parametro + int nCs ; + double dUcs ; + if ( ! GetIndSCurveAndLocPar( dUStartTrim, ICurve::FROM_PLUS, nCs, dUcs)) + return false ; + // per parametro end : determino la curva di appartenenza e il valore locale del parametro + int nCe ; + double dUce ; + if ( ! GetIndSCurveAndLocPar( dUEndTrim, ICurve::FROM_MINUS, nCe, dUce)) + return false ; // trim finale if ( ! TrimEndAtParam( dUEndTrim)) return false ; - // dominio parametrico della prima curva semplice - PCRVSMPL_LIST::iterator Iter = m_CrvSmplS.begin() ; - if ( Iter == m_CrvSmplS.end()) - return false ; - double dParStart, dParEnd ; - (*Iter)->GetDomain( dParStart, dParEnd) ; - double dUFirstCrv = ( dParEnd - dParStart) ; - // se il trim finale ha interessato la prima entità, devo opportunamente ricalcolare il parametro - if ( dUEndTrim < dUFirstCrv) { - double dNewUStartTrim = dUStartTrim / dUEndTrim ; + // se i due trim sono fatti sulla stessa curva devo compensare la riparametrizzazione dopo il primo + if ( nCs == nCe) { + double dNewUStartTrim = nCs + dUcs / dUce ; return TrimStartAtParam( dNewUStartTrim) ; } // altrimenti, va bene il valore ricevuto come parametro @@ -1109,7 +1140,7 @@ CurveComposite::TrimStartAtLen( double dLenTrim) { // ciclo sulle diverse curve dall'inizio double dLenToTrim = dLenTrim ; - PCRVSMPL_LIST::iterator Iter ; + PCRVSMPL_DEQUE::iterator Iter ; for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ;) { // lunghezza della curva double dCrvLen ; @@ -1133,7 +1164,7 @@ CurveComposite::TrimStartAtLen( double dLenTrim) if ( m_nCounter == 0) return false ; (*Iter)->GetStartPoint( m_PtStart) ; - m_bClosed = ( AreSamePointNear( m_PtStart, m_PtEnd)) ; + m_bClosed = ( AreSamePointApprox( m_PtStart, m_PtEnd)) ; break ; } // altrimenti superata lunghezza ancora da tagliare @@ -1143,7 +1174,7 @@ CurveComposite::TrimStartAtLen( double dLenTrim) return false ; } (*Iter)->GetStartPoint( m_PtStart) ; - m_bClosed = ( AreSamePointNear( m_PtStart, m_PtEnd)) ; + m_bClosed = ( AreSamePointApprox( m_PtStart, m_PtEnd)) ; break ; } } @@ -1161,7 +1192,7 @@ CurveComposite::TrimEndAtLen( double dLenTrim) // ciclo sulle diverse curve dalla fine bool bToErase = false ; double dLenToTrim = dLenTrim ; - PCRVSMPL_LIST::iterator Iter ; + PCRVSMPL_DEQUE::iterator Iter ; for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ;) { double dCrvLen ; // se non sono già nella zona da cancellare, aggiorno lunghezze @@ -1189,7 +1220,7 @@ CurveComposite::TrimEndAtLen( double dLenTrim) else if ( dLenToTrim > - EPS_SMALL) { // imposto punto finale e verifica curva chiusa (*Iter)->GetEndPoint( m_PtEnd) ; - m_bClosed = ( AreSamePointNear( m_PtStart, m_PtEnd)) ; + m_bClosed = ( AreSamePointApprox( m_PtStart, m_PtEnd)) ; // passo alla entità successiva ++ Iter ; // dichiaro ingresso in zona da cancellare @@ -1204,7 +1235,7 @@ CurveComposite::TrimEndAtLen( double dLenTrim) } // imposto punto finale e verifica curva chiusa (*Iter)->GetEndPoint( m_PtEnd) ; - m_bClosed = ( AreSamePointNear( m_PtStart, m_PtEnd)) ; + m_bClosed = ( AreSamePointApprox( m_PtStart, m_PtEnd)) ; // passo alla entità successiva ++ Iter ; // dichiaro ingresso in zona da cancellare @@ -1226,7 +1257,7 @@ CurveComposite::Translate( const Vector3d& vtMove) m_OGrMgr.Reset() ; // traslo le singole curve - PCRVSMPL_LIST::iterator Iter ; + PCRVSMPL_DEQUE::iterator Iter ; for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) (*Iter)->Translate( vtMove) ; @@ -1249,7 +1280,7 @@ CurveComposite::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAn m_OGrMgr.Reset() ; // ruoto le singole curve - PCRVSMPL_LIST::iterator Iter ; + PCRVSMPL_DEQUE::iterator Iter ; for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) (*Iter)->Rotate( ptAx, vtAx, dCosAng, dSinAng) ; @@ -1278,7 +1309,7 @@ CurveComposite::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, dou } // scalo le singole curve - PCRVSMPL_LIST::iterator Iter ; + PCRVSMPL_DEQUE::iterator Iter ; for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) { // eseguo la scalatura if ( ! (*Iter)->Scale( frRef, dCoeffX, dCoeffY, dCoeffZ)) @@ -1304,7 +1335,7 @@ CurveComposite::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) m_OGrMgr.Reset() ; // specchio le singole curve - PCRVSMPL_LIST::iterator Iter ; + PCRVSMPL_DEQUE::iterator Iter ; for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) (*Iter)->Mirror( ptOn, vtNorm) ; @@ -1331,7 +1362,7 @@ CurveComposite::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector return false ; // eseguo scorrimento delle singole curve - PCRVSMPL_LIST::iterator Iter ; + PCRVSMPL_DEQUE::iterator Iter ; for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) (*Iter)->Shear( ptOn, vtNorm, vtDir, dCoeff) ; @@ -1354,7 +1385,7 @@ CurveComposite::ToGlob( const Frame3d& frRef) m_OGrMgr.Reset() ; // trasformo le singole curve - PCRVSMPL_LIST::iterator Iter ; + PCRVSMPL_DEQUE::iterator Iter ; for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) (*Iter)->ToGlob( frRef) ; @@ -1377,7 +1408,7 @@ CurveComposite::ToLoc( const Frame3d& frRef) m_OGrMgr.Reset() ; // trasformo le singole curve - PCRVSMPL_LIST::iterator Iter ; + PCRVSMPL_DEQUE::iterator Iter ; for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) (*Iter)->ToLoc( frRef) ; @@ -1404,7 +1435,7 @@ CurveComposite::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) m_OGrMgr.Reset() ; // trasformo le singole curve - PCRVSMPL_LIST::iterator Iter ; + PCRVSMPL_DEQUE::iterator Iter ; for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) { (*Iter)->LocToLoc( frOri, frDest) ; } @@ -1522,7 +1553,7 @@ CurveComposite::RemoveFirstOrLastCurve( bool bLast) // eseguo mini verifica m_nStatus = ( m_nCounter > 0 ? OK : TO_VERIFY) ; if ( m_nStatus == OK) - m_bClosed = ( AreSamePointNear( m_PtStart, m_PtEnd)) ; + m_bClosed = ( AreSamePointApprox( m_PtStart, m_PtEnd)) ; else m_bClosed = false ; return pCrv ; @@ -1535,9 +1566,9 @@ CurveComposite::RemoveFirstOrLastCurve( bool bLast) bool CurveComposite::IsParamAtJoint( double dU) const { - // se all'inizio, alla fine o lontano dagli interi - if ( fabs( dU) < EPS_ZERO || - fabs( dU - m_nCounter) < EPS_ZERO || + // se aperta e all'inizio o alla fine o lontano dagli interi non è giunzione + if ( ( ! m_bClosed && fabs( dU) < EPS_ZERO) || + ( ! m_bClosed && fabs( dU - m_nCounter) < EPS_ZERO) || fabs( dU - (int) ( dU + EPS_ZERO)) > EPS_ZERO) return false ; else @@ -1580,7 +1611,7 @@ bool CurveComposite::ArcsToBezierCurves( void) { // verifico le singole curve - PCRVSMPL_LIST::iterator Iter ; + PCRVSMPL_DEQUE::iterator Iter ; for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) { // se arco, devo trasformare in una o più curve di Bezier if ( (*Iter)->GetType() == CRV_ARC) { @@ -1608,12 +1639,17 @@ CurveComposite::ArcsToBezierCurves( void) if ( ! cCompo.ArcsToBezierCurves() || cCompo.GetCurveNumber() != nParts) return false ; // inserisco le curve prima dell'arco - m_CrvSmplS.splice( Iter, cCompo.m_CrvSmplS) ; + PCRVSMPL_DEQUE::iterator Iter2 ; + for ( Iter2 = cCompo.m_CrvSmplS.begin() ; Iter2 != cCompo.m_CrvSmplS.end() ; ++ Iter2) { + Iter = m_CrvSmplS.insert( Iter, (*Iter2)) ; + ++ Iter ; + } + cCompo.m_CrvSmplS.clear() ; + cCompo.m_nCounter = 0 ; // elimino l'arco (e sposto l'iteratore alla curva precedente) delete (*Iter) ; - PCRVSMPL_LIST::iterator ToErase = Iter ; + Iter = m_CrvSmplS.erase( Iter) ; -- Iter ; - m_CrvSmplS.erase( ToErase) ; // aggiorno il numero di curve m_nCounter += nParts - 1 ; } diff --git a/CurveComposite.h b/CurveComposite.h index cffb2f2..0e76bf1 100644 --- a/CurveComposite.h +++ b/CurveComposite.h @@ -19,7 +19,7 @@ #include "GeoObjRW.h" #include "/EgtDev/Include/EGkCurveComposite.h" #include "/EgtDev/Include/EgtLogger.h" -#include +#include //---------------------------------------------------------------------------- class CurveComposite : public ICurveComposite, public IGeoObjRW @@ -68,6 +68,12 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW virtual bool GetMidDir( Vector3d& vtDir) const { return ::GetTang( *this, 0.5 * m_nCounter, FROM_MINUS, vtDir) ; } virtual bool GetDomain( double& dStart, double& dEnd) const ; + virtual bool IsValidParam( double dPar, Side nSide) const + { return ::IsValidParam( *this, dPar, nSide) ; } + virtual bool IsStartParam( double dPar) const + { return ::IsStartParam( *this, dPar) ; } + virtual bool IsEndParam( double dPar) const + { return ::IsEndParam( *this, dPar) ; } virtual bool GetLength( double& dLen) const ; virtual bool GetLengthAtParam( double dU, double& dLen) const ; virtual bool GetParamAtLength( double dLen, double& dU) const ; @@ -127,20 +133,21 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW bool Copy( const CurveComposite& ccSrc) ; bool Validate( void) ; bool AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart = true) ; + bool GetIndSCurveAndLocPar( double dU, Side nS, int& nSCrv, double& dLocU) const ; private : enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ; private : - typedef std::list< ICurve*> PCRVSMPL_LIST ; + typedef std::deque PCRVSMPL_DEQUE ; private : ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto - Status m_nStatus ; // stato - int m_nCounter ; // contatore del numero di curve - PCRVSMPL_LIST m_CrvSmplS ; // lista di curve semplici - Point3d m_PtStart ; // punto iniziale - Point3d m_PtEnd ; // punto finale - bool m_bClosed ; // flag per indicare che la curva è chiusa - mutable PCRVSMPL_LIST::const_iterator m_Iter ; // iteratore + Status m_nStatus ; // stato + int m_nCounter ; // contatore del numero di curve + PCRVSMPL_DEQUE m_CrvSmplS ; // deque di curve semplici + Point3d m_PtStart ; // punto iniziale + Point3d m_PtEnd ; // punto finale + bool m_bClosed ; // flag per indicare che la curva è chiusa + mutable PCRVSMPL_DEQUE::const_iterator m_Iter ; // iteratore } ; diff --git a/CurveLine.h b/CurveLine.h index c1546f2..9ba389e 100644 --- a/CurveLine.h +++ b/CurveLine.h @@ -67,6 +67,12 @@ class CurveLine : public ICurveLine, public IGeoObjRW { return GetStartDir( vtDir) ; } virtual bool GetDomain( double& dStart, double& dEnd) const { dStart = 0 ; dEnd = 1 ; return ( m_nStatus == OK) ; } + virtual bool IsValidParam( double dPar, Side nSide) const + { return ::IsValidParam( *this, dPar, nSide) ; } + virtual bool IsStartParam( double dPar) const + { return ::IsStartParam( *this, dPar) ; } + virtual bool IsEndParam( double dPar) const + { return ::IsEndParam( *this, dPar) ; } virtual bool GetLength( double& dLen) const ; virtual bool GetLengthAtParam( double dU, double& dLen) const ; virtual bool GetParamAtLength( double dLen, double& dU) const ; diff --git a/DistPointCrvAux.cpp b/DistPointCrvAux.cpp index 94edc24..adfa3de 100644 --- a/DistPointCrvAux.cpp +++ b/DistPointCrvAux.cpp @@ -54,7 +54,7 @@ CalcMinDistPointPolyLine( const Point3d& ptP, PolyLine& PL, MDCVECTOR& vApproxMi approxMin.dParMin = dUIni ; approxMin.dParMax = dUFin ; // setto che il punto è alla fine - bOnEnd = ( AreSamePointNear( approxMin.ptQ, ptFin)) ; + bOnEnd = ( AreSamePointApprox( approxMin.ptQ, ptFin)) ; // aggiungo alla lista vApproxMin.push_back( approxMin) ; } @@ -72,7 +72,7 @@ CalcMinDistPointPolyLine( const Point3d& ptP, PolyLine& PL, MDCVECTOR& vApproxMi approxMin.dParMin = dUIni ; approxMin.dParMax = dUFin ; // setto che il punto è alla fine - bOnEnd = ( AreSamePointNear( approxMin.ptQ, ptFin)) ; + bOnEnd = ( AreSamePointApprox( approxMin.ptQ, ptFin)) ; // il nuovo vettore deve contenere solo quest'ultimo minimo vApproxMin.clear() ; vApproxMin.push_back( approxMin) ; diff --git a/DistPointCrvComposite.cpp b/DistPointCrvComposite.cpp index ae3e38e..c380f03 100644 --- a/DistPointCrvComposite.cpp +++ b/DistPointCrvComposite.cpp @@ -69,7 +69,7 @@ DistPointCrvComposite::DistPointCrvComposite( const Point3d& ptP, const ICurveCo aInfo.dPar += dIniCrvPar ; // se il primo nuovo punto coincide con l'ultimo dei precedenti if ( i == 0 && fabs( m_Info.back().dPar - aInfo.dPar) < EPS_SMALL && - AreSamePointNear( m_Info.back().ptQ, aInfo.ptQ)) { + AreSamePointApprox( m_Info.back().ptQ, aInfo.ptQ)) { if ( m_Info.back().nFlag == MDPCI_NORMAL) { // START deve sostituire il vecchio if ( aInfo.nFlag == MDPCI_START_CONT) diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 526cbd9..eea0a67 100644 Binary files a/EgtGeomKernel.rc and b/EgtGeomKernel.rc differ diff --git a/EgtGeomKernel.vcxproj b/EgtGeomKernel.vcxproj index be40c0f..37b4b46 100644 --- a/EgtGeomKernel.vcxproj +++ b/EgtGeomKernel.vcxproj @@ -258,6 +258,7 @@ copy $(TargetPath) \EgtProg\Dll64 + @@ -362,6 +363,7 @@ copy $(TargetPath) \EgtProg\Dll64 + diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters index d99c584..9fe9e08 100644 --- a/EgtGeomKernel.vcxproj.filters +++ b/EgtGeomKernel.vcxproj.filters @@ -195,6 +195,9 @@ File di origine\GeoInters + + File di origine\GeoInters + @@ -479,6 +482,9 @@ File di intestazione + + File di intestazione + diff --git a/ExtText.cpp b/ExtText.cpp index 6a6b5e2..9c1bbc9 100644 --- a/ExtText.cpp +++ b/ExtText.cpp @@ -23,8 +23,6 @@ using namespace std ; -//---------------------------------------------------------------------------- - //---------------------------------------------------------------------------- GEOOBJ_REGISTER( EXT_TEXT, NGE_E_TXT, ExtText) ; @@ -44,7 +42,7 @@ ExtText::~ExtText( void) bool ExtText::Set( const string& sText, const Point3d& ptP, double dAngDeg, double dH) { - // controllo testo + // controllo testo non vuoto if ( sText.empty()) return false ; // assegno i dati @@ -72,9 +70,12 @@ ExtText::Set( const string& sText, const Point3d& ptP, double dAngDeg, const string& sFont, int nW, bool bItl, double dH, double dRat, double dAddAdv, int nInsPos) { - // controllo testo + // controllo testo non vuoto if ( sText.empty()) return false ; + // controllo lunghezza nome font + if ( sFont.size() > MAX_FONT_LEN) + return false ; // assegno i dati m_ptP = ptP ; m_vtN = Z_AX ; @@ -100,9 +101,12 @@ ExtText::Set( const string& sText, const Point3d& ptP, const Vector3d& vtN, cons const string& sFont, int nW, bool bItl, double dH, double dRat, double dAddAdv, int nInsPos) { - // controllo testo + // controllo testo non vuoto if ( sText.empty()) return false ; + // controllo lunghezza nome font + if ( sFont.size() > MAX_FONT_LEN) + return false ; // assegno i dati m_ptP = ptP ; m_vtN = vtN ; @@ -232,8 +236,23 @@ ExtText::Save( NgeWriter& ngeOut) const if ( ! ngeOut.WriteVector( m_vtD, ";", true)) return false ; // testo - if ( ! ngeOut.WriteString( m_sText, nullptr, true)) + int nTextLines = int( m_sText.size()) / MAX_TXT_LINE + + ( ( int( m_sText.size()) % MAX_TXT_LINE) > 0 ? 1 : 0) ; + if ( ! ngeOut.WriteInt( nTextLines, ";", true)) return false ; + string sBuff ; + for ( int i = 0 ; i < nTextLines ; ++ i) { + // copio i caratteri nel buffer + sBuff = m_sText.substr( i * MAX_TXT_LINE, MAX_TXT_LINE) ; + // sostituisco eventuale primo o ultimo spazio con carattere speciale + if ( sBuff.front() == ' ') + sBuff.front() = CHR_SPECIAL ; + if ( sBuff.back() == ' ') + sBuff.back() = CHR_SPECIAL ; + // scrivo il testo + if ( ! ngeOut.WriteString( sBuff, nullptr, true)) + return false ; + } // font if ( ! ngeOut.WriteString( m_sFont, ";")) return false ; @@ -271,9 +290,24 @@ ExtText::Load( NgeReader& ngeIn) return false ; if ( ! ngeIn.ReadVector( m_vtD, ";", true)) return false ; - // leggo la prossima linea : testo - if ( ! ngeIn.ReadString( m_sText, nullptr, true)) + // leggo la prossima linea : numero di righe di testo + int nTextLines ; + if ( ! ngeIn.ReadInt( nTextLines, ";", true)) return false ; + // leggo le stringhe che costituisco il testo + string sBuff ; + for ( int i = 0 ; i < nTextLines ; ++i) { + // leggo la linea + if ( ! ngeIn.ReadString( sBuff, nullptr, true)) + return false ; + // sostituisco eventuale primo o ultimo carattere speciale con spazio + if ( sBuff.front() == CHR_SPECIAL) + sBuff.front() = ' ' ; + if ( sBuff.back() == CHR_SPECIAL) + sBuff.back() = ' ' ; + // la accodo + m_sText += sBuff ; + } // leggo la prossima linea : font, spessore, italico, altezza, ratio, addAdvance if ( ! ngeIn.ReadString( m_sFont, ";")) return false ; diff --git a/ExtText.h b/ExtText.h index 646ec2e..621e619 100644 --- a/ExtText.h +++ b/ExtText.h @@ -110,6 +110,11 @@ class ExtText : public IExtText, public IGeoObjRW private : bool Copy( const ExtText& gpSrc) ; + private : + static const int MAX_FONT_LEN = 125 ; + static const int MAX_TXT_LINE = 125 ; + static const char CHR_SPECIAL = '\a' ; + private : ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto Point3d m_ptP ; // punto di inserimento diff --git a/FontOs.cpp b/FontOs.cpp index e2780d3..785d05e 100644 --- a/FontOs.cpp +++ b/FontOs.cpp @@ -468,7 +468,7 @@ OsFont::GetCharOutline( unsigned int nChar, double& dAdvance, ICURVEPLIST& lstPC Point3d ptP( DoubleFromFixed( pCurve->apfx[i].x), DoubleFromFixed( pCurve->apfx[i].y), 0) ; - if ( ! AreSamePointNear( ptLast, ptP)) { + if ( ! AreSamePointApprox( ptLast, ptP)) { // aggiungo la retta alla curva composita if ( ! AddLineToCompo( ::Get( pCCompo), ptLast, ptP)) return false ; @@ -511,7 +511,7 @@ OsFont::GetCharOutline( unsigned int nChar, double& dAdvance, ICURVEPLIST& lstPC pCurve = (LPTTPOLYCURVE) &( pCurve->apfx[nPnt]) ; } // si aggiunge, se necessario, una linea retta per chiudere la curva - if ( ! AreSamePointNear( ptFirst, ptLast)) { + if ( ! AreSamePointApprox( ptFirst, ptLast)) { // aggiungo la retta alla curva composita if ( ! AddLineToCompo( ::Get( pCCompo), ptLast, ptFirst)) return false ; diff --git a/GdbExecutor.cpp b/GdbExecutor.cpp index 8ec6539..a340f2e 100644 --- a/GdbExecutor.cpp +++ b/GdbExecutor.cpp @@ -19,7 +19,7 @@ #include "GeoConst.h" #include "GeomDB.h" #include "DllMain.h" -#include "/EgtDev/Include/EgnStringUtils.h" +#include "/EgtDev/Include/EgkStringUtils3d.h" #include "/EgtDev/Include/EgnStringConverter.h" #include "/EgtDev/Include/EgnCmdParser.h" #include "/EgtDev/Include/EgkGeoPoint3d.h" @@ -127,6 +127,7 @@ GdbExecutor::GdbExecutor( void) m_ExecMgr.Insert( "NEW", &GdbExecutor::ExecuteNew) ; m_ExecMgr.Insert( "LOAD", &GdbExecutor::ExecuteLoad) ; m_ExecMgr.Insert( "SAVE", &GdbExecutor::ExecuteSave) ; + m_ExecMgr.Insert( "OUTTEXTICCI", &GdbExecutor::ExecuteOutTextIcci) ; m_ExecMgr.Insert( "OUTTSC", &GdbExecutor::ExecuteOutTsc) ; } @@ -2438,6 +2439,10 @@ GdbExecutor::TextSimple( const STRVECTOR& vsParams) Frame3d frRef ; if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef)) return false ; + // recupero il testo + string sText ; + if ( ! GetTextParam( vsParams[2], sText)) + return false ; // recupero il punto di inserimento Point3d ptP ; if ( ! GetPointParam( vsParams[3], frRef, ptP)) @@ -2455,7 +2460,7 @@ GdbExecutor::TextSimple( const STRVECTOR& vsParams) if ( ! IsValid( pTXT)) return false ; // lo riempio - if ( ! pTXT->Set( vsParams[2], ptP, dAngRotDeg, dH)) + if ( ! pTXT->Set( sText, ptP, dAngRotDeg, dH)) return false ; // inserisco il testo nel DB return AddGeoObj( vsParams[0], vsParams[1], Release( pTXT)) ; @@ -2472,6 +2477,10 @@ GdbExecutor::TextComplete( const STRVECTOR& vsParams) Frame3d frRef ; if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef)) return false ; + // recupero il testo + string sText ; + if ( ! GetTextParam( vsParams[2], sText)) + return false ; // recupero il punto di inserimento Point3d ptP ; if ( ! GetPointParam( vsParams[3], frRef, ptP)) @@ -2526,7 +2535,7 @@ GdbExecutor::TextComplete( const STRVECTOR& vsParams) if ( ! IsValid( pTXT)) return false ; // lo riempio - if ( ! pTXT->Set( vsParams[2], ptP, dAngRotDeg, vsParams[5], nW, bItl, dH, dRat, dAddAdv, nInsPos)) + if ( ! pTXT->Set( sText, ptP, dAngRotDeg, vsParams[5], nW, bItl, dH, dRat, dAddAdv, nInsPos)) return false ; // inserisco il testo nel DB return AddGeoObj( vsParams[0], vsParams[1], Release( pTXT)) ; @@ -2539,12 +2548,16 @@ GdbExecutor::TextModifyText( const STRVECTOR& vsParams) // 2 parametri : Id, NewText if ( vsParams.size() != 2) return false ; + // recupero il testo + string sText ; + if ( ! GetTextParam( vsParams[1], sText)) + return false ; // recupero il testo IExtText* pTXT = GetExtText( m_pGDB->GetGeoObj( GetIdParam( vsParams[0]))) ; if ( pTXT == nullptr) return false ; // eseguo l'operazione - return pTXT->ModifyText( vsParams[1]) ; + return pTXT->ModifyText( sText) ; } //---------------------------------------------------------------------------- @@ -2554,12 +2567,16 @@ GdbExecutor::TextChangeFont( const STRVECTOR& vsParams) // 2 parametri : Id, NewFont if ( vsParams.size() != 2) return false ; + // recupero il nome del font + string sFont ; + if ( ! GetTextParam( vsParams[1], sFont)) + return false ; // recupero il testo IExtText* pTXT = GetExtText( m_pGDB->GetGeoObj( GetIdParam( vsParams[0]))) ; if ( pTXT == nullptr) return false ; // eseguo l'operazione - return pTXT->ChangeFont( vsParams[1]) ; + return pTXT->ChangeFont( sFont) ; } //---------------------------------------------------------------------------- @@ -3491,6 +3508,13 @@ GdbExecutor::GetColorParam( const string& sParam, bool& bByParent, Color& cCol) return false ; } +//---------------------------------------------------------------------------- +bool +GdbExecutor::GetTextParam( const string& sParam, string& sText) +{ + return m_pParser->GetTextParam( sParam, sText) ; +} + //---------------------------------------------------------------------------- bool GdbExecutor::ExecuteLevel( const string& sCmd2, const STRVECTOR& vsParams) @@ -4491,6 +4515,112 @@ GdbExecutor::ExecuteSave( const string& sCmd2, const STRVECTOR& vsParams) return m_pGDB->Save( sFile, nFlag) ; } +//---------------------------------------------------------------------------- +bool +GdbExecutor::ExecuteOutTextIcci( const string& sCmd2, const STRVECTOR& vsParams) +{ + // devono essere 6 parametri : IdText, IdGroup, IdEnt1, IdEnt2, ptText, hText + if ( vsParams.size() != 6) + return false ; + // recupero l'indice delle entità + int nIdEnt1 = GetIdParam( vsParams[2]) ; + int nIdEnt2 = GetIdParam( vsParams[3]) ; + // verifico siano due curve + const ICurve* pCrv1 = GetCurve( m_pGDB->GetGeoObj( nIdEnt1)) ; + if ( pCrv1 == nullptr) + return false ; + const ICurve* pCrv2 = GetCurve( m_pGDB->GetGeoObj( nIdEnt2)) ; + if ( pCrv2 == nullptr) + return false ; + // recupero i riferimenti in cui sono immerse + Frame3d frEnt1 ; + if ( ! m_pGDB->GetGlobFrame( nIdEnt1, frEnt1)) + return false ; + Frame3d frEnt2 ; + if ( ! m_pGDB->GetGlobFrame( nIdEnt2, frEnt2)) + return false ; + // se i riferimenti sono diversi, porto la seconda entità nel riferimento della prima + PtrOwner crvTrans( nullptr) ; + if ( ! AreSameFrame( frEnt1, frEnt2)) { + crvTrans.Set( pCrv2->Clone()) ; + if ( ! ::IsValid( crvTrans)) + return false ; + crvTrans->LocToLoc( frEnt2, frEnt1) ; + pCrv2 = ::Get( crvTrans) ; + } + // calcolo le intersezioni tra le due curve + IntersCurveCurve intCC( *pCrv1, *pCrv2, true) ; + // preparo il testo con i risultati + string sText = "Inters CrvA=" + ToString( nIdEnt1) + " CrvB=" + ToString( nIdEnt2) ; + sText += "
Nbr=" + ToString( intCC.GetNumInters()) ; + if ( intCC.GetOverlaps()) + sText += " Overlaps" ; + for ( int i = 0 ; i < intCC.GetNumInters() ; ++ i) { + IntCrvCrvInfo aInfo ; + intCC.GetIntCrvCrvInfo( i, aInfo) ; + int nMax = ( aInfo.bOverlap ? 2 : 1) ; + for ( int j = 0 ; j < nMax ; ++ j) { + if ( j == 0) + sText += "
" + ToString( i + 1) + "A" ; + else + sText += "
" ; + sText += " U=" + ToString( aInfo.IciA[j].dU,7) + " P=(" + ToString( aInfo.IciA[j].ptI,4) + ")" ; + switch( aInfo.IciA[j].nPrevTy) { + case ICCT_NULL : sText += " ??-" ; break ; + case ICCT_IN : sText += " IN-" ; break ; + case ICCT_OUT : sText += " OUT-" ; break ; + case ICCT_ON : sText += " ON-" ; break ; + } + switch( aInfo.IciA[j].nNextTy) { + case ICCT_NULL : sText += "??" ; break ; + case ICCT_IN : sText += "IN" ; break ; + case ICCT_OUT : sText += "OUT" ; break ; + case ICCT_ON : sText += "ON" ; break ; + } + } + for ( int j = 0 ; j < nMax ; ++ j) { + if ( j == 0) + sText += "
" + ToString( i + 1) + "B" ; + else + sText += string( "
") + ( aInfo.bCBOverEq ? " + " : " - ") ; + sText += " U=" + ToString( aInfo.IciB[j].dU,7) + " P=(" + ToString( aInfo.IciB[j].ptI,4) + ")" ; + switch( aInfo.IciB[j].nPrevTy) { + case ICCT_NULL : sText += " ??-" ; break ; + case ICCT_IN : sText += " IN-" ; break ; + case ICCT_OUT : sText += " OUT-" ; break ; + case ICCT_ON : sText += " ON-" ; break ; + } + switch( aInfo.IciB[j].nNextTy) { + case ICCT_NULL : sText += "??" ; break ; + case ICCT_IN : sText += "IN" ; break ; + case ICCT_OUT : sText += "OUT" ; break ; + case ICCT_ON : sText += "ON" ; break ; + } + } + } + // recupero il riferimento in cui è immerso il testo + Frame3d frText ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frText)) + return false ; + // recupero il punto di inserimento + Point3d ptText ; + if ( ! GetPointParam( vsParams[4], frText, ptText)) + return false ; + // recupero l'altezza del carattere + double dH ; + if ( ! FromString( vsParams[5], dH)) + return false ; + // creo il testo + PtrOwner pTXT( CreateExtText()) ; + if ( ! IsValid( pTXT)) + return false ; + // lo riempio + if ( ! pTXT->Set( sText, ptText, 0, dH)) + return false ; + // inserisco il testo nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pTXT)) ; +} + //---------------------------------------------------------------------------- bool GdbExecutor::ExecuteOutTsc( const string& sCmd2, const STRVECTOR& vsParams) diff --git a/GdbExecutor.h b/GdbExecutor.h index e7b0433..34aae48 100644 --- a/GdbExecutor.h +++ b/GdbExecutor.h @@ -49,6 +49,7 @@ class GdbExecutor : public IGdbExecutor bool GetDirParam( const std::string& sParam, const Frame3d& frDir, double& dDir) ; bool GetFrameParam( const std::string& sParam, const Frame3d& frRef, Frame3d& frF) ; bool GetColorParam( const std::string& sParam, bool& bByParent, Color& cCol) ; + bool GetTextParam( const std::string& sParam, std::string& sText) ; bool GetPolylineFromCurve( int nId, const Frame3d& frDest, double dLinTol, PolyLine& PL) ; bool ExecuteGroup( const std::string& sCmd2, const STRVECTOR& vsParams) ; bool ExecutePoint( const std::string& sCmd2, const STRVECTOR& vsParams) ; @@ -137,6 +138,7 @@ class GdbExecutor : public IGdbExecutor bool ExecuteNew( const std::string& sCmd2, const STRVECTOR& vsParams) ; bool ExecuteLoad( const std::string& sCmd2, const STRVECTOR& vsParams) ; bool ExecuteSave( const std::string& sCmd2, const STRVECTOR& vsParams) ; + bool ExecuteOutTextIcci( const std::string& sCmd2, const STRVECTOR& vsParams) ; bool ExecuteOutTsc( const std::string& sCmd2, const STRVECTOR& vsParams) ; bool OutGroupTsc( int nId, int nFlag, int nLev = 0) ; diff --git a/IntersCrvCompoCrvCompo.cpp b/IntersCrvCompoCrvCompo.cpp new file mode 100644 index 0000000..23dc4e3 --- /dev/null +++ b/IntersCrvCompoCrvCompo.cpp @@ -0,0 +1,504 @@ +//---------------------------------------------------------------------------- +// EgalTech 2014-2014 +//---------------------------------------------------------------------------- +// File : IntersCrvCompoCrvCompo.cpp Data : 24.06.14 Versione : 1.5f6 +// Contenuto : Implementazione della classe intersezione curva composita/cc. +// +// +// +// Modifiche : 24.06.14 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "IntersCrvCompoCrvCompo.h" +#include + +using namespace std ; + +//---------------------------------------------------------------------------- +bool +SortGreater( const IntCrvCrvInfo& aInfo1, const IntCrvCrvInfo& aInfo2) +{ + double dU1 = ( aInfo1.bOverlap ? 0.5 * ( aInfo1.IciA[0].dU + aInfo1.IciA[1].dU) : aInfo1.IciA[0].dU) ; + double dU2 = ( aInfo2.bOverlap ? 0.5 * ( aInfo2.IciA[0].dU + aInfo2.IciA[1].dU) : aInfo2.IciA[0].dU) ; + return ( dU2 > dU1 + EPS_PARAM) ; +} + +//---------------------------------------------------------------------------- +void +MediaParamPoints( IntCrvInfo& Ici1, IntCrvInfo& Ici2) +{ + // medio i parametri e i punti + // per non mediare i parametri tra gli estremi di curva chiusa + if ( fabs( Ici1.dU - Ici2.dU) < HSPAN_PARAM) { + Ici1.dU = 0.5 * ( Ici1.dU + Ici2.dU) ; + Ici2.dU = Ici1.dU ; + } + Ici1.ptI = 0.5 * ( Ici1.ptI + Ici2.ptI) ; + Ici2.ptI = Ici1.ptI ; +} + +//---------------------------------------------------------------------------- +// Prev della curva B ma tenendo conto della direzione di A +// => se controverse va preso Next +int +GetCrvBDirAPrev( IntCrvCrvInfo& Icci) +{ + // non è overlap, è il prev del primo punto + if ( ! Icci.bOverlap) + return Icci.IciB[0].nPrevTy ; + // è overlap equiverso, è il prev del primo punto + if ( Icci.bCBOverEq) + return Icci.IciB[0].nPrevTy ; + // è overlap controverso, è il next del primo punto + return Icci.IciB[0].nNextTy ; +} + +//---------------------------------------------------------------------------- +// Next della curva B ma tenendo conto della direzione di A +// => se controverse va preso Prev +int +GetCrvBDirANext( IntCrvCrvInfo& Icci) +{ + // non è overlap, è il next del primo punto + if ( ! Icci.bOverlap) + return Icci.IciB[0].nNextTy ; + // è overlap equiverso, è il next del secondo punto + if ( Icci.bCBOverEq) + return Icci.IciB[1].nNextTy ; + // è overlap controverso, è il prev del secondo punto + return Icci.IciB[1].nPrevTy ; +} + +//---------------------------------------------------------------------------- +bool +CalcATypeFromDisk( const ICurveComposite& CCompoA, double dUA, ICurve::Side nSideA, + const ICurveComposite& CCompoB, double dUB, int& nType) +{ + // devo studiare un intorno dell'intersezione + Point3d ptP ; + // direzione di arrivo (FROM_MINUS) o partenza (FROM_PLUS) curva A + Vector3d vtADir ; + if ( ! CCompoA.IsValidParam( dUA, nSideA) || + ! CCompoA.GetPointTang( dUA, nSideA, ptP, vtADir)) + return false ; + if ( nSideA == ICurve::FROM_MINUS) + vtADir *= - 1 ; + // direzioni di arrivo (prev) e partenza (next) curva B + Vector3d vtBpDir ; + if ( ! CCompoB.IsValidParam( dUB, ICurve::FROM_MINUS) || + ! CCompoB.GetPointTang( dUB, ICurve::FROM_MINUS, ptP, vtBpDir)) + return false ; + vtBpDir *= - 1 ; + Vector3d vtBnDir ; + if ( ! CCompoB.IsValidParam( dUB, ICurve::FROM_PLUS) || + ! CCompoB.GetPointTang( dUB, ICurve::FROM_PLUS, ptP, vtBnDir)) + return false ; + // angolo del versore DirA rispetto a DirBn + double dAngADeg ; + if ( ! vtBnDir.GetAngleXY( vtADir, dAngADeg)) + return false ; + if ( dAngADeg < 0) + dAngADeg += ANG_FULL ; + // angolo del versore DirBp rispetto a DirBn + double dAngBpDeg ; + if ( ! vtBnDir.GetAngleXY( vtBpDir, dAngBpDeg)) + return false ; + if ( dAngBpDeg < 0) + dAngBpDeg += ANG_FULL ; + // se l'angolo di DirA è compreso tra DirBn e DirBp (muovendosi in senso CCW) allora è IN, altrimenti OUT + if ( dAngADeg > 0 && dAngADeg < dAngBpDeg) + nType = ICCT_IN ; + else + nType = ICCT_OUT ; + return true ; +} + +//---------------------------------------------------------------------------- +IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA, const ICurveComposite& CCompoB) +{ + // Le intersezioni sono calcolate nel piano XY locale. + + // nessuna intersezione trovata + m_bOverlaps = false ; + m_nNumInters = 0 ; + m_Info.clear() ; + + // doppio ciclo sulle entità delle curve composite + // !!! questa parte è O(N^2), vanno usate Grid Gerarchiche o BVH per renderla O(N*logN) !!! + int nCountA = 0 ; + for ( const ICurve* pCrvA = CCompoA.GetFirstCurve() ; + pCrvA != nullptr ; + pCrvA = CCompoA.GetNextCurve(), ++ nCountA) { + int nCountB = 0 ; + for ( const ICurve* pCrvB = CCompoB.GetFirstCurve() ; + pCrvB != nullptr ; + pCrvB = CCompoB.GetNextCurve(), ++ nCountB) { + // eseguo l'intersezione di queste curve elementari + IntersCurveCurve intCC( *pCrvA, *pCrvB) ; + // ne recupero i risultati + int nCurrInters = intCC.GetNumInters() ; + if ( nCurrInters > 0) { + m_nNumInters += nCurrInters ; + m_bOverlaps = ( intCC.GetOverlaps() ? true : m_bOverlaps) ; + for ( int i = 0 ; i < nCurrInters ; ++ i) { + IntCrvCrvInfo aInfo ; + intCC.GetIntCrvCrvInfo( i, aInfo) ; + aInfo.IciA[0].dU += nCountA ; + aInfo.IciB[0].dU += nCountB ; + if ( aInfo.bOverlap) { + aInfo.IciA[1].dU += nCountA ; + aInfo.IciB[1].dU += nCountB ; + } + m_Info.push_back( aInfo) ; + } + } + } + } + + // ordino le intersezioni secondo l'ordine crescente del parametro della prima curva + stable_sort( m_Info.begin(), m_Info.end(), SortGreater) ; + + // sistemazione di intersezioni coincidenti + for ( int i = 0 ; i < m_nNumInters ; ++ i) { + // calcolo indice precedente + int j = i - 1 ; + if ( i == 0) { + // se prima curva aperta, salto alla prossima + if ( ! CCompoA.IsClosed()) + continue ; + // è chiusa quindi prendo l'ultima + j = m_nNumInters - 1 ; + } + // se i due indici coincidono, c'è una sola intersezione e posso uscire + if ( i == j) + break ; + // calcolo sottoindici + int ki = 0 ; // del successivo si prende sempre il primo + int kj = ( m_Info[j].bOverlap ? 1 : 0) ; // del precedente si prende il secondo se overlap + // verifico se precedente e corrente si riferiscono alla stessa intersezione (10 * EPS_SMALL) + if ( SqDist( m_Info[i].IciA[ki].ptI, m_Info[j].IciA[kj].ptI) < ( 100 * EPS_SMALL * EPS_SMALL) && + SqDist( m_Info[i].IciB[ki].ptI, m_Info[j].IciB[kj].ptI) < ( 100 * EPS_SMALL * EPS_SMALL)) { + // caso DET-NULL -> NULL-DET per prima curva + if ( m_Info[j].IciA[kj].nPrevTy != ICCT_NULL && m_Info[j].IciA[kj].nNextTy == ICCT_NULL && + m_Info[i].IciA[ki].nPrevTy == ICCT_NULL && m_Info[i].IciA[ki].nNextTy != ICCT_NULL) { + // per la prima curva tengo i determinati + m_Info[i].IciA[ki].nPrevTy = m_Info[j].IciA[kj].nPrevTy ; + m_Info[j].IciA[kj].nNextTy = m_Info[i].IciA[ki].nNextTy ; + // se overlap equiverso + if ( m_Info[i].bOverlap && m_Info[i].bCBOverEq) { + // per la seconda curva ogni sottotipo è il duale di quello della prima + m_Info[i].IciB[ki].nPrevTy = GetDualIcct( m_Info[i].IciA[ki].nPrevTy) ; + m_Info[i].IciB[ki].nNextTy = GetDualIcct( m_Info[i].IciA[ki].nNextTy) ; + } + // se altrimenti overlap controverso + else if ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq) { + // per la seconda curva ogni sottotipo è come quello della prima ma in posizione invertita + m_Info[i].IciB[ki].nPrevTy = m_Info[i].IciA[ki].nNextTy ; + m_Info[i].IciB[ki].nNextTy = m_Info[i].IciA[ki].nPrevTy ; + } + // se overlap equiverso + if ( m_Info[j].bOverlap && m_Info[j].bCBOverEq) { + m_Info[j].IciB[kj].nPrevTy = GetDualIcct( m_Info[i].IciA[ki].nPrevTy) ; + m_Info[j].IciB[kj].nNextTy = GetDualIcct( m_Info[i].IciA[ki].nNextTy) ; + } + // se altrimenti overlap controverso + else if ( m_Info[j].bOverlap && ! m_Info[j].bCBOverEq) { + m_Info[j].IciB[kj].nPrevTy = m_Info[i].IciA[ki].nNextTy ; + m_Info[j].IciB[kj].nNextTy = m_Info[i].IciA[ki].nPrevTy ; + } + // medio parametri e punti separatamente per le due curve + MediaParamPoints( m_Info[i].IciA[ki], m_Info[j].IciA[kj]) ; + MediaParamPoints( m_Info[i].IciB[ki], m_Info[j].IciB[kj]) ; + // se entrambi overlap non cancello + if ( m_Info[j].bOverlap && m_Info[i].bOverlap) + continue ; + // cancello un singolo + int k = ( ! m_Info[i].bOverlap ? i : j) ; + m_Info.erase( m_Info.begin() + k) ; + -- i ; + -- m_nNumInters ; + } + // caso NULL-DET -> DET-NULL per prima curva (possibile su inizio/fine di curva chiusa) + else if ( m_Info[j].IciA[kj].nPrevTy == ICCT_NULL && m_Info[j].IciA[kj].nNextTy != ICCT_NULL && + m_Info[i].IciA[ki].nPrevTy != ICCT_NULL && m_Info[i].IciA[ki].nNextTy == ICCT_NULL) { + // per la prima curva tengo i determinati + m_Info[i].IciA[ki].nNextTy = m_Info[j].IciA[kj].nNextTy ; + m_Info[j].IciA[kj].nPrevTy = m_Info[i].IciA[ki].nPrevTy ; + // se overlap equiverso + if ( m_Info[i].bOverlap && m_Info[i].bCBOverEq) { + // per la seconda curva ogni sottotipo è il duale di quello della prima + m_Info[i].IciB[ki].nPrevTy = GetDualIcct( m_Info[i].IciA[ki].nPrevTy) ; + m_Info[i].IciB[ki].nNextTy = GetDualIcct( m_Info[i].IciA[ki].nNextTy) ; + } + // se altrimenti overlap controverso + else if ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq) { + // per la seconda curva ogni sottotipo è come quello della prima ma in posizione scambiata + m_Info[i].IciB[ki].nPrevTy = m_Info[i].IciA[ki].nNextTy ; + m_Info[i].IciB[ki].nNextTy = m_Info[i].IciA[ki].nPrevTy ; + } + // se overlap equiverso + if ( m_Info[j].bOverlap && m_Info[j].bCBOverEq) { + // per la seconda curva ogni sottotipo è il duale di quello della prima + m_Info[j].IciB[kj].nPrevTy = GetDualIcct( m_Info[i].IciA[ki].nPrevTy) ; + m_Info[j].IciB[kj].nNextTy = GetDualIcct( m_Info[i].IciA[ki].nNextTy) ; + } + // se altrimenti overlap controverso + else if ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq) { + // per la seconda curva ogni sottotipo è come quello della prima ma in posizione scambiata + m_Info[j].IciB[kj].nPrevTy = m_Info[i].IciA[ki].nNextTy ; + m_Info[j].IciB[kj].nNextTy = m_Info[i].IciA[ki].nPrevTy ; + } + // medio parametri e punti separatamente per le due curve + MediaParamPoints( m_Info[i].IciA[ki], m_Info[j].IciA[kj]) ; + MediaParamPoints( m_Info[i].IciB[ki], m_Info[j].IciB[kj]) ; + // se entrambi overlap non cancello + if ( m_Info[j].bOverlap && m_Info[i].bOverlap) + continue ; + // cancello un singolo + int k = ( ! m_Info[i].bOverlap ? i : j) ; + m_Info.erase( m_Info.begin() + k) ; + -- i ; + -- m_nNumInters ; + } + // caso DET-NULL -> NULL-DET per seconda curva + else if ( m_Info[j].IciB[kj].nPrevTy != ICCT_NULL && m_Info[j].IciB[kj].nNextTy == ICCT_NULL && + m_Info[i].IciB[ki].nPrevTy == ICCT_NULL && m_Info[i].IciB[ki].nNextTy != ICCT_NULL) { + // per la seconda curva tengo i determinati + m_Info[i].IciB[ki].nPrevTy = m_Info[j].IciB[kj].nPrevTy ; + m_Info[j].IciB[kj].nNextTy = m_Info[i].IciB[ki].nNextTy ; + // se overlap equiverso + if ( m_Info[i].bOverlap && m_Info[i].bCBOverEq) { + // per la prima curva ogni sottotipo è il duale di quello della seconda + m_Info[i].IciA[ki].nPrevTy = GetDualIcct( m_Info[i].IciB[ki].nPrevTy) ; + m_Info[i].IciA[ki].nNextTy = GetDualIcct( m_Info[i].IciB[ki].nNextTy) ; + } + // se altrimenti overlap controverso + else if ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq) { + // per la prima curva ogni sottotipo è come quello della seconda ma in posizione scambiata + m_Info[i].IciA[ki].nPrevTy = m_Info[i].IciB[ki].nNextTy ; + m_Info[i].IciA[ki].nNextTy = m_Info[i].IciB[ki].nPrevTy ; + } + // se overlap equiverso + if ( m_Info[j].bOverlap && m_Info[j].bCBOverEq) { + // per la prima curva ogni sottotipo è il duale di quello della seconda + m_Info[j].IciA[kj].nPrevTy = GetDualIcct( m_Info[i].IciB[ki].nPrevTy) ; + m_Info[j].IciA[kj].nNextTy = GetDualIcct( m_Info[i].IciB[ki].nNextTy) ; + } + // se altrimenti overlap controverso + else if ( m_Info[j].bOverlap && ! m_Info[j].bCBOverEq) { + // per la prima curva ogni sottotipo è come quello della seconda ma in posizione scambiata + m_Info[j].IciA[kj].nPrevTy = m_Info[i].IciB[ki].nNextTy ; + m_Info[j].IciA[kj].nNextTy = m_Info[i].IciB[ki].nPrevTy ; + } + // medio parametri e punti separatamente per le due curve + MediaParamPoints( m_Info[i].IciA[ki], m_Info[j].IciA[kj]) ; + MediaParamPoints( m_Info[i].IciB[ki], m_Info[j].IciB[kj]) ; + // se entrambi overlap non cancello + if ( m_Info[j].bOverlap && m_Info[i].bOverlap) + continue ; + // cancello un singolo + int k = ( ! m_Info[i].bOverlap ? i : j) ; + m_Info.erase( m_Info.begin() + k) ; + -- i ; + -- m_nNumInters ; + } + // caso NULL-DET -> DET-NULL per seconda curva (possibile su inizio/fine di curva chiusa) + else if ( m_Info[j].IciB[kj].nPrevTy == ICCT_NULL && m_Info[j].IciB[kj].nNextTy != ICCT_NULL && + m_Info[i].IciB[ki].nPrevTy != ICCT_NULL && m_Info[i].IciB[ki].nNextTy == ICCT_NULL) { + // per la seconda curva tengo i determinati + m_Info[i].IciB[ki].nNextTy = m_Info[j].IciB[kj].nNextTy ; + m_Info[j].IciB[kj].nPrevTy = m_Info[i].IciB[ki].nPrevTy ; + // se overlap equiverso + if ( m_Info[i].bOverlap && m_Info[i].bCBOverEq) { + // per la prima curva ogni sottotipo è il duale di quello della seconda + m_Info[i].IciA[ki].nPrevTy = GetDualIcct( m_Info[i].IciB[ki].nPrevTy) ; + m_Info[i].IciA[ki].nNextTy = GetDualIcct( m_Info[i].IciB[ki].nNextTy) ; + } + // se altrimenti overlap controverso + else if ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq) { + // per la prima curva ogni sottotipo è come quello della seconda ma in posizione scambiata + m_Info[i].IciA[ki].nPrevTy = m_Info[i].IciB[ki].nNextTy ; + m_Info[i].IciA[ki].nNextTy = m_Info[i].IciB[ki].nPrevTy ; + } + // se overlap equiverso + if ( m_Info[j].bOverlap && m_Info[j].bCBOverEq) { + // per la prima curva ogni sottotipo è il duale di quello della seconda + m_Info[j].IciA[kj].nPrevTy = GetDualIcct( m_Info[i].IciB[ki].nPrevTy) ; + m_Info[j].IciA[kj].nNextTy = GetDualIcct( m_Info[i].IciB[ki].nNextTy) ; + } + // se altrimenti overlap controverso + else if ( m_Info[j].bOverlap && ! m_Info[j].bCBOverEq) { + // per la prima curva ogni sottotipo è come quello della seconda ma in posizione scambiata + m_Info[j].IciA[kj].nPrevTy = m_Info[i].IciB[ki].nNextTy ; + m_Info[j].IciA[kj].nNextTy = m_Info[i].IciB[ki].nPrevTy ; + } + // medio parametri e punti separatamente per le due curve + MediaParamPoints( m_Info[i].IciA[ki], m_Info[j].IciA[kj]) ; + MediaParamPoints( m_Info[i].IciB[ki], m_Info[j].IciB[kj]) ; + // se entrambi overlap non cancello + if ( m_Info[j].bOverlap && m_Info[i].bOverlap) + continue ; + // cancello un singolo + int k = ( ! m_Info[i].bOverlap ? i : j) ; + m_Info.erase( m_Info.begin() + k) ; + -- i ; + -- m_nNumInters ; + } + // caso NULL-NULL per corrente di prima curva + else if ( m_Info[i].IciA[ki].nPrevTy == ICCT_NULL && m_Info[i].IciA[ki].nNextTy == ICCT_NULL) { + // cancello l'intersezione corrente (non aggiunge nulla rispetto alla precedente) + m_Info.erase( m_Info.begin() + i) ; + -- i ; + -- m_nNumInters ; + } + // caso NULL-NULL per precedente di prima curva + else if ( m_Info[j].IciA[kj].nPrevTy == ICCT_NULL && m_Info[j].IciA[kj].nNextTy == ICCT_NULL) { + // cancello l'intersezione precedente (non aggiunge nulla rispetto alla corrente) + m_Info.erase( m_Info.begin() + j) ; + if ( j < i) + i -= 2 ; + else + -- i ; + -- m_nNumInters ; + } + } + } + + // verifico se sono rimaste delle intersezioni di tipo non definito e cerco di risolverle + for ( int i = 0 ; i < m_nNumInters ; ++ i) { + // in assenza di overlap + if ( ! m_Info[i].bOverlap) { + // se il tipo di accostamento per la curva A non è definito + if ( m_Info[i].IciA[0].nPrevTy == ICCT_NULL) { + // devo studiare un intorno dell'intersezione + int nType ; + if ( ! CalcATypeFromDisk( CCompoA, m_Info[i].IciA[0].dU, ICurve::FROM_MINUS, + CCompoB, m_Info[i].IciB[0].dU, nType)) + continue ; + // aggiorno il tipo di accostamento della curva A alla curva B + m_Info[i].IciA[0].nPrevTy = nType ; + } + // se il tipo di accostamento per la curva B non è definito + if ( m_Info[i].IciB[0].nPrevTy == ICCT_NULL) { + // devo studiare un intorno dell'intersezione + int nType ; + if ( ! CalcATypeFromDisk( CCompoB, m_Info[i].IciB[0].dU, ICurve::FROM_MINUS, + CCompoA, m_Info[i].IciA[0].dU, nType)) + continue ; + // aggiorno il tipo di accostamento della curva B alla curva A + m_Info[i].IciB[0].nPrevTy = nType ; + } + // se il tipo di allontanamento per la curva A non è definito + if ( m_Info[i].IciA[0].nNextTy == ICCT_NULL) { + // devo studiare un intorno dell'intersezione + int nType ; + if ( ! CalcATypeFromDisk( CCompoA, m_Info[i].IciA[0].dU, ICurve::FROM_PLUS, + CCompoB, m_Info[i].IciB[0].dU, nType)) + continue ; + // aggiorno il tipo di allontanamento della curva A dalla curva B + m_Info[i].IciA[0].nNextTy = nType ; + } + // se il tipo di allontanamento per la curva B non è definito + if ( m_Info[i].IciB[0].nNextTy == ICCT_NULL) { + // devo studiare un intorno dell'intersezione + int nType ; + if ( ! CalcATypeFromDisk( CCompoB, m_Info[i].IciB[0].dU, ICurve::FROM_PLUS, + CCompoA, m_Info[i].IciA[0].dU, nType)) + continue ; + // aggiorno il tipo di allontanamento della curva B dalla curva A + m_Info[i].IciB[0].nNextTy = nType ; + } + } + // in presenza di overlap + else { + // se il tipo di accostamento è non definito per la curva A + if ( m_Info[i].IciA[0].nPrevTy == ICCT_NULL) { + // devo studiare un intorno dell'intersezione + int nType ; + if ( ! CalcATypeFromDisk( CCompoA, m_Info[i].IciA[0].dU, ICurve::FROM_MINUS, + CCompoB, m_Info[i].IciB[0].dU, nType)) + continue ; + // aggiorno il tipo di accostamento della curva A alla curva B + m_Info[i].IciA[0].nPrevTy = nType ; + // aggiorno anche il corrispondente tipo sulla curva B + if ( m_Info[i].bCBOverEq) + m_Info[i].IciB[0].nPrevTy = GetDualIcct( nType) ; + else + m_Info[i].IciB[0].nNextTy = nType ; + } + // se il tipo di allontanamento è non definito per la curva A + if ( m_Info[i].IciA[1].nNextTy == ICCT_NULL) { + // devo studiare un intorno dell'intersezione + int nType ; + if ( ! CalcATypeFromDisk( CCompoA, m_Info[i].IciA[1].dU, ICurve::FROM_PLUS, + CCompoB, m_Info[i].IciB[1].dU, nType)) + continue ; + // aggiorno il tipo di allontanamento della curva A dalla curva B + m_Info[i].IciA[1].nNextTy = nType ; + // aggiorno anche il corrispondente tipo sulla curva B + if ( m_Info[i].bCBOverEq) + m_Info[i].IciB[1].nNextTy = GetDualIcct( nType) ; + else + m_Info[i].IciB[1].nPrevTy = nType ; + } + } + } + + // verifico se due intersezioni consecutive di tipo overlap si possono ridurre a una sola + for ( int i = 0 ; i < m_nNumInters ; ++ i) { + // calcolo indice precedente + int j = i - 1 ; + if ( i == 0) { + // se prima curva aperta, salto alla prossima + if ( ! CCompoA.IsClosed()) + continue ; + // è chiusa quindi prendo l'ultima + j = m_nNumInters - 1 ; + } + // se i due indici coincidono, c'è una sola intersezione e posso uscire + if ( i == j) + break ; + // assegno sottoindici (considero solo intersezioni overlap) + int ki = 0 ; + int kj = 1 ; + // verifico se entrambe overlap, la precedente termina con ON e la successiva inizia con ON + // sia sulla curva A sia sulla curva B (tenendo conto del senso equiverso/controverso) + if ( m_Info[j].bOverlap && m_Info[i].bOverlap && + m_Info[j].IciA[kj].nNextTy == ICCT_ON && m_Info[i].IciA[ki].nPrevTy == ICCT_ON && + GetCrvBDirANext( m_Info[j]) == ICCT_ON && GetCrvBDirAPrev( m_Info[i]) == ICCT_ON) { + // CurvaA : riporto il secondo punto del successivo sul secondo punto del precedente + m_Info[j].IciA[kj].dU = m_Info[i].IciA[kj].dU ; + m_Info[j].IciA[kj].ptI = m_Info[i].IciA[kj].ptI ; + m_Info[j].IciA[kj].nPrevTy = m_Info[i].IciA[kj].nPrevTy ; + m_Info[j].IciA[kj].nNextTy = m_Info[i].IciA[kj].nNextTy ; + // CurvaB : riporto il secondo punto del successivo sul secondo punto del precedente + m_Info[j].IciB[kj].dU = m_Info[i].IciB[kj].dU ; + m_Info[j].IciB[kj].ptI = m_Info[i].IciB[kj].ptI ; + m_Info[j].IciB[kj].nPrevTy = m_Info[i].IciB[kj].nPrevTy ; + m_Info[j].IciB[kj].nNextTy = m_Info[i].IciB[kj].nNextTy ; + // cancello il successivo + m_Info.erase( m_Info.begin() + i) ; + -- i ; + -- m_nNumInters ; + } + } + + // se è rimasta una sola intersezione con overlap anche ad entrambi gli estremi e le curve sono chiuse + if ( m_nNumInters == 1 && CCompoA.IsClosed() && CCompoB.IsClosed() && + m_Info[0].IciA[0].nPrevTy == ICCT_ON && m_Info[0].IciA[1].nNextTy == ICCT_ON && + GetCrvBDirANext( m_Info[0]) == ICCT_ON && GetCrvBDirAPrev( m_Info[0]) == ICCT_ON) { + // questa intersezione con overlap deve interessare completamente le due curve + double dStart, dEnd ; + CCompoA.GetDomain( dStart, dEnd) ; + m_Info[0].IciA[0].dU = dStart ; + m_Info[0].IciA[1].dU = dEnd ; + CCompoB.GetDomain( dStart, dEnd) ; + m_Info[0].IciB[0].dU = ( m_Info[0].bCBOverEq ? dStart : dEnd) ; + m_Info[0].IciB[1].dU = ( m_Info[0].bCBOverEq ? dEnd : dStart) ; + } + +} diff --git a/IntersCrvCompoCrvCompo.h b/IntersCrvCompoCrvCompo.h new file mode 100644 index 0000000..a6e9853 --- /dev/null +++ b/IntersCrvCompoCrvCompo.h @@ -0,0 +1,47 @@ +//---------------------------------------------------------------------------- +// EgalTech 2014-2014 +//---------------------------------------------------------------------------- +// File : IntersCrvCompoCrvCompo.h Data : 24.06.14 Versione : 1.5f6 +// Contenuto : Dichiarazione della classe intersezione curva composita/cc. +// +// +// +// Modifiche : 24.06.14 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +#pragma once + +#include "/EgtDev/Include/EGkIntersCurveCurve.h" +#include "/EgtDev/Include/EGkCurveComposite.h" + + +//----------------------------------------------------------------------------- +class IntersCrvCompoCrvCompo +{ + friend class IntersCurveCurve ; + + public : + IntersCrvCompoCrvCompo( const ICurveComposite& CCompo1, const ICurveComposite& CCompo2) ; + + public : + bool GetOverlaps( void) + { return m_bOverlaps ; } + int GetNumInters( void) + { return m_nNumInters ; } + bool GetIntCrvCrvInfo( int nInd, IntCrvCrvInfo& aInfo) + { if ( nInd < 0 || nInd >= m_nNumInters) + return false ; + aInfo = m_Info[nInd] ; + return true ; } + + private : + IntersCrvCompoCrvCompo( void) ; + + private : + bool m_bOverlaps ; + int m_nNumInters ; + ICCIVECTOR m_Info ; +} ; + diff --git a/IntersCurveCurve.cpp b/IntersCurveCurve.cpp index 36929f1..86efcb8 100644 --- a/IntersCurveCurve.cpp +++ b/IntersCurveCurve.cpp @@ -14,6 +14,7 @@ //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "IntersLineLine.h" +#include "IntersCrvCompoCrvCompo.h" #include "/EgtDev/Include/EGkIntersCurveCurve.h" #include "/EgtDev/Include/EGkDistPointCurve.h" #include "/EgtDev/Include/EGtPointerOwner.h" @@ -52,6 +53,17 @@ IntersCurveCurve::IntersCurveCurve( const ICurve& Curve1, const ICurve& Curve2, case CRV_BEZ : break ; case CRV_COMPO : + switch ( Curve2.GetType()) { + case CRV_LINE : + break ; + case CRV_ARC : + break ; + case CRV_BEZ : + break ; + case CRV_COMPO : + CrvCompoCrvCompoCalculate( Curve1, Curve2) ; + break ; + } break ; } @@ -70,7 +82,21 @@ IntersCurveCurve::LineLineCalculate( const ICurve& Curve1, const ICurve& Curve2, m_bOverlaps = intLnLn.m_bOverlaps ; m_nNumInters = intLnLn.m_nNumInters ; for ( int i = 0 ; i < m_nNumInters ; ++ i) - m_Info.push_back( intLnLn.m_Info[i]) ; + m_Info.push_back( intLnLn.m_Info) ; + } +} + +//---------------------------------------------------------------------------- +void +IntersCurveCurve::CrvCompoCrvCompoCalculate( const ICurve& Curve1, const ICurve& Curve2) +{ + IntersCrvCompoCrvCompo intCcCc( *GetCurveComposite( &Curve1), *GetCurveComposite( &Curve2)) ; + + if ( intCcCc.m_nNumInters > 0) { + m_bOverlaps = intCcCc.m_bOverlaps ; + m_nNumInters = intCcCc.m_nNumInters ; + for ( int i = 0 ; i < m_nNumInters ; ++ i) + m_Info.push_back( intCcCc.m_Info[i]) ; } } @@ -88,36 +114,6 @@ IntersCurveCurve::GetNumInters( void) return m_nNumInters ; } -//---------------------------------------------------------------------------- -bool -IntersCurveCurve::GetIntersParam( int nInd, int nCrv, double& dPar) -{ - if ( nInd < 0 || nInd >= m_nNumInters || nCrv < 0 || nCrv > 1) - return false ; - dPar = m_Info[nInd].Ici[nCrv].dU ; - return true ; -} - -//---------------------------------------------------------------------------- -bool -IntersCurveCurve::GetIntersPoint( int nInd, int nCrv, Point3d& ptI) -{ - if ( nInd < 0 || nInd >= m_nNumInters || nCrv < 0 || nCrv > 1) - return false ; - ptI = m_Info[nInd].Ici[nCrv].ptI ; - return true ; -} - -//---------------------------------------------------------------------------- -bool -IntersCurveCurve::GetIntersType( int nInd, int nCrv, int& nType) -{ - if ( nInd < 0 || nInd >= m_nNumInters || nCrv < 0 || nCrv > 1) - return false ; - nType = m_Info[nInd].Ici[nCrv].nTy ; - return true ; -} - //---------------------------------------------------------------------------- bool IntersCurveCurve::GetIntCrvCrvInfo( int nInd, IntCrvCrvInfo& aInfo) @@ -135,57 +131,14 @@ IntersCurveCurve::GetIntersPointNearTo( int nCrv, const Point3d& ptNear, Point3d if ( m_nNumInters == 0 || nCrv < 0 || nCrv > 1) return false ; - // inizializzo risultato della ricerca - bool bFound = false ; - // ricerca del punto più vicino tra le intersezioni singole + bool bFound = false ; double dMinSqDist = INFINITO * INFINITO ; for ( int i = 0 ; i < m_nNumInters ; ++ i) { - // se è estremo di un tratto in sovrapposizione, salto al successivo - if ( IsIcctPrevOn( m_Info[i].Ici[nCrv].nTy) || - IsIcctNextOn( m_Info[i].Ici[nCrv].nTy)) - continue ; - // faccio la verifica - double dSqDist = SqDist( ptNear, m_Info[i].Ici[nCrv].ptI) ; - if ( dSqDist < dMinSqDist) { - dMinSqDist = dSqDist ; - ptI = m_Info[i].Ici[nCrv].ptI ; - bFound = true ; - } - } - - // se non ci sono sovrapposizioni, posso uscire - if ( ! m_bOverlaps) - return bFound ; - - // ricerca del punto più vicino tra le sovrapposizioni (sono sempre a coppie) - bool bPrevOverlap = false ; - for ( int i = 0 ; i < m_nNumInters ; ++ i) { - // se non è estremo di un tratto in sovrapposizione, vado al prossimo - if ( ! IsIcctPrevOn( m_Info[i].Ici[nCrv].nTy) && - ! IsIcctNextOn( m_Info[i].Ici[nCrv].nTy)) { - bPrevOverlap = false ; - continue ; - } - // se il precedente non era una sovrapposizione, ne marco l'inizio - if ( ! bPrevOverlap) { - bPrevOverlap = true ; - continue ; - } - // recupero il tratto di sovrapposizione - bPrevOverlap = false ; - double dUStartTrim = m_Info[i-1].Ici[nCrv].dU ; - double dUEndTrim = m_Info[i].Ici[nCrv].dU ; - PtrOwner pCrv( m_pCurve[nCrv]->Clone()) ; - if ( ! ::IsValid( pCrv)) - continue ; - if ( ! pCrv->TrimStartEndAtParam( dUStartTrim, dUEndTrim)) - continue ; - // cerco il punto - int nFlag ; - Point3d ptP ; - if ( DistPointCurve( ptNear, *pCrv).GetMinDistPoint( 0.5, ptP, nFlag)) { - // faccio la verifica + // se è un'intersezione singola + if ( ! m_Info[i].bOverlap) { + // faccio la verifica sul punto + Point3d ptP = ( nCrv == 0 ? m_Info[i].IciA[0].ptI : m_Info[i].IciB[0].ptI) ; double dSqDist = SqDist( ptNear, ptP) ; if ( dSqDist < dMinSqDist) { dMinSqDist = dSqDist ; @@ -193,6 +146,39 @@ IntersCurveCurve::GetIntersPointNearTo( int nCrv, const Point3d& ptNear, Point3d bFound = true ; } } + // altrimenti + else { + // recupero il tratto di sovrapposizione + double dUStartTrim, dUEndTrim ; + if ( nCrv == 0) { + dUStartTrim = m_Info[i].IciA[0].dU ; + dUEndTrim = m_Info[i].IciA[1].dU ; + } + else { + dUStartTrim = m_Info[i].IciB[0].dU ; + dUEndTrim = m_Info[i].IciB[1].dU ; + if ( ! m_Info[i].bCBOverEq) + swap( dUStartTrim, dUEndTrim) ; + } + // !!! sistemare per curva chiusa con tratto che attraversa fine/inizio !!! + PtrOwner pCrv( m_pCurve[nCrv]->Clone()) ; + if ( ! ::IsValid( pCrv)) + continue ; + if ( ! pCrv->TrimStartEndAtParam( dUStartTrim, dUEndTrim)) + continue ; + // cerco il punto + int nFlag ; + Point3d ptP ; + if ( DistPointCurve( ptNear, *pCrv).GetMinDistPoint( 0.5, ptP, nFlag)) { + // faccio la verifica + double dSqDist = SqDist( ptNear, ptP) ; + if ( dSqDist < dMinSqDist) { + dMinSqDist = dSqDist ; + ptI = ptP ; + bFound = true ; + } + } + } } return bFound ; diff --git a/IntersLineLine.cpp b/IntersLineLine.cpp index bb1b459..97d119b 100644 --- a/IntersLineLine.cpp +++ b/IntersLineLine.cpp @@ -18,7 +18,24 @@ using namespace std ; //---------------------------------------------------------------------------- -IntersLineLine::IntersLineLine( const ICurveLine& Line1, const ICurveLine& Line2, bool bFinites) +// Il punto è esterno al FatSegment se dista da questo più di Tol e la sua proiezione sta sul segmento +bool +IsPointOutFatSegment( const Point3d& ptP, const Point3d& ptS, const Vector3d& vtDir, double dLenXY, double dTol) +{ + // distanza del punto dalla linea del segmento + if ( fabs( CrossXY( ( ptP - ptS), vtDir)) < dTol * dLenXY) + return false ; + // distanza con segno della proiezione del punto sul segmento dall'inizio per lunghezza segmento + double dDistXY = ScalarXY( ( ptP - ptS), vtDir) ; + // se il punto non si proietta sul segmento entro la tolleranza + if ( dDistXY < - dTol * dLenXY || dDistXY > ( dLenXY + dTol) * dLenXY) + return false ; + // altrimenti + return true ; +} + +//---------------------------------------------------------------------------- +IntersLineLine::IntersLineLine( const ICurveLine& Line1, const ICurveLine& Line2, bool bFinite) { // Le intersezioni sono calcolate nel piano XY locale. @@ -30,149 +47,252 @@ IntersLineLine::IntersLineLine( const ICurveLine& Line1, const ICurveLine& Line2 if ( ! Line1.IsValid() || ! Line2.IsValid()) return ; - // linea 1 : pto Start e direzione + // se sono linee (infinite) + if ( ! bFinite) + IntersInfiniteLines( Line1, Line2) ; + else + IntersFiniteLines( Line1, Line2) ; +} + +//---------------------------------------------------------------------------- +void +IntersLineLine::IntersInfiniteLines( const ICurveLine& Line1, const ICurveLine& Line2) +{ + // linea 1 : Start, End, Direzione e Lunghezza Point3d ptS1 = Line1.GetStart() ; - Vector3d vtDir1 = Line1.GetEnd() - ptS1 ; - // linea 2 : pto Start e direzione + Point3d ptE1 = Line1.GetEnd() ; + Vector3d vtDir1 = ptE1 - ptS1 ; + double dLen1XY = vtDir1.LenXY() ; + if ( dLen1XY < EPS_SMALL) + return ; + // linea 2 : Start, Direzione e Lunghezza Point3d ptS2 = Line2.GetStart() ; - Vector3d vtDir2 = Line2.GetEnd() - ptS2 ; + Point3d ptE2 = Line2.GetEnd() ; + Vector3d vtDir2 = ptE2 - ptS2 ; + double dLen2XY = vtDir2.LenXY() ; + if ( dLen2XY < EPS_SMALL) + return ; // prodotto vettoriale nel piano XY tra le direzioni delle linee double dCrossXY = CrossXY( vtDir1, vtDir2) ; // se le linee non sono parallele - if ( dCrossXY * dCrossXY > EPS_ZERO * EPS_ZERO) { + if ( fabs( dCrossXY) > SIN_EPS_ANG_ZERO * ( dLen1XY * dLen2XY)) { // posizioni parametriche dell'intersezione sulle linee - m_Info[0].Ici[0].dU = CrossXY( ( ptS2 - ptS1), vtDir2) / dCrossXY ; - m_Info[0].Ici[1].dU = CrossXY( ( ptS2 - ptS1), vtDir1) / dCrossXY ; - // tipo di posizione - enum IntPos { IP_NULL = 0, IP_START = 1, IP_MID = 2, IP_END = 3} ; - int nPos1 = IP_MID ; - int nPos2 = IP_MID ; - // se segmenti, ne verifico la posizione - if ( bFinites) { - // prima linea - if ( ( m_Info[0].Ici[0].dU * vtDir1).IsSmall()) - nPos1 = IP_START ; // vicino a inizio - else if ( (( 1 - m_Info[0].Ici[0].dU) * vtDir1).IsSmall()) - nPos1 = IP_END ; // vicino a fine - else if ( m_Info[0].Ici[0].dU > 0 && m_Info[0].Ici[0].dU < 1) - nPos1 = IP_MID ; // nell'interno - else - nPos1 = IP_NULL ; // fuori - // seconda linea - if ( ( m_Info[0].Ici[1].dU * vtDir2).IsSmall()) - nPos2 = IP_START ; // vicino a inizio - else if ( (( 1 - m_Info[0].Ici[1].dU) * vtDir2).IsSmall()) - nPos2 = IP_END ; // vicino a fine - else if ( m_Info[0].Ici[1].dU > 0 && m_Info[0].Ici[1].dU < 1) - nPos2 = IP_MID ; // nell'interno - else - nPos2 = IP_NULL ; // fuori - } - // se soluzione non accettata, esco - if ( nPos1 == IP_NULL || nPos2 == IP_NULL) - return ; + m_Info.IciA[0].dU = CrossXY( ( ptS2 - ptS1), vtDir2) / dCrossXY ; + m_Info.IciB[0].dU = CrossXY( ( ptS2 - ptS1), vtDir1) / dCrossXY ; // calcolo i punti sulle due linee (possono differire in Z) - m_Info[0].Ici[0].ptI = ptS1 + m_Info[0].Ici[0].dU * vtDir1 ; - m_Info[0].Ici[1].ptI = ptS2 + m_Info[0].Ici[1].dU * vtDir2 ; - // calcolo tipo di intersezione - m_Info[0].Ici[0].nTy = ICCT_RESET ; - m_Info[0].Ici[1].nTy = ICCT_RESET ; - // si incontrano alle estremità, non si può dire alcunché - if ( ( nPos1 == IP_START || nPos1 == IP_END) && - ( nPos2 == IP_START || nPos2 == IP_END)) { - m_Info[0].Ici[0].nTy = ICCT_PNULL + ICCT_NNULL ; // NULL + NULL - m_Info[0].Ici[1].nTy = ICCT_PNULL + ICCT_NNULL ; // NULL + NULL + m_Info.IciA[0].ptI = ptS1 + m_Info.IciA[0].dU * vtDir1 ; + m_Info.IciB[0].ptI = ptS2 + m_Info.IciB[0].dU * vtDir2 ; + // si intersecano sempre nel mezzo + if ( CrossXY( ( ptS1 - ptS2), vtDir2) > 0) { + m_Info.IciA[0].nPrevTy = ICCT_OUT ; + m_Info.IciA[0].nNextTy = ICCT_IN ; } - // l'inizio di 1 interseca il mezzo di 2 - else if ( nPos1 == IP_START) { - if ( dCrossXY > 0) - m_Info[0].Ici[0].nTy = ICCT_PNULL + ICCT_NOUT ; // NULL + OUT - else - m_Info[0].Ici[0].nTy = ICCT_PNULL + ICCT_NIN ; // NULL + IN - m_Info[0].Ici[1].nTy = ICCT_PNULL + ICCT_NNULL ; // NULL + NULL - } - // la fine di 1 interseca il mezzo di 2 - else if ( nPos1 == IP_END) { - if ( dCrossXY < 0) - m_Info[0].Ici[0].nTy = ICCT_POUT + ICCT_NNULL ; // OUT + NULL - else - m_Info[0].Ici[0].nTy = ICCT_PIN + ICCT_NNULL ; // IN + NULL - m_Info[0].Ici[1].nTy = ICCT_PNULL + ICCT_NNULL ; // NULL + NULL - } - // l'inizio di 2 interseca il mezzo di 1 - else if ( nPos2 == IP_START) { - m_Info[0].Ici[0].nTy = ICCT_PNULL + ICCT_NNULL ; // NULL + NULL - if ( - dCrossXY > 0) - m_Info[0].Ici[1].nTy = ICCT_PNULL + ICCT_NOUT ; // NULL + OUT - else - m_Info[0].Ici[1].nTy = ICCT_PNULL + ICCT_NIN ; // NULL + IN - } - // la fine di 2 interseca il mezzo di 1 - else if ( nPos2 == IP_END) { - m_Info[0].Ici[0].nTy = ICCT_PNULL + ICCT_NNULL ; // NULL + NULL - if ( - dCrossXY < 0) - m_Info[0].Ici[1].nTy = ICCT_POUT + ICCT_NNULL ; // OUT + NULL - else - m_Info[0].Ici[1].nTy = ICCT_PIN + ICCT_NNULL ; // IN + NULL - } - // si intersecano nel mezzo else { - if ( CrossXY( ( ptS1 - ptS2), vtDir2) > 0) - m_Info[0].Ici[0].nTy = ICCT_POUT + ICCT_NIN ; // OUT + IN - else - m_Info[0].Ici[0].nTy = ICCT_PIN + ICCT_NOUT ; // IN + OUT - if ( CrossXY( ( ptS2 - ptS1), vtDir1) > 0) - m_Info[0].Ici[1].nTy = ICCT_POUT + ICCT_NIN ; // OUT + IN - else - m_Info[0].Ici[1].nTy = ICCT_PIN + ICCT_NOUT ; // IN + OUT + m_Info.IciA[0].nPrevTy = ICCT_IN ; + m_Info.IciA[0].nNextTy = ICCT_OUT ; } + if ( CrossXY( ( ptS2 - ptS1), vtDir1) > 0) { + m_Info.IciB[0].nPrevTy = ICCT_OUT ; + m_Info.IciB[0].nNextTy = ICCT_IN ; + } + else { + m_Info.IciB[0].nPrevTy = ICCT_IN ; + m_Info.IciB[0].nNextTy = ICCT_OUT ; + } + m_Info.bOverlap = false ; m_bOverlaps = false ; m_nNumInters = 1 ; // una intersezione return ; } // se le linee sono parallele e non coincidenti - if ( fabs( CrossXY( ( ptS2 - ptS1), vtDir1)) > EPS_SMALL * vtDir1.LenXY()) + if ( fabs( CrossXY( ( ptS2 - ptS1), vtDir1)) > EPS_SMALL * dLen1XY) return ; // non ci sono intersezioni // le linee sono parallele e coincidenti e sono infinite - if ( ! bFinites) { - m_bOverlaps = true ; - m_nNumInters = 0 ; // non esistono estremi del tratto sovrapposto + m_bOverlaps = true ; + m_nNumInters = 0 ; // non esistono estremi del tratto sovrapposto +} + +//---------------------------------------------------------------------------- +void +IntersLineLine::IntersFiniteLines( const ICurveLine& Line1, const ICurveLine& Line2) +{ + // verifico sovrapposizione box + BBox3d boxL1 ; + if ( ! Line1.GetLocalBBox( boxL1)) + return ; + BBox3d boxL2 ; + if ( ! Line2.GetLocalBBox( boxL2)) + return ; + if ( ! boxL1.OverlapsXY( boxL2)) + return ; + + // linea 1 : Start, End, Direzione e Lunghezza + Point3d ptS1 = Line1.GetStart() ; + Point3d ptE1 = Line1.GetEnd() ; + Vector3d vtDir1 = ptE1 - ptS1 ; + double dLen1XY = vtDir1.LenXY() ; + if ( dLen1XY < EPS_SMALL) + return ; + // linea 2 : Start, Direzione e Lunghezza + Point3d ptS2 = Line2.GetStart() ; + Point3d ptE2 = Line2.GetEnd() ; + Vector3d vtDir2 = ptE2 - ptS2 ; + double dLen2XY = vtDir2.LenXY() ; + if ( dLen2XY < EPS_SMALL) + return ; + // prodotto vettoriale nel piano XY tra le direzioni delle linee + double dCrossXY = CrossXY( vtDir1, vtDir2) ; + // flag per linee parallele + bool bParallel = ( fabs( dCrossXY) < SIN_EPS_ANG_ZERO * ( dLen1XY * dLen2XY)) ; + // flag per segmenti che si allontanano significativamente + bool bFarEnds = ( IsPointOutFatSegment( ptS1, ptS2, vtDir2, dLen2XY, EPS_SMALL) || + IsPointOutFatSegment( ptE1, ptS2, vtDir2, dLen2XY, EPS_SMALL) || + IsPointOutFatSegment( ptS2, ptS1, vtDir1, dLen1XY, EPS_SMALL) || + IsPointOutFatSegment( ptE2, ptS1, vtDir1, dLen1XY, EPS_SMALL)) ; + + // se non sono paralleli e si allontanano tra loro abbastanza + if ( ! bParallel && bFarEnds) { + // posizioni parametriche dell'intersezione sulle linee + m_Info.IciA[0].dU = CrossXY( ( ptS2 - ptS1), vtDir2) / dCrossXY ; + m_Info.IciB[0].dU = CrossXY( ( ptS2 - ptS1), vtDir1) / dCrossXY ; + // tipo di posizione + enum IntPos { IP_NULL = 0, IP_START = 1, IP_MID = 2, IP_END = 3} ; + // verifica posizione intersezione su prima linea + int nPos1 = IP_NULL ; // fuori + if ( ( m_Info.IciA[0].dU * vtDir1).IsSmall()) + nPos1 = IP_START ; // vicino a inizio + else if ( (( 1 - m_Info.IciA[0].dU) * vtDir1).IsSmall()) + nPos1 = IP_END ; // vicino a fine + else if ( m_Info.IciA[0].dU > 0 && m_Info.IciA[0].dU < 1) + nPos1 = IP_MID ; // nell'interno + // verifica posizione intersezione su seconda linea + int nPos2 = IP_NULL ; // fuori + if ( ( m_Info.IciB[0].dU * vtDir2).IsSmall()) + nPos2 = IP_START ; // vicino a inizio + else if ( (( 1 - m_Info.IciB[0].dU) * vtDir2).IsSmall()) + nPos2 = IP_END ; // vicino a fine + else if ( m_Info.IciB[0].dU > 0 && m_Info.IciB[0].dU < 1) + nPos2 = IP_MID ; // nell'interno + // se soluzione non accettata, esco + if ( nPos1 == IP_NULL || nPos2 == IP_NULL) + return ; + // limito i parametri a stare sui segmenti (0...1) + m_Info.IciA[0].dU = min( max( m_Info.IciA[0].dU, 0.), 1.) ; + m_Info.IciB[0].dU = min( max( m_Info.IciB[0].dU, 0.), 1.) ; + // calcolo i punti sulle due linee (possono differire in Z) + m_Info.IciA[0].ptI = ptS1 + m_Info.IciA[0].dU * vtDir1 ; + m_Info.IciB[0].ptI = ptS2 + m_Info.IciB[0].dU * vtDir2 ; + // calcolo tipo di intersezione + m_Info.IciA[0].nPrevTy = ICCT_NULL ; + m_Info.IciA[0].nNextTy = ICCT_NULL ; + m_Info.IciB[0].nPrevTy = ICCT_NULL ; + m_Info.IciB[0].nNextTy = ICCT_NULL ; + // si incontrano alle estremità, non si può dire alcunché + if ( ( nPos1 == IP_START || nPos1 == IP_END) && + ( nPos2 == IP_START || nPos2 == IP_END)) { + ; // rimangono tutti NULL + } + // l'inizio di 1 interseca il mezzo di 2 + else if ( nPos1 == IP_START) { + if ( dCrossXY > 0) + m_Info.IciA[0].nNextTy = ICCT_OUT ; // NULL + OUT + else + m_Info.IciA[0].nNextTy = ICCT_IN ; // NULL + IN + // curva B NULL + NULL + } + // la fine di 1 interseca il mezzo di 2 + else if ( nPos1 == IP_END) { + if ( dCrossXY < 0) + m_Info.IciA[0].nPrevTy = ICCT_OUT ; // OUT + NULL + else + m_Info.IciA[0].nPrevTy = ICCT_IN ; // IN + NULL + // curva B NULL + NULL + } + // l'inizio di 2 interseca il mezzo di 1 + else if ( nPos2 == IP_START) { + // curva A NULL + NULL + if ( - dCrossXY > 0) + m_Info.IciB[0].nNextTy = ICCT_OUT ; // NULL + OUT + else + m_Info.IciB[0].nNextTy = ICCT_IN ; // NULL + IN + } + // la fine di 2 interseca il mezzo di 1 + else if ( nPos2 == IP_END) { + // curva A NULL + NULL + if ( - dCrossXY < 0) + m_Info.IciB[0].nPrevTy = ICCT_OUT ; // OUT + NULL + else + m_Info.IciB[0].nPrevTy = ICCT_IN ; // IN + NULL + } + // si intersecano nel mezzo + else { + if ( CrossXY( ( ptS1 - ptS2), vtDir2) > 0) { + m_Info.IciA[0].nPrevTy = ICCT_OUT ; + m_Info.IciA[0].nNextTy = ICCT_IN ; + } + else { + m_Info.IciA[0].nPrevTy = ICCT_IN ; + m_Info.IciA[0].nNextTy = ICCT_OUT ; + } + if ( CrossXY( ( ptS2 - ptS1), vtDir1) > 0) { + m_Info.IciB[0].nPrevTy = ICCT_OUT ; + m_Info.IciB[0].nNextTy = ICCT_IN ; + } + else { + m_Info.IciB[0].nPrevTy = ICCT_IN ; + m_Info.IciB[0].nNextTy = ICCT_OUT ; + } + } + m_Info.bOverlap = false ; + m_bOverlaps = false ; + m_nNumInters = 1 ; return ; } - // le linee sono parallele e coincidenti e sono segmenti, si cercano eventuali sovrapposizioni - // determino se sono equiverse o controverse + // se le linee sono parallele e non coincidenti + //if ( fabs( CrossXY( ( ptS2 - ptS1), vtDir1)) > EPS_SMALL * dLen1XY) + if ( bParallel && bFarEnds) + return ; // non ci sono intersezioni + + // le linee sono parallele e coincidenti, si cercano eventuali sovrapposizioni + // determino se sono equiversi o controversi bool bEqVers = ( ScalarXY( vtDir1, vtDir2) > 0) ; // calcolo dei valori parametrici degli estremi del secondo segmento sul primo double dUmin = ScalarXY( ( ptS2 - ptS1), vtDir1) / vtDir1.SqLenXY() ; - double dUmax = ScalarXY( ( ptS2 + vtDir2 - ptS1), vtDir1) / vtDir1.SqLenXY() ; + double dUmax = ScalarXY( ( ptE2 - ptS1), vtDir1) / vtDir1.SqLenXY() ; if ( ! bEqVers) swap( dUmin, dUmax) ; // estremo inferiore del primo coincide con superiore del secondo -> un punto estremo if ( ( dUmax * vtDir1).IsSmall()) { - m_Info[0].Ici[0].dU = 0 ; - m_Info[0].Ici[1].dU = ( bEqVers ? 1 : 0) ; - m_Info[0].Ici[0].ptI = ptS1 + m_Info[0].Ici[0].dU * vtDir1 ; - m_Info[0].Ici[1].ptI = ptS2 + m_Info[0].Ici[1].dU * vtDir2 ; - m_Info[0].Ici[0].nTy = ICCT_PNULL + ICCT_NNULL ; // NULL + NULL - m_Info[0].Ici[1].nTy = ICCT_PNULL + ICCT_NNULL ; // NULL + NULL + m_Info.IciA[0].dU = 0 ; + m_Info.IciB[0].dU = ( bEqVers ? 1 : 0) ; + m_Info.IciA[0].ptI = ptS1 + m_Info.IciA[0].dU * vtDir1 ; + m_Info.IciB[0].ptI = ptS2 + m_Info.IciB[0].dU * vtDir2 ; + m_Info.IciA[0].nPrevTy = ICCT_NULL ; + m_Info.IciA[0].nNextTy = ICCT_NULL ; + m_Info.IciB[0].nPrevTy = ICCT_NULL ; + m_Info.IciB[0].nNextTy = ICCT_NULL ; + m_Info.bOverlap = false ; m_bOverlaps = false ; - m_nNumInters = 1 ; // una intersezione + m_nNumInters = 1 ; return ; } // estremo superiore del primo coincide con inferiore del secondo -> un punto estremo else if ( ( ( 1 - dUmin) * vtDir1).IsSmall()) { - m_Info[0].Ici[0].dU = 1 ; - m_Info[0].Ici[1].dU = ( bEqVers ? 0 : 1) ; - m_Info[0].Ici[0].ptI = ptS1 + m_Info[0].Ici[0].dU * vtDir1 ; - m_Info[0].Ici[1].ptI = ptS2 + m_Info[0].Ici[1].dU * vtDir2 ; - m_Info[0].Ici[0].nTy = ICCT_PNULL + ICCT_NNULL ; // NULL + NULL - m_Info[0].Ici[1].nTy = ICCT_PNULL + ICCT_NNULL ; // NULL + NULL + m_Info.IciA[0].dU = 1 ; + m_Info.IciB[0].dU = ( bEqVers ? 0 : 1) ; + m_Info.IciA[0].ptI = ptS1 + m_Info.IciA[0].dU * vtDir1 ; + m_Info.IciB[0].ptI = ptS2 + m_Info.IciB[0].dU * vtDir2 ; + m_Info.IciA[0].nPrevTy = ICCT_NULL ; + m_Info.IciA[0].nNextTy = ICCT_NULL ; + m_Info.IciB[0].nPrevTy = ICCT_NULL ; + m_Info.IciB[0].nNextTy = ICCT_NULL ; + m_Info.bOverlap = false ; m_bOverlaps = false ; - m_nNumInters = 1 ; // una intersezione + m_nNumInters = 1 ; return ; } // esterni -> nessuna intersezione @@ -183,38 +303,50 @@ IntersLineLine::IntersLineLine( const ICurveLine& Line1, const ICurveLine& Line2 else { // devo prendere il massimo dei minimi if ( dUmin > 0) { - m_Info[0].Ici[0].dU = dUmin ; - m_Info[0].Ici[1].dU = ( bEqVers ? 0 : 1) ; + m_Info.IciA[0].dU = dUmin ; + m_Info.IciB[0].dU = ( bEqVers ? 0 : 1) ; } else { - m_Info[0].Ici[0].dU = 0 ; - m_Info[0].Ici[1].dU = ScalarXY( ( ptS1 - ptS2), vtDir2) / vtDir2.SqLenXY() ; + m_Info.IciA[0].dU = 0 ; + m_Info.IciB[0].dU = ScalarXY( ( ptS1 - ptS2), vtDir2) / vtDir2.SqLenXY() ; + } + m_Info.IciA[0].ptI = ptS1 + m_Info.IciA[0].dU * vtDir1 ; + m_Info.IciB[0].ptI = ptS2 + m_Info.IciB[0].dU * vtDir2 ; + m_Info.IciA[0].nPrevTy = ICCT_NULL ; + m_Info.IciA[0].nNextTy = ICCT_ON ; + if ( bEqVers) { + m_Info.IciB[0].nPrevTy = ICCT_NULL ; + m_Info.IciB[0].nNextTy = ICCT_ON ; + } + else { + m_Info.IciB[0].nPrevTy = ICCT_ON ; + m_Info.IciB[0].nNextTy = ICCT_NULL ; } - m_Info[0].Ici[0].ptI = ptS1 + m_Info[0].Ici[0].dU * vtDir1 ; - m_Info[0].Ici[1].ptI = ptS2 + m_Info[0].Ici[1].dU * vtDir2 ; - m_Info[0].Ici[0].nTy = ICCT_PNULL + ICCT_NON ; // NULL + ON - if ( bEqVers) - m_Info[0].Ici[1].nTy = ICCT_PNULL + ICCT_NON ; // NULL + ON - else - m_Info[0].Ici[1].nTy = ICCT_PON + ICCT_NNULL ; // ON + NULL // e il minimo dei massimi if ( dUmax < 1) { - m_Info[1].Ici[0].dU = dUmax ; - m_Info[1].Ici[1].dU = ( bEqVers ? 1 : 0) ; + m_Info.IciA[1].dU = dUmax ; + m_Info.IciB[1].dU = ( bEqVers ? 1 : 0) ; } else { - m_Info[1].Ici[0].dU = 1 ; - m_Info[1].Ici[1].dU = ScalarXY( ( ptS1 + vtDir1 - ptS2), vtDir2) / vtDir2.SqLenXY() ; + m_Info.IciA[1].dU = 1 ; + m_Info.IciB[1].dU = ScalarXY( ( ptS1 + vtDir1 - ptS2), vtDir2) / vtDir2.SqLenXY() ; } - m_Info[1].Ici[0].ptI = ptS1 + m_Info[1].Ici[0].dU * vtDir1 ; - m_Info[1].Ici[1].ptI = ptS2 + m_Info[1].Ici[1].dU * vtDir2 ; - m_Info[1].Ici[0].nTy = ICCT_PON + ICCT_NNULL ; // ON + NULL - if ( bEqVers) - m_Info[1].Ici[1].nTy = ICCT_PON + ICCT_NNULL ; // ON + NULL - else - m_Info[1].Ici[1].nTy = ICCT_PNULL + ICCT_NON ; // NULL + ON + m_Info.IciA[1].ptI = ptS1 + m_Info.IciA[1].dU * vtDir1 ; + m_Info.IciB[1].ptI = ptS2 + m_Info.IciB[1].dU * vtDir2 ; + m_Info.IciA[1].nPrevTy = ICCT_ON ; + m_Info.IciA[1].nNextTy = ICCT_NULL ; + if ( bEqVers) { + m_Info.IciB[1].nPrevTy = ICCT_ON ; + m_Info.IciB[1].nNextTy = ICCT_NULL ; + } + else { + m_Info.IciB[1].nPrevTy = ICCT_NULL ; + m_Info.IciB[1].nNextTy = ICCT_ON ; + } + m_Info.bOverlap = true ; + m_Info.bCBOverEq = bEqVers ; m_bOverlaps = true ; - m_nNumInters = 2 ; // estremi del tratto di sovrapposizione + m_nNumInters = 1 ; return ; } } diff --git a/IntersLineLine.h b/IntersLineLine.h index d7db2b9..52540a1 100644 --- a/IntersLineLine.h +++ b/IntersLineLine.h @@ -23,43 +23,27 @@ class IntersLineLine friend class IntersCurveCurve ; public : - IntersLineLine( const ICurveLine& Line1, const ICurveLine& Line2, bool bFinites = true) ; + IntersLineLine( const ICurveLine& Line1, const ICurveLine& Line2, bool bFinite = true) ; public : bool GetOverlaps( void) { return m_bOverlaps ; } int GetNumInters( void) { return m_nNumInters ; } - bool GetIntersParam( int nInd, int nCrv, double& dPar) - { if ( nInd < 0 || nInd >= m_nNumInters || nCrv < 0 || nCrv > 1) + bool GetIntCrvCrvInfo( IntCrvCrvInfo& aInfo) + { if ( m_nNumInters == 0) return false ; - dPar = m_Info[nInd].Ici[nCrv].dU ; - return true ;} - bool GetIntersPoint( int nInd, int nCrv, Point3d& ptI) - { if ( nInd < 0 || nInd >= m_nNumInters || nCrv < 0 || nCrv > 1) - return false ; - ptI = m_Info[nInd].Ici[nCrv].ptI ; - return true ;} - bool GetIntersType( int nInd, int nCrv, int& nType) - { if ( nInd < 0 || nInd >= m_nNumInters || nCrv < 0 || nCrv > 1) - return false ; - nType = m_Info[nInd].Ici[nCrv].nTy ; - return true ;} - bool GetIntCrvCrvInfo( int nInd, IntCrvCrvInfo& aInfo) - { if ( nInd < 0 || nInd >= m_nNumInters) - return false ; - aInfo = m_Info[nInd] ; + aInfo = m_Info ; return true ; } private : IntersLineLine( void) ; - - private : - static const int MAX_INTERS = 2 ; + void IntersInfiniteLines( const ICurveLine& Line1, const ICurveLine& Line2) ; + void IntersFiniteLines( const ICurveLine& Line1, const ICurveLine& Line2) ; private : bool m_bOverlaps ; int m_nNumInters ; - IntCrvCrvInfo m_Info[MAX_INTERS] ; + IntCrvCrvInfo m_Info ; } ; diff --git a/LineTgTwoArcs.cpp b/LineTgTwoArcs.cpp index ad7e40e..85784da 100644 --- a/LineTgTwoArcs.cpp +++ b/LineTgTwoArcs.cpp @@ -32,8 +32,8 @@ GetLineTgTwoArcs( const ICurveArc& crvArc1, const Point3d& ptNear1, const ICurveArc& crvArc2, const Point3d& ptNear2) { // verifico che i due archi abbiano lo stesso piano intrinseco - if ( ! AreSameVectorNear( crvArc1.GetNormVersor(), crvArc2.GetNormVersor()) && - ! AreOppositeVectorNear( crvArc1.GetNormVersor(), crvArc2.GetNormVersor())) + if ( ! AreSameVectorApprox( crvArc1.GetNormVersor(), crvArc2.GetNormVersor()) && + ! AreOppositeVectorApprox( crvArc1.GetNormVersor(), crvArc2.GetNormVersor())) return nullptr ; // calcolo il riferimento intrinseco del primo arco (Z->DirNorm e X->DirStart) diff --git a/OutTsc.cpp b/OutTsc.cpp index e811ac9..69e1b70 100644 --- a/OutTsc.cpp +++ b/OutTsc.cpp @@ -304,7 +304,7 @@ OutTsc::Line2P( const Point3d& ptP1, const Point3d& ptP2) return false ; // verifico non sia praticamente nulla - if ( AreSamePointNear( ptP1, ptP2)) + if ( AreSamePointApprox( ptP1, ptP2)) return true ; // incremento indice corrente @@ -487,14 +487,17 @@ OutTsc::PutCurve( const ICurve* pCurve, int nFlag) // ciclo per disegnare le derivate e le curvature Remark( "Curve:Tangents+Der2") ; double dU ; + bool bFirst = true ; for ( bool bFound = PL.GetFirstU( dU) ; bFound ; bFound = PL.GetNextU( dU)) { // ricavo il punto, la tangente, la normale e la curvatura CrvPointDiffGeom oDiffG ; - pCurve->GetPointDiffGeom( dU, ICurve::FROM_MINUS, oDiffG) ; + pCurve->GetPointDiffGeom( dU, ( bFirst ? ICurve::FROM_PLUS : ICurve::FROM_MINUS), oDiffG) ; + bFirst = false ; // curvatura o tangente o niente ArcCurvOrTgOrNone( oDiffG) ; - // se punto con possibili discontinuità - if ( oDiffG.nFlag == CrvPointDiffGeom::TO_VERIFY) { + // se punto con possibili discontinuità e non punto iniziale o finale di curva chiusa + if ( oDiffG.nFlag == CrvPointDiffGeom::TO_VERIFY && + ! ( pCurve->IsClosed() && ( pCurve->IsStartParam( dU) || pCurve->IsEndParam( dU)))) { // ricavo il punto, la tangente, la normale e la curvatura dall'intorno superiore CrvPointDiffGeom oDiffGs ; pCurve->GetPointDiffGeom( dU, ICurve::FROM_PLUS, oDiffGs) ; @@ -511,14 +514,17 @@ OutTsc::PutCurve( const ICurve* pCurve, int nFlag) // ciclo per disegnare le derivate e le curvature Remark( "Curve:Normals") ; double dU ; + bool bFirst = true ; for ( bool bFound = PL.GetFirstU( dU) ; bFound ; bFound = PL.GetNextU( dU)) { // ricavo il punto, la tangente, la normale e la curvatura CrvPointDiffGeom oDiffG ; - pCurve->GetPointDiffGeom( dU, ICurve::FROM_MINUS, oDiffG) ; + pCurve->GetPointDiffGeom( dU, ( bFirst ? ICurve::FROM_PLUS : ICurve::FROM_MINUS), oDiffG) ; + bFirst = false ; // curvatura o tangente o niente NormalOrNone( oDiffG) ; - // se punto con possibili discontinuità - if ( oDiffG.nFlag == CrvPointDiffGeom::TO_VERIFY) { + // se punto con possibili discontinuità e non punto iniziale o finale di curva chiusa + if ( oDiffG.nFlag == CrvPointDiffGeom::TO_VERIFY && + ! ( pCurve->IsClosed() && ( pCurve->IsStartParam( dU) || pCurve->IsEndParam( dU)))) { // ricavo il punto, la tangente, la normale e la curvatura dall'intorno superiore CrvPointDiffGeom oDiffGs ; pCurve->GetPointDiffGeom( dU, ICurve::FROM_PLUS, oDiffGs) ; @@ -578,7 +584,7 @@ OutTsc::PutBBox( const BBox3d& b3B) if ( b3B.GetMinMax( ptMin, ptMax)) { Remark( "BoundingBox") ; // se ridotto a un punto - if ( AreSamePointNear( ptMin, ptMax)) + if ( AreSamePointApprox( ptMin, ptMax)) Point( ptMin) ; // se ridotto ad una linea else if ( (( ptMax.x - ptMin.x) < EPS_SMALL && ( ptMax.y - ptMin.y) < EPS_SMALL) || diff --git a/PolyLine.cpp b/PolyLine.cpp index 7c86d30..a09c57e 100644 --- a/PolyLine.cpp +++ b/PolyLine.cpp @@ -199,7 +199,7 @@ PolyLine::IsClosed( void) const if ( m_lUPoints.size() < 3) return false ; - return ( AreSamePointNear( m_lUPoints.front().second, m_lUPoints.back().second)) ; + return ( AreSamePointApprox( m_lUPoints.front().second, m_lUPoints.back().second)) ; } //---------------------------------------------------------------------------- diff --git a/SurfTriMesh.cpp b/SurfTriMesh.cpp index d6cf097..42cd3ac 100644 --- a/SurfTriMesh.cpp +++ b/SurfTriMesh.cpp @@ -958,7 +958,7 @@ SurfTriMesh::CreateByTwoCurves( const PolyLine& PL1, const PolyLine& PL2) dA2s = ( dU2s - dU2F) / dDeltaU2 ; int nIdV[3] ; // se i punti iniziali non coincidono, inserisco il vertice iniziale di 2 - if ( ! AreSamePointNear( ptP1p, ptP2p)) { + if ( ! AreSamePointApprox( ptP1p, ptP2p)) { if ( ( nV2p = AddVertex( ptP2p)) == SVT_NULL) return false ; } @@ -1001,7 +1001,7 @@ SurfTriMesh::CreateByTwoCurves( const PolyLine& PL1, const PolyLine& PL2) if ( AddTriangle( nIdV) == SVT_NULL) return false ; // se i punti correnti coincidono passo al successivo anche su 2 - if ( AreSamePointNear( ptP1s, ptP2s)) { + if ( AreSamePointApprox( ptP1s, ptP2s)) { nV2p = nV2s ; dA2p = dA2s ; dU2p = dU2s ; ptP2p = ptP2s ; bNext2 = PL2.GetNextUPoint( &dU2s, &ptP2s, bClosed) ; if ( bNext2) @@ -1025,7 +1025,7 @@ SurfTriMesh::CreateByTwoCurves( const PolyLine& PL1, const PolyLine& PL2) if ( AddTriangle( nIdV) == SVT_NULL) return false ; // se i punti correnti coincidono passo al successivo anche su 1 - if ( AreSamePointNear( ptP1s, ptP2s)) { + if ( AreSamePointApprox( ptP1s, ptP2s)) { nV1p = nV1s ; dA1p = dA1s ; dU1p = dU1s ; ptP1p = ptP1s ; bNext1 = PL1.GetNextUPoint( &dU1s, &ptP1s, bClosed) ; if ( bNext1) @@ -1124,14 +1124,14 @@ SurfTriMesh::VerifyPolylinesForTwoCurves( const PolyLine& PL1, const PolyLine& P dA2p = 0 ; dA2s = ( dU2s - dU2F) / dDeltaU2 ; // se chiuse, verifico la coincidenza dell'inizio delle due curve - if ( bClosed && AreSamePointNear( ptP1p, ptP2p)) + if ( bClosed && AreSamePointApprox( ptP1p, ptP2p)) return false ; // verifiche sui punti successivi (non sugli ultimi) while ( bNext1 || bNext2) { // se c'è nuovo dA1s e la diagonale più corta è dA2p -> dA1s oppure non c'è dA2s if ( ( bNext1 && ( dA1s - dA2p) <= ( dA2s - dA1p) + EPS_PARAM) || ! bNext2) { // verifico se coincidono - if ( AreSamePointNear( ptP2p, ptP1s)) + if ( AreSamePointApprox( ptP2p, ptP1s)) return false ; // passo al punto successivo su 1 dA1p = dA1s ; dU1p = dU1s ; ptP1p = ptP1s ; @@ -1142,7 +1142,7 @@ SurfTriMesh::VerifyPolylinesForTwoCurves( const PolyLine& PL1, const PolyLine& P // altrimenti è dA1p -> dA2s = 1 else { // verifico se coincidono - if ( AreSamePointNear( ptP1p, ptP2s)) + if ( AreSamePointApprox( ptP1p, ptP2s)) return false ; // passo al punto successivo su 2 dA2p = dA2s ; dU2p = dU2s ; ptP2p = ptP2s ; @@ -1381,8 +1381,8 @@ SurfTriMesh::VeryfyPolylineForRevolution( const PolyLine& PL, const Point3d& ptA // verifico distanza if ( DistPointLine( ORIG, ptPp, ptPc).IsSmall()) { if ( bClosed || - ( ! ( nSeg == 1 && AreSamePointNear( ORIG, ptPp)) && - ! ( nSeg == nTotSeg && AreSamePointNear( ORIG, ptPc)))) + ( ! ( nSeg == 1 && AreSamePointApprox( ORIG, ptPp)) && + ! ( nSeg == nTotSeg && AreSamePointApprox( ORIG, ptPc)))) return false ; } // salvo punto diff --git a/Triangulate.cpp b/Triangulate.cpp index ba5a167..63c8bf6 100644 --- a/Triangulate.cpp +++ b/Triangulate.cpp @@ -78,11 +78,8 @@ Triangulate::Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr) return false ; // se era CW, devo invertire il senso dei triangoli - if ( ! bCCW) { - int nSize = int( vTr.size()) ; - for ( int i = 0 ; i < nSize / 2 ; ++ i) - swap( vTr[i], vTr[nSize-i-1]) ; - } + if ( ! bCCW) + reverse( vTr.begin(), vTr.end()) ; return true ; } @@ -322,11 +319,11 @@ bool Triangulate::TestPointInTriangle( const Point3d& ptP, const Point3d& ptA, const Point3d& ptB, const Point3d& ptC) { // if P is on a vertex is considered outside - if ( AreSamePointNear( ptP, ptA)) + if ( AreSamePointApprox( ptP, ptA)) return false ; - if ( AreSamePointNear( ptP, ptB)) + if ( AreSamePointApprox( ptP, ptB)) return false ; - if ( AreSamePointNear( ptP, ptC)) + if ( AreSamePointApprox( ptP, ptC)) return false ; // if P is on the right of at least one edge is outside if ( TriangleIsCCW( ptA, ptP, ptB)) diff --git a/Vector3d.cpp b/Vector3d.cpp index e59ec12..977f3b7 100644 --- a/Vector3d.cpp +++ b/Vector3d.cpp @@ -45,7 +45,7 @@ Vector3d::FromPolar( double dLen, double dAngDeg) } //---------------------------------------------------------------------------- -// Lunghezza di un vettore +// Lunghezza del vettore //---------------------------------------------------------------------------- double Vector3d::Len( void) const @@ -61,7 +61,7 @@ Vector3d::Len( void) const } //---------------------------------------------------------------------------- -// Lunghezza di un vettore nel piano XY +// Lunghezza del vettore nel piano XY //---------------------------------------------------------------------------- double Vector3d::LenXY( void) const @@ -155,7 +155,7 @@ Vector3d::Rotate( const Vector3d& vtAx, double dAngDeg) } //---------------------------------------------------------------------------- -// Rotazione +// Rotazione da coseno e seno dell'angolo di rotazione //---------------------------------------------------------------------------- bool Vector3d::Rotate( const Vector3d& vtAx, double dCosAng, double dSinAng) @@ -373,6 +373,31 @@ Vector3d::GetAngle( const Vector3d& vtEnd, double& dAngDeg) const return true ; } +//---------------------------------------------------------------------------- +// Calcolo dell'angolo tra il vettore e un altro nel piano XY +//---------------------------------------------------------------------------- +bool +Vector3d::GetAngleXY( const Vector3d& vtEnd, double& dAngDeg) const +{ + double dProSca ; + double dProVett ; + + + // quantità ugualmente proporzionali a coseno e seno + dProSca = ScalarXY( *this, vtEnd) ; + dProVett = CrossXY( *this, vtEnd) ; + + // se entrambe nulle + if ( fabs( dProSca) < EPS_ZERO && fabs( dProVett) < EPS_ZERO) { + dAngDeg = 0 ; + return false ; + } + + dAngDeg = atan2( dProVett, dProSca) * RADTODEG ; + + return true ; +} + //---------------------------------------------------------------------------- // Calcolo angolo di rotazione per portare la componente del vettore perpendicolare // all'asse di rotazione sulla stessa direzione della componente perpendicolare di vtEnd