//---------------------------------------------------------------------------- // EgalTech 2013-2014 //---------------------------------------------------------------------------- // File : LineTgCurvePerpCurve.cpp Data : 27.11.14 Versione : 1.5k5 // Contenuto : Implementazione funzioni per calcolo rette tg e perp. a curve. // // // // Modifiche : 27.11.14 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "CreateCurveAux.h" #include "/EgtDev/Include/EGkDistPointLine.h" #include "/EgtDev/Include/EGkLineTgCurvePerpCurve.h" #include "/EgtDev/Include/EGkLinePntTgCurve.h" #include "/EgtDev/Include/EgtPointerOwner.h" using namespace std ; //---------------------------------------------------------------------------- static CurveLine* GetLineTgLinePerpLine( const CurveLine& crvLine1, const Point3d& ptNear1, const CurveLine& crvLine2, const Point3d& ptNear2) ; static CurveLine* GetLineTgLinePerpArc( const CurveLine& crvLine1, const Point3d& ptNear1, const CurveArc& crvArc2, const Point3d& ptNear2) ; static CurveLine* GetLineTgArcPerpArc( const CurveArc& crvArc1, const Point3d& ptNear1, const CurveArc& crvArc2, const Point3d& ptNear2) ; static CurveLine* GetLineTgArcPerpLine( const CurveArc& crvArc1, const Point3d& ptNear1, const CurveLine& crvLine2, const Point3d& ptNear2) ; //---------------------------------------------------------------------------- ICurveLine* GetLineTgCurvePerpCurve( 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 GetLineTgLinePerpLine( crvLine1, ptNear1, crvLine2, ptNear2) ; } case CRV_ARC : { const CurveArc& crvArc2 = *GetBasicCurveArc( &cCrv2) ; return GetLineTgLinePerpArc( crvLine1, ptNear1, crvArc2, ptNear2) ; } return nullptr ; case CRV_BEZIER : return nullptr ; case CRV_COMPO : return nullptr ; default : return nullptr ; } } return nullptr ; case CRV_ARC : { const CurveArc& crvArc1 = *GetBasicCurveArc( &cCrv1) ; switch ( cCrv2.GetType()) { case CRV_LINE : { const CurveLine& crvLine2 = *GetBasicCurveLine( &cCrv2) ; return GetLineTgArcPerpLine( crvArc1, ptNear1, crvLine2, ptNear2) ; } case CRV_ARC : { const CurveArc& crvArc2 = *GetBasicCurveArc( &cCrv2) ; return GetLineTgArcPerpArc( crvArc1, ptNear1, crvArc2, ptNear2) ; } case CRV_BEZIER : return nullptr ; case CRV_COMPO : return nullptr ; default : return nullptr ; } } case CRV_BEZIER : return nullptr ; case CRV_COMPO : return nullptr ; default : return nullptr ; } } //---------------------------------------------------------------------------- CurveLine* GetLineTgLinePerpLine( const CurveLine& crvLine1, const Point3d& ptNear1, const CurveLine& crvLine2, const Point3d& ptNear2) { // versore della prima linea Vector3d vtDir1 ; if ( ! crvLine1.GetStartDir( vtDir1)) return nullptr ; // versore della seconda linea Vector3d vtDir2 ; if ( ! crvLine2.GetStartDir( vtDir2)) return nullptr ; // le due linee devono essere tra loro ortogonali if ( ! AreOrthoApprox( vtDir1, vtDir2)) return nullptr ; // determino il piede delle perpendicolare da un estremo della prima linea alla seconda linea // e verifico stia sul secondo segmento Point3d ptP2 ; if ( ! DistPointLine( crvLine1.GetStart(), crvLine2, false).GetMinDistPoint( ptP2) || ! crvLine2.IsPointOn( ptP2) ) return nullptr ; // calcolo il punto sulla prima linea pił vicino a Near1 Point3d ptP1 ; if ( ! DistPointLine( ptNear1, crvLine1).GetMinDistPoint( ptP1)) 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* GetLineTgLinePerpArc( 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 ; // il centro dell'arco deve essere sulla linea ( o la sua proiezione sul piano // arco contenente linea) Point3d ptCen = crvArc2.GetCenter() ; ptCen -= ( ptCen - crvLine1.GetStart()) * crvArc2.GetNormVersor() * crvArc2.GetNormVersor() ; if ( ! DistPointLine( ptCen, crvLine1, false).IsSmall()) return nullptr ; // calcolo i due punti possibili sulla circonferenza e scelgo il pił vicino a Near2 Vector3d vtDirP = crvArc2.GetCenter() - crvLine1.GetStart() ; vtDirP -= vtDirP * crvArc2.GetNormVersor() * crvArc2.GetNormVersor() ; if ( ! vtDirP.Normalize()) return nullptr ; Point3d ptP2 ; if ( ! FindPointOnArc( crvArc2, vtDirP, ptNear2, ptP2)) return nullptr ; // calcolo il punto sulla linea pił vicino a Near1 Point3d ptP1 ; if ( ! DistPointLine( ptNear1, crvLine1).GetMinDistPoint( ptP1)) 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* GetLineTgArcPerpArc( 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 ; // calcolo la retta dal centro del secondo arco tangente al primo arco e la inverto PtrOwner pCrvPtA( GetBasicCurveLine( GetLinePointTgCurve( crvArc2.GetCenter(), crvArc1, ptNear1))) ; if ( ! IsNull( pCrvPtA)) pCrvPtA->Invert() ; else { // se il centro del secondo arco sta sul primo arco, la retta si riduce ad un punto... // (inoltre possono essere su piani paralleli e diversi) Point3d ptCen = crvArc2.GetCenter() ; ptCen -= ( ptCen - crvArc1.GetCenter()) * crvArc1.GetNormVersor() * crvArc1.GetNormVersor() ; if ( crvArc1.IsPointOn( ptCen)) { // vettore tangente al primo arco nel punto considerato Vector3d vtTang = ( ptCen - crvArc1.GetCenter()) ^ crvArc1.GetNormVersor() ; if ( ! vtTang.Normalize()) return nullptr ; // costruisco la linea tangente pCrvPtA.Set( CreateBasicCurveLine()) ; if ( IsNull( pCrvPtA)) return nullptr ; pCrvPtA->Set( ptCen, ptCen + vtTang) ; } else return nullptr ; } // determino le intersezioni della retta con il secondo arco Vector3d vtDirP = pCrvPtA->GetEnd() - pCrvPtA->GetStart() ; vtDirP -= vtDirP * crvArc2.GetNormVersor() * crvArc2.GetNormVersor() ; if ( ! vtDirP.Normalize()) return nullptr ; Point3d ptP2 ; if ( ! FindPointOnArc( crvArc2, vtDirP, ptNear2, ptP2)) return nullptr ; // modifico il punto finale della retta if ( ! pCrvPtA->ModifyEnd( ptP2)) return nullptr ; // restituisco la retta return Release( pCrvPtA) ; } //---------------------------------------------------------------------------- CurveLine* GetLineTgArcPerpLine( const CurveArc& crvArc1, const Point3d& ptNear1, const CurveLine& crvLine2, const Point3d& ptNear2) { // l'arco deve essere piatto (no elica) if ( ! crvArc1.IsPlane()) return nullptr ; // versore della linea Vector3d vtDir2 ; if ( ! crvLine2.GetStartDir( vtDir2)) return nullptr ; // la linea deve giacere nel piano dell'arco o parallelo if ( ! AreOrthoApprox( vtDir2, crvArc1.GetNormVersor())) return nullptr ; // determino la proiezione del centro dell'arco sulla linea Point3d ptCenPro = crvLine2.GetStart() + ( crvArc1.GetCenter() - crvLine2.GetStart()) * vtDir2 * vtDir2 ; // versore perpendicolare alla direzione tra centro arco e sua proiezione sulla linea Vector3d vtDirP = ( ptCenPro - crvArc1.GetCenter()) ^ crvArc1.GetNormVersor() ; if ( ! vtDirP.Normalize()) return nullptr ; // punti estremi della linea cercata tra arco e linea data Point3d ptP1a = crvArc1.GetCenter() + vtDirP * crvArc1.GetRadius() ; Point3d ptP2a = ptCenPro + vtDirP * crvArc1.GetRadius() ; bool bLaOk = crvArc1.IsPointOn( ptP1a) && crvLine2.IsPointOn( ptP2a) ; Point3d ptP1b = crvArc1.GetCenter() - vtDirP * crvArc1.GetRadius() ; Point3d ptP2b = ptCenPro - vtDirP * crvArc1.GetRadius() ; bool bLbOk = crvArc1.IsPointOn( ptP1b) && crvLine2.IsPointOn( ptP2b) ; // se nessuna valida if ( ! bLaOk && ! bLbOk) return nullptr ; // altrimenti scelgo if ( ! bLaOk) { swap( ptP1a, ptP1b) ; swap( ptP2a, ptP2b) ; } else if ( ! bLbOk) ; else { if ( SqDist( ptP1a, ptNear1) + SqDist( ptP2a, ptNear2) > SqDist( ptP1b, ptNear1) + SqDist( ptP2b, ptNear2)) { swap( ptP1a, ptP1b) ; swap( ptP2a, ptP2b) ; } } // creo la linea PtrOwner pCrvLine( CreateBasicCurveLine()) ; if ( IsNull( pCrvLine)) return nullptr ; // setto la linea if ( ! pCrvLine->Set( ptP1a, ptP2a)) return nullptr ; // la restituisco return Release( pCrvLine) ; }