EgtGeomKernel 2.4h2 :

- in CurveArc migliorato controllo valore parametro in ChangeRadius e ChangeAngCenter
- migliorato calcolo fillet con possibilità di arrivare a 180 deg
- aggiunta GetCircle2P per creazione circonferenza da due punti su estremi di un diametro.
This commit is contained in:
DarioS
2022-08-21 16:16:02 +02:00
parent 6238ea1095
commit 78b9234865
7 changed files with 165 additions and 77 deletions
+104 -68
View File
@@ -22,6 +22,83 @@
using namespace std ;
//----------------------------------------------------------------------------
static bool
CalcForFillet( const ICurve& cCrv1, const Point3d& ptNear1,
const ICurve& cCrv2, const Point3d& ptNear2,
const Vector3d& vtNorm, double dRadius,
Point3d& ptCen, Point3d& ptTg1, Point3d& ptTg2,
int& nSide1, int& nSide2, double& dSinA, double& dTgPar1, double& dTgPar2)
{
// calcolo un riferimento sul piano perpendicolare alla normale
Frame3d frIntr ;
if ( ! frIntr.Set( ORIG, vtNorm))
return false ;
// determino il lato di offset della curva 1
DistPointCurve dPC1( ptNear2, cCrv1) ;
if ( ! dPC1.GetSideAtMinDistPoint( 0, vtNorm, nSide1))
return false ;
double dOffs1 = ( nSide1 == MDS_RIGHT ? dRadius : - dRadius) ;
// calcolo l'offset nel piano locale e dal lato opportuno di una copia della curva 1
PtrOwner<ICurve> pCopy1( cCrv1.Clone()) ;
if ( IsNull( pCopy1))
return false ;
pCopy1->ToLoc( frIntr) ;
pCopy1->SetExtrusion( Z_AX) ;
if ( ! pCopy1->SimpleOffset( dOffs1, ICurve::OFF_FILLET))
return false ;
// determino il lato di offset della curva 2
DistPointCurve dPC2( ptNear1, cCrv2) ;
if ( ! dPC2.GetSideAtMinDistPoint( 0, vtNorm, nSide2))
return false ;
double dOffs2 = ( nSide2 == MDS_RIGHT ? dRadius : - dRadius) ;
// calcolo l'offset nel piano locale e dal lato opportuno di una copia della curva 2
PtrOwner<ICurve> pCopy2( cCrv2.Clone()) ;
if ( IsNull( pCopy2))
return false ;
pCopy2->ToLoc( frIntr) ;
pCopy2->SetExtrusion( Z_AX) ;
if ( ! pCopy2->SimpleOffset( dOffs2, ICurve::OFF_FILLET))
return false ;
// calcolo l'intersezione tra le due curve
Point3d ptInt1, ptInt2 ;
Point3d ptNearI = Media( ptNear1, ptNear2) ;
ptNearI.ToLoc( frIntr) ;
IntersCurveCurve intCC( *pCopy1, *pCopy2) ;
if ( ! intCC.GetIntersPointNearTo( 0, ptNearI, ptInt1) ||
! intCC.GetIntersPointNearTo( 1, ptNearI, ptInt2))
return false ;
ptInt1.ToGlob( frIntr) ;
ptInt2.ToGlob( frIntr) ;
ptCen = Media( ptInt1, ptInt2) ;
// proiezione del punto di intersezione sulla prima curva
DistPointCurve dPCI1( ptInt1, cCrv1) ;
int nFlag1 ;
if ( ! dPCI1.GetParamAtMinDistPoint( 0, dTgPar1, nFlag1) || nFlag1 != MDPCI_NORMAL)
return false ;
Vector3d vtTg1 ;
if ( ! cCrv1.GetPointTang( dTgPar1, ICurve::FROM_MINUS, ptTg1, vtTg1))
return false ;
// proiezione del punto di intersezione sulla seconda curva
DistPointCurve dPCI2( ptInt2, cCrv2) ;
int nFlag2 ;
if ( ! dPCI2.GetParamAtMinDistPoint( 0, dTgPar2, nFlag2) || nFlag2 != MDPCI_NORMAL)
return false ;
Vector3d vtTg2 ;
if ( ! cCrv2.GetPointTang( dTgPar2, ICurve::FROM_MINUS, ptTg2, vtTg2))
return false ;
// determino rotazione tra le curve
dSinA = ( vtTg1 ^ vtTg2) * vtNorm ;
return true ;
}
//----------------------------------------------------------------------------
ICurveArc*
CreateFillet( const ICurve& cCrv1, const Point3d& ptNear1,
@@ -34,76 +111,26 @@ CreateFillet( const ICurve& cCrv1, const Point3d& ptNear1,
&vtNorm == nullptr || &dPar1 == nullptr || &dPar2 == nullptr)
return nullptr ;
// calcolo un riferimento sul piano perpendicolare alla normale
Frame3d frIntr ;
if ( ! frIntr.Set( ORIG, vtNorm))
// eseguo calcoli
Point3d ptCen, ptTg1, ptTg2 ;
int nSide1, nSide2 ;
double dSinA, dTgPar1, dTgPar2 ;
if ( ! CalcForFillet( cCrv1, ptNear1, cCrv2, ptNear2, vtNorm, dRadius,
ptCen, ptTg1, ptTg2, nSide1, nSide2, dSinA, dTgPar1, dTgPar2))
return nullptr ;
// determino il lato di offset della curva 1
DistPointCurve dPC1( ptNear2, cCrv1) ;
int nSide1 ;
if ( ! dPC1.GetSideAtMinDistPoint( 0, vtNorm, nSide1))
return nullptr ;
double dOffs1 = ( nSide1 == MDS_RIGHT ? dRadius : - dRadius) ;
// calcolo l'offset nel piano locale e dal lato opportuno di una copia della curva 1
PtrOwner<ICurve> pCopy1( cCrv1.Clone()) ;
if ( IsNull( pCopy1))
return nullptr ;
pCopy1->ToLoc( frIntr) ;
pCopy1->SetExtrusion( Z_AX) ;
if ( ! pCopy1->SimpleOffset( dOffs1, ICurve::OFF_FILLET))
return nullptr ;
// se tangenti parallele al contatto con fillet, ricalcolo con raggio più piccolo
bool bParallel = ( abs( dSinA) < EPS_SMALL) ;
if ( bParallel) {
Point3d ptQQQ, ptQQ1, ptQQ2 ;
double dQQQ1, dQQQ2 ;
if ( ! CalcForFillet( cCrv1, ptNear1, cCrv2, ptNear2, vtNorm, dRadius - 10 * EPS_SMALL,
ptQQQ, ptQQ1, ptQQ2, nSide1, nSide2, dSinA, dQQQ1, dQQQ2) || abs( dSinA) < EPS_SMALL)
return nullptr ;
}
// determino il lato di offset della curva 2
DistPointCurve dPC2( ptNear1, cCrv2) ;
int nSide2 ;
if ( ! dPC2.GetSideAtMinDistPoint( 0, vtNorm, nSide2))
return nullptr ;
double dOffs2 = ( nSide2 == MDS_RIGHT ? dRadius : - dRadius) ;
// calcolo l'offset nel piano locale e dal lato opportuno di una copia della curva 2
PtrOwner<ICurve> pCopy2( cCrv2.Clone()) ;
if ( IsNull( pCopy2))
return nullptr ;
pCopy2->ToLoc( frIntr) ;
pCopy2->SetExtrusion( Z_AX) ;
if ( ! pCopy2->SimpleOffset( dOffs2, ICurve::OFF_FILLET))
return nullptr ;
// calcolo l'intersezione tra le due curve
Point3d ptInt1, ptInt2 ;
Point3d ptNear1I = ptNear1 ;
ptNear1I.ToLoc( frIntr) ;
IntersCurveCurve intCC( *pCopy1, *pCopy2) ;
if ( ! intCC.GetIntersPointNearTo( 0, ptNear1I, ptInt1) ||
! intCC.GetIntersPointNearTo( 1, ptNear1I, ptInt2))
return nullptr ;
ptInt1.ToGlob( frIntr) ;
ptInt2.ToGlob( frIntr) ;
// proiezione del punto di intersezione sulla prima curva
DistPointCurve dPCI1( ptInt1, cCrv1) ;
double dTgPar1 ;
int nFlag1 ;
if ( ! dPCI1.GetParamAtMinDistPoint( 0, dTgPar1, nFlag1) || nFlag1 != MDPCI_NORMAL)
return nullptr ;
Point3d ptTg1 ;
Vector3d vtTg1 ;
if ( ! cCrv1.GetPointTang( dTgPar1, ICurve::FROM_MINUS, ptTg1, vtTg1))
return nullptr ;
// proiezione del punto di intersezione sulla seconda curva
DistPointCurve dPCI2( ptInt2, cCrv2) ;
double dTgPar2 ;
int nFlag2 ;
if ( ! dPCI2.GetParamAtMinDistPoint( 0, dTgPar2, nFlag2) || nFlag2 != MDPCI_NORMAL)
return nullptr ;
Point3d ptTg2 ;
Vector3d vtTg2 ;
if ( ! cCrv2.GetPointTang( dTgPar2, ICurve::FROM_MINUS, ptTg2, vtTg2))
return nullptr ;
// determino rotazione tra le curve
bool bCCW = (( vtTg1 ^ vtTg2) * vtNorm) > 0 ;
// orientamento tra le curve
bool bCCW = ( dSinA > 0) ;
// assegno i valori dei parametri di trim (+ da inizio, - da fine)
if ( bCCW) {
@@ -118,8 +145,17 @@ CreateFillet( const ICurve& cCrv1, const Point3d& ptNear1,
// creo l'arco di fillet
PtrOwner<CurveArc> crvFillet( CreateBasicCurveArc()) ;
if ( IsNull( crvFillet) ||
! crvFillet->SetC2PN( ptInt1, ptTg1, ptTg2, vtNorm))
! crvFillet->SetC2PN( ptCen, ptTg1, ptTg2, vtNorm))
return nullptr ;
// se direzioni agli estremi praticamente parallele
if ( bParallel) {
// calcolo il verso dell'arco di fillet
bool bFilletCcw = ( ( bCCW && nSide1 == nSide2) || ( ! bCCW && nSide1 != nSide2)) ;
// si deve verificare se va usato l'arco esplementare
bool bArcCcw = ( crvFillet->GetAngCenter() > 0) ;
if ( bFilletCcw != bArcCcw)
crvFillet->ToExplementary() ;
}
return Release(crvFillet) ;
}