//---------------------------------------------------------------------------- // 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 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 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 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 pLine1( CreateBasicCurveLine()) ; if ( IsNull( pLine1) || ! pLine1->Set( ptP1, ptP1a)) return false ; if ( ! ccAux.AddCurve( Release( pLine1))) return false ; // tratto intermedio PtrOwner pLine2( CreateBasicCurveLine()) ; if ( IsNull( pLine2) || ! pLine2->Set( ptP1a, ptP2a)) return false ; if ( ! ccAux.AddCurve( Release( pLine2))) return false ; // aggiungo una nuova linea PtrOwner 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 pLine1( CreateBasicCurveLine()) ; if ( IsNull( pLine1) || ! pLine1->Set( ptP1, ptPc)) return false ; if ( ! ccAux.AddCurve( Release( pLine1))) return false ; // aggiungo una nuova linea PtrOwner pLine2( CreateBasicCurveLine()) ; if ( IsNull( pLine2) || ! pLine2->Set( ptPc, ptP2)) return false ; if ( ! ccAux.AddCurve( Release( pLine2))) return false ; return true ; } } return false ; }