From 3a3c5917714f5191b558e51b5171c1b828ec06f9 Mon Sep 17 00:00:00 2001 From: Dario Sassi Date: Mon, 30 Apr 2018 14:36:00 +0000 Subject: [PATCH] EgtGeomKernel 1.9e1 : - prima versione di Collision Avoiding per Utensili rispetto a Superfici TriMesh. --- ...eSurfFrMove.cpp => CAvSimpleSurfFrMove.cpp | 36 +- CDSimpleSurfFrMove.h => CAvSimpleSurfFrMove.h | 14 +- CAvToolSurfTm.cpp | 78 + CAvToolSurfTm.h | 39 + CAvToolTriangle.cpp | 902 +++++++ CAvToolTriangle.h | 72 + CDBoxPolyhedron.cpp => CDeBoxPolyhedron.cpp | 8 +- CDBoxTria.cpp => CDeBoxTria.cpp | 12 +- EgtGeomKernel.rc | Bin 11710 -> 11710 bytes EgtGeomKernel.vcxproj | 21 +- EgtGeomKernel.vcxproj.filters | 63 +- GdbExecutor.cpp | 2012 +++++++++++++++- GdbExecutor.h | 27 + IntersLineSurfStd.cpp | 2093 +++++++++++++++++ IntersLineSurfStd.h | 268 +++ SurfFlatRegion.h | 2 +- 16 files changed, 5586 insertions(+), 61 deletions(-) rename CDSimpleSurfFrMove.cpp => CAvSimpleSurfFrMove.cpp (93%) rename CDSimpleSurfFrMove.h => CAvSimpleSurfFrMove.h (78%) create mode 100644 CAvToolSurfTm.cpp create mode 100644 CAvToolSurfTm.h create mode 100644 CAvToolTriangle.cpp create mode 100644 CAvToolTriangle.h rename CDBoxPolyhedron.cpp => CDeBoxPolyhedron.cpp (83%) rename CDBoxTria.cpp => CDeBoxTria.cpp (92%) create mode 100644 IntersLineSurfStd.cpp create mode 100644 IntersLineSurfStd.h diff --git a/CDSimpleSurfFrMove.cpp b/CAvSimpleSurfFrMove.cpp similarity index 93% rename from CDSimpleSurfFrMove.cpp rename to CAvSimpleSurfFrMove.cpp index 1f42674..96c7a20 100644 --- a/CDSimpleSurfFrMove.cpp +++ b/CAvSimpleSurfFrMove.cpp @@ -1,7 +1,7 @@ //---------------------------------------------------------------------------- -// EgalTech 2015-2016 +// EgalTech 2015-2018 //---------------------------------------------------------------------------- -// File : CDSimpleSurfFrMove.cpp Data : 10.01.16 Versione : 1.6l7 +// File : CASimpleSurfFrMove.cpp Data : 27.04.18 Versione : 1.9e1 // Contenuto : Implementazione delle funzioni di movimento per SurfFlatRegion // senza collisione con altri oggetti dello stesso tipo e nello // stesso piano o in piani paralleli. @@ -14,22 +14,22 @@ //--------------------------- Include ---------------------------------------- #include "stdafx.h" -#include "CDSimpleSurfFrMove.h" +#include "CAvSimpleSurfFrMove.h" #include "SurfFlatRegion.h" #include "CurveLine.h" #include "CurveArc.h" #include "CurveComposite.h" #include "IntersLineArc.h" #include "GeoConst.h" -#include "/EgtDev/Include/EGkCDSimpleSurfFrMove.h" +#include "/EgtDev/Include/EGkCAvSimpleSurfFrMove.h" #include "/EgtDev/Include/EgtPointerOwner.h" using namespace std ; //---------------------------------------------------------------------------- -// CDSimpleSurfFrMove +// CASimpleSurfFrMove //---------------------------------------------------------------------------- -CDSimpleSurfFrMove::CDSimpleSurfFrMove( const ISurfFlatRegion& SfrM, const ISurfFlatRegion& SfrF) +CAvSimpleSurfFrMove::CAvSimpleSurfFrMove( const ISurfFlatRegion& SfrM, const ISurfFlatRegion& SfrF) { // salvo puntatori alle regioni m_pRegM = &SfrM ; @@ -38,9 +38,9 @@ CDSimpleSurfFrMove::CDSimpleSurfFrMove( const ISurfFlatRegion& SfrM, const ISurf //---------------------------------------------------------------------------- bool -CDSimpleSurfFrMove::Translate( const Vector3d& vtDir, double& dLen) +CAvSimpleSurfFrMove::Translate( const Vector3d& vtDir, double& dLen) { - MyCDSimpleSurfFrMove ScdMove ( *m_pRegM, *m_pRegF) ; + MyCAvSimpleSurfFrMove ScdMove ( *m_pRegM, *m_pRegF) ; m_SCollInfo.nType = SCI_NONE ; if ( ! ScdMove.Translate( vtDir, dLen)) return false ; @@ -50,18 +50,18 @@ CDSimpleSurfFrMove::Translate( const Vector3d& vtDir, double& dLen) //---------------------------------------------------------------------------- bool -CDSimpleSurfFrMove::Rotate( const Point3d& ptCen, double& dAng) +CAvSimpleSurfFrMove::Rotate( const Point3d& ptCen, double& dAng) { - MyCDSimpleSurfFrMove ScdMove ( *m_pRegM, *m_pRegF) ; + MyCAvSimpleSurfFrMove ScdMove ( *m_pRegM, *m_pRegF) ; m_SCollInfo.nType = SCI_NONE ; return ScdMove.Rotate( ptCen, dAng) ; } //---------------------------------------------------------------------------- -// MyCDSimpleSurfFrMove +// MyCAvSimpleSurfFrMove //---------------------------------------------------------------------------- -MyCDSimpleSurfFrMove::MyCDSimpleSurfFrMove( const ISurfFlatRegion& SfrM, const ISurfFlatRegion& SfrF) +MyCAvSimpleSurfFrMove::MyCAvSimpleSurfFrMove( const ISurfFlatRegion& SfrM, const ISurfFlatRegion& SfrF) { // recupero rappresentazione base della regione mobile m_pRegM = GetBasicSurfFlatRegion( &SfrM) ; @@ -77,7 +77,7 @@ MyCDSimpleSurfFrMove::MyCDSimpleSurfFrMove( const ISurfFlatRegion& SfrM, const I //---------------------------------------------------------------------------- bool -MyCDSimpleSurfFrMove::Translate( const Vector3d& vtDir, double& dLen) +MyCAvSimpleSurfFrMove::Translate( const Vector3d& vtDir, double& dLen) { // verifico validità regioni if ( m_pRegM == nullptr || m_pRegF == nullptr) @@ -179,7 +179,7 @@ MyCDSimpleSurfFrMove::Translate( const Vector3d& vtDir, double& dLen) //---------------------------------------------------------------------------- bool -MyCDSimpleSurfFrMove::Rotate( const Point3d& ptCen, double& dAng) +MyCAvSimpleSurfFrMove::Rotate( const Point3d& ptCen, double& dAng) { // verifico validità regioni if ( m_pRegM == nullptr || m_pRegF == nullptr) @@ -250,7 +250,7 @@ MyCDSimpleSurfFrMove::Rotate( const Point3d& ptCen, double& dAng) // Massima traslazione da posizione sicura in direzione e con limite dati //---------------------------------------------------------------------------- bool -MyCDSimpleSurfFrMove::TranslateCurveNoCollisionCurve( const ICurve* pCrv1, const ICurve* pCrv2, +MyCAvSimpleSurfFrMove::TranslateCurveNoCollisionCurve( const ICurve* pCrv1, const ICurve* pCrv2, const Vector3d& vtDir, double& dLen, SCollInfo& scInfo) { // se entrambe linee, procedo direttamente @@ -308,7 +308,7 @@ MyCDSimpleSurfFrMove::TranslateCurveNoCollisionCurve( const ICurve* pCrv1, const // Massima traslazione da posizione sicura in direzione e con limite dati //---------------------------------------------------------------------------- bool -MyCDSimpleSurfFrMove::TranslateLineNoCollisionLine( const CurveLine* pLine1, const CurveLine* pLine2, +MyCAvSimpleSurfFrMove::TranslateLineNoCollisionLine( const CurveLine* pLine1, const CurveLine* pLine2, const Vector3d& vtDir, double& dLen, SCollInfo& scInfo) { // versore ortogonale al movimento @@ -422,7 +422,7 @@ MyCDSimpleSurfFrMove::TranslateLineNoCollisionLine( const CurveLine* pLine1, con // Massima rotazione da posizione sicura in direzione e con limite dati //---------------------------------------------------------------------------- bool -MyCDSimpleSurfFrMove::RotateCurveNoCollisionCurve( const ICurve* pCrv1, const ICurve* pCrv2, +MyCAvSimpleSurfFrMove::RotateCurveNoCollisionCurve( const ICurve* pCrv1, const ICurve* pCrv2, const Point3d& ptCen, double& dAng) { // se entrambe linee, procedo direttamente @@ -470,7 +470,7 @@ MyCDSimpleSurfFrMove::RotateCurveNoCollisionCurve( const ICurve* pCrv1, const IC // Massima rotazione da posizione sicura in direzione e con limite dati //---------------------------------------------------------------------------- bool -MyCDSimpleSurfFrMove::RotateLineNoCollisionLine( const CurveLine* pLine1, const CurveLine* pLine2, +MyCAvSimpleSurfFrMove::RotateLineNoCollisionLine( const CurveLine* pLine1, const CurveLine* pLine2, const Point3d& ptCen, double& dAng) { // senso di rotazione diff --git a/CDSimpleSurfFrMove.h b/CAvSimpleSurfFrMove.h similarity index 78% rename from CDSimpleSurfFrMove.h rename to CAvSimpleSurfFrMove.h index d05f19f..72319c9 100644 --- a/CDSimpleSurfFrMove.h +++ b/CAvSimpleSurfFrMove.h @@ -1,10 +1,10 @@ //---------------------------------------------------------------------------- -// EgalTech 2015-2016 +// EgalTech 2015-2018 //---------------------------------------------------------------------------- -// File : CDSimpleSurfFrMove.h Data : 10.01.16 Versione : 1.6l7 +// File : CAvSimpleSurfFrMove.h Data : 27.04.18 Versione : 1.9e1 // Contenuto : Dich.ne classe privata per movimento di superfici flat region -// nel loro piano con semplice verifica di collisione -// (ovvero controllando solo gli esterni). +// nel loro piano evitando collisioni semplici +// (ovvero controllando solo i loop esterni). // // Modifiche : 10.01.16 DS Creazione modulo. // @@ -13,16 +13,16 @@ #pragma once -#include "/EgtDev/Include/EGkCDSimpleSurfFrMove.h" +#include "/EgtDev/Include/EGkCAvSimpleSurfFrMove.h" class CurveLine ; class SurfFlatRegion ; //---------------------------------------------------------------------------- -class MyCDSimpleSurfFrMove +class MyCAvSimpleSurfFrMove { public : - MyCDSimpleSurfFrMove( const ISurfFlatRegion& SfrM, const ISurfFlatRegion& SfrF) ; + MyCAvSimpleSurfFrMove( const ISurfFlatRegion& SfrM, const ISurfFlatRegion& SfrF) ; public : bool Translate( const Vector3d& vtDir, double& dLen) ; diff --git a/CAvToolSurfTm.cpp b/CAvToolSurfTm.cpp new file mode 100644 index 0000000..f768d24 --- /dev/null +++ b/CAvToolSurfTm.cpp @@ -0,0 +1,78 @@ +//---------------------------------------------------------------------------- +// EgalTech 2018-2018 +//---------------------------------------------------------------------------- +// File : CAToolSurfTm.cpp Data : 27.04.18 Versione : 1.9e1 +// Contenuto : Implementazione della classe CAToolSurfTm. +// +// +// +// Modifiche : 27.04.18 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +#include "stdafx.h" +#include "CAvToolTriangle.h" +#include "CAvToolSurfTm.h" + +using namespace std ; + +//---------------------------------------------------------------------------- +ICAvToolSurfTm* +CreateCAvToolSurfTm( void) +{ + return static_cast ( new(nothrow) CAvToolSurfTm) ; +} + + +//---------------------------------------------------------------------------- +// CAvToolSurfTm +//---------------------------------------------------------------------------- +CAvToolSurfTm::CAvToolSurfTm( void) + : m_pSTm( nullptr) +{ +} + +//---------------------------------------------------------------------------- +bool +CAvToolSurfTm::SetSurfTm( const ISurfTriMesh& Stm) +{ + m_pSTm = GetBasicSurfTriMesh( &Stm) ; + return ( m_pSTm != nullptr && m_pSTm->IsValid()) ; +} + +//---------------------------------------------------------------------------- +bool +CAvToolSurfTm::SetMoveDir( const Vector3d& vtMove) +{ + return m_frMove.Set( ORIG, vtMove) ; +} + +//---------------------------------------------------------------------------- +bool +CAvToolSurfTm::SetStdTool( double dH, double dR, double dCornR) +{ + return m_Tool.SetStdTool( "", dH, dR, dCornR, 0) ; +} + +//---------------------------------------------------------------------------- +double +CAvToolSurfTm::TestPosition( const Point3d& ptT, const Vector3d& vtDir) +{ + double dTotDist = 0 ; + Point3d ptCurr = ptT ; + Triangle3d Tria ; + for ( int nTria = m_pSTm->GetFirstTriangle( Tria) ; + nTria != SVT_NULL ; + nTria = m_pSTm->GetNextTriangle( nTria, Tria)) { + double dDist = CAvToolTriangle( m_Tool, ptCurr, vtDir, Tria, m_frMove.VersZ()) ; + if ( dDist < - EPS_SMALL) + return dDist ; + if ( dDist > EPS_SMALL) { + dTotDist += dDist ; + ptCurr += dDist * m_frMove.VersZ() ; + } + } + return dTotDist ; +} + diff --git a/CAvToolSurfTm.h b/CAvToolSurfTm.h new file mode 100644 index 0000000..d31eb2c --- /dev/null +++ b/CAvToolSurfTm.h @@ -0,0 +1,39 @@ +//---------------------------------------------------------------------------- +// EgalTech 2018-2018 +//---------------------------------------------------------------------------- +// File : CAToolSurfTm.h Data : 27.04.18 Versione : 1.9e1 +// Contenuto : Dichiarazioni per classe CAToolSurfTm. +// +// +// +// Modifiche : 27.04.18 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +#pragma once + +#include "HashGrids2d.h" +#include "SurfTriMesh.h" +#include "Tool.h" +#include "/EgtDev/Include/EGkCAvToolSurfTm.h" + + +//----------------------------------------------------------------------------- +class CAvToolSurfTm : public ICAvToolSurfTm +{ + public : // ICAvToolSurfTm + bool SetSurfTm( const ISurfTriMesh& Stm) override ; + bool SetMoveDir( const Vector3d& vtrMove) override ; + bool SetStdTool( double dH, double dR, double dCornR) override ; + double TestPosition( const Point3d& ptT, const Vector3d& vtDir) override ; + + public : + CAvToolSurfTm( void) ; + + private : + Frame3d m_frMove ; + const SurfTriMesh* m_pSTm ; + HashGrids2d m_HGrids ; + Tool m_Tool ; +} ; diff --git a/CAvToolTriangle.cpp b/CAvToolTriangle.cpp new file mode 100644 index 0000000..b45c5e8 --- /dev/null +++ b/CAvToolTriangle.cpp @@ -0,0 +1,902 @@ +//---------------------------------------------------------------------------- +// EgalTech 2018-2018 +//---------------------------------------------------------------------------- +// File : CAvToolTriangle.cpp Data : 27.04.18 Versione : 1.9e1 +// Contenuto : Implementazione delle funzioni ToolTriangleCollisionAvoid. +// +// +// +// Modifiche : 10.03.18 LM Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +#include "stdafx.h" +#include "CAvToolTriangle.h" +#include "IntersLineSurfStd.h" +#include "IntersLineTria.h" +#include "/EgtDev/Include/ENkPolynomialRoots.h" +#include "/EgtDev/Include/EgtNumUtils.h" + +using namespace std ; + +//---------------------------------------------------------------------------- +// La funzione determina la minima distanza di allontanamento lungo una direzione fissata +// per evitare la collisione tra un utensile ed un triangolo. +// Se nella posizione iniziale non c'è gia collisione si restituisce il valore 0. +// In caso di errore si restituisce il valore -1. +double +CAvToolTriangle( const Tool& tlTool, const Point3d& ptToolOrig, const Vector3d& vtToolAx, + const Triangle3d& trTria, const Vector3d& vtMove) +{ + // se utensile cilindrico + if ( tlTool.GetType() == Tool::CYLMILL) { + // parametri geometrici + double dHeigth = tlTool.GetHeigth() ; + double dRadius = tlTool.GetRadius() ; + // distanza di allontanamento del cilindro + double dDist = CAvCylinderTriangle( ptToolOrig, vtToolAx, dHeigth, dRadius, trTria, vtMove) ; + return dDist ; + } + // se utensile sferico + else if ( tlTool.GetType() == Tool::BALLMILL) { + // parametri geometrici + double dCylHeigth = tlTool.GetHeigth() - tlTool.GetTipHeigth() ; + double dRadius = tlTool.GetRadius() ; + // prima determino l'allontanamento della sfera + Point3d ptSpheOrig = ptToolOrig - dCylHeigth * vtToolAx ; + double dDist = CAvSphereTriangle( ptSpheOrig, dRadius, trTria, vtMove) ; + // poi verifico quello del cilindro (tenendo conto di quanto è stata allontanata la sfera + Point3d ptCylOrig = ptToolOrig + vtMove * max( dDist, 0.) ; + double dDist2 = CAvCylinderTriangle( ptCylOrig, vtToolAx, dCylHeigth, dRadius, trTria, vtMove) ; + return ( max( dDist, 0.) + max( dDist2, 0.)) ; + } + // altrimenti utensile di tipo non gestito + else + return - 1. ; +} + +//---------------------------------------------------------------------------- +// **** SFERA **** +//---------------------------------------------------------------------------- +// La funzione determina la minima distanza di allontanamento lungo una direzione fissata +// per evitare la collisione tra una sfera ed un triangolo. +double +CAvSphereTriangle( const Point3d& ptSpheCen, double dSpheRad, const Triangle3d& trTria, const Vector3d& vtMove) +{ + // Se la sfera sta già tutta dalla parte del movimento rispetto al piano del triangolo non va allontanata + Vector3d vtVert0 = ptSpheCen - trTria.GetP( 0) ; + Vector3d vtVert1 = ptSpheCen - trTria.GetP( 1) ; + Vector3d vtVert2 = ptSpheCen - trTria.GetP( 2) ; + if ( vtVert0 * vtMove > dSpheRad - EPS_SMALL && + vtVert1 * vtMove > dSpheRad - EPS_SMALL && + vtVert2 * vtMove > dSpheRad - EPS_SMALL) + return 0. ; + + // Valuto Tangenza col piano + double dPlaneLeakDist = SpherePlaneLeakDist( ptSpheCen, dSpheRad, trTria.GetP( 0), trTria.GetN(), vtMove) ; + // Se il punto di tangenza esiste, verifico se è interno al triangolo + if ( dPlaneLeakDist >= 0) { + Point3d ptTan = ptSpheCen + dPlaneLeakDist * vtMove - dSpheRad * trTria.GetN() ; + // Se il punto è interno abbiamo finito + if ( IsPointInsideTriangle( ptTan, trTria)) + return dPlaneLeakDist ; + } + + // Valuto le distanze di allontanamento dai segmenti (con i loro estremi) e prendo la maggiore + double dLeakDist = 0. ; + for ( int nSeg = 0 ; nSeg < 3 ; ++ nSeg) { + Vector3d vtSeg = trTria.GetP( ( nSeg + 1) % 3) - trTria.GetP( nSeg) ; + double dSegLen = vtSeg.Len() ; + vtSeg /= dSegLen ; + double dCurLeakDist = SphereSegmentLeakDist( ptSpheCen, dSpheRad, trTria.GetP( nSeg), vtSeg, dSegLen, vtMove) ; + if ( dCurLeakDist > dLeakDist) + dLeakDist = dCurLeakDist ; + } + return dLeakDist ; +} + +//---------------------------------------------------------------------------- +// Calcola la distanza di allontanamento lungo una direzione fissata di una sfera da un piano. +double +SpherePlaneLeakDist( const Point3d& ptSpheCen, double dSpheRad, + const Point3d& ptPlane, const Vector3d& vtPlaneN, const Vector3d& vtMove) +{ + // Se la direzione di allontanamento sta nel piano + if ( abs( vtPlaneN * vtMove) < EPS_SMALL) { + if ( abs( ( ptSpheCen - ptPlane) * vtPlaneN) > dSpheRad) + return 0. ; + else + return -1. ; + } + // altrimenti ... + else { + double dLeakDist = ( dSpheRad - ( ptSpheCen - ptPlane) * vtPlaneN) / ( vtMove * vtPlaneN) ; + return max( dLeakDist, 0.) ; + } +} + +//---------------------------------------------------------------------------- +// Calcola la distanza di allontanamento lungo una direzione fissata di una sfera da un segmento. +// Il segmento è descritto da punto iniziale, versore della direzione e lunghezza. +double +SphereSegmentLeakDist( const Point3d& ptSpheCen, double dSpheRad, + const Point3d& ptSeg, const Vector3d& vtSegDir, double dSegLen, + const Vector3d& vtMove) +{ + // Controllo con l'interno del segmento + double dU[2] ; + int nTanPointNum = SphereLineTangentPoints( ptSpheCen, dSpheRad, ptSeg, vtSegDir, dSegLen, vtMove, dU[0], dU[1]) ; + double dLeakDistIn = 0. ; + for ( int nSol = 0 ; nSol < nTanPointNum && nTanPointNum != 3 ; ++ nSol) { + if ( dU[nSol] < 0.) + continue ; + Point3d ptC = ptSpheCen + dU[nSol] * vtMove ; + double dSegPar = ( ptC - ptSeg) * vtSegDir ; + if ( dSegPar > 0 && dSegPar < dSegLen) + dLeakDistIn = dU[nSol] ; + } + // Controllo con gli estremi + Point3d ptSegEnd = ptSeg + dSegLen * vtSegDir ; + double dDistStart = SpherePointLeakDist( ptSpheCen, dSpheRad, ptSeg, vtMove) ; + double dDistEnd = SpherePointLeakDist( ptSpheCen, dSpheRad, ptSegEnd, vtMove) ; + // Restituisco il massimo + return max( dLeakDistIn, max( dDistStart, dDistEnd)) ; +} + +//---------------------------------------------------------------------------- +// Calcola la distanza di allontanamento lungo una direzione fissata di una sfera da un punto. +double +SpherePointLeakDist( const Point3d& ptSpheCen, double dSpheRad, const Point3d ptP, const Vector3d& vtMove) +{ + Vector3d vtOR = ptP - ptSpheCen ; + double dDotORMot = vtOR * vtMove ; + Vector3d vtOROrt = vtOR - dDotORMot * vtMove ; + double dSqOROrtLen = vtOROrt.SqLen() ; + double dSqSphRad = dSpheRad * dSpheRad ; + if ( dSqOROrtLen > dSqSphRad + 2 * dSpheRad * EPS_SMALL) + return 0. ; + else + return max( dDotORMot + sqrt( max( dSpheRad * dSpheRad - dSqOROrtLen, 0.)), 0.) ; +} + +//---------------------------------------------------------------------------- +// **** CILINDRO **** +//---------------------------------------------------------------------------- +// La funzione determina la minima distanza di allontanamento lungo una direzione fissata +// per evitare la collisione tra un cilindro ed un triangolo. +double +CAvCylinderTriangle( const Point3d& ptCylOrig, const Vector3d& vtCylAx, double dHeigth, double dRad, + const Triangle3d& trTria, const Vector3d& vtMove) +{ + // Classificazione del moto + int nMotionType = 0 ; + if ( AreSameVectorApprox( vtCylAx, vtMove)) + nMotionType = 1 ; + else if ( AreOppositeVectorApprox( vtCylAx, vtMove)) + nMotionType = 2 ; + else if ( AreOrthoApprox( vtCylAx, vtMove)) + nMotionType = 3 ; + + // Moto lungo la direzione dell'asse del cilindro + if ( nMotionType == 1 || nMotionType == 2) { + // In questo caso il problema si riduce alla determinazione della distanza di allontanamento + // del disco all'estremità opposta rispetto alla direzione di moto. + // Il punto base di questo disco viene così calcolato + Point3d ptBase = ptCylOrig ; + if ( nMotionType == 1) + ptBase -= dHeigth * vtCylAx ; + // La sua normale vale + // Nel Caso 1 coincide con quella dell'utensile, nel caso 2 è opposta + // !!!!! DA FARE !!!!! + // Valuto le distanze con segno dei vertici dal piano del disco : + // se sono tutte negative non interferiscono. + double dDistV[3] ; + dDistV[0] = PointPlaneSignedDist( trTria.GetP( 0), ptBase, vtCylAx) ; + dDistV[1] = PointPlaneSignedDist( trTria.GetP( 1), ptBase, vtCylAx) ; + dDistV[2] = PointPlaneSignedDist( trTria.GetP( 2), ptBase, vtCylAx) ; + double dMaxDistV = max( dDistV[0], max( dDistV[1], dDistV[2])) ; + if ( dMaxDistV < 0.) + return 0. ; + // Se tutti i punti distano dall'asse di movimento meno del raggio, l'ultimo + // punto di contatto deve essere un vertice del triangolo. + double dSqRad = dRad * dRad ; + bool bInV[3] ; + bInV[0] = ( GetPointLineSqDist( trTria.GetP( 0), ptBase, vtMove) < dSqRad) ; + bInV[1] = ( GetPointLineSqDist( trTria.GetP( 1), ptBase, vtMove) < dSqRad) ; + bInV[2] = ( GetPointLineSqDist( trTria.GetP( 2), ptBase, vtMove) < dSqRad) ; + if ( bInV[0] && bInV[1] && bInV[2]) + return max( dMaxDistV, 0.) ; + // Ciclo sui segmenti del triangolo e calcolo la loro distanza di allontanamento, calcolo + // anche la distanza di allontanamento dai vertici distanti dall'asse meno del raggio. + double dMaxDistVS = 0. ; + for ( int nVS = 0 ; nVS < 3 ; ++ nVS) { + // Vertici + if ( bInV[nVS] && dDistV[nVS] > dMaxDistVS) + dMaxDistVS = dDistV[nVS] ; + // Se un lato del triangolo ha entrambi gli estremi con distanza negativa dal piano del disco, + // non può interferire con esso. + int nVE = ( nVS + 1) % 3 ; + if ( dDistV[nVS] < 0 && dDistV[nVE] < 0) + continue ; + // Versore e lunghezza del segmento + Vector3d vtSeg = trTria.GetP( nVE) - trTria.GetP( nVS) ; + double dSegLen = vtSeg.Len() ; + vtSeg /= dSegLen ; + // Distanza dal piano del segmento corrente + double dCurDist = DiskSegmentLeakDistLongMotion( ptBase, vtCylAx, dRad, trTria.GetP( nVS), vtSeg, dSegLen) ; + if ( dCurDist > dMaxDistVS) + dMaxDistVS = dCurDist ; + } + // Distanza di allontanamento dall'interno del triangolo + double dMaxDistI = DiskTriaInteriorLeakDistLongMot( ptBase, vtCylAx, dRad, trTria) ; + return max( dMaxDistVS, dMaxDistI) ; + } + // Moto perpendicolare all'asse del cilindro + else if ( nMotionType == 3) { + // PROVE PUNTI E SEGMENTI + double dLeakDist = - DBL_MAX ; + for ( int nVrt = 0 ; nVrt < 3 ; ++ nVrt) { + double dCurDist = CylPointLeakDistOrtMotion( trTria.GetP( nVrt), ptCylOrig, vtCylAx, vtMove, dHeigth, dRad) ; + if ( dLeakDist < dCurDist) + dLeakDist = dCurDist ; + } + // FINE PROVE PUNTI + // INIZIO PROVA SEGMENTI + for ( int nVrtS = 0 ; nVrtS < 3 ; ++ nVrtS) { + int nVrtE = ( nVrtS + 1) % 3 ; + Vector3d vtSeg = trTria.GetP( nVrtE) - trTria.GetP( nVrtS) ; + double dSegLen = vtSeg.Len() ; + vtSeg /= dSegLen ; + double dCurDist = CylSegmentLeakDistOrtMotion( trTria.GetP( nVrtS), ptCylOrig, vtSeg, + vtCylAx, vtMove, dSegLen, dHeigth, dRad) ; + if ( dLeakDist < dCurDist) + dLeakDist = dCurDist ; + } + // FINE PROVA SEGMENTI + // PROVA INTERNO + Point3d ptBaseCont, ptBottomCont ; + double dBaseLeak = DiskPlaneLeakDistOrtMot( trTria, ptCylOrig, vtCylAx, vtMove, dRad, ptBaseCont) ; + double dBottomLeak = DiskPlaneLeakDistOrtMot( trTria, ptCylOrig - dHeigth * vtCylAx, vtCylAx, vtMove, dRad, ptBottomCont) ; + if ( ! IsPointInsideTriangle( ptBaseCont, trTria)) + dBaseLeak = 0. ; + if ( ! IsPointInsideTriangle( ptBottomCont, trTria)) + dBottomLeak = 0. ; + double dInnerLeak = max( dBaseLeak , dBottomLeak) ; + if ( dLeakDist < dInnerLeak) + dLeakDist = dInnerLeak ; + // FINE PROVA INTERNO + return dLeakDist ; + } + // Moto generico + else + return -1. ; +} + +//---------------------------------------------------------------------------- +// Determina la distanza di fuga di un disco, che trasla lungo il suo asse di simmetria, da +// un segmento. Il disco è descritto dal quadrato del suo raggio, il moto dal centro nella +// posizione di partenza e il versore di traslazione. Il segmento è +// descritto da un punto suo estremo, dal versore direzione diretto verso +// l'altro estremo e dalla sua lunghezza. +//double +//DiskSegmentLeakDistLongMotion( const Point3d& ptDisc, const Point3d& ptSeg, +// const Vector3d& vtDiscLeak, const Vector3d& vtSeg, +// double dSegLen, double dDiscSqRad) +//{ +// // Il disco non può interferire col segmento nel suo moto, se la distanza del +// // segmento dall'asse di traslazione è maggiore del raggio. +// if ( LineSegmentSqDist( ptDisc, ptSeg, vtDiscLeak, vtSeg, dSegLen) > dDiscSqRad) +// return 0. ; +// +// // Imposto l'equazione: la distanza quadrata del generico punto della retta associata al +// // segmento dall'asse lungo cui si sposta il disco deve valere raggio quadrato del disco. +// Vector3d vtLineSegOrt = ( ptSeg - ptDisc) - ( ptSeg - ptDisc) * vtDiscLeak * vtDiscLeak ; +// Vector3d vtSegOrt = vtSeg - vtSeg * vtDiscLeak * vtDiscLeak ; +// DBLVECTOR vdCoef( 3) ; +// DBLVECTOR vdRoots ; +// vdCoef[0] = vtLineSegOrt.SqLen() - dDiscSqRad ; +// vdCoef[1] = 2 * vtLineSegOrt * vtSegOrt ; +// vdCoef[2] = vtSegOrt.SqLen() ; +// // Soluzione dell'equazione +// int nRoot = PolynomialRoots( 2, vdCoef, vdRoots) ; +// // Ciclo sulle soluzioni per trovare la distanza di allontanamento +// double dSegDist = - DBL_MAX ; +// for ( int nSol = 0 ; nSol < nRoot ; ++ nSol) { +// // Soluzione interna al segmento +// if ( vdRoots[nSol] > 0 && vdRoots[nSol] < dSegLen) { +// Point3d ptC = ptSeg + vdRoots[nSol] * vtSeg ; +// // Distanza del punto soluzione dal piano del disco nella posizione iniziale +// double dCurDist = PointPlaneSignedDist( ptC, ptDisc, vtDiscLeak) ; +// if ( dSegDist < dCurDist) +// dSegDist = dCurDist ; +// } +// } +// return dSegDist ; +//} +///// ALTRA VERSIONE SPERIMENTALE DELLA PRECEDNTE +double +DiskSegmentLeakDistLongMotion( const Point3d& ptDisc, const Vector3d& vtDiscLeak, double dDiscRad, + const Point3d& ptSeg, const Vector3d& vtSeg, double dSegLen) +{ + // Il disco non può interferire col segmento nel suo moto, se la distanza del + // segmento dall'asse di traslazione è maggiore del raggio. + if ( LineSegmentSqDist( ptDisc, vtDiscLeak, ptSeg, vtSeg, dSegLen) > dDiscRad * dDiscRad) + return 0. ; + + // Imposto l'equazione: la distanza quadrata del generico punto della retta associata al + // segmento dall'asse lungo cui si sposta il disco deve valere raggio quadrato del disco. + Vector3d vtLineSegOrt = ( ptSeg - ptDisc) - ( ptSeg - ptDisc) * vtDiscLeak * vtDiscLeak ; + Vector3d vtSegOrt = vtSeg - vtSeg * vtDiscLeak * vtDiscLeak ; + DBLVECTOR vdCoef(3) ; + DBLVECTOR vdRoots ; + vdCoef[0] = vtLineSegOrt.SqLen() - dDiscRad * dDiscRad ; + vdCoef[1] = 2 * vtLineSegOrt * vtSegOrt ; + vdCoef[2] = vtSegOrt.SqLen() ; + // Segmento e asse paralleli + if ( vdCoef[2] < SQ_EPS_ZERO) { + if ( abs( vdCoef[0]) < 2 * dDiscRad * EPS_SMALL) { + double dLenSt = PointPlaneSignedDist( ptSeg, ptDisc, vtDiscLeak) ; + double dLenEn = PointPlaneSignedDist( ptSeg + dSegLen * vtSeg, ptDisc, vtDiscLeak) ; + return max( max( dLenSt, dLenEn), 0.) ; + } + else + return 0. ; + } + // Soluzione dell'equazione + else { + int nRoot = PolynomialRoots( 2, vdCoef, vdRoots) ; + // Ciclo sulle soluzioni per trovare la distanza di allontanamento + double dSegDist = 0. ; + for ( int nSol = 0 ; nSol < nRoot ; ++ nSol) { + // Soluzione interna al segmento + if ( vdRoots[nSol] > 0. && vdRoots[nSol] < dSegLen) { + Point3d ptC = ptSeg + vdRoots[nSol] * vtSeg ; + // Distanza del punto soluzione dal piano del disco nella posizione iniziale + double dCurDist = PointPlaneSignedDist( ptC, ptDisc, vtDiscLeak) ; + if ( dCurDist > dSegDist) + dSegDist = dCurDist ; + } + } + return dSegDist ; + } +} + +//---------------------------------------------------------------------------- +// Determina la distanza di allontanamento di un disco, che trasla lungo il suo asse di simmetria, +// dall'interno di un triangolo. Il disco è descritto dal suo raggio e il moto dal +// centro nella posizione iniziale e dal versore del suo asse di simmetria +// (COINCIDENTE CON IL VERSORE DELLA DIREZIONE DI ALLONTANAMENTO). +double +DiskTriaInteriorLeakDistLongMot( const Point3d& ptDisk, const Vector3d& vtDiskAx, double dDiskRad, + const Triangle3d& trTria) +{ + // Se disco e triangolo sono complanari + if ( AreSameVectorApprox( vtDiskAx, trTria.GetN())) { + // verifico solo il centro, se centro esterno non più del raggio sicuramente toccherebbe i lati + double dDist = PointPlaneSignedDist( ptDisk, trTria.GetP( 0), trTria.GetN()) ; + if ( IsPointInsideTriangle( ptDisk - dDist * trTria.GetN(), trTria)) + return max( -dDist, 0.) ; + } + // Cerco un punto di contatto nell'interno del triangolo. Se tale punto + // esiste, la retta intersezione fra il piano del triangolo e quello del + // disco è tangente alla circonferenza. + // Vettore tangente alla circonferenza e vettore radiale + Vector3d vtRadLine = vtDiskAx * ( trTria.GetN() * vtDiskAx) - trTria.GetN() ; + vtRadLine.Normalize() ; + // Punti delle due rette candidate all'intersezione col triangolo + Point3d ptStPlus = ptDisk + dDiskRad * vtRadLine ; + Point3d ptStMinus = ptDisk - dDiskRad * vtRadLine ; + // Intersezioni con la prima retta + double dDistPlus = 0. ; + Point3d ptIntPlus1, ptIntPlus2 ; + int nIntPlus = IntersLineTria( ptStPlus, vtDiskAx, 10, trTria, ptIntPlus1, ptIntPlus2, false) ; + if ( nIntPlus != ILTT_NO) { + double dDist1 = PointPlaneSignedDist( ptIntPlus1, ptDisk, vtDiskAx) ; + // Se l'intersezione è doppia, ha senso anche dDist2. + if ( nIntPlus == ILTT_SEGM || + nIntPlus == ILTT_SEGM_ON_EDGE) { + double dDist2 = PointPlaneSignedDist( ptIntPlus2, ptDisk, vtDiskAx) ; + dDistPlus = max( dDist1, dDist2) ; + } + // Altrimenti ha senso solo dDist1 + else + dDistPlus = dDist1 ; + } + // Intersezioni con la seconda retta + double dDistMinus = 0. ; + Point3d ptIntMinus1, ptIntMinus2 ; + int nIntMinus = IntersLineTria( ptStMinus, vtDiskAx, 10, trTria, ptIntMinus1, ptIntMinus2, false) ; + if ( nIntMinus != ILTT_NO) { + double dDist1 = PointPlaneSignedDist( ptIntMinus1, ptDisk, vtDiskAx) ; + // Se l'intersezione è doppia, ha senso anche dDist2. + if ( nIntMinus == ILTT_SEGM || + nIntMinus == ILTT_SEGM_ON_EDGE) { + double dDist2 = PointPlaneSignedDist( ptIntMinus2, ptDisk, vtDiskAx) ; + dDistMinus = max( dDist1, dDist2) ; + } + // Altrimenti ha senso solo dDist1 + else + dDistMinus = dDist1 ; + } + return max( dDistPlus, dDistMinus) ; +} + +//---------------------------------------------------------------------------- +// Restituisce la distanza di allontanamento di un cilindro, che trasla lungo il suo asse +// di simmetria, da un triangolo. +// Il cilindro è descritto da raggio e altezza. Il suo moto è descritto dalla +// posizione iniziale, dal versore dell'asse di simmetria +// e dal versore della direzione del moto. Il segmento è descritto da punto +// iniziale, versore direzione e lunghezza. +double +CylTriaSegmentLeakDistLongMot( const Triangle3d& trTria, const Vector3d& vtMotion, + const Point3d& ptCylBase, double dCylRad) +{ + // Cerco i punti di contatto sui segmenti + double dSegDist = - DBL_MIN ; + // Ciclo sui segmenti + for ( int nVS = 0 ; nVS < 3 ; ++ nVS) { + int nVE = ( nVS + 1) % 3 ; + // Versore del segmento + Vector3d vtSeg = trTria.GetP( nVE) - trTria.GetP( nVS) ; + double dSegLen = vtSeg.Len() ; + vtSeg /= dSegLen ; + // Vettore punto retta + Vector3d vtPointLine = trTria.GetP( nVS) - ptCylBase ; + // Componenti dei vettori ortogonali all'asse del cilindro + Vector3d vtSegOrt = vtSeg - vtSeg * vtMotion * vtMotion ; + Vector3d vtPointLineOrt = vtPointLine - vtPointLine * vtMotion * vtMotion ; + + DBLVECTOR vdCoef(3) ; + DBLVECTOR vdRoots ; + vdCoef[0] = vtPointLineOrt.SqLen() - dCylRad * dCylRad ; + vdCoef[1] = 2 * vtPointLineOrt * vtSegOrt ; + vdCoef[2] = vtSegOrt.SqLen() ; + + // Soluzione dell'equazione + int nRoot = PolynomialRoots( 2, vdCoef, vdRoots) ; + for ( int nSol = 0 ; nSol < nRoot ; ++ nSol) { + Point3d ptInt = trTria.GetP( nVS) + vdRoots[nSol] * vtSegOrt ; + if ( ( ptInt - trTria.GetP( nVS)) * vtSeg > 0 && + ( ptInt - trTria.GetP( nVS)) * vtSeg < dSegLen) { + double dCurDist = ( ptInt - ptCylBase) * vtMotion ; + if ( dSegDist < dCurDist) + dSegDist = dCurDist ; + } + } + } + return dSegDist ; +} + +//---------------------------------------------------------------------------- +// Restituisce la distanza di fuga di un cilindro da un punto nel caso di moto +// ortogonale all'asse di simmetria. Il cilindro è descritto da raggio e altezza. +// Il suo moto è descritto dalla posizione iniziale, dal versore (NORMA UNITARIA) +// dell'asse di simmetria e dal versore della direzione del moto. +double +CylPointLeakDistOrtMotion( const Point3d& ptP, const Point3d& ptCylOrig, + const Vector3d& vtCylAx, const Vector3d& vtMove, + double dCylHei, double dCylRad) +{ + double dSqRad = dCylRad * dCylRad ; + Vector3d vtRP = ptP - ptCylOrig ; + // Se il punto sta al di sopra o al di sotto rispetto al cilindro abbiamo finito + double dDotRPCylAx = vtRP * vtCylAx ; + if ( dDotRPCylAx > EPS_SMALL || dDotRPCylAx < - dCylHei - EPS_SMALL) + return 0. ; + Vector3d vtPlaneRP = vtRP - dDotRPCylAx * vtCylAx ; + // Se il punto sta dietro al cilindro abbiamo finito + double dDotPlaneRPRemDir = vtPlaneRP * vtMove ; + if ( dDotPlaneRPRemDir < 0. && vtPlaneRP.SqLen() > dSqRad) + return 0. ; + Vector3d vtPlaneOrtRP = vtPlaneRP - vtPlaneRP * vtMove * vtMove ; + // Se il punto è a destra o sinistra del cilindro abbiamo finito + double dSqOrtLen = vtPlaneOrtRP.SqLen() ; + if ( dSqOrtLen > dSqRad + 2 * dCylRad * EPS_SMALL) + return 0. ; + // Calcolo e restituisco la distanza + return dDotPlaneRPRemDir + sqrt( max( dSqRad - dSqOrtLen, 0.)) ; +} + +//---------------------------------------------------------------------------- +// Restituisce la distanza di fuga di un disco da un segmento nel caso di +// moto ortogonale all'asse di simmetria. +// Il disco è descritto dal suo raggio. Il movimento è descritto dal versore +// dell'asse del disco, dal centro nella posizione iniziale e dal +// versore della direzione del moto. Il segmento è descritto da punto iniziale, +// versore direzione e lunghezza. +double +DiskSegmentLeakDistOrtMot( const Point3d& ptSeg, const Point3d& ptDiscOrig, + const Vector3d& vtSeg, const Vector3d& vtDiscAx, const Vector3d& vtMove, + double dSegLen, double dDiscRad) +{ + // Se il segmento non è nel piano, il più remoto punto di contatto è, + // se esiete, l'intersezione fra piano e segmento. Il caso in cui il + // segmento giace nel piano non ci interessa + if ( ! ( abs( vtSeg * vtDiscAx) < EPS_ZERO)) { + Point3d ptSegEnd = ptSeg + dSegLen * vtSeg ; + double dDotStart = ( ptSeg - ptDiscOrig) * vtDiscAx ; + double dDotEnd = ( ptSegEnd - ptDiscOrig) * vtDiscAx ; + if ( dDotStart * dDotEnd < 0.) { + double dS = ( ptDiscOrig - ptSeg) * vtDiscAx / ( vtSeg * vtDiscAx) ; + Point3d ptInt = ptSeg + dS * vtSeg ; + Vector3d vtOI = ( ptInt - ptDiscOrig) ; + double dLongCord = vtOI * vtMove ; + Vector3d vtLong = dLongCord * vtMove ; + Vector3d vtOrt = vtOI - vtLong ; + double dSqOrtLen = vtOrt.SqLen() ; + if ( dSqOrtLen > dDiscRad * dDiscRad + 2 * dDiscRad * EPS_SMALL) + return 0. ; + else + return max( dLongCord + sqrt( max( dDiscRad * dDiscRad - dSqOrtLen, 0.)), 0.) ; + } + else + return 0. ; + } + return 0. ; +} + +//---------------------------------------------------------------------------- +// Restituisce la distanza di allontanamento di un cilindro da un segmento. +// Il cilindro è descritto da raggio e altezza. +// Il suo moto è descritto dalla posizione iniziale, dal versore (NORMA UNITARIA) +// dell'asse di simmetria e dal versore della direzione del moto. +double +CylSegmentLeakDistOrtMotion( const Point3d& ptSeg, const Point3d& ptCylOrig, + const Vector3d& vtSeg, const Vector3d& vtCylAx, const Vector3d& vtMove, + double dSegLen, double dCylHei, double dCylRad) +{ + // Le variabili fanno rifermiento a un sistema di riferimento + // con origine nel centro del disco nella posizione iniziale. + // X := vtCylAx, Y:= vtMove, Z:= vtCylAx ^ vtMove. + Vector3d vtPlane = vtCylAx ^ vtMove ; + vtPlane.Normalize() ; + Point3d ptSegEnd = ptSeg + dSegLen * vtSeg ; + Vector3d vtSegStart = ptSeg - ptCylOrig ; + Vector3d vtSegEnd = ptSegEnd - ptCylOrig ; + double dCordStart1 = vtSegStart * vtCylAx ; + double dCordEnd1 = vtSegEnd * vtCylAx ; + Vector3d vtSegStart1 = dCordStart1 * vtCylAx ; + Vector3d vtSegEnd1 = dCordEnd1 * vtCylAx ; + Vector3d vtSegStart23 = vtSegStart - vtSegStart1 ; + Vector3d vtSegEnd23 = vtSegEnd - vtSegEnd1 ; + // Se entrambi gli estremi del segmento sono a un lato + // del cilindro non vi può essere interferenza. + double dCordStart2 = vtSegStart23 * vtPlane ; + double dCordEnd2 = vtSegEnd23 * vtPlane ; + if ( ( dCordStart2 > dCylRad && dCordEnd2 > dCylRad) || + ( dCordStart2 < - dCylRad && dCordEnd2 < - dCylRad)) + return 0. ; + // Verifico la distanza di fuga di superficie laterale e dischi di base e fondo. + double dBaseLeakDist = DiskSegmentLeakDistOrtMot( ptSeg, ptCylOrig, vtSeg, vtCylAx, + vtMove, dSegLen, dCylRad) ; + double dBottomLeakDist = DiskSegmentLeakDistOrtMot( ptSeg, ptCylOrig - dCylHei * vtCylAx, + vtSeg, vtCylAx, vtMove, dSegLen, dCylRad) ; + + double dSurfLeakDist = - DBL_MAX ; + if ( ( dCordStart1 < 0. && dCordStart1 > - dCylHei) || + ( dCordEnd1 < 0. && dCordEnd1 > - dCylHei)) { + // Se il vettore del segmento è parallelo all'asse del cilindro, + // il suo prodotto vettoriale con il versore dell'asse è nullo. + Vector3d vtRad = vtCylAx ^ vtSeg ; + if ( ! vtRad.Normalize()) { + dSurfLeakDist = max( ( ptSeg - ptCylOrig) * vtMove, 0.) ; + } + // Se il versore radiale NON è ortogonale a quello di movimento può esserci tangenza, + // altrimenti il versore del segmento non ha componenti ortogonali al piano + // generato da asse cilindro e moto e non può esserci tangenza. + else if ( ! ( abs( vtRad * vtMove) < EPS_SMALL)) { + // Nella posizione finale il cilindro e la retta del segmento sono tangenti. + // Vettore che spicca dal punto di tangenza fra cilindro e retta + // associata al segmento e termina sull'asse del cilindro. + vtRad *= dCylRad ; + // Lunghezza della componente del vettore radiale ortogonale alla linea di movimento + double dDotRemRad = abs( vtRad * vtMove) ; + double dOrtLen = sqrt( max( dCylRad * dCylRad - dDotRemRad * dDotRemRad, 0.)) ; + // Cerco lungo la retta un punto che stia nel segmento e abbia distanza dal piano + // abbia distanza dal piano +/- dOrtLen. + Vector3d vtPlane = vtMove ^ vtCylAx ; + vtPlane.Normalize() ; + Vector3d vtD = ptSeg - ptCylOrig ; + double dDotPlaneD = vtD * vtPlane ; + double dDotPlaneSeg = vtSeg * vtPlane ; + double dPlusU = ( dOrtLen - dDotPlaneD) / dDotPlaneSeg ; + double dMinusU = ( - dOrtLen - dDotPlaneD) / dDotPlaneSeg ; + Point3d ptTanPlus = ptSeg + dPlusU * vtSeg ; + Point3d ptTanMinus = ptSeg + dMinusU * vtSeg ; + double dTanCordPlus1 = ( ptTanPlus - ptCylOrig) * vtCylAx ; + double dTanCordMinus1 = ( ptTanMinus - ptCylOrig) * vtCylAx ; + if ( ( dPlusU > - EPS_SMALL && dPlusU < dSegLen + EPS_SMALL) && + ( dTanCordPlus1 < 0 && dTanCordPlus1 > - dCylHei)) { + dSurfLeakDist = max( ( ( ptSeg - ptCylOrig) + dPlusU * vtSeg) * vtMove + dDotRemRad, 0.) ; + } + if ( dMinusU > - EPS_SMALL && dMinusU < dSegLen + EPS_SMALL && + ( dTanCordMinus1 < 0 && dTanCordMinus1 > - dCylHei)) { + double dNewDist = max( ( ( ptSeg - ptCylOrig) + dMinusU * vtSeg) * vtMove + dDotRemRad, 0.) ; + dSurfLeakDist = max( dNewDist, dSurfLeakDist) ; + } + } + } + return max( max( dBaseLeakDist, dBottomLeakDist), max( dSurfLeakDist, 0.)) ; +} + +//---------------------------------------------------------------------------- +// Restituisce la distanza di allontanamento di un disco, che trasla ortogonalmente al suo asse +// di simmetria, da un piano. +// Il disco è descritto dal suo raggio. Il moto è descritto dal centro nella posizione +// iniziale, dal versore (NORMA UNITARIA) dell'asse di simmetria del disco e dal versore +// della direzione del moto. +double +DiskPlaneLeakDistOrtMot( const Triangle3d& trTria, const Point3d& ptDiscOrig, const Vector3d& vtDiscAx, + const Vector3d& vtMotion, double dCylRad, Point3d& ptContact) +{ + Vector3d vtLine = trTria.GetN() ^ vtDiscAx ; + if ( vtLine.Normalize() && abs( vtMotion * vtLine) < 1 - EPS_ZERO) { + // Definisco l'equazione + DBLVECTOR vdCoef( 3) ; + DBLVECTOR vdRoots ; + double dP = ( trTria.GetP( 0) - ptDiscOrig) * trTria.GetN() / ( vtMotion * trTria.GetN()) ; + Point3d ptLine = ptDiscOrig + dP * vtMotion ; + Vector3d vtMotOrt = vtMotion - vtMotion * vtLine * vtLine ; + Vector3d vtDist = ptLine - ptDiscOrig ; + Vector3d vtDistOrt = vtDist - vtDist * vtLine * vtLine ; + // Setto i coefficienti dell'equazione + vdCoef[0] = vtDistOrt.SqLen() - dCylRad * dCylRad ; + vdCoef[1] = - 2 * vtMotOrt * vtDistOrt ; + vdCoef[2] = vtMotOrt.SqLen() ; + // Risolvo l'equazione + int nRoot = PolynomialRoots( 2, vdCoef, vdRoots) ; + // Studio le soluzioni + double dLeakDist = - DBL_MAX ; + for ( int nS = 0 ; nS < nRoot ; ++ nS) { + if ( dLeakDist < vdRoots[nS]) { + double dLinePar = vdRoots[nS] * vtMotion * vtLine - vtDist * vtLine ; + ptContact = ptLine + dLinePar * vtLine ; + dLeakDist = vdRoots[nS] ; + } + } + return max( dLeakDist, 0.) ; + } + return 0. ; +} + +// FUNZIONI GEOMETRICHE DI BASE PER IL CALCOLO DELLA DISTANZA DI ALLONTANAMENTO + +//---------------------------------------------------------------------------- +// Dati un punto e una retta, restituisce il quadrato della loro distanza. +// La retta è descritta da un suo punto e dal suo versore tangente. +double +GetPointLineSqDist( const Point3d& ptP, const Point3d& ptLine, const Vector3d& vtLine) +{ + return ( ( ptP - ptLine) - ( ptP - ptLine) * vtLine * vtLine).SqLen() ; +} + +//---------------------------------------------------------------------------- +// Dati un punto e un piano, ne restituisce la distanza con segno. +// Il piano è descritto da un suo punto e dal suo versore normale. +double +PointPlaneSignedDist( const Point3d& ptP, const Point3d& ptPlane, const Vector3d& vtNorm) +{ + return ( ptP - ptPlane) * vtNorm ; +} + +//---------------------------------------------------------------------------- +// Dati un sistema di tre punti e un piano, ne calcola le tre distanze con segno e ne restituisce la +// maggiore. I tre punti sono passati mediante un triangolo, il piano è descritto da un suo punto e +// dal suo versore normale. +double +ThreePointPlaneSignedDist( const Triangle3d& trTria, const Point3d& ptPlane, const Vector3d& vtNorm) +{ + double dMaxSgnDist = - INFINITO ; + for ( int nV = 0 ; nV < 3 ; ++ nV) { + double dCurrSgnDist = PointPlaneSignedDist( trTria.GetP( nV), ptPlane, vtNorm) ; + if ( dCurrSgnDist > dMaxSgnDist) + dMaxSgnDist = dCurrSgnDist ; + } + return dMaxSgnDist ; +} + +//---------------------------------------------------------------------------- +// Dati un piano, descritto da un suo punto e dal versore normale, +// e una retta, descritta da un suo punto e dal versore direzione, +// e un numero reale d, determina se esiste un punto sulla retta che ha distanza con +// segno d dal piano. I casi possibili sono: +// Nessun punto dista d dal piano (retta parallela al piano con distanza diversa da d), +// viene restituito 0 e il valore di dPar non ha senso. +// Un solo punto dista d dal piano (retta non parallela al piano), viene restituito 1 +// e il valore di dPar è il parametro del punto sulla retta. +// Tutti i punti distano d dal piano (retta parallela al piano con distanza d), viene +// restituito 2 e qualunque valore di dPar ha senso. +int +LinePlaneDDistPar( const Point3d& ptPlane, const Vector3d& vtPlane, const Point3d& ptLine, const Vector3d& vtLine, + double dDist, double& dPar) +{ + // Vettore congiungente il punto del piano con il punto iniziale della retta + Vector3d vtPlLn = ptLine - ptPlane ; + // Distanza con segno del punto iniziale della retta dal piano + double dSgnDist0 = vtPlLn * vtPlane ; + // Prodotto scalare fra versore della direzione della retta e versore normale al piano + double dDotDirNorm = vtLine * vtPlane ; + // Retta parallela al piano + if ( abs( dDotDirNorm) < EPS_ZERO) { + if ( abs( dSgnDist0 - dDist) < EPS_SMALL) + return 2 ; + else + return 0 ; + } + // Caso generale + else { + dPar = ( dDist - dSgnDist0) / dDotDirNorm ; + return 1 ; + } +} + +//---------------------------------------------------------------------------- +// Date due rette nello spazio restituisce il quadrato della loro distanza. +// Le rette vengono descritte da punto di passaggio e versore direzione. +double +LineLineSqDist( const Point3d& ptP1, const Vector3d& vtD1, const Point3d& ptP2, const Vector3d& vtD2) +{ + // Caso di rette parallele + if ( abs( 1. - abs( vtD1 * vtD2)) < EPS_SMALL) + return ( ( ptP2 - ptP1) - ( ptP2 - ptP1) * vtD1 * vtD1).SqLen() ; + // Caso generale + else { + Vector3d vtOrtD2 = vtD2 - vtD2 * vtD1 * vtD1 ; + Vector3d vtOrtP1P2 = ( ptP2 - ptP1) - ( ptP2 - ptP1) * vtD1 * vtD1 ; + double dD = ( vtOrtD2 * vtOrtP1P2) / vtOrtP1P2.SqLen() ; + return vtOrtP1P2.SqLen() + dD * dD * vtOrtD2.SqLen() + 2 * dD * vtOrtD2 * vtOrtP1P2 ; + } +} + +//---------------------------------------------------------------------------- +// Data una retta e un segmento, ne restituisce il quadrato della distanza. +// La retta è descritta da un qualsiasi punto ad essa appartenente e un versore +// che ne identifica la direzione. Il segmento è descritto da un suo estremo, +// dal versore direzione diretto verso l'altro estremo e dalla sua lunghezza. +double +LineSegmentSqDist( const Point3d& ptPLn, const Vector3d& vtDLn, + const Point3d& ptPSg, const Vector3d& vtDSg, double dSgLen) +{ + // Caso di parallelismo + if ( AreSameOrOppositeVectorApprox( vtDLn, vtDSg)) + return ( ( ptPSg - ptPLn) - ( ptPSg - ptPLn) * vtDLn * vtDLn).SqLen() ; + // Caso generale + else { + double dDLn = ( ptPSg - ptPLn) * vtDLn ; + double dDSg = ( ptPSg - ptPLn) * vtDSg ; + double dDLnSg = vtDLn * vtDSg ; + // posizione parametrica del punto sul segmento + double dSgPar = ( dDLn * dDLnSg - dDSg) / ( 1. - dDLnSg * dDLnSg) ; + // se prima dell'inizio, è distanza dell'inizio dalla linea + if ( dSgPar <= 0.) + return GetPointLineSqDist( ptPSg, ptPLn, vtDLn) ; + // se dopo fine, è distanza fine dalla linea + else if ( dSgPar >= dSgLen) + return GetPointLineSqDist( ptPSg + dSgLen * vtDSg, ptPLn, vtDLn) ; + // altrimenti, determino i due punti a minima distanza + else { + double dLnPar = ( dDLn - dDSg * dDLnSg) / ( 1. - dDLnSg * dDLnSg) ; + Point3d ptMinLn = ptPLn + dLnPar * vtDLn ; + Point3d ptMinSg = ptPSg + dSgPar * vtDSg ; + return SqDist( ptMinLn, ptMinSg) ; + } + } +} + +//---------------------------------------------------------------------------- +// Stabilisce se un punto appartiene a un triangolo interno o frontiera. +bool +IsPointInsideTriangle( const Point3d& ptP, const Triangle3d& trTria) +{ + // Se il punto non sta sul piano del triangolo ho finito + if ( abs( ( ptP - trTria.GetP( 0)) * trTria.GetN()) > EPS_SMALL) + return false ; + + // Vettori dei lati normalizzati + Vector3d vtV0 = trTria.GetP( 1) - trTria.GetP( 0) ; + vtV0.Normalize() ; + Vector3d vtV1 = trTria.GetP( 2) - trTria.GetP( 1) ; + vtV1.Normalize() ; + Vector3d vtV2 = trTria.GetP( 0) - trTria.GetP( 2) ; + vtV2.Normalize() ; + + // E' sufficiente che il segno di un prodotto misto sia negativo per essere fuori + double dProd0 = ( vtV0 ^ ( ptP - trTria.GetP( 0))) * trTria.GetN() ; + if ( dProd0 < - EPS_SMALL) + return false ; + double dProd1 = ( vtV1 ^ ( ptP - trTria.GetP( 1))) * trTria.GetN() ; + if ( dProd1 < - EPS_SMALL) + return false ; + double dProd2 = ( vtV2 ^ ( ptP - trTria.GetP( 2))) * trTria.GetN() ; + if ( dProd2 < - EPS_SMALL) + return false ; + + return true ; +} + +//---------------------------------------------------------------------------- +// Date due rette, descritte da un punto e un vettore direzione, +// trova i parametri corrispondenti ai punti di minima distanza. +// Se le rette non sono parallele abbiamo una singola coppia di +// punti e viene restituito true, altrimenti ne abbiamo infinite +// e viene restituito false. Si noti che i parametri dU1, dU2 +// non hanno necessariamente il significato di lunghezza; +// perché non è richiesto che i vettori siano normalizzati. +bool +FindMinDistPar( const Point3d& ptL1, const Point3d& ptL2, + const Vector3d& vtV1, const Vector3d& vtV2, + double& dU1, double& dU2) +{ + // Se le rette sono parallele + if ( abs( abs( vtV1 * vtV2) - 1) < EPS_ZERO) + return false ; + + // Vettore congiungente i punti iniziali + Vector3d vtD = ptL2 - ptL1 ; + // Proiezioni di vtD sui versori direzione + double dD1 = vtD * vtV1 ; + double dD2 = vtD * vtV2 ; + // Prodotto scalare fra i versori direzione + double dV = vtV1 * vtV2 ; + + // Se le rette sono perpendicolari + if ( abs( vtV1 * vtV2) < EPS_ZERO) { + dU1 = dD1 ; + dU2 = - dD2 ; + } + // Caso generale + else { + dU1 = ( dD1 - dD2 * dV) / ( 1 - dV * dV) ; + dU2 = ( - dD2 + dD1 * dV) / ( 1 - dV * dV) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +// Calcolo delle posizioni di tangenza di una sfera che si muove dalla posizione +// originale lungo una direzione prefissata rispetto ad una retta. +// Le posizioni sono rappresentate dalla distanza percorsa. +// Il parametro di ritorno può assumere i seguenti valori : +// 0 : la sfera non è mai tangente alla retta; dU1 e dU2 non hanno senso +// 1 : la sfera è tangente alla retta in una posizione; solo dU1 ha senso +// 2 : la sfera è tangente alla retta in due posizioni; dU1 e dU2 valide +// 3 : la sfera è sempre tangente +int +SphereLineTangentPoints( const Point3d& ptSpheCen, double dSpheRad, + const Point3d& ptSeg, const Vector3d& vtSegDir, double dSegLen, + const Vector3d& vtMove, double& dU1, double& dU2) +{ + // Definisco l'equazione + Vector3d vtMotOrt = vtMove - vtMove * vtSegDir * vtSegDir ; + Vector3d vtLineSeg = ptSeg - ptSpheCen ; + Vector3d vtLineSegOrt = vtLineSeg - vtLineSeg * vtSegDir * vtSegDir ; + // Setto i coefficienti dell'equazione + DBLVECTOR vdCoeff( 3) ; + vdCoeff[0] = vtLineSegOrt.SqLen() - dSpheRad * dSpheRad ; + vdCoeff[1] = - 2 * vtMotOrt * vtLineSegOrt ; + vdCoeff[2] = vtMotOrt.SqLen() ; + if ( vdCoeff[2] < EPS_ZERO * EPS_ZERO) { + if ( abs( vdCoeff[0]) < EPS_SMALL) + return 3 ; + else + return 0 ; + } + // Risolvo l'equazione + DBLVECTOR vdRoots ; + int nRoots = PolynomialRoots( 2, vdCoeff, vdRoots) ; + // Studio le soluzioni + if ( nRoots == 1) + dU1 = vdRoots[0] ; + else if ( nRoots == 2) { + dU1 = min( vdRoots[0], vdRoots[1]) ; + dU2 = max( vdRoots[0], vdRoots[1]) ; + } + return nRoots ; +} + + + + + diff --git a/CAvToolTriangle.h b/CAvToolTriangle.h new file mode 100644 index 0000000..7f2c91d --- /dev/null +++ b/CAvToolTriangle.h @@ -0,0 +1,72 @@ +//---------------------------------------------------------------------------- +// EgalTech 2018-2018 +//---------------------------------------------------------------------------- +// File : CAvToolTriangle.h Data : 27.04.18 Versione : 1.9e1 +// Contenuto : Dichiarazione delle funzioni del modulo CAvToolTriangle. +// +// +// +// Modifiche : 10.03.18 LM Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +#pragma once + +#include "Tool.h" +#include "/EgtDev/Include/EGkTriangle3d.h" + +double CAvToolTriangle( const Tool& tlTool, const Point3d& ptToolOrig, const Vector3d& vtToolAx, + const Triangle3d& trTria, const Vector3d& vtMove) ; + +// Componenti: +// Sfera +double CAvSphereTriangle( const Point3d& ptSpheCen, double dSpheRad, const Triangle3d& trTria, const Vector3d& vtMove) ; +double SpherePlaneLeakDist( const Point3d& ptSpheCen, double dSpheRad, + const Point3d& ptPlane, const Vector3d& vtPlaneN, const Vector3d& vtMove) ; +double SphereSegmentLeakDist( const Point3d& ptSpheCen, double dSpheRad, + const Point3d& ptSeg, const Vector3d& vtSegDir, double dSegLen, + const Vector3d& vtMove) ; +double SpherePointLeakDist( const Point3d& ptSpheCen, double dSpheRad, const Point3d ptP, const Vector3d& vtMove) ; +// Cilindro +double CAvCylinderTriangle( const Point3d& ptCompOrig, const Vector3d& vtCompAx, double dHeigth, double dRad, + const Triangle3d& trTria, const Vector3d& vtMove) ; +double DiskSegmentLeakDistLongMotion( const Point3d& ptDisk, const Vector3d& vtDiscLeak, double dDiscRad, + const Point3d& ptSeg, const Vector3d& vtSeg, double dSegLen) ; +double DiskTriaInteriorLeakDistLongMot( const Point3d& ptDisk, const Vector3d& vtDiskAx, double dDiskRad, + const Triangle3d& trTria) ; +double CylPointLeakDistOrtMotion( const Point3d& ptP, const Point3d& ptCompOrig, + const Vector3d& vtCylAx, const Vector3d& vtRemDir, + double dCylHei, double dCylRad) ; +double DiskSegmentLeakDistOrtMot( const Point3d& ptSeg, const Point3d& ptDiscOrig, + const Vector3d& vtSeg, const Vector3d& vtDiscAx, const Vector3d& vtRemDir, + double dSegLen, double dDiscRad) ; +double CylSegmentLeakDistOrtMotion( const Point3d& ptSeg, const Point3d& ptCylOrig, + const Vector3d& vtSeg, const Vector3d& vtCylAx, const Vector3d& vtRemDir, + double dSegLen, double dCylHei, double dCylRad) ; +double DiskPlaneLeakDistOrtMot( const Triangle3d& trTria, const Point3d& ptDiscOrig, const Vector3d& vtDiscAx, + const Vector3d& vtMotion, double dCylRad, Point3d& ptContact) ; +// Funzioni geometriche di base +double GetPointLineSqDist( const Point3d& ptP, const Point3d& ptLine, const Vector3d& vtLine) ; +double PointPlaneSignedDist( const Point3d& ptP, const Point3d& ptPlane, const Vector3d& vtNorm) ; +double ThreePointPlaneSignedDist( const Triangle3d& trTria, const Point3d& ptPlane, const Vector3d& vtNorm) ; +int LinePlaneDDistPar( const Point3d& ptPlane, const Vector3d& vtPlane, const Point3d& ptLine, const Vector3d& vtLine, + double dDist, double& dPar) ; +double LineLineSqDist( const Point3d& ptP1, const Vector3d& vtD1, const Point3d& ptP2, const Vector3d& vtD2) ; +double LineSegmentSqDist( const Point3d& ptPLn, const Vector3d& vtDLn, + const Point3d& ptPSg, const Vector3d& vtDSg, double dSgLen) ; +bool IsPointInsideTriangle( const Point3d& ptP, const Triangle3d& trTria) ; +bool FindMinDistPar( const Point3d& ptL1, const Point3d& ptL2, + const Vector3d& vtV1, const Vector3d& vtV2, + double& dU1, double& dU2) ; +int SphereLineTangentPoints( const Point3d& ptSpheCen, double dSpheRad, + const Point3d& ptSeg, const Vector3d& vtSegDir, double dSegLen, + const Vector3d& vtMove, double& dU1, double& dU2) ; + + + + + + + + \ No newline at end of file diff --git a/CDBoxPolyhedron.cpp b/CDeBoxPolyhedron.cpp similarity index 83% rename from CDBoxPolyhedron.cpp rename to CDeBoxPolyhedron.cpp index d06305d..f6a4c5d 100644 --- a/CDBoxPolyhedron.cpp +++ b/CDeBoxPolyhedron.cpp @@ -13,14 +13,14 @@ //--------------------------- Include ---------------------------------------- #include "stdafx.h" -#include "/EgtDev/Include/EGkCDBoxTria.h" -#include "/EgtDev/Include/EGkCDBoxPolyhedron.h" +#include "/EgtDev/Include/EGkCDeBoxTria.h" +#include "/EgtDev/Include/EGkCDeBoxPolyhedron.h" using namespace std ; //---------------------------------------------------------------------------- bool -CDBoxPolyhedron( const BBox3d& b3Box, const ISurfTriMesh& Stm) +CDeBoxPolyhedron( const BBox3d& b3Box, const ISurfTriMesh& Stm) { // verifico che la trimesh sia effettivamente un poliedro if ( ! Stm.IsClosed()) @@ -36,7 +36,7 @@ CDBoxPolyhedron( const BBox3d& b3Box, const ISurfTriMesh& Stm) Triangle3d Tria ; int nId = Stm.GetFirstTriangle( Tria) ; while ( nId != SVT_NULL) { - if ( CDBoxTria( b3Box, Tria)) + if ( CDeBoxTria( b3Box, Tria)) return true ; nId = Stm.GetNextTriangle( nId, Tria) ; } diff --git a/CDBoxTria.cpp b/CDeBoxTria.cpp similarity index 92% rename from CDBoxTria.cpp rename to CDeBoxTria.cpp index bf32aa0..f146e2a 100644 --- a/CDBoxTria.cpp +++ b/CDeBoxTria.cpp @@ -1,7 +1,7 @@ //---------------------------------------------------------------------------- -// EgalTech 2016-2016 +// EgalTech 2016-2018 //---------------------------------------------------------------------------- -// File : CDBoxTria.cpp Data : 05.10.16 Versione : 1.6v1 +// File : CDeBoxTria.cpp Data : 28.04.18 Versione : 1.9e1 // Contenuto : Implementazione della verifica di collisione tra // BoundingBox e Triangle3d. // @@ -13,14 +13,14 @@ //--------------------------- Include ---------------------------------------- #include "stdafx.h" -#include "/EgtDev/Include/EGkCDBoxTria.h" +#include "/EgtDev/Include/EGkCDeBoxTria.h" #include "/EgtDev/Include/EGkPlane3d.h" using namespace std ; //-------------------------------------------------------------------------------- static bool -CDBoxPlane( const BBox3d& Box, const Plane3d& Plane) +CDeBoxPlane( const BBox3d& Box, const Plane3d& Plane) { // vedi Ericson, Real-Time Collision Detection, pag. 164 @@ -90,7 +90,7 @@ CDBoxPlane( const BBox3d& Box, const Plane3d& Plane) //---------------------------------------------------------------------------- bool -CDBoxTria( const BBox3d& b3Box, const Triangle3d& trTria) +CDeBoxTria( const BBox3d& b3Box, const Triangle3d& trTria) { // vedi Ericson, Real-Time Collision Detection, pag. 172 + Akenine-Moller @@ -149,5 +149,5 @@ CDBoxTria( const BBox3d& b3Box, const Triangle3d& trTria) // Test separating axis corresponding to triangle face normal (category 2) Plane3d Plane ; Plane.Set( trTria.GetP( 0), trTria.GetN()) ; - return CDBoxPlane( b3Box, Plane) ; + return CDeBoxPlane( b3Box, Plane) ; } diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 21ef669b63dbedb11607cf72b244c10b55c4ab59..cd62d3fec17bc1977f53deb83728a36e84fda52c 100644 GIT binary patch delta 118 zcmdlNy)SyhH#SyN1|0^&&A-{?nVC}=3@0mc>u&bq>S2M3-{!MM7I$OZ+#~G9j8n2h Q8ZL=uq6g#VEaea`09ZC23IG5A delta 118 zcmdlNy)SyhH#Sxi1|0_D&A-{?nVC}u&bq>S2M3-{!MM7I$OZ+#~G9j8n2h Q8ZL=uq6g#VEaea`09p(l5&!@I diff --git a/EgtGeomKernel.vcxproj b/EgtGeomKernel.vcxproj index 0fb9680..849934a 100644 --- a/EgtGeomKernel.vcxproj +++ b/EgtGeomKernel.vcxproj @@ -258,8 +258,11 @@ copy $(TargetPath) \EgtProg\Dll64 - - + + + + + @@ -269,6 +272,7 @@ copy $(TargetPath) \EgtProg\Dll64 + @@ -336,7 +340,6 @@ copy $(TargetPath) \EgtProg\Dll64 - @@ -378,9 +381,10 @@ copy $(TargetPath) \EgtProg\Dll64 - - - + + + + @@ -467,6 +471,8 @@ copy $(TargetPath) \EgtProg\Dll64 + + @@ -504,11 +510,13 @@ copy $(TargetPath) \EgtProg\Dll64 + + @@ -519,6 +527,7 @@ copy $(TargetPath) \EgtProg\Dll64 + diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters index 371b337..d962bf8 100644 --- a/EgtGeomKernel.vcxproj.filters +++ b/EgtGeomKernel.vcxproj.filters @@ -330,15 +330,6 @@ File di origine\GeoOffset - - File di origine\GeoCollision - - - File di origine\GeoCollision - - - File di origine\GeoCollision - File di origine\GeoInters @@ -375,6 +366,24 @@ File di origine\GeoInters + + File di origine\GeoInters + + + File di origine\GeoCollision + + + File di origine\GeoCollision + + + File di origine\GeoCollision + + + File di origine\GeoCollision + + + File di origine\GeoCollision + @@ -782,15 +791,6 @@ File di intestazione\Include - - File di intestazione\Include - - - File di intestazione\Include - - - File di intestazione\Include - File di intestazione\Include @@ -857,6 +857,33 @@ File di intestazione + + File di intestazione + + + File di intestazione + + + File di intestazione + + + File di intestazione + + + File di intestazione + + + File di intestazione\Include + + + File di intestazione\Include + + + File di intestazione\Include + + + File di intestazione\Include + diff --git a/GdbExecutor.cpp b/GdbExecutor.cpp index 9778de7..242b298 100644 --- a/GdbExecutor.cpp +++ b/GdbExecutor.cpp @@ -19,6 +19,10 @@ #include "GeoConst.h" #include "GeomDB.h" #include "DllMain.h" +#include "VolZmap.h" +#include "IntersLineSurfStd.h" +#include "CAvToolTriangle.h" +#include "CurveArc.h" #include "/EgtDev/Include/EGkStringUtils3d.h" #include "/EgtDev/Include/EGkGeoPoint3d.h" #include "/EgtDev/Include/EGkGeoVector3d.h" @@ -47,7 +51,7 @@ #include "/EgtDev/Include/EGnCmdParser.h" #include "/EgtDev/Include/EgtStringConverter.h" #include "/EgtDev/Include/EgtPointerOwner.h" -#include "VolZmap.h" + using namespace std ; @@ -96,6 +100,8 @@ GdbExecutor::GdbExecutor( void) m_ExecMgr.Insert( "STM", &GdbExecutor::ExecuteSurfTriMesh) ; m_ExecMgr.Insert( "SURFTRIMESH", &GdbExecutor::ExecuteSurfTriMesh) ; // m_ExecMgr.Insert( "VOLZMAP", &GdbExecutor::ExecuteVolZmap) ; + m_ExecMgr.Insert( "INTERSECTION", &GdbExecutor::ExecuteIntersection) ; + m_ExecMgr.Insert( "AVOID", &GdbExecutor::ExecuteToolAvoidTriangle) ; m_ExecMgr.Insert( "TEXT", &GdbExecutor::ExecuteText) ; m_ExecMgr.Insert( "LEV", &GdbExecutor::ExecuteLevel) ; m_ExecMgr.Insert( "LEVEL", &GdbExecutor::ExecuteLevel) ; @@ -2912,6 +2918,2010 @@ GdbExecutor::VolZmapBBoxZmapIntersection( const STRVECTOR& vsParams) return true ; }*/ +//---------------------------------------------------------------------------- +bool +GdbExecutor::ExecuteIntersection( const std::string& sCmd2, const STRVECTOR& vsParams) +{ + if ( sCmd2 == "LINEDISC") + return LineDiscInters( vsParams) ; + else if ( sCmd2 == "RAYDISC") + return RayDiscInters( vsParams) ; + else if ( sCmd2 == "SEGMENTDISC") + return SegmentDiscInters( vsParams) ; + else if ( sCmd2 == "LINESPHERE") + return LineSphereInters( vsParams) ; + else if ( sCmd2 == "RAYSPHERE") + return RaySphereInters( vsParams) ; + else if ( sCmd2 == "SEGMENTSPHERE") + return SegmentSphereInters( vsParams) ; + else if ( sCmd2 == "LINESEMISPHERE") + return LineSemiSphereInters( vsParams) ; + else if ( sCmd2 == "RAYSEMISPHERE") + return RaySemiSphereInters( vsParams) ; + else if ( sCmd2 == "SEGMENTSEMISPHERE") + return SegmentSemiSphereInters( vsParams) ; + else if ( sCmd2 == "LINCOMPSEMISPHERE") + return LinCompSemiSphereInters( vsParams) ; + else if ( sCmd2 == "LINEINFINITECYLINDER") + return LineInfiniteCylinderInters( vsParams) ; + else if ( sCmd2 == "RAYINFINITECYLINDER") + return RayInfiniteCylinderInters( vsParams) ; + else if ( sCmd2 == "SEGMENTINFINITECYLINDER") + return SegmentInfiniteCylinderInters( vsParams) ; + else if ( sCmd2 == "SEGMENTCYL") + return SegmentCylinderInters( vsParams) ; + else if ( sCmd2 == "SEGMENTCONE") + return SegmentConeInters( vsParams) ; + else if ( sCmd2 == "LINETRUNCONE") + return LineTruncateConeInters( vsParams) ; + else if ( sCmd2 == "RAYTRUNCONE") + RayTruncateConeInters( vsParams) ; + else if ( sCmd2 == "SEGMENTTRUNCONE") + return SegmentTruncateConeInters( vsParams) ; + else if ( sCmd2 == "LINETORUS") + return LineTorusInters( vsParams) ; + else if ( sCmd2 == "RAYTORUS") + return RayTorusInters( vsParams) ; + else if ( sCmd2 == "SEGMENTTORUS") + return SegmentTorusInters( vsParams) ; + else if ( sCmd2 == "LINCOMPTORUSPART") + return LinCompTorusPartInters( vsParams) ; + return false ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::LineDiscInters( const STRVECTOR& vsParams) +{ // parametri : Id, IdParent, ptDisc, ptLine, vtDisc, vtLine, dRad + if ( vsParams.size() < 7) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frRef ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef)) + return false ; + // recupero centro del disco + Point3d ptDisc ; + if ( ! GetPointParam( vsParams[2], frRef, ptDisc)) + return false ; + // recupero punto retta + Point3d ptLine ; + if ( ! GetPointParam( vsParams[3], frRef, ptLine)) + return false ; + // recupero vettore disco + Vector3d vtDisc ; + if ( ! GetVectorParam( vsParams[4], frRef, vtDisc)) + return false ; + vtDisc.Normalize() ; + // recupero vettore retta + Vector3d vtLine ; + if ( ! GetVectorParam( vsParams[5], frRef, vtLine)) + return false ; + vtLine.Normalize() ; + // recupero raggio disco + double dRadius ; + if ( ! FromString( vsParams[6], dRadius)) + return false ; + + double dU1, dU2 ; + int nIntType = LineDisc( ptDisc, ptLine, vtDisc, vtLine, dRadius, dU1, dU2) ; + + Point3d ptPS = ptLine + dU1 * vtLine ; + Point3d ptPE = ptLine + dU2 * vtLine ; + + if ( nIntType == D_ERROR_INT) + return false ; + if ( nIntType == D_NO_INTERS) + int nSol = 0 ; + if ( nIntType == D_BOUNDARY_INT_LINE_NOT_IN_PLANE) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - vtLine, ptPS + vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nIntType == D_INNER_INT_LINE_NOT_IN_PLANE) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - 3 * vtLine, ptPS + 3 * vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nIntType == D_ONE_INT_LINE_ON_PLANE) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - 5 * vtLine, ptPS + 5 * vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nIntType == D_INFINITE_INT_LINE_ON_PLANE) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS, ptPE) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::RayDiscInters( const STRVECTOR& vsParams) +{ // parametri : Id, IdParent, ptDisc, ptLine, vtDisc, vtLine, dRad + if ( vsParams.size() < 7) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frRef ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef)) + return false ; + // recupero centro del disco + Point3d ptDisc ; + if ( ! GetPointParam( vsParams[2], frRef, ptDisc)) + return false ; + // recupero punto retta + Point3d ptLine ; + if ( ! GetPointParam( vsParams[3], frRef, ptLine)) + return false ; + // recupero vettore disco + Vector3d vtDisc ; + if ( ! GetVectorParam( vsParams[4], frRef, vtDisc)) + return false ; + vtDisc.Normalize() ; + // recupero vettore retta + Vector3d vtLine ; + if ( ! GetVectorParam( vsParams[5], frRef, vtLine)) + return false ; + vtLine.Normalize() ; + // recupero raggio disco + double dRadius ; + if ( ! FromString( vsParams[6], dRadius)) + return false ; + + double dU1, dU2 ; + int nIntType = RayDisc( ptDisc, ptLine, vtDisc, vtLine, dRadius, dU1, dU2) ; + + Point3d ptPS = ptLine + dU1 * vtLine ; + Point3d ptPE = ptLine + dU2 * vtLine ; + + if ( nIntType == D_ERROR_INT) + return false ; + if ( nIntType == D_NO_INTERS) + int nSol = 0 ; + if ( nIntType == D_BOUNDARY_INT_LINE_NOT_IN_PLANE) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - vtLine, ptPS + vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nIntType == D_INNER_INT_LINE_NOT_IN_PLANE) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - 3 * vtLine, ptPS + 3 * vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nIntType == D_ONE_INT_LINE_ON_PLANE) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - 5 * vtLine, ptPS + 5 * vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nIntType == D_INFINITE_INT_LINE_ON_PLANE) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS, ptPE) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::SegmentDiscInters( const STRVECTOR& vsParams) +{ // parametri : Id, IdParent, ptDisc, ptLine, vtDisc, vtLine, dRad, dLen + if ( vsParams.size() < 7) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frRef ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef)) + return false ; + // recupero centro del disco + Point3d ptDisc ; + if ( ! GetPointParam( vsParams[2], frRef, ptDisc)) + return false ; + // recupero punto retta + Point3d ptLine ; + if ( ! GetPointParam( vsParams[3], frRef, ptLine)) + return false ; + // recupero vettore disco + Vector3d vtDisc ; + if ( ! GetVectorParam( vsParams[4], frRef, vtDisc)) + return false ; + vtDisc.Normalize() ; + // recupero vettore retta + Vector3d vtLine ; + if ( ! GetVectorParam( vsParams[5], frRef, vtLine)) + return false ; + vtLine.Normalize() ; + // recupero raggio disco + double dRadius ; + if ( ! FromString( vsParams[6], dRadius)) + return false ; + // recupero lunghezza segmento + double dLen ; + if ( ! FromString( vsParams[6], dLen)) + return false ; + + double dU1, dU2 ; + int nIntType = SegmentDisc( ptDisc, ptLine, vtDisc, vtLine, dRadius, dLen, dU1, dU2) ; + + Point3d ptPS = ptLine + dU1 * vtLine ; + Point3d ptPE = ptLine + dU2 * vtLine ; + + if ( nIntType == D_ERROR_INT) + return false ; + if ( nIntType == D_NO_INTERS) + int nSol = 0 ; + if ( nIntType == D_BOUNDARY_INT_LINE_NOT_IN_PLANE) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - vtLine, ptPS + vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nIntType == D_INNER_INT_LINE_NOT_IN_PLANE) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - 3 * vtLine, ptPS + 3 * vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nIntType == D_ONE_INT_LINE_ON_PLANE) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - 5 * vtLine, ptPS + 5 * vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nIntType == D_INFINITE_INT_LINE_ON_PLANE) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS, ptPE) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::LineSphereInters( const STRVECTOR& vsParams) +{ // parametri : Id, IdParent, ptC, ptP, vtV, dRad + if ( vsParams.size() < 6) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frRef ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef)) + return false ; + // recupero centro della sfera + Point3d ptC ; + if ( ! GetPointParam( vsParams[2], frRef, ptC)) + return false ; + // recupero punto retta + Point3d ptP ; + if ( ! GetPointParam( vsParams[3], frRef, ptP)) + return false ; + // recupero vettore retta + Vector3d vtV ; + if ( ! GetVectorParam( vsParams[4], frRef, vtV)) + return false ; + vtV.Normalize() ; + // recupero raggio sfera + double dRadius ; + if ( ! FromString( vsParams[5], dRadius)) + return false ; + + double dU1, dU2 ; + int nIntType = LineSphere( ptC, ptP, vtV, dRadius, dU1, dU2) ; + + Point3d ptPS = ptP + dU1 * vtV ; + Point3d ptPE = ptP + dU2 * vtV ; + + if ( nIntType == S_ERROR_INT) + return false ; + if ( nIntType == S_NO_INTERS) + int nSol = 0 ; + if ( nIntType == S_TWO_INT) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS, ptPE) ; + // inserisco nel DB + return AddGeoObj (vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nIntType == S_ONE_INT_TAN) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - vtV, ptPS + vtV) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::RaySphereInters( const STRVECTOR& vsParams) +{ // parametri : Id, IdParent, ptC, ptP, vtV, dRad + if ( vsParams.size() < 6) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frRef ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef)) + return false ; + // recupero centro della sfera + Point3d ptC ; + if ( ! GetPointParam( vsParams[2], frRef, ptC)) + return false ; + // recupero punto retta + Point3d ptP ; + if ( ! GetPointParam( vsParams[3], frRef, ptP)) + return false ; + // recupero vettore retta + Vector3d vtV ; + if ( ! GetVectorParam( vsParams[4], frRef, vtV)) + return false ; + vtV.Normalize() ; + // recupero raggio sfera + double dRadius ; + if ( ! FromString( vsParams[5], dRadius)) + return false ; + + double dU1, dU2 ; + int nIntType = RaySphere( ptC, ptP, vtV, dRadius, dU1, dU2) ; + + Point3d ptPS = ptP + dU1 * vtV ; + Point3d ptPE = ptP + dU2 * vtV ; + + if ( nIntType == S_ERROR_INT) + return false ; + if ( nIntType == S_NO_INTERS) + int nSol = 0 ; + if ( nIntType == S_TWO_INT) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS, ptPE) ; + // inserisco nel DB + return AddGeoObj (vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nIntType == S_ONE_INT_TAN) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - vtV, ptPS + vtV) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nIntType == S_ONE_INT_SEC) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - 3 * vtV, ptPS + 3 * vtV) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::SegmentSphereInters( const STRVECTOR& vsParams) +{ + // parametri : Id, IdParent, ptC, ptP, vtV, dRad, dLen + if ( vsParams.size() < 7) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frRef ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef)) + return false ; + // recupero centro della sfera + Point3d ptC ; + if ( ! GetPointParam( vsParams[2], frRef, ptC)) + return false ; + // recupero punto retta + Point3d ptP ; + if ( ! GetPointParam( vsParams[3], frRef, ptP)) + return false ; + // recupero vettore retta + Vector3d vtV ; + if ( ! GetVectorParam( vsParams[4], frRef, vtV)) + return false ; + vtV.Normalize() ; + // recupero raggio sfera + double dRadius ; + if ( ! FromString( vsParams[5], dRadius)) + return false ; + // recupero lunghezza segmento + double dLen ; + if ( ! FromString( vsParams[6], dLen)) + return false ; + + double dU1, dU2 ; + int nIntType = SegmentSphere( ptC, ptP, vtV, dRadius, dLen, dU1, dU2) ; + + + if ( nIntType == S_ERROR_INT) + return false ; + if ( nIntType == S_NO_INTERS) + int nSol = 0 ; + if ( nIntType == S_TWO_INT) { + Point3d ptPS = ptP + dU1 * vtV ; + Point3d ptPE = ptP + dU2 * vtV ; + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS, ptPE) ; + // inserisco nel DB + return AddGeoObj (vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nIntType == S_ONE_INT_TAN) { + Point3d ptPS = ptP + dU1 * vtV ; + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - vtV, ptPS + vtV) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nIntType == S_ONE_INT_SEC) { + Point3d ptPS = ptP + dU1 * vtV ; + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - 3 * vtV, ptPS + 3 * vtV) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::LineSemiSphereInters( const STRVECTOR& vsParams) +{ + // parametri : Id, IdParent, ptC, ptP, vtSphOr, vtV, dRad + if ( vsParams.size() < 7) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frRef ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef)) + return false ; + // recupero centro della sfera + Point3d ptC ; + if ( ! GetPointParam( vsParams[2], frRef, ptC)) + return false ; + // recupero punto retta + Point3d ptP ; + if ( ! GetPointParam( vsParams[3], frRef, ptP)) + return false ; + // recupero vetore orientazione + Vector3d vtSphOr ; + if ( ! GetVectorParam( vsParams[4], frRef, vtSphOr)) + return false ; + vtSphOr.Normalize() ; + // recupero vettore retta + Vector3d vtV ; + if ( ! GetVectorParam( vsParams[5], frRef, vtV)) + return false ; + vtV.Normalize() ; + // recupero raggio sfera + double dRadius ; + if ( ! FromString( vsParams[6], dRadius)) + return false ; + + double dU1, dU2 ; + int nIntType = LineSemiSphere( ptC, ptP, vtSphOr, vtV, dRadius, dU1, dU2) ; + + Point3d ptPS = ptP + dU1 * vtV ; + Point3d ptPE = ptP + dU2 * vtV ; + + if ( nIntType == S_ERROR_INT) + return false ; + if ( nIntType == S_NO_INTERS) + int nSol = 0 ; + if ( nIntType == S_TWO_INT) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS, ptPE) ; + // inserisco nel DB + return AddGeoObj (vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nIntType == S_ONE_INT_TAN) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - vtV, ptPS + vtV) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::RaySemiSphereInters( const STRVECTOR& vsParams) +{ + // parametri : Id, IdParent, ptC, ptP, vtSphOr, vtV, dRad + if ( vsParams.size() < 7) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frRef ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef)) + return false ; + // recupero centro della sfera + Point3d ptC ; + if ( ! GetPointParam( vsParams[2], frRef, ptC)) + return false ; + // recupero punto retta + Point3d ptP ; + if ( ! GetPointParam( vsParams[3], frRef, ptP)) + return false ; + // recupero vetore orientazione + Vector3d vtSphOr ; + if ( ! GetVectorParam( vsParams[4], frRef, vtSphOr)) + return false ; + vtSphOr.Normalize() ; + // recupero vettore retta + Vector3d vtV ; + if ( ! GetVectorParam( vsParams[5], frRef, vtV)) + return false ; + vtV.Normalize() ; + // recupero raggio sfera + double dRadius ; + if ( ! FromString( vsParams[6], dRadius)) + return false ; + + double dU1, dU2 ; + int nIntType = RaySemiSphere( ptC, ptP, vtSphOr, vtV, dRadius, dU1, dU2) ; + + Point3d ptPS = ptP + dU1 * vtV ; + Point3d ptPE = ptP + dU2 * vtV ; + + if ( nIntType == S_ERROR_INT) + return false ; + if ( nIntType == S_NO_INTERS) + int nSol = 0 ; + if ( nIntType == S_TWO_INT) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS, ptPE) ; + // inserisco nel DB + return AddGeoObj (vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nIntType == S_ONE_INT_SEC) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - vtV, ptPS + vtV) ; + // inserisco nel DB + return AddGeoObj (vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nIntType == S_ONE_INT_TAN) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - vtV, ptPS + vtV) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::SegmentSemiSphereInters( const STRVECTOR& vsParams) +{ + // parametri : Id, IdParent, ptC, ptP, vtSphOr, vtV, dRad, dLen + if ( vsParams.size() < 8) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frRef ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef)) + return false ; + // recupero centro della sfera + Point3d ptC ; + if ( ! GetPointParam( vsParams[2], frRef, ptC)) + return false ; + // recupero punto retta + Point3d ptP ; + if ( ! GetPointParam( vsParams[3], frRef, ptP)) + return false ; + // recupero vetore orientazione + Vector3d vtSphOr ; + if ( ! GetVectorParam( vsParams[4], frRef, vtSphOr)) + return false ; + vtSphOr.Normalize() ; + // recupero vettore retta + Vector3d vtV ; + if ( ! GetVectorParam( vsParams[5], frRef, vtV)) + return false ; + vtV.Normalize() ; + // recupero raggio sfera + double dRadius ; + if ( ! FromString( vsParams[6], dRadius)) + return false ; + // recupero lunghezza segmento + double dLen ; + if ( ! FromString( vsParams[7], dLen)) + return false ; + + double dU1, dU2 ; + int nIntType = SegmentSemiSphere( ptC, ptP, vtSphOr, vtV, dRadius, dLen, dU1, dU2) ; + + + if ( nIntType == S_ERROR_INT) + return false ; + if ( nIntType == S_NO_INTERS) + int nSol = 0 ; + if ( nIntType == S_TWO_INT) { + Point3d ptPS = ptP + dU1 * vtV ; + Point3d ptPE = ptP + dU2 * vtV ; + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS, ptPE) ; + // inserisco nel DB + return AddGeoObj (vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nIntType == S_ONE_INT_TAN) { + Point3d ptPS = ptP + dU1 * vtV ; + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - vtV, ptPS + vtV) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nIntType == S_ONE_INT_SEC) { + Point3d ptPS = ptP + dU1 * vtV ; + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - 3 * vtV, ptPS + 3 * vtV) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::LinCompSemiSphereInters( const STRVECTOR& vsParams) +{ + // parametri : Id, IdParent, ptC, ptP, vtSphOr, vtV, dRad, dLen, nLinType + if ( vsParams.size() < 9) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frRef ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef)) + return false ; + // recupero centro della sfera + Point3d ptC ; + if ( ! GetPointParam( vsParams[2], frRef, ptC)) + return false ; + // recupero punto retta + Point3d ptP ; + if ( ! GetPointParam( vsParams[3], frRef, ptP)) + return false ; + // recupero vetore orientazione + Vector3d vtSphOr ; + if ( ! GetVectorParam( vsParams[4], frRef, vtSphOr)) + return false ; + vtSphOr.Normalize() ; + // recupero vettore retta + Vector3d vtV ; + if ( ! GetVectorParam( vsParams[5], frRef, vtV)) + return false ; + vtV.Normalize() ; + // recupero raggio sfera + double dRadius ; + if ( ! FromString( vsParams[6], dRadius)) + return false ; + // recupero lunghezza segmento + double dLen ; + if ( ! FromString( vsParams[7], dLen)) + return false ; + int nLinType ; + if ( ! FromString( vsParams[8], nLinType)) + return false ; + + double dU1, dU2 ; + int nIntType = LinCompSemiSphere( ptC, ptP, vtSphOr, vtV, dRadius, dLen, nLinType, dU1, dU2) ; + + if ( nIntType == S_ERROR_INT) + return false ; + if ( nIntType == S_NO_INTERS) + int nSol = 0 ; + if ( nIntType == S_TWO_INT) { + Point3d ptPS = ptP + dU1 * vtV ; + Point3d ptPE = ptP + dU2 * vtV ; + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS, ptPE) ; + // inserisco nel DB + return AddGeoObj (vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nIntType == S_ONE_INT_TAN) { + Point3d ptPS = ptP + dU1 * vtV ; + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - vtV, ptPS + vtV) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nIntType == S_ONE_INT_SEC) { + Point3d ptPS = ptP + dU1 * vtV ; + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - 3 * vtV, ptPS + 3 * vtV) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::LineInfiniteCylinderInters( const STRVECTOR& vsParams) +{ + // parametri : Id, IdParent, ptCyl, ptLine, vtCyl, vtLine, dRad + if ( vsParams.size() < 7) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frRef ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef)) + return false ; + // recupero punto del cilindro + Point3d ptCyl ; + if ( ! GetPointParam( vsParams[2], frRef, ptCyl)) + return false ; + // recupero punto retta + Point3d ptLine ; + if ( ! GetPointParam( vsParams[3], frRef, ptLine)) + return false ; + // recupero vettore cilindro + Vector3d vtCyl ; + if ( ! GetVectorParam( vsParams[4], frRef, vtCyl)) + return false ; + vtCyl.Normalize() ; + // recupero vettore retta + Vector3d vtLine ; + if ( ! GetVectorParam( vsParams[5], frRef, vtLine)) + return false ; + vtLine.Normalize() ; + // recupero raggio cilindro + double dRadius ; + if ( ! FromString( vsParams[6], dRadius)) + return false ; + + double dU1, dU2 ; + int nTypeInt = LineInfiniteCylinder( ptCyl, ptLine, vtCyl, vtLine, dRadius, dU1, dU2) ; + + Point3d ptPS = ptLine + dU1 * vtLine ; + Point3d ptPE = ptLine + dU2 * vtLine ; + + if ( nTypeInt == CC_ERROR_INT) + return false ; + if ( nTypeInt == CC_NO_INTERS) + int nSol = 0 ; + if ( nTypeInt == CC_ONE_INT_SEC) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - 3 * vtLine, ptPS + 3 * vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == CC_ONE_INT_TAN) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - vtLine, ptPS + vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == CC_TWO_INT) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS, ptPE) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == CC_INF_INT) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS, ptPE) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::RayInfiniteCylinderInters( const STRVECTOR& vsParams) +{ + // parametri : Id, IdParent, ptCyl, ptLine, vtCyl, vtLine, dRad + if ( vsParams.size() < 7) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frRef ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef)) + return false ; + // recupero punto del cilindro + Point3d ptCyl ; + if ( ! GetPointParam( vsParams[2], frRef, ptCyl)) + return false ; + // recupero punto retta + Point3d ptLine ; + if ( ! GetPointParam( vsParams[3], frRef, ptLine)) + return false ; + // recupero vettore cilindro + Vector3d vtCyl ; + if ( ! GetVectorParam( vsParams[4], frRef, vtCyl)) + return false ; + vtCyl.Normalize() ; + // recupero vettore retta + Vector3d vtLine ; + if ( ! GetVectorParam( vsParams[5], frRef, vtLine)) + return false ; + vtLine.Normalize() ; + // recupero raggio cilindro + double dRadius ; + if ( ! FromString( vsParams[6], dRadius)) + return false ; + + double dU1, dU2 ; + int nTypeInt = LineInfiniteCylinder( ptCyl, ptLine, vtCyl, vtLine, dRadius, dU1, dU2) ; + + Point3d ptPS = ptLine + dU1 * vtLine ; + Point3d ptPE = ptLine + dU2 * vtLine ; + + if ( nTypeInt == CC_ERROR_INT) + return false ; + if ( nTypeInt == CC_NO_INTERS) + int nSol = 0 ; + if ( nTypeInt == CC_ONE_INT_SEC) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - 3 * vtLine, ptPS + 3 * vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == CC_ONE_INT_TAN) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - vtLine, ptPS + vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == CC_TWO_INT) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS, ptPE) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == CC_INF_INT) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS, ptPE) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::SegmentInfiniteCylinderInters( const STRVECTOR& vsParams) +{ + // parametri : Id, IdParent, ptCyl, ptLine, vtCyl, vtLine, dRad, dLen + if ( vsParams.size() < 8) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frRef ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef)) + return false ; + // recupero punto del cilindro + Point3d ptCyl ; + if ( ! GetPointParam( vsParams[2], frRef, ptCyl)) + return false ; + // recupero punto retta + Point3d ptLine ; + if ( ! GetPointParam( vsParams[3], frRef, ptLine)) + return false ; + // recupero vettore cilindro + Vector3d vtCyl ; + if ( ! GetVectorParam( vsParams[4], frRef, vtCyl)) + return false ; + vtCyl.Normalize() ; + // recupero vettore retta + Vector3d vtLine ; + if ( ! GetVectorParam( vsParams[5], frRef, vtLine)) + return false ; + vtLine.Normalize() ; + // recupero raggio cilindro + double dRadius ; + if ( ! FromString( vsParams[6], dRadius)) + return false ; + // recupero lunghezza segmento + double dLen ; + if ( ! FromString( vsParams[7], dLen)) + return false ; + + double dU1, dU2 ; + int nTypeInt = SegmentInfiniteCylinder( ptCyl, ptLine, vtCyl, vtLine, dRadius, dLen, dU1, dU2) ; + Point3d ptPS = ptLine + dU1 * vtLine ; + Point3d ptPE = ptLine + dU2 * vtLine ; + + if ( nTypeInt == CC_ERROR_INT) + return false ; + if ( nTypeInt == CC_NO_INTERS) + int nSol = 0 ; + if ( nTypeInt == CC_ONE_INT_SEC) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - 3 * vtLine, ptPS + 3 * vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == CC_ONE_INT_TAN) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - vtLine, ptPS + vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == CC_TWO_INT) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS, ptPE) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == CC_INF_INT) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS, ptPE) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::SegmentCylinderInters( const STRVECTOR& vsParams) +{ + // parametri : Id, IdParent, ptCyl, ptLine, vtCyl, vtLine, dRad, dCylHeigth, dLen + if ( vsParams.size() < 9) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frRef ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef)) + return false ; + // recupero punto del cilindro + Point3d ptCyl ; + if ( ! GetPointParam( vsParams[2], frRef, ptCyl)) + return false ; + // recupero punto retta + Point3d ptLine ; + if ( ! GetPointParam( vsParams[3], frRef, ptLine)) + return false ; + // recupero vettore cilindro + Vector3d vtCyl ; + if ( ! GetVectorParam( vsParams[4], frRef, vtCyl)) + return false ; + vtCyl.Normalize() ; + // recupero vettore retta + Vector3d vtLine ; + if ( ! GetVectorParam( vsParams[5], frRef, vtLine)) + return false ; + vtLine.Normalize() ; + // recupero raggio cilindro + double dRadius ; + if ( ! FromString( vsParams[6], dRadius)) + return false ; + // recupero altezza cilindro + double dHeigth ; + if ( ! FromString( vsParams[7], dHeigth)) + return false ; + // recupero lunghezza segmento + double dLen ; + if ( ! FromString( vsParams[8], dLen)) + return false ; + + double dU1, dU2 ; + int nTypeInt = SegmentCylinder( ptCyl, ptLine, vtCyl, vtLine, dRadius, dHeigth, dLen, dU1, dU2) ; + Point3d ptPS = ptLine + dU1 * vtLine ; + Point3d ptPE = ptLine + dU2 * vtLine ; + + if ( nTypeInt == CC_ERROR_INT) + return false ; + if ( nTypeInt == CC_NO_INTERS) + int nSol = 0 ; + if ( nTypeInt == CC_ONE_INT_SEC) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - 3 * vtLine, ptPS + 3 * vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == CC_ONE_INT_TAN) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - vtLine, ptPS + vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == CC_TWO_INT) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS, ptPE) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == CC_INF_INT) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS, ptPE) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::SegmentConeInters( const STRVECTOR& vsParams) +{ + // parametri : Id, IdParent, ptVCone, ptLine, vtCone, vtLine, dRad, dCylHeigth, dLen + if ( vsParams.size() < 9) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frRef ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef)) + return false ; + // recupero punto del cono + Point3d ptVCone ; + if ( ! GetPointParam( vsParams[2], frRef, ptVCone)) + return false ; + // recupero punto retta + Point3d ptLine ; + if ( ! GetPointParam( vsParams[3], frRef, ptLine)) + return false ; + // recupero vettore cono + Vector3d vtCone ; + if ( ! GetVectorParam( vsParams[4], frRef, vtCone)) + return false ; + vtCone.Normalize() ; + // recupero vettore retta + Vector3d vtLine ; + if ( ! GetVectorParam( vsParams[5], frRef, vtLine)) + return false ; + vtLine.Normalize() ; + // recupero raggio cono + double dRadius ; + if ( ! FromString( vsParams[6], dRadius)) + return false ; + // recupero altezza cono + double dHeigth ; + if ( ! FromString( vsParams[7], dHeigth)) + return false ; + // recupero lunghezza segmento + double dLen ; + if ( ! FromString( vsParams[8], dLen)) + return false ; + + double dU1, dU2 ; + int nTypeInt = SegmentCone( ptVCone, ptLine, vtCone, vtLine, dRadius, dHeigth, dLen, dU1, dU2) ; + Point3d ptPS = ptLine + dU1 * vtLine ; + Point3d ptPE = ptLine + dU2 * vtLine ; + + if ( nTypeInt == CC_ERROR_INT) + return false ; + if ( nTypeInt == CC_NO_INTERS) + int nSol = 0 ; + if ( nTypeInt == CC_ONE_INT_SEC) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - 3 * vtLine, ptPS + 3 * vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == CC_ONE_INT_TAN) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - vtLine, ptPS + vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == CC_TWO_INT) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS, ptPE) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == CC_INF_INT) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS, ptPE) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == CC_ON_VERT) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - 6 * vtLine, ptPS + 6 * vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::LineTruncateConeInters( const STRVECTOR& vsParams) +{ // parametri : Id, IdParent, ptMinBase, ptLine, vtCone, vtLine, dMinRad, dMaxRad, dConeHeigth + if ( vsParams.size() < 9) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frRef ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef)) + return false ; + // recupero punto della base minore + Point3d ptMinBase ; + if ( ! GetPointParam( vsParams[2], frRef, ptMinBase)) + return false ; + // recupero punto retta + Point3d ptLine ; + if ( ! GetPointParam( vsParams[3], frRef, ptLine)) + return false ; + // recupero vettore cono + Vector3d vtCone ; + if ( ! GetVectorParam( vsParams[4], frRef, vtCone)) + return false ; + vtCone.Normalize() ; + // recupero vettore retta + Vector3d vtLine ; + if ( ! GetVectorParam( vsParams[5], frRef, vtLine)) + return false ; + vtLine.Normalize() ; + // recupero raggio Min + double dMinRad ; + if ( ! FromString( vsParams[6], dMinRad)) + return false ; + // recupero raggio Max + double dMaxRad ; + if ( ! FromString( vsParams[7], dMaxRad)) + return false ; + // recupero altezza cono + double dConeHeigth ; + if ( ! FromString( vsParams[8], dConeHeigth)) + return false ; + + double dU1, dU2 ; + int nTypeInt = LineTruncatedCone( ptMinBase, ptLine, vtCone, vtLine, dMinRad, dMaxRad, dConeHeigth, dU1, dU2) ; + Point3d ptPS = ptLine + dU1 * vtLine ; + Point3d ptPE = ptLine + dU2 * vtLine ; + + if ( nTypeInt == CC_ERROR_INT) + return false ; + if ( nTypeInt == CC_NO_INTERS) + int nSol = 0 ; + if ( nTypeInt == CC_ONE_INT_SEC) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - 3 * vtLine, ptPS + 3 * vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == CC_ONE_INT_TAN) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - vtLine, ptPS + vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == CC_TWO_INT) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS, ptPE) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == CC_INF_INT) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS, ptPE) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == CC_ON_VERT) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - 6 * vtLine, ptPS + 6 * vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::RayTruncateConeInters( const STRVECTOR& vsParams) +{ + // parametri : Id, IdParent, ptMinBase, ptLine, vtCone, vtLine, dMinRad, dMaxRad, dConeHeigth + if ( vsParams.size() < 9) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frRef ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef)) + return false ; + // recupero punto della base minore + Point3d ptMinBase ; + if ( ! GetPointParam( vsParams[2], frRef, ptMinBase)) + return false ; + // recupero punto retta + Point3d ptLine ; + if ( ! GetPointParam( vsParams[3], frRef, ptLine)) + return false ; + // recupero vettore cono + Vector3d vtCone ; + if ( ! GetVectorParam( vsParams[4], frRef, vtCone)) + return false ; + vtCone.Normalize() ; + // recupero vettore retta + Vector3d vtLine ; + if ( ! GetVectorParam( vsParams[5], frRef, vtLine)) + return false ; + vtLine.Normalize() ; + // recupero raggio Min + double dMinRad ; + if ( ! FromString( vsParams[6], dMinRad)) + return false ; + // recupero raggio Max + double dMaxRad ; + if ( ! FromString( vsParams[7], dMaxRad)) + return false ; + // recupero altezza cono + double dConeHeigth ; + if ( ! FromString( vsParams[8], dConeHeigth)) + return false ; + + double dU1, dU2 ; + int nTypeInt = RayTruncatedCone( ptMinBase, ptLine, vtCone, vtLine, dMinRad, dMaxRad, dConeHeigth, dU1, dU2) ; + Point3d ptPS = ptLine + dU1 * vtLine ; + Point3d ptPE = ptLine + dU2 * vtLine ; + + if ( nTypeInt == CC_ERROR_INT) + return false ; + if ( nTypeInt == CC_NO_INTERS) + int nSol = 0 ; + if ( nTypeInt == CC_ONE_INT_SEC) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - 3 * vtLine, ptPS + 3 * vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == CC_ONE_INT_TAN) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - vtLine, ptPS + vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == CC_TWO_INT) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS, ptPE) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == CC_INF_INT) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS, ptPE) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == CC_ON_VERT) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - 6 * vtLine, ptPS + 6 * vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::SegmentTruncateConeInters( const STRVECTOR& vsParams) +{ // parametri : Id, IdParent, ptMinBase, ptLine, vtCone, vtLine, dMinRad, dMaxRad, dConeHeigth + if ( vsParams.size() < 10) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frRef ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef)) + return false ; + // recupero punto della base minore + Point3d ptMinBase ; + if ( ! GetPointParam( vsParams[2], frRef, ptMinBase)) + return false ; + // recupero punto retta + Point3d ptLine ; + if ( ! GetPointParam( vsParams[3], frRef, ptLine)) + return false ; + // recupero vettore cono + Vector3d vtCone ; + if ( ! GetVectorParam( vsParams[4], frRef, vtCone)) + return false ; + vtCone.Normalize() ; + // recupero vettore retta + Vector3d vtLine ; + if ( ! GetVectorParam( vsParams[5], frRef, vtLine)) + return false ; + vtLine.Normalize() ; + // recupero raggio Min + double dMinRad ; + if ( ! FromString( vsParams[6], dMinRad)) + return false ; + // recupero raggio Max + double dMaxRad ; + if ( ! FromString( vsParams[7], dMaxRad)) + return false ; + // recupero altezza cono + double dConeHeigth ; + if ( ! FromString( vsParams[8], dConeHeigth)) + return false ; + // recupero lunghezza segmento + double dLen ; + if ( ! FromString( vsParams[9], dLen)) + return false ; + + double dU1, dU2 ; + int nTypeInt = SegmentTruncatedCone( ptMinBase, ptLine, vtCone, vtLine, dMinRad, dMaxRad, dConeHeigth, dLen, dU1, dU2) ; + Point3d ptPS = ptLine + dU1 * vtLine ; + Point3d ptPE = ptLine + dU2 * vtLine ; + + if ( nTypeInt == CC_ERROR_INT) + return false ; + if ( nTypeInt == CC_NO_INTERS) + int nSol = 0 ; + if ( nTypeInt == CC_ONE_INT_SEC) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - 3 * vtLine, ptPS + 3 * vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == CC_ONE_INT_TAN) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - vtLine, ptPS + vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == CC_TWO_INT) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS, ptPE) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == CC_INF_INT) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS, ptPE) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == CC_ON_VERT) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptPS - 6 * vtLine, ptPS + 6 * vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::LineTorusInters( const STRVECTOR& vsParams) +{ // parametri : Id, IdParent, ptTorus, ptLine, vtTorus, vtLine, dMinRad, dMaxRad, + if ( vsParams.size() < 8) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frRef ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef)) + return false ; + // recupero punto toro + Point3d ptTorus ; + if ( ! GetPointParam( vsParams[2], frRef, ptTorus)) + return false ; + // recupero punto retta + Point3d ptLine ; + if ( ! GetPointParam( vsParams[3], frRef, ptLine)) + return false ; + // recupero vettore toro + Vector3d vtTorus ; + if ( ! GetVectorParam( vsParams[4], frRef, vtTorus)) + return false ; + vtTorus.Normalize() ; + // recupero vettore retta + Vector3d vtLine ; + if ( ! GetVectorParam( vsParams[5], frRef, vtLine)) + return false ; + vtLine.Normalize() ; + // recupero raggio Min + double dMinRad ; + if ( ! FromString( vsParams[6], dMinRad)) + return false ; + // recupero raggio Max + double dMaxRad ; + if ( ! FromString( vsParams[7], dMaxRad)) + return false ; + + std::vector vdP ; + std::vector vbT ; + int nTypeInt = LineTorus( ptTorus, ptLine, vtTorus, vtLine, dMinRad, dMaxRad, vdP, vbT) ; + + if ( nTypeInt == T_ERROR) + return false ; + if ( nTypeInt == T_NO_INT) + int nSol = 0 ; + if ( nTypeInt == T_ONE_TAN) { + Point3d ptInt = ptLine + vdP[0] * vtLine ; + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptInt - vtLine, ptInt + vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == T_TWO_TAN) { + Point3d ptInt0 = ptLine + vdP[0] * vtLine ; + Point3d ptInt1 = ptLine + vdP[1] * vtLine ; + PtrOwner pLine0( new CurveLine) ; + PtrOwner pLine1( new CurveLine) ; + pLine0->Set( ptInt0 - vtLine, ptInt0 + vtLine) ; + pLine1->Set( ptInt1 - vtLine, ptInt1 + vtLine) ; + // inserisco nel DB + return ( AddGeoObj( vsParams[0], vsParams[1], Release( pLine0)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine1))) ; + } + if ( nTypeInt == T_TWO_SEC) { + Point3d ptInt0 = ptLine + vdP[0] * vtLine ; + Point3d ptInt1 = ptLine + vdP[1] * vtLine ; + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptInt0, ptInt1) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == T_THREE_ONE_TAN_TWO_SEC) { + Point3d ptInt0 = ptLine + vdP[0] * vtLine ; + Point3d ptInt1 = ptLine + vdP[1] * vtLine ; + Point3d ptInt2 = ptLine + vdP[2] * vtLine ; + if ( vbT[0] && vbT[1] && ( ! vbT[2])) { + PtrOwner pLine0( new CurveLine) ; + pLine0->Set( ptInt0, ptInt1) ; + PtrOwner pLine1( new CurveLine) ; + pLine1->Set( ptInt2 - vtLine, ptInt2 + vtLine) ; + // inserisco nel DB + return ( AddGeoObj( vsParams[0], vsParams[1], Release( pLine0)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine1))) ; + } + else if ( vbT[0] && ( ! vbT[1]) && vbT[2]) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptInt0, ptInt2) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + else if ( ( ! vbT[0]) && vbT[1] && vbT[2]) { + PtrOwner pLine0( new CurveLine) ; + pLine0->Set( ptInt0 - vtLine, ptInt0 + vtLine) ; + PtrOwner pLine1( new CurveLine) ; + pLine1->Set( ptInt1, ptInt2) ; + // inserisco nel DB + return ( AddGeoObj( vsParams[0], vsParams[1], Release( pLine0)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine1))) ; + } + } + else if ( T_FOUR_SEC) { + Point3d ptInt0 = ptLine + vdP[0] * vtLine ; + Point3d ptInt1 = ptLine + vdP[1] * vtLine ; + Point3d ptInt2 = ptLine + vdP[2] * vtLine ; + Point3d ptInt3 = ptLine + vdP[3] * vtLine ; + PtrOwner pLine0( new CurveLine) ; + pLine0->Set( ptInt0, ptInt1) ; + PtrOwner pLine1( new CurveLine) ; + pLine1->Set( ptInt2, ptInt3) ; + // inserisco nel DB + return ( AddGeoObj( vsParams[0], vsParams[1], Release( pLine0)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine1))) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::RayTorusInters( const STRVECTOR& vsParams) +{ + // parametri : Id, IdParent, ptTorus, ptLine, vtTorus, vtLine, dMinRad, dMaxRad, + if ( vsParams.size() < 8) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frRef ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef)) + return false ; + // recupero punto toro + Point3d ptTorus ; + if ( ! GetPointParam( vsParams[2], frRef, ptTorus)) + return false ; + // recupero punto retta + Point3d ptLine ; + if ( ! GetPointParam( vsParams[3], frRef, ptLine)) + return false ; + // recupero vettore toro + Vector3d vtTorus ; + if ( ! GetVectorParam( vsParams[4], frRef, vtTorus)) + return false ; + vtTorus.Normalize() ; + // recupero vettore retta + Vector3d vtLine ; + if ( ! GetVectorParam( vsParams[5], frRef, vtLine)) + return false ; + vtLine.Normalize() ; + // recupero raggio Min + double dMinRad ; + if ( ! FromString( vsParams[6], dMinRad)) + return false ; + // recupero raggio Max + double dMaxRad ; + if ( ! FromString( vsParams[7], dMaxRad)) + return false ; + + std::vector vdP ; + std::vector vbT ; + int nTypeInt = RayTorus( ptTorus, ptLine, vtTorus, vtLine, dMinRad, dMaxRad, vdP, vbT) ; + + if ( nTypeInt == T_ERROR) + return false ; + if ( nTypeInt == T_NO_INT) + int nSol = 0 ; + if ( nTypeInt == T_ONE_TAN) { + Point3d ptInt = ptLine + vdP[0] * vtLine ; + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptInt - vtLine, ptInt + vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == T_ONE_SEC) { + Point3d ptInt = ptLine + vdP[0] * vtLine ; + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptInt - 4 * vtLine, ptInt + 4 * vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == T_TWO_TAN) { + Point3d ptInt0 = ptLine + vdP[0] * vtLine ; + Point3d ptInt1 = ptLine + vdP[1] * vtLine ; + PtrOwner pLine0( new CurveLine) ; + PtrOwner pLine1( new CurveLine) ; + pLine0->Set( ptInt0 - vtLine, ptInt0 + vtLine) ; + pLine1->Set( ptInt1 - vtLine, ptInt1 + vtLine) ; + // inserisco nel DB + return ( AddGeoObj( vsParams[0], vsParams[1], Release( pLine0)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine1))) ; + } + if ( nTypeInt == T_TWO_SEC) { + Point3d ptInt0 = ptLine + vdP[0] * vtLine ; + Point3d ptInt1 = ptLine + vdP[1] * vtLine ; + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptInt0, ptInt1) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == T_TWO_TAN_SEC) { + Point3d ptInt0 = ptLine + vdP[0] * vtLine ; + Point3d ptInt1 = ptLine + vdP[1] * vtLine ; + double dDil0 = ( vbT[0] ? 4 : 1) ; + double dDil1 = ( vbT[1] ? 4 : 1) ; + PtrOwner pLine0( new CurveLine) ; + pLine0->Set( ptInt0 - dDil0 * vtLine, ptInt0 + dDil0 * vtLine) ; + PtrOwner pLine1( new CurveLine) ; + pLine1->Set( ptInt1 - dDil1 * vtLine, ptInt1 + dDil1 * vtLine) ; + // inserisco nel DB + return ( AddGeoObj( vsParams[0], vsParams[1], Release( pLine0)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine1))) ; + } + if ( nTypeInt == T_THREE_SEC) { + Point3d ptInt0 = ptLine + vdP[0] * vtLine ; + Point3d ptInt1 = ptLine + vdP[1] * vtLine ; + Point3d ptInt2 = ptLine + vdP[2] * vtLine ; + PtrOwner pLine0( new CurveLine) ; + pLine0->Set( ptInt0 - 4 * vtLine, ptInt0 + 4 * vtLine) ; + PtrOwner pLine1( new CurveLine) ; + pLine1->Set( ptInt1 - 4 * vtLine, ptInt1 + 4 * vtLine) ; + PtrOwner pLine2( new CurveLine) ; + pLine2->Set( ptInt2 - 4 * vtLine, ptInt2 + 4 * vtLine) ; + // inserisco nel DB + return ( AddGeoObj( vsParams[0], vsParams[1], Release( pLine0)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine1)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine2))) ; + } + if ( nTypeInt == T_THREE_ONE_TAN_TWO_SEC) { + Point3d ptInt0 = ptLine + vdP[0] * vtLine ; + Point3d ptInt1 = ptLine + vdP[1] * vtLine ; + Point3d ptInt2 = ptLine + vdP[2] * vtLine ; + if ( vbT[0] && vbT[1] && ( ! vbT[2])) { + PtrOwner pLine0( new CurveLine) ; + pLine0->Set( ptInt0, ptInt1) ; + PtrOwner pLine1( new CurveLine) ; + pLine1->Set( ptInt2 - vtLine, ptInt2 + vtLine) ; + // inserisco nel DB + return ( AddGeoObj( vsParams[0], vsParams[1], Release( pLine0)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine1))) ; + } + else if ( vbT[0] && ( ! vbT[1]) && vbT[2]) { + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptInt0, ptInt2) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + else if ( ( ! vbT[0]) && vbT[1] && vbT[2]) { + PtrOwner pLine0( new CurveLine) ; + pLine0->Set( ptInt0 - vtLine, ptInt0 + vtLine) ; + PtrOwner pLine1( new CurveLine) ; + pLine1->Set( ptInt1, ptInt2) ; + // inserisco nel DB + return ( AddGeoObj( vsParams[0], vsParams[1], Release( pLine0)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine1))) ; + } + } + else if ( nTypeInt == T_FOUR_SEC) { + Point3d ptInt0 = ptLine + vdP[0] * vtLine ; + Point3d ptInt1 = ptLine + vdP[1] * vtLine ; + Point3d ptInt2 = ptLine + vdP[2] * vtLine ; + Point3d ptInt3 = ptLine + vdP[3] * vtLine ; + PtrOwner pLine0( new CurveLine) ; + pLine0->Set( ptInt0, ptInt1) ; + PtrOwner pLine1( new CurveLine) ; + pLine1->Set( ptInt2, ptInt3) ; + // inserisco nel DB + return ( AddGeoObj( vsParams[0], vsParams[1], Release( pLine0)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine1))) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::SegmentTorusInters( const STRVECTOR& vsParams) +{ + // parametri : Id, IdParent, ptTorus, ptLine, vtTorus, vtLine, dMinRad, dMaxRad, dSgLen + if ( vsParams.size() < 9) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frRef ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef)) + return false ; + // recupero punto toro + Point3d ptTorus ; + if ( ! GetPointParam( vsParams[2], frRef, ptTorus)) + return false ; + // recupero punto retta + Point3d ptLine ; + if ( ! GetPointParam( vsParams[3], frRef, ptLine)) + return false ; + // recupero vettore toro + Vector3d vtTorus ; + if ( ! GetVectorParam( vsParams[4], frRef, vtTorus)) + return false ; + vtTorus.Normalize() ; + // recupero vettore retta + Vector3d vtLine ; + if ( ! GetVectorParam( vsParams[5], frRef, vtLine)) + return false ; + vtLine.Normalize() ; + // recupero raggio Min + double dMinRad ; + if ( ! FromString( vsParams[6], dMinRad)) + return false ; + // recupero raggio Max + double dMaxRad ; + if ( ! FromString( vsParams[7], dMaxRad)) + return false ; + // recupero raggio Max + double dSgLen ; + if ( ! FromString( vsParams[8], dSgLen)) + return false ; + + std::vector vdP ; + std::vector vbT ; + int nTypeInt = SegmentTorus( ptTorus, ptLine, vtTorus, vtLine, dMinRad, dMaxRad, dSgLen, vdP, vbT) ; + + if ( nTypeInt == T_ERROR) + return false ; + if ( nTypeInt == T_NO_INT) + int nSol = 0 ; + if ( nTypeInt == T_ONE_TAN) { + Point3d ptInt = ptLine + vdP[0] * vtLine ; + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptInt - vtLine, ptInt + vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == T_ONE_SEC) { + Point3d ptInt = ptLine + vdP[0] * vtLine ; + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptInt - 4 * vtLine, ptInt + 4 * vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == T_TWO_TAN) { + Point3d ptInt0 = ptLine + vdP[0] * vtLine ; + Point3d ptInt1 = ptLine + vdP[1] * vtLine ; + PtrOwner pLine0( new CurveLine) ; + PtrOwner pLine1( new CurveLine) ; + pLine0->Set( ptInt0 - vtLine, ptInt0 + vtLine) ; + pLine1->Set( ptInt1 - vtLine, ptInt1 + vtLine) ; + // inserisco nel DB + return ( AddGeoObj( vsParams[0], vsParams[1], Release( pLine0)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine1))) ; + } + if ( nTypeInt == T_TWO_SEC) { + Point3d ptInt0 = ptLine + vdP[0] * vtLine ; + Point3d ptInt1 = ptLine + vdP[1] * vtLine ; + PtrOwner pLine0( new CurveLine) ; + PtrOwner pLine1( new CurveLine) ; + pLine0->Set( ptInt0 - 4 * vtLine, ptInt0 + 4 * vtLine) ; + pLine1->Set( ptInt1 - 4 * vtLine, ptInt1 + 4 * vtLine) ; + // inserisco nel DB + return ( AddGeoObj( vsParams[0], vsParams[1], Release( pLine0)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine1))) ; + } + if ( nTypeInt == T_TWO_TAN_SEC) { + Point3d ptInt0 = ptLine + vdP[0] * vtLine ; + Point3d ptInt1 = ptLine + vdP[1] * vtLine ; + double dDil0 = ( vbT[0] ? 4 : 1) ; + double dDil1 = ( vbT[1] ? 4 : 1) ; + PtrOwner pLine0( new CurveLine) ; + pLine0->Set( ptInt0 - dDil0 * vtLine, ptInt0 + dDil0 * vtLine) ; + PtrOwner pLine1( new CurveLine) ; + pLine1->Set( ptInt1 - dDil1 * vtLine, ptInt1 + dDil1 * vtLine) ; + // inserisco nel DB + return ( AddGeoObj( vsParams[0], vsParams[1], Release( pLine0)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine1))) ; + } + if ( nTypeInt == T_THREE_SEC) { + Point3d ptInt0 = ptLine + vdP[0] * vtLine ; + Point3d ptInt1 = ptLine + vdP[1] * vtLine ; + Point3d ptInt2 = ptLine + vdP[2] * vtLine ; + PtrOwner pLine0( new CurveLine) ; + pLine0->Set( ptInt0 - 4 * vtLine, ptInt0 + 4 * vtLine) ; + PtrOwner pLine1( new CurveLine) ; + pLine1->Set( ptInt1 - 4 * vtLine, ptInt1 + 4 * vtLine) ; + PtrOwner pLine2( new CurveLine) ; + pLine2->Set( ptInt2 - 4 * vtLine, ptInt2 + 4 * vtLine) ; + // inserisco nel DB + return ( AddGeoObj( vsParams[0], vsParams[1], Release( pLine0)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine1)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine2))) ; + } + if ( nTypeInt == T_THREE_ONE_TAN_TWO_SEC) { + Point3d ptInt0 = ptLine + vdP[0] * vtLine ; + Point3d ptInt1 = ptLine + vdP[1] * vtLine ; + Point3d ptInt2 = ptLine + vdP[2] * vtLine ; + if ( vbT[0] && vbT[1] && ( ! vbT[2])) { + PtrOwner pLine0( new CurveLine) ; + pLine0->Set( ptInt0 - 4 * vtLine, ptInt0 + 4 * vtLine) ; + PtrOwner pLine1( new CurveLine) ; + pLine1->Set( ptInt1 - 4 * vtLine, ptInt1 + 4 * vtLine) ; + PtrOwner pLine2( new CurveLine) ; + pLine2->Set( ptInt2 - vtLine, ptInt2 + vtLine) ; + // inserisco nel DB + return ( AddGeoObj( vsParams[0], vsParams[1], Release( pLine0)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine1)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine2))) ; + } + else if ( vbT[0] && ( ! vbT[1]) && vbT[2]) { + PtrOwner pLine0( new CurveLine) ; + pLine0->Set( ptInt0 - 4 * vtLine, ptInt0 + 4 * vtLine) ; + PtrOwner pLine1( new CurveLine) ; + pLine1->Set( ptInt1 - vtLine, ptInt1 + vtLine) ; + PtrOwner pLine2( new CurveLine) ; + pLine2->Set( ptInt2 - 4 * vtLine, ptInt2 + 4 * vtLine) ; + // inserisco nel DB + return ( AddGeoObj( vsParams[0], vsParams[1], Release( pLine0)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine1)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine2))) ; + } + else if ( ( ! vbT[0]) && vbT[1] && vbT[2]) { + PtrOwner pLine0( new CurveLine) ; + pLine0->Set( ptInt0 - vtLine, ptInt0 + vtLine) ; + PtrOwner pLine1( new CurveLine) ; + pLine1->Set( ptInt1 - 4 * vtLine, ptInt1 + 4 * vtLine) ; + PtrOwner pLine2( new CurveLine) ; + pLine2->Set( ptInt2 - 4 * vtLine, ptInt2 + 4 * vtLine) ; + // inserisco nel DB + return ( AddGeoObj( vsParams[0], vsParams[1], Release( pLine0)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine1)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine2))) ; + } + } + else if ( nTypeInt == T_FOUR_SEC) { + Point3d ptInt0 = ptLine + vdP[0] * vtLine ; + Point3d ptInt1 = ptLine + vdP[1] * vtLine ; + Point3d ptInt2 = ptLine + vdP[2] * vtLine ; + Point3d ptInt3 = ptLine + vdP[3] * vtLine ; + PtrOwner pLine0( new CurveLine) ; + pLine0->Set( ptInt0, ptInt1) ; + PtrOwner pLine1( new CurveLine) ; + pLine1->Set( ptInt2, ptInt3) ; + // inserisco nel DB + return ( AddGeoObj( vsParams[0], vsParams[1], Release( pLine0)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine1))) ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::LinCompTorusPartInters( const STRVECTOR& vsParams) +{ + // parametri : Id, IdParent, ptTorus, ptLine, vtTorus, vtLine, dMinRad, dMaxRad, dSgLen, nLinType + if ( vsParams.size() < 10) + return false ; + // recupero il riferimento in cui è immerso + Frame3d frRef ; + if ( ! m_pGDB->GetGroupGlobFrame( GetIdParam( vsParams[1]), frRef)) + return false ; + // recupero punto toro + Point3d ptTorus ; + if ( ! GetPointParam( vsParams[2], frRef, ptTorus)) + return false ; + // recupero punto retta + Point3d ptLine ; + if ( ! GetPointParam( vsParams[3], frRef, ptLine)) + return false ; + // recupero vettore toro + Vector3d vtTorus ; + if ( ! GetVectorParam( vsParams[4], frRef, vtTorus)) + return false ; + vtTorus.Normalize() ; + // recupero vettore retta + Vector3d vtLine ; + if ( ! GetVectorParam( vsParams[5], frRef, vtLine)) + return false ; + vtLine.Normalize() ; + // recupero raggio Min + double dMinRad ; + if ( ! FromString( vsParams[6], dMinRad)) + return false ; + // recupero raggio Max + double dMaxRad ; + if ( ! FromString( vsParams[7], dMaxRad)) + return false ; + // recupero raggio Max + double dSgLen ; + if ( ! FromString( vsParams[8], dSgLen)) + return false ; + int nLinType ; + if ( ! FromString( vsParams[9], nLinType)) + return false ; + + std::vector vdP ; + std::vector vbT ; + int nTypeInt = LinCompTorusExtInt( ptTorus, ptLine, vtTorus, vtLine, dMinRad, dMaxRad, dSgLen, nLinType, vdP, vbT) ; + + if ( nTypeInt == T_ERROR) + return false ; + if ( nTypeInt == T_NO_INT) + int nSol = 0 ; + if ( nTypeInt == T_ONE_TAN) { + Point3d ptInt = ptLine + vdP[0] * vtLine ; + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptInt - vtLine, ptInt + vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == T_ONE_SEC) { + Point3d ptInt = ptLine + vdP[0] * vtLine ; + PtrOwner pLine( new CurveLine) ; + pLine->Set( ptInt - 4 * vtLine, ptInt + 4 * vtLine) ; + // inserisco nel DB + return AddGeoObj( vsParams[0], vsParams[1], Release( pLine)) ; + } + if ( nTypeInt == T_TWO_TAN) { + Point3d ptInt0 = ptLine + vdP[0] * vtLine ; + Point3d ptInt1 = ptLine + vdP[1] * vtLine ; + PtrOwner pLine0( new CurveLine) ; + PtrOwner pLine1( new CurveLine) ; + pLine0->Set( ptInt0 - vtLine, ptInt0 + vtLine) ; + pLine1->Set( ptInt1 - vtLine, ptInt1 + vtLine) ; + // inserisco nel DB + return ( AddGeoObj( vsParams[0], vsParams[1], Release( pLine0)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine1))) ; + } + if ( nTypeInt == T_TWO_SEC) { + Point3d ptInt0 = ptLine + vdP[0] * vtLine ; + Point3d ptInt1 = ptLine + vdP[1] * vtLine ; + PtrOwner pLine0( new CurveLine) ; + PtrOwner pLine1( new CurveLine) ; + pLine0->Set( ptInt0 - 4 * vtLine, ptInt0 + 4 * vtLine) ; + pLine1->Set( ptInt1 - 4 * vtLine, ptInt1 + 4 * vtLine) ; + // inserisco nel DB + return ( AddGeoObj( vsParams[0], vsParams[1], Release( pLine0)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine1))) ; + } + if ( nTypeInt == T_TWO_TAN_SEC) { + Point3d ptInt0 = ptLine + vdP[0] * vtLine ; + Point3d ptInt1 = ptLine + vdP[1] * vtLine ; + double dDil0 = ( vbT[0] ? 4 : 1) ; + double dDil1 = ( vbT[1] ? 4 : 1) ; + PtrOwner pLine0( new CurveLine) ; + pLine0->Set( ptInt0 - dDil0 * vtLine, ptInt0 + dDil0 * vtLine) ; + PtrOwner pLine1( new CurveLine) ; + pLine1->Set( ptInt1 - dDil1 * vtLine, ptInt1 + dDil1 * vtLine) ; + // inserisco nel DB + return ( AddGeoObj( vsParams[0], vsParams[1], Release( pLine0)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine1))) ; + } + if ( nTypeInt == T_THREE_SEC) { + Point3d ptInt0 = ptLine + vdP[0] * vtLine ; + Point3d ptInt1 = ptLine + vdP[1] * vtLine ; + Point3d ptInt2 = ptLine + vdP[2] * vtLine ; + PtrOwner pLine0( new CurveLine) ; + pLine0->Set( ptInt0 - 4 * vtLine, ptInt0 + 4 * vtLine) ; + PtrOwner pLine1( new CurveLine) ; + pLine1->Set( ptInt1 - 4 * vtLine, ptInt1 + 4 * vtLine) ; + PtrOwner pLine2( new CurveLine) ; + pLine2->Set( ptInt2 - 4 * vtLine, ptInt2 + 4 * vtLine) ; + // inserisco nel DB + return ( AddGeoObj( vsParams[0], vsParams[1], Release( pLine0)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine1)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine2))) ; + } + if ( nTypeInt == T_THREE_ONE_TAN_TWO_SEC) { + Point3d ptInt0 = ptLine + vdP[0] * vtLine ; + Point3d ptInt1 = ptLine + vdP[1] * vtLine ; + Point3d ptInt2 = ptLine + vdP[2] * vtLine ; + if ( vbT[0] && vbT[1] && ( ! vbT[2])) { + PtrOwner pLine0( new CurveLine) ; + pLine0->Set( ptInt0 - 4 * vtLine, ptInt0 + 4 * vtLine) ; + PtrOwner pLine1( new CurveLine) ; + pLine1->Set( ptInt1 - 4 * vtLine, ptInt1 + 4 * vtLine) ; + PtrOwner pLine2( new CurveLine) ; + pLine2->Set( ptInt2 - vtLine, ptInt2 + vtLine) ; + // inserisco nel DB + return ( AddGeoObj( vsParams[0], vsParams[1], Release( pLine0)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine1)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine2))) ; + } + else if ( vbT[0] && ( ! vbT[1]) && vbT[2]) { + PtrOwner pLine0( new CurveLine) ; + pLine0->Set( ptInt0 - 4 * vtLine, ptInt0 + 4 * vtLine) ; + PtrOwner pLine1( new CurveLine) ; + pLine1->Set( ptInt1 - vtLine, ptInt1 + vtLine) ; + PtrOwner pLine2( new CurveLine) ; + pLine2->Set( ptInt2 - 4 * vtLine, ptInt2 + 4 * vtLine) ; + // inserisco nel DB + return ( AddGeoObj( vsParams[0], vsParams[1], Release( pLine0)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine1)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine2))) ; + } + else if ( ( ! vbT[0]) && vbT[1] && vbT[2]) { + PtrOwner pLine0( new CurveLine) ; + pLine0->Set( ptInt0 - vtLine, ptInt0 + vtLine) ; + PtrOwner pLine1( new CurveLine) ; + pLine1->Set( ptInt1 - 4 * vtLine, ptInt1 + 4 * vtLine) ; + PtrOwner pLine2( new CurveLine) ; + pLine2->Set( ptInt2 - 4 * vtLine, ptInt2 + 4 * vtLine) ; + // inserisco nel DB + return ( AddGeoObj( vsParams[0], vsParams[1], Release( pLine0)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine1)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine2))) ; + } + } + else if ( nTypeInt == T_FOUR_SEC) { + Point3d ptInt0 = ptLine + vdP[0] * vtLine ; + Point3d ptInt1 = ptLine + vdP[1] * vtLine ; + Point3d ptInt2 = ptLine + vdP[2] * vtLine ; + Point3d ptInt3 = ptLine + vdP[3] * vtLine ; + PtrOwner pLine0( new CurveLine) ; + pLine0->Set( ptInt0, ptInt1) ; + PtrOwner pLine1( new CurveLine) ; + pLine1->Set( ptInt2, ptInt3) ; + // inserisco nel DB + return ( AddGeoObj( vsParams[0], vsParams[1], Release( pLine0)) && + AddGeoObj( "$NN", vsParams[1], Release( pLine1))) ; + } + return true ; + +} + +//---------------------------------------------------------------------------- +bool +GdbExecutor::ExecuteToolAvoidTriangle( const std::string& sCmd2, const STRVECTOR& vsParams) +{ + if ( sCmd2 == "AVOID") { + // Parametri : IdT, nIdLeackV, nIdToolV, dHeigth, dRad, nToolType + if ( vsParams.size() != 6) + return false ; + // Recupero gli identificativi di triangolo, vettore di + // fuga e configurazione spaziale dell'utensile + int nIdT = GetIdParam( vsParams[0], false) ; + int nIdLeakV = GetIdParam( vsParams[1], false) ; + int nIdToolV = GetIdParam( vsParams[2], false) ; + // Recupero parametri geometrici dell'utensile e il suo tipo + double dHei = GetIdParam( vsParams[3], false) ; + double dRad = GetIdParam( vsParams[4], false) ; + int nToolType = GetIdParam( vsParams[5], false) ; + // Vettore di fuga + IGeoVector3d * pGLeakV = GetGeoVector3d( m_pGDB->GetGeoObj( nIdLeakV)) ; + Point3d ptLeakBase = pGLeakV->GetBase() ; + Vector3d vtLeakDir = pGLeakV->GetVector() ; + // Vettore utensile + IGeoVector3d * pGToolV = GetGeoVector3d( m_pGDB->GetGeoObj( nIdToolV)) ; + Point3d ptToolOrig = pGToolV->GetBase() ; + Vector3d vtToolDir = pGToolV->GetVector() ; + // Triangolo + ISurfTriMesh * pGT = GetSurfTriMesh( m_pGDB->GetGeoObj( nIdT)) ; + Triangle3d trTria ; + pGT->GetFirstTriangle( trTria) ; + // Creo un utensile + Tool tlTool ; + if ( nToolType == 1) + tlTool.SetStdTool( "Cilindro", dHei, dRad, 0, 0) ; + else if ( nToolType == 2) + tlTool.SetStdTool( "Sfera", dHei, dRad, dRad, 0) ; + else + return false ; + // Determino la distanza di fuga + double dDist = CAvToolTriangle( tlTool, ptToolOrig, vtToolDir, trTria, vtLeakDir) ; + // Restituisco informazione sulla distanza + m_pGDB->SetInfo( nIdT, "D", dDist) ; + return true ; + } + else + return false ; +} + //---------------------------------------------------------------------------- bool GdbExecutor::ExecuteText( const string& sCmd2, const STRVECTOR& vsParams) diff --git a/GdbExecutor.h b/GdbExecutor.h index d538cfc..bb640e6 100644 --- a/GdbExecutor.h +++ b/GdbExecutor.h @@ -18,6 +18,7 @@ #include "/EgtDev/Include/EgtPerfCounter.h" #include "/EgtDev/Include/EgtExecMgr.h" #include "/EgtDev/Include/EgkGeoCollection.h" +#include "Tool.h" class PolyLine ; class PolyArc ; @@ -122,6 +123,32 @@ class GdbExecutor : public IGdbExecutor bool VolZmapSetGenTool( const STRVECTOR& vsParams) ; bool VolZmapDeepnessMeasure( const STRVECTOR& vsParams) ; bool VolZmapBBoxZmapIntersection( const STRVECTOR& vsParams) ; + bool ExecuteIntersection( const std::string& sCmd2, const STRVECTOR& vsParams) ; // + bool LineDiscInters( const STRVECTOR& vsParams) ; // + bool RayDiscInters( const STRVECTOR& vsParams) ; // + bool SegmentDiscInters( const STRVECTOR& vsParams) ; // + bool LineSphereInters( const STRVECTOR& vsParams) ; // + bool RaySphereInters( const STRVECTOR& vsParams) ; // + bool SegmentSphereInters( const STRVECTOR& vsParams) ; // + bool LineSemiSphereInters( const STRVECTOR& vsParams) ; // + bool RaySemiSphereInters( const STRVECTOR& vsParams) ; // + bool SegmentSemiSphereInters( const STRVECTOR& vsParams) ; // + bool LinCompSemiSphereInters( const STRVECTOR& vsParams) ; // + bool LineInfiniteCylinderInters( const STRVECTOR& vsParams) ; // + bool RayInfiniteCylinderInters( const STRVECTOR& vsParams) ; // + bool SegmentInfiniteCylinderInters( const STRVECTOR& vsParams) ; // + bool LineCylinderInters( const STRVECTOR& vsParams) ; // + bool RayCylinderInters( const STRVECTOR& vsParams) ; // + bool SegmentCylinderInters( const STRVECTOR& vsParams) ; // + bool SegmentConeInters( const STRVECTOR& vsParams) ; // + bool LineTruncateConeInters( const STRVECTOR& vsParams) ; // + bool RayTruncateConeInters( const STRVECTOR& vsParams) ; // + bool SegmentTruncateConeInters( const STRVECTOR& vsParams) ; // + bool LineTorusInters( const STRVECTOR& vsParams) ; // + bool RayTorusInters( const STRVECTOR& vsParams) ; // + bool SegmentTorusInters( const STRVECTOR& vsParams) ; // + bool LinCompTorusPartInters( const STRVECTOR& vsParams) ; // + bool ExecuteToolAvoidTriangle( const std::string& sCmd2, const STRVECTOR& vsParams) ; // bool ExecuteText( const std::string& sCmd2, const STRVECTOR& vsParams) ; bool TextSimple( const STRVECTOR& vsParams) ; bool TextComplete( const STRVECTOR& vsParams) ; diff --git a/IntersLineSurfStd.cpp b/IntersLineSurfStd.cpp new file mode 100644 index 0000000..4a8674a --- /dev/null +++ b/IntersLineSurfStd.cpp @@ -0,0 +1,2093 @@ +//---------------------------------------------------------------------------- +// EgalTech 2015-2015 +//---------------------------------------------------------------------------- +// File : Tool.h Data : 01.12.17 Versione : ???1.6a4 +// Contenuto : Implementazione delle funzioni di intersezione +// superficie e componente lineare +// +// +// Modifiche : 22.01.15 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +#include "stdafx.h" +#include "/EgtDev/Include/EgtNumUtils.h" +#include "IntersLineSurfStd.h" + + +//---------------------------------------------------------------------------- +int LineDisc( const Point3d& ptPDisc, const Point3d& ptPLine, const Vector3d& vtVDisc, const Vector3d& vtVLine, + double dRad, double& dU1, double& dU2) +{ + int nIntType ; + // Se il raggio non è significativamente + // maggiore di zero, vi è un errore. + if ( dRad < EPS_SMALL) { + nIntType = D_ERROR_INT ; + return nIntType ; + } + // Si richiede che i vettori siano normalizzati + if ( ! ( vtVDisc.IsNormalized() && vtVLine.IsNormalized())) { + nIntType = D_ERROR_INT ; + return nIntType ; + } + + std::vector vdCoef(3) ; + std::vector vdRoots ; + + // Setto i coefficienti dell'equazione di itersezione fra retta e sfera, + // dallo studio di queste intersezioni e di quella col piano si del disco si deduce + // la posizione reciproca fra retta e disco + vdCoef[0] = ( ptPLine - ptPDisc).SqLen() - dRad * dRad ; + vdCoef[1] = 2 * ( ptPLine - ptPDisc) * vtVLine ; + vdCoef[2] = 1 ; + + // Soluzione dell'equazione + int nRoot = PolynomialRoots( 2, vdCoef, vdRoots) ; + + // Studio delle soluzioni + // Non vi sono intersezioni + if ( nRoot == 0) + nIntType = D_NO_INTERS ; + // Vi è un punto di tangenza con la sfera + else if ( nRoot == 1) { + dU1 = vdRoots[0] ; + Point3d ptTang = ptPLine + dU1 * vtVLine ; + // Se la retta giace nel piano, nel punto di + // tangenza la retta è tangente anche al disco. + if ( abs( vtVLine * vtVDisc) < EPS_ZERO && + abs( ( ptPLine - ptPDisc) * vtVDisc) < EPS_SMALL) + nIntType = D_ONE_INT_LINE_ON_PLANE ; + // Altrimenti se il punto di tangenza è sul + // piano, vi è ancora interferenza. + else if ( abs( ( ptTang - ptPDisc) * vtVDisc) < EPS_SMALL) + nIntType = D_BOUNDARY_INT_LINE_NOT_IN_PLANE ; + // Altrimenti non c'è interferenza fra disco e retta. + else + nIntType = D_NO_INTERS ; + } + // Caso di due intersezioni con la sfera + else if ( nRoot == 2) { + dU1 = vdRoots[0] ; + dU2 = vdRoots[1] ; + if ( dU1 > dU2) + std::swap( dU1, dU2) ; + // Soluzioni ben distinte + if ( dU2 - dU1 > EPS_SMALL) { + // Se la retta è nel piano parte di essa è nel disco + if ( abs( vtVLine * vtVDisc) < EPS_ZERO && + abs( ( ptPLine - ptPDisc) * vtVDisc) < EPS_SMALL) + nIntType = D_INFINITE_INT_LINE_ON_PLANE ; + else { + // Intersezione della retta con il piano + double dPlU = ( ( ptPDisc - ptPLine) * vtVDisc) / ( vtVDisc * vtVLine) ; + // Se tale intersezione è situata fra quelle con la + // sfera, allora essa è all'interno del disco. + if ( dPlU > dU1 && dPlU < dU2) { + dU1 = dPlU ; + nIntType = D_INNER_INT_LINE_NOT_IN_PLANE ; + } + // Altrimenti non c'è interferenza fra retta e disco + else + nIntType = D_NO_INTERS ; + } + } + // Soluzioni quasi coincidenti + else { + dU1 = 0.5 * ( vdRoots[0] + vdRoots[1]) ; + Point3d ptTang = ptPLine + dU1 * vtVLine ; + // Se la retta è nel piano, c'è una tangenza col disco + if ( abs( vtVLine * vtVDisc) < EPS_ZERO && + abs( ( ptPLine - ptPDisc) * vtVDisc) < EPS_SMALL) + nIntType = D_ONE_INT_LINE_ON_PLANE ; + // Altrimenti se il punto di tangenza è sul + // piano, vi è ancora interferenza. + else if ( abs( ( ptTang - ptPDisc) * vtVDisc) < EPS_SMALL) + nIntType = D_BOUNDARY_INT_LINE_NOT_IN_PLANE ; + // Altrimenti non c'è interferenza. + else + nIntType = D_NO_INTERS ; + } + } + return nIntType ; +} + +//---------------------------------------------------------------------------- +int RayDisc( const Point3d& ptPDisc, const Point3d& ptPLine, const Vector3d& vtVDisc, const Vector3d& vtVLine, + double dRad, double& dU1, double& dU2) +{ + int nIntType = LineDisc( ptPDisc, ptPLine, vtVDisc, vtVLine, dRad, dU1, dU2) ; + if ( nIntType == D_ERROR_INT) + return nIntType ; + + // La retta corrispondente al raggio è nel + // piano e attraversa la circonferenza. + if ( nIntType == D_INFINITE_INT_LINE_ON_PLANE) { + // Poiché dU2 > dU1, se dU2 < 0 allora dU1 < 0. + // La semiretta non interferisce col disco. + if ( dU2 < - EPS_SMALL) + nIntType = D_NO_INTERS ; + // Se solo dU1 < 0, c'è intersezione e la + // semi-retta parte dall'interno del disco + else if ( dU1 < - EPS_SMALL) { + dU1 = 0 ; + nIntType = D_INFINITE_INT_LINE_ON_PLANE ; + } + } + // In tutti gli altri casi c'è un solo punto + // di contatto fra retta e disco. + else { + // Se tale punto avviene a un parametro negativo, + // la semi-retta non interseca il disco. + if ( dU1 < - EPS_SMALL) + nIntType = D_NO_INTERS ; + } + return nIntType ; +} + +//---------------------------------------------------------------------------- +int SegmentDisc( const Point3d& ptPDisc, const Point3d& ptPLine, const Vector3d& vtVDisc, const Vector3d& vtVLine, + double dRad, double dLen, double& dU1, double& dU2) +{ + int nIntType = LineDisc( ptPDisc, ptPLine, vtVDisc, vtVLine, dRad, dU1, dU2) ; + if ( nIntType == D_ERROR_INT) + return nIntType ; + + // La retta corrispondente al segmento è nel + // piano e attraversa la circonferenza. + if ( nIntType == D_INFINITE_INT_LINE_ON_PLANE) { + // Interferenza + if ( dU1 < dLen + EPS_SMALL && dU2 > - EPS_SMALL) { + if ( dU1 > dLen - EPS_SMALL) + nIntType = D_ONE_INT_LINE_ON_PLANE ; + else if ( dU2 < EPS_SMALL) { + dU1 = 0 ; + nIntType = D_ONE_INT_LINE_ON_PLANE ; + } + else { + Clamp( dU1, 0., dLen) ; + Clamp( dU2, 0., dLen) ; + } + } + // Il segmento non interagisce + else + nIntType = D_NO_INTERS ; + } + // Negli altri casi c'è una sola intersezione + else if ( dU1 < - EPS_SMALL || dU2 > dLen + EPS_SMALL) + nIntType = D_NO_INTERS ; + return nIntType ; +} + +//---------------------------------------------------------------------------- +int LineSphere( const Point3d& ptSphC, const Point3d& ptPLine, const Vector3d& vtVLine, + double dRad, double& dU1, double& dU2) +{ + int nIntType = S_ERROR_INT ; + // Se il raggio non è significativamente + // maggiore di zero, vi è un errore. + if ( dRad < EPS_SMALL) + return nIntType ; + // Si richiede che il vettore sia normalizzato + if ( ! vtVLine.IsNormalized()) + return nIntType ; + + // Vettore congiungente il punto della retta con il centro della sfera + Vector3d vtR = ( ptSphC - ptPLine) - ( ptSphC - ptPLine) * vtVLine * vtVLine ; + // Quadrato del raggio della sfera + double dSqRad = dRad * dRad ; + // Quadrato della distanza punto retta + double dSqDist = vtR * vtR ; + // Retta esterna + if ( dSqDist > dSqRad + 2 * dRad * EPS_SMALL) + nIntType = S_NO_INTERS ; + // Retta tangente + else if ( dSqDist > dSqRad - 2 * dRad * EPS_SMALL) { + dU1 = ( ptSphC - ptPLine) * vtVLine ; + nIntType = S_ONE_INT_TAN ; + } + // Retta secante + else { + double dSemiDistSol = sqrt( dSqRad - dSqDist) ; + dU1 = ( ptSphC - ptPLine) * vtVLine - dSemiDistSol ; + dU2 = ( ptSphC - ptPLine) * vtVLine + dSemiDistSol ; + nIntType = S_TWO_INT ; + } + return nIntType ; +} + +//---------------------------------------------------------------------------- +int RaySphere( const Point3d& ptSphC, const Point3d& ptPLine, const Vector3d& vtVLine, + double dRad, double& dU1, double& dU2) +{ + int nIntType = LineSphere( ptSphC, ptPLine, vtVLine, dRad, dU1, dU2) ; + if ( nIntType == S_ERROR_INT) + return nIntType ; + + // Caso in cui retta associata al raggio è tangente + if ( nIntType == S_ONE_INT_TAN) { + // Se la soluzione è negativa, il raggio + // non interferisce con la sfera. + if ( dU1 < - EPS_SMALL) + nIntType = S_NO_INTERS ; + } + // Caso in cui la retta associata al raggio è secante + else if ( nIntType == S_TWO_INT) { + // Se dU1 è negativo, vi è solo una soluzione, + // e in questo caso il raggio non è tangente. + if ( dU1 < - EPS_SMALL) { + dU1 = dU2 ; + nIntType = S_ONE_INT_SEC ; + } + // Se anche dU2 è negativo il raggio, + // non interferisce. + if ( dU2 < - EPS_SMALL) + nIntType = S_NO_INTERS ; + } + return nIntType ; +} + +//---------------------------------------------------------------------------- +int SegmentSphere( const Point3d& ptSphC, const Point3d& ptPLine, const Vector3d& vtVLine, + double dRad, double dLen, double& dU1, double& dU2) +{ + int nIntType = LineSphere( ptSphC, ptPLine, vtVLine, dRad, dU1, dU2) ; + if ( nIntType == S_ERROR_INT) + return nIntType ; + + // La retta associata al segmento è tangente + if ( nIntType == S_ONE_INT_TAN) { + // Se il punto è fuori dal segmento, + // non vi sono soluzioni + if ( dU1 < - EPS_SMALL || dU1 > dLen + EPS_SMALL) + nIntType = S_NO_INTERS ; + } + // La retta associata al segmento è secante + else if ( nIntType = S_TWO_INT) { + // Segmento esterno + if ( dU1 > dLen + EPS_SMALL) + nIntType = S_NO_INTERS ; + else if ( dU1 > - EPS_SMALL) { + // Segmento secante con una intersezione + // In questo caso è valida dU1 + if ( dU2 > dLen + EPS_SMALL) + nIntType = S_ONE_INT_SEC ; + } + else { + // Il segmento non interferisce + if ( dU2 > dLen + EPS_SMALL) { + nIntType = S_NO_INTERS ; + } + // Segmento secante con una intersezione + // In questo caso è valida dU2, quindi + // assegnamo dU2 a dU1 + else if ( dU2 > - EPS_SMALL) { + dU1 = dU2 ; + nIntType = S_ONE_INT_SEC ; + } + // Il segmento non interferisce + else + nIntType = S_NO_INTERS ; + } + } + return nIntType ; +} + +//---------------------------------------------------------------------------- +int LineSemiSphere( const Point3d& ptSphC, const Point3d& ptPLine, + const Vector3d& vtSSphOrient, const Vector3d& vtVLine, + double dRad, double& dU1, double& dU2) +{ + int nIntType = LineSphere( ptSphC, ptPLine, vtVLine, dRad, dU1, dU2) ; + if ( nIntType == S_ERROR_INT || ( ! vtSSphOrient.IsNormalized())) + return S_ERROR_INT ; + // Un punto di tangenza + if ( nIntType == S_ONE_INT_TAN) { + Point3d ptInt = ptPLine + dU1 * vtVLine ; + Vector3d vtInt = ptInt - ptSphC ; + vtInt.Normalize() ; + // Se il punto di contatto è nella calotta superiore + // Scarto la soluzione + if ( vtInt * vtSSphOrient > EPS_ZERO) + nIntType = S_NO_INTERS ; + } + // Due punti di secanza + else if ( nIntType == S_TWO_INT) { + Point3d ptInt1 = ptPLine + dU1 * vtVLine ; + Point3d ptInt2 = ptPLine + dU1 * vtVLine ; + Vector3d vtInt1 = ptInt1 - ptSphC ; + Vector3d vtInt2 = ptInt2 - ptSphC ; + vtInt1.Normalize() ; + vtInt2.Normalize() ; + int nInt = 2 ; + // Scarto le soluzioni sulla calotta superiore + if ( vtInt1 * vtSSphOrient > EPS_ZERO) { + dU1 = dU2 ; + -- nInt ; + } + if ( vtInt2 * vtSSphOrient > EPS_ZERO) + -- nInt ; + // In base al numero di soluzioni valide + // aggiorno la tipologia di intersezione. + if ( nInt == 1) + nIntType = S_ONE_INT_SEC ; + else if ( nInt == 0) + nIntType = S_NO_INTERS ; + } + return nIntType ; +} + +//---------------------------------------------------------------------------- +int RaySemiSphere( const Point3d& ptSphC, const Point3d& ptPLine, + const Vector3d& vtSSphOrient, const Vector3d& vtVLine, + double dRad, double& dU1, double& dU2) +{ + int nIntType = RaySphere( ptSphC, ptPLine, vtVLine, dRad, dU1, dU2) ; + if ( nIntType == S_ERROR_INT || ( ! vtSSphOrient.IsNormalized())) + return S_ERROR_INT ; + // Un Punto in cui la semi-retta interferisce con la semi-sfera + if ( nIntType == S_ONE_INT_SEC || nIntType == S_ONE_INT_TAN) { + Point3d ptInt = ptPLine + dU1 * vtVLine ; + Vector3d vtInt = ptInt - ptSphC ; + vtInt.Normalize() ; + // Se il punto di contatto è nella calotta superiore + // Scarto la soluzione + if ( vtInt * vtSSphOrient > EPS_ZERO) + nIntType = S_NO_INTERS ; + } + // Due punti in cui la semi-retta è secante + else if ( nIntType == S_TWO_INT) { + Point3d ptInt1 = ptPLine + dU1 * vtVLine ; + Point3d ptInt2 = ptPLine + dU1 * vtVLine ; + Vector3d vtInt1 = ptInt1 - ptSphC ; + Vector3d vtInt2 = ptInt2 - ptSphC ; + vtInt1.Normalize() ; + vtInt2.Normalize() ; + int nInt = 2 ; + // Scarto le soluzioni sulla calotta superiore + if ( vtInt1 * vtSSphOrient > EPS_ZERO) { + dU1 = dU2 ; + -- nInt ; + } + if ( vtInt2 * vtSSphOrient > EPS_ZERO) + -- nInt ; + // In base al numero di soluzioni valide + // aggiorno la tipologia di intersezione. + if ( nInt == 1) + nIntType = S_ONE_INT_SEC ; + else if ( nInt == 0) + nIntType = S_NO_INTERS ; + } + return nIntType ; +} + +//---------------------------------------------------------------------------- +int SegmentSemiSphere( const Point3d& ptSphC, const Point3d& ptPLine, + const Vector3d& vtSSphOrient, const Vector3d& vtVLine, + double dRad, double dLen, double& dU1, double& dU2) +{ + int nIntType = SegmentSphere( ptSphC, ptPLine, vtVLine, dRad, dLen, dU1, dU2) ; + if ( nIntType == S_ERROR_INT || ( ! vtSSphOrient.IsNormalized())) + return S_ERROR_INT ; + // Un Punto in cui il segmento interferisce con la semi-sfera + if ( nIntType == S_ONE_INT_SEC || nIntType == S_ONE_INT_TAN) { + Point3d ptInt = ptPLine + dU1 * vtVLine ; + Vector3d vtInt = ptInt - ptSphC ; + vtInt.IsNormalized() ; + // Se il punto di contatto è nella calotta superiore + // Scarto la soluzione + if ( vtInt * vtSSphOrient > EPS_ZERO) + nIntType = S_NO_INTERS ; + } + // Due punti in cui il segmento è secante + else if ( nIntType == S_TWO_INT) { + Point3d ptInt1 = ptPLine + dU1 * vtVLine ; + Point3d ptInt2 = ptPLine + dU1 * vtVLine ; + Vector3d vtInt1 = ptInt1 - ptSphC ; + Vector3d vtInt2 = ptInt2 - ptSphC ; + vtInt1.Normalize() ; + vtInt2.Normalize() ; + int nInt = 2 ; + // Scarto le soluzioni sulla calotta superiore + if ( vtInt1 * vtSSphOrient > EPS_ZERO) { + dU1 = dU2 ; + -- nInt ; + } + if ( vtInt2 * vtSSphOrient > EPS_ZERO) + -- nInt ; + // In base al numero di soluzioni valide + // aggiorno la tipologia di intersezione. + if ( nInt == 1) + nIntType = S_ONE_INT_SEC ; + else if ( nInt == 0) + nIntType = S_NO_INTERS ; + } + return nIntType ; +} + +//---------------------------------------------------------------------------- +int LinCompSemiSphere( const Point3d& ptSphC, const Point3d& ptPLine, + const Vector3d& vtSSphOrient, const Vector3d& vtVLine, + double dRad, double dLen, int nLinType, double& dU1, double& dU2) +{ + int nIntType ; + // Retta + if ( nLinType == Line) + nIntType = LineSphere( ptSphC, ptPLine, vtVLine, dRad, dU1, dU2) ; + // Semi-retta + else if ( nLinType == Ray) + nIntType = RaySphere( ptSphC, ptPLine, vtVLine, dRad, dU1, dU2) ; + // Segmento + else if ( nLinType == Segment) + nIntType = SegmentSphere( ptSphC, ptPLine, vtVLine, dRad, dLen, dU1, dU2) ; + // Errore + else + nIntType = S_ERROR_INT ; + // Ancora errore + if ( nIntType == S_ERROR_INT || ( ! vtSSphOrient.IsNormalized())) + return S_ERROR_INT ; + // Un Punto in cui il segmento interferisce con la semi-sfera + if ( nIntType == S_ONE_INT_SEC || nIntType == S_ONE_INT_TAN) { + Point3d ptInt = ptPLine + dU1 * vtVLine ; + Vector3d vtInt = ptInt - ptSphC ; + vtInt.IsNormalized() ; + // Se il punto di contatto è nella calotta superiore + // Scarto la soluzione + if ( vtInt * vtSSphOrient > EPS_ZERO) + nIntType = S_NO_INTERS ; + } + // Due punti in cui il segmento è secante + else if ( nIntType == S_TWO_INT) { + Point3d ptInt1 = ptPLine + dU1 * vtVLine ; + Point3d ptInt2 = ptPLine + dU1 * vtVLine ; + Vector3d vtInt1 = ptInt1 - ptSphC ; + Vector3d vtInt2 = ptInt2 - ptSphC ; + vtInt1.Normalize() ; + vtInt2.Normalize() ; + int nInt = 2 ; + // Scarto le soluzioni sulla calotta superiore + if ( vtInt1 * vtSSphOrient > EPS_ZERO) { + dU1 = dU2 ; + -- nInt ; + } + if ( vtInt2 * vtSSphOrient > EPS_ZERO) + -- nInt ; + // In base al numero di soluzioni valide + // aggiorno la tipologia di intersezione. + if ( nInt == 1) + nIntType = S_ONE_INT_SEC ; + else if ( nInt == 0) + nIntType = S_NO_INTERS ; + } + return nIntType ; +} + +//---------------------------------------------------------------------------- +int LineInfiniteCylinder( const Point3d& ptPCyl, const Point3d& ptPLine, const Vector3d& vtVCyl, const Vector3d& vtVLine, + double dCylRad, double& dU1, double& dU2) +{ + int nIntType ; + // Se il raggio non è significativamente + // maggiore di zero, vi è un errore. + if ( dCylRad < EPS_SMALL) { + nIntType = CC_ERROR_INT ; + return nIntType ; + } + // Si richiede che i vettori siano normalizzati + if ( ! ( vtVCyl.IsNormalized() && vtVLine.IsNormalized())) { + nIntType = S_ERROR_INT ; + return nIntType ; + } + + // Caso in cui i vettori della retta e del cilindro sono paralleli + if ( ( ( vtVLine * vtVCyl) * vtVCyl).SqLen() > 1 - EPS_ZERO * EPS_ZERO) { + + double dRadialDist = ( ( ptPLine - ptPCyl) - ( ( ptPLine - ptPCyl) * vtVCyl) * vtVCyl).Len() ; + // La retta appartiene al cilindro + if ( abs( dRadialDist - dCylRad) < EPS_SMALL) { + + nIntType = CC_INF_INT ; + dU1 = - INFINITO ; + dU2 = INFINITO ; + return nIntType ; + } + // non vi è intersezione + else { + nIntType = CC_NO_INTERS ; + return nIntType ; + } + } + + std::vector vdCoef(3) ; + std::vector vdRoots ; + // Setto i coefficienti dell'equazione + vdCoef[0] = ( ptPLine - ptPCyl).SqLen() - ( ( ptPLine - ptPCyl) * vtVCyl) * ( ( ptPLine - ptPCyl) * vtVCyl) + - dCylRad * dCylRad ; + vdCoef[1] = 2 * ( ( ptPLine - ptPCyl) * vtVLine - ( ( ptPLine - ptPCyl) * vtVCyl) * ( vtVCyl * vtVLine) ) ; + vdCoef[2] = 1 - ( vtVCyl * vtVLine) * ( vtVCyl * vtVLine) ; + // Risolvo l'equazione + int nRoot = PolynomialRoots( 2, vdCoef, vdRoots) ; + // Non vi sono intersezioni + if ( nRoot == 0) + nIntType = CC_NO_INTERS ; + // C'è un punto di tangenza + else if ( nRoot == 1) { + dU1 = vdRoots[0] ; + nIntType = CC_ONE_INT_TAN ; + } + // L'equazione ha due soluzioni, bisogna + // valutare se sono den distinte. + else if ( nRoot == 2) { + dU1 = vdRoots[0] ; + dU2 = vdRoots[1] ; + if ( dU1 > dU2) + std::swap( dU1, dU2) ; + // Soluzioni sufficientemente lontane: + // ci sono due intersezioni + if ( dU2 - dU1 > EPS_SMALL) + nIntType = CC_TWO_INT ; + // Soluzioni non sufficientemente lontane: + // c'è un punto di tangenza. + else + nIntType = CC_ONE_INT_TAN ; + } + return nIntType ; +} + +//---------------------------------------------------------------------------- +int RayInfiniteCylinder( const Point3d& ptPCyl, const Point3d& ptPLine, const Vector3d& vtVCyl, const Vector3d& vtVLine, + double dCylRad, double& dU1, double& dU2) +{ + int nIntType = LineInfiniteCylinder( ptPCyl, ptPLine, vtVCyl, vtVLine, dCylRad, dU1, dU2) ; + if ( nIntType == CC_ERROR_INT) + return nIntType ; + + // Se la retta associata appartiene al + // cilindro, solo il parametro di inizio + // deve essere modificato + if ( nIntType == CC_INF_INT) + dU1 = 0 ; + // La retta associata è tangente: se la tangenza + // ha parametro negativo, la semi-retta non interferisce + else if ( nIntType == CC_ONE_INT_TAN) { + if ( dU1 < - EPS_SMALL) + nIntType = CC_NO_INTERS ; + } + // La retta associata è secante + else if ( nIntType == CC_TWO_INT) { + // Se dU1 è negativo, solo dU2 è accettabile + // assegno dU2 a dU1 + if ( dU1 < - EPS_SMALL) { + dU1 = dU2 ; + nIntType = CC_ONE_INT_SEC ; + } + // Se anche dU2 è negativo la + // la semi-retta non interferisce + if ( dU2 < - EPS_SMALL) + nIntType = CC_NO_INTERS ; + } + return nIntType ; +} + +//---------------------------------------------------------------------------- +int SegmentInfiniteCylinder( const Point3d& ptPCyl, const Point3d& ptPLine, const Vector3d& vtVCyl, const Vector3d& vtVLine, + double dCylRad, double dLen, double& dU1, double& dU2) +{ + int nIntType = LineInfiniteCylinder( ptPCyl, ptPLine, vtVCyl, vtVLine, dCylRad, dU1, dU2) ; + if ( nIntType == CC_ERROR_INT) + return nIntType ; + + // La retta associata al segmento + // appartiene al cilindro. + if ( nIntType == CC_INF_INT) { + dU1 = 0 ; + dU2 = dLen ; + } + // La retta associata al segmento + // è tangente al cilindro. + else if ( nIntType == CC_ONE_INT_TAN) { + // Sel il parametro è fuori intervallo il + // segmento non interferisce con il cilindro. + if ( dU1 < - EPS_SMALL || dU1 > dLen + EPS_SMALL) + nIntType = CC_NO_INTERS ; + } + // La retta associata al segmento è + // secante al cilindro + else if ( nIntType == CC_TWO_INT) { + // Segmento non interagente + if ( dU1 > dLen + EPS_SMALL) + nIntType = CC_NO_INTERS ; + else if ( dU1 > - EPS_SMALL) { + // Segmento secante in dU1 + if ( dU2 > dLen + EPS_SMALL) + nIntType = CC_ONE_INT_SEC ; + } + else { + // Segmento non interagente + if ( dU2 > dLen + EPS_SMALL) { + nIntType = CC_NO_INTERS ; + } + // Segmento secante in dU2 + else if ( dU2 > - EPS_SMALL) { + dU1 = dU2 ; + nIntType = CC_ONE_INT_SEC ; + } + // Segmento non interagente + else + nIntType = CC_NO_INTERS ; + } + } + return nIntType ; +} + +//---------------------------------------------------------------------------- +int LineSemiFiniteCylinder( const Point3d& ptPCyl, const Point3d& ptPLine, const Vector3d& vtVCyl, const Vector3d& vtVLine, + double dCylRad, double& dU1, double& dU2) +{ + int nIntType = LineInfiniteCylinder( ptPCyl, ptPLine, vtVCyl, vtVLine, dCylRad, dU1, dU2) ; + if ( nIntType == CC_ERROR_INT) + return nIntType ; + + // Caso parte della retta appartenente al cilindro + if ( nIntType == CC_INF_INT) { + // Retta e cilindro equiversi + if ( vtVCyl * vtVLine > 0) + dU1 = ( ptPLine - ptPCyl) * vtVCyl ; + // Retta e cilindro controversi + else { + dU1 = - INFINITO ; + dU2 = ( ptPLine - ptPCyl) * vtVCyl ; + } + } + // Caso retta tangente + else if ( nIntType == CC_ONE_INT_TAN) { + // Se il punto di tangenza è fuori dalla parte + // ammissibile del cilindro, rigetto la soluzione + Point3d ptInt = ptPLine + dU1 * vtVLine ; + if ( ( ptInt - ptPCyl) * vtVCyl < 0) + nIntType = CC_NO_INTERS ; + } + // Caso di due intersezioni + else if ( nIntType == CC_TWO_INT) { + // Rigetto le soluzioni fuori dalla + // regione ammissibile del cilindro. + Point3d ptInt1 = ptPLine + dU1 * vtVLine ; + Point3d ptInt2 = ptPLine + dU2 * vtVLine ; + int nSolNum = 2 ; + if ( ( ptInt1 - ptPCyl) * vtVCyl < 0) { + -- nSolNum ; + dU1 = dU2 ; + } + if ( ( ptInt2 - ptPCyl) * vtVCyl < 0) + -- nSolNum ; + // Dal numero di soluzioni rimaste + // aggiorno la tipologia di interferenza. + if ( nSolNum == 1) + nIntType = CC_ONE_INT_SEC ; + else if ( nSolNum == 0) + nIntType = CC_NO_INTERS ; + } + return nIntType ; +} + +//---------------------------------------------------------------------------- +int RaySemiFiniteCylinder( const Point3d& ptPCyl, const Point3d& ptPLine, const Vector3d& vtVCyl, const Vector3d& vtVLine, + double dCylRad, double& dU1, double& dU2) +{ + int nIntType = LineSemiFiniteCylinder( ptPCyl, ptPLine, vtVCyl, vtVLine, dCylRad, dU1, dU2) ; + if ( nIntType == CC_ERROR_INT) + return nIntType ; + + // Parte della semi-retta appartiene al cilindro + if ( nIntType == CC_INF_INT) { + // La semi-retta non interferisce + if ( dU2 < - EPS_SMALL) + nIntType = CC_NO_INTERS ; + // La semi-retta incomincia nel cilindro + else if ( dU1 < - EPS_SMALL) + dU1 = 0 ; + } + // La retta associata è tangente + // o secante in un punto. + else if ( nIntType == CC_ONE_INT_SEC || + nIntType == CC_ONE_INT_TAN) { + // Se il parametro è negativo, + // scarto la soluzione. + if ( dU1 < - EPS_SMALL) + nIntType = CC_NO_INTERS ; + } + // Retta associata secante + else if ( nIntType == CC_TWO_INT) { + int nSolNum = 2 ; + if ( dU1 < - EPS_SMALL) { + dU1 = dU2 ; + -- nSolNum ; + } + if ( dU2 < - EPS_SMALL) + -- nSolNum ; + // Dal numero di soluzioni rimaste + // aggiorno la tipologia di interferenza. + if ( nSolNum == 1) + nIntType = CC_ONE_INT_SEC ; + else if ( nSolNum == 0) + nIntType = CC_NO_INTERS ; + } + return nIntType ; +} + +//---------------------------------------------------------------------------- +int SegmentSemiFiniteCylinder( const Point3d& ptPCyl, const Point3d& ptPLine, const Vector3d& vtVCyl, const Vector3d& vtVLine, + double dCylRad, double dLen, double& dU1, double& dU2) +{ + int nIntType = LineSemiFiniteCylinder( ptPCyl, ptPLine, vtVCyl, vtVLine, dCylRad, dU1, dU2) ; + if ( nIntType == CC_ERROR_INT) + return nIntType ; + + // Parte della retta associata + // appartiene al cilindro. + if ( nIntType == CC_INF_INT) { + // Il segmento non interferisce + if ( dU1 > dLen + EPS_SMALL) + nIntType = CC_NO_INTERS ; + else if ( dU1 > - EPS_SMALL) { + // Il segmento termina nel cilindro + if ( dU2 > dLen + EPS_SMALL) + dU2 = dLen ; + } + else { + // Il segmento contenuto totalmente + if ( dU2 > dLen + EPS_SMALL) { + dU1 = 0 ; + dU2 = dLen ; + } + // Il segmento comincia nel cilindro + else if ( dU2 > - EPS_SMALL) + dU1 = 0 ; + // Il segmeno non interferisce + else + nIntType = CC_NO_INTERS ; + } + } + // La retta associata è tangente + // o secante in un punto. + else if ( nIntType == CC_ONE_INT_SEC || + nIntType == CC_ONE_INT_TAN) { + // Il sgmento non interferisce + if ( dU1 < 0 || dU1 > dLen) + nIntType = CC_NO_INTERS ; + } + // La retta associata è secante + else if ( nIntType == CC_TWO_INT) { + // Il segmento non interferisce + if ( dU1 > dLen + EPS_SMALL) + nIntType = CC_NO_INTERS ; + else if ( dU1 > - EPS_SMALL) { + // Segmento secante in dU1 + if ( dU2 > dLen + EPS_SMALL) + nIntType = CC_ONE_INT_SEC ; + } + else { + // Il segmento non interagisce + if ( dU2 > dLen + EPS_SMALL) { + nIntType = CC_NO_INTERS ; + } + // Il segmento è secante in dU2, + // assegno dU2 a dU1. + else if ( dU2 > - EPS_SMALL) { + dU1 = dU2 ; + nIntType = CC_ONE_INT_SEC ; + } + // Il segmento non interferisce + else + nIntType = CC_NO_INTERS ; + } + } + return nIntType ; +} + +//---------------------------------------------------------------------------- +int LineCylinder( const Point3d& ptPCyl, const Point3d& ptPLine, const Vector3d& vtVCyl, const Vector3d& vtVLine, + double dCylRad, double dCylHeigth, double& dU1, double& dU2) +{ + int nIntType = LineInfiniteCylinder( ptPCyl, ptPLine, vtVCyl, vtVLine, dCylRad, dU1, dU2) ; + if ( nIntType == CC_ERROR_INT) + return nIntType ; + + // Parte della retta appartenente al cilindro + if ( nIntType == CC_INF_INT) { + dU1 = ( ptPCyl- ptPLine) * vtVLine ; + // Retta e cilindro equiversi + if ( vtVCyl * vtVLine > 0) + dU2 = dU1 + dCylHeigth ; + // Retta e cilindro controversi + else + dU2 = dU1 - dCylHeigth ; + } + // Caso di un punto di tangenza + else if ( nIntType == CC_ONE_INT_TAN) { + // Se il punto di tangenza è fuori dalla parte + // ammissibile del cilindro, rigetto la soluzione + Point3d ptInt = ptPLine + dU1 * vtVLine ; + if ( ( ptInt - ptPCyl) * vtVCyl < 0 || + ( ptInt - ptPCyl) * vtVCyl > dCylHeigth) + nIntType = CC_NO_INTERS ; + } + // Caso di due intersezioni + else if ( nIntType == CC_TWO_INT) { + // Rigetto le soluzioni fuori dalla + // regione ammissibile del cilindro. + Point3d ptInt1 = ptPLine + dU1 * vtVLine ; + Point3d ptInt2 = ptPLine + dU2 * vtVLine ; + int nSolNum = 2 ; + if ( ( ptInt1 - ptPCyl) * vtVCyl < 0 || + ( ptInt1 - ptPCyl) * vtVCyl > dCylHeigth) { + -- nSolNum ; + dU1 = dU2 ; + } + if ( ( ptInt2 - ptPCyl) * vtVCyl < 0 || + ( ptInt2 - ptPCyl) * vtVCyl > dCylHeigth) + -- nSolNum ; + // Dal numero di soluzioni rimaste + // aggiorno la tipologia di interferenza. + if ( nSolNum == 1) + nIntType = CC_ONE_INT_SEC ; + else if ( nSolNum == 0) + nIntType = CC_NO_INTERS ; + } + return nIntType ; +} + +//---------------------------------------------------------------------------- +int RayCylinder( const Point3d& ptPCyl, const Point3d& ptPLine, const Vector3d& vtVCyl, const Vector3d& vtVLine, + double dCylRad, double dCylHeigth, double& dU1, double& dU2) +{ + int nIntType = LineCylinder( ptPCyl, ptPLine, vtVCyl, vtVLine, dCylRad, dCylHeigth, dU1, dU2) ; + if ( nIntType == CC_ERROR_INT) + return nIntType ; + + // Parte della retta associata + // appartiene al cilindro + if ( nIntType == CC_INF_INT) { + // Semi-retta non interferisce + if ( dU2 < - EPS_SMALL) + nIntType = CC_NO_INTERS ; + // La semi-retta comincia nel cilindro + else if ( dU1 < - EPS_SMALL) + dU1 = 0 ; + } + // Retta associata tangente + else if ( nIntType == CC_ONE_INT_TAN) { + if ( dU1 < - EPS_SMALL) + nIntType = CC_NO_INTERS ; + } + else if ( nIntType == CC_TWO_INT) { + // Scarto soluzioni con parametro negativo + int nSolNum = 2 ; + if ( dU1 < - EPS_SMALL) { + dU1 = dU2 ; + -- nSolNum ; + } + if ( dU2 < - EPS_SMALL) + -- nSolNum ; + // Dal numero di soluzioni rimaste + // aggiorno la tipologia di interferenza. + if ( nSolNum == 1) + nIntType = CC_ONE_INT_SEC ; + else if ( nSolNum == 0) + nIntType = CC_NO_INTERS ; + } + return nIntType ; +} + +//---------------------------------------------------------------------------- +int SegmentCylinder( const Point3d& ptPCyl, const Point3d& ptPLine, const Vector3d& vtVCyl, const Vector3d& vtVLine, + double dCylRad, double dCylHeigth, double dLen, double& dU1, double& dU2) +{ + int nIntType = LineCylinder( ptPCyl, ptPLine, vtVCyl, vtVLine, dCylRad, dCylHeigth, dU1, dU2) ; + if ( nIntType == CC_ERROR_INT) + return nIntType ; + + // Parte della retta associata + // appartiene al cilindro + if ( nIntType == CC_INF_INT) { + // Segmento non interferisce + if ( dU1 > dLen + EPS_SMALL) + nIntType = CC_NO_INTERS ; + else if ( dU1 > - EPS_SMALL) { + if ( dU2 > dLen + EPS_SMALL) + dU2 = dLen ; + } + else { + // Segmento non interferisce + if ( dU2 < - EPS_SMALL) + nIntType = CC_NO_INTERS ; + // Il segmento comincia nel cilindro + else { + dU1 = 0 ; + // Il segmento termina nel cilindro + if ( dU2 > dLen + EPS_SMALL) + dU2 = dLen ; + } + } + } + // La retta associata è tangente al cilindro + else if ( nIntType == CC_ONE_INT_TAN) { + // Segmento non interferisce + if ( dU1 < - EPS_SMALL || dU1 > dLen + EPS_SMALL) + nIntType = CC_NO_INTERS ; + } + // Retta associata è secante + else if ( nIntType == CC_TWO_INT) { + // Il segmento non interferisce + if ( dU1 > dLen + EPS_SMALL) + nIntType = CC_NO_INTERS ; + else if ( dU1 > - EPS_SMALL) { + // Segmento secante in dU1 + if ( dU2 > dLen + EPS_SMALL) + nIntType = CC_ONE_INT_SEC ; + } + else { + // Il segmento non interagisce + if ( dU2 > dLen + EPS_SMALL) { + nIntType = CC_NO_INTERS ; + } + // Il segmento è secante in dU2, + // assegno dU2 a dU1. + else if ( dU2 > - EPS_SMALL) { + dU1 = dU2 ; + nIntType = CC_ONE_INT_SEC ; + } + // Il segmento non interferisce + else + nIntType = CC_NO_INTERS ; + } + } + return nIntType ; +} + +//---------------------------------------------------------------------------- +int LineInfiniteCone( const Point3d& ptVCone, const Point3d& ptPLine, const Vector3d& vtDCone, const Vector3d& vtDLine, + double dConeRad, double dConeHeigth, double& dU1, double& dU2) +{ + int nIntType ; + // Raggio e altezza del cono devono essere maggiori di zero + if ( ! ( dConeRad > EPS_SMALL && dConeHeigth > EPS_SMALL)) { + nIntType = CC_ERROR_INT ; + return nIntType ; + } + // Tangnte dell'angolo semi-apertura del cono + double dTanTheta = dConeRad / dConeHeigth ; + // Il coseno deve essere positivo + if ( ! ( dTanTheta > 0 && dTanTheta * dTanTheta < 1 / ( EPS_SMALL * EPS_SMALL) - 1)) { + nIntType = CC_ERROR_INT ; + return nIntType ; + } + + // Si richiede che i vettori siano normalizzati + if ( ! ( vtDCone.IsNormalized() && vtDLine.IsNormalized())) { + nIntType = CC_ERROR_INT ; + return nIntType ; + } + + // Lunghezze delle componenti parallela e ortogonale del + // vettore della retta rispetto all'asse del cilindro. + double dDLong = vtDLine * vtDCone ; + double dDOrt = (vtDLine - dDLong * vtDCone).Len() ; + // Flag parallelismo fra la retta e una retta generatrice del cono. + bool bSameAngle = abs( dDLong) > EPS_ZERO && abs( dDOrt / abs( dDLong) - dTanTheta) < EPS_ZERO ; + if ( bSameAngle) { + // Valuto se parte della retta appartiene al cono. + Vector3d vtOO = ptVCone - ptPLine ; + Vector3d vtOOPerp = vtOO - ( vtOO * vtDLine) * vtDLine ; + // Caso in cui la retta appartiene al cono + if ( vtOOPerp.SqLen() < EPS_SMALL * EPS_SMALL) { + // Calcolo il parametro a cui si trova il + // vertice del cono lungo la retta. + if ( vtDLine * vtDCone > 0) { + dU1 = vtOO * vtDLine ; + dU2 = INFINITO ; + } + else { + dU1 = - INFINITO ; + dU2 = vtOO * vtDLine ; + } + nIntType = CC_INF_INT ; + return nIntType ; + } + // Vertice del cono non sta sulla retta + else { + double dC0 = ( ptPLine - ptVCone) * ( ptPLine - ptVCone) - + ( 1 + dTanTheta * dTanTheta) * ( ( ptPLine - ptVCone) * vtDCone) * ( ( ptPLine - ptVCone) * vtDCone) ; + double dC1 = 2 * ( vtDLine * ( ptPLine - ptVCone) - + ( 1 + dTanTheta * dTanTheta) * ( vtDCone * vtDLine) * ( ptPLine - ptVCone) * vtDCone) ; + if ( abs( dC1) > EPS_ZERO) { + dU1 = - dC0 / dC1 ; + Point3d ptInt = ptPLine + dU1 * vtDLine ; + // Se la soluzione è sulla falda negativa deve essere eliminata. + if ( ( ptInt - ptVCone) * vtDCone < 0) + return CC_NO_INTERS ; + return CC_ONE_INT_SEC ; + } + else if ( abs( dC0) > EPS_SMALL) + return CC_NO_INTERS ; + } + } + + std::vector vdCoef(3) ; + std::vector vdRoots ; + // Setto i coefficienti dell'equazione + vdCoef[0] = ( ptPLine - ptVCone) * ( ptPLine - ptVCone) - + ( 1 + dTanTheta * dTanTheta) * ( ( ptPLine - ptVCone) * vtDCone) * ( ( ptPLine - ptVCone) * vtDCone) ; + vdCoef[1] = 2 * ( vtDLine * ( ptPLine - ptVCone) - + ( 1 + dTanTheta * dTanTheta) * ( vtDCone * vtDLine) * ( ptPLine - ptVCone) * vtDCone) ; + vdCoef[2] = 1 - ( 1 + dTanTheta * dTanTheta) * ( vtDCone * vtDLine) * ( vtDCone * vtDLine) ; + + // Risolvo l'equazione + int nRoot = PolynomialRoots( 2, vdCoef, vdRoots) ; + // Studio le soluzioni + if ( nRoot == 0) + nIntType = CC_NO_INTERS ; + else if ( nRoot == 1) { + dU1 = vdRoots[0] ; + Point3d ptInt = ptPLine + dU1 * vtDLine ; + // Soluzione sul cono negativo + if ( ( ptInt - ptVCone) * vtDCone < 0) + nIntType = CC_NO_INTERS ; + // Soluzione sul vertice + else if ( SqDist( ptInt, ptVCone) < EPS_SMALL * EPS_SMALL) + nIntType = CC_ON_VERT ; + // Retta parallela e secante in un punto + else if ( bSameAngle) + nIntType = CC_ONE_INT_SEC ; + // Retta tangente al cono + else + nIntType = CC_ONE_INT_TAN ; + } + else if ( nRoot == 2) { + dU1 = vdRoots[0] ; + dU2 = vdRoots[1] ; + if ( dU1 > dU2) + std::swap( dU1, dU2) ; + // Se le soluzioni non sono sufficientemente lontane, + // la soluzione è di tangenza + if ( dU2 - dU1 < EPS_SMALL * EPS_SMALL) { + Point3d ptInt1 = ptPLine + dU1 * vtDLine ; + // Soluzione sul cono negativo + if ( ( ptInt1 - ptVCone) * vtDCone < 0) + nIntType = CC_NO_INTERS ; + // Soluzione sul vertice + else if ( SqDist( ptInt1, ptVCone) < EPS_SMALL * EPS_SMALL) + nIntType = CC_ON_VERT ; + // Retta parallela e secante in un punto + else if ( bSameAngle) + nIntType = CC_ONE_INT_SEC ; + // Retta tangente al cono + else + nIntType = CC_ONE_INT_TAN ; + } + // Soluzioni ben distinte + else { + Point3d ptInt1 = ptPLine + dU1 * vtDLine ; + Point3d ptInt2 = ptPLine + dU2 * vtDLine ; + // Elimino le soluzioni sul cono negativo + int nNumSol = 2 ; + if ( ( ptInt2 - ptVCone) * vtDCone < 0) + -- nNumSol ; + if ( ( ptInt1 - ptVCone) * vtDCone < 0) { + -- nNumSol ; + dU1 = dU2 ; + } + // Dal numero di soluzioni rimaste + // aggiorno la tipologia di interferenza. + if ( nNumSol == 0) + nIntType = CC_NO_INTERS ; + else if ( nNumSol == 1) + nIntType = CC_ONE_INT_SEC ; + else if ( nNumSol == 2) + nIntType = CC_TWO_INT ; + } + } + return nIntType ; +} + +//---------------------------------------------------------------------------- +int RayInfiniteCone( const Point3d& ptVCone, const Point3d& ptPLine, const Vector3d& vtDCone, const Vector3d& vtDLine, + double dConeRad, double dConeHeigth, double& dU1, double& dU2) +{ + int nIntType = LineInfiniteCone( ptVCone, ptPLine, vtDCone, vtDLine, dConeRad, dConeHeigth, dU1, dU2) ; + if ( nIntType == CC_ERROR_INT) + return nIntType ; + + // Parte della retta associata + // appartiene al cono. + if ( nIntType == CC_INF_INT) { + if ( vtDLine * vtDCone > 0) { + // Semi-retta comincia nel cono + if ( dU1 < 0) + dU1 = 0 ; + } + else { + // Semiretta non interferisce + // con il cono. + if ( dU2 < 0) + nIntType = CC_NO_INTERS ; + // Semi-retta comincia nel cono + else + dU1 = 0 ; + } + } + // Retta associata interferisce in un punto + else if ( nIntType == CC_ONE_INT_TAN || + nIntType == CC_ONE_INT_SEC || + nIntType == CC_ON_VERT) { + // Semi-retta non interferisce + if ( dU1 < - EPS_SMALL) + nIntType = CC_NO_INTERS ; + } + // Retta associata interferisce in due punti. + else if ( nIntType == CC_TWO_INT) { + // Semi-retta non interferisce + if ( dU2 < - EPS_SMALL) + nIntType = CC_NO_INTERS ; + // Semi-retta secante in un punto + else if ( dU1 < - EPS_SMALL) + nIntType = CC_ONE_INT_SEC ; + } + return nIntType ; +} + +//---------------------------------------------------------------------------- +int SegmentInfiniteCone( const Point3d& ptVCone, const Point3d& ptPLine, const Vector3d& vtDCone, const Vector3d& vtDLine, + double dConeRad, double dConeHeigth, double dSgLen, double& dU1, double& dU2) +{ + int nIntType = LineInfiniteCone( ptVCone, ptPLine, vtDCone, vtDLine, dConeRad, dConeHeigth, dU1, dU2) ; + if ( nIntType == CC_ERROR_INT) + return nIntType ; + + // Parte della retta associata + // appartiene al cono + if ( nIntType == CC_INF_INT) { + // Il segmento non interferisce + if ( dU1 > dSgLen + EPS_SMALL) + nIntType = CC_NO_INTERS ; + else if ( dU1 > - EPS_SMALL) { + // Il segmento termina nel cono + if ( dU2 > dSgLen + EPS_SMALL) + dU2 = dSgLen ; + } + else { + // Il segmento contenuto totalmente + if ( dU2 > dSgLen + EPS_SMALL) { + dU1 = 0 ; + dU2 = dSgLen ; + } + // Il segmento comincia nel cono + else if ( dU2 > - EPS_SMALL) + dU1 = 0 ; + // Il segmeno non interferisce + else + nIntType = CC_NO_INTERS ; + } + } + // Retta associata interferisce in un punto + else if ( nIntType == CC_ONE_INT_TAN || + nIntType == CC_ONE_INT_SEC || + nIntType == CC_ON_VERT) { + // Segmento non interagente + if ( dU1 < - EPS_SMALL || dU1 > dSgLen + EPS_SMALL) + nIntType = CC_NO_INTERS ; + } + // Retta associata interferisce in due punti. + else if ( nIntType == CC_TWO_INT) { + // Il segmento non interferisce + if ( dU1 > dSgLen + EPS_SMALL) + nIntType = CC_NO_INTERS ; + else if ( dU1 > - EPS_SMALL) { + // Segmento secante in dU1 + if ( dU2 > dSgLen + EPS_SMALL) + nIntType = CC_ONE_INT_SEC ; + } + else { + // Il segmento non interagisce + if ( dU2 > dSgLen + EPS_SMALL) { + nIntType = CC_NO_INTERS ; + } + // Il segmento è secante in dU2, + // assegno dU2 a dU1. + else if ( dU2 > - EPS_SMALL) { + dU1 = dU2 ; + nIntType = CC_ONE_INT_SEC ; + } + // Il segmento non interferisce + else + nIntType = CC_NO_INTERS ; + } + } + return nIntType ; +} + +//---------------------------------------------------------------------------- +int LineCone( const Point3d& ptVCone, const Point3d& ptPLine, const Vector3d& vtDCone, const Vector3d& vtDLine, + double dConeRad, double dConeHeigth, double& dU1, double& dU2) +{ + int nIntType = LineInfiniteCone( ptVCone, ptPLine, vtDCone, vtDLine, dConeRad, dConeHeigth, dU1, dU2) ; + if ( nIntType == CC_ERROR_INT) + return nIntType ; + // Tangnte dell'angolo semi-apertura del cono + double dTanTheta = dConeRad / dConeHeigth ; + // Parte della retta associata giace sul cono + if ( nIntType == CC_INF_INT) { + double dApothem = dConeHeigth * sqrt( 1 + dTanTheta * dTanTheta) ; + // Retta e asse del cono equiversi + if ( vtDLine * vtDCone > 0) + dU2 = dU1 + dApothem ; + // Retta e asse del cono controversi + else + dU1 = dU2 - dApothem ; + } + // Retta e il cono infinito interagiscono in un punto + else if ( nIntType == CC_ONE_INT_TAN || + nIntType == CC_ONE_INT_SEC || + nIntType == CC_ON_VERT) { + // Se la soluzione è fuori dal cono la rigetto + Point3d ptInt = ptPLine + dU1 * vtDLine ; + if ( ( ptInt - ptVCone) * vtDCone > dConeHeigth) + nIntType = CC_NO_INTERS ; ; + } + // Retta e il cono infinito interagiscono in due punti + else if ( nIntType == CC_TWO_INT) { + // Rigetto le soluzioni fuori dal cono + Point3d ptInt1 = ptPLine + dU1 * vtDLine ; + Point3d ptInt2 = ptPLine + dU2 * vtDLine ; + int nNumSol = 2 ; + if ( ( ptInt2 - ptVCone) * vtDCone > dConeHeigth) + -- nNumSol ; + if ( ( ptInt1 - ptVCone) * vtDCone > dConeHeigth) { + -- nNumSol ; + dU1 = dU2 ; + } + // Dal numero di soluzioni rimaste + // aggiorno la tipologia di interferenza. + if ( nNumSol == 0) + nIntType = CC_NO_INTERS ; + else if ( nNumSol == 1) + nIntType = CC_ONE_INT_SEC ; + else if ( nNumSol == 2) + nIntType = CC_TWO_INT ; + } + return nIntType ; +} + +//---------------------------------------------------------------------------- +int RayCone( const Point3d& ptVCone, const Point3d& ptPLine, const Vector3d& vtDCone, const Vector3d& vtDLine, + double dConeRad, double dConeHeigth, double& dU1, double& dU2) +{ + int nIntType = LineCone( ptVCone, ptPLine, vtDCone, vtDLine, dConeRad, dConeHeigth, dU1, dU2) ; + if ( nIntType == CC_ERROR_INT) + return nIntType ; + // Parte della retta associata + // giace sul cono + if ( nIntType == CC_INF_INT) { + double dApothem = sqrt( dConeRad * dConeRad + dConeHeigth * dConeHeigth) ; + // Semi-retta esterna + if ( dU2 < - EPS_SMALL) + nIntType = CC_NO_INTERS ; + // Una soluzione tangente + else if ( dU2 < EPS_SMALL) { + dU1 = 0 ; + nIntType = CC_ONE_INT_TAN ; + } + // Semi-retta comincia nel cono + else if ( dU2 < dApothem) + dU1 = 0 ; + } + // Retta associata interagisce in un punto + else if ( nIntType == CC_ONE_INT_TAN || + nIntType == CC_ONE_INT_SEC || + nIntType == CC_ON_VERT) { + // Semi-retta esterna + if ( dU1 < - EPS_SMALL) + nIntType = CC_NO_INTERS ; + } + // Retta associata interagisce in due punti + else if ( nIntType == CC_TWO_INT) { + // Se dU1 è negativo, solo dU2 è accettabile + // assegno dU2 a dU1 + if ( dU1 < - EPS_SMALL) { + dU1 = dU2 ; + nIntType = CC_ONE_INT_SEC ; + } + // Se anche dU2 è negativo la + // la semi-retta non interferisce + if ( dU2 < - EPS_SMALL) + nIntType = CC_NO_INTERS ; + } + return nIntType ; +} + +//---------------------------------------------------------------------------- +int SegmentCone( const Point3d& ptVCone, const Point3d& ptPLine, const Vector3d& vtDCone, const Vector3d& vtDLine, + double dConeRad, double dConeHeigth, double dSgLen, double& dU1, double& dU2) +{ + int nIntType = LineCone( ptVCone, ptPLine, vtDCone, vtDLine, dConeRad, dConeHeigth, dU1, dU2) ; + if ( nIntType == CC_ERROR_INT) + return nIntType ; + + if ( nIntType == CC_INF_INT) { + // Segmento non interferisce + if ( dU1 > dSgLen + EPS_SMALL) + nIntType = CC_NO_INTERS ; + else if ( dU1 > - EPS_SMALL) { + if ( dU2 > dSgLen + EPS_SMALL) + dU2 = dSgLen ; + } + else { + // Segmento non interferisce + if ( dU2 < - EPS_SMALL) + nIntType = CC_NO_INTERS ; + // Il segmento comincia nel cono + else { + dU1 = 0 ; + // Il segmento termina nel cono + if ( dU2 > dSgLen + EPS_SMALL) + dU2 = dSgLen ; + } + } + } + // Retta associata interagisce in un punto + else if ( nIntType == CC_ONE_INT_TAN || + nIntType == CC_ONE_INT_SEC || + nIntType == CC_ON_VERT) { + // Segmento non interferisce + if ( dU1 < - EPS_SMALL || dU1 > dSgLen + EPS_SMALL) + nIntType = CC_NO_INTERS ; + } + // Retta associata interagisce in due punti + else if ( nIntType == CC_TWO_INT) { + // Il segmento non interferisce + if ( dU1 > dSgLen + EPS_SMALL) + nIntType = CC_NO_INTERS ; + else if ( dU1 > - EPS_SMALL) { + // Segmento secante in dU1 + if ( dU2 > dSgLen + EPS_SMALL) + nIntType = CC_ONE_INT_SEC ; + } + else { + // Il segmento non interagisce + if ( dU2 > dSgLen + EPS_SMALL) { + nIntType = CC_NO_INTERS ; + } + // Il segmento è secante in dU2, + // assegno dU2 a dU1. + else if ( dU2 > - EPS_SMALL) { + dU1 = dU2 ; + nIntType = CC_ONE_INT_SEC ; + } + // Il segmento non interferisce + else + nIntType = CC_NO_INTERS ; + } + } + return nIntType ; +} + +//---------------------------------------------------------------------------- +int LineTruncatedCone( const Point3d& ptMinBase, const Point3d& ptPLine, const Vector3d& vtDCone, const Vector3d& vtDLine, + double dMinRad, double dMaxRad, double dHeigth, double& dU1, double& dU2) +{ + // Controlli sull'ammissibilità del tronco di cono + if ( ! ( dMinRad > EPS_SMALL && dMaxRad > EPS_SMALL && dHeigth > EPS_SMALL)) + return CC_ERROR_INT ; + + double dDeltaH = dMinRad * dHeigth / ( dMaxRad - dMinRad) ; + Point3d ptVCone = ptMinBase - dDeltaH * vtDCone ; + + int nIntType = LineInfiniteCone( ptVCone, ptPLine, vtDCone, vtDLine, dMinRad, dDeltaH, dU1, dU2) ; + if ( nIntType == CC_ERROR_INT) + return nIntType ; + + // Parte della retta associata giace sul cono + if ( nIntType == CC_INF_INT) { + + double dMinApo = sqrt( dDeltaH * dDeltaH + dMinRad * dMinRad) ; + double dMaxApo = sqrt( ( dDeltaH + dHeigth) * ( dDeltaH + dHeigth) + dMaxRad * dMaxRad) ; + // Retta e vettore cono equiversi + if ( vtDLine * vtDCone > 0) { + double dSignedLenOO = ( ptPLine - ptVCone) * vtDLine ; + dU1 = dMinApo - dSignedLenOO ; + dU2 = dMaxApo - dSignedLenOO ; + } + // Retta e vettore cono controversi + else { + double dSignedLenOO = ( ptPLine - ptVCone) * vtDLine ; + dU1 = - dMaxApo - dSignedLenOO ; + dU2 = - dMinApo - dSignedLenOO ; + } + } + // Retta associata interagisce in un punto + else if ( nIntType == CC_ONE_INT_TAN || + nIntType == CC_ONE_INT_SEC || + nIntType == CC_ON_VERT) { + + Point3d ptInt = ptPLine + dU1 * vtDLine ; + + if ( ( ptInt - ptVCone) * vtDCone < dDeltaH - EPS_SMALL || + ( ptInt - ptVCone) * vtDCone > dDeltaH + dHeigth + EPS_SMALL) + nIntType = CC_NO_INTERS ; + } + // Retta associata interagisce in due punti + else if ( nIntType == CC_TWO_INT) { + // Elimino le soluzioni da fuori dal tronco + Point3d ptInt1 = ptPLine + dU1 * vtDLine ; + Point3d ptInt2 = ptPLine + dU2 * vtDLine ; + int nNumSol = 2 ; + if ( ( ptInt2 - ptVCone) * vtDCone < dDeltaH || + ( ptInt2 - ptVCone) * vtDCone > dDeltaH + dHeigth) + -- nNumSol ; + if ( ( ptInt1 - ptVCone) * vtDCone < dDeltaH || + ( ptInt1 - ptVCone) * vtDCone > dDeltaH + dHeigth) { + -- nNumSol ; + dU1 = dU2 ; + } + // Dal numero di soluzioni rimaste + // aggiorno la tipologia di interferenza. + if ( nNumSol == 0) + nIntType = CC_NO_INTERS ; + else if ( nNumSol == 1) + nIntType = CC_ONE_INT_SEC ; + else if ( nNumSol == 2) + nIntType = CC_TWO_INT ; + } + return nIntType ; +} + +//---------------------------------------------------------------------------- +int RayTruncatedCone( const Point3d& ptMinBase, const Point3d& ptPLine, const Vector3d& vtDCone, const Vector3d& vtDLine, + double dMinRad, double dMaxRad, double dHeigth, double& dU1, double& dU2) +{ + int nIntType = LineTruncatedCone( ptMinBase, ptPLine, vtDCone, vtDLine, dMinRad, dMaxRad, dHeigth, dU1, dU2) ; + if ( nIntType == CC_ERROR_INT) + return nIntType ; + + // Parte della retta associata giace sul tronco di cono + if ( nIntType == CC_INF_INT) { + double dDeltaH = dMinRad * dHeigth / ( dMaxRad - dMinRad) ; + double dMinApo = sqrt( dDeltaH * dDeltaH + dMinRad * dMinRad) ; + double dMaxApo = sqrt( ( dDeltaH + dHeigth) * ( dDeltaH + dHeigth) + dMaxRad * dMaxRad) ; + // Semi-retta non interagisce + if ( dU2 < - EPS_SMALL) + nIntType = CC_NO_INTERS ; + // Semi-retta parte sul bordo del tronco + else if ( dU2 < EPS_SMALL) { + dU1 = 0 ; + nIntType = CC_ONE_INT_TAN ; + } + // Semi-retta comincia nel tronco + else if ( dU2 < dMaxApo - dMinApo) + dU1 = 0 ; + } + // Retta associata interagisce in un punto + else if ( nIntType == CC_ONE_INT_TAN || + nIntType == CC_ONE_INT_SEC || + nIntType == CC_ON_VERT) { + // Semi-retta non interagisce + if ( dU1 < - EPS_SMALL) + nIntType = CC_NO_INTERS ; + } + // Retta associata interagisce in un punto + else if ( nIntType == CC_TWO_INT) { + // Se dU1 è negativo, solo dU2 è accettabile + // assegno dU2 a dU1 + if ( dU1 < - EPS_SMALL) { + dU1 = dU2 ; + nIntType = CC_ONE_INT_SEC ; + } + // Se anche dU2 è negativo la + // la semi-retta non interferisce + if ( dU2 < - EPS_SMALL) + nIntType = CC_NO_INTERS ; + } + return nIntType ; +} + +//---------------------------------------------------------------------------- +int SegmentTruncatedCone( const Point3d& ptMinBase, const Point3d& ptPLine, const Vector3d& vtDCone, const Vector3d& vtDLine, + double dMinRad, double dMaxRad, double dHeigth, double dSgLen, double& dU1, double& dU2) +{ + int nIntType = LineTruncatedCone( ptMinBase, ptPLine, vtDCone, vtDLine, dMinRad, dMaxRad, dHeigth, dU1, dU2) ; + if ( nIntType == CC_ERROR_INT) + return nIntType ; + // Parte della retta associata giace sul tronco + if ( nIntType == CC_INF_INT) { + // Segmento non interferisce + if ( dU1 > dSgLen + EPS_SMALL) + nIntType = CC_NO_INTERS ; + else if ( dU1 > - EPS_SMALL) { + if ( dU2 > dSgLen + EPS_SMALL) + dU2 = dSgLen ; + } + else { + // Segmento non interferisce + if ( dU2 < - EPS_SMALL) + nIntType = CC_NO_INTERS ; + // Il segmento comincia nel cilindro + else { + dU1 = 0 ; + // Il segmento termina nel cilindro + if ( dU2 > dSgLen + EPS_SMALL) + dU2 = dSgLen ; + } + } + } + // Retta associata interagisce in un punto + else if ( nIntType == CC_ONE_INT_TAN || + nIntType == CC_ONE_INT_SEC || + nIntType == CC_ON_VERT) { + // Segmento non interferisce + if ( dU1 < - EPS_SMALL || dU1 > dSgLen + EPS_SMALL) + nIntType = CC_NO_INTERS ; + } + // Retta associata interagisce in due punti + else if ( nIntType == CC_TWO_INT) { + // Il segmento non interferisce + if ( dU1 > dSgLen + EPS_SMALL) + nIntType = CC_NO_INTERS ; + else if ( dU1 > - EPS_SMALL) { + // Segmento secante in dU1 + if ( dU2 > dSgLen + EPS_SMALL) + nIntType = CC_ONE_INT_SEC ; + } + else { + // Il segmento non interagisce + if ( dU2 > dSgLen + EPS_SMALL) { + nIntType = CC_NO_INTERS ; + } + // Il segmento è secante in dU2, + // assegno dU2 a dU1. + else if ( dU2 > - EPS_SMALL) { + dU1 = dU2 ; + nIntType = CC_ONE_INT_SEC ; + } + // Il segmento non interferisce + else + nIntType = CC_NO_INTERS ; + } + } + return nIntType ; +} + +//---------------------------------------------------------------------------- +int LineTorus( const Point3d& ptOTorus, const Point3d& ptLine, const Vector3d& vtAxTorus, const Vector3d& vtLine, + double dMinRad, double dMaxRad, std::vector& vdPar, std::vector& vbType) +{ + int nIntType = T_ERROR ; + // Si richiede che i vettori siano normalizzati + if ( ! ( vtAxTorus.IsNormalized() && vtLine.IsNormalized())) + return nIntType ; + // I Raggi devono essere positivi e sufficientemente diversi + if ( dMinRad < EPS_SMALL || dMaxRad < dMinRad + EPS_SMALL) + return nIntType ; + + Point3d ptLn = ptLine ; + Vector3d vtLn = vtLine ; + // Sistema di riferimento del toro + Frame3d frTorusFrame ; + frTorusFrame.Set( ptOTorus, vtAxTorus) ; + // Porto la retta nel sistema di riferimento del toro + ptLn.ToLoc( frTorusFrame) ; + vtLn.ToLoc( frTorusFrame) ; + + std::vector vdCoef(5) ; + std::vector vdRoots ; + // Setto i coefficienti dell'equazione + double dSqDistPO = ptLn.x * ptLn.x + ptLn.y * ptLn.y + ptLn.z * ptLn.z ; + double dPtVt = ptLn.x * vtLn.x + ptLn.y * vtLn.y + ptLn.z * vtLn.z ; + double dSqMaxR = dMaxRad * dMaxRad ; + double dDeltaSqR = dSqMaxR - dMinRad * dMinRad ; + double dB = 2 * dDeltaSqR - 4 * dSqMaxR ; + vdCoef[0] = dSqDistPO * dSqDistPO + dB * ( dSqDistPO - ptLn.z * ptLn.z) + + 2 * dDeltaSqR * ptLn.z * ptLn.z + dDeltaSqR * dDeltaSqR ; + vdCoef[1] = 4 * dPtVt * dSqDistPO + 2 * dB * ( dPtVt - ptLn.z * vtLn.z) + 4 * dDeltaSqR * ptLn.z * vtLn.z ; + vdCoef[2] = 4 * dPtVt * dPtVt + dB * ( 1 - vtLn.z * vtLn.z) + 2 * ( dSqDistPO + dDeltaSqR * vtLn.z * vtLn.z) ; + vdCoef[3] = 4 * dPtVt ; + vdCoef[4] = 1 ; + + // Risolvo l'equazione e ridimensiono il vettore dei parametri + PolynomialRoots( 4, vdCoef, vdRoots) ; + vdPar = vdRoots ; + + // Riordino le soluzioni + for ( int ni = 0 ; ni < int( vdPar.size()) - 1 ; ++ ni) { + for ( int nj = ni ; nj < int( vdPar.size()) ; ++ nj) { + if( vdPar[ni] > vdPar[nj]) { + std::swap( vdPar[ni], vdPar[nj]) ; + } + } + } + + // Studio le soluzioni + if ( vdPar.size() == 0) + nIntType = T_NO_INT ; + else if ( vdPar.size() == 1) { + nIntType = T_ONE_TAN ; + vbType.push_back( false) ; + } + else if ( vdPar.size() == 2) { + // Soluzioni sufficientemente distinte + if ( vdPar[1] - vdPar[0] > EPS_SMALL) { + nIntType = T_TWO_SEC ; + vbType.push_back( true) ; + vbType.push_back( true) ; + } + // Soluzioni coincidenti + else { + vdPar.resize( 1) ; + nIntType = T_ONE_TAN ; + vbType.push_back( false) ; + } + } + else if ( vdPar.size() == 3) { + nIntType = T_THREE_ONE_TAN_TWO_SEC ; + Point3d ptInt1 = ptLn + vdPar[0] * vtLn ; + Point3d ptInt2 = ptLn + vdPar[1] * vtLn ; + Point3d ptInt3 = ptLn + vdPar[2] * vtLn ; + } + else if ( vdPar.size() == 4) { + // Prime due soluzioni distinte + if ( vdPar[1] - vdPar[0] > EPS_SMALL) { + // Seconda e terza soluzione distinta + if ( vdPar[2] - vdPar[1] > EPS_SMALL) { + // Quarta e terza soluzione distinte + // Qauttro secanti + if ( vdPar[3] - vdPar[2] > EPS_SMALL) { + nIntType = T_FOUR_SEC ; + vbType.push_back( true) ; + vbType.push_back( true) ; + vbType.push_back( true) ; + vbType.push_back( true) ; + } + // Quarta e terza soluzione coincidenti + // Secante secante tangente + else { + nIntType = T_THREE_ONE_TAN_TWO_SEC ; + vdPar.resize( 3) ; + vbType.push_back( true) ; + vbType.push_back( true) ; + vbType.push_back( false) ; + } + } + // Seconda e terza soluzione coincidenti + else { + // Secante tangente secante + if ( vdPar[3] - vdPar[2] > EPS_SMALL) { + nIntType = T_THREE_ONE_TAN_TWO_SEC ; + vdPar[2] = vdPar[3] ; + vdPar.resize( 3) ; + vbType.push_back( true) ; + vbType.push_back( false) ; + vbType.push_back( true) ; + } + } + } + // Prime due soluzioni conicidenti + else { + // Terza e quarta soluzione distinte + // Tangente secante secante + if ( vdPar[3] - vdPar[2] > EPS_SMALL) { + nIntType = T_THREE_ONE_TAN_TWO_SEC ; + vdPar[1] = vdPar[2] ; + vdPar[2] = vdPar[3] ; + vdPar.resize( 3) ; + vbType.push_back( false) ; + vbType.push_back( true) ; + vbType.push_back( true) ; + } + // Terza e quarta soluzione distinte + else { + // Secona e terza soluzione distinte + // Tanbente tangente + if ( vdPar[2] - vdPar[1] > EPS_SMALL) { + nIntType = T_TWO_TAN ; + vdPar[1] = vdPar[2] ; + vdPar.resize( 2) ; + vbType.push_back( false) ; + vbType.push_back( false) ; + } + // Seconda e terza soluzione coincidenti + // Una soluzione tangente + else { + nIntType = T_ONE_TAN ; + vdPar[0] = 0.5 * ( vdPar[0] + vdPar[3]) ; + vdPar.resize( 1) ; + vbType.push_back( false) ; + } + } + } + } + return nIntType ; +} + +//---------------------------------------------------------------------------- +int RayTorus( const Point3d& ptOTorus, const Point3d& ptLine, const Vector3d& vtAxTorus, const Vector3d& vtLine, + double dMinRad, double dMaxRad, std::vector& vdPar, std::vector& vbType) +{ + int nIntType = LineTorus( ptOTorus, ptLine, vtAxTorus, vtLine, dMinRad, dMaxRad, vdPar, vbType) ; + if ( nIntType == T_ERROR || nIntType == T_NO_INT) + return nIntType ; + + int nSize = int( vdPar.size()) ; + // Ciclo sui parametri + for ( int n = 0 ; n < nSize ; ++ n) { + // Se il parametro è negativo lo elimino + if ( vdPar[n] < - EPS_SMALL) { + for ( int m = n ; m < nSize - 1 ; ++ m) { + vdPar[m] = vdPar[m+1] ; + vbType[m] = vbType[m+1] ; + } + // Ridimensiono + -- nSize ; + vdPar.resize( nSize) ; + vbType.resize( nSize) ; + // Aggiorno l'indice + -- n ; + } + } + + int nSecNum = 0 ; + // Ciclo sui parametri + for ( int n= 0 ; n < nSize ; ++ n) { + // Se secante ne aumento il numero + if ( vbType[n]) + ++ nSecNum ; + } + + // Numero di puti di tangenza + int nNumTan = nSize - nSecNum ; + // Nessun contatto + if ( nSize == 0) + nIntType = T_NO_INT ; + else if ( nSize == 1) { + // Semi-retta secante in un punto + if ( vbType[0]) + nIntType = T_ONE_SEC ; + else + // Semi-retta tangente in un punto + nIntType = T_ONE_TAN ; + } + else if ( nSize == 2) { + // Semi-retta secante in due punti + if ( nNumTan == 0) + nIntType = T_TWO_SEC ; + // Semi-retta secante in un punto e tangente in un altro + else if ( nNumTan == 1) + nIntType = T_TWO_TAN_SEC ; + // Semi-retta tangente in due punti + else + nIntType = T_TWO_TAN ; + } + else if ( nSize == 3) { + // Semi-retta secante in tre punti + if ( nNumTan == 0) + nIntType = T_THREE_SEC ; + // Semi-retta secante in due punti e tangente in un punto + else if ( nNumTan == 1) + nIntType = T_THREE_ONE_TAN_TWO_SEC ; + // Errore + else + nIntType = T_ERROR ; + } + else if ( nSize == 4) { + // Semi-retta secante in quattro punti + if ( nNumTan == 0) + nIntType = T_FOUR_SEC ; + // Errore + else + nIntType = T_ERROR ; + } + // Errore + else + nIntType = T_ERROR ; + + return nIntType ; +} + +//---------------------------------------------------------------------------- +int SegmentTorus( const Point3d& ptOTorus, const Point3d& ptLine, const Vector3d& vtAxTorus, const Vector3d& vtLine, + double dMinRad, double dMaxRad, double dSgLen, std::vector& vdPar, std::vector& vbType) +{ + int nIntType = LineTorus( ptOTorus, ptLine, vtAxTorus, vtLine, dMinRad, dMaxRad, vdPar, vbType) ; + if ( nIntType == T_ERROR || nIntType == T_NO_INT) + return nIntType ; + + int nSize = int( vdPar.size()) ; + // Ciclo sui parametri + for ( int n = 0 ; n < nSize ; ++ n) { + // Se il parametro è negativo lo elimino + if ( vdPar[n] < - EPS_SMALL || vdPar[n] > dSgLen + EPS_SMALL) { + for ( int m = n ; m < nSize - 1 ; ++ m) { + vdPar[m] = vdPar[m+1] ; + vbType[m] = vbType[m+1] ; + } + // Ridimensiono + -- nSize ; + vdPar.resize( nSize) ; + vbType.resize( nSize) ; + // Aggiorno l'indice + -- n ; + } + } + + int nSecNum = 0 ; + // Ciclo sui parametri + for ( int n = 0 ; n < nSize ; ++ n) { + // Se secante ne aumento il numero + if ( vbType[n]) + ++ nSecNum ; + } + + // Numero di puti di tangenza + int nNumTan = nSize - nSecNum ; + // Nessun contatto + if ( nSize == 0) + nIntType = T_NO_INT ; + else if ( nSize == 1) { + // Segmento secante in un punto + if ( vbType[0]) + nIntType = T_ONE_SEC ; + else + // Segmento tangente in un punto + nIntType = T_ONE_TAN ; + } + else if ( nSize == 2) { + // Segmento secante in due punti + if ( nNumTan == 0) + nIntType = T_TWO_SEC ; + // Segmento secante in un punto e tangente in un altro + else if ( nNumTan == 1) + nIntType = T_TWO_TAN_SEC ; + // Segmento tangente in due punti + else + nIntType = T_TWO_TAN ; + } + else if ( nSize == 3) { + // Segmento secante in tre punti + if ( nNumTan == 0) + nIntType = T_THREE_SEC ; + // Segmento secante in due punti e tangente in un punto + else if ( nNumTan == 1) + nIntType = T_THREE_ONE_TAN_TWO_SEC ; + // Errore + else + nIntType = T_ERROR ; + } + else if ( nSize == 4) { + // Segmento secante in quattro punti + if ( nNumTan == 0) + nIntType = T_FOUR_SEC ; + // Errore + else + nIntType = T_ERROR ; + } + // Errore + else + nIntType = T_ERROR ; + + return nIntType ; +} + +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca fra un componente lineare e la parte inferiore +// ed esterna rispetto al centro di una superficie torica. +int LinCompTorusExtInt( const Point3d& ptOTorus, const Point3d& ptLine, + const Vector3d& vtAxTorus, const Vector3d& vtLine, + double dMinRad, double dMaxRad, double dSgLen, int nLinType, + std::vector& vdPar, std::vector& vbType) +{ + int nIntType ; + // Retta + if ( nLinType == Line) + nIntType = LineTorus( ptOTorus, ptLine, vtAxTorus, vtLine, dMinRad, dMaxRad, vdPar, vbType) ; + // Semi-retta + else if ( nLinType == Ray) + nIntType = RayTorus( ptOTorus, ptLine, vtAxTorus, vtLine, dMinRad, dMaxRad, vdPar, vbType) ; + // Segmento + else if ( nLinType == Segment) + nIntType = SegmentTorus( ptOTorus, ptLine, vtAxTorus, vtLine, dMinRad, dMaxRad, dSgLen, vdPar, vbType) ; + // Errore + else + nIntType = S_ERROR_INT ; + // Ritorno errore + if ( nIntType == S_ERROR_INT) + return nIntType ; + + int nSize = int( vdPar.size()) ; + // Ciclo sui punti di contatto + for ( int n = 0 ; n < nSize ; ++ n) { + Vector3d vtInt = ptLine + vdPar[n] * vtLine - ptOTorus ; + Vector3d vtIntPlane = vtInt - vtInt * vtAxTorus * vtAxTorus ; + vtInt.Normalize() ; + // Se il punto di contatto è fuori dalla regione ammissibile lo elimino + if ( vtIntPlane.Len() < dMaxRad - EPS_SMALL || + vtInt * vtAxTorus > EPS_ZERO) { + for ( int m = n ; m < nSize - 1 ; ++ m) { + vdPar[m] = vdPar[m+1] ; + vbType[m] = vbType[m+1] ; + } + // Ridimensiono + -- nSize ; + vdPar.resize( nSize) ; + vbType.resize( nSize) ; + // Aggiorno l'indice + -- n ; + } + } + + int nSecNum = 0 ; + // Ciclo sui parametri + for ( int n = 0 ; n < nSize ; ++ n) { + // Se secante ne aumento il numero + if ( vbType[n]) + ++ nSecNum ; + } + + // Numero di puti di tangenza + int nNumTan = nSize - nSecNum ; + // Nessun contatto + if ( nSize == 0) + nIntType = T_NO_INT ; + else if ( nSize == 1) { + // Segmento secante in un punto + if ( vbType[0]) + nIntType = T_ONE_SEC ; + else + // Segmento tangente in un punto + nIntType = T_ONE_TAN ; + } + else if ( nSize == 2) { + // Segmento secante in due punti + if ( nNumTan == 0) + nIntType = T_TWO_SEC ; + // Segmento secante in un punto e tangente in un altro + else if ( nNumTan == 1) + nIntType = T_TWO_TAN_SEC ; + // Segmento tangente in due punti + else + nIntType = T_TWO_TAN ; + } + else if ( nSize == 3) { + // Segmento secante in tre punti + if ( nNumTan == 0) + nIntType = T_THREE_SEC ; + // Segmento secante in due punti e tangente in un punto + else if ( nNumTan == 1) + nIntType = T_THREE_ONE_TAN_TWO_SEC ; + // Errore + else + nIntType = T_ERROR ; + } + else if ( nSize == 4) { + // Segmento secante in quattro punti + if ( nNumTan == 0) + nIntType = T_FOUR_SEC ; + // Errore + else + nIntType = T_ERROR ; + } + // Errore + else + nIntType = T_ERROR ; + + return nIntType ; +} + +//int RayTorus( const Point3d& ptOTorus, const Point3d& ptLine, const Vector3d& vtAxTorus, const Vector3d& vtLine, +// double dMinRad, double dMaxRad, std::vector& vdPar, std::vector& vbType) +//{ +// int nIntType = LineTorus( ptOTorus, ptLine, vtAxTorus, vtLine, dMinRad, dMaxRad, vdPar, vbType) ; +// if ( nIntType == T_ERROR || nIntType == T_NO_INT) +// return nIntType ; +// +// // Retta tangente in un punto +// if ( nIntType == T_ONE_TAN) { +// // La semiretta non interagise +// if ( vdPar[0] < - EPS_SMALL) { +// vdPar.resize( 0) ; +// vbType.resize( 0) ; +// nIntType = T_NO_INT ; +// } +// } +// // Retta tangente in due punti +// else if ( nIntType == T_TWO_TAN) { +// // Semi-retta non interagisce +// if ( vdPar[1] < - EPS_SMALL) { +// vdPar.resize( 0) ; +// vbType.resize( 0) ; +// nIntType = T_NO_INT ; +// } +// // Semi-retta tangente in un punto +// else if ( vdPar[0] < - EPS_SMALL) { +// vdPar[0] = vdPar[1] ; +// vdPar.resize( 1) ; +// vbType.resize( 1) ; +// nIntType = T_ONE_TAN ; +// } +// } +// else if ( nIntType == T_TWO_SEC) { +// // Semi-retta non interagisce +// if ( vdPar[1] < - EPS_SMALL) { +// vdPar.resize( 0) ; +// vbType.resize( 0) ; +// nIntType = T_NO_INT ; +// } +// // Semi-retta secante in un punto +// else if ( vdPar[0] < - EPS_SMALL) { +// vdPar[0] = vdPar[1] ; +// vdPar.resize( 1) ; +// vbType.resize( 1) ; +// nIntType = T_ONE_SEC ; +// } +// } +// else if ( nIntType == T_THREE_ONE_TAN_TWO_SEC) { +// // Semi-retta non interagente +// if ( vdPar[2] < - EPS_SMALL) { +// vdPar.resize( 0) ; +// vbType.resize( 0) ; +// nIntType = T_NO_INT ; +// } +// // Semi-retta tangente in un punto +// else if ( vdPar[1] < - EPS_ZERO) { +// vdPar[0] = vdPar[2] ; +// vbType[0] = vbType[2] ; +// vdPar.resize( 1) ; +// vbType.resize( 1) ; +// if ( vbType[0]) +// T_ONE_SEC ; +// else +// T_ONE_TAN ; +// } +// else { +// // Semi-retta interagente in due punti +// if ( vdPar[0] < - EPS_SMALL) { +// vdPar[0] = vdPar[1] ; +// vdPar[1] = vdPar[2] ; +// vbType[0] = vbType[1] ; +// vbType[1] = vbType[2] ; +// vdPar.resize( 2) ; +// vbType.resize( 2) ; +// if ( vbType[0] || vbType[1]) { +// if ( vbType[0] == vbType[1]) +// nIntType = T_TWO_SEC ; +// else +// nIntType = T_TWO_TAN_SEC ; +// } +// } +// } +// } +// // Retta secante in quattro punti +// else if ( nIntType == T_FOUR_SEC) { +// ; +// } +// +// return nIntType ; +//} \ No newline at end of file diff --git a/IntersLineSurfStd.h b/IntersLineSurfStd.h new file mode 100644 index 0000000..431b15a --- /dev/null +++ b/IntersLineSurfStd.h @@ -0,0 +1,268 @@ +//---------------------------------------------------------------------------- +// EgalTech 2017-2017 +//---------------------------------------------------------------------------- +// File : Tool.h Data : 01.12.17 Versione : ???1.6a4 +// Contenuto : Dichiarazione dei prototipi delle funzioni di intersezione +// superficie e componente lineare +// +// +// Modifiche : 22.01.15 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- +#pragma once + +#include "/EgtDev/Include/EGkPoint3d.h" +#include "/EgtDev/Include/EGkVector3d.h" +#include "/EgtDev/Include/EGkFrame3d.h" +#include "/EgtDev/Include/ENkPolynomialRoots.h" +#include +#include + +// In tutte le funzioni dichiarate i punti e i vettori che definiscono gli oggetti geometrici +// devono essere espressi nel medesimo sistema di riferimento. I vettori devono essere normalizzati. +// Il valore di ritorno è una costante intera che individua la tipologia di interferenza. +// Se si verificano irregolarità, essa vale ERROR_INT. +// Per riferimento vengono restituiti i parametri lungo la retta a cui avvengono le +// intersezioni. Se non vi sono intersezioni i valori di dU1 e dU2 non hanno senso, +// se vi è un'intersezione solo il valore di dU1 ha senso. Se vi sono più intersezioni, +// dU1 e dU2 hanno entrambi senso. +// Nelle routine per la semi-sfera come argomento appare un versore, che ne individua l'orientazione +// nello spazio. Si immagini uno spazio con origine nel centro della sfera e asse Z diretto come tale +// versore. La sfera è divisa in due parti: una nel semi spazio Z+ e una in quello Z-. +// La semi-sfera di interesse è quella nel semi-spazio Z-. +// Se il versore non ha, come deve, norma 1 viene restituito lo stato di errore. +// Anche per la routine d'intersezione di un componente lineare con la parte inferiore +// ed esterna (rispetto al centro) della superficie torica vale la stessa considerazione. + +// Costanti tipologia di componente lineare +enum LinType { Line = 0, Ray = 1, Segment = 2} ; + + +// Costanti tipologia di intersezioni fra un componente lineare e un disco +enum LinCompDiscIntersType { D_ERROR_INT = - 1, D_NO_INTERS = 0, D_BOUNDARY_INT_LINE_NOT_IN_PLANE = 1, + D_INNER_INT_LINE_NOT_IN_PLANE = 2, D_ONE_INT_LINE_ON_PLANE = 3, + D_INFINITE_INT_LINE_ON_PLANE = 4} ; +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca fra una retta e un disco. +// Nel caso in cui parte della retta giaccia all'interno del disco dU1 è il parametro a +// cui la retta entra e dU2 quello a cui esce. +int LineDisc( const Point3d& ptPDisc, const Point3d& ptPLine, const Vector3d& vtVDisc, const Vector3d& vtVLine, + double dRad, double& dU1, double& dU2) ; + +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca fra una semi-retta e un disco. +// Nel caso in cui parte della semi-retta giaccia all'interno del disco dU1 è il parametro a +// cui la semi-retta entra e dU2 quello a cui esce. +int RayDisc( const Point3d& ptPDis, const Point3d& ptPLine, const Vector3d& vtVDisc, const Vector3d& vtVLine, + double dRad, double& dU1, double& dU2) ; + +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca fra un segmento e un disco. +// Nel caso in cui parte del segmento giaccia all'interno del disco dU1 è il parametro a +// cui il segmento entra e dU2 quello a cui esce. +int SegmentDisc( const Point3d& ptPDisc, const Point3d& ptPLine, const Vector3d& vtVDisc, const Vector3d& vtVLine, + double dRad, double dLen, double& dU1, double& dU2) ; + +// Costanti tipologia di intersezione fra un componente lineare e una sfera +enum LinCompSphereIntersType { S_ERROR_INT = - 1, S_NO_INTERS = 0, S_ONE_INT_SEC = 1, S_TWO_INT = 2, S_ONE_INT_TAN = 3} ; + +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca fra una retta e una sfera. +int LineSphere( const Point3d& ptSphC, const Point3d& ptPLine, const Vector3d& vtVLine, + double dRad, double& dU1, double& dU2) ; + +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca fra una semi-retta e una sfera. +int RaySphere( const Point3d& ptSphC, const Point3d& ptPLine, const Vector3d& vtVLine, + double dRad, double& dU1, double& dU2) ; + +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca fra un segmento e una sfera. +int SegmentSphere( const Point3d& ptSphC, const Point3d& ptPLine, const Vector3d& vtVLine, + double dRad, double dLen, double& dU1, double& dU2) ; + +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca fra una retta e una superficie semi-sferica +int LineSemiSphere( const Point3d& ptSphC, const Point3d& ptPLine, + const Vector3d& vtSSphOrient, const Vector3d& vtVLine, + double dRad, double& dU1, double& dU2) ; + +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca fra una semi-retta e una superficie semi-sferica +int RaySemiSphere( const Point3d& ptSphC, const Point3d& ptPLine, + const Vector3d& vtSSphOrient, const Vector3d& vtVLine, + double dRad, double& dU1, double& dU2) ; + +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca fra un segmento e una sfera. +int SegmentSemiSphere( const Point3d& ptSphC, const Point3d& ptPLine, + const Vector3d& vtSSphOrient, const Vector3d& vtVLine, + double dRad, double dLen, double& dU1, double& dU2) ; + +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca fra un segmento e una sfera. +int LinCompSemiSphere( const Point3d& ptSphC, const Point3d& ptPLine, + const Vector3d& vtSSphOrient, const Vector3d& vtVLine, + double dRad, double dLen, int nLinType, double& dU1, double& dU2) ; + +// Costanti tipologia di intersezione fra un componente lineare e +// un solido cilindrico o conico +enum LinCompCCIntersType { CC_ERROR_INT = - 1, CC_NO_INTERS = 0, CC_ONE_INT_SEC = 1, + CC_TWO_INT = 2, CC_ONE_INT_TAN = 3, CC_INF_INT = 4, CC_ON_VERT = 5} ; + +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca fra un cilindro infinito e una retta. +// Nel caso in cui la retta giaccia sul cilindro, nIntType vale INF_INT e dU1 e dU2 valgono +// rispettivamente - INFINITO e INFINITO. +int LineInfiniteCylinder( const Point3d& ptPCyl, const Point3d& ptPLine, const Vector3d& vtVCyl, const Vector3d& vtVLine, + double dCylRad, double& dU1, double& dU2) ; + +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca fra un cilindro infinito e una semi-retta. +// Nel caso in cui la semi-retta giaccia sul cilindro, nIntType vale INF_INT e dU1 e dU2 +// valgono rispettivamente 0 e INFINITO. +int RayInfiniteCylinder( const Point3d& ptPCyl, const Point3d& ptPLine, const Vector3d& vtVCyl, const Vector3d& vtVLine, + double dCylRad, double& dU1, double& dU2) ; + +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca fra un cilindro infinito e un segmento. +// Nel caso in cui il sgmento giaccia sul cilindro, nIntType vale INF_INT e dU1 e dU2 +// valgono rispettivamente 0 e dLen (lunghezza del segmento). +int SegmentInfiniteCylinder( const Point3d& ptPCyl, const Point3d& ptPLine, const Vector3d& vtVCyl, const Vector3d& vtVLine, + double dCylRad, double dLen, double& dU1, double& dU2) ; + +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca fra una retta e un cilindro semi-finito. +// Nel caso in cui parte della retta giaccia sul cilindro, nIntType vale INF_INT e un +// parametro ha valore finito mentre l'altro ha valore infinito. +int LineSemiFiniteCylinder( const Point3d& ptPCyl, const Point3d& ptPLine, const Vector3d& vtVCyl, const Vector3d& vtVLine, + double dCylRad, double& dU1, double& dU2) ; + +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca fra una semi-retta e un cilindro semi-finito. +// Nel caso in cui parte della semi-retta giaccia sul cilindro, nIntType vale INF_INT +// e almeno un parametro ha valore finito. +int RaySemiFiniteCylinder( const Point3d& ptPCyl, const Point3d& ptPLine, const Vector3d& vtVCyl, const Vector3d& vtVLine, + double dCylRad, double& dU1, double& dU2) ; + +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca fra un cilindro semi-finito e un segmento. +// Nel caso in cui il segmento giaccia sul cilindro, nIntType vale INF_INT e dU1 e dU2 +// hanno entrambi valori finiti. +int SegmentSemiFiniteCylinder( const Point3d& ptPCyl, const Point3d& ptPLine, const Vector3d& vtVCyl, const Vector3d& vtVLine, + double dCylRad, double dLen, double& dU1, double& dU2) ; + +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca fra una retta e un cilindro. +// Nel caso in cui parte della retta giaccia sul cilindro, nIntType vale INF_INT e entrambi i +// i parametri dU1 e dU2 sono finiti. +int LineCylinder( const Point3d& ptPCyl, const Point3d& ptPLine, const Vector3d& vtVCyl, const Vector3d& vtVLine, + double dCylRad, double dCylHeigth, double& dU1, double& dU2) ; + + +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca fra una semi-retta e un cilindro. +// Nel caso in cui parte della semi-retta giaccia sul cilindro, nIntType vale INF_INT e entrambi +// i parametri dU1 e dU2 hanno senso. +int RayCylinder( const Point3d& ptPCyl, const Point3d& ptPLine, const Vector3d& vtVCyl, const Vector3d& vtVLine, + double dCylRad, double dCylHeigth, double& dU1, double& dU2) ; + +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca fra un segmento e un cilindro. +// Nel caso in cui parte del segmento giaccia sul cilindro, nIntType vale INF_INT e entrambi i +// i parametri dU1 e dU2 hanno senso. +int SegmentCylinder( const Point3d& ptPCyl, const Point3d& ptPLine, const Vector3d& vtVCyl, const Vector3d& vtVLine, + double dCylRad, double dCylHeigth, double dLen, double& dU1, double& dU2) ; + +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca fra una retta e un cono infinito. +// Nel caso in cui parte della retta giaccia sul cono, nIntType vale INF_INT e entrambi i +// i parametri dU1 e dU2 hanno senso; uno è finito e l'altro no. +int LineInfiniteCone( const Point3d& ptVCone, const Point3d& ptPLine, const Vector3d& vtDCone, const Vector3d& vtDLine, + double dConeRad, double dConeHeigth, double& dU1, double& dU2) ; + +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca fra una semi-retta e un cono infinito. +// Nel caso in cui parte della semi-retta giaccia sul cono, nIntType vale INF_INT e entrambi i +// i parametri dU1 e dU2 hanno senso. +int RayInfiniteCone( const Point3d& ptVCone, const Point3d& ptPLine, const Vector3d& vtDCone, const Vector3d& vtDLine, + double dConeRad, double dConeHeigth, double& dU1, double& dU2) ; + +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca fra un segmento e un cono infinito. +// Nel caso in cui parte del segmento giaccia sul cono, nIntType vale INF_INT e entrambi i +// i parametri dU1 e dU2 hanno senso. +int SegmentInfiniteCone( const Point3d& ptVCone, const Point3d& ptPLine, const Vector3d& vtDCone, const Vector3d& vtDLine, + double dConeRad, double dConeHeigth, double dSgLen, double& dU1, double& dU2) ; + +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca fra una retta e un cono. +// Nel caso in cui parte del segmento giaccia sul cono, nIntType vale INF_INT e entrambi i +// i parametri dU1 e dU2 hanno senso. +int LineCone( const Point3d& ptVCone, const Point3d& ptPLine, const Vector3d& vtDCone, const Vector3d& vtDLine, + double dConeRad, double dConeHeigth, double& dU1, double& dU2) ; + +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca fra una semi-retta e un cono. +// Nel caso in cui parte della semi-retta giaccia sul cono, nIntType vale INF_INT e entrambi i +// i parametri dU1 e dU2 hanno senso. +int RayCone( const Point3d& ptVCone, const Point3d& ptPLine, const Vector3d& vtDCone, const Vector3d& vtDLine, + double dConeRad, double dConeHeigth, double& dU1, double& dU2) ; + +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca fra un segmento e un cono. +// Nel caso in cui parte del segmento giaccia sul cono, nIntType vale INF_INT e entrambi i +// i parametri dU1 e dU2 hanno senso. +int SegmentCone( const Point3d& ptVCone, const Point3d& ptPLine, const Vector3d& vtDCone, const Vector3d& vtDLine, + double dConeRad, double dConeHeigth, double dSgLen, double& dU1, double& dU2) ; + +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca di una retta e un tronco di cono +// Nel caso in cui parte della retta giaccia sul tronco di cono, nIntType vale +// INF_INT e entrambi i parametri dU1 e dU2 hanno senso. +int LineTruncatedCone( const Point3d& ptMinBase, const Point3d& ptPLine, const Vector3d& vtDCone, const Vector3d& vtDLine, + double dMinRad, double dMaxRad, double dHeigth, double& dU1, double& dU2) ; + +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca di una semi-retta e un tronco di cono. +// Nel caso in cui parte della semi-retta giaccia sul tronco di cono, nIntType vale +// INF_INT e entrambi i parametri dU1 e dU2 hanno senso. +int RayTruncatedCone( const Point3d& ptMinBase, const Point3d& ptPLine, const Vector3d& vtDCone, const Vector3d& vtDLine, + double dMinRad, double dMaxRad, double dHeigth, double& dU1, double& dU2) ; + +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca di un segmento e un tronco di cono. +// Nel caso in cui parte del segmento giaccia sul tronco di cono, nIntType vale +// INF_INT e entrambi i parametri dU1 e dU2 hanno senso. +int SegmentTruncatedCone( const Point3d& ptMinBase, const Point3d& ptPLine, const Vector3d& vtDCone, const Vector3d& vtDLine, + double dMinRad, double dMaxRad, double dHeigth, double dSgLen, double& dU1, double& dU2) ; + +// Cosntani tipologia di intersezione fra un componente lineare e un toro +enum LinCompTorusIntersType { T_ERROR = - 1, T_NO_INT = 0, T_ONE_TAN = 1, T_ONE_SEC = 2, T_TWO_TAN = 3, T_TWO_SEC = 4, + T_TWO_TAN_SEC = 5, T_THREE_SEC = 6, T_THREE_ONE_TAN_TWO_SEC = 7, T_FOUR_SEC = 8} ; + +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca fra una retta e un toro. +// Punti e vettori devono essere espressi nel medesimo sistema di riferimento. +int LineTorus( const Point3d& ptOTorus, const Point3d& ptLine, const Vector3d& vtAxTorus, const Vector3d& vtLine, + double dMinRad, double dMaxRad, std::vector& vdPar, std::vector& vbType) ; //double dU1, double dU2, double dU3, double dU4) ; + +//---------------------------------------------------------------------------- +int RayTorus( const Point3d& ptOTorus, const Point3d& ptLine, const Vector3d& vtAxTorus, const Vector3d& vtLine, + double dMinRad, double dMaxRad, std::vector& vdPar, std::vector& vbType) ; + +//---------------------------------------------------------------------------- +int SegmentTorus( const Point3d& ptOTorus, const Point3d& ptLine, const Vector3d& vtAxTorus, const Vector3d& vtLine, + double dMinRad, double dMaxRad, double dSgLen, std::vector& vdPar, std::vector& vbType) ; + +//---------------------------------------------------------------------------- +// Valuta la posizione reciproca fra un componente lineare e la parte inferiore +// ed esterna rispetto al centro di una superficie torica. +int LinCompTorusExtInt( const Point3d& ptOTorus, const Point3d& ptLine, + const Vector3d& vtAxTorus, const Vector3d& vtLine, + double dMinRad, double dMaxRad, double dSgLen, int nLinType, + std::vector& vdPar, std::vector& vbType) ; + + + diff --git a/SurfFlatRegion.h b/SurfFlatRegion.h index d23d332..ceeef20 100644 --- a/SurfFlatRegion.h +++ b/SurfFlatRegion.h @@ -106,7 +106,7 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW LOG_ERROR( GetEGkLogger(), "SurfFlatRegion : copy error") return *this ; } - friend class MyCDSimpleSurfFrMove ; + friend class MyCAvSimpleSurfFrMove ; private : enum Status { ERR = 0, OK = 1, TO_VERIFY = 2} ;