//---------------------------------------------------------------------------- // EgalTech 2013-2014 //---------------------------------------------------------------------------- // File : LinePerpTwoCurves.cpp Data : 25.11.14 Versione : 1.5k5 // Contenuto : Implementazione funzioni per calcolo rette perpendicolari a curve. // // // // Modifiche : 25.11.14 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "CurveLine.h" #include "CurveArc.h" #include "CreateCurveAux.h" #include "/EgtDev/Include/EGkLinePerpTwoCurves.h" #include "/EgtDev/Include/EGkLinePntPerpCurve.h" #include "/EgtDev/Include/EGkDistPointCurve.h" #include "/EgtDev/Include/EgtPointerOwner.h" using namespace std ; //---------------------------------------------------------------------------- static CurveLine* GetLinePerpTwoLines( const CurveLine& crvLine1, const Point3d& ptNear1, const CurveLine& crvLine2, const Point3d& ptNear2) ; static CurveLine* GetLinePerpLineArc( const CurveLine& crvLine1, const Point3d& ptNear1, const CurveArc& crvArc2, const Point3d& ptNear2) ; static CurveLine* GetLinePerpTwoArcs( const CurveArc& crvArc1, const Point3d& ptNear1, const CurveArc& crvArc2, const Point3d& ptNear2) ; static CurveLine* GetLinePerpTwoConcentricArcs( const CurveArc& crvArc1, const Point3d& ptNear1, const CurveArc& crvArc2, const Point3d& ptNear2) ; //---------------------------------------------------------------------------- ICurveLine* GetLinePerpTwoCurves( const ICurve& cCrv1, const Point3d& ptNear1, const ICurve& cCrv2, const Point3d& ptNear2) { switch ( cCrv1.GetType()) { case CRV_LINE : { const CurveLine& crvLine1 = *GetBasicCurveLine( &cCrv1) ; switch ( cCrv2.GetType()) { case CRV_LINE : { const CurveLine& crvLine2 = *GetBasicCurveLine( &cCrv2) ; return GetLinePerpTwoLines( crvLine1, ptNear1, crvLine2, ptNear2) ; } case CRV_ARC : { const CurveArc& crvArc2 = *GetBasicCurveArc( &cCrv2) ; return GetLinePerpLineArc( crvLine1, ptNear1, crvArc2, ptNear2) ; } case CRV_BEZIER : return nullptr ; case CRV_COMPO : return nullptr ; default : return nullptr ; } } break ; case CRV_ARC : { const CurveArc& crvArc1 = *GetBasicCurveArc( &cCrv1) ; switch ( cCrv2.GetType()) { case CRV_LINE : { const CurveLine& crvLine2 = *GetBasicCurveLine( &cCrv2) ; CurveLine* pCrvLine = GetLinePerpLineArc( crvLine2, ptNear2, crvArc1, ptNear1) ; if ( pCrvLine != nullptr) pCrvLine->Invert() ; return pCrvLine ; } case CRV_ARC : { const CurveArc& crvArc2 = *GetBasicCurveArc( &cCrv2) ; return GetLinePerpTwoArcs( crvArc1, ptNear1, crvArc2, ptNear2) ; } case CRV_BEZIER : return nullptr ; case CRV_COMPO : return nullptr ; default : return nullptr ; } } break ; case CRV_BEZIER : return nullptr ; case CRV_COMPO : return nullptr ; default : return nullptr ; } } //---------------------------------------------------------------------------- CurveLine* GetLinePerpTwoLines( const CurveLine& crvLine1, const Point3d& ptNear1, const CurveLine& crvLine2, const Point3d& ptNear2) { // le due linee devono essere parallele Vector3d vtDir1 ; if ( ! crvLine1.GetStartDir( vtDir1)) return nullptr ; Vector3d vtDir2 ; if ( ! crvLine2.GetStartDir( vtDir2)) return nullptr ; if ( ! AreSameOrOppositeVectorApprox( vtDir1, vtDir2)) return nullptr ; // determino la sovrapposizione longitudinale del secondo segmento sul primo double dLen1 ; crvLine1.GetLength( dLen1) ; double dStartLen = ( crvLine2.GetStart() - crvLine1.GetStart()) * vtDir1 ; double dEndLen = ( crvLine2.GetEnd() - crvLine1.GetStart()) * vtDir1 ; if ( dStartLen > dEndLen) swap( dStartLen, dEndLen) ; if ( dStartLen < 0) dStartLen = 0 ; if ( dEndLen > dLen1) dEndLen = dLen1 ; // determino la posizione dei punti vicini sull'intervallo ammesso double dNear1Len = ( ptNear1 - crvLine1.GetStart()) * vtDir1 ; if ( dNear1Len < dStartLen) dNear1Len = dStartLen ; if ( dNear1Len > dEndLen) dNear1Len = dEndLen ; double dNear2Len = ( ptNear2 - crvLine1.GetStart()) * vtDir1 ; if ( dNear2Len < dStartLen) dNear2Len = dStartLen ; if ( dNear2Len > dEndLen) dNear2Len = dEndLen ; // prendo la posizione intermedia double dPosLen = 0.5 * ( dNear1Len + dNear2Len) ; Point3d ptP1 = crvLine1.GetStart() + vtDir1 * dPosLen ; Point3d ptP2 = crvLine2.GetStart() + ( ptP1 - crvLine2.GetStart()) * vtDir2 * vtDir2 ; // creo la linea PtrOwner pCrvLine( CreateBasicCurveLine()) ; if ( IsNull( pCrvLine)) return nullptr ; // setto la linea if ( ! pCrvLine->Set( ptP1, ptP2)) return nullptr ; // la restituisco return Release( pCrvLine) ; } //---------------------------------------------------------------------------- CurveLine* GetLinePerpLineArc( const CurveLine& crvLine1, const Point3d& ptNear1, const CurveArc& crvArc2, const Point3d& ptNear2) { // l'arco deve essere piatto (no elica) if ( ! crvArc2.IsPlane()) return nullptr ; // versore della linea Vector3d vtDir1 ; if ( ! crvLine1.GetStartDir( vtDir1)) return nullptr ; // la linea deve giacere nel piano dell'arco o parallelo if ( ! AreOrthoApprox( vtDir1, crvArc2.GetNormVersor())) return nullptr ; // lunghezza della linea double dLen1 ; crvLine1.GetLength( dLen1) ; // determino la proiezione del centro dell'arco sulla linea e verifico stia sul segmento double dCenLen = ( crvArc2.GetCenter() - crvLine1.GetStart()) * vtDir1 ; if ( dCenLen < - EPS_ZERO || dCenLen > dLen1 + EPS_ZERO) return nullptr ; // punto di proiezione Point3d ptP1 = crvLine1.GetStart() + vtDir1 * dCenLen ; // punto sulla circonferenza (linea e circonferenza possono essere su piani paralleli) Vector3d vtDirP = crvArc2.GetCenter() - ptP1 ; vtDirP -= vtDirP * crvArc2.GetNormVersor() * crvArc2.GetNormVersor() ; if ( ! vtDirP.Normalize()) { // il centro č sul segmento, prendo la normale alla retta nel piano dell'arco vtDirP = vtDir1 ^ crvArc2.GetNormVersor() ; if ( ! vtDirP.Normalize()) return nullptr ; } Point3d ptP2 ; if ( ! FindPointOnArc( crvArc2, vtDirP, ptNear2, ptP2)) return nullptr ; // creo la linea PtrOwner pCrvLine( CreateBasicCurveLine()) ; if ( IsNull( pCrvLine)) return nullptr ; // setto la linea if ( ! pCrvLine->Set( ptP1, ptP2)) return nullptr ; // la restituisco return Release( pCrvLine) ; } //---------------------------------------------------------------------------- CurveLine* GetLinePerpTwoArcs( const CurveArc& crvArc1, const Point3d& ptNear1, const CurveArc& crvArc2, const Point3d& ptNear2) { // i due archi devono giacere nello stesso piano o in piani paralleli ed essere piatti if ( ! AreSameOrOppositeVectorApprox( crvArc1.GetNormVersor(), crvArc2.GetNormVersor()) || ! crvArc1.IsPlane() || ! crvArc2.IsPlane()) return nullptr ; // la linea cercata deve passare per i due centri Vector3d vtDirP = crvArc2.GetCenter() - crvArc1.GetCenter() ; vtDirP -= vtDirP * crvArc2.GetNormVersor() * crvArc2.GetNormVersor() ; if ( ! vtDirP.Normalize()) return GetLinePerpTwoConcentricArcs( crvArc1, ptNear1, crvArc2, ptNear2) ; Point3d ptP1 ; if ( ! FindPointOnArc( crvArc1, vtDirP, ptNear1, ptP1)) return nullptr ; Point3d ptP2 ; if ( ! FindPointOnArc( crvArc2, vtDirP, ptNear2, ptP2)) return nullptr ; // creo la linea PtrOwner pCrvLine( CreateBasicCurveLine()) ; if ( IsNull( pCrvLine)) return nullptr ; // setto la linea if ( ! pCrvLine->Set( ptP1, ptP2)) return nullptr ; // la restituisco return Release( pCrvLine) ; } //---------------------------------------------------------------------------- CurveLine* GetLinePerpTwoConcentricArcs( const CurveArc& crvArc1, const Point3d& ptNear1, const CurveArc& crvArc2, const Point3d& ptNear2) { // trovo il punto pių vicino a Near2 sul secondo arco DistPointCurve dstPtCurve( ptNear2, crvArc2) ; Point3d ptP ; int nFlag ; if ( ! dstPtCurve.GetMinDistPoint( 0, ptP, nFlag)) return nullptr ; // calcolo la linea perpendicolare al primo arco dal punto trovato e la inverto CurveLine* pCrvLine = GetBasicCurveLine( GetLinePointPerpCurve( ptP, crvArc1, ptNear1)) ; if ( pCrvLine != nullptr) pCrvLine->Invert() ; // restituisco la linea return pCrvLine ; }