Files
EgtGeomKernel/OffsetAux.cpp
SaraP 595421bcdd EgtGeomKernel :
- gestone delle eccezioni di vroni
- correzioni varie.
2024-02-12 12:22:24 +01:00

180 lines
6.2 KiB
C++

//----------------------------------------------------------------------------
// EgalTech 2013-2013
//----------------------------------------------------------------------------
// File : OffsetAux.cpp Data : 23.11.23 Versione : 2.5k5
// Contenuto : Implementazione di alcune funzioni di utilità per gli offset delle curve.
//
//
//
// Modifiche : 23.11.23 SP Creazione modulo spostando alcune funzioni da OffsetCurve.cpp.
//
//
//----------------------------------------------------------------------------
#include "stdafx.h"
#include "OffsetAux.h"
#include "CurveArc.h"
#include "CurveLine.h"
#include "GeoConst.h"
using namespace std ;
//----------------------------------------------------------------------------
bool
IdentifyFillets( ICurveComposite* pCrvCo, double dDist)
{
// identifico le sottocurve di tipo fillet e assegno loro temp param 1.0 per riconoscerle nella funzione AdjustCurveFillets
for ( int i = 0 ; i < pCrvCo->GetCurveCount() ; i ++) {
// recupero la curva
PtrOwner<ICurve> pCrv( pCrvCo->GetCurve(i)->Clone()) ;
if ( IsNull( pCrv))
return false ;
if ( IsFillet( pCrv, dDist))
pCrvCo->SetCurveTempParam( i, 1.0) ;
else
pCrvCo->SetCurveTempParam( i, 0.0) ;
}
return true ;
}
//----------------------------------------------------------------------------
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 ( abs( pArc->GetRadius() - abs( dDist)) > EPS_SMALL)
return false ;
// deve essere CCW se offset a destra e CW se offset a sinistra
return ( pArc->GetAngCenter() * dDist > 0) ;
}
//----------------------------------------------------------------------------
bool
AdjustCurveFillets( ICurveComposite* pCrvCo, double dDist, int nType)
{
ICURVEPLIST CrvLst ;
PtrOwner<ICurve> pCrv( pCrvCo->RemoveFirstOrLastCurve( false)) ;
while ( ! IsNull( pCrv)) {
// se identificato come fillet lo trasformo in smusso o estensione
if ( pCrv->GetTempParam() > EPS_SMALL) {
CurveComposite ccTemp ;
ModifyFillet( 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) ;
return true ;
}
//----------------------------------------------------------------------------
bool
ModifyFillet( ICurve* pCrv, double dDist, int nType, ICurveComposite& 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 && abs( 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 = ( abs( dAngDeg) < SMALL_EXT_ANG) ;
if ( bAngSmall)
nType = ICurve::OFF_EXTEND ;
switch ( nType) {
case ICurve::OFF_CHAMFER :
{
// lunghezza aggiuntiva in tangenza
double dLen = abs( dDist) * tan( abs( 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 = abs( dDist) * tan( abs( 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 ;
}