diff --git a/EgtGeomKernel.rc b/EgtGeomKernel.rc index f1cdf97..dc4787c 100644 Binary files a/EgtGeomKernel.rc and b/EgtGeomKernel.rc differ diff --git a/PolyLine.cpp b/PolyLine.cpp index 1e00cea..6a200a8 100644 --- a/PolyLine.cpp +++ b/PolyLine.cpp @@ -1331,9 +1331,6 @@ IsPointInsidePolyLine( const Point3d& ptP, const PolyLine& plPoly, double dToler double dArea ; if ( ! plPoly.IsClosedAndFlat( plPlane, dArea, 10 * EPS_SMALL)) return false ; - // Impongo l'orientamento CCW - if ( dArea < 0) - plPlane.Invert() ; // Il punto deve giacere nel piano della polilinea if ( ! PointInPlaneEpsilon( ptP, plPlane, 10 * EPS_SMALL)) return false ; @@ -1367,7 +1364,7 @@ IsPointInsidePolyLine( const Point3d& ptP, const PolyLine& plPoly, double dToler if ( prev( itMinDistEnd) != List.begin()) vtPrevTg = prev( itMinDistEnd)->first - prev( itMinDistEnd, 2)->first ; else - vtPrevTg = prev( itMinDistEnd)->first - prev( List.rbegin())->first ; + vtPrevTg = prev( itMinDistEnd)->first - next( List.rbegin())->first ; vtPrevTg.Normalize() ; // tangente media vtTang = vtPrevTg + vtCurrTg ; diff --git a/SurfFlatRegion.cpp b/SurfFlatRegion.cpp index 286c9fc..6482889 100644 --- a/SurfFlatRegion.cpp +++ b/SurfFlatRegion.cpp @@ -19,6 +19,7 @@ #include "NgeReader.h" #include "CurveAux.h" #include "CurveComposite.h" +#include "CurveLine.h" #include "AdjustLoops.h" #include "GeoConst.h" #include "/EgtDev/Include/EGkStringUtils3d.h" @@ -576,7 +577,7 @@ SurfFlatRegion::GetLocalBBox( BBox3d& b3Loc, int nFlag) const // è il bounding box dei loop esterni for ( auto i : m_vExtInd) { BBox3d b3Tmp ; - if ( m_vpLoop[i]->GetBBox( m_frF, b3Loc, nFlag)) + if ( m_vpLoop[i]->GetBBox( m_frF, b3Tmp, nFlag)) b3Loc.Add( b3Tmp) ; } return ( ! b3Loc.IsEmpty()) ; @@ -1354,3 +1355,244 @@ SurfFlatRegion::GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion& return REGC_INTERS ; } } + +//---------------------------------------- +bool +SurfFlatRegion::GetZigZagInfill( double dStep, bool bStepCorrection, bool bInvert, ICRVCOMPOPOVECTOR& vpCrvs) const +{ + // ingombro della regione + BBox3d b3Pocket ; + GetLocalBBox( b3Pocket) ; + Point3d ptMin ; double dDimX, dDimY, dDimZ ; + b3Pocket.GetMinDim( ptMin, dDimX, dDimY, dDimZ) ; + + // lunghezza dei contorni + DBLVECTOR vLen( m_vpLoop.size()) ; + for ( size_t i = 0 ; i < vLen.size() ; i++) + m_vpLoop[i]->GetLength( vLen[i]) ; + + // passi in Y + double dYStep = dStep ; + int nYStep = static_cast( floor( dDimY / dStep)) ; + if ( bStepCorrection) { + // se permesso, lo modifico per coprire uniformemente la regione + nYStep = static_cast( ceil( ( dDimY - 30 * EPS_SMALL) / dStep)) ; + dYStep = ( nYStep > 0 ? ( dDimY - 30 * EPS_SMALL) / nYStep : 0) ; + } + int nRef = ( ( nYStep + ( bInvert ? 0 : 1)) % 2) ; + + // tratto valido + struct Section { + bool bActive ; + Point3d ptS ; + Point3d ptE ; + double dOs ; + double dOe ; + size_t nIdxS ; // indice del loop a cui appartiene ptS + size_t nIdxE ; // indice del loop a cui appartiene ptE + } ; + // raccolta di tratti + typedef vector> VECVECSECT ; + + VECVECSECT vvSec ; + vvSec.resize( nYStep + 1) ; + + // calcolo le linee di svuotatura + int nCount = 0 ; + for ( int i = 0 ; i <= nYStep ; ++ i) { + // determino senso + bool bPlus = (( i % 2) == nRef) ; + // definisco la linea + PtrOwner pLine( CreateBasicCurveLine()) ; + const double EXP_LEN = 1.0 ; + Point3d ptStart( ptMin.x - EXP_LEN, ptMin.y + 10 * EPS_SMALL + i * dYStep, ptMin.z + dDimZ) ; + if ( IsNull( pLine) || ! pLine->SetPVL( ptStart, X_AX , dDimX + 2 * EXP_LEN)) { + return false ; + } + + // calcolo la classificazione della curva rispetto alla regione + CRVCVECTOR ccClass ; + if ( ! GetCurveClassification( *pLine, EPS_SMALL, ccClass)) + return false ; + + // determino gli intervalli di curva da conservare + Intervals inOk ; + for ( auto& ccOne : ccClass) { + if ( ccOne.nClass == CRVC_IN || ccOne.nClass == CRVC_ON_P || ccOne.nClass == CRVC_ON_M) + inOk.Add( ccOne.dParS, ccOne.dParE) ; + } + // inserisco i tratti validi (secondo X+ i pari, secondo X- i dispari) + double dParS, dParE ; + bool bFound = ( bPlus ? inOk.GetFirst( dParS, dParE) : inOk.GetLast( dParE, dParS)) ; + while ( bFound) { + // determino i dati della sezione + Section Sect ; + Sect.bActive = true ; + pLine->GetPointD1D2( dParS, ICurve::FROM_PLUS, Sect.ptS) ; + pLine->GetPointD1D2( dParE, ICurve::FROM_MINUS, Sect.ptE) ; + + // porto i punti nel riferimento della curva + if ( ! AreSameFrame( m_frF, GLOB_FRM)) { + Sect.ptS.ToLoc( m_frF) ; + Sect.ptE.ToLoc( m_frF) ; + } + + // cerco la curva della regione che passa per ptS + bool bCrvFound = false ; + for ( size_t k = 0 ; ! bCrvFound && k < m_vpLoop.size() ; k++) { + bCrvFound = m_vpLoop[k]->GetParamAtPoint( Sect.ptS, Sect.dOs, 10 * EPS_SMALL) ; + if ( bCrvFound) + Sect.nIdxS = k ; + } + if ( ! bCrvFound) + return false ; + + // cerco la curva della regione che passa per ptE + bCrvFound = false ; + for ( size_t k = 0 ; ! bCrvFound && k < m_vpLoop.size() ; k++) { + bCrvFound = m_vpLoop[k]->GetParamAtPoint( Sect.ptE, Sect.dOe, 10 * EPS_SMALL) ; + if ( bCrvFound) + Sect.nIdxE = k ; + } + if ( ! bCrvFound) + return false ; + + // inserisco nel contenitore + vvSec[i].emplace_back( Sect) ; + ++ nCount ; + // recupero intervallo successivo + bFound = ( bPlus ? inOk.GetNext( dParS, dParE) : inOk.GetPrev( dParE, dParS)) ; + } + } + + // dominio del contorno + DBLVECTOR vUmax( m_vpLoop.size()) ; + DBLVECTOR vUmin( m_vpLoop.size()) ; + DBLVECTOR vUspan( m_vpLoop.size()) ; + for ( size_t i = 0 ; i < m_vpLoop.size() ; i++) { + m_vpLoop[i]->GetDomain( vUmin[i], vUmax[i]) ; + vUspan[i] = vUmax[i] - vUmin[i] ; + } + + // creo i percorsi di svuotatura + vpCrvs.reserve( nCount) ; + int nI = -1, nJ = -1 ; + while ( true) { + // se sezione non valida + if ( nI < 0 || nJ < 0) { + // ricerco la prima valida + for ( int k = 0 ; k < int( vvSec.size()) && nI < 0 ; ++ k) { + for ( int l = 0 ; l < int( vvSec[k].size()) && nJ < 0 ; ++ l) { + if ( vvSec[k][l].bActive) { + nI = k ; + nJ = l ; + } + } + } + // se trovata, creo nuova curva composita + if ( nI >= 0 && nJ >= 0) { + // creo la curva + vpCrvs.emplace_back( CreateCurveComposite()) ; + // aggiungo punto iniziale + vpCrvs.back()->AddPoint( vvSec[nI][nJ].ptS) ; + } + // altrimenti, esco + else + break ; + } + // determino senso + bool bPlus = (( nI % 2) == nRef) ; + // aggiungo la sezione alla curva + Section& Sec = vvSec[nI][nJ] ; + Sec.bActive = false ; + vpCrvs.back()->AddLine( vvSec[nI][nJ].ptE) ; + // cerco nella stessa fila o in quella successiva sezione successiva raccordabile tramite il contorno + double dUstart = Sec.dOe ; + double dUref = ( bPlus ? INFINITO : - INFINITO) ; + int nNextI = -1 ; + int nNextJ = -1 ; + int li = nJ + 1 ; + for ( int k = nI ; k <= nI + 1 && k < int( vvSec.size()) ; ++ k) { + for ( int l = li ; l < int( vvSec[k].size()) ; ++ l) { + if ( ! vvSec[k][l].bActive) + continue ; + // la nuova sezione deve partire dalla stessa curva su cui ci si è fermati + if ( vvSec[k][l].nIdxS != Sec.nIdxE) + continue ; + double dU = vvSec[k][l].dOs ; + if ( bPlus) { + if ( dU < dUstart) + dU += vUspan[Sec.nIdxE] ; + if ( dU < dUref) { + dUref = dU ; + nNextI = k ; + nNextJ = l ; + } + } + else { + if ( dU > dUstart) + dU -= vUspan[Sec.nIdxE] ; + if ( dU > dUref) { + dUref = dU ; + nNextI = k ; + nNextJ = l ; + } + } + } + li = 0 ; + } + // se trovato, aggiungo il tratto di contorno e continuo + if ( nNextI != -1) { + PtrOwner pCopy ; + size_t idx = vvSec[nNextI][nNextJ].nIdxS ; + if ( bPlus) { + if ( dUref > vUmax[idx]) + dUref -= vUspan[idx] ; + pCopy.Set( m_vpLoop[idx]->CopyParamRange( dUstart, dUref)) ; + if ( ! IsNull( pCopy)) { + double dCLen ; pCopy->GetLength( dCLen) ; + if ( dCLen > 0.5 * vLen[idx]) { + pCopy.Set( m_vpLoop[idx]->CopyParamRange( dUref, dUstart)) ; + if ( ! IsNull( pCopy)) + pCopy->Invert() ; + } + } + } + else { + if ( dUref < vUmin[idx]) + dUref += vUspan[idx] ; + pCopy.Set( m_vpLoop[idx]->CopyParamRange( dUref, dUstart)) ; + if ( ! IsNull( pCopy)) { + pCopy->Invert() ; + double dCLen ; pCopy->GetLength( dCLen) ; + if ( dCLen > 0.5 * vLen[idx]) + pCopy.Set( m_vpLoop[idx]->CopyParamRange( dUstart, dUref)) ; + } + } + BBox3d b3Copy ; + if ( ! IsNull( pCopy)) + pCopy->GetBBox( m_frF, b3Copy) ; + if ( ! b3Copy.IsEmpty() && ( b3Copy.GetMax().y - b3Copy.GetMin().y) < dYStep + 10 * EPS_SMALL) { + vpCrvs.back()->AddCurve( Release( pCopy)) ; + nI = nNextI ; + nJ = nNextJ ; + } + else { + nI = -1 ; + nJ = -1 ; + } + } + else { + nI = -1 ; + nJ = -1 ; + } + } + + // porto le curve calcolate nel riferimento globale + if ( ! AreSameFrame( m_frF, GLOB_FRM)) { + for ( int i = 0 ; i < ( int) vpCrvs.size() ; i++) + vpCrvs[i]->ToGlob( m_frF) ; + } + + return true ; +} \ No newline at end of file diff --git a/SurfFlatRegion.h b/SurfFlatRegion.h index 88a9700..37d8195 100644 --- a/SurfFlatRegion.h +++ b/SurfFlatRegion.h @@ -18,6 +18,7 @@ #include "GeoObjRW.h" #include "SurfTriMesh.h" #include "/EgtDev/Include/EGkCurve.h" +#include "/EgtDev/Include/EGkCurveComposite.h" #include "/EgtDev/Include/EGkSurfFlatRegion.h" #include @@ -94,6 +95,7 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW bool GetChunkCentroid( int nChunk, Point3d& ptCen) const override ; bool GetCurveClassification( const ICurve& Crv, double dLenMin, CRVCVECTOR& ccClass) const override ; int GetChunkSimpleClassification( int nChunk, const ISurfFlatRegion& Other, int nOthChunk) const override ; // compare only outsides + bool GetZigZagInfill( double dStep, bool bStepCorrection, bool bInvert, ICRVCOMPOPOVECTOR& vpCrvs) const override ; public : // IGeoObjRW int GetNgeId( void) const override ; @@ -136,7 +138,7 @@ class SurfFlatRegion : public ISurfFlatRegion, public IGeoObjRW int nType1, bool bInvert1, int nType2, bool bInvert2, PCRV_DEQUE& vpCurve) ; static bool MyChainCurves( PCRV_DEQUE& vpCurve, PCRV_DEQUE& vpLoop) ; static SurfFlatRegion* MyNewSurfFromLoops( PCRV_DEQUE& vpLoop) ; - static bool MyTestAndDelete( PCRV_DEQUE& vpCrv) ; + static bool MyTestAndDelete( PCRV_DEQUE& vpCrv) ; private : ObjGraphicsMgr m_OGrMgr ; // gestore grafica dell'oggetto