Compare commits
17 Commits
Trimming
...
5AxTrimming
| Author | SHA1 | Date | |
|---|---|---|---|
| 1cfd283f26 | |||
| 1f47402215 | |||
| 55e2983991 | |||
| 7c85ea2d43 | |||
| 1c49379ee1 | |||
| 481d81a8d2 | |||
| 68e25e10e8 | |||
| 88410333e9 | |||
| 6bbedc812f | |||
| 4e6dd05aa9 | |||
| a5684b2bf3 | |||
| 119bbe0bcb | |||
| 35b903e8a0 | |||
| 979597084d | |||
| 02742ee80f | |||
| a2bcc4d682 | |||
| cbd487e4ff |
+175
-181
@@ -1290,24 +1290,22 @@ CreateSurfFrIncidence( const ICurveComposite* pCrv, const PocketParams& PockPara
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvIsland,
|
||||
const double dParS, const double dParE, const Vector3d& vtTanS,
|
||||
const Vector3d& vtTanE, const double dRad, const double dDiamJ,
|
||||
const PocketParams& PockParams, ICurveComposite* pCrvBorder)
|
||||
AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvIsland, const double dParS, const double dParE,
|
||||
const Vector3d& vtTanS, const Vector3d& vtTanE, const double dRad, const double dDiamJ, const PocketParams& PockParams,
|
||||
ICurveComposite* pCrvBorder)
|
||||
{
|
||||
/* parametri :
|
||||
/* --- Parametri :
|
||||
pCrvCompo -> curva originaria di bordo
|
||||
vCrvIsland -> vettore delle isole all'interno di pCrvCompo
|
||||
vCrvIsland -> vettore delle isole chiuse all'interno di pCrvCompo
|
||||
dParS -> parametro sulla pCrvCompo per l'inizio del tratto aperto
|
||||
dParE -> parametro sulla pCrvCompo per la fine del tratto aperto
|
||||
vtTanS -> vettore di tangenza finale tratto chiuso precedente
|
||||
vtTanE -> vettore di tangenza iniziale ( invertito ) del tratto chiuso successivo
|
||||
vtTanS -> vettore di tangenza iniziale tratto chiuso precedente
|
||||
vtTanE -> vettore di tangenza finale (invertito) del tratto chiuso successivo
|
||||
dRad -> raggio di Offset per la regione di incidenza
|
||||
dDiamJ -> ampiezza delle curve a fagiolo per estendere la regione di incidenza
|
||||
pCrvRes -> curva da restituire ( inizialmente è il tratto aperto sulla pCrvCompo ;
|
||||
questa curva sarà l'estensione del lato aperto, adattandosi alla geometria
|
||||
dei chiusi ( non posso vedere solo i chiusi adiacenti all'aperto, devo considerare TUTTI i chiusi
|
||||
della pCrvCompo
|
||||
dDiamJ -> ampiezza delle curve "a fagiolo" per estendere la regione di incidenza
|
||||
pCrvRes -> curva da restituire (inizialmente è il tratto aperto sulla pCrvCompo). Questa curva sarà l'estensione del lato aperto,
|
||||
adattandosi alla geometria dei chiusi (non posso vedere solo i chiusi adiacenti all'aperto, devo considerare TUTTI i chiusi
|
||||
della pCrvCompo e delle isole al suo interno)
|
||||
*/
|
||||
|
||||
// controllo la validità dei parametri
|
||||
@@ -1315,28 +1313,28 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI
|
||||
pCrvBorder == nullptr || ! pCrvBorder->IsValid() || pCrvBorder->GetCurveCount() == 0)
|
||||
return false ;
|
||||
|
||||
// definisco la regione di incidenza ( leggermente più grande )
|
||||
// definisco la regione di incidenza (leggermente più grande)
|
||||
PtrOwner<ISurfFlatRegion> pSfrInc( CreateSurfFlatRegion()) ;
|
||||
if ( IsNull( pSfrInc))
|
||||
return false ;
|
||||
if ( ! CreateSurfFrIncidence( pCrvBorder, PockParams, dRad + 75. * EPS_SMALL, pSfrInc)) {
|
||||
pSfrInc.Set( GetSurfFlatRegionFromFatCurve( CloneCurveComposite( pCrvBorder), dRad + 75 * EPS_SMALL, false, false)) ;
|
||||
pSfrInc.Set( GetSurfFlatRegionFromFatCurve( CloneCurveComposite( pCrvBorder), dRad + 75. * EPS_SMALL, false, false)) ;
|
||||
if ( IsNull( pSfrInc) || ! pSfrInc->IsValid())
|
||||
return false ;
|
||||
}
|
||||
|
||||
// creo un vettore con tutte le curve che potrebbero cadere, in parte, nella regione di incidenza
|
||||
ICRVCOMPOPOVECTOR vCrvToCheck ;
|
||||
for ( int i = 0 ; i < int( vCrvIsland.size()) ; ++ i)
|
||||
vCrvToCheck.emplace_back( vCrvIsland[i]->Clone()) ; // aggiungo le isole
|
||||
for ( int i = 0 ; i < ssize( vCrvIsland) ; ++ i)
|
||||
vCrvToCheck.emplace_back( CloneCurveComposite( vCrvIsland[i])) ;
|
||||
// se la curva originale non è tutta Aperta -> devo aggiungere anche essa nelle curve da controllare
|
||||
bool bIsAllOpen = abs( abs( dParE - dParS) - pCrvCompo->GetCurveCount()) < EPS_SMALL ;
|
||||
bool bIsAllOpen = ( abs( abs( dParE - dParS) - pCrvCompo->GetCurveCount()) < EPS_SMALL) ;
|
||||
if ( ! bIsAllOpen) {
|
||||
// recupero il tratto di curva prima e dopo dell'aperto corrente
|
||||
PtrOwner<ICurveComposite> pCompoOther( ConvertCurveToComposite( pCrvCompo->CopyParamRange( dParE, dParS))) ;
|
||||
if ( IsNull( pCompoOther) || ! pCompoOther->IsValid())
|
||||
return false ;
|
||||
vCrvToCheck.emplace_back( Release( pCompoOther)) ; // aggiungo il bordo
|
||||
vCrvToCheck.emplace_back( Release( pCompoOther)) ;
|
||||
}
|
||||
|
||||
// controllo se la curva è un'isola ( normale del piano -Z_AX)
|
||||
@@ -1346,28 +1344,28 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI
|
||||
return false ;
|
||||
bIsIsland = AreSameVectorEpsilon( plCheck.GetVersN(), - Z_AX, 10. * EPS_SMALL) ;
|
||||
|
||||
// scorro il vettore creato...
|
||||
for ( int i = 0 ; i < int( vCrvToCheck.size()) ; ++ i) {
|
||||
// 1) recupero la curva corrente
|
||||
PtrOwner<ICurveComposite> pCrvCurr( vCrvToCheck[i]->Clone()) ;
|
||||
// scorro il vettore di curve chiuse da verificare
|
||||
for ( int i = 0 ; i < ssize( vCrvToCheck) ; ++ i) {
|
||||
// recupero la curva corrente
|
||||
PtrOwner<ICurveComposite> pCrvCurr( CloneCurveComposite( vCrvToCheck[i])) ;
|
||||
if ( IsNull( pCrvCurr) || ! pCrvCurr->IsValid())
|
||||
return false ;
|
||||
// 2) ricavo i tratti con proprietà uniformi ( Aperti/Chiusi )
|
||||
// ricavo i tratti con proprietà uniformi (Aperti/Chiusi)
|
||||
ICRVCOMPOPOVECTOR vpCrvs ;
|
||||
if ( ! GetHomogeneousParts( pCrvCurr, PockParams, vpCrvs))
|
||||
return false ;
|
||||
// 3) considero solo i tratti chiusi
|
||||
for ( int nU = 0 ; nU < int( vpCrvs.size()) ; ++ nU) {
|
||||
// considero solo i tratti chiusi
|
||||
for ( int nU = 0 ; nU < ssize( vpCrvs) ; ++ nU) {
|
||||
if ( vpCrvs[nU]->GetTempProp() == TEMP_PROP_OPEN_EDGE)
|
||||
continue ;
|
||||
// 4) effettuo l'Offset della curva di metà dDiamJ
|
||||
// effettuo l'Offset della curva di metà dDiamJ
|
||||
OffsetCurve OffsCrv ;
|
||||
if ( ! OffsCrv.Make( vpCrvs[nU], - dDiamJ / 2. - 20. * EPS_SMALL, PockParams.nOffsType))
|
||||
return false ;
|
||||
// 5) scorro tutte le curve di Offset che si sono formate, prendendo sempre la più lunga tra le rimanenti
|
||||
// scorro tutte le curve di Offset che si sono formate, prendendo sempre la più lunga tra le rimanenti
|
||||
PtrOwner<ICurve> pOffLongestCrv( OffsCrv.GetLongerCurve()) ;
|
||||
while ( ! IsNull( pOffLongestCrv)) {
|
||||
// 6) creo la regione di incidenza di tale curva ( "Curva a fagiolo")
|
||||
// creo la regione di incidenza di tale curva ("Curva a fagiolo")
|
||||
bool bSquareEnds = ( PockParams.nOffsType == ICurve::OFF_CHAMFER) ;
|
||||
bool bSquareMids = ( PockParams.nOffsType == ICurve::OFF_CHAMFER) ;
|
||||
PtrOwner<ISurfFlatRegion> pSfrBean( GetSurfFlatRegionFromFatCurve( Release( pOffLongestCrv), dDiamJ / 2., bSquareEnds, bSquareMids)) ;
|
||||
@@ -1376,7 +1374,7 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI
|
||||
// inverto se necessario
|
||||
if ( AreOppositeVectorApprox( pSfrBean->GetNormVersor(), pSfrInc->GetNormVersor()))
|
||||
pSfrBean->Invert() ;
|
||||
// 7) se la "Regione a fagiolo" non influenza la regione di incidenza, la transcuro
|
||||
// se la "Regione a fagiolo" non influenza la regione di incidenza, la transcuro
|
||||
bool bDiscard = false ;
|
||||
if ( ! bIsIsland) {
|
||||
// se tratto un loop esterno
|
||||
@@ -1384,21 +1382,19 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI
|
||||
if ( IsNull( pSfrBean_test) || ! pSfrBean_test->IsValid())
|
||||
return false ;
|
||||
pSfrBean_test->Intersect( *pSfrInc) ;
|
||||
bDiscard = ( IsNull( pSfrBean_test) ||
|
||||
! pSfrBean_test->IsValid() ||
|
||||
pSfrBean_test->GetChunkCount() == 0) ;
|
||||
bDiscard = ( IsNull( pSfrBean_test) || ! pSfrBean_test->IsValid() || pSfrBean_test->GetChunkCount() == 0) ;
|
||||
}
|
||||
else if ( bIsAllOpen && bIsIsland) {
|
||||
// se isola aperta
|
||||
for ( int cI = 0 ; cI < pSfrInc->GetChunkCount() && ! bDiscard ; ++ cI) {
|
||||
for ( int cB = 0 ; cB < pSfrBean->GetChunkCount() && ! bDiscard ; ++ cB) {
|
||||
if ( pSfrInc->GetChunkSimpleClassification( cI, *pSfrBean, cB) == REGC_IN1) {
|
||||
for ( int l = 1 ; l < pSfrBean->GetLoopCount( cB) ; ++ l) {
|
||||
for ( int nC = 0 ; nC < pSfrInc->GetChunkCount() && ! bDiscard ; ++ nC) {
|
||||
for ( int nB = 0 ; nB < pSfrBean->GetChunkCount() && ! bDiscard ; ++ nB) {
|
||||
if ( pSfrInc->GetChunkSimpleClassification( nC, *pSfrBean, nB) == REGC_IN1) {
|
||||
for ( int nL = 1 ; nL < pSfrBean->GetLoopCount( nB) ; ++ nL) {
|
||||
PtrOwner<ISurfFlatRegion> pSfrTmp( CreateSurfFlatRegion()) ;
|
||||
if ( IsNull( pSfrTmp) || ! pSfrTmp->AddExtLoop( pSfrBean->GetLoop( cB, l)) ||
|
||||
if ( IsNull( pSfrTmp) || ! pSfrTmp->AddExtLoop( pSfrBean->GetLoop( nB, nL)) ||
|
||||
! pSfrTmp->Invert())
|
||||
return false ;
|
||||
bDiscard = ( pSfrInc->GetChunkSimpleClassification( cI, *pSfrTmp, 0) == REGC_IN1) ;
|
||||
bDiscard = ( pSfrInc->GetChunkSimpleClassification( nC, *pSfrTmp, 0) == REGC_IN1) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1500,9 +1496,9 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI
|
||||
// pulisco la curva originale
|
||||
pCrvBorder->Clear() ;
|
||||
if ( bIsIsland) { // se isola inserisco il loop interno corretto della regione
|
||||
for ( int l = 1 ; l < pSfrInc->GetLoopCount( 0) ; ++ l) {
|
||||
for ( int nL = 1 ; nL < pSfrInc->GetLoopCount( 0) ; ++ nL) {
|
||||
// recupero il Loop
|
||||
PtrOwner<ICurveComposite> pCrvIntLoop( ConvertCurveToComposite( pSfrInc->GetLoop( 0, l))) ;
|
||||
PtrOwner<ICurveComposite> pCrvIntLoop( ConvertCurveToComposite( pSfrInc->GetLoop( 0, nL))) ;
|
||||
if ( IsNull( pCrvIntLoop) || ! pCrvIntLoop->IsValid())
|
||||
return false ;
|
||||
// controllo che sia interno alla curva di bordo corrente ( l'isola aperta)
|
||||
@@ -1516,8 +1512,8 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI
|
||||
if ( IsNull( pCrvNewBorder) || ! pCrvNewBorder->IsValid())
|
||||
return false ;
|
||||
// imposto la curva come tutta aperta ( gira come girava già l'isola)
|
||||
for ( int u = 0 ; u < pCrvNewBorder->GetCurveCount() ; ++ u)
|
||||
pCrvNewBorder->SetCurveTempProp( u, TEMP_PROP_OPEN_EDGE, 0) ;
|
||||
for ( int nU = 0 ; nU < pCrvNewBorder->GetCurveCount() ; ++ nU)
|
||||
pCrvNewBorder->SetCurveTempProp( nU, TEMP_PROP_OPEN_EDGE, 0) ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
@@ -1556,7 +1552,7 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI
|
||||
if ( ! pCrvNewBorder->GetParamAtPoint( ptMinDist, dUTmp))
|
||||
return false ;
|
||||
if ( dUTmp < EPS_SMALL)
|
||||
dUTmp = pCrvNewBorder->GetCurveCount() - 5 * EPS_SMALL ;
|
||||
dUTmp = pCrvNewBorder->GetCurveCount() - 5. * EPS_SMALL ;
|
||||
// copio la curva tra questi due parametri
|
||||
PtrOwner<ICurveComposite> pCrvTmp( ConvertCurveToComposite( pCrvNewBorder->CopyParamRange( 0., dUTmp))) ;
|
||||
if ( IsNull( pCrvTmp) || ! pCrvTmp->IsValid())
|
||||
@@ -1583,7 +1579,7 @@ AdjustContourWithOpenEdges( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vCrvI
|
||||
return false ;
|
||||
|
||||
// recupero i parametri di lavorazione correnti
|
||||
double dDiam = PockParams.dRad * 2 ;
|
||||
double dDiam = 2. * PockParams.dRad ;
|
||||
double dOffR = PockParams.dRadialOffset ;
|
||||
double dStep = PockParams.dSideStep ;
|
||||
|
||||
@@ -1610,71 +1606,66 @@ AdjustContourWithOpenEdges( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vCrvI
|
||||
// salvo il raggio trovato
|
||||
PockParams.dOpenEdgeRad = dRad ;
|
||||
|
||||
// ricavo i tratti omogenei
|
||||
// ricavo i tratti omogenei. Il primo tratto è la prima metà del tratto aperto più lungo ( se esiste )
|
||||
ICRVCOMPOPOVECTOR vpCrvs ;
|
||||
if ( ! GetHomogeneousParts( pCrvCompo, PockParams, vpCrvs))
|
||||
return false ;
|
||||
// NB. Il primo tratto è la prima metà del tratto aperto più lungo ( se esiste )
|
||||
|
||||
// Offset esterno per CurveJ
|
||||
double dDiamJ = 1.05 * ( dDiam) + 2 * dOffR ;
|
||||
double dDiamJ = 1.05 * ( dDiam) + 2. * dOffR ;
|
||||
if ( abs( PockParams.dMaxOpenEdgeRad) > 0)
|
||||
dDiamJ = 100 * EPS_SMALL ;
|
||||
dDiamJ = 100. * EPS_SMALL ;
|
||||
else if ( PockParams.nType == POCKET_CONFORMAL_ZIGZAG || PockParams.nType == POCKET_CONFORMAL_ONEWAY)
|
||||
dDiamJ = 1.05 * ( PockParams.dRad + dRad) + dOffR ;
|
||||
// NB. 1.05 serve per eccedere leggermente, in modo che il contro-offset della prima curva di svuotatura presenti
|
||||
// dei piccoli archi tra i chiusi e gli aperti ( in modo da svuotare bene lungo il chiuso)
|
||||
|
||||
// curva finale da restituire
|
||||
PtrOwner<ICurveComposite> pCrvCompo_final( CreateCurveComposite()) ;
|
||||
if ( IsNull( pCrvCompo_final))
|
||||
PtrOwner<ICurveComposite> pCompoFinal( CreateCurveComposite()) ;
|
||||
if ( IsNull( pCompoFinal))
|
||||
return false ;
|
||||
|
||||
// parametro iniziale del tratto corrente, sulla curva originale
|
||||
double dParS = 0. ;
|
||||
// scorro tutti i tratti omogenei nel vettore
|
||||
for ( int i = 0 ; i < int( vpCrvs.size()) ; ++ i) {
|
||||
for ( int i = 0 ; i < ssize( vpCrvs) ; ++ i) {
|
||||
// recupero la proprietà della curva composita
|
||||
int nCurrTmpProp = vpCrvs[i]->GetTempProp() ;
|
||||
// aggiorno i parametri del lato aperto corrente sulla curva originale
|
||||
double dParE = dParS + 1. * vpCrvs[i]->GetCurveCount() ;
|
||||
// se aperta
|
||||
if ( nCurrTmpProp == TEMP_PROP_OPEN_EDGE) {
|
||||
// controllo che sia almeno lungo quanto il diametro utensile
|
||||
double dLen = 0. ;
|
||||
vpCrvs[i]->GetLength( dLen) ;
|
||||
// ricavo la tangenze dei lati chiusi agli estremi di questa curva
|
||||
Vector3d vtTanS = V_INVALID ;
|
||||
Vector3d vtTanE = V_INVALID ;
|
||||
Vector3d vtTanS = V_INVALID ; // tangente finale del chiuso precedente
|
||||
Vector3d vtTanE = V_INVALID ; // tangente iniziale del chiuso successivo
|
||||
if ( i != 0) {
|
||||
if ( ! vpCrvs[i-1]->GetEndDir( vtTanS) || // tangente finale del chiuso precedente
|
||||
! vpCrvs[( i + 1) % int( vpCrvs.size())]->GetStartDir( vtTanE)) // tangente iniziale del chiuso successivo...
|
||||
if ( ! vpCrvs[i-1]->GetEndDir( vtTanS) || ! vpCrvs[( i + 1) % int( vpCrvs.size())]->GetStartDir( vtTanE))
|
||||
return false ;
|
||||
vtTanE.Invert() ; // invertita
|
||||
vtTanE.Invert() ;
|
||||
}
|
||||
if ( ! AdjustOpenEdge( pCrvCompo, vCrvIsl, dParS, dParE, vtTanS, vtTanE, dRad, dDiamJ, PockParams, vpCrvs[i]))
|
||||
return false ;
|
||||
}
|
||||
// assegno le proprietà di lato Aperto/Chiuso per la curva corrente
|
||||
for ( int u = 0 ; u < vpCrvs[i]->GetCurveCount() ; ++ u)
|
||||
vpCrvs[i]->SetCurveTempProp( u, nCurrTmpProp, TEMP_PROP_CLOSE_EDGE) ;
|
||||
for ( int nU = 0 ; nU < vpCrvs[i]->GetCurveCount() ; ++ nU)
|
||||
vpCrvs[i]->SetCurveTempProp( nU, nCurrTmpProp, TEMP_PROP_CLOSE_EDGE) ;
|
||||
// aggiungo la curva ricavata ( se chiusa -> la copio, se aperta -> copio l'estesa)
|
||||
if ( ! pCrvCompo_final->AddCurve( vpCrvs[i]->Clone())) {
|
||||
if ( ! pCompoFinal->AddCurve( vpCrvs[i]->Clone())) {
|
||||
// per sicurezza, se gli estremi non coincidono, creo un piccolo raccordo lineare
|
||||
Point3d ptH ; vpCrvs[i]->GetStartPoint( ptH) ;
|
||||
if ( ! pCrvCompo_final->AddLine( ptH) ||
|
||||
! pCrvCompo_final->SetCurveTempProp( pCrvCompo_final->GetCurveCount() - 1, 1, 0) ||
|
||||
! pCrvCompo_final->AddCurve( vpCrvs[i]->Clone()))
|
||||
if ( ! pCompoFinal->AddLine( ptH) ||
|
||||
! pCompoFinal->SetCurveTempProp( pCompoFinal->GetCurveCount() - 1, TEMP_PROP_OPEN_EDGE, 0) ||
|
||||
! pCompoFinal->AddCurve( vpCrvs[i]->Clone()))
|
||||
return false ;
|
||||
}
|
||||
// aggiorno
|
||||
dParS = dParE ;
|
||||
}
|
||||
// non dovrebbe esserci un gap, ma meglio prevenire problemi
|
||||
pCrvCompo_final->Close() ;
|
||||
pCompoFinal->Close() ;
|
||||
// sostituisco
|
||||
pCrvCompo->Clear() ;
|
||||
pCrvCompo->CopyFrom( pCrvCompo_final) ;
|
||||
pCrvCompo->CopyFrom( pCompoFinal) ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
@@ -2168,7 +2159,7 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams)
|
||||
{
|
||||
// controllo parametri :
|
||||
if ( pSfr == nullptr || ! pSfr->IsValid())
|
||||
return true ; // <- se superficie non valida, allora non ho niente da impostare sui suoi lati
|
||||
return true ;
|
||||
|
||||
// se lati tutti chiusi, allora non devo fare nulla
|
||||
if ( PockParams.bAllClosed)
|
||||
@@ -2178,18 +2169,18 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams)
|
||||
// I lati aperti vanno estesi seguendo lo geometria dei lati chiusi adiacenti e tenendo conto delle isole chiuse
|
||||
// vicine ad essi
|
||||
|
||||
// creo la superficie da restituire... ( questa superficie sarà estesa presso i lati aperti)
|
||||
// creo la superficie da restituire ( questa superficie sarà estesa presso i lati aperti)
|
||||
PtrOwner<ISurfFlatRegion> pSrfFinal( CreateSurfFlatRegion()) ;
|
||||
if ( IsNull( pSrfFinal))
|
||||
return false ;
|
||||
|
||||
// per ogni Chunck della superificie ottenuta...
|
||||
// per ogni Chunck della superificie ottenuta
|
||||
for ( int nC = 0 ; nC < pSfr->GetChunkCount() ; ++ nC) {
|
||||
|
||||
// flag per indicare se il Chunk è stato modificato mediante estensione degli aperti
|
||||
bool bIsChunkModified = true ;
|
||||
|
||||
// ricavo il Loop esterno ( External Loop)
|
||||
// ricavo il Loop esterno (External Loop)
|
||||
PtrOwner<ICurveComposite> pCrvEL( ConvertCurveToComposite( pSfr->GetLoop( nC, 0))) ;
|
||||
if ( IsNull( pCrvEL) || ! pCrvEL->IsValid())
|
||||
return false ;
|
||||
@@ -2203,13 +2194,13 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams)
|
||||
vCrvIsl.emplace_back( Release( pCrvIL)) ;
|
||||
}
|
||||
|
||||
// se la curva esterna presenta dei lati aperti -> devo modificarla
|
||||
// se la curva esterna presenta dei lati aperti, allora necessita di estensione
|
||||
bool bSomeOpen = false ;
|
||||
int nProp0 = TEMP_PROP_INVALID ;
|
||||
for ( int u = 0 ; u < pCrvEL->GetCurveCount() && ! bSomeOpen ; ++ u)
|
||||
bSomeOpen = ( pCrvEL->GetCurveTempProp( u, nProp0, 0) && nProp0 == TEMP_PROP_OPEN_EDGE) ;
|
||||
for ( int nU = 0 ; nU < pCrvEL->GetCurveCount() && ! bSomeOpen ; ++ nU)
|
||||
bSomeOpen = ( pCrvEL->GetCurveTempProp( nU, nProp0, 0) && nProp0 == TEMP_PROP_OPEN_EDGE) ;
|
||||
if ( bSomeOpen) {
|
||||
// allorargo il Loop esterno presso i lati aperti
|
||||
// allarargo il Loop esterno presso i lati aperti
|
||||
if ( ! AdjustContourWithOpenEdges( pCrvEL, vCrvIsl, PockParams))
|
||||
return false ;
|
||||
bIsChunkModified = true ;
|
||||
@@ -2218,8 +2209,8 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams)
|
||||
// controllo i bordi delle isole ottenute
|
||||
// NB. L'isola può essere tutta aperta o tutta chiusa ( se non uniforme, la forzo chiusa)
|
||||
// [ La definizione di isola con proprietà non uniformi non è definita ]
|
||||
ICRVCOMPOPOVECTOR vCrvToTIsland ; // isole che considero valide
|
||||
for ( int nI = 0 ; nI < int( vCrvIsl.size()) ; ++ nI) {
|
||||
ICRVCOMPOPOVECTOR vCompoIsland ; // isole che considero valide
|
||||
for ( int nI = 0 ; nI < ssize( vCrvIsl) ; ++ nI) {
|
||||
// controllo uniformità
|
||||
int nCurrTmpProp = TEMP_PROP_INVALID ;
|
||||
int nPrecTmpProp = TEMP_PROP_INVALID ;
|
||||
@@ -2227,12 +2218,12 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams)
|
||||
PtrOwner<ICurveComposite> pCrvIsl( CloneCurveComposite( vCrvIsl[nI])) ;
|
||||
if ( IsNull( pCrvIsl) || ! pCrvIsl->IsValid())
|
||||
return false ;
|
||||
for ( int nU = 0 ; nU < pCrvIsl->GetCurveCount() && ! bIsMixed ; ++ nU) {
|
||||
for ( int nU = 0 ; nU < pCrvIsl->GetCurveCount() && ! bIsMixed ; ++ nU) {
|
||||
pCrvIsl->GetCurveTempProp( nU, nCurrTmpProp, 0) ;
|
||||
bIsMixed = ( nU != 0 && nCurrTmpProp != nPrecTmpProp) ;
|
||||
nPrecTmpProp = nCurrTmpProp ;
|
||||
}
|
||||
// se proprità non uniformi -> tutta chiusa
|
||||
// se proprità non uniformi, allora tutta chiusa
|
||||
if ( bIsMixed) {
|
||||
for ( int nU = 0 ; nU < pCrvIsl->GetCurveCount() ; ++ nU)
|
||||
pCrvIsl->SetTempProp( nU, TEMP_PROP_CLOSE_EDGE) ;
|
||||
@@ -2245,52 +2236,50 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams)
|
||||
double dMaxOffs ;
|
||||
CalcCurveLimitOffset( *pCrvIsl, dMaxOffs) ;
|
||||
// se l'isola è trascurabile passo alla successiva
|
||||
if ( dMaxOffs < 2 * PockParams.dRad + 2 * PockParams.dRadialOffset)
|
||||
if ( dMaxOffs < 2. * PockParams.dRad + 2. * PockParams.dRadialOffset)
|
||||
continue ;
|
||||
// altrimenti la restringo
|
||||
// altrimenti effettuo estensione
|
||||
ICRVCOMPOPOVECTOR vCrvOther ;
|
||||
vCrvOther.emplace_back( pCrvEL->Clone()) ;
|
||||
for ( int nII = 0 ; nII < int( vCrvIsl.size()) ; ++ nII) {
|
||||
if ( nII != nI)
|
||||
vCrvOther.emplace_back( vCrvIsl[nII]->Clone()) ;
|
||||
vCrvOther.emplace_back( CloneCurveComposite( pCrvEL)) ;
|
||||
for ( int nOther = 0 ; nOther < ssize( vCrvIsl) ; ++ nOther) {
|
||||
if ( nOther != nI)
|
||||
vCrvOther.emplace_back( vCrvIsl[nOther]->Clone()) ;
|
||||
}
|
||||
if ( ! AdjustContourWithOpenEdges( pCrvIsl, vCrvOther, PockParams))
|
||||
return false ;
|
||||
bIsChunkModified = true ;
|
||||
}
|
||||
// conservo l'isola ( estesa o meno)
|
||||
vCrvToTIsland.emplace_back( pCrvIsl->Clone()) ; // <-- valida
|
||||
vCompoIsland.emplace_back( CloneCurveComposite( pCrvIsl)) ;
|
||||
}
|
||||
|
||||
// se c'è stata almeno una modifica di lato aperto al Chunk ( nC-esimo), devo ricreare il Chunk
|
||||
// con i nuovi loop ricavati ( Chunk dopo Chunk creo la superficie finale)
|
||||
if ( bIsChunkModified) {
|
||||
/*
|
||||
l'estensione degli aperti, può unire il loop esterno con il loop delle sue isole.
|
||||
Creo una nuova regione dai nuovi contorni ottenuti
|
||||
*/
|
||||
// L'estensione degli aperti, può unire il loop esterno con il loop delle sue isole.
|
||||
// Creo una nuova regione dai nuovi contorni ottenuti
|
||||
SurfFlatRegionByContours SfrBC ;
|
||||
// loop Esterno
|
||||
pCrvEL->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL, true, true) ;
|
||||
pCrvEL->MergeCurves( 10. * EPS_SMALL, 10. * EPS_ANG_SMALL, true, true) ;
|
||||
SfrBC.AddCurve( Release( pCrvEL)) ;
|
||||
// isole non trascurate
|
||||
for ( int nI = 0 ; nI < int( vCrvToTIsland.size()) ; ++ nI) {
|
||||
vCrvToTIsland[nI]->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL, true, true) ;
|
||||
SfrBC.AddCurve( Release( vCrvToTIsland[nI])) ;
|
||||
for ( int nI = 0 ; nI < ssize( vCompoIsland) ; ++ nI) {
|
||||
vCompoIsland[nI]->MergeCurves( 10. * EPS_SMALL, 10. * EPS_ANG_SMALL, true, true) ;
|
||||
SfrBC.AddCurve( Release( vCompoIsland[nI])) ;
|
||||
}
|
||||
// ricavo il nuovo Chunk nC-esimo esteso presso i lati aperti
|
||||
// ricavo il nuovo Chunk corrente esteso presso i lati aperti
|
||||
PtrOwner<ISurfFlatRegion> pNewChunk( SfrBC.GetSurf()) ;
|
||||
if ( IsNull( pNewChunk) || ! pNewChunk->IsValid())
|
||||
return false ;
|
||||
// aggiungo il Chunk nC-esimo alla superficie finale
|
||||
// aggiungo il Chunk corrente alla superficie finale
|
||||
if ( pSrfFinal->GetChunkCount() == 0)
|
||||
pSrfFinal.Set( pNewChunk) ;
|
||||
else if ( ! pSrfFinal->Add( *pNewChunk))
|
||||
return false ;
|
||||
}
|
||||
// se il Chunk c-esimo non è mai stato modificato
|
||||
// se il Chunk corrente non è mai stato modificato
|
||||
else {
|
||||
// aggiungo il Chunk alla superficie finale
|
||||
// lo aggiungo semplicemente
|
||||
if ( pSrfFinal->GetChunkCount() == 0)
|
||||
pSrfFinal.Set( pSfr->CloneChunk( nC)) ;
|
||||
else if ( ! pSrfFinal->Add( *pSfr->CloneChunk( nC)))
|
||||
@@ -2311,12 +2300,12 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams)
|
||||
PtrOwner<ICurveComposite> pCrvIsl( ConvertCurveToComposite( pSrfFinal->GetLoop( nC, nL))) ;
|
||||
if ( IsNull( pCrvIsl) || ! pCrvIsl->IsValid())
|
||||
return false ;
|
||||
for ( int nU = 0 ; nU < pCrvIsl->GetCurveCount() && ! bIsMixed ; ++ nU) {
|
||||
for ( int nU = 0 ; nU < pCrvIsl->GetCurveCount() && ! bIsMixed ; ++ nU) {
|
||||
pCrvIsl->GetCurveTempProp( nU, nCurrTmpProp, 0) ;
|
||||
bIsMixed = ( nU != 0 && nCurrTmpProp != nPrecTmpProp) ;
|
||||
nPrecTmpProp = nCurrTmpProp ;
|
||||
}
|
||||
// se proprità non uniformi -> tutta chiusa
|
||||
// se proprità non uniformi, tutta chiusa
|
||||
if ( bIsMixed) {
|
||||
for ( int nU = 0 ; nU < pCrvIsl->GetCurveCount() ; ++ nU)
|
||||
pSrfFinal->SetCurveTempProp( nC, nL, nU, TEMP_PROP_CLOSE_EDGE) ;
|
||||
@@ -3741,6 +3730,8 @@ CalcTrapezoidSpiral( ICurveComposite* pCrvPocket, const Frame3d& frTrap, double
|
||||
}
|
||||
|
||||
}
|
||||
else if ( bInvertByRef)
|
||||
pMCrv->Invert() ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6856,19 +6847,20 @@ CalcZigZagLink( ICurveComposite* pCrv1, ICurveComposite* pCrv2, const PocketPara
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
CalcZigZag( const ISurfFlatRegion* pSrfZigZag, const PocketParams& PockParams, ICRVCOMPOPOVECTOR& vpCrvs,
|
||||
CalcZigZag( const ISurfFlatRegion* pSfrZigZag, const PocketParams& PockParams, ICRVCOMPOPOVECTOR& vpCrvs,
|
||||
bool bFromInfill)
|
||||
{
|
||||
|
||||
// check parametri
|
||||
if ( pSrfZigZag == nullptr || ! pSrfZigZag->IsValid())
|
||||
if ( pSfrZigZag == nullptr || ! pSfrZigZag->IsValid())
|
||||
return true ;
|
||||
|
||||
// creo il vettore dei contorni
|
||||
ICRVCOMPOPOVECTOR vFirstOff ;
|
||||
for ( int c = 0 ; c < pSrfZigZag->GetChunkCount() ; ++ c)
|
||||
for ( int l = 0 ; l < pSrfZigZag->GetLoopCount( c) ; ++ l)
|
||||
vFirstOff.emplace_back( GetCurveComposite( pSrfZigZag->GetLoop( c, l))) ;
|
||||
for ( int nC = 0 ; nC < pSfrZigZag->GetChunkCount() ; ++ nC) {
|
||||
for ( int nL = 0 ; nL < pSfrZigZag->GetLoopCount( nC) ; ++ nL)
|
||||
vFirstOff.emplace_back( GetCurveComposite( pSfrZigZag->GetLoop( nC, nL))) ;
|
||||
}
|
||||
|
||||
// ingombro del contorno offsettato
|
||||
BBox3d b3Pocket ;
|
||||
@@ -6883,15 +6875,14 @@ CalcZigZag( const ISurfFlatRegion* pSrfZigZag, const PocketParams& PockParams, I
|
||||
int nYStep ;
|
||||
double dYStep ;
|
||||
if ( ! bFromInfill) {
|
||||
nYStep = static_cast< int >( ceil(( dDimY - 30 * EPS_SMALL) / PockParams.dSideStep)) ;
|
||||
dYStep = ( nYStep > 0 ? ( dDimY - 30 * EPS_SMALL) / nYStep : 0) ;
|
||||
nYStep = static_cast<int>( ceil( ( dDimY - 30. * EPS_SMALL) / PockParams.dSideStep)) ;
|
||||
dYStep = ( nYStep > 0 ? ( dDimY - 30. * EPS_SMALL) / nYStep : 0) ;
|
||||
}
|
||||
else {
|
||||
nYStep = static_cast< int >( floor(( dDimY + 30 * EPS_SMALL) / PockParams.dSideStep)) ;
|
||||
nYStep = static_cast<int>( floor( ( dDimY + 30. * EPS_SMALL) / PockParams.dSideStep)) ;
|
||||
dYStep = PockParams.dSideStep ;
|
||||
}
|
||||
|
||||
int nRef = (( nYStep + ( PockParams.bInvert ? 0 : 1)) % 2) ;
|
||||
int nRef = ( PockParams.bInvert ? 1 : 0) ;
|
||||
|
||||
// tratto valido
|
||||
struct Section {
|
||||
@@ -6903,7 +6894,6 @@ CalcZigZag( const ISurfFlatRegion* pSrfZigZag, const PocketParams& PockParams, I
|
||||
int nOffIndS ;
|
||||
int nOffIndE ;
|
||||
} ;
|
||||
|
||||
struct ParIsland {
|
||||
double dU ;
|
||||
int nInd ;
|
||||
@@ -6917,27 +6907,26 @@ CalcZigZag( const ISurfFlatRegion* pSrfZigZag, const PocketParams& PockParams, I
|
||||
int nCount = 0 ;
|
||||
for ( int i = 0 ; i <= nYStep ; ++ i) {
|
||||
// determino senso
|
||||
bool bPlus = (( i % 2) == nRef) ;
|
||||
bool bPlus = ( ( i % 2) == nRef) ;
|
||||
// definisco la linea
|
||||
PtrOwner<ICurveLine> pLine( CreateCurveLine()) ;
|
||||
const double EXP_LEN = 1.0 ;
|
||||
Point3d ptStart ;
|
||||
if ( ! bFromInfill)
|
||||
ptStart.Set( ptMin.x - EXP_LEN, ptMin.y + 10 * EPS_SMALL + i * dYStep, ptMin.z + dDimZ) ;
|
||||
ptStart.Set( ptMin.x - EXP_LEN, ptMin.y + 10. * EPS_SMALL + i * dYStep, ptMin.z + dDimZ) ;
|
||||
else {
|
||||
double dShift = ( i == 0 ? 10 * EPS_SMALL : ( i == nYStep ? - 10 * EPS_SMALL : 0.)) ;
|
||||
double dShift = ( i == 0 ? 10. * EPS_SMALL : ( i == nYStep ? - 10. * EPS_SMALL : 0.)) ;
|
||||
ptStart.Set( ptMin.x - EXP_LEN, ptMin.y + dShift + i * dYStep, ptMin.z + dDimZ) ;
|
||||
}
|
||||
if ( IsNull( pLine) || ! pLine->SetPVL( ptStart, X_AX, dDimX + 2 * EXP_LEN))
|
||||
if ( IsNull( pLine) || ! pLine->SetPVL( ptStart, X_AX, dDimX + 2. * EXP_LEN))
|
||||
return false ;
|
||||
|
||||
if ( ! bPlus)
|
||||
pLine->Invert() ;
|
||||
|
||||
// calcolo la classificazione della linea rispetto alla superficie
|
||||
CRVCVECTOR ccClass ;
|
||||
pSrfZigZag->GetCurveClassification( *pLine, EPS_SMALL, ccClass) ;
|
||||
for ( int j = 0 ; j < int( ccClass.size()) ; ++ j) {
|
||||
pSfrZigZag->GetCurveClassification( *pLine, EPS_SMALL, ccClass) ;
|
||||
for ( int j = 0 ; j < ssize( ccClass) ; ++ j) {
|
||||
// se interno
|
||||
if ( ccClass[j].nClass == CRVC_IN) {
|
||||
// recupero il tratto
|
||||
@@ -6946,21 +6935,21 @@ CalcZigZag( const ISurfFlatRegion* pSrfZigZag, const PocketParams& PockParams, I
|
||||
PtrOwner<ICurveLine> pSeg( GetCurveLine( pLine->CopyParamRange( ccClass[j].dParS, ccClass[j].dParE))) ;
|
||||
if ( IsNull( pSeg))
|
||||
continue ;
|
||||
Point3d ptS, ptE ;
|
||||
pSeg->GetStartPoint( ptS) ; pSeg->GetEndPoint( ptE) ;
|
||||
Point3d ptS ; pSeg->GetStartPoint( ptS) ;
|
||||
Point3d ptE ; pSeg->GetEndPoint( ptE) ;
|
||||
// se troppo piccolo, lo scarto
|
||||
if ( SqDist( ptS, ptE) < 250 * 250 * SQ_EPS_SMALL)
|
||||
if ( SqDist( ptS, ptE) < ( 250. * 250.) * SQ_EPS_SMALL)
|
||||
continue ;
|
||||
currSec.ptS = ptS ; currSec.ptE = ptE ;
|
||||
for ( int k = 0 ; k < int( vFirstOff.size()) ; ++ k) {
|
||||
for ( int k = 0 ; k < ssize( vFirstOff) ; ++ k) {
|
||||
if ( vFirstOff[k]->IsPointOn( ptS)) {
|
||||
currSec.nOffIndS = k ;
|
||||
double dUOS; vFirstOff[k]->GetParamAtPoint( ptS, dUOS) ;
|
||||
double dUOS ; vFirstOff[k]->GetParamAtPoint( ptS, dUOS) ;
|
||||
currSec.dOs = dUOS ;
|
||||
}
|
||||
if ( vFirstOff[k]->IsPointOn( ptE)){
|
||||
currSec.nOffIndE = k ;
|
||||
double dUOE; vFirstOff[k]->GetParamAtPoint( ptE, dUOE) ;
|
||||
double dUOE ; vFirstOff[k]->GetParamAtPoint( ptE, dUOE) ;
|
||||
currSec.dOe = dUOE ;
|
||||
}
|
||||
}
|
||||
@@ -6971,10 +6960,12 @@ CalcZigZag( const ISurfFlatRegion* pSrfZigZag, const PocketParams& PockParams, I
|
||||
}
|
||||
|
||||
int nStatus = 0 ; // 0 -> inizio oppure ho inserito una parte di isola | 2 -> sto inserendo un segmento
|
||||
Point3d ptS_ref ;
|
||||
Point3d ptSRef ;
|
||||
PtrOwner<ICurveComposite> pLastSeg( CreateCurveComposite()) ; // ultimo segmento nel percorso
|
||||
PtrOwner<ICurveComposite> pCrvLink( CreateCurveComposite()) ; // ultimo link aggiunto
|
||||
// vettore dei link aggiunti ( per Feed )
|
||||
if ( IsNull( pLastSeg) || IsNull( pCrvLink))
|
||||
return false ;
|
||||
// vettore dei link aggiunti (per Feed)
|
||||
ICRVCOMPOPOVECTOR vAddedLinks ;
|
||||
bool bFirstLine = true ; // flag per prima linea di ogni percorso
|
||||
|
||||
@@ -6985,8 +6976,8 @@ CalcZigZag( const ISurfFlatRegion* pSrfZigZag, const PocketParams& PockParams, I
|
||||
// se sezione non valida
|
||||
if ( nI < 0 || nJ < 0) {
|
||||
// ricerco la prima valida ( il primo segmento con bActive messo a true)
|
||||
for ( int k = 0 ; k < int( vvSec.size()) && nI < 0 ; ++ k) {
|
||||
for ( int l = 0 ; l < int( vvSec[k].size()) && nJ < 0 ; ++ l) {
|
||||
for ( int k = 0 ; k < ssize( vvSec) && nI < 0 ; ++ k) {
|
||||
for ( int l = 0 ; l < ssize( vvSec[k]) && nJ < 0 ; ++ l) {
|
||||
if ( vvSec[k][l].bActive) {
|
||||
nI = k ;
|
||||
nJ = l ;
|
||||
@@ -6994,9 +6985,11 @@ CalcZigZag( const ISurfFlatRegion* pSrfZigZag, const PocketParams& PockParams, I
|
||||
}
|
||||
}
|
||||
// se trovata, creo nuova curva composita
|
||||
if ( nI >= 0 && nJ >= 0) {
|
||||
if ( nI >= 0 && nJ >= 0) {
|
||||
// creo la curva
|
||||
vpCrvs.emplace_back( CreateCurveComposite()) ;
|
||||
if ( IsNull( vpCrvs.back()))
|
||||
return false ;
|
||||
nStatus = 0 ;
|
||||
// aggiungo punto iniziale
|
||||
vpCrvs.back()->AddPoint( vvSec[nI][nJ].ptS) ;
|
||||
@@ -7007,28 +7000,30 @@ CalcZigZag( const ISurfFlatRegion* pSrfZigZag, const PocketParams& PockParams, I
|
||||
break ;
|
||||
}
|
||||
// determino senso
|
||||
bool bPlus = (( nI % 2) == nRef) ;
|
||||
bool bPlus = ( ( nI % 2) == nRef) ;
|
||||
// aggiungo la sezione alla curva
|
||||
Section& Sec = vvSec[nI][nJ] ;
|
||||
Sec.bActive = false ;
|
||||
// creo i vettori con le linee Under e Above nella struttura della Section
|
||||
ICURVEPOVECTOR vLineAbove ;
|
||||
if ( nI < nYStep) {
|
||||
for ( int a = 0 ; a < ( int)vvSec[nI + 1].size() ; ++ a) {
|
||||
if ( vvSec[nI + 1][a].bActive)
|
||||
for ( int nA = 0 ; nA < ssize( vvSec[nI + 1]) ; ++ nA) {
|
||||
if ( vvSec[nI + 1][nA].bActive)
|
||||
continue ;
|
||||
PtrOwner<ICurveLine> pLA( CreateCurveLine()) ;
|
||||
pLA->Set( vvSec[nI + 1][a].ptS, vvSec[nI + 1][a].ptE) ;
|
||||
if ( IsNull( pLA) || ! pLA->Set( vvSec[nI + 1][nA].ptS, vvSec[nI + 1][nA].ptE))
|
||||
return false ;
|
||||
vLineAbove.emplace_back( Release( pLA)) ;
|
||||
}
|
||||
}
|
||||
ICURVEPOVECTOR vLineUnder ;
|
||||
if ( nI > 0) {
|
||||
for ( int u = 0 ; u < int( vvSec[nI-1].size()) ; ++ u) {
|
||||
if ( vvSec[nI-1][u].bActive)
|
||||
for ( int nU = 0 ; nU < ssize( vvSec[nI - 1]) ; ++ nU) {
|
||||
if ( vvSec[nI - 1][nU].bActive)
|
||||
continue ;
|
||||
PtrOwner<ICurveLine> pLU( CreateCurveLine()) ;
|
||||
pLU->Set( vvSec[nI-1][u].ptS, vvSec[nI-1][u].ptE) ;
|
||||
if ( IsNull( pLU) || ! pLU->Set( vvSec[nI - 1][nU].ptS, vvSec[nI - 1][nU].ptE))
|
||||
return false ;
|
||||
vLineUnder.emplace_back( Release( pLU)) ;
|
||||
}
|
||||
}
|
||||
@@ -7037,13 +7032,13 @@ CalcZigZag( const ISurfFlatRegion* pSrfZigZag, const PocketParams& PockParams, I
|
||||
if ( IsNull( pLineCompo))
|
||||
return false ;
|
||||
|
||||
Point3d ptE_l ;
|
||||
Point3d ptEL ;
|
||||
if ( bFirstLine)
|
||||
ptE_l = vvSec[nI][nJ].ptS ;
|
||||
ptEL = vvSec[nI][nJ].ptS ;
|
||||
else
|
||||
vpCrvs.back()->GetEndPoint( ptE_l) ;
|
||||
vpCrvs.back()->GetEndPoint( ptEL) ;
|
||||
|
||||
pLineCompo->AddPoint( ptE_l) ;
|
||||
pLineCompo->AddPoint( ptEL) ;
|
||||
pLineCompo->AddLine( vvSec[nI][nJ].ptE) ;
|
||||
// assegno la feed al tratto lineare
|
||||
if ( ! AssignFeedZigZagOneWay( pLineCompo, false, vLineAbove, vLineUnder, vAddedLinks, PockParams)) // Assegno la Feed
|
||||
@@ -7054,7 +7049,7 @@ CalcZigZag( const ISurfFlatRegion* pSrfZigZag, const PocketParams& PockParams, I
|
||||
|
||||
if ( nStatus == 0) { // primo segmento per il raccordo smussato
|
||||
pLastSeg.Set( pLineCompo) ;
|
||||
pLastSeg->GetStartPoint( ptS_ref) ;
|
||||
pLastSeg->GetStartPoint( ptSRef) ;
|
||||
}
|
||||
if ( nStatus == 2) { // ho precedentemente aggiunto il bordo di un'isola, quindi mi salvo il secondo segmento
|
||||
|
||||
@@ -7076,8 +7071,8 @@ CalcZigZag( const ISurfFlatRegion* pSrfZigZag, const PocketParams& PockParams, I
|
||||
vpCrvs.back()->Clear() ;
|
||||
|
||||
if ( bFromInfill)
|
||||
for ( int u = 0 ; u < pCrvLink->GetCurveCount() ; ++ u)
|
||||
pCrvLink->SetCurveTempProp( u, -1, 1) ;
|
||||
for ( int k = 0 ; k < pCrvLink->GetCurveCount() ; ++ k)
|
||||
pCrvLink->SetCurveTempProp( k, TEMP_PROP_INVALID, 1) ;
|
||||
|
||||
if ( ! AssignFeedZigZagOneWay( pCrvLink, true, vLineAbove, vLineUnder, vAddedLinks, PockParams))
|
||||
return false ;
|
||||
@@ -7086,11 +7081,9 @@ CalcZigZag( const ISurfFlatRegion* pSrfZigZag, const PocketParams& PockParams, I
|
||||
vpCrvs.back()->AddCurve( pSeg2->Clone()) ; // aggiungo pSeg2
|
||||
|
||||
// aggiorno il vettore dei Link ( nel caso sia un link tra due segmenti sullo stesso livello )
|
||||
Point3d ptS1 ;
|
||||
pSeg1->GetStartPoint( ptS1) ;
|
||||
Point3d ptS2 ;
|
||||
pSeg2->GetStartPoint( ptS2) ;
|
||||
if ( abs( ptS1.y - ptS2.y) < 50 * EPS_SMALL)
|
||||
Point3d ptS1 ; pSeg1->GetStartPoint( ptS1) ;
|
||||
Point3d ptS2 ; pSeg2->GetStartPoint( ptS2) ;
|
||||
if ( abs( ptS1.y - ptS2.y) < 50. * EPS_SMALL)
|
||||
vAddedLinks.emplace_back( pCrvLink->Clone()) ;
|
||||
|
||||
// pSeg2 ora diventa pSeg1 e il procedimento si itera per tutto il percorso
|
||||
@@ -7105,21 +7098,21 @@ CalcZigZag( const ISurfFlatRegion* pSrfZigZag, const PocketParams& PockParams, I
|
||||
double dUref = ( bPlus ? INFINITO : -INFINITO) ;
|
||||
int nNextI = -1 ;
|
||||
int nNextJ = -1 ;
|
||||
int li = nJ + 1 ;
|
||||
for ( int k = nI ; k <= nI + 1 && k < int( vvSec.size()) ; ++ k) {
|
||||
for ( int l = li ; l < int( vvSec[k].size()) ; ++ l) {
|
||||
if ( ! vvSec[k][l].bActive) // se sezione non attiva... non la considero
|
||||
int nLi = nJ + 1 ;
|
||||
for ( int k = nI ; k <= nI + 1 && k < ssize( vvSec) ; ++ k) {
|
||||
for ( int nL = nLi ; nL < ssize( vvSec[k]) ; ++ nL) {
|
||||
if ( ! vvSec[k][nL].bActive) // se sezione non attiva... non la considero
|
||||
continue ;
|
||||
if ( vvSec[k][l].nOffIndS != nIndexIslandE) // se isola diversa... non la considero
|
||||
if ( vvSec[k][nL].nOffIndS != nIndexIslandE) // se isola diversa... non la considero
|
||||
continue ;
|
||||
double dU = vvSec[k][l].dOs ;
|
||||
double dU = vvSec[k][nL].dOs ;
|
||||
if ( bPlus) {
|
||||
if ( dU < dUstart)
|
||||
dU += dUspan ;
|
||||
if ( dU < dUref) {
|
||||
dUref = dU ;
|
||||
nNextI = k ;
|
||||
nNextJ = l ;
|
||||
nNextJ = nL ;
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -7128,15 +7121,15 @@ CalcZigZag( const ISurfFlatRegion* pSrfZigZag, const PocketParams& PockParams, I
|
||||
if ( dU > dUref) {
|
||||
dUref = dU ;
|
||||
nNextI = k ;
|
||||
nNextJ = l ;
|
||||
nNextJ = nL ;
|
||||
}
|
||||
}
|
||||
}
|
||||
li = 0 ;
|
||||
nLi = 0 ;
|
||||
}
|
||||
// se trovato, controllo il contorno dell'isola
|
||||
if ( nNextI != -1) {
|
||||
PtrOwner<ICurve> pCopy ;
|
||||
PtrOwner<ICurve> pCopy( nullptr) ;
|
||||
if ( bPlus) {
|
||||
if ( dUref > dUmax)
|
||||
dUref -= dUspan ;
|
||||
@@ -7165,7 +7158,8 @@ CalcZigZag( const ISurfFlatRegion* pSrfZigZag, const PocketParams& PockParams, I
|
||||
BBox3d b3Copy ;
|
||||
if ( ! IsNull( pCopy))
|
||||
pCopy->GetLocalBBox( b3Copy) ;
|
||||
if ( ! b3Copy.IsEmpty() && ( b3Copy.GetMax().y - b3Copy.GetMin().y) < dYStep + 10 * EPS_SMALL) { // tengo la curva (non ritorno indietro più dello step)
|
||||
if ( ! b3Copy.IsEmpty() && ( b3Copy.GetMax().y - b3Copy.GetMin().y) < dYStep + 10. * EPS_SMALL) {
|
||||
// tengo la curva, non torno indietro dello Step
|
||||
Point3d ptS, ptE ;
|
||||
pCrvLink->Clear() ;
|
||||
pCrvLink->AddCurve( pCopy->Clone()) ;
|
||||
@@ -7502,8 +7496,7 @@ GetZigZagOneWayBorderCrvs( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegio
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static bool
|
||||
AddZigZag( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, PocketParams& PockParams,
|
||||
ICRVCOMPOPOVECTOR& vCrvCompoRes)
|
||||
AddZigZag( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, PocketParams& PockParams, ICRVCOMPOPOVECTOR& vCrvCompoRes)
|
||||
{
|
||||
// ricavo il numero di Chunk da svuotare
|
||||
if ( pSrfPock == nullptr)
|
||||
@@ -7554,7 +7547,7 @@ AddZigZag( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, PocketPar
|
||||
if ( ! IsChunkAllHomogeneous( pSrfPock, nChunkInd, bIsChunkClosed, bIsChunkAllOpen))
|
||||
return false ;
|
||||
// se il Chunk originale aveva lati aperti, estendo il percorso a ZigZag
|
||||
for ( int nU = 0 ; nU < int( vpCrvs.size()) ; ++ nU) {
|
||||
for ( int nU = 0 ; nU < ssize( vpCrvs) ; ++ nU) {
|
||||
Vector3d vtRef ; vpCrvs[nU]->GetStartDir( vtRef) ;
|
||||
vtRef.Invert() ;
|
||||
bool bIsExtended = false ;
|
||||
@@ -7568,7 +7561,7 @@ AddZigZag( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, PocketPar
|
||||
// se lucidatura
|
||||
if ( PockParams.bPolishing) {
|
||||
// ciclo sui percorsi
|
||||
for ( int k = 0 ; k < int( vpCrvs.size()) ; ++ k) {
|
||||
for ( int k = 0 ; k < ssize( vpCrvs) ; ++ k) {
|
||||
// se attacco a scivolo
|
||||
if ( PockParams.nLiType == LEAD_IN_GLIDE) {
|
||||
double dU ;
|
||||
@@ -7722,7 +7715,7 @@ AddOneWay( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, PocketPar
|
||||
b3Pocket.GetMinDim( ptMin, dDimX, dDimY, dDimZ) ;
|
||||
|
||||
// passi in Y
|
||||
int nYStep = static_cast<int>( ceil(( dDimY + 2 * dExtra) / PockParams.dSideStep)) ;
|
||||
int nYStep = static_cast<int>( ceil( ( dDimY + 2 * dExtra) / PockParams.dSideStep)) ;
|
||||
double dYStep = ( nYStep > 0 ? ( dDimY + 2 * dExtra) / nYStep : 0) ;
|
||||
-- nYStep ;
|
||||
|
||||
@@ -7737,7 +7730,7 @@ AddOneWay( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, PocketPar
|
||||
|
||||
// definisco la linea
|
||||
PtrOwner<ICurveLine> pLine( CreateCurveLine()) ;
|
||||
Point3d ptStart( ptMin.x - EXP_LEN, ptMin.y + ( - dExtra + i * dYStep), ptMin.z + dDimZ) ;
|
||||
Point3d ptStart( ptMin.x - EXP_LEN, ptMin.y + ( - dExtra + i * dYStep), ptMin.z + dDimZ) ;
|
||||
if ( IsNull( pLine) || ! pLine->SetPVL( ptStart, X_AX, dDimX + 2 * EXP_LEN))
|
||||
return false ;
|
||||
|
||||
@@ -9808,7 +9801,7 @@ CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double
|
||||
myParams.dRadialOffset = dRadOffs + ( myParams.bToolCompensation ? dStep : 0.0) ;
|
||||
myParams.bSmooth = bSmooth ;
|
||||
myParams.dAngle = dAngle ;
|
||||
myParams.dSideStep = dStep ;
|
||||
myParams.dSideStep = Clamp( dStep, 10. * EPS_SMALL, 2. * dRad) ;
|
||||
myParams.dOpenMinSafe = dOpenMinSafe ;
|
||||
myParams.bCalcUnclearedRegs = bCalcUnclReg ;
|
||||
myParams.bInvert = bInvert ;
|
||||
@@ -9835,10 +9828,11 @@ CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double
|
||||
! myParams.frLocXY.Rotate( ptCenter, pSfr->GetNormVersor() , myParams.dAngle))
|
||||
return false ;
|
||||
|
||||
// porto la superficie da svuotare nel sistema di riferimento lungo Z_AX
|
||||
PtrOwner<ISurfFlatRegion> pSfrAdj( pSfr->Clone()) ;
|
||||
if ( IsNull( pSfrAdj) || ! pSfrAdj->ToLoc( myParams.frLocXY))
|
||||
// porto la superficie da svuotare nel sistema di riferimento locale
|
||||
PtrOwner<ISurfFlatRegion> pSfrAdjLoc( pSfr->Clone()) ;
|
||||
if ( IsNull( pSfrAdjLoc) || ! pSfrAdjLoc->ToLoc( myParams.frLocXY))
|
||||
return false ;
|
||||
|
||||
// porto la superficie limite ( se valida) in tale sistema
|
||||
if ( myParams.SfrLimit.IsValid())
|
||||
myParams.SfrLimit.ToLoc( myParams.frLocXY) ;
|
||||
@@ -9852,20 +9846,20 @@ CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double
|
||||
// Se richiesti contorni tengo una copia della supericie attuale ( le funzioni sotto potrebbero rimuoverne dei Chunks)
|
||||
PtrOwner<ISurfFlatRegion> pSfrContour( nullptr) ;
|
||||
if ( myParams.bToolCompensation) {
|
||||
if ( ! pSfrContour.Set( CloneSurfFlatRegion( pSfrAdj)) || ! pSfrAdj->IsValid())
|
||||
if ( ! pSfrContour.Set( CloneSurfFlatRegion( pSfrAdjLoc)) || ! pSfrAdjLoc->IsValid())
|
||||
return false ;
|
||||
}
|
||||
|
||||
// ------------ casi ottimizzati ------------------------------------------
|
||||
ICRVCOMPOPOVECTOR vCrvOptCurves ;
|
||||
if ( ! GetPocketingOptimizedCurves( pSfrAdj, myParams, vCrvOptCurves))
|
||||
if ( ! GetPocketingOptimizedCurves( pSfrAdjLoc, myParams, vCrvOptCurves))
|
||||
return false ;
|
||||
for ( int i = 0 ; i < ssize( vCrvOptCurves) ; ++ i) {
|
||||
vCrvOptCurves[i]->ToGlob( myParams.frLocXY) ;
|
||||
vCrvCompoRes.emplace_back( Release( vCrvOptCurves[i])) ;
|
||||
}
|
||||
// se ho svuotato tutta la superficie, allora ho finito
|
||||
if ( IsNull( pSfrAdj) || ! pSfrAdj->IsValid() || pSfrAdj->GetChunkCount() == 0) {
|
||||
if ( IsNull( pSfrAdjLoc) || ! pSfrAdjLoc->IsValid() || pSfrAdjLoc->GetChunkCount() == 0) {
|
||||
// se necessario aggiungo i bordi ed esco
|
||||
if ( myParams.bToolCompensation)
|
||||
return AddContours( pSfrContour, myParams, vCrvCompoRes) ;
|
||||
@@ -9874,14 +9868,14 @@ CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double
|
||||
|
||||
// ------------ recupero le singole curve di svuotatura -------------------
|
||||
ICRVCOMPOPOVECTOR vCrvSingleCurves ;
|
||||
if ( ! GetSinglePocketingCurves( pSfrAdj, myParams, vCrvSingleCurves))
|
||||
if ( ! GetSinglePocketingCurves( pSfrAdjLoc, myParams, vCrvSingleCurves))
|
||||
return false ;
|
||||
for ( int i = 0 ; i < ssize( vCrvSingleCurves) ; ++ i) {
|
||||
vCrvSingleCurves[i]->ToGlob( myParams.frLocXY) ;
|
||||
vCrvCompoRes.emplace_back( Release( vCrvSingleCurves[i])) ;
|
||||
}
|
||||
// se ho svuotato tutta la superficie, allora ho finito
|
||||
if ( IsNull( pSfrAdj) || ! pSfrAdj->IsValid() || pSfrAdj->GetChunkCount() == 0) {
|
||||
if ( IsNull( pSfrAdjLoc) || ! pSfrAdjLoc->IsValid() || pSfrAdjLoc->GetChunkCount() == 0) {
|
||||
// se necessario aggiunfo i bordi ed esco
|
||||
if ( myParams.bToolCompensation)
|
||||
return AddContours( pSfrContour, myParams, vCrvCompoRes) ;
|
||||
@@ -9889,7 +9883,7 @@ CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double
|
||||
}
|
||||
|
||||
// ------------ estensione lati aperti ------------------------------------
|
||||
if ( ! ModifySurfByOpenEdges( pSfrAdj, myParams))
|
||||
if ( ! ModifySurfByOpenEdges( pSfrAdjLoc, myParams))
|
||||
return false ;
|
||||
|
||||
// porto una copia della superficie originale nel frame creato
|
||||
@@ -9901,24 +9895,24 @@ CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double
|
||||
ICRVCOMPOPOVECTOR vCrvCompoPock ;
|
||||
switch ( nType) {
|
||||
case POCKET_ZIGZAG :
|
||||
if ( ! AddZigZag( pSfrAdj, pSfrLoc, myParams, vCrvCompoPock))
|
||||
if ( ! AddZigZag( pSfrAdjLoc, pSfrLoc, myParams, vCrvCompoPock))
|
||||
return false ;
|
||||
break ;
|
||||
case POCKET_ONEWAY :
|
||||
if ( ! AddOneWay( pSfrAdj, pSfrLoc, myParams, vCrvCompoPock))
|
||||
if ( ! AddOneWay( pSfrAdjLoc, pSfrLoc, myParams, vCrvCompoPock))
|
||||
return false ;
|
||||
break ;
|
||||
case POCKET_SPIRALIN :
|
||||
if ( ! AddSpiralIn( pSfrAdj, pSfrLoc, myParams, vCrvCompoPock))
|
||||
if ( ! AddSpiralIn( pSfrAdjLoc, pSfrLoc, myParams, vCrvCompoPock))
|
||||
return false ;
|
||||
break ;
|
||||
case POCKET_SPIRALOUT :
|
||||
if ( ! AddSpiralOut( pSfrAdj, pSfrLoc, myParams, vCrvCompoPock))
|
||||
if ( ! AddSpiralOut( pSfrAdjLoc, pSfrLoc, myParams, vCrvCompoPock))
|
||||
return false ;
|
||||
break ;
|
||||
case POCKET_CONFORMAL_ZIGZAG :
|
||||
case POCKET_CONFORMAL_ONEWAY :
|
||||
if ( ! AddConformal( pSfrAdj, pSfrLoc, myParams, vCrvCompoPock))
|
||||
if ( ! AddConformal( pSfrAdjLoc, pSfrLoc, myParams, vCrvCompoPock))
|
||||
return false ;
|
||||
break ;
|
||||
}
|
||||
|
||||
+60
-19
@@ -2703,6 +2703,18 @@ GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert)
|
||||
return true ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
double
|
||||
CalcWeightVal( double dLen, const ICurve* pCrv, const Vector3d vtCurr1, const Point3d& ptCurr1, double dCoeff, double dMyDist, double& dUStep2)
|
||||
{
|
||||
pCrv->GetParamAtLength( dLen, dUStep2) ;
|
||||
Point3d ptStep2 ; Vector3d vtStep2 = V_NULL ;
|
||||
pCrv->GetPointD1D2( dUStep2, ICurve::FROM_MINUS, ptStep2, &vtStep2) ; vtStep2.Normalize() ;
|
||||
double dStepCos2 = vtCurr1 * vtStep2 ;
|
||||
double dDist = Dist( ptCurr1, ptStep2) ;
|
||||
return (1 - dStepCos2) + dCoeff * dDist / dMyDist ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
GetIsoPointOnSecondCurve( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2, double dUCurr1, double& dUCurr2, double dMyDist, double dUPrev2,
|
||||
@@ -2711,6 +2723,7 @@ GetIsoPointOnSecondCurve( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2, doub
|
||||
Point3d ptCurr1 ;
|
||||
Vector3d vtCurr1 ;
|
||||
pCrvEdge1->GetPointD1D2( dUCurr1, ICurve::FROM_MINUS, ptCurr1, &vtCurr1) ;
|
||||
vtCurr1.Normalize() ;
|
||||
// --- Piano di taglio per punto a minima distanza
|
||||
IntersCurvePlane ICP( *pCrvEdge2, ptCurr1, vtCurr1) ;
|
||||
int nIndParCloser = - 1, nIndPointCloser = -1 ;
|
||||
@@ -2786,31 +2799,59 @@ GetIsoPointOnSecondCurve( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2, doub
|
||||
|
||||
// Verifico se le direzioni tangenti sono tra di loro circa parallele
|
||||
const double COS_ANG_TOL = cos( 15. * DEGTORAD) ;
|
||||
if ( vtCurr1 * vtCurr2 < COS_ANG_TOL) {
|
||||
// Se fuori dalla tolleranza, recupero il miglior versore tangente sul secondo bordo nell'intervallo successivo di lunghezza ( 2. * dMyDist)
|
||||
const double COS_SMALL_ANG_TOL = cos( 4. * DEGTORAD) ;
|
||||
double dSearchLen = dMyDist / 2 ;
|
||||
int NUM_STEP = 10 ;
|
||||
const double dCoeff = 0.1 ;
|
||||
double dCos = vtCurr1 * vtCurr2 ;
|
||||
double dDistCurr = Dist( ptCurr1, ptCurr2) ;
|
||||
double dMin = (1 - dCos) + dCoeff * dDistCurr / dMyDist ;
|
||||
double bUpdated = false ;
|
||||
// se poco fuori tolleranza controllo se ho un punto abbastanza vicino con la stessa tangente
|
||||
if ( vtCurr1 * vtCurr2 < COS_SMALL_ANG_TOL) {
|
||||
// Se tanto fuori dalla tolleranza, recupero il miglior versore tangente sul secondo bordo nell'intervallo successivo di lunghezza ( 2. * dMyDist)
|
||||
if ( vtCurr1 * vtCurr2 < COS_ANG_TOL) {
|
||||
dSearchLen = dMyDist ;
|
||||
NUM_STEP = 20 ;
|
||||
}
|
||||
pCrvEdge2->GetLengthAtPoint( ptCurr2, dLenCurr2) ;
|
||||
double dLimInfLen2 = Clamp( dLenCurr2 - dMyDist, dLenPrev2, dLen2) ;
|
||||
double dLimSupLen2 = Clamp( dLenCurr2 + dMyDist, dLenPrev2, dLen2) ;
|
||||
// [Controllo migliorabile, magari mendiante metodo di bisezione (?)]
|
||||
const int NUM_STEP = 20 ;
|
||||
double dMinCos = - 1. - EPS_ZERO ;
|
||||
const double DEGTOL = 5. ;
|
||||
double dLimInfLen2 = Clamp( dLenCurr2 - dSearchLen, dLenPrev2, dLen2) ;
|
||||
double dLimSupLen2 = Clamp( dLenCurr2 + dSearchLen, dLenPrev2, dLen2) ;
|
||||
|
||||
// faccio un campionamento grossolano e poi campiono più finemente in prossimità dei minimi
|
||||
DBLVECTOR vVal ;
|
||||
for ( int i = 0 ; i <= NUM_STEP ; ++ i) {
|
||||
double dLen = dLimInfLen2 + i * ( dLimSupLen2 - dLimInfLen2) / NUM_STEP ;
|
||||
double dUStep2 ; pCrvEdge2->GetParamAtLength( dLen, dUStep2) ;
|
||||
Point3d ptStep2 ; Vector3d vtStep2 = V_NULL ;
|
||||
pCrvEdge2->GetPointD1D2( dUStep2, ICurve::FROM_MINUS, ptStep2, &vtStep2) ; vtStep2.Normalize() ;
|
||||
double dStepCos2 = vtCurr1 * vtStep2 ;
|
||||
double dAngTol = ( i < NUM_STEP / 2 ? ( 2. * DEGTOL) / NUM_STEP * i :
|
||||
( - 2. * DEGTOL) / NUM_STEP * ( i - NUM_STEP)) ;
|
||||
double dCosTol = 1. - cos( dAngTol * DEGTORAD) ;
|
||||
if ( dStepCos2 + dCosTol > dMinCos) {
|
||||
ptCurr2 = ptStep2 ;
|
||||
vtCurr2 = vtStep2 ;
|
||||
double dUStep2 ;
|
||||
vVal.push_back( CalcWeightVal( dLen, pCrvEdge2, vtCurr1, ptCurr1, dCoeff, dMyDist, dUStep2)) ;
|
||||
if ( vVal.back() < dMin) {
|
||||
dMin = vVal.back() ;
|
||||
dUCurr2 = dUStep2 ;
|
||||
dMinCos = dStepCos2 + dCosTol ;
|
||||
}
|
||||
}
|
||||
DBLDBLVECTOR vInterv ;
|
||||
for ( int i = 1 ; i < ssize(vVal) - 1 ; ++i) {
|
||||
if ( vVal[i] < vVal[i-1] && vVal[i] < vVal[i+1])
|
||||
vInterv.emplace_back( dLimInfLen2 + ( i - 1) * ( dLimSupLen2 - dLimInfLen2) / NUM_STEP,
|
||||
dLimInfLen2 + ( i + 1) * ( dLimSupLen2 - dLimInfLen2) / NUM_STEP) ;
|
||||
}
|
||||
if ( ssize( vInterv) != 0) {
|
||||
for ( int j = 0 ; j < ssize( vInterv) ; ++j) {
|
||||
for ( int i = 0 ; i <= NUM_STEP ; ++ i) {
|
||||
double dLen = vInterv[j].first + i * ( vInterv[j].second - vInterv[j].first) / NUM_STEP ;
|
||||
double dUStep2 ;
|
||||
double dVal = CalcWeightVal( dLen, pCrvEdge2, vtCurr1, ptCurr1, dCoeff, dMyDist, dUStep2) ;
|
||||
if ( dVal < dMin) {
|
||||
dUCurr2 = dUStep2 ;
|
||||
dMin = dVal ;
|
||||
bUpdated = true ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// se il parametro è cambiato devo ricalcolare la lunghezza, che viene restituita
|
||||
if ( bUpdated)
|
||||
pCrvEdge2->GetLengthAtParam( dUCurr2, dLenCurr2) ;
|
||||
return true ;
|
||||
}
|
||||
Binary file not shown.
@@ -324,6 +324,7 @@ copy $(TargetPath) \EgtProg\Dll64</Command>
|
||||
<ClCompile Include="IntersLineVolZmap.cpp" />
|
||||
<ClCompile Include="IntersPlaneVolZmap.cpp" />
|
||||
<ClCompile Include="IntersLineSurfBez.cpp" />
|
||||
<ClCompile Include="OffsetCurve3d.cpp" />
|
||||
<ClCompile Include="Trimming.cpp" />
|
||||
<ClCompile Include="MultiGeomDB.cpp" />
|
||||
<ClCompile Include="SurfTriMeshOffset.cpp" />
|
||||
|
||||
@@ -576,6 +576,9 @@
|
||||
<ClCompile Include="Trimming.cpp">
|
||||
<Filter>File di origine\GeoStriping</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="OffsetCurve3d.cpp">
|
||||
<Filter>File di origine\GeoOffset</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="stdafx.h">
|
||||
|
||||
+171
-53
@@ -15,6 +15,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "IntersLineCyl.h"
|
||||
#include "/EgtDev/Include/EGkFrame3d.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineCylinder.h"
|
||||
#include "/EgtDev/Include/ENkPolynomialRoots.h"
|
||||
|
||||
using namespace std ;
|
||||
@@ -25,99 +26,176 @@ using namespace std ;
|
||||
// In caso di intersezione viene restituito true e i parametri in dU1 e dU2.
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
||||
double dRad, double dHeight,
|
||||
double& dU1, double& dU2)
|
||||
IntersLineCyl( const Point3d& ptP, const Vector3d& vtV, double dH, double dRad, bool bTapLow, bool bTapUp,
|
||||
double& dU1, Point3d& ptInt1, Vector3d& vtN1, double& dU2, Point3d& ptInt2, Vector3d& vtN2, bool bIgnoreTap, bool bInvertNormals)
|
||||
{
|
||||
// Verifico il versore
|
||||
if ( vtL.IsSmall())
|
||||
dU1 = NAN ;
|
||||
dU2 = NAN ;
|
||||
|
||||
// Verifico il versore
|
||||
if ( vtV.IsSmall())
|
||||
return false ;
|
||||
|
||||
// Verifico il cilindro
|
||||
if ( dRad < EPS_SMALL || dHeight < EPS_SMALL)
|
||||
// Verifico il cilindro
|
||||
if ( dRad < EPS_SMALL || dH < EPS_SMALL)
|
||||
return false ;
|
||||
|
||||
// Determino le eventuali intersezioni con le due basi a quota minima e massima (solo se linea non parallela ad esse)
|
||||
// Determino le eventuali intersezioni con le due basi a quota minima e massima (solo se linea non parallela ad esse)
|
||||
int nBasInt = 0 ;
|
||||
if ( abs( vtL.z) > EPS_ZERO) {
|
||||
if ( abs( vtV.z) > EPS_ZERO) {
|
||||
// le linee tangenti al cilindro non sono considerate intersecanti
|
||||
double EpsRad = ( vtL.IsZeroXY() ? - EPS_SMALL : EPS_SMALL) ;
|
||||
Point3d ptInt1 = ptL + ( ( 0 - ptL.z) / vtL.z) * vtL ;
|
||||
if ( ptInt1.x * ptInt1.x + ptInt1.y * ptInt1.y < dRad * dRad + 2 * dRad * EpsRad) {
|
||||
dU1 = ( ptInt1 - ptL) * vtL ;
|
||||
double dEpsRad = ( vtV.IsZeroXY() ? - EPS_SMALL : EPS_SMALL) ;
|
||||
if ( bIgnoreTap)
|
||||
dEpsRad = 0. ;
|
||||
ptInt1 = ptP + ( ( 0 - ptP.z) / vtV.z) * vtV ;
|
||||
if ( ptInt1.x * ptInt1.x + ptInt1.y * ptInt1.y < dRad * dRad + 2 * dRad * dEpsRad) {
|
||||
nBasInt += 1 ;
|
||||
vtN1 = - Z_AX ;
|
||||
dU1 = ( ( 0 - ptP.z) / vtV.z) ;
|
||||
}
|
||||
Point3d ptInt2 = ptL + ( ( dHeight - ptL.z) / vtL.z) * vtL ;
|
||||
if ( ptInt2.x * ptInt2.x + ptInt2.y * ptInt2.y < dRad * dRad + 2 * dRad * EpsRad) {
|
||||
dU2 = ( ptInt2 - ptL) * vtL ;
|
||||
ptInt2 = ptP + ( ( dH - ptP.z) / vtV.z) * vtV ;
|
||||
if ( ptInt2.x * ptInt2.x + ptInt2.y * ptInt2.y < dRad * dRad + 2 * dRad * dEpsRad) {
|
||||
nBasInt += 2 ;
|
||||
vtN2 = Z_AX ;
|
||||
dU2 = ( ( dH - ptP.z) / vtV.z) ;
|
||||
}
|
||||
}
|
||||
|
||||
// Se la linea interseca entrambe le basi, si sono trovate le due intersezioni
|
||||
// Se la linea interseca entrambe le basi, si sono trovate le due intersezioni
|
||||
if ( nBasInt == 3) {
|
||||
if ( dU1 > dU2)
|
||||
if ( dU1 > dU2) {
|
||||
swap( dU1, dU2) ;
|
||||
// Trovate intersezioni
|
||||
swap( ptInt1, ptInt2) ;
|
||||
swap( vtN1, vtN2) ;
|
||||
}
|
||||
if ( bInvertNormals) {
|
||||
vtN1 *= - 1 ;
|
||||
vtN2 *= - 1 ;
|
||||
}
|
||||
// Trovate intersezioni
|
||||
return true ;
|
||||
}
|
||||
|
||||
// Determino le intersezioni con la superficie laterale del cilindro
|
||||
DBLVECTOR vdCoeff{ ptL.x * ptL.x + ptL.y * ptL.y - dRad * dRad,
|
||||
2 * ( ptL.x * vtL.x + ptL.y * vtL.y),
|
||||
vtL.x * vtL.x + vtL.y * vtL.y} ;
|
||||
|
||||
// Determino le intersezioni con la superficie laterale del cilindro
|
||||
DBLVECTOR vdCoeff{ ptP.x * ptP.x + ptP.y * ptP.y - dRad * dRad,
|
||||
2 * ( ptP.x * vtV.x + ptP.y * vtV.y),
|
||||
vtV.x * vtV.x + vtV.y * vtV.y} ;
|
||||
DBLVECTOR vdRoots ;
|
||||
int nRoot = PolynomialRoots( 2, vdCoeff, vdRoots) ;
|
||||
|
||||
// Elimino le soluzioni cha danno intersezioni fuori dai limiti in Z del cilindro
|
||||
// Epsilon per piani di tappo
|
||||
double dEpsLow = ( bTapLow ? - EPS_SMALL : EPS_SMALL) ;
|
||||
double dEpsUp = ( bTapUp ? EPS_SMALL : - EPS_SMALL) ;
|
||||
if ( bIgnoreTap) {
|
||||
dEpsLow = 0. ;
|
||||
dEpsUp = 0. ;
|
||||
}
|
||||
|
||||
// Elimino le soluzioni cha danno intersezioni fuori dai limiti in Z del cilindro
|
||||
if ( nRoot == 2) {
|
||||
double dIntZ2 = ptL.z + vdRoots[1] * vtL.z ;
|
||||
if ( dIntZ2 < 0 - EPS_SMALL || dIntZ2 > dHeight + EPS_SMALL)
|
||||
double dIntZ2 = ptP.z + vdRoots[1] * vtV.z ;
|
||||
if ( dIntZ2 < 0 + dEpsLow || dIntZ2 > dH + dEpsUp)
|
||||
-- nRoot ;
|
||||
}
|
||||
if ( nRoot >= 1) {
|
||||
double dIntZ1 = ptL.z + vdRoots[0] * vtL.z ;
|
||||
if ( dIntZ1 < 0 - EPS_SMALL || dIntZ1 > dHeight + EPS_SMALL) {
|
||||
double dIntZ1 = ptP.z + vdRoots[0] * vtV.z ;
|
||||
if ( dIntZ1 < 0 + dEpsLow || dIntZ1 > dH + dEpsUp) {
|
||||
if ( nRoot == 2)
|
||||
vdRoots[0] = vdRoots[1] ;
|
||||
-- nRoot ;
|
||||
}
|
||||
}
|
||||
|
||||
// Due soluzioni: la retta interseca due volte la superficie laterale
|
||||
// Due soluzioni: la retta interseca due volte la superficie laterale
|
||||
if ( nRoot == 2) {
|
||||
// Punti di intersezione con la superficie del cilindro
|
||||
ptInt1 = ptP + vdRoots[0] * vtV ;
|
||||
ptInt2 = ptP + vdRoots[1] * vtV ;
|
||||
dU1 = vdRoots[0] ;
|
||||
dU2 = vdRoots[1] ;
|
||||
if ( dU1 > dU2)
|
||||
// Determino le normali
|
||||
vtN1.Set( ptInt1.x, ptInt1.y, 0) ;
|
||||
vtN1.Normalize() ;
|
||||
vtN2.Set( ptInt2.x, ptInt2.y, 0) ;
|
||||
vtN2.Normalize() ;
|
||||
if ( dU1 > dU2) {
|
||||
swap( dU1, dU2) ;
|
||||
// Trovate intersezioni
|
||||
return true ;
|
||||
}
|
||||
|
||||
// Una soluzione : la retta interseca la superficie laterale e un piano
|
||||
else if ( nRoot == 1) {
|
||||
// Se piano superiore
|
||||
if ( nBasInt == 2) {
|
||||
dU1 = vdRoots[0] ;
|
||||
swap( ptInt1, ptInt2) ;
|
||||
swap( vtN1, vtN2) ;
|
||||
}
|
||||
// altrimenti piano inferiore
|
||||
else if ( nBasInt == 1) {
|
||||
dU2 = vdRoots[0] ;
|
||||
if ( bInvertNormals) {
|
||||
vtN1 *= - 1 ;
|
||||
vtN2 *= - 1 ;
|
||||
}
|
||||
// altrimenti niente
|
||||
else
|
||||
return false ;
|
||||
if ( dU1 > dU2)
|
||||
swap( dU1, dU2) ;
|
||||
// Trovate intersezioni
|
||||
// Trovate intersezioni
|
||||
return true ;
|
||||
}
|
||||
|
||||
// Nessuna soluzione : nessuna intersezione
|
||||
// Una soluzione : la retta interseca la superficie laterale e un piano
|
||||
else if ( nRoot == 1) {
|
||||
// Se piano superiore
|
||||
if ( nBasInt == 2) {
|
||||
// Punto di intersezione
|
||||
dU1 = vdRoots[0] ;
|
||||
ptInt1 = ptP + vdRoots[0] * vtV ;
|
||||
// Normale alla superficie del cilindro verso l'interno
|
||||
vtN1.Set( ptInt1.x, ptInt1.y, 0) ;
|
||||
vtN1.Normalize() ;
|
||||
}
|
||||
// altrimenti piano inferiore
|
||||
else if ( nBasInt == 1) {
|
||||
// Punto di intersezione
|
||||
dU2 = vdRoots[0] ;
|
||||
ptInt2 = ptP + vdRoots[0] * vtV ;
|
||||
// Normale alla superficie del cilindro verso l'interno
|
||||
vtN2.Set( ptInt2.x, ptInt2.y, 0) ;
|
||||
vtN2.Normalize() ;
|
||||
}
|
||||
// altrimenti niente
|
||||
else
|
||||
return false ;
|
||||
if ( dU1 > dU2) {
|
||||
swap( dU1, dU2) ;
|
||||
swap( ptInt1, ptInt2) ;
|
||||
swap( vtN1, vtN2) ;
|
||||
}
|
||||
if ( bInvertNormals) {
|
||||
vtN1 *= - 1 ;
|
||||
vtN2 *= - 1 ;
|
||||
}
|
||||
// Trovate intersezioni
|
||||
return true ;
|
||||
}
|
||||
|
||||
// Nessuna soluzione : nessuna intersezione
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Riferimento con origine nel centro della base e asse di simmetria coincidente con l'asse Z.
|
||||
// La funzione restituisce true in caso di intersezione, false altrimenti.
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersLineCyl( const Point3d& ptLineSt, const Vector3d& vtLineDir,
|
||||
const Frame3d& CylFrame, double dH, double dRad, bool bTapLow, bool bTapUp,
|
||||
double& dU1, Point3d& ptInt1, Vector3d& vtN1, double& dU2, Point3d& ptInt2, Vector3d& vtN2, bool bIgnoreTap, bool bInvertNormals)
|
||||
{
|
||||
// Porto la linea nel riferimento del cilindro
|
||||
Point3d ptP = GetToLoc( ptLineSt, CylFrame) ;
|
||||
Vector3d vtV = GetToLoc( vtLineDir, CylFrame) ;
|
||||
if ( IntersLineCyl( ptP, vtV, dH, dRad, bTapLow, bTapUp,
|
||||
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, bIgnoreTap, bInvertNormals))
|
||||
{
|
||||
ptInt1.ToGlob( CylFrame) ;
|
||||
vtN1.ToGlob( CylFrame) ;
|
||||
ptInt2.ToGlob( CylFrame) ;
|
||||
vtN2.ToGlob( CylFrame) ;
|
||||
return true ;
|
||||
}
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Linea e cilindro sono nel medesimo riferimento.
|
||||
// Il cilindro è definito con centro della base, asse, raggio e altezza.
|
||||
@@ -133,7 +211,13 @@ IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
||||
if ( ! frCyl.Set( ptCyl, vtCyl))
|
||||
return false ;
|
||||
// Ora eseguo i conti nel riferimento intrinseco
|
||||
return IntersLineCyl( GetToLoc( ptL, frCyl), GetToLoc( vtL, frCyl), dRad, dHeight, dU1, dU2) ;
|
||||
bool bTapLow = false ;
|
||||
bool bTapUp = false ;
|
||||
bool bIgnoreTap = true ;
|
||||
Point3d ptInt1, ptInt2 ;
|
||||
Vector3d vtN1, vtN2 ;
|
||||
return IntersLineCyl( ptL, vtL, frCyl, dHeight, dRad, bTapLow, bTapUp,
|
||||
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, bIgnoreTap) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -144,7 +228,7 @@ IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
||||
bool
|
||||
IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
||||
const Point3d& ptCyl1, const Point3d& ptCyl2, double dRad,
|
||||
double& dU1, double& dU2)
|
||||
double& dU1, double& dU2)
|
||||
{
|
||||
// Determino asse ed altezza del cilindro
|
||||
Vector3d vtCyl = ptCyl2 - ptCyl1 ;
|
||||
@@ -157,5 +241,39 @@ IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
||||
if ( ! frCyl.Set( ptCyl1, vtCyl))
|
||||
return false ;
|
||||
// Ora eseguo i conti nel riferimento intrinseco
|
||||
return IntersLineCyl( GetToLoc( ptL, frCyl), GetToLoc( vtL, frCyl), dRad, dHeight, dU1, dU2) ;
|
||||
bool bTapLow = false ;
|
||||
bool bTapUp = false ;
|
||||
bool bIgnoreTap = true ;
|
||||
Point3d ptInt1, ptInt2 ;
|
||||
Vector3d vtN1, vtN2 ;
|
||||
return IntersLineCyl( ptL, vtL, frCyl, dHeight, dRad, bTapLow, bTapUp,
|
||||
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, bIgnoreTap) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// linea già nel riferimento intrinseco del cilindro
|
||||
//----------------------------------------------------------------------------
|
||||
bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
||||
double dRad, double dHeight,
|
||||
double& dU1, double& dU2)
|
||||
{
|
||||
Point3d ptInt1, ptInt2 ;
|
||||
Vector3d vtN1, vtN2 ;
|
||||
bool bTapLow = false, bTapUp = false ;
|
||||
bool bIgnoreTap = true ;
|
||||
return IntersLineCyl( ptL, vtL, dHeight, dRad, bTapLow, bTapUp,
|
||||
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, bIgnoreTap) ;
|
||||
}
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// funzione esposta per altre dll
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
IntersLineCyl( const Point3d& ptLineSt, const Vector3d& vtLineDir,
|
||||
const Frame3d& CylFrame, double dH, double dRad,
|
||||
double& dU1, Point3d& ptInt1, Vector3d& vtN1, double& dU2, Point3d& ptInt2, Vector3d& vtN2)
|
||||
{
|
||||
return IntersLineCyl( ptLineSt, vtLineDir, CylFrame, dH, dRad, false, false,
|
||||
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, true, false) ;
|
||||
}
|
||||
|
||||
+23
-4
@@ -20,17 +20,27 @@
|
||||
// Il cilindro è centrato sull'asse Z e appoggiato sul piano XY.
|
||||
// Con intersezione viene restituito true e i parametri in dU1 e dU2.
|
||||
//----------------------------------------------------------------------------
|
||||
bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
||||
double dRad, double dHeight,
|
||||
double& dU1, double& dU2) ;
|
||||
bool
|
||||
IntersLineCyl( const Point3d& ptP, const Vector3d& vtV, double dH, double dRad, bool bTapLow, bool bTapUp,
|
||||
double& dU1, Point3d& ptInt1, Vector3d& vtN1, double& dU2, Point3d& ptInt2, Vector3d& vtN2, bool bIgnoreTap = false, bool bInvertNormals = false) ;
|
||||
|
||||
// come sopra ma passo il riferimento intrinseco del cilindro in cui portare la linea
|
||||
bool
|
||||
IntersLineCyl( const Point3d& ptLineSt, const Vector3d& vtLineDir,
|
||||
const Frame3d& CylFrame, double dH, double dRad, bool bTapLow, bool bTapUp,
|
||||
double& dU1, Point3d& ptInt1, Vector3d& vtN1, double& dU2, Point3d& ptInt2, Vector3d& vtN2, bool bIgnoreTap = false, bool bInvertNormals = false) ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
inline bool
|
||||
TestIntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
||||
double dRad, double dHeight)
|
||||
{
|
||||
Point3d ptInt1, ptInt2 ;
|
||||
Vector3d vtN1, vtN2 ;
|
||||
double dU1, dU2 ;
|
||||
return IntersLineCyl( ptL, vtL, dRad, dHeight, dU1, dU2) ;
|
||||
bool bTapLow = false, bTapUp = false ;
|
||||
bool bIgnoreTap = true ;
|
||||
return IntersLineCyl( ptL, vtL, dHeight, dRad, bTapLow, bTapUp, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, bIgnoreTap) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
@@ -50,3 +60,12 @@ bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
||||
bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
||||
const Point3d& ptCyl1, const Point3d& ptCyl2, double dRad,
|
||||
double& dU1, double& dU2) ;
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// // Linea e cilindro sono nel medesimo riferimento.
|
||||
// Il cilindro è definito con raggio e altezza. ( la linea è già nel riferimento intrinseco del cilindro)
|
||||
// In caso di intersezione viene restituito true e i parametri in dU1 e dU2.
|
||||
//----------------------------------------------------------------------------
|
||||
bool IntersLineCyl( const Point3d& ptL, const Vector3d& vtL,
|
||||
double dRad, double dHeight,
|
||||
double& dU1, double& dU2) ;
|
||||
|
||||
@@ -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 ;
|
||||
}
|
||||
+41
-11
@@ -40,6 +40,7 @@ const int P5AX_CVEX = 2 ; // su angolo convesso
|
||||
const int P5AX_CONC = 3 ; // in angolo concavo
|
||||
const int P5AX_BEFORE_CONC = 4 ; // adiacente ad angolo concavo
|
||||
const int P5AX_AFTER_CONC = 5 ; // adiacente ad angolo concavo
|
||||
const int P5AX_SMOOTH_CONC = 6 ; // zona concava curva, senza spigolo netto
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
static double
|
||||
@@ -64,6 +65,7 @@ PointsInTolerance( const PNT5AXVECTOR& vPt5ax, int nPrec, int nCurr, int nNext,
|
||||
static bool
|
||||
AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
|
||||
{
|
||||
const double dSinSmallAngle = sin( 0 * DEGTORAD) ;
|
||||
for ( int i = 1 ; i < ssize( vPt5ax) ; ++ i) {
|
||||
// precedente
|
||||
int j = i - 1 ;
|
||||
@@ -79,18 +81,24 @@ AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
|
||||
Point3d ptInt ;
|
||||
if ( IntersLinePlane( ptEdge, vtEdge, 1, plPlane3, ptInt, false) == ILPT_YES) {
|
||||
// verifico se spigolo convesso o concavo
|
||||
bool bConvex ;
|
||||
if ( ! AreSamePointApprox( ptInt, vPt5ax[j].ptP))
|
||||
bConvex = ( ( vPt5ax[j].vtDir1 ^ ( ptInt - vPt5ax[j].ptP)) * vtEdge > 0) ;
|
||||
else
|
||||
bConvex = (( vPt5ax[i].vtDir1 ^ ( ptInt - vPt5ax[i].ptP)) * vtEdge < 0) ;
|
||||
bool bConvex = (vPt5ax[i].ptP - vPt5ax[j].ptP) * vPt5ax[j].vtDir1 < 0 ;
|
||||
bool bValidInters = true ;
|
||||
if ( i > 2) {
|
||||
int k = i - 2 ;
|
||||
// verifico la concavità anche tornando indietro lungo la linea
|
||||
if ( ( ( vPt5ax[k].ptP - vPt5ax[j].ptP) * vPt5ax[i].vtDir1 < 0) != bConvex) {
|
||||
LOG_WARN( GetEGkLogger(), "La superficie su cui si sta proiettando la curva ha delle normali incoerenti")
|
||||
return false ;
|
||||
}
|
||||
// verifico che l'intersezione sia tra i e j e non prima di j
|
||||
bValidInters = ( ptInt - vPt5ax[j].ptP) * ( vPt5ax[j].ptP - vPt5ax[k].ptP) > 0 ;
|
||||
}
|
||||
// se convesso, metto due punti con direzione appena prima e appena dopo
|
||||
if ( bConvex) {
|
||||
Vector3d vtLine1 = ptInt - vPt5ax[j].ptP ; double dLen1 = vtLine1.Len() ;
|
||||
Vector3d vtLine2 = vPt5ax[i].ptP - ptInt ; double dLen2 = vtLine2.Len() ;
|
||||
if ( dLen1 > 2 * EPS_SMALL) {
|
||||
if ( dLen1 > 10 * EPS_SMALL && bValidInters) {
|
||||
Point5ax Pt5ax ;
|
||||
Pt5ax.ptP = ptInt - vtLine1 / dLen1 * 2 * EPS_SMALL ;
|
||||
Pt5ax.vtDir1 = vPt5ax[j].vtDir1 ;
|
||||
Pt5ax.vtDir2 = vPt5ax[j].vtDir2 ;
|
||||
Pt5ax.vtDirU = vPt5ax[j].vtDirU ;
|
||||
@@ -102,9 +110,14 @@ AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
|
||||
}
|
||||
else
|
||||
vPt5ax[j].nFlag = P5AX_CVEX ;
|
||||
if ( dLen2 > 2 * EPS_SMALL) {
|
||||
if ( dLen2 > 10 * EPS_SMALL) {
|
||||
Point5ax Pt5ax ;
|
||||
Pt5ax.ptP = ptInt + vtLine2 / dLen2 * 2 * EPS_SMALL ;
|
||||
if ( bValidInters)
|
||||
Pt5ax.ptP = ptInt + vtLine2 / dLen2 * 2 * EPS_SMALL ;
|
||||
else {
|
||||
Vector3d vtNewLine = vPt5ax[i].ptP - vPt5ax[j].ptP ; vtNewLine.Normalize() ;
|
||||
Pt5ax.ptP = vPt5ax[j].ptP + vtNewLine * 2 * EPS_SMALL ;
|
||||
}
|
||||
Pt5ax.vtDir1 = vPt5ax[i].vtDir1 ;
|
||||
Pt5ax.vtDir2 = vPt5ax[i].vtDir2 ;
|
||||
Pt5ax.vtDirU = vPt5ax[i].vtDirU ;
|
||||
@@ -133,6 +146,21 @@ AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
// guardo se la proiezione il tratto successivo, lungo la normale precedente + maggiore di un angolo minimo ( angolo interno smooth)
|
||||
Vector3d vtDirNext = vPt5ax[i].ptP - vPt5ax[j].ptP ;
|
||||
vtDirNext.Normalize() ;
|
||||
if ( vtDirNext * vPt5ax[j].vtDir1 > dSinSmallAngle) {
|
||||
// se concavo senza spigolo netto segnalo zona concava smooth
|
||||
vPt5ax[i].nFlag = P5AX_SMOOTH_CONC ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// riscorro tutto il vettore per vedere se ho creato delle zone concave smooth frammentate (separate solo da un tratto non classificato concavo), che quindi uniformo
|
||||
for ( int i = 1 ; i < ssize( vPt5ax) - 1 ; ++ i) {
|
||||
if ( vPt5ax[i].nFlag != P5AX_SMOOTH_CONC && vPt5ax[i-1].nFlag == P5AX_SMOOTH_CONC && vPt5ax[i+1].nFlag == P5AX_SMOOTH_CONC)
|
||||
vPt5ax[i].nFlag = P5AX_SMOOTH_CONC ;
|
||||
}
|
||||
return true ;
|
||||
}
|
||||
@@ -377,8 +405,10 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf,
|
||||
}
|
||||
|
||||
// se richiesto, inserimento punti intermedi in presenza di spigoli
|
||||
if ( bSharpEdges)
|
||||
AddPointsOnCorners( vPt5ax) ;
|
||||
if ( bSharpEdges) {
|
||||
if ( ! AddPointsOnCorners( vPt5ax))
|
||||
return false ;
|
||||
}
|
||||
|
||||
// rimozione punti in eccesso rispetto alle tolleranze
|
||||
RemovePointsInExcess( vPt5ax, dLinTol, dMaxSegmLen, bSharpEdges) ;
|
||||
|
||||
+1117
-538
File diff suppressed because it is too large
Load Diff
+55
-137
@@ -5976,103 +5976,6 @@ CalcSyncPointFromEdge( const SHARPEDGEVECTOR& vSharpEdge, const ICurveComposite*
|
||||
return true ;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Calcolo della curva di Sync tra un punto di una curva di Bordo (calcolato come il punto a curvatura massima) e il suo
|
||||
// associato sull'altra Curva di Bordo
|
||||
// -> Restituisce la singola Linea di Sincronizzazione
|
||||
static bool
|
||||
CalcSyncPointFromCurvature( const CurvaturePoint& PointK, const ICurveComposite* pCompoSubEdge, BIPOINT& SyncLine)
|
||||
{
|
||||
// Verifico la validità del SubEdge su cui trovare il punto di Sincronizzazione
|
||||
if ( pCompoSubEdge == nullptr || ! pCompoSubEdge->IsValid())
|
||||
return false ;
|
||||
|
||||
// --- Piano di taglio per punto a distanza minima
|
||||
double dUCurrSubEdge = 0. ;
|
||||
IntersCurvePlane ICP( *pCompoSubEdge, PointK.ptCurvature, Media( PointK.vtTanPrev, PointK.vtTanNext)) ;
|
||||
int nIndParCloser = -1, nIndPointCloser = -1 ;
|
||||
double dSqMinDist = INFINITO ;
|
||||
for ( int nInfo = 0 ; nInfo < ICP.GetIntersCount() ; ++ nInfo) {
|
||||
IntCrvPlnInfo aInfo ;
|
||||
if ( ICP.GetIntCrvPlnInfo( nInfo, aInfo)) {
|
||||
if ( nIndParCloser == -1)
|
||||
nIndParCloser = nInfo ;
|
||||
double dSqDist = SqDist( PointK.ptCurvature, aInfo.Ici[0].ptI) ;
|
||||
if ( dSqDist < dSqMinDist) {
|
||||
dSqMinDist = dSqDist ;
|
||||
nIndPointCloser = nInfo ;
|
||||
}
|
||||
}
|
||||
}
|
||||
bool bOkPlane = ( nIndParCloser != -1 && nIndPointCloser != -1) ;
|
||||
if ( bOkPlane) {
|
||||
// Se gli indici sono tra loro coerenti allora ho individuato il punto
|
||||
if ( nIndParCloser == nIndPointCloser) {
|
||||
IntCrvPlnInfo aInfo ;
|
||||
ICP.GetIntCrvPlnInfo( nIndParCloser, aInfo) ;
|
||||
dUCurrSubEdge = aInfo.Ici[0].dU ;
|
||||
}
|
||||
// Se gli indici sono discordi, devo scegliere quale dei due punti tenere
|
||||
else {
|
||||
// scelgo il punto più vicino al corrente
|
||||
IntCrvPlnInfo aInfoPt, aInfoPar ;
|
||||
ICP.GetIntCrvPlnInfo( nIndPointCloser, aInfoPt) ;
|
||||
ICP.GetIntCrvPlnInfo( nIndParCloser, aInfoPar) ;
|
||||
dUCurrSubEdge = ( SqDist( PointK.ptCurvature, aInfoPt.Ici[0].ptI) < SqDist( PointK.ptCurvature, aInfoPar.Ici[0].ptI) ?
|
||||
aInfoPt.Ici[0].dU : aInfoPar.Ici[0].dU) ;
|
||||
}
|
||||
}
|
||||
if ( ! bOkPlane) {
|
||||
// --- Altrimenti, cerco il punto a minima distanza
|
||||
DistPointCurve DPC( PointK.ptCurvature, *pCompoSubEdge) ;
|
||||
int nFlag ;
|
||||
bool bOkMinDist = ( DPC.GetParamAtMinDistPoint( 0., dUCurrSubEdge, nFlag)) ;
|
||||
if ( ! bOkMinDist) {
|
||||
// --- Alla peggio mi posiziono a metà tra la posizione corrente e quella finale
|
||||
double dPrevLen ; pCompoSubEdge->GetLengthAtParam( 0., dPrevLen) ;
|
||||
double dLen ; pCompoSubEdge->GetLength( dLen) ;
|
||||
pCompoSubEdge->GetParamAtLength( ( dPrevLen + dLen) / 2., dUCurrSubEdge) ;
|
||||
}
|
||||
}
|
||||
|
||||
// Definisco il primo estremo della linea di Sincronizzazione corrente
|
||||
SyncLine.first = PointK.ptCurvature ;
|
||||
|
||||
// Verifico se posso muovermi attorno al punto trovato per allinearmi meglio con le normali alla curva
|
||||
// NB. Si cerca di privilgiare i punti più vicini ( in parametro) al punto calcolato sopra, in modo da cercare di
|
||||
// non discostare troppo la Linea di sincronizzazione dal punto trovato.
|
||||
const double MAX_DIST = 2.5 ;
|
||||
const int NUM_SAMPLE_PNT = 20 ;
|
||||
double dLen ; pCompoSubEdge->GetLength( dLen) ;
|
||||
double dSyncLen ; pCompoSubEdge->GetLengthAtParam( dUCurrSubEdge, dSyncLen) ;
|
||||
Vector3d vtSyncTanPrev, vtSyncTanNext ;
|
||||
pCompoSubEdge->GetPointD1D2( dUCurrSubEdge, ICurve::FROM_MINUS, SyncLine.second, &vtSyncTanPrev) ; vtSyncTanPrev.Normalize() ;
|
||||
pCompoSubEdge->GetPointD1D2( dUCurrSubEdge, ICurve::FROM_PLUS, SyncLine.second, &vtSyncTanNext) ; vtSyncTanNext.Normalize() ;
|
||||
double dLimInfLen = Clamp( dSyncLen - MAX_DIST, 0., dLen) ;
|
||||
double dLimSupLen = Clamp( dSyncLen + MAX_DIST, 0., dLen) ;
|
||||
int nSamplePnt = int( ceil( NUM_SAMPLE_PNT / 4.)) ;
|
||||
double dMaxCos = ( Media( PointK.vtTanPrev, PointK.vtTanNext) * Media( vtSyncTanPrev, vtSyncTanNext)) ;
|
||||
double dShiftR = ( dLimSupLen - dSyncLen) / nSamplePnt ;
|
||||
double dShiftL = ( dSyncLen - dLimInfLen) / nSamplePnt ;
|
||||
array<double, 2> vdLens = { dSyncLen, dSyncLen} ;
|
||||
for ( int i = 1 ; i <= nSamplePnt ; ++ i) {
|
||||
vdLens[0] += dShiftR ;
|
||||
vdLens[1] -= dShiftL ;
|
||||
for ( int j = 0 ; j < 2 ; ++ j) {
|
||||
double dU ; pCompoSubEdge->GetParamAtLength( vdLens[j], dU) ;
|
||||
Point3d ptCurr ; Vector3d vtTan ;
|
||||
pCompoSubEdge->GetPointD1D2( dU, ICurve::FROM_MINUS, ptCurr, &vtTan) ; vtTan.Normalize() ;
|
||||
double dCos = ( vtTan * Media( PointK.vtTanPrev, PointK.vtTanNext)) ;
|
||||
if ( dCos > dMaxCos) {
|
||||
dMaxCos = dCos ;
|
||||
SyncLine.second = ptCurr ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
// ---------------------------------------------------------------------------
|
||||
// Gestione degli spigoli all'interno della Quadrangolazione corrente
|
||||
static bool
|
||||
@@ -6184,7 +6087,7 @@ ManageEdgesInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp
|
||||
// ---------------------------------------------------------------------------
|
||||
// Calcolo delle Curve di Sync per evitare Twist
|
||||
static bool
|
||||
ManageTwistInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComposite* pSubEdge2, BIPNTVECTOR& vSyncLines)
|
||||
ManageTwistInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComposite* pSubEdge2, BIPNTVECTOR& vSyncLines, bool& bEraseLastIso)
|
||||
{
|
||||
// Verifica validità delle curve
|
||||
if ( pSubEdge1 == nullptr || ! pSubEdge1->IsValid() || pSubEdge2 == nullptr || ! pSubEdge2->IsValid())
|
||||
@@ -6192,6 +6095,7 @@ ManageTwistInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp
|
||||
|
||||
const double COS_LIMIT = cos( 50. * DEGTORAD) ;
|
||||
const int NUM_SAMPLE_PNT = 20 ;
|
||||
const int nStepSkip = NUM_SAMPLE_PNT / 10 ;
|
||||
#if DEBUG_CURVATURE
|
||||
vector<pair<Point3d, double>> _vPtK1 ;
|
||||
vector<pair<Point3d, double>> _vPtK2 ;
|
||||
@@ -6203,13 +6107,16 @@ ManageTwistInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp
|
||||
Vector3d vtS1 ; pSubEdge1->GetStartDir( vtS1) ;
|
||||
Vector3d vtE1 ; pSubEdge1->GetEndDir( vtE1) ;
|
||||
double dLen1 = - EPS_SMALL ;
|
||||
double dLen2 = - EPS_SMALL ;
|
||||
pSubEdge1->GetLength( dLen1) ;
|
||||
pSubEdge2->GetLength( dLen2) ;
|
||||
double dMyDist = min( dLen1, dLen2) * 0.85 ;
|
||||
bool bSplit1 = ( vtS1 * vtE1 < COS_LIMIT) ;
|
||||
if ( bSplit1) {
|
||||
// Individuo il punto a Curvatura Massima
|
||||
pSubEdge1->GetLength( dLen1) ;
|
||||
double dKMax1 = - INFINITO + 1, dUK1Max = - EPS_SMALL ;
|
||||
Point3d ptKMax1 ; Vector3d vtTanKMax1Prev, vtTanKMax1Next ;
|
||||
for ( int i = 0 ; i <= NUM_SAMPLE_PNT ; ++ i) {
|
||||
for ( int i = nStepSkip ; i <= NUM_SAMPLE_PNT - nStepSkip ; ++ i) {
|
||||
// Ricavo la Lunghezza corrente e il parametro dU associato
|
||||
double dCurrLen1 = Clamp( i * ( dLen1 / NUM_SAMPLE_PNT), 0., dLen1) ;
|
||||
double dUCurr1 ; pSubEdge1->GetParamAtLength( dCurrLen1, dUCurr1) ;
|
||||
@@ -6237,22 +6144,21 @@ ManageTwistInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp
|
||||
vtTanKMax1Next.Normalize() ;
|
||||
// Calcolo la nuova linea di sincronizzazione
|
||||
CurvaturePoint myCurvaturePoint( dUK1Max, ptKMax1, vtTanKMax1Prev, vtTanKMax1Next) ;
|
||||
BIPOINT SyncLine ;
|
||||
CalcSyncPointFromCurvature( myCurvaturePoint, pSubEdge2, SyncLine) ;
|
||||
vSyncLines.emplace_back( SyncLine) ;
|
||||
double dUOn2 ; double dLenCurr2 ;
|
||||
GetIsoPointOnSecondCurve( pSubEdge1, pSubEdge2, dUK1Max, dUOn2, dMyDist, 0, 0, dLenCurr2, dLen2) ;
|
||||
Point3d ptOn2 ; pSubEdge2->GetPointD1D2( dUOn2, ICurve::FROM_MINUS, ptOn2) ;
|
||||
vSyncLines.emplace_back( ptKMax1, ptOn2) ;
|
||||
}
|
||||
|
||||
// --- Verifico il cambiamento di Deviazione angolare tra Inizio-Fine del tratto per la prima curva di Bordo
|
||||
Vector3d vtS2 ; pSubEdge2->GetStartDir( vtS2) ;
|
||||
Vector3d vtE2 ; pSubEdge2->GetEndDir( vtE2) ;
|
||||
double dLen2 = - EPS_SMALL ;
|
||||
bool bSplit2 = ( vtS2 * vtE2 < COS_LIMIT) ;
|
||||
if ( bSplit2) {
|
||||
// Individuo il punto a Curvatura Massima
|
||||
pSubEdge2->GetLength( dLen2) ;
|
||||
double dKMax2 = - INFINITO + 1, dUK2Max = - EPS_SMALL ;
|
||||
Point3d ptKMax2 ; Vector3d vtTanKMax2Prev, vtTanKMax2Next ;
|
||||
for ( int i = 0 ; i <= NUM_SAMPLE_PNT ; ++ i) {
|
||||
for ( int i = nStepSkip ; i <= NUM_SAMPLE_PNT - nStepSkip ; ++ i) {
|
||||
// Ricavo la Lunghezza corrente e il parametro dU associato
|
||||
double dCurrLen2 = Clamp( i * ( dLen2 / NUM_SAMPLE_PNT), 0., dLen2) ;
|
||||
double dUCurr2 ; pSubEdge2->GetParamAtLength( dCurrLen2, dUCurr2) ;
|
||||
@@ -6280,11 +6186,10 @@ ManageTwistInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp
|
||||
vtTanKMax2Next.Normalize() ;
|
||||
// Calcolo la nuova linea di sincronizzazione
|
||||
CurvaturePoint myCurvaturePoint( dUK2Max, ptKMax2, vtTanKMax2Prev, vtTanKMax2Next) ;
|
||||
BIPOINT SyncLine ;
|
||||
CalcSyncPointFromCurvature( myCurvaturePoint, pSubEdge1, SyncLine) ;
|
||||
// !<-- Inverto la curva di Sincronizzaione per coerenza con la prima -->!
|
||||
swap( SyncLine.first, SyncLine.second) ;
|
||||
vSyncLines.emplace_back( SyncLine) ;
|
||||
double dUOn1 ; double dLenCurr1 ;
|
||||
GetIsoPointOnSecondCurve( pSubEdge2, pSubEdge1, dUK2Max, dUOn1, dMyDist, 0, 0, dLenCurr1, dLen1) ;
|
||||
Point3d ptOn1 ; pSubEdge1->GetPointD1D2( dUOn1, ICurve::FROM_MINUS, ptOn1) ;
|
||||
vSyncLines.emplace_back( ptOn1, ptKMax2) ;
|
||||
}
|
||||
|
||||
#if DEBUG_CURVATURE // Curvatura minima -> AQUA | Curvatura massima -> ORANGE
|
||||
@@ -6338,17 +6243,25 @@ ManageTwistInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp
|
||||
// NB. Risultano ridondanti, creano SottoQuadrangolazioni molto strette o possono Inclinare eccssivamente l'Utensile
|
||||
// NB. Così facendo evito anche di creare curve di Sync lungo le diagonali della Quadrangolazione
|
||||
const double LEN_TOL = 2. ;
|
||||
const double dParTol = 0.1 ;
|
||||
double dLenPrev1 = - LEN_TOL, dLenPrev2 = - LEN_TOL ;
|
||||
for ( int i = 0 ; i < ssize( vSyncLines) ; ++ i) {
|
||||
double dSyncLen1 ; pSubEdge1->GetLengthAtPoint( vSyncLines[i].first, dSyncLen1, TOL) ;
|
||||
bool bErase = ( dSyncLen1 < max( LEN_TOL, 0.2 * dLen1) || dSyncLen1 > min( dLen1 - LEN_TOL, 0.8 * dLen1)) ;
|
||||
bool bErase = ( dSyncLen1 < max( LEN_TOL, dParTol * dLen1) || dSyncLen1 - dLenPrev1 < LEN_TOL) ;
|
||||
bEraseLastIso = dSyncLen1 > min( dLen1 - LEN_TOL, ( 1 - dParTol) * dLen1) ;
|
||||
if ( ! bErase) {
|
||||
double dSyncLen2 ; pSubEdge2->GetLengthAtPoint( vSyncLines[i].second, dSyncLen2, TOL) ;
|
||||
bErase = ( dSyncLen2 < max( LEN_TOL, 0.2 * dLen2) || dSyncLen2 > min( dLen2 - LEN_TOL, 0.8 * dLen2)) ;
|
||||
bErase = ( dSyncLen2 < max( LEN_TOL, dParTol * dLen2) || dSyncLen2 - dLenPrev2 < LEN_TOL) ;
|
||||
bEraseLastIso = bEraseLastIso || dSyncLen2 > min( dLen2 - LEN_TOL, ( 1 - dParTol) * dLen2) ;
|
||||
dLenPrev2 = dSyncLen2 ;
|
||||
}
|
||||
if ( bErase) {
|
||||
if ( bErase && ! bEraseLastIso) {
|
||||
vSyncLines.erase( vSyncLines.begin() + i) ;
|
||||
-- i ;
|
||||
}
|
||||
dLenPrev1 = dSyncLen1 ;
|
||||
if ( bEraseLastIso)
|
||||
break ;
|
||||
}
|
||||
if ( vSyncLines.empty())
|
||||
return true ;
|
||||
@@ -6374,6 +6287,10 @@ ManageTwistInQuadrangulation( const ICurveComposite* pSubEdge1, const ICurveComp
|
||||
vSyncLines.pop_back() ; // lascio solo la prima... ( bisognerebbe scegliere quale lasciare con un criterio migliore ?)
|
||||
}
|
||||
|
||||
// se ne ho due tengo solo la prima
|
||||
if ( ssize( vSyncLines) == 2)
|
||||
vSyncLines.pop_back() ;
|
||||
|
||||
return true ;
|
||||
}
|
||||
|
||||
@@ -6420,11 +6337,11 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
|
||||
// Recupero dU, Point3d e dLen corrente sul primo bordo, per un incremento del passo di campionamento
|
||||
dLenCurr1 = Clamp( dLenPrev1 + dMyDist, 0., dLen1) ;
|
||||
pCrvEdge1->GetParamAtLength( dLenCurr1, dUCurr1) ;
|
||||
//// se sono abbastanza vicino ad una joint allora prendo quel punto
|
||||
//double dUClosestJoint1 = round( dUCurr1) ;
|
||||
//double dLenAlt1 = 0 ; pCrvEdge1->GetLengthAtParam( dUClosestJoint1, dLenAlt1) ;
|
||||
//if ( abs( dLenCurr1 - dLenAlt1) < 1)
|
||||
// dUCurr1 = dUClosestJoint1 ;
|
||||
// se sono abbastanza vicino ad una joint allora prendo quel punto
|
||||
double dUClosestJoint1 = round( dUCurr1) ;
|
||||
double dLenAlt1 = 0 ; pCrvEdge1->GetLengthAtParam( dUClosestJoint1, dLenAlt1) ;
|
||||
if ( abs( dLenCurr1 - dLenAlt1) < 1)
|
||||
dUCurr1 = dUClosestJoint1 ;
|
||||
pCrvEdge1->GetPointD1D2( dUCurr1, ICurve::FROM_MINUS, ptCurr1, &vtCurr1) ;
|
||||
vtCurr1.Normalize() ;
|
||||
|
||||
@@ -6437,14 +6354,17 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
|
||||
|
||||
GetIsoPointOnSecondCurve( pCrvEdge1, pCrvEdge2, dUCurr1, dUCurr2, dMyDist, dUPrev2, dLenPrev2, dLenCurr2, dLen2) ;
|
||||
|
||||
//////////////////////////N.B.: se si aggiunge questo pezzo bisogna anche gestire il fatto che i punti precedentemente aggiunti potrebbero non stare più sulla curva modificata!!!
|
||||
//// verifico se sono vicino ad una joint esistente allora modifico la curva 2
|
||||
//double dUClosestJoint2 = round( dUCurr2) ;
|
||||
//double dLenAlt2 = 0 ; pCrvEdge2->GetLengthAtParam( dUClosestJoint2, dLenAlt2) ;
|
||||
//if ( abs( dLenCurr1 - dLenAlt2) < 1) {
|
||||
// Point3d ptNewJoint ; pCrvEdge2->GetPointD1D2( dUClosestJoint2, ICurve::FROM_MINUS, ptNewJoint) ;
|
||||
// pCrvEdge2->ModifyJoint( int( dUClosestJoint2), ptNewJoint) ;
|
||||
// dUCurr2 = dUClosestJoint2 ;
|
||||
//if ( abs( dLenCurr2 - dLenAlt2) < 1) {
|
||||
// Point3d ptNewJoint ; pCrvEdge2->GetPointD1D2( dUCurr2, ICurve::FROM_MINUS, ptNewJoint) ;
|
||||
// if ( pCrvEdge2->ModifyJoint( int( dUClosestJoint2), ptNewJoint))
|
||||
// dUCurr2 = dUClosestJoint2 ;
|
||||
//}
|
||||
|
||||
|
||||
pCrvEdge2->GetPointD1D2( dUCurr2, ICurve::FROM_MINUS, ptCurr2, &vtCurr2) ;
|
||||
|
||||
#if DEBUG_SYNCLINES
|
||||
@@ -6455,10 +6375,6 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
|
||||
#endif
|
||||
vSyncLines.emplace_back( ptCurr1, ptCurr2) ;
|
||||
|
||||
//// Inserisco le curve di sincronizzazione nel Layer di destinazine
|
||||
//PtrOwner<ICurveLine> pLine( CreateCurveLine()) ; pLine->Set( ptCurr1, ptCurr2) ;
|
||||
//pGeomDB->AddGeoObj( GDB_ID_NULL, nDestGrp, Release( pLine)) ;
|
||||
|
||||
// --- Analisi degli spigoli all'interno della Quadrangolazione corrente ---
|
||||
// NB. Non è sempre detto che uno spigolo di una curva sia sincronizzato con lo spigolo di un'altra ( se questi esistono)...
|
||||
// Pertanto la Bezier Ruled ricavata non è detto che sia in grado di approssimare lo spigolo correttamente, potrebbe sdondarlo
|
||||
@@ -6466,19 +6382,15 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
|
||||
PtrOwner<ICurveComposite> pCrvQuad2( ConvertCurveToComposite( pCrvEdge2->CopyParamRange( dUPrev2, dUCurr2))) ;
|
||||
BIPNTVECTOR vEdgeSyncLines ;
|
||||
ManageEdgesInQuadrangulation( pCrvQuad1, pCrvQuad2, vEdgeSyncLines) ;
|
||||
//for ( int i = 0 ; i < ssize( vEdgeSyncLines) ; ++ i) {
|
||||
// PtrOwner<ICurveLine> pLine( CreateCurveLine()) ; pLine->Set( vEdgeSyncLines[i].first, vEdgeSyncLines[i].second) ;
|
||||
// int nNewId = pGeomDB->AddGeoObj( GDB_ID_NULL, nDestGrp, Release( pLine)) ;
|
||||
// pGeomDB->SetMaterial( nNewId, GREEN) ;
|
||||
//}
|
||||
|
||||
// --- Aggiunta di Linee di Sync all'interno della Quandrangolazione corrente ---
|
||||
// Perchè parametrizzando per la lunghezza i SottoTratti ricavati, nel caso di elevate variazioni angolari tra l'inizio e la fine
|
||||
// ( tra due curva di Sync) si potrebbero generare delle torsioni non volute
|
||||
// -->! NB. Queste linee vengono create considerando le SubQuadrangolazioni con gli Spigoli. !<--
|
||||
BIPNTVECTOR vTwistSyncLines ;
|
||||
bool bEraseLastIso = false ;
|
||||
if ( vEdgeSyncLines.empty())
|
||||
ManageTwistInQuadrangulation( pCrvQuad1, pCrvQuad2, vTwistSyncLines) ;
|
||||
ManageTwistInQuadrangulation( pCrvQuad1, pCrvQuad2, vTwistSyncLines, bEraseLastIso) ;
|
||||
else {
|
||||
BIPOINT SyncLinePrev, SyncLineNext ;
|
||||
pCrvQuad1->GetStartPoint( SyncLinePrev.first) ;
|
||||
@@ -6500,12 +6412,20 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
|
||||
pCrvQuad2->GetParamAtPoint( SyncLineNext.second, dUE2) ;
|
||||
PtrOwner<ICurveComposite> pCrvSubQuad1( ConvertCurveToComposite( pCrvQuad1->CopyParamRange( dUS1, dUE1))) ;
|
||||
PtrOwner<ICurveComposite> pCrvSubQuad2( ConvertCurveToComposite( pCrvQuad2->CopyParamRange( dUE1, dUE2))) ;
|
||||
ManageTwistInQuadrangulation( pCrvSubQuad1, pCrvSubQuad2, vTwistSyncLines) ;
|
||||
ManageTwistInQuadrangulation( pCrvSubQuad1, pCrvSubQuad2, vTwistSyncLines, bEraseLastIso) ;
|
||||
// Aggiorno i parametri
|
||||
SyncLinePrev = SyncLineNext ;
|
||||
}
|
||||
bEraseLastIso = false ;
|
||||
}
|
||||
// aggiungo le nuove curve ( non importa che siano in ordine di parametro)
|
||||
if ( bEraseLastIso) {
|
||||
vSyncLines.pop_back() ;
|
||||
double dQuadLen1 ; pCrvQuad1->GetLengthAtPoint( vTwistSyncLines[0].first, dQuadLen1) ;
|
||||
dLenCurr1 = dLenPrev1 + dQuadLen1 ;
|
||||
double dQuadLen2 ; pCrvQuad2->GetLengthAtPoint( vTwistSyncLines[0].second, dQuadLen2) ;
|
||||
dLenCurr2 = dLenPrev2 + dQuadLen2 ;
|
||||
}
|
||||
// aggiungo le nuove curve ( non importa che siano ordinate per parametro)
|
||||
vSyncLines.insert( vSyncLines.end(), vEdgeSyncLines.begin(), vEdgeSyncLines.end()) ;
|
||||
vSyncLines.insert( vSyncLines.end(), vTwistSyncLines.begin(), vTwistSyncLines.end()) ;
|
||||
|
||||
@@ -6518,8 +6438,6 @@ SurfBezier::CreateSmoothRuledByTwoCurves( const ICurve* pCurve0, const ICurve* p
|
||||
SaveGeoObj( vGeo, vCol, "D:\\Temp\\bezier\\ruled\\trimming\\smooth.nge") ;
|
||||
#endif
|
||||
|
||||
|
||||
// devo riempire vSyncLines
|
||||
return CreateByIsoParamSet( pCrvEdge1, pCrvEdge2, vSyncLines) ;
|
||||
}
|
||||
|
||||
|
||||
+37
-13
@@ -1188,8 +1188,10 @@ SurfTriMesh::GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR&
|
||||
pSfrTria->Offset( dTol, ICurve::OFF_FILLET) ;
|
||||
if ( IsNull( pSfr))
|
||||
pSfr.Set( pSfrTria) ;
|
||||
else
|
||||
pSfr->Add( *pSfrTria) ;
|
||||
else {
|
||||
if ( ! pSfr->Add( *pSfrTria))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
}
|
||||
// passo al successivo
|
||||
@@ -1201,14 +1203,18 @@ SurfTriMesh::GetSilhouette( const Vector3d& vtDir, double dTol, POLYLINEVECTOR&
|
||||
return false ;
|
||||
|
||||
// Effettuo contro-offset
|
||||
pSfr->Offset( -dTol, ICurve::OFF_EXTEND) ;
|
||||
if ( ! pSfr->Offset( -dTol, ICurve::OFF_EXTEND))
|
||||
return false ;
|
||||
|
||||
// Recupero i contorni della regione
|
||||
for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) {
|
||||
for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; ++ j) {
|
||||
PolyLine PL ;
|
||||
if ( pSfr->ApproxLoopWithLines( i, j, LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
|
||||
vPL.emplace_back( PL) ;
|
||||
if ( ! pSfr->ApproxLoopWithLines( i, j, LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL)) {
|
||||
vPL.clear() ;
|
||||
return false ;
|
||||
}
|
||||
vPL.emplace_back( PL) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1259,8 +1265,10 @@ SurfTriMesh::GetSilhouette( const Plane3d& plPlane, double dTol, POLYLINEVECTOR&
|
||||
pSfrTria->Offset( dTol, ICurve::OFF_FILLET) ;
|
||||
if ( IsNull( pSfr))
|
||||
pSfr.Set( pSfrTria) ;
|
||||
else
|
||||
pSfr->Add( *pSfrTria) ;
|
||||
else {
|
||||
if ( ! pSfr->Add( *pSfrTria))
|
||||
return false ;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1274,14 +1282,18 @@ SurfTriMesh::GetSilhouette( const Plane3d& plPlane, double dTol, POLYLINEVECTOR&
|
||||
return true ;
|
||||
|
||||
// Effettuo contro-offset
|
||||
pSfr->Offset( -dTol, ICurve::OFF_EXTEND) ;
|
||||
if ( ! pSfr->Offset( -dTol, ICurve::OFF_EXTEND))
|
||||
return false ;
|
||||
|
||||
// Recupero i contorni della regione
|
||||
for ( int i = 0 ; i < pSfr->GetChunkCount() ; ++ i) {
|
||||
for ( int j = 0 ; j < pSfr->GetLoopCount( i) ; ++ j) {
|
||||
PolyLine PL ;
|
||||
if ( pSfr->ApproxLoopWithLines( i, j, LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL))
|
||||
vPL.emplace_back( PL) ;
|
||||
if ( ! pSfr->ApproxLoopWithLines( i, j, LIN_TOL_STD, ANG_TOL_STD_DEG, ICurve::APL_STD, PL)) {
|
||||
vPL.clear() ;
|
||||
return false ;
|
||||
}
|
||||
vPL.emplace_back( PL) ;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3810,12 +3822,19 @@ SurfTriMesh::VerifyConnection( bool bShellsAndParts) const
|
||||
BBox3d b3Box ;
|
||||
PtrOwner<ISurfTriMesh> pStmShell ;
|
||||
} ;
|
||||
// vettore di shell con vettori dei propri triangoli (per accelerare nei casi degeneri)
|
||||
INTMATRIX mShellTria( m_nShells) ;
|
||||
for ( int i = 0 ; i < ssize( m_vTria) ; ++ i) {
|
||||
if ( m_vTria[i].nShell < m_nShells)
|
||||
mShellTria[m_vTria[i].nShell].push_back( i) ;
|
||||
}
|
||||
// classificazione delle shell
|
||||
vector<SHELLINFO> vOuterShells ;
|
||||
vector<SHELLINFO> vInnerShells ;
|
||||
INTVECTOR vOpenShells ;
|
||||
for ( int nSh = 0 ; nSh < m_nShells ; ++ nSh) {
|
||||
// se la shell è chiusa
|
||||
if ( IsShellClosed( nSh)) {
|
||||
if ( ssize( mShellTria[nSh]) >= 4 && IsShellClosed( nSh)) {
|
||||
// creo una superficie clonata dalla shell
|
||||
PtrOwner<ISurfTriMesh> pStmShell( CloneShell( nSh)) ;
|
||||
if ( IsNull( pStmShell) || ! pStmShell->IsValid())
|
||||
@@ -3827,7 +3846,9 @@ SurfTriMesh::VerifyConnection( bool bShellsAndParts) const
|
||||
BBox3d b3Box ;
|
||||
pStmShell->GetLocalBBox( b3Box, BBF_STANDARD) ;
|
||||
// la inserisco nel vettore opportuno
|
||||
if ( dVol > 0)
|
||||
if ( abs( dVol) < 1 * 1 * EPS_SMALL)
|
||||
vOpenShells.push_back( nSh) ;
|
||||
else if ( dVol > 0)
|
||||
vOuterShells.emplace_back( nSh, dVol, b3Box, Release( pStmShell)) ;
|
||||
else
|
||||
vInnerShells.emplace_back( nSh, dVol, b3Box, Release( pStmShell)) ;
|
||||
@@ -3979,6 +4000,7 @@ SurfTriMesh::IsShellClosed( int nShell) const
|
||||
return false ;
|
||||
// ciclo sui triangoli della shell
|
||||
bool bClosed = true ;
|
||||
int nTriaCnt = 0 ;
|
||||
for ( int i = 0 ; i < GetTriangleSize() ; ++ i) {
|
||||
// se triangolo non cancellato e della shell
|
||||
if ( m_vTria[i].nIdVert[0] != SVT_DEL && m_vTria[i].nShell == nShell) {
|
||||
@@ -3989,10 +4011,12 @@ SurfTriMesh::IsShellClosed( int nShell) const
|
||||
bClosed = false ;
|
||||
break ;
|
||||
}
|
||||
else
|
||||
++ nTriaCnt ;
|
||||
}
|
||||
}
|
||||
// restituisco il risultato
|
||||
return bClosed ;
|
||||
return ( bClosed && nTriaCnt >= 4) ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
|
||||
+127
-42
@@ -3533,10 +3533,11 @@ IsBorderAButtonHole( const PolyLine& PL, double dLinTol, double dAngTol, Frame3d
|
||||
//-----------------------------------------------------------------------------
|
||||
static bool
|
||||
InterpolateSyncCurvesOnEndGuidePoints( const ICurveComposite* pGuide, const ICurveComposite* pOtherGuide,
|
||||
const Plane3d& plStart, const Plane3d& plEnd, double dLinTol,
|
||||
BIPNTVECTOR& vBiPts)
|
||||
const Plane3d& plStart, const Plane3d& plEnd, const Vector3d vtAuxStart, const Vector3d vtAuxEnd,
|
||||
double dLinTol, BIPNTVECTOR& vBiPts)
|
||||
{
|
||||
vBiPts.clear() ;
|
||||
const double dLinAngTol = 15 * EPS_SMALL ; // tolleranza sulla lunghezza della corda dell'angolo di tolleranza
|
||||
|
||||
// Verifico che le curve siano valide
|
||||
if ( pGuide == nullptr || ! pGuide->IsValid() ||
|
||||
@@ -3566,52 +3567,134 @@ InterpolateSyncCurvesOnEndGuidePoints( const ICurveComposite* pGuide, const ICur
|
||||
// Interpolo le normali dei piani rispetto a tale valore
|
||||
Vector3d vtN = Media( plStart.GetVersN(), plEnd.GetVersN(), dInterPar) ;
|
||||
vtN.Normalize() ;
|
||||
Vector3d vtAux = Media( vtAuxStart, vtAuxEnd, dInterPar) ; vtAux.Normalize() ;
|
||||
// Definisco il piano di intersezione
|
||||
Point3d ptCurr ;
|
||||
if ( ! pCrv->GetEndPoint( ptCurr))
|
||||
return false ;
|
||||
|
||||
// con i piani
|
||||
#if DEBUG_SYNC_INTERPOLATION
|
||||
Frame3d frPl ; frPl.Set( ptCurr, vtN) ;
|
||||
PtrOwner<IGeoFrame3d> frCurr( CreateGeoFrame3d()) ; frCurr->Set( frPl) ;
|
||||
VT.emplace_back( Release( frCurr)) ;
|
||||
VC.emplace_back( WHITE) ;
|
||||
SaveGeoObj( VT, VC, "C:\\Temp\\SyncLinesPlanes.nge") ;
|
||||
SaveGeoObj( VT, VC, "C:\\Temp\\trimming\\interpolate\\SyncLinesPlanes.nge") ;
|
||||
#endif
|
||||
// Recupero il parametro di intersezione tra la curva e il piano
|
||||
#if 0
|
||||
VT.clear() ; VC.clear() ;
|
||||
PtrOwner<IGeoPoint3d> PT( CreateGeoPoint3d()) ; PT->Set( ptCurr) ;
|
||||
VT.emplace_back( Release( PT)) ;
|
||||
VC.emplace_back( AQUA) ;
|
||||
PtrOwner<IGeoVector3d> VECT( CreateGeoVector3d()) ; VECT->Set( vtN) ;
|
||||
VECT->ChangeBase( ptCurr) ;
|
||||
PtrOwner<ICurveArc> pArc( CreateCurveArc()) ; pArc->Set( ptCurr, vtN, 1000.) ;
|
||||
PtrOwner<ISurfFlatRegion> pSfrPlane( CreateSurfFlatRegion()) ;
|
||||
pSfrPlane->AddExtLoop( Release( pArc)) ;
|
||||
VT.emplace_back( Release( pSfrPlane)) ;
|
||||
VC.emplace_back( Color( 0., 0., 0., .5)) ;
|
||||
VT.emplace_back( Release( VECT)) ;
|
||||
VC.emplace_back( BLUE) ;
|
||||
VT.emplace_back( pOtherGuide->Clone()) ;
|
||||
VC.emplace_back( WHITE) ;
|
||||
SaveGeoObj( VT, VC, "C:\\Temp\\SyncLinesPlanes.nge") ;
|
||||
#endif
|
||||
IntersCurvePlane IntCP( *pOtherGuide, ptCurr, vtN) ;
|
||||
if ( IntCP.GetIntersCount() == 0)
|
||||
return false ; // ambiguità
|
||||
// Recupero il punto della prima intersezione trovata
|
||||
Point3d ptInt ;
|
||||
double dPar ;
|
||||
if ( ! IntCP.GetIntersPointNearTo( ptCurr, ptInt, dPar))
|
||||
return false ;
|
||||
#if DEBUG_SYNC_INTERPOLATION
|
||||
PtrOwner<IGeoPoint3d> ptG( CreateGeoPoint3d()) ; ptG->Set( ptInt) ;
|
||||
VT.emplace_back( Release( ptG)) ;
|
||||
VC.emplace_back( WHITE) ;
|
||||
SaveGeoObj( VT, VC, "C:\\Temp\\SyncLinesPlanes.nge") ;
|
||||
if ( false) {
|
||||
VT.clear() ; VC.clear() ;
|
||||
PtrOwner<IGeoPoint3d> PT( CreateGeoPoint3d()) ; PT->Set( ptCurr) ;
|
||||
VT.emplace_back( Release( PT)) ;
|
||||
VC.emplace_back( AQUA) ;
|
||||
PtrOwner<IGeoVector3d> VECT( CreateGeoVector3d()) ; VECT->Set( vtN) ;
|
||||
VECT->ChangeBase( ptCurr) ;
|
||||
PtrOwner<ICurveArc> pArc( CreateCurveArc()) ; pArc->Set( ptCurr, vtN, 1000.) ;
|
||||
PtrOwner<ISurfFlatRegion> pSfrPlane( CreateSurfFlatRegion()) ;
|
||||
pSfrPlane->AddExtLoop( Release( pArc)) ;
|
||||
VT.emplace_back( Release( pSfrPlane)) ;
|
||||
VC.emplace_back( Color( 0., 0., 0., .5)) ;
|
||||
VT.emplace_back( Release( VECT)) ;
|
||||
VC.emplace_back( BLUE) ;
|
||||
VT.emplace_back( pOtherGuide->Clone()) ;
|
||||
VC.emplace_back( WHITE) ;
|
||||
SaveGeoObj( VT, VC, "C:\\Temp\\trimming\\interpolate\\SyncLinesPlanes.nge") ;
|
||||
}
|
||||
#endif
|
||||
// Memorizzo tale punto
|
||||
vBiPts.emplace_back( make_pair( ptCurr, ptInt)) ;
|
||||
|
||||
IntersCurvePlane IntCP( *pOtherGuide, ptCurr, vtN) ;
|
||||
bool bFound = false ;
|
||||
if ( IntCP.GetIntersCount() != 0) {
|
||||
// Recupero il punto della prima intersezione trovata
|
||||
Point3d ptIntClosest ;
|
||||
double dPar ;
|
||||
IntCP.GetIntersPointNearTo( ptCurr, ptIntClosest, dPar) ;
|
||||
// verifico che sia allineato con la direzione che dovrebbe avere
|
||||
Vector3d vtDir = ptIntClosest - ptCurr ;
|
||||
vtDir.Normalize() ;
|
||||
double dDiff = (vtDir - vtAux).Len() ;
|
||||
if ( dDiff < dLinAngTol) {
|
||||
#if DEBUG_SYNC_INTERPOLATION
|
||||
PtrOwner<IGeoPoint3d> ptG( CreateGeoPoint3d()) ; ptG->Set( ptIntClosest) ;
|
||||
VT.emplace_back( Release( ptG)) ;
|
||||
VC.emplace_back( WHITE) ;
|
||||
SaveGeoObj( VT, VC, "C:\\Temp\\trimming\\interpolate\\SyncLinesPlanes.nge") ;
|
||||
#endif
|
||||
//Memorizzo tale punto
|
||||
vBiPts.emplace_back( make_pair( ptCurr, ptIntClosest)) ;
|
||||
bFound = true ;
|
||||
}
|
||||
else if ( IntCP.GetIntersCount() > 1) {
|
||||
double dMinDiff = INFINITO ;
|
||||
Point3d ptBest ;
|
||||
for ( int j = 0 ; j < IntCP.GetIntersCount() ; ++j) {
|
||||
IntCrvPlnInfo icpi ; IntCP.GetIntCrvPlnInfo( j, icpi) ;
|
||||
Point3d ptInt = icpi.Ici->ptI ;
|
||||
double dDiff = ( ptInt - ptCurr).Len() ;
|
||||
if ( dDiff < dMinDiff) {
|
||||
dMinDiff = dDiff ;
|
||||
ptBest = ptInt ;
|
||||
}
|
||||
}
|
||||
if ( dMinDiff < dLinAngTol)
|
||||
bFound = true ;
|
||||
}
|
||||
}
|
||||
|
||||
if ( ! bFound) {
|
||||
// applico la direzione desiderata nel punto corrente della guida
|
||||
// calcolo la lunghezza dell'isocurva in quella zona
|
||||
Point3d ptS1, ptS2 ;
|
||||
pGuide->GetStartPoint( ptS1) ;
|
||||
pOtherGuide->GetStartPoint( ptS2);
|
||||
double dDistRef = Dist( ptS1, ptS2) ;
|
||||
double dParamOther = -1. ;
|
||||
int nFlag = -1 ;
|
||||
Point3d ptEnd = ptCurr + (vtAux * dDistRef) ;
|
||||
if ( ! DistPointCurve( ptEnd, *pOtherGuide).GetParamAtMinDistPoint( 0, dParamOther, nFlag))
|
||||
return false ;
|
||||
|
||||
// nell'intorno del più vicino, cerco l'isocurva più vicina alla direzione desiderata
|
||||
Point3d ptBest ;
|
||||
double dMinDiff = INFINITO ;
|
||||
double dSearchLen = 3. ;
|
||||
double dStepLen = 0.1 ;
|
||||
double dCurrLenOther ; pOtherGuide->GetLengthAtParam( dParamOther, dCurrLenOther) ;
|
||||
double dLenOther ; pOtherGuide->GetLength( dLenOther) ;
|
||||
dCurrLenOther -= dSearchLen ;
|
||||
dCurrLenOther = Clamp( dCurrLenOther, 0., dLenOther) ;
|
||||
for ( int j = 0 ; j < 2 * dSearchLen / dStepLen ; ++j) {
|
||||
dCurrLenOther += j * dStepLen ;
|
||||
if ( dCurrLenOther > dLenOther)
|
||||
break ;
|
||||
double dCurrParOther = 0 ; pOtherGuide->GetParamAtLength( dCurrLenOther, dCurrParOther) ;
|
||||
Point3d ptCurrOther ; pOtherGuide->GetPointD1D2( dCurrParOther, ICurve::FROM_MINUS, ptCurrOther) ;
|
||||
Vector3d vtDir = ptCurrOther - ptCurr ; vtDir.Normalize() ;
|
||||
double dDiff = ( vtDir - vtAux).Len() ;
|
||||
if ( dDiff < dMinDiff) {
|
||||
dMinDiff = dDiff ;
|
||||
ptBest = ptCurrOther ;
|
||||
}
|
||||
#if DEBUG_SYNC_INTERPOLATION
|
||||
VT.clear() ;
|
||||
VC.clear() ;
|
||||
VT.emplace_back( pGuide->Clone()) ;
|
||||
VC.emplace_back( BLUE) ;
|
||||
VT.emplace_back( pOtherGuide->Clone()) ;
|
||||
VC.emplace_back( BLUE) ;
|
||||
PtrOwner<IGeoVector3d> vtFirst( CreateGeoVector3d()) ; vtFirst->Set( -vtN * 12, ptCurrOther) ;
|
||||
VT.emplace_back( Release( vtFirst)) ;
|
||||
VC.emplace_back( AQUA) ;
|
||||
PtrOwner<IGeoVector3d> vtCurr( CreateGeoVector3d()) ; vtCurr->Set( -vtDir * 12, ptCurrOther) ;
|
||||
VT.emplace_back( Release( vtCurr)) ;
|
||||
VC.emplace_back( WHITE) ;
|
||||
SaveGeoObj( VT, VC, "C:\\Temp\\trimming\\interpolate\\SyncLinesPlanes.nge") ;
|
||||
#endif
|
||||
}
|
||||
if ( dMinDiff < 2 * dLinAngTol)
|
||||
vBiPts.emplace_back( make_pair( ptCurr, ptBest)) ;
|
||||
}
|
||||
}
|
||||
|
||||
return true ;
|
||||
@@ -4066,18 +4149,18 @@ GetTrimmingSyncInterpolation( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2,
|
||||
Vector3d vtStart1, vtStart2 ;
|
||||
if ( ! pCompoGuide1->GetStartDir( vtStart1) || ! pCompoGuide2->GetStartDir( vtStart2))
|
||||
return false ;
|
||||
Vector3d vtAux = ptE1 - ptS1 ; vtAux.Normalize() ;
|
||||
Vector3d vtAuxStart = ptE1 - ptS1 ; vtAuxStart.Normalize() ;
|
||||
Vector3d vtMTan = Media( vtStart1, vtStart2) ; vtMTan.Normalize() ;
|
||||
Vector3d vtN = OrthoCompo( vtMTan, vtAux) ; vtN.Normalize() ;
|
||||
Vector3d vtN = OrthoCompo( vtMTan, vtAuxStart) ; vtN.Normalize() ;
|
||||
Plane3d plStart ;
|
||||
if ( ! plStart.Set( ptS1, vtN))
|
||||
return false ;
|
||||
Vector3d vtEnd1, vtEnd2 ;
|
||||
if ( ! pCompoGuide1->GetEndDir( vtEnd1) || ! pCompoGuide2->GetEndDir( vtEnd2))
|
||||
return false ;
|
||||
vtAux = ptE2 - ptS2 ; vtAux.Normalize() ;
|
||||
Vector3d vtAuxEnd = ptE2 - ptS2 ; vtAuxEnd.Normalize() ;
|
||||
vtMTan = Media( vtEnd1, vtEnd2) ; vtMTan.Normalize() ;
|
||||
vtN = OrthoCompo( vtMTan, vtAux) ; vtN.Normalize() ;
|
||||
vtN = OrthoCompo( vtMTan, vtAuxEnd) ; vtN.Normalize() ;
|
||||
Plane3d plEnd ;
|
||||
if ( ! plEnd.Set( ptS2, vtN))
|
||||
return false ;
|
||||
@@ -4096,13 +4179,15 @@ GetTrimmingSyncInterpolation( const ICurve* pCrvEdge1, const ICurve* pCrvEdge2,
|
||||
|
||||
// Curve di Sincronizzazione del Bordo 1 sul Bordo 2
|
||||
BIPNTVECTOR vBiPts1 ;
|
||||
if ( ! InterpolateSyncCurvesOnEndGuidePoints( pCompoGuide1, pCompoGuide2, plStart, plEnd, dMyLinTol, vBiPts1))
|
||||
if ( ! InterpolateSyncCurvesOnEndGuidePoints( pCompoGuide1, pCompoGuide2, plStart, plEnd, vtAuxStart, vtAuxEnd, dMyLinTol, vBiPts1))
|
||||
return false ;
|
||||
|
||||
vtAuxStart *= -1 ;
|
||||
vtAuxEnd *= -1 ;
|
||||
// Curve di Sincronizzazione del Bordo 2 sul Bordo 1
|
||||
BIPNTVECTOR vBiPts2 ;
|
||||
if ( ! InterpolateSyncCurvesOnEndGuidePoints( pCompoGuide2, pCompoGuide1, plStart, plEnd, dMyLinTol, vBiPts2))
|
||||
return false ;
|
||||
//if ( ! InterpolateSyncCurvesOnEndGuidePoints( pCompoGuide2, pCompoGuide1, plStart, plEnd, vtAuxStart, vtAuxEnd, dMyLinTol, vBiPts2))
|
||||
// return false ;
|
||||
|
||||
// Restituisco le Curve di Sincronizzazione
|
||||
// [Da Bordo 1 a Bordo 2 originale]
|
||||
|
||||
@@ -393,9 +393,6 @@ class VolZmap : public IVolZmap, public IGeoObjRW
|
||||
double& dU1, double& dU2) const ;
|
||||
bool GetDepthWithDexel( const Point3d& ptP, const Vector3d& vtDir, double& dInLength, double& dOutLength) const ;
|
||||
bool GetDepthWithVoxel( const Point3d& ptP, const Vector3d& vtDir, double& dInLength, double& dOutLength) const ;
|
||||
bool IntersLineCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir,
|
||||
const Frame3d& CylFrame, double dH, double dRad, bool bTapLow, bool bTapUp,
|
||||
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const ;
|
||||
bool IntersLineEllipticalCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir,
|
||||
const Frame3d& CircFrame, double dRad, double dLongMvLen, double dOrtMvLen,
|
||||
bool bTapLow, bool bTapUp,
|
||||
|
||||
@@ -2071,127 +2071,6 @@ VolZmap::CDeSurfTm( const ISurfTriMesh& tmSurf, double dSafeDist, bool bPrecise)
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Riferimento con origine nel centro della base e asse di simmetria coincidente con l'asse Z.
|
||||
// La funzione restituisce true in caso di intersezione, false altrimenti.
|
||||
//----------------------------------------------------------------------------
|
||||
bool
|
||||
VolZmap::IntersLineCylinder( const Point3d& ptLineSt, const Vector3d& vtLineDir,
|
||||
const Frame3d& CylFrame, double dH, double dRad, bool bTapLow, bool bTapUp,
|
||||
Point3d& ptInt1, Vector3d& vtN1, Point3d& ptInt2, Vector3d& vtN2) const
|
||||
{
|
||||
// Porto la linea nel riferimento del cilindro
|
||||
Point3d ptP = GetToLoc( ptLineSt, CylFrame) ;
|
||||
Vector3d vtV = GetToLoc( vtLineDir, CylFrame) ;
|
||||
|
||||
// Determino le eventuali intersezioni con le due basi a quota minima e massima (solo se linea non parallela ad esse)
|
||||
int nBasInt = 0 ;
|
||||
if ( abs( vtV.z) > EPS_ZERO) {
|
||||
// le linee tangenti al cilindro non sono considerate intersecanti
|
||||
double dEpsRad = ( vtV.IsZeroXY() ? - EPS_SMALL : EPS_SMALL) ;
|
||||
ptInt1 = ptP + ( ( 0 - ptP.z) / vtV.z) * vtV ;
|
||||
if ( ptInt1.x * ptInt1.x + ptInt1.y * ptInt1.y < dRad * dRad + 2 * dRad * dEpsRad) {
|
||||
nBasInt += 1 ;
|
||||
vtN1 = Z_AX ;
|
||||
}
|
||||
ptInt2 = ptP + ( ( dH - ptP.z) / vtV.z) * vtV ;
|
||||
if ( ptInt2.x * ptInt2.x + ptInt2.y * ptInt2.y < dRad * dRad + 2 * dRad * dEpsRad) {
|
||||
nBasInt += 2 ;
|
||||
vtN2 = - Z_AX ;
|
||||
}
|
||||
}
|
||||
|
||||
// Se la linea interseca entrambe le basi, si sono trovate le due intersezioni
|
||||
if ( nBasInt == 3) {
|
||||
// Porto i punti e i versori nel riferimento globale
|
||||
ptInt1.ToGlob( CylFrame) ;
|
||||
vtN1.ToGlob( CylFrame) ;
|
||||
ptInt2.ToGlob( CylFrame) ;
|
||||
vtN2.ToGlob( CylFrame) ;
|
||||
// Trovate intersezioni
|
||||
return true ;
|
||||
}
|
||||
|
||||
// Determino le intersezioni con la superficie laterale del cilindro
|
||||
DBLVECTOR vdCoeff{ ptP.x * ptP.x + ptP.y * ptP.y - dRad * dRad,
|
||||
2 * ( ptP.x * vtV.x + ptP.y * vtV.y),
|
||||
vtV.x * vtV.x + vtV.y * vtV.y} ;
|
||||
DBLVECTOR vdRoots ;
|
||||
int nRoot = PolynomialRoots( 2, vdCoeff, vdRoots) ;
|
||||
|
||||
// Epsilon per piani di tappo
|
||||
double dEpsLow = ( bTapLow ? - EPS_SMALL : EPS_SMALL) ;
|
||||
double dEpsUp = ( bTapUp ? EPS_SMALL : - EPS_SMALL) ;
|
||||
|
||||
// Elimino le soluzioni cha danno intersezioni fuori dai limiti in Z del cilindro
|
||||
if ( nRoot == 2) {
|
||||
double dIntZ2 = ptP.z + vdRoots[1] * vtV.z ;
|
||||
if ( dIntZ2 < 0 + dEpsLow || dIntZ2 > dH + dEpsUp)
|
||||
-- nRoot ;
|
||||
}
|
||||
if ( nRoot >= 1) {
|
||||
double dIntZ1 = ptP.z + vdRoots[0] * vtV.z ;
|
||||
if ( dIntZ1 < 0 + dEpsLow || dIntZ1 > dH + dEpsUp) {
|
||||
if ( nRoot == 2)
|
||||
vdRoots[0] = vdRoots[1] ;
|
||||
-- nRoot ;
|
||||
}
|
||||
}
|
||||
|
||||
// Due soluzioni: la retta interseca due volte la superficie laterale
|
||||
if ( nRoot == 2) {
|
||||
// Punti di intersezione con la superficie del cilindro
|
||||
ptInt1 = ptP + vdRoots[0] * vtV ;
|
||||
ptInt2 = ptP + vdRoots[1] * vtV ;
|
||||
// Determino le normali
|
||||
vtN1.Set( -ptInt1.x, -ptInt1.y, 0) ;
|
||||
vtN1.Normalize() ;
|
||||
vtN2.Set( -ptInt2.x, -ptInt2.y, 0) ;
|
||||
vtN2.Normalize() ;
|
||||
// Porto i punti e i versori nel riferimento globale
|
||||
ptInt1.ToGlob( CylFrame) ;
|
||||
vtN1.ToGlob( CylFrame) ;
|
||||
ptInt2.ToGlob( CylFrame) ;
|
||||
vtN2.ToGlob( CylFrame) ;
|
||||
// Trovate intersezioni
|
||||
return true ;
|
||||
}
|
||||
|
||||
// Una soluzione : la retta interseca la superficie laterale e un piano
|
||||
else if ( nRoot == 1) {
|
||||
// Se piano superiore
|
||||
if ( nBasInt == 2) {
|
||||
// Punto di intersezione
|
||||
ptInt1 = ptP + vdRoots[0] * vtV ;
|
||||
// Normale alla superficie del cilindro verso l'interno
|
||||
vtN1.Set( -ptInt1.x, -ptInt1.y, 0) ;
|
||||
vtN1.Normalize() ;
|
||||
}
|
||||
// altrimenti piano inferiore
|
||||
else if ( nBasInt == 1) {
|
||||
// Punto di intersezione
|
||||
ptInt2 = ptP + vdRoots[0] * vtV ;
|
||||
// Normale alla superficie del cilindro verso l'interno
|
||||
vtN2.Set( -ptInt2.x, -ptInt2.y, 0) ;
|
||||
vtN2.Normalize() ;
|
||||
}
|
||||
// altrimenti niente
|
||||
else
|
||||
return false ;
|
||||
// Porto i punti e i versori nel riferimento globale
|
||||
ptInt1.ToGlob( CylFrame) ;
|
||||
vtN1.ToGlob( CylFrame) ;
|
||||
ptInt2.ToGlob( CylFrame) ;
|
||||
vtN2.ToGlob( CylFrame) ;
|
||||
// Trovate intersezioni
|
||||
return true ;
|
||||
}
|
||||
|
||||
// Nessuna soluzione : nessuna intersezione
|
||||
else
|
||||
return false ;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// Riferimento con origine nel vertice del cono e asse di simmetria coincidente con l'asse Z.
|
||||
// La funzione restituisce true in caso di intersezione, false altrimenti.
|
||||
|
||||
+6
-4
@@ -21,6 +21,7 @@
|
||||
#include "CurveLine.h"
|
||||
#include "CurveArc.h"
|
||||
#include "GeoConst.h"
|
||||
#include "IntersLineCyl.h"
|
||||
#include "/EgtDev/Include/EGkStmFromCurves.h"
|
||||
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
|
||||
#include "/EgtDev/Include/EgtNumUtils.h"
|
||||
@@ -968,12 +969,13 @@ VolZmap::CreateOffsetCylinderOnEdge( const Point3d& ptP1, const Point3d& ptP2, d
|
||||
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
|
||||
Point3d ptInt1, ptInt2 ;
|
||||
Vector3d vtN1, vtN2 ;
|
||||
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dH, abs( dOffs), true, true,
|
||||
ptInt1, vtN1, ptInt2, vtN2)) {
|
||||
double dU1, dU2 ;
|
||||
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dH, abs( dOffs), true, true,
|
||||
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, false)) {
|
||||
if ( dOffs > 0.)
|
||||
AddIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, -vtN1, -vtN2, nTool, nTool) ;
|
||||
AddIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nTool, nTool) ;
|
||||
else
|
||||
SubtractIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nTool) ;
|
||||
SubtractIntervalsForOffset( nGrid, i, j, ptInt1.z, ptInt2.z, -vtN1, -vtN2, nTool) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+21
-15
@@ -21,6 +21,7 @@
|
||||
#include "VolZmap.h"
|
||||
#include "GeoConst.h"
|
||||
#include "IntersLineBox.h"
|
||||
#include "IntersLineCyl.h"
|
||||
#include "/EgtDev/Include/EGkIntervals.h"
|
||||
#include "/EgtDev/Include/EGkStringUtils3d.h"
|
||||
#include "/EgtDev/Include/EGkSurfBezier.h"
|
||||
@@ -6249,7 +6250,8 @@ VolZmap::CompCyl_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE, co
|
||||
Point3d ptC( ( i + 0.5) * m_dStep, ( j + 0.5) * m_dStep, 0) ;
|
||||
Point3d ptInt1, ptInt2 ;
|
||||
Vector3d vtN1, vtN2 ;
|
||||
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dH, dRad, bTapB, bTapT, ptInt1, vtN1, ptInt2, vtN2)) {
|
||||
double dU1, dU2 ;
|
||||
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dH, dRad, bTapB, bTapT, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, true)) {
|
||||
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
|
||||
}
|
||||
}
|
||||
@@ -6294,8 +6296,9 @@ VolZmap::CompConus_Drilling( int nGrid, const Point3d& ptS, const Point3d& ptE,
|
||||
Vector3d vtN1, vtN2 ;
|
||||
|
||||
// Cilindro
|
||||
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dH, dMaxRad, true, bTapT,
|
||||
ptInt1, vtN1, ptInt2, vtN2)) {
|
||||
double dU1, dU2 ;
|
||||
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dH, dMaxRad, true, bTapT,
|
||||
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, true)) {
|
||||
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
|
||||
}
|
||||
|
||||
@@ -6474,7 +6477,8 @@ VolZmap::CompCyl_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE,
|
||||
|
||||
// Cilindro iniziale
|
||||
CylFrame.ChangeOrig( ptITip) ;
|
||||
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dHei, dRad, bTapB, bTapT, ptInt1, vtN1, ptInt2, vtN2)) {
|
||||
double dU1, dU2 ;
|
||||
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dHei, dRad, bTapB, bTapT, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, true)) {
|
||||
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
|
||||
}
|
||||
|
||||
@@ -6482,7 +6486,7 @@ VolZmap::CompCyl_Milling( int nGrid, const Point3d& ptS, const Point3d& ptE,
|
||||
// del sistema di riferimento, quindi usiamo lo stesso sistema sommando a ptC
|
||||
// il vettore che congiunge le due origini.
|
||||
CylFrame.ChangeOrig( ptITip + vtMove) ;
|
||||
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dHei, dRad, bTapB, bTapT, ptInt1, vtN1, ptInt2, vtN2)) {
|
||||
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dHei, dRad, bTapB, bTapT, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, true)) {
|
||||
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
|
||||
}
|
||||
|
||||
@@ -7069,7 +7073,8 @@ VolZmap::CompBall_Milling( int nGrid, const Point3d& ptLs, const Point3d& ptLe,
|
||||
// Cilindro inviluppo della sfera
|
||||
Point3d ptInt1, ptInt2 ;
|
||||
Vector3d vtN1, vtN2 ;
|
||||
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dLengthPath, dRad, false, false, ptInt1, vtN1, ptInt2, vtN2)) {
|
||||
double dU1, dU2 ;
|
||||
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dLengthPath, dRad, false, false, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, true)) {
|
||||
SubtractIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, nToolNum) ;
|
||||
}
|
||||
}
|
||||
@@ -7217,15 +7222,15 @@ VolZmap::AddingCylinder( int nGrid, const Point3d& ptS, const Point3d& ptE, cons
|
||||
|
||||
Point3d ptInt1, ptInt2 ;
|
||||
Vector3d vtN1, vtN2 ;
|
||||
|
||||
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dHei, dRad, true, true,
|
||||
ptInt1, vtN1, ptInt2, vtN2)) {
|
||||
AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, - vtN1, - vtN2, CurrTool.GetToolNum()) ;
|
||||
double dU1, dU2 ;
|
||||
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dHei, dRad, true, true,
|
||||
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, false)) {
|
||||
AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, CurrTool.GetToolNum()) ;
|
||||
}
|
||||
|
||||
if ( IntersLineCylinder( ptC - dLen1 * vtV1, Z_AX, CylFrame, dHei, dRad, true, true,
|
||||
ptInt1, vtN1, ptInt2, vtN2)) {
|
||||
AddIntervals( nGrid, i, j, ptInt1.z + dLen1 * vtV1.z, ptInt2.z + dLen1 * vtV1.z, - vtN1, - vtN2, CurrTool.GetToolNum()) ;
|
||||
if ( IntersLineCyl( ptC - dLen1 * vtV1, Z_AX, CylFrame, dHei, dRad, true, true,
|
||||
dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, false)) {
|
||||
AddIntervals( nGrid, i, j, ptInt1.z + dLen1 * vtV1.z, ptInt2.z + dLen1 * vtV1.z, vtN1, vtN2, CurrTool.GetToolNum()) ;
|
||||
}
|
||||
|
||||
if ( IntersLineMyPolyhedron( ptC, Z_AX, PolyFrame, dLen1, 2 * ( dRad + dMyTol), dHei + 2 * dMyTol, 0,
|
||||
@@ -7621,8 +7626,9 @@ VolZmap::AddingSphere( int nGrid, const Point3d& ptS, const Point3d& ptE, double
|
||||
// Cilindro inviluppo della sfera
|
||||
Point3d ptInt1, ptInt2 ;
|
||||
Vector3d vtN1, vtN2 ;
|
||||
if ( IntersLineCylinder( ptC, Z_AX, CylFrame, dLengthPath, dRad, false, false, ptInt1, vtN1, ptInt2, vtN2)) {
|
||||
AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, - vtN1, - vtN2, CurrTool.GetToolNum()) ;
|
||||
double dU1, dU2 ;
|
||||
if ( IntersLineCyl( ptC, Z_AX, CylFrame, dLengthPath, dRad, false, false, dU1, ptInt1, vtN1, dU2, ptInt2, vtN2, false, false)) {
|
||||
AddIntervals( nGrid, i, j, ptInt1.z, ptInt2.z, vtN1, vtN2, CurrTool.GetToolNum()) ;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+11
-2
@@ -828,10 +828,19 @@ Voronoi::CalcSpecialPointOffset( PNTVECTVECTOR& vResult, double dOffs)
|
||||
Point3d ptTemp ;
|
||||
Vector3d vtDir ;
|
||||
if ( ! pCrv->GetParamAtPoint( pt, dPar, 100 * EPS_SMALL) || ! pCrv->GetPointD1D2( dPar, ICurve::FROM_MINUS, ptTemp, &vtDir))
|
||||
return false ;
|
||||
continue ;
|
||||
vtDir.Normalize() ;
|
||||
|
||||
vResult.emplace_back( pt, vtDir) ;
|
||||
// verifico che il punto non sia già stato trovato
|
||||
bool bAdd = true ;
|
||||
for ( int j = 0 ; j < ssize( vResult) ; j ++) {
|
||||
if ( AreSamePointApprox( vResult[j].first, pt)) {
|
||||
bAdd = false ;
|
||||
break ;
|
||||
}
|
||||
}
|
||||
if ( bAdd)
|
||||
vResult.emplace_back( pt, vtDir) ;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user