EgtGeomKernel 1.9g1 :

- migliorata CollisionAvoidance con utensili generici
- gestione Tool potenziata con possibilità di restituire il profilo.
This commit is contained in:
Dario Sassi
2018-07-05 10:30:30 +00:00
parent 4eed828592
commit 73db4fe50c
11 changed files with 720 additions and 417 deletions
+319 -136
View File
@@ -12,6 +12,8 @@
//----------------------------------------------------------------------------
#include "stdafx.h"
#include "CurveLine.h"
#include "CurveArc.h"
#include "CAvToolTriangle.h"
#include "IntersLineSurfStd.h"
#include "IntersLineTria.h"
@@ -20,6 +22,57 @@
using namespace std ;
//----------------------------------------------------------------------------
static bool
GetTopTapFromPrevCurve( const ICurve* pPrevCurve)
{
if ( pPrevCurve == nullptr)
return false ;
if ( pPrevCurve->GetType() == CRV_LINE) {
const ICurveLine* pPrevLine = GetCurveLine( pPrevCurve) ;
Point3d ptPrevStart = pPrevLine->GetStart() ;
Point3d ptPrevEnd = pPrevLine->GetEnd() ;
if ( abs( ptPrevStart.y - ptPrevEnd.y) > EPS_SMALL ||
ptPrevStart.x > ptPrevEnd.x)
return true ;
}
else if ( pPrevCurve->GetType() == CRV_ARC) {
const ICurveArc* pPrevArc = GetCurveArc( pPrevCurve) ;
Point3d ptPrevStart ; pPrevArc->GetStartPoint( ptPrevStart) ;
Point3d ptPrevEnd ; pPrevArc->GetEndPoint( ptPrevEnd) ;
Point3d ptPrevCen = pPrevArc->GetCenter() ;
double dRadius = pPrevArc->GetRadius() ;
if ( abs( ptPrevCen.x) > EPS_SMALL)
return true ;
}
return false ;
}
//----------------------------------------------------------------------------
static bool
GetBotTapFromNextCurve( const ICurve* pNextCurve)
{
if ( pNextCurve == nullptr)
return false ;
if ( pNextCurve->GetType() == CRV_LINE) {
const ICurveLine* pNextLine = GetCurveLine( pNextCurve) ;
Point3d ptNextStart = pNextLine->GetStart() ;
Point3d ptNextEnd = pNextLine->GetEnd() ;
if ( abs( ptNextStart.y - ptNextEnd.y) > EPS_SMALL || ptNextStart.x < ptNextEnd.x)
return true ;
}
else if ( pNextCurve->GetType() == CRV_ARC) {
const ICurveArc* pNextArc = GetCurveArc( pNextCurve) ;
Point3d ptNextStart ; pNextArc->GetStartPoint( ptNextStart) ;
Point3d ptNextEnd ; pNextArc->GetEndPoint( ptNextEnd) ;
Point3d ptNextCen = pNextArc->GetCenter() ;
double dRadius = pNextArc->GetRadius() ;
if ( abs( ptNextCen.x) > EPS_SMALL)
return true ;
}
return false ;
}
//----------------------------------------------------------------------------
// La funzione determina la minima distanza di allontanamento lungo una direzione fissata
// per evitare la collisione tra un utensile ed un triangolo.
@@ -29,6 +82,9 @@ double
CAvToolTriangle( const Tool& tlTool, const Point3d& ptToolOrig, const Vector3d& vtToolAx,
const Triangle3d& trTria, const Vector3d& vtMove)
{
// Se avvicinamento non devo fare nulla
if ( vtMove * trTria.GetN() < - EPS_ZERO)
return 0. ;
// se utensile cilindrico
if ( tlTool.GetType() == Tool::CYLMILL) {
// parametri geometrici
@@ -57,7 +113,8 @@ CAvToolTriangle( const Tool& tlTool, const Point3d& ptToolOrig, const Vector3d&
return dDist2 ;
return ( dDist + dDist2) ;
}
else if ( tlTool.GetType() == Tool::GEN) {
// se utensile a naso di toro
else if ( tlTool.GetType() == Tool::BULLNOSEMILL) {
// parametri geometrici
double dCylHeigth = tlTool.GetHeigth() - tlTool.GetTipHeigth() ;
Point3d ptTorusCen = ptToolOrig - dCylHeigth * vtToolAx ;
@@ -104,6 +161,117 @@ CAvToolTriangle( const Tool& tlTool, const Point3d& ptToolOrig, const Vector3d&
return dDist2 ;
return ( dDist + dDist2) ;
}
// se utensile generico
else if ( tlTool.GetType() == Tool::GEN) {
// distanza di allontanamento
double dDist = 0 ;
// riferimento per componenti
Point3d ptCompOrig = ptToolOrig - tlTool.GetHeigth() * vtToolAx ;
// analizzo le curve del profilo a partire dall'ultima
const CurveComposite* pToolProfile = tlTool.GetOutline() ;
const ICurve* pCurve = pToolProfile->GetLastCurve() ;
const ICurve* pNextCurve = nullptr ;
while ( pCurve != nullptr) {
// distanza di allontanamento del tratto corrente
double dDist2 = 0 ;
// curva precedente
const ICurve* pPrevCurve = pToolProfile->GetPrevCurve() ;
// Se segmento
if ( pCurve->GetType() == CRV_LINE) {
// Recupero gli estremi
const ICurveLine* pLine = GetCurveLine( pCurve) ;
Point3d ptStart = pLine->GetStart() ;
Point3d ptEnd = pLine->GetEnd() ;
// Ne determino l'altezza
double dHeight = abs( ptStart.y - ptEnd.y) ;
if ( dHeight > EPS_SMALL) {
// Verifiche curva precedente per eventuale tappo sopra
bool bTop = GetTopTapFromPrevCurve( pPrevCurve) ;
// Verifiche curva successiva per eventuale tappo sotto
bool bBot = GetBotTapFromNextCurve( pNextCurve) ;
// Calcolo distanza di allontanamento del componente corrente
if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL) {
double dRadius = ptStart.x ;
// riferimento del cilindro in alto
ptCompOrig += dHeight * vtToolAx ;
dDist2 = CAvCylinderTriangle( ptCompOrig, vtToolAx, dHeight, dRadius, trTria, vtMove, bTop, bBot) ;
}
else if ( ptStart.x > ptEnd.x) {
double dMaxRad = ptStart.x ;
double dMinRad = ptEnd.x ;
// riferimento del cono in basso (base più piccola)
dDist2 = CAvTrConeTriangle( ptCompOrig, vtToolAx, dMinRad, dMaxRad, dHeight, trTria, vtMove, bTop, bBot) ;
// sposto riferimento in alto
ptCompOrig += dHeight * vtToolAx ;
}
else if ( ptStart.x < ptEnd.x) {
double dMaxRad = ptEnd.x ;
double dMinRad = ptStart.x ;
// riferimento del cono in alto (base più piccola)
ptCompOrig += dHeight * vtToolAx ;
dDist2 = CAvTrConeTriangle( ptCompOrig, - vtToolAx, dMinRad, dMaxRad, dHeight, trTria, vtMove, bTop, bBot) ;
}
}
}
// Se arco
else if ( pCurve->GetType() == CRV_ARC) {
// Recupero estremi, centro e raggio
const ICurveArc* pArc = GetCurveArc( pCurve) ;
Point3d ptStart ; pArc->GetStartPoint( ptStart) ;
Point3d ptEnd ; pArc->GetEndPoint( ptEnd) ;
Point3d ptCen = pArc->GetCenter() ;
double dRadius = pArc->GetRadius() ;
// Calcolo della distanza di allontanamento del componente corrente
// Sfera
if ( abs( ptCen.x) < EPS_SMALL) {
// riferimento sul centro sfera
ptCompOrig += ( ptCen.y - ptEnd.y) * vtToolAx ;
dDist2 = CAvSphereTriangle( ptCompOrig, dRadius, trTria, vtMove) ;
// sposto riferimento in alto
ptCompOrig += ( ptStart.y - ptCen.y) * vtToolAx ;
}
// Toro
else {
// Verifiche curva precedente per eventuale tappo sopra
bool bTop = GetTopTapFromPrevCurve( pPrevCurve) ;
// Verifiche curva successiva per eventuale tappo sotto
bool bBot = GetBotTapFromNextCurve( pNextCurve) ;
// riferimento sul centro toro
ptCompOrig += ( ptCen.y - ptEnd.y) * vtToolAx ;
// verifica presenza semitori
bool bHalfTorusDown = ( ptEnd.y < ptCen.y - EPS_SMALL) ;
bool bHalfTorusUp = ( ptStart.y > ptCen.y + EPS_SMALL) ;
// semi-toro sotto
if (bHalfTorusDown) {
double dMyDist = CAvTorusTriangle( ptCompOrig, vtToolAx, ptCen.x, dRadius, trTria, vtMove,
( bHalfTorusUp ? true : bTop), bBot) ;
if ( dMyDist < - EPS_SMALL)
return dMyDist ;
dDist2 = max( dDist2, dMyDist) ;
}
// semi-toro sopra
if ( bHalfTorusUp) {
double dMyDist = CAvTorusTriangle( ptCompOrig, - vtToolAx, ptCen.x, dRadius, trTria, vtMove,
bTop, ( bHalfTorusDown ? true : bBot)) ;
if ( dMyDist < - EPS_SMALL)
return dMyDist ;
dDist2 = max( dDist2, dMyDist) ;
}
// sposto riferimento in alto
ptCompOrig += ( ptStart.y - ptCen.y) * vtToolAx ;
}
}
// Aggiornamento distanza allontanamento
if ( dDist2 < - EPS_SMALL)
return dDist2 ;
dDist += dDist2 ;
ptCompOrig += dDist2 * vtMove ;
// passo alla curva precedente
pNextCurve = pCurve ;
pCurve = pPrevCurve ;
}
return dDist ;
}
// altrimenti utensile di tipo non gestito
else
return - 1. ;
@@ -117,13 +285,13 @@ CAvToolTriangle( const Tool& tlTool, const Point3d& ptToolOrig, const Vector3d&
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
// Se la sfera sta già tutta dalla parte esterna 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)
if ( vtVert0 * trTria.GetN() > dSpheRad - EPS_SMALL &&
vtVert1 * trTria.GetN() > dSpheRad - EPS_SMALL &&
vtVert2 * trTria.GetN() > dSpheRad - EPS_SMALL)
return 0. ;
// Valuto Tangenza col piano
@@ -151,13 +319,14 @@ CAvSphereTriangle( const Point3d& ptSpheCen, double dSpheRad, const Triangle3d&
//----------------------------------------------------------------------------
// Calcola la distanza di allontanamento lungo una direzione fissata di una sfera da un piano.
// Se ritorno -1 non è errore, ma sfera interseca piano e movimento nel 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)
if ( abs( vtPlaneN * vtMove) < EPS_ZERO) {
if ( abs( ( ptSpheCen - ptPlane) * vtPlaneN) > dSpheRad - EPS_SMALL)
return 0. ;
else
return -1. ;
@@ -191,8 +360,8 @@ SphereSegmentLeakDist( const Point3d& ptSpheCen, double dSpheRad,
}
// Controllo con gli estremi
Point3d ptSegEnd = ptSeg + dSegLen * vtSegDir ;
double dDistStart = SpherePointLeakDist( ptSpheCen, dSpheRad, ptSeg, vtMove) ;
double dDistEnd = SpherePointLeakDist( ptSpheCen, dSpheRad, ptSegEnd, vtMove) ;
double dDistStart = SpherePointLeakDist( ptSpheCen, dSpheRad - EPS_SMALL, ptSeg, vtMove) ;
double dDistEnd = SpherePointLeakDist( ptSpheCen, dSpheRad - EPS_SMALL, ptSegEnd, vtMove) ;
// Restituisco il massimo
return max( dLeakDistIn, max( dDistStart, dDistEnd)) ;
}
@@ -366,10 +535,9 @@ CylSegmentLeakDistOrtMotion( const Point3d& ptCylOrig, const Vector3d& vtCylAx,
const Point3d& ptSeg, const Vector3d& vtSeg, double dSegLen, const Vector3d& vtMove,
bool bTop, bool bBot)
{
double dTopTol = bTop ? EPS_SMALL : - EPS_SMALL ;
double dBotTol = bBot ? - EPS_SMALL : EPS_SMALL ;
// Le variabili fanno rifermiento a un sistema di riferimento
// con origine nel centro del disco nella posizione iniziale.
double dTopTol = ( bTop ? EPS_SMALL : - EPS_SMALL) ;
double dBotTol = ( bBot ? - EPS_SMALL : EPS_SMALL) ;
// Riferimento con origine nel centro del disco nella posizione iniziale.
// X := vtCylAx, Y:= vtMove, Z:= vtCylAx ^ vtMove.
Vector3d vtPlane = vtCylAx ^ vtMove ;
vtPlane.Normalize() ;
@@ -382,8 +550,11 @@ CylSegmentLeakDistOrtMotion( const Point3d& ptCylOrig, const Vector3d& 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.
// Se entrambi gli estremi sono sopra o sotto, non ci può essere interferenza
if ( ( dCordStart1 > dTopTol && dCordEnd1 > dTopTol) ||
( dCordStart1 < - dCylHei + dBotTol && dCordEnd1 < - dCylHei + dBotTol))
return 0. ;
// Se entrambi gli estremi del segmento sono a un lato, non ci può essere interferenza
double dCordStart2 = vtSegStart23 * vtPlane ;
double dCordEnd2 = vtSegEnd23 * vtPlane ;
if ( ( dCordStart2 > dCylRad && dCordEnd2 > dCylRad) ||
@@ -393,49 +564,46 @@ CylSegmentLeakDistOrtMotion( const Point3d& ptCylOrig, const Vector3d& vtCylAx,
double dBaseLeakDist = DiskSegmentLeakDistOrtMot( ptCylOrig, vtCylAx, dCylRad, ptSeg, vtSeg, dSegLen, vtMove) ;
double dBottomLeakDist = DiskSegmentLeakDistOrtMot( ptCylOrig - dCylHei * vtCylAx, vtCylAx, dCylRad,
ptSeg, vtSeg, dSegLen, vtMove) ;
double dSurfLeakDist = 0. ;
if ( ( dCordStart1 < dTopTol && dCordStart1 > - dCylHei + dBotTol) ||
( dCordEnd1 < dTopTol && dCordEnd1 > - dCylHei + dBotTol)) {
// 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 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 < dTopTol && dTanCordPlus1 > - dCylHei + dBotTol)) {
dSurfLeakDist = max( ( ( ptSeg - ptCylOrig) + dPlusU * vtSeg) * vtMove + dDotRemRad, 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 < dTopTol && dTanCordPlus1 > - dCylHei + dBotTol)) {
dSurfLeakDist = max( ( ( ptSeg - ptCylOrig) + dPlusU * vtSeg) * vtMove + dDotRemRad, 0.) ;
}
if ( dMinusU > - EPS_SMALL && dMinusU < dSegLen + EPS_SMALL &&
( dTanCordMinus1 < dTopTol && dTanCordMinus1 > - dCylHei + dBotTol)) {
double dNewDist = max( ( ( ptSeg - ptCylOrig) + dMinusU * vtSeg) * vtMove + dDotRemRad, 0.) ;
dSurfLeakDist = max( dNewDist, dSurfLeakDist) ;
}
if ( dMinusU > - EPS_SMALL && dMinusU < dSegLen + EPS_SMALL &&
( dTanCordMinus1 < dTopTol && dTanCordMinus1 > - dCylHei + dBotTol)) {
double dNewDist = max( ( ( ptSeg - ptCylOrig) + dMinusU * vtSeg) * vtMove + dDotRemRad, 0.) ;
dSurfLeakDist = max( dNewDist, dSurfLeakDist) ;
}
}
return max( max( dBaseLeakDist, dBottomLeakDist), max( dSurfLeakDist, 0.)) ;
@@ -609,10 +777,10 @@ TrConeTriangleInteriorLeakDistLongMot( const Point3d& ptMinBase, const Vector3d&
// altrimenti sono i dischi a determinare l'allontanamento
double dMove = 0 ;
if ( ( nMinLeakType == 1 && IsPointInsideTriangle( ptMinTouch, trTria)) ||
( nMinLeakType == 3 && CoplanarDiscTriangleInterferance( ptMinTouch, dMinBaseR, trTria)))
( nMinLeakType == 4 && CoplanarDiscTriangleInterferance( ptMinTouch, dMinBaseR, trTria)))
dMove = max( dMinLeakDist, 0.) ;
if ( ( nMaxLeakType == 1 && IsPointInsideTriangle( ptMaxTouch, trTria)) ||
( nMaxLeakType == 3 && CoplanarDiscTriangleInterferance( ptMaxTouch, dMaxBaseR, trTria)))
( nMaxLeakType == 4 && CoplanarDiscTriangleInterferance( ptMaxTouch, dMaxBaseR, trTria)))
dMove = max( dMove, dMaxLeakDist) ;
return dMove ;
}
@@ -944,13 +1112,18 @@ TorusTriangleInteriorLeakDistOrtMot( const Point3d& ptTorusCen, const Vector3d&
// Se piano ortogonale all'asse del toro non ci può essere tangenza
if ( ! vtPlaneOrtToAx.Normalize( EPS_ZERO))
return 0. ;
// Se la componente del versore normale al triangolo nella direzione
// del moto è nulla, non può esserci contatto con l'interno
double dDotMoveN = vtMove * trTria.GetN() ;
if ( abs( dDotMoveN) < EPS_ZERO)
return 0. ;
// Scarto il primo contatto
if ( vtPlaneOrtToAx * vtMove < 0.)
return 0. ;
vtPlaneOrtToAx *= dMaxRad ;
// Trovo il punto che toccherà il piano
Point3d ptTouch = ptTorusCen - vtPlaneOrtToAx - dMinRad * trTria.GetN() ;
double dLeakDist = max( ( ( trTria.GetP( 0) - ptTouch) * trTria.GetN()) / ( vtMove * trTria.GetN()), 0.) ;
double dLeakDist = max( ( ( trTria.GetP( 0) - ptTouch) * trTria.GetN()) / dDotMoveN, 0.) ;
// Se il punto di contatto è interno al triangolo restituisco distanza di fuga non negativa
if ( IsPointInsideTriangle( ptTouch + dLeakDist * vtMove, trTria))
return dLeakDist ;
@@ -959,6 +1132,16 @@ TorusTriangleInteriorLeakDistOrtMot( const Point3d& ptTorusCen, const Vector3d&
// DISTANZA DI ALLONTANAMENTO PER DISCHI
//----------------------------------------------------------------------------
double
DiskPointLeakDistLongMot( const Point3d& ptDiskCen, double dDiskRad,
const Point3d& ptP, const Vector3d& vtMove)
{
if ( GetPointLineSqDist( ptP, ptDiskCen, vtMove) < dDiskRad * dDiskRad)
return PointPlaneSignedDist( ptP, ptDiskCen, vtMove) ;
return 0. ;
}
//----------------------------------------------------------------------------
double
DiskSegmentLeakDistLongMot( const Point3d& ptDiskCen, double dDiskRad,
@@ -1067,69 +1250,6 @@ DiskTriaInteriorLeakDistLongMot( const Point3d& ptDiskCen, double dDiskRad,
return max( dDistPlus, dDistMinus) ;
}
//----------------------------------------------------------------------------
// Valuta l'allontanamento di un disco, che trasla lungo il proprio asse di simmetria,
// da un piano. Il disco è descritto dal suo centro nella posizione iniziale e dal raggio.
// Il piano è descritto da un suo punto e dal suo versore normale. Il moto è descritto
// dal versore di traslazione.
// La funzione restituisce un intero che descrive la situazione di allontanamento e,
// nel caso che abbia senso, per referenza restituisce il punto in cui avviene
// l'estremo contatto.
// 0: Nessun contatto
// 1: Un contatto
// 2: Disco e piano ortogonali, il contatto è una semiretta
// 3: Disco e piano paralleli, la superficie di contatto è il disco intero
// Nel caso 0 il parametro ptTouch non ha senso, così come nel caso 2.
// Nel caso 3 ptTouch è il centro del disco nella posizione finale.
int
DiskPlaneLastContactLongMot( const Point3d& ptDiskCen, double dDiskRad,
const Point3d& ptPlane, const Vector3d& vtPlane,
const Vector3d& vtMove, Point3d& ptTouch)
{
// Se disco e piano sono paralleli
if ( AreSameOrOppositeVectorApprox( vtMove, vtPlane)) {
double dDist = PointPlaneSignedDist( ptPlane, ptDiskCen, vtMove) ;
if ( dDist > - EPS_SMALL) {
ptTouch = ptDiskCen + dDist * vtMove ;
return 4 ;
}
return 0 ;
}
// Vettore radiale
Vector3d vtRadLine = vtMove * ( vtPlane * vtMove) - vtPlane ;
// Disco e piano ortogonali
if ( vtRadLine.IsNormalized()) {
double dDist = abs( PointPlaneSignedDist(ptPlane, ptDiskCen, vtMove)) ;
if ( abs( dDist - dDiskRad) < EPS_SMALL)
return 2 ;
else if ( dDist < dDiskRad)
return 3 ;
return 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.
vtRadLine.Normalize() ;
// Punti delle due rette candidate all'intersezione col triangolo
Point3d ptStPlus = ptDiskCen + dDiskRad * vtRadLine ;
Point3d ptStMinus = ptDiskCen - dDiskRad * vtRadLine ;
// Parametri d'intersezione delle rette col piano
double dDistPlus = ( ( ptPlane - ptStPlus) * vtPlane) / ( vtMove * vtPlane) ;
double dDistMinus = ( ( ptPlane - ptStMinus) * vtPlane) / ( vtMove * vtPlane) ;
double dDist ;
if ( dDistPlus > dDistMinus) {
dDist = dDistPlus ;
ptTouch = ptStPlus + dDist * vtMove ;
}
else {
dDist = dDistMinus ;
ptTouch = ptStMinus + dDist * vtMove ;
}
if ( dDist > - EPS_SMALL)
return 1 ;
return 0 ;
}
//----------------------------------------------------------------------------
double
DiskPointLeakDistOrtMot( const Point3d& ptDisc, const Vector3d& vtDiskAx, double dDiskRad,
@@ -1256,16 +1376,16 @@ ThreePointPlaneSignedDist( const Triangle3d& trTria, const Point3d& ptPlane, con
}
//----------------------------------------------------------------------------
// 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.
// Calcola, se esiste, il punto di una retta a distanza con segno data da un piano.
// Il piano è descritto da punto e versore normale.
// La retta è descritta da punto e versore direzione.
// I casi possibili sono:
// - Nessun punto della retta 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 della retta 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 della retta 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)
@@ -1412,12 +1532,12 @@ CoplanarDiscTriangleInterferance( const Point3d& ptCen, double dRad, const Trian
// 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)
FindLineLineMinDistPar( const Point3d& ptL1, const Vector3d& vtV1,
const Point3d& ptL2, const Vector3d& vtV2,
double& dU1, double& dU2)
{
// Se le rette sono parallele
if ( abs( abs( vtV1 * vtV2) - 1) < EPS_ZERO)
if ( AreSameOrOppositeVectorExact( vtV1, vtV2))
return false ;
// Vettore congiungente i punti iniziali
@@ -1482,3 +1602,66 @@ SphereLineTangentPoints( const Point3d& ptSpheCen, double dSpheRad,
}
return nRoots ;
}
//----------------------------------------------------------------------------
// Valuta l'allontanamento di un disco, lungo il proprio asse di simmetria, da un piano.
// Il disco è descritto dal centro nella posizione iniziale e dal raggio (la normale è il versore traslazione).
// Il piano è descritto da un suo punto e dal suo versore normale.
// Il moto è descritto dal versore di traslazione.
// Il valore restituito è un intero che descrive la situazione di allontanamento e,
// quando sensato, per referenza restituisce il punto di ultimo contatto.
// 0: Nessun contatto
// 1: Un contatto
// 2: Disco e piano ortogonali, con disco tg al piano, il contatto è una semiretta
// 3: Disco e piano ortogonali, con disco secante il piano, il contatto è una striscia
// 4: Disco e piano paralleli, come ultimo contatto si restituisce il centro.
// Nel caso 0 il parametro ptTouch non ha senso, così come nel caso 2 e nel caso 3
int
DiskPlaneLastContactLongMot( const Point3d& ptDiskCen, double dDiskRad,
const Point3d& ptPlane, const Vector3d& vtPlane,
const Vector3d& vtMove, Point3d& ptTouch)
{
// Se disco e piano sono paralleli
if ( AreSameOrOppositeVectorApprox( vtMove, vtPlane)) {
double dDist = PointPlaneSignedDist( ptPlane, ptDiskCen, vtMove) ;
if ( dDist > - EPS_SMALL) {
ptTouch = ptDiskCen + dDist * vtMove ;
return 4 ;
}
return 0 ;
}
// Vettore radiale
Vector3d vtRadLine = vtMove * ( vtPlane * vtMove) - vtPlane ;
// Disco e piano ortogonali
if ( vtRadLine.IsNormalized()) {
double dDist = abs( PointPlaneSignedDist(ptPlane, ptDiskCen, vtMove)) ;
if ( abs( dDist - dDiskRad) < EPS_SMALL)
return 2 ;
else if ( dDist < dDiskRad)
return 3 ;
return 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.
vtRadLine.Normalize() ;
// Punti delle due rette candidate all'intersezione col triangolo
Point3d ptStPlus = ptDiskCen + dDiskRad * vtRadLine ;
Point3d ptStMinus = ptDiskCen - dDiskRad * vtRadLine ;
// Parametri d'intersezione delle rette col piano
double dDistPlus = ( ( ptPlane - ptStPlus) * vtPlane) / ( vtMove * vtPlane) ;
double dDistMinus = ( ( ptPlane - ptStMinus) * vtPlane) / ( vtMove * vtPlane) ;
double dDist ;
if ( dDistPlus > dDistMinus) {
dDist = dDistPlus ;
ptTouch = ptStPlus + dDist * vtMove ;
}
else {
dDist = dDistMinus ;
ptTouch = ptStMinus + dDist * vtMove ;
}
if ( dDist > - EPS_SMALL)
return 1 ;
return 0 ;
}