diff --git a/BiArcs.cpp b/BiArcs.cpp index 323e2c4..77e97dc 100644 --- a/BiArcs.cpp +++ b/BiArcs.cpp @@ -33,7 +33,7 @@ GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir // calcolo la curva dove giacciono i punti di giunzione tra i due archi del biarco PtrOwner pJCrv( CalcJCurve( ptP0, dDir0Deg, ptP1, dDir1Deg)) ; if ( ! ::IsValid( pJCrv)) - return false ; + return nullptr ; // limito il parametro nell'intervallo 0 - 1 if ( dU < 0) @@ -44,18 +44,18 @@ GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir // recupero il punto di giunzione Point3d ptJ ; if ( ! pJCrv->GetPointD1D2( dU, ICurve::FROM_MINUS, ptJ)) - return false ; + return nullptr ; // preparo la curva composita per i biarchi PtrOwner pBiArc( CreateCurveComposite()) ; if ( ! IsValid( pBiArc)) - return false ; + return nullptr ; // calcolo la curva dal punto iniziale alla giunzione if ( ! AreSamePointApprox( ptP0, ptJ)) { ICurve* pCrv = GetArc2PD( ptP0, ptJ, dDir0Deg) ; if ( pCrv == nullptr) - return false ; + return nullptr ; pBiArc->AddCurve( pCrv) ; } @@ -64,7 +64,7 @@ GetBiArc( const Point3d& ptP0, double dDir0Deg, const Point3d& ptP1, double dDir // curva dal punto finale, direzione opposta alla giunzione ICurve* pCrv = GetArc2PD( ptP1, ptJ, dDir1Deg + ANG_STRAIGHT) ; if ( pCrv == nullptr) - return false ; + return nullptr ; // inverto la curva pCrv->Invert() ; pBiArc->AddCurve( pCrv) ; diff --git a/CalcDerivate.h b/CalcDerivate.h new file mode 100644 index 0000000..973d259 --- /dev/null +++ b/CalcDerivate.h @@ -0,0 +1,181 @@ +//---------------------------------------------------------------------------- +// EgalTech 2014-2014 +//---------------------------------------------------------------------------- +// File : CalcDerivate.h Data : 05.08.14 Versione : 1.5h1 +// Contenuto : Funzioni per calcolo derivate secondo Bessel e Akima. +// +// +// +// Modifiche : 05.08.14 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +#pragma once + +#include "/EgtDev/Include/EGkPoint3d.h" + + +//---------------------------------------------------------------------------- +bool +CalcBesselStartDer( double dU0, const Point3d& ptP0, double dU1, const Point3d& ptP1, + double dU2, const Point3d& ptP2, Vector3d& vtDer) +{ + // verifico che i parametri siano in ordine ascendente + if ( dU0 > dU1 - EPS_PARAM || dU1 > dU2 - EPS_PARAM) + return false ; + // calcolo la derivata + double dD0 = dU1 - dU0 ; + double dD1 = dU2 - dU1 ; + double dD01 = dU2 - dU0 ; + vtDer = ( 2 * dD0 + dD1) / ( dD0 * dD01) * ( ptP1 - ptP0) - dD0 / ( dD01 * dD1) * ( ptP2 - ptP1) ; + return ( ! vtDer.IsZero()) ; +} + +//---------------------------------------------------------------------------- +bool +CalcBesselMidDer( double dU0, const Point3d& ptP0, double dU1, const Point3d& ptP1, + double dU2, const Point3d& ptP2, Vector3d& vtDer) +{ + // verifico che i parametri siano in ordine ascendente + if ( dU0 > dU1 - EPS_PARAM || dU1 > dU2 - EPS_PARAM) + return false ; + // calcolo la derivata + double dD0 = dU1 - dU0 ; + double dD1 = dU2 - dU1 ; + double dD01 = dU2 - dU0 ; + vtDer = dD1 / ( dD0 * dD01) * ( ptP1 - ptP0) + dD0 / ( dD01 * dD1) * ( ptP2 - ptP1) ; + return ( ! vtDer.IsZero()) ; +} + +//---------------------------------------------------------------------------- +bool +CalcBesselEndDer( double dU0, const Point3d& ptP0, double dU1, const Point3d& ptP1, + double dU2, const Point3d& ptP2, Vector3d& vtDer) +{ + // verifico che i parametri siano in ordine ascendente + if ( dU0 > dU1 - EPS_PARAM || dU1 > dU2 - EPS_PARAM) + return false ; + // calcolo la derivata + double dD0 = dU1 - dU0 ; + double dD1 = dU2 - dU1 ; + double dD01 = dU2 - dU0 ; + vtDer = - dD1 / ( dD0 * dD01) * ( ptP1 - ptP0) + ( dD0 + 2 * dD1) / ( dD01 * dD1) * ( ptP2 - ptP1) ; + return ( ! vtDer.IsZero()) ; +} + +//---------------------------------------------------------------------------- +bool +CalcCircleStartDer( double dU0, const Point3d& ptP0, double dU1, const Point3d& ptP1, + double dU2, const Point3d& ptP2, Vector3d& vtDer) +{ + // verifico che i parametri siano in ordine ascendente + if ( dU0 > dU1 - EPS_PARAM || dU1 > dU2 - EPS_PARAM) + return false ; + // vettori dal primo punto agli altri due + Vector3d vtA = ptP1 - ptP0 ; + Vector3d vtB = ptP2 - ptP0 ; + // calcolo del versore normale + Vector3d vtN = vtA ^ vtB ; + double dNSqLen = vtN.SqLen() ; + // se i punti sono allineati calcolo con Bessel + if ( ! vtN.Normalize( EPS_ZERO)) + return CalcBesselStartDer( dU0, ptP0, dU1, ptP1, dU2, ptP2, vtDer) ; + // calcolo del centro + Point3d ptCen = ptP0 + ( vtB.SqLen() * ( vtA.SqLen() - vtA * vtB) * vtA + + vtA.SqLen() * ( vtB.SqLen() - vtA * vtB) * vtB) / ( 2 * dNSqLen) ; + // calcolo la derivata + vtDer = ptP0 - ptCen ; + vtDer.Rotate( vtN, 0, 1) ; + if ( ( vtDer * vtA) < 0) + vtDer *= - 1 ; + // ne aggiusto il modulo + if ( ! vtDer.Normalize()) + return false ; + vtDer *= Dist( ptP0, ptP1) / ( dU1 - dU0) ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +CalcCircleEndDer( double dU0, const Point3d& ptP0, double dU1, const Point3d& ptP1, + double dU2, const Point3d& ptP2, Vector3d& vtDer) +{ + // verifico che i parametri siano in ordine ascendente + if ( dU0 > dU1 - EPS_PARAM || dU1 > dU2 - EPS_PARAM) + return false ; + // vettori dal primo punto agli altri due + Vector3d vtA = ptP1 - ptP0 ; + Vector3d vtB = ptP2 - ptP0 ; + // calcolo del versore normale + Vector3d vtN = vtA ^ vtB ; + double dNSqLen = vtN.SqLen() ; + // se i punti sono allineati calcolo con Bessel + if ( ! vtN.Normalize( EPS_ZERO)) + return CalcBesselEndDer( dU0, ptP0, dU1, ptP1, dU2, ptP2, vtDer) ; + // calcolo del centro + Point3d ptCen = ptP0 + ( vtB.SqLen() * ( vtA.SqLen() - vtA * vtB) * vtA + + vtA.SqLen() * ( vtB.SqLen() - vtA * vtB) * vtB) / ( 2 * dNSqLen) ; + // calcolo la derivata + vtDer = ptP2 - ptCen ; + vtDer.Rotate( vtN, 0, 1) ; + if ( ( vtDer * ( ptP2 - ptP1)) < 0) + vtDer *= - 1 ; + // ne aggiusto il modulo + if ( ! vtDer.Normalize()) + return false ; + vtDer *= Dist( ptP0, ptP1) / ( dU1 - dU0) ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +CalcCircleMidDer( double dU0, const Point3d& ptP0, double dU1, const Point3d& ptP1, + double dU2, const Point3d& ptP2, Vector3d& vtDer) +{ + // la derivata Bessel coincide con la derivata circolare sul punto in mezzo + return CalcBesselMidDer( dU0, ptP0, dU1, ptP1, dU2, ptP2, vtDer) ; +} + +//---------------------------------------------------------------------------- +bool +CalcAkimaMidDer( double dU0, const Point3d& ptP0, double dU1, const Point3d& ptP1, + double dU2, const Point3d& ptP2, double dU3, const Point3d& ptP3, + double dU4, const Point3d& ptP4, bool bDetectCorner, + Vector3d& vtPrevDer, Vector3d& vtNextDer) +{ + // verifico che i parametri siano in ordine crescente + if ( dU0 > dU1 - EPS_PARAM || dU1 > dU2 - EPS_PARAM || + dU2 > dU3 - EPS_PARAM || dU3 > dU4 - EPS_PARAM) + return false ; + // calcolo la derivata + Vector3d vtV0 = ( ptP1 - ptP0) / ( dU1 - dU0) ; + Vector3d vtV1 = ( ptP2 - ptP1) / ( dU2 - dU1) ; + Vector3d vtV2 = ( ptP3 - ptP2) / ( dU3 - dU2) ; + Vector3d vtV3 = ( ptP4 - ptP3) / ( dU4 - dU3) ; + Vector3d vtPV1 = vtV0 ^ vtV1 ; + Vector3d vtPV3 = vtV2 ^ vtV3 ; + double dPV1 = vtPV1.Len() ; + double dPV3 = vtPV3.Len() ; + if ( ( dPV1 + dPV3) > EPS_SMALL && ( vtV1 * vtV2) > 0.5) { + if ( ! bDetectCorner || ( ( vtV0 * vtV1) > 0 && ( vtV2 * vtV3) > 0)) { + double dA = dPV1 / ( dPV1 + dPV3) ; + vtPrevDer = ( 1 - dA) * vtV1 + dA * vtV2 ; + } + else { + CalcCircleMidDer( dU1, ptP1, dU2, ptP2, dU3, ptP3, vtPrevDer) ; + } + vtNextDer = vtPrevDer ; + } + else { + if ( bDetectCorner) { + CalcCircleEndDer( dU0, ptP0, dU1, ptP1, dU2, ptP2, vtPrevDer) ; + CalcCircleStartDer( dU2, ptP2, dU3, ptP3, dU4, ptP4, vtNextDer) ; + } + else { + vtPrevDer = 0.5 * ( vtV1 + vtV2) ; + vtNextDer = vtPrevDer ; + } + } + return ( ! vtPrevDer.IsZero() && ! vtNextDer.IsZero()) ; +} diff --git a/CurveByInterp.cpp b/CurveByInterp.cpp new file mode 100644 index 0000000..f8eed51 --- /dev/null +++ b/CurveByInterp.cpp @@ -0,0 +1,268 @@ +//---------------------------------------------------------------------------- +// EgalTech 2013-2014 +//---------------------------------------------------------------------------- +// File : CurveByInterp.cpp Data : 05.08.14 Versione : 1.5h1 +// Contenuto : Implementazione della classe CurveByInterp, per creare +// una curva mediante interpolazione di punti. +// +// +// Modifiche : 05.08.14 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "CalcDerivate.h" +#include "/EgtDev/Include/EGkCurveByInterp.h" +#include "/EgtDev/Include/EgkCurveComposite.h" +#include "/EgtDev/Include/EgkBiArcs.h" +#include "/EgtDev/Include/EgkCurveBezier.h" +#include "/EgtDev/Include/EgtPointerOwner.h" + + +//---------------------------------------------------------------------------- +bool +CurveByInterp::Start( void) +{ + // pulisco il vettore dei punti + m_vPnt.clear() ; + return true ; +} + +//---------------------------------------------------------------------------- +bool +CurveByInterp::AddPoint( const Point3d& ptP) +{ + // se il punto coincide con il precedente, lo salto + if ( ! m_vPnt.empty() && AreSamePointApprox( ptP, m_vPnt.back())) + return false ; + // aggiungo il punto + try { m_vPnt.push_back( ptP) ; } + catch ( ...) { return false ; } + return true ; +} + +//---------------------------------------------------------------------------- +bool +CurveByInterp::End( void) +{ + return true ; +} + +//---------------------------------------------------------------------------- +ICurve* +CurveByInterp::GetCurve( int nMethod, int nType) +{ + // calcolo le tangenti + if ( ! CalcTangents( nMethod)) + return nullptr ; + + // se richiesti biarchi + if ( nType == BIARCS) { + // creo la curva composita + PtrOwner pCrvCompo( CreateCurveComposite()) ; + if ( ! IsValid( pCrvCompo)) + return nullptr ; + // ciclo sugli intervalli + for ( int i = 1 ; i < int( m_vPnt.size()) ; ++ i) { + // creo un biarco per ogni intervallo + double dDirStartDeg ; + m_vNextDer[i-1].ToSpherical( nullptr, nullptr, &dDirStartDeg) ; + double dDirEndDeg ; + m_vPrevDer[i].ToSpherical( nullptr, nullptr, &dDirEndDeg) ; + ICurve* pCrv = GetBiArc( m_vPnt[i-1], dDirStartDeg, m_vPnt[i], dDirEndDeg, 0.5) ; + if ( ! pCrvCompo->AddCurve( pCrv)) + return nullptr ; + } + return ::Release( pCrvCompo) ; + } + + // se richieste curve di Bezier cubiche + if ( nType == CUBIC_BEZIERS) { + // creo la curva composita + PtrOwner pCrvCompo( CreateCurveComposite()) ; + if ( ! IsValid( pCrvCompo)) + return nullptr ; + // ciclo sugli intervalli + for ( int i = 1 ; i < int( m_vPnt.size()) ; ++ i) { + // creo una curva di Bezier cubica per ogni intervallo + PtrOwner pCBez( CreateCurveBezier()) ; + if ( ! IsValid( pCBez)) + return false ; + pCBez->Init( 3, false) ; + pCBez->SetControlPoint( 0, m_vPnt[i-1]) ; + pCBez->SetControlPoint( 1, m_vPnt[i-1] + ( m_vPar[i] - m_vPar[i-1]) / 3 * m_vNextDer[i-1]) ; + pCBez->SetControlPoint( 2, m_vPnt[i] - ( m_vPar[i] - m_vPar[i-1]) / 3 * m_vPrevDer[i]) ; + pCBez->SetControlPoint( 3, m_vPnt[i]) ; + if ( ! pCrvCompo->AddCurve( ::Release( pCBez))) + return nullptr ; + } + return ::Release( pCrvCompo) ; + } + + return false ; +} + +//---------------------------------------------------------------------------- +bool +CurveByInterp::CalcTangents( int nMethod) +{ + // pulisco i vettori dei parametri e delle tangenti + m_vPar.clear() ; + m_vPrevDer.clear() ; + m_vNextDer.clear() ; + + // numero di punti + int nSize = int( m_vPnt.size()) ; + + // sono necessari almeno due punti + if ( nSize < 2) + return false ; + + // calcolo le distanze tra i punti per derivarne i parametri + m_vPar.reserve( nSize) ; + double dPar = 0 ; + m_vPar.push_back( dPar) ; + for ( int i = 1 ; i < nSize ; ++ i) { + double dDist = Dist( m_vPnt[i-1], m_vPnt[i]) ; + dPar += dDist ; + m_vPar.push_back( dPar) ; + } + + // calcolo le derivate + m_vPrevDer.reserve( nSize) ; + m_vNextDer.reserve( nSize) ; + // se ci sono solo 2 punti, le tangenti devono essere dirette lungo la linea che li unisce + if ( nSize == 2) { + // non esiste derivata prima del primo punto + m_vPrevDer.push_back( Vector3d( 0, 0, 0)) ; + m_vNextDer.push_back( ( m_vPnt[1] - m_vPnt[0]) / ( m_vPar[1] - m_vPar[0])) ; + m_vPrevDer.push_back( m_vNextDer[0]) ; + // non esiste derivata dopo il secondo e ultimo punto + m_vNextDer.push_back( Vector3d( 0, 0, 0)) ; + return true ; + } + // verifico se curva chiusa (primo e ultimo punto coincidono) + bool bClosed = AreSamePointApprox( m_vPnt.front(), m_vPnt.back()) ; + // calcolo le derivate + for ( int i = 0 ; i < nSize ; ++ i) { + Vector3d vtPrevDer ; + Vector3d vtNextDer ; + // primo punto + if ( i == 0) { + // se curva chiusa, come precedente uso il penultimo punto + if ( bClosed) { + // se richiesto Bessel o non ci sono almeno 5 punti + if ( nMethod == BESSEL || nSize < 5) { + if ( ! CalcBesselMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i], m_vPnt[i], + m_vPar[i+1], m_vPnt[i+1], vtNextDer)) + return false ; + vtPrevDer = vtNextDer ; + } + // altrimenti + else { + if ( ! CalcAkimaMidDer( m_vPar[nSize-3] - m_vPar[nSize-1], m_vPnt[nSize-3], m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], + m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], + m_vPar[i+2], m_vPnt[i+2], ( nMethod == AKIMA_CORNER), + vtPrevDer, vtNextDer)) + return false ; + } + } + // altrimenti, uso i primi tre punti + else { + if ( ! CalcBesselStartDer( m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], + m_vPar[i+2], m_vPnt[i+2], vtNextDer)) + return false ; + vtPrevDer = Vector3d( 0, 0, 0) ; + } + } + // ultimo punto + else if ( i == nSize - 1) { + // se curva chiusa, come successivo uso il secondo punto + if ( bClosed) { + // se richiesto Bessel o non ci sono almeno 5 punti + if ( nMethod == BESSEL || nSize < 5) { + if ( ! CalcBesselMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i], + m_vPar[1] + m_vPar[i], m_vPnt[1], vtPrevDer)) + return false ; + vtNextDer = vtPrevDer ; + } + // altrimenti + else { + if ( ! CalcAkimaMidDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1], + m_vPar[i], m_vPnt[i], m_vPar[1] + m_vPar[i], m_vPnt[1], + m_vPar[2] + m_vPar[i], m_vPnt[2], ( nMethod == AKIMA_CORNER), + vtPrevDer, vtNextDer)) + return false ; + } + } + // altrimenti, uso gli ultimi tre punti + else { + if ( ! CalcBesselEndDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1], + m_vPar[i], m_vPnt[i], vtPrevDer)) + return false ; + vtNextDer = Vector3d( 0, 0, 0) ; + } + } + // punti intermedi + else { + // se richiesto Bessel + if ( nMethod == BESSEL) { + if ( ! CalcBesselMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i], + m_vPar[i+1], m_vPnt[i+1], vtPrevDer)) + return false ; + vtNextDer = vtPrevDer ; + } + // se secondo punto + else if ( i == 1) { + // se curva aperta o non ci sono almeno 5 punti + if ( ! bClosed || nSize < 5) { + if ( ! CalcBesselMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i], + m_vPar[i+1], m_vPnt[i+1], vtPrevDer)) + return false ; + vtNextDer = vtPrevDer ; + } + // altrimenti + else { + if ( ! CalcAkimaMidDer( m_vPar[nSize-2] - m_vPar[nSize-1], m_vPnt[nSize-2], m_vPar[i-1], m_vPnt[i-1], + m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], + m_vPar[i+2], m_vPnt[i+2], ( nMethod == AKIMA_CORNER), + vtPrevDer, vtNextDer)) + return false ; + } + } + // se penultimo punto + else if ( i == nSize - 2) { + // se curva aperta o non ci sono almeno 5 punti + if ( ! bClosed || nSize < 5) { + if ( ! CalcBesselMidDer( m_vPar[i-1], m_vPnt[i-1], m_vPar[i], m_vPnt[i], + m_vPar[i+1], m_vPnt[i+1], vtPrevDer)) + return false ; + vtNextDer = vtPrevDer ; + } + // altrimenti + else { + if ( ! CalcAkimaMidDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1], + m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], + m_vPar[1] + m_vPar[i+1], m_vPnt[1], ( nMethod == AKIMA_CORNER), + vtPrevDer, vtNextDer)) + return false ; + } + } + // altrimenti + else { + if ( ! CalcAkimaMidDer( m_vPar[i-2], m_vPnt[i-2], m_vPar[i-1], m_vPnt[i-1], + m_vPar[i], m_vPnt[i], m_vPar[i+1], m_vPnt[i+1], + m_vPar[i+2], m_vPnt[i+2], ( nMethod == AKIMA_CORNER), + vtPrevDer, vtNextDer)) + return false ; + } + } + // salvo la derivata + m_vPrevDer.push_back( vtPrevDer) ; + m_vNextDer.push_back( vtNextDer) ; + } + + return true ; +} diff --git a/CurveComposite.cpp b/CurveComposite.cpp index 72dcf31..3e587a3 100644 --- a/CurveComposite.cpp +++ b/CurveComposite.cpp @@ -111,6 +111,9 @@ CurveComposite::AddCurve( const ICurve& cCrv, bool bEndOrStart, double dLinTol) bool CurveComposite::AddCurve( ICurve* pCrv, bool bEndOrStart, double dLinTol) { + // verifica curva + if ( pCrv == nullptr) + return false ; // se curva semplice if ( pCrv->IsSimple()) { // inserisco la curva diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 1595fc1..2d4656f 100644 Binary files a/EgtGeomKernel.rc and b/EgtGeomKernel.rc differ diff --git a/EgtGeomKernel.vcxproj b/EgtGeomKernel.vcxproj index ee7c6cd..f9d7312 100644 --- a/EgtGeomKernel.vcxproj +++ b/EgtGeomKernel.vcxproj @@ -234,6 +234,7 @@ copy $(TargetPath) \EgtProg\Dll64 + @@ -303,6 +304,7 @@ copy $(TargetPath) \EgtProg\Dll64 + @@ -342,6 +344,7 @@ copy $(TargetPath) \EgtProg\Dll64 + diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters index 89d46b0..53b917f 100644 --- a/EgtGeomKernel.vcxproj.filters +++ b/EgtGeomKernel.vcxproj.filters @@ -213,6 +213,9 @@ File di origine\GeoCreate + + File di origine\GeoCreate + @@ -515,6 +518,12 @@ File di intestazione + + File di intestazione + + + File di intestazione + diff --git a/GdbExecutor.cpp b/GdbExecutor.cpp index 3e6706d..cfcf456 100644 --- a/GdbExecutor.cpp +++ b/GdbExecutor.cpp @@ -34,6 +34,7 @@ #include "/EgtDev/Include/EgkIntersCurveCurve.h" #include "/EgtDev/Include/EgkChainCurves.h" #include "/EgtDev/Include/EgkBiArcs.h" +#include "/EgtDev/Include/EGkCurveByInterp.h" #include "/EgtDev/Include/EgkSurfTriMesh.h" #include "/EgtDev/Include/EgkExtText.h" #include "/EgtDev/Include/EGkStmFromTriangleSoup.h" @@ -1567,6 +1568,9 @@ GdbExecutor::ExecuteCurveCompo( const string& sCmd2, const STRVECTOR& vsParams) // creazione per congiunzione di punti con bulge (segmenti di retta e arco) else if ( sCmd2 == "PB" || sCmd2 == "FROMPOINTBULGES") return CurveCompoFromPointBulges( vsParams) ; + // creazione per interpolazione di punti + else if ( sCmd2 == "PINTERP" || sCmd2 == "FROMPOINTINTERPOLATION") + return CurveCompoFromPointInterpolation( vsParams) ; // creazione da split di curva semplice else if ( sCmd2 == "S" || sCmd2 == "FROMSPLIT") return CurveCompoFromSplit( vsParams) ; @@ -1725,6 +1729,52 @@ GdbExecutor::CurveCompoFromPointBulges( const STRVECTOR& vsParams) return AddGeoObj( vsParams[0], vsParams[1], Release( pCrvCompo)) ; } +//---------------------------------------------------------------------------- +bool +GdbExecutor::CurveCompoFromPointInterpolation( const STRVECTOR& vsParams) +{ + // 5 parametri : Id, ParentId, Points, Method, Type + if ( vsParams.size() != 5) + return false ; + // recupero il riferimento del gruppo destinazione + Frame3d frDest ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frDest)) + return false ; + // recupero i punti + PNTVECTOR vPoints ; + if ( ! GetPointsParam( vsParams[2], frDest, vPoints)) + return false ; + // recupero il metodo di interpolazione + string sMethod = vsParams[3] ; + ToUpper( sMethod) ; + int nMethod = 0 ; + if ( sMethod == "BESSEL") + nMethod = CurveByInterp::BESSEL ; + else if ( sMethod == "AKIMA") + nMethod = CurveByInterp::AKIMA ; + else if ( sMethod == "AKIMA_CORNER") + nMethod = CurveByInterp::AKIMA_CORNER ; + // recupero il tipo di risultato di interpolazione + string sType = vsParams[4] ; + ToUpper( sType) ; + int nType = 0 ; + if ( sType == "BIARCS") + nType = CurveByInterp::BIARCS ; + else if ( sType == "CUBIC_BEZIERS") + nType = CurveByInterp::CUBIC_BEZIERS ; + // oggetto interpolatore + CurveByInterp crvByInterp ; + crvByInterp.Start() ; + for ( int i = 0 ; i < int( vPoints.size()) ; ++ i) + crvByInterp.AddPoint( vPoints[i]) ; + crvByInterp.End() ; + PtrOwner pCrv( crvByInterp.GetCurve( nMethod, nType)) ; + if ( ! ::IsValid( pCrv)) + return false ; + // inserisco la curva composita nel DB + return AddGeoObj( vsParams[0], vsParams[1], ::Release( pCrv)) ; +} + //---------------------------------------------------------------------------- bool GdbExecutor::CurveCompoFromSplit( const STRVECTOR& vsParams) @@ -3221,10 +3271,22 @@ GdbExecutor::GetPointsParam( const string& sParam, const Frame3d& frPnt, PNTVECT STRVECTOR::iterator Iter ; for ( Iter = vsPoints.begin() ; Iter != vsPoints.end() ; ++Iter) { Trim( (*Iter), " \t\r\n") ; - Point3d ptP ; - if ( ! GetPointParam( *Iter, frPnt, ptP)) - return false ; - vPoints.push_back( ptP) ; + if ( GetIdParam( *Iter) == ID_SEL) { + int nId = m_pGDB->GetFirstSelectedObj() ; + while ( nId != GDB_ID_NULL) { + Point3d ptP ; + if ( ! GetPointParam( ToString( nId), frPnt, ptP)) + return false ; + vPoints.push_back( ptP) ; + nId = m_pGDB->GetNextSelectedObj() ; + } + } + else { + Point3d ptP ; + if ( ! GetPointParam( *Iter, frPnt, ptP)) + return false ; + vPoints.push_back( ptP) ; + } } return true ; @@ -3767,17 +3829,43 @@ GdbExecutor::ExecuteSelect( const string& sCmd2, const STRVECTOR& vsParams) } // selezione di tutti gli oggetti di un gruppo else if ( sCmd2 == "GOBJS") { - // deve essere 1 parametro ( Id) - if ( vsParams.size() != 1) + // 1 o 2 parametri : Id/s [, Filter] + if ( vsParams.size() != 1 && vsParams.size() != 2) return false ; // recupero lista Id INTVECTOR vnNames ; if ( ! GetNamesParam( vsParams[0], vnNames)) return false ; + // recupero eventuale filtro + int nFilter = 0 ; + if ( vsParams.size() >= 2) { + string sFilter = vsParams[1] ; + ToUpper( sFilter) ; + if ( sFilter == "GR" || sFilter == "GROUP") + nFilter = GDB_TY_GROUP ; + if ( sFilter == "V" || sFilter == "VECTOR") + nFilter = GEO_VECT3D ; + else if ( sFilter == "P" || sFilter == "POINT") + nFilter = GEO_PNT3D ; + else if ( sFilter == "FR" || sFilter == "FRAME") + nFilter = GEO_FRAME3D ; + else if ( sFilter == "CL" || sFilter == "CURVELINE") + nFilter = CRV_LINE ; + else if ( sFilter == "CA" || sFilter == "CURVEARC") + nFilter = CRV_ARC ; + else if ( sFilter == "CB" || sFilter == "CURVEBEZIER") + nFilter = CRV_BEZ ; + else if ( sFilter == "CC" || sFilter == "CURVECOMPO") + nFilter = CRV_COMPO ; + else if ( sFilter == "STM" || sFilter == "SURFTRIMESH") + nFilter = SRF_TRIMESH ; + else if ( sFilter == "TEXT") + nFilter = EXT_TEXT ; + } // esecuzione selezione di tutti gli oggetti di ogni gruppo INTVECTOR::iterator Iter ; for ( Iter = vnNames.begin() ; Iter != vnNames.end() ; ++Iter) { - if ( ! m_pGDB->SelectGroupObjs( *Iter)) + if ( ! m_pGDB->SelectGroupObjs( *Iter, nFilter)) return false ; } return true ; diff --git a/GdbExecutor.h b/GdbExecutor.h index 7b218a6..23a3acc 100644 --- a/GdbExecutor.h +++ b/GdbExecutor.h @@ -90,6 +90,7 @@ class GdbExecutor : public IGdbExecutor bool CurveCompoMake( const STRVECTOR& vsParams) ; bool CurveCompoFromPoints( const STRVECTOR& vsParams) ; bool CurveCompoFromPointBulges( const STRVECTOR& vsParams) ; + bool CurveCompoFromPointInterpolation( const STRVECTOR& vsParams) ; bool CurveCompoFromSplit( const STRVECTOR& vsParams) ; bool CurveCompoFromPolygon( const STRVECTOR& vsParams, int nType) ; bool CurveCompoFromBiarc( const STRVECTOR& vsParams) ; diff --git a/GeomDB.cpp b/GeomDB.cpp index badc6cf..5ca3cf8 100644 --- a/GeomDB.cpp +++ b/GeomDB.cpp @@ -1121,7 +1121,7 @@ GeomDB::DeselectObj( int nId) //---------------------------------------------------------------------------- bool -GeomDB::SelectGroupObjs( int nId) +GeomDB::SelectGroupObjs( int nId, int nFilter) { // recupero il gruppo Gdb GdbGroup* pGdbGroup ; @@ -1129,11 +1129,22 @@ GeomDB::SelectGroupObjs( int nId) return false ; // ciclo sugli oggetti del gruppo e li seleziono - GdbObj* pGdbObj = pGdbGroup->GetFirstObj() ; - while ( pGdbObj != nullptr) { + for ( GdbObj* pGdbObj = pGdbGroup->GetFirstObj() ; + pGdbObj != nullptr ; + pGdbObj = pGdbObj->GetNext()) { + // eventuale filtro + if ( nFilter != 0) { + // se richiesti solo gruppi + if ( nFilter == GDB_TY_GROUP && ::GetGdbGroup( pGdbObj) == nullptr) + continue ; + // altrimenti richiesti solo oggetti geometrici di un particolare tipo + GdbGeo* pGObj = ::GetGdbGeo( pGdbObj) ; + if ( pGObj == nullptr || pGObj->GetType() != nFilter) + continue ; + } + // eseguo selezione if ( ! SetStatus( pGdbObj, GDB_ST_SEL)) return false ; - pGdbObj = pGdbObj->GetNext() ; } return true ; } diff --git a/GeomDB.h b/GeomDB.h index 53c375a..4a342c4 100644 --- a/GeomDB.h +++ b/GeomDB.h @@ -90,7 +90,7 @@ class GeomDB : public IGeomDB // selection virtual bool SelectObj( int nId) ; virtual bool DeselectObj( int nId) ; - virtual bool SelectGroupObjs( int nId) ; + virtual bool SelectGroupObjs( int nId, int nFilter = 0) ; virtual bool DeselectGroupObjs( int nId) ; virtual bool IsSelectedObj( int nId) const ; virtual int GetSelectedObjNbr( void) const ; diff --git a/StmFromTriangleSoup.cpp b/StmFromTriangleSoup.cpp index 3b55dad..396344e 100644 --- a/StmFromTriangleSoup.cpp +++ b/StmFromTriangleSoup.cpp @@ -45,7 +45,7 @@ StmFromTriangleSoup::Start( int nBuckets) //---------------------------------------------------------------------------- bool -StmFromTriangleSoup::AddTriangle( Triangle3d& Tria) +StmFromTriangleSoup::AddTriangle( const Triangle3d& Tria) { // verifico inizializzazione if ( m_pSTM == nullptr)