63fb9a638b
- a SimpleOffset di Curve aggiunto parametro opzionale dMaxAngExt (angolo esterno oltre il quale estendi diventa smussa) con default 90deg.
525 lines
20 KiB
C++
525 lines
20 KiB
C++
//----------------------------------------------------------------------------
|
|
// EgalTech 2013-2013
|
|
//----------------------------------------------------------------------------
|
|
// File : CurveCompositeOffset.cpp Data : 07.12.14 Versione : 1.5l1
|
|
// Contenuto : Metodi per offset semplice della classe CCurveComposite.
|
|
//
|
|
//
|
|
//
|
|
// Modifiche : 07.12.14 DS Creazione modulo.
|
|
//
|
|
//
|
|
//----------------------------------------------------------------------------
|
|
|
|
//--------------------------- Include ----------------------------------------
|
|
#include "stdafx.h"
|
|
#include "CurveComposite.h"
|
|
#include "CurveLine.h"
|
|
#include "CurveArc.h"
|
|
#include "GeoConst.h"
|
|
#include "/EgtDev/Include/EGkCurve.h"
|
|
#include "/EgtDev/Include/EGkIntersCurves.h"
|
|
#include "/EgtDev/Include/EgtNumUtils.h"
|
|
#include "/EgtDev/Include/EgtPointerOwner.h"
|
|
|
|
using namespace std ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
static const int TP_IS_VERT_LINE = 1 ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
static bool IsVerticalLine( const ICurve* pCrv, double* pdLenZ) ;
|
|
static bool VerifyAndAdjustSamePoint( ICurve* pCrv1, ICurve* pCrv2, CurveComposite& ccAux) ;
|
|
static bool VerifyAndAdjustInternalAngle( ICurve* pCrv1, ICurve* pCrv2, CurveComposite& ccAux) ;
|
|
static bool VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dDist, int nType, double dMaxAngExt,
|
|
CurveComposite& ccAux) ;
|
|
static bool AddFirstLastVerticalLines( CurveComposite& ccOffs, double dLenVertFirst, double dLenVertLast) ;
|
|
static bool MediaInternalAngleDeltaZ( CurveComposite& ccOffs) ;
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
CurveComposite::SimpleOffsetXY( double dDist, int nType, double dMaxAngExt)
|
|
{
|
|
// creo una copia formata solo da rette e archi che giacciono nel piano XY (VtExtr è Z+)
|
|
CurveComposite ccCopy ;
|
|
if ( ! ccCopy.CopyFrom( *this) ||
|
|
! ccCopy.ArcsBezierCurvesToArcsPerpExtr( 10 * EPS_SMALL, ANG_TOL_STD_DEG))
|
|
return false ;
|
|
|
|
// determino se vietate linee verticali (perpendicolari a piano offset)
|
|
bool bNoVertLine = (( nType & ICurve::OFF_NO_VERTICAL) != 0) ;
|
|
|
|
// determino se richiesti angoli interni con deltaZ mediata
|
|
bool bMedIntDz = (( nType & ICurve::OFF_MEDIA_INTDZ) != 0) ;
|
|
|
|
// verifico se curva chiusa
|
|
bool bClosed = ccCopy.IsClosed() && ( nType & ICurve::OFF_FORCE_OPEN) == 0 ;
|
|
|
|
// creo la curva di offset
|
|
CurveComposite ccOffs ;
|
|
ccOffs.m_VtExtr = m_VtExtr ;
|
|
ccOffs.m_dThick = m_dThick ;
|
|
|
|
// eseguo l'offset ( estraggo entità dalla copia, le modifiche e le inserisco nell'offset)
|
|
// lunghezze di eventuali linee verticali iniziale e finale
|
|
double dLenVertFirst = 0 ;
|
|
double dLenVertLast = 0 ;
|
|
// recupero la prima curva
|
|
PtrOwner<ICurve> pCrv1( ccCopy.RemoveFirstOrLastCurve( false)) ;
|
|
if ( IsNull( pCrv1))
|
|
return false ;
|
|
// se la curva è una linea verticale in Z, passo alla successiva
|
|
if ( IsVerticalLine( pCrv1, &dLenVertFirst)) {
|
|
if ( bNoVertLine)
|
|
return false ;
|
|
pCrv1.Set( ccCopy.RemoveFirstOrLastCurve( false)) ;
|
|
}
|
|
// offset della prima curva
|
|
if ( IsNull( pCrv1))
|
|
return false ;
|
|
if ( ! pCrv1->SimpleOffset( dDist, nType))
|
|
return false ;
|
|
ICurve* pCrvPrev = pCrv1 ;
|
|
if ( ! ccOffs.AddSimpleCurve( Release( pCrv1)))
|
|
return false ;
|
|
// curve successive
|
|
PtrOwner<ICurve> pCrv2( ccCopy.RemoveFirstOrLastCurve( false)) ;
|
|
while ( ! IsNull( pCrv2)) {
|
|
// se la curva è una linea verticale in Z, passo alla successiva
|
|
if ( IsVerticalLine( pCrv2, &dLenVertLast)) {
|
|
if ( bNoVertLine)
|
|
return false ;
|
|
pCrv2.Set( ccCopy.RemoveFirstOrLastCurve( false)) ;
|
|
continue ;
|
|
}
|
|
// eseguo semplice offset
|
|
if ( ! pCrv2->SimpleOffset( dDist, nType))
|
|
return false ;
|
|
// verifico relazione con la curva precedente e aggiungo eventuali curve intermedie
|
|
CurveComposite ccTemp ;
|
|
if ( VerifyAndAdjustSamePoint( pCrvPrev, pCrv2, ccTemp) ||
|
|
VerifyAndAdjustInternalAngle( pCrvPrev, pCrv2, ccTemp) ||
|
|
VerifyAndAdjustExternalAngle( pCrvPrev, pCrv2, dDist, nType, dMaxAngExt, ccTemp)) {
|
|
if ( ccTemp.GetCurveCount() > 0 && ! ccOffs.AddCurveByRelocate( ccTemp))
|
|
return false ;
|
|
}
|
|
// nessun caso è andato a buon fine, errore
|
|
else
|
|
return false ;
|
|
// aggiorno curva precedente
|
|
pCrvPrev = pCrv2 ;
|
|
// inserisco nell'offset
|
|
if ( ! ccOffs.AddSimpleCurve( Release( pCrv2)))
|
|
return false ;
|
|
// passo alla curva successiva
|
|
pCrv2.Set( ccCopy.RemoveFirstOrLastCurve( false)) ;
|
|
}
|
|
|
|
// se originale chiuso, devo confrontare anche ultima e prima curva
|
|
if ( bClosed && ccOffs.GetCurveCount() > 0) {
|
|
// la curva successiva ora è la prima dell'offset
|
|
ICurve* pCrvNext = ccOffs.m_CrvSmplS.front() ;
|
|
// verifico relazione con la curva precedente e aggiungo eventuali curve intermedie
|
|
CurveComposite ccTemp ;
|
|
if ( VerifyAndAdjustSamePoint( pCrvPrev, pCrvNext, ccTemp) ||
|
|
VerifyAndAdjustInternalAngle( pCrvPrev, pCrvNext, ccTemp) ||
|
|
VerifyAndAdjustExternalAngle( pCrvPrev, pCrvNext, dDist, nType, dMaxAngExt, ccTemp)) {
|
|
int nCrvCount = ccTemp.GetCurveCount() ;
|
|
if ( nCrvCount > 0 && ! ccOffs.AddCurveByRelocate( ccTemp))
|
|
return false ;
|
|
if ( nCrvCount > 1) {
|
|
ccOffs.ChangeStartPoint( double( ccOffs.m_CrvSmplS.size()) - 1) ;
|
|
}
|
|
}
|
|
// nessun caso è andato a buon fine, errore
|
|
else
|
|
return false ;
|
|
}
|
|
|
|
// se originale aperto, devo rimettere eventuali lineee verticali iniziale e finale
|
|
if ( ! bClosed && ccOffs.GetCurveCount() > 0 &&
|
|
! AddFirstLastVerticalLines( ccOffs, dLenVertFirst, dLenVertLast))
|
|
return false ;
|
|
|
|
// se richiesti angoli interni con Z mediata, verifico e sistemo
|
|
if ( bMedIntDz && ! MediaInternalAngleDeltaZ( ccOffs))
|
|
return false ;
|
|
|
|
// sposto le curve dall'offset alla composita attuale
|
|
return RelocateFrom( ccOffs) ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
IsVerticalLine( const ICurve* pCrv, double* pdLenZ)
|
|
{
|
|
// verifico sia una linea
|
|
const CurveLine* pLine = GetBasicCurveLine( pCrv) ;
|
|
if ( pLine == nullptr)
|
|
return false ;
|
|
// verifico sia diretta come l'asse Z
|
|
if ( AreSamePointXYApprox( pLine->GetStart(), pLine->GetEnd())) {
|
|
if ( pdLenZ != nullptr)
|
|
*pdLenZ = pLine->GetEnd().z - pLine->GetStart().z ;
|
|
return true ;
|
|
}
|
|
else {
|
|
if ( pdLenZ != nullptr)
|
|
*pdLenZ = 0 ;
|
|
return false ;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VerifyAndAdjustSamePoint( ICurve* pCrv1, ICurve* pCrv2, CurveComposite& ccAux)
|
|
{
|
|
// verifica dei puntatori
|
|
if ( pCrv1 == nullptr || pCrv2 == nullptr)
|
|
return false ;
|
|
|
|
// pulisco la curva ausiliaria
|
|
ccAux.Clear() ;
|
|
|
|
// calcolo dei punti estremi (finale per prima curva, iniziale per seconda)
|
|
Point3d ptP1, ptP2 ;
|
|
if ( ! pCrv1->GetEndPoint( ptP1) || ! pCrv2->GetStartPoint( ptP2))
|
|
return false ;
|
|
// verifica distanza tra estremi
|
|
if ( ! AreSamePointXYEpsilon( ptP1, ptP2, 10 * EPS_SMALL))
|
|
return false ;
|
|
// se punti quasi coincidenti in Z
|
|
if ( abs( ptP1.z - ptP2.z) < 10 * EPS_SMALL) {
|
|
// se coincidono esattamente, va bene così
|
|
if ( AreSamePointExact( ptP1, ptP2))
|
|
return true ;
|
|
// sono in tolleranza, ma devo ricongiungere gli estremi
|
|
Point3d ptMid = 0.5 * ( ptP1 + ptP2) ;
|
|
return ( pCrv1->ModifyEnd( ptMid) && pCrv2->ModifyStart( ptMid)) ;
|
|
}
|
|
// devo allineare i punti in XY e aggiungere un tratto verticale
|
|
else {
|
|
// facio coincidere gli estremi in XY
|
|
Point3d ptP1a = 0.5 * ( ptP1 + ptP2) ;
|
|
ptP1a.z = ptP1.z ;
|
|
Point3d ptP2a = 0.5 * ( ptP1 + ptP2) ;
|
|
ptP2a.z = ptP2.z ;
|
|
if ( ! pCrv1->ModifyEnd( ptP1a) || ! pCrv2->ModifyStart( ptP2a))
|
|
return false ;
|
|
// aggiungo una retta in Z
|
|
PtrOwner<CurveLine> pCrv( CreateBasicCurveLine()) ;
|
|
if ( IsNull( pCrv) || ! pCrv->Set( ptP1a, ptP2a))
|
|
return false ;
|
|
return ccAux.AddCurve( Release( pCrv)) ;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VerifyAndAdjustInternalAngle( ICurve* pCrv1, ICurve* pCrv2, CurveComposite& ccAux)
|
|
{
|
|
// verifica dei puntatori
|
|
if ( pCrv1 == nullptr || pCrv2 == nullptr)
|
|
return false ;
|
|
|
|
// pulisco la curva ausiliaria
|
|
ccAux.Clear() ;
|
|
|
|
// calcolo l'intersezione tra le due curve
|
|
IntersCurveCurve intCC( *pCrv1, *pCrv2) ;
|
|
if ( intCC.GetIntersCount() == 0)
|
|
return false ;
|
|
// prendo l'intersezione più vicina al punto medio tra gli estremi delle curve
|
|
Point3d ptP1, ptP2 ;
|
|
if ( ! pCrv1->GetEndPoint( ptP1) || ! pCrv2->GetStartPoint( ptP2))
|
|
return false ;
|
|
Point3d ptMid = 0.5 * ( ptP1 + ptP2) ;
|
|
Point3d ptNew1, ptNew2 ;
|
|
if ( ! intCC.GetIntersPointNearTo( 0, ptMid, ptNew1) ||
|
|
! intCC.GetIntersPointNearTo( 1, ptMid, ptNew2))
|
|
return false ;
|
|
// se punti coincidenti in Z
|
|
if ( abs( ptNew1.z - ptNew2.z) < EPS_SMALL) {
|
|
// modifico le due curve sul punto medio
|
|
Point3d ptNew = 0.5 * ( ptNew1 + ptNew2) ;
|
|
return ( pCrv1->ModifyEnd( ptNew) && pCrv2->ModifyStart( ptNew)) ;
|
|
}
|
|
// altrimenti
|
|
else {
|
|
// modifico le due curve sui rispettivi punti di intersezione
|
|
if ( ! pCrv1->ModifyEnd( ptNew1) || ! pCrv2->ModifyStart( ptNew2))
|
|
return false ;
|
|
// aggiungo una retta in Z
|
|
PtrOwner<CurveLine> pCrv( CreateBasicCurveLine()) ;
|
|
if ( IsNull( pCrv) || ! pCrv->Set( ptNew1, ptNew2))
|
|
return false ;
|
|
pCrv->SetTempProp( TP_IS_VERT_LINE) ;
|
|
return ccAux.AddCurve( Release( pCrv)) ;
|
|
}
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
VerifyAndAdjustExternalAngle( ICurve* pCrv1, ICurve* pCrv2, double dDist, int nType, double dMaxAngExt,
|
|
CurveComposite& ccAux)
|
|
{
|
|
// verifica dei puntatori
|
|
if ( pCrv1 == nullptr || pCrv2 == nullptr)
|
|
return false ;
|
|
|
|
// pulisco la curva ausiliaria
|
|
ccAux.Clear() ;
|
|
|
|
// elimino dal tipo le parti estranee all'angolo esterno
|
|
nType &= ( ICurve::OFF_FILLET | ICurve::OFF_CHAMFER | ICurve::OFF_EXTEND) ;
|
|
|
|
// porto il massimo angolo per tipo Extend in limiti accettabili (90° - 150°)
|
|
dMaxAngExt = Clamp( dMaxAngExt, ANG_RIGHT, 1.667 * ANG_RIGHT) ;
|
|
|
|
// calcolo direzioni tangenti sull'estremo in comune
|
|
Vector3d vtDir1, vtDir2 ;
|
|
if ( ! pCrv1->GetEndDir( vtDir1) || ! pCrv2->GetStartDir( vtDir2))
|
|
return false ;
|
|
// verifico se presente componente in Z
|
|
bool bDZ1 = abs( vtDir1.z) > EPS_ANG_ZERO ;
|
|
bool bDZ2 = abs( vtDir2.z) > EPS_ANG_ZERO ;
|
|
// le porto nel piano XY
|
|
vtDir1.z = 0 ;
|
|
vtDir2.z = 0 ;
|
|
if ( ! vtDir1.Normalize() || ! vtDir2.Normalize())
|
|
return false ;
|
|
|
|
// calcolo l'angolo di rotazione dalla prima direzione alla seconda
|
|
double dAngDeg ;
|
|
if ( ! vtDir1.GetAngleXY( vtDir2, dAngDeg))
|
|
return false ;
|
|
// se vicino all'angolo piatto, si devono ricalcolare usando le curve originali e spostandosi un poco
|
|
if ( abs( dAngDeg) > ( ANG_STRAIGHT - EPS_ANG_SMALL)) {
|
|
// ritorno alle curve originali
|
|
PtrOwner<ICurve> pCrvOri1( pCrv1->Clone()) ;
|
|
PtrOwner<ICurve> pCrvOri2( pCrv2->Clone()) ;
|
|
if ( IsNull( pCrvOri1) || ! pCrvOri1->SimpleOffset( - dDist, nType))
|
|
return false ;
|
|
if ( IsNull( pCrvOri2) || ! pCrvOri2->SimpleOffset( - dDist, nType))
|
|
return false ;
|
|
// eseguo calcolo spostato su curve originali
|
|
double dU1 = 1 ;
|
|
double dU2 = 0 ;
|
|
Point3d ptDummy ;
|
|
Vector3d vtDir1b ;
|
|
Vector3d vtDir2b ;
|
|
if ( ! MoveParamToAvoidTg( dU1, ICurve::FROM_MINUS, *pCrvOri1) ||
|
|
! pCrvOri1->GetPointTang( dU1, ICurve::FROM_MINUS, ptDummy, vtDir1b) ||
|
|
! MoveParamToAvoidTg( dU2, ICurve::FROM_PLUS, *pCrvOri2) ||
|
|
! pCrvOri2->GetPointTang( dU2, ICurve::FROM_PLUS, ptDummy, vtDir2b))
|
|
return false ;
|
|
if ( ! vtDir1b.GetAngleXY( vtDir2b, dAngDeg))
|
|
return false ;
|
|
}
|
|
|
|
// verifico sia angolo esterno (accetto se entità quasi esattamente sovrapposto)
|
|
if ( abs( dAngDeg) < ( ANG_STRAIGHT - 10 * EPS_ANG_ZERO) &&
|
|
( ( dDist < 0 && dAngDeg > 0) ||
|
|
( dDist > 0 && dAngDeg < 0)))
|
|
return false ;
|
|
|
|
// se l'angolo esterno supera il limite, offset extend diventa offset chamfer
|
|
if ( nType == ICurve::OFF_EXTEND && abs( dAngDeg) > dMaxAngExt + 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 ;
|
|
|
|
// congiungo le due curve
|
|
switch ( nType) {
|
|
case ICurve::OFF_FILLET :
|
|
{
|
|
Point3d ptP1, ptP2 ;
|
|
if ( ! pCrv1->GetEndPoint( ptP1) || ! pCrv2->GetStartPoint( ptP2))
|
|
return false ;
|
|
double dAngStart ;
|
|
vtDir1.ToSpherical( nullptr, nullptr, &dAngStart) ;
|
|
PtrOwner<CurveArc> pCrv( CreateBasicCurveArc()) ;
|
|
if ( IsNull( pCrv) || ! pCrv->Set2PD( ptP1, ptP2, dAngStart))
|
|
return false ;
|
|
// restituisco la curva
|
|
return ccAux.AddCurve( Release( pCrv)) ;
|
|
}
|
|
break ;
|
|
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 ( ! pCrv1->GetEndPoint( ptP1) || ! pCrv2->GetStartPoint( ptP2))
|
|
return false ;
|
|
ptP1a = ptP1 + vtDir1 * dLen ;
|
|
ptP2a = ptP2 - vtDir2 * dLen ;
|
|
// se sull'angolo c'era un dislivello (linea verticale eliminata)
|
|
double dDeltaZ = ptP2.z - ptP1.z ;
|
|
if ( abs( dDeltaZ) > EPS_SMALL) {
|
|
ptP1a.z += dDeltaZ / 4 ;
|
|
ptP2a.z -= dDeltaZ / 4 ;
|
|
bDZ1 = true ;
|
|
bDZ2 = true ;
|
|
}
|
|
// se prima c'è linea senza DZ posso allungarla
|
|
if ( pCrv1->GetType() == CRV_LINE && ! bDZ1)
|
|
pCrv1->ModifyEnd( ptP1a) ;
|
|
// altrimenti, devo aggiungere una nuova linea
|
|
else {
|
|
PtrOwner<CurveLine> pCrv( CreateBasicCurveLine()) ;
|
|
if ( IsNull( pCrv) || ! pCrv->Set( ptP1, ptP1a))
|
|
return false ;
|
|
if ( ! ccAux.AddCurve( Release( pCrv)))
|
|
return false ;
|
|
}
|
|
// tratto intermedio
|
|
{
|
|
PtrOwner<CurveLine> pCrv( CreateBasicCurveLine()) ;
|
|
if ( IsNull( pCrv) || ! pCrv->Set( ptP1a, ptP2a))
|
|
return false ;
|
|
if ( ! ccAux.AddCurve( Release( pCrv)))
|
|
return false ;
|
|
}
|
|
// se dopo c'è linea senza DZ posso allungarla
|
|
if ( pCrv2->GetType() == CRV_LINE && ! bDZ2)
|
|
pCrv2->ModifyStart( ptP2a) ;
|
|
// altrimenti, devo aggiungere una nuova linea
|
|
else {
|
|
PtrOwner<CurveLine> pCrv( CreateBasicCurveLine()) ;
|
|
if ( IsNull( pCrv) || ! pCrv->Set( ptP2a, ptP2))
|
|
return false ;
|
|
if ( ! ccAux.AddCurve( Release( pCrv)))
|
|
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 ( ! pCrv1->GetEndPoint( ptP1) || ! pCrv2->GetStartPoint( ptP2))
|
|
return false ;
|
|
ptPc = ptP1 + vtDir1 * dLen ;
|
|
// se sull'angolo c'era un dislivello (linea verticale eliminata)
|
|
double dDeltaZ = ptP2.z - ptP1.z ;
|
|
if ( abs( dDeltaZ) > EPS_SMALL) {
|
|
ptPc.z += dDeltaZ / 2 ;
|
|
bDZ1 = true ;
|
|
bDZ2 = true ;
|
|
}
|
|
// se prima c'è linea senza DZ posso allungarla o angolo molto piccolo
|
|
if ( ( pCrv1->GetType() == CRV_LINE && ! bDZ1) || bAngSmall)
|
|
pCrv1->ModifyEnd( ptPc) ;
|
|
// altrimenti, devo aggiungere una nuova linea
|
|
else {
|
|
PtrOwner<CurveLine> pCrv( CreateBasicCurveLine()) ;
|
|
if ( IsNull( pCrv) || ! pCrv->Set( ptP1, ptPc))
|
|
return false ;
|
|
if ( ! ccAux.AddCurve( Release( pCrv)))
|
|
return false ;
|
|
}
|
|
// se dopo c'è linea senza DZ posso allungarla o angolo molto piccolo
|
|
if ( ( pCrv2->GetType() == CRV_LINE && ! bDZ2) || bAngSmall)
|
|
pCrv2->ModifyStart( ptPc) ;
|
|
// altrimenti, devo aggiungere una nuova linea
|
|
else {
|
|
PtrOwner<CurveLine> pCrv( CreateBasicCurveLine()) ;
|
|
if ( IsNull( pCrv) || ! pCrv->Set( ptPc, ptP2))
|
|
return false ;
|
|
if ( ! ccAux.AddCurve( Release( pCrv)))
|
|
return false ;
|
|
}
|
|
return true ;
|
|
}
|
|
}
|
|
return false ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
AddFirstLastVerticalLines( CurveComposite& ccOffs, double dLenVertFirst, double dLenVertLast)
|
|
{
|
|
// se richiesto inserimento prima retta verticale
|
|
if ( abs( dLenVertFirst) > EPS_SMALL) {
|
|
Point3d ptP2 ;
|
|
if ( ! ccOffs.GetStartPoint( ptP2))
|
|
return false ;
|
|
Point3d ptP1 = ptP2 ;
|
|
ptP1.z -= dLenVertFirst ;
|
|
PtrOwner<CurveLine> pCrv( CreateBasicCurveLine()) ;
|
|
if ( IsNull( pCrv) || ! pCrv->Set( ptP1, ptP2))
|
|
return false ;
|
|
if ( ! ccOffs.AddCurve( Release( pCrv), false))
|
|
return false ;
|
|
}
|
|
// se richiesto inserimento ultima retta verticale
|
|
if ( abs( dLenVertLast) > EPS_SMALL) {
|
|
Point3d ptP1 ;
|
|
if ( ! ccOffs.GetEndPoint( ptP1))
|
|
return false ;
|
|
Point3d ptP2 = ptP1 ;
|
|
ptP2.z += dLenVertLast ;
|
|
PtrOwner<CurveLine> pCrv( CreateBasicCurveLine()) ;
|
|
if ( IsNull( pCrv) || ! pCrv->Set( ptP1, ptP2))
|
|
return false ;
|
|
if ( ! ccOffs.AddCurve( Release( pCrv)))
|
|
return false ;
|
|
}
|
|
return true ;
|
|
}
|
|
|
|
//----------------------------------------------------------------------------
|
|
bool
|
|
MediaInternalAngleDeltaZ( CurveComposite& ccOffs)
|
|
{
|
|
// definisco una composita temporanea
|
|
CurveComposite ccTemp ;
|
|
|
|
// ciclo sulle curve
|
|
bool bModifyNext = false ;
|
|
Point3d ptMid ;
|
|
ICurve* pCrv = ccOffs.RemoveFirstOrLastCurve( false) ;
|
|
while ( pCrv != nullptr) {
|
|
// verifico se curva di raccordo in Z di angolo interno
|
|
if ( pCrv->GetTempProp() == TP_IS_VERT_LINE) {
|
|
// ne recupero il punto medio e la cancello
|
|
pCrv->GetMidPoint( ptMid) ;
|
|
delete pCrv ;
|
|
// modifico il finale della curva precedente
|
|
if ( ! ccTemp.ModifyEnd( ptMid))
|
|
return false ;
|
|
// imposto flag per modifica iniziale della curva successiva
|
|
bModifyNext = true ;
|
|
}
|
|
// altrimenti
|
|
else {
|
|
// se da modificare
|
|
if ( bModifyNext && ! pCrv->ModifyStart( ptMid)) {
|
|
delete pCrv ;
|
|
return false ;
|
|
}
|
|
bModifyNext = false ;
|
|
// la sposto nella composita di offset
|
|
if ( ! ccTemp.AddCurve( pCrv))
|
|
return false ;
|
|
}
|
|
// passo alla curva successiva
|
|
pCrv = ccOffs.RemoveFirstOrLastCurve( false) ;
|
|
}
|
|
// se modifica in sospeso, allora curva originale chiusa e modifico inizio
|
|
if ( bModifyNext && ! ccTemp.ModifyStart( ptMid))
|
|
return false ;
|
|
|
|
// riporto le curve nella composita di offset
|
|
return ccOffs.RelocateFrom( ccTemp) ;
|
|
}
|