|
|
|
@@ -0,0 +1,464 @@
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
// EgalTech 2026
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
// File : OffsetCurve3d.cpp Data : 10.06.26 Versione : 3.1f1
|
|
|
|
|
// Contenuto : Classe per offset di Curve 3d.
|
|
|
|
|
//
|
|
|
|
|
//
|
|
|
|
|
//
|
|
|
|
|
// Modifiche : 10.06.26 DB Creazione modulo.
|
|
|
|
|
//
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
//--------------------------- Include ----------------------------------------
|
|
|
|
|
#include "stdafx.h"
|
|
|
|
|
#include "GeoConst.h"
|
|
|
|
|
#include "CurveLine.h"
|
|
|
|
|
#include "CurveComposite.h"
|
|
|
|
|
#include "RemoveCurveDefects.h"
|
|
|
|
|
#include "IntersLineCyl.h"
|
|
|
|
|
#include "/EgtDev/Include/EGkPoint3d.h"
|
|
|
|
|
#include "/EgtDev/Include/EGkPolyLine.h"
|
|
|
|
|
#include "/EgtDev/Include/EGkOffsetCurve3d.h"
|
|
|
|
|
#include "/EgtDev/Include/EgtPointerOwner.h"
|
|
|
|
|
#include <algorithm>
|
|
|
|
|
|
|
|
|
|
using namespace std ;
|
|
|
|
|
|
|
|
|
|
#define SAVECVRORIG 1
|
|
|
|
|
#define SAVEOFFDIR 1
|
|
|
|
|
#define SAVECYL 1
|
|
|
|
|
#if SAVECVRORIG || SAVEOFFDIR || SAVECYL
|
|
|
|
|
#include "/EgtDev/Include/EGkColor.h"
|
|
|
|
|
#include "/EgtDev/Include/EGkGeoVector3d.h"
|
|
|
|
|
vector<IGeoObj*> vGeo ;
|
|
|
|
|
vector<Color> vCol ;
|
|
|
|
|
#include "/EgtDev/Include/EGkGeoObjSave.h"
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
bool AdjustConcavePartsInPath( const ICurveComposite* pCrv, ICURVEPOVECTOR& vOffsetCrvs, const INTVECTOR& vFlag, double dRad) ;
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
OffsetCurve3d::~OffsetCurve3d( void)
|
|
|
|
|
{
|
|
|
|
|
Reset() ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
bool
|
|
|
|
|
OffsetCurve3d::Reset( void)
|
|
|
|
|
{
|
|
|
|
|
for ( auto& pCrv : m_CrvLst) {
|
|
|
|
|
if ( pCrv != nullptr) {
|
|
|
|
|
delete pCrv ;
|
|
|
|
|
pCrv = nullptr ;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
m_CrvLst.clear() ;
|
|
|
|
|
return true ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
bool
|
|
|
|
|
OffsetCurve3d::Make( const PolyLine& PL, const VCT3DVECTOR& vOffDir, double dOffDist, int nType)
|
|
|
|
|
{
|
|
|
|
|
// pulisco tutto
|
|
|
|
|
Reset() ;
|
|
|
|
|
PtrOwner<CurveComposite> pCrv( CreateBasicCurveComposite()) ;
|
|
|
|
|
if ( ! pCrv->FromPolyLine( PL))
|
|
|
|
|
return false ;
|
|
|
|
|
|
|
|
|
|
#if SAVECVRORIG
|
|
|
|
|
vGeo.push_back( pCrv->Clone()) ;
|
|
|
|
|
vCol.push_back( AQUA) ;
|
|
|
|
|
Point3d ptBase ; PL.GetFirstPoint( ptBase) ;
|
|
|
|
|
for ( int i = 0 ; i < ssize( vOffDir) ; ++i) {
|
|
|
|
|
IGeoVector3d* pVec = CreateGeoVector3d() ;
|
|
|
|
|
pVec->Set( vOffDir[i] * dOffDist, ptBase) ;
|
|
|
|
|
PL.GetNextPoint( ptBase) ;
|
|
|
|
|
vGeo.push_back( pVec) ;
|
|
|
|
|
vCol.push_back( BLUE) ;
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
// verifico se la curva è un segmento di retta
|
|
|
|
|
bool bIsLine = PL.GetPointNbr() == 2 ;
|
|
|
|
|
if ( bIsLine) {
|
|
|
|
|
// faccio l'offset di una linea
|
|
|
|
|
return true ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// se offset nullo, copio la curva ed esco
|
|
|
|
|
if ( abs( dOffDist) < 10 * EPS_SMALL) {
|
|
|
|
|
PtrOwner<CurveComposite> pCopy( CreateBasicCurveComposite()) ;
|
|
|
|
|
if ( IsNull( pCopy) || ! pCopy->CopyFrom( pCrv))
|
|
|
|
|
return false ;
|
|
|
|
|
// unisco parti allineate (tranne gli estremi)
|
|
|
|
|
pCopy->MergeCurves( 10 * EPS_SMALL, ANG_TOL_STD_DEG, false) ;
|
|
|
|
|
// sposto in lista
|
|
|
|
|
m_CrvLst.push_back( Release( pCopy)) ;
|
|
|
|
|
return true ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// elimino tratti molto corti
|
|
|
|
|
if ( ! RemoveCurveSmallParts( pCrv, m_dLinTol))
|
|
|
|
|
return false ;
|
|
|
|
|
|
|
|
|
|
bool bClosed = pCrv->IsClosed() ;
|
|
|
|
|
|
|
|
|
|
INTVECTOR vFlag ;
|
|
|
|
|
vFlag.push_back( OffsetCurve3d::AngType::ANG_STR) ;
|
|
|
|
|
const ICurve* pSubCrv = pCrv->GetFirstCurve() ;
|
|
|
|
|
for ( int i = 1 ; i < pCrv->GetCurveCount() ; ++i) {
|
|
|
|
|
pSubCrv = pCrv->GetNextCurve() ;
|
|
|
|
|
Vector3d vtDirCurr ; pSubCrv->GetStartDir( vtDirCurr) ;
|
|
|
|
|
int nFlag = vtDirCurr * vOffDir[i] > 0 ? OffsetCurve3d::AngType::ANG_SMOOTH_CONC : OffsetCurve3d::AngType::ANG_STR ;
|
|
|
|
|
vFlag.push_back( nFlag) ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
double dRadCorr ;
|
|
|
|
|
Point3d ptPrev ; pCrv->GetStartPoint( ptPrev) ;
|
|
|
|
|
ptPrev += vOffDir[0] * dOffDist ;
|
|
|
|
|
Vector3d vtNormPrev ;
|
|
|
|
|
Vector3d vtCorrPrev ;
|
|
|
|
|
Vector3d vtTangPrev ;
|
|
|
|
|
Vector3d vtDirPrev ; pCrv->GetStartDir( vtDirPrev) ;
|
|
|
|
|
const ICurve* pCrvPrev = pCrv->GetFirstCurve() ;
|
|
|
|
|
const ICurve* pCrvCurr ;
|
|
|
|
|
vector<PtrOwner<ICurve>> vOffsetCrvs ;
|
|
|
|
|
for ( int i = 1 ; i < pCrv->GetCurveCount() ; ++i) {
|
|
|
|
|
pCrvCurr = pCrv->GetNextCurve() ;
|
|
|
|
|
Vector3d vtOffDir = vOffDir[i] ;
|
|
|
|
|
Vector3d vtDirCurr ; pCrvCurr->GetStartDir( vtDirCurr) ;
|
|
|
|
|
pCrvPrev->GetStartDir( vtDirPrev) ;
|
|
|
|
|
Vector3d vtTang = Media( vtDirCurr, vtDirPrev) ;
|
|
|
|
|
vtTang.Normalize() ;
|
|
|
|
|
Vector3d vtNorm = vtOffDir ;
|
|
|
|
|
vtNorm.Rotate( vtTang, -90) ;
|
|
|
|
|
//Vector3d vtCorr = vtTang ^ vtNorm ; vtCorr.Normalize() ;
|
|
|
|
|
// devo invertire vtCorr??? se sì, quando?/////////////////////////////////////////
|
|
|
|
|
Vector3d vtCorr = vtOffDir ;
|
|
|
|
|
double dCorrK = 1 ;
|
|
|
|
|
if ( vFlag[i] == OffsetCurve3d::AngType::ANG_CONC) {
|
|
|
|
|
double dHalfAlfa = acos( vtTang * vtTangPrev) ;
|
|
|
|
|
dCorrK = 1 / sin( 90 - dHalfAlfa) ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
Point3d ptP ; pCrvCurr->GetStartPoint( ptP) ;
|
|
|
|
|
dRadCorr = dOffDist ;
|
|
|
|
|
ptP = ptP + dRadCorr * dCorrK * vtCorr ;
|
|
|
|
|
// se secondo punto di angolo esterno di fianco, inserisco movimenti intermedi
|
|
|
|
|
if ( vFlag[i] == OffsetCurve3d::AngType::ANG_CVEX && vFlag[i-1] == OffsetCurve3d::AngType::ANG_CVEX) {
|
|
|
|
|
double dAlfa = acos( vtTang * vtTangPrev) ;
|
|
|
|
|
double dDelta = dOffDist * tan( dAlfa / 4) ;
|
|
|
|
|
Point3d ptAdd1 = ptPrev + dDelta * vtTangPrev ;
|
|
|
|
|
ICurveLine* pCL1 = CreateBasicCurveLine() ;
|
|
|
|
|
pCL1->Set( ptPrev, ptAdd1) ;
|
|
|
|
|
vOffsetCrvs.emplace_back( pCL1) ;
|
|
|
|
|
Point3d ptAdd2 = ptP - dDelta * vtTang ;
|
|
|
|
|
ICurveLine* pCL2 = CreateBasicCurveLine() ;
|
|
|
|
|
pCL2->Set( ptAdd1, ptAdd2) ;
|
|
|
|
|
vOffsetCrvs.emplace_back( pCL2) ;
|
|
|
|
|
ptPrev = ptAdd2 ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//// se punto di angolo interno di fianco, elimino eventuali movimenti precedenti invertiti
|
|
|
|
|
//if ( vFlag[i] == OffsetCurve3d::AngType::ANG_CVEX == 3) {
|
|
|
|
|
// local nLastId = EgtGetLastInGroup( nClPathId)
|
|
|
|
|
// while nLastId do
|
|
|
|
|
// local vtMlast = ptP - EgtEP( nLastId, GDB_ID.ROOT) ; vtMlast:normalize()
|
|
|
|
|
// if vtMlast * vtGpre < 0.5 then
|
|
|
|
|
// ptPpre = EgtSP( nLastId, GDB_ID.ROOT)
|
|
|
|
|
// EgtErase( nLastId)
|
|
|
|
|
// else
|
|
|
|
|
// break
|
|
|
|
|
// end
|
|
|
|
|
// nLastId = EgtGetLastInGroup( nClPathId)
|
|
|
|
|
// end
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
//// se appena dopo angolo interno di fianco, verifico se da aggiungere
|
|
|
|
|
//bool bToAdd = true
|
|
|
|
|
//if ( nFlpre == 3 and abs( dSideAng) > GEO.EPS_ANG_SMALL) {
|
|
|
|
|
// local vtMove = ptP - ptPpre ; vtMove:normalize()
|
|
|
|
|
// if vtMove * vtTang < 0.5 then
|
|
|
|
|
// bToAdd = false
|
|
|
|
|
// end
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
// aggiungo tratto
|
|
|
|
|
ICurveLine* pCL = CreateBasicCurveLine() ;
|
|
|
|
|
pCL->Set( ptPrev, ptP) ;
|
|
|
|
|
vOffsetCrvs.emplace_back( pCL) ;
|
|
|
|
|
// aggiorno punto precedente
|
|
|
|
|
ptPrev = ptP ;
|
|
|
|
|
vtNormPrev = vtNorm ;
|
|
|
|
|
vtCorrPrev = vtCorr ;
|
|
|
|
|
vtTangPrev = vtTang ;
|
|
|
|
|
vtDirPrev = vtDirCurr ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//// qui faccio la correzione per gli angoli interni
|
|
|
|
|
//AdjustConcavePartsInPath( pCrv, vOffsetCrvs, vFlag, dOffDist) ;
|
|
|
|
|
|
|
|
|
|
#if SAVECVRORIG || SAVEOFFDIR || SAVECYL
|
|
|
|
|
SaveGeoObj( vGeo, vCol, "C:\\Temp\\curve offset 3d\\crvoffset.nge") ;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
PtrOwner<ICurveComposite> pCrvOffset( CreateBasicCurveComposite()) ;
|
|
|
|
|
for ( int i = 0 ; i < ssize( vOffsetCrvs) ; ++i) {
|
|
|
|
|
if ( ! pCrvOffset->AddCurve( Release( vOffsetCrvs[i])))
|
|
|
|
|
return false ;
|
|
|
|
|
}
|
|
|
|
|
m_CrvLst.push_back( Release( pCrvOffset)) ;
|
|
|
|
|
|
|
|
|
|
return true ;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// raccordi
|
|
|
|
|
|
|
|
|
|
// angoli interni
|
|
|
|
|
|
|
|
|
|
// angoli esterni
|
|
|
|
|
|
|
|
|
|
// auto intersezioni
|
|
|
|
|
|
|
|
|
|
//// sesto passo : se curva aperta, elimino i tratti che stanno nella circonferenza di offset dei punti estremi
|
|
|
|
|
|
|
|
|
|
//// ottavo passo : concateno i percorsi risultanti (senza cambiare verso)
|
|
|
|
|
|
|
|
|
|
//// nono passo : se con smusso o estensione, sostituisco i fillet con questi
|
|
|
|
|
|
|
|
|
|
//// ordino le curve in ordine decrescente di lunghezza
|
|
|
|
|
//if ( m_CrvLst.size() > 1) {
|
|
|
|
|
// for ( auto pCrv : m_CrvLst) {
|
|
|
|
|
// double dLen ;
|
|
|
|
|
// if ( pCrv->GetLength( dLen))
|
|
|
|
|
// pCrv->SetTempProp( int( 1000 * dLen)) ;
|
|
|
|
|
// else
|
|
|
|
|
// pCrv->SetTempProp( 0) ;
|
|
|
|
|
// }
|
|
|
|
|
// m_CrvLst.sort( []( const ICurve* pA, const ICurve* pB) { return ( pA->GetTempProp() > pB->GetTempProp()) ; }) ;
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
//// se originale era chiusa, verifico le risultanti e se necessario cerco di chiuderle
|
|
|
|
|
//if ( bClosed) {
|
|
|
|
|
// for ( auto pCrv : m_CrvLst) {
|
|
|
|
|
// CurveComposite* pCrvCo = GetBasicCurveComposite( pCrv) ;
|
|
|
|
|
// if ( pCrvCo != nullptr)
|
|
|
|
|
// pCrvCo->Close() ;
|
|
|
|
|
// }
|
|
|
|
|
//}
|
|
|
|
|
|
|
|
|
|
//return true ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
ICurve*
|
|
|
|
|
OffsetCurve3d::GetCurve( void)
|
|
|
|
|
{
|
|
|
|
|
return GetLongerCurve() ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
ICurve*
|
|
|
|
|
OffsetCurve3d::GetLongerCurve( void)
|
|
|
|
|
{
|
|
|
|
|
if ( m_CrvLst.empty())
|
|
|
|
|
return nullptr ;
|
|
|
|
|
// le curve sono ordinate in senso decrescente di lunghezza
|
|
|
|
|
ICurve* pCrv = m_CrvLst.front() ;
|
|
|
|
|
m_CrvLst.pop_front() ;
|
|
|
|
|
return pCrv ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
ICurve*
|
|
|
|
|
OffsetCurve3d::GetShorterCurve( void)
|
|
|
|
|
{
|
|
|
|
|
if ( m_CrvLst.empty())
|
|
|
|
|
return nullptr ;
|
|
|
|
|
// le curve sono ordinate in senso decrescente di lunghezza
|
|
|
|
|
ICurve* pCrv = m_CrvLst.back() ;
|
|
|
|
|
m_CrvLst.pop_back() ;
|
|
|
|
|
return pCrv ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
struct Cyl {
|
|
|
|
|
Cyl( void): frCyl( GLOB_FRM), dH( 0.), dRad( 0.) {;} ;
|
|
|
|
|
Cyl( const Frame3d& _frCyl, double _dH, double _dRad, double _dLinTol) :
|
|
|
|
|
frCyl( _frCyl), dH( _dH), dRad( _dRad) { ;}
|
|
|
|
|
Cyl( const Point3d& _ptBase, const Vector3d& vtZ, double _dH, double _dRad, double _dLinTol) :
|
|
|
|
|
dH( _dH), dRad( _dRad){
|
|
|
|
|
frCyl.Set( _ptBase, vtZ); }
|
|
|
|
|
public :
|
|
|
|
|
Frame3d frCyl ;
|
|
|
|
|
public:
|
|
|
|
|
double dH ;
|
|
|
|
|
double dRad ;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
typedef vector<Cyl> CYLVECT ;
|
|
|
|
|
|
|
|
|
|
//----------------------------------------------------------------------------
|
|
|
|
|
bool
|
|
|
|
|
IsPointInsideCylinder( const Point3d& ptTest, const Cyl& offCyl)
|
|
|
|
|
{
|
|
|
|
|
Point3d ptTestLoc = ptTest ; ptTestLoc.ToLoc( offCyl.frCyl) ;
|
|
|
|
|
if ( ptTestLoc.z > offCyl.dH || ptTestLoc.z < 0)
|
|
|
|
|
return false ;
|
|
|
|
|
double dDist = ptTestLoc.x * ptTestLoc.x + ptTestLoc.y * ptTestLoc.y ;
|
|
|
|
|
double dRadSq = offCyl.dRad * offCyl.dRad ;
|
|
|
|
|
if ( dDist > dRadSq)
|
|
|
|
|
return false ;
|
|
|
|
|
return true ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
bool
|
|
|
|
|
AdjustConcavePartsInPath( const ICurveComposite* pCrv, ICURVEPOVECTOR& vOffsetCrvs, const INTVECTOR& vFlag, double dRad)
|
|
|
|
|
{
|
|
|
|
|
const double dLinTol = 5 * EPS_SMALL ;
|
|
|
|
|
INTVECTOR vErase ;
|
|
|
|
|
for ( int i = 0 ; i < ssize( vOffsetCrvs) ; ++i) {
|
|
|
|
|
int nFlag = vFlag[i] ;
|
|
|
|
|
if ( nFlag == OffsetCurve3d::AngType::ANG_SMOOTH_CONC) {
|
|
|
|
|
// scorro i prossimi finchè trovo la fine della zona concava
|
|
|
|
|
INTVECTOR vLines ;
|
|
|
|
|
while ( nFlag == OffsetCurve3d::AngType::ANG_SMOOTH_CONC) {
|
|
|
|
|
vLines.push_back( i) ;
|
|
|
|
|
++i ;
|
|
|
|
|
nFlag = vFlag[i] ;
|
|
|
|
|
}
|
|
|
|
|
CYLVECT vCyl ;
|
|
|
|
|
// creo un cilindro della dimensione del raggio
|
|
|
|
|
for ( int j = 0 ; j < ssize( vLines) ; ++j) {
|
|
|
|
|
const ICurve* pSubCrv = pCrv->GetCurve( vLines[j]) ;
|
|
|
|
|
Point3d ptStart, ptEnd ;
|
|
|
|
|
pSubCrv->GetStartPoint( ptStart) ;
|
|
|
|
|
pSubCrv->GetEndPoint( ptEnd) ;
|
|
|
|
|
Vector3d vtHeight = ptEnd - ptStart ; vtHeight.Normalize() ;
|
|
|
|
|
double dHeight = vtHeight.Len() ;
|
|
|
|
|
vCyl.emplace_back( ptStart, vtHeight, dHeight, dRad, dLinTol) ;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// controllo l'end di ogni linea per verificare se sta nel cilindro definito da uno degli altri tratti
|
|
|
|
|
// controllo tutto i punti
|
|
|
|
|
bool bErasedSomePart = false ;
|
|
|
|
|
bool bErasedPrev = false ;
|
|
|
|
|
INTVECTOR vInters ;
|
|
|
|
|
for ( int j = 0 ; j < ssize( vLines) ; ++j) {
|
|
|
|
|
Point3d ptStart, ptEnd ;
|
|
|
|
|
const ICurve* pSubCrv = pCrv->GetCurve( vLines[j]) ;
|
|
|
|
|
if ( pSubCrv == nullptr)
|
|
|
|
|
return false ;
|
|
|
|
|
pSubCrv->GetEndPoint( ptEnd) ;
|
|
|
|
|
pSubCrv->GetStartPoint( ptStart) ;
|
|
|
|
|
// se stanno in uno dei cilindri degli altri tratti della zona concava
|
|
|
|
|
for ( int k = 0 ; k < ssize( vLines) ; ++k) {
|
|
|
|
|
if ( j == k)
|
|
|
|
|
continue ;
|
|
|
|
|
bool bToErase = IsPointInsideCylinder( ptEnd, vCyl[k]) ;
|
|
|
|
|
if ( bErasedPrev && ! bToErase)
|
|
|
|
|
bToErase = bToErase || IsPointInsideCylinder( ptStart, vCyl[k]) ;
|
|
|
|
|
if ( bToErase) {
|
|
|
|
|
bErasedSomePart = true ;
|
|
|
|
|
bErasedPrev = true ;
|
|
|
|
|
vInters.push_back( vLines[j]) ;
|
|
|
|
|
if ( j < ssize( vLines) - 1)
|
|
|
|
|
vInters.push_back( vLines[j+1]) ;
|
|
|
|
|
++j ;
|
|
|
|
|
break ;
|
|
|
|
|
}
|
|
|
|
|
else
|
|
|
|
|
bErasedPrev = false ;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ( bErasedSomePart) {
|
|
|
|
|
// calcolo le intersezioni effettive del primo e ultimo tratto cancellati con i cilindri che li hanno cancellati
|
|
|
|
|
// controllo che effettivamente tutti i tratti cancellati siano consecutivi
|
|
|
|
|
for ( int j = 1 ; j < ssize( vInters) ; ++j) {
|
|
|
|
|
if ( vInters[j] != vInters[j-1] + 1)
|
|
|
|
|
return false ;
|
|
|
|
|
}
|
|
|
|
|
for ( int j = 0 ; j < ssize( vInters) ; ++j) {
|
|
|
|
|
// cancello i tratti intermedi
|
|
|
|
|
if ( j > 0 && j < ssize( vInters) - 1) {
|
|
|
|
|
vErase.push_back( vInters[j]) ;
|
|
|
|
|
continue ;
|
|
|
|
|
}
|
|
|
|
|
// per il primo e ultimo controllo le intersezioni con tutti i cilindri
|
|
|
|
|
ICurve* pCL = vOffsetCrvs[vInters[j]] ;
|
|
|
|
|
Point3d ptStart ; pCL->GetStartPoint( ptStart) ;
|
|
|
|
|
Vector3d vtStart ; pCL->GetStartDir( vtStart) ;
|
|
|
|
|
double dLen ; pCL->GetLength( dLen) ;
|
|
|
|
|
double dUTrim = ( j == 0 ? INFINITO : 0) ;
|
|
|
|
|
Point3d ptTrim = P_INVALID ;
|
|
|
|
|
for ( int k = 0 ; k < ssize( vCyl) ; ++k) {
|
|
|
|
|
if ( vInters[j] == k)
|
|
|
|
|
continue ;
|
|
|
|
|
Point3d ptInt1 = P_INVALID, ptInt2 = P_INVALID ;
|
|
|
|
|
double dU1, dU2 ;
|
|
|
|
|
Vector3d vtN1, vtN2 ;
|
|
|
|
|
if ( IntersLineCyl( ptStart, vtStart * dLen, vCyl[k].frCyl, vCyl[k].dH, vCyl[k].dRad, false, false, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, true)) {
|
|
|
|
|
bool bUpdate = ( j == 0 ? dU1 < dUTrim : dU1 > dUTrim) ;
|
|
|
|
|
bUpdate = bUpdate && ptInt1.IsValid() && dU1 > 0 && dU1 < 1 ;
|
|
|
|
|
bUpdate = bUpdate && vtN1 * vtStart < 0 ;
|
|
|
|
|
if ( bUpdate) {
|
|
|
|
|
dUTrim = dU1 ;
|
|
|
|
|
ptTrim = ptInt1 ;
|
|
|
|
|
}
|
|
|
|
|
bUpdate = ( j == 0 ? dU2 < dUTrim : dU2 > dUTrim) ;
|
|
|
|
|
bUpdate = bUpdate && ptInt2.IsValid() && dU2 > 0 && dU2 < 1 ;
|
|
|
|
|
bUpdate = bUpdate && vtN2 * vtStart > 0 ;
|
|
|
|
|
if ( bUpdate) {
|
|
|
|
|
dUTrim = dU2 ;
|
|
|
|
|
ptTrim = ptInt2 ;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if ( ptTrim.IsValid()) {
|
|
|
|
|
if ( j == 0) {
|
|
|
|
|
pCL->ModifyEnd( ptTrim) ;
|
|
|
|
|
double dNewLen ; pCL->GetLength( dNewLen) ;
|
|
|
|
|
if ( dNewLen < 0.1 && vInters[0] != 0) { // se fosse il primo allora potrei modificare il successivo
|
|
|
|
|
int nPrev = vInters[0] - 1 ;
|
|
|
|
|
vErase.push_back( vInters[0]) ;
|
|
|
|
|
vInters[0] = nPrev ;
|
|
|
|
|
ICurve* pCLPrev = vOffsetCrvs[nPrev] ;
|
|
|
|
|
pCLPrev->ModifyEnd( ptTrim) ;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
else {
|
|
|
|
|
pCL->ModifyStart( ptTrim) ;
|
|
|
|
|
double dNewLen ; pCL->GetLength( dNewLen) ;
|
|
|
|
|
if ( dNewLen < 0.1 && vInters[j] != ssize( vOffsetCrvs) - 1) { // se fosse l'ultima curva allora potrei modificare la precedente
|
|
|
|
|
int nNext = vInters[j] + 1 ;
|
|
|
|
|
vErase.push_back( vInters[j]) ;
|
|
|
|
|
vInters[j] = nNext ;
|
|
|
|
|
ICurve* pCLNext = vOffsetCrvs[nNext] ;
|
|
|
|
|
pCLNext->ModifyStart( ptTrim) ;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
i = vLines.back() ;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// scorro tutto il vettore delle linee di offset e unisco aggiungendo una linea dove ne ho cancellate
|
|
|
|
|
for ( int i = 0 ; i < ssize( vOffsetCrvs) - 1 ; ++i) {
|
|
|
|
|
Point3d ptEndCurr, ptStartNext ;
|
|
|
|
|
vOffsetCrvs[i]->GetEndPoint( ptEndCurr) ;
|
|
|
|
|
vOffsetCrvs[i+1]->GetStartPoint( ptStartNext) ;
|
|
|
|
|
if ( ! AreSamePointApprox( ptEndCurr, ptStartNext)) {
|
|
|
|
|
ICurveLine* pCL = CreateBasicCurveLine() ;
|
|
|
|
|
pCL->Set( ptEndCurr, ptStartNext) ;
|
|
|
|
|
PtrOwner<ICurve> pCrvL( pCL) ;
|
|
|
|
|
vOffsetCrvs.insert( vOffsetCrvs.begin() + i + 1, std::move(pCrvL)) ;
|
|
|
|
|
++i ;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true ;
|
|
|
|
|
}
|