Compare commits

...

45 Commits

Author SHA1 Message Date
Daniele Bariletti 39360eefd7 EgtGeomKernel :
- raffinamento finale della intersCompoCompo.
2026-03-06 17:25:50 +01:00
Daniele Bariletti 6b5fb15c9b EgtGeomKernel :
- piccola correzione alla IntersCurveCurve.
2026-03-06 12:37:26 +01:00
Daniele Bariletti 4e698d4049 EgtGeomKernel :
- spostato rilevamento spike nelle intersezioni tra curve.
- pulizia codice.
2026-03-05 17:33:55 +01:00
Daniele Bariletti e20bd7fd0c Merge branch 'master' into NewMakeUniform 2026-03-04 15:55:39 +01:00
Daniele Bariletti 7e62acf351 EgtGeomKernel :
- aggiunta funzione per richiedere Part e Shell cui appartiene una faccia.
2026-03-04 15:55:25 +01:00
Daniele Bariletti 421bc2eb3b EgtGeomKernel :
- correzione alla make uniform.
2026-03-04 15:24:33 +01:00
Daniele Bariletti db98fa5d5a Merge branch 'master' into NewMakeUniform 2026-03-03 17:10:06 +01:00
Daniele Bariletti 5f28258d16 EgtGeomKernel :
- migliorie e correzioni all'importazione delle bezier.
- tolto limite alle bezier per rivoluzione.
2026-03-03 17:09:30 +01:00
Daniele Bariletti 8f06488b33 EgtGeomKernel :
- miglioramento all'intersezione tra curve.
2026-02-27 16:52:55 +01:00
Riccardo Elitropi ac7ba1b12c EgtGeomKernel :
- in CalcPocketing piccola miglioria su tolleranza trapezi.
2026-02-25 16:56:30 +01:00
Dario Sassi 67131a1482 EgtGeomKernel :
- salvato file come UTF-8.
2026-02-25 15:17:56 +01:00
Daniele Bariletti a92cba8697 Merge branch 'master' into NewMakeUniform 2026-02-24 12:36:18 +01:00
Daniele Bariletti 52cca7233e EgtGeomKernel 3.1b3 :
- correzione alle intersezioni tra curve.
- cambio versione.
2026-02-24 12:36:05 +01:00
Dario Sassi b2beed0fe0 EgtGeomKernel :
- ora From string per Color accette sia RGBA che RGB.
2026-02-24 08:39:23 +01:00
Daniele Bariletti 1f301b6100 Merge branch 'master' into NewMakeUniform 2026-02-23 16:26:55 +01:00
Daniele Bariletti c74ca4932f Merge branch 'master' of https://gitlab.steamware.net/egalware-cadcam/libreriebase/EgtGeomKernel 2026-02-23 16:26:29 +01:00
Daniele Bariletti fafcd67a2c EgtGeomKernel :
- correzione alle ruled guided.
2026-02-23 16:26:23 +01:00
Riccardo Elitropi 390cc3bd8b EgtGeomKernel :
- in trimming migliorata la gestione delle curve di sincronizzazione mediante interpolazione.
2026-02-23 15:47:14 +01:00
Daniele Bariletti b2ccda1b34 Merge branch 'master' into NewMakeUniform 2026-02-23 10:59:22 +01:00
Daniele Bariletti 69916e7756 EgtGeomKernel :
- correzione alla ruled guided.
2026-02-23 10:57:15 +01:00
Daniele Bariletti 3a7b6f1343 EgtGeomKernel :
- aggiunto flag Refined alla funzione GetLeaves.
2026-02-23 09:44:39 +01:00
Daniele Bariletti 71a054749c EgtGeomKernel :
- miglioria alla bezier ruled guided.
2026-02-23 09:35:04 +01:00
Daniele Bariletti 06d87d5c52 Merge branch 'master' into NewMakeUniform 2026-02-23 09:27:55 +01:00
Daniele Bariletti 6d544f93f4 EgtGeomKernel :
- miglioramento dell'approssimazione con curve di bezier.
2026-02-23 09:11:28 +01:00
Riccardo Elitropi 3c1a7ff1bb EgtGeomKernel 3.1b2 :
- in Trimming aggiunta prima versione di interpolazione per le curve di sincronizzazione.
2026-02-20 16:47:42 +01:00
Daniele Bariletti 73bedf4f55 EgkGeomKernel :
- correzione all'intersezione tra curva e piano.
2026-02-19 15:39:43 +01:00
Daniele Bariletti bae8d4651d EgtGeomKernel :
- piccola correzione alla Surf Bez Ruled Guided.
2026-02-19 11:50:44 +01:00
Riccardo Elitropi f9127ce64d EgtGeomKernel 3.1b1 :
- cambio di versione.
2026-02-17 10:00:13 +01:00
Riccardo Elitropi 86338db67d EgtGeomKernel :
- in CalcPocketing piccola correzione.
2026-02-17 09:24:18 +01:00
Daniele Bariletti 2438d1d23a Merge branch 'master' of https://gitlab.steamware.net/egalware-cadcam/libreriebase/EgtGeomKernel 2026-02-12 16:25:34 +01:00
Daniele Bariletti f790736fd7 EgtGeomKernel :
- modificata conversione da linea a bezier.
2026-02-12 16:25:28 +01:00
Daniele Bariletti 985b69ae33 EgtGeomKernel :
- correzione alla triangolazione delle bezier.
- riduzione della dimensione minima dei triangoli nelle surf bezier.
2026-02-12 16:17:11 +01:00
Riccardo Elitropi 6faf5ccde2 EgtGeomKernel 3.1a8 :
- in CalcPocketing migliorati i casi a trapezio.
2026-02-12 15:46:42 +01:00
Daniele Bariletti 2e129d7b06 EgtGeomKernel :
- tolto un argomento alla funzione ApproxCurveWithBezier.
2026-02-11 16:50:50 +01:00
Daniele Bariletti 2b7070e408 Merge branch 'master' of https://gitlab.steamware.net/egalware-cadcam/libreriebase/EgtGeomKernel 2026-02-11 15:27:04 +01:00
Daniele Bariletti 571a24b419 EgtGeomKernel :
- migliorata approssimazione con curve di bezier.
2026-02-11 15:26:57 +01:00
Dario Sassi 5f132ae3d3 EgtGeomKernel 3.1a7 :
- ricompilazione con cambio versione.
2026-02-11 12:20:15 +01:00
Riccardo Elitropi fe5a09281e EgtGeomKernel :
- rimozione memory leaks in CalcPocketing.
2026-02-11 11:31:08 +01:00
Riccardo Elitropi b66522de33 EgtGeomKernel 3.1a6 :
- in CalcPocketing migliorati i casi ottimizzati a Trapezio.
2026-02-10 17:03:46 +01:00
Daniele Bariletti e87ef178c2 EgtGeomKernel :
- correzione alla distanza punto- curva di bezier.
2026-02-10 15:42:03 +01:00
Dario Sassi 0987496caf EgtGeomKernel :
- piccoli aggiustamenti.
2026-02-09 12:48:38 +01:00
Riccardo Elitropi 5ad9c48285 EgtGeomKernel :
- in Trimming rimozione memory Leaks.
2026-02-09 11:21:06 +01:00
Dario Sassi ec6eb3e645 EgtGeomKernel :
- modifica a Trimming
- sistemazioni estetiche varie.
2026-02-09 08:24:16 +01:00
Daniele Bariletti 64c3363426 Merge branch 'NewApproxWithBezier' 2026-02-06 17:28:46 +01:00
Daniele Bariletti b426ccc04d EgtGeomKernel :
- modifica alla funzione MakeUniform: utilizzo solo di curve anziché di flat region.
2026-02-03 16:22:57 +01:00
22 changed files with 1903 additions and 800 deletions
+251 -74
View File
@@ -722,7 +722,7 @@ AssignFeedSpiral( ICurveComposite* pCrv, const ISurfFlatRegion* pSrfRemoved, boo
//----------------------------------------------------------------------------
static bool
AssignFeedSpiralOpt( const int nOptType, const PocketParams& PockParams, ICurveComposite* pCrv )
AssignFeedSpiralOpt( int nOptType, const PocketParams& PockParams, ICurveComposite* pCrv )
{
// controllo della curva corrente
if ( pCrv == nullptr || ! pCrv->IsValid() || pCrv->GetCurveCount() == 0)
@@ -732,24 +732,24 @@ AssignFeedSpiralOpt( const int nOptType, const PocketParams& PockParams, ICurveC
if ( ! PockParams.bCalcFeed)
return AssignMaxFeed( pCrv, PockParams) ;
switch ( PockParams.nType) {
case POCKET_SPIRALIN :
if ( nOptType == 0) { // Spirale dall'Esterno
for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) {
if ( u == 0) // prima circonferenza
pCrv->SetCurveTempParam( 0, GetMinFeed( PockParams), 0) ;
else // semi cerchi in tangenza
pCrv->SetCurveTempParam( u, GetMaxFeed( PockParams), 0) ;
}
if ( PockParams.nType == POCKET_SPIRALIN || PockParams.nType == POCKET_CONFORMAL_ZIGZAG ||
PockParams.nType == POCKET_CONFORMAL_ONEWAY) {
if ( nOptType == 0) { // Spirale dall'Esterno
for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) {
if ( u == 0) // prima circonferenza
pCrv->SetCurveTempParam( 0, GetMinFeed( PockParams), 0) ;
else // semi cerchi in tangenza
pCrv->SetCurveTempParam( u, GetMaxFeed( PockParams), 0) ;
}
else if ( nOptType == 1) { // Trapezoidi
for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u)
pCrv->SetCurveTempParam( u, GetMinFeed( PockParams), 0) ;
}
break ;
}
else if ( nOptType == 1) { // Trapezoidi
for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u)
pCrv->SetCurveTempParam( u, GetMinFeed( PockParams), 0) ;
}
}
/* NB. Essendo la funzione CalcSpiral richiamata sia per lo SpiralIN che per lo SpiralOUT le curve sono sempre
orientate nello stesso modo, solamente alla fine viene invertita la curva finale per la svuotatura... */
case POCKET_SPIRALOUT :
else {
if ( nOptType == 0) { // Spiral verso l'esterno
for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u) {
if ( u > pCrv->GetCurveCount() - 3) // prime semi circonferenze
@@ -762,9 +762,6 @@ AssignFeedSpiralOpt( const int nOptType, const PocketParams& PockParams, ICurveC
for ( int u = 0 ; u < pCrv->GetCurveCount() ; ++ u)
pCrv->SetCurveTempParam( u, GetMinFeed( PockParams), 0) ;
}
break ;
default :
break ;
}
return true ;
@@ -1061,9 +1058,9 @@ ExtendPath( ICurveComposite* pCompo, const ISurfFlatRegion* pSfr, const PocketPa
bool bInside = true ;
bool bOkOut = true ;
if ( PockParams.SfrLimit.IsValid()) {
bOkOut = ( IsPointInsideSurfFr( ptFall, &PockParams.SfrLimit, dMinDist, bInside) && ! bInside) ;
bOkOut = ( IsPointInsideSurfFr( ptFall, &PockParams.SfrLimit, dMinDist - 10. * EPS_SMALL, bInside) && ! bInside) ;
if ( bOkOut)
bOkOut = ( IsPointInsideSurfFr( Media( ptFall, pt), &PockParams.SfrLimit, dMinDist, bInside) && ! bInside) ;
bOkOut = ( IsPointInsideSurfFr( Media( ptFall, pt), &PockParams.SfrLimit, dMinDist - 10. * EPS_SMALL, bInside) && ! bInside) ;
}
if ( bOkOut)
bOkOut = ( IsPointInsideSurfFr( ptFall, pSfr, dMinDist, bInside) && ! bInside) ;
@@ -2638,6 +2635,87 @@ PreparareTrapezoidTwoBases( const ICurveComposite* pCrvCompo, const double dDiam
return true ;
}
//----------------------------------------------------------------------------
static bool
IsForcedStepTrapezoid( const ICurveComposite* pCrvTrap, const PocketParams& PockParam,
int nBase, int nSecondBase, bool& bForced)
{
bForced = false ;
// se la curva non è valida, allora non può essere forzato
if ( pCrvTrap == nullptr || ! pCrvTrap->IsValid())
return false ;
// scorro la curva e ricavo le TempProps
array<int, 4> vnProps ;
int nClose = 0 ;
for ( int i = 0 ; i < 4 ; ++ i) {
if ( ! pCrvTrap->GetCurveTempProp( i, vnProps[i], 0))
return false ;
if ( vnProps[i] == TEMP_PROP_CLOSE_EDGE)
++ nClose ;
}
double dDiam = 2. * PockParam.dRad ;
switch ( nClose) {
// se trapezio tutto aperto, allora non è forzato
case 0 :
bForced = false ;
break ;
// se ho un lato chiuso, non è forzato
case 1 :
bForced = false ;
break ;
// se ho due lati chiusi
case 2 : {
if ( nBase < 0 || nBase > 4 || nSecondBase < 0 || nSecondBase > 4)
return false ;
// se entrambe le basi sono chiuse, è forzato
if ( vnProps[nBase] == TEMP_PROP_CLOSE_EDGE && vnProps[nSecondBase] == TEMP_PROP_CLOSE_EDGE)
bForced = true ;
// se entrambe le basi sono aperte
else if ( vnProps[nBase] == TEMP_PROP_OPEN_EDGE && vnProps[nSecondBase] == TEMP_PROP_OPEN_EDGE) {
const ICurve* pCrvOpenBase = pCrvTrap->GetCurve( nBase) ;
const ICurve* pCrvOpenSecondBase = pCrvTrap->GetCurve( nSecondBase) ;
if ( pCrvOpenBase == nullptr || ! pCrvOpenBase->IsValid() ||
pCrvOpenSecondBase == nullptr || ! pCrvOpenSecondBase->IsValid())
return false ;
double dLenOpenBase ; pCrvOpenBase->GetLength( dLenOpenBase) ;
double dLenSecondOpenBase ; pCrvOpenSecondBase->GetLength( dLenSecondOpenBase) ;
bForced = ( dLenOpenBase < dDiam + 10. * EPS_SMALL &&
dLenSecondOpenBase < dDiam + 10. * EPS_SMALL) ;
}
// se alternate, non forzo
else
bForced = false ;
}
break ;
// se ho tre lati chiusi
case 3 : {
// diventa forzato se il lato aperto non è grande
double dLenOpen = 0. ;
for ( int i = 0 ; i < 4 ; ++ i) {
if ( vnProps[i] == TEMP_PROP_OPEN_EDGE) {
const ICurve* pCrvOpen = pCrvTrap->GetCurve( i) ;
if ( pCrvOpen == nullptr || ! pCrvOpen->IsValid())
return false ;
pCrvOpen->GetLength( dLenOpen) ;
break ;
}
}
bForced = ( dLenOpen < dDiam + 10. * EPS_SMALL) ;
}
break ;
// se tutto chiuso, è forzato
case 4 :
bForced = true ;
break ;
default :
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
static bool
GetTrapezoidFromShape( const ICurveComposite* pCrvCompo, ICurveComposite* pCrvTrap,
@@ -3040,8 +3118,12 @@ GetTrapezoidFromShape( const ICurveComposite* pCrvCompo, ICurveComposite* pCrvTr
return false ;
// se parametro MaxOptSize non compatibile => non è ottimizzato
if ( PockParams.dMaxOptSize > EPS_SMALL && dPocketSize > PockParams.dMaxOptSize)
pCrvTrap->Clear() ;
bool bForced = false ;
IsForcedStepTrapezoid( pCrvTrap, PockParams, nBase, nSecondBase, bForced) ;
if ( ! bForced) {
if ( PockParams.dMaxOptSize > EPS_SMALL && dPocketSize > PockParams.dMaxOptSize)
pCrvTrap->Clear() ;
}
return true ;
}
@@ -3444,18 +3526,18 @@ CalcTrapezoidSpiral( ICurveComposite* pCrvPocket, const Frame3d& frTrap, double
Vector3d vtX ; pCrvPocket->GetCurve( 1)->GetStartDir( vtX) ;
Frame3d frDim ; frDim.Set( ptOrig, Z_AX, vtX) ; frDim.Invert() ;
BBox3d b3Dim ; pCrvPocket->GetBBox( frDim, b3Dim, BBF_EXACT) ;
dMaxLarg = ( vnProp[0] != 0 ? b3Dim.GetDimY() : dPocketSize) ;
dMaxLarg = ( vnProp[0] != TEMP_PROP_CLOSE_EDGE ? b3Dim.GetDimY() : dPocketSize) ;
}
// calcolo percorso di svuotatura
// se lati obliqui sono entrambi chiusi e dimensione svuotatura è maggiore di diametro fresa e minore del doppio gestione speciale
if ( ( bRealTrap && dMaxLarg > PockParams.dRad * 2 + 10 * EPS_SMALL) &&
if ( ( bRealTrap && dMaxLarg > dDiam + 10. * EPS_SMALL) &&
( ( ( vnProp[0] != TEMP_PROP_CLOSE_EDGE && vnProp[2] != TEMP_PROP_CLOSE_EDGE) &&
( vnProp[3] == TEMP_PROP_CLOSE_EDGE && vnProp[1] == TEMP_PROP_CLOSE_EDGE) &&
( max( dLen0, dLen2) < 2 * dDiam + EPS_SMALL)) ||
( max( dLen0, dLen2) < 2. * dDiam + EPS_SMALL)) ||
( ( vnProp[1] != TEMP_PROP_CLOSE_EDGE && vnProp[3] != TEMP_PROP_CLOSE_EDGE) &&
( vnProp[0] == TEMP_PROP_CLOSE_EDGE && vnProp[2] == TEMP_PROP_CLOSE_EDGE) &&
( max( dLen1, dLen3) < 2 * dDiam + EPS_SMALL)))) {
( max( dLen0, dLen2) < 2. * dDiam + EPS_SMALL)))) {
if ( ! SpecialAdjustTrapezoidSpiralForAngles( pMCrv, ( vnProp[0] == TEMP_PROP_CLOSE_EDGE), pCrvPocket, PockParams, ptRef)) {
pMCrv->Clear() ;
return false ;
@@ -3608,14 +3690,8 @@ CalcTrapezoidSpiral( ICurveComposite* pCrvPocket, const Frame3d& frTrap, double
if ( pMCrv->GetCurveCount() == 0)
return true ;
pMCrv->ToGlob( frTrap) ;
if ( PockParams.bInvert) {
pMCrv->Invert() ;
// inverto le proprietà in modo che nProp3 sia sempre legata al punto iniziale e nProp1 a quello finale
swap( vnProp[1], vnProp[3]) ;
}
// segno i lati aperti come temp prop della curva
int nOpenEdges = vnProp[0] + vnProp[1] * 2 + vnProp[2] * 4 + vnProp[3] * 8 ;
pMCrv->SetTempProp( nOpenEdges, 0) ;
@@ -3625,6 +3701,112 @@ CalcTrapezoidSpiral( ICurveComposite* pCrvPocket, const Frame3d& frTrap, double
return true ;
}
//----------------------------------------------------------------------------
static bool
AdjustTrapeziodLeadIn( ICurveComposite* pCrvRes, const PocketParams& PockParam,
const ISurfFlatRegion* pSfrChunk)
{
// recupero la TempProp
int nTmpProp = pCrvRes->GetTempProp( 0) ;
// se esiste almeno un aperto
if ( nTmpProp > 0) {
// se solo lato3 aperto
bool bCheckHead = ( nTmpProp != 8 && nTmpProp != 2) ;
if ( nTmpProp == 2)
pCrvRes->Invert() ; // entro dall'unico aperto
if ( bCheckHead) {
// recupero gli estremi della curva corrente e la inverto in base alla Testa
Point3d ptS ; pCrvRes->GetStartPoint( ptS) ;
Point3d ptE ; pCrvRes->GetEndPoint( ptE) ;
Point3d ptSGlob = GetToGlob( ptS, PockParam.frLocXY) ;
Point3d ptEGlob = GetToGlob( ptE, PockParam.frLocXY) ;
if ( ( PockParam.bAboveHead && ptEGlob.z > ptSGlob.z) ||
( ! PockParam.bAboveHead && ptEGlob.z < ptSGlob.z))
pCrvRes->Invert() ;
}
}
// Assegno la Feed
AssignFeedSpiralOpt( 1, PockParam, pCrvRes) ;
// Se curva da invertire, inverto
if ( PockParam.bInvert)
pCrvRes->Invert() ;
// se esiste almeno un aperto, provo ad estendere il percorso
if ( nTmpProp > 0) {
// Calcolo eventuale entrata da fuori
Vector3d vtRef ; pCrvRes->GetStartDir( vtRef) ;
vtRef.Invert() ;
bool bIsStartExtended = false ;
if ( ! ExtendPath( pCrvRes, pSfrChunk, PockParam, vtRef, false, PockParam.dRad + PockParam.dOpenMinSafe, bIsStartExtended))
return false ;
}
return true ;
}
//----------------------------------------------------------------------------
static bool
GetZigZagOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams& PockParam,
ICurveComposite* pCrvRes)
{
// controllo dei parametri
if ( pSfrChunk == nullptr || ! pSfrChunk->IsValid())
return false ;
pCrvRes->Clear() ;
// ricavo la curva di bordo del chunk corrente
PtrOwner<ICurveComposite> pCrvBorder( ConvertCurveToComposite( pSfrChunk->GetLoop( 0, 0))) ;
if ( IsNull( pCrvBorder) || ! pCrvBorder->IsValid())
return false ;
pCrvBorder->MergeCurves( 10. * EPS_SMALL, 10. * EPS_ANG_SMALL, true, true) ;
pCrvBorder->SetExtrusion( pSfrChunk->GetNormVersor()) ;
/* TRAPEZI
- E' richiesto che una dimensione del box della curva sia compatibile con il primo Offset, il
quale sarebbe una singola curva aperta
*/
PtrOwner<ICurveComposite> pCrvTrap( CreateCurveComposite()) ;
if ( IsNull( pCrvTrap))
return false ;
Frame3d frTrap ;
double dPocketSize ;
int nBase, nSecondBase ;
bool bOkTrap = GetTrapezoidFromShape( pCrvBorder, pCrvTrap, frTrap, PockParam, dPocketSize, nBase, nSecondBase) ;
if ( bOkTrap && pCrvTrap->IsValid()) {
// verifico se il trapezio ottenuto deve o meno rispettare il SideStep
bool bForcedTrap = false ;
IsForcedStepTrapezoid( pCrvTrap, PockParam, nBase, nSecondBase, bForcedTrap) ;
if ( ! bForcedTrap)
bOkTrap = ( dPocketSize < PockParam.dMaxOptSize + 10. * EPS_SMALL) ;
}
if ( bOkTrap && pCrvTrap->IsValid()) {
pCrvTrap->SetExtrusion( Z_AX) ;
CalcTrapezoidSpiral( pCrvTrap, frTrap, dPocketSize, nBase, nSecondBase, PockParam, pCrvRes, bOkTrap) ;
if ( bOkTrap) {
// verifico che tale curva non interferisca con la regione limite
if ( PockParam.SfrLimit.IsValid()) {
double dOffsCheck = PockParam.dRad + PockParam.dRadialOffset - 50. * EPS_SMALL ; // restrittivo per sicurezza
PtrOwner<ISurfFlatRegion> pSfrToolShape( GetSurfFlatRegionFromFatCurve( pCrvRes->Clone(), dOffsCheck, false, false)) ;
bOkTrap = ( ! IsNull( pSfrToolShape) && pSfrToolShape->IsValid()) ;
if ( bOkTrap) {
bOkTrap = ( pSfrToolShape->Intersect( PockParam.SfrLimit) &&
! pSfrToolShape->IsValid()) ;
if ( ! bOkTrap)
pCrvRes->Clear() ;
}
}
if ( bOkTrap) {
AdjustTrapeziodLeadIn( pCrvRes, PockParam, pSfrChunk) ;
// imposto il flag di curva singola
pCrvRes->SetTempProp( TEMP_PROP_OPT_TRAPEZOID, 0) ;
}
}
}
return true ;
}
//----------------------------------------------------------------------------
static bool
GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams& PockParam,
@@ -3673,7 +3855,7 @@ GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams&
ssize( ccClass) == 1 && ccClass[0].nClass == CRVC_OUT) ;
// NB. una versione più complessa dovrebbe verificare se la sottrazione tra la
// superficie dell'utensile e la regione limite non genera un'altra circonferenza...
// In questo caso si la sottrazione potrebbe essere trattata come una circonferenza
// In questo caso la sottrazione potrebbe essere trattata come una circonferenza
// chiusa ed essere ancora svotata a spirale...
}
}
@@ -3714,8 +3896,14 @@ GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams&
Frame3d frTrap ;
double dPocketSize ;
int nBase, nSecondBase ;
bool bOkTrap = ( GetTrapezoidFromShape( pCrvBorder, pCrvTrap, frTrap, PockParam, dPocketSize, nBase, nSecondBase) &&
dPocketSize < PockParam.dMaxOptSize + 10. * EPS_SMALL) ;
bool bOkTrap = GetTrapezoidFromShape( pCrvBorder, pCrvTrap, frTrap, PockParam, dPocketSize, nBase, nSecondBase) ;
if ( bOkTrap && pCrvTrap->IsValid()) {
// verifico se il trapezio ottenuto deve o meno rispettare il SideStep
bool bForcedTrap = false ;
IsForcedStepTrapezoid( pCrvTrap, PockParam, nBase, nSecondBase, bForcedTrap) ;
if ( ! bForcedTrap)
bOkTrap = ( dPocketSize < PockParam.dMaxOptSize + 10. * EPS_SMALL) ;
}
if ( bOkTrap && pCrvTrap->IsValid()) {
pCrvTrap->SetExtrusion( Z_AX) ;
CalcTrapezoidSpiral( pCrvTrap, frTrap, dPocketSize, nBase, nSecondBase, PockParam, pCrvRes, bOkTrap) ;
@@ -3733,29 +3921,9 @@ GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams&
}
}
if ( bOkTrap) {
// calcolo eventuali uscite e ingressi
if ( pCrvRes->GetTempProp( 0) > 0) {
// Recupero gli estremi della curva corrente e la inverto in base alla Testa
Point3d ptS ; pCrvRes->GetStartPoint( ptS) ;
Point3d ptE ; pCrvRes->GetEndPoint( ptE) ;
Point3d ptSGlob = GetToGlob( ptS, PockParam.frLocXY) ;
Point3d ptEGlob = GetToGlob( ptE, PockParam.frLocXY) ;
if ( ( PockParam.bAboveHead && ptEGlob.z > ptSGlob.z) ||
( ! PockParam.bAboveHead && ptEGlob.z < ptSGlob.z))
pCrvRes->Invert() ;
if ( PockParam.bInvert)
pCrvRes->Invert() ;
// Calcolo eventuale entrata da fuori
Vector3d vtRef ; pCrvRes->GetStartDir( vtRef) ;
vtRef.Invert() ;
bool bIsStartExtended = false ;
if ( ! ExtendPath( pCrvRes, pSfrChunk, PockParam, vtRef, false, PockParam.dRad + PockParam.dOpenMinSafe, bIsStartExtended))
return false ;
}
else {
if ( PockParam.bInvert)
pCrvRes->Invert() ;
}
AdjustTrapeziodLeadIn( pCrvRes, PockParam, pSfrChunk) ;
// imposto il flag di curva singola
pCrvRes->SetTempProp( TEMP_PROP_OPT_TRAPEZOID, 0) ;
}
}
}
@@ -3798,23 +3966,31 @@ GetPocketingOptimizedCurves( ISurfFlatRegion* pSfr, const PocketParams& PockPara
PockParam.nType == POCKET_CONFORMAL_ZIGZAG || PockParam.nType == POCKET_CONFORMAL_ONEWAY) {
// curva da resituire
PtrOwner<ICurveComposite> pCrvOptSpiral( CreateCurveComposite()) ;
if ( IsNull( pCrvOptSpiral) ||
! GetSpiralOptimizedCurves( pSfrChunk, PockParam, pCrvOptSpiral))
if ( IsNull( pCrvOptSpiral) ||
! GetSpiralOptimizedCurves( pSfrChunk, PockParam, pCrvOptSpiral))
return false ;
// se ho ricavato una curva ottimizzata
if ( ! IsNull( pCrvOptSpiral) && pCrvOptSpiral->IsValid() && pCrvOptSpiral->GetCurveCount() > 0) {
vCrvOptCurves.emplace_back( Release( pCrvOptSpiral)) ;
vCrvOptCurves.emplace_back( Release( pCrvOptSpiral)) ;
pSfr->EraseChunk( nCurrChunk) ;
}
else
++ nCurrChunk ;
}
else if ( PockParam.nType == POCKET_ZIGZAG || PockParam.nType == POCKET_ONEWAY) {
// curva da restituire
PtrOwner<ICurveComposite> pCrvOptZigZag( CreateCurveComposite()) ;
if ( IsNull( pCrvOptZigZag) ||
! GetZigZagOptimizedCurves( pSfrChunk, PockParam, pCrvOptZigZag))
return false ;
// se ho ricavato una curva ottimizzata
if ( ! IsNull( pCrvOptZigZag) && pCrvOptZigZag->IsValid() && pCrvOptZigZag->GetCurveCount() > 0) {
vCrvOptCurves.emplace_back( Release( pCrvOptZigZag)) ;
pSfr->EraseChunk( nCurrChunk) ;
}
else
++ nCurrChunk ;
}
// else if ( PockParam.nType == POCKET_ZIGZAG)
// ;
// else if ( PockParam.nType == POCKET_ONEWAY)
// ;
// else if ( PockParam.nType == POCKET_CONFORMAL_ONEWAY || PockParam.nType == POCKET_CONFORMAL_ZIGZAG)
// ;
}
return true ;
@@ -8916,14 +9092,14 @@ CalcSpiralPocketing( const ISurfFlatRegion* pSfr, int nType, const PocketParams&
// il tipo può essere solo SpiralIn o SpiralOut
if ( nType != POCKET_SPIRALIN && nType != POCKET_SPIRALOUT)
return false ;
PtrOwner<ISurfFlatRegion> pSfrLimit( PockParams.SfrLimit.IsValid() ? PockParams.SfrLimit.Clone() : CreateSurfFlatRegion()) ;
// calcolo il percorso di svuotatura spiral
return ( CalcPocketing( pSfr, PockParams.dRad, PockParams.dRadialOffset, PockParams.dSideStep,
PockParams.dAngle, PockParams.dOpenMinSafe, nType, PockParams.bSmooth,
PockParams.bCalcUnclearedRegs, PockParams.bInvert, PockParams.bAvoidOpt,
PockParams.bAllowZigZagOneWayBorders, PockParams.bCalcFeed, PockParams.ptStart,
PockParams.SfrLimit.IsValid() ? PockParams.SfrLimit.Clone() : CreateSurfFlatRegion(),
PockParams.bAvoidOpt, PockParams.dMaxOptSize, PockParams.dLiTang, PockParams.nLiType,
vCrvCompoRes)) ;
pSfrLimit, PockParams.bAvoidOpt, PockParams.dMaxOptSize, PockParams.dLiTang,
PockParams.nLiType, vCrvCompoRes)) ;
}
//----------------------------------------------------------------------------
@@ -9218,9 +9394,10 @@ SmoothExtensionLinesByIntersection( ICRVCOMPOPOVECTOR& vCrvPaths, const PocketPa
//----------------------------------------------------------------------------
bool
CalcPocketing( const ISurfFlatRegion* pSfr, double dRad, double dRadOffs, double dStep, double dAngle,
double dOpenMinSafe, int nType, bool bSmooth, bool bCalcUnclReg, bool bInvert, bool bAvoidOpt, bool bAllowZigZagOneWayBorders,
bool bCalcFeed, const Point3d& ptEndPrec, const ISurfFlatRegion* pSfrLimit, bool bAllOffs,
double dMaxOptSize, double dLiTang, int nLiType, ICRVCOMPOPOVECTOR& vCrvCompoRes)
double dOpenMinSafe, int nType, bool bSmooth, bool bCalcUnclReg, bool bInvert, bool bAvoidOpt,
bool bAllowZigZagOneWayBorders, bool bCalcFeed, const Point3d& ptEndPrec,
const ISurfFlatRegion* pSfrLimit, bool bAllOffs, double dMaxOptSize, double dLiTang,
int nLiType, ICRVCOMPOPOVECTOR& vCrvCompoRes)
{
// controllo dei parametri
if ( pSfr == nullptr || ! pSfr->IsValid() ||
+134 -91
View File
@@ -37,6 +37,7 @@
#define SAVECURVEPASSED 0
#define SAVELINEARAPPROX 0
#if SAVEAPPROX || SAVECURVEPASSED || SAVELINEARAPPROX
static int nCrvPassed = 0 ;
#include "/EgtDev/Include/EGkGeoObjSave.h"
#endif
@@ -533,9 +534,8 @@ LineToBezierCurve( const ICurveLine* pCrvLine, int nDeg, bool bMakeRatOrNot)
return nullptr ;
PtrOwner<ICurveBezier> pCrvBezier( CreateCurveBezier()) ;
// rendo tutte le curve di grado 2 e razionali così posso convertire anche archi e avere tutte curve dello stesso grado e razionali
pCrvBezier->Init( nDeg, true) ;
if( ! pCrvBezier->FromLine( *pCrvLine))
pCrvBezier->Init( nDeg, false) ;
if ( ! pCrvBezier->FromLine( *pCrvLine))
return nullptr ;
if ( bMakeRatOrNot)
pCrvBezier->MakeRational() ;
@@ -589,6 +589,13 @@ ArcToBezierCurve( const ICurveArc* pArc, int nDeg, bool bMakeRatOrNot)
PtrOwner<ICurveBezier> pCrvBez( CreateBasicCurveBezier()) ;
if ( IsNull( pCrvBez) || ! pCrvBez->FromArc( cArc))
return nullptr ;
if ( ! bMakeRatOrNot) {
Point3d ptCen = pArc->GetCenter() ;
Vector3d vtN = pArc->GetNormVersor() ;
pCrvBez.Set( ApproxArcCurveBezierWithSingleCubic( pCrvBez, ptCen, vtN)) ;
}
if ( IsNull( pCrvBez))
return nullptr ;
// aumento il grado della curva come richiesto
while ( pCrvBez->GetDegree() < nDeg)
pCrvBez.Set( BezierIncreaseDegree( pCrvBez)) ;
@@ -1147,7 +1154,7 @@ FindSpan( double dU, int nDeg, const DBLVECTOR& vKnots, int& nSpan)
return true ;
}
// trovo a quale span appartiene il parametro dU
int nKnots = int( vKnots.size()) ;
int nKnots = ssize( vKnots) ;
if ( abs( dU - vKnots[nKnots-1]) < EPS_SMALL) {
nSpan = nKnots - 1 - nDeg ;
return true ;
@@ -1173,7 +1180,7 @@ static bool
CalcBasisFunc( double dU, int nSpan, int nDeg, const DBLVECTOR& vKnots, DBLVECTOR& vBasis)
{
// mi aspetto che il vettore vBasis sia di lunghezza nDeg + 1
if ( vBasis.size() != nDeg + 1)
if ( ssize( vBasis) != nDeg + 1)
return false ;
vBasis[0] = 1 ;
@@ -1312,7 +1319,7 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa
int nItCount = 0 ;
while ( dErr > dLinTol && nItCount < 10) {
pCrvInt->Clear() ;
int nPoints = int( vPnt.size()) ;
int nPoints = ssize( vPnt) ;
int nDeg = 3 ;
if ( nPoints < 2)
return nullptr ;
@@ -1328,7 +1335,7 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa
else if ( nPoints == 3) {
// se ho solo tre punti uso un altro algoritmo
CurveByInterp cbi ;
for ( int i = 0 ; i < int( vPnt.size()) ; ++i)
for ( int i = 0 ; i < ssize( vPnt) ; ++i)
cbi.AddPoint( vPnt[i]) ;
pCrvInt->AddCurve( cbi.GetCurve( CurveByInterp::AKIMA_CORNER, CurveByInterp::CUBIC_BEZIERS)) ;
if ( ! IsNull( pCrvInt) && pCrvInt->IsValid())
@@ -1360,7 +1367,7 @@ InterpolatePointSetWithBezier( const PNTVECTOR& vPnt, double dLinTol, double dMa
}
}
if ( vLen.size() != 0) {
if ( ! vLen.empty()) {
if ( nEnd == 0)
nEnd = nPoints - 1 ;
Vector3d vtStartDir = V_INVALID ;
@@ -1402,9 +1409,9 @@ ParamByLen( const PNTVECTOR& vPnt, DBLVECTOR& vParam, int nFirst, int nLast)
int nPoints = nLast - nFirst + 1 ;
if ( nPoints < 2)
return false ;
if( ssize(vParam) == 0)
if ( vParam.empty())
vParam.resize( nPoints) ;
if( vParam[nFirst] == 0 && vParam[nLast] == 1)
if ( vParam[nFirst] == 0 && vParam[nLast] == 1)
return true ;
vParam[nFirst] = 0 ;
for ( int i = nFirst + 1 ; i <= nLast ; ++i) {
@@ -1420,8 +1427,8 @@ ParamByLen( const PNTVECTOR& vPnt, DBLVECTOR& vParam, int nFirst, int nLast)
//----------------------------------------------------------------------------
ICurveBezier*
ApproxPointSetWithSingleBezier( const PNTVECTOR& vPnt, int nFirst, int nLast, const Vector3d& vtStartDir, const Vector3d& vtEndDir,
const DBLVECTOR& vParam)
ApproxPointSetWithSingleBezier( const PNTVECTOR& vPnt, int nFirst, int nLast,
const Vector3d& vtStartDir, const Vector3d& vtEndDir, const DBLVECTOR& vParam)
{
// cerco di approssimare un set di punti con una sola bezier cubica non razionale
int nPoints = nLast - nFirst + 1 ;
@@ -1435,7 +1442,7 @@ ApproxPointSetWithSingleBezier( const PNTVECTOR& vPnt, int nFirst, int nLast, co
pCrvBez->SetControlPoint( 0, pt0) ;
pCrvBez->SetControlPoint( 3, pt3) ;
Eigen::Vector2d mA ;
if( nPoints > 4) {
if ( nPoints > 4) {
// risoluzione sistema
Eigen::Matrix2d mC ; mC.setZero() ;
Eigen::Vector2d mX ; mX.setZero() ;
@@ -1461,16 +1468,14 @@ ApproxPointSetWithSingleBezier( const PNTVECTOR& vPnt, int nFirst, int nLast, co
}
// l'algoritmo è fatto in modo che alpha1 e alpha2 siano positivi ( se tutto va bene)
// io invece ho tenuto le tangenti con la direzione originale, quindi il primo dovrebbe essere positivo e il secondo negativo
if ( mA(0) < 0 || mA(1) > 0 || nPoints < 4) {
if( mA(0) < 0 || mA(1) > 0)
if ( mA(0) < 0 || mA(1) > 0 || nPoints < 4) {
if ( mA(0) < 0 || mA(1) > 0)
LOG_DBG_ERR( GetEGkLogger(), "valori di alfa sballati, potrebbe essere la spaziatura dismogenea tra punti")
double dDistCorr = Dist( pt3, pt0) / 3 ;
mA(0) = dDistCorr ;
mA(1) = - dDistCorr ;
}
double alpah1 = mA(0) ;
double alpha2 = mA(1) ;
Point3d pt1 = pt0 + vtStartDir * mA(0) ;
Point3d pt2 = pt3 + vtEndDir * mA(1) ;
pCrvBez->SetControlPoint( 1, pt1) ;
@@ -1480,14 +1485,15 @@ ApproxPointSetWithSingleBezier( const PNTVECTOR& vPnt, int nFirst, int nLast, co
//----------------------------------------------------------------------------
bool
CalcPointSetApproxError( const PNTVECTOR& vPntOrig, const DBLVECTOR& vParam, int nFirst, int nLast, const ICurve* pCrvNew, double& dErr, int& nPointMaxErr)
CalcPointSetApproxError( const PNTVECTOR& vPntOrig, const DBLVECTOR& vParam,
int nFirst, int nLast, const ICurve* pCrvNew, double& dErr, int& nPointMaxErr)
{
dErr = 0 ;
// calcolo l'errore di approssimazione
for ( int i = nFirst ; i <= nLast ; ++i) {
Point3d ptBez ; pCrvNew->GetPointD1D2( vParam[i], ICurve::Side::FROM_MINUS, ptBez) ;
double dErrTemp = Dist( vPntOrig[i], ptBez) ;
if( dErrTemp > dErr) {
if ( dErrTemp > dErr) {
dErr = dErrTemp ;
nPointMaxErr = i ;
}
@@ -1498,19 +1504,21 @@ CalcPointSetApproxError( const PNTVECTOR& vPntOrig, const DBLVECTOR& vParam, int
//----------------------------------------------------------------------------
ICurve*
FitWithBezier( const ICurve* pCrvOrig, const PNTVECTOR& vPnt, DBLVECTOR& vParam, int nFirst, int nLast, const VCT3DVECTOR& vPrevDer, const VCT3DVECTOR& vNextDer, double dTol)
FitWithBezier( const ICurve* pCrvOrig, const PNTVECTOR& vPnt, DBLVECTOR& vParam,
int nFirst, int nLast, const VCT3DVECTOR& vPrevDer, const VCT3DVECTOR& vNextDer, double dTol, bool bLimitSplit = false)
{
ParamByLen(vPnt, vParam, nFirst, nLast) ;
ParamByLen( vPnt, vParam, nFirst, nLast) ;
PtrOwner<ICurveComposite> pCrvFit( CreateCurveComposite()) ;
PtrOwner<ICurveBezier> pCrvBez( CreateCurveBezier()) ;
double dErr = INFINITO ;
double dErrPrec = INFINITO ;
double dErrSplit = dTol * 25 ;
int nIter = 0 ;
while ( dErr > dTol && nIter < 10) {
if( dErr < INFINITO) {
// riparametrizzo i punti
while ( dErr > dTol && nIter < 10) {
if ( dErr < INFINITO) {
// riparametrizzo i punti
for ( int i = nFirst + 1 ; i < nLast ; ++i) {
//questo potrebbe diventare un while appena capisco di quanto si aggiusta il parametro ad ogni iterazione
// questo potrebbe diventare un while appena capisco di quanto si aggiusta il parametro ad ogni iterazione
double dCorr = 1 ;
do {
Vector3d vtDer1, vtDer2 ;
@@ -1525,32 +1533,50 @@ FitWithBezier( const ICurve* pCrvOrig, const PNTVECTOR& vPnt, DBLVECTOR& vParam,
}
}
// fit della curva
pCrvBez.Set( ApproxPointSetWithSingleBezier( vPnt, nFirst, nLast, vNextDer[nFirst], vPrevDer[nLast], vParam)) ;
if( IsNull( pCrvBez) || ! pCrvBez->IsValid())
// fit della curva
Vector3d vtStartDir, vtEndDir ;
if ( bLimitSplit) {
vtStartDir = vNextDer[nFirst / 3] ;
vtEndDir = vPrevDer[nLast / 3] ;
}
else {
vtStartDir = vNextDer[nFirst] ;
vtEndDir = vPrevDer[nLast] ;
}
pCrvBez.Set( ApproxPointSetWithSingleBezier( vPnt, nFirst, nLast, vtStartDir, vtEndDir, vParam)) ;
if ( IsNull( pCrvBez) || ! pCrvBez->IsValid())
return nullptr ;
#if SAVEAPPROX
SaveGeoObj( pCrvBez->Clone(), "D:\\Temp\\bezier\\approxWithBezier\\first_approx.nge") ;
SaveGeoObj( pCrvBez->Clone(), "D:\\Temp\\bezier\\approxWithBezier\\"+ToString(nCrvPassed) + "first_approx.nge") ;
#endif
int nPointMaxErr = 0 ;
CalcPointSetApproxError( vPnt, vParam, nFirst, nLast, pCrvBez, dErr, nPointMaxErr) ;
// se sto unendo due punti consecutivi e l'errore è oltre quello richiesto allora restituisco un segmento che unisce i punti
if( nLast - nFirst == 1 && dErr > dTol) {
// se sto unendo due punti consecutivi e l'errore è oltre quello richiesto allora restituisco un segmento che unisce i punti
if ( ((nLast - nFirst == 1) || ( bLimitSplit && nLast - nFirst == 3)) && dErr > dTol) {
CurveLine CL ; CL.Set( vPnt[nFirst], vPnt[nLast]) ;
pCrvBez.Set( GetCurveBezier( CurveToBezierCurve( &CL))) ;
dErr = 0 ;
}
if ( bLimitSplit && nPointMaxErr % 3 != 0) {
nPointMaxErr = 3 * int( round( nPointMaxErr / 3.)) ;
if ( nPointMaxErr == nFirst)
nPointMaxErr += 3 ;
else if( nPointMaxErr == nLast)
nPointMaxErr -= 3 ;
}
++nIter ;
bool bSplit = false ;
if( nIter == 10 && dErr > dTol)
if ( ( nIter == 10 && dErr > dTol) || dErr > dErrPrec || dErrPrec - dErr < dErrPrec / 20)
bSplit = true ;
// se la curva di approssimazione è ancora molto lontana dalla curva originale allora divido il set di punti in due
if ( dErr > dErrSplit || bSplit) {
if ( nLast - nFirst > 1) {
if( ! pCrvFit->AddCurve( FitWithBezier( pCrvOrig, vPnt, vParam, nFirst, nPointMaxErr, vPrevDer, vNextDer,dTol)) ||
! pCrvFit->AddCurve( FitWithBezier( pCrvOrig, vPnt, vParam, nPointMaxErr, nLast, vPrevDer, vNextDer, dTol)))
dErrPrec = dErr ;
// se la curva di approssimazione è ancora molto lontana dalla curva originale allora divido il set di punti in due
if ( dErr > dErrSplit || bSplit) {
if ( nLast - nFirst > 1 && nPointMaxErr - nFirst > 1 && nLast - nPointMaxErr > 1) {
if ( ! pCrvFit->AddCurve( FitWithBezier( pCrvOrig, vPnt, vParam, nFirst, nPointMaxErr, vPrevDer, vNextDer,dTol, bLimitSplit)) ||
! pCrvFit->AddCurve( FitWithBezier( pCrvOrig, vPnt, vParam, nPointMaxErr, nLast, vPrevDer, vNextDer, dTol, bLimitSplit)))
return nullptr ;
break ;
}
@@ -1561,17 +1587,15 @@ FitWithBezier( const ICurve* pCrvOrig, const PNTVECTOR& vPnt, DBLVECTOR& vParam,
if ( pCrvFit->GetCurveCount() > 0)
return Release( pCrvFit) ;
else if ( dErr < dTol && ! IsNull( pCrvBez) && pCrvBez->IsValid())
else if ( dErr < dTol && ! IsNull( pCrvBez) && pCrvBez->IsValid())
return Release( pCrvBez) ;
else
return nullptr ;
}
static int nCrvPassed = 0 ;
//----------------------------------------------------------------------------
ICurve*
ApproxCurveWithBezier( const ICurve* pCrv , double dTol, int nType)
ApproxCurveWithBezier( const ICurve* pCrv , double dTol)
{
#if SAVECURVEPASSED
@@ -1591,47 +1615,48 @@ ApproxCurveWithBezier( const ICurve* pCrv , double dTol, int nType)
SaveGeoObj( CC.Clone(), "D:\\Temp\\bezier\\approxWithBezier\\approssimazione_lineare.nge") ;
#endif
CurveByInterp cbi ;
PNTVECTOR vPnt ;
PNTVECTOR vPntOverSampling ;
Point3d pt ; plApprox.GetFirstPoint( pt) ;
do {
if ( ssize(vPnt) != 0) {
vPnt.push_back( Media(vPnt.back(), pt,1./3.)) ;
vPnt.push_back( Media(vPnt.back(), pt,2./3.)) ;
if ( ! vPntOverSampling.empty()) {
vPntOverSampling.push_back( Media( vPnt.back(), pt,1./3.)) ;
vPntOverSampling.push_back( Media( vPnt.back(), pt,2./3.)) ;
}
vPntOverSampling.push_back( pt) ;
vPnt.push_back( pt) ;
cbi.AddPoint( pt) ;
} while ( plApprox.GetNextPoint( pt)) ;
// calcolo la curvatura nei vari punti per identificare zone a curvatura costante
DBLVECTOR vCrvVal( ssize(vPnt)) ;
DBLVECTOR vRad ( ssize( vPnt)) ;
for( int i = 1 ; i < ssize( vPnt) - 1 ; ++i) {
for ( int i = 1 ; i < ssize( vPnt) - 1 ; ++i) {
Vector3d vtA = vPnt[i] - vPnt[i-1] ;
Vector3d vtB = vPnt[i+1] - vPnt[i-1] ;
double dR = ( vtA.Len() * vtB.Len() * ( vtA - vtB).Len()) / ( 2 * (vtA ^ vtB).Len()) ;
double dCurvature = dR > 0 ? 1. / dR : 0 ;
double dR = ( vtA.Len() * vtB.Len() * ( vtA - vtB).Len()) / ( 2 * ( vtA ^ vtB).Len()) ;
vRad[i] = dR ;
vCrvVal[i] = dCurvature ;
}
vCrvVal[0] = vCrvVal[1] ;
vCrvVal.back() = vCrvVal.end()[-2] ;
vRad[0] = vRad[1] ;
vRad.back() = vRad.end()[-2] ;
// identifico le zone a curvatura costante // primo e ultimo punto degli intervalli non devono avere curvatura uguale agli altri perché sono di frontiera
INTINTVECTOR vConstCurv ;
double dCurvaturePrec = vCrvVal[0] ;
double dRadPrec = vRad[0] ;
int nStart = 0 ;
int nEnd = 1 ;
double dRatio = 1.5 ;
while ( nStart < ssize( vPnt) - 1) {
dCurvaturePrec = vCrvVal[nEnd] ;
while ( nEnd < ssize( vPnt) - 1 && abs( vCrvVal[nEnd] - dCurvaturePrec) < 0.1) {
dCurvaturePrec = vCrvVal[nEnd] ;
double dRadTol = max( max( vRad[nEnd], dRadPrec) / 10 , 1.) ;
if ( dRadPrec > dRatio * vRad[nEnd] || dRatio * dRadPrec < vRad[nEnd])
dRadTol = 0 ;
while ( nEnd < ssize( vPnt) - 1 && abs( vRad[nEnd] - dRadPrec) < dRadTol) {
dRadPrec = vRad[nEnd] ;
++nEnd ;
}
vConstCurv.emplace_back( nStart, nEnd) ;
vConstCurv.emplace_back( nStart * 3, nEnd * 3) ;
nStart = nEnd ;
dRadPrec = vRad[nEnd] ;
++nEnd ;
}
if( ssize(vConstCurv) == 0)
if ( vConstCurv.empty())
vConstCurv.emplace_back( 0, ssize( vPnt) - 1) ;
int nPoints = ssize( vPnt) ;
@@ -1643,22 +1668,40 @@ ApproxCurveWithBezier( const ICurve* pCrv , double dTol, int nType)
VCT3DVECTOR vPrevDer ;
VCT3DVECTOR vNextDer ;
ComputeAkimaTangents( false, vParam, vPnt, vPrevDer, vNextDer) ;
int nOverSampling = ssize( vPntOverSampling) ;
vParam.resize( nOverSampling) ;
nFirst = 0 ;
nLast = nOverSampling - 1 ;
ParamByLen( vPntOverSampling, vParam, nFirst, nLast) ;
//normalizzo tutte le derivate
for( int i = 0 ; i < ssize( vPrevDer) ; ++i) {
for ( int i = 0 ; i < ssize( vPrevDer) ; ++i) {
vPrevDer[i].Normalize() ;
vNextDer[i].Normalize() ;
}
// potrei verificare prima se un tratto è retto e aggiustare le tangenti del tratto precedente e successivo prima di approssimare
PtrOwner<ICurveComposite> pCCApproxTot( CreateCurveComposite()) ;
for( INTINT iiSE : vConstCurv) {
for ( INTINT iiSE : vConstCurv) {
nFirst = iiSE.first ;
nLast = iiSE.second ;
//definisco la bezier che vado a raffinare iterativamente
PtrOwner<ICurve> pCApprox( FitWithBezier( pCrv, vPnt, vParam, nFirst, nLast, vPrevDer, vNextDer, dTol)) ;
if( IsNull( pCApprox) || ! pCApprox->IsValid())
return nullptr ;
if( ! pCCApproxTot->AddCurve( Release( pCApprox)))
return nullptr ;
// riconosco se ho un tratto retto
int nPnt = nFirst / 3 ;
if ( nLast - nFirst == 3 && ( nPnt > 0 && vRad[nPnt] > dRatio * vRad[nPnt - 1]) && ( nPnt < ssize( vRad) && vRad[nPnt]> dRatio * vRad[nPnt + 1])) {
CurveLine CL ; CL.Set( vPntOverSampling[nFirst], vPntOverSampling[nLast]) ;
PtrOwner<ICurveBezier> pCApprox( LineToBezierCurve( &CL, 3, false)) ;
if ( ! pCCApproxTot->AddCurve( Release( pCApprox)))
return nullptr ;
}
else {
//definisco la bezier che vado a raffinare iterativamente
PtrOwner<ICurve> pCApprox( FitWithBezier( pCrv, vPntOverSampling, vParam, nFirst, nLast, vPrevDer, vNextDer, dTol, true)) ;
if ( IsNull( pCApprox) || ! pCApprox->IsValid())
return nullptr ;
if ( ! pCCApproxTot->AddCurve( Release( pCApprox)))
return nullptr ;
}
}
return Release( pCCApproxTot) ;
@@ -1668,7 +1711,7 @@ ApproxCurveWithBezier( const ICurve* pCrv , double dTol, int nType)
bool
CalcApproxError( const ICurve* pCrvOri, const ICurve* pCrvNew, double& dErr, int nPoints)
{
if( pCrvOri == nullptr || ! pCrvOri->IsValid() || pCrvNew == nullptr || ! pCrvNew->IsValid()){
if ( pCrvOri == nullptr || ! pCrvOri->IsValid() || pCrvNew == nullptr || ! pCrvNew->IsValid()){
dErr = INFINITO ;
return false ;
}
@@ -1753,7 +1796,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
{
// se con nodi extra
if ( cnData.bExtraKnotes) {
int nKnotesNbr = int( cnData.vU.size()) ;
int nKnotesNbr = ssize( cnData.vU) ;
if ( nKnotesNbr < 4)
return false ;
cnData.bExtraKnotes = false ;
@@ -1767,7 +1810,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
bool bAlreadyChecked = false ;
// se la curva è peridica verifco che effettivamente ci sia un numero di punti ripetituti uguale al grado della curva
// wrap della curva su se stessa
if ( cnData.bPeriodic && (int(cnData.vU.size()) > int(cnData.vCP.size()) + cnData.nDeg - 1)) {
if ( cnData.bPeriodic && ( ssize( cnData.vU) > ssize( cnData.vCP) + cnData.nDeg - 1)) {
bool bRepeated = true ;
for ( int i = 0 ; i < cnData.nDeg ; ++i) {
if ( ! AreSamePointApprox( cnData.vCP[i], cnData.vCP.end()[-cnData.nDeg + i]) ) {
@@ -1776,11 +1819,11 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
}
}
bool bFirstAddedAtEnd = false ;
if ( ! bRepeated || (bRepeated && AreSamePointApprox( cnData.vCP[0],cnData.vCP[cnData.nDeg]))){
if ( ! bRepeated || ( bRepeated && AreSamePointApprox( cnData.vCP[0], cnData.vCP[cnData.nDeg]))) {
// salvo il vettore dei nodi in caso mi accorga di avere tra le mani una curva unclamped
DBLVECTOR vU = cnData.vU ;
// se effettivamente ho dei nodi in più da togliere allora li tolgo ed eventualmente aggiungo punti di controllo
if ( int(cnData.vU.size()) > int(cnData.vCP.size()) + cnData.nDeg - 1 ) {
if ( ssize( cnData.vU) > ssize( cnData.vCP) + cnData.nDeg - 1 ) {
// se il primo e l'ultimo punto non coincidono allora aggiungo il primo punto in fondo al vettore dei punti di controllo
if ( ! AreSamePointApprox( cnData.vCP[0], cnData.vCP.back())) {
bFirstAddedAtEnd = true ;
@@ -1792,11 +1835,11 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
cnData.vU = DBLVECTOR( cnData.vU.begin(), cnData.vU.end() - cnData.nDeg) ;
// controllo eventualmente anche i nodi extra
// se ne ho due in più ne tolgo uno in cima e uno in fondo
if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg + 1 ) { // significa che ci sono due nodi extra, uno all'inizio e uno alla fine, da togliere
if ( ssize( cnData.vU) == ssize( cnData.vCP) + cnData.nDeg + 1) { // significa che ci sono due nodi extra, uno all'inizio e uno alla fine, da togliere
cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end() - 1) ;
}
// se ne ho solo uno in più lo tolgo in cima
else if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg) {
else if ( ssize( cnData.vU) == ssize( cnData.vCP) + cnData.nDeg) {
cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end()) ;
}
}
@@ -1823,7 +1866,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
// recupero il vettore dei nodi
cnData.vU = vU ;
// verifico se ho nodi extra
if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg + 1 ) {
if ( ssize( cnData.vU) == ssize( cnData.vCP) + cnData.nDeg + 1 ) {
// significa che ci sono due nodi extra:
// se la curva ha grado maggiore di 1 e i primi due nodi sono uguali allora tolgo quelli
if ( cnData.nDeg > 1 && abs(cnData.vU[1] - cnData.vU[0]) < EPS_SMALL) {
@@ -1834,7 +1877,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end() - 1) ;
}
// se ne ho solo uno in più lo tolgo in cima
else if ( cnData.vU.size() == int( cnData.vCP.size()) + cnData.nDeg)
else if ( ssize( cnData.vU) == ssize( cnData.vCP) + cnData.nDeg)
cnData.vU = vector<double>( cnData.vU.begin() + 1, cnData.vU.end()) ;
}
bAlreadyChecked = true ;
@@ -1859,7 +1902,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
// qui aggiungo un controllo se la curva è collassata in un punto ( ho un polo), lascio stare
bool bCollapsed = true ;
Point3d ptFirst = cnData.vCP.front() ;
for ( int i = 1 ; i < int( cnData.vCP.size()) ; ++i) {
for ( int i = 1 ; i < ssize( cnData.vCP) ; ++i) {
if ( ! AreSamePointApprox( ptFirst, cnData.vCP[i])) {
bCollapsed = false ;
break ;
@@ -1876,7 +1919,7 @@ NurbsCurveCanonicalize( CNurbsData& cnData)
// agli indici perché uso u_p-1 e u_(m-p+1), anziché u_p e u_m-p
// comincio ad aumentare la molteplictià del nodo u_m-p+1
int nCP = int( cnData.vCP.size()) ;
int nCP = ssize( cnData.vCP) ;
int nU = nCP + cnData.nDeg - 1 ;
int nDeg = cnData.nDeg ;
PNTVECTOR vBC ;
@@ -2072,9 +2115,9 @@ NurbsToBezierCurve( const CNurbsData& cnData)
if ( cnData.bPeriodic || cnData.bExtraKnotes)
return nullptr ;
// numero dei nodi
int nU = int( cnData.vCP.size()) + cnData.nDeg - 1 ;
int nU = ssize( cnData.vCP) + cnData.nDeg - 1 ;
// controllo relazione nodi - punti di controllo
if ( nU != int( cnData.vU.size()))
if ( nU != ssize( cnData.vU))
return nullptr ;
// numero degli intervalli
int nInt = nU - 2 * cnData.nDeg + 1 ;
@@ -2444,7 +2487,7 @@ CalcCurvesVoronoiDiagram( const CICURVEPVECTOR& vCrvC, ICURVEPOVECTOR& vCrvs, in
PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ;
if ( pVoronoiObj == nullptr)
return false ;
for ( int i = 0 ; i < int( vCrvC.size()) ; i ++) {
for ( int i = 0 ; i < ssize( vCrvC) ; i ++) {
if ( ! pVoronoiObj->AddCurve( vCrvC[i]))
return false ;
}
@@ -2471,7 +2514,7 @@ CalcCurvesMedialAxis( const CICURVEPVECTOR& vCrvC, ICURVEPOVECTOR& vCrvs, int nS
PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ;
if ( pVoronoiObj == nullptr)
return false ;
for ( int i = 0 ; i < int( vCrvC.size()) ; i ++) {
for ( int i = 0 ; i < ssize( vCrvC) ; i ++) {
if ( ! pVoronoiObj->AddCurve( vCrvC[i]))
return false ;
}
@@ -2532,7 +2575,7 @@ bool CalcOffsetCurves( const ICURVEPVECTOR& vpCrvs, ICURVEPOVECTOR& vCrvs, doubl
PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ;
if ( pVoronoiObj == nullptr)
return false ;
for ( int i = 0 ; i < int( vpCrvs.size()) ; i ++) {
for ( int i = 0 ; i < ssize( vpCrvs) ; i ++) {
if ( ! pVoronoiObj->AddCurve( vpCrvs[i]))
return false ;
}
@@ -2562,7 +2605,7 @@ bool CalcFatOffsetCurves( const ICURVEPVECTOR& vpCrvs, ICURVEPOVECTOR& vCrvs, do
PtrOwner<Voronoi> pVoronoiObj( new( std::nothrow) Voronoi()) ;
if ( pVoronoiObj == nullptr)
return false ;
for ( int i = 0 ; i < int( vpCrvs.size()) ; i ++) {
for ( int i = 0 ; i < ssize( vpCrvs) ; i ++) {
if ( ! pVoronoiObj->AddCurve( vpCrvs[i]))
return false ;
}
@@ -2596,7 +2639,7 @@ ResetCurveVoronoi( const ICurve& crvC)
bool
GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert)
{
if( ssize( vCrv) == 1)
if ( ssize( vCrv) == 1)
return true ;
ChainCurves chainCrv ;
// modifico direttamente le curve passate in input
@@ -2616,22 +2659,22 @@ GetChainedCurves( ICRVCOMPOPOVECTOR& vCrv, double dChainTol, bool bAllowInvert)
ICurveComposite* pFirstCrv = vCrv[abs(vIds[0]) - 1] ;
for ( int nId : vIds) {
bool bInvert = false ;
if( nId < 0)
if ( nId < 0)
bInvert = true ;
nId = abs( nId) - 1 ;
if( bInvert)
if ( bInvert)
vCrv[nId]->Invert() ;
if( ! pFirstCrv->AddCurve( Release( vCrv[nId]), true, dChainTol))
if ( ! pFirstCrv->AddCurve( Release( vCrv[nId]), true, dChainTol))
return false ;
}
pFirstCrv->GetEndPoint( ptStart) ;
}
// elimino gli elementi del vettore che non contengono più curve
int c = ssize( vCrv) ;
while( c > -1) {
if( IsNull( vCrv[c]))
while ( c > -1) {
if ( IsNull( vCrv[c]))
vCrv.erase( vCrv.begin() + c) ;
--c ;
}
return true ;
}
}
+3 -4
View File
@@ -275,20 +275,19 @@ CurveBezier::FromLine( const ICurveLine& crLine)
{
if ( m_nStatus != OK || ! crLine.IsValid())
return false ;
double dWeight = 1 ;
int nCount = 0 ;
Point3d ptStart ; crLine.GetStartPoint( ptStart) ;
SetControlPoint( nCount, ptStart, dWeight) ;
SetControlPoint( nCount, ptStart) ;
++nCount ;
double dPart = 1. / m_nDeg ;
for ( int i = 1 ; i < m_nDeg ; ++i) {
double dU = i * dPart ;
Point3d ptMid ; crLine.GetPointD1D2( dU, ICurve::FROM_MINUS, ptMid) ;
SetControlPoint( nCount, ptMid, dWeight) ;
SetControlPoint( nCount, ptMid) ;
++nCount ;
}
Point3d ptEnd ; crLine.GetEndPoint( ptEnd) ;
SetControlPoint( nCount, ptEnd, dWeight) ;
SetControlPoint( nCount, ptEnd) ;
++nCount ;
return true ;
}
+15 -2
View File
@@ -116,6 +116,7 @@ PolishMinDistPointCurve( const Point3d& ptP, const ICurve& cCurve,
vtDiff = ptQ - ptP ;
// angolo tra vettore e tangente
dTemp = vtDer1 * vtDiff ;
bool bEquiverse = dTemp > 0 ;
if ( abs( dTemp) > EPS_ZERO)
dSqCosA = dTemp * dTemp / ( vtDer1.SqLen() * vtDiff.SqLen()) ;
else
@@ -123,8 +124,20 @@ PolishMinDistPointCurve( const Point3d& ptP, const ICurve& cCurve,
// stima prossimo valore del parametro (Newton : Unext = U - F(U) / F'(U))
dPrevPar = dPar ;
dTemp = vtDer2 * vtDiff + vtDer1.SqLen() ;
if ( abs( dTemp) > EPS_ZERO)
dPar = dPrevPar - ( vtDer1 * vtDiff) / dTemp ;
// se il coseno tra questi due vettori è troppo grande potrei aver avuto una cattiva stima iniziale
// provo quindi ad aggiustare a mano, anziché usare il segno suggerito da newton, che con queste premesse potrebbe divergere
double dCos75 = 0.2588 ;
if ( abs( dTemp) > EPS_ZERO) {
double dDelta = ( vtDer1 * vtDiff) / dTemp ;
if ( dSqCosA > dCos75) {
if ( ( bEquiverse && dDelta > 0) || ( ! bEquiverse && dDelta < 0))
dDelta *= -1 ;
dPar = dPrevPar + dDelta ;
}
else
dPar = dPrevPar - dDelta ;
}
// clipping parametro
if ( dPar < approxMin.dParMin) {
if ( approxMin.bParMinSing && ! bClampedFromSing) {
+12 -1
View File
@@ -26,7 +26,7 @@ DistPointCrvBezier::DistPointCrvBezier( const Point3d& ptP, const ICurveBezier&
// distanza non calcolata
m_dDist = - 1 ;
if ( &CrvBez == nullptr || ! CrvBez.IsValid())
if ( ! CrvBez.IsValid())
return ;
// determino tolleranza di approssimazione in base a ingombro curva
@@ -42,6 +42,17 @@ DistPointCrvBezier::DistPointCrvBezier( const Point3d& ptP, const ICurveBezier&
if ( ! CrvBez.ApproxWithLines( dLinTol, ANG_TOL_APPROX_DEG, ICurve::APL_STD, PL))
return ;
int nDeg = CrvBez.GetDegree() ;
if ( PL.GetPointNbr() < nDeg + 1) {
// costruisco una polilinea con un numero di curve scelto in base al grado della curva
PL.Clear() ;
for ( int i = 0 ; i <= nDeg + 1 ; ++i) {
double dU = double(i) / (nDeg + 1) ;
Point3d ptBez ;
CrvBez.GetPointD1D2( dU, ICurve::Side::FROM_MINUS, ptBez) ;
PL.AddUPoint( dU, ptBez) ;
}
}
// cerco la minima distanza per la polilinea
MDCVECTOR vApproxMin ;
if ( ! CalcMinDistPointPolyLine( ptP, PL, dLinTol, vApproxMin))
+11 -10
View File
@@ -23,10 +23,10 @@ using namespace std ;
//----------------------------------------------------------------------------
DistPointSurfBz::DistPointSurfBz( const Point3d& ptP, const ISurfBezier& pSrfBz)
: m_dDist( -1), m_bIsInside( false)
: m_dDist( -1), m_bIsInside( false), m_bIsSurfClosed( false)
{
// Bezier non valida
if ( &pSrfBz == nullptr || ! pSrfBz.IsValid())
if ( ! pSrfBz.IsValid())
return ;
// Calcolo la distanza
Calculate( ptP, pSrfBz) ;
@@ -37,9 +37,9 @@ void
DistPointSurfBz::Calculate( const Point3d& ptP, const ISurfBezier& srfBz)
{
// Inizializzo distanza non calcolata
m_dDist = - 1. ;
m_dDist = -1 ;
// Controllo se la superficie è chiusa
// Controllo se la superficie è chiusa
m_bIsSurfClosed = srfBz.IsClosed() ;
// Lavoro con l'oggetto superficie trimesh di base
@@ -49,17 +49,17 @@ DistPointSurfBz::Calculate( const Point3d& ptP, const ISurfBezier& srfBz)
DistPointSurfTm dpst( ptP, *pStmRef) ;
//recupero il punto a distanza minima sulla trimesh e lo raffino, prima di restituire distanza e punto minimo
// recupero il punto a distanza minima sulla trimesh e lo raffino, prima di restituire distanza e punto minimo
Point3d ptMinTm ; dpst.GetMinDistPoint( ptMinTm) ;
int nT ; dpst.GetMinDistTriaIndex( nT) ;
//salvo il punto corrispondente nel parametrico
// salvo il punto corrispondente nel parametrico
srfBz.UnprojectPointFromStm( nT, ptMinTm, m_ptParam) ;
// salvo il punto a minima distanza sulla superficie e la normale alla superficie in quel punto
srfBz.GetPointNrmD1D2( m_ptParam.x, m_ptParam.y, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS, m_ptMinDistPoint, m_vtN) ;
// salvo la distanza minima
m_dDist = Dist( ptP, m_ptMinDistPoint) ;
// se il punto è sulla superficie
// se il punto è sulla superficie
if ( m_dDist < EPS_SMALL) {
m_bIsInside = false ;
return ;
@@ -96,13 +96,14 @@ DistPointSurfBz::GetMinDistPoint( Point3d& ptMinDistPoint) const
//----------------------------------------------------------------------------
bool
DistPointSurfBz::GetParamPoint( Point3d& ptParamPoint) const
DistPointSurfBz::GetParamsAtMinDistPoint( double& dU, double& dV) const
{
// Distanza non valida
if ( m_dDist < -EPS_ZERO)
return false ;
// Distanza valida
ptParamPoint = m_ptParam ;
dU = m_ptParam.x ;
dV = m_ptParam.y ;
return true ;
}
@@ -116,4 +117,4 @@ DistPointSurfBz::GetNorm( Vector3d& vtN) const
// Distanza valida
vtN = m_vtN ;
return true ;
}
}
BIN
View File
Binary file not shown.
+232 -101
View File
@@ -34,6 +34,7 @@ static bool CalcATypeFromDisk( const ICurve& CurveA, double dUA, ICurve::Side nS
const ICurve& CurveB, double dUB, int& nType) ;
static bool CalcATypeFromDisk2( const ICurve& CurveA, double dUA, ICurve::Side nSideA,
const ICurve& CurveB, double dUB1, double dUB2, int& nType) ;
static bool CalcSide( const IntCrvCrvInfo& Icci1, const IntCrvCrvInfo& Icci2, const ICurve* pThisCrv, const ICurve* pOtherCrv, bool bCrvAOrB, int& nType) ;
//----------------------------------------------------------------------------
IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
@@ -197,7 +198,7 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
// se coincidono U e ptInt tra A e B
if ( abs( m_Info[i].IciA[0].dU - m_Info[j].IciB[0].dU) < EPS_SMALL &&
AreSamePointXYEpsilon( m_Info[i].IciA[0].ptI, m_Info[j].IciB[0].ptI, 10 * EPS_SMALL)) {
// se non è alla fine di curva chiusa
// se non è alla fine di curva chiusa
if ( ! bCrvAClosed || abs( m_Info[j].IciA[0].dU - dCrvBSpan) > EPS_SMALL)
// elimino la seconda
EraseOtherInfo( i, j) ;
@@ -264,7 +265,7 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
EraseOtherInfo( i, j) ;
EraseCurrentInfo( i, j) ;
}
// caso DET-NULL -> NULL-DET per prima curva
// caso DET-(NULL) -> (NULL)-DET per prima curva
else if ( m_Info[j].IciA[kj].nPrevTy != ICCT_NULL && m_Info[j].IciA[kj].nNextTy == ICCT_NULL &&
m_Info[i].IciA[ki].nPrevTy == ICCT_NULL && m_Info[i].IciA[ki].nNextTy != ICCT_NULL) {
// per la prima curva tengo i determinati
@@ -272,16 +273,22 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
m_Info[j].IciA[kj].nNextTy = m_Info[i].IciA[ki].nNextTy ;
// se overlap equiverso
if ( m_Info[i].bOverlap && m_Info[i].bCBOverEq) {
// per la seconda curva ogni sottotipo è il duale di quello della prima
// per la seconda curva ogni sottotipo è il duale di quello della prima
m_Info[i].IciB[ki].nPrevTy = GetDualIcct( m_Info[i].IciA[ki].nPrevTy) ;
m_Info[i].IciB[ki].nNextTy = GetDualIcct( m_Info[i].IciA[ki].nNextTy) ;
}
// se altrimenti overlap controverso
else if ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq) {
// per la seconda curva ogni sottotipo è come quello della prima ma in posizione invertita
// per la seconda curva ogni sottotipo è come quello della prima ma in posizione invertita
m_Info[i].IciB[ki].nPrevTy = m_Info[i].IciA[ki].nNextTy ;
m_Info[i].IciB[ki].nNextTy = m_Info[i].IciA[ki].nPrevTy ;
}
else {
if ( m_Info[i].IciB[ki].nPrevTy == ICCT_NULL)
m_Info[i].IciB[ki].nPrevTy = m_Info[j].IciB[kj].nPrevTy ;
if ( m_Info[i].IciB[ki].nNextTy == ICCT_NULL)
m_Info[i].IciB[ki].nNextTy = m_Info[j].IciB[kj].nNextTy ;
}
// se overlap equiverso
if ( m_Info[j].bOverlap && m_Info[j].bCBOverEq) {
m_Info[j].IciB[kj].nPrevTy = GetDualIcct( m_Info[i].IciA[ki].nPrevTy) ;
@@ -292,6 +299,13 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
m_Info[j].IciB[kj].nPrevTy = m_Info[i].IciA[ki].nNextTy ;
m_Info[j].IciB[kj].nNextTy = m_Info[i].IciA[ki].nPrevTy ;
}
else {
if ( m_Info[j].IciB[kj].nPrevTy == ICCT_NULL)
m_Info[j].IciB[kj].nPrevTy = m_Info[i].IciB[ki].nPrevTy ;
if ( m_Info[j].IciB[kj].nNextTy == ICCT_NULL)
m_Info[j].IciB[kj].nNextTy = m_Info[i].IciB[ki].nNextTy ;
}
// medio parametri e punti separatamente per le due curve
MediaParamPoints( m_Info[i].IciA[ki], m_Info[j].IciA[kj], CCompoA) ;
MediaParamPoints( m_Info[i].IciB[ki], m_Info[j].IciB[kj], CCompoB) ;
@@ -306,7 +320,7 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
EraseCurrentInfo( i, j) ;
}
}
// caso NULL-DET -> DET-NULL per prima curva (possibile su inizio/fine di curva chiusa)
// caso (NULL)-DET -> DET-(NULL) per prima curva (possibile su inizio/fine di curva chiusa)
else if ( m_Info[j].IciA[kj].nPrevTy == ICCT_NULL && m_Info[j].IciA[kj].nNextTy != ICCT_NULL &&
m_Info[i].IciA[ki].nPrevTy != ICCT_NULL && m_Info[i].IciA[ki].nNextTy == ICCT_NULL) {
// per la prima curva tengo i determinati
@@ -314,28 +328,41 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
m_Info[j].IciA[kj].nPrevTy = m_Info[i].IciA[ki].nPrevTy ;
// se overlap equiverso
if ( m_Info[i].bOverlap && m_Info[i].bCBOverEq) {
// per la seconda curva ogni sottotipo è il duale di quello della prima
// per la seconda curva ogni sottotipo è il duale di quello della prima
m_Info[i].IciB[ki].nPrevTy = GetDualIcct( m_Info[i].IciA[ki].nPrevTy) ;
m_Info[i].IciB[ki].nNextTy = GetDualIcct( m_Info[i].IciA[ki].nNextTy) ;
}
// se altrimenti overlap controverso
else if ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq) {
// per la seconda curva ogni sottotipo è come quello della prima ma in posizione scambiata
// per la seconda curva ogni sottotipo è come quello della prima ma in posizione scambiata
m_Info[i].IciB[ki].nPrevTy = m_Info[i].IciA[ki].nNextTy ;
m_Info[i].IciB[ki].nNextTy = m_Info[i].IciA[ki].nPrevTy ;
}
else {
if ( m_Info[i].IciB[ki].nPrevTy == ICCT_NULL)
m_Info[i].IciB[ki].nPrevTy = m_Info[j].IciB[kj].nPrevTy ;
if ( m_Info[i].IciB[ki].nNextTy == ICCT_NULL)
m_Info[i].IciB[ki].nNextTy = m_Info[j].IciB[kj].nNextTy ;
}
// se overlap equiverso
if ( m_Info[j].bOverlap && m_Info[j].bCBOverEq) {
// per la seconda curva ogni sottotipo è il duale di quello della prima
// per la seconda curva ogni sottotipo è il duale di quello della prima
m_Info[j].IciB[kj].nPrevTy = GetDualIcct( m_Info[i].IciA[ki].nPrevTy) ;
m_Info[j].IciB[kj].nNextTy = GetDualIcct( m_Info[i].IciA[ki].nNextTy) ;
}
// se altrimenti overlap controverso
else if ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq) {
// per la seconda curva ogni sottotipo è come quello della prima ma in posizione scambiata
// per la seconda curva ogni sottotipo è come quello della prima ma in posizione scambiata
m_Info[j].IciB[kj].nPrevTy = m_Info[i].IciA[ki].nNextTy ;
m_Info[j].IciB[kj].nNextTy = m_Info[i].IciA[ki].nPrevTy ;
}
else {
if ( m_Info[j].IciB[kj].nPrevTy == ICCT_NULL)
m_Info[j].IciB[kj].nPrevTy = m_Info[i].IciB[ki].nPrevTy ;
if ( m_Info[j].IciB[kj].nNextTy == ICCT_NULL)
m_Info[j].IciB[kj].nNextTy = m_Info[i].IciB[ki].nNextTy ;
}
// medio parametri e punti separatamente per le due curve
MediaParamPoints( m_Info[i].IciA[ki], m_Info[j].IciA[kj], CCompoA) ;
MediaParamPoints( m_Info[i].IciB[ki], m_Info[j].IciB[kj], CCompoB) ;
@@ -370,17 +397,21 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
}
// caso NULL-NULL per corrente di prima curva
else if ( m_Info[i].IciA[ki].nPrevTy == ICCT_NULL && m_Info[i].IciA[ki].nNextTy == ICCT_NULL) {
m_Info[j].IciA[kj].nNextTy = m_Info[i].IciA[ki].nNextTy ;
if ( m_Info[i].IciB[ki].dU > m_Info[j].IciB[kj].dU + EPS_PARAM)
m_Info[j].IciA[kj].nNextTy = ICCT_NULL ;
if ( m_Info[j].IciB[kj].nNextTy == ICCT_NULL)
m_Info[j].IciB[kj].nNextTy = m_Info[i].IciB[ki].nNextTy ;
if ( m_Info[j].IciB[kj].nPrevTy == ICCT_NULL)
m_Info[j].IciB[kj].nPrevTy = m_Info[i].IciB[ki].nPrevTy ;
// cancello l'intersezione corrente (non aggiunge nulla rispetto alla precedente)
EraseCurrentInfo( i, j) ;
}
// caso NULL-NULL per precedente di prima curva
else if ( m_Info[j].IciA[kj].nPrevTy == ICCT_NULL && m_Info[j].IciA[kj].nNextTy == ICCT_NULL) {
m_Info[i].IciA[ki].nPrevTy = m_Info[j].IciA[kj].nPrevTy ;
if ( m_Info[j].IciB[kj].dU < m_Info[i].IciB[ki].dU - EPS_PARAM)
m_Info[i].IciA[ki].nPrevTy = ICCT_NULL ;
if ( m_Info[i].IciB[ki].nPrevTy == ICCT_NULL)
m_Info[i].IciB[ki].nPrevTy = m_Info[j].IciB[kj].nPrevTy ;
if ( m_Info[i].IciB[ki].nNextTy == ICCT_NULL)
m_Info[i].IciB[ki].nNextTy = m_Info[j].IciB[kj].nNextTy ;
// cancello l'intersezione precedente (non aggiunge nulla rispetto alla corrente)
EraseOtherInfo( i, j) ;
}
@@ -414,7 +445,7 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
EraseOtherInfo( i, j) ;
EraseCurrentInfo( i, j) ;
}
// caso DET-NULL -> NULL-DET per seconda curva
// caso DET-(NULL) -> (NULL)-DET per seconda curva
else if ( m_Info[j].IciB[kj].nPrevTy != ICCT_NULL && m_Info[j].IciB[kj].nNextTy == ICCT_NULL &&
m_Info[i].IciB[ki].nPrevTy == ICCT_NULL && m_Info[i].IciB[ki].nNextTy != ICCT_NULL) {
// per la seconda curva tengo i determinati
@@ -422,25 +453,25 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
m_Info[j].IciB[kj].nNextTy = m_Info[i].IciB[ki].nNextTy ;
// se overlap equiverso
if ( m_Info[i].bOverlap && m_Info[i].bCBOverEq) {
// per la prima curva ogni sottotipo è il duale di quello della seconda
// per la prima curva ogni sottotipo è il duale di quello della seconda
m_Info[i].IciA[ki].nPrevTy = GetDualIcct( m_Info[i].IciB[ki].nPrevTy) ;
m_Info[i].IciA[ki].nNextTy = GetDualIcct( m_Info[i].IciB[ki].nNextTy) ;
}
// se altrimenti overlap controverso
else if ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq) {
// per la prima curva ogni sottotipo è come quello della seconda ma in posizione scambiata
// per la prima curva ogni sottotipo è come quello della seconda ma in posizione scambiata
m_Info[i].IciA[ki].nPrevTy = m_Info[i].IciB[ki].nNextTy ;
m_Info[i].IciA[ki].nNextTy = m_Info[i].IciB[ki].nPrevTy ;
}
// se overlap equiverso
if ( m_Info[j].bOverlap && m_Info[j].bCBOverEq) {
// per la prima curva ogni sottotipo è il duale di quello della seconda
// per la prima curva ogni sottotipo è il duale di quello della seconda
m_Info[j].IciA[kj].nPrevTy = GetDualIcct( m_Info[i].IciB[ki].nPrevTy) ;
m_Info[j].IciA[kj].nNextTy = GetDualIcct( m_Info[i].IciB[ki].nNextTy) ;
}
// se altrimenti overlap controverso
else if ( m_Info[j].bOverlap && ! m_Info[j].bCBOverEq) {
// per la prima curva ogni sottotipo è come quello della seconda ma in posizione scambiata
// per la prima curva ogni sottotipo è come quello della seconda ma in posizione scambiata
m_Info[j].IciA[kj].nPrevTy = m_Info[i].IciB[ki].nNextTy ;
m_Info[j].IciA[kj].nNextTy = m_Info[i].IciB[ki].nPrevTy ;
}
@@ -458,7 +489,7 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
EraseCurrentInfo( i, j) ;
}
}
// caso NULL-DET -> DET-NULL per seconda curva (possibile su inizio/fine di curva chiusa)
// caso (NULL)-DET -> DET-(NULL) per seconda curva (possibile su inizio/fine di curva chiusa)
else if ( m_Info[j].IciB[kj].nPrevTy == ICCT_NULL && m_Info[j].IciB[kj].nNextTy != ICCT_NULL &&
m_Info[i].IciB[ki].nPrevTy != ICCT_NULL && m_Info[i].IciB[ki].nNextTy == ICCT_NULL) {
// per la seconda curva tengo i determinati
@@ -466,25 +497,25 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
m_Info[j].IciB[kj].nPrevTy = m_Info[i].IciB[ki].nPrevTy ;
// se overlap equiverso
if ( m_Info[i].bOverlap && m_Info[i].bCBOverEq) {
// per la prima curva ogni sottotipo è il duale di quello della seconda
// per la prima curva ogni sottotipo è il duale di quello della seconda
m_Info[i].IciA[ki].nPrevTy = GetDualIcct( m_Info[i].IciB[ki].nPrevTy) ;
m_Info[i].IciA[ki].nNextTy = GetDualIcct( m_Info[i].IciB[ki].nNextTy) ;
}
// se altrimenti overlap controverso
else if ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq) {
// per la prima curva ogni sottotipo è come quello della seconda ma in posizione scambiata
// per la prima curva ogni sottotipo è come quello della seconda ma in posizione scambiata
m_Info[i].IciA[ki].nPrevTy = m_Info[i].IciB[ki].nNextTy ;
m_Info[i].IciA[ki].nNextTy = m_Info[i].IciB[ki].nPrevTy ;
}
// se overlap equiverso
if ( m_Info[j].bOverlap && m_Info[j].bCBOverEq) {
// per la prima curva ogni sottotipo è il duale di quello della seconda
// per la prima curva ogni sottotipo è il duale di quello della seconda
m_Info[j].IciA[kj].nPrevTy = GetDualIcct( m_Info[i].IciB[ki].nPrevTy) ;
m_Info[j].IciA[kj].nNextTy = GetDualIcct( m_Info[i].IciB[ki].nNextTy) ;
}
// se altrimenti overlap controverso
else if ( m_Info[j].bOverlap && ! m_Info[j].bCBOverEq) {
// per la prima curva ogni sottotipo è come quello della seconda ma in posizione scambiata
// per la prima curva ogni sottotipo è come quello della seconda ma in posizione scambiata
m_Info[j].IciA[kj].nPrevTy = m_Info[i].IciB[ki].nNextTy ;
m_Info[j].IciA[kj].nNextTy = m_Info[i].IciB[ki].nPrevTy ;
}
@@ -522,17 +553,21 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
}
// caso NULL-NULL per corrente di seconda curva
else if ( m_Info[i].IciB[ki].nPrevTy == ICCT_NULL && m_Info[i].IciB[ki].nNextTy == ICCT_NULL) {
m_Info[j].IciB[kj].nNextTy = m_Info[i].IciB[ki].nNextTy ;
if ( m_Info[i].IciA[ki].dU > m_Info[j].IciA[kj].dU + EPS_PARAM)
m_Info[j].IciB[kj].nNextTy = ICCT_NULL ;
if ( m_Info[j].IciA[kj].nNextTy == ICCT_NULL)
m_Info[j].IciA[kj].nNextTy = m_Info[i].IciA[ki].nNextTy ;
if ( m_Info[j].IciA[kj].nPrevTy == ICCT_NULL)
m_Info[j].IciA[kj].nPrevTy = m_Info[i].IciA[ki].nPrevTy ;
// cancello l'intersezione corrente (non aggiunge nulla rispetto alla precedente)
EraseCurrentInfo( i, j) ;
}
// caso NULL-NULL per precedente di seconda curva
else if ( m_Info[j].IciB[kj].nPrevTy == ICCT_NULL && m_Info[j].IciB[kj].nNextTy == ICCT_NULL) {
m_Info[i].IciB[0].nPrevTy = m_Info[j].IciB[0].nPrevTy ;
if ( m_Info[j].IciA[0].dU < m_Info[i].IciA[0].dU - EPS_PARAM)
m_Info[i].IciA[0].nPrevTy = m_Info[j].IciA[0].nPrevTy ;
m_Info[i].IciB[ki].nPrevTy = ICCT_NULL ;
if ( m_Info[i].IciA[ki].nPrevTy == ICCT_NULL)
m_Info[i].IciA[ki].nPrevTy = m_Info[j].IciA[kj].nPrevTy ;
if ( m_Info[i].IciA[ki].nNextTy == ICCT_NULL)
m_Info[i].IciA[ki].nNextTy = m_Info[j].IciA[kj].nNextTy ;
// cancello l'intersezione precedente (non aggiunge nulla rispetto alla corrente)
EraseOtherInfo( i, j) ;
}
@@ -541,16 +576,16 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
// ripristino ordinamento su prima curva
stable_sort( m_Info.begin(), m_Info.end(), SortGreaterA) ;
// verifico se sono rimaste delle intersezioni di tipo non definito sulla curva A e cerco di risolverle per continuità
// verifico se sono rimaste delle intersezioni di tipo non definito sulla curva A e cerco di risolverle per continuità
for ( int i = 0 ; i < m_nNumInters ; ++ i) {
// se il tipo di accostamento per la curva A non è definito
// se il tipo di accostamento per la curva A non è definito
if ( m_Info[i].IciA[0].nPrevTy == ICCT_NULL) {
if ( i > 0 || ( bCrvAClosed && ! bAutoInters)) {
int j = ( i > 0 ? i - 1 : m_nNumInters - 1) ;
m_Info[i].IciA[0].nPrevTy = ( m_Info[j].bOverlap ? m_Info[j].IciA[1].nNextTy : m_Info[j].IciA[0].nNextTy) ;
}
}
// se il tipo di allontanamento per la curva A non è definito
// se il tipo di allontanamento per la curva A non è definito
int ki = ( m_Info[i].bOverlap ? 1 : 0) ;
if ( m_Info[i].IciA[ki].nNextTy == ICCT_NULL) {
if ( i < m_nNumInters - 1 || ( bCrvAClosed && ! bAutoInters)) {
@@ -560,21 +595,22 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
}
}
// verifico se sono rimaste delle intersezioni di tipo non definito sulla curva B e cerco di risolverle per continuità
// verifico se sono rimaste delle intersezioni di tipo non definito sulla curva B e cerco di risolverle per continuità
stable_sort( m_Info.begin(), m_Info.end(), SortGreaterB) ;
for ( int i = 0 ; i < m_nNumInters ; ++ i) {
// se il tipo di accostamento per la curva B non è definito
// se il tipo di accostamento per la curva B non è definito
if ( m_Info[i].IciB[0].nPrevTy == ICCT_NULL) {
if ( i > 0 || ( bCrvBClosed && ! bAutoInters)) {
int j = ( i > 0 ? i - 1 : m_nNumInters - 1) ;
m_Info[i].IciB[0].nPrevTy = ( m_Info[j].bOverlap && ! m_Info[j].bCBOverEq ? m_Info[j].IciB[1].nNextTy : m_Info[j].IciB[0].nNextTy) ;
m_Info[i].IciB[0].nPrevTy = ( m_Info[j].bOverlap ? m_Info[j].IciB[1].nNextTy : m_Info[j].IciB[0].nNextTy) ;
}
}
// se il tipo di allontanamento per la curva B non è definito
if ( m_Info[i].IciB[0].nNextTy == ICCT_NULL) {
// se il tipo di allontanamento per la curva B non è definito
int ki = ( m_Info[i].bOverlap ? 1 : 0) ;
if ( m_Info[i].IciB[ki].nNextTy == ICCT_NULL) {
if ( i < m_nNumInters - 1 || ( bCrvBClosed && ! bAutoInters)) {
int j = ( i < m_nNumInters - 1 ? i + 1 : 0) ;
m_Info[i].IciB[0].nNextTy = ( m_Info[j].bOverlap && ! m_Info[j].bCBOverEq ? m_Info[j].IciB[1].nPrevTy : m_Info[j].IciB[0].nPrevTy) ;
m_Info[i].IciB[ki].nNextTy = m_Info[j].IciB[0].nPrevTy ;
}
}
}
@@ -585,7 +621,7 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
for ( int i = 0 ; i < m_nNumInters ; ++ i) {
// in assenza di overlap
if ( ! m_Info[i].bOverlap) {
// se il tipo di accostamento per la curva A non è definito
// se il tipo di accostamento per la curva A non è definito
if ( m_Info[i].IciA[0].nPrevTy == ICCT_NULL) {
// devo studiare un intorno dell'intersezione
int nType ;
@@ -594,7 +630,7 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
// aggiorno il tipo di accostamento della curva A alla curva B
m_Info[i].IciA[0].nPrevTy = nType ;
}
// se il tipo di accostamento per la curva B non è definito
// se il tipo di accostamento per la curva B non è definito
if ( m_Info[i].IciB[0].nPrevTy == ICCT_NULL) {
// devo studiare un intorno dell'intersezione
int nType ;
@@ -603,7 +639,7 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
// aggiorno il tipo di accostamento della curva B alla curva A
m_Info[i].IciB[0].nPrevTy = nType ;
}
// se il tipo di allontanamento per la curva A non è definito
// se il tipo di allontanamento per la curva A non è definito
if ( m_Info[i].IciA[0].nNextTy == ICCT_NULL) {
// devo studiare un intorno dell'intersezione
int nType ;
@@ -612,7 +648,7 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
// aggiorno il tipo di allontanamento della curva A dalla curva B
m_Info[i].IciA[0].nNextTy = nType ;
}
// se il tipo di allontanamento per la curva B non è definito
// se il tipo di allontanamento per la curva B non è definito
if ( m_Info[i].IciB[0].nNextTy == ICCT_NULL) {
// devo studiare un intorno dell'intersezione
int nType ;
@@ -624,66 +660,68 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
}
// in presenza di overlap
else {
// se il tipo di accostamento è non definito per la curva A
// se il tipo di accostamento è non definito per la curva A
if ( m_Info[i].IciA[0].nPrevTy == ICCT_NULL) {
// se autointersezione con spike
double dDeltaU = abs( m_Info[i].IciA[0].dU - m_Info[i].IciB[0].dU) ;
if ( bAutoInters && ( dDeltaU < EPS_PARAM || ( bCrvAClosed && abs( dDeltaU - dCrvASpan) < EPS_PARAM))) {
// è punta di spike
int nType = ICCT_SPK ;
// aggiorno il tipo di allontanamento della curva A dalla curva B
// devo studiare un intorno dell'intersezione
int nType ;
if ( CalcATypeFromDisk( CCompoA, m_Info[i].IciA[0].dU, ICurve::FROM_MINUS,
CCompoB, m_Info[i].IciB[0].dU, nType)) {
// aggiorno il tipo di accostamento della curva A alla curva B
m_Info[i].IciA[0].nPrevTy = nType ;
// aggiorno anche il corrispondente tipo sulla curva B
// aggiorno anche il corrispondente tipo sulla curva B
if ( m_Info[i].bCBOverEq)
m_Info[i].IciB[0].nPrevTy = GetDualIcct( nType) ;
else
m_Info[i].IciB[0].nNextTy = nType ;
}
// caso standard
else {
// devo studiare un intorno dell'intersezione
int nType ;
if ( CalcATypeFromDisk( CCompoA, m_Info[i].IciA[0].dU, ICurve::FROM_MINUS,
CCompoB, m_Info[i].IciB[0].dU, nType)) {
// aggiorno il tipo di accostamento della curva A alla curva B
m_Info[i].IciA[0].nPrevTy = nType ;
// aggiorno anche il corrispondente tipo sulla curva B
if ( m_Info[i].bCBOverEq)
m_Info[i].IciB[0].nPrevTy = GetDualIcct( nType) ;
else
m_Info[i].IciB[0].nNextTy = nType ;
}
}
}
// se il tipo di allontanamento è non definito per la curva A
// se il tipo di allontanamento è non definito per la curva A
if ( m_Info[i].IciA[1].nNextTy == ICCT_NULL) {
// se autointersezione con spike
double dDeltaU = abs( m_Info[i].IciA[1].dU - m_Info[i].IciB[1].dU) ;
if ( bAutoInters && ( dDeltaU < EPS_PARAM || ( bCrvAClosed && abs( dDeltaU - dCrvASpan) < EPS_PARAM))) {
// è punta di spike
int nType = ICCT_SPK ;
// aggiorno il tipo di allontanamento della curva A dalla curva B
// devo studiare un intorno dell'intersezione
int nType ;
if ( CalcATypeFromDisk( CCompoA, m_Info[i].IciA[1].dU, ICurve::FROM_PLUS,
CCompoB, m_Info[i].IciB[1].dU, nType)) {
// aggiorno il tipo di allontanamento della curva A dalla curva B
m_Info[i].IciA[1].nNextTy = nType ;
// aggiorno anche il corrispondente tipo sulla curva B
// aggiorno anche il corrispondente tipo sulla curva B
if ( m_Info[i].bCBOverEq)
m_Info[i].IciB[1].nNextTy = GetDualIcct( nType) ;
else
m_Info[i].IciB[1].nPrevTy = nType ;
}
// caso standard
else {
// devo studiare un intorno dell'intersezione
int nType ;
if ( CalcATypeFromDisk( CCompoA, m_Info[i].IciA[1].dU, ICurve::FROM_PLUS,
CCompoB, m_Info[i].IciB[1].dU, nType)) {
// aggiorno il tipo di allontanamento della curva A dalla curva B
m_Info[i].IciA[1].nNextTy = nType ;
// aggiorno anche il corrispondente tipo sulla curva B
if ( m_Info[i].bCBOverEq)
m_Info[i].IciB[1].nNextTy = GetDualIcct( nType) ;
else
m_Info[i].IciB[1].nPrevTy = nType ;
}
}
}
}
if ( bAutoInters) {
// controllo l'eventuale presenza di spike
for ( int i = 0 ; i < m_nNumInters ; ++ i) {
if ( m_Info[i].bOverlap && ! m_Info[i].bCBOverEq) {
// se secondo tratto dello spike
double dDeltaU = abs( m_Info[i].IciA[0].dU - m_Info[i].IciB[0].dU) ;
if ( dDeltaU < EPS_PARAM || ( bCrvAClosed && abs( dDeltaU - dCrvASpan) < EPS_PARAM)) {
// è punta di spike
int nType = ICCT_SPK ;
// aggiorno il tipo di allontanamento della curva A dalla curva B
m_Info[i].IciA[0].nPrevTy = nType ;
// aggiorno anche il corrispondente tipo sulla curva B
if ( m_Info[i].bCBOverEq)
m_Info[i].IciB[0].nPrevTy = GetDualIcct( nType) ;
else
m_Info[i].IciB[0].nNextTy = nType ;
}
// se primo tratto dello spike
dDeltaU = abs( m_Info[i].IciA[1].dU - m_Info[i].IciB[1].dU) ;
if ( dDeltaU < EPS_PARAM || ( bCrvAClosed && abs( dDeltaU - dCrvASpan) < EPS_PARAM)) {
// è punta di spike
int nType = ICCT_SPK ;
// aggiorno il tipo di allontanamento della curva A dalla curva B
m_Info[i].IciA[1].nNextTy = nType ;
// aggiorno anche il corrispondente tipo sulla curva B
if ( m_Info[i].bCBOverEq)
m_Info[i].IciB[1].nNextTy = GetDualIcct( nType) ;
else
m_Info[i].IciB[1].nPrevTy = nType ;
}
}
}
@@ -697,10 +735,10 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
// se prima curva aperta, salto alla prossima
if ( ! CCompoA.IsClosed())
continue ;
// è chiusa quindi prendo l'ultima
// è chiusa quindi prendo l'ultima
j = m_nNumInters - 1 ;
}
// se i due indici coincidono, c'è una sola intersezione e posso uscire
// se i due indici coincidono, c'è una sola intersezione e posso uscire
if ( i == j)
break ;
// assegno sottoindici (considero solo intersezioni overlap)
@@ -728,7 +766,7 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
}
}
// se è rimasta una sola intersezione con overlap anche ad entrambi gli estremi e le curve sono chiuse
// se è rimasta una sola intersezione con overlap anche ad entrambi gli estremi e le curve sono chiuse
if ( m_nNumInters == 1 && CCompoA.IsClosed() && CCompoB.IsClosed() &&
m_Info[0].IciA[0].nPrevTy == ICCT_ON && m_Info[0].IciA[1].nNextTy == ICCT_ON &&
GetCrvBDirANext( m_Info[0]) == ICCT_ON && GetCrvBDirAPrev( m_Info[0]) == ICCT_ON) {
@@ -742,10 +780,103 @@ IntersCrvCompoCrvCompo::IntersCrvCompoCrvCompo( const ICurveComposite& CCompoA,
m_Info[0].IciB[1].dU = ( m_Info[0].bCBOverEq ? dEnd : dStart) ;
}
// verifico se una curva ha tutte le info e queste info sono coerenti
if ( m_nNumInters > 1) {
bool bCoherent = true ;
INTVECTOR vIncoherenceWithPrev ;
// salvo eventuali incoerenze col precedente
for ( int i = bCrvAClosed ? 0 : 1 ; i < m_nNumInters ; ++i) {
int j = i == 0 ? m_nNumInters - 1 : i - 1 ;
int kj = m_Info[j].bOverlap ? 1 : 0 ;
if ( m_Info[j].IciA[kj].nNextTy != m_Info[i].IciA[0].nPrevTy &&
m_Info[j].IciA[kj].nNextTy != ICCT_SPK && m_Info[i].IciA[0].nPrevTy != ICCT_SPK) {
vIncoherenceWithPrev.push_back( i) ;
bCoherent = false ;
}
}
// incoerenze sulla curva A
if ( ! bCoherent) {
for ( int i : vIncoherenceWithPrev) {
int j = i == 0 ? m_nNumInters - 1 : i - 1 ;
int kj = m_Info[j].bOverlap ? 1 : 0 ;
int nType = 0 ;
CalcSide( m_Info[j], m_Info[i], &CCompoA, &CCompoB, true, nType) ;
if ( nType == MDS_LEFT)
nType = ICCT_IN ;
else if ( nType == MDS_RIGHT)
nType = ICCT_OUT ;
m_Info[i].IciA[0].nPrevTy = nType ;
m_Info[j].IciA[kj].nNextTy = nType ;
}
}
stable_sort( m_Info.begin(), m_Info.end(), SortGreaterB) ;
bCoherent = true ;
vIncoherenceWithPrev.clear() ;
// salvo eventuali incoerenze col precedente
for ( int i = bCrvBClosed ? 0 : 1 ; i < m_nNumInters ; ++i) {
int j = i == 0 ? m_nNumInters - 1 : i - 1 ;
int kj = m_Info[j].bOverlap ? 1 : 0 ;
if ( m_Info[j].IciB[kj].nNextTy != m_Info[i].IciB[0].nPrevTy &&
m_Info[j].IciB[kj].nNextTy != ICCT_SPK && m_Info[i].IciB[0].nPrevTy != ICCT_SPK) {
vIncoherenceWithPrev.push_back( i) ;
bCoherent = false ;
}
}
// incoerenze sulla curva B
if ( ! bCoherent) {
for ( int i : vIncoherenceWithPrev) {
int j = i == 0 ? m_nNumInters - 1 : i - 1 ;
int kj = m_Info[j].bOverlap ? 1 : 0 ;
int nType = 0 ;
CalcSide( m_Info[j], m_Info[i], &CCompoB, &CCompoA, false, nType) ;
if ( nType == MDS_LEFT)
nType = ICCT_IN ;
else if ( nType == MDS_RIGHT)
nType = ICCT_OUT ;
m_Info[i].IciB[0].nPrevTy = nType ;
m_Info[j].IciB[kj].nNextTy = nType ;
}
}
}
else {
// posso completare A guardando B e viceversa
}
stable_sort( m_Info.begin(), m_Info.end(), SortGreaterA) ;
// verifiche su intersezioni in zone non-manifold
OrderNonManifoldInters( m_Info, CCompoA, CCompoB) ;
}
//----------------------------------------------------------------------------
static bool
CalcSide( const IntCrvCrvInfo& Icci1, const IntCrvCrvInfo& Icci2,const ICurve* pThisCrv, const ICurve* pOtherCrv, bool bCrvAOrB, int& nType)
{
// calcolo tra l'intersezione 1 e 2 se la curva sta dentro o fuori
int kj = Icci1.bOverlap ? 1 : 0 ;
double dU = 0 ;
if ( bCrvAOrB) {
// se precedente minore del successivo faccio la media
if ( Icci1.IciA[kj].dU < Icci2.IciA[0].dU)
dU = (Icci2.IciA[0].dU + Icci1.IciA[kj].dU) / 2 ;
// altrimenti guardo tra lo start e il successivo
else
dU = (Icci2.IciA[0].dU + 0.) / 2 ;
}
else {
// se precedente minore del successivo faccio la media
if ( Icci1.IciB[kj].dU < Icci2.IciB[0].dU)
dU = (Icci2.IciB[0].dU + Icci1.IciB[kj].dU) / 2 ;
// altrimenti guardi tra lo start e il successivo
else
dU = (Icci2.IciB[0].dU + 0.) / 2 ;
}
Point3d ptTest ; pThisCrv->GetPointD1D2( dU, ICurve::FROM_MINUS, ptTest) ;
DistPointCurve dpc( ptTest, *pOtherCrv) ;
dpc.GetSideAtMinDistPoint( 0, Z_AX, nType) ;
return true ;
}
//----------------------------------------------------------------------------
bool
IntersCrvCompoCrvCompo::IntersSimpleCurves( const ICurve& CurveA, int nA, const ICurve& CurveB, int nB,
@@ -883,7 +1014,7 @@ SortGreaterB( const IntCrvCrvInfo& aInfo1, const IntCrvCrvInfo& aInfo2)
bool
OrderNonManifoldInters( ICCIVECTOR& Info, const ICurve& CurveA, const ICurve& CurveB)
{
// questi controlli sono validi solo se la curva B è chiusa
// questi controlli sono validi solo se la curva B è chiusa
if ( ! CurveB.IsClosed())
return false ;
@@ -912,7 +1043,7 @@ OrderNonManifoldInters( ICCIVECTOR& Info, const ICurve& CurveA, const ICurve& Cu
// se prima curva aperta, salto alla prossima
if ( ! CurveA.IsClosed())
continue ;
// è chiusa quindi prendo l'ultima
// è chiusa quindi prendo l'ultima
j = nNumInters - 1 ;
}
// se i due indici coincidono, salto
@@ -1002,7 +1133,7 @@ MediaParamPoints( IntCrvInfo& Ici1, IntCrvInfo& Ici2, const ICurveComposite& crv
//Point3d ptMed ;
//if ( ! crvCompo.GetPointD1D2( dUmed, ICurve::FROM_MINUS, ptMed))
// return ;
// verifico che non sia più lontano dei punti originali dal loro medio
// verifico che non sia più lontano dei punti originali dal loro medio
//if ( SqDist( Ici1.ptI, ptMed) > dSqDist / 4)
// return ;
// medio i parametri
@@ -1016,13 +1147,13 @@ MediaParamPoints( IntCrvInfo& Ici1, IntCrvInfo& Ici2, const ICurveComposite& crv
static int
GetCrvBDirAPrev( IntCrvCrvInfo& Icci)
{
// non è overlap, è il prev del primo punto
// non è overlap, è il prev del primo punto
if ( ! Icci.bOverlap)
return Icci.IciB[0].nPrevTy ;
// è overlap equiverso, è il prev del primo punto
// è overlap equiverso, è il prev del primo punto
if ( Icci.bCBOverEq)
return Icci.IciB[0].nPrevTy ;
// è overlap controverso, è il next del primo punto
// è overlap controverso, è il next del primo punto
return Icci.IciB[0].nNextTy ;
}
@@ -1032,13 +1163,13 @@ GetCrvBDirAPrev( IntCrvCrvInfo& Icci)
static int
GetCrvBDirANext( IntCrvCrvInfo& Icci)
{
// non è overlap, è il next del primo punto
// non è overlap, è il next del primo punto
if ( ! Icci.bOverlap)
return Icci.IciB[0].nNextTy ;
// è overlap equiverso, è il next del secondo punto
// è overlap equiverso, è il next del secondo punto
if ( Icci.bCBOverEq)
return Icci.IciB[1].nNextTy ;
// è overlap controverso, è il prev del secondo punto
// è overlap controverso, è il prev del secondo punto
return Icci.IciB[1].nPrevTy ;
}
@@ -1082,7 +1213,7 @@ CalcATypeFromDisk( const ICurve& CurveA, double dUA, ICurve::Side nSideA,
return false ;
if ( dAngBpDeg < 0)
dAngBpDeg += ANG_FULL ;
// se l'angolo di DirA è compreso tra DirBn e DirBp (muovendosi in senso CCW) allora è IN, altrimenti OUT
// se l'angolo di DirA è compreso tra DirBn e DirBp (muovendosi in senso CCW) allora è IN, altrimenti OUT
if ( dAngADeg > 0 && dAngADeg < dAngBpDeg)
nType = ICCT_IN ;
else
@@ -1155,12 +1286,12 @@ CalcATypeFromDisk2( const ICurve& CurveA, double dUA, ICurve::Side nSideA,
// li ordino in senso crescente
if ( dAngB1pDeg > dAngB2pDeg)
swap( dAngB1pDeg, dAngB2pDeg) ;
// se non ci sono variazioni angolari significative, non posso decidere alcunché
// se non ci sono variazioni angolari significative, non posso decidere alcunché
const double MIN_DEV_ANG = 2 ;
if ( abs( DiffAngle( dAngB1pDeg + ANG_STRAIGHT, 0)) < MIN_DEV_ANG &&
abs( DiffAngle( dAngB2pDeg + ANG_STRAIGHT, dAngB2nDeg)) < MIN_DEV_ANG)
return false ;
// IN è tra 0 e dAngB1pDeg e tra dAngB2nDeg e dAngB2pDeg
// IN è tra 0 e dAngB1pDeg e tra dAngB2nDeg e dAngB2pDeg
if ( ( dAngADeg > 0 && dAngADeg < dAngB1pDeg) ||
( dAngADeg > dAngB2nDeg && dAngADeg < dAngB2pDeg))
nType = ICCT_IN ;
+5 -5
View File
@@ -296,8 +296,8 @@ int
IntersCurveCurve::GetInters3DCount( void)
{
int nCount = 0 ;
for( int i = 0 ; i < m_nIntersCount ; ++i) {
if( ! m_Info[i].bOverlap || ( m_Info[i].bOverlap && m_Info[i].bCBOverEq)) {
for ( int i = 0 ; i < m_nIntersCount ; ++i) {
if ( ! m_Info[i].bOverlap || ( m_Info[i].bOverlap && m_Info[i].bCBOverEq)) {
if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[0].ptI.z) < EPS_SMALL)
++nCount ;
}
@@ -365,8 +365,8 @@ IntersCurveCurve::GetInt3DCrvCrvInfo( int nInd, IntCrvCrvInfo& aInfo)
if ( nInd < 0 || nInd >= GetInters3DCount())
return false ;
int nCount = - 1 ;
for( int i = 0 ; i < m_nIntersCount ; ++i) {
if( ! m_Info[i].bOverlap || ( m_Info[i].bOverlap && m_Info[i].bCBOverEq)) {
for ( int i = 0 ; i < m_nIntersCount ; ++i) {
if ( ! m_Info[i].bOverlap || ( m_Info[i].bOverlap && m_Info[i].bCBOverEq)) {
if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[0].ptI.z) < EPS_SMALL)
++nCount ;
}
@@ -374,7 +374,7 @@ IntersCurveCurve::GetInt3DCrvCrvInfo( int nInd, IntCrvCrvInfo& aInfo)
if ( abs( m_Info[i].IciA[0].ptI.z - m_Info[i].IciB[1].ptI.z) < EPS_SMALL)
++nCount ;
}
if( nCount == nInd) {
if ( nCount == nInd) {
aInfo = m_Info[nInd] ;
return true ;
}
-2
View File
@@ -139,8 +139,6 @@ IntersCurvePlane::CalcIntersLinePlane( const Plane3d& plPlane, const ICurve& Cur
void
IntersCurvePlane::OrderAndCompleteIntersections()
{
if ( m_Info.size() < 2)
return ;
// cancello le interesezioni puntuali adiacenti a tratti di sovrapposizione
// riempio le info PrevTy e NexyTy
sort( m_Info.begin(), m_Info.end(), []( IntCrvPlnInfo& icpA, IntCrvPlnInfo& icpB) { return icpA.Ici[0].dU < icpA.Ici[0].dU ;}) ;
+99 -52
View File
@@ -19,6 +19,7 @@
#include "/EgtDev/Include/EGkDistPointLine.h"
#include "/EgtDev/Include/EGkDistPointCurve.h"
#include "/EgtDev/Include/EGkDistPointSurfTm.h"
#include "/EgtDev/Include/EGkDistPointSurfBz.h"
#include "/EgtDev/Include/EGkIntersPlanePlane.h"
#include "/EgtDev/Include/EGkIntersLinePlane.h"
#include "/EgtDev/Include/EGkIntersLineSurfTm.h"
@@ -92,6 +93,8 @@ AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
Pt5ax.ptP = ptInt - vtLine1 / dLen1 * 2 * EPS_SMALL ;
Pt5ax.vtDir1 = vPt5ax[j].vtDir1 ;
Pt5ax.vtDir2 = vPt5ax[j].vtDir2 ;
Pt5ax.vtDirU = vPt5ax[j].vtDirU ;
Pt5ax.vtDirV = vPt5ax[j].vtDirV ;
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
Pt5ax.nFlag = P5AX_CVEX ;
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
@@ -104,6 +107,8 @@ AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
Pt5ax.ptP = ptInt + vtLine2 / dLen2 * 2 * EPS_SMALL ;
Pt5ax.vtDir1 = vPt5ax[i].vtDir1 ;
Pt5ax.vtDir2 = vPt5ax[i].vtDir2 ;
Pt5ax.vtDirU = vPt5ax[i].vtDirU ;
Pt5ax.vtDirV = vPt5ax[i].vtDirV ;
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
Pt5ax.nFlag = P5AX_CVEX ;
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
@@ -118,6 +123,8 @@ AddPointsOnCorners( PNT5AXVECTOR& vPt5ax)
Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = Media( vPt5ax[i].vtDir1, vPt5ax[j].vtDir1) ; Pt5ax.vtDir1.Normalize() ;
Pt5ax.vtDir2 = Media( vPt5ax[i].vtDir2, vPt5ax[j].vtDir2) ; Pt5ax.vtDir2.Normalize() ;
Pt5ax.vtDirU = Media( vPt5ax[i].vtDirU, vPt5ax[j].vtDirU) ; Pt5ax.vtDirU.Normalize() ;
Pt5ax.vtDirV = Media( vPt5ax[i].vtDirV, vPt5ax[j].vtDirV) ; Pt5ax.vtDirV.Normalize() ;
Pt5ax.dPar = ( vPt5ax[i].dPar + vPt5ax[j].dPar) / 2 ;
Pt5ax.nFlag = P5AX_CONC ;
vPt5ax.insert( vPt5ax.begin() + i, Pt5ax) ;
@@ -233,23 +240,55 @@ RemovePointsInExcess( PNT5AXVECTOR& vPt5ax, double dLinTol, double dMaxSegmLen,
}
//----------------------------------------------------------------------------
static bool
ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, double dPar, Point5ax& Pt5ax)
static const SurfTriMesh*
MyGetAuxSurf( const ISurf* pSrf)
{
// punto sulle supefici a minima distanza
if ( pSrf == nullptr)
return nullptr ;
switch ( pSrf->GetType()) {
case SRF_TRIMESH :
return GetBasicSurfTriMesh( pSrf) ;
case SRF_FLATRGN :
return GetBasicSurfFlatRegion( pSrf)->GetAuxSurf() ;
case SRF_BEZIER :
return GetBasicSurfBezier( pSrf)->GetAuxSurf() ;
default :
return nullptr ;
}
}
//----------------------------------------------------------------------------
static bool
ProjectPointOnSurf( const Point3d& ptP, const CISURFPVECTOR& vpSurf, double dPar, Point5ax& Pt5ax)
{
// punto sulle superfici a minima distanza
int nSurfMin = -1 ;
int nTriaMin ;
int nTriaMin = -1 ;
double dUMin = -1, dVMin = -1 ;
Point3d ptMin ;
double dMinDist ;
for ( int i = 0 ; i < ssize( vpStm) ; ++ i) {
double dMinDist = NAN ;
for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) {
// punto sulla superficie a minima distanza
DistPointSurfTm dPS( ptP, *vpStm[i]) ;
double dDist ;
if ( dPS.GetDist( dDist) && ( nSurfMin == -1 || dDist < dMinDist)) {
nSurfMin = i ;
dPS.GetMinDistPoint( ptMin) ;
dPS.GetMinDistTriaIndex ( nTriaMin) ;
dMinDist = dDist ;
int nSrfType = ( vpSurf[i] != nullptr ? vpSurf[i]->GetType() : GEO_NONE) ;
if ( nSrfType == SRF_TRIMESH || nSrfType == SRF_FLATRGN) {
DistPointSurfTm dPS( ptP, *MyGetAuxSurf( vpSurf[i])) ;
double dDist ;
if ( dPS.GetDist( dDist) && ( nSurfMin == -1 || dDist < dMinDist)) {
nSurfMin = i ;
dPS.GetMinDistPoint( ptMin) ;
dPS.GetMinDistTriaIndex ( nTriaMin) ;
dMinDist = dDist ;
}
}
else if ( nSrfType == SRF_BEZIER) {
DistPointSurfBz dPS( ptP, *GetBasicSurfBezier( vpSurf[i])) ;
double dDist ;
if ( dPS.GetDist( dDist) && ( nSurfMin == -1 || dDist < dMinDist)) {
nSurfMin = i ;
dPS.GetMinDistPoint( ptMin) ;
dPS.GetParamsAtMinDistPoint( dUMin, dVMin) ;
dMinDist = dDist ;
}
}
}
@@ -257,19 +296,44 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, double dPar
if ( nSurfMin >= 0) {
// assegno il punto
Point3d ptInt = ptMin ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
Triangle3dEx trTria ;
if ( ! vpStm[nSurfMin]->GetTriangle( nTriaMin, trTria))
return false ;
Vector3d vtN ;
if ( ! CalcNormal( ptMin, trTria, vtN))
vtN = trTria.GetN() ;
// assegno valori al punto 5assi
Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = vtN ;
Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ;
// calcolo gli altri dati
int nSrfType = ( vpSurf[nSurfMin] != nullptr ? vpSurf[nSurfMin]->GetType() : GEO_NONE) ;
if ( nSrfType == SRF_TRIMESH || nSrfType == SRF_FLATRGN) {
// recupero superficie trimesh
const SurfTriMesh* pSurfTm = MyGetAuxSurf( vpSurf[nSurfMin]) ;
// calcolo la normale (si calcola smooth, in caso di errore si prende quella del triangolo)
Triangle3dEx trTria ;
if ( ! pSurfTm->GetTriangle( nTriaMin, trTria))
return false ;
Vector3d vtN ;
if ( ! CalcNormal( ptMin, trTria, vtN))
vtN = trTria.GetN() ;
// assegno valori al punto 5assi
Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = vtN ;
Pt5ax.vtDirU = V_NULL ;
Pt5ax.vtDirV = V_NULL ;
Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ;
}
else if ( nSrfType == SRF_BEZIER) {
Point3d ptSB ;
Vector3d vtN, vtDerU, vtDerV ;
if ( ! GetBasicSurfBezier( vpSurf[nSurfMin])->GetPointNrmD1D2( dUMin, dVMin, ISurfBezier::FROM_MINUS, ISurfBezier::FROM_MINUS,
ptSB, vtN, &vtDerU, &vtDerV))
return false ;
vtDerU.Normalize() ;
vtDerV.Normalize() ;
// assegno valori al punto 5assi
Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = vtN ;
Pt5ax.vtDirU = vtDerU ;
Pt5ax.vtDirV = vtDerV ;
Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ;
}
// ritorno con successo
return true ;
}
@@ -282,31 +346,6 @@ bool
ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf,
double dLinTol, double dMaxSegmLen, bool bSharpEdges, PNT5AXVECTOR& vPt5ax)
{
// sistemazioni per tipo di superficie
CISRFTMPVECTOR vpSurfTm ;
for ( int i = 0 ; i < ssize( vpSurf) ; ++ i) {
const SurfTriMesh* pSurfTm = nullptr ;
switch ( vpSurf[i]->GetType()) {
case SRF_TRIMESH :
pSurfTm = GetBasicSurfTriMesh( vpSurf[i]) ;
break ;
case SRF_BEZIER :
{ double dOldLinTol = GetSurfBezierAuxSurfRefinedTol() ;
SetSurfBezierAuxSurfRefinedTol( GetSurfBezierTol( dLinTol)) ;
pSurfTm = GetBasicSurfBezier( vpSurf[i])->GetAuxSurfRefined() ;
SetSurfBezierAuxSurfRefinedTol( dOldLinTol) ;
} break ;
case SRF_FLATRGN :
pSurfTm = GetBasicSurfFlatRegion( vpSurf[i])->GetAuxSurf() ;
break ;
default :
break ;
}
if ( pSurfTm == nullptr)
return false ;
vpSurfTm.emplace_back( pSurfTm) ;
}
// controllo le tolleranze
dLinTol = max( dLinTol, LIN_TOL_MIN) ;
dMaxSegmLen = max( dMaxSegmLen, 10 * EPS_SMALL) ;
@@ -331,7 +370,7 @@ ProjectCurveOnSurf( const ICurve& crCrv, const CISURFPVECTOR& vpSurf,
while ( bFound) {
// se trovo proiezione, la salvo
Point5ax Pt5ax ;
if ( ProjectPointOnSurf( ptP, vpSurfTm, dPar, Pt5ax))
if ( ProjectPointOnSurf( ptP, vpSurf, dPar, Pt5ax))
vPt5ax.emplace_back( Pt5ax) ;
// passo al successivo
bFound = PL.GetNextUPoint( &dPar, &ptP) ;
@@ -403,6 +442,8 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const Frame
Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = frRefLine.VersZ() ;
Pt5ax.vtDirU = V_NULL ;
Pt5ax.vtDirV = V_NULL ;
Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ;
// ritorno con successo
@@ -557,6 +598,8 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const IGeoP
Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = vtLine ;
Pt5ax.vtDirU = V_NULL ;
Pt5ax.vtDirV = V_NULL ;
Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ;
// ritorno con successo
@@ -696,6 +739,8 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const ICurv
Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = vtLine ;
Pt5ax.vtDirU = V_NULL ;
Pt5ax.vtDirV = V_NULL ;
Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ;
// ritorno con successo
@@ -852,6 +897,8 @@ ProjectPointOnSurf( const Point3d& ptP, const CISRFTMPVECTOR& vpStm, const SurfT
Pt5ax.ptP = ptInt ;
Pt5ax.vtDir1 = vtN ;
Pt5ax.vtDir2 = vtN2 ;
Pt5ax.vtDirU = V_NULL ;
Pt5ax.vtDirV = V_NULL ;
Pt5ax.dPar = dPar ;
Pt5ax.nFlag = P5AX_STD ;
// ritorno con successo
+14 -7
View File
@@ -76,11 +76,18 @@ FromString( const string& sVal, Frame3d& frFrame)
bool
FromString( const string& sVal, Color& cCol)
{
// devono essere 4 parametri : Red, Green, Blue, Alpha
int vnVal[4] ;
if ( ! FromString( sVal, vnVal))
return false ;
// assegno il colore
cCol.Set( vnVal[0], vnVal[1], vnVal[2], vnVal[3]) ;
return true ;
// dovrebbero essere 4 parametri : Red, Green, Blue, Alpha
int vnRGBA[4] ;
if ( FromString( sVal, vnRGBA)) {
cCol.Set( vnRGBA[0], vnRGBA[1], vnRGBA[2], vnRGBA[3]) ;
return true ;
}
// riprovo con 3 parametri : Red, Green, Blue
int vnRGB[3] ;
if ( FromString( sVal, vnRGB)) {
cCol.Set( vnRGB[0], vnRGB[1], vnRGB[2]) ;
return true ;
}
// altrimenti errore
return false ;
}
+210 -56
View File
@@ -24,6 +24,13 @@
#include "/EgtDev/Include/EGkSurfAux.h"
#include "/EgtDev/Include/EGkSfrCreate.h"
#include "/EgtDev/Include/EgtPointerOwner.h"
#include "/EgtDev/Include/EGkChainCurves.h"
#define SAVEMKUNIF_CRVS 0
#if SAVEMKUNIF_CRVS
#include "/EgtDev/Include/EGkGeoObjSave.h"
#endif
using namespace std ;
@@ -530,6 +537,25 @@ NurbsToBezierSurface(const SNurbsSurfData& snData)
return Release( pSrfBz) ;
}
//----------------------------------------------------------------------------
ICurveComposite*
GetRectangleCurve( const Point3d& ptStart, double dWidth, double dHeight)
{
PolyLine PL ;
PL.AddUPoint( 0, ptStart) ;
PL.AddUPoint( 1, Point3d( ptStart.x + dWidth, ptStart.y)) ;
PL.AddUPoint( 2, Point3d( ptStart.x + dWidth, ptStart.y + dHeight, 0)) ;
PL.AddUPoint( 3, Point3d( ptStart.x , ptStart.y + dHeight, 0)) ;
PL.AddUPoint( 4, ptStart) ;
// creo la curva e la inserisco nel GDB
PtrOwner<ICurveComposite> pCrvCompo( CreateCurveComposite()) ;
bool bOk = true ;
bOk = bOk && ! IsNull( pCrvCompo) ;
// inserisco i segmenti che uniscono i punti
bOk = bOk && pCrvCompo->FromPolyLine( PL) ;
return Release( pCrvCompo) ;
}
//----------------------------------------------------------------------------
bool
MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, const DBLVECTOR& vV0,
@@ -539,36 +565,33 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
bool bRescaledU = false ;
bool bRescaledV = false ;
int nSpanU = 1, nSpanV = 1 ;
PtrOwner<ISurfFlatRegion> pRescaledSfr( CreateSurfFlatRegion()) ;
ICRVCOMPOPOVECTOR vUniformedCurves ;
BOOLVECTOR vbUniform(2) ;
fill( vbUniform.begin(), vbUniform.end(), true) ;
DBLMATRIX mKnots(2) ;
for ( int nDir = 0 ; nDir <= 1 ; ++ nDir) {
// vettore dei nodi
DBLVECTOR vU ;
DBLVECTOR& vU = mKnots[nDir] ;
int nExtraKnots = 0 ;
// controllo in U
if ( nDir == 0) {
if ( nDegU > 1) {
nExtraKnots = nDegU - 1 ;
}
for ( int i = nExtraKnots ; i < int( vU0.size()) - nExtraKnots ; ++i ) {
for ( int i = nExtraKnots ; i < ssize( vU0) - nExtraKnots ; ++i ) {
double dKnot = vU0[i] * SBZ_TREG_COEFF ;
// lo aggiungo solo se è diverso dal precedente
if ( i == nExtraKnots || dKnot > vU.back() + EPS_SMALL || dKnot < vU.back() - EPS_SMALL)
if ( i == nExtraKnots || dKnot > vU.back() + EPS_SMALL)
vU.push_back( dKnot) ;
}
nSpanU = (int)vU.size() - 1 ;
nSpanU = ssize( vU) - 1 ;
}
// controllo in V
else if ( nDir == 1 ) {
if ( nDegV > 1) {
nExtraKnots = nDegV - 1 ;
}
for ( int i = nExtraKnots ; i < int( vV0.size()) - nExtraKnots ; ++i ) {
for ( int i = nExtraKnots ; i < ssize( vV0) - nExtraKnots ; ++i ) {
double dKnot = vV0[i] * SBZ_TREG_COEFF ;
// lo aggiungo solo se è diverso dal precedente
if ( i == nExtraKnots || dKnot > vU.back() + EPS_SMALL || dKnot < vU.back() - EPS_SMALL)
if ( i == nExtraKnots || dKnot > vU.back() + EPS_SMALL)
vU.push_back( dKnot) ;
}
nSpanV = (int)vU.size() - 1 ;
nSpanV = ssize( vU) - 1 ;
}
// controllo se il vettore dei nodi è uniforme
@@ -581,45 +604,97 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
if ( b < (int)vU.size())
d1 = abs( vU[b] - vU[a]) ;
}
if ( b != (int)vU.size()) {
if ( b != (int)vU.size())
vbUniform[nDir] = false ;
}
// vettore delle curve di loop della regione di trim
ICRVCOMPOPOVECTOR vLoop ;
if ( ! vbUniform[0] || ! vbUniform[1]) {
for ( int c = 0 ; c < pSfr->GetChunkCount() ; ++c) {
for ( int l = 0 ; l < pSfr->GetLoopCount( c); ++l)
vLoop.emplace_back( ConvertCurveToComposite( pSfr->GetLoop( c, l))) ;
}
}
#if SAVEMKUNIF_CRVS
//debug
vector<IGeoObj*> vGeo ;
for( int i = 0 ; i < ssize( vLoop); ++i){
vGeo.push_back(vLoop[i]->Clone()) ;
}
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\failed_trim_crv_loops.nge") ;
//debug
#endif
for ( int nDir = 0 ; nDir <= 1 ; ++ nDir) {
DBLVECTOR& vU = mKnots[nDir] ;
if ( ! vbUniform[nDir]) {
nDir == 0 ? bRescaledU = true : bRescaledV = true ;
pRescaledSfr.Set( CreateSurfFlatRegion()) ;
if ( IsNull( pRescaledSfr))
return false ;
// creo il vettore delle curve all'interno di una striscia
ICRVCOMPOPOVECTOR vCrvStrip ;
for ( int p = 0 ; p < (int)vU.size() - 1 ; ++p) {
PtrOwner<ISurfFlatRegion> pSfr_copy( pSfr->Clone()) ;
if ( IsNull( pSfr_copy))
return false ;
double dLenStrip = abs( vU[p+1] - vU[p]) ;
if ( dLenStrip < EPS_SMALL)
continue ;
// creo la maschera per tagliare la superficie originale e ottenere una striscia
PtrOwner<ISurfFlatRegion> pSfrTrim( CreateSurfFlatRegion()) ;
PtrOwner<ICurveComposite> pTrimMask ;
// ricavo la maschera del trim, con cui poi farò l'intersezione con la sfr iniziale
Vector3d vtTrim ;
if ( nDir == 0) {
pSfrTrim.Set( GetSurfFlatRegionRectangle( dLenStrip, dScaleV + 2)) ;
vtTrim.Set( abs(vU[p] - vU.front()), - 1, 0) ;
Point3d ptStart( abs(vU[p] - vU.front()), - 1, 0) ;
pTrimMask.Set( GetRectangleCurve( ptStart, dLenStrip, dScaleV + 2)) ;
}
else{
pSfrTrim.Set( GetSurfFlatRegionRectangle( dScaleU + 2, dLenStrip)) ;
vtTrim.Set( - 1, abs(vU[p] - vU.front()), 0) ;
Point3d ptStart( - 1, abs(vU[p] - vU.front()), 0) ;
pTrimMask.Set( GetRectangleCurve( ptStart, dScaleU + 2, dLenStrip)) ;
}
pSfrTrim->Translate( vtTrim) ;
if ( ! pSfr_copy->Intersect( *pSfrTrim))
return false ;
// qui potrei decidere di eliminare tutti i tratti dei loop paralleli alla direzione del parametro che sto analizzando ( e di valore coincidente a quello di un nodo)
// aggiungo la nuova striscia solo se è valida
if ( pSfr_copy->IsValid() ) {
for ( int l = 0 ; l < ssize( vLoop); ++l) {
#if SAVEMKUNIF_CRVS
//debug
vector<IGeoObj*> vGeo ;
vGeo.push_back(pTrimMask->Clone()) ;
vGeo.push_back(vLoop[l]->Clone()) ;
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\failed_trim_crv_inters.nge") ;
//debug
#endif
IntersCurveCurve icc( *pTrimMask, *vLoop[l]) ;
CRVCVECTOR vCurveClass ;
icc.GetCurveClassification( 1, 10 * EPS_SMALL, vCurveClass) ;
for( int i = 0 ; i < ssize( vCurveClass); ++i) {
if( vCurveClass[i].nClass == CRVC_IN || vCurveClass[i].nClass == CRVC_ON_P)
vCrvStrip.emplace_back( ConvertCurveToComposite( vLoop[l]->CopyParamRange( vCurveClass[i].dParS, vCurveClass[i].dParE))) ;
}
}
#if SAVEMKUNIF_CRVS
//debug
vector<IGeoObj*> vGeo ;
for( int i = 0 ; i < ssize( vCrvStrip); ++i){
vGeo.push_back(vCrvStrip[i]->Clone()) ;
}
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\failed_trim_crv_strip.nge") ;
//debug
#endif
// riscalo le curve nella striscia
if ( ! vCrvStrip.empty()) {
double dCoeffX = 1, dCoeffY = 1 ;
if ( nDir == 0)
pSfr_copy->Scale( GLOB_FRM, SBZ_TREG_COEFF / dLenStrip, 1, 1) ;
else
pSfr_copy->Scale( GLOB_FRM, 1, SBZ_TREG_COEFF / dLenStrip, 1) ;
// prima di riunire la striscia al resto devo traslarla sul bordo destro della superificie che sto ricostruendo
dCoeffX = SBZ_TREG_COEFF / dLenStrip ;
else
dCoeffY = SBZ_TREG_COEFF / dLenStrip ;
for( int i = 0 ; i < ssize( vCrvStrip); ++i) {
if( ! IsNull( vCrvStrip[i]))
vCrvStrip[i]->Scale( GLOB_FRM, dCoeffX, dCoeffY, 1) ;
else
return false ;
}
// prima di riunire le curve al resto devo traslarle sul bordo destro della superificie che sto ricostruendo
Point3d pt ;
nDir == 0 ? pt.Set( abs(vU[p] - vU.front()), 0, 0) : pt.Set( 0,abs(vU[p] - vU.front()), 0) ;
if ( nDir == 0)
@@ -632,25 +707,78 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
vtJoin.Set( p * SBZ_TREG_COEFF - pt.x, 0, 0) ;
else
vtJoin.Set( 0, p * SBZ_TREG_COEFF - pt.y, 0) ;
pSfr_copy->Translate( vtJoin) ;
// se sto ritentando MakeUniform, allora faccio anche OFFSET e controOFFSET
if ( bRetry)
pSfr_copy->Offset( 10 * EPS_SMALL, ICurve::OFF_CHAMFER) ; // OFFSET
if ( pRescaledSfr->IsValid()) {
if ( ! pRescaledSfr->Add( *pSfr_copy))
return false ;
for( int i = 0 ; i < ssize( vCrvStrip); ++i)
vCrvStrip[i]->Translate( vtJoin) ;
#if SAVEMKUNIF_CRVS
//debug
vector<IGeoObj*> vGeo ;
for( int i = 0 ; i < ssize( vCrvStrip); ++i){
vGeo.push_back(vCrvStrip[i]->Clone()) ;
}
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\failed_trim_crv_strip.nge") ;
//debug
#endif
// faccio la chain con le curve delle striscie precedenti
if ( ! vUniformedCurves.empty() || ! vCrvStrip.empty()) {
#if SAVEMKUNIF_CRVS
//debug
vector<IGeoObj*> vGeo ;
for( int i = 0 ; i < ssize( vUniformedCurves); ++i){
vGeo.push_back(vUniformedCurves[i]->Clone()) ;
}
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\failed_trim_crv_unif.nge") ;
//debug
#endif
ChainCurves chainCrv ;
double dChainTol = 5 * EPS_SMALL ;
chainCrv.Init( false, dChainTol, max(ssize( vUniformedCurves), ssize(vCrvStrip))) ;
for ( int c = 0 ; c < ssize( vUniformedCurves) ; ++c) {
Point3d ptStart, ptEnd ;
Vector3d vtStart, vtEnd ;
vUniformedCurves[c]->GetStartPoint( ptStart) ;
vUniformedCurves[c]->GetEndPoint( ptEnd) ;
vUniformedCurves[c]->GetStartDir( vtStart) ;
vUniformedCurves[c]->GetEndDir( vtEnd) ;
chainCrv.AddCurve( 1 + c, ptStart, vtStart, ptEnd, vtEnd) ;
}
for ( int c = 0 ; c < ssize( vCrvStrip); ++c) {
Point3d ptStart, ptEnd ;
Vector3d vtStart, vtEnd ;
vCrvStrip[c]->GetStartPoint( ptStart) ;
vCrvStrip[c]->GetEndPoint( ptEnd) ;
vCrvStrip[c]->GetStartDir( vtStart) ;
vCrvStrip[c]->GetEndDir( vtEnd) ;
chainCrv.AddCurve( 1 + ssize( vUniformedCurves) + c, ptStart, vtStart, ptEnd, vtEnd) ;
}
INTVECTOR vIds ;
ICRVCOMPOPOVECTOR vNewCrv ;
int nCrvPrec = ssize( vUniformedCurves) ;
while ( chainCrv.GetChainFromNear( ORIG, false, vIds)) {
vNewCrv.emplace_back( CreateBasicCurveComposite()) ;
for ( int nId : vIds) {
nId -= 1 ;
if ( nId < nCrvPrec)
vNewCrv.back()->AddCurve( Release( vUniformedCurves[nId]), true, dChainTol) ;
else
vNewCrv.back()->AddCurve( Release( vCrvStrip[nId - ssize( vUniformedCurves)]), true, dChainTol) ;
}
}
// aggiorno le curve
vUniformedCurves.clear() ;
vUniformedCurves.swap( vNewCrv) ;
}
else
pRescaledSfr.Set( pSfr_copy) ;
}
vCrvStrip.clear() ;
}
if ( nDir == 0) {
dScaleU = ((int)vU.size() - 1) * SBZ_TREG_COEFF ;
if ( pRescaledSfr->IsValid()) {
if ( bRetry)
pRescaledSfr->Offset( -10 * EPS_SMALL, ICurve::OFF_CHAMFER) ; //contro OFFSET
delete pSfr ;
pSfr = Release( pRescaledSfr) ;
if( ! vbUniform[1]) {
vLoop.swap( vUniformedCurves) ;
vUniformedCurves.clear() ;
}
}
else
@@ -658,12 +786,38 @@ MakeUniform( ISurfFlatRegion*& pSfr, bool& bRescaled, const DBLVECTOR& vU0, cons
}
}
if ( ! IsNull( pRescaledSfr) && pRescaledSfr->IsValid()) {
if ( bRetry)
pRescaledSfr->Offset( -10 * EPS_SMALL, ICurve::OFF_CHAMFER) ; // contro OFFSET
delete pSfr ;
pSfr = Release( pRescaledSfr) ;
if ( ! vUniformedCurves.empty()) {
#if SAVEMKUNIF_CRVS
//debug
vector<IGeoObj*> vGeo ;
for( int i = 0 ; i < ssize( vUniformedCurves); ++i){
vGeo.push_back(vUniformedCurves[i]->Clone()) ;
}
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\import3dm\\trim_error\\failed_trim_crv_unif.nge") ;
//debug
#endif
// controllo che tutte le curve siano chiuse, sennò vuol dire che ho perso qualche pezzo durante le intersezioni
for ( int i = 0 ; i < ssize( vUniformedCurves); ++i) {
if ( ! vUniformedCurves[i]->IsClosed())
return false ;
}
// creo una regione dalle curve riscalate
SurfFlatRegionByContours sfrRescaled ;
for ( int i = 0 ; i < ssize( vUniformedCurves); ++i)
sfrRescaled.AddCurve( Release( vUniformedCurves[i])) ;
PtrOwner<ISurfFlatRegion> pRescaledSfr( sfrRescaled.GetSurf()) ;
if ( ! IsNull( pRescaledSfr) && pRescaledSfr->IsValid()) {
delete pSfr ;
pSfr = Release( pRescaledSfr) ;
}
else
return false ;
}
else if( ! vbUniform[0] || ! vbUniform[1])
return false ;
if ( ! bRescaledU && ! bRescaledV)
pSfr->Scale( GLOB_FRM, nSpanU / dScaleU * SBZ_TREG_COEFF, nSpanV / dScaleV * SBZ_TREG_COEFF, 1) ;
+260 -135
View File
@@ -45,10 +45,12 @@
#include "/EgtDev/Extern/Eigen/Dense"
#define SAVEFAILEDTRIANGULATION 0
#define SAVEISO 0
#define SAVEREBUILTISO 0
#define SAVERULEDISO 0
#define SAVERULEDGUIDEDISO 0
#if SAVEFAILEDTRIANGULATION || SAVEISO || SAVERULEDISO || SAVERULEDGUIDEDISO
#define SAVEMATCHCURVES 0
#define SAVEFAILEDTREE 0
#if SAVEFAILEDTRIANGULATION || SAVEREBUILTISO || SAVERULEDISO || SAVERULEDGUIDEDISO || SAVEMATCHCURVES || SAVEFAILEDTREE
#include "/EgtDev/Include/EGkGeoObjSave.h"
#endif
@@ -876,8 +878,8 @@ SurfBezier::CopyFrom( const SurfBezier& sbSrc)
m_bTrimmed = true ;
m_pTrimReg = sbSrc.m_pTrimReg->Clone() ;
}
#ifndef SAVEFAILEDTRIANGULATION
if( sbSrc.GetAuxSurf() != nullptr)
#if ! SAVEFAILEDTRIANGULATION && ! SAVEFAILEDTREE
if ( sbSrc.GetAuxSurf() != nullptr)
m_pSTM = sbSrc.GetAuxSurf()->Clone() ;
#endif
for ( int i = 0 ; i < int( sbSrc.m_mCCEdge.size()) ; ++i) {
@@ -1075,7 +1077,7 @@ SurfBezier::Load( NgeReader& ngeIn)
ICURVEPOVECTOR vCrv ;
GetAllPatchesIsocurves( false, vCrv) ;
vector<IGeoObj*> vGeo ;
for( int i = 0 ; i < ssize(vCrv) ; ++i)
for ( int i = 0 ; i < ssize(vCrv) ; ++i)
vGeo.push_back( vCrv[i]->Clone()) ;
SaveGeoObj( vGeo, "D:\\Temp\\bezier\\ruled\\rebuild\\isoCrv.nge") ;
#endif
@@ -1820,7 +1822,7 @@ SurfBezier::GetAuxSurf( void) const
}
}
// eseguo calcolo
m_pSTM = GetApproxSurf( s_dAuxSurfTol, 100 * EPS_SMALL, false) ;
m_pSTM = GetApproxSurf( s_dAuxSurfTol, 10 * EPS_SMALL, false) ;
++nSurf ;
if ( m_pSTM != nullptr)
m_pSTM->SetTempParam( s_dAuxSurfTol) ;
@@ -1855,13 +1857,13 @@ SurfBezier::GetAuxSurfRefined( void) const
}
}
// eseguo calcolo
m_pSTMRefined = GetApproxSurf( s_dAuxSurfRefinedTol, 100 * EPS_SMALL, true) ;
m_pSTMRefined = GetApproxSurf( s_dAuxSurfRefinedTol, 10 * EPS_SMALL, true) ;
if ( m_pSTMRefined != nullptr)
m_pSTMRefined->SetTempParam( s_dAuxSurfRefinedTol) ;
return m_pSTMRefined ;
}
#if SAVEFAILEDTRIANGULATION
#if SAVEFAILEDTRIANGULATION || SAVEFAILEDTREE
static int nErr = 0 ;
#endif
@@ -1898,8 +1900,12 @@ SurfBezier::GetApproxSurf( double dTol, double dSideMin, bool bUpdateEdges) cons
Point3d ptMin = get<0>( vTrees[i]) ;
Point3d ptMax = get<1>( vTrees[i]) ;
Tree.SetSurf( this, ptMin, ptMax) ;
if( ! Tree.BuildTree( dTol, dSideMin)) {
if ( ! Tree.BuildTree( dTol, dSideMin)) {
LOG_DBG_ERR( GetEGkLogger(), "ERROR : Bezier Surface parametric space couldn't be split in cells") ;
#if SAVEFAILEDTREE
SaveGeoObj( Clone(),"D:\\Temp\\bezier\\not_triangulated\\" + ToString( nErr) + ".nge") ;
++nErr ;
#endif
return nullptr ;
}
if ( ! Tree.GetPolygons( vvPL, vvPL3d, m_mCCEdge, m_vCCLoop, bUpdateEdges))
@@ -2175,7 +2181,7 @@ SurfBezier::ReorderPntEnhancedVector( const POLYLINEVECTOR& vPL, bool bTriangula
//----------------------------------------------------------------------------
bool
SurfBezier::GetLeaves( vector<tuple<int, Point3d, Point3d>>& vLeaves) const
SurfBezier::GetLeaves( vector<tuple<int, Point3d, Point3d>>& vLeaves, bool bRefined) const
{
Tree Tree ;
if ( ! Tree.SetSurf( this))
@@ -2186,7 +2192,10 @@ SurfBezier::GetLeaves( vector<tuple<int, Point3d, Point3d>>& vLeaves) const
Point3d ptMin = get<0>( vTrees[i]) ;
Point3d ptMax = get<1>( vTrees[i]) ;
Tree.SetSurf( this, ptMin, ptMax) ;
Tree.BuildTree( s_dAuxSurfTol, 100 * EPS_SMALL) ;
if ( ! bRefined)
Tree.BuildTree( s_dAuxSurfTol, 10 * EPS_SMALL) ;
else
Tree.BuildTree( s_dAuxSurfRefinedTol, 10 * EPS_SMALL) ;
vector<Cell> vCells ;
Tree.GetLeaves( vCells) ;
for ( int k = 0 ; k < int( vCells.size()) ; ++ k) {
@@ -3029,10 +3038,10 @@ SurfBezier::UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, in
dPtStm.GetMinDistTriaIndex( nTriaIndex) ;
// se ho trovato un nuovo triangolo, controllo che questo fosse nella lista dei triangoli equidistanti dal punto originale
// sennò ripeto il conto con meno scostamento
if( nTriaOld != nTriaIndex) {
if ( nTriaOld != nTriaIndex) {
auto iter = find( vnT.begin(), vnT.end(),nTriaIndex) ;
int nIdTria = distance( vnT.begin(), iter) ;
if( nIdTria > ssize( vnT) - 1) {
if ( nIdTria > ssize( vnT) - 1) {
ptI2 = ptI + ( ptIPrevOrNext - ptI) * 5 * EPS_SMALL ;
DistPointSurfTm dPtStm2( ptI2, *pSurfTm) ;
dPtStm2.GetMinDistTriaIndex( nTriaIndex) ;
@@ -4138,7 +4147,7 @@ SurfBezier::CreateByExtrusion( const ICurve* pCrv, const Vector3d& vtExtr)
// se composita verifico che curve siano con lo stesso grado e uniformi come tipo
bool bRat = false ;
int nDegU = 3 ;
if( pCrv->GetType() != CRV_COMPO) {
if ( pCrv->GetType() != CRV_COMPO) {
CC.AddCurve( CurveToBezierCurve( pCrv, nDegU, bRat)) ;
}
else {
@@ -4151,7 +4160,7 @@ SurfBezier::CreateByExtrusion( const ICurve* pCrv, const Vector3d& vtExtr)
}
}
if( CC.GetCurveCount() == 0 || ! CC.IsValid())
if ( CC.GetCurveCount() == 0 || ! CC.IsValid())
return false ;
// riempio la matrice dei punti di controllo
@@ -4222,46 +4231,73 @@ SurfBezier::CreateByScrewing( const ICurve* pCurve, const Point3d& ptAx, const V
if ( bOnlyRev && abs( dAngRotDeg) > ANG_FULL)
dAngRotDeg = _copysign( ANG_FULL, dAngRotDeg) ;
// se sto facendo una rivoluzione e la curva è piana, controllo che la curva non attraversi l'asse
if ( abs( dMove) < EPS_SMALL ) {
Plane3d plPlane ;
if ( pCurve->IsFlat( plPlane, false, 10 * EPS_SMALL)) {
BBox3d b3Crv ;
pCurve->GetLocalBBox( b3Crv) ;
double dAxLen = b3Crv.MaxDistFromPoint( ptAx) ;
CurveLine crvAx ;
crvAx.Set( ptAx - dAxLen * vtAx, ptAx + dAxLen * vtAx) ;
IntersCurveCurve icc( *pCurve, crvAx) ;
Point3d ptStart ; pCurve->GetStartPoint( ptStart) ;
Point3d ptEnd ; pCurve->GetEndPoint( ptEnd) ;
for ( int i = 0 ; i < icc.GetIntersCount() ; ++i) {
IntCrvCrvInfo iccInfo ;
icc.GetIntCrvCrvInfo( i, iccInfo) ;
// controllo che sia una vera intersezione in 3D, altrimenti passo alla successiva
if ( ! AreSamePointApprox( iccInfo.IciA[0].ptI, iccInfo.IciB[0].ptI))
continue ;
// se è il punto di inizio o di fine va bene e procedo
if ( AreSamePointApprox( ptStart, iccInfo.IciA[0].ptI) || AreSamePointApprox( ptEnd, iccInfo.IciA[0].ptI))
continue ;
// se la curva oltrepassa l'asse allora mi fermo, se tocca l'asse, ma resta dallo stesso lato, allora vado avanti
if ( iccInfo.IciA->nPrevTy != iccInfo.IciA->nNextTy)
return false ;
}
}
}
//// se sto facendo una rivoluzione e la curva è piana, controllo che la curva non attraversi l'asse
//CurveComposite ccNotTraversing ;
//if ( abs( dMove) < EPS_SMALL ) {
// Plane3d plPlane ;
// if ( pCurve->IsFlat( plPlane, false, 10 * EPS_SMALL)) {
// BBox3d b3Crv ;
// pCurve->GetLocalBBox( b3Crv) ;
// double dAxLen = b3Crv.MaxDistFromPoint( ptAx) ;
// CurveLine crvAx ;
// crvAx.Set( ptAx - dAxLen * vtAx, ptAx + dAxLen * vtAx) ;
// IntersCurveCurve icc( *pCurve, crvAx) ;
// Point3d ptStart ; pCurve->GetStartPoint( ptStart) ;
// Point3d ptEnd ; pCurve->GetEndPoint( ptEnd) ;
// bool bOk = true ;
// double dSplit = 0 ;
// for ( int i = 0 ; i < icc.GetIntersCount() ; ++i) {
// IntCrvCrvInfo iccInfo ;
// icc.GetIntCrvCrvInfo( i, iccInfo) ;
// // controllo che sia una vera intersezione in 3D, altrimenti passo alla successiva
// if ( ! AreSamePointApprox( iccInfo.IciA[0].ptI, iccInfo.IciB[0].ptI))
// continue ;
// // se è il punto di inizio o di fine va bene e procedo
// if ( AreSamePointApprox( ptStart, iccInfo.IciA[0].ptI) || AreSamePointApprox( ptEnd, iccInfo.IciA[0].ptI))
// continue ;
// // se la curva oltrepassa l'asse allora terrò solo la parte prima dell'asse, se tocca l'asse va bene
// if ( iccInfo.IciA->nPrevTy != iccInfo.IciA->nNextTy) {
// bOk = false ;
// dSplit = iccInfo.IciA[0].dU ;
// }
// }
// converto in bezier la curva iniziale
// // tengo solo la parte della curva fino all'intersezione con l'asse
// if ( ! bOk) {
// ccNotTraversing.AddCurve( pCurve->CopyParamRange( 0, dSplit)) ;
// }
// else
// ccNotTraversing.CopyFrom( pCurve) ;
// }
//}
//// converto in bezier la curva iniziale
// CurveComposite CrvU ;
//// se la curva è già una bezier singola la tengo, sennò la converto
// if ( ccNotTraversing.GetType() != CRV_BEZIER)
// CrvU.AddCurve( CurveToBezierCurve( &ccNotTraversing, 3, false)) ;
// else {
// if ( ! GetCurveBezier(&ccNotTraversing)->IsRational())
// CrvU.AddCurve( ccNotTraversing.Clone()) ;
// else {
// ICurveBezier* pCrvCopy = GetCurveBezier( ccNotTraversing.Clone()) ;
// if ( ! CrvU.AddCurve( EditBezierCurve( pCrvCopy, 3, false)))
// return false ;
// }
// }
// converto in bezier la curva iniziale
CurveComposite CrvU ;
// se la curva è già una bezier singola la tengo, sennò la converto
if ( pCurve->GetType() != CRV_BEZIER)
CrvU.AddCurve( CurveToBezierCurve( pCurve, 3, true)) ;
else {
if ( GetCurveBezier(pCurve)->IsRational())
if ( ! GetCurveBezier( pCurve)->IsRational())
CrvU.AddCurve( pCurve->Clone()) ;
else {
ICurveBezier* pCrvCopy = GetCurveBezier( pCurve->Clone()) ;
pCrvCopy->MakeRational() ;
CrvU.AddCurve( pCrvCopy) ;
if ( ! CrvU.AddCurve( EditBezierCurve( pCrvCopy, 3, true)))
return false ;
}
}
if ( ! CrvU.IsValid())
@@ -5071,7 +5107,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
if ( j == vMatch1.size())
bAdvance1 = false ;
// se trovo che ho uno spigolo allora procedo con la gestione spigoli
if( vEdgeSplit0[c+1] && vEdgeSplit1[j+1]) {
if ( vEdgeSplit0[c+1] && vEdgeSplit1[j+1]) {
// se ho uno spigolo su entrambe le curve forzo l'accoppiamento
bAdvance0 = true ;
bPerfectMatch = true ;
@@ -5080,7 +5116,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
ptJoint0 = vPnt1[j+1] ;
ptJoint1 = vPnt0[c+1] ;
}
else if ( (vEdgeSplit0[c+1] && ! bAdvance1) || (vEdgeSplit1[j+1] && ! bAdvance0)) {
else if (( vEdgeSplit0[c+1] && ! bAdvance1) || (vEdgeSplit1[j+1] && ! bAdvance0)) {
bAdvance0 = false ;
bAdvance1 = false ;
}
@@ -5241,28 +5277,28 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
// bAdvance0 = true ;
// bAdvance1 = true ;
// int nParam0, nParam1 ;
// while( bAdvance0) {
// while ( bAdvance0) {
// dParam0 = vMatch0[c_temp].second ;
// nParam0 = int( round( dParam0)) ;
// dParam1 = vMatch1[nParam0].second ;
// nParam1 = int( round( dParam1)) ;
// if( abs( nParam1 - c_temp) <= 2)
// if ( abs( nParam1 - c_temp) <= 2)
// bAdvance0 = false ;
// else
// ++ c_temp ;
// }
// while( bAdvance1) {
// while ( bAdvance1) {
// dParam1 = vMatch1[j_temp].second ;
// nParam1 = int( round( dParam1)) ;
// dParam0 = vMatch0[nParam1].second ;
// nParam0 = int( round( dParam0)) ;
// if( abs( nParam0 - j_temp) <= 2)
// if ( abs( nParam0 - j_temp) <= 2)
// bAdvance1 = false ;
// else
// ++ j_temp ;
// }
// // se non sono avanzato, allora mi basta accoppiare i due punti in questione
// if( c_temp == c || j_temp == j) {
// if ( c_temp == c || j_temp == j) {
// ++c ;
// ++j ;
// vPairs.emplace_back( c + nSplit0, j + nSplit1) ;
@@ -5292,13 +5328,13 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
// PtrOwner<ICurve> pCC1 ;
// int nPointsBetween0 = 0 ;
// int nPointsBetween1 = 0 ;
// if( bAdvance0 && bAdvance1) {
// if ( bAdvance0 && bAdvance1) {
// pCC0.Set( CrvU0.CopyParamRange( dLastParamMatch1, c_temp + 1)) ;
// pCC1.Set( CrvU1.CopyParamRange( dLastParamMatch0, j_temp + 1)) ;
// nPointsBetween0 = c_temp - c ;
// nPointsBetween1 = j_temp - j ;
// }
// else if( bAdvance0){
// else if ( bAdvance0) {
// pCC0.Set( CrvU0.CopyParamRange( dLastParamMatch1, c_temp + 1)) ;
// pCC1.Set( CrvU1.CopyParamRange( dLastParamMatch0, dParam0)) ;
// nPointsBetween0 = c_temp - c ;
@@ -5306,7 +5342,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
// if ( bIntParam0)
// nPointsBetween1 -= 1 ;
// }
// else if( bAdvance1){
// else if ( bAdvance1) {
// pCC0.Set( CrvU0.CopyParamRange( dLastParamMatch1, dParam1)) ;
// pCC1.Set( CrvU1.CopyParamRange( dLastParamMatch0, j_temp + 1)) ;
// nPointsBetween0 = int( dParam1) - ( c + 1) ;
@@ -5337,7 +5373,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
// int nJBefore = j ;
// //debug
// while ( bSplitToAdd) {
// if ( c0 > ssize( vdParamPos0) - 1 && c1 > ssize( vdParamPos1) - 1) {
// if ( c0 > ssize( vdParamPos0) - 1 && c1 > ssize( vdParamPos1) - 1) {
// LOG_DBG_ERR( GetEGkLogger(), "Surf Bez Ruled Guided: error 1 while reparametrizing some section") ;
// return false ;
// }
@@ -5384,13 +5420,13 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
// bSplitToAdd = ! ( c0 == ssize( vdParamPos0) - 1 && c1 == ssize( vdParamPos1) - 1) ;
// }
// // aggiorno i dati dell'ultima aggiunta
// if( bAdvance0 && ! bAdvance1) {
// if ( bAdvance0 && ! bAdvance1) {
// ptLastPointMatch0 = vMatch0[c_temp].first ;
// dLastParamMatch0 = vMatch0[c_temp].second ;
// ptLastPointMatch1 = vPnt0[c_temp] ;
// dLastParamMatch0 = c_temp ;
// }
// else if( ! bAdvance0 && bAdvance1) {
// else if ( ! bAdvance0 && bAdvance1) {
// ptLastPointMatch0 = vPnt1[j_temp] ;
// dLastParamMatch0 = j_temp ;
// ptLastPointMatch1 = vMatch1[j_temp].first ;
@@ -5406,7 +5442,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
// }
}
}
bAdvance = ! (c >= int(vMatch0.size()) - 1 && j >= int(vMatch1.size()) - 1) ;
bAdvance = ! ( c >= ssize( vMatch0) - 1 && j >= ssize( vMatch1) - 1) ;
}
// applico effettivamente gli split
@@ -5501,7 +5537,7 @@ SurfBezier::CreateByTwoCurves( const ICurve* pCurve0, const ICurve* pCurve1, int
vector<IGeoObj*> vGeo ;
ICURVEPOVECTOR vCrv ;
GetAllPatchesIsocurves( false, vCrv) ;
for( int i = 0 ; i < ssize( vCrv) ; ++i) {
for ( int i = 0 ; i < ssize( vCrv) ; ++i) {
vGeo.push_back( vCrv[i]->Clone()) ;
}
vector<Color> vCol( ssize( vCrv)) ;
@@ -5883,8 +5919,8 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c
{
// vCrv è il vettore delle isocurve (nel parametro V) che si vogliono forzare per la creazione della rigata tra Curve0 e Curve1
//controllo che siano entrambe chiuse o entrambe aperte
if( pCurve0->IsClosed() ^ pCurve1->IsClosed())
// controllo che siano entrambe chiuse o entrambe aperte
if ( pCurve0->IsClosed() != pCurve1->IsClosed())
return false ;
bool bClosed = pCurve0->IsClosed() ;
@@ -5934,22 +5970,95 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c
Point3d ptU1 = vCrv[i].second ;
double dParam0 ; CrvU0.GetParamAtPoint( ptU0, dParam0) ;
double dParam1 ; CrvU1.GetParamAtPoint( ptU1, dParam1) ;
if( bClosed && (dParam0 < EPS_SMALL || nSpanU0 - dParam0 < EPS_SMALL) && (dParam1 < EPS_SMALL || nSpanU1 - dParam1 < EPS_SMALL)) {
if( ! bFirstAdded) {
dParam0 = 0 ;
dParam1 = 0 ;
bFirstAdded = true ;
if ( bClosed) {
// curve di sync che sono esattamente sugli start/end di churve chiuse
if ( ( dParam0 < EPS_SMALL || nSpanU0 - dParam0 < EPS_SMALL) &&
( dParam1 < EPS_SMALL || nSpanU1 - dParam1 < EPS_SMALL)) {
if ( ! bFirstAdded) {
dParam0 = 0 ;
dParam1 = 0 ;
bFirstAdded = true ;
}
else {
dParam0 = nSpanU0 ;
dParam1 = nSpanU1 ;
}
}
else {
dParam0 = nSpanU0 ;
dParam1 = nSpanU1 ;
// curve si sync che hanno solo uno dei due punti su un punto di start/end, ma NON sono a cavallo dello start
else if ( ( dParam0 < EPS_SMALL || nSpanU0 - dParam0 < EPS_SMALL)) {
if ( ( nSpanU1 - dParam1) > dParam1)
dParam0 = 0 ;
else
dParam0 = nSpanU0 ;
}
else if (( dParam1 < EPS_SMALL || nSpanU1 - dParam1 < EPS_SMALL)) {
if ( ( nSpanU0 - dParam0) > dParam0)
dParam1 = 0 ;
else
dParam1 = nSpanU1 ;
}
//else if ( abs(( nSpanU0 - dParam0) / nSpanU0 - ( nSpanU1 - dParam1) / nSpanU1) > 0.1) {
// // gestisco il cambio di start se ho una sync a cavallo di start e end
// // quella sync diventa il nuovo start
//}
}
vIso.emplace_back( i, dParam0, dParam1) ;
}
sort( vIso.begin(), vIso.end()) ;
// sposto lo start sulla prima curva di sync che trovo
if ( bClosed) {
double dNewStart0 = vIso[0].dParam0 ;
double dNewStart1 = vIso[0].dParam1 ;
CrvU0.ChangeStartPoint( dNewStart0) ;
CrvU1.ChangeStartPoint( dNewStart1) ;
vIso[0].dParam0 = 0 ;
vIso[0].dParam1 = 0 ;
double dCeil0 = ceil( dNewStart0) ;
double dFloor0 = floor( dNewStart0) ;
double dCeil1 = ceil( dNewStart1) ;
double dFloor1 = floor( dNewStart1) ;
vPnt0.pop_back() ;
rotate( vPnt0.begin(), vPnt0.begin() + int( dCeil0), vPnt0.end()) ;
vPnt1.pop_back() ;
rotate( vPnt1.begin(), vPnt1.begin() + int( dCeil1), vPnt1.end()) ;
if ( abs( dNewStart0 - round( dNewStart0)) > EPS_SMALL) {
Point3d ptNewStart ; CrvU0.GetStartPoint( ptNewStart) ;
vPnt0.insert( vPnt0.begin(), ptNewStart) ;
++nSpanU0 ;
}
if ( abs( dNewStart1 - round( dNewStart1)) > EPS_SMALL) {
Point3d ptNewStart ; CrvU1.GetStartPoint( ptNewStart) ;
vPnt1.insert( vPnt1.begin(), ptNewStart) ;
++nSpanU1 ;
}
for ( int i = 1 ; i < ssize( vIso) ; ++i) {
if ( vIso[i].dParam0 >= dCeil0)
vIso[i].dParam0 -= dFloor0 ;
else if ( vIso[i].dParam0 <= dFloor0)
vIso[i].dParam0 += nSpanU0 - dCeil0 ;
else
CrvU0.GetParamAtPoint( vCrv[vIso[i].nCrv].first, vIso[i].dParam0) ;
if ( vIso[i].dParam1 >= dCeil1)
vIso[i].dParam1 -= dFloor1 ;
else if ( vIso[i].dParam1 <= dFloor1)
vIso[i].dParam1 += nSpanU1 - dCeil1 ;
else
CrvU1.GetParamAtPoint( vCrv[vIso[i].nCrv].second, vIso[i].dParam1) ;
}
}
else {
vIso.emplace_back( -1, 0, 0) ;
rotate( vIso.begin(), vIso.begin() + ssize(vIso) - 1, vIso.end()) ;
}
// se manca aggiungo la coppia finale
if ( vIso.back().dParam0 != nSpanU0 || vIso.back().dParam1 != nSpanU1)
vIso.emplace_back( -1, nSpanU0, nSpanU1) ;
// scorro vIso per verificare che non ci siano curve che si intersecano
int c = 0 ;
dLastParam0 = vIso[c].dParam0 ;
@@ -5965,12 +6074,25 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c
dLastParam0 = 0 ;
dLastParam1 = 0 ;
if( vIso[0].dParam0 > 0 || vIso[0].dParam1 > 0)
if ( vIso[0].dParam0 > 0 || vIso[0].dParam1 > 0)
vPairs.emplace_back( 0, 0) ;
for ( int i = 0 ; i < ssize( vIso) ; ++i) {
const BIPOINT& pCrv = vCrv[vIso[i].nCrv] ;
Point3d ptU0 = pCrv.first ;
Point3d ptU1 = pCrv.second ;
Point3d ptU0, ptU1 ;
if ( vIso[i].nCrv != -1) {
const BIPOINT& pCrv = vCrv[vIso[i].nCrv] ;
ptU0 = pCrv.first ;
ptU1 = pCrv.second ;
}
else {
if ( vIso[i].dParam0 == 0 && vIso[i].dParam1 == 0) {
CrvU0.GetStartPoint( ptU0) ;
CrvU1.GetStartPoint( ptU1) ;
}
else {
CrvU0.GetEndPoint( ptU0) ;
CrvU1.GetEndPoint( ptU1) ;
}
}
double& dParam0 = vIso[i].dParam0 ;
double& dParam1 = vIso[i].dParam1 ;
// se sono vicino ad un'intero allora considero il parametro intero ( uno split già esistente)
@@ -6037,7 +6159,7 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c
return false ;
}
// se ho una corrispondenza tra punti ( e non sono alla fine del tratto) allora non aggiungo split
if ( abs( vdParamPos0[c0] - vdParamPos1[c1]) < EPS_PARAM && vdParamPos0[c0] < 1) {
if ( abs( vdParamPos0[c0] - vdParamPos1[c1]) < EPS_SMALL && vdParamPos0[c0] < 1) {
++c0 ;
++c1 ;
++nLastParam0 ;
@@ -6052,6 +6174,7 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c
nSplit1 = vdSplit1.size() ;
}
else if ( dPar = round( dPar) ; dPar > nLastParam1){
++ c1 ;
++ nLastParam1 ;
}
++nLastParam0 ;
@@ -6066,6 +6189,7 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c
nSplit0 = vdSplit0.size() ;
}
else if ( dPar = round( dPar) ; dPar > nLastParam0){
++ c0 ;
++ nLastParam0 ;
}
++nLastParam1 ;
@@ -6125,11 +6249,12 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c
nSpanU0 = CrvU0.GetCurveCount() ;
nSpanU1 = CrvU1.GetCurveCount() ;
// aggiungo l'ultima coppia
vPairs.emplace_back( nSpanU0, nSpanU1) ;
// aggiungo l'ultima coppia se necessario
if ( vPairs.back().first != nSpanU0 || vPairs.back().second != nSpanU1)
vPairs.emplace_back( nSpanU0, nSpanU1) ;
// trovo il numero di span che dovrà avere la superficie
int nSpanU = int(vPairs.size()) - 1 ;
int nSpanU = int( vPairs.size()) - 1 ;
int nSecondRowInd = nDegU * nSpanU + 1 ;
// inizializzo la superficie
@@ -6186,7 +6311,7 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c
vector<IGeoObj*> vGeo ;
ICURVEPOVECTOR vCrvIso ;
GetAllPatchesIsocurves( false, vCrvIso) ;
for( int i = 0 ; i < ssize( vCrvIso) ; ++i) {
for ( int i = 0 ; i < ssize( vCrvIso) ; ++i) {
vGeo.push_back( vCrvIso[i]->Clone()) ;
}
vector<Color> vCol( ssize( vCrvIso)) ;
@@ -6208,36 +6333,36 @@ SurfBezier::CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, c
//----------------------------------------------------------------------------
bool
SurfBezier::RemoveCollapsedSpans()
SurfBezier::RemoveCollapsedSpans( void)
{
double dTol = EPS_SMALL ;
//controllo se ho delle span collassate e le rimuovo
if( m_nSpanU > 1 || m_nSpanV > 1) {
if ( m_nSpanU > 1 || m_nSpanV > 1) {
CalcPoles() ;
if( ! m_vbPole[2]) {
if ( ! m_vbPole[2]) {
// scorro i punti della prima riga
INTVECTOR vnCollapsedSpan ;
for( int i = 0 ; i < m_nSpanU ; ++i) {
for ( int i = 0 ; i < m_nSpanU ; ++i) {
bool bSamePoint = true ;
Point3d ptFirst = m_vPtCtrl[m_nDegU * i] ;
// cerco se trovo tutti i punti in U coincidenti in una delle Span
for( int j = 1 ; j < m_nDegU + 1 && bSamePoint ; ++j) {
if( ! AreSamePointEpsilon( ptFirst, m_vPtCtrl[m_nDegU * i + j], dTol))
for ( int j = 1 ; j < m_nDegU + 1 && bSamePoint ; ++j) {
if ( ! AreSamePointEpsilon( ptFirst, m_vPtCtrl[m_nDegU * i + j], dTol))
bSamePoint = false ;
}
if( bSamePoint) {
if ( bSamePoint) {
// se trovo un'altra riga collassata do per scontato che tutta span sia collassata
ptFirst = m_vPtCtrl[GetInd( m_nDegU * i, 1)] ;
for( int j = 1 ; j < m_nDegU + 1 && bSamePoint ; ++j) {
if( ! AreSamePointEpsilon( ptFirst, m_vPtCtrl[GetInd( m_nDegU * i + j, 1)], dTol))
for ( int j = 1 ; j < m_nDegU + 1 && bSamePoint ; ++j) {
if ( ! AreSamePointEpsilon( ptFirst, m_vPtCtrl[GetInd( m_nDegU * i + j, 1)], dTol))
bSamePoint = false ;
}
if( bSamePoint)
if ( bSamePoint)
vnCollapsedSpan.push_back( i) ;
}
}
int nOldSpanU = m_nSpanU ;
if( ! vnCollapsedSpan.empty()) {
if ( ! vnCollapsedSpan.empty()) {
// cancello le span che risultano collassate
int nNewSpanU = m_nSpanU - ssize( vnCollapsedSpan) ;
int nNewDim = ( m_nDegU * nNewSpanU + 1) * ( m_nDegV * m_nSpanV + 1) ;
@@ -6245,21 +6370,21 @@ SurfBezier::RemoveCollapsedSpans()
DBLVECTOR vNewWeight( nNewDim) ;
int nCurrSkipInd = -1 ;
int nCurrSkip = -1 ;
for( int nIndV = 0 ; nIndV < m_nSpanV * m_nDegV + 1 ; ++nIndV) {
for ( int nIndV = 0 ; nIndV < m_nSpanV * m_nDegV + 1 ; ++nIndV) {
nCurrSkipInd = 0 ;
nCurrSkip = vnCollapsedSpan[nCurrSkipInd] ;
for( int i = 0 ; i < m_nSpanU ; ++i) {
if( i != nCurrSkip) {
for( int j = ( i - nCurrSkipInd) ==0 ? 0 : 1 ; j < m_nDegU + 1 ; ++j) {
for ( int i = 0 ; i < m_nSpanU ; ++i) {
if ( i != nCurrSkip) {
for ( int j = ( i - nCurrSkipInd) ==0 ? 0 : 1 ; j < m_nDegU + 1 ; ++j) {
vNewCtrlPnt[nIndV * ( m_nDegU * nNewSpanU + 1) + (i - nCurrSkipInd) * m_nDegU + j] = m_vPtCtrl[GetInd( m_nDegU * i + j, nIndV)] ;
if( m_bRat) {
if ( m_bRat) {
vNewWeight[nIndV * ( m_nDegU * nNewSpanU + 1) + (i - nCurrSkipInd) * m_nDegU + j] = m_vWeCtrl[GetInd( m_nDegU * i + j, nIndV)] ;
}
}
}
else {
++nCurrSkipInd ;
if( nCurrSkipInd > ssize( vnCollapsedSpan) - 1)
if ( nCurrSkipInd > ssize( vnCollapsedSpan) - 1)
nCurrSkip = -1 ;
else
nCurrSkip = vnCollapsedSpan[nCurrSkipInd] ;
@@ -6270,32 +6395,32 @@ SurfBezier::RemoveCollapsedSpans()
// vettori dei punti e numero di span
ISurfFlatRegion* pSFRTrim = nullptr ;
bool bTrimmed = m_bTrimmed ;
if( bTrimmed) {
if ( bTrimmed) {
pSFRTrim = GetTrimRegion() ;
m_pTrimReg = nullptr ;
}
Init( m_nDegU, m_nDegV, nNewSpanU, m_nSpanV, m_bRat) ;
m_vPtCtrl = vNewCtrlPnt ;
if( m_bRat)
if ( m_bRat)
m_vWeCtrl = vNewWeight ;
if( bTrimmed) {
if ( bTrimmed) {
// elimino le span di troppo dallo spazio parametrico
PtrOwner<ISurfFlatRegion> pNewTrim( pSFRTrim->Clone()) ;
for( int i = ssize( vnCollapsedSpan) - 1 ; i >= 0 ; --i) {
for ( int i = ssize( vnCollapsedSpan) - 1 ; i >= 0 ; --i) {
int nSpan = vnCollapsedSpan[i] ;
// tolgo tutta la parte a destra della colonna da togliere
PtrOwner<ISurfFlatRegion> pSFRCut ( GetSurfFlatRegionRectangle( ( nOldSpanU - nSpan) * SBZ_TREG_COEFF, m_nSpanV * SBZ_TREG_COEFF + 2)) ;
if( nSpan != 0) {
if ( nSpan != 0) {
pSFRCut->Translate( Vector3d( nSpan * SBZ_TREG_COEFF, -1)) ;
pNewTrim->Subtract( *pSFRCut) ;
}
if( pNewTrim->IsValid()) {
if ( pNewTrim->IsValid()) {
// ritaglio dal parametrico originale la parte a destra della colonna da eliminare e la incollo alla parte a sinistra
PtrOwner<ISurfFlatRegion> pRightPart( pSFRTrim->Clone()) ;
pSFRCut.Set( GetSurfFlatRegionRectangle( ( nSpan + 1) * SBZ_TREG_COEFF, m_nSpanV * SBZ_TREG_COEFF + 2)) ;
pSFRCut->Translate( Vector3d( nSpan * SBZ_TREG_COEFF, -1)) ;
if( pRightPart->Subtract( *pSFRCut) && pRightPart->IsValid()) {
if( ! pNewTrim->Add( *pRightPart) || ! pNewTrim->IsValid())
if ( pRightPart->Subtract( *pSFRCut) && pRightPart->IsValid()) {
if ( ! pNewTrim->Add( *pRightPart) || ! pNewTrim->IsValid())
break ;
}
}
@@ -6307,30 +6432,30 @@ SurfBezier::RemoveCollapsedSpans()
}
}
if( ! m_vbPole[1]) {
if ( ! m_vbPole[1]) {
// scorro i punti della prima colonna
INTVECTOR vnCollapsedSpan ;
for( int i = 0 ; i < m_nSpanV ; ++i) {
for ( int i = 0 ; i < m_nSpanV ; ++i) {
bool bSamePoint = true ;
Point3d ptFirst = m_vPtCtrl[GetInd( 0, i * m_nDegV)] ;
// cerco se trovo tutti i punti in U coincidenti in una delle Span
for( int j = 1 ; j < m_nDegV + 1 && bSamePoint ; ++j) {
if( ! AreSamePointEpsilon( ptFirst, m_vPtCtrl[GetInd( 0, i * m_nDegV + j)], dTol))
for ( int j = 1 ; j < m_nDegV + 1 && bSamePoint ; ++j) {
if ( ! AreSamePointEpsilon( ptFirst, m_vPtCtrl[GetInd( 0, i * m_nDegV + j)], dTol))
bSamePoint = false ;
}
if( bSamePoint) {
if ( bSamePoint) {
// se trovo un'altra colonna collassata do per scontato che tutta span sia collassata
ptFirst = m_vPtCtrl[GetInd( 1, i * m_nDegV)] ;
for( int j = 1 ; j < m_nDegV + 1 && bSamePoint ; ++j) {
if( ! AreSamePointEpsilon( ptFirst, m_vPtCtrl[GetInd( 1, i * m_nDegV + j)], dTol))
for ( int j = 1 ; j < m_nDegV + 1 && bSamePoint ; ++j) {
if ( ! AreSamePointEpsilon( ptFirst, m_vPtCtrl[GetInd( 1, i * m_nDegV + j)], dTol))
bSamePoint = false ;
}
if( bSamePoint)
if ( bSamePoint)
vnCollapsedSpan.push_back( i) ;
}
}
int nOldSpanV = m_nSpanV ;
if( ! vnCollapsedSpan.empty()) {
if ( ! vnCollapsedSpan.empty()) {
// cancello le span che risultano collassate
int nNewSpanV = m_nSpanV - ssize( vnCollapsedSpan) ;
int nNewDim = ( m_nDegU * m_nSpanU + 1) * ( m_nDegV * nNewSpanV + 1) ;
@@ -6338,12 +6463,12 @@ SurfBezier::RemoveCollapsedSpans()
DBLVECTOR vNewWeight( nNewDim) ;
int nCurrSkipInd = 0 ;
int nCurrSkip = vnCollapsedSpan[nCurrSkipInd] ;
for( int nIndV = 0 ; nIndV < m_nSpanV * m_nDegV + 1 ; ++nIndV) {
if( nIndV / m_nDegV != nCurrSkip) {
for( int i = 0 ; i < m_nSpanU ; ++i) {
for( int j = i==0 ? 0 : 1 ; j < m_nDegU + 1 ; ++j) {
for ( int nIndV = 0 ; nIndV < m_nSpanV * m_nDegV + 1 ; ++nIndV) {
if ( nIndV / m_nDegV != nCurrSkip) {
for ( int i = 0 ; i < m_nSpanU ; ++i) {
for ( int j = i==0 ? 0 : 1 ; j < m_nDegU + 1 ; ++j) {
vNewCtrlPnt[( nIndV - ( nCurrSkipInd * m_nDegV)) * ( m_nDegU * m_nSpanU + 1) + i * m_nDegU + j] = m_vPtCtrl[GetInd( m_nDegU * i + j, nIndV)] ;
if( m_bRat) {
if ( m_bRat) {
vNewWeight[( nIndV - ( nCurrSkipInd * m_nDegV)) * ( m_nDegU * m_nSpanU + 1) + i * m_nDegU + j] = m_vWeCtrl[GetInd( m_nDegU * i + j, nIndV)] ;
}
}
@@ -6352,7 +6477,7 @@ SurfBezier::RemoveCollapsedSpans()
else {
nIndV += m_nDegV - 1 ;
++nCurrSkipInd ;
if( nCurrSkipInd > ssize( vnCollapsedSpan) - 1)
if ( nCurrSkipInd > ssize( vnCollapsedSpan) - 1)
nCurrSkip = -1 ;
else
nCurrSkip = vnCollapsedSpan[nCurrSkipInd] ;
@@ -6362,32 +6487,32 @@ SurfBezier::RemoveCollapsedSpans()
// vettori dei punti e numero di span
ISurfFlatRegion* pSFRTrim = nullptr ;
bool bTrimmed = m_bTrimmed ;
if( bTrimmed) {
if ( bTrimmed) {
pSFRTrim = GetTrimRegion() ;
m_pTrimReg = nullptr ;
}
Init( m_nDegU, m_nDegV, m_nSpanU, nNewSpanV, m_bRat) ;
m_vPtCtrl = vNewCtrlPnt ;
if( m_bRat)
if ( m_bRat)
m_vWeCtrl = vNewWeight ;
if( bTrimmed) {
if ( bTrimmed) {
// elimino le span di troppo dallo spazio parametrico
PtrOwner<ISurfFlatRegion> pNewTrim( pSFRTrim->Clone()) ;
for( int i = ssize( vnCollapsedSpan) - 1 ; i >= 0 ; --i) {
for ( int i = ssize( vnCollapsedSpan) - 1 ; i >= 0 ; --i) {
int nSpan = vnCollapsedSpan[i] ;
// tolgo tutta la parte a sopra la riga da togliere
PtrOwner<ISurfFlatRegion> pSFRCut ( GetSurfFlatRegionRectangle( m_nSpanU * SBZ_TREG_COEFF + 2, ( nOldSpanV - nSpan) * SBZ_TREG_COEFF)) ;
if( nSpan != 0) {
if ( nSpan != 0) {
pSFRCut->Translate( Vector3d( -1, nSpan * SBZ_TREG_COEFF)) ;
pNewTrim->Subtract( *pSFRCut) ;
}
if( pNewTrim->IsValid()) {
if ( pNewTrim->IsValid()) {
// ritaglio dal parametrico originale la parte sopra la riga da eliminare e la incollo alla parte sotto la riga
PtrOwner<ISurfFlatRegion> pUpperPart( pSFRTrim->Clone()) ;
pSFRCut.Set( GetSurfFlatRegionRectangle( m_nSpanU * SBZ_TREG_COEFF + 2, ( nSpan + 1) * SBZ_TREG_COEFF)) ;
pSFRCut->Translate( Vector3d( -1, nSpan * SBZ_TREG_COEFF)) ;
if( pUpperPart->Subtract( *pSFRCut) && pUpperPart->IsValid()) {
if( ! pNewTrim->Add( *pUpperPart) || ! pNewTrim->IsValid())
if ( pUpperPart->Subtract( *pSFRCut) && pUpperPart->IsValid()) {
if ( ! pNewTrim->Add( *pUpperPart) || ! pNewTrim->IsValid())
break ;
}
}
@@ -6405,7 +6530,7 @@ SurfBezier::RemoveCollapsedSpans()
//----------------------------------------------------------------------------
bool
SurfBezier::SwapParameters()
SurfBezier::SwapParameters( void)
{
// inverto il parametro U con il parametro V
// salvo i vecchi dati
@@ -6415,7 +6540,7 @@ SurfBezier::SwapParameters()
int nDegV = m_nDegU ;
bool bTrimmed = m_bTrimmed ;
PtrOwner<ISurfFlatRegion> pSFRTRim ;
if( m_bTrimmed) {
if ( m_bTrimmed) {
pSFRTRim.Set( GetTrimRegion()) ;
m_pTrimReg = nullptr ;
}
@@ -6423,16 +6548,16 @@ SurfBezier::SwapParameters()
// creo il vettore dei punti di controllo
PNTVECTOR vNewCtrlPt( GetDim()) ;
DBLVECTOR vNewWeight( GetDim()) ;
for( int j = 0 ; j < m_nDegV * m_nSpanV + 1 ; ++j) {
for( int i = 0 ; i < m_nDegU * m_nSpanU + 1 ; ++ i) {
for ( int j = 0 ; j < m_nDegV * m_nSpanV + 1 ; ++j) {
for ( int i = 0 ; i < m_nDegU * m_nSpanU + 1 ; ++ i) {
vNewCtrlPt[i * ( nDegU * nSpanU + 1) + j] = m_vPtCtrl[GetInd(i,j)] ;
if( m_bRat)
if ( m_bRat)
vNewWeight[i * ( nDegU * nSpanU + 1) + j] = m_vWeCtrl[GetInd(i,j)] ;
}
}
Init( nDegU, nDegV, nSpanU, nSpanV, m_bRat) ;
if( bTrimmed) {
if ( bTrimmed) {
pSFRTRim->Mirror( ORIG, Vector3d(1,-1)) ;
SetTrimRegion( *pSFRTRim) ;
}
@@ -6440,4 +6565,4 @@ SurfBezier::SwapParameters()
m_vWeCtrl = vNewWeight ;
return true ;
}
}
+4 -4
View File
@@ -116,9 +116,9 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
bool GetControlCurveOnV( int nIndU, PolyLine& plCtrlV) const override ;
const SurfTriMesh* GetAuxSurf( void) const override ;
const SurfTriMesh* GetAuxSurfRefined( void) const override ;
SurfTriMesh* GetApproxSurf( double dTol, double dSideMin = 100 * EPS_SMALL, bool bUpdateEdges = false) const override ;
SurfTriMesh* GetApproxSurf( double dTol, double dSideMin = 10 * EPS_SMALL, bool bUpdateEdges = false) const override ;
// funzione per ottenere la suddivisione dello spazio parametrico nelle celle utilizzate per la triangolazione.
bool GetLeaves( std::vector<std::tuple<int, Point3d, Point3d>>& vLeaves) const override ;
bool GetLeaves( std::vector<std::tuple<int, Point3d, Point3d>>& vLeaves, bool bRefined = false) const override ;
bool GetTriangles2D( std::vector<std::tuple<int,Point3d, Point3d, Point3d>>& vTria2D) const override ;
// funzioni che servono per ricavare l'immagine nel parametrico di un punto appartenente alla trimesh ausiliaria della superficie di Bezier
bool UnprojectPointFromStm( int nT, const Point3d& ptI, Point3d& ptSP, int nIL = IntLineTriaType::ILTT_IN) const override ;
@@ -151,8 +151,8 @@ class SurfBezier : public ISurfBezier, public IGeoObjRW
PNTVECTOR GetAllControlPoints( void) const ;
bool GetAllPatchesIsocurves( bool bUorV, ICURVEPOVECTOR& vCrv) const ;
bool CreateByIsoParamSet( const ICurve* pCurve0, const ICurve* pCurve1, const BIPNTVECTOR& vCrv) ;
bool RemoveCollapsedSpans() override ;
bool SwapParameters() ;
bool RemoveCollapsedSpans( void) override ;
bool SwapParameters( void) ;
public : // IGeoObjRW
int GetNgeId( void) const override ;
+29
View File
@@ -4415,6 +4415,35 @@ SurfTriMesh::ClonePart( int nPart) const
return Release( pSurfTM) ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::GetPartAndShellFromFacet( int nFacet, int& nPart, int& nShell) const
{
// l'indice della faccia deve essere nei limiti
if ( nFacet < 0 || nFacet >= int( m_vFacet.size()))
return false ;
// mi assicuro che siano calcolate il numero di parti e di shell
int nParts = GetPartCount() ;
int nTria = m_vFacet[nFacet] ;
nShell = m_vTria[nTria].nShell ;
// scopro in quale part è la shell
int nPartTemp = 0 ;
nPart = - 1 ;
while ( nPartTemp < nParts && nPart == - 1) {
for ( int i : m_vPart[nPartTemp].vShell) {
if ( i == nShell) {
nPart = nPartTemp ;
break ;
}
}
++nPartTemp ;
}
return true ;
}
//----------------------------------------------------------------------------
bool
SurfTriMesh::ResetTFlags( void)
+1
View File
@@ -347,6 +347,7 @@ class SurfTriMesh : public ISurfTriMesh, public IGeoObjRW
bool GetPartVolume( int nPart, double& dVolume) const override ;
bool GetPartLoops( int nPart, POLYLINEVECTOR& vPL) const override ;
SurfTriMesh* ClonePart( int nPart) const override ;
bool GetPartAndShellFromFacet( int nFacet, int& nPart, int& nShell) const override ;
bool SetTFlag( int nId, int nTFlag) override ;
bool GetTFlag( int nId, int& nFlag) const override ;
int GetMaxTFlag( void) const override
+10 -10
View File
@@ -36,25 +36,25 @@ class Tool
bool SetAdditiveTool( const std::string& sToolName, double dH, double dR, double dRc, int nToolNum) ;
bool SetToolNum( int nToolNum)
{ m_nCurrentNum = nToolNum ; return true ; }
int GetType() const
int GetType( void) const
{ return m_nType ; }
int GetToolNum() const
int GetToolNum( void) const
{ return m_nCurrentNum ; }
double GetHeigth() const
double GetHeigth( void) const
{ return m_dHeight ; }
double GetTipHeigth() const
double GetTipHeigth( void) const
{ return m_dTipHeight ; }
double GetRadius() const
double GetRadius( void) const
{ return m_dRadius ; }
double GetTipRadius() const
double GetTipRadius( void) const
{ return m_dTipRadius ; }
double GetCornRadius() const
double GetCornRadius( void) const
{ return m_dRCorner ; }
double GetRefRadius() const
double GetRefRadius( void) const
{ return m_dRefRadius ; }
double GetMrtChsWidth() const
double GetMrtChsWidth( void) const
{ return m_dMrtChsWidth ; }
double GetMrtChsThickness() const
double GetMrtChsThickness( void) const
{ return m_dMrtChsThickness ; }
const CurveComposite& GetOutline( void) const
{ return ( m_Outline) ; }
+109 -21
View File
@@ -177,7 +177,7 @@ Tree::SetSurf( const SurfBezier* pSrfBz, const Point3d& ptMin, const Point3d& pt
int nLoop = 0 ;
// recupero la superficie di trim per avere accesso diretto ai loop e mantenendo le informazioni sui chunk
PtrOwner<SurfFlatRegion> pTrimReg( m_pSrfBz->GetTrimRegion()->Clone()) ;
double dLinTol = 0.01 ; // questo è riferito allo spazio parametrico
double dLinTol = 0.005 ; // questo è riferito allo spazio parametrico
double dAngTolDeg = 5 ;
for ( int i = 0 ; i < pTrimReg->GetChunkCount() ; ++ i) {
PtrOwner<SurfFlatRegion> pChunk( pTrimReg->CloneChunk( i)) ;
@@ -185,6 +185,8 @@ Tree::SetSurf( const SurfBezier* pSrfBz, const Point3d& ptMin, const Point3d& pt
// i chunk della falt region sono ancora flat region composte da 1 chunk
// rimuovo i difetti dei loop prima di salvarli
PtrOwner<ICurveComposite> pLoop( GetBasicCurveComposite( pChunk->GetLoop( 0, j))) ;
if ( IsNull( pLoop))
return false ;
pLoop->MergeCurves( dLinTol, dAngTolDeg) ;
pLoop->RemoveSmallDefects( dLinTol, dAngTolDeg, true) ;
pLoop->RemoveSmallParts( dLinTol, dAngTolDeg) ;
@@ -461,8 +463,8 @@ Tree::Split( int nId, double dSplitValue)
dSplitValue < cToSplit.GetTopRight().y - 10 * EPS_SMALL ;
Point3d ptP00, ptP01, ptP10, ptP11 ;
if( bGoodSplitVert) {
if( cToSplit.GetBottomRight().x - dSplitValue > dSplitValue - cToSplit.GetBottomLeft().x) {
if ( bGoodSplitVert) {
if ( cToSplit.GetBottomRight().x - dSplitValue > dSplitValue - cToSplit.GetBottomLeft().x) {
GetPoint( cToSplit.GetBottomLeft().x, cToSplit.GetBottomLeft().y, ptP00) ;
GetPoint( dSplitValue, cToSplit.GetBottomRight().y, ptP10) ;
GetPoint( cToSplit.GetTopLeft().x, cToSplit.GetTopLeft().y, ptP01) ;
@@ -474,12 +476,13 @@ Tree::Split( int nId, double dSplitValue)
GetPoint( dSplitValue, cToSplit.GetTopLeft().y, ptP01) ;
GetPoint( cToSplit.GetTopRight().x, cToSplit.GetTopRight().y, ptP11) ;
}
if( AreSamePointApprox( ptP00, ptP10) && AreSamePointApprox( ptP01, ptP11) &&
( cToSplit.GetBottomRight().x - dSplitValue < SBZ_TREG_COEFF - EPS_SMALL || dSplitValue - cToSplit.GetBottomLeft().x < SBZ_TREG_COEFF - EPS_SMALL))
if ( AreSamePointApprox( ptP00, ptP10) && AreSamePointApprox( ptP01, ptP11) &&
( cToSplit.GetBottomRight().x - dSplitValue < SBZ_TREG_COEFF - EPS_SMALL ||
dSplitValue - cToSplit.GetBottomLeft().x < SBZ_TREG_COEFF - EPS_SMALL))
bGoodSplitVert = false ;
}
if( bGoodSplitHoriz) {
if( cToSplit.GetTopLeft().y - dSplitValue > dSplitValue - cToSplit.GetBottomLeft().y) {
if ( bGoodSplitHoriz) {
if ( cToSplit.GetTopLeft().y - dSplitValue > dSplitValue - cToSplit.GetBottomLeft().y) {
GetPoint( cToSplit.GetBottomLeft().x, cToSplit.GetBottomLeft().y, ptP00) ;
GetPoint( cToSplit.GetBottomRight().x, cToSplit.GetBottomRight().y, ptP10) ;
GetPoint( cToSplit.GetTopLeft().x, dSplitValue, ptP01) ;
@@ -491,8 +494,9 @@ Tree::Split( int nId, double dSplitValue)
GetPoint( cToSplit.GetTopLeft().x, cToSplit.GetTopLeft().y, ptP01) ;
GetPoint( cToSplit.GetTopRight().x, cToSplit.GetTopRight().y, ptP11) ;
}
if( AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11) &&
( cToSplit.GetTopLeft().y - dSplitValue < SBZ_TREG_COEFF - EPS_SMALL || dSplitValue - cToSplit.GetBottomLeft().y < SBZ_TREG_COEFF - EPS_SMALL))
if ( AreSamePointApprox( ptP00, ptP01) && AreSamePointApprox( ptP10, ptP11) &&
( cToSplit.GetTopLeft().y - dSplitValue < SBZ_TREG_COEFF - EPS_SMALL ||
dSplitValue - cToSplit.GetBottomLeft().y < SBZ_TREG_COEFF - EPS_SMALL))
bGoodSplitHoriz = false ;
}
@@ -662,8 +666,18 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
}
}
// calcolo se la parte di superficie nella cella è piatta
PolyLine PL ;
PL.AddUPoint( 0, ptP00) ;
PL.AddUPoint( 1, ptP10) ;
PL.AddUPoint( 2, ptP11) ;
PL.AddUPoint( 3, ptP01) ;
PL.AddUPoint( 4, ptCen) ;
Plane3d plPlane ;
bool bIsFlat = PL.IsFlat( plPlane, dLinTol) ;
// su isoparametriche in U e V
if ( dSagU < dLinTol && dSagV < dLinTol) {
if ( dSagU < dLinTol && dSagV < dLinTol && ! bIsFlat) {
// step di verifica in U e in V
int nStepU = ( dLenParU > 1. / m_nDegU ? m_nDegU + 1 : 2) ;
int nStepV = ( dLenParV > 1. / m_nDegV ? m_nDegV + 1 : 2) ;
@@ -724,6 +738,73 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
//{ string sLog = " Da Isoparam : FrecciaU=" + ToString( dSagU, 3) + " FrecciaV=" + ToString( dSagV, 3) ;
// LOG_DBG_INFO( GetEGkLogger(), sLog.c_str())}
}
else if ( dSagU < dLinTol && dSagV < dLinTol && bIsFlat) {
// se la cella è piatta devo verificare che i bordi siano dei tratti retti, altrimenti potrei commettere un errore di approssimazione
// bordo inferiore e superiore
double dMaxDist = 0 ;
for ( int i = 0 ; i < 2 ; ++i) {
CurveLine clU ;
if ( i == 0)
clU.Set( ptP00, ptP10) ;
else if ( i == 1)
clU.Set( ptP01, ptP11) ;
double dV = 0 ;
if ( i == 0)
dV = pcToSplit->GetBottomLeft().y ;
else if ( i == 1)
dV = pcToSplit->GetTopRight().y ;
int nStepU = 4 ;
for ( int j = 1 ; j < nStepU ; ++ j) {
// parametro U
double dCoeffU = double( j) / nStepU ;
double dU = ( 1 - dCoeffU) * pcToSplit->GetBottomLeft().x + dCoeffU * pcToSplit->GetTopRight().x ;
Point3d ptBez ;
GetPoint( dU, dV, ptBez) ;
DistPointCurve dpc( ptBez, clU) ;
double dDist = 0 ;
dpc.GetDist( dDist) ;
if ( dDist > dMaxDist)
dMaxDist = dDist ;
}
}
if ( dMaxDist > dLinTol)
dSagU = dMaxDist ;
// bordo sinistro e destro
dMaxDist = 0 ;
for ( int i = 0 ; i < 2 ; ++i) {
CurveLine clV ;
if ( i == 0)
clV.Set( ptP00, ptP01) ;
else if ( i == 1)
clV.Set( ptP10, ptP11) ;
double dU = 0 ;
if ( i == 0)
dU = pcToSplit->GetBottomLeft().x ;
else if ( i == 1)
dU = pcToSplit->GetTopRight().x ;
int nStepV = 4 ;
for ( int j = 1 ; j < nStepV ; ++ j) {
// parametro in V
double dCoeffV = double( j) / nStepV ;
double dV = ( 1 - dCoeffV) * pcToSplit->GetBottomLeft().y + dCoeffV * pcToSplit->GetTopRight().y ;
Point3d ptBez ;
GetPoint( dU, dV, ptBez) ;
DistPointCurve dpc( ptBez, clV) ;
double dDist = 0 ;
dpc.GetDist( dDist) ;
if ( dDist > dMaxDist)
dMaxDist = dDist ;
}
}
if ( dMaxDist > dLinTol)
dSagV = dMaxDist ;
}
// per lo split scelgo la direzione che è più vicina alla superficie originale nel punto di maggior distanza
// misura approssimativa della curvatura in una direzione
@@ -734,7 +815,8 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
bVert = false ;
else
bVert = ( dSagV <= dSagU) ;
pcToSplit->SetSplitDirVert( bVert) ;
bool bFirstTry = true ;
retry :
// verifico che la cella sia da splittare e che eventualmente sia abbastanza grande da poterlo fare
double dSideMinVal = 0 ;
double dLengMinVal = 0 ;
@@ -776,6 +858,11 @@ Tree::BuildTree( double dLinTol, double dSideMin, double dSideMax)
}
else if ( dSagV > dLinTol || dSagU > dLinTol) {
bSplit = bDimOk ;
if ( ! bSplit && bFirstTry) {
bFirstTry = false ;
bVert = ! bVert ;
goto retry ;
}
//if ( bSplit)
// LOG_DBG_INFO( GetEGkLogger(), " Split by SagittaUV")
}
@@ -1455,7 +1542,7 @@ Tree::GetPolygons( POLYLINEMATRIX& vvPolygons, POLYLINEMATRIX& vvPolygons3d, vec
++ nPolyInd ;
continue ;
}
else if( m_mTree[nId].m_nCollapsed != Cell::Collapsed::NO_COLLAPSE)
else if ( m_mTree[nId].m_nCollapsed != Cell::Collapsed::NO_COLLAPSE)
continue ;
else {
// vettore in cui salvo il chunk di appartenenza di ogni loop che attraversa la cella
@@ -1980,7 +2067,7 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells
nCells.push_back( nCell) ;
nEdge = -2 ;
}
if( ssize( nCells) == 1)
if ( ssize( nCells) == 1)
return nCells ;
Vector3d vtDir ;
@@ -2009,14 +2096,14 @@ Tree::FindCell( const Point3d& ptToAssign, const CurveLine& cl, INTVECTOR vCells
if ( abs(vtDir.x) < 1 - EPS_SMALL/100 && abs(vtDir.y) < 1 - EPS_SMALL/100 )
ptIntersPlus = ptIntersPlus + vtDir * EPS_SMALL ;
// altrimenti ruoto a destra
else if( ( nEdge == 4 && vtDir.x > 1 - EPS_SMALL / 100) || ( nEdge == 6 && vtDir.x < - 1 + EPS_SMALL / 100) ||
else if (( nEdge == 4 && vtDir.x > 1 - EPS_SMALL / 100) || ( nEdge == 6 && vtDir.x < - 1 + EPS_SMALL / 100) ||
( nEdge == 5 && vtDir.y > 1 - EPS_SMALL / 100) || ( nEdge == 7 && vtDir.y < - 1 + EPS_SMALL / 100)) {
Vector3d vtDirDX = vtDir ; vtDirDX.Rotate( Z_AX, -45) ;
ptIntersPlus = ptIntersPlus + vtDirDX * EPS_SMALL ;
}
// altrimenti ruoto a sinistra
else /*if( ( nEdge == 4 && vtDir.y < - 1 + EPS_SMALL / 100) || ( nEdge == 6 && vtDir.y < 1 - EPS_SMALL / 100) ||
( nEdge == 5 && vtDir.x > 1 - EPS_SMALL / 100) || ( nEdge == 7 && vtDir.x < - 1 + EPS_SMALL / 100)) // + tutti gli altri casi */ {
else /*if (( nEdge == 4 && vtDir.y < - 1 + EPS_SMALL / 100) || ( nEdge == 6 && vtDir.y < 1 - EPS_SMALL / 100) ||
( nEdge == 5 && vtDir.x > 1 - EPS_SMALL / 100) || ( nEdge == 7 && vtDir.x < - 1 + EPS_SMALL / 100)) // + tutti gli altri casi */ {
Vector3d vtDirDX = vtDir ; vtDirDX.Rotate( Z_AX, 45) ;
ptIntersPlus = ptIntersPlus + vtDirDX * EPS_SMALL ;
}
@@ -2138,7 +2225,7 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
bool bLoopInside = true ;
Point3d ptCurr ;
int nIdPolygon = - 1;
if( ! pCell->m_vnPolyId.empty())
if ( ! pCell->m_vnPolyId.empty())
nIdPolygon = pCell->m_vnPolyId[0] ;
else
return false ;
@@ -2178,9 +2265,9 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
}
// se l'intersezione e la stessa della precedente allora potrei essere entrato in un loop infinito
// se per più volte il punto di intersezione resta più o meno lo stesso allora blocco tutto
if( AreSamePointEpsilon( vptInters.back(), ptLastInters, 10 * EPS_SMALL)) {
if ( AreSamePointEpsilon( vptInters.back(), ptLastInters, 10 * EPS_SMALL)) {
++ nInfiniteLoopCount ;
if( nInfiniteLoopCount == 4) {
if ( nInfiniteLoopCount == 4) {
LOG_ERROR( GetEGkLogger(), "Error Triangulating SurfBezier: infinte while loop occured in Tree::TraceLoopLabelCell")
return false ;
}
@@ -2189,7 +2276,7 @@ Tree::TraceLoopLabelCell( const POLYLINEVECTOR& vplPolygons)
// aggiorno il puntatore alla cella
pCell = &m_mTree[nId] ;
// recupero l'indice del poligono base associato alla cella
if( ! pCell->m_vnPolyId.empty())
if ( ! pCell->m_vnPolyId.empty())
nIdPolygon = pCell->m_vnPolyId[0] ;
else
return false ;
@@ -4025,7 +4112,8 @@ Tree::OnWhichEdge( int nId, const Point3d& ptToAssign, int& nEdge) const
Point3d ptTl ( ptBL.x, ptTR.y) ;
Point3d ptBr ( ptTR.x, ptBL.y) ;
if( ptToAssign.y < ptBL.y - EPS_SMALL || ptToAssign.y > ptTR.y + EPS_SMALL || ptToAssign.x < ptBL.x - EPS_SMALL || ptToAssign.x > ptTR.x + EPS_SMALL)
if ( ptToAssign.y < ptBL.y - EPS_SMALL || ptToAssign.y > ptTR.y + EPS_SMALL ||
ptToAssign.x < ptBL.x - EPS_SMALL || ptToAssign.x > ptTR.x + EPS_SMALL)
return false ;
else if ( AreSamePointXYApprox( ptToAssign, ptTR))
nEdge = 7 ;
+26 -17
View File
@@ -23,7 +23,8 @@
#include <utility>
struct PairHashInt64 {
size_t operator()(const std::pair<int64_t, int64_t>& key) const {
size_t
operator()( const std::pair<int64_t, int64_t>& key) const {
size_t h1 = std::hash<int64_t>{}(key.first) ;
size_t h2 = std::hash<int64_t>{}(key.second) ;
return h1 ^ (h2 << 1); // Combine hashes
@@ -33,14 +34,20 @@ struct PairHashInt64 {
//----------------------------------------------------------------------------
struct Inters {
int nIn ;
PNTVECTOR vpt ;
int nOut ;
PNTVECTOR vpt ;
bool bCCW ;
int nChunk ;
bool bSortedbyStart ;
// riordino le intersezioni per lato in senso antiorario dal top
// se ho più intersezioni che entrano in un lato le riordino considerando che percorro i lati in senso antiorario a partire da ptTR
bool operator < ( Inters& b)
// nIn e nOut sono flag che indicano da quale lato ho l'ingresso e l'uscita a partire dal lato top in senso antiorario
// oltre il 3 sono le celle adiacenti in diagonale al vertice-> 4 corrisponde al ptTl e da lì in senso antiorario
// -1 se la curva è sempre dentro la cella
// riordino le intersezioni per lato in senso antiorario dal top
// se ho più intersezioni che entrano in un lato le riordino considerando che percorro i lati in senso antiorario a partire da ptTR
bool
operator < ( Inters& b)
{
// trovo in che ordine stanno i due start, tenendo conto anche della possibilità che siano vertici
INTVECTOR vEdges = { 7, 0, 4, 1, 5, 2, 6, 3} ;
@@ -75,7 +82,8 @@ struct Inters {
( bEqIn && nEdgeIn == 3 && vpt[0].y < b.vpt[0].y)) ;
}
static bool FirstEncounter( Inters& a, Inters& b)
static bool
FirstEncounter( Inters& a, Inters& b)
{
// riordino in base al lato toccato, o dall'uscita o dall'ingresso, che viene prima.
// ottengo l'ordine che avrei percorrendo il bordo da ptTR e considerando i loop che incontro, indipendentemente se li incontro nel punto di uscita o ingresso
@@ -135,18 +143,18 @@ struct Inters {
( nPos1 == 3 && a.vpt[nFirstA].y < b.vpt[nFirstB].y) ;
}
bool operator == ( Inters& b)
bool
operator == ( Inters& b)
{
return AreSamePointExact( vpt[0], b.vpt[0]) ;
}
bool operator != ( Inters& b)
bool
operator != ( Inters& b)
{
return ! AreSamePointExact( vpt[0], b.vpt[0]) ;
}
} ;
// nIn e nOut sono flag che indicano da quale lato ho l'ingresso e l'uscita a partire dal lato top in senso antiorario
// oltre il 3 sono le celle adiacenti in diagonale al vertice-> 4 corrisponde al ptTl e da lì in senso antiorario
// -1 se la curva è sempre dentro la cella
//----------------------------------------------------------------------------
class Cell
@@ -160,11 +168,12 @@ class Cell
// | |
// |_________________|
// Edge 5 ( SW) Edge 2 (Bottom) Edge 6 ( SE)
public:
enum Collapsed { TO_VERIFY = -1, // da verificare
NO_COLLAPSE = 0, // non ho coppie di lati collassati
VERT_EDGES = 1, // coppia di lati verticali(1-3) sono collassati
HORIZ_EDGES = 2} ; // coppia di lati verticali(0-2) sono collassati
public :
enum Collapsed { TO_VERIFY = -1, // da verificare
NO_COLLAPSE = 0, // non ho coppie di lati collassati
VERT_EDGES = 1, // coppia di lati verticali(1-3) sono collassati
HORIZ_EDGES = 2} ; // coppia di lati verticali(0-2) sono collassati
public :
~Cell( void) {}
@@ -336,4 +345,4 @@ class Tree
INTVECTOR m_vnParents ; // vettore delle celle ottenute dalla divisione preliminare in singole patch
ICRVCOMPOPOVECTOR m_vCCLoop2D ; // vettore che contiene le CurveCompo che rappresentano i loop di trim tenendo conto della divisione in celle
std::vector<std::pair<BIPNTVECTOR, ChainCurves>> m_vCEdge2D ; // vettore che le chain che rappresentano ciò che resta degli edge originali, tenendo conto dei trim.
} ;
} ;
+475 -205
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -1601,9 +1601,9 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
PNTVECTOR vPntTopStartBack(3) ;
PNTVECTOR vPntTopEndBack(3) ;
if ( nSub > 1) {
if( bTopIsPivot)
if ( bTopIsPivot)
vtDirTop = vtDirTip ;
if( bTipIsPivot)
if ( bTipIsPivot)
vtDirTip = vtDirTop ;
// determino in che modo collegare il cilindro iniziale con quello finale
Vector3d vtTopBaseEnd = vtDirTop - (( vtDirTop * vtLe) * vtLe) ;
@@ -1812,7 +1812,7 @@ VolZmap::Comp_5AxisMilling( int nGrid, const Point3d& ptS, const Point3d& ptE, c
}
}
if( ! bTopIsPivot) {
if ( ! bTopIsPivot) {
// superiori
if ( dSide > 0) {
PNTVECTOR vPntTop01 = cBezTopStartF1->GetAllControlPoints();