EgtGeomKernel :

- in CalcPocketing migliorati i collegamenti per lavorazioni Conformal e migliorato l'orientamento delle curve per lavorazioni Spiral.
This commit is contained in:
Riccardo Elitropi
2025-07-11 15:38:55 +02:00
parent 2fe22a62c2
commit 3b5c34cb05
+203 -90
View File
@@ -398,6 +398,16 @@ AssignFeedZigZagOneWay( ICurveComposite* pCompo, const bool bIsLink, const ICURV
return true ;
}
//----------------------------------------------------------------------------
static bool
SwapSideBySecondTempParam( ICurveComposite* pCompo)
{
if ( pCompo == nullptr || ! pCompo->IsValid())
return false ;
pCompo->SetTempParam( int( pCompo->GetTempParam( 1)) == MDS_LEFT ? MDS_RIGHT : MDS_LEFT, 1) ;
return true ;
}
//----------------------------------------------------------------------------
static bool
CheckSimpleOverlap( const ICurve* pCrv, const ICurveComposite* pCrvOri, int& nStat, double dToll)
@@ -462,7 +472,7 @@ AssignFeedForOpenEdge( ICurveComposite* pCrv, const ISurfFlatRegion* pSfrOpenEdg
pNewCrv->SetTempProp( pCrv->GetTempProp( 0), 0) ;
pNewCrv->SetTempProp( pCrv->GetTempProp( 1), 1) ;
pNewCrv->SetTempParam( pCrv->GetTempParam( 0), 0) ;
pNewCrv->SetTempParam( pCrv->GetTempParam( 0), 0) ;
pNewCrv->SetTempParam( pCrv->GetTempParam( 1), 1) ;
double dThick ; pCrv->GetThickness( dThick) ;
pNewCrv->SetThickness( dThick) ;
Vector3d vtExtr ; pCrv->GetExtrusion( vtExtr) ;
@@ -4784,7 +4794,7 @@ CalcSpecialBoundedSmoothedLink( const Point3d& ptStart, const Vector3d& vtStart,
pZigZagLink->AddLine( ptNew) ;
}
// questa composita contiene al massimo 5 curve e, in generale, quella una curva molto più lunga
// questa composita contiene al massimo 5 curve e, in generale, una curva molto più lunga
// delle altre ( quella che collega le due estensioni calcolate). Spezzo la composita ottenuta in curve
// la cui lunghezza massima è circa il raggio utensile
PolyLine PL ;
@@ -4965,12 +4975,14 @@ CutCurveToConnect( ICurveComposite* pCrvS, ICurveComposite* pCrvE, const ICRVCOM
double dLenS ; pCrvS->GetLength( dLenS) ;
double dLenE ; pCrvE->GetLength( dLenE) ;
// se ho una curva di primo Offset allora non devo accorciarla ( sia per bordi esterni che per isole)
// azzero i parametri per curve di primo Offset
for ( int i = 0 ; i < int( vFirstOffset.size()) ; ++ i) {
if ( vFirstOffset[i]->IsPointOn( ptSS) && vFirstOffset[i]->IsPointOn( ptSE))
dLenPercS = 0. ;
if ( vFirstOffset[i]->IsPointOn( ptES) && vFirstOffset[i]->IsPointOn( ptEE))
dLenPercE = 0. ;
#if 0
if ( vFirstOffset[i]->IsPointOn( ptES) && vFirstOffset[i]->IsPointOn( ptEE))
dLenPercE = 0. ;
#endif
}
#if 0 // nel caso volessi estendere anche prima del punto finale
double dLStepS = ( dLenPercS < EPS_SMALL ? 0. : PockParams.dRad) ;
@@ -5081,6 +5093,9 @@ GetUnclearedRegionAndSetFeed( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR&
// recupero le proprietà temporanee
int nProp0 = vOffs[i]->GetTempProp( 0) ;
int nProp1 = vOffs[i]->GetTempProp( 1) ;
// il primo TempParam viene settato in proporzione alla Feed
// il secondo TempParam contiene l'nSide della curva
double dTempPar1 = vOffs[i]->GetTempParam( 1) ;
// Feed
bool bFirstOffs = false ;
@@ -5104,6 +5119,7 @@ GetUnclearedRegionAndSetFeed( ICRVCOMPOPOVECTOR& vFirstOffs, ICRVCOMPOPOVECTOR&
}
vOffs[i]->SetTempProp( nProp0, 0) ;
vOffs[i]->SetTempProp( nProp1, 1) ;
vOffs[i]->SetTempParam( dTempPar1, 1) ;
// ================= LINK ================================
int nLink_Ind = ( bFollowOrder ? i + 1 : i) ;
@@ -5150,12 +5166,13 @@ ChooseCurveForRemovingUnclearedRegion( const ICRVCOMPOPOVECTOR& vOffs, const ICR
const Point3d& ptToGo, const PocketParams& PockParams,
int& nInd, Point3d& ptCloser, bool& bFirstOffs)
{
/*
E' richiesto che le curve di Offset presentino le seguenti TempProps :
- TempProp0 -> Offset progressivo ricavato ( 0, 1, 2, ... nMaxIter) [per CONFORMAL]
- TempProp1 -> parte esterna della curva ( MDS_LEFT o MDS_LEFT) [per CONFORMAL]
[per SPIRAL le proprietà sono ricavate automaticamente]
*/
// E' richiesto che le curve di Offset presentino le seguenti proprietà :
// - CONFORMAL
// * TempProp0 -> Offset progressivo ricavato ( 0, 1, 2, ... nMaxIter)
// * TempProp1 -> parte esterna della curva ( MDS_LEFT o MDS_RIGHT)
// - SPIRAL
// * vOffsFirstCurve -> per capire se l'Offset corrente è di primo Offset o meno
// * TempParam1 -> parte esterna della curva ( MDS_LEFT o MDS_RIGHT)
// controllo dei parametri
nInd = -1 ;
@@ -5177,10 +5194,8 @@ ChooseCurveForRemovingUnclearedRegion( const ICRVCOMPOPOVECTOR& vOffs, const ICR
vOffsPtMinDist[i].nInd = i ;
// nel caso di Conformal, escludo le curve di primo Offset dalla ricerca
if ( PockParams.nType == POCKET_CONFORMAL_ZIGZAG || PockParams.nType == POCKET_CONFORMAL_ONEWAY) {
bool bSkip = false ;
for ( int j = 0 ; j < int( vOffsFirstCurve.size()) && ! bSkip ; ++ j)
bSkip = ( vOffs[i]->GetTempProp( 0) == 0) ; // prima iterazione
if ( bSkip) {
// prima iterazione
if ( vOffs[i]->GetTempProp( 0) == 0) {
vOffsPtMinDist[i].bFirstOffs = true ;
continue ;
}
@@ -5190,26 +5205,16 @@ ChooseCurveForRemovingUnclearedRegion( const ICRVCOMPOPOVECTOR& vOffs, const ICR
// in questo modo riesco a creare le curve a ricciolo
int nSide ;
DistPointCurve DistPtCrv( ptToGo, *vOffs[i]) ;
bool bFirstBorderIsland = false ;
if ( DistPtCrv.GetSideAtMinDistPoint( EPS_SMALL, Z_AX, nSide)) {
// nel caso Spiral
if ( PockParams.nType == POCKET_SPIRALIN || PockParams.nType == POCKET_SPIRALOUT) {
// InVsOut
vOffsPtMinDist[i].bInVsOut = ( ( ! PockParams.bInvert && nSide == MDS_LEFT) ||
( PockParams.bInvert && nSide == MDS_RIGHT)) ;
vOffsPtMinDist[i].bInVsOut = ( int( vOffs[i]->GetTempParam( 1) != nSide)) ;
// controllo se la curva in questione è di primo Offset
Point3d ptCheck ; vOffs[i]->GetStartPoint( ptCheck) ;
for ( int j = 0 ; j < int( vOffsFirstCurve.size()) ; ++ j) {
if ( vOffsFirstCurve[j]->IsPointOn( ptCheck, 100 * EPS_SMALL)) {
vOffsPtMinDist[i].bFirstOffs = true ;
// controllo se Isola o di bordo
double dArea = 0. ;
vOffs[i]->GetAreaXY( dArea) ;
bFirstBorderIsland = ( ( ! PockParams.bInvert && dArea < 0.) ||
( PockParams.bInvert && dArea > 0.)) ;
// se isola di primo Offset, InVsOut va invertito
if ( bFirstBorderIsland)
vOffsPtMinDist[i].bInVsOut = ( ! vOffsPtMinDist[i].bInVsOut) ;
break ;
}
}
@@ -5228,7 +5233,7 @@ ChooseCurveForRemovingUnclearedRegion( const ICRVCOMPOPOVECTOR& vOffs, const ICR
PockParams.dSideStep + PockParams.dSideStep ;
}
// se curva di bordo esterno, aggiungo un'altra penalità ( euristica)
if ( vOffsPtMinDist[i].bFirstOffs && ! bFirstBorderIsland)
if ( vOffsPtMinDist[i].bFirstOffs)
vOffsPtMinDist[i].dSqDist *= 2. ;
}
}
@@ -5252,7 +5257,7 @@ RemoveUnclearedRegions( const ISurfFlatRegion* pSfrUncleared, ICRVCOMPOPOVECTOR&
/*
E' richiesto che le curve di Offset presentino le seguenti TempProps :
- TempProp0 -> Offset progressivo ricavato ( 0, 1, 2, ... nMaxIter) [per CONFORMAL]
- TempProp1 -> parte esterna della curva ( MDS_LEFT o MDS_LEFT) [per CONFORMAL]
- TempProp1 -> parte esterna della curva ( MDS_LEFT o MDS_RIGHT) [per CONFORMAL]
[per SPIRAL le proprietà sono ricavate automaticamente]
*/
@@ -5267,12 +5272,10 @@ RemoveUnclearedRegions( const ISurfFlatRegion* pSfrUncleared, ICRVCOMPOPOVECTOR&
for ( int nC = 0 ; nC < pSfrUncleared->GetChunkCount() ; ++ nC) {
// recupero il centroide del Chunk da rimuovere
Point3d ptCentroid ; pSfrUncleared->GetChunkCentroid( nC, ptCentroid) ;
/*
Tra tutte le curve di Offset escludo le curve che :
- Sono di primo Offset
- Non contengono il centroide ( condizione già verificata per quelle di primo Offset)
... cerco la più vicina tra le rimanenti
*/
// Tra tutte le curve di Offset escludo le curve che :
// - Sono di primo Offset
// - Non contengono il centroide ( condizione già verificata per quelle di primo Offset)
// ... cerco la più vicina tra le rimanenti
// recupero la curva migliore
int nInd = -1 ;
Point3d ptCloser ;
@@ -5570,6 +5573,9 @@ CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, con
vLinks.clear() ;
vLinks.resize( int( vOffs.size())) ;
// NB. Dato che le curve di Offset sono invertite a seconda di dove si trova il materiale,
// Utilizzo il secondo TempParam per evere l'nSide
// scorro tutte le curva di Offset
for ( int i = 0 ; i < int( vOffs.size()) - 1 ; ++ i) {
@@ -5577,6 +5583,7 @@ CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, con
Point3d ptS ;
if ( ! vOffs[i]->GetStartPoint( ptS))
return false ;
// tra le curve successive cerco la curva interna e più vicina ad essa
int nNextInd = -1 ; // indice della curva successiva
double dMinDist = INFINITO ; // distanza tra questa curva e la successiva
@@ -5588,8 +5595,8 @@ CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, con
// se interna
if ( IntCC.GetCurveClassification( 1, EPS_SMALL, ccClass) &&
int( ccClass.size()) == 1 &&
( ( ! PockParams.bInvert && ccClass[0].nClass == CRVC_IN) ||
( PockParams.bInvert && ccClass[0].nClass == CRVC_OUT))) {
( ( ccClass[0].nClass == CRVC_IN && int( vOffs[i]->GetTempParam( 1)) == MDS_RIGHT) ||
( ccClass[0].nClass == CRVC_OUT && int( vOffs[i]->GetTempParam( 1)) == MDS_LEFT))) {
// calcolo la distanza minima tra essa
int nFlag ;
double dPar = 0. ;
@@ -5649,13 +5656,14 @@ CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, con
// scambio la curva i+1 esima con la j-esima ( se non sono già in ordine)
if ( nNextInd != i + 1)
swap( vOffs[nNextInd], vOffs[i+1]) ;
// cambio il suo punto iniziale nel punto più vicino tovato
double dUS ;
if ( ! vOffs[i+1]->GetParamAtPoint( ptStartNext, dUS, EPS_SMALL))
return false ;
vOffs[i+1]->ChangeStartPoint( dUS) ;
// accorcio la curva per raccordarmi in tangenza con la successiva
// se ho più di una curva di Offset
if ( int( vOffs.size()) > 1) {
// clono le curve i ed i+1 esime ( nel caso non riuscissi ad accorciarle o raccordarle )
PtrOwner<ICurveComposite> pCrv_i( vOffs[i]->Clone()) ;
@@ -5666,15 +5674,14 @@ CreateSpiralPocketingPath( ICRVCOMPOPOVECTOR& vOffs, ICURVEPOVECTOR& vLinks, con
PtrOwner<ICurveComposite> pCrvLink( CreateCurveComposite()) ;
if ( IsNull( pCrvLink))
return false ;
// NB. Le curve di Offset da tagliare non devono essere quelle di primo Offset
double dLenPercS = ( i == 0 ? 0. : 10 * EPS_SMALL) ;
double dLenPercE = ( bMinDistAtSmooth ? 0. : 10 * EPS_SMALL) ;
if ( ! CutCurveToConnect( vOffs[i], vOffs[i+1], vOffsFirstCurve, PockParams, dLenPercS, dLenPercE, pCrvLink) ||
! pCrvLink->IsValid()) {
// se non sono riuscito, cerco una strada più semplice ripristinando le curve
pCrvLink->Clear() ;
vOffs[i].Set( pCrv_i) ; // chiuso
vOffs[i+1].Set( pCrv_ii) ; // chiuso
vOffs[i].Set( pCrv_i) ;
vOffs[i+1].Set( pCrv_ii) ;
// recupero i vettori tangenti iniziali ( le curve sono chiuse )
Vector3d vtS, vtE ;
if ( ! vOffs[i]->GetStartDir( vtS) || ! vOffs[i+1]->GetStartDir( vtE))
@@ -5823,6 +5830,55 @@ IsCompoMadeBy2DifferentHomogeneousParts( const ICurveComposite* pCompo, const Po
return true ;
}
//----------------------------------------------------------------------------
static int
CalcInversionForSpiralOffset( const ISurfFlatRegion* pSfrChunk)
{
// controllo validità della regione
if ( pSfrChunk == nullptr || ! pSfrChunk->IsValid())
return -1 ;
// Caso 0 : Non esistono isole
// Caso 1 : Loop Esterno Chiuso e, se esiste, Isola Chiusa
// Caso 2 : Loop Esterno Chiuso e, se esiste, Isola Aperta
// Caso 3 : Loop Esterno Aperto e, se esiste, Isola Chiusa
// Caso 4 : Loop Esterno Aperto e, se esiste, Isola Aperta
// se non esistono isole, allora Caso 0
if ( pSfrChunk->GetLoopCount( 0) == 1)
return 0 ;
// Il Loop esterno è considerato chiuso <=> esiste almeno una curva chiusa
bool bExtClosed = false ;
for ( int nU = 0 ; nU < pSfrChunk->GetLoopCurveCount( 0, 0) && ! bExtClosed ; ++ nU) {
int nTempProp = TEMP_PROP_INVALID ;
bExtClosed = ( pSfrChunk->GetCurveTempProp( 0, 0, nU, nTempProp) &&
nTempProp == TEMP_PROP_CLOSE_EDGE) ;
}
// Le isole vengono classificate come tutte chiuse <=> esiste almeno un isola chiusa
bool bIntClosed = false ;
for ( int nLoop = 1 ; nLoop < pSfrChunk->GetLoopCount( 0) && ! bIntClosed ; ++ nLoop) {
for ( int nU = 0 ; nU < pSfrChunk->GetLoopCurveCount( 0, nLoop) && ! bIntClosed ; ++ nU) {
int nTempProp = TEMP_PROP_INVALID ;
bIntClosed = ( pSfrChunk->GetCurveTempProp( 0, nLoop, nU, nTempProp) &&
nTempProp == TEMP_PROP_CLOSE_EDGE) ;
}
}
// restituisco il caso corrente
if ( bExtClosed && bIntClosed)
return 1 ;
if ( bExtClosed && ! bIntClosed)
return 2 ;
if ( ! bExtClosed && bIntClosed)
return 3 ;
if ( ! bExtClosed && ! bIntClosed)
return 4 ;
return -1 ;
}
//----------------------------------------------------------------------------
static bool
CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, const PocketParams& PockParams, int& nReg, Point3d& ptStart,
@@ -5837,14 +5893,19 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co
// ciclo di offset verso l'interno
const int MAX_ITER = 1000 ;
int nIter = 0 ;
ICRVCOMPOPOVECTOR vOffs ; // vettore delle curve di offset
ICRVCOMPOPOVECTOR vOffsFirstCurve ; // curve di primo offset
ICRVCOMPOPOVECTOR vOffs ; // vettore delle curve di offset
ICRVCOMPOPOVECTOR vOffsFirstCurve ; // curve di primo offset
// tengo una copia della regione corrente da svuotare
PtrOwner<ISurfFlatRegion> pSrfAct( CloneSurfFlatRegion( pSfrPock)) ;
if ( IsNull( pSrfAct) || pSrfAct->GetChunkCount() == 0)
return false ;
// ricavo il tipo di relazione descritta tra Open/Close di bordo esterno e/o isole
int nCase = CalcInversionForSpiralOffset( pSrfAct) ;
if ( nCase == -1)
return false ;
// ricavo le regioni progressive
double dOffsPrec = 0. ;
int nCrvFirstOffs = 0 ;
@@ -5862,12 +5923,15 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co
// se primo Offset
if ( nIter == 0) {
// aggiorno il nuovo valore delle regioni totali di primo Offset
int my_nReg = nReg ;
nReg = pSfrOffsVR->GetChunkCount() ; // aggiorno il nuovo valore delle regioni totali di primo Offset
nReg = pSfrOffsVR->GetChunkCount() ;
// gli Offset progressivi appartengono al Chunk nReg-esimo
pSrfAct.Set( pSfrOffsVR->CloneChunk( my_nReg)) ;
if ( IsNull( pSrfAct)) // se supero i chunk ottenuti
// se supero i chunk ottenuti
if ( IsNull( pSrfAct))
return true ;
// imposto la regione id svuotatura corrente
pSfrOffsVR.Set( pSrfAct->Clone()) ;
}
@@ -5877,24 +5941,41 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co
for ( int i = 0 ; i < nChunks ; ++ i) {
// per ogni chunk...
int nLoops = pSfrOffsVR->GetLoopCount( i) ;
for ( int j = 0 ; j < nLoops ; ++ j) {
for ( int j = 0 ; j < nLoops ; ++ j) {
// per ogni loop...
PtrOwner<ICurveComposite> pCrvCompoBorder( ConvertCurveToComposite( pSfrOffsVR->GetLoop( i, j))) ;
if ( IsNull( pCrvCompoBorder) || ! pCrvCompoBorder->IsValid())
return false ;
/*
Il materiale deve sempre trovarsi alla destra ( se bInvert -> alla sinistra) del tool
soltanto sul primo bordo; Nel caso di isole aperte o nelle passate di Offset intermedio
l'orientamente non ha importanza.
*/
if ( nIter != 0 && j > 0) // inverto l'orientamento delle curve interne ( offset delle isole trovate)
pCrvCompoBorder->Invert() ;
// controllo quali regioni di Offset possono essere sostituite
bool bInsert = true ;
if ( ! CheckIfOffsetIsNecessary( pSrfAct, pCrvCompoBorder, dOffs, dOffsPrec, nIter, PockParams, bInsert))
return false ;
if ( bInsert)
if ( bInsert) {
// imposto come secondo TempParam il Side di classificazione
pCrvCompoBorder->SetTempParam( j == 0 ? MDS_RIGHT : MDS_LEFT, 1) ;
// stabilisco l'orientamento della curva
// --- Loop esterno chiuso e isole chiuse
if ( nCase == 1 && nIter != 0 && j > 0) {
pCrvCompoBorder->Invert() ;
SwapSideBySecondTempParam( pCrvCompoBorder) ;
}
// --- Loop esterno chiuso e isole aperte
else if ( nCase == 2 && j > 0) {
pCrvCompoBorder->Invert() ;
SwapSideBySecondTempParam( pCrvCompoBorder) ;
}
// --- Loop esterno aperto e isole chiuse
else if ( nCase == 3 && j == 0) {
pCrvCompoBorder->Invert() ;
SwapSideBySecondTempParam( pCrvCompoBorder) ;
}
// --- Loop esterno aperto e isole aperte
else if ( nCase == 4 && j > 0) {
pCrvCompoBorder->Invert() ;
SwapSideBySecondTempParam( pCrvCompoBorder) ;
}
vOffs.emplace_back( Release( pCrvCompoBorder)) ;
}
if ( nIter == 0) { // salvo il bordo per i link ( non invertiti, devo sapere IN/OUT)
PtrOwner<ICurveComposite> pCrvCompoExtBorder( ConvertCurveToComposite( pSfrOffsVR->GetLoop( i, j))) ;
vOffsFirstCurve.emplace_back( Release( pCrvCompoExtBorder)) ;
@@ -5940,11 +6021,12 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co
Point3d ptNewStart ;
// Se ho come lavorazione uno SpiralIn posso poter entrare dalle isole aperte...
int nIndexSwap = 0 ; // indice del vettore di curve per identificare la curva su cui entrare
int nIndexSwap = 0 ;
if ( PockParams.nType == POCKET_SPIRALIN) {
if ( SetAdvancedPtStartForPath( vOffsFirstCurve, PockParams, pSfrPock, ptRef, ptStart,
vtMidOut, bMidOut, nIndexSwap, vCrvOrigChunkLoops))
vtMidOut, bMidOut, nIndexSwap, vCrvOrigChunkLoops)) {
vOffsFirstCurve[nIndexSwap]->GetStartPoint( ptNewStart) ;
}
else
return false ;
}
@@ -5958,8 +6040,10 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co
// se richiesta inversione
if ( PockParams.bInvert) {
for ( int i = 0 ; i < int( vOffs.size()) ; ++ i)
for ( int i = 0 ; i < int( vOffs.size()) ; ++ i) {
vOffs[i]->Invert() ;
SwapSideBySecondTempParam( vOffs[i]) ;
}
}
// smusso le curve di offset ( ad eccezione di quelle di primo Offset)
@@ -5979,10 +6063,6 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co
vOffs[0]->SetTempParam( 0., 0) ; // prima iterazione
// riordino le curve e creo i collegamenti
/*
Se richiesto parametro di smusso, tutti gli Offset ( ad eccezione di quelli generati alla
prima iterazione vengono tagliati, quindi diventano aperti
*/
ICURVEPOVECTOR vLinks( vOffs.size()) ;
if ( ! CreateSpiralPocketingPath( vOffs, vLinks, PockParams, vOffsFirstCurve))
return false ;
@@ -7067,8 +7147,8 @@ AddOneWay( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, PocketPar
//----------------------------------------------------------------------------
static bool
SmoothLinkByOffs( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, ICurveComposite* pCrvLink,
const PocketParams& PockParams, bool bFirstOffs0, bool bFirstOffs1, double dSmoothPar, double dTol)
SmoothLinkByOffs( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, ICurveComposite* pCrvLink,
const PocketParams& PockParams, bool bFirstOffs0, bool bFirstOffs1, double dSmoothPar, double dTol)
{
// controllo dei parametri
@@ -7077,53 +7157,79 @@ SmoothLinkByOffs( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, ICurve
pCrvLink == nullptr || ! pCrvLink->IsValid())
return false ;
// curva precedente
// definisco la lunghezza del segmento iniziale e finale sulle due curve di Offset
double dRefLenSeg = 2. * dSmoothPar ;
// --- Curva precedente ---
// recupero la lunghezza e il dominio del primo Offset
double dLen ;
pCrvOffs0->GetLength( dLen) ;
double dUStart, dUEnd ;
pCrvOffs0->GetDomain( dUStart, dUEnd) ;
// inizializzo la curva
PtrOwner<ICurveComposite> pCrvBef( CreateCurveComposite()) ;
if ( IsNull( pCrvBef))
return false ;
// se primo Offset di bordo o chiuso...
if ( bFirstOffs0 && pCrvOffs0->IsClosed()) {
const ICurve* pCrvFirst = pCrvOffs0->GetFirstCurve() ;
if ( pCrvFirst == nullptr || ! pCrvFirst->IsValid())
return false ;
PtrOwner<ICurve> pMyCrv( pCrvFirst->Clone()) ;
double dU = dUEnd ;
if ( dLen > dRefLenSeg - EPS_SMALL)
pCrvOffs0->GetParamAtLength( dRefLenSeg, dU) ;
PtrOwner<ICurve> pMyCrv( pCrvOffs0->CopyParamRange( dUStart, dU)) ;
if ( IsNull( pMyCrv) || ! pMyCrv->IsValid())
return false ;
pCrvBef->AddCurve( Release( pMyCrv)) ;
}
// altrimenti...
else {
const ICurve* pCrvLast = pCrvOffs0->GetLastCurve() ;
if ( pCrvLast == nullptr || ! pCrvLast->IsValid())
return false ;
PtrOwner<ICurve> pMyCrv( pCrvLast->Clone()) ;
double dU = dUStart ;
if ( dLen > dRefLenSeg)
pCrvOffs0->GetParamAtLength( dLen - dRefLenSeg, dU) ;
PtrOwner<ICurve> pMyCrv( pCrvOffs0->CopyParamRange( dU, dUEnd)) ;
if ( IsNull( pMyCrv) || ! pMyCrv->IsValid())
return false ;
pCrvBef->AddCurve( Release( pMyCrv)) ;
}
// se non valida, errore
if ( ! pCrvBef->IsValid())
return false ;
// curva successiva
// --- Curva successiva ---
// recupero la lunghezza e il dominio del primo Offset
pCrvOffs1->GetLength( dLen) ;
pCrvOffs1->GetDomain( dUStart, dUEnd) ;
// inizializzo la curva
PtrOwner<ICurveComposite> pCrvAft( CreateCurveComposite()) ;
if ( IsNull( pCrvAft))
return false ;
const ICurve* pCrvFirst = pCrvOffs1->GetFirstCurve() ;
if ( pCrvFirst == nullptr || ! pCrvFirst->IsValid())
return false ;
PtrOwner<ICurve> pMyCrv( pCrvFirst->Clone()) ;
// calcolo il parametro di taglio
double dU = dUEnd ;
if ( dLen > dRefLenSeg - EPS_SMALL)
pCrvOffs1->GetParamAtLength( dRefLenSeg, dU) ;
PtrOwner<ICurve> pMyCrv( pCrvOffs1->CopyParamRange( dUStart, dU)) ;
if ( IsNull( pMyCrv) || ! pMyCrv->IsValid())
return false ;
pCrvAft->AddCurve( Release( pMyCrv)) ;
// se non valida, errore
if ( ! pCrvAft->IsValid())
return false ;
// controllo la validità delle curve precedenti e successive ricavate
if ( IsNull( pCrvBef) || IsNull( pCrvAft) || ! pCrvBef->IsValid() || ! pCrvAft->IsValid())
return false ;
// estendo il Link
// estendo il Link ( linea di ingresso, segmento Link, linea d'uscita)
pCrvLink->AddCurve( Release( pCrvBef), false, dTol) ;
pCrvLink->AddCurve( Release( pCrvAft), true, dTol) ;
// smusso
// miglioro la curva
pCrvLink->MergeCurves( 100 * EPS_SMALL, ANG_TOL_STD_DEG) ;
// smusso la curva
ModifyCurveToSmoothed( pCrvLink, PockParams, dSmoothPar, dSmoothPar, false) ;
// toglo gli estremi
// toglo gli estremi, il Link è in tangenza e le linee di ingresso e d'uscita sono più
// estese dell'arco di smusso creato
delete( pCrvLink->RemoveFirstOrLastCurve( false)) ;
delete( pCrvLink->RemoveFirstOrLastCurve( true)) ;
// modifico Offset0 per raccordarlo al nuovo Link
// modifico il primo Offset per raccordarlo al nuovo Link
if ( bFirstOffs0 && pCrvOffs0->IsClosed()) {
const ICurve* pCrvFirst = pCrvLink->GetFirstCurve() ;
if ( pCrvFirst == nullptr || ! pCrvFirst->IsValid())
@@ -7139,7 +7245,8 @@ SmoothLinkByOffs( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, ICurve
double dUE ; pCrvOffs0->GetParamAtPoint( ptS, dUE, dTol) ;
pCrvOffs0->TrimEndAtParam( dUE) ;
}
// modifico Offset1 per raccordarlo al nuovo Link
// modifico il secondo Offset per raccordarlo al nuovo Link
Point3d ptE ; pCrvLink->GetEndPoint( ptE) ;
double dUS ; pCrvOffs1->GetParamAtPoint( ptE, dUS, dTol) ;
if ( bFirstOffs1 && pCrvOffs1->IsClosed())
@@ -7199,8 +7306,8 @@ GetConformalLinkForOpenCrv( const ICurveComposite* pCrvOffs0, const ICurveCompos
//----------------------------------------------------------------------------
static bool
GetConformalLink( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, PocketParams& PockParams,
const ICRVCOMPOPOVECTOR& vCrvClassBorder, ICurveComposite* pCrvLink)
CalcConformalLink( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, PocketParams& PockParams,
const ICRVCOMPOPOVECTOR& vCrvClassBorder, ICurveComposite* pCrvLink)
{
// controllo validità delle due curve di Offset
if ( pCrvOffs0 == nullptr || ! pCrvOffs0->IsValid() ||
@@ -7252,10 +7359,16 @@ GetConformalLink( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, Pocket
ICRVCOMPOPOVECTOR vCrvChunk ;
for ( int i = 0 ; i < int( vIndOffs0.size()) ; ++ i)
vCrvChunk.emplace_back( vCrvClassBorder[vIndOffs0[i]]->Clone()) ;
// se la curva successiva è chiusa, aggiorno il suo punto iniziale a quello a minima distanza
if ( ! bOpen1) {
Point3d ptS ; pCrvOffs0->GetStartPoint( ptS) ;
double dPar ;
int nFlag ;
if ( DistPointCurve( ptS, *pCrvOffs1).GetParamAtMinDistPoint( 0., dPar, nFlag))
pCrvOffs1->ChangeStartPoint( dPar) ;
}
if ( ! CutCurveToConnect( pCrvOffs0, pCrvOffs1, vCrvChunk, PockParams,
( ( bOpen0 || bFirstIterOffs0) ? 0. : 10 * EPS_SMALL),
( ( bOpen1 || bFirstIterOffs1) ? 0. : 10 * EPS_SMALL),
pCrvLink) ||
bOpen0 ? 0. : 10 * EPS_SMALL, bOpen1 ? 0. : 10 * EPS_SMALL, pCrvLink) ||
! pCrvLink->IsValid()) {
// se curva di Link non valida, cerco una strada più semplice
pCrvLink->Clear() ;
@@ -7782,7 +7895,7 @@ CalcConformalOffsAndLinks( VICRVCOMPOPOVECTOR& vvCrvOffs, const ISurfFlatRegion*
if ( IsNull( pCrvLink))
return false ;
// se non calcolabile, allora retroazione, altrimenti lo memorizzo
if ( ! GetConformalLink( vCrvOffs[i], vCrvOffs[i+1], PockParams, vCrvSfrClass, pCrvLink) ||
if ( ! CalcConformalLink( vCrvOffs[i], vCrvOffs[i+1], PockParams, vCrvSfrClass, pCrvLink) ||
IsNull( pCrvLink) || ! pCrvLink->IsValid() || pCrvLink->GetCurveCount() == 0)
vCrvLink.resize( int( vCrvLink.size()) + 1) ;
else