From f119a5a1be82ed44452b7b0d63e49500b22e6d97 Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Tue, 24 Jun 2014 07:05:43 +0000 Subject: [PATCH] EgtGeomKernel 1.5f6 : - agg. intersezione linee-linee - agg. alle curve metodi per passare da lunghezza a parametro e viceversa - agg. metodi per creare curve composite come poligoni regolari - corr. errore in triangulate con contorni CW - agg. opportune funzioni a TSC. --- CurveArc.cpp | 89 +++++++ CurveArc.h | 3 + CurveBezier.cpp | 27 +- CurveBezier.h | 1 + CurveComposite.cpp | 479 ++++++++++++++++++++++++++++------ CurveComposite.h | 28 +- CurveLine.cpp | 85 ++++++ CurveLine.h | 3 + DistPointCurve.cpp | 10 +- DistPointLine.h | 2 +- EgtGeomKernel.rc | Bin 11710 -> 11710 bytes EgtGeomKernel.vcxproj | 4 + EgtGeomKernel.vcxproj.filters | 12 + GdbExecutor.cpp | 193 +++++++++++++- GdbExecutor.h | 5 +- IntersCurveCurve.cpp | 199 ++++++++++++++ IntersLineLine.cpp | 220 ++++++++++++++++ IntersLineLine.h | 65 +++++ PolyLine.cpp | 2 +- Triangulate.cpp | 26 +- Vector3d.cpp | 23 +- 21 files changed, 1347 insertions(+), 129 deletions(-) create mode 100644 IntersCurveCurve.cpp create mode 100644 IntersLineLine.cpp create mode 100644 IntersLineLine.h diff --git a/CurveArc.cpp b/CurveArc.cpp index e58d17a..f875f4e 100644 --- a/CurveArc.cpp +++ b/CurveArc.cpp @@ -741,6 +741,80 @@ CurveArc::GetLength( double& dLen) const return ( dLen > EPS_SMALL) ; } +//---------------------------------------------------------------------------- +bool +CurveArc::GetLengthAtParam( double dU, double& dLen) const +{ + // verifico lo stato + if ( m_nStatus != OK) + return false ; + + // fuori dominio del parametro -> errore + if ( dU < 0 - EPS_PARAM) + return false ; + if ( dU > ( 1 + EPS_PARAM)) + return false ; + + // inizio + if ( dU < 0 + EPS_PARAM) { + dLen = 0 ; + return true ; + } + + // lunghezza totale + double dTotLen ; + if ( ! GetLength( dTotLen)) + return false ; + + // fine + if ( dU > 1 - EPS_PARAM) { + dLen = dTotLen ; + return true ; + } + + // posizione intermedia + dLen = dU * dTotLen ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +CurveArc::GetParamAtLength( double dLen, double& dU) const +{ + // verifico lo stato + if ( m_nStatus != OK) + return false ; + + // se prima di inizio, errore + if ( dLen < - EPS_SMALL) + return false ; + + // inizio + if ( dLen < EPS_SMALL) { + dU = 0 ; + return true ; + } + + // lunghezza totale + double dTotLen ; + if ( ! GetLength( dTotLen)) + return false ; + + // se dopo fine, errore + if ( dLen > dTotLen + EPS_SMALL) + return false ; + + // fine + if ( dLen < dTotLen - EPS_SMALL) { + dU = 1 ; + return true ; + } + + // posizione intermedia + dU = dLen / dTotLen ; + return true ; +} + //---------------------------------------------------------------------------- bool CurveArc::IsPointOn( const Point3d& ptP, double dTol) const @@ -866,6 +940,21 @@ CurveArc::TrimEndAtParam( double dUTrim) return TrimEndAtLen( dUTrim * dLen) ; } +//---------------------------------------------------------------------------- +bool +CurveArc::TrimStartEndAtParam( double dUStartTrim, double dUEndTrim) +{ + // verifico che i trim non cancellino interamente la curva + if ( dUStartTrim > dUEndTrim - EPS_PARAM) + return false ; + // trim finale + if ( ! TrimEndAtParam( dUEndTrim)) + return false ; + // trim iniziale con il parametro opportunamente ricalcolato + double dNewUStartTrim = dUStartTrim / dUEndTrim ; + return TrimStartAtParam( dNewUStartTrim) ; +} + //---------------------------------------------------------------------------- bool CurveArc::TrimStartAtLen( double dLenTrim) diff --git a/CurveArc.h b/CurveArc.h index 8bad016..2acb6f5 100644 --- a/CurveArc.h +++ b/CurveArc.h @@ -68,6 +68,8 @@ class CurveArc : public ICurveArc, public IGeoObjRW virtual bool GetDomain( double& dStart, double& dEnd) const { dStart = 0 ; dEnd = 1 ; return ( m_nStatus == OK) ; } virtual bool GetLength( double& dLen) const ; + virtual bool GetLengthAtParam( double dU, double& dLen) const ; + virtual bool GetParamAtLength( double dLen, double& dU) const ; virtual bool GetPointD1D2( double dU, Side nS, Point3d& ptPos, Vector3d* pvtDer1 = nullptr, Vector3d* pvtDer2 = nullptr) const ; virtual bool GetPointTang( double dU, Side nS, Point3d& ptPos, Vector3d& vtTang) const @@ -81,6 +83,7 @@ class CurveArc : public ICurveArc, public IGeoObjRW virtual bool Offset( double dDist, int nSide, int nType = OFF_FILLET) ; virtual bool TrimStartAtParam( double dUTrim) ; virtual bool TrimEndAtParam( double dUTrim) ; + virtual bool TrimStartEndAtParam( double dUStartTrim, double dUEndTrim) ; virtual bool TrimStartAtLen( double dLenTrim) ; virtual bool TrimEndAtLen( double dLenTrim) ; diff --git a/CurveBezier.cpp b/CurveBezier.cpp index 74f9148..8d3238f 100644 --- a/CurveBezier.cpp +++ b/CurveBezier.cpp @@ -1061,12 +1061,16 @@ CurveBezier::GetSegmentParam( double dLen, double& dCurrLen, double& dSegLen, bool CurveBezier::GetParamAtLength( double dLen, double& dU) const { - const double MAX_SEG_LEN = 0.2 ; + const double MIN_SEG_LEN = 0.2 ; // la curva deve essere validata if ( m_nStatus != OK) return false ; + // se prima di inizio, errore + if ( dLen < - EPS_SMALL) + return false ; + // inizio if ( dLen < EPS_SMALL) { dU = 0 ; @@ -1079,7 +1083,7 @@ CurveBezier::GetParamAtLength( double dLen, double& dU) const double dCurrLen = 0 ; double dUIni = 0 ; double dUFin = 1 ; - while ( ( bOk = GetSegmentParam( dLen, dCurrLen, dSegLen, dUIni, dUFin)) && dSegLen > MAX_SEG_LEN) + while ( ( bOk = GetSegmentParam( dLen, dCurrLen, dSegLen, dUIni, dUFin)) && dSegLen > MIN_SEG_LEN) ; // aggiustamento finale parametro if ( bOk) @@ -1279,10 +1283,10 @@ CurveBezier::TrimEndAtParam( double dUTrim) return false ; // se devo togliere a partire dall'inizio o prima non rimane niente - if ( dUTrim <= 0) + if ( dUTrim < EPS_PARAM) return false ; // se devo togliere dalla fine o dopo non tolgo niente - if ( dUTrim >= 1) + if ( dUTrim > 1 - EPS_PARAM) return true ; // eseguo il trim (algoritmo di de Casteljau) for ( int k = 1 ; k <= m_nDeg ; k ++) { @@ -1304,6 +1308,21 @@ CurveBezier::TrimEndAtParam( double dUTrim) return true ; } +//---------------------------------------------------------------------------- +bool +CurveBezier::TrimStartEndAtParam( double dUStartTrim, double dUEndTrim) +{ + // verifico che i trim non cancellino interamente la curva + if ( dUStartTrim > dUEndTrim - EPS_PARAM) + return false ; + // trim finale + if ( ! TrimEndAtParam( dUEndTrim)) + return false ; + // trim iniziale con il parametro opportunamente ricalcolato + double dNewUStartTrim = dUStartTrim / dUEndTrim ; + return TrimStartAtParam( dNewUStartTrim) ; +} + //---------------------------------------------------------------------------- bool CurveBezier::TrimStartAtLen( double dLenTrim) diff --git a/CurveBezier.h b/CurveBezier.h index c5fdf0c..04d9b72 100644 --- a/CurveBezier.h +++ b/CurveBezier.h @@ -86,6 +86,7 @@ class CurveBezier : public ICurveBezier, public IGeoObjRW { return false ; } virtual bool TrimStartAtParam( double dUTrim) ; virtual bool TrimEndAtParam( double dUTrim) ; + virtual bool TrimStartEndAtParam( double dUStartTrim, double dUEndTrim) ; virtual bool TrimStartAtLen( double dLenTrim) ; virtual bool TrimEndAtLen( double dLenTrim) ; diff --git a/CurveComposite.cpp b/CurveComposite.cpp index 11a3314..346a59e 100644 --- a/CurveComposite.cpp +++ b/CurveComposite.cpp @@ -66,7 +66,7 @@ CurveComposite::Clear( void) //---------------------------------------------------------------------------- bool -CurveComposite::AddCurve( const ICurve& cCrv) +CurveComposite::AddCurve( const ICurve& cCrv, bool bEndOrStart) { // se curva semplice if ( cCrv.IsSimple()) { @@ -75,7 +75,7 @@ CurveComposite::AddCurve( const ICurve& cCrv) if ( pSmplCrv == nullptr) return false ; // inserisco la curva - if ( ! AddSimpleCurve( pSmplCrv)) + if ( ! AddSimpleCurve( pSmplCrv, bEndOrStart)) return false ; } // altrimenti curva composta, devo aggiungere le singole curve semplici @@ -87,17 +87,17 @@ CurveComposite::AddCurve( const ICurve& cCrv) pCrvCompo = GetCurveComposite( &cCrv) ; if ( pCrvCompo == nullptr) return false ; - pCrvOri = pCrvCompo->GetFirstCurve() ; + pCrvOri = ( bEndOrStart ? pCrvCompo->GetFirstCurve() : pCrvCompo->GetLastCurve()) ; while ( pCrvOri != nullptr) { // creo una copia della curva pSmplCrv = GetCurve( pCrvOri->Clone()) ; if ( pSmplCrv == nullptr) return false ; // inserisco la curva - if ( ! AddSimpleCurve( pSmplCrv)) + if ( ! AddSimpleCurve( pSmplCrv, bEndOrStart)) return false ; // passo alla prossima curva componente - pCrvOri = pCrvCompo->GetNextCurve() ; + pCrvOri = ( bEndOrStart ? pCrvCompo->GetNextCurve() : pCrvCompo->GetPrevCurve()) ; } } @@ -109,12 +109,12 @@ CurveComposite::AddCurve( const ICurve& cCrv) //---------------------------------------------------------------------------- bool -CurveComposite::AddCurve( ICurve* pCrv) +CurveComposite::AddCurve( ICurve* pCrv, bool bEndOrStart) { // se curva semplice if ( pCrv->IsSimple()) { // inserisco la curva - if ( ! AddSimpleCurve( pCrv)) + if ( ! AddSimpleCurve( pCrv, bEndOrStart)) return false ; } // altrimenti curva composta, devo aggiungere le singole curve semplici @@ -125,9 +125,9 @@ CurveComposite::AddCurve( ICurve* pCrv) return false ; // recupero le curve componenti e le inserisco nella lista ICurve* pSmplCrv ; - while ( ( pSmplCrv = pCrvCompo->RemoveFirstCurve()) != nullptr) { + while ( ( pSmplCrv = pCrvCompo->RemoveFirstOrLastCurve( ! bEndOrStart)) != nullptr) { // inserisco la curva - if ( ! AddSimpleCurve( pSmplCrv)) + if ( ! AddSimpleCurve( pSmplCrv, bEndOrStart)) return false ; } // cancello la curva composita originaria @@ -142,12 +142,8 @@ CurveComposite::AddCurve( ICurve* pCrv) //---------------------------------------------------------------------------- bool -CurveComposite::AddSimpleCurve( ICurve* pSmplCrv) +CurveComposite::AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart) { - Point3d ptStart ; - Point3d ptEnd ; - - // prendo la proprietà del puntatore PtrOwner pCrv( pSmplCrv) ; if ( ! ::IsValid( pCrv)) @@ -162,23 +158,42 @@ CurveComposite::AddSimpleCurve( ICurve* pSmplCrv) return false ; // recupero i punti iniziali e finali della curva + Point3d ptStart, ptEnd ; if ( ! pCrv->GetStartPoint( ptStart) || ! pCrv->GetEndPoint( ptEnd)) return false ; - // se non è la prima, verifico sia in continuità con il finale corrente - if ( m_nCounter > 0 && ! AreSamePointNear( ptStart, m_PtEnd)) - return false ; + // se non è la prima + if ( m_nCounter > 0) { + // se inserita alla fine + if ( bEndOrStart) { + // verifico sia in continuità con il finale attuale + if ( ! AreSamePointNear( ptStart, m_PtEnd)) + return false ; + } + // altrimenti inserita all'inizio + else { + // verifico sia in continuità con l'iniziale attuale + if ( ! AreSamePointNear( ptEnd, m_PtStart)) + return false ; + } + } // se prima curva, assegno il punto iniziale if ( m_nCounter == 0) m_PtStart = ptStart ; // inserisco la curva nella lista - m_CrvSmplS.push_back( ::Release( pCrv)) ; + if ( bEndOrStart) + m_CrvSmplS.push_back( ::Release( pCrv)) ; + else + m_CrvSmplS.push_front( ::Release( pCrv)) ; m_nCounter ++ ; - // assegno il punto finale - m_PtEnd = ptEnd ; + // assegno il nuovo punto estremo + if ( bEndOrStart) + m_PtEnd = ptEnd ; + else + m_PtStart = ptStart ; // aggiorno il flag di curva chiusa m_bClosed = ( AreSamePointNear( m_PtStart, m_PtEnd)) ; @@ -319,6 +334,103 @@ CurveComposite::FromPointBulgeVector( const UPNTVECTOR& vUPnt, const Vector3d& v return true ; } +//---------------------------------------------------------------------------- +bool +CurveComposite::PolygonCenterCorner( int nSides, const Point3d& ptCen, const Point3d& ptCorner) +{ + // verifico lo stato + if ( m_nCounter != 0 || m_nStatus != TO_VERIFY) + return false ; + // almeno 3 lati + if ( nSides < 3) + return false ; + + // angolo al centro corrispondente ad un lato + double dAngCenSideDeg = ANG_FULL / nSides ; + double dCosAng = cos( dAngCenSideDeg * DEGTORAD) ; + double dSinAng = sin( dAngCenSideDeg * DEGTORAD) ; + + // ciclo di inserimento dei segmenti che uniscono i punti + Point3d ptStart = ptCorner ; + Point3d ptEnd ; + for ( int i = 1 ; i <= nSides ; ++ i) { + // calcolo il secondo punto del lato + ptEnd = ptStart ; + 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)) + return false ; + } + // creo il segmento di retta + PtrOwner pCrvLine( CreateCurveLine()) ; + if ( ! ::IsValid( pCrvLine)) + return false ; + // assegno i punti estremi + if ( ! pCrvLine->Set( ptStart, ptEnd)) + return false ; + // aggiungo la retta alla curva composita + if ( ! AddSimpleCurve( Release( pCrvLine))) + return false ; + // aggiorno punto iniziale prossimo lato + ptStart = ptEnd ; + } + + // imposto ricalcolo della grafica + m_OGrMgr.Reset() ; + + return true ; +} + +//---------------------------------------------------------------------------- +bool +CurveComposite::PolygonCenterMidSide( int nSides, const Point3d& ptCen, const Point3d& ptMidSide) +{ + // verifico lo stato + if ( m_nCounter != 0 || m_nStatus != TO_VERIFY) + return false ; + // almeno 3 lati + if ( nSides < 3) + return false ; + + // calcolo la posizione del corner + double dHalfCentSideAngDeg = ANG_FULL / ( 2 * nSides) ; + double dCoeff = tan( dHalfCentSideAngDeg * DEGTORAD) ; + Vector3d vtDir = ptCen - ptMidSide ; + vtDir.z = 0 ; + vtDir.Rotate( Z_AX, 0, 1) ; + Point3d ptCorner = ptMidSide + vtDir * dCoeff ; + + // ora costruisco come poligono con centro e corner + return PolygonCenterCorner( nSides, ptCen, ptCorner) ; +} + +//---------------------------------------------------------------------------- +bool +CurveComposite::PolygonSide( int nSides, const Point3d& ptStart, const Point3d& ptEnd) +{ + // verifico lo stato + if ( m_nCounter != 0 || m_nStatus != TO_VERIFY) + return false ; + // almeno 3 lati + if ( nSides < 3) + return false ; + // verifico che la lunghezza sia superiore al minimo + if ( AreSamePointNear( ptStart, ptEnd)) + return false ; + + // calcolo la posizione del centro + double dHalfCentSideAngDeg = ANG_FULL / ( 2 * nSides) ; + double dCoeff = 1 / ( 2 * tan( dHalfCentSideAngDeg * DEGTORAD)) ; + Vector3d vtDir = ptEnd - ptStart ; + vtDir.z = 0 ; + vtDir.Rotate( Z_AX, 0, 1) ; + Point3d ptCen = Media( ptStart, ptEnd, 0.5) + vtDir * dCoeff ; + + // ora costruisco come poligono con centro e corner + return PolygonCenterCorner( nSides, ptCen, ptStart) ; +} + //---------------------------------------------------------------------------- CurveComposite* CurveComposite::Clone( void) const @@ -561,11 +673,15 @@ CurveComposite::Validate( void) (*Iter)->GetEndPoint( ptPrevEnd) ; } // aggiorno - m_nStatus = OK ; + m_nStatus = ( nCount > 0 ? OK : TO_VERIFY) ; m_nCounter = nCount ; - m_CrvSmplS.front()->GetStartPoint( m_PtStart) ; - m_CrvSmplS.back()->GetEndPoint( m_PtEnd) ; - m_bClosed = ( AreSamePointNear( m_PtStart, m_PtEnd)) ; + if ( m_nStatus == OK) { + m_CrvSmplS.front()->GetStartPoint( m_PtStart) ; + m_CrvSmplS.back()->GetEndPoint( m_PtEnd) ; + m_bClosed = ( AreSamePointNear( m_PtStart, m_PtEnd)) ; + } + else + m_bClosed = false ; } return ( m_nStatus == OK) ; @@ -635,20 +751,22 @@ CurveComposite::GetDomain( double& dStart, double& dEnd) const bool CurveComposite::GetPointD1D2( double dU, Side nS, Point3d& ptPos, Vector3d* pvtDer1, Vector3d* pvtDer2) const { - PCRVSMPL_LIST::const_iterator Iter ; - + // verifico lo stato + if ( m_nStatus != OK) + return false ; // il parametro U deve essere compreso tra 0 e m_nCounter - if ( dU < ( 0 + EPS_ZERO)) { + if ( dU < ( 0 + EPS_PARAM)) { dU = 0 ; nS = ICurve::FROM_PLUS ; } - else if ( dU > ( m_nCounter - EPS_ZERO)) { + else if ( dU > ( m_nCounter - EPS_PARAM)) { dU = m_nCounter ; nS = ICurve::FROM_MINUS ; } // 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 @@ -666,13 +784,15 @@ CurveComposite::GetPointD1D2( double dU, Side nS, Point3d& ptPos, Vector3d* pvtD bool CurveComposite::GetLength( double& dLen) const { - double dLenCrvSmpl ; - PCRVSMPL_LIST::const_iterator Iter ; - + // verifico lo stato + if ( m_nStatus != OK) + return false ; // ciclo di calcolo dLen = 0 ; + PCRVSMPL_LIST::const_iterator Iter ; for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) { + double dLenCrvSmpl ; if ( (*Iter)->GetLength( dLenCrvSmpl)) dLen += dLenCrvSmpl ; else @@ -682,10 +802,106 @@ CurveComposite::GetLength( double& dLen) const return true ; } +//---------------------------------------------------------------------------- +bool +CurveComposite::GetLengthAtParam( double dU, double& dLen) const +{ + // verifico lo stato + if ( m_nStatus != OK) + return false ; + + // il parametro U deve essere compreso tra 0 e m_nCounter + if ( dU < - EPS_PARAM || dU > ( m_nCounter + EPS_PARAM)) + return false ; + + // ciclo di calcolo + dLen = 0 ; + double dUToGo = dU ; + PCRVSMPL_LIST::const_iterator Iter ; + for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) { + // dominio parametrico della curva semplice + double dParStart, dParEnd ; + (*Iter)->GetDomain( dParStart, dParEnd) ; + // se resto nella curva + if ( dUToGo <= ( dParEnd - dParStart)) { + double dParamLen ; + if ( ! (*Iter)->GetLengthAtParam( dUToGo, dParamLen)) + return false ; + dLen += dParamLen ; + break ; + } + // altrimenti + else { + // lunghezza parametrica rimanente + dUToGo -= ( dParEnd - dParStart) ; + // lunghezza progressiva + double dCrvLen ; + if ( ! (*Iter)->GetLength( dCrvLen)) + return false ; + dLen += dCrvLen ; + } + } + + return true ; +} + +//---------------------------------------------------------------------------- +bool +CurveComposite::GetParamAtLength( double dLen, double& dU) const +{ + // verifico lo stato + if ( m_nStatus != OK) + return false ; + + // se prima di inizio, errore + if ( dLen < - EPS_SMALL) + return false ; + + // inizio + if ( dLen < EPS_SMALL) { + dU = 0 ; + return true ; + } + + // ciclo di calcolo + dU = 0 ; + double dLenToGo = dLen ; + PCRVSMPL_LIST::const_iterator Iter ; + for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) { + // lunghezza della curva semplice + double dCrvLen ; + if ( ! (*Iter)->GetLength( dCrvLen)) + return false ; + // se resto nella curva + if ( dLenToGo <= dCrvLen) { + double dULen ; + if ( ! (*Iter)->GetParamAtLength( dLenToGo, dULen)) + return false ; + dU += dULen ; + break ; + } + // altrimenti + else { + // lunghezza rimanente + dLenToGo -= dCrvLen ; + // lunghezza parametrica progressiva + double dParStart, dParEnd ; + (*Iter)->GetDomain( dParStart, dParEnd) ; + dU += ( dParEnd - dParStart) ; + } + } + + return false ; +} + //---------------------------------------------------------------------------- bool CurveComposite::IsPointOn( const Point3d& ptP, double dTol) const { + // verifico lo stato + if ( m_nStatus != OK) + return false ; + // verifico che il punto sia sulla curva ( distanza minore di tolleranza) double dSqDist ; dTol = max( dTol, EPS_ZERO) ; return ( DistPointCrvComposite( ptP, *this).GetSqDist( dSqDist) && dSqDist < dTol * dTol) ; @@ -698,7 +914,7 @@ CurveComposite::ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL // pulisco la polilinea PL.Clear() ; - // la curva deve essere validata + // verifico lo stato if ( m_nStatus != OK) return false ; @@ -732,6 +948,10 @@ CurveComposite::ApproxWithLines( double dLinTol, double dAngTolDeg, PolyLine& PL bool CurveComposite::Invert( void) { + // verifico lo stato + if ( m_nStatus != OK) + return false ; + // inverto le singole curve PCRVSMPL_LIST::iterator Iter ; for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ; ++Iter) @@ -753,28 +973,25 @@ CurveComposite::Invert( void) bool CurveComposite::TrimStartAtParam( double dUTrim) { - double dParStart ; - double dParEnd ; - double dUToTrim ; - PCRVSMPL_LIST::iterator Iter ; - - // ciclo sulle diverse curve dall'inizio - dUToTrim = dUTrim ; + double dUToTrim = dUTrim ; + PCRVSMPL_LIST::iterator Iter ; for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ;) { // dominio parametrico della curva semplice + double dParStart, dParEnd ; (*Iter)->GetDomain( dParStart, dParEnd) ; // lunghezza parametrica progressiva dUToTrim -= ( dParEnd - dParStart) ; // se lunghezza ancora da tagliare non nulla - if ( dUToTrim > EPS_ZERO) { + if ( dUToTrim > EPS_PARAM) { delete (*Iter) ; Iter ++ ; m_CrvSmplS.pop_front() ; m_nCounter -- ; } // se lunghezza ancora da tagliare nulla (entro la tolleranza) - else if ( dUToTrim > - EPS_ZERO) { + else if ( dUToTrim > - EPS_PARAM || + ! (*Iter)->TrimStartAtParam( 1 + dUToTrim)) { delete (*Iter) ; Iter ++ ; m_CrvSmplS.pop_front() ; @@ -785,12 +1002,8 @@ CurveComposite::TrimStartAtParam( double dUTrim) m_bClosed = ( AreSamePointNear( m_PtStart, m_PtEnd)) ; break ; } - // altrimenti superata lunghezza ancora da tagliare + // altrimenti superata lunghezza ancora da tagliare (taglio già fatto al test sopra) else { - if ( ! (*Iter)->TrimStartAtParam( 1 + dUToTrim)) { - m_nStatus = ERR ; - return false ; - } (*Iter)->GetStartPoint( m_PtStart) ; m_bClosed = ( AreSamePointNear( m_PtStart, m_PtEnd)) ; break ; @@ -807,18 +1020,13 @@ CurveComposite::TrimStartAtParam( double dUTrim) bool CurveComposite::TrimEndAtParam( double dUTrim) { - bool bToErase ; - double dParStart ; - double dParEnd ; - double dUToTrim ; - PCRVSMPL_LIST::iterator Iter ; - - // ciclo sulle diverse curve dalla fine - bToErase = false ; - dUToTrim = dUTrim ; + bool bToErase = false ; + double dUToTrim = dUTrim ; + PCRVSMPL_LIST::iterator Iter ; for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ;) { // dominio parametrico della curva semplice + double dParStart, dParEnd ; (*Iter)->GetDomain( dParStart, dParEnd) ; // lunghezza parametrica progressiva dUToTrim -= ( dParEnd - dParStart) ; @@ -831,11 +1039,11 @@ CurveComposite::TrimEndAtParam( double dUTrim) m_nCounter -- ; } // se lunghezza parametrica ancora da tagliare non nulla - else if ( dUToTrim > EPS_ZERO) { + else if ( dUToTrim > EPS_PARAM) { Iter ++ ; } // se lunghezza parametrica ancora da tagliare nulla (entro la tolleranza) - else if ( dUToTrim > - EPS_ZERO) { + else if ( dUToTrim > - EPS_PARAM) { // imposto punto finale e verifico curva chiusa (*Iter)->GetEndPoint( m_PtEnd) ; m_bClosed = ( AreSamePointNear( m_PtStart, m_PtEnd)) ; @@ -848,8 +1056,9 @@ CurveComposite::TrimEndAtParam( double dUTrim) else { // trimmo la curva semplice if ( ! (*Iter)->TrimEndAtParam( 1 + dUToTrim)) { - m_nStatus = ERR ; - return false ; + // se trim fallito, rimaneva troppo poco e quindi la cancello + bToErase = true ; + continue ; } // imposto punto finale e verifica curva chiusa (*Iter)->GetEndPoint( m_PtEnd) ; @@ -867,19 +1076,43 @@ CurveComposite::TrimEndAtParam( double dUTrim) return true ; } +//---------------------------------------------------------------------------- +bool +CurveComposite::TrimStartEndAtParam( double dUStartTrim, double dUEndTrim) +{ + // verifico che i trim non cancellino interamente la curva + if ( dUStartTrim > dUEndTrim - EPS_PARAM) + 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 ; + return TrimStartAtParam( dNewUStartTrim) ; + } + // altrimenti, va bene il valore ricevuto come parametro + else + return TrimStartAtParam( dUStartTrim) ; +} + //---------------------------------------------------------------------------- bool CurveComposite::TrimStartAtLen( double dLenTrim) { - double dLenToTrim ; - double dCrvLen ; - PCRVSMPL_LIST::iterator Iter ; - - // ciclo sulle diverse curve dall'inizio - dLenToTrim = dLenTrim ; + double dLenToTrim = dLenTrim ; + PCRVSMPL_LIST::iterator Iter ; for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ;) { // lunghezza della curva + double dCrvLen ; if ( ! (*Iter)->GetLength( dCrvLen)) return false ; // lunghezza progressiva @@ -925,16 +1158,12 @@ CurveComposite::TrimStartAtLen( double dLenTrim) bool CurveComposite::TrimEndAtLen( double dLenTrim) { - bool bToErase ; - double dLenToTrim ; - double dCrvLen ; - PCRVSMPL_LIST::iterator Iter ; - - // ciclo sulle diverse curve dalla fine - bToErase = false ; - dLenToTrim = dLenTrim ; + bool bToErase = false ; + double dLenToTrim = dLenTrim ; + PCRVSMPL_LIST::iterator Iter ; for ( Iter = m_CrvSmplS.begin() ; Iter != m_CrvSmplS.end() ;) { + double dCrvLen ; // se non sono già nella zona da cancellare, aggiorno lunghezze if ( ! bToErase) { // lunghezza della curva @@ -1196,7 +1425,7 @@ CurveComposite::GetFirstCurve( void) const return nullptr ; // vado all'inizio - *(const_cast (&m_Iter)) = m_CrvSmplS.begin() ; + m_Iter = m_CrvSmplS.begin() ; // recupero la curva if ( m_Iter != m_CrvSmplS.end()) @@ -1214,7 +1443,7 @@ CurveComposite::GetNextCurve( void) const return nullptr ; // vado al successivo - (*(const_cast (&m_Iter))) ++ ; + ++ m_Iter ; // recupero la curva if ( m_Iter != m_CrvSmplS.end()) @@ -1223,18 +1452,79 @@ CurveComposite::GetNextCurve( void) const return nullptr ; } +//---------------------------------------------------------------------------- +const ICurve* +CurveComposite::GetLastCurve( void) const +{ + // la curva deve essere validata + if ( m_nStatus != OK) + return nullptr ; + + // vado alla fine + m_Iter = m_CrvSmplS.end() ; + if ( m_Iter == m_CrvSmplS.begin()) + return nullptr ; + -- m_Iter ; + + // recupero la curva + if ( m_Iter != m_CrvSmplS.end()) + return (*m_Iter) ; + else + return nullptr ; +} + +//---------------------------------------------------------------------------- +const ICurve* +CurveComposite::GetPrevCurve( void) const +{ + // la curva deve essere validata + if ( m_nStatus != OK) + return nullptr ; + + // vado al precedente + if ( m_Iter == m_CrvSmplS.begin()) + return nullptr ; + -- m_Iter ; + + // recupero la curva + return (*m_Iter) ; +} + //---------------------------------------------------------------------------- ICurve* -CurveComposite::RemoveFirstCurve( void) +CurveComposite::RemoveFirstOrLastCurve( bool bLast) { // la curva composita deve essere validata if ( m_nStatus != OK) return nullptr ; - // recupero la curva semplice iniziale e la tolgo dalla lista + // recupero la curva semplice iniziale o finale e la tolgo dalla lista if ( ! m_CrvSmplS.empty()) { - ICurve* pCrv = *(m_CrvSmplS.begin()) ; - m_CrvSmplS.pop_front() ; + ICurve* pCrv ; + if ( bLast) { + // recupero la curva + pCrv = *(m_CrvSmplS.rbegin()) ; + // la tolgo dalla lista + m_CrvSmplS.pop_back() ; + // aggiorno la curva composita + pCrv->GetStartPoint( m_PtEnd) ; + -- m_nCounter ; + } + else { + // recupero la curva + pCrv = *(m_CrvSmplS.begin()) ; + // la tolgo dalla lista + m_CrvSmplS.pop_front() ; + // aggiorno la curva composita + pCrv->GetEndPoint( m_PtStart) ; + -- m_nCounter ; + } + // eseguo mini verifica + m_nStatus = ( m_nCounter > 0 ? OK : TO_VERIFY) ; + if ( m_nStatus == OK) + m_bClosed = ( AreSamePointNear( m_PtStart, m_PtEnd)) ; + else + m_bClosed = false ; return pCrv ; } else @@ -1254,6 +1544,37 @@ CurveComposite::IsParamAtJoint( double dU) const return true ; } +//---------------------------------------------------------------------------- +bool +CurveComposite::ChangeStartPoint( double dU) +{ + // la curva deve essere chiusa (ne verifica anche lo stato) + if ( ! IsClosed()) + return false ; + + // il nuovo inizio è l'estremo di una curva semplice più vicino al parametro ricevuto + int nCurve = static_cast ( dU + 0.5) ; + + // verifico ci siano abbastanza curve + if ( nCurve > m_nCounter) + return false ; + + // tolgo le curve dalla testa e le inserisco in coda + for ( int i = 0 ; i < nCurve ; ++ i) { + // estraggo la curva dall'inizio + ICurve* pCrv = RemoveFirstOrLastCurve( false) ; + if ( pCrv == nullptr) + return false ; + // la inserisco alla fine + if ( ! AddCurve( pCrv, true)) { + delete pCrv ; + return false ; + } + } + + return true ; +} + //---------------------------------------------------------------------------- bool CurveComposite::ArcsToBezierCurves( void) diff --git a/CurveComposite.h b/CurveComposite.h index 699c732..cffb2f2 100644 --- a/CurveComposite.h +++ b/CurveComposite.h @@ -55,7 +55,7 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW public : // ICurve virtual bool IsSimple( void) const { return false ; } virtual bool IsClosed( void) const - { return ::IsClosed( *this) ; } + { return ( m_nStatus == OK && m_bClosed) ; } virtual bool GetStartPoint( Point3d& ptStart) const ; virtual bool GetEndPoint( Point3d& ptEnd) const ; virtual bool GetMidPoint( Point3d& ptMid) const ; @@ -64,11 +64,13 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW virtual bool GetStartDir( Vector3d& vtDir) const { return ::GetTang( *this, 0, FROM_PLUS, vtDir) ; } virtual bool GetEndDir( Vector3d& vtDir) const - { return ::GetTang( *this, 1, FROM_MINUS, vtDir) ; } + { return ::GetTang( *this, m_nCounter, FROM_MINUS, vtDir) ; } virtual bool GetMidDir( Vector3d& vtDir) const - { return ::GetTang( *this, 0.5, FROM_MINUS, vtDir) ; } + { return ::GetTang( *this, 0.5 * m_nCounter, FROM_MINUS, vtDir) ; } virtual bool GetDomain( double& dStart, double& dEnd) const ; virtual bool GetLength( double& dLen) const ; + virtual bool GetLengthAtParam( double dU, double& dLen) const ; + virtual bool GetParamAtLength( double dLen, double& dU) const ; virtual bool GetPointD1D2( double dU, Side nS, Point3d& ptPos, Vector3d* pvtDer1 = nullptr, Vector3d* pvtDer2 = nullptr) const ; virtual bool GetPointTang( double dU, Side nS, Point3d& ptPos, Vector3d& vtTang) const @@ -83,21 +85,30 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW { return false ; } virtual bool TrimStartAtParam( double dUTrim) ; virtual bool TrimEndAtParam( double dUTrim) ; + virtual bool TrimStartEndAtParam( double dUStartTrim, double dUEndTrim) ; virtual bool TrimStartAtLen( double dLenTrim) ; virtual bool TrimEndAtLen( double dLenTrim) ; public : // ICurveComposite virtual bool Copy( const IGeoObj* pGObjSrc) ; virtual bool Clear( void) ; - virtual bool AddCurve( const ICurve& cCrv) ; - virtual bool AddCurve( ICurve* pCrv) ; + virtual bool AddCurve( const ICurve& cCrv, bool bEndOrStart = true) ; + virtual bool AddCurve( ICurve* pCrv, bool bEndOrStart = true) ; virtual bool FromSplit( const ICurve& cCrv, int nParts) ; virtual bool FromPointVector( const PNTVECTOR& vPnt) ; virtual bool FromPointBulgeVector( const UPNTVECTOR& vUPnt, const Vector3d& vtN) ; - virtual int GetCurveNumber( void) const { return m_nCounter ; } + virtual bool PolygonCenterCorner( int nSides, const Point3d& ptCen, const Point3d& ptCorner) ; + virtual bool PolygonCenterMidSide( int nSides, const Point3d& ptCen, const Point3d& ptMidSide) ; + virtual bool PolygonSide( int nSides, const Point3d& ptStart, const Point3d& ptEnd) ; + virtual int GetCurveNumber( void) const + { return m_nCounter ; } virtual const ICurve* GetFirstCurve( void) const ; virtual const ICurve* GetNextCurve( void) const ; + virtual const ICurve* GetLastCurve( void) const ; + virtual const ICurve* GetPrevCurve( void) const ; virtual bool IsParamAtJoint( double dU) const ; + virtual ICurve* RemoveFirstOrLastCurve( bool bLast = true) ; + virtual bool ChangeStartPoint( double dU) ; virtual bool ArcsToBezierCurves( void) ; public : // IGeoObjRW @@ -115,8 +126,7 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW private : bool Copy( const CurveComposite& ccSrc) ; bool Validate( void) ; - bool AddSimpleCurve( ICurve* pSmplCrv) ; - ICurve* RemoveFirstCurve( void) ; + bool AddSimpleCurve( ICurve* pSmplCrv, bool bEndOrStart = true) ; private : enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ; @@ -132,5 +142,5 @@ class CurveComposite : public ICurveComposite, public IGeoObjRW Point3d m_PtStart ; // punto iniziale Point3d m_PtEnd ; // punto finale bool m_bClosed ; // flag per indicare che la curva è chiusa - PCRVSMPL_LIST::const_iterator m_Iter ; // iteratore + mutable PCRVSMPL_LIST::const_iterator m_Iter ; // iteratore } ; diff --git a/CurveLine.cpp b/CurveLine.cpp index 019c056..88db4e0 100644 --- a/CurveLine.cpp +++ b/CurveLine.cpp @@ -328,6 +328,76 @@ CurveLine::GetLength( double& dLen) const return ( dLen > EPS_SMALL) ; } +//---------------------------------------------------------------------------- +bool +CurveLine::GetLengthAtParam( double dU, double& dLen) const +{ + // verifico lo stato + if ( m_nStatus != OK) + return false ; + + // fuori dominio del parametro -> errore + if ( dU < 0 - EPS_PARAM) + return false ; + if ( dU > ( 1 + EPS_PARAM)) + return false ; + + // inizio + if ( dU < 0 + EPS_PARAM) { + dLen = 0 ; + return true ; + } + + // la lunghezza totale è la distanza tra gli estremi + double dTotLen = Dist( m_PtStart, m_PtEnd) ; + + // fine + if ( dU > 1 - EPS_PARAM) { + dLen = dTotLen ; + return true ; + } + + // posizione intermedia + dLen = dU * dTotLen ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +CurveLine::GetParamAtLength( double dLen, double& dU) const +{ + // verifico lo stato + if ( m_nStatus != OK) + return false ; + + // se prima di inizio, errore + if ( dLen < - EPS_SMALL) + return false ; + + // inizio + if ( dLen < EPS_SMALL) { + dU = 0 ; + return true ; + } + + // la lunghezza totale è la distanza tra gli estremi + double dTotLen = Dist( m_PtStart, m_PtEnd) ; + + // se dopo fine, errore + if ( dLen > dTotLen + EPS_SMALL) + return false ; + + // fine + if ( dLen < dTotLen - EPS_SMALL) { + dU = 1 ; + return true ; + } + + // posizione intermedia + dU = dLen / dTotLen ; + return true ; +} + //---------------------------------------------------------------------------- bool CurveLine::IsPointOn( const Point3d& ptP, double dTol) const @@ -433,6 +503,21 @@ CurveLine::TrimEndAtParam( double dUTrim) return TrimEndAtLen( dUTrim * dLen) ; } +//---------------------------------------------------------------------------- +bool +CurveLine::TrimStartEndAtParam( double dUStartTrim, double dUEndTrim) +{ + // verifico che i trim non cancellino interamente la curva + if ( dUStartTrim > dUEndTrim - EPS_PARAM) + return false ; + // trim finale + if ( ! TrimEndAtParam( dUEndTrim)) + return false ; + // trim iniziale con il parametro opportunamente ricalcolato + double dNewUStartTrim = dUStartTrim / dUEndTrim ; + return TrimStartAtParam( dNewUStartTrim) ; +} + //---------------------------------------------------------------------------- bool CurveLine::TrimStartAtLen( double dLenTrim) diff --git a/CurveLine.h b/CurveLine.h index aaf9183..c1546f2 100644 --- a/CurveLine.h +++ b/CurveLine.h @@ -68,6 +68,8 @@ class CurveLine : public ICurveLine, public IGeoObjRW virtual bool GetDomain( double& dStart, double& dEnd) const { dStart = 0 ; dEnd = 1 ; return ( m_nStatus == OK) ; } virtual bool GetLength( double& dLen) const ; + virtual bool GetLengthAtParam( double dU, double& dLen) const ; + virtual bool GetParamAtLength( double dLen, double& dU) const ; virtual bool GetPointD1D2( double dU, Side nS, Point3d& ptPos, Vector3d* pvtDer1 = nullptr, Vector3d* pvtDer2 = nullptr) const ; virtual bool GetPointTang( double dU, Side nS, Point3d& ptPos, Vector3d& vtTang) const @@ -81,6 +83,7 @@ class CurveLine : public ICurveLine, public IGeoObjRW virtual bool Offset( double dDist, int nSide, int nType = OFF_FILLET) ; virtual bool TrimStartAtParam( double dUTrim) ; virtual bool TrimEndAtParam( double dUTrim) ; + virtual bool TrimStartEndAtParam( double dUStartTrim, double dUEndTrim) ; virtual bool TrimStartAtLen( double dLenTrim) ; virtual bool TrimEndAtLen( double dLenTrim) ; diff --git a/DistPointCurve.cpp b/DistPointCurve.cpp index 7c5b2d8..c02785a 100644 --- a/DistPointCurve.cpp +++ b/DistPointCurve.cpp @@ -21,8 +21,10 @@ //---------------------------------------------------------------------------- -DistPointCurve::DistPointCurve( const Point3d& ptP, const ICurve& Curve) +DistPointCurve::DistPointCurve( const Point3d& ptP, const ICurve& Curve, bool bIsSegment) { + // Il flag bIsSegment vale solo per linee. + // distanza non calcolata e curva sconosciuta m_dDist = - 1 ; m_pCurve = nullptr ; @@ -34,7 +36,7 @@ DistPointCurve::DistPointCurve( const Point3d& ptP, const ICurve& Curve) // chiamo calcolatore opportuno switch ( Curve.GetType()) { case CRV_LINE : - LineCalculate( ptP, Curve) ; + LineCalculate( ptP, Curve, bIsSegment) ; break ; case CRV_ARC : ArcCalculate( ptP, Curve) ; @@ -52,9 +54,9 @@ DistPointCurve::DistPointCurve( const Point3d& ptP, const ICurve& Curve) //---------------------------------------------------------------------------- void -DistPointCurve::LineCalculate( const Point3d& ptP, const ICurve& Curve) +DistPointCurve::LineCalculate( const Point3d& ptP, const ICurve& Curve, bool bIsSegment) { - DistPointLine dstPtLn( ptP, *GetCurveLine( &Curve)) ; + DistPointLine dstPtLn( ptP, *GetCurveLine( &Curve), bIsSegment) ; if ( dstPtLn.m_dSqDist > 0) { m_dDist = sqrt( dstPtLn.m_dSqDist) ; diff --git a/DistPointLine.h b/DistPointLine.h index cbe21e7..15a6c92 100644 --- a/DistPointLine.h +++ b/DistPointLine.h @@ -2,7 +2,7 @@ // EgalTech 2013-2014 //---------------------------------------------------------------------------- // File : DistPointLine.h Data : 02.01.14 Versione : 1.5a1 -// Contenuto : Dichiarazione dell'oggetto distanza punto da linea/segmento. +// Contenuto : Dichiarazione della classe distanza punto da linea/segmento. // // // diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index d36b9fcf05829598d84bd976ace35b498694ed72..526cbd9101b0624cd7d58fc399f8fbdec4687328 100644 GIT binary patch delta 81 zcmdlNy)SyhH#SDI&FAG5nSs + + @@ -309,6 +311,7 @@ copy $(TargetPath) \EgtProg\Dll64 + @@ -359,6 +362,7 @@ copy $(TargetPath) \EgtProg\Dll64 + diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters index 1c40fce..d99c584 100644 --- a/EgtGeomKernel.vcxproj.filters +++ b/EgtGeomKernel.vcxproj.filters @@ -189,6 +189,12 @@ File di origine\GeoCreate + + File di origine\GeoInters + + + File di origine\GeoInters + @@ -467,6 +473,12 @@ File di intestazione + + File di intestazione + + + File di intestazione + diff --git a/GdbExecutor.cpp b/GdbExecutor.cpp index aebf250..8ec6539 100644 --- a/GdbExecutor.cpp +++ b/GdbExecutor.cpp @@ -33,6 +33,7 @@ #include "/EgtDev/Include/EgkCurveBezier.h" #include "/EgtDev/Include/EgkCurveComposite.h" #include "/EgtDev/Include/EgkDistPointCurve.h" +#include "/EgtDev/Include/EgkIntersCurveCurve.h" #include "/EgtDev/Include/EgkSurfTriMesh.h" #include "/EgtDev/Include/EgkExtText.h" #include "/EgtDev/Include/EgtPointerOwner.h" @@ -41,8 +42,14 @@ using namespace std ; //---------------------------------------------------------------------------- +// Per Id di entità static const int ID_SEL = -2 ; static const int ID_NO = -3 ; +// Per tipo di costruzione di poligono +static const int POLYG_INSCR = 1 ; +static const int POLYG_CIRC = 2 ; +static const int POLYG_SIDE = 3 ; + //---------------------------------------------------------------------------- IGdbExecutor* @@ -1523,9 +1530,30 @@ GdbExecutor::ExecuteCurveCompo( const string& sCmd2, const STRVECTOR& vsParams) // creazione da split di curva semplice else if ( sCmd2 == "S" || sCmd2 == "FROMSPLIT") return CurveCompoFromSplit( vsParams) ; - // modifica per aggiunta di una curva - else if ( sCmd2 == "ADD" || sCmd2 == "ADDCURVE") - return CurveCompoAddCurve( vsParams) ; + // creazione come poligono inscritto + else if ( sCmd2 == "POLYGIN" || sCmd2 == "FROMPOLYGONINSCRIBED") + return CurveCompoFromPolygon( vsParams, POLYG_INSCR) ; + // creazione come poligono circoscritto + else if ( sCmd2 == "POLYGCIRC" || sCmd2 == "FROMPOLYGONCIRCUMSCRIBED") + return CurveCompoFromPolygon( vsParams, POLYG_CIRC) ; + // creazione come poligono dato il lato + else if ( sCmd2 == "POLYGSIDE" || sCmd2 == "FROMPOLYGONSIDE") + return CurveCompoFromPolygon( vsParams, POLYG_SIDE) ; + // modifica per aggiunta di una curva alla fine + else if ( sCmd2 == "AEC" || sCmd2 == "ADDENDCURVE") + return CurveCompoAddCurve( vsParams, true) ; + // modifica per aggiunta di una curva all'inizio + else if ( sCmd2 == "ASC" || sCmd2 == "ADDSTARTCURVE") + return CurveCompoAddCurve( vsParams, false) ; + // modifica per estrazione della curva finale + else if ( sCmd2 == "EEC" || sCmd2 == "EXTRACTENDCURVE") + return CurveCompoExtractCurve( vsParams, true) ; + // modifica per estrazione della curva iniziale + else if ( sCmd2 == "ESC" || sCmd2 == "EXTRACTSTARTCURVE") + return CurveCompoExtractCurve( vsParams, false) ; + // cambio punto di partenza (se chiusa) + else if ( sCmd2 == "CS" || sCmd2 == "CHANGESTART") + return CurveCompoChangeStart( vsParams) ; // altrimenti errore else return false ; @@ -1696,10 +1724,8 @@ GdbExecutor::CurveCompoFromSplit( const STRVECTOR& vsParams) if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frDest)) return false ; // porto la curva composita dal riferimento della sorgente a quello di inserimento - if ( ! AreSameFrame( frSou, frDest)) { - pCrvCompo->ToGlob( frSou) ; - pCrvCompo->ToLoc( frDest) ; - } + if ( ! AreSameFrame( frSou, frDest)) + pCrvCompo->LocToLoc( frSou, frDest) ; // inserisco la curva composita nel DB if ( AddGeoObj( vsParams[0], vsParams[1], Release( pCrvCompo))) { @@ -1716,7 +1742,56 @@ GdbExecutor::CurveCompoFromSplit( const STRVECTOR& vsParams) //---------------------------------------------------------------------------- bool -GdbExecutor::CurveCompoAddCurve( const STRVECTOR& vsParams) +GdbExecutor::CurveCompoFromPolygon( const STRVECTOR& vsParams, int nType) +{ + // 5 parametri : Id, IdParent, NumLati, ptP1, ptP2 + if ( vsParams.size() != 5) + return false ; + // recupero il numero di lati + int nNumLati ; + if ( ! FromString( vsParams[2], nNumLati)) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frRef ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef)) + return false ; + // recupero punto P1 + Point3d ptP1 ; + if ( ! GetPointParam( vsParams[3], frRef, ptP1)) + return false ; + // recupero punto P2 + Point3d ptP2 ; + if ( ! GetPointParam( vsParams[4], frRef, ptP2)) + return false ; + // creo la curva composita + PtrOwner pCrvCompo( CreateCurveComposite()) ; + if ( ! IsValid( pCrvCompo)) + return false ; + // costruisco il poligono + switch ( nType) { + case POLYG_INSCR : + if ( ! pCrvCompo->PolygonCenterCorner( nNumLati, ptP1, ptP2)) + return false ; + break ; + case POLYG_CIRC : + if ( ! pCrvCompo->PolygonCenterMidSide( nNumLati, ptP1, ptP2)) + return false ; + break ; + case POLYG_SIDE : + if ( ! pCrvCompo->PolygonSide( nNumLati, ptP1, ptP2)) + return false ; + break ; + default : + return false ; + break ; + } + // inserisco la linea nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pCrvCompo)) ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::CurveCompoAddCurve( const STRVECTOR& vsParams, bool bEndOrStart) { // per eventuale cancellazione curva da accodare bool bErase ; @@ -1737,7 +1812,7 @@ GdbExecutor::CurveCompoAddCurve( const STRVECTOR& vsParams) if ( pCrvToAdd == nullptr) return false ; // eseguo l'accodamento - if ( ! pCrvComp->AddCurve( *pCrvToAdd)) + if ( ! pCrvComp->AddCurve( *pCrvToAdd, bEndOrStart)) return false ; // se richiesto, elimino la curva accodata if ( bErase) { @@ -1747,6 +1822,53 @@ GdbExecutor::CurveCompoAddCurve( const STRVECTOR& vsParams) return true ; } +//---------------------------------------------------------------------------- +bool +GdbExecutor::CurveCompoExtractCurve( const STRVECTOR& vsParams, bool bEndOrStart) +{ + // 3 parametri : IdSou, IdDest, IdParent + if ( vsParams.size() != 3) + return false ; + // recupero la curva composita e il suo riferimento + int nIdCCompo = GetIdParam( vsParams[0]) ; + ICurveComposite* pCrvCompo = GetCurveComposite( m_pGDB->GetGeoObj( nIdCCompo)) ; + if ( pCrvCompo == nullptr) + return false ; + Frame3d frSou ; + if ( ! m_pGDB->GetGlobFrame( nIdCCompo, frSou)) + return false ; + // estraggo la opportuna entità + ICurve* pCrv = pCrvCompo->RemoveFirstOrLastCurve( bEndOrStart) ; + // recupero il riferimento del gruppo destinazione + Frame3d frDest ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[2]), frDest)) + return false ; + // porto la curva estratta dal riferimento della sorgente a quello di inserimento + if ( ! AreSameFrame( frSou, frDest)) + pCrv->LocToLoc( frSou, frDest) ; + // inserisco la curva estratta nel DB + return AddGeoObj( vsParams[1], vsParams[2], pCrv) ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::CurveCompoChangeStart( const STRVECTOR& vsParams) +{ + // 2 parametri : Id, ParNewStart + if ( vsParams.size() != 2) + return false ; + // recupero la curva composita + ICurveComposite* pCrvComp = GetCurveComposite( m_pGDB->GetGeoObj( GetIdParam( vsParams[0]))) ; + if ( pCrvComp == nullptr) + return false ; + // recupero il parametro del nuovo inizio + double dParNewStart ; + if ( ! FromString( vsParams[1], dParNewStart)) + return false ; + // eseguo il cambio di inizio + return pCrvComp->ChangeStartPoint( dParNewStart) ; +} + //---------------------------------------------------------------------------- bool GdbExecutor::ExecuteSurfTriMesh( const string& sCmd2, const STRVECTOR& vsParams) @@ -2871,7 +2993,40 @@ GdbExecutor::GetPointParam( const string& sParam, const Frame3d& frPnt, Point3d& return false ; return ptP.LocToLoc( frEnt, frPnt) ; } - //case 'I' : // punto di intersezione con un'altra curva + case 'I' : // punto di intersezione con un'altra curva + { + // secondo parametro : altra curva + int nIdEnt2 = GetIdParam( vsParams[1]) ; + const IGeoObj* pGObj2 = m_pGDB->GetGeoObj( nIdEnt2) ; + if ( pGObj2 == nullptr) + return false ; + // deve essere una curva + const ICurve* pCrv2 = GetCurve( pGObj2) ; + if ( pCrv2 == nullptr) + return false ; + // recupero il riferimento in cui è immersa + Frame3d frEnt2 ; + if ( ! m_pGDB->GetGlobFrame( nIdEnt2, frEnt2)) + return false ; + // se il riferimento è diverso da quello della prima entità, devo trasformarla + PtrOwner crvTrans( nullptr) ; + if ( ! AreSameFrame( frEnt, frEnt2)) { + crvTrans.Set( pCrv2->Clone()) ; + if ( ! ::IsValid( crvTrans)) + return false ; + crvTrans->LocToLoc( frEnt2, frEnt) ; + pCrv2 = ::Get( crvTrans) ; + } + // eventuale terzo parametro : punto di riferimento + Point3d ptRef ; + if ( vsParams.size() >= 3 && ! GetPointParam( vsParams[2], frEnt, ptRef)) + return false ; + // calcolo il punto di intersezione sulla prima curva più vicino al punto di riferimento + IntersCurveCurve intCC( *pCrv, *pCrv2, true) ; + if ( ! intCC.GetIntersPointNearTo( 0, ptRef, ptP)) + return false ; + return ptP.LocToLoc( frEnt, frPnt) ; + } } } // se frame @@ -3785,7 +3940,7 @@ GdbExecutor::ExecuteCopy( const string& sCmd2, const STRVECTOR& vsParams) nIdNew = m_pGDB->CopyGlob( GetIdParam( vsParams[0]), nIdDest, GetIdParam( vsParams[2]), nSonBeforeAfter) ; else nIdNew = m_pGDB->Copy( GetIdParam( vsParams[0]), nIdDest, GetIdParam( vsParams[2]), nSonBeforeAfter) ; - // se IdDest da calcolare, può essere una variabili a cui cambiare il valore + // se IdDest da calcolare, può essere una variabile a cui cambiare il valore if ( nIdDest == GDB_ID_NULL) m_pParser->SetVariable( vsParams[1], nIdNew) ; @@ -4215,11 +4370,11 @@ GdbExecutor::ExecuteInvertSurf( const string& sCmd2, const STRVECTOR& vsParams) bool GdbExecutor::ExecuteTrimCurve( const string& sCmd2, const STRVECTOR& vsParams) { - enum SeLp { SL, EL, SP, EP} ; + enum SeLp { SL, EL, SP, EP, SEP} ; - // 2 parametri ( Nome, parametro) - if ( vsParams.size() != 2) + // almeno 2 parametri : Nome, parametro [, secondo parametro] + if ( vsParams.size() < 2) return false ; // recupero lista nomi INTVECTOR vnNames ; @@ -4239,6 +4394,8 @@ GdbExecutor::ExecuteTrimCurve( const string& sCmd2, const STRVECTOR& vsParams) StEnLenPar = SP ; else if ( sCmd2 == "ENDPAR" || sCmd2 == "EP") StEnLenPar = EP ; + else if ( sCmd2 == "STARTENDPAR" || sCmd2 == "SEP") + StEnLenPar = SEP ; else return false ; // esecuzione trim @@ -4263,6 +4420,14 @@ GdbExecutor::ExecuteTrimCurve( const string& sCmd2, const STRVECTOR& vsParams) if ( ! pCurve->TrimEndAtParam( dPar)) return false ; break ; + case SEP : + // ci deve essere un terzo parametro + double dPar2 ; + if ( vsParams.size() < 3 || ! FromString( vsParams[2], dPar2)) + return false ; + if ( ! pCurve->TrimStartEndAtParam( dPar, dPar2)) + return false ; + break ; } } else diff --git a/GdbExecutor.h b/GdbExecutor.h index 31380ed..e7b0433 100644 --- a/GdbExecutor.h +++ b/GdbExecutor.h @@ -89,7 +89,10 @@ class GdbExecutor : public IGdbExecutor bool CurveCompoFromPoints( const STRVECTOR& vsParams) ; bool CurveCompoFromPointBulges( const STRVECTOR& vsParams) ; bool CurveCompoFromSplit( const STRVECTOR& vsParams) ; - bool CurveCompoAddCurve( const STRVECTOR& vsParams) ; + bool CurveCompoFromPolygon( const STRVECTOR& vsParams, int nType) ; + bool CurveCompoAddCurve( const STRVECTOR& vsParams, bool bEndOrStart) ; + bool CurveCompoExtractCurve( const STRVECTOR& vsParams, bool bEndOrStart) ; + bool CurveCompoChangeStart( const STRVECTOR& vsParams) ; bool ExecuteSurfTriMesh( const std::string& sCmd2, const STRVECTOR& vsParams) ; bool SurfTriMeshBegin( const STRVECTOR& vsParams) ; bool SurfTriMeshAddVertex( const STRVECTOR& vsParams) ; diff --git a/IntersCurveCurve.cpp b/IntersCurveCurve.cpp new file mode 100644 index 0000000..36929f1 --- /dev/null +++ b/IntersCurveCurve.cpp @@ -0,0 +1,199 @@ +//---------------------------------------------------------------------------- +// EgalTech 2014-2014 +//---------------------------------------------------------------------------- +// File : IntersCurveCurve.cpp Data : 20.06.14 Versione : 1.5f6 +// Contenuto : Implementazione della classe intersezione linea/linea. +// +// +// +// Modifiche : 15.06.14 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "IntersLineLine.h" +#include "/EgtDev/Include/EGkIntersCurveCurve.h" +#include "/EgtDev/Include/EGkDistPointCurve.h" +#include "/EgtDev/Include/EGtPointerOwner.h" + +using namespace std ; + +//---------------------------------------------------------------------------- +IntersCurveCurve::IntersCurveCurve( const ICurve& Curve1, const ICurve& Curve2, bool bIsSegment) +{ + // Le intersezioni sono calcolate nel piano XY locale. + // Il flag bIsSegment vale solo per linee. + + // reset + m_bOverlaps = false ; + m_nNumInters = 0 ; + m_pCurve[0] = nullptr ; + m_pCurve[1] = nullptr ; + + // chiamo calcolatore opportuno + switch ( Curve1.GetType()) { + case CRV_LINE : + switch ( Curve2.GetType()) { + case CRV_LINE : + LineLineCalculate( Curve1, Curve2, bIsSegment) ; + break ; + case CRV_ARC : + break ; + case CRV_BEZ : + break ; + case CRV_COMPO : + break ; + } + break ; + case CRV_ARC : + break ; + case CRV_BEZ : + break ; + case CRV_COMPO : + break ; + } + + // salvo i puntatori alle curve + m_pCurve[0] = &Curve1 ; + m_pCurve[1] = &Curve2 ; +} + +//---------------------------------------------------------------------------- +void +IntersCurveCurve::LineLineCalculate( const ICurve& Curve1, const ICurve& Curve2, bool bIsSegment) +{ + IntersLineLine intLnLn( *GetCurveLine( &Curve1), *GetCurveLine( &Curve2), bIsSegment) ; + + if ( intLnLn.m_nNumInters > 0) { + 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]) ; + } +} + +//---------------------------------------------------------------------------- +bool +IntersCurveCurve::GetOverlaps( void) +{ + return m_bOverlaps ; +} + +//---------------------------------------------------------------------------- +int +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) +{ + if ( nInd < 0 || nInd >= m_nNumInters) + return false ; + aInfo = m_Info[nInd] ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +IntersCurveCurve::GetIntersPointNearTo( int nCrv, const Point3d& ptNear, Point3d& ptI) +{ + 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 + 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 + double dSqDist = SqDist( ptNear, ptP) ; + if ( dSqDist < dMinSqDist) { + dMinSqDist = dSqDist ; + ptI = ptP ; + bFound = true ; + } + } + } + + return bFound ; +} diff --git a/IntersLineLine.cpp b/IntersLineLine.cpp new file mode 100644 index 0000000..bb1b459 --- /dev/null +++ b/IntersLineLine.cpp @@ -0,0 +1,220 @@ +//---------------------------------------------------------------------------- +// EgalTech 2014-2014 +//---------------------------------------------------------------------------- +// File : IntersLineLine.cpp Data : 15.06.14 Versione : 1.5f6 +// Contenuto : Implementazione della classe intersezione linea/linea. +// +// +// +// Modifiche : 15.06.14 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "IntersLineLine.h" + +using namespace std ; + +//---------------------------------------------------------------------------- +IntersLineLine::IntersLineLine( const ICurveLine& Line1, const ICurveLine& Line2, bool bFinites) +{ + // Le intersezioni sono calcolate nel piano XY locale. + + // nessuna intersezione trovata + m_bOverlaps = false ; + m_nNumInters = 0 ; + + // verifico validità linee + if ( ! Line1.IsValid() || ! Line2.IsValid()) + return ; + + // linea 1 : pto Start e direzione + Point3d ptS1 = Line1.GetStart() ; + Vector3d vtDir1 = Line1.GetEnd() - ptS1 ; + // linea 2 : pto Start e direzione + Point3d ptS2 = Line2.GetStart() ; + Vector3d vtDir2 = Line2.GetEnd() - ptS2 ; + // 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) { + // 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 ; + // 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 + } + // 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_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()) + 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 + return ; + } + + // le linee sono parallele e coincidenti e sono segmenti, si cercano eventuali sovrapposizioni + // determino se sono equiverse o controverse + 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() ; + 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_bOverlaps = false ; + m_nNumInters = 1 ; // una intersezione + 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_bOverlaps = false ; + m_nNumInters = 1 ; // una intersezione + return ; + } + // esterni -> nessuna intersezione + else if ( dUmax < 0 || 1 < dUmin) { + return ; + } + // altrimenti si sovrappongono -> tratto comune + 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) ; + } + else { + m_Info[0].Ici[0].dU = 0 ; + m_Info[0].Ici[1].dU = ScalarXY( ( ptS1 - ptS2), vtDir2) / vtDir2.SqLenXY() ; + } + 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) ; + } + else { + m_Info[1].Ici[0].dU = 1 ; + m_Info[1].Ici[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_bOverlaps = true ; + m_nNumInters = 2 ; // estremi del tratto di sovrapposizione + return ; + } +} diff --git a/IntersLineLine.h b/IntersLineLine.h new file mode 100644 index 0000000..d7db2b9 --- /dev/null +++ b/IntersLineLine.h @@ -0,0 +1,65 @@ +//---------------------------------------------------------------------------- +// EgalTech 2014-2014 +//---------------------------------------------------------------------------- +// File : IntersLineLine.h Data : 19.06.14 Versione : 1.5f5 +// Contenuto : Dichiarazione della classe intersezione linea/linea. +// +// +// +// Modifiche : 19.06.14 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +#pragma once + +#include "/EgtDev/Include/EGkIntersCurveCurve.h" +#include "/EgtDev/Include/EGkCurveLine.h" + + +//----------------------------------------------------------------------------- +class IntersLineLine +{ + friend class IntersCurveCurve ; + + public : + IntersLineLine( const ICurveLine& Line1, const ICurveLine& Line2, bool bFinites = 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) + 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] ; + return true ; } + + private : + IntersLineLine( void) ; + + private : + static const int MAX_INTERS = 2 ; + + private : + bool m_bOverlaps ; + int m_nNumInters ; + IntCrvCrvInfo m_Info[MAX_INTERS] ; +} ; + diff --git a/PolyLine.cpp b/PolyLine.cpp index 8c78856..7c86d30 100644 --- a/PolyLine.cpp +++ b/PolyLine.cpp @@ -355,7 +355,7 @@ PolyLine::NewellPlane( Plane3d& plPlane) const // At least 3 sides if ( nNumSide < 3) return false ; - // Normal must be normalizable + // Normal must be normalizable (the length of the normal is the double of the area of the polygon) if ( ! vtN.Normalize()) return false ; // Normalize normal and fill in the plane equation fields diff --git a/Triangulate.cpp b/Triangulate.cpp index cc58b51..ba5a167 100644 --- a/Triangulate.cpp +++ b/Triangulate.cpp @@ -1,13 +1,13 @@ //---------------------------------------------------------------------------- // EgalTech 2014-2014 //---------------------------------------------------------------------------- -// File : Triangulate.cpp Data : 08.04.14 Versione : 1.5d2 +// File : Triangulate.cpp Data : 23.06.14 Versione : 1.5f6 // Contenuto : Implementazione della classe Triangulate. // // // // Modifiche : 08.04.14 DS Creazione modulo. -// +// 23.06.14 DS Corretto errore con contorni CW. // //---------------------------------------------------------------------------- @@ -17,6 +17,8 @@ #include "\EgtDev\Include\EGkPolyLine.h" #include "\EgtDev\Include\EGkPlane3d.h" +using namespace std ; + //---------------------------------------------------------------------------- // In : PolyLine // Out : PNTVECTOR (Point3d Vector) : points of the polyline @@ -71,8 +73,18 @@ Triangulate::Make( const PolyLine& PL, PNTVECTOR& vPt, INTVECTOR& vTr) vPol.push_back( i) ; } - // eseguo la triangolazione - return MakeByEC2( vPt, vPol, vTr) ; + // eseguo la triangolazione + if ( ! MakeByEC2( vPt, vPol, 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]) ; + } + + return true ; } //---------------------------------------------------------------------------- @@ -205,10 +217,10 @@ Triangulate::MakeByEC2( const PNTVECTOR& vPt, const INTVECTOR& vPol, INTVECTOR& if ( TestTriangle( vPt, vPol, vPrev, vNext, k)) dSqDist2 = SqDist( vPt[vPol[vPrev[k]]], vPt[vPol[vNext[k]]]) ; } - // Choose the better - if ( dSqDist <= dSqDist1 && dSqDist <= dSqDist2) + // Choose the better (EPS_ZERO to have a difference) + if ( dSqDist < dSqDist1 + EPS_ZERO && dSqDist < dSqDist2 + EPS_ZERO) ; // i is the better - else if ( dSqDist1 <= dSqDist2) + else if ( dSqDist1 < dSqDist2 + EPS_ZERO) i = j ; else i = k ; diff --git a/Vector3d.cpp b/Vector3d.cpp index 6869173..e59ec12 100644 --- a/Vector3d.cpp +++ b/Vector3d.cpp @@ -44,15 +44,6 @@ Vector3d::FromPolar( double dLen, double dAngDeg) z = 0 ; } -//---------------------------------------------------------------------------- -// Quadrato della lunghezza di un vettore -//---------------------------------------------------------------------------- -double -Vector3d::SqLen( void) const -{ - return ( x * x + y * y + z * z) ; -} - //---------------------------------------------------------------------------- // Lunghezza di un vettore //---------------------------------------------------------------------------- @@ -69,6 +60,20 @@ Vector3d::Len( void) const return sqrt( x * x + y * y + z * z) ; } +//---------------------------------------------------------------------------- +// Lunghezza di un vettore nel piano XY +//---------------------------------------------------------------------------- +double +Vector3d::LenXY( void) const +{ + if ( fabs( y) < EPS_ZERO) + return fabs( x) ; + if ( fabs( x) < EPS_ZERO) + return fabs( y) ; + + return sqrt( x * x + y * y) ; +} + //---------------------------------------------------------------------------- // Ritorna la rappresentazione in coordinate sferiche //----------------------------------------------------------------------------