//---------------------------------------------------------------------------- // 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" //---------------------------------------------------------------------------- inline 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()) ; } //---------------------------------------------------------------------------- inline 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()) ; } //---------------------------------------------------------------------------- inline 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()) ; } //---------------------------------------------------------------------------- inline 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.Invert() ; // ne aggiusto il modulo if ( ! vtDer.Normalize()) return false ; vtDer *= Dist( ptP0, ptP1) / ( dU1 - dU0) ; return true ; } //---------------------------------------------------------------------------- inline 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.Invert() ; // ne aggiusto il modulo if ( ! vtDer.Normalize()) return false ; vtDer *= Dist( ptP1, ptP2) / ( dU2 - dU1) ; return true ; } //---------------------------------------------------------------------------- inline 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) ; } //---------------------------------------------------------------------------- inline 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()) ; }