From fee6604d5ee330f07ef458960fb382ba54e7dc91 Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Tue, 7 Oct 2025 14:38:07 +0200 Subject: [PATCH 1/3] EgtGeomKernel 2.7j1 : - in CalcPocketing migliorata la gestione delle svuotature Conformal. --- CalcPocketing.cpp | 440 +++++++++++++++++++++++++++++----------------- EgtGeomKernel.rc | Bin 11710 -> 11718 bytes 2 files changed, 276 insertions(+), 164 deletions(-) diff --git a/CalcPocketing.cpp b/CalcPocketing.cpp index 539a225..a40159c 100644 --- a/CalcPocketing.cpp +++ b/CalcPocketing.cpp @@ -55,6 +55,7 @@ struct PocketParams { double dOpenMinSafe = 5. ; // estensione minima di sicurezza double dMaxOptSize = 0. ; // dimensione per ottimizzazione double dAngle = 0. ; // angolo per orientare le passate OneWay e ZigZag + double dSmooth = 5. ; // parametro di smusso per link ( raccordo ) double dLiTang = INFINITO ; // valore di LeadIn in ingresso bool bCalcUnclearedRegs = true ; // flag per calcolare o meno le regioni non svuotate bool bOptOffsets = true ; // flag per evitare Offset non necessari @@ -1015,7 +1016,7 @@ GetIndOfHypoteticalChunk( const ICRVCOMPOPOVECTOR& vCrv, const ICurveComposite* //---------------------------------------------------------------------------- static bool ExtendPath( ICurveComposite* pCompo, const ISurfFlatRegion* pSfr, const PocketParams& PockParams, - const Vector3d& vtFirstOut, bool bEndOrStart, bool& bOkExtended) + const Vector3d& vtFirstOut, bool bEndOrStart, double dExtension, bool& bOkExtended) { /* Estensione della curva pCompo con un segmento lineare. @@ -1056,7 +1057,7 @@ ExtendPath( ICurveComposite* pCompo, const ISurfFlatRegion* pSfr, const PocketPa // ruoto il versore d'uscita Vector3d vtRotOut = GetRotate( vtFirstOut, Z_AX, - vAngles[i]) ; // calcolo il punto di caduta dell'utensile - Point3d ptFall = pt + vtRotOut * ( PockParams.dRad + PockParams.dOpenMinSafe) ; + Point3d ptFall = pt + vtRotOut * dExtension ; // controllo che sia sufficientemente distante dalla superficie limite bool bInside = true ; bool bOkOut = true ; @@ -1170,29 +1171,10 @@ GetHomogeneousParts( ICurveComposite* pCrvCompo, const PocketParams& PockParams, return true ; } -//---------------------------------------------------------------------------- -static bool -GetFirstOffsCrvFromSfr( const ISurfFlatRegion* pSfr, double dOffs, ICRVCOMPOPOVECTOR& vCrvFirstOffs) -{ - // controllo dei parametri - if ( pSfr == nullptr || ! pSfr->IsValid()) - return false ; - vCrvFirstOffs.clear() ; - - // creo la regione mediante Offset - PtrOwner pSfrOffs( pSfr->CreateOffsetSurf( dOffs, ICurve::OFF_FILLET)) ; - if ( IsNull( pSfrOffs) || ! pSfrOffs->IsValid()) - return false ; - - // inserisco le curve orientante - return ( GetSfrCrvCompoLoops( pSfrOffs, vCrvFirstOffs)) ; -} - //--------------------------------------------------------------------------- static bool CreateSurfFrIncidence( const ICurveComposite* pCrv, const PocketParams& PockParams, - const Vector3d& vtTanS_, const Vector3d& vtTanE_, const double dRad, - ISurfFlatRegion* pSfrInc) + const double dRad, ISurfFlatRegion* pSfrInc) { // controllo dei parametri if ( pCrv == nullptr || ! pCrv->IsValid()) @@ -1318,11 +1300,11 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI pCrvBorder == nullptr || ! pCrvBorder->IsValid() || pCrvBorder->GetCurveCount() == 0) return false ; - // definisco la regione di incidenza + // definisco la regione di incidenza ( leggermente più grande ) PtrOwner pSfrInc( CreateSurfFlatRegion()) ; if ( IsNull( pSfrInc)) return false ; - if ( ! CreateSurfFrIncidence( pCrvBorder, PockParams, vtTanS, vtTanE, dRad + 75 * EPS_SMALL, pSfrInc)) { + if ( ! CreateSurfFrIncidence( pCrvBorder, PockParams, dRad + 75. * EPS_SMALL, pSfrInc)) { pSfrInc.Set( GetSurfFlatRegionFromFatCurve( CloneCurveComposite( pCrvBorder), dRad + 75 * EPS_SMALL, false, false)) ; if ( IsNull( pSfrInc) || ! pSfrInc->IsValid()) return false ; @@ -1347,12 +1329,12 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI double dArea ; Plane3d plCheck ; if ( ! pCrvCompo->GetArea( plCheck, dArea)) return false ; - bIsIsland = AreSameVectorEpsilon( plCheck.GetVersN(), - Z_AX, 10 * EPS_SMALL) ; + bIsIsland = AreSameVectorEpsilon( plCheck.GetVersN(), - Z_AX, 10. * EPS_SMALL) ; // scorro il vettore creato... - for ( int c = 0 ; c < int( vCrvToCheck.size()) ; ++ c) { + for ( int i = 0 ; i < int( vCrvToCheck.size()) ; ++ i) { // 1) recupero la curva corrente - PtrOwner pCrvCurr( vCrvToCheck[c]->Clone()) ; + PtrOwner pCrvCurr( vCrvToCheck[i]->Clone()) ; if ( IsNull( pCrvCurr) || ! pCrvCurr->IsValid()) return false ; // 2) ricavo i tratti con proprietà uniformi ( Aperti/Chiusi ) @@ -1360,12 +1342,12 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI if ( ! GetHomogeneousParts( pCrvCurr, PockParams, vpCrvs)) return false ; // 3) considero solo i tratti chiusi - for ( int cl = 0 ; cl < int( vpCrvs.size()) ; ++ cl) { - if ( vpCrvs[cl]->GetTempProp() == TEMP_PROP_OPEN_EDGE) + for ( int nU = 0 ; nU < int( vpCrvs.size()) ; ++ nU) { + if ( vpCrvs[nU]->GetTempProp() == TEMP_PROP_OPEN_EDGE) continue ; // 4) effettuo l'Offset della curva di metà dDiamJ OffsetCurve OffsCrv ; - if ( ! OffsCrv.Make( vpCrvs[cl], - dDiamJ * 0.5 - 20 * EPS_SMALL, PockParams.nOffsType)) + if ( ! OffsCrv.Make( vpCrvs[nU], - dDiamJ / 2. - 20. * EPS_SMALL, PockParams.nOffsType)) return false ; // 5) scorro tutte le curve di Offset che si sono formate, prendendo sempre la più lunga tra le rimanenti PtrOwner pOffLongestCrv( OffsCrv.GetLongerCurve()) ; @@ -1373,7 +1355,7 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI // 6) creo la regione di incidenza di tale curva ( "Curva a fagiolo") bool bSquareEnds = ( PockParams.nOffsType == ICurve::OFF_CHAMFER) ; bool bSquareMids = ( PockParams.nOffsType == ICurve::OFF_CHAMFER) ; - PtrOwner pSfrBean( GetSurfFlatRegionFromFatCurve( Release( pOffLongestCrv), dDiamJ * 0.5, bSquareEnds, bSquareMids)) ; + PtrOwner pSfrBean( GetSurfFlatRegionFromFatCurve( Release( pOffLongestCrv), dDiamJ / 2., bSquareEnds, bSquareMids)) ; if ( IsNull( pSfrBean) || ! pSfrBean->IsValid()) return false ; // inverto se necessario @@ -1381,7 +1363,8 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI pSfrBean->Invert() ; // 7) se la "Regione a fagiolo" non influenza la regione di incidenza, la transcuro bool bDiscard = false ; - if ( ! bIsIsland) { // se tratto un loop esterno + if ( ! bIsIsland) { + // se tratto un loop esterno PtrOwner pSfrBean_test( CloneSurfFlatRegion( pSfrBean)) ; if ( IsNull( pSfrBean_test) || ! pSfrBean_test->IsValid()) return false ; @@ -1390,7 +1373,8 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI ! pSfrBean_test->IsValid() || pSfrBean_test->GetChunkCount() == 0) ; } - else if ( bIsAllOpen && bIsIsland) { // se isola aperta + else if ( bIsAllOpen && bIsIsland) { + // se isola aperta for ( int cI = 0 ; cI < pSfrInc->GetChunkCount() && ! bDiscard ; ++ cI) { for ( int cB = 0 ; cB < pSfrBean->GetChunkCount() && ! bDiscard ; ++ cB) { if ( pSfrInc->GetChunkSimpleClassification( cI, *pSfrBean, cB) == REGC_IN1) { @@ -1424,8 +1408,7 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI PtrOwner pSfrLimit( PockParams.SfrLimit.Clone()) ; if ( IsNull( pSfrLimit) || ! pSfrLimit->IsValid()) return false ; - // piccolo Offset per sicurezza - pSfrLimit->Offset( 50 * EPS_SMALL, ICurve::OFF_FILLET) ; + pSfrLimit->Offset( 50. * EPS_SMALL, ICurve::OFF_FILLET) ; pSfrInc->Subtract( *pSfrLimit) ; // rimuovo la regione limite // può capitare che la regione Limite mi crei più Chunk sulla pSfrInc @@ -1574,7 +1557,6 @@ AdjustOpenEdge( const ICurveComposite* pCrvCompo, const ICRVCOMPOPOVECTOR& vCrvI } return true ; - } //---------------------------------------------------------------------------- @@ -1601,9 +1583,14 @@ AdjustContourWithOpenEdges( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vCrvI if ( PockParams.bAllowZigZagOneWayBorders && ( PockParams.nType == POCKET_ZIGZAG || PockParams.nType == POCKET_ONEWAY)) dRad += PockParams.dOffsExtra ; - // se lavorazione a ZigZag con smusso, esco di Step/2 per pulire gli aperti + // se lavorazione a ZigZag con smusso if ( PockParams.nType == POCKET_ZIGZAG && PockParams.bSmooth) - dRad += max( PockParams.dSideStep / 2, PockParams.dRad / 8) ; + dRad += PockParams.bSmooth ; + // se lavorazione Conformal + if ( PockParams.nType == POCKET_CONFORMAL_ZIGZAG || PockParams.nType == POCKET_CONFORMAL_ONEWAY) { + if ( PockParams.dRad - PockParams.dSideStep > 0) + dRad -= PockParams.dSideStep ; + } // salvo il raggio trovato PockParams.dOpenEdgeRad = dRad ; @@ -1639,25 +1626,21 @@ AdjustContourWithOpenEdges( ICurveComposite* pCrvCompo, ICRVCOMPOPOVECTOR& vCrvI // controllo che sia almeno lungo quanto il diametro utensile double dLen = 0. ; vpCrvs[i]->GetLength( dLen) ; - if ( dLen > PockParams.dRad * 2 - 5 * EPS_SMALL) { - // ricavo la tangenze dei lati chiusi agli estremi di questa curva - Vector3d vtTanS = V_INVALID ; - Vector3d vtTanE = V_INVALID ; - if ( i != 0) { - if ( ! vpCrvs[i-1]->GetEndDir( vtTanS) || // tangente finale del chiuso precedente - ! vpCrvs[( i + 1) % int( vpCrvs.size())]->GetStartDir( vtTanE)) // tangente iniziale del chiuso successivo... - return false ; - vtTanE.Invert() ; // invertita - } - if ( ! AdjustOpenEdge( pCrvCompo, vCrvIsl, dParS, dParE, vtTanS, vtTanE, dRad, dDiamJ, PockParams, vpCrvs[i])) + // ricavo la tangenze dei lati chiusi agli estremi di questa curva + Vector3d vtTanS = V_INVALID ; + Vector3d vtTanE = V_INVALID ; + if ( i != 0) { + if ( ! vpCrvs[i-1]->GetEndDir( vtTanS) || // tangente finale del chiuso precedente + ! vpCrvs[( i + 1) % int( vpCrvs.size())]->GetStartDir( vtTanE)) // tangente iniziale del chiuso successivo... return false ; + vtTanE.Invert() ; // invertita } - else - nCurrTmpProp = TEMP_PROP_CLOSE_EDGE ; + if ( ! AdjustOpenEdge( pCrvCompo, vCrvIsl, dParS, dParE, vtTanS, vtTanE, dRad, dDiamJ, PockParams, vpCrvs[i])) + return false ; } // assegno le proprietà di lato Aperto/Chiuso per la curva corrente for ( int u = 0 ; u < vpCrvs[i]->GetCurveCount() ; ++ u) - vpCrvs[i]->SetCurveTempProp( u, nCurrTmpProp, 0) ; + vpCrvs[i]->SetCurveTempProp( u, nCurrTmpProp, TEMP_PROP_CLOSE_EDGE) ; // aggiungo la curva ricavata ( se chiusa -> la copio, se aperta -> copio l'estesa) if ( ! pCrvCompo_final->AddCurve( vpCrvs[i]->Clone())) { // per sicurezza, se gli estremi non coincidono, creo un piccolo raccordo lineare @@ -1840,14 +1823,14 @@ AdvanceExtendCurves( ICRVCOMPOPOVECTOR& vCrvCompo, const ISurfFlatRegion* pSfr, Vector3d vtStart ; vCrvCompo[i]->GetStartDir( vtStart) ; vtStart.Invert() ; bool bIsStartExtended = false ; - if ( ! ExtendPath( vCrvCompo[i], pSfr, PockParams, vtStart, false, bIsStartExtended)) + if ( ! ExtendPath( vCrvCompo[i], pSfr, PockParams, vtStart, false, PockParams.dRad + PockParams.dOpenMinSafe, bIsStartExtended)) return false ; // se aperta, controllo la fine if ( ! bIsClosed) { // ricavo vettore tangente finale e provo ad estendere Vector3d vtEnd ; vCrvCompo[i]->GetEndDir( vtEnd) ; bool bIsEndExtended = false ; - if ( ! ExtendPath( vCrvCompo[i], pSfr, PockParams, vtEnd, true, bIsEndExtended)) + if ( ! ExtendPath( vCrvCompo[i], pSfr, PockParams, vtEnd, true, PockParams.dRad + PockParams.dOpenMinSafe, bIsEndExtended)) return false ; if ( bIsEndExtended) break ; @@ -2155,7 +2138,6 @@ GetSinglePocketingCurves( ISurfFlatRegion* pSfr, PocketParams& PockParams, return true ; } - //---------------------------------------------------------------------------- static bool ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams) @@ -2295,7 +2277,6 @@ ModifySurfByOpenEdges( ISurfFlatRegion* pSfr, PocketParams& PockParams) if ( ! pSrfFinal->IsValid()) return false ; - // chiudo le isole che risultano ambigue ( quindi non omgenee) for ( int nC = 0 ; nC < pSrfFinal->GetChunkCount() ; ++ nC) { for ( int nL = 1 ; nL < pSrfFinal->GetLoopCount( nC) ; ++ nL) { @@ -3662,7 +3643,7 @@ GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams& pCrvRes->GetStartDir( vtMidOut) ; vtMidOut.Rotate( pSfrChunk->GetNormVersor(), PockParam.bInvert ? ANG_RIGHT : - ANG_RIGHT) ; bool bIsExtended ; - ExtendPath( pCrvRes, pSfrChunk, PockParam, vtMidOut, false, bIsExtended) ; + ExtendPath( pCrvRes, pSfrChunk, PockParam, vtMidOut, false, PockParam.dRad + PockParam.dOpenMinSafe, bIsExtended) ; } // se invece lavorazione in SpiralOut, inverto il percorso else if ( PockParam.nType == POCKET_SPIRALOUT) @@ -3694,11 +3675,11 @@ GetSpiralOptimizedCurves( const ISurfFlatRegion* pSfrChunk, const PocketParams& Vector3d vtRef ; pCrvRes->GetStartDir( vtRef) ; vtRef.Invert() ; bool bIsStartExtended = false ; - if ( ! ExtendPath( pCrvRes, pSfrChunk, PockParam, vtRef, false, bIsStartExtended)) + if ( ! ExtendPath( pCrvRes, pSfrChunk, PockParam, vtRef, false, PockParam.dRad + PockParam.dOpenMinSafe, bIsStartExtended)) return false ; pCrvRes->GetEndDir( vtRef) ; bool bIsEndExtended = false ; - if ( ! ExtendPath( pCrvRes, pSfrChunk, PockParam, vtRef, true, bIsEndExtended)) + if ( ! ExtendPath( pCrvRes, pSfrChunk, PockParam, vtRef, true, PockParam.dRad + PockParam.dOpenMinSafe, bIsEndExtended)) return false ; if ( bIsEndExtended && ! bIsStartExtended) pCrvRes->Invert() ; @@ -4943,7 +4924,7 @@ CalcBoundedSmoothedLink( const Point3d& ptStart, const Vector3d& vtStart, const return false ; } // La curva necessita di un ulteriore smusso, in quanto tagliata su un bordo - ModifyCurveToSmoothed( pCompoTest, PockParams, PockParams.dRad / 4., PockParams.dRad / 4., false) ; + ModifyCurveToSmoothed( pCompoTest, PockParams, PockParams.dSmooth, PockParams.dSmooth, false) ; // nel caso speciale della circonferenza, devo impostare il punto iniziale if ( dParMeet < EPS_ZERO) { if ( pCompoTest->IsClosed()) { // sempre... @@ -6064,7 +6045,7 @@ CalcSpiral( const ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, co } // smusso le curve di offset ( ad eccezione di quelle di primo Offset) - double dSmoothPar = PockParams.dRad / 8. ; + double dSmoothPar = PockParams.dSmooth / SQRT2 ; for ( int i = 0 ; i < int( vOffs.size()) ; ++ i) { if ( i >= nCrvFirstOffs) ModifyCurveToSmoothed( vOffs[i], PockParams, dSmoothPar, dSmoothPar, false) ; @@ -6664,7 +6645,7 @@ AddSpiralIn( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, bool bIsExtended = false ; if ( bSomeOpen) - ExtendPath( pMCrv, pSfrOrig, PockParams, vtMidOut, false, bIsExtended) ; + ExtendPath( pMCrv, pSfrOrig, PockParams, vtMidOut, false, PockParams.dRad + PockParams.dOpenMinSafe, bIsExtended) ; // inserisco le curve nel vettore vCrvCompoRes.emplace_back( Release( pMCrv)) ; @@ -6946,10 +6927,10 @@ AddZigZag( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, PocketPar Vector3d vtRef ; vpCrvs[nU]->GetStartDir( vtRef) ; vtRef.Invert() ; bool bIsExtended = false ; - if ( ! ExtendPath( vpCrvs[nU], pSfrOrig, PockParams, vtRef, false,bIsExtended)) + if ( ! ExtendPath( vpCrvs[nU], pSfrOrig, PockParams, vtRef, false, PockParams.dRad + PockParams.dOpenMinSafe, bIsExtended)) return false ; vpCrvs[nU]->GetEndDir( vtRef) ; - if ( ! ExtendPath( vpCrvs[nU], pSfrOrig, PockParams, vtRef, true, bIsExtended)) + if ( ! ExtendPath( vpCrvs[nU], pSfrOrig, PockParams, vtRef, true, PockParams.dRad + PockParams.dOpenMinSafe, bIsExtended)) return false ; } } @@ -7147,10 +7128,10 @@ AddOneWay( ISurfFlatRegion* pSrfPock, const ISurfFlatRegion* pSfrOrig, PocketPar Vector3d vtRef ; pCrvSegCompo->GetStartDir( vtRef) ; vtRef.Invert() ; bool bIsExtended = false ; - if ( ! ExtendPath( pCrvSegCompo, pSfrOrig, PockParams, vtRef, false,bIsExtended)) + if ( ! ExtendPath( pCrvSegCompo, pSfrOrig, PockParams, vtRef, false, PockParams.dRad + PockParams.dOpenMinSafe, bIsExtended)) return false ; pCrvSegCompo->GetEndDir( vtRef) ; - if ( ! ExtendPath( pCrvSegCompo, pSfrOrig, PockParams, vtRef, true, bIsExtended)) + if ( ! ExtendPath( pCrvSegCompo, pSfrOrig, PockParams, vtRef, true, PockParams.dRad + PockParams.dOpenMinSafe, bIsExtended)) return false ; } vCrvCompoRes.emplace_back( Release( pCrvSegCompo)) ; @@ -7412,7 +7393,7 @@ CalcConformalLink( ICurveComposite* pCrvOffs0, ICurveComposite* pCrvOffs1, Pocke if ( PockParams.nType == POCKET_CONFORMAL_ZIGZAG) { // effettuo smusso del tratto lineare SmoothLinkByOffs( pCrvOffs0, pCrvOffs1, pCrvLink, PockParams, bFirstIterOffs0, bFirstIterOffs1, - PockParams.dRad / 5., TOL) ; + PockParams.dSmooth, TOL) ; // per sicurezza aggiorno i nuovi punti e i nuovi parametri double dUNewE ; Point3d ptStartNext ; @@ -7953,21 +7934,37 @@ ExtendConformalOffsAndSetFeed( const ISurfFlatRegion* pSfrPock, const ISurfFlatR return false ; if ( vCrvOffs.empty()) return true ; - /* - dalla superificie estesa presso i lati aperti, effettuo un Offset interno pari alla somma del - raggio utensile e dell'offset radiale. La ricerca delle zone non svuotate avviene all'interno - di questa regione - */ - ICRVCOMPOPOVECTOR vCrvFirstOffs ; - if ( ! GetFirstOffsCrvFromSfr( pSfrPock, - PockParams.dRad - PockParams.dRadialOffset, vCrvFirstOffs)) + + // definisco la regione di ricerca delle aree non svuotate come la regione originale + PtrOwner pSfrBorder( CloneSurfFlatRegion( pSfrPock)) ; + if ( IsNull( pSfrBorder) || ! pSfrBorder->IsValid()) + return false ; + + // dalla superficie originale, rimuovo le parti definite dai lati chiusi + double dOffs = PockParams.dRad + PockParams.dRadialOffset - 2. * EPS_SMALL ; + ICRVCOMPOPOVECTOR vpCrvs ; + for ( int nC = 0 ; nC < pSfrPock->GetChunkCount() ; ++ nC) { + for ( int nL = 0 ; nL < pSfrPock->GetLoopCount( nC) ; ++ nL) { + PtrOwner pCompoLoop( ConvertCurveToComposite( pSfrPock->GetLoop( nC, nL))) ; + if ( IsNull( pCompoLoop) || ! pCompoLoop->IsValid()) + return false ; + PtrOwner pSfrToDiscard( GetSurfFlatRegionFromFatCurve( pCompoLoop->Clone(), dOffs, false, false)) ; + if ( IsNull( pSfrToDiscard) || ! pSfrToDiscard->IsValid()) + return false ; + if ( ! pSfrBorder->Subtract( *pSfrToDiscard)) + return false ; + } + } + ICRVCOMPOPOVECTOR vCrvBorder ; + if ( ! GetSfrCrvCompoLoops( pSfrBorder, vCrvBorder)) return false ; // determino eventuale regioni con parti non svuotate e imposto la Feed alle curve PtrOwner pSfrUncleared( CreateSurfFlatRegion()) ; if ( IsNull( pSfrUncleared)) return false ; - if ( GetUnclearedRegionAndSetFeed( vCrvFirstOffs, vCrvOffs, vCrvLinks, pSfrOrig, PockParams, pSfrUncleared)) { + if ( GetUnclearedRegionAndSetFeed( vCrvBorder, vCrvOffs, vCrvLinks, pSfrOrig, PockParams, pSfrUncleared)) { // estendo i percorsi di Offset se richiesto - if ( ! RemoveUnclearedRegions( pSfrUncleared, vCrvOffs, vCrvFirstOffs, PockParams)) + if ( ! RemoveUnclearedRegions( pSfrUncleared, vCrvOffs, vCrvBorder, PockParams)) return false ; } @@ -8058,14 +8055,24 @@ AddLeadInLeadOutToCurveConformalPaths( const ISurfFlatRegion* pSfrOrig, const IS } // estendo il percorso sul tratto iniziale e finale ( se ammissibile) - Vector3d vtTan ; vCrvPaths[i]->GetStartDir( vtTan) ; - vtTan.Invert() ; - bool bOkExtension ; - if ( ! ExtendPath( vCrvPaths[i], pSfrOrig, PockParams, vtTan, false, bOkExtension)) - return false ; - vCrvPaths[i]->GetEndDir( vtTan) ; - if ( ! ExtendPath( vCrvPaths[i], pSfrOrig, PockParams, vtTan, true, bOkExtension)) - return false ; + Vector3d vtTanS, vtTanE ; + vCrvPaths[i]->GetStartDir( vtTanS) ; vtTanS.Invert() ; + vCrvPaths[i]->GetEndDir( vtTanE) ; + const int MAXTRY = 8 ; + bool bOkStartExtension = false, bOkEndExtension = false ; + for ( int j = 0 ; j <= MAXTRY ; ++ j) { + if ( bOkStartExtension && bOkEndExtension) + break ; + double dDist = PockParams.dOpenMinSafe + j * ( PockParams.dRad / ( 1. * MAXTRY)) ; + if ( ! bOkStartExtension) { + if ( ! ExtendPath( vCrvPaths[i], pSfrOrig, PockParams, vtTanS, false, dDist, bOkStartExtension)) + return false ; + } + if ( ! bOkEndExtension) { + if ( ! ExtendPath( vCrvPaths[i], pSfrOrig, PockParams, vtTanE, true, dDist, bOkEndExtension)) + return false ; + } + } } return true ; @@ -8336,7 +8343,7 @@ ExtendGuideByIteration( ICurveComposite* pCompoTempGuide, const ICurveComposite* pCompoPerimeter == nullptr || ! pCompoPerimeter->IsValid()) return false ; - const double EXTENSION_VAL = 1000. ; + const double EXTENSION_VAL = 5000. ; // ricavo il punto finale della guida Point3d ptEndGuide ; pCompoTempGuide->GetEndPoint( ptEndGuide) ; @@ -8365,7 +8372,9 @@ ExtendGuideByIteration( ICurveComposite* pCompoTempGuide, const ICurveComposite* Point3d ptPoly ; PL.GetFirstPoint( ptPoly) ; while ( PL.GetNextPoint( ptPoly)) { - if ( ! pSeg->Set( ptEndGuide, ptEndGuide + ( ptPoly - ptEndGuide) * EXTENSION_VAL)) + Vector3d vtDir = ptPoly - ptEndGuide ; + vtDir.Normalize() ; + if ( ! pSeg->Set( ptEndGuide, ptEndGuide + vtDir * EXTENSION_VAL)) return false ; // calcolo l'intersezione tra questo segmento e la curva di perimetro aperta IntersCurveCurve ICC( *pSeg, *pCompoPerimeter) ; @@ -8582,7 +8591,6 @@ GetConformalOffsets( const ISurfFlatRegion* pSfrChunk, const ISurfFlatRegion* pS ICRVCOMPOPOVECTOR vpCrvs ; PtrOwner pCrvExtLoop( ConvertCurveToComposite( pSfrChunk->GetLoop( 0, 0))) ; if ( IsNull( pCrvExtLoop) || ! pCrvExtLoop->IsValid() || - ! AdjustCloseEdgesForConformalGuide( pCrvExtLoop, PockParam) || ! IsCompoMadeBy2DifferentHomogeneousParts( pCrvExtLoop, PockParam, bOk, vpCrvs)) return false ; if ( ! bOk) @@ -8747,10 +8755,94 @@ GetConformalOffsets( const ISurfFlatRegion* pSfrChunk, const ISurfFlatRegion* pS } // smusso le curve di Offset ( ad eccezione di quelle generate alla prima iterazione) - double dSmoothPar = PockParam.dRad / 8. ; for ( int i = 1 ; i < int( vCrvOffs.size()) ; ++ i) { for ( int j = 0 ; j < int( vCrvOffs[i].size()) ; ++ j) - ModifyCurveToSmoothed( vCrvOffs[i][j], PockParam, dSmoothPar, dSmoothPar, false) ; + ModifyCurveToSmoothed( vCrvOffs[i][j], PockParam, PockParam.dSmooth, PockParam.dSmooth, false) ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +CalcSpiralPocketing( const ISurfFlatRegion* pSfr, int nType, const PocketParams& PockParams, + ICRVCOMPOPOVECTOR& vCrvCompoRes) +{ + // verifica validità della superficie + if ( pSfr == nullptr || ! pSfr->IsValid()) + return false ; + // il tipo può essere solo SpiralIn o SpiralOut + if ( nType != POCKET_SPIRALIN && nType != POCKET_SPIRALOUT) + return false ; + // 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)) ; +} + +//---------------------------------------------------------------------------- +static bool +GetOrigChunkForConformal( const ISurfFlatRegion* pSfrChunk, const ISurfFlatRegion* pSfrOrig, + set& setChunks) +{ + // NB. funzione migliorabile... potrei calcolare tutto all'inizio senza ripetere le intersezioni + // controllo validità delle regioni + if ( pSfrChunk == nullptr || ! pSfrChunk->IsValid() || + pSfrOrig == nullptr || ! pSfrOrig->IsValid()) + return false ; + + // se la superficie originale ha un solo Chunk allora è lui stesso + if ( pSfrOrig->GetChunkCount() == 1) { + setChunks.insert( 0) ; + return true ; + } + + // essendo la pSfrChunk estesa, cerco quale chunk di pSfrOrig ha una intersezione valida + for ( int nC = 0 ; nC < pSfrOrig->GetChunkCount() ; ++ nC) { + // se il Chunk è già stato analizzato in precedenza, passo al successivo + if ( setChunks.find( nC) != setChunks.end()) + continue ; + // recupero il Chunk corrente + PtrOwner pSfrChunkOrig( pSfrOrig->CloneChunk( nC)) ; + if ( IsNull( pSfrChunkOrig) || ! pSfrChunkOrig->IsValid()) + return false ; + // controllo se esiste l'intersezione + if ( pSfrChunkOrig->Intersect( *pSfrChunk) && pSfrChunkOrig->IsValid()) + setChunks.insert( nC) ; + } + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +CreateSurfFromOtherChunks( ISurfFlatRegion* pSfr, const ISurfFlatRegion* pSfrOther, const set& setChunks) +{ + // controllo della regione + if ( pSfr == nullptr || + pSfrOther == nullptr || ! pSfrOther->IsValid()) + return false ; + + // se non ho indici di Chunk non faccio nulla + if ( setChunks.empty()) + return true ; + + // scorro gli indici dei Chunks + for ( auto it = setChunks.begin() ; it != setChunks.end() ; ++ it) { + // recupero l'indice del Chunk + int nChunk = *it ; + // recupero il Chunk come regione piana + PtrOwner pSfrChunk( pSfrOther->CloneChunk( nChunk)) ; + if ( ! IsNull( pSfrChunk) && pSfrChunk->IsValid()) { + if ( ! pSfr->IsValid()) + pSfr->CopyFrom( pSfrChunk) ; + else if ( ! pSfr->Add( *pSfrChunk)) + return false ; + } } return true ; @@ -8767,99 +8859,119 @@ AddConformal( ISurfFlatRegion* pSfrPock, const ISurfFlatRegion* pSfrOrig, return true ; // se superifice tutta aperta, lavoro in SPIRAL_IN - if ( PockParams.bAllOpen) { - PockParams.nType = POCKET_SPIRALIN ; - return ( AddSpiralIn( pSfrPock, pSfrOrig, PockParams, vCrvCompoRes)) ; - } + if ( PockParams.bAllOpen) + return ( CalcSpiralPocketing( pSfrOrig, POCKET_SPIRALIN, PockParams, vCrvCompoRes)) ; // se superficie tutta chiusa, lavoro in SPIRAL_OUT - if ( PockParams.bAllClosed) { - PockParams.nType = POCKET_SPIRALOUT ; - return ( AddSpiralOut( pSfrPock, pSfrOrig, PockParams, vCrvCompoRes)) ; - } + if ( PockParams.bAllClosed) + return ( CalcSpiralPocketing( pSfrOrig, POCKET_SPIRALOUT, PockParams, vCrvCompoRes)) ; + + // definisco eventuali regioni da lavorare in SpiralIn e SpiralOut + PtrOwner pSfrSpiralIn( CreateSurfFlatRegion()) ; + PtrOwner pSfrSpiralOut( CreateSurfFlatRegion()) ; + if ( IsNull( pSfrSpiralIn) || IsNull( pSfrSpiralOut)) + return false ; + // NB. La supercicie pSfrPock è estesa presso i lati aperti, quindi il suo numero di Chunk potrebbe + // essere differente dal numero di Chunk della superficie originale di svuotatura. Tengo un insieme di + // di indici dei Chunk che devono essere lavorati in SpiralIn e in SpiralOut + set setIndChunkSpiralIn ; + set setIndChunkSpiralOut ; // scorro i chunk della superficie da lavorare for ( int nC = 0 ; nC < pSfrPock->GetChunkCount() ; ++ nC) { + // controllo se il Chunk ha tutte proprietà omogenee tra loro bool bClose, bOpen ; if ( ! IsChunkAllHomogeneous( pSfrPock, nC, bClose, bOpen)) return false ; + // recupero il Chunk come regione piana PtrOwner pSfrChunk( pSfrPock->CloneChunk( nC)) ; if ( IsNull( pSfrChunk) || ! pSfrChunk->IsValid()) return false ; - // se Chunk tutto aperto, lo lavoro in SPIRAL_IN + + // --- se Chunk tutto aperto, aggiorno i Chunk della superficie originale da lavorare in SpiralIn if ( bOpen) { - int nType = PockParams.nType ; - PockParams.nType = POCKET_SPIRALIN ; - if ( ! AddSpiralIn( pSfrChunk, pSfrOrig, PockParams, vCrvCompoRes)) + if ( ! GetOrigChunkForConformal( pSfrChunk, pSfrOrig, setIndChunkSpiralIn)) return false ; - PockParams.nType = nType ; + continue ; } - // se Chunk tutto chiuso, lo lavoro in SPIRAL_OUT + // --- se Chunk tutto chiuso, lo lavoro in SPIRAL_OUT else if ( bClose) { - int nType = PockParams.nType ; - PockParams.nType = POCKET_SPIRALOUT ; - if ( ! AddSpiralOut( pSfrChunk, pSfrOrig, PockParams, vCrvCompoRes)) - return false ; - PockParams.nType = nType ; + if ( ! GetOrigChunkForConformal( pSfrChunk, pSfrOrig, setIndChunkSpiralOut)) + continue ; } - // se Chunk non omogeneo - else { - // ricavo gli Offset ( se possibili) dei tratti chiusi del Chunk - VICRVCOMPOPOVECTOR vvCrvOffs ; - if ( ! GetConformalOffsets( pSfrChunk, pSfrChunk, pSfrOrig, PockParams, vvCrvOffs)) + // --- se chunk non omogoneo, ricavo gli Offset ( se possibili) dei tratti chiusi del Chunk + VICRVCOMPOPOVECTOR vvCrvOffs ; + if ( ! GetConformalOffsets( pSfrChunk, pSfrChunk, pSfrOrig, PockParams, vvCrvOffs)) + return false ; + + // se non ottengo Curve di Offset, lavoro in SpiralIn ( il Chunk ha dei lati aperti) + if ( vvCrvOffs.empty()) { + if ( ! GetOrigChunkForConformal( pSfrChunk, pSfrOrig, setIndChunkSpiralIn)) return false ; - // se non ottengo Curve di Offset, lavoro in SpiralIn ( il Chunk ha dei lati aperti) - if ( vvCrvOffs.empty()) { - int nType = PockParams.nType ; - PockParams.nType = POCKET_SPIRALIN ; - PtrOwner pSfrChunk_cl( CloneSurfFlatRegion( pSfrChunk)) ; - if ( IsNull( pSfrChunk_cl) || ! pSfrChunk_cl->IsValid() || - ! AddSpiralIn( pSfrChunk_cl, pSfrOrig, PockParams, vCrvCompoRes)) - return false ; - PockParams.nType = nType ; - } - else { - // definisco vettore degli Offset e dei Link - ICRVCOMPOPOVECTOR vCrvOffs ; - ICURVEPOVECTOR vCrvLink ; - // ordino le curve di Offset e raccordo - if ( ! CalcConformalOffsAndLinks( vvCrvOffs, pSfrChunk, pSfrPock, PockParams, vCrvOffs, vCrvLink)) { - // se calcolare i raccordi risulta troppo ambiguo o complesso, ritorno a SpiralIn - int nType = PockParams.nType ; - PockParams.nType = POCKET_SPIRALIN ; - PtrOwner pSfrChunk_cl( CloneSurfFlatRegion( pSfrChunk)) ; - if ( IsNull( pSfrChunk_cl) || ! pSfrChunk_cl->IsValid() || - ! AddSpiralIn( pSfrChunk_cl, pSfrOrig, PockParams, vCrvCompoRes)) - return false ; - PockParams.nType = nType ; - continue ; - } - // flag per controllo - bool bOk = true ; - // estendo i percorsi per eventuali regioni non svuotate e calcolo le Feed - bOk = bOk && ExtendConformalOffsAndSetFeed( pSfrPock, pSfrOrig, PockParams, vCrvOffs, vCrvLink) ; - // concateno Offset e Links - ICRVCOMPOPOVECTOR vCrvPaths ; - bOk = bOk && ChainConformalOffsWithLinks( vCrvOffs, vCrvLink, vCrvPaths) ; - // estendo per lati aperti ed ordino i percorsi trovati - bOk = bOk && OrderAndExtendConformalPaths( vCrvPaths, pSfrChunk, pSfrOrig, PockParams) ; - if ( ! bOk) { - // se qualche passaggio restituisce errore, provo in SpiralIn - int nType = PockParams.nType ; - PockParams.nType = POCKET_SPIRALIN ; - PtrOwner pSfrChunk_cl( CloneSurfFlatRegion( pSfrChunk)) ; - if ( IsNull( pSfrChunk_cl) || ! pSfrChunk_cl->IsValid() || - ! AddSpiralIn( pSfrChunk_cl, pSfrOrig, PockParams, vCrvCompoRes)) - return false ; - PockParams.nType = nType ; - } - else { - // aggiungo i percorsi ricavati - for ( int i = 0 ; i < int( vCrvPaths.size()) ; ++ i) - vCrvCompoRes.emplace_back( Release( vCrvPaths[i])) ; - } - } + continue ; + } + + // definisco i vettori ordinati degli Offset e dei Link + ICRVCOMPOPOVECTOR vCrvOffs ; + ICURVEPOVECTOR vCrvLink ; + if ( ! CalcConformalOffsAndLinks( vvCrvOffs, pSfrChunk, pSfrPock, PockParams, vCrvOffs, vCrvLink)) { + if ( ! GetOrigChunkForConformal( pSfrChunk, pSfrOrig, setIndChunkSpiralIn)) + return false ; + continue ; + } + + // flag per controllo + bool bOk = true ; + // estendo i percorsi per eventuali regioni non svuotate e calcolo le Feed + bOk = bOk && ExtendConformalOffsAndSetFeed( pSfrPock, pSfrOrig, PockParams, vCrvOffs, vCrvLink) ; + // concateno Offset e Links + ICRVCOMPOPOVECTOR vCrvPaths ; + bOk = bOk && ChainConformalOffsWithLinks( vCrvOffs, vCrvLink, vCrvPaths) ; + // estendo per lati aperti ed ordino i percorsi trovati + bOk = bOk && OrderAndExtendConformalPaths( vCrvPaths, pSfrChunk, pSfrOrig, PockParams) ; + + // se qualche passaggio restituisce errore, provo in SpiralIn + if ( ! bOk) { + if ( ! GetOrigChunkForConformal( pSfrChunk, pSfrOrig, setIndChunkSpiralIn)) + return false ; + continue ; + } + // altrimenti aggiungo i percorsi ricavati + for ( int i = 0 ; i < int( vCrvPaths.size()) ; ++ i) + vCrvCompoRes.emplace_back( Release( vCrvPaths[i])) ; + } + + // se ho superfici da lavorare in SpiralIn, aggiungo le curve + if ( ! setIndChunkSpiralIn.empty()) { + // costruisco la regione di SpiralIn + PtrOwner pSfrSpiralIn( CreateSurfFlatRegion()) ; + if ( IsNull( pSfrSpiralIn) || + ! CreateSurfFromOtherChunks( pSfrSpiralIn, pSfrOrig, setIndChunkSpiralIn)) + return false ; + // recupero le curve di Pocketing SpiralIn + ICRVCOMPOPOVECTOR vCrvSpiralIn ; + if ( ! CalcSpiralPocketing( pSfrSpiralIn, POCKET_SPIRALIN, PockParams, vCrvSpiralIn)) + return false ; + for ( int i = 0 ; i < int( vCrvSpiralIn.size()) ; ++ i) { + if ( vCrvSpiralIn[i] != nullptr && vCrvSpiralIn[i]->IsValid()) + vCrvCompoRes.emplace_back( Release( vCrvSpiralIn[i])) ; + } + } + // se ho superfici da lavorare in SpiralOut, aggiungo le curve + if ( ! setIndChunkSpiralOut.empty()) { + // costruisco la regione di SpiralOut + PtrOwner pSfrSpiralOut( CreateSurfFlatRegion()) ; + if ( IsNull( pSfrSpiralIn) || + ! CreateSurfFromOtherChunks( pSfrSpiralOut, pSfrOrig, setIndChunkSpiralOut)) + return false ; + // recupero le curve di Pocketing SpiralOut + ICRVCOMPOPOVECTOR vCrvSpiralOut ; + if ( ! CalcSpiralPocketing( pSfrSpiralOut, POCKET_SPIRALOUT, PockParams, vCrvSpiralOut)) + return false ; + for ( int i = 0 ; i < int( vCrvSpiralOut.size()) ; ++ i) { + if ( vCrvSpiralOut[i] != nullptr && vCrvSpiralOut[i]->IsValid()) + vCrvCompoRes.emplace_back( Release( vCrvSpiralOut[i])) ; } } diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index 9e3075700997cb4d54ba6737a2c9b322741742db..658e2a7eb6badcd83a506195e011f1777d427fe8 100644 GIT binary patch delta 113 zcmdlNeJpyzCpLCN1_K5i2E)zg<>Z-}vw)0`ilvO3`?y`0k)+NuOn4V{jlc delta 129 zcmX>Wy)SyhCpK0~1|0_T&A0i^Gfl4H(wY20QiVB_!F=*Y0rAZON^y*vCvdwk!xdRG X!zB%b7O`L#2Wsk(M$&}U Date: Wed, 8 Oct 2025 18:31:15 +0200 Subject: [PATCH 2/3] EgtGeomKernel : - aggiunte funzioni per copia da un db a un altro (CopyEx e CopyGlobEx). --- EgtGeomKernel.vcxproj | 2 + EgtGeomKernel.vcxproj.filters | 6 ++ GdbObj.cpp | 14 +++ GdbObj.h | 1 + GeomDB.cpp | 4 +- GeomDB.h | 2 + MultiGeomDB.cpp | 161 ++++++++++++++++++++++++++++++++++ 7 files changed, 188 insertions(+), 2 deletions(-) create mode 100644 MultiGeomDB.cpp diff --git a/EgtGeomKernel.vcxproj b/EgtGeomKernel.vcxproj index b9099fc..d71a302 100644 --- a/EgtGeomKernel.vcxproj +++ b/EgtGeomKernel.vcxproj @@ -320,6 +320,7 @@ copy $(TargetPath) \EgtProg\Dll64 + @@ -340,6 +341,7 @@ copy $(TargetPath) \EgtProg\Dll64 + diff --git a/EgtGeomKernel.vcxproj.filters b/EgtGeomKernel.vcxproj.filters index 68e0c44..30abde1 100644 --- a/EgtGeomKernel.vcxproj.filters +++ b/EgtGeomKernel.vcxproj.filters @@ -552,6 +552,9 @@ File di origine\GeoOffset + + File di origine\Gdb + @@ -1235,6 +1238,9 @@ File di intestazione\Include + + File di intestazione\Include + diff --git a/GdbObj.cpp b/GdbObj.cpp index 8ddd1a2..d7cfb0f 100644 --- a/GdbObj.cpp +++ b/GdbObj.cpp @@ -101,6 +101,20 @@ GdbObj::CopyFrom( const GdbObj* pSou) return ( CopyAttribsFrom( pSou) && CopyTextureDataFrom( pSou) && CopyUserObjFrom( pSou)) ; } +//---------------------------------------------------------------------------- +bool +GdbObj::CopyStippleDataFrom( const GdbObj* pSou) +{ + // se l'oggetto sorgente non esiste + if ( pSou == nullptr) + return false ; + // copio stipple + m_nStpFactor = pSou->m_nStpFactor ; + m_nStpPattern = pSou->m_nStpPattern ; + + return true ; +} + //---------------------------------------------------------------------------- bool GdbObj::CopyAttribsFrom( const GdbObj* pSou) diff --git a/GdbObj.h b/GdbObj.h index f56e78c..d31689d 100644 --- a/GdbObj.h +++ b/GdbObj.h @@ -57,6 +57,7 @@ class GdbObj GdbObj( void) ; bool CopyFrom( const GdbObj* pSou) ; bool CopyAttribsFrom( const GdbObj* pSou) ; + bool CopyStippleDataFrom( const GdbObj* pSou) ; bool CopyTextureDataFrom( const GdbObj* pSou) ; bool CopyUserObjFrom( const GdbObj* pSou) ; diff --git a/GeomDB.cpp b/GeomDB.cpp index 2edf165..fd300d2 100644 --- a/GeomDB.cpp +++ b/GeomDB.cpp @@ -38,7 +38,7 @@ using namespace std ; class LockAddErase { public : - LockAddErase(std::atomic_flag& bAddEraseOn, bool bUse = true): m_bAddEraseOn( bAddEraseOn), m_bUse( bUse) + LockAddErase( atomic_flag& bAddEraseOn, bool bUse = true): m_bAddEraseOn( bAddEraseOn), m_bUse( bUse) { if ( ! m_bUse) return ; while ( m_bAddEraseOn.test_and_set()) { this_thread::sleep_for( chrono::nanoseconds{ 1}) ; @@ -51,7 +51,7 @@ class LockAddErase } ; private : - std::atomic_flag& m_bAddEraseOn ; + atomic_flag& m_bAddEraseOn ; bool m_bUse ; } ; diff --git a/GeomDB.h b/GeomDB.h index e5ad7eb..6e0f18a 100644 --- a/GeomDB.h +++ b/GeomDB.h @@ -29,6 +29,8 @@ class GeomDB : public IGeomDB friend class GdbObj ; friend class GdbGroup ; friend class GdbGeo ; + friend int CopyGeoObj( const GeomDB* pSouGDB, int nSouId, GeomDB* pDstGDB, int nDestId, int nRefId, int nSonBeforeAfter, bool bGlob) ; + friend int CopyGroupObj( const GeomDB* pSouGDB, int nSouId, GeomDB* pDstGDB, int nDestId, int nRefId, int nSonBeforeAfter, bool bGlob) ; public : ~GeomDB( void) override ; diff --git a/MultiGeomDB.cpp b/MultiGeomDB.cpp new file mode 100644 index 0000000..e0240a2 --- /dev/null +++ b/MultiGeomDB.cpp @@ -0,0 +1,161 @@ +//---------------------------------------------------------------------------- +// EgalTech 2025-2025 +//---------------------------------------------------------------------------- +// File : MultiGeomDB.cpp Data : 08.10.25 Versione : 2.7j1 +// Contenuto : Implementazione delle funzioni tra due GeomDB. +// +// +// +// Modifiche : 08.10.25 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "GeomDB.h" +#include "/EgtDev/Include/EGkMultiGeomDB.h" +#include "/EgtDev/Include/EgtPointerOwner.h" + +using namespace std ; + +//---------------------------------------------------------------------------- +static int +CopyGeoObj( const GeomDB* pSouGDB, int nSouId, GeomDB* pDstGDB, int nDestId, int nRefId, int nSonBeforeAfter, bool bGlob) +{ + // verifico i puntatori ai GeomDB + if ( pSouGDB == nullptr || pDstGDB == nullptr) + return GDB_ID_NULL ; + // recupero l'oggetto da copiare dal GeomDB sorgente + PtrOwner pGObj( pSouGDB->GetGeoObj( nSouId)->Clone()) ; + if ( IsNull( pGObj)) + return GDB_ID_NULL ; + // se in globale + if ( bGlob) { + // recupero il riferimento del sorgente + Frame3d frSou ; + if ( ! pSouGDB->GetGlobFrame( nSouId, frSou)) + return GDB_ID_NULL ; + // recupero il riferimento del gruppo destinazione + Frame3d frDest ; + int nDestParentId = ( IS_GDB_SON( nSonBeforeAfter) ? nRefId : pDstGDB->GetParentId( nRefId)) ; + if ( ! pDstGDB->GetGroupGlobFrame( nDestParentId, frDest)) + return GDB_ID_NULL ; + // porto la copia da riferimento sorgente a quello destinazione + pGObj->LocToLoc( frSou, frDest) ; + } + // lo inserisco nel GeomDB destinazione + int nNewId = pDstGDB->InsertGeoObj( nDestId, nRefId, nSonBeforeAfter, Release( pGObj)) ; + if ( nNewId == GDB_ID_NULL) + return GDB_ID_NULL ; + // copio le caratteristiche non geometriche + const GdbObj* pSouGdbObj = pSouGDB->GetGdbObj( nSouId) ; + GdbObj* pDstGdbObj = pDstGDB->GetGdbObj( nNewId) ; + if ( pSouGDB == nullptr || pDstGdbObj == nullptr || + ! pDstGdbObj->CopyAttribsFrom( pSouGdbObj) || + ! pDstGdbObj->CopyTextureDataFrom( pSouGdbObj) || + ! pDstGdbObj->CopyStippleDataFrom( pSouGdbObj) || + ! pDstGdbObj->CopyUserObjFrom( pSouGdbObj)) { + pDstGDB->Erase( nNewId) ; + return GDB_ID_NULL ; + } + + return nNewId ; +} + +//---------------------------------------------------------------------------- +static int +CopyGroupObj( const GeomDB* pSouGDB, int nSouId, GeomDB* pDstGDB, int nDestId, int nRefId, int nSonBeforeAfter, bool bGlob) +{ + // recupero il riferimento del gruppo + Frame3d frFrame ; + pSouGDB->GetGroupFrame( nSouId) ; + // se in globale + if ( bGlob) { + // recupero il riferimento del gruppo in globale + if ( ! pSouGDB->GetGlobFrame( nSouId, frFrame)) + return GDB_ID_NULL ; + // recupero il riferimento del gruppo destinazione + Frame3d frDest ; + int nDestParentId = ( IS_GDB_SON( nSonBeforeAfter) ? nRefId : pDstGDB->GetParentId( nRefId)) ; + if ( ! pDstGDB->GetGroupGlobFrame( nDestParentId, frDest)) + return GDB_ID_NULL ; + // porto la copia da riferimento sorgente a quello destinazione + frFrame.ToLoc( frDest) ; + } + // inserisco un nuovo gruppo nel GeomDB destinazione + int nNewId = pDstGDB->InsertGroup( nDestId, nRefId, nSonBeforeAfter, frFrame) ; + if ( nNewId == GDB_ID_NULL) + return GDB_ID_NULL ; + // copio le caratteristiche non geometriche + const GdbObj* pSouGdbObj = pSouGDB->GetGdbObj( nSouId) ; + GdbObj* pDstGdbObj = pDstGDB->GetGdbObj( nNewId) ; + if ( pSouGDB == nullptr || pDstGdbObj == nullptr || + ! pDstGdbObj->CopyAttribsFrom( pSouGdbObj) || + ! pDstGdbObj->CopyTextureDataFrom( pSouGdbObj) || + ! pDstGdbObj->CopyStippleDataFrom( pSouGdbObj) || + ! pDstGdbObj->CopyUserObjFrom( pSouGdbObj)) { + pDstGDB->Erase( nNewId) ; + return GDB_ID_NULL ; + } + // copio gli eventuali figli + int nSonSouId = pSouGDB->GetFirstInGroup( nSouId) ; + while ( nSonSouId != GDB_ID_NULL) { + // nuovo identificativo oggetto destinazione + int nSonNewId = GDB_ID_NULL ; + // recupero il tipo di oggetto sorgente + int nSonSouType = pSouGDB->GetGdbType( nSonSouId) ; + // se l'oggetto da copiare è geometrico + if ( nSonSouType == GDB_TY_GEO) + nSonNewId = CopyGeoObj( pSouGDB, nSonSouId, pDstGDB, GDB_ID_NULL, nNewId, GDB_LAST_SON, false) ; + // se altrimenti è un gruppo + else if ( nSonSouType == GDB_TY_GROUP) + nSonNewId = CopyGroupObj( pSouGDB, nSonSouId, pDstGDB, GDB_ID_NULL, nNewId, GDB_LAST_SON, false) ; + // se copia non riuscita, esco con errore + if ( nSonNewId == GDB_ID_NULL) + return GDB_ID_NULL ; + // passo al figlio successivo + nSonSouId = pSouGDB->GetNext( nSonSouId) ; + } + + return nNewId ; +} + +//---------------------------------------------------------------------------- +static int +Copy( IGeomDB* pSouGeomDB, int nSouId, IGeomDB* pDestGeomDB, int nDestId, int nRefId, int nSonBeforeAfter, bool bGlob) +{ + // adatto e verifico i GeomDB + const GeomDB* pSouGDB = static_cast( pSouGeomDB) ; + GeomDB* pDstGDB = static_cast( pDestGeomDB) ; + if ( pSouGDB == nullptr || pDstGDB == nullptr) + return GDB_ID_NULL ; + // nuovo identificativo oggetto destinazione + int nNewId = GDB_ID_NULL ; + // recupero il tipo di oggetto sorgente + int nSouType = pSouGDB->GetGdbType( nSouId) ; + // se l'oggetto da copiare è geometrico + if ( nSouType == GDB_TY_GEO) { + nNewId = CopyGeoObj( pSouGDB, nSouId, pDstGDB, nDestId, nRefId, nSonBeforeAfter, bGlob) ; + } + // se altrimenti è un gruppo + else if ( nSouType == GDB_TY_GROUP) { + nNewId = CopyGroupObj( pSouGDB, nSouId, pDstGDB, nDestId, nRefId, nSonBeforeAfter, bGlob) ; + } + + return nNewId ; +} + +//---------------------------------------------------------------------------- +int +Copy( IGeomDB* pSouGeomDB, int nSouId, IGeomDB* pDestGeomDB, int nDestId, int nRefId, int nSonBeforeAfter) +{ + return Copy( pSouGeomDB, nSouId, pDestGeomDB, nDestId, nRefId, nSonBeforeAfter, false) ; +} + +//---------------------------------------------------------------------------- +int +CopyGlob( IGeomDB* pSouGeomDB, int nSouId, IGeomDB* pDestGeomDB, int nDestId, int nRefId, int nSonBeforeAfter) +{ + return Copy( pSouGeomDB, nSouId, pDestGeomDB, nDestId, nRefId, nSonBeforeAfter, true) ; +} From 39d295f41250896ec2880533089e62146eda4c08 Mon Sep 17 00:00:00 2001 From: Riccardo Elitropi Date: Thu, 9 Oct 2025 09:50:07 +0200 Subject: [PATCH 3/3] EgtGeomKernel : - Migliorata e Corretta la funzione MakeUniform per VolZMap. --- VolZmap.cpp | 326 +++++++++++++++++++++++++++++----------------- VolZmap.h | 11 +- VolZmapVolume.cpp | 257 +++++++++++++++++++----------------- 3 files changed, 351 insertions(+), 243 deletions(-) diff --git a/VolZmap.cpp b/VolZmap.cpp index 03731c7..4f105f2 100644 --- a/VolZmap.cpp +++ b/VolZmap.cpp @@ -1,4 +1,4 @@ -//---------------------------------------------------------------------------- +//---------------------------------------------------------------------------- // EgalTech 2015-2016 //---------------------------------------------------------------------------- // File : VolZmap.cpp Data : 22.01.15 Versione : 1.6a4 @@ -563,10 +563,10 @@ VolZmap::GetPartLocalBBox( int nPart, BBox3d& b3Loc, int nFlag) const // Verifico lo stato. if ( m_nStatus != OK) return false ; - // Se una sola mappa o il numero di componenti è indefinito, vi è un errore. + // Se una sola mappa o il numero di componenti è indefinito, vi è un errore. if ( m_nMapNum == 1 || m_nConnectedCompoCount == - 1) return false ; - // Se la componente richiesta non esiste, vi è un errore. + // Se la componente richiesta non esiste, vi è un errore. if ( nPart < 0 || nPart > m_nConnectedCompoCount - 1) return false ; // Calcolo Bounding-box @@ -614,10 +614,10 @@ VolZmap::GetPartBBox( int nPart, const Frame3d& frRef, BBox3d& b3Ref, int nFlag) // Verifico lo stato. if ( m_nStatus != OK) return false ; - // Se una sola mappa o il numero di componenti è indefinito, vi è un errore. + // Se una sola mappa o il numero di componenti è indefinito, vi è un errore. if ( m_nMapNum == 1 || m_nConnectedCompoCount == - 1) return false ; - // Se la componente richiesta non esiste, vi è un errore. + // Se la componente richiesta non esiste, vi è un errore. if ( nPart < 0 || nPart > m_nConnectedCompoCount - 1) return false ; // Calcolo Bounding-box @@ -689,7 +689,7 @@ VolZmap::Rotate( const Point3d& ptAx, const Vector3d& vtAx, double dCosAng, doub // verifico lo stato if ( m_nStatus != OK) return false ; - // verifico validità dell'asse di rotazione + // verifico validità dell'asse di rotazione if ( vtAx.IsSmall()) return false ; @@ -722,7 +722,7 @@ VolZmap::Mirror( const Point3d& ptOn, const Vector3d& vtNorm) // verifico lo stato if ( m_nStatus != OK) return false ; - // verifico validità del piano di specchiatura + // verifico validità del piano di specchiatura if ( vtNorm.IsSmall()) return false ; @@ -736,7 +736,7 @@ VolZmap::Shear( const Point3d& ptOn, const Vector3d& vtNorm, const Vector3d& vtD // verifico lo stato if ( m_nStatus != OK) return false ; - // verifico validità dei parametri + // verifico validità dei parametri if ( vtNorm.IsSmall() || vtDir.IsSmall()) return false ; @@ -750,11 +750,11 @@ VolZmap::ToGlob( const Frame3d& frRef) // verifico lo stato if ( m_nStatus != OK) return false ; - // verifico validità del frame + // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; - // se frame identità, non devo fare alcunché + // se frame identità, non devo fare alcunché if ( IsGlobFrame( frRef)) return true ; @@ -773,11 +773,11 @@ VolZmap::ToLoc( const Frame3d& frRef) // verifico lo stato if ( m_nStatus != OK) return false ; - // verifico validità del frame + // verifico validità del frame if ( frRef.GetType() == Frame3d::ERR) return false ; - // se frame identità, non devo fare alcunché + // se frame identità, non devo fare alcunché if ( IsGlobFrame( frRef)) return true ; @@ -796,11 +796,11 @@ VolZmap::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) // verifico lo stato if ( m_nStatus != OK) return false ; - // verifico validità dei frame + // verifico validità dei frame if ( frOri.GetType() == Frame3d::ERR || frDest.GetType() == Frame3d::ERR) return false ; - // se i due riferimenti coincidono, non devo fare alcunché + // se i due riferimenti coincidono, non devo fare alcunché if ( AreSameFrame( frOri, frDest)) return true ; @@ -816,10 +816,10 @@ VolZmap::LocToLoc( const Frame3d& frOri, const Frame3d& frDest) int VolZmap::GetPartCount( void) const { - // Se mono-dexel la connessione è incalcolabile. + // Se mono-dexel la connessione è incalcolabile. if ( m_nMapNum == 1) return - 1 ; - // Se il numero delle componenti è indefinito + // Se il numero delle componenti è indefinito // lo ricalcolo e restituisco il risultato. if ( m_nConnectedCompoCount == - 1) { const_cast(this)->CheckMapConnection() ; @@ -870,7 +870,7 @@ VolZmap::CheckMapConnection( void) IntervalsToProcessStackVec.resize( nThreadMax) ; // Mi espando dal primo intervallo mettendo gli intervalli che intersecano nei vari thread FirstExpansionFromZ( nThreadMax, NewInt, IntervalsToProcessStackVec) ; - // Lancio in parallelo più ricerche + // Lancio in parallelo più ricerche int nActiveThread = 0 ; vector> vRes ; vRes.resize( nThreadMax) ; @@ -891,7 +891,7 @@ VolZmap::CheckMapConnection( void) } } } - // Se l'intervallo non attraversa un nodo o ha già + // Se l'intervallo non attraversa un nodo o ha già // un indice assegnato salto questa iterazione. else continue ; @@ -935,7 +935,7 @@ VolZmap::ExpandFromXInterval( IntContainer& IntCont) double dZmin = m_Values[0][tGrIndex1 * m_nNx[0] + tI][tIntZ].dMin ; double dZmax = m_Values[0][tGrIndex1 * m_nNx[0] + tI][tIntZ].dMax ; // Se i segmenti si incrociano e il nuovo trovato non - // ha già un indice assegnato, assegno l'indice e + // ha già un indice assegnato, assegno l'indice e // aggiungo l'intervallo trovato allo stack. if ( dZmin - 2 * EPS_SMALL < dZ && dZmax + 2 * EPS_SMALL > dZ && @@ -955,7 +955,7 @@ VolZmap::ExpandFromXInterval( IntContainer& IntCont) double dYmin = m_Values[2][tI * m_nNx[2] + tGrIndex2][tIntY].dMin ; double dYmax = m_Values[2][tI * m_nNx[2] + tGrIndex2][tIntY].dMax ; // Se i segmenti si incrociano e il nuovo trovato non - // ha già un indice assegnato, assegno l'indice e + // ha già un indice assegnato, assegno l'indice e // aggiungo l'intervallo trovato allo stack. if ( dYmin - 2 * EPS_SMALL < dY && dYmax + 2 * EPS_SMALL > dY && @@ -1006,7 +1006,7 @@ VolZmap::ExpandFromYInterval( IntContainer& IntCont) double dZmin = m_Values[0][tJ * m_nNx[0] + tGrIndex2][tIntZ].dMin ; double dZmax = m_Values[0][tJ * m_nNx[0] + tGrIndex2][tIntZ].dMax ; // Se i segmenti si incrociano e il nuovo trovato non - // ha già un indice assegnato, assegno l'indice e + // ha già un indice assegnato, assegno l'indice e // aggiungo l'intervallo trovato allo stack. if ( dZmin - 2 * EPS_SMALL < dZ && dZmax + 2 * EPS_SMALL > dZ && @@ -1026,7 +1026,7 @@ VolZmap::ExpandFromYInterval( IntContainer& IntCont) double dXmin = m_Values[1][tGrIndex1 * m_nNx[1] + tJ][tIntX].dMin ; double dXmax = m_Values[1][tGrIndex1 * m_nNx[1] + tJ][tIntX].dMax ; // Se i segmenti si incrociano e il nuovo trovato non - // ha già un indice assegnato, assegno l'indice e + // ha già un indice assegnato, assegno l'indice e // aggiungo l'intervallo trovato allo stack. if ( dXmin - 2 * EPS_SMALL < dX && dXmax + 2 * EPS_SMALL > dX && @@ -1077,7 +1077,7 @@ VolZmap::ExpandFromZInterval( IntContainer& IntCont) double dXmin = m_Values[1][tK * m_nNx[1] + tGrIndex2][tIntX].dMin ; double dXmax = m_Values[1][tK * m_nNx[1] + tGrIndex2][tIntX].dMax ; // Se i segmenti si incrociano e il nuovo trovato non - // ha già un indice assegnato, assegno l'indice e + // ha già un indice assegnato, assegno l'indice e // aggiungo l'intervallo trovato allo stack. if ( dXmin - 2 * EPS_SMALL < dX && dXmax + 2 * EPS_SMALL > dX && @@ -1097,7 +1097,7 @@ VolZmap::ExpandFromZInterval( IntContainer& IntCont) double dYmin = m_Values[2][tGrIndex1 * m_nNx[2] + tK][tIntY].dMin ; double dYmax = m_Values[2][tGrIndex1 * m_nNx[2] + tK][tIntY].dMax ; // Se i segmenti si incrociano e il nuovo trovato non - // ha già un indice assegnato, assegno l'indice e + // ha già un indice assegnato, assegno l'indice e // aggiungo l'intervallo trovato allo stack. if ( dYmin - 2 * EPS_SMALL < dY && dYmax + 2 * EPS_SMALL > dY && @@ -1146,7 +1146,7 @@ VolZmap::FirstExpansionFromZ( int nNumThread, IntervalIndexes IntSt, IntContaine double dXmin = m_Values[1][tK * m_nNx[1] + tGrIndex2][tIntX].dMin ; double dXmax = m_Values[1][tK * m_nNx[1] + tGrIndex2][tIntX].dMax ; // Se i segmenti si incrociano e il nuovo trovato non - // ha già un indice assegnato, assegno l'indice e + // ha già un indice assegnato, assegno l'indice e // aggiungo l'intervallo trovato allo stack. if ( dXmin - 2 * EPS_SMALL < dX && dXmax + 2 * EPS_SMALL > dX && @@ -1167,7 +1167,7 @@ VolZmap::FirstExpansionFromZ( int nNumThread, IntervalIndexes IntSt, IntContaine double dYmin = m_Values[2][tGrIndex1 * m_nNx[2] + tK][tIntY].dMin ; double dYmax = m_Values[2][tGrIndex1 * m_nNx[2] + tK][tIntY].dMax ; // Se i segmenti si incrociano e il nuovo trovato non - // ha già un indice assegnato, assegno l'indice e + // ha già un indice assegnato, assegno l'indice e // aggiungo l'intervallo trovato allo stack. if ( dYmin - 2 * EPS_SMALL < dY && dYmax + 2 * EPS_SMALL > dY && @@ -1214,13 +1214,13 @@ VolZmap::ClonePart( int nPart) const // verifico lo stato if ( m_nStatus != OK) return nullptr ; - // Se è definita una sola griglia non sono definibili le parti, errore + // Se è definita una sola griglia non sono definibili le parti, errore if ( m_nMapNum == 1) return nullptr ; - // Se è richiesta una componente fuori intervallo, errore + // Se è richiesta una componente fuori intervallo, errore if ( nPart < 0 || nPart >= m_nConnectedCompoCount) return nullptr ; - // Se il numero di componenti è indefinito, lo ricalcolo. + // Se il numero di componenti è indefinito, lo ricalcolo. if ( m_nConnectedCompoCount == - 1) const_cast(this)->CheckMapConnection() ; // Se non vi sono componenti, errore @@ -1291,7 +1291,7 @@ VolZmap::ClonePart( int nPart) const pVolume->m_Values[nMap].resize( pVolume->m_nDim[nMap]) ; } - // Se almeno una griglia è nulla, non ha senso Zmap + // Se almeno una griglia è nulla, non ha senso Zmap if ( pVolume->m_nDim[0] == 0 || pVolume->m_nDim[1] == 0 || pVolume->m_nDim[2] == 0) @@ -1343,8 +1343,8 @@ VolZmap::ClonePart( int nPart) const dNewOy = nMinIndJ[0] * m_dStep ; dNewOz = nMinIndJ[1] * m_dStep ; - // Porto i dexel nel nuovo sistema di riferimento e le quote estreme Z. Non c'è bisogno di trasformare le normali, - // infatti i sistemi di riferimento in gioco differiscono al più per una traslazione. + // Porto i dexel nel nuovo sistema di riferimento e le quote estreme Z. Non c'è bisogno di trasformare le normali, + // infatti i sistemi di riferimento in gioco differiscono al più per una traslazione. for ( int nMap = 0 ; nMap < int( m_nMapNum) ; ++ nMap) { // Quote estreme Z switch ( nMap) { @@ -1407,10 +1407,10 @@ VolZmap::RemovePart( int nPart) // verifico lo stato if ( m_nStatus != OK) return false ; - // Se è definita una sola griglia non sono definibili le parti, errore + // Se è definita una sola griglia non sono definibili le parti, errore if ( m_nMapNum == 1) return false ; - // Se il numero di componenti è indefinito, lo ricalcolo + // Se il numero di componenti è indefinito, lo ricalcolo if ( m_nConnectedCompoCount == - 1) CheckMapConnection() ; // Se non vi sono componenti, abbiamo finito @@ -1452,7 +1452,7 @@ VolZmap::GetPartMinDistFromPoint( const Point3d& ptP) const // Verifico lo stato e che siano definibili le componenti connesse if ( m_nStatus != OK || m_nMapNum == 1) return - 1 ; - // Se il numero di componenti è indefinito, lo ricalcolo + // Se il numero di componenti è indefinito, lo ricalcolo if ( m_nConnectedCompoCount == -1) const_cast( this)->CheckMapConnection() ; // Se non vi sono componenti, abbiamo finito @@ -1485,7 +1485,7 @@ VolZmap::GetPartMinDistFromPoint( const Point3d& ptP) const swap( ptEn.y, ptEn.z) ; swap( ptEn.x, ptEn.z) ; } - // Calcolo la distanza del punto dal segmento corrente. Se è minore della minima distanza aggiorno quest'ultima + // Calcolo la distanza del punto dal segmento corrente. Se è minore della minima distanza aggiorno quest'ultima // e la corrispondente componente connessa di minima distanza con la distanza e la componente connessa correnti. double dDist ; DistPointLine DistCalc( ptPL, ptSt, ptEn) ; @@ -1677,107 +1677,197 @@ VolZmap::SubtractSurfTm( const ISurfTriMesh* pStm) //---------------------------------------------------------------------------- bool -VolZmap::MakeUniform( double dToler) +VolZmap::MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum) { - // controllo validità dello Zmap + // Controllo validità dello Zmap if ( ! IsValid()) return false ; - // la tolleranza deve essere minore dello step - dToler = min( dToler, 0.95 * m_dStep) ; - // creo lo Zmpa che andrà a sostituire il corrente - PtrOwner pOldVolZmap( CloneBasicVolZmap( this)) ; - if ( IsNull( pOldVolZmap)) + // creo lo ZMap per i riferimenti degli intervalli sulle griglie + PtrOwner pZMapCopy( CloneBasicVolZmap( this)) ; + if ( IsNull( pZMapCopy) || ! pZMapCopy->IsValid()) return false ; - // ciclo sulle griglie - for ( int nGrid = 0 ; nGrid < m_nMapNum ; ++ nGrid) { - // salvo lo Zmap prima di modificare gli spilloni - PtrOwner pVolZMapCurrGrid( CloneBasicVolZmap( this)) ; - if ( IsNull( pVolZMapCurrGrid)) + // creo uno ZMap per gli intervalli da aggiungere o da rimuovere + PtrOwner pZMapExtra( CreateBasicVolZmap()) ; + if ( IsNull( pZMapExtra) || + ! pZMapExtra->CreateEmpty( m_MapFrame.Orig(), m_dMaxZ[1] - m_dMinZ[1], + m_dMaxZ[2] - m_dMinZ[2], m_dMaxZ[0] - m_dMinZ[0], + m_dStep, IsTriDexel())) return false ; - // ciclo sul numero di dexel presenti - for ( int nDex = 0 ; nDex < int( m_Values[nGrid].size()) ; ++ nDex) { - // se il dexel corrente non ha sotto-intervalli passo al successivo - if ( int( m_Values[nGrid][nDex].size()) == 0) + + // Dovendo effettuare estensioni, allargo gli ingobri nelle direzioni principali + m_dMinZ[0] -= dToler ; + m_dMinZ[1] -= dToler ; + m_dMinZ[2] -= dToler ; + m_dMaxZ[0] += dToler ; + m_dMaxZ[1] += dToler ; + m_dMaxZ[2] += dToler ; + + // NB. Tutti i parametri sono sempre presi dalla Copia dello ZMap corrente + // Ciclo sulle griglie + for ( int nGrid = 0 ; nGrid < pZMapCopy->m_nMapNum ; ++ nGrid) { + // Ciclo sul numero di dexel presenti nella Copia + for ( int nDex = 0 ; nDex < int( pZMapCopy->m_Values[nGrid].size()) ; ++ nDex) { + // Se il dexel corrente non ha sotto-intervalli passo al successivo + if ( pZMapCopy->m_Values[nGrid][nDex].empty()) continue ; - // indici del dexel + // Indici del dexel int nI = nDex % m_nNx[nGrid] ; int nJ = nDex / m_nNx[nGrid] ; - // salvo le informazioni dei sotto-intervalli del dexel corrente - vector vInfo ; - for ( int nExtr = 0 ; nExtr < int( m_Values[nGrid][nDex].size()) ; ++ nExtr) - vInfo.push_back( m_Values[nGrid][nDex][nExtr]) ; - // per ogni sotto-intervallo, estendo a destra e a sinistra della tolleranza - int nSub_intervals = int( vInfo.size()) ; - // scorro gli intervalli - for ( int nInfo = 0 ; nInfo < int( pVolZMapCurrGrid->m_Values[nGrid][nDex].size()) ; ++ nInfo) { - // estremo inferiore - if ( vInfo[nInfo].dMin - dToler > m_dMinZ[nGrid]) { - AddIntervals( nGrid, nI, nJ, - vInfo[nInfo].dMin - dToler, - vInfo[nInfo].dMin + dToler, - vInfo[nInfo].vtMinN, vInfo[nInfo].vtMinN, vInfo[nInfo].nToolMin, - true) ; - // se si sono uniti degli intervalli, potrei dover aggiungere degli spilloni nelle altre due - // direzioni nel voxel corrispondente - if ( IsTriDexel() && dToler > 0.5 * m_dStep - EPS_SMALL && - nSub_intervals != int( m_Values[nGrid][nDex].size())) { - nSub_intervals = int( m_Values[nGrid][nDex].size()) ; // aggiorno gli intervalli correnti - // l'intervallo corrente si è unito con il precedente... - AddMissingIntervalsInVoxel( pOldVolZmap, nGrid, nI, nJ, vInfo[nInfo].dMin, dToler, - vInfo[nInfo].vtMinN, vInfo[nInfo].vtMinN, - vInfo[nInfo].nToolMin) ; + // Recupero il numero di intervalli presenti nel Dexel corrente + int nIntervals = int( pZMapCopy->m_Values[nGrid][nDex].size()) ; + // Scorro gli intervalli presenti + for ( int nInfo = 0 ; nInfo < int( pZMapCopy->m_Values[nGrid][nDex].size()) ; ++ nInfo) { + // Recupero l'intervallo corrente + Data& Interval = pZMapCopy->m_Values[nGrid][nDex][nInfo] ; + // --- Se richiesta prima estensione + if ( bIsExtensionFirst) { + // *** Estremo inferiore -> Intervallo : [ dMin - dToler, dMin + dToler ] + // Aggiungo l'intervallo nello Zmap corrente ( lascio invariato lo ZMapCopy) + AddIntervals( nGrid, nI, nJ, Interval.dMin - dToler, Interval.dMin + dToler, + Interval.vtMinN, Interval.vtMinN, nToolNum, true) ; + // Se si sono uniti degli intervalli, potrei dover aggiungere degli spilloni nelle altre due direzioni + if ( IsTriDexel() && nIntervals != int( m_Values[nGrid][nDex].size())) { + // Aggiorno gli intervalli correnti ( dato che il corrente si è unito al precedente) + // ( lascio invariato lo ZMapCopy) + nIntervals = int( m_Values[nGrid][nDex].size()) ; + pZMapExtra->UniformIntervalsInVoxel( nGrid, nI, nJ, + pZMapCopy->m_Values[nGrid][nDex][nInfo-1].dMax, + Interval.dMin, dToler, true, + nToolNum, V_INVALID, V_INVALID) ; + } + // *** Estremo superiore -> Intervallo : [ dMax - dToler, dMax + dToler ] + // Aggiungo l'intervallo nello Zmap corrente ( lascio invariato lo ZMapCopy) + AddIntervals( nGrid, nI, nJ, Interval.dMax - dToler, Interval.dMax + dToler, + Interval.vtMaxN, Interval.vtMaxN, nToolNum, true) ; + // Se si sono uniti degli intervalli, potrei dover aggiungere degli spilloni nelle altre due direzioni + if ( IsTriDexel() && nIntervals != int( m_Values[nGrid][nDex].size())) { + // Aggiorno gli intervalli correnti ( dato che il corrente si è unito al successivo) + // ( lascio invariato lo ZMapCopy) + nIntervals = int( m_Values[nGrid][nDex].size()) ; + pZMapExtra->UniformIntervalsInVoxel( nGrid, nI, nJ, + Interval.dMax, + pZMapCopy->m_Values[nGrid][nDex][nInfo+1].dMin, dToler, true, + nToolNum, V_INVALID, V_INVALID) ; } } - // estremo superiore - if ( vInfo[nInfo].dMax + dToler < m_dMaxZ[nGrid]) { - AddIntervals( nGrid, nI, nJ, - vInfo[nInfo].dMax - dToler, - vInfo[nInfo].dMax + dToler, - vInfo[nInfo].vtMaxN, vInfo[nInfo].vtMaxN, vInfo[nInfo].nToolMax, - true) ; - if ( IsTriDexel() && dToler > 0.5 * m_dStep - EPS_SMALL && - nSub_intervals != int( m_Values[nGrid][nDex].size())) { - nSub_intervals = int( m_Values[nGrid][nDex].size()) ; // aggiorno gli intervalli correnti - AddMissingIntervalsInVoxel( pOldVolZmap, nGrid, nI, nJ, vInfo[nInfo].dMax, dToler, - vInfo[nInfo].vtMaxN, vInfo[nInfo].vtMaxN, - vInfo[nInfo].nToolMax) ; + // --- Se richiesta prima restrizione + else { + // *** Estremo inferiore -> Intervallo : [ dMin - dToler, dMin + dToler ] + // Sottraggo l'intervallo nello Zmap corrente ( lascio invariato lo ZMapCopy) + SubtractIntervals( nGrid, nI, nJ, Interval.dMin - dToler, Interval.dMin + dToler, + Interval.vtMinN, Interval.vtMinN, nToolNum, true) ; + // Se l'intervallo si è annullato, potrei dover sottrarre degli spilloni nelle altre due direzioni + if ( IsTriDexel() && nIntervals != int( m_Values[nGrid][nDex].size())) { + // Aggiorno gli intervalli correnti ( lascio invariato lo ZMapCopy) + nIntervals = int( m_Values[nGrid][nDex].size()) ; + pZMapExtra->UniformIntervalsInVoxel( nGrid, nI, nJ, + Interval.dMin, + Interval.dMax, dToler, true, + Tool::UNDEF, V_INVALID, V_INVALID) ; + } + // *** Estremo superiore -> Intervallo : [ dMax - dToler, dMax + dToler ] + // Sottraggo l'intervallo nello Zmap corrente ( lascio invariato lo ZMapCopy) + SubtractIntervals( nGrid, nI, nJ, Interval.dMax - dToler, Interval.dMax + dToler, + Interval.vtMaxN, Interval.vtMaxN, nToolNum, true) ; + // Se l'intervallo si è annullato, potrei dover sottrarre degli spilloni nelle altre due direzioni + if ( IsTriDexel() && nIntervals != int( m_Values[nGrid][nDex].size())) { + // Aggiorno gli intervalli correnti ( lascio invariato lo ZMapCopy) + nIntervals = int( m_Values[nGrid][nDex].size()) ; + pZMapExtra->UniformIntervalsInVoxel( nGrid, nI, nJ, + Interval.dMin, + Interval.dMax, dToler, true, + Tool::UNDEF, V_INVALID, V_INVALID) ; } - } - } - // per ogni sotto-intervallo ricavato fino ad ora, restringo della tolleranza - // ( NB. avendo aggiunto intervalli, il dexel può modificare la sua struttura interna ) - for ( int nInfo = 0 ; nInfo < int( m_Values[nGrid][nDex].size()) ; ++ nInfo) { - // ( NB. la rimozione di un intervallo ora va definita per intervalli a destra e a sinistra, - // altrimenti rimuovo parti in eccesso ) - if ( ! pVolZMapCurrGrid->m_Values[nGrid][nDex].empty()) { - if ( nInfo != 0 || - pVolZMapCurrGrid->m_Values[nGrid][nDex][0].dMin - dToler > m_dMinZ[nGrid]) - m_Values[nGrid][nDex][nInfo].dMin += dToler ; - if ( nInfo != int( m_Values[nGrid][nDex].size()) - 1 || - pVolZMapCurrGrid->m_Values[nGrid][nDex].back().dMax + dToler < m_dMaxZ[nGrid]) - m_Values[nGrid][nDex][nInfo].dMax -= dToler ; } } } } + // Ciclo sulle griglie ( uso lo Zmap Corrente, lascio invariato pZMapCopy) + for ( int nGrid = 0 ; nGrid < m_nMapNum ; ++ nGrid) { + // Ciclo sul numero di dexel presenti + for ( int nDex = 0 ; nDex < int( m_Values[nGrid].size()) ; ++ nDex) { + // Se l'intervallo è vuoto, non faccio nulla + if ( m_Values[nGrid][nDex].empty()) + continue ; + // Per ogni intervallo ricavato fino ad ora, restringo della tolleranza + for ( int nInfo = 0 ; nInfo < int( m_Values[nGrid][nDex].size()) ; ++ nInfo) { + // --- Se richiesta prima estensione + if ( bIsExtensionFirst) { + m_Values[nGrid][nDex][nInfo].dMin += dToler ; + m_Values[nGrid][nDex][nInfo].dMax -= dToler ; + } + // --- Se richiesta prima restrizione + else { + m_Values[nGrid][nDex][nInfo].dMin -= dToler ; + m_Values[nGrid][nDex][nInfo].dMax += dToler ; + } + // Definisco il colore + for ( int nOrigInfo = 0 ; nOrigInfo < int( pZMapCopy->m_Values[nGrid][nDex].size()) ; ++ nOrigInfo) { + if ( pZMapCopy->m_Values[nGrid][nDex][nOrigInfo].dMin - m_Values[nGrid][nDex][nInfo].dMin < EPS_SMALL) + m_Values[nGrid][nDex][nInfo].nToolMin = pZMapCopy->m_Values[nGrid][nDex][nOrigInfo].nToolMin ; + if ( pZMapCopy->m_Values[nGrid][nDex][nOrigInfo].dMax - m_Values[nGrid][nDex][nInfo].dMax < EPS_SMALL) + m_Values[nGrid][nDex][nInfo].nToolMax = pZMapCopy->m_Values[nGrid][nDex][nOrigInfo].nToolMax ; + } + } + } + } + + // Gestisco le parti Extra ricavate + // Ciclo sulle griglie ( uso lo ZmapExtra, lascio invariato pZMapCopy) + for ( int nGrid = 0 ; nGrid < pZMapExtra->m_nMapNum ; ++ nGrid) { + // Ciclo sul numero di dexel presenti + for ( int nDex = 0 ; nDex < int( pZMapExtra->m_Values[nGrid].size()) ; ++ nDex) { + // Se l'intervallo è vuoto, non faccio nulla + if ( pZMapExtra->m_Values[nGrid][nDex].empty()) + continue ; + // Indici del dexel + int nI = nDex % m_nNx[nGrid] ; + int nJ = nDex / m_nNx[nGrid] ; + // Per ogni intervallo ricavato fino ad ora... + for ( int nInfo = 0 ; nInfo < int( pZMapExtra->m_Values[nGrid][nDex].size()) ; ++ nInfo) { + double dMin = pZMapExtra->m_Values[nGrid][nDex][nInfo].dMin ; + double dMax = pZMapExtra->m_Values[nGrid][nDex][nInfo].dMax ; + Vector3d vtNMin = pZMapExtra->m_Values[nGrid][nDex][nInfo].vtMinN ; + Vector3d vtNMax = pZMapExtra->m_Values[nGrid][nDex][nInfo].vtMaxN ; + // --- Se richiesta prima estensione + if ( bIsExtensionFirst) { + // ... aggiungo i contributi + AddIntervals( nGrid, nI, nJ, dMin, dMax, vtNMin, vtNMax, nToolNum, true) ; + } + // --- Se richiesta prima restrizione + else { + // ... sottraggo i contributi + SubtractIntervals( nGrid, nI, nJ, dMin, dMax, vtNMin, vtNMax, nToolNum, true) ; + } + } + } + } + + // Restringo gli ingombri espensi in precedenza + m_dMinZ[0] += dToler ; + m_dMinZ[1] += dToler ; + m_dMinZ[2] += dToler ; + m_dMaxZ[0] -= dToler ; + m_dMaxZ[1] -= dToler ; + m_dMaxZ[2] -= dToler ; + return true ; } - //---------------------------------------------------------------------------- bool VolZmap::SetToModifyDexelBlocks( int nGrid, int nDex, int nInt) { - // Controllo sulla validità della griglia + // Controllo sulla validità della griglia if ( nGrid < 0 || nGrid > 2) return false ; - // Controllo sulla validità del dexel + // Controllo sulla validità del dexel if ( nDex <= - 1 || nDex >= int( m_Values[nGrid].size())) return false ; - // Controllo sulla validità dell'intervallo + // Controllo sulla validità dell'intervallo if ( nInt <= - 1 || nInt >= int( m_Values[nGrid][nDex].size())) return false ; @@ -1957,7 +2047,7 @@ VolZmap::IsMapPartABox( int nMap, int nInfI, int nSupI, int nInfJ, int nSupJ, do bool VolZmap::IsBox( void) { - // Se non tridexel, non posso stabilire con il metodo seguente se è un box + // Se non tridexel, non posso stabilire con il metodo seguente se è un box // Verifico solo che gli spilloni di una mappa o sono nulli o hanno gli stessi estremi if ( m_nMapNum == 1) return false ; @@ -1976,7 +2066,7 @@ VolZmap::IsBox( void) return true ; } - // Caso di più thread + // Caso di più thread m_bIsBox = true ; for ( int nMap = 0 ; nMap < m_nMapNum ; ++ nMap) { vector< future> vRes ; @@ -2021,7 +2111,7 @@ VolZmap::IsBox( void) } } } - // Se uno dei thread trova che la sua porzione non è un box, non lo può essere il solido intero. + // Se uno dei thread trova che la sua porzione non è un box, non lo può essere il solido intero. if ( ! m_bIsBox) return false ; // Controllo che gli estremi Z siano uguali. @@ -2058,7 +2148,7 @@ VolZmap::Cut( const Plane3d& plPlane) } // Ciclo sui dexel della mappa for ( int nD = 0 ; nD < int( m_Values[nMap].size()) ; ++ nD) { - // Se spillone già vuoto, passo al successivo + // Se spillone già vuoto, passo al successivo if ( m_Values[nMap][nD].empty()) continue ; // Indici di spillone @@ -2074,20 +2164,20 @@ VolZmap::Cut( const Plane3d& plPlane) double dEnDist = DistPointPlane( ptEn, plMyPlane) ; // Se entrambi sotto il piano if ( dStDist < EPS_SMALL && dEnDist < EPS_SMALL) - // Non devo fare alcunché + // Non devo fare alcunché ; // se altrimenti entrambi gli estremi sono oltre il piano else if ( dStDist > -EPS_SMALL && dEnDist > -EPS_SMALL) { // Si elimina tutto SubtractIntervals( nMap, nI, nJ, dMin, dMax, V_NULL, V_NULL, 1) ; } - // se altrimenti è da tenere il punto iniziale + // se altrimenti è da tenere il punto iniziale else if ( dStDist < 0) { // Si elimina la parte tra intersezione e punto finale double dInt = dMin + ( dMax - dMin) * abs( dStDist) / ( abs( dStDist) + abs( dEnDist)) ; SubtractIntervals( nMap, nI, nJ, dInt, dMax, plMyPlane.GetVersN(), V_NULL, 1) ; } - // se altrimenti è da tenere il punto finale + // se altrimenti è da tenere il punto finale else if (dEnDist < 0) { // Si elimina la parte tra punto iniziale e intersezione double dInt = dMin + ( dMax - dMin) * abs( dStDist) / ( abs( dStDist) + abs( dEnDist)) ; @@ -2177,7 +2267,7 @@ VolZmap::Compact( void) } } - // Se non vi è materiale + // Se non vi è materiale if ( ! bNotEmptyGrid) { m_nStatus = TO_VERIFY ; m_nNumBlock = 0 ; @@ -2199,8 +2289,8 @@ VolZmap::Compact( void) double dNewOy = nMinJ[0] * m_dStep ; double dNewOz = nMinJ[1] * m_dStep ; - // Porto i dexel nel nuovo sistema di riferimento e le quote estreme Z. Non c'è bisogno di trasformare le normali, - // infatti i sistemi di riferimento in gioco differiscono al più per una traslazione. + // Porto i dexel nel nuovo sistema di riferimento e le quote estreme Z. Non c'è bisogno di trasformare le normali, + // infatti i sistemi di riferimento in gioco differiscono al più per una traslazione. for ( int nMap = 0 ; nMap < int( m_nMapNum) ; ++ nMap) { // Quote estreme Z switch ( nMap) { diff --git a/VolZmap.h b/VolZmap.h index 146c9af..ee53485 100644 --- a/VolZmap.h +++ b/VolZmap.h @@ -151,7 +151,7 @@ class VolZmap : public IVolZmap, public IGeoObjRW int GetPartMinDistFromPoint( const Point3d& ptP) const override ; bool AddSurfTm( const ISurfTriMesh* pStm) override ; bool SubtractSurfTm( const ISurfTriMesh* pStm) override ; - bool MakeUniform( double dToler) override ; + bool MakeUniform( double dToler, bool bIsExtensionFirst, int nToolNum) override ; bool Offset( double dOffs, int nType) override ; public : // IGeoObjRW @@ -260,10 +260,11 @@ class VolZmap : public IVolZmap, public IGeoObjRW bool AddIntervals( int nGrid, int nI, int nJ, double dMin, double dMax, const Vector3d& vtNMin, const Vector3d& vtNMax, int nToolNum, bool bSkipSwap = false) ; - bool AddMissingIntervalsInVoxel( VolZmap* VolZmapRef, int nGrid, int nI, int nJ, double dZ, double dToler, - Vector3d vtToolMin, Vector3d vtToolMax, int nToolNum) ; - bool AddSubIntervalInVoxel( VolZmap* VolZmapRef, int nGrid, int nI, int nJ, int nK, double& dMin, double& dMax, - Vector3d& vtMin, Vector3d& vtMax) ; + bool UniformIntervalsInVoxel( int nGrid, int nI, int nJ, double dZMin, double dZMax, + double dToler, bool bAdd, int nToolNum, const Vector3d& vtToolMin, + const Vector3d& vtToolMax) ; + bool ManageSubIntervalInVoxel( VolZmap* VolZmapRef, int nGrid, int nI, int nJ, int nK, double& dMin, double& dMax, + Vector3d& vtMin, Vector3d& vtMax) ; // Spostamenti utensile bool MillingTranslationStep( const Point3d& ptPs, const Point3d& ptPe, const Vector3d& vtD, const Vector3d& vtA) ; bool MillingGeneralMotionStep( const Point3d& ptPs, const Vector3d& vtDs, const Vector3d& vtAs, diff --git a/VolZmapVolume.cpp b/VolZmapVolume.cpp index b306385..fd0b30b 100644 --- a/VolZmapVolume.cpp +++ b/VolZmapVolume.cpp @@ -615,134 +615,157 @@ VolZmap::AddIntervals( int nGrid, int nI, int nJ, //---------------------------------------------------------------------------- bool -VolZmap::AddSubIntervalInVoxel( VolZmap* VolZmapRef, int nGrid, int nI, int nJ, int nK, - double& dMin, double& dMax, Vector3d& vtMin, Vector3d& vtMax) +VolZmap::ManageSubIntervalInVoxel( VolZmap* VolZmapRef, int nGrid, int nI, int nJ, int nK, + double& dMin, double& dMax, Vector3d& vtMin, Vector3d& vtMax) { - // se non Tridex, esco + // Se non Tridex, esco if ( ! IsTriDexel()) return true ; - + // Controllo che il numero di griglia sia entro i limiti if ( nGrid < 0 || nGrid > 2) return false ; // Controllo che indici nI, nJ siano entro i limiti - if ( nI < 0 && nI >= m_nNx[nGrid] && - nJ < 0 && nJ >= m_nNy[nGrid]) + if ( nI < 0 && nI >= m_nNx[nGrid] && nJ < 0 && nJ >= m_nNy[nGrid]) return false ; - // valori di default - vector vTdMin = { -1., -1., -1., -1.} ; - vector vTdMax = { -1., -1., -1., -1.} ; - VCT3DVECTOR vtNMin = { V_INVALID, V_INVALID, V_INVALID, V_INVALID} ; - VCT3DVECTOR vtNMax = { V_INVALID, V_INVALID, V_INVALID, V_INVALID} ; + // Valori di Default + DBLVECTOR vdMin = { -1., -1., -1., -1.} ; + DBLVECTOR vdMax = { -1., -1., -1., -1.} ; + VCT3DVECTOR vNMin = { V_INVALID, V_INVALID, V_INVALID, V_INVALID} ; + VCT3DVECTOR vNMax = { V_INVALID, V_INVALID, V_INVALID, V_INVALID} ; - // se esiste un precedente lungo x-locale + // Se esiste un voxel precedente lungo x-locale ( nI - 1, nJ) if ( nI != 0) { - int nPos = nJ * m_nNx[nGrid] + ( nI - 1) ; // recupero posizione dexel - // cerco l'intervallo corretto sullo Zmap di riferimento + // Ne recupero la posizione + int nPos = nJ * m_nNx[nGrid] + ( nI - 1) ; + // Scorro tutti gli intervalli del dexel in (nI - 1, nJ) for ( int it = 0 ; it < int( VolZmapRef->m_Values[nGrid][nPos].size()) ; ++ it) { + // Se nei pressi dell'estremo superiore if ( VolZmapRef->m_Values[nGrid][nPos][it].dMax + EPS_SMALL > nK * m_dStep && VolZmapRef->m_Values[nGrid][nPos][it].dMax - EPS_SMALL < ( nK + 1) * m_dStep) { - vtNMax[0] = VolZmapRef->m_Values[nGrid][nPos][it].vtMaxN ; - vTdMax[0] = VolZmapRef->m_Values[nGrid][nPos][it].dMax ; + // Memorizzo i parametri + vNMax[0] = VolZmapRef->m_Values[nGrid][nPos][it].vtMaxN ; + vdMax[0] = VolZmapRef->m_Values[nGrid][nPos][it].dMax ; } + // Se nei pressi dell'estremo inferiore if ( VolZmapRef->m_Values[nGrid][nPos][it].dMin + EPS_SMALL > nK * m_dStep && VolZmapRef->m_Values[nGrid][nPos][it].dMin - EPS_SMALL < ( nK + 1) * m_dStep) { - vtNMin[0] = VolZmapRef->m_Values[nGrid][nPos][it].vtMinN ; - vTdMin[0] = VolZmapRef->m_Values[nGrid][nPos][it].dMin ; + // Memorizzo i parametri + vNMin[0] = VolZmapRef->m_Values[nGrid][nPos][it].vtMinN ; + vdMin[0] = VolZmapRef->m_Values[nGrid][nPos][it].dMin ; } } } - // se esiste il successivo lungo x-locale - if ( nI != m_dMaxZ[( nGrid + 2) % 3]) { - int nPos = nJ * m_nNx[nGrid] + ( nI + 1) ; // recupero posizione dexel + + // Se esiste un voxel successivo lungo x-locale, ne recupero la posizione + int nPos = nJ * m_nNx[nGrid] + ( nI + 1) ; + if ( nPos < int( VolZmapRef->m_Values[nGrid].size())) { + // Cerco l'intervallo corretto sullo Zmap di riferimento for ( int it = 0 ; it < int( VolZmapRef->m_Values[nGrid][nPos].size()) ; ++ it) { - // cerco l'intervallo corretto sullo Zmap di riferimento + // Se nei pressi dell'estremo superiore if ( VolZmapRef->m_Values[nGrid][nPos][it].dMax + EPS_SMALL > nK * m_dStep && VolZmapRef->m_Values[nGrid][nPos][it].dMax - EPS_SMALL < ( nK + 1) * m_dStep) { - vtNMax[1] = VolZmapRef->m_Values[nGrid][nPos][it].vtMaxN ; - vTdMax[1] = VolZmapRef->m_Values[nGrid][nPos][it].dMax ; + // Memorizzo i parametri + vNMax[1] = VolZmapRef->m_Values[nGrid][nPos][it].vtMaxN ; + vdMax[1] = VolZmapRef->m_Values[nGrid][nPos][it].dMax ; } + // Se nei pressi dell'estremo inferiore if ( VolZmapRef->m_Values[nGrid][nPos][it].dMin + EPS_SMALL > nK * m_dStep && VolZmapRef->m_Values[nGrid][nPos][it].dMin - EPS_SMALL < ( nK + 1) * m_dStep) { - vtNMin[1] = VolZmapRef->m_Values[nGrid][nPos][it].vtMinN ; - vTdMin[1] = VolZmapRef->m_Values[nGrid][nPos][it].dMin ; + // Memorizzo i parametri + vNMin[1] = VolZmapRef->m_Values[nGrid][nPos][it].vtMinN ; + vdMin[1] = VolZmapRef->m_Values[nGrid][nPos][it].dMin ; } } } - // se esiste il precedente lungo y-locale + + // Se esiste un voxel precedente lungo y-locale if ( nJ != 0) { - int nPos = ( nJ - 1) * m_nNx[nGrid] + nI ; // recupero posizione dexel + // Ne recupero la posizione + int nPos = ( nJ - 1) * m_nNx[nGrid] + nI ; + // Cerco l'intervallo corretto sullo Zmap di riferimento for ( int it = 0 ; it < int( VolZmapRef->m_Values[nGrid][nPos].size()) ; ++ it) { - // cerco l'intervallo corretto sullo Zmap di riferimento + // Se nei pressi dell'estremo superiore if ( VolZmapRef->m_Values[nGrid][nPos][it].dMax + EPS_SMALL > nK * m_dStep && VolZmapRef->m_Values[nGrid][nPos][it].dMax - EPS_SMALL < ( nK + 1) * m_dStep) { - vtNMax[2] = VolZmapRef->m_Values[nGrid][nPos][it].vtMaxN ; - vTdMax[2] = VolZmapRef->m_Values[nGrid][nPos][it].dMax ; + // Memorizzo i parametri + vNMax[2] = VolZmapRef->m_Values[nGrid][nPos][it].vtMaxN ; + vdMax[2] = VolZmapRef->m_Values[nGrid][nPos][it].dMax ; } + // Se nei pressi dell'estremo inferiore if ( VolZmapRef->m_Values[nGrid][nPos][it].dMin + EPS_SMALL > nK * m_dStep && VolZmapRef->m_Values[nGrid][nPos][it].dMin - EPS_SMALL < ( nK + 1) * m_dStep) { - vtNMin[2] = VolZmapRef->m_Values[nGrid][nPos][it].vtMinN ; - vTdMin[2] = VolZmapRef->m_Values[nGrid][nPos][it].dMin ; - } - } - } - // se esiste il successivo lungo y-locale - if ( nJ != m_dMaxZ[( nGrid + 1) % 3]) { - int nPos = ( nJ + 1) * m_nNx[nGrid] + nI ; // recupero posizione dexel - // cerco l'intervallo corretto sullo Zmap di riferimento - for ( int it = 0 ; it < int( VolZmapRef->m_Values[nGrid][nPos].size()) ; ++ it) { - if ( VolZmapRef->m_Values[nGrid][nPos][it].dMax + EPS_SMALL > nK * m_dStep && - VolZmapRef->m_Values[nGrid][nPos][it].dMax - EPS_SMALL < ( nK + 1) * m_dStep) { - vtNMax[3] = VolZmapRef->m_Values[nGrid][nPos][it].vtMaxN ; - vTdMax[3] = VolZmapRef->m_Values[nGrid][nPos][it].dMax ; - } - if ( VolZmapRef->m_Values[nGrid][nPos][it].dMin + EPS_SMALL > nK * m_dStep && - VolZmapRef->m_Values[nGrid][nPos][it].dMin - EPS_SMALL < ( nK + 1) * m_dStep) { - vtNMin[3] = VolZmapRef->m_Values[nGrid][nPos][it].vtMinN ; - vTdMin[3] = VolZmapRef->m_Values[nGrid][nPos][it].dMin ; + // Memorizzo i parametri + vNMin[2] = VolZmapRef->m_Values[nGrid][nPos][it].vtMinN ; + vdMin[2] = VolZmapRef->m_Values[nGrid][nPos][it].dMin ; } } } - // scelgo le normali che si discostano il meno possibile dalla normale della faccia del voxel + // Se esiste un voxel successivo lungo y-locale, ne recupero la posizione + nPos = ( nJ + 1) * m_nNx[nGrid] + nI ; + if ( nPos < int( VolZmapRef->m_Values[nGrid].size())) { + // Cerco l'intervallo corretto sullo Zmap di riferimento + for ( int it = 0 ; it < int( VolZmapRef->m_Values[nGrid][nPos].size()) ; ++ it) { + // Se nei pressi dell'estremo superiore + if ( VolZmapRef->m_Values[nGrid][nPos][it].dMax + EPS_SMALL > nK * m_dStep && + VolZmapRef->m_Values[nGrid][nPos][it].dMax - EPS_SMALL < ( nK + 1) * m_dStep) { + // Memorizzo i parametri + vNMax[3] = VolZmapRef->m_Values[nGrid][nPos][it].vtMaxN ; + vdMax[3] = VolZmapRef->m_Values[nGrid][nPos][it].dMax ; + } + // Se nei pressi dell'estremo inferiore + if ( VolZmapRef->m_Values[nGrid][nPos][it].dMin + EPS_SMALL > nK * m_dStep && + VolZmapRef->m_Values[nGrid][nPos][it].dMin - EPS_SMALL < ( nK + 1) * m_dStep) { + // Memorizzo i parametri + vNMin[3] = VolZmapRef->m_Values[nGrid][nPos][it].vtMinN ; + vdMin[3] = VolZmapRef->m_Values[nGrid][nPos][it].dMin ; + } + } + } - // analisi dei massimi e delle normali --------------------------- - // 1) angolo minimo tra la normale trovata la faccia del voxel + // --- Scelgo le normali che si discostano il meno possibile dalla normale della faccia del voxel + + // 1) Angolo minimo tra la normale trovata la faccia del voxel double dMinAngle = ANG_FULL ; - // 2) vettore di riferimento per la direzione della normale + // 2) Vettore di riferimento per la direzione della normale vtMax = ( nGrid == 0 ? m_MapFrame.VersZ() : - ( nGrid == 1 ? m_MapFrame.VersX() : m_MapFrame.VersY())) ; + nGrid == 1 ? m_MapFrame.VersX() : + nGrid == 2 ? m_MapFrame.VersY() : + V_INVALID) ; Vector3d vtRef = vtMax ; - // 3) determino il massimo per questo intervallo + // 3) Determino il massimo per questo intervallo dMax = ( nK + 1) * m_dStep ; - for ( int i = 0 ; i < 4 ; ++ i) { // scorro le normali - if ( vtNMax[i].IsValid()) { // se normale trovata, quindi valida... - double dCurrAngle ; // angolo corrente tra la normale della TriMesh e quella della faccia del voxel - vtNMax[i].GetAngle( vtRef, dCurrAngle) ; - if ( abs( dCurrAngle) < dMinAngle) { // se angolo minore del minimo trovato... - // aggiorno i parametri + for ( int i = 0 ; i < 4 ; ++ i) { + // Scorro le normali valide trovate + if ( vNMax[i].IsValid()) { + // Angolo corrente tra la normale di riferimento e quella della faccia del voxel + double dCurrAngle ; vNMax[i].GetAngle( vtRef, dCurrAngle) ; + // Se angolo minore del minimo trovato... + if ( abs( dCurrAngle) < dMinAngle) { + // ... Aggiorno i parametri dMinAngle = dCurrAngle ; - vtMax = vtNMax[i] ; - dMax = vTdMax[i] ; + vtMax = vNMax[i] ; + dMax = vdMax[i] ; } } } - // analisi dei minimi e delle normali --------------------------- + // Ripeto lo stesso ragionamento per le normali dei massimi dMinAngle = ANG_FULL ; vtRef.Invert() ; dMin = nK * m_dStep ; vtMin = vtRef ; for ( int i = 0 ; i < 4 ; ++ i) { - if ( vtNMin[i].IsValid()) { + if ( vNMin[i].IsValid()) { double dCurrAngle ; - vtNMin[i].GetAngle( vtRef, dCurrAngle) ; + vNMin[i].GetAngle( vtRef, dCurrAngle) ; if ( abs( dCurrAngle) < dMinAngle) { dMinAngle = dCurrAngle ; - vtMin = vtNMin[i] ; - dMin = vTdMin[i] ; + vtMin = vNMin[i] ; + dMin = vdMin[i] ; } } } @@ -752,72 +775,66 @@ VolZmap::AddSubIntervalInVoxel( VolZmap* VolZmapRef, int nGrid, int nI, int nJ, //---------------------------------------------------------------------------- bool -VolZmap::AddMissingIntervalsInVoxel( VolZmap* VolZmapRef, int nGrid, int nI, int nJ, double dZ, double dToler, - Vector3d vtToolMin, Vector3d vtToolMax, int nToolNum) +VolZmap::UniformIntervalsInVoxel( int nGrid, int nI, int nJ, double dZMin, + double dZMax, double dToler, bool bAdd, int nToolNum, const Vector3d& vtToolMin, + const Vector3d& vtToolMax) { - - // se non Tridex, esco + // Se non Tridex, esco if ( ! IsTriDexel()) return true ; - + // Controllo che il numero di griglia sia entro i limiti if ( nGrid < 0 || nGrid > 2) return false ; // Controllo che indici nI, nJ siano entro i limiti - if ( nI < 0 && nI >= m_nNx[nGrid] && - nJ < 0 && nJ >= m_nNy[nGrid]) + if ( nI < 0 && nI >= m_nNx[nGrid] && nJ < 0 && nJ >= m_nNy[nGrid]) return false ; - // passo da indici di dexel a indici di voxel - nI /= m_nDexVoxRatio ; - nJ /= m_nDexVoxRatio ; + // Numero di voxel contenuti nel dexel corrente ( uguale per ogni dexel di una specifica griglia) + int nVoxNum = int( m_nNy[(( nGrid + 1) % 3)] / m_nDexVoxRatio + + ( m_nNy[(( nGrid + 1) % 3)] % m_nDexVoxRatio == 0 ? 1 : 2)) ; - // numero di voxel nel dexel corrente - int nVoxNum = int( m_nNy[(( nGrid+1) % 3)] / m_nDexVoxRatio + - ( m_nNy[(( nGrid+1) % 3)] % m_nDexVoxRatio == 0 ? 1 : 2)) ; - - int nK = 0 ; - for ( int i = 0 ; i < nVoxNum ; ++ i) { - // controllo se sono nel voxel corrente - if ( i * m_dStep < dZ && ( i + 1) * m_dStep > dZ) { - nK = i ; - break ; + // Scorro i Voxel correnti + for ( int nVox = 0 ; nVox < nVoxNum ; ++ nVox) { + // Considero solo i Voxel interni all'intervallo corrente + if ( dZMin - m_dStep / 2. < nVox * m_dStep && nVox * m_dStep < dZMax + m_dStep / 2.) { + // recupero gli indici per la griglia successiva + int nMyGrid = ( nGrid + 1) % 3 ; + int nMyI = nJ ; + int nMyJ = nVox ; + int nMyK = nI ; + double dMyMinZ = nMyK * m_dStep ; // shift di -Step / 2 + double dMyMaxZ = ( nMyK + 1) * m_dStep ; // shift di Step / 2 + Vector3d vtMyMaxN = ( vtToolMax.IsValid() ? vtToolMax : + nMyGrid == 0 ? m_MapFrame.VersZ() : + nMyGrid == 1 ? m_MapFrame.VersX() : + m_MapFrame.VersY()) ; + Vector3d vtMyMinN = ( vtToolMin.IsValid() ? vtToolMin : - vtMyMaxN) ; + if ( bAdd) + AddIntervals( nMyGrid, nMyI, nMyJ, dMyMinZ, dMyMaxZ, vtMyMinN, vtMyMaxN, nToolNum, true) ; + else + SubtractIntervals( nMyGrid, nMyI, nMyJ, dMyMinZ, dMyMaxZ, vtMyMinN, vtMyMaxN, nToolNum, true) ; + // recupero gli indici della griglia precedente + nMyGrid = ( nGrid + 2) % 3 ; + nMyI = nVox ; + nMyJ = nI ; + nMyK = nJ ; + dMyMinZ = nMyK * m_dStep ; // shift di -Step / 2 + dMyMaxZ = ( nMyK + 1) * m_dStep ; // shift di Step / 2 + vtMyMaxN = ( vtToolMax.IsValid() ? vtToolMax : + nMyGrid == 0 ? m_MapFrame.VersZ() : + nMyGrid == 1 ? m_MapFrame.VersX() : + m_MapFrame.VersY()) ; + vtMyMinN = ( vtToolMin.IsValid() ? vtToolMin : - vtMyMaxN) ; + if ( bAdd) + AddIntervals( nMyGrid, nMyI, nMyJ, dMyMinZ, dMyMaxZ, vtMyMinN, vtMyMaxN, nToolNum, true) ; + else + SubtractIntervals( nMyGrid, nMyI, nMyJ, dMyMinZ, dMyMaxZ, vtMyMinN, vtMyMaxN, nToolNum, true) ; } } - // ----------- griglia successiva ----------- - { - int nMyGrid = ( nGrid + 1) % 3 ; - int nMyI = nJ ; - int nMyJ = nK ; - int nMyK = nI ; - double dMyMin ; - double dMyMax ; - Vector3d vtMyMin ; - Vector3d vtMyMax ; - AddSubIntervalInVoxel( VolZmapRef, nMyGrid, nMyI, nMyJ, nMyK, dMyMin, dMyMax, vtMyMin, vtMyMax) ; - AddIntervals( nMyGrid, nMyI, nMyJ, dMyMin - EPS_SMALL, dMyMax + EPS_SMALL, vtMyMin, vtMyMax, - nToolNum, true) ; - } - - // ----------- griglia precedente ----------- - { - int nMyGrid = ( nGrid + 2) % 3 ; - int nMyI = nK ; - int nMyJ = nI ; - int nMyK = nJ ; - double dMyMin ; - double dMyMax ; - Vector3d vtMyMin ; - Vector3d vtMyMax ; - AddSubIntervalInVoxel( VolZmapRef, nMyGrid, nMyI, nMyJ, nMyK, dMyMin, dMyMax, vtMyMin, vtMyMax) ; - AddIntervals( nMyGrid, nMyI, nMyJ, dMyMin - EPS_SMALL, dMyMax + EPS_SMALL, vtMyMin, vtMyMax, - nToolNum, true) ; - } - return true ; - } // ------------------------- BOUNDING BOX --------------------------------------------------------------------------------------