diff --git a/CAvToolTriangle.cpp b/CAvToolTriangle.cpp index 63a001c..54febf1 100644 --- a/CAvToolTriangle.cpp +++ b/CAvToolTriangle.cpp @@ -1,7 +1,7 @@ //---------------------------------------------------------------------------- // EgalTech 2018-2018 //---------------------------------------------------------------------------- -// File : CAvToolTriangle.cpp Data : 27.04.18 Versione : 1.9e1 +// File : CAvToolTriangle.cpp Data : 19.07.18 Versione : 1.9g2 // Contenuto : Implementazione delle funzioni ToolTriangleCollisionAvoid. // // @@ -19,6 +19,7 @@ #include "IntersLineTria.h" #include "/EgtDev/Include/ENkPolynomialRoots.h" #include "/EgtDev/Include/EgtNumUtils.h" +#include "/EgtDev/Include/EGkIntervals.h" using namespace std ; @@ -34,13 +35,13 @@ GetTopTapFromPrevCurve( const ICurve* pPrevCurve) const Point3d& ptPrevEnd = pPrevLine->GetEnd() ; if ( abs( ptPrevStart.y - ptPrevEnd.y) > EPS_SMALL || ptPrevStart.x > ptPrevEnd.x) - return true ; + return true ; } else if ( pPrevCurve->GetType() == CRV_ARC) { const ICurveArc* pPrevArc = GetCurveArc( pPrevCurve) ; const Point3d& ptPrevCen = pPrevArc->GetCenter() ; if ( abs( ptPrevCen.x) > EPS_SMALL) - return true ; + return true ; } return false ; } @@ -51,20 +52,20 @@ GetBotTapFromNextCurve( const ICurve* pNextCurve) { if ( pNextCurve == nullptr) return false ; - if ( pNextCurve->GetType() == CRV_LINE) { + if ( pNextCurve->GetType() == CRV_LINE) { const ICurveLine* pNextLine = GetCurveLine( pNextCurve) ; const Point3d& ptNextStart = pNextLine->GetStart() ; - const Point3d& ptNextEnd = pNextLine->GetEnd() ; + const Point3d& ptNextEnd = pNextLine->GetEnd() ; if ( abs( ptNextStart.y - ptNextEnd.y) > EPS_SMALL || ptNextStart.x < ptNextEnd.x) - return true ; + return true ; } else if ( pNextCurve->GetType() == CRV_ARC) { const ICurveArc* pNextArc = GetCurveArc( pNextCurve) ; const Point3d& ptNextCen = pNextArc->GetCenter() ; if ( abs( ptNextCen.x) > EPS_SMALL) - return true ; + return true ; } - return false ; + return false ; } //---------------------------------------------------------------------------- @@ -169,7 +170,7 @@ CAvToolTriangle( const Tool& tlTool, const Point3d& ptToolOrig, const Vector3d& // distanza di allontanamento del tratto corrente double dDist2 = 0 ; // curva precedente - const ICurve* pPrevCurve = pToolProfile->GetPrevCurve() ; + const ICurve* pPrevCurve = pToolProfile->GetPrevCurve() ; // Se segmento if ( pCurve->GetType() == CRV_LINE) { // Recupero gli estremi @@ -177,14 +178,14 @@ CAvToolTriangle( const Tool& tlTool, const Point3d& ptToolOrig, const Vector3d& const Point3d& ptStart = pLine->GetStart() ; const Point3d& ptEnd = pLine->GetEnd() ; // Ne determino l'altezza - double dHeight = abs( ptStart.y - ptEnd.y) ; + 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) ; + bool bBot = GetBotTapFromNextCurve( pNextCurve) ; // Calcolo distanza di allontanamento del componente corrente - if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL) { + if ( abs( ptStart.x - ptEnd.x) < EPS_SMALL) { double dRadius = ptStart.x ; // riferimento del cilindro in alto ptCompOrig += dHeight * vtToolAx ; @@ -193,7 +194,7 @@ CAvToolTriangle( const Tool& tlTool, const Point3d& ptToolOrig, const Vector3d& else if ( ptStart.x > ptEnd.x) { double dMaxRad = ptStart.x ; double dMinRad = ptEnd.x ; - // riferimento del cono in basso (base più piccola) + // 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 ; @@ -203,9 +204,9 @@ CAvToolTriangle( const Tool& tlTool, const Point3d& ptToolOrig, const Vector3d& 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) ; + dDist2 = CAvTrConeTriangle( ptCompOrig, - vtToolAx, dMinRad, dMaxRad, dHeight, trTria, vtMove, bTop, bBot) ; } - } + } } // Se arco else if ( pCurve->GetType() == CRV_ARC) { @@ -215,51 +216,62 @@ CAvToolTriangle( const Tool& tlTool, const Point3d& ptToolOrig, const Vector3d& Point3d ptEnd ; pArc->GetEndPoint( ptEnd) ; const Point3d& ptCen = pArc->GetCenter() ; double dRadius = pArc->GetRadius() ; - // Calcolo della distanza di allontanamento del componente corrente - // Sfera + double dAngToCen = pArc->GetAngCenter() ; + // Calcolo della distanza di allontanamento del componente corrente + // Se sfera if ( abs( ptCen.x) < EPS_SMALL) { // riferimento sul centro sfera - ptCompOrig += ( ptCen.y - ptEnd.y) * vtToolAx ; + ptCompOrig += ( ptCen.y - ptEnd.y) * vtToolAx ; dDist2 = CAvSphereTriangle( ptCompOrig, dRadius, trTria, vtMove) ; // sposto riferimento in alto - ptCompOrig += ( ptStart.y - ptCen.y) * vtToolAx ; + ptCompOrig += ( ptStart.y - ptCen.y) * vtToolAx ; } - // Toro + // altrimenti toro else { // Verifiche curva precedente per eventuale tappo sopra bool bTop = GetTopTapFromPrevCurve( pPrevCurve) ; // Verifiche curva successiva per eventuale tappo sotto - bool bBot = GetBotTapFromNextCurve( pNextCurve) ; + 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) ; + bool bHalfTorusDown = ( ptEnd.y < ptCen.y - EPS_SMALL) ; + bool bHalfTorusUp = ( ptStart.y > ptCen.y + EPS_SMALL) ; + // semi-toro sotto + if ( bHalfTorusDown) { + double dMyDist ; + if ( dAngToCen < 0) + dMyDist = CAvTorusTriangle( ptCompOrig, vtToolAx, ptCen.x, dRadius, trTria, vtMove, + ( bHalfTorusUp ? true : bTop), bBot) ; + else + dMyDist = CAvConcaveTorusTriangle( 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)) ; + double dMyDist ; + if ( dAngToCen < 0) + dMyDist = CAvTorusTriangle( ptCompOrig, - vtToolAx, ptCen.x, dRadius, trTria, vtMove, + bTop, ( bHalfTorusDown ? true : bBot)) ; + else + dMyDist = CAvConcaveTorusTriangle( 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 ; - } + ptCompOrig += ( ptStart.y - ptCen.y) * vtToolAx ; + } } // Aggiornamento distanza allontanamento if ( dDist2 < - EPS_SMALL) return dDist2 ; dDist += dDist2 ; - ptCompOrig += dDist2 * vtMove ; + ptCompOrig += dDist2 * vtMove ; // passo alla curva precedente pNextCurve = pCurve ; pCurve = pPrevCurve ; @@ -459,15 +471,42 @@ CAvCylinderTriangle( const Point3d& ptCylOrig, const Vector3d& vtCylAx, double d } // Movimento perpendicolare all'asse del cilindro else if ( nMotionType == 3) { - // PROVE PUNTI E SEGMENTI + double dLeakDist = 0. ; + // INTERNO : se distanza di allontanamento da interno è positiva, abbiamo finito + Point3d ptTopCont, ptBotCont ; + double dTopLeak = DiskPlaneLeakDistOrtMot( ptCylOrig, vtCylAx, dRad, trTria.GetP( 0), trTria.GetN(), + vtMove, ptTopCont) ; + double dBotLeak = DiskPlaneLeakDistOrtMot( ptCylOrig - dHeigth * vtCylAx, vtCylAx, dRad, + trTria.GetP( 0), trTria.GetN(), vtMove, ptBotCont) ; + bool bTopInn = IsPointInsideTriangle( ptTopCont, trTria) ; + bool bBotInn = IsPointInsideTriangle( ptBotCont, trTria) ; + if ( bTopInn) { + if ( bBotInn) + dLeakDist = max( dLeakDist, max( dTopLeak, dBotLeak)) ; + else if ( dTopLeak > dBotLeak) + dLeakDist = max( dLeakDist, dTopLeak) ; + } + else if ( bBotInn) { + if ( dBotLeak > dTopLeak) + dLeakDist = max( dLeakDist, dBotLeak) ; + } + else if ( abs( dTopLeak - dBotLeak) < EPS_SMALL) { + Point3d ptInt1, ptInt2 ; + int nRes = IntersLineTria( ptTopCont, ptBotCont, trTria, ptInt1, ptInt2) ; + if ( nRes != ILTT_NO) + dLeakDist = max( dLeakDist, ( dTopLeak + dBotLeak) / 2) ; + } + // Se distanza da interno positiva abbiamo finito + if ( dLeakDist > EPS_SMALL) + return dLeakDist ; + // PUNTI for ( int nVrt = 0 ; nVrt < 3 ; ++ nVrt) { double dCurDist = CylPointLeakDistOrtMotion( ptCylOrig, vtCylAx, dHeigth, dRad, trTria.GetP( nVrt), vtMove, bTop, bBot) ; if ( dLeakDist < dCurDist) dLeakDist = dCurDist ; - } - // FINE PROVE PUNTI - // INIZIO PROVA SEGMENTI + } + // SEGMENTI for ( int nVrtS = 0 ; nVrtS < 3 ; ++ nVrtS) { int nVrtE = ( nVrtS + 1) % 3 ; Vector3d vtSeg = trTria.GetP( nVrtE) - trTria.GetP( nVrtS) ; @@ -477,22 +516,7 @@ CAvCylinderTriangle( const Point3d& ptCylOrig, const Vector3d& vtCylAx, double d trTria.GetP( nVrtS), vtSeg, dSegLen, vtMove, bTop, bBot) ; if ( dLeakDist < dCurDist) dLeakDist = dCurDist ; - } - // FINE PROVA SEGMENTI - // PROVA INTERNO - Point3d ptBaseCont, ptBottomCont ; - double dBaseLeak = DiskPlaneLeakDistOrtMot( ptCylOrig, vtCylAx, dRad, trTria.GetP( 0), trTria.GetN(), - vtMove, ptBaseCont) ; - double dBottomLeak = DiskPlaneLeakDistOrtMot( ptCylOrig - dHeigth * vtCylAx, vtCylAx, dRad, - trTria.GetP( 0), trTria.GetN(), vtMove, ptBottomCont) ; - if ( ! IsPointInsideTriangle( ptBaseCont, trTria)) - dBaseLeak = 0. ; - if ( ! IsPointInsideTriangle( ptBottomCont, trTria)) - dBottomLeak = 0. ; - double dInnerLeak = max( dBaseLeak, dBottomLeak) ; - if ( dLeakDist < dInnerLeak) - dLeakDist = dInnerLeak ; - // FINE PROVA INTERNO + } return dLeakDist ; } // Movimento generico @@ -560,7 +584,7 @@ CylSegmentLeakDistOrtMotion( const Point3d& ptCylOrig, const Vector3d& vtCylAx, 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 + // 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) || @@ -570,7 +594,7 @@ 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. ; // Se il vettore del segmento è parallelo all'asse del cilindro, // il suo prodotto vettoriale con il versore dell'asse è nullo. @@ -635,7 +659,7 @@ CAvTrConeTriangle( const Point3d& ptMinBase, const Vector3d& vtTrConeAx, double dMaxDistV = max( dMaxDistV, PointPlaneSignedDist( trTria.GetP( 2), ptBase, vtMove)) ; if ( dMaxDistV < 0.) return 0. ; - // Distanza di allontanamento dall'interno + // Distanza di allontanamento dall'interno double dInnLeakDist = TrConeTriangleInteriorLeakDistLongMot( ptMinBase, vtTrConeAx, dMinBaseR, dMaxBaseR, dTrConeH, trTria, vtMove) ; if ( dInnLeakDist > EPS_SMALL) @@ -659,24 +683,29 @@ CAvTrConeTriangle( const Point3d& ptMinBase, const Vector3d& vtTrConeAx, double } // Allontanamento in direzione ortogonale all'asse del cono else if ( AreOrthoApprox( vtTrConeAx, vtMove)) { - double dOutLeakDist = 0. ; + double dLeakDist = 0. ; + // Distanza di allontanamento dall'interno del trianolo: se positiva, abbiamo finito + double dInnLeakDist = TrConeTriangleInteriorLeakDistOrtMot( ptMinBase, vtTrConeAx, dMinBaseR, dMaxBaseR, dTrConeH, + trTria, vtMove) ; + if ( dInnLeakDist > EPS_SMALL) + return dInnLeakDist ; + else + dLeakDist = max( dLeakDist, dInnLeakDist) ; // Distanza di allontanamento da vertici e lati for ( int nV = 0; nV < 3; ++ nV) { // Dai vertici double dCurVertDist = TrConePointLeakDistOrtMot( ptMinBase, vtTrConeAx, dMinBaseR, dMaxBaseR, dTrConeH, trTria.GetP( nV), vtMove, bTop, bBot) ; - dOutLeakDist = max( dOutLeakDist, dCurVertDist) ; + dLeakDist = max( dLeakDist, dCurVertDist) ; // Dal lato Vector3d vtSeg = trTria.GetP( ( nV + 1) % 3) - trTria.GetP( nV) ; double dSegLen = vtSeg.Len() ; vtSeg /= dSegLen ; double dCurSegDist = TrConeSegmentLeakDistOrtMot( ptMinBase, vtTrConeAx, dMinBaseR, dMaxBaseR, dTrConeH, trTria.GetP( nV), vtSeg, dSegLen, vtMove, bTop, bBot) ; - dOutLeakDist = max( dOutLeakDist, dCurSegDist) ; - } - double dInnLeakDist = TrConeTriangleInteriorLeakDistOrtMot( ptMinBase, vtTrConeAx, dMinBaseR, dMaxBaseR, dTrConeH, - trTria, vtMove) ; - return max( dOutLeakDist, dInnLeakDist) ; + dLeakDist = max( dLeakDist, dCurSegDist) ; + } + return dLeakDist ; } // Movimento generico else @@ -712,7 +741,7 @@ TrConePointLeakDistLongMot( const Point3d& ptMinBase, const Vector3d& vtTrConeAx double dMinBaseLeakDist = PointPlaneSignedDist( ptP, ptMinBase, vtMove) ; double dMaxBaseLeakDist = PointPlaneSignedDist( ptP, ptMinBase + dTrConeH * vtTrConeAx, vtMove) ; return max( max( dMinBaseLeakDist, dMaxBaseLeakDist), 0.) ; - } + } } //---------------------------------------------------------------------------- @@ -775,33 +804,46 @@ double TrConeTriangleInteriorLeakDistLongMot( const Point3d& ptMinBase, const Vector3d& vtTrConeAx, double dMinBaseR, double dMaxBaseR, double dTrConeH, const Triangle3d& trTria, const Vector3d& vtMove) { - // Distanza di allontanamento del disco minore - Point3d ptMinTouch ; - int nMinLeakType = DiskPlaneLastContactLongMot( ptMinBase, dMinBaseR, trTria.GetP( 0), trTria.GetN(), - vtMove, ptMinTouch) ; - double dMinLeakDist = ( ptMinTouch - ptMinBase) * vtMove ; - // Distanza di allontanamento del disco maggiore - Point3d ptMaxTouch ; Point3d ptMaxBase = ptMinBase + dTrConeH * vtTrConeAx ; - int nMaxLeakType = DiskPlaneLastContactLongMot( ptMaxBase, dMaxBaseR, trTria.GetP( 0), trTria.GetN(), - vtMove, ptMaxTouch) ; - double dMaxLeakDist = ( ptMaxTouch - ptMaxBase) * vtMove ; - // se le due distanze sono uguali e tipo di contatto 1, allora superficie laterale cono tangente a piano - if ( abs( dMaxLeakDist - dMinLeakDist) < EPS_SMALL) { - Point3d ptInt1, ptInt2 ; - int nRes = IntersLineTria( ptMinTouch, ptMaxTouch, trTria, ptInt1, ptInt2) ; - if ( nRes != ILTT_NO) - return max( ( dMaxLeakDist + dMinLeakDist) / 2, 0.) ; + // Movimento nel piano del triangolo: la distanza di allontanamento è determinata dalla frontiera + if ( AreOrthoApprox( vtMove, trTria.GetN())) + return 0. ; + // Movimento ortogolnale al piano + else if ( AreSameOrOppositeVectorApprox( vtMove, trTria.GetN())) { + if ( vtMove * vtTrConeAx > 0) { + Point3d ptTouch ; + double dDist = DiskPlaneLeakDistLongMot( ptMinBase, dMinBaseR, trTria.GetP( 0), trTria.GetN(), vtMove, ptTouch) ; + if ( CoplanarDiscTriangleInterferance( ptTouch, dMinBaseR, trTria)) + return max( dDist, 0.) ; + return 0. ; + } + else { + Point3d ptTouch ; + Point3d ptMaxBase = ptMinBase - dTrConeH * vtTrConeAx ; + double dDist = DiskPlaneLeakDistLongMot( ptMaxBase, dMaxBaseR, trTria.GetP( 0), trTria.GetN(), vtMove, ptTouch) ; + if ( CoplanarDiscTriangleInterferance( ptTouch, dMaxBaseR, trTria)) + return max( dDist, 0.) ; + return 0. ; + } } - // altrimenti sono i dischi a determinare l'allontanamento - double dMove = 0 ; - if ( ( nMinLeakType == 1 && IsPointInsideTriangle( ptMinTouch, trTria)) || - ( nMinLeakType == 4 && CoplanarDiscTriangleInterferance( ptMinTouch, dMinBaseR, trTria))) - dMove = max( dMinLeakDist, 0.) ; - if ( ( nMaxLeakType == 1 && IsPointInsideTriangle( ptMaxTouch, trTria)) || - ( nMaxLeakType == 4 && CoplanarDiscTriangleInterferance( ptMaxTouch, dMaxBaseR, trTria))) - dMove = max( dMove, dMaxLeakDist) ; - return dMove ; + // Movimento generico rispetto al piano + else { + if ( vtMove * vtTrConeAx > 0) { + Point3d ptTouch ; + double dDist = DiskPlaneLeakDistLongMot( ptMinBase, dMinBaseR, trTria.GetP( 0), trTria.GetN(), vtMove, ptTouch) ; + if ( IsPointInsideTriangle( ptTouch, trTria)) + return max( dDist, 0.) ; + return 0. ; + } + else { + Point3d ptTouch ; + Point3d ptMaxBase = ptMinBase - dTrConeH * vtTrConeAx ; + double dDist = DiskPlaneLeakDistLongMot( ptMaxBase, dMaxBaseR, trTria.GetP( 0), trTria.GetN(), vtMove, ptTouch) ; + if ( IsPointInsideTriangle( ptTouch, trTria)) + return max( dDist, 0.) ; + return 0. ; + } + } } //---------------------------------------------------------------------------- @@ -897,22 +939,31 @@ TrConeTriangleInteriorLeakDistOrtMot( const Point3d& ptMinBase, const Vector3d& double dMaxLeakDist = DiskPlaneLeakDistOrtMot( ptMaxBase, vtTrConeAx, dMaxBaseR, trTria.GetP( 0), trTria.GetN(), vtMove, ptMaxTouch) ; - // se le due distanze sono uguali, allora superficie laterale cono tangente a piano - if ( abs( dMaxLeakDist - dMinLeakDist) < EPS_SMALL && - dMinLeakDist > 0. && dMaxLeakDist > 0.) { - Point3d ptInt1, ptInt2 ; - int nRes = IntersLineTria( ptMinTouch, ptMaxTouch, trTria, ptInt1, ptInt2) ; - if ( nRes != ILTT_NO) - return max( ( dMaxLeakDist + dMinLeakDist) / 2, 0.) ; + // Valuto distanza di allontanamento del tronco a partire da quelle dei dischi + bool bMaxInside = IsPointInsideTriangle( ptMaxTouch, trTria) ; + bool bMinInside = IsPointInsideTriangle( ptMinTouch, trTria) ; + double dLeakDist = 0. ; + // Se entrambe interne + if ( bMaxInside && bMinInside) + dLeakDist = max( dMaxLeakDist, dMinLeakDist) ; + // altrimenti se base maggiore interna + else if ( bMaxInside) { + if ( dMaxLeakDist > dMinLeakDist) + dLeakDist = dMaxLeakDist ; } - - // altrimenti sono i dischi a determinare l'allontanamento - double dMove = 0 ; - if ( IsPointInsideTriangle( ptMinTouch, trTria)) - dMove = max( dMinLeakDist, 0.) ; - if ( IsPointInsideTriangle( ptMaxTouch, trTria)) - dMove = max( dMove, dMaxLeakDist) ; - return dMove ; + // altrimenti se base minore interna + else if ( bMinInside) { + if ( dMinLeakDist > dMaxLeakDist) + dLeakDist = dMinLeakDist ; + } + // altrimenti se tocca la superficie laterale + else if ( abs( dMaxLeakDist - dMinLeakDist) < EPS_SMALL) { + Point3d ptInt1, ptInt2 ; + int nRes = IntersLineTria( ptMaxTouch, ptMinTouch, trTria, ptInt1, ptInt2) ; + if ( nRes != ILTT_NO) + dLeakDist = ( dMaxLeakDist + dMinLeakDist) / 2 ; + } + return dLeakDist ; } //---------------------------------------------------------------------------- @@ -925,6 +976,10 @@ CAvTorusTriangle( const Point3d& ptTorusCen, const Vector3d& vtTorusAx, double d { // Allontanamento con direzione coincidente con l'asse del toro if ( AreSameOrOppositeVectorApprox( vtTorusAx, vtMove)) { + // Le corone toriche non possono effettuare un moto in direzione opposta + // al proprio asse di simmetria: vedi documentazione. + if ( vtTorusAx * vtMove < 0.) + return 0. ; // Verifica preliminare che la fetta di spazio delimitata dal piano sotto del cono rispetto alla direzione // di allontanamento non sia già sopra al triangolo (tutti i vertici del triangolo sono sotto). Point3d ptBase = ptTorusCen - dMinRad * vtMove ; @@ -955,8 +1010,27 @@ CAvTorusTriangle( const Point3d& ptTorusCen, const Vector3d& vtTorusAx, double d } return dOutLeakDist ; } + // Allontanamento in direzione ortogonale all'asse del toro else if ( AreOrthoApprox( vtTorusAx, vtMove)) { + double dTopTol = bTop ? EPS_SMALL : - EPS_SMALL ; + double dBotTol = bBot ? - EPS_SMALL : EPS_SMALL ; + double dRadSum = dMaxRad + dMinRad ; + Vector3d vtTrasv = vtTorusAx ^ vtMove ; + Vector3d vtR0 = trTria.GetP( 0) - ptTorusCen ; + Vector3d vtR1 = trTria.GetP( 1) - ptTorusCen ; + Vector3d vtR2 = trTria.GetP( 2) - ptTorusCen ; + if ( ( vtR0 * vtMove < - dRadSum && vtR1 * vtMove < - dRadSum && vtR2 * vtMove < - dRadSum) || + ( vtR0 * vtTrasv < - dRadSum && vtR1 * vtTrasv < - dRadSum && vtR2 * vtTrasv < - dRadSum) || + ( vtR0 * vtTrasv > dRadSum && vtR1 * vtTrasv > dRadSum && vtR2 * vtTrasv > dRadSum) || + ( vtR0 * vtTorusAx > dTopTol && vtR1 * vtTorusAx > dTopTol && vtR2 * vtTorusAx > dTopTol) || + ( vtR0 * vtTorusAx < - dMinRad + dBotTol && vtR1 * vtTorusAx < - dMinRad + dBotTol && + vtR2 * vtTorusAx < - dMinRad + dBotTol)) + return 0. ; + // Distanza di allontanamento dall'interno del triangolo: se positivo abbiamo finito + double dInLeakDist = TorusTriangleInteriorLeakDistOrtMot( ptTorusCen, vtTorusAx, dMaxRad, dMinRad, trTria, vtMove) ; + if ( dInLeakDist > EPS_SMALL) + return dInLeakDist ; // Distanza di allontanamento dai lati double dOutLeakDist = 0. ; for ( int nV = 0 ; nV < 3 ; ++ nV) { @@ -964,12 +1038,12 @@ CAvTorusTriangle( const Point3d& ptTorusCen, const Vector3d& vtTorusAx, double d double dSegLen = vtSeg.Len() ; vtSeg /= dSegLen ; double dCurDist = TorusSegmentLeakDistOrtMot( ptTorusCen, vtTorusAx, dMaxRad, dMinRad, - trTria.GetP( nV), vtSeg, dSegLen, vtMove, bTop, bBot) ; + trTria.GetP( nV), vtSeg, dSegLen, vtMove, bTop, bBot) ; dOutLeakDist = max( dCurDist, dOutLeakDist) ; - } - double dInLeakDist = TorusTriangleInteriorLeakDistOrtMot( ptTorusCen, vtTorusAx, dMaxRad, dMinRad, trTria, vtMove) ; + } return max( dOutLeakDist, dInLeakDist) ; } + // Movimento generico else return -1 ; @@ -983,55 +1057,62 @@ TorusSegmentLeakDistLongMot( const Point3d& ptTorusCen, double dMaxRad, double d // Se segmento dista dall'asse del toro più del raggio esterno, posso uscire subito double dLinSegSqDist = LineSegmentSqDist( ptTorusCen, vtMove, ptSeg, vtSeg, dSegLen) ; if ( dLinSegSqDist > ( dMaxRad + dMinRad) * ( dMaxRad + dMinRad)) - return 0.0 ; + return 0. ; + // Se estremi del segmento più vicini della corona torica, posso uscire subito + double dStartSqDist = GetPointLineSqDist( ptSeg, ptTorusCen, vtMove) ; + double dEndSqDist = GetPointLineSqDist( ptSeg + vtSeg * dSegLen, ptTorusCen, vtMove) ; + if ( dStartSqDist < dMaxRad * dMaxRad && dEndSqDist < dMaxRad * dMaxRad) + return 0. ; - // Dati del segmento - Point3d ptMySeg = ptSeg ; - double dMySegLen = dSegLen ; - // Limito il segmento entro la corona del toro - double dLen1, dLen2 ; - int nInters = IntersLineInfiniteCylinder( ptSeg, vtSeg, ptTorusCen, vtMove, dMaxRad + dMinRad, dLen1, dLen2) ; - if ( nInters == CC_TWO_INT) { - if ( dLen1 > EPS_SMALL) { - ptMySeg += vtSeg * dLen1 ; - dMySegLen -= dLen1 ; - dLen2 -= dLen1 ; - } - if ( dLen2 < dMySegLen) - dMySegLen -= ( dMySegLen - dLen2) ; - } - else if ( nInters == CC_ONE_INT_TAN) { - ptMySeg += vtSeg * dLen1 ; - dMySegLen = 0 ; + // Intervallo del segmento non limitato + Intervals SegLimits ; + SegLimits.Set( 0, dSegLen) ; + // Limito il segmento entro il cilindro esterno della corona del toro + double dOutLen1, dOutLen2 ; + int nOutInters = IntersLineInfiniteCylinder( ptSeg, vtSeg, ptTorusCen, vtMove, dMaxRad + dMinRad, + dOutLen1, dOutLen2) ; + if ( nOutInters == CC_TWO_INT || nOutInters == CC_ONE_INT_TAN) + SegLimits.Intersect( dOutLen1, dOutLen2) ; + if ( SegLimits.IsEmpty()) + return 0. ; + // Tolgo eventuale cilindro interno alla corona del toro + if ( dLinSegSqDist < dMaxRad * dMaxRad) { + double dIntLen1, dIntLen2 ; + int nIntInters = IntersLineInfiniteCylinder( ptSeg, vtSeg, ptTorusCen, vtMove, dMaxRad, + dIntLen1, dIntLen2) ; + if ( nIntInters == CC_TWO_INT) + SegLimits.Subtract( dIntLen1, dIntLen2) ; } - Vector3d vtR0 = ptMySeg - ptTorusCen ; - double dLongR0 = vtR0 * vtMove ; - Vector3d vtOrtR0 = vtR0 - dLongR0 * vtMove ; - Vector3d vtSegOrt = vtSeg - vtSeg * vtMove * vtMove ; - - // Cerco massima distanza di allontanamento lungo il segmento - double dStep = max( 0.1 * dMinRad, EPS_SMALL) ; // !!! USARE ALGORITMO GOLDEN SECTION !!! - int nStepNum = int( dMySegLen / dStep) + 1 ; - dStep = dMySegLen / nStepNum ; - - double dDotSegLine = vtSeg * vtMove ; + // Eseguo controllo sugli intervalli double dSqMinRad = dMinRad * dMinRad ; double dSqMaxRad = dMaxRad * dMaxRad ; - double dSqLenOrt = vtOrtR0 * vtOrtR0 ; - double dSegOrtSqLen = vtSegOrt * vtSegOrt ; - double dSegOrtDotROrt = vtOrtR0 * vtSegOrt ; + double dSqTotRad = ( dMaxRad + dMinRad) * ( dMaxRad + dMinRad) ; double dMaxLeakDist = 0.0 ; - for ( int n = 0 ; n <= nStepNum ; ++ n) { - double dPar = n * dStep ; - double dPointAxSqLen = GetPointLineSqDist( ptMySeg + dPar * vtSeg, ptTorusCen, vtMove) ; - if ( dPointAxSqLen > dSqMaxRad && dPointAxSqLen < ( dMaxRad + dMinRad) * ( dMaxRad + dMinRad)) { - double dPolynomialSqRoot = sqrt( EvalSecondDegreePolynomial( dSqLenOrt, 2 * dSegOrtDotROrt, dSegOrtSqLen, dPar)) ; - double dNonLinearComp = sqrt( dSqMinRad - ( dMaxRad - dPolynomialSqRoot) * ( dMaxRad - dPolynomialSqRoot)) ; - double dLeakDist = dLongR0 + dPar * dDotSegLine + dNonLinearComp ; - if ( dLeakDist > dMaxLeakDist) - dMaxLeakDist = dLeakDist ; + double dLen1, dLen2 ; + bool bFound = SegLimits.GetFirst( dLen1, dLen2) ; + while ( bFound) { + // verifico l'intervallo + Point3d ptStart = ptSeg + vtSeg * dLen1 ; + double dLen = dLen2 - dLen1 ; + double dStep = max( 0.1 * dMinRad, EPS_SMALL) ; // !!! USARE ALGORITMO GOLDEN SECTION !!! + int nStepNum = int( dLen / dStep) + 1 ; + dStep = dLen / nStepNum ; + for ( int n = 0 ; n <= nStepNum ; ++ n) { + double dPar = n * dStep ; + Point3d ptCurPoint = ptStart + dPar * vtSeg ; + double dPointAxSqLen = GetPointLineSqDist( ptCurPoint, ptTorusCen, vtMove) ; + if ( dPointAxSqLen > dSqMaxRad && dPointAxSqLen < dSqTotRad) { + double dTmp = dMaxRad - sqrt( dPointAxSqLen) ; + double dTmp2 = dSqMinRad - dTmp * dTmp ; + double dNonLinearPart = ( dTmp2 > 0. ? sqrt( dTmp2) : 0.) ; + double dLeakDist = ( ptCurPoint - ptTorusCen) * vtMove + dNonLinearPart ; + if ( dLeakDist > dMaxLeakDist) + dMaxLeakDist = dLeakDist ; + } } + // passo al successivo intervallo + bFound = SegLimits.GetNext( dLen1, dLen2) ; } return dMaxLeakDist ; } @@ -1089,45 +1170,85 @@ TorusSegmentLeakDistOrtMot( const Point3d& ptTorusCen, const Vector3d& vtTorusAx 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 ; + double dTopTol = ( bTop ? EPS_SMALL : - EPS_SMALL) ; + double dBotTol = ( bBot ? - EPS_SMALL : EPS_SMALL) ; - Vector3d vtR0 = ptSeg - ptTorusCen ; - - if ( LineSegmentSqDist( ptTorusCen, vtMove, ptSeg, vtSeg, dSegLen) > ( dMaxRad + dMinRad) * ( dMaxRad + dMinRad)) - return 0. ; - if ( vtR0 * vtTorusAx < - dMinRad && ( vtR0 + dSegLen * vtSeg) * vtTorusAx < - dMinRad) - return 0. ; + Vector3d vtTrasv = vtTorusAx ^ vtMove ; + vtTrasv.Normalize() ; + Point3d ptBBInf = ptTorusCen - ( dMaxRad + dMinRad) * ( vtTrasv + vtMove) - ( dMinRad - dBotTol) * vtTorusAx ; + Point3d ptBBSup = ptTorusCen + ( dMaxRad + dMinRad) * ( vtTrasv - vtMove) + dTopTol * vtTorusAx ; + // Clamp piani laterali + Point3d ptMySeg = ptSeg ; + double dMySegLen = dSegLen ; + double dDotSegTrasv = vtSeg * vtTrasv ; + bool bInsideLateral = false ; + if ( abs( dDotSegTrasv) > EPS_ZERO) { + double dMinU = min( ( ( ptBBInf - ptMySeg) * vtTrasv) / dDotSegTrasv, + ( ( ptBBSup - ptMySeg) * vtTrasv) / dDotSegTrasv) ; + double dMaxU = max( ( ( ptBBInf - ptMySeg) * vtTrasv) / dDotSegTrasv, + ( ( ptBBSup - ptMySeg) * vtTrasv) / dDotSegTrasv) ; + if ( dMinU <= dMySegLen && dMaxU >= 0.) { + if ( dMinU > 0.) { + ptMySeg += dMinU * vtSeg ; + dMySegLen -= dMinU ; + dMaxU -= dMinU ; + } + if ( dMaxU < dMySegLen) + dMySegLen -= ( dMySegLen - dMaxU) ; + bInsideLateral = true ; + } + } + else if ( ( ( ptMySeg - ptBBInf) * vtTrasv >= 0. && ( ptMySeg - ptBBSup) * vtTrasv <= 0.) || + ( ( ptMySeg + dMySegLen * vtSeg - ptBBInf) * vtTrasv >= 0. && + ( ptMySeg + dMySegLen * vtSeg - ptBBSup) * vtTrasv <= 0.)) + bInsideLateral = true ; + // Clamp piani orizzontali + double dDotSegAx = vtSeg * vtTorusAx ; + bool bInsideOrizontal = false ; + if ( abs( dDotSegAx) > EPS_ZERO) { + double dMinV = min( ( ( ptBBInf - ptMySeg) * vtTorusAx) / dDotSegAx, + ( ( ptBBSup - ptMySeg) * vtTorusAx) / dDotSegAx) ; + double dMaxV = max( ( ( ptBBInf - ptMySeg) * vtTorusAx) / dDotSegAx, + ( ( ptBBSup - ptMySeg) * vtTorusAx) / dDotSegAx) ; + if ( dMinV <= dMySegLen && dMaxV >= 0.) { + if ( dMinV > 0.) { + ptMySeg += dMinV * vtSeg ; + dMySegLen -= dMinV ; + dMaxV -= dMinV ; + } + if ( dMaxV < dMySegLen) + dMySegLen -= ( dMySegLen - dMaxV) ; + bInsideOrizontal = true ; + } + } + else if ( ( ( ptMySeg - ptBBInf) * vtTorusAx >= 0. && ( ptMySeg - ptBBSup) * vtTorusAx <= 0.) || + ( ( ptMySeg + dMySegLen * vtSeg - ptBBInf) * vtTorusAx >= 0. && + ( ptMySeg + dMySegLen * vtSeg - ptBBSup) * vtTorusAx <= 0.)) + bInsideOrizontal = true ; - double dSqR0 = vtR0 * vtR0 ; - double dH0 = vtR0 * vtTorusAx ; - Vector3d vtR0Ax = vtR0 - dH0 * vtTorusAx ; - double dL0 = vtR0 * vtMove ; - Vector3d vtR0Mot = vtR0 - dL0 * vtMove ; - double dSegDotAx = vtSeg * vtTorusAx ; - double dSegDotMove = vtSeg * vtMove ; - double dSegDotR0 = vtSeg * vtR0 ; - - double dStep = max( 0.1 * dMinRad, EPS_SMALL) ; // !!! USARE ALGORITMO GOLDEN SECTION !!! - int nStepNum = int( dSegLen / dStep) ; - - double dMaxLeakDist = - DBL_MAX ; - for ( int n = 0 ; n <= nStepNum + 1 ; ++ n) { - double dT = ( n <= nStepNum ? n * dStep : dSegLen) ; - double dHt = dH0 + dSegDotAx * dT ; - // Se non vi è interferenza fra punto e toro salto iterazione - if ( dHt > dTopTol || dHt < - dMinRad + dBotTol) - continue ; - double dSqR0LatT = dSqR0 - dH0 * dH0 - dL0 * dL0 + 2 * ( dSegDotR0 - dH0 * dSegDotAx - dL0 * dSegDotMove) * dT + - ( 1 - dSegDotMove * dSegDotMove - dSegDotAx * dSegDotAx) * dT * dT ; - // Raggio della circonferenza di quota Ht - double dHtCircRad = dMaxRad + sqrt( dMinRad * dMinRad - dHt * dHt) ; - // Se non vi è interferenza fra punto e toro salto iterazione - if ( dSqR0LatT > dHtCircRad * dHtCircRad) - continue ; - double dCurDist = dL0 + dSegDotMove * dT + sqrt( dHtCircRad * dHtCircRad - dSqR0LatT) ; - if ( dCurDist > dMaxLeakDist) - dMaxLeakDist = dCurDist ; + // Cerco distanza di massimo allontanamento lungo il segmento ridotto + double dMaxLeakDist = 0. ; + if ( bInsideLateral && bInsideOrizontal) { + double dSqMinRad = dMinRad * dMinRad ; + double dStep = max( 0.1 * dMinRad, EPS_SMALL) ; + int nStepNum = int( dMySegLen / dStep) ; + for ( int n = 0 ; n <= nStepNum ; ++ n) { + Point3d ptCurPoint = ptMySeg + ( n * dStep) * vtSeg ; + Vector3d vtR = ptCurPoint - ptTorusCen ; + double dH = vtR * vtTorusAx ; + Vector3d vtPlaneR = vtR - dH * vtTorusAx ; + double dL = vtPlaneR * vtMove ; + Vector3d vtPlaneOrtR = vtPlaneR - dL * vtMove ; + double dDeltaRad = dSqMinRad - dH * dH > 0. ? sqrt( dSqMinRad - dH * dH) : 0. ; + // Raggio della circonferenza alla quota dH + double dHRad = dMaxRad + dDeltaRad ; + double dSqDeltaL = dHRad * dHRad - vtPlaneOrtR.SqLen() ; + if ( dSqDeltaL > 0.) { + double dCurDist = dL + sqrt( dSqDeltaL) ; + if ( dCurDist > dMaxLeakDist) + dMaxLeakDist = dCurDist ; + } + } } return dMaxLeakDist ; } @@ -1144,7 +1265,7 @@ TorusTriangleInteriorLeakDistOrtMot( const Point3d& ptTorusCen, const Vector3d& 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() ; + double dDotMoveN = vtMove * trTria.GetN() ; if ( abs( dDotMoveN) < EPS_ZERO) return 0. ; // Scarto il primo contatto @@ -1160,6 +1281,297 @@ TorusTriangleInteriorLeakDistOrtMot( const Point3d& ptTorusCen, const Vector3d& return 0. ; } +//---------------------------------------------------------------------------- +double +CAvConcaveTorusTriangle( const Point3d& ptTorusCen, const Vector3d& vtTorusAx, double dMaxRad, double dMinRad, + const Triangle3d& trTria, const Vector3d& vtMove, bool bTop, bool bBot) +{ + // Allontanamento con direzione coincidente con l'asse del toro + if ( AreSameOrOppositeVectorApprox( vtTorusAx, vtMove)) { + // Le corone toriche non possono effettuare un moto in direzione opposta + // al proprio asse di simmetria: vedi documentazione. + if ( vtTorusAx * vtMove < 0.) + return 0. ; + // Distanza di allontanamento dai lati + double dOutLeakDist = 0. ; + for ( int nV = 0 ; nV < 3 ; ++ nV) { + Vector3d vtSeg = trTria.GetP( ( nV + 1) % 3) - trTria.GetP( nV) ; + double dSegLen = vtSeg.Len() ; + vtSeg /= dSegLen ; + double dCurDist = ConcaveTorusSegmentLeakDistLongMot( ptTorusCen, dMaxRad, dMinRad, + trTria.GetP( nV), vtSeg, dSegLen, vtMove) ; + dOutLeakDist = max( dCurDist, dOutLeakDist) ; + // Valuto contatto del disco con i vertici + dCurDist = PointPlaneSignedDist( trTria.GetP( nV), ptTorusCen, vtMove) ; + if ( GetPointLineSqDist( trTria.GetP( nV), ptTorusCen, vtTorusAx) < ( dMaxRad - dMinRad) * ( dMaxRad - dMinRad) && + dCurDist > dOutLeakDist) + dOutLeakDist = max( dOutLeakDist, dCurDist) ; + } + double dInLeakDist = ConcaveTorusTriangleInteriorLeakDistLongMot( ptTorusCen, vtTorusAx, dMaxRad, dMinRad, + trTria, vtMove) ; + return max( dInLeakDist, dOutLeakDist) ; + } + + // Allontanamento con direzione ortogonale a quella dell'asse del toro + else if ( AreOrthoApprox( vtTorusAx, vtMove)) { + double dLeakDist = 0. ; + // Distanza di allontanamento dei segmenti + for ( int nV = 0 ; nV < 3 ; ++ nV) { + Vector3d vtSeg = trTria.GetP( ( nV + 1) % 3) - trTria.GetP( nV) ; + double dSegLen = vtSeg.Len() ; + vtSeg /= dSegLen ; + double dCurDist = ConcaveTorusSegmentLeakDistOrtMot( ptTorusCen, vtTorusAx, dMaxRad, dMinRad, + trTria.GetP( nV), vtSeg, dSegLen, vtMove, bTop, bBot) ; + dLeakDist = max( dLeakDist, dCurDist) ; + } + double dInnLeakDist = ConcaveTorusTriangleInteriorLeakDistOrtMot( ptTorusCen, vtTorusAx, dMaxRad, dMinRad, + trTria, vtMove) ; + dLeakDist = max( dLeakDist, dInnLeakDist) ; + return dLeakDist ; + } + // Casi non gestiti + else + return 0. ; +} + +//---------------------------------------------------------------------------- +double +ConcaveTorusSegmentLeakDistLongMot( const Point3d& ptTorusCen, double dMaxRad, double dMinRad, + const Point3d& ptSeg, const Vector3d& vtSeg, double dSegLen, const Vector3d& vtMove) +{ + // Se segmento dista dall'asse del toro più del raggio massimo, posso uscire subito + double dLinSegSqDist = LineSegmentSqDist( ptTorusCen, vtMove, ptSeg, vtSeg, dSegLen) ; + if ( dLinSegSqDist > dMaxRad * dMaxRad) + return 0.0 ; + + // Individuo le parti del segmento che attraversano il toro + Point3d ptMyFirstSeg = ptSeg ; + Point3d ptMySecondSeg = ptSeg ; + double dMyFirstSegLen = dSegLen ; + double dMySecondSegLen = dSegLen ; + // Limito il segmento entro la corona del toro + double dFirstLen1 = 0 ; + double dFirstLen2 = dMyFirstSegLen ; + double dSecondLen1, dSecondLen2 ; + Intervals SegLimits ; + SegLimits.Set( 0, dMyFirstSegLen) ; + Intervals ChordLimits ; + int nFirstInters = IntersLineInfiniteCylinder( ptSeg, vtSeg, ptTorusCen, vtMove, dMaxRad, + dFirstLen1, dFirstLen2) ; + int nSecondInters = CC_NO_INTERS ; + if ( nFirstInters == CC_TWO_INT) + ChordLimits.Set( dFirstLen1, dFirstLen2) ; + else if ( nFirstInters == CC_ONE_INT_TAN) + ChordLimits.Set( dFirstLen1, dFirstLen1) ; + SegLimits.Intersect( ChordLimits) ; + double dMin, dMax ; + SegLimits.GetMinMax( dMin, dMax) ; + if ( dMax - dMin > EPS_SMALL) { + nSecondInters = IntersLineInfiniteCylinder( ptSeg, vtSeg, ptTorusCen, vtMove, dMaxRad - dMinRad, + dSecondLen1, dSecondLen2) ; + if ( nSecondInters == CC_TWO_INT) + SegLimits.Subtract( dSecondLen1, dSecondLen2) ; + } + + // Cerco massima distanza di allontanamento lungo il segmento + double dFirstStep = max( 0.1 * dMinRad, EPS_SMALL) ; // !!! USARE ALGORITMO GOLDEN SECTION !!! + double dSecondStep = dFirstStep ; + int nFirstStepNum = 0 ; + int nSecondStepNum = 0 ; + // Primo segmento + if ( SegLimits.GetFirst( dFirstLen1, dFirstLen2)) { + ptMyFirstSeg += dFirstLen1 * vtSeg ; + dMyFirstSegLen = dFirstLen2 - dFirstLen1 ; + nFirstStepNum = int( dMyFirstSegLen / dFirstStep) + 1 ; + dFirstStep = dMyFirstSegLen / nFirstStepNum ; + } + // Secondo segmento + if ( SegLimits.GetNext( dSecondLen1, dSecondLen2)) { + ptMySecondSeg += dSecondLen1 * vtSeg ; + dMySecondSegLen = dSecondLen2 - dSecondLen1 ; + nSecondStepNum = int( dMySecondSegLen / dSecondStep) + 1 ; + dSecondStep = dMySecondSegLen / nSecondStepNum ; + } + + double dSqMinRad = dMinRad * dMinRad ; + double dSqMaxRad = dMaxRad * dMaxRad ; + // Cerco massimo allontanamento nel primo segmento + double dMaxLeakDist = 0.0 ; + for ( int n = 0 ; n <= nFirstStepNum ; ++ n) { + double dPar = n * dFirstStep ; + Point3d ptCurPoint = ptMyFirstSeg + dPar * vtSeg ; + double dPointAxSqLen = GetPointLineSqDist( ptCurPoint, ptTorusCen, vtMove) ; + if ( dPointAxSqLen > ( dMaxRad - dMinRad) * ( dMaxRad - dMinRad) && dPointAxSqLen < dSqMaxRad) { + double dNonLinearPart = sqrt( max( dSqMinRad - ( dMaxRad - sqrt( dPointAxSqLen)) * ( dMaxRad - sqrt( dPointAxSqLen)), 0.)) ; + double dLeakDist = ( ptCurPoint - ptTorusCen) * vtMove - dNonLinearPart ; + if ( dLeakDist > dMaxLeakDist) + dMaxLeakDist = dLeakDist ; + } + } + // Cerco nel secondo segmento un allontanamento ancor maggiore + if ( nSecondStepNum > 0) { + for ( int n = 0 ; n <= nSecondStepNum ; ++ n) { + double dPar = n * dSecondStep ; + Point3d ptCurPoint = ptMySecondSeg + dPar * vtSeg ; + double dPointAxSqLen = GetPointLineSqDist( ptCurPoint, ptTorusCen, vtMove) ; + if ( dPointAxSqLen > ( dMaxRad - dMinRad) * ( dMaxRad - dMinRad) && dPointAxSqLen < dSqMaxRad) { + double dNonLinearPart = sqrt( max( dSqMinRad - ( dMaxRad - sqrt( dPointAxSqLen)) * ( dMaxRad - sqrt( dPointAxSqLen)), 0.)) ; + double dLeakDist = ( ptCurPoint - ptTorusCen) * vtMove - dNonLinearPart ; + if ( dLeakDist > dMaxLeakDist) + dMaxLeakDist = dLeakDist ; + } + } + } + + return dMaxLeakDist ; +} + +//---------------------------------------------------------------------------- +double +ConcaveTorusTriangleInteriorLeakDistLongMot( const Point3d& ptTorusCen, const Vector3d& vtTorusAx, + double dMaxRad, double dMinRad, + const Triangle3d& trTria, const Vector3d& vtMove) +{ + // Se piano del triangolo e asse del toro perpendicolari + if ( AreSameOrOppositeVectorApprox( trTria.GetN(), vtMove)) { + // Se tutti i punti del triangolo distano meno del raggio dMaxRad non c'è interferenza col toro + if ( GetPointLineSqDist( trTria.GetP( 0), ptTorusCen, vtMove) < dMinRad * dMinRad && + GetPointLineSqDist( trTria.GetP( 1), ptTorusCen, vtMove) < dMinRad * dMinRad && + GetPointLineSqDist( trTria.GetP( 2), ptTorusCen, vtMove) < dMinRad * dMinRad) + return 0. ; + // Calcolo distanza di allontanamento e verifico se positiva + double dLeakDist = max( ( ( trTria.GetP( 0) - ptTorusCen) * trTria.GetN()) / ( vtMove * trTria.GetN()), 0.) ; + if ( dLeakDist > 0) { + // Se triangolo interferisce con anello esterno del toro (bordo interno) + Point3d ptNewCen = ptTorusCen + ( dLeakDist /*- dMinRad*/) * vtMove ; + if ( CoplanarDiscTriangleInterferance( ptNewCen, dMinRad/*dMaxRad*/, trTria)) + return dLeakDist ; + } + // Nessuna interferenza + return 0. ; + } + // Altrimenti valuto i dischi + double dLeakDist = 0. ; + dLeakDist = max( DiskTriaInteriorLeakDistLongMot( ptTorusCen, dMinRad, trTria, vtMove), 0.) ; + dLeakDist = max( DiskTriaInteriorLeakDistLongMot( ptTorusCen + dMinRad * vtTorusAx, dMaxRad, trTria, vtMove), dLeakDist) ; + return dLeakDist ; +} + +//---------------------------------------------------------------------------- +double +ConcaveTorusSegmentLeakDistOrtMot( const Point3d& ptTorusCen, const Vector3d& vtTorusAx, double dMaxRad, double dMinRad, + 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 ; + + Vector3d vtTrasv = vtTorusAx ^ vtMove ; + vtTrasv.Normalize() ; + Point3d ptBBInf = ptTorusCen - dMaxRad * ( vtTrasv + vtMove) + dBotTol * vtTorusAx ; + Point3d ptBBSup = ptTorusCen + dMaxRad * ( vtTrasv - vtMove) + ( dMinRad + dTopTol) * vtTorusAx ; + // Clamp piani laterali + Point3d ptMySeg = ptSeg ; + double dMySegLen = dSegLen ; + double dDotSegTrasv = vtSeg * vtTrasv ; + bool bInsideLateral = false ; + if ( abs( dDotSegTrasv) > EPS_ZERO) { + double dMinU = min( ( ( ptBBInf - ptMySeg) * vtTrasv) / dDotSegTrasv, + ( ( ptBBSup - ptMySeg) * vtTrasv) / dDotSegTrasv) ; + double dMaxU = max( ( ( ptBBInf - ptMySeg) * vtTrasv) / dDotSegTrasv, + ( ( ptBBSup - ptMySeg) * vtTrasv) / dDotSegTrasv) ; + if ( dMinU <= dMySegLen && dMaxU >= 0.) { + if ( dMinU > 0.) { + ptMySeg += dMinU * vtSeg ; + dMySegLen -= dMinU ; + dMaxU -= dMinU ; + } + if ( dMaxU < dMySegLen) + dMySegLen -= ( dMySegLen - dMaxU) ; + bInsideLateral = true ; + } + } + else if ( ( ( ptMySeg - ptBBInf) * vtTrasv >= 0. && ( ptMySeg - ptBBSup) * vtTrasv <= 0.) || + ( ( ptMySeg + dMySegLen * vtSeg - ptBBInf) * vtTrasv >= 0. && + ( ptMySeg + dMySegLen * vtSeg - ptBBSup) * vtTrasv <= 0.)) + bInsideLateral = true ; + // Clamp piani orizzontali + double dDotSegAx = vtSeg * vtTorusAx ; + bool bInsideOrizontal = false ; + if ( abs( dDotSegAx) > EPS_ZERO) { + double dMinV = min( ( ( ptBBInf - ptMySeg) * vtTorusAx) / dDotSegAx, + ( ( ptBBSup - ptMySeg) * vtTorusAx) / dDotSegAx) ; + double dMaxV = max( ( ( ptBBInf - ptMySeg) * vtTorusAx) / dDotSegAx, + ( ( ptBBSup - ptMySeg) * vtTorusAx) / dDotSegAx) ; + if ( dMinV <= dMySegLen && dMaxV >= 0.) { + if ( dMinV > 0.) { + ptMySeg += dMinV * vtSeg ; + dMySegLen -= dMinV ; + dMaxV -= dMinV ; + } + if ( dMaxV < dMySegLen) + dMySegLen -= ( dMySegLen - dMaxV) ; + bInsideOrizontal = true ; + } + } + else if ( ( ( ptMySeg - ptBBInf) * vtTorusAx >= 0. && ( ptMySeg - ptBBSup) * vtTorusAx <= 0.) || + ( ( ptMySeg + dMySegLen * vtSeg - ptBBInf) * vtTorusAx >= 0. && + ( ptMySeg + dMySegLen * vtSeg - ptBBSup) * vtTorusAx <= 0.)) + bInsideOrizontal = true ; + + + double dMaxLeakDist = 0. ; + if ( bInsideLateral && bInsideOrizontal) { + double dSqMinRad = dMinRad * dMinRad ; + double dStep = max( 0.1 * dMinRad, EPS_SMALL) ; + int nStepNum = int( dMySegLen / dStep) ; + for ( int n = 0 ; n <= nStepNum ; ++ n) { + Point3d ptCurPoint = ptMySeg + ( n * dStep) * vtSeg ; + Vector3d vtR = ptCurPoint - ptTorusCen ; + double dH = vtR * vtTorusAx ; + Vector3d vtPlaneR = vtR - dH * vtTorusAx ; + double dL = vtPlaneR * vtMove ; + Vector3d vtPlaneOrtR = vtPlaneR - dL * vtMove ; + double dDeltaRad = dSqMinRad - dH * dH > 0. ? sqrt( dSqMinRad - dH * dH) : 0. ; + // Raggio della circonferenza alla quota dH + double dHRad = dMaxRad - dDeltaRad ; + double dSqDeltaL = dHRad * dHRad - vtPlaneOrtR.SqLen() ; + if ( dSqDeltaL > 0.) { + double dCurDist = dL + sqrt( dSqDeltaL) ; + if ( dCurDist > dMaxLeakDist) + dMaxLeakDist = dCurDist ; + } + } + } + return dMaxLeakDist ; +} + +//---------------------------------------------------------------------------- +double +ConcaveTorusTriangleInteriorLeakDistOrtMot( const Point3d& ptTorusCen, const Vector3d& vtTorusAx, double dMaxRad, double dMinRad, + const Triangle3d& trTria, const Vector3d& vtMove) +{ + double dLeakDist = 0. ; + // Caso movimento nel piano: la distanza di allontanamento è determinata dalla frontiera + if ( AreSameOrOppositeVectorApprox( trTria.GetN(), vtMove)) + return dLeakDist ; + // Base minore + Point3d ptContact ; + Point3d ptDiskCen = ptTorusCen ; + double dCurDist = DiskPlaneLeakDistOrtMot( ptDiskCen, vtTorusAx, dMaxRad - dMinRad, trTria.GetP( 0), trTria.GetN(), + vtMove, ptContact) ; + if ( IsPointInsideOpenTriangle( ptContact, trTria)) + dLeakDist = max( dLeakDist, dCurDist) ; + // Base maggiore + ptDiskCen += dMinRad * vtTorusAx ; + dCurDist = DiskPlaneLeakDistOrtMot( ptDiskCen, vtTorusAx, dMaxRad, trTria.GetP( 0), trTria.GetN(), + vtMove, ptContact) ; + if ( IsPointInsideOpenTriangle( ptContact, trTria)) + dLeakDist = max( dLeakDist, dCurDist) ; + return dLeakDist ; +} + + // DISTANZA DI ALLONTANAMENTO PER DISCHI //---------------------------------------------------------------------------- @@ -1260,7 +1672,7 @@ DiskTriaInteriorLeakDistLongMot( const Point3d& ptDiskCen, double dDiskRad, // Altrimenti ha senso solo dDist1 else dDistPlus = dDist1 ; - } + } // Intersezioni con la seconda retta double dDistMinus = 0. ; Point3d ptIntMinus1, ptIntMinus2 ; @@ -1280,6 +1692,38 @@ DiskTriaInteriorLeakDistLongMot( const Point3d& ptDiskCen, double dDiskRad, return max( dDistPlus, dDistMinus) ; } +//---------------------------------------------------------------------------- +double +DiskPlaneLeakDistLongMot( const Point3d& ptDiskCen, double dDiskRad, + const Point3d& ptPlane, const Vector3d& vtPlane, + const Vector3d& vtMove, Point3d& ptTouch) +{ + // Disco ortogonale al piano: competenza della frontiera + if ( AreOrthoApprox( vtPlane, vtMove)) + return -1. ; + // Disco e piano complanari + if ( AreSameOrOppositeVectorApprox( vtPlane, vtMove)) { + double dLeakDist = ( ptPlane - ptDiskCen) * vtMove ; + ptTouch = ptDiskCen + dLeakDist * vtMove ; + return max( 0., dLeakDist) ; + } + // Vettore radiale + Vector3d vtRadLine = vtPlane - ( vtPlane * vtMove) * vtMove ; + vtRadLine.Normalize() ; + Point3d ptStPlus = ptDiskCen + dDiskRad * vtRadLine ; + Point3d ptStMinus = ptDiskCen - dDiskRad * vtRadLine ; + double dLeakPlus = ( ( ptPlane - ptStPlus) * vtPlane) / ( vtMove * vtPlane) ; + double dLeakMinus = ( ( ptPlane - ptStMinus) * vtPlane) / ( vtMove * vtPlane) ; + if ( dLeakPlus > dLeakMinus) { + ptTouch = ptStPlus + dLeakPlus * vtMove ; + return dLeakPlus ; + } + else { + ptTouch = ptStMinus + dLeakMinus * vtMove ; + return dLeakMinus ; + } +} + //---------------------------------------------------------------------------- double DiskPointLeakDistOrtMot( const Point3d& ptDisc, const Vector3d& vtDiskAx, double dDiskRad, @@ -1349,7 +1793,7 @@ DiskPlaneLeakDistOrtMot( const Point3d& ptDiscCen, const Vector3d& vtDiskAx, dou const Point3d& ptPlane, const Vector3d& vtPlane, const Vector3d& vtMove, Point3d& ptContact) { - Vector3d vtLine = vtPlane ^ vtDiskAx ; + Vector3d vtLine = vtPlane ^ vtDiskAx ; if ( vtLine.Normalize()) { Vector3d vtRad = dDiskRad * vtLine ^ vtDiskAx ; if ( vtRad * vtMove > 0) @@ -1442,11 +1886,12 @@ LinePlaneDDistPar( const Point3d& ptPlane, const Vector3d& vtPlane, const Point3 //---------------------------------------------------------------------------- // Date due rette nello spazio restituisce il quadrato della loro distanza. -// Le rette vengono descritte da punto di passaggio e versore direzione. +// Le rette sono definite da un punto e dal versore direzione. double -LineLineSqDist( const Point3d& ptP1, const Vector3d& vtD1, const Point3d& ptP2, const Vector3d& vtD2) +LineLineSqDist( const Point3d& ptP1, const Vector3d& vtD1, + const Point3d& ptP2, const Vector3d& vtD2) { - // Caso di rette parallele + // Se parallele if ( abs( 1. - abs( vtD1 * vtD2)) < EPS_SMALL) return ( ( ptP2 - ptP1) - ( ptP2 - ptP1) * vtD1 * vtD1).SqLen() ; // Caso generale @@ -1454,22 +1899,22 @@ LineLineSqDist( const Point3d& ptP1, const Vector3d& vtD1, const Point3d& ptP2, Vector3d vtOrtD2 = vtD2 - vtD2 * vtD1 * vtD1 ; Vector3d vtOrtP1P2 = ( ptP2 - ptP1) - ( ptP2 - ptP1) * vtD1 * vtD1 ; double dD = ( vtOrtD2 * vtOrtP1P2) / vtOrtP1P2.SqLen() ; - return vtOrtP1P2.SqLen() + dD * dD * vtOrtD2.SqLen() + 2 * dD * vtOrtD2 * vtOrtP1P2 ; + return ( vtOrtP1P2.SqLen() + dD * dD * vtOrtD2.SqLen() + 2 * dD * vtOrtD2 * vtOrtP1P2) ; } } //---------------------------------------------------------------------------- // Data una retta e un segmento, ne restituisce il quadrato della distanza. -// La retta è descritta da un qualsiasi punto ad essa appartenente e un versore -// che ne identifica la direzione. Il segmento è descritto da un suo estremo, -// dal versore direzione diretto verso l'altro estremo e dalla sua lunghezza. +// La retta è definita da un punto e dal versore direzione. +// Il segmento è definito da un estremo, dal versore direzione verso l'altro estremo e dalla lunghezza. double LineSegmentSqDist( const Point3d& ptPLn, const Vector3d& vtDLn, const Point3d& ptPSg, const Vector3d& vtDSg, double dSgLen) { - // Caso di parallelismo + // Se paralleli if ( AreSameOrOppositeVectorApprox( vtDLn, vtDSg)) return ( ( ptPSg - ptPLn) - ( ptPSg - ptPLn) * vtDLn * vtDLn).SqLen() ; + // Caso generale else { double dDLn = ( ptPSg - ptPLn) * vtDLn ; @@ -1531,6 +1976,44 @@ IsPointInsideTriangle( const Point3d& ptP, const Triangle3d& trTria) return true ; } +//---------------------------------------------------------------------------- +// Stabilisce se un punto appartiene all'interno di un triangolo +bool +IsPointInsideOpenTriangle( const Point3d& ptP, const Triangle3d& trTria) +{ + // Se il punto non è nel box del triangolo, è sicuramente esterno + BBox3d b3Tria( trTria.GetP( 0)) ; + b3Tria.Add( trTria.GetP( 1)) ; + b3Tria.Add( trTria.GetP( 2)) ; + if ( ! b3Tria.Encloses( ptP)) + return false ; + + // Se il punto non sta sul piano del triangolo, è sicuramente esterno + if ( abs( ( ptP - trTria.GetP( 0)) * trTria.GetN()) > EPS_SMALL) + return false ; + + // Vettori dei lati normalizzati + Vector3d vtV0 = trTria.GetP( 1) - trTria.GetP( 0) ; + vtV0.Normalize() ; + Vector3d vtV1 = trTria.GetP( 2) - trTria.GetP( 1) ; + vtV1.Normalize() ; + Vector3d vtV2 = trTria.GetP( 0) - trTria.GetP( 2) ; + vtV2.Normalize() ; + + // E' sufficiente che il segno di un prodotto misto sia negativo per essere fuori + double dProd0 = ( vtV0 ^ ( ptP - trTria.GetP( 0))) * trTria.GetN() ; + if ( dProd0 < EPS_SMALL) + return false ; + double dProd1 = ( vtV1 ^ ( ptP - trTria.GetP( 1))) * trTria.GetN() ; + if ( dProd1 < EPS_SMALL) + return false ; + double dProd2 = ( vtV2 ^ ( ptP - trTria.GetP( 2))) * trTria.GetN() ; + if ( dProd2 < EPS_SMALL) + return false ; + + return true ; +} + //---------------------------------------------------------------------------- // Valuta l'interferenza di un disco e un triangolo complanari. bool @@ -1701,4 +2184,3 @@ DiskPlaneLastContactLongMot( const Point3d& ptDiskCen, double dDiskRad, return 1 ; return 0 ; } - diff --git a/CAvToolTriangle.h b/CAvToolTriangle.h index b3e716d..62e3f03 100644 --- a/CAvToolTriangle.h +++ b/CAvToolTriangle.h @@ -16,6 +16,7 @@ #include "Tool.h" #include "/EgtDev/Include/EGkTriangle3d.h" +//----------------------------------------------------------------------------- double CAvToolTriangle( const Tool& tlTool, const Point3d& ptToolOrig, const Vector3d& vtToolAx, const Triangle3d& trTria, const Vector3d& vtMove) ; @@ -23,7 +24,7 @@ double CAvToolTriangle( const Tool& tlTool, const Point3d& ptToolOrig, const Vec // Sfera double CAvSphereTriangle( const Point3d& ptSpheCen, double dSpheRad, const Triangle3d& trTria, const Vector3d& vtMove) ; -double SpherePlaneLeakDist( const Point3d& ptSpheCen, double dSpheRad, +double SpherePlaneLeakDist( const Point3d& ptSpheCen, double dSpheRad, const Point3d& ptPlane, const Vector3d& vtPlaneN, const Vector3d& vtMove) ; double SphereSegmentLeakDist( const Point3d& ptSpheCen, double dSpheRad, const Point3d& ptSeg, const Vector3d& vtSegDir, double dSegLen, @@ -58,17 +59,29 @@ double TrConeTriangleInteriorLeakDistOrtMot( const Point3d& ptMinBase, const Vec double dTrConeH, const Triangle3d& trTria, const Vector3d& vtMove) ; // Toro -double CAvTorusTriangle( const Point3d& ptTorusCen, const Vector3d& vtTorusAx, double dMaxRad, double dMinRad, +double CAvTorusTriangle( const Point3d& ptTorusCen, const Vector3d& vtTorusAx, double dMaxRad, double dMinRad, const Triangle3d& trTria, const Vector3d& vtMove, bool bTop, bool bBot) ; double TorusSegmentLeakDistLongMot( const Point3d& ptTorusCen, double dMaxRad, double dMinRad, const Point3d& ptSeg, const Vector3d& vtSeg, double dSegLen, const Vector3d& vtMove) ; double TorusTriangleInteriorLeakDistLongMot( const Point3d& ptTorusCen, double dMaxRad, double dMinRad, const Triangle3d& trTria, const Vector3d& vtMove) ; -double TorusSegmentLeakDistOrtMot( const Point3d& ptTorusCen, const Vector3d& vtTorusAx, double dMaxRad, double dMinRad, - const Point3d& ptSeg, const Vector3d& vtSeg, double dSegLen, const Vector3d& vtMove, +double TorusSegmentLeakDistOrtMot( const Point3d& ptTorusCen, const Vector3d& vtTorusAx, double dMaxRad, double dMinRad, + const Point3d& ptSeg, const Vector3d& vtSeg, double dSegLen, const Vector3d& vtMove, bool bTop, bool bBot) ; double TorusTriangleInteriorLeakDistOrtMot( const Point3d& ptTorusCen, const Vector3d& vtTorusAx, double dMaxRad, double dMinRad, - const Triangle3d& trTria, const Vector3d& vtMove) ; + const Triangle3d& trTria, const Vector3d& vtMove) ; + +double CAvConcaveTorusTriangle( const Point3d& ptTorusCen, const Vector3d& vtTorusAx, double dMaxRad, double dMinRad, + const Triangle3d& trTria, const Vector3d& vtMove, bool bTop, bool bBot) ; +double ConcaveTorusSegmentLeakDistLongMot( const Point3d& ptTorusCen, double dMaxRad, double dMinRad, + const Point3d& ptSeg, const Vector3d& vtSeg, double dSegLen, const Vector3d& vtMove) ; +double ConcaveTorusTriangleInteriorLeakDistLongMot( const Point3d& ptTorusCen, const Vector3d& vtTorusAx, double dMaxRad, double dMinRad, + const Triangle3d& trTria, const Vector3d& vtMove) ; +double ConcaveTorusSegmentLeakDistOrtMot( const Point3d& ptTorusCen, const Vector3d& vtTorusAx, double dMaxRad, double dMinRad, + const Point3d& ptSeg, const Vector3d& vtSeg, double dSegLen, const Vector3d& vtMove, + bool bTop, bool bBot) ; +double ConcaveTorusTriangleInteriorLeakDistOrtMot( const Point3d& ptTorusCen, const Vector3d& vtTorusAx, double dMaxRad, double dMinRad, + const Triangle3d& trTria, const Vector3d& vtMove) ; // Dischi double DiskPointLeakDistLongMot( const Point3d& ptDiskCen, double dDiskRad, @@ -77,6 +90,9 @@ double DiskSegmentLeakDistLongMot( const Point3d& ptDiskCen, double dDiskRad, const Point3d& ptSeg, const Vector3d& vtSeg, double dSegLen, const Vector3d& vtMove) ; double DiskTriaInteriorLeakDistLongMot( const Point3d& ptDiskCen, double dDiskRad, const Triangle3d& trTria, const Vector3d& vtMove) ; +double DiskPlaneLeakDistLongMot( const Point3d& ptDiskCen, double dDiskRad, + const Point3d& ptPlane, const Vector3d& vtPlane, + const Vector3d& vtMove, Point3d& ptTouch) ; double DiskPointLeakDistOrtMot( const Point3d& ptDisc, const Vector3d& vtDiskAx, double dDiscRad, const Point3d& ptP, const Vector3d& vtMove) ; double DiskSegmentLeakDistOrtMot( const Point3d& ptDiskCen, const Vector3d& vtDiskAx, double dDiskRad, @@ -95,6 +111,7 @@ double LineLineSqDist( const Point3d& ptP1, const Vector3d& vtD1, const Point3d& double LineSegmentSqDist( const Point3d& ptPLn, const Vector3d& vtDLn, const Point3d& ptPSg, const Vector3d& vtDSg, double dSgLen) ; bool IsPointInsideTriangle( const Point3d& ptP, const Triangle3d& trTria) ; +bool IsPointInsideOpenTriangle( const Point3d& ptP, const Triangle3d& trTria) ; bool CoplanarDiscTriangleInterferance( const Point3d& ptCen, double dRad, const Triangle3d& trTria) ; bool FindLineLineMinDistPar( const Point3d& ptL1, const Vector3d& vtV1, const Point3d& ptL2, const Vector3d& vtV2, diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 346f4ff..80fd6ea 100644 Binary files a/EgtGeomKernel.rc and b/EgtGeomKernel.rc differ diff --git a/IntersLineSurfStd.cpp b/IntersLineSurfStd.cpp index 256f650..122d09d 100644 --- a/IntersLineSurfStd.cpp +++ b/IntersLineSurfStd.cpp @@ -546,7 +546,7 @@ IntersLineInfiniteCylinder( const Point3d& ptPLine, const Vector3d& vtVLine, dU1 = vdRoots[0] ; nIntType = CC_ONE_INT_TAN ; } - // L'equazione ha due soluzioni, bisogna valutare se sono den distinte. + // L'equazione ha due soluzioni, bisogna valutare se sono ben distinte. else if ( nRoot == 2) { dU1 = vdRoots[0] ; dU2 = vdRoots[1] ; diff --git a/Intervals.cpp b/Intervals.cpp index 167ae72..b77574d 100644 --- a/Intervals.cpp +++ b/Intervals.cpp @@ -140,6 +140,37 @@ Intervals::Subtract( double dMin, double dMax) } } +//---------------------------------------------------------------------------- +void +Intervals::Intersect( double dMin, double dMax) +{ + // se l'insieme è vuoto non devo fare alcunché + if ( m_vInts.empty()) + return ; + // se l'insieme contiene un solo intervallo + if ( m_vInts.size() == 1) { + // verifico ordine + if ( dMin > dMax) + swap( dMin, dMax) ; + // se non si sovrappongono, il risultato è vuoto + if ( dMax < m_vInts.front().first - m_dToler || dMin > m_vInts.front().second + m_dToler) { + m_vInts.clear() ; + return ; + } + // calcolo l'intersezione + m_vInts.front().first = max( m_vInts.front().first, dMin) ; + m_vInts.front().second = min( m_vInts.front().second, dMax) ; + return ; + } + // Insieme di intervalli ausiliario ampio come il corrente + Intervals Aux ; + Aux.Set( m_vInts.front().first, m_vInts.back().second) ; + // Sottraggo Other da Aux + Aux.Subtract( dMin, dMax) ; + // Sottraggo Aux dal corrente + Subtract( Aux) ; +} + //---------------------------------------------------------------------------- void Intervals::Add( const Intervals& Other)