EgtGeomKernel 1.6k1 :

- aggiunto offset di regioni
- migliorato offset di curve
- migliorata creazione di regioni.
This commit is contained in:
Dario Sassi
2015-11-03 21:24:31 +00:00
parent 740392c456
commit ba71993098
11 changed files with 553 additions and 22 deletions
+193 -16
View File
@@ -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 ;
}