4056be90d9
- modifiche a IntersLineBox e IntersPlaneBox - adattamenti conseguenti.
2156 lines
74 KiB
C++
2156 lines
74 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2017-2022
|
|
//----------------------------------------------------------------------------
|
|
// File : IntersLineSurfStd.cpp Data : 08.01.22 Versione : 2.4a3
|
|
// Contenuto : Implementazione delle funzioni di intersezione
|
|
// componente lineare e superficie standard.
|
|
//
|
|
//
|
|
// Modifiche : 22.01.15 DS Creazione modulo.
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
#include "stdafx.h"
|
|
#include "IntersLineSurfStd.h"
|
|
#include "IntersLineBox.h"
|
|
#include "/EgtDev/Include/EGkIntersLinePlane.h"
|
|
#include "/EgtDev/Include/EGkFrame3d.h"
|
|
#include "/EgtDev/Include/ENkPolynomialRoots.h"
|
|
#include "/EgtDev/Include/EgtNumUtils.h"
|
|
#include <algorithm>
|
|
|
|
using namespace std ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
LineDisc( const Point3d& ptPLine, const Vector3d& vtVLine,
|
|
const Point3d& ptPDisc, const Vector3d& vtVDisc, double dRad,
|
|
double& dU1, double& dU2)
|
|
{
|
|
// Il raggio del disco deve essere non nullo.
|
|
if ( dRad < EPS_SMALL)
|
|
return D_ERROR_INT ;
|
|
// Si richiede che i vettori siano normalizzati
|
|
if ( ! vtVDisc.IsNormalized() || ! vtVLine.IsNormalized())
|
|
return D_ERROR_INT ;
|
|
|
|
// Intersezione con il piano del disco
|
|
Point3d ptInt ;
|
|
Plane3d plDisc ; plDisc.Set( ptPDisc, vtVDisc) ;
|
|
int nLpInt = IntersLinePlane( ptPLine, vtVLine, 1, plDisc, ptInt, false) ;
|
|
if ( nLpInt == ILPT_NO)
|
|
return D_NO_INTERS ;
|
|
|
|
// Un punto di intersezione con il piano
|
|
if ( nLpInt == ILPT_YES) {
|
|
double dDistCdP = Dist( ptInt, ptPDisc) ;
|
|
// Se distanza uguale al raggio, intersezione sul bordo
|
|
if ( abs( dDistCdP - dRad) < EPS_SMALL) {
|
|
dU1 = ( ptInt - ptPLine) * vtVLine ;
|
|
dU2 = dU1 ;
|
|
return D_BOUNDARY_INT_LINE_NOT_IN_PLANE ;
|
|
}
|
|
// Se distanza superiore al raggio, nessuna intersezione
|
|
if ( dDistCdP > dRad)
|
|
return D_NO_INTERS ;
|
|
// Distanza inferiore al raggio, intersezione interna
|
|
dU1 = ( ptInt - ptPLine) * vtVLine ;
|
|
dU2 = dU1 ;
|
|
return D_INNER_INT_LINE_NOT_IN_PLANE ;
|
|
}
|
|
|
|
// La linea giace nel piano
|
|
{
|
|
// Proiezione del centro del disco sulla linea
|
|
Point3d ptP = ptPLine + (( ptPDisc - ptPLine) * vtVLine) * vtVLine ;
|
|
// Distanza di questo punto di proiezione dal centro del disco
|
|
double dDist = Dist( ptPDisc, ptP) ;
|
|
// Se distanza uguale al raggio, intersezione tangente
|
|
if ( abs( dDist - dRad) < EPS_SMALL) {
|
|
dU1 = ( ptP - ptPLine) * vtVLine ;
|
|
dU2 = dU1 ;
|
|
return D_ONE_INT_LINE_ON_PLANE ;
|
|
}
|
|
// Se distanza superiore al raggio, nessuna intersezione
|
|
if ( dDist > dRad)
|
|
return D_NO_INTERS ;
|
|
// Distanza inferiore al raggio, due intersezioni secanti
|
|
double dDist2 = sqrt( dRad * dRad - dDist * dDist) ;
|
|
Point3d ptI1 = ptP - dDist2 * vtVLine ;
|
|
dU1 = ( ptI1 - ptPLine) * vtVLine ;
|
|
Point3d ptI2 = ptP + dDist2 * vtVLine ;
|
|
dU2 = ( ptI2 - ptPLine) * vtVLine ;
|
|
return D_INFINITE_INT_LINE_ON_PLANE ;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
RayDisc( const Point3d& ptPLine, const Vector3d& vtVLine,
|
|
const Point3d& ptPDisc, const Vector3d& vtVDisc, double dRad,
|
|
double& dU1, double& dU2)
|
|
{
|
|
int nIntType = LineDisc( ptPLine, vtVLine, ptPDisc, vtVDisc, 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& ptPLine, const Vector3d& vtVLine, double dLen,
|
|
const Point3d& ptPDisc, const Vector3d& vtVDisc, double dRad,
|
|
double& dU1, double& dU2)
|
|
{
|
|
int nIntType = LineDisc( ptPLine, vtVLine, ptPDisc, vtVDisc, 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 || dU1 > dLen + EPS_SMALL)
|
|
nIntType = D_NO_INTERS ;
|
|
return nIntType ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
int
|
|
LineSphere( const Point3d& ptPLine, const Vector3d& vtVLine,
|
|
const Point3d& ptSphC, double dRad,
|
|
double& dU1, double& dU2)
|
|
{
|
|
// Il raggio della sfera deve essere non nullo.
|
|
if ( dRad < EPS_SMALL)
|
|
return S_ERROR_INT ;
|
|
// Si richiede che il vettore sia normalizzato
|
|
if ( ! vtVLine.IsNormalized())
|
|
return S_ERROR_INT ;
|
|
|
|
// 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 ;
|
|
// Studio delle soluzioni
|
|
int nIntType ;
|
|
// 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& ptPLine, const Vector3d& vtVLine,
|
|
const Point3d& ptSphC, double dRad,
|
|
double& dU1, double& dU2)
|
|
{
|
|
int nIntType = LineSphere( ptPLine, vtVLine, ptSphC, 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& ptPLine, const Vector3d& vtVLine, double dLen,
|
|
const Point3d& ptSphC, double dRad,
|
|
double& dU1, double& dU2)
|
|
{
|
|
int nIntType = LineSphere( ptPLine, vtVLine, ptSphC, 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& ptPLine, const Vector3d& vtVLine,
|
|
const Point3d& ptSphC, const Vector3d& vtSSphOrient, double dRad,
|
|
double& dU1, double& dU2)
|
|
{
|
|
int nIntType = LineSphere( ptPLine, vtVLine, ptSphC, 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& ptPLine, const Vector3d& vtVLine,
|
|
const Point3d& ptSphC, const Vector3d& vtSSphOrient, double dRad,
|
|
double& dU1, double& dU2)
|
|
{
|
|
int nIntType = RaySphere( ptPLine, vtVLine, ptSphC, 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& ptPLine, const Vector3d& vtVLine, double dLen,
|
|
const Point3d& ptSphC, const Vector3d& vtSSphOrient, double dRad,
|
|
double& dU1, double& dU2)
|
|
{
|
|
int nIntType = SegmentSphere( ptPLine, vtVLine, dLen, ptSphC, dRad, 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& ptPLine, const Vector3d& vtVLine, double dLen, int nLinType,
|
|
const Point3d& ptSphC, const Vector3d& vtSSphOrient, double dRad,
|
|
double& dU1, double& dU2)
|
|
{
|
|
int nIntType ;
|
|
// Retta
|
|
if ( nLinType == Line)
|
|
nIntType = LineSphere( ptPLine, vtVLine, ptSphC, dRad, dU1, dU2) ;
|
|
// Semi-retta
|
|
else if ( nLinType == Ray)
|
|
nIntType = RaySphere( ptPLine, vtVLine, ptSphC, dRad, dU1, dU2) ;
|
|
// Segmento
|
|
else if ( nLinType == Segment)
|
|
nIntType = SegmentSphere( ptPLine, vtVLine, dLen, ptSphC, dRad, 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
|
|
IntersLineInfiniteCylinder( const Point3d& ptPLine, const Vector3d& vtVLine,
|
|
const Point3d& ptPCyl, const Vector3d& vtVCyl, double dCylRad,
|
|
double& dU1, double& dU2)
|
|
{
|
|
// Se il raggio non è significativamente maggiore di zero, vi è un errore.
|
|
if ( dCylRad < EPS_SMALL)
|
|
return CC_ERROR_INT ;
|
|
// Si richiede che i vettori siano normalizzati
|
|
if ( ! vtVCyl.IsNormalized() || ! vtVLine.IsNormalized())
|
|
return CC_ERROR_INT ;
|
|
|
|
// La retta e l'asse del cilindro sono paralleli
|
|
if ( AreSameOrOppositeVectorExact( vtVLine, vtVCyl)) {
|
|
double dRadialDist = ( ( ptPLine - ptPCyl) - ( ( ptPLine - ptPCyl) * vtVCyl) * vtVCyl).Len() ;
|
|
// La retta appartiene al cilindro
|
|
if ( abs( dRadialDist - dCylRad) < EPS_SMALL) {
|
|
dU1 = - INFINITO ;
|
|
dU2 = INFINITO ;
|
|
return CC_INF_INT ;
|
|
}
|
|
// non vi è intersezione
|
|
else
|
|
return CC_NO_INTERS ;
|
|
}
|
|
|
|
// Setto i coefficienti dell'equazione
|
|
DBLVECTOR vdCoef( 3) ;
|
|
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
|
|
DBLVECTOR vdRoots ;
|
|
int nRoot = PolynomialRoots( 2, vdCoef, vdRoots) ;
|
|
// Studio delle soluzioni
|
|
int nIntType = CC_NO_INTERS ;
|
|
// C'è un punto di tangenza
|
|
if ( nRoot == 1) {
|
|
dU1 = vdRoots[0] ;
|
|
nIntType = CC_ONE_INT_TAN ;
|
|
}
|
|
// L'equazione ha due soluzioni, bisogna valutare se sono ben distinte.
|
|
else if ( nRoot == 2) {
|
|
dU1 = vdRoots[0] ;
|
|
dU2 = vdRoots[1] ;
|
|
if ( dU1 > dU2)
|
|
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
|
|
IntersRayInfiniteCylinder( const Point3d& ptPLine, const Vector3d& vtVLine,
|
|
const Point3d& ptPCyl, const Vector3d& vtVCyl, double dCylRad,
|
|
double& dU1, double& dU2)
|
|
{
|
|
int nIntType = IntersLineInfiniteCylinder( ptPLine, vtVLine, ptPCyl, vtVCyl, 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
|
|
IntersSegmentInfiniteCylinder( const Point3d& ptPLine, const Vector3d& vtVLine, double dLen,
|
|
const Point3d& ptPCyl, const Vector3d& vtVCyl, double dCylRad,
|
|
double& dU1, double& dU2)
|
|
{
|
|
int nIntType = IntersLineInfiniteCylinder( ptPLine, vtVLine, ptPCyl, vtVCyl, 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
|
|
IntersLineSemiFiniteCylinder( const Point3d& ptPLine, const Vector3d& vtVLine,
|
|
const Point3d& ptPCyl, const Vector3d& vtVCyl, double dCylRad,
|
|
double& dU1, double& dU2)
|
|
{
|
|
int nIntType = IntersLineInfiniteCylinder( ptPLine, vtVLine, ptPCyl, vtVCyl, 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& ptPLine, const Vector3d& vtVLine,
|
|
const Point3d& ptPCyl, const Vector3d& vtVCyl, double dCylRad,
|
|
double& dU1, double& dU2)
|
|
{
|
|
int nIntType = IntersLineSemiFiniteCylinder( ptPLine, vtVLine, ptPCyl, vtVCyl, 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& ptPLine, const Vector3d& vtVLine, double dLen,
|
|
const Point3d& ptPCyl, const Vector3d& vtVCyl, double dCylRad,
|
|
double& dU1, double& dU2)
|
|
{
|
|
int nIntType = IntersLineSemiFiniteCylinder( ptPLine, vtVLine, ptPCyl, vtVCyl, 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
|
|
IntersLineCylinder( const Point3d& ptPLine, const Vector3d& vtVLine,
|
|
const Point3d& ptPCyl, const Vector3d& vtVCyl, double dCylRad, double dCylHeigth,
|
|
double& dU1, double& dU2)
|
|
{
|
|
int nIntType = IntersLineInfiniteCylinder( ptPLine, vtVLine, ptPCyl, vtVCyl, 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& ptPLine, const Vector3d& vtVLine,
|
|
const Point3d& ptPCyl, const Vector3d& vtVCyl, double dCylRad, double dCylHeigth,
|
|
double& dU1, double& dU2)
|
|
{
|
|
int nIntType = IntersLineCylinder( ptPLine, vtVLine, ptPCyl, vtVCyl, 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
|
|
IntersSegmentCylinder( const Point3d& ptPLine, const Vector3d& vtVLine, double dLen,
|
|
const Point3d& ptPCyl, const Vector3d& vtVCyl, double dCylRad, double dCylHeigth,
|
|
double& dU1, double& dU2)
|
|
{
|
|
int nIntType = IntersLineCylinder( ptPLine, vtVLine, ptPCyl, vtVCyl, 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& ptPLine, const Vector3d& vtDLine,
|
|
const Point3d& ptVCone, const Vector3d& vtDCone, double dConeRad, double dConeHeigth,
|
|
double& dU1, double& dU2)
|
|
{
|
|
// Raggio e altezza del cono devono essere maggiori di zero
|
|
if ( dConeRad < EPS_SMALL || dConeHeigth < EPS_SMALL)
|
|
return CC_ERROR_INT ;
|
|
// Si richiede che i vettori siano normalizzati
|
|
if ( ! vtDCone.IsNormalized() || ! vtDLine.IsNormalized())
|
|
return CC_ERROR_INT ;
|
|
|
|
// Tangente dell'angolo semi-apertura del cono
|
|
double dTanTheta = dConeRad / dConeHeigth ;
|
|
|
|
// 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 ;
|
|
}
|
|
return CC_INF_INT ;
|
|
}
|
|
// 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 ;
|
|
}
|
|
}
|
|
|
|
// Setto i coefficienti dell'equazione
|
|
DBLVECTOR vdCoef( 3) ;
|
|
double dDiffDiff = ( ptPLine - ptVCone) * ( ptPLine - ptVCone) ;
|
|
double dDiffDC = ( ptPLine - ptVCone) * vtDCone ;
|
|
double dDiffDL = ( ptPLine - ptVCone) * vtDLine ;
|
|
double dDCDL = vtDCone * vtDLine ;
|
|
double dInvSqCosTheta = 1 + dTanTheta * dTanTheta ;
|
|
vdCoef[0] = dDiffDiff - dInvSqCosTheta * dDiffDC * dDiffDC ;
|
|
vdCoef[1] = 2 * ( dDiffDL - dInvSqCosTheta * dDCDL * dDiffDC) ;
|
|
vdCoef[2] = 1 - dInvSqCosTheta * dDCDL * dDCDL ;
|
|
|
|
// Risolvo l'equazione
|
|
DBLVECTOR vdRoots ;
|
|
int nRoot = PolynomialRoots( 2, vdCoef, vdRoots) ;
|
|
|
|
// Studio le soluzioni
|
|
int nIntType = CC_NO_INTERS ;
|
|
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)
|
|
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& ptPLine, const Vector3d& vtDLine,
|
|
const Point3d& ptVCone, const Vector3d& vtDCone, double dConeRad, double dConeHeigth,
|
|
double& dU1, double& dU2)
|
|
{
|
|
int nIntType = LineInfiniteCone( ptPLine, vtDLine, ptVCone, vtDCone, 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& ptPLine, const Vector3d& vtDLine, double dSgLen,
|
|
const Point3d& ptVCone, const Vector3d& vtDCone, double dConeRad, double dConeHeigth,
|
|
double& dU1, double& dU2)
|
|
{
|
|
int nIntType = LineInfiniteCone( ptPLine, vtDLine, ptVCone, vtDCone, 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& ptPLine, const Vector3d& vtDLine,
|
|
const Point3d& ptVCone, const Vector3d& vtDCone, double dConeRad, double dConeHeigth,
|
|
double& dU1, double& dU2)
|
|
{
|
|
int nIntType = LineInfiniteCone( ptPLine, vtDLine, ptVCone, vtDCone, dConeRad, dConeHeigth, dU1, dU2) ;
|
|
if ( nIntType == CC_ERROR_INT)
|
|
return nIntType ;
|
|
// Tangente 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& ptPLine, const Vector3d& vtDLine,
|
|
const Point3d& ptVCone, const Vector3d& vtDCone, double dConeRad, double dConeHeigth,
|
|
double& dU1, double& dU2)
|
|
{
|
|
int nIntType = LineCone( ptPLine, vtDLine, ptVCone, vtDCone, 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& ptPLine, const Vector3d& vtDLine, double dSgLen,
|
|
const Point3d& ptVCone, const Vector3d& vtDCone, double dConeRad, double dConeHeigth,
|
|
double& dU1, double& dU2)
|
|
{
|
|
// Verifico se il segmento interseca un insieme di box impilati che includono il cono
|
|
Frame3d frCone ; frCone.Set( ptVCone, vtDCone) ;
|
|
Point3d ptLineL = ptPLine ; ptLineL.ToLoc( frCone) ;
|
|
Vector3d vtLineL = vtDLine ; vtLineL.ToLoc( frCone) ;
|
|
const int N_SLABS = 4 ;
|
|
double dH = dConeHeigth / N_SLABS ;
|
|
double dR = dConeRad / N_SLABS ;
|
|
int nMiss = 0 ;
|
|
for ( int i = 1 ; i <= N_SLABS ; ++ i) {
|
|
double dPar1, dPar2 ;
|
|
ptLineL.z -= ( i - 1) * dH ;
|
|
double dCurrR = i * dR ;
|
|
if ( ! IntersLineBox( ptLineL, vtLineL, Point3d( -dCurrR, -dCurrR, 0), Point3d( dCurrR, dCurrR, dH), dPar1, dPar2) ||
|
|
dPar2 < -EPS_SMALL || dPar1 > dSgLen + EPS_SMALL)
|
|
++ nMiss ;
|
|
}
|
|
if ( nMiss == N_SLABS)
|
|
return CC_NO_INTERS ;
|
|
|
|
// Calcolo l'intersezione con la linea illimitata
|
|
int nIntType = LineCone( ptPLine, vtDLine, ptVCone, vtDCone, 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
|
|
LineConeFrustum( const Point3d& ptPLine, const Vector3d& vtDLine,
|
|
const Point3d& ptMinBase, const Vector3d& vtDCone, 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( ptPLine, vtDLine, ptVCone, vtDCone, 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
|
|
RayConeFrustum( const Point3d& ptPLine, const Vector3d& vtDLine,
|
|
const Point3d& ptMinBase, const Vector3d& vtDCone, double dMinRad, double dMaxRad, double dHeigth,
|
|
double& dU1, double& dU2)
|
|
{
|
|
int nIntType = LineConeFrustum( ptPLine, vtDLine, ptMinBase, vtDCone, 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
|
|
SegmentConeFrustum( const Point3d& ptPLine, const Vector3d& vtDLine, double dSgLen,
|
|
const Point3d& ptMinBase, const Vector3d& vtDCone, double dMinRad, double dMaxRad, double dHeigth,
|
|
double& dU1, double& dU2)
|
|
{
|
|
// Verifico se il segmento interseca un insieme di box impilati che includono il tronco cono
|
|
Frame3d frCone ; frCone.Set( ptMinBase, vtDCone) ;
|
|
Point3d ptLineL = ptPLine ; ptLineL.ToLoc( frCone) ;
|
|
Vector3d vtLineL = vtDLine ; vtLineL.ToLoc( frCone) ;
|
|
const int N_SLABS = 4 ;
|
|
double dH = dHeigth / N_SLABS ;
|
|
double dR = ( dMaxRad - dMinRad) / N_SLABS ;
|
|
int nMiss = 0 ;
|
|
for ( int i = 1 ; i <= N_SLABS ; ++ i) {
|
|
double dPar1, dPar2 ;
|
|
ptLineL.z -= ( i - 1) * dH ;
|
|
double dCurrR = dMinRad + i * dR ;
|
|
if ( ! IntersLineBox( ptLineL, vtLineL, Point3d( -dCurrR, -dCurrR, 0), Point3d( dCurrR, dCurrR, dH), dPar1, dPar2) ||
|
|
dPar2 < -EPS_SMALL || dPar1 > dSgLen + EPS_SMALL)
|
|
++ nMiss ;
|
|
}
|
|
if ( nMiss == N_SLABS)
|
|
return CC_NO_INTERS ;
|
|
|
|
// Calcolo l'intersezione con la linea illimitata
|
|
int nIntType = LineConeFrustum( ptPLine, vtDLine, ptMinBase, vtDCone, 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& ptLine, const Vector3d& vtLine,
|
|
const Point3d& ptOTorus, const Vector3d& vtAxTorus, double dMinRad, double dMaxRad,
|
|
BOOLVECTOR& vbType, DBLVECTOR& vdPar)
|
|
{
|
|
// I Raggi devono essere positiv
|
|
if ( dMinRad < EPS_SMALL || dMaxRad < EPS_SMALL)
|
|
return T_ERROR ;
|
|
// Si richiede che i vettori siano normalizzati
|
|
if ( ! vtAxTorus.IsNormalized() || ! vtLine.IsNormalized())
|
|
return T_ERROR ;
|
|
|
|
// Sistema di riferimento del toro
|
|
Frame3d frTorusFrame ;
|
|
frTorusFrame.Set( ptOTorus, vtAxTorus) ;
|
|
// Porto la retta nel sistema di riferimento del toro
|
|
Point3d ptLn = ptLine ;
|
|
ptLn.ToLoc( frTorusFrame) ;
|
|
Vector3d vtLn = vtLine ;
|
|
vtLn.ToLoc( frTorusFrame) ;
|
|
|
|
// Setto i coefficienti dell'equazione
|
|
DBLVECTOR vdCoef( 5) ;
|
|
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
|
|
DBLVECTOR vdRoots ;
|
|
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]) {
|
|
swap( vdPar[ni], vdPar[nj]) ;
|
|
}
|
|
}
|
|
}
|
|
|
|
// Studio le soluzioni
|
|
int nIntType = T_ERROR ;
|
|
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 ;
|
|
}
|
|
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& ptLine, const Vector3d& vtLine,
|
|
const Point3d& ptOTorus, const Vector3d& vtAxTorus, double dMinRad, double dMaxRad,
|
|
BOOLVECTOR& vbType, DBLVECTOR& vdPar)
|
|
{
|
|
int nIntType = LineTorus( ptLine, vtLine, ptOTorus, vtAxTorus, dMinRad, dMaxRad, vbType, vdPar) ;
|
|
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& ptLine, const Vector3d& vtLine, double dSgLen,
|
|
const Point3d& ptOTorus, const Vector3d& vtAxTorus, double dMinRad, double dMaxRad,
|
|
BOOLVECTOR& vbType, DBLVECTOR& vdPar)
|
|
{
|
|
// Verifico se il segmento interseca il box del toro
|
|
Frame3d frTorus ; frTorus.Set( ptOTorus, vtAxTorus) ;
|
|
Point3d ptLineL = ptLine ; ptLineL.ToLoc( frTorus) ;
|
|
Vector3d vtLineL = vtLine ; vtLineL.ToLoc( frTorus) ;
|
|
double dTotRad = dMaxRad + dMinRad ;
|
|
double dU1, dU2 ;
|
|
if ( ! IntersLineBox( ptLineL, vtLineL, Point3d( -dTotRad, -dTotRad, -dMinRad), Point3d( dTotRad, dTotRad, dMinRad), dU1, dU2) ||
|
|
dU2 < -EPS_SMALL || dU1 > dSgLen + EPS_SMALL)
|
|
return T_NO_INT ;
|
|
|
|
// Calcolo l'intersezione con la linea illimitata
|
|
int nIntType = LineTorus( ptLine, vtLine, ptOTorus, vtAxTorus, dMinRad, dMaxRad, vbType, vdPar) ;
|
|
if ( nIntType == T_ERROR || nIntType == T_NO_INT)
|
|
return nIntType ;
|
|
|
|
// Elimino le intersezioni fuori dal segmento
|
|
int nSize = int( vdPar.size()) ;
|
|
for ( int n = 0 ; n < nSize ; ++ n) {
|
|
if ( vdPar[n] < -EPS_SMALL || vdPar[n] > dSgLen + EPS_SMALL) {
|
|
// tolgo l'intersezione dai vettori delle intersezioni
|
|
vdPar.erase( vdPar.begin() + n) ;
|
|
vbType.erase( vbType.begin() + n) ;
|
|
// aggiorno la dimensione dei vettori
|
|
-- nSize ;
|
|
// aggiorno l'indice
|
|
-- n ;
|
|
}
|
|
}
|
|
|
|
// Determino il numero delle intersezioni secanti
|
|
int nSecNum = 0 ;
|
|
for ( int n = 0 ; n < nSize ; ++ n) {
|
|
if ( vbType[n])
|
|
++ nSecNum ;
|
|
}
|
|
|
|
// Numero di punti 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& ptLine, const Vector3d& vtLine, double dSgLen, int nLinType,
|
|
const Point3d& ptOTorus, const Vector3d& vtAxTorus, double dMinRad, double dMaxRad,
|
|
BOOLVECTOR& vbType, DBLVECTOR& vdPar)
|
|
{
|
|
int nIntType ;
|
|
// Retta
|
|
if ( nLinType == Line)
|
|
nIntType = LineTorus( ptLine, vtLine, ptOTorus, vtAxTorus, dMinRad, dMaxRad, vbType, vdPar) ;
|
|
// Semi-retta
|
|
else if ( nLinType == Ray)
|
|
nIntType = RayTorus( ptLine, vtLine, ptOTorus, vtAxTorus, dMinRad, dMaxRad, vbType, vdPar) ;
|
|
// Segmento
|
|
else if ( nLinType == Segment)
|
|
nIntType = SegmentTorus( ptLine, vtLine, dSgLen, ptOTorus, vtAxTorus, dMinRad, dMaxRad, vbType, vdPar) ;
|
|
// Errore
|
|
else
|
|
nIntType = T_ERROR ;
|
|
// Ritorno errore
|
|
if ( nIntType == T_ERROR)
|
|
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 ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
// Valuta la posizione reciproca fra un componente lineare e la parte superiore
|
|
// ed interna di una superficie torica.
|
|
int
|
|
LinCompTorusInnUpInt( const Point3d& ptLine, const Vector3d& vtLine, double dSgLen, int nLinType,
|
|
const Point3d& ptOTorus, const Vector3d& vtAxTorus, double dMinRad, double dMaxRad,
|
|
BOOLVECTOR& vbType, DBLVECTOR& vdPar)
|
|
{
|
|
int nIntType ;
|
|
// Retta
|
|
if ( nLinType == Line)
|
|
nIntType = LineTorus( ptLine, vtLine, ptOTorus, vtAxTorus, dMinRad, dMaxRad, vbType, vdPar) ;
|
|
// Semi-retta
|
|
else if ( nLinType == Ray)
|
|
nIntType = RayTorus( ptLine, vtLine, ptOTorus, vtAxTorus, dMinRad, dMaxRad, vbType, vdPar) ;
|
|
// Segmento
|
|
else if ( nLinType == Segment)
|
|
nIntType = SegmentTorus( ptLine, vtLine, dSgLen, ptOTorus, vtAxTorus, dMinRad, dMaxRad, vbType, vdPar) ;
|
|
// 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 ;
|
|
}
|