EgtGeomKernel 1.6k1 :
- aggiunto offset di regioni - migliorato offset di curve - migliorata creazione di regioni.
This commit is contained in:
+193
-16
@@ -36,6 +36,8 @@ static bool VerifyAndAdjustInternalAngle( ICurve* pCrv1, ICurve* pCrv2) ;
|
||||
static bool VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dAngDeg, double dDist, int nType,
|
||||
CurveComposite& ccAux) ;
|
||||
static double GetMinDist( double dCoeff, ICurve* pCrv1, ICurve* pCrv2) ;
|
||||
static bool IsFillet( ICurve* pCrv, double dDist) ;
|
||||
static bool ModifyFillet( ICurve* pCrv, double dDist, int nType, CurveComposite& ccAux) ;
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -54,16 +56,40 @@ OffsetCurve::~OffsetCurve( void)
|
||||
bool
|
||||
OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
{
|
||||
// verifico che la curva esista e si trovi nel piano XY o in uno ad esso parallelo
|
||||
// verifico che la curva esista e sia piana
|
||||
Plane3d plPlane ;
|
||||
if ( pCrv == nullptr || ! pCrv->IsFlat( plPlane) ||
|
||||
! ( plPlane.vtN.IsZplus() || plPlane.vtN.IsZminus()))
|
||||
if ( pCrv == nullptr || ! pCrv->IsFlat( plPlane))
|
||||
return false ;
|
||||
// se esiste estrusione, verifico sia perpendicolare al piano della curva
|
||||
Vector3d vtExtr ;
|
||||
if ( pCrv->GetExtrusion( vtExtr) && ! vtExtr.IsSmall()) {
|
||||
if ( ! AreSameOrOppositeVectorApprox( plPlane.vtN, vtExtr))
|
||||
return false ;
|
||||
}
|
||||
else
|
||||
vtExtr = plPlane.vtN ;
|
||||
|
||||
// creo una copia formata solo da rette e archi che giacciono nel piano XY (VtExtr è Z+)
|
||||
// determino se necessario cambiare riferimento ( dal vettore estrusione)
|
||||
bool bNeedRef = ( ! vtExtr.IsZplus()) ;
|
||||
|
||||
// creo una copia della curva
|
||||
CurveComposite ccCopy ;
|
||||
if ( ! ccCopy.CopyFrom( pCrv) ||
|
||||
! ccCopy.ArcsBezierCurvesToArcsPerpExtr( 10 * EPS_SMALL, ANG_TOL_STD_DEG))
|
||||
if ( ! ccCopy.CopyFrom( pCrv))
|
||||
return false ;
|
||||
ccCopy.SetExtrusion( vtExtr) ;
|
||||
|
||||
// se necessario cambio il riferimento
|
||||
Frame3d frExtr ;
|
||||
if ( bNeedRef) {
|
||||
// calcolo il riferimento OCS con VtExtr come asse Z
|
||||
if ( ! frExtr.Set( ORIG, vtExtr))
|
||||
return false ;
|
||||
// esprimo la curva in questo riferimento
|
||||
ccCopy.ToLoc( frExtr) ;
|
||||
}
|
||||
|
||||
// verifico che la curva sia fatta solo da rette e archi che giacciono nel piano XY (VtExtr è ora Z+)
|
||||
if ( ! ccCopy.ArcsBezierCurvesToArcsPerpExtr( 10 * EPS_SMALL, ANG_TOL_STD_DEG))
|
||||
return false ;
|
||||
|
||||
// verifico se curva chiusa e non forzata aperta
|
||||
@@ -108,7 +134,7 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
vAngs.push_back( 0) ;
|
||||
}
|
||||
|
||||
// primo passo : estraggo entità dalla copia, loro offset elementare e aggiunta raccordi esterni
|
||||
// primo passo : estraggo entità dalla copia, loro offset elementare e aggiunta raccordi esterni (sempre fillet)
|
||||
CurveComposite ccCopy2 ;
|
||||
if ( ! ccCopy2.CopyFrom( &ccCopy))
|
||||
return false ;
|
||||
@@ -119,27 +145,29 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
if ( IsNull( pCrv1))
|
||||
return false ;
|
||||
pCrv1->SetTempProp( nInd1) ;
|
||||
if ( ! pCrv1->SimpleOffset( dDist, nType) &&
|
||||
GetBasicCurveArc( Get( pCrv1))->MyExtendedOffset( dDist, true, nType))
|
||||
if ( ! pCrv1->SimpleOffset( dDist, ICurve::OFF_FILLET) &&
|
||||
GetBasicCurveArc( Get( pCrv1))->MyExtendedOffset( dDist, true, ICurve::OFF_FILLET))
|
||||
pCrv1->SetTempProp( - nInd1) ;
|
||||
// curve successive
|
||||
PtrOwner<ICurve> pCrv2( ccCopy2.RemoveFirstOrLastCurve( false)) ;
|
||||
while ( ! IsNull( pCrv2)) {
|
||||
// eseguo semplice offset
|
||||
pCrv2->SetTempProp( nInd1 + 1) ;
|
||||
if ( ! pCrv2->SimpleOffset( dDist, nType) &&
|
||||
GetBasicCurveArc( Get( pCrv2))->MyExtendedOffset( dDist, true, nType))
|
||||
if ( ! pCrv2->SimpleOffset( dDist, ICurve::OFF_FILLET) &&
|
||||
GetBasicCurveArc( Get( pCrv2))->MyExtendedOffset( dDist, true, ICurve::OFF_FILLET))
|
||||
pCrv2->SetTempProp( - (nInd1 + 1)) ;
|
||||
// verifico relazione con la curva precedente e aggiungo eventuali curve intermedie
|
||||
CurveComposite ccTemp ;
|
||||
bool bOk = VerifyAndAdjustExternalAngle( Get( pCrv1), Get( pCrv2), vAngs[nInd1], dDist, nType, ccTemp) ;
|
||||
bool bOk = VerifyAndAdjustExternalAngle( Get( pCrv1), Get( pCrv2), vAngs[nInd1], dDist, ICurve::OFF_FILLET, ccTemp) ;
|
||||
// metto in lista curva precedente
|
||||
m_CrvLst.push_back( Release( pCrv1)) ;
|
||||
// se aggiunto qualcosa, lo metto in lista
|
||||
if ( ccTemp.GetCurveCount() > 0) {
|
||||
PtrOwner<ICurve> pCrv3( ccTemp.RemoveFirstOrLastCurve( false)) ;
|
||||
while ( ! IsNull( pCrv3))
|
||||
while ( ! IsNull( pCrv3)) {
|
||||
m_CrvLst.push_back( Release( pCrv3)) ;
|
||||
pCrv3.Set( ccTemp.RemoveFirstOrLastCurve( false)) ;
|
||||
}
|
||||
}
|
||||
// aggiorno curva precedente
|
||||
++ nInd1 ;
|
||||
@@ -159,12 +187,14 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
ICurve* pCrv2 = m_CrvLst.front() ;
|
||||
// verifico relazione con la curva precedente e aggiungo eventuali curve intermedie
|
||||
CurveComposite ccTemp ;
|
||||
bool bOk = VerifyAndAdjustExternalAngle( pCrv1, pCrv2, vAngs[nInd1], dDist, nType, ccTemp) ;
|
||||
bool bOk = VerifyAndAdjustExternalAngle( pCrv1, pCrv2, vAngs[nInd1], dDist, ICurve::OFF_FILLET, ccTemp) ;
|
||||
// se aggiunto qualcosa, lo metto in lista
|
||||
if ( ccTemp.GetCurveCount() > 0) {
|
||||
PtrOwner<ICurve> pCrv3( ccTemp.RemoveFirstOrLastCurve( false)) ;
|
||||
while ( ! IsNull( pCrv3))
|
||||
while ( ! IsNull( pCrv3)) {
|
||||
m_CrvLst.push_back( Release( pCrv3)) ;
|
||||
pCrv3.Set( ccTemp.RemoveFirstOrLastCurve( false)) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,6 +398,48 @@ OffsetCurve::Make( const ICurve* pCrv, double dDist, int nType)
|
||||
++ iIter ;
|
||||
}
|
||||
|
||||
// ottavo passo : se con smusso o estensione, sostituisco i fillet con questi
|
||||
if ( ( nType & ICurve::OFF_CHAMFER) != 0 || ( nType & ICurve::OFF_EXTEND) != 0) {
|
||||
for ( auto iIter = m_CrvLst.begin() ; iIter != m_CrvLst.end() ; ++ iIter) {
|
||||
// processo le curve semplici della composita
|
||||
CurveComposite* pCrvCo = GetBasicCurveComposite( *iIter) ;
|
||||
ICURVEPLIST CrvLst ;
|
||||
PtrOwner<ICurve> pCrv( pCrvCo->RemoveFirstOrLastCurve( false)) ;
|
||||
while ( ! IsNull( pCrv)) {
|
||||
// se fillet lo trasformo in smusso o estensione
|
||||
if ( IsFillet( Get( pCrv), dDist)) {
|
||||
CurveComposite ccTemp ;
|
||||
bool bOk = ModifyFillet( Get( pCrv), dDist, nType, ccTemp) ;
|
||||
// metto in lista le curve risultanti
|
||||
if ( ccTemp.GetCurveCount() > 0) {
|
||||
PtrOwner<ICurve> pCrv2( ccTemp.RemoveFirstOrLastCurve( false)) ;
|
||||
while ( ! IsNull( pCrv2)) {
|
||||
CrvLst.push_back( Release( pCrv2)) ;
|
||||
pCrv2.Set( ccTemp.RemoveFirstOrLastCurve( false)) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// altrimenti salvo in lista
|
||||
else
|
||||
CrvLst.push_back( Release( pCrv)) ;
|
||||
// passo alla curva successiva
|
||||
pCrv.Set( pCrvCo->RemoveFirstOrLastCurve( false)) ;
|
||||
}
|
||||
// rimetto le curve nella composita
|
||||
for ( auto pCrv : CrvLst) {
|
||||
pCrvCo->AddCurve( pCrv) ;
|
||||
}
|
||||
// unisco tratti allineati
|
||||
pCrvCo->MergeCurves( LIN_TOL_MIN, ANG_TOL_STD_DEG) ;
|
||||
}
|
||||
}
|
||||
|
||||
// riporto il risultato nel riferimento originale
|
||||
if ( bNeedRef) {
|
||||
for ( auto pCrv : m_CrvLst)
|
||||
pCrv->ToGlob( frExtr) ;
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -692,4 +764,109 @@ GetMinDist( double dCoeff, ICurve* pCrv1, ICurve* pCrv2)
|
||||
if ( ! dstPC.GetDist( dMinDist))
|
||||
return 0 ;
|
||||
return dMinDist ;
|
||||
}
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IsFillet( ICurve* pCrv, double dDist)
|
||||
{
|
||||
// deve essere un arco
|
||||
if ( pCrv->GetType() != CRV_ARC)
|
||||
return false ;
|
||||
CurveArc* pArc = GetBasicCurveArc( pCrv) ;
|
||||
// deve avere raggio uguale alla distanza di offset
|
||||
if ( fabs( pArc->GetRadius() - fabs( dDist)) > EPS_SMALL)
|
||||
return false ;
|
||||
// deve essere CCW se offset a destra e CW se offset a sinistra
|
||||
return ( pArc->GetAngCenter() * dDist > 0) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
ModifyFillet( ICurve* pCrv, double dDist, int nType, CurveComposite& ccAux)
|
||||
{
|
||||
// la curva deve essere un arco
|
||||
CurveArc* pArc = GetBasicCurveArc( pCrv) ;
|
||||
if ( pArc == nullptr)
|
||||
return false ;
|
||||
|
||||
// angolo al centro dell'arco
|
||||
double dAngDeg = pArc->GetAngCenter() ;
|
||||
|
||||
// elimino dal tipo le parti estranee all'angolo esterno
|
||||
nType &= ( ICurve::OFF_FILLET | ICurve::OFF_CHAMFER | ICurve::OFF_EXTEND) ;
|
||||
|
||||
// se l'angolo esterno supera il retto, offset extend diventa offset chamfer
|
||||
if ( nType == ICurve::OFF_EXTEND && fabs( dAngDeg) > ANG_RIGHT + EPS_ANG_SMALL)
|
||||
nType = ICurve::OFF_CHAMFER ;
|
||||
|
||||
// se angolo esterno molto piccolo, semplifico tutto
|
||||
const double SMALL_EXT_ANG = 1.0 ;
|
||||
bool bAngSmall = ( fabs( dAngDeg) < SMALL_EXT_ANG) ;
|
||||
if ( bAngSmall)
|
||||
nType = ICurve::OFF_EXTEND ;
|
||||
|
||||
switch ( nType) {
|
||||
case ICurve::OFF_CHAMFER :
|
||||
{
|
||||
// lunghezza aggiuntiva in tangenza
|
||||
double dLen = fabs( dDist) * tan( fabs( dAngDeg) / 4 * DEGTORAD) ;
|
||||
// punti di costruzione smusso
|
||||
Point3d ptP1, ptP1a, ptP2a, ptP2 ;
|
||||
if ( ! pArc->GetStartPoint( ptP1) || ! pArc->GetEndPoint( ptP2))
|
||||
return false ;
|
||||
Vector3d vtDir1, vtDir2 ;
|
||||
if ( ! pArc->GetStartDir( vtDir1) || ! pArc->GetEndDir( vtDir2))
|
||||
return false ;
|
||||
ptP1a = ptP1 + vtDir1 * dLen ;
|
||||
ptP2a = ptP2 - vtDir2 * dLen ;
|
||||
// aggiungo una nuova linea
|
||||
PtrOwner<CurveLine> pLine1( CreateBasicCurveLine()) ;
|
||||
if ( IsNull( pLine1) || ! pLine1->Set( ptP1, ptP1a))
|
||||
return false ;
|
||||
if ( ! ccAux.AddCurve( Release( pLine1)))
|
||||
return false ;
|
||||
// tratto intermedio
|
||||
PtrOwner<CurveLine> pLine2( CreateBasicCurveLine()) ;
|
||||
if ( IsNull( pLine2) || ! pLine2->Set( ptP1a, ptP2a))
|
||||
return false ;
|
||||
if ( ! ccAux.AddCurve( Release( pLine2)))
|
||||
return false ;
|
||||
// aggiungo una nuova linea
|
||||
PtrOwner<CurveLine> pLine3( CreateBasicCurveLine()) ;
|
||||
if ( IsNull( pLine3) || ! pLine3->Set( ptP2a, ptP2))
|
||||
return false ;
|
||||
if ( ! ccAux.AddCurve( Release( pLine3)))
|
||||
return false ;
|
||||
return true ;
|
||||
}
|
||||
break ;
|
||||
case ICurve::OFF_EXTEND :
|
||||
{
|
||||
// lunghezza aggiuntiva in tangenza
|
||||
double dLen = fabs( dDist) * tan( fabs( dAngDeg) / 2 * DEGTORAD) ;
|
||||
// punti di costruzione estensione
|
||||
Point3d ptP1, ptPc, ptP2 ;
|
||||
if ( ! pArc->GetStartPoint( ptP1) || ! pArc->GetEndPoint( ptP2))
|
||||
return false ;
|
||||
Vector3d vtDir1, vtDir2 ;
|
||||
if ( ! pArc->GetStartDir( vtDir1) || ! pArc->GetEndDir( vtDir2))
|
||||
return false ;
|
||||
ptPc = ptP1 + vtDir1 * dLen ;
|
||||
// aggiungo una nuova linea
|
||||
PtrOwner<CurveLine> pLine1( CreateBasicCurveLine()) ;
|
||||
if ( IsNull( pLine1) || ! pLine1->Set( ptP1, ptPc))
|
||||
return false ;
|
||||
if ( ! ccAux.AddCurve( Release( pLine1)))
|
||||
return false ;
|
||||
// aggiungo una nuova linea
|
||||
PtrOwner<CurveLine> pLine2( CreateBasicCurveLine()) ;
|
||||
if ( IsNull( pLine2) || ! pLine2->Set( ptPc, ptP2))
|
||||
return false ;
|
||||
if ( ! ccAux.AddCurve( Release( pLine2)))
|
||||
return false ;
|
||||
return true ;
|
||||
}
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user