//---------------------------------------------------------------------------- // EgalTech 2026 //---------------------------------------------------------------------------- // File : CalcDerivate.cpp Data : 03.02.26 Versione : 1.5h1 // Contenuto : Funzioni per calcolo derivate secondo Bessel e Akima. // // // // Modifiche : 03.02.26 DB Creazione modulo. // // //---------------------------------------------------------------------------- #pragma once #include "stdafx.h" #include "CalcDerivate.h" #include "/EgtDev/Include/EGkPoint3d.h" #include "/EgtDev/Include/EgtNumCollection.h" #include "/EgtDev/Include/EGkGeoCollection.h" //---------------------------------------------------------------------------- bool ComputeAkimaTangents( bool bDetectCorner, const DBLVECTOR& vPar, const PNTVECTOR& vPnt, VCT3DVECTOR& vPrevDer, VCT3DVECTOR& vNextDer) { // pulisco i vettori dei parametri e delle tangenti vPrevDer.clear() ; vNextDer.clear() ; // numero di punti int nSize = int( vPnt.size()) ; // sono necessari almeno due punti if ( nSize < 2) return false ; // calcolo le derivate vPrevDer.reserve( nSize) ; 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 vPrevDer.emplace_back( 0, 0, 0) ; vNextDer.push_back( ( vPnt[1] - vPnt[0]) / ( vPar[1] - vPar[0])) ; vPrevDer.push_back( vNextDer[0]) ; // non esiste derivata dopo il secondo e ultimo punto vNextDer.emplace_back( 0, 0, 0) ; return true ; } // verifico se curva chiusa (primo e ultimo punto coincidono) bool bClosed = AreSamePointApprox( vPnt.front(), 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 non ci sono almeno 5 punti if ( nSize < 5) { if ( ! CalcCircleMidDer( vPar[nSize-2] - vPar[nSize-1], vPnt[nSize-2], vPar[i], vPnt[i], vPar[i+1], vPnt[i+1], vtNextDer)) return false ; vtPrevDer = vtNextDer ; } // altrimenti else { if ( ! CalcAkimaMidDer( vPar[nSize-3] - vPar[nSize-1], vPnt[nSize-3], vPar[nSize-2] - vPar[nSize-1], vPnt[nSize-2], vPar[i], vPnt[i], vPar[i+1], vPnt[i+1], vPar[i+2], vPnt[i+2], bDetectCorner, vtPrevDer, vtNextDer)) return false ; } } // altrimenti, uso arco sui primi tre punti else { if ( ! CalcCircleStartDer( vPar[i], vPnt[i], vPar[i+1], vPnt[i+1], vPar[i+2], vPnt[i+2], vtNextDer)) return false ; vtPrevDer = Vector3d( 0, 0, 0) ; } } // ultimo punto else if ( i == nSize - 1) { // se curva chiusa, le tg devono coincidere con quelle del primo if ( bClosed) { vtPrevDer = vPrevDer[0] ; vtNextDer = vNextDer[0] ; } // altrimenti, uso arco sugli ultimi tre punti else { if ( ! CalcCircleEndDer( vPar[i-2], vPnt[i-2], vPar[i-1], vPnt[i-1], vPar[i], vPnt[i], vtPrevDer)) return false ; vtNextDer = Vector3d( 0, 0, 0) ; } } // punti intermedi else { // se secondo punto if ( i == 1) { // se curva aperta o non ci sono almeno 5 punti if ( ! bClosed || nSize < 5) { if ( ! CalcCircleMidDer( vPar[i-1], vPnt[i-1], vPar[i], vPnt[i], vPar[i+1], vPnt[i+1], vtPrevDer)) return false ; vtNextDer = vtPrevDer ; } // altrimenti else { if ( ! CalcAkimaMidDer( vPar[nSize-2] - vPar[nSize-1], vPnt[nSize-2], vPar[i-1], vPnt[i-1], vPar[i], vPnt[i], vPar[i+1], vPnt[i+1], vPar[i+2], vPnt[i+2], bDetectCorner, 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 ( ! CalcCircleMidDer( vPar[i-1], vPnt[i-1], vPar[i], vPnt[i], vPar[i+1], vPnt[i+1], vtPrevDer)) return false ; vtNextDer = vtPrevDer ; } // altrimenti else { if ( ! CalcAkimaMidDer( vPar[i-2], vPnt[i-2], vPar[i-1], vPnt[i-1], vPar[i], vPnt[i], vPar[i+1], vPnt[i+1], vPar[1] + vPar[i+1], vPnt[1], bDetectCorner, vtPrevDer, vtNextDer)) return false ; } } // altrimenti else { if ( ! CalcAkimaMidDer( vPar[i-2], vPnt[i-2], vPar[i-1], vPnt[i-1], vPar[i], vPnt[i], vPar[i+1], vPnt[i+1], vPar[i+2], vPnt[i+2], bDetectCorner, vtPrevDer, vtNextDer)) return false ; } } // salvo la derivata vPrevDer.push_back( vtPrevDer) ; vNextDer.push_back( vtNextDer) ; } return true ; } //---------------------------------------------------------------------------- bool ComputeBesselTangents( const DBLVECTOR& vPar, const PNTVECTOR& vPnt, VCT3DVECTOR& vPrevDer, VCT3DVECTOR& vNextDer) { // pulisco i vettori dei parametri e delle tangenti vPrevDer.clear() ; vNextDer.clear() ; // numero di punti int nSize = int( vPnt.size()) ; // sono necessari almeno due punti if ( nSize < 2) return false ; // calcolo le derivate vPrevDer.reserve( nSize) ; 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 vPrevDer.emplace_back( 0, 0, 0) ; vNextDer.push_back( ( vPnt[1] - vPnt[0]) / ( vPar[1] - vPar[0])) ; vPrevDer.push_back( vNextDer[0]) ; // non esiste derivata dopo il secondo e ultimo punto vNextDer.emplace_back( 0, 0, 0) ; return true ; } // verifico se curva chiusa (primo e ultimo punto coincidono) bool bClosed = AreSamePointApprox( vPnt.front(), 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) { if ( ! CalcBesselMidDer( vPar[nSize-2] - vPar[nSize-1], vPnt[nSize-2], vPar[i], vPnt[i], vPar[i+1], vPnt[i+1], vtNextDer)) return false ; vtPrevDer = vtNextDer ; } // altrimenti, uso i primi tre punti else { if ( ! CalcBesselStartDer( vPar[i], vPnt[i], vPar[i+1], vPnt[i+1], vPar[i+2], vPnt[i+2], vtNextDer)) return false ; vtPrevDer = Vector3d( 0, 0, 0) ; } } // ultimo punto else if ( i == nSize - 1) { // se curva chiusa, le tg devono coincidere con quelle del primo if ( bClosed) { vtPrevDer = vPrevDer[0] ; vtNextDer = vNextDer[0] ; } // altrimenti, uso gli ultimi tre punti else { if ( ! CalcBesselEndDer( vPar[i-2], vPnt[i-2], vPar[i-1], vPnt[i-1], vPar[i], vPnt[i], vtPrevDer)) return false ; vtNextDer = Vector3d( 0, 0, 0) ; } } // punti intermedi else { if ( ! CalcBesselMidDer( vPar[i-1], vPnt[i-1], vPar[i], vPnt[i], vPar[i+1], vPnt[i+1], vtPrevDer)) return false ; vtNextDer = vtPrevDer ; } // salvo la derivata vPrevDer.push_back( vtPrevDer) ; vNextDer.push_back( vtNextDer) ; } return true ; }