diff --git a/CurveArc.cpp b/CurveArc.cpp index f0eafb6..26096e8 100644 --- a/CurveArc.cpp +++ b/CurveArc.cpp @@ -1012,10 +1012,11 @@ CurveArc::ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, PolyLin return false ; // determino se approssimazione interna o esterna - bool bCCW = ( (( m_VtExtr * m_VtN) > - EPS_ZERO) ? ( m_dAngCenDeg > 0) : ( m_dAngCenDeg < 0)) ; + Vector3d vtExtr = ( m_VtExtr.IsSmall() ? Z_AX : m_VtExtr) ; + bool bCCW = ( (( vtExtr * m_VtN) > - EPS_ZERO) ? ( m_dAngCenDeg > 0) : ( m_dAngCenDeg < 0)) ; bool bInside = true ; - if ( ( nType == APL_RIGHT && bCCW) || - ( nType == APL_LEFT && ! bCCW)) + if ( ( ( nType == APL_RIGHT || nType == APL_RIGHT_CONVEX) && bCCW) || + ( ( nType == APL_LEFT || nType == APL_LEFT_CONVEX) && ! bCCW)) bInside = false ; // eseguo approssimazione @@ -1027,6 +1028,12 @@ CurveArc::ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, PolyLin return false ; } + // se necessario, sistemo per convessità dalla parte ammessa + if ( nType == APL_RIGHT_CONVEX || nType == APL_LEFT_CONVEX) { + if ( ! PL.MakeConvex( vtExtr, ( nType == APL_LEFT_CONVEX))) + return false ; + } + return true ; } diff --git a/CurveBezier.cpp b/CurveBezier.cpp index dcf7fb0..fd041bd 100644 --- a/CurveBezier.cpp +++ b/CurveBezier.cpp @@ -1331,13 +1331,21 @@ CurveBezier::ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, Poly dAngTolDeg = max( dAngTolDeg, ANG_TOL_MIN_DEG) ; // se lineare con lato obbligato, gestione speciale - if ( nType == APL_LEFT || nType == APL_RIGHT) { + if ( nType == APL_LEFT || nType == APL_LEFT_CONVEX || + nType == APL_RIGHT || nType == APL_RIGHT_CONVEX) { // prima approssimazione lineare a 10 * Epsilon if ( ! ApproxWithLines( 10 * EPS_SMALL, dAngTolDeg, APL_STD, PL)) return false ; // eliminazione dei punti in tolleranza andando solo dalla parte ammessa - Vector3d vtN = ( m_VtExtr.IsSmall() ? Z_AX : m_VtExtr) ; - return PL.ApproxOnSide( vtN, ( nType == APL_LEFT), dLinTol) ; + Vector3d vtExtr = ( m_VtExtr.IsSmall() ? Z_AX : m_VtExtr) ; + if ( ! PL.ApproxOnSide( vtExtr, ( nType == APL_LEFT), dLinTol)) + return false ; + // se necessario, sistemo per convessità dalla parte ammessa + if ( nType == APL_RIGHT_CONVEX || nType == APL_LEFT_CONVEX) { + if ( ! PL.MakeConvex( vtExtr, ( nType == APL_LEFT_CONVEX))) + return false ; + } + return true ; } // inserisco il punto iniziale diff --git a/CurveComposite.cpp b/CurveComposite.cpp index 7f8ff6d..c68b6e9 100644 --- a/CurveComposite.cpp +++ b/CurveComposite.cpp @@ -35,7 +35,7 @@ GEOOBJ_REGISTER( CRV_COMPO, NGE_C_CMP, CurveComposite) ; //---------------------------------------------------------------------------- CurveComposite::CurveComposite( void) - : m_nStatus( TO_VERIFY), m_bClosed( false), m_VtExtr(), m_dThick(), m_nTempProp() + : m_nStatus( TO_VERIFY), m_VtExtr(), m_dThick(), m_nTempProp() { } @@ -57,7 +57,6 @@ CurveComposite::Clear( void) m_CrvSmplS.clear() ; m_nStatus = TO_VERIFY ; - m_bClosed = false ; m_VtExtr = V_NULL ; m_dThick = 0 ; m_nTempProp = 0 ; @@ -193,10 +192,12 @@ CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart, double dLinT // se inserita alla fine if ( bEndOrStart) { // verifico sia in continuità con il finale attuale - if ( ! AreSamePointApprox( ptStart, m_PtEnd)) { + Point3d ptEnd ; + GetEndPoint( ptEnd) ; + if ( ! AreSamePointApprox( ptStart, ptEnd)) { // se in tolleranza, modifico l'inizio dell'entità - if ( SqDist( ptStart, m_PtEnd) < ( dLinTol * dLinTol)) { - if ( ! pCrv->ModifyStart( m_PtEnd)) + if ( SqDist( ptStart, ptEnd) < ( dLinTol * dLinTol)) { + if ( ! pCrv->ModifyStart( ptEnd)) return false ; } else @@ -206,10 +207,12 @@ CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart, double dLinT // altrimenti inserita all'inizio else { // verifico sia in continuità con l'iniziale attuale - if ( ! AreSamePointApprox( ptEnd, m_PtStart)) { + Point3d ptStart ; + GetStartPoint( ptStart) ; + if ( ! AreSamePointApprox( ptEnd, ptStart)) { // se in tolleranza, modifico la fine dell'entità - if ( SqDist( ptEnd, m_PtStart) < ( dLinTol * dLinTol)) { - if ( ! pCrv->ModifyEnd( m_PtStart)) + if ( SqDist( ptEnd, ptStart) < ( dLinTol * dLinTol)) { + if ( ! pCrv->ModifyEnd( ptStart)) return false ; } else @@ -218,29 +221,12 @@ CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart, double dLinT } } - // se prima curva, assegno il punto iniziale o finale - if ( m_CrvSmplS.empty()) { - if ( bEndOrStart) - m_PtStart = ptStart ; - else - m_PtEnd = ptEnd ; - } - // inserisco la curva nella lista if ( bEndOrStart) m_CrvSmplS.push_back( ::Release( pCrv)) ; else m_CrvSmplS.push_front( ::Release( pCrv)) ; - // assegno il nuovo punto estremo - if ( bEndOrStart) - m_PtEnd = ptEnd ; - else - m_PtStart = ptStart ; - - // aggiorno il flag di curva chiusa - m_bClosed = ( AreSamePointApprox( m_PtStart, m_PtEnd)) ; - // aggiorno lo stato m_nStatus = OK ; @@ -255,11 +241,14 @@ CurveComposite::Close( void) if ( m_nStatus != OK) return false ; // se già chiusa, non faccio alcunché - if ( m_bClosed) + if ( IsClosed()) return true ; // aggiungo la linea di chiusura PtrOwner pLine( CreateBasicCurveLine()) ; - if ( ! pLine->Set( m_PtEnd, m_PtStart) || + Point3d ptStart, ptEnd ; + if ( ! GetStartPoint( ptStart) || + ! GetEndPoint( ptEnd) || + ! pLine->Set( ptEnd, ptStart) || ! AddSimpleCurve( Release( pLine))) return false ; // imposto ricalcolo della grafica @@ -795,46 +784,11 @@ CurveComposite::Validate( void) } // aggiorno m_nStatus = ( nCount > 0 ? OK : TO_VERIFY) ; - if ( m_nStatus == OK) { - m_CrvSmplS.front()->GetStartPoint( m_PtStart) ; - m_CrvSmplS.back()->GetEndPoint( m_PtEnd) ; - m_bClosed = ( AreSamePointApprox( m_PtStart, m_PtEnd)) ; - } - else - m_bClosed = false ; } return ( m_nStatus == OK) ; } -//---------------------------------------------------------------------------- -bool -CurveComposite::ValidateMoveStart( void) -{ - // ci deve essere almeno una curva - if ( m_CrvSmplS.empty()) - return false ; - // imposto punto iniziale e verifico curva chiusa - if ( ! m_CrvSmplS.front()->GetStartPoint( m_PtStart)) - return false ; - m_bClosed = ( AreSamePointApprox( m_PtStart, m_PtEnd)) ; - return true ; -} - -//---------------------------------------------------------------------------- -bool -CurveComposite::ValidateMoveEnd( void) -{ - // ci deve essere almeno una curva - if ( m_CrvSmplS.empty()) - return false ; - // imposto punto finale e verifica curva chiusa - if ( ! m_CrvSmplS.back()->GetEndPoint( m_PtEnd)) - return false ; - m_bClosed = ( AreSamePointApprox( m_PtStart, m_PtEnd)) ; - return true ; -} - //---------------------------------------------------------------------------- bool CurveComposite::IsFlat( Plane3d& plPlane, double dToler) const @@ -930,18 +884,31 @@ CurveComposite::IsFlat( Plane3d& plPlane, double dToler) const return bFlat ; } +//---------------------------------------------------------------------------- +bool +CurveComposite::IsClosed( void) const +{ + // verifico lo stato + if ( m_nStatus != OK || m_CrvSmplS.empty()) + return false ; + + // ricavo punti iniziale e finale e li confronto + Point3d ptStart, ptEnd ; + return ( m_CrvSmplS.front()->GetStartPoint( ptStart) && + m_CrvSmplS.back()->GetEndPoint( ptEnd) && + AreSamePointApprox( ptStart, ptEnd)) ; +} + //---------------------------------------------------------------------------- bool CurveComposite::GetStartPoint( Point3d& ptStart) const { // verifico lo stato - if ( m_nStatus != OK) + if ( m_nStatus != OK || m_CrvSmplS.empty()) return false ; // assegno il punto - ptStart = m_PtStart ; - - return true ; + return m_CrvSmplS.front()->GetStartPoint( ptStart) ; } //---------------------------------------------------------------------------- @@ -949,13 +916,11 @@ bool CurveComposite::GetEndPoint( Point3d& ptEnd) const { // verifico lo stato - if ( m_nStatus != OK) + if ( m_nStatus != OK || m_CrvSmplS.empty()) return false ; // assegno il punto - ptEnd = m_PtEnd ; - - return true ; + return m_CrvSmplS.back()->GetEndPoint( ptEnd) ; } //---------------------------------------------------------------------------- @@ -995,6 +960,30 @@ CurveComposite::GetCentroid( Point3d& ptCen) const return GetMidPoint( ptCen) ; } +//---------------------------------------------------------------------------- +bool +CurveComposite::GetStartDir( Vector3d& vtDir) const +{ + // verifico lo stato + if ( m_nStatus != OK || m_CrvSmplS.empty()) + return false ; + + // assegno il punto + return m_CrvSmplS.front()->GetStartDir( vtDir) ; +} + +//---------------------------------------------------------------------------- +bool +CurveComposite::GetEndDir( Vector3d& vtDir) const +{ + // verifico lo stato + if ( m_nStatus != OK || m_CrvSmplS.empty()) + return false ; + + // assegno il punto + return m_CrvSmplS.back()->GetEndDir( vtDir) ; +} + //---------------------------------------------------------------------------- bool CurveComposite::GetMidDir( Vector3d& vtDir) const @@ -1039,7 +1028,7 @@ CurveComposite::GetIndSCurveAndLocPar( double dU, Side nS, int& nSCrv, double& d // 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) + if ( IsClosed() && nS == ICurve::FROM_MINUS) dU = dMaxU ; // altrimenti posso valutare solo dopo l'inizio else { @@ -1049,7 +1038,7 @@ CurveComposite::GetIndSCurveAndLocPar( double dU, Side nS, int& nSCrv, double& d } else if ( dU > ( dMaxU - EPS_PARAM)) { // se chiusa e voglio valutare dopo la fine devo valutare dopo l'inizio - if ( m_bClosed && nS == ICurve::FROM_PLUS) + if ( IsClosed() && nS == ICurve::FROM_PLUS) dU = 0 ; // altrimenti posso valutare solo prima della fine else { @@ -1268,6 +1257,13 @@ CurveComposite::ApproxWithLines( double dLinTol, double dAngTolDeg, int nType, P dStartPar += 1 ; } + // se necessario, sistemo per convessità dalla parte ammessa + if ( nType == APL_RIGHT_CONVEX || nType == APL_LEFT_CONVEX) { + Vector3d vtExtr = ( m_VtExtr.IsSmall() ? Z_AX : m_VtExtr) ; + if ( ! PL.MakeConvex( vtExtr, ( nType == APL_LEFT_CONVEX))) + return false ; + } + return true ; } @@ -1321,7 +1317,7 @@ CurveComposite::CopyParamRange( double dUStart, double dUEnd) const // se il parametro start supera quello di end if ( dUStart > dUEnd - EPS_PARAM) { // se curva aperta, il trim la cancella completamente quindi non resta alcunchè - if ( ! m_bClosed) + if ( ! IsClosed()) return nullptr ; // se curva chiusa, il trim si avvolge attorno al punto di giunzione else @@ -1361,16 +1357,12 @@ CurveComposite::Invert( void) return false ; // inverto le singole curve - PCSD_ITER Iter ; - for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) + for ( auto Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) (*Iter)->Invert() ; // inverto l'ordine della lista reverse( m_CrvSmplS.begin(), m_CrvSmplS.end()) ; - // scambio punti iniziale e finale - swap( m_PtStart, m_PtEnd) ; - // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1425,9 +1417,6 @@ CurveComposite::ModifyStart( const Point3d& ptNewStart) // modifico l'inizio di questa curva if ( ! pCrv->ModifyStart( ptNewStart)) return false ; - // aggiorno il punto iniziale e il flag di curva chiusa - m_PtStart = ptNewStart ; - m_bClosed = ( AreSamePointApprox( m_PtStart, m_PtEnd)) ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1449,9 +1438,6 @@ CurveComposite::ModifyEnd( const Point3d& ptNewEnd) // modifico la fine di questa curva if ( ! pCrv->ModifyEnd( ptNewEnd)) return false ; - // aggiorno il punto finale e il flag di curva chiusa - m_PtEnd = ptNewEnd ; - m_bClosed = ( AreSamePointApprox( m_PtStart, m_PtEnd)) ; // imposto ricalcolo della grafica m_OGrMgr.Reset() ; @@ -1465,8 +1451,7 @@ CurveComposite::TrimStartAtParam( double dUTrim) { // ciclo sulle diverse curve dall'inizio double dUToTrim = dUTrim ; - PCSD_ITER Iter ; - for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ;) { + for ( auto Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ;) { // dominio parametrico della curva semplice double dParStart, dParEnd ; (*Iter)->GetDomain( dParStart, dParEnd) ; @@ -1486,14 +1471,10 @@ CurveComposite::TrimStartAtParam( double dUTrim) m_CrvSmplS.pop_front() ; if ( m_CrvSmplS.empty()) return false ; - (*Iter)->GetStartPoint( m_PtStart) ; - 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 = ( AreSamePointApprox( m_PtStart, m_PtEnd)) ; break ; } } @@ -1511,8 +1492,7 @@ CurveComposite::TrimEndAtParam( double dUTrim) // ciclo sulle diverse curve dalla fine bool bToErase = false ; double dUToTrim = dUTrim ; - PCSD_ITER Iter ; - for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ;) { + for ( auto Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ;) { // dominio parametrico della curva semplice double dParStart, dParEnd ; (*Iter)->GetDomain( dParStart, dParEnd) ; @@ -1530,9 +1510,6 @@ CurveComposite::TrimEndAtParam( double dUTrim) } // se lunghezza parametrica ancora da tagliare nulla (entro la tolleranza) else if ( dUToTrim > - EPS_PARAM) { - // imposto punto finale e verifico curva chiusa - (*Iter)->GetEndPoint( m_PtEnd) ; - m_bClosed = ( AreSamePointApprox( m_PtStart, m_PtEnd)) ; // passo alla entità successiva ++ Iter ; // dichiaro ingresso in zona da cancellare @@ -1546,9 +1523,6 @@ CurveComposite::TrimEndAtParam( double dUTrim) bToErase = true ; continue ; } - // imposto punto finale e verifica curva chiusa - (*Iter)->GetEndPoint( m_PtEnd) ; - m_bClosed = ( AreSamePointApprox( m_PtStart, m_PtEnd)) ; // passo alla entità successiva ++ Iter ; // dichiaro ingresso in zona da cancellare @@ -1575,7 +1549,7 @@ CurveComposite::TrimStartEndAtParam( double dUStartTrim, double dUEndTrim) // se il parametro start supera quello di end if ( dUStartTrim > dUEndTrim - EPS_PARAM) { // se curva aperta, il trim la cancella completamente quindi errore - if ( ! m_bClosed) + if ( ! IsClosed()) return false ; // se curva chiusa, il trim interessa il punto di giunzione else { @@ -1619,8 +1593,7 @@ CurveComposite::TrimStartAtLen( double dLenTrim) { // ciclo sulle diverse curve dall'inizio double dLenToTrim = dLenTrim ; - PCSD_ITER Iter ; - for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ;) { + for ( auto Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ;) { // lunghezza della curva double dCrvLen ; if ( ! (*Iter)->GetLength( dCrvLen)) @@ -1642,8 +1615,6 @@ CurveComposite::TrimStartAtLen( double dLenTrim) m_CrvSmplS.pop_front() ; if ( m_CrvSmplS.empty()) return false ; - (*Iter)->GetStartPoint( m_PtStart) ; - m_bClosed = ( AreSamePointApprox( m_PtStart, m_PtEnd)) ; break ; } // altrimenti superata lunghezza ancora da tagliare @@ -1652,8 +1623,6 @@ CurveComposite::TrimStartAtLen( double dLenTrim) m_nStatus = ERR ; return false ; } - (*Iter)->GetStartPoint( m_PtStart) ; - m_bClosed = ( AreSamePointApprox( m_PtStart, m_PtEnd)) ; break ; } } @@ -1671,8 +1640,7 @@ CurveComposite::TrimEndAtLen( double dLenTrim) // ciclo sulle diverse curve dalla fine bool bToErase = false ; double dLenToTrim = dLenTrim ; - PCSD_ITER Iter ; - for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ;) { + for ( auto Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ;) { double dCrvLen ; // se non sono già nella zona da cancellare, aggiorno lunghezze if ( ! bToErase) { @@ -1695,9 +1663,6 @@ CurveComposite::TrimEndAtLen( double dLenTrim) } // se lunghezza ancora da tagliare nulla (entro la tolleranza) else if ( dLenToTrim > - EPS_SMALL) { - // imposto punto finale e verifica curva chiusa - (*Iter)->GetEndPoint( m_PtEnd) ; - m_bClosed = ( AreSamePointApprox( m_PtStart, m_PtEnd)) ; // passo alla entità successiva ++ Iter ; // dichiaro ingresso in zona da cancellare @@ -1710,9 +1675,6 @@ CurveComposite::TrimEndAtLen( double dLenTrim) m_nStatus = ERR ; return false ; } - // imposto punto finale e verifica curva chiusa - (*Iter)->GetEndPoint( m_PtEnd) ; - m_bClosed = ( AreSamePointApprox( m_PtStart, m_PtEnd)) ; // passo alla entità successiva ++ Iter ; // dichiaro ingresso in zona da cancellare @@ -1743,9 +1705,6 @@ CurveComposite::ExtendStartByLen( double dLenExt) return false ; } - // imposto punto iniziale e verifica curva chiusa - ValidateMoveStart() ; - // imposto ricalcolo della grafica m_OGrMgr.Reset() ; return true ; @@ -1760,7 +1719,7 @@ CurveComposite::ExtendEndByLen( double dLenExt) return false ; // vado sulla fine - PCSD_ITER Iter = m_CrvSmplS.end() ; + auto Iter = m_CrvSmplS.end() ; if ( Iter == m_CrvSmplS.begin()) return false ; -- Iter ; @@ -1773,9 +1732,6 @@ CurveComposite::ExtendEndByLen( double dLenExt) return false ; } - // imposto punto finale e verifica curva chiusa - ValidateMoveEnd() ; - // imposto ricalcolo della grafica m_OGrMgr.Reset() ; return true ; @@ -1789,13 +1745,8 @@ CurveComposite::Translate( const Vector3d& vtMove) m_OGrMgr.Reset() ; // traslo le singole curve - PCSD_ITER Iter ; - for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) - (*Iter)->Translate( vtMove) ; - - // traslo i punti estremi - m_PtStart.Translate( vtMove) ; - m_PtEnd.Translate( vtMove) ; + for ( auto& pCrv : m_CrvSmplS) + pCrv->Translate( vtMove) ; return true ; } @@ -1812,13 +1763,9 @@ CurveComposite::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAn m_OGrMgr.Reset() ; // ruoto le singole curve - PCSD_ITER Iter ; - for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) - (*Iter)->Rotate( ptAx, vtAx, dCosAng, dSinAng) ; + for ( auto& pCrv : m_CrvSmplS) + pCrv->Rotate( ptAx, vtAx, dCosAng, dSinAng) ; - // ruoto i punti estremi - m_PtStart.Rotate( ptAx, vtAx, dCosAng, dSinAng) ; - m_PtEnd.Rotate( ptAx, vtAx, dCosAng, dSinAng) ; // ruoto il vettore estrusione m_VtExtr.Rotate( vtAx, dCosAng, dSinAng) ; @@ -1857,7 +1804,7 @@ CurveComposite::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, dou } // scalo le singole curve - for ( PCSD_ITER Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ) { + for ( auto Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ) { // eseguo la scalatura bool bOk = (*Iter)->Scale( frRef, dCoeffX, dCoeffY, dCoeffZ) ; // se tutto bene, passo alla prossima @@ -1871,9 +1818,6 @@ CurveComposite::Scale( const Frame3d& frRef, double dCoeffX, double dCoeffY, dou } } - // scalo i punti estremi - m_PtStart.Scale( frRef, dCoeffX, dCoeffY, dCoeffZ) ; - m_PtEnd.Scale( frRef, dCoeffX, dCoeffY, dCoeffZ) ; // scalo vettore estrusione, lo normalizzo e aggiusto spessore m_VtExtr.Scale( frRef, dCoeffX, dCoeffY, dCoeffZ) ; double dLen = m_VtExtr.Len() ; @@ -1898,13 +1842,9 @@ CurveComposite::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) m_OGrMgr.Reset() ; // specchio le singole curve - PCSD_ITER Iter ; - for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) - (*Iter)->Mirror( ptOn, vtNorm) ; + for ( auto& pCrv : m_CrvSmplS) + pCrv->Mirror( ptOn, vtNorm) ; - // specchio i punti estremi - m_PtStart.Mirror( ptOn, vtNorm) ; - m_PtEnd.Mirror( ptOn, vtNorm) ; // specchio il vettore estrusione m_VtExtr.Mirror( vtNorm) ; @@ -1927,13 +1867,9 @@ CurveComposite::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector return false ; // eseguo scorrimento delle singole curve - PCSD_ITER Iter ; - for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) - (*Iter)->Shear( ptOn, vtNorm, vtDir, dCoeff) ; + for ( auto& pCrv : m_CrvSmplS) + pCrv->Shear( ptOn, vtNorm, vtDir, dCoeff) ; - // eseguo scorrimento dei punti estremi - m_PtStart.Shear( ptOn, vtNorm, vtDir, dCoeff) ; - m_PtEnd.Shear( ptOn, vtNorm, vtDir, dCoeff) ; // eseguo scorrimento del vettore estrusione, lo normalizzo e aggiusto spessore m_VtExtr.Shear( vtNorm, vtDir, dCoeff) ; double dLen = m_VtExtr.Len() ; @@ -1957,13 +1893,10 @@ CurveComposite::ToGlob( const Frame3d& frRef) m_OGrMgr.Reset() ; // trasformo le singole curve - PCSD_ITER Iter ; - for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) - (*Iter)->ToGlob( frRef) ; + for ( auto& pCrv : m_CrvSmplS) + pCrv->ToGlob( frRef) ; - // trasformo i punti estremi e il vettore estrusione - m_PtStart.ToGlob( frRef) ; - m_PtEnd.ToGlob( frRef) ; + // trasformo il vettore estrusione m_VtExtr.ToGlob( frRef) ; return true ; @@ -1981,13 +1914,10 @@ CurveComposite::ToLoc( const Frame3d& frRef) m_OGrMgr.Reset() ; // trasformo le singole curve - PCSD_ITER Iter ; - for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) - (*Iter)->ToLoc( frRef) ; + for ( auto& pCrv : m_CrvSmplS) + pCrv->ToLoc( frRef) ; - // trasformo i punti estremi e il vettore estrusione - m_PtStart.ToLoc( frRef) ; - m_PtEnd.ToLoc( frRef) ; + // trasformo il vettore estrusione m_VtExtr.ToLoc( frRef) ; return true ; @@ -2009,14 +1939,10 @@ CurveComposite::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) m_OGrMgr.Reset() ; // trasformo le singole curve - PCSD_ITER Iter ; - for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) { - (*Iter)->LocToLoc( frOri, frDest) ; - } + for ( auto& pCrv : m_CrvSmplS) + pCrv->LocToLoc( frOri, frDest) ; - // trasformo i punti estremi e il vettore estrusione - m_PtStart.LocToLoc( frOri, frDest) ; - m_PtEnd.LocToLoc( frOri, frDest) ; + // trasformo il vettore estrusione m_VtExtr.LocToLoc( frOri, frDest) ; return true ; @@ -2063,6 +1989,8 @@ CurveComposite::GetNextCurve( void) const return nullptr ; // vado al successivo + if ( m_Iter == m_CrvSmplS.end()) + return nullptr ; ++ m_Iter ; // recupero la curva @@ -2129,23 +2057,15 @@ CurveComposite::RemoveFirstOrLastCurve( bool bLast) pCrv = *(m_CrvSmplS.rbegin()) ; // la tolgo dalla lista m_CrvSmplS.pop_back() ; - // aggiorno la curva composita - pCrv->GetStartPoint( m_PtEnd) ; } else { // recupero la curva pCrv = *(m_CrvSmplS.begin()) ; // la tolgo dalla lista m_CrvSmplS.pop_front() ; - // aggiorno la curva composita - pCrv->GetEndPoint( m_PtStart) ; } // eseguo mini verifica m_nStatus = ( m_CrvSmplS.size() > 0 ? OK : TO_VERIFY) ; - if ( m_nStatus == OK) - m_bClosed = ( AreSamePointApprox( m_PtStart, m_PtEnd)) ; - else - m_bClosed = false ; // assegno estrusione e spessore della curva composita pCrv->SetExtrusion( m_VtExtr) ; pCrv->SetThickness( m_dThick) ; @@ -2160,8 +2080,9 @@ bool CurveComposite::IsParamAtJoint( double dU) const { // 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 - double( m_CrvSmplS.size())) < EPS_ZERO) || + bool bClosed = IsClosed() ; + if ( ( ! bClosed && fabs( dU) < EPS_ZERO) || + ( ! bClosed && fabs( dU - double( m_CrvSmplS.size())) < EPS_ZERO) || fabs( dU - (int) ( dU + EPS_ZERO)) > EPS_ZERO) return false ; else @@ -2204,11 +2125,9 @@ CurveComposite::ArcsToBezierCurves( void) if ( pCC == nullptr) return false ; // inserisco le curve prima dell'arco - int nParts = 0 ; for ( PCSD_ITER Iter2 = pCC->m_CrvSmplS.begin() ; Iter2 != pCC->m_CrvSmplS.end() ; ++ Iter2) { Iter = m_CrvSmplS.insert( Iter, (*Iter2)) ; ++ Iter ; - ++ nParts ; } pCC->m_CrvSmplS.clear() ; // elimino l'arco (e sposto l'iteratore alla curva precedente) @@ -2250,12 +2169,10 @@ CurveComposite::ArcsBezierCurvesToArcsPerpExtr( double dLinTol, double dAngTolDe if ( pCC == nullptr) return false ; // inserisco le curve prima dell'originale - int nParts = 0 ; PCSD_ITER Iter2 ; for ( Iter2 = pCC->m_CrvSmplS.begin() ; Iter2 != pCC->m_CrvSmplS.end() ; ++ Iter2) { Iter = m_CrvSmplS.insert( Iter, (*Iter2)) ; ++ Iter ; - ++ nParts ; } pCC->m_CrvSmplS.clear() ; // elimino l'arco (e sposto l'iteratore alla curva precedente) diff --git a/CurveComposite.h b/CurveComposite.h index 5982965..604a31f 100644 --- a/CurveComposite.h +++ b/CurveComposite.h @@ -58,8 +58,7 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW public : // ICurve virtual bool IsSimple( void) const { return false ; } - virtual bool IsClosed( void) const - { return ( m_nStatus == OK && m_bClosed) ; } + virtual bool IsClosed( void) const ; virtual bool IsFlat( Plane3d& plPlane, double dToler = EPS_SMALL) const ; virtual bool GetStartPoint( Point3d& ptStart) const ; virtual bool GetEndPoint( Point3d& ptEnd) const ; @@ -67,10 +66,8 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW virtual bool GetCenterPoint( Point3d& ptCen) const { return GetMidPoint( ptCen) ; } virtual bool GetCentroid( Point3d& ptCen) const ; - virtual bool GetStartDir( Vector3d& vtDir) const - { return ::GetTang( *this, 0, FROM_PLUS, vtDir) ; } - virtual bool GetEndDir( Vector3d& vtDir) const - { return ::GetTang( *this, double( m_CrvSmplS.size()), FROM_MINUS, vtDir) ; } + virtual bool GetStartDir( Vector3d& vtDir) const ; + virtual bool GetEndDir( Vector3d& vtDir) const ; virtual bool GetMidDir( Vector3d& vtDir) const ; virtual bool GetExtrusion( Vector3d& vtExtr) const { vtExtr = m_VtExtr ; return ( m_nStatus == OK) ; } @@ -164,8 +161,6 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW private : bool CopyFrom( const CurveComposite& ccSrc) ; bool Validate( void) ; - bool ValidateMoveStart( void) ; - bool ValidateMoveEnd( void) ; bool AddCurveByRelocate( CurveComposite& ccSrc, bool bEndOrStart = true, double dLinTol = EPS_SMALL) ; bool AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart = true, double dLinTol = EPS_SMALL) ; bool GetIndSCurveAndLocPar( double dU, Side nS, int& nSCrv, double& dLocU) const ; @@ -184,9 +179,6 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto Status m_nStatus ; // stato 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 Vector3d m_VtExtr ; // vettore estrusione (normalmente coincide con m_VtN) double m_dThick ; // spessore int m_nTempProp ; // proprietà temporanea diff --git a/CurveCompositeOffset.cpp b/CurveCompositeOffset.cpp index 76eafaa..57badfc 100644 --- a/CurveCompositeOffset.cpp +++ b/CurveCompositeOffset.cpp @@ -96,7 +96,6 @@ CurveComposite::SimpleOffsetXY( double dDist, int nType) if ( VerifyAndAdjustSamePoint( pCrv1, pCrv2, ccTemp) || VerifyAndAdjustInternalAngle( pCrv1, pCrv2, ccTemp) || VerifyAndAdjustExternalAngle( pCrv1, pCrv2, dDist, nType, ccTemp)) { - ccOffs.ValidateMoveEnd() ; if ( ccTemp.GetCurveNumber() > 0 && ! ccOffs.AddCurveByRelocate( ccTemp)) return false ; } @@ -121,8 +120,6 @@ CurveComposite::SimpleOffsetXY( double dDist, int nType) if ( VerifyAndAdjustSamePoint( pCrv1, pCrv2, ccTemp) || VerifyAndAdjustInternalAngle( pCrv1, pCrv2, ccTemp) || VerifyAndAdjustExternalAngle( pCrv1, pCrv2, dDist, nType, ccTemp)) { - ccOffs.ValidateMoveStart() ; - ccOffs.ValidateMoveEnd() ; if ( ccTemp.GetCurveNumber() > 0 && ! ccOffs.AddCurveByRelocate( ccTemp)) return false ; } diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index e5077bf..96b1d77 100644 Binary files a/EgtGeomKernel.rc and b/EgtGeomKernel.rc differ diff --git a/FontManager.cpp b/FontManager.cpp index 0f3bcaf..eaeb973 100644 --- a/FontManager.cpp +++ b/FontManager.cpp @@ -45,11 +45,15 @@ FontManager::SetCurrFont( const string& sFont, int nWeight, bool bItalic, // lo cerco tra i font Nfe if ( FileExtensionMatches( sFontName, "NFE")) { - // verifico che il font richiesto esista, altrimenti prendo il primo dello stesso tipo + // verifico che il font richiesto esista, altrimenti prendo default se Nfe string sPath = m_sNfeFontDir + "\\" + sFontName ; if ( ! ExistsFile( sPath)) { - if ( FindFirstFileEgt( m_sNfeFontDir + "\\*.Nfe", sFontName)) - sPath = m_sNfeFontDir + "\\" + sFontName ; + sPath = m_sNfeFontDir + "\\" + m_sDefaultFont ; + // verifico esistenza, altrimenti prendo il primo dello stesso tipo + if ( ! ExistsFile( sPath)) { + if ( FindFirstFileEgt( m_sNfeFontDir + "\\*.Nfe", sFontName)) + sPath = m_sNfeFontDir + "\\" + sFontName ; + } } // imposto il font corrente m_bCurrNfeFont = true ; diff --git a/IntersLineSurfTm.cpp b/IntersLineSurfTm.cpp index 671ea89..ce2024d 100644 --- a/IntersLineSurfTm.cpp +++ b/IntersLineSurfTm.cpp @@ -44,7 +44,14 @@ IntersLineSurfTm( const Point3d& ptL, const Vector3d& vtL, double dLen, const IS int nRes = IntersLineTria( ptL, vtDir, dLen, Tria, ptInt, ptInt2) ; if ( nRes == ILTT_IN || nRes == ILTT_EDGE || nRes == ILTT_VERT) { double dU = ( ptInt - ptL) * vtDir ; - vInfo.emplace_back( dU, nT, ptInt) ; + double dCosDN = vtDir * Tria.GetN() ; + vInfo.emplace_back( nRes, dU, nT, dCosDN, ptInt) ; + } + else if ( nRes == ILTT_SEGM || nRes == ILTT_SEGM_ON_EDGE) { + double dU = ( ptInt - ptL) * vtDir ; + double dU2 = ( ptInt2 - ptL) * vtDir ; + double dCosDN = vtDir * Tria.GetN() ; + vInfo.emplace_back( nRes, dU, dU2, nT, dCosDN, ptInt, ptInt2) ; } nT = Stm.GetNextTriangle( nT, Tria) ; } diff --git a/IntersLineTria.cpp b/IntersLineTria.cpp index 3fdcc69..8c0500f 100644 --- a/IntersLineTria.cpp +++ b/IntersLineTria.cpp @@ -2,7 +2,7 @@ // EgalTech 2015-2015 //---------------------------------------------------------------------------- // File : IntersLinePlane.cpp Data : 18.02.15 Versione : 1.6b7 -// Contenuto : Implementazione della intersezione linea/piano. +// Contenuto : Implementazione della intersezione linea/triangolo. // // // @@ -14,9 +14,17 @@ //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "ProjPlane.h" +#include "CurveLine.h" +#include "IntersLineLine.h" +#include "/EgtDev/Include/EGkFrame3d.h" #include "/EgtDev/Include/EGkIntersLineTria.h" #include "/EgtDev/Include/EGkIntersLinePlane.h" + +//---------------------------------------------------------------------------- +static int IntersCoplanarLineTria( const Point3d& ptL, const Vector3d& vtL, double dLen, const Triangle3d& trTria, + Point3d& ptInt, Point3d& ptInt2) ; + //---------------------------------------------------------------------------- int IntersLineTria( const Point3d& ptL1, const Point3d& ptL2, const Triangle3d& trTria, @@ -61,7 +69,120 @@ IntersLineTria( const Point3d& ptL, const Vector3d& vtL, double dLen, const Tria } // se la linea giace nel piano del triangolo else { - // !!!! DA FARE !!!! - return ILTT_NO ; + return IntersCoplanarLineTria( ptL, vtL, dLen, trTria, ptInt, ptInt2) ; } } + +//---------------------------------------------------------------------------- +int +IntersCoplanarLineTria( const Point3d& ptL, const Vector3d& vtL, double dLen, const Triangle3d& trTria, + Point3d& ptInt, Point3d& ptInt2) +{ + // verifico se il segmento è completamente contenuto nel triangolo + ptInt = ptL ; + ptInt2 = ptL + vtL * dLen ; + int nPTT = PointInTria( ptInt, trTria) ; + int nPTT2 = PointInTria( ptInt2, trTria) ; + if ( nPTT != PTT_OUT && nPTT2 != PTT_OUT) + return ILTT_SEGM ; + // se segmento nullo, basta verificare la posizione del punto iniziale + if ( dLen < EPS_SMALL || vtL.IsSmall()) { + switch ( nPTT) { + case PTT_OUT : + return ILTT_NO ; + case PTT_VERT : + return ILTT_VERT ; + case PTT_EDGE : + return ILTT_EDGE ; + default : + return ILTT_IN ; + } + } + // definisco un riferimento coincidente con il piano del triangolo + Frame3d frRef ; + if ( ! frRef.Set( trTria.GetP( 0), trTria.GetN(), ( trTria.GetP( 1) - trTria.GetP( 0)))) + return ILTT_NO ; + // esprimo il triangolo e il segmento in questo riferimento + Triangle3d trTriaL = trTria ; + trTriaL.ToLoc( frRef) ; + Point3d ptLL = ptL ; + ptLL.ToLoc( frRef) ; + Vector3d vtLL = vtL ; + vtLL.ToLoc( frRef) ; + // calcolo le intersezioni tra i lati del triangolo e il segmento + CurveLine LineLL ; + LineLL.Set( ptLL, ptLL + vtLL * dLen) ; + int nNumInt = 0 ; + IntCrvCrvInfo IntCCI[3] ; + for ( int i = 0 ; i < 3 ; ++ i) { + CurveLine LineTL ; + LineTL.Set( trTriaL.GetP( i), trTriaL.GetP( ( i + 1) % 3)) ; + IntersLineLine IntLL( LineLL, LineTL) ; + if ( IntLL.GetIntCrvCrvInfo( IntCCI[nNumInt])) + ++ nNumInt ; + } + // se nessuna intersezione + if ( nNumInt == 0) + return ILTT_NO ; + // se una sola intersezione + else if ( nNumInt == 1) { + // punto di intersezione + Point3d ptIntL = IntCCI[0].IciA[0].ptI ; + ptInt = ptIntL ; + ptInt.ToGlob( frRef) ; + // se è l'inizio del segmento ( e il resto del segmento deve essere per forza esterno) + if ( AreSamePointApprox( ptIntL, LineLL.GetStart())) + return ( ( nPTT == PTT_VERT) ? ILTT_VERT : ILTT_EDGE) ; + // se è la fine del segmento ( e il resto del segmento deve essere per forza esterno) + else if ( AreSamePointApprox( ptIntL, LineLL.GetEnd())) + return ( ( nPTT2 == PTT_VERT) ? ILTT_VERT : ILTT_EDGE) ; + // altrimenti è un punto intermedio + else { + // se l'inizio è nel triangolo + if ( nPTT == PTT_IN) { + ptInt2 = ptInt ; + ptInt = ptL ; + } + // altrimenti è la fine nel triangolo + else + ptInt2 = ptL + vtL * dLen ; + return ILTT_SEGM ; + } + } + // se 2 intersezioni + else if ( nNumInt == 2) { + // punti di intersezione + Point3d ptIntL = IntCCI[0].IciA[0].ptI ; + ptInt = ptIntL ; + ptInt.ToGlob( frRef) ; + Point3d ptInt2L = IntCCI[1].IciA[0].ptI ; + ptInt2 = ptInt2L ; + ptInt2.ToGlob( frRef) ; + // se coincidono, deve essere un vertice + if ( AreSamePointApprox( ptIntL, ptInt2L)) + return ILTT_VERT ; + // altrimenti è un tratto + else { + // le ordino secondo il verso positivo della linea + if ( ( ptInt - ptL) * vtL > ( ptInt2 - ptL) * vtL) + std::swap( ptInt, ptInt2) ; + return ILTT_SEGM ; + } + } + // altrimenti 3 intersezioni, una deve coincidere con un lato le altre due sono i suoi vertici + else { + for ( int i = 0 ; i < 3 ; ++ i) { + if ( IntCCI[i].bOverlap) { + // punti di intersezione + Point3d ptIntL = IntCCI[i].IciA[0].ptI ; + ptInt = ptIntL ; + ptInt.ToGlob( frRef) ; + Point3d ptInt2L = IntCCI[i].IciA[1].ptI ; + ptInt2 = ptInt2L ; + ptInt2.ToGlob( frRef) ; + return ILTT_SEGM_ON_EDGE ; + } + } + } + return ILTT_NO ; +} \ No newline at end of file diff --git a/PolyLine.cpp b/PolyLine.cpp index de5f016..49c98b4 100644 --- a/PolyLine.cpp +++ b/PolyLine.cpp @@ -835,6 +835,54 @@ PolyLine::ApproxOnSide( const Vector3d& vtN, bool bLeftSide, double dToler) return true ; } +//---------------------------------------------------------------------------- +bool +PolyLine::MakeConvex( const Vector3d& vtN, bool bLeftSide) +{ + // ciclo i controlli finchè non ci sono rimozioni + bool bRemoved = true ; + while ( bRemoved) { + bRemoved = false ; + // se non ci sono almeno 3 punti, esco subito + if ( m_lUPoints.size() < 3) + return true ; + // punto precedente + auto precP = m_lUPoints.begin() ; + // punto corrente + auto currP = next( precP) ; + // punto successivo + auto nextP = next( currP) ; + // mentre esiste un successivo + while ( nextP != m_lUPoints.end()) { + // --- si verifica se possibile eliminare il punto corrente rimanendo dal lato voluto --- + // se lato sinistro e gira a sinistra o lato destro e gira a destra + double dCrossXY = ( ( currP->first - precP->first) ^ ( nextP->first - currP->first)) * vtN ; + if ( ( bLeftSide && dCrossXY > - EPS_ZERO) || ( ! bLeftSide && dCrossXY < EPS_ZERO)) { + // elimino il punto corrente + m_lUPoints.erase( currP) ; + // avanzo con corrente e successivo + currP = nextP ; + ++ nextP ; + // dichiaro rimozione + bRemoved = true ; + continue ; + } + // non è stato eliminato alcunché : avanzo il terzetto di uno step + precP = currP ; + currP = nextP ; + ++ nextP ; + } + // se rimasti due punti coincidenti, elimino il secondo + if ( m_lUPoints.size() == 2 && + AreSamePointApprox( m_lUPoints.front().first, m_lUPoints.back().first)) { + m_lUPoints.pop_back() ; + return false ; + } + } + + return true ; +} + //---------------------------------------------------------------------------- bool PolyLine::Invert( bool bInvertU)