diff --git a/EXE_GdbCreateCurve.cpp b/EXE_GdbCreateCurve.cpp index 1d86f5d..2ae84b8 100644 --- a/EXE_GdbCreateCurve.cpp +++ b/EXE_GdbCreateCurve.cpp @@ -1627,10 +1627,13 @@ MyCreateCurveCompoByChain( int nParentId, const INTVECTOR& vIds, // estrusione e spessore Vector3d vtExtr = CalcExtrusion( pGeomDB, nParentId, nRefType) ; double dThick = 0 ; + // vettore con elenco Id curve originali + INTVECTOR vOrig ; // recupero le curve semplici e le inserisco nella curva composita for ( size_t i = 0 ; i < vId2s.size() ; ++ i) { int nId = abs( vId2s[i]) ; bool bInvert = ( vId2s[i] < 0) ; + vOrig.push_back( nId) ; // recupero la curva e il suo riferimento ICurve* pCrv = GetCurve( pGeomDB->GetGeoObj( nId)) ; if ( pCrv == nullptr) @@ -1683,6 +1686,9 @@ MyCreateCurveCompoByChain( int nParentId, const INTVECTOR& vIds, if ( nFirstId == GDB_ID_NULL) nFirstId = nNewId ; ++ nCount ; + // assegno nota con curve originali + if ( ! bErase) + pGeomDB->SetInfo( nNewId, "ORIG", vOrig) ; } // se richiesto e ok, cancello le curve originali if ( bErase && nFirstId != GDB_ID_NULL) { diff --git a/EXE_GdbCreateSurf.cpp b/EXE_GdbCreateSurf.cpp index e29c1cf..41f65fe 100644 --- a/EXE_GdbCreateSurf.cpp +++ b/EXE_GdbCreateSurf.cpp @@ -345,9 +345,14 @@ ExeCreateSurfTmByRegion( int nParentId, INTVECTOR& vCrvIds, double dLinTol) ICURVEPVECTOR vCrvP ; vCrvP.reserve( vCrvIds.size()) ; for ( size_t i = 0 ; i < vCrvIds.size() ; ++ i) { - vCrvLoc.emplace_back( pGeomDB, vCrvIds[i], frLoc) ; - vCrvP.push_back( const_cast( vCrvLoc[i].Get())) ; - bOk = bOk && ( vCrvLoc[i].Get() != nullptr) ; + int nId = (( vCrvIds[i] != GDB_ID_SEL) ? vCrvIds[i] : pGeomDB->GetFirstSelectedObj()) ; + while ( nId != GDB_ID_NULL) { + vCrvLoc.emplace_back( pGeomDB, nId, frLoc) ; + vCrvP.push_back( const_cast( vCrvLoc.back().Get())) ; + bOk = bOk && ( vCrvLoc[i].Get() != nullptr) ; + // passo al successivo + nId = (( vCrvIds[i] != GDB_ID_SEL) ? GDB_ID_NULL : pGeomDB->GetNextSelectedObj()) ; + } } // calcolo la superficie ISurfTriMesh* pSTM = ( bOk ? GetSurfTriMeshByRegion( vCrvP, dLinTol) : nullptr) ; @@ -391,9 +396,14 @@ ExeCreateSurfTmByExtrusion( int nParentId, INTVECTOR& vCrvIds, const Vector3d& v ICURVEPVECTOR vCrvP ; vCrvP.reserve( vCrvIds.size()) ; for ( size_t i = 0 ; i < vCrvIds.size() ; ++ i) { - vCrvLoc.emplace_back( pGeomDB, vCrvIds[i], frLoc) ; - vCrvP.push_back( const_cast( vCrvLoc[i].Get())) ; - bOk = bOk && ( vCrvLoc[i].Get() != nullptr) ; + int nId = (( vCrvIds[i] != GDB_ID_SEL) ? vCrvIds[i] : pGeomDB->GetFirstSelectedObj()) ; + while ( nId != GDB_ID_NULL) { + vCrvLoc.emplace_back( pGeomDB, nId, frLoc) ; + vCrvP.push_back( const_cast( vCrvLoc.back().Get())) ; + bOk = bOk && ( vCrvLoc[i].Get() != nullptr) ; + // passo al successivo + nId = (( vCrvIds[i] != GDB_ID_SEL) ? GDB_ID_NULL : pGeomDB->GetNextSelectedObj()) ; + } } // porto in locale il vettore estrusione Vector3d vtExtrL = GetVectorLocal( pGeomDB, vtExtr, nRefType, frLoc) ; diff --git a/EXE_GdbModifyCurve.cpp b/EXE_GdbModifyCurve.cpp index 5eab9e7..e4449a7 100644 --- a/EXE_GdbModifyCurve.cpp +++ b/EXE_GdbModifyCurve.cpp @@ -874,7 +874,7 @@ ExeMergeCurvesInCurveCompo( int nId, double dLinTol) } //------------------------------------------------------------------------------- -int +bool ExeApproxCurve( int nId, int nApprType, double dLinTol) { IGeomDB* pGeomDB = GetCurrGeomDB() ; @@ -896,6 +896,9 @@ ExeApproxCurve( int nId, int nApprType, double dLinTol) else { // con bi-archi PolyArc PA ; bOk = bOk && pCurve->ApproxWithArcsEx( dLinTol, ANG_TOL_MAX_DEG, LIN_FEA_LEN_STD, PA) && pCC->FromPolyArc( PA) ; + // merge di archi identici di biarchi + const double ANG_TOL_STD_DEG = 15 ; + bOk = bOk && pCC->MergeCurves( 0.5 * dLinTol, ANG_TOL_STD_DEG) ; } // copio estrusione e spessore Vector3d vtExtr ; @@ -904,22 +907,17 @@ ExeApproxCurve( int nId, int nApprType, double dLinTol) double dThick ; if ( bOk && pCurve->GetThickness( dThick)) pCC->SetThickness(dThick) ; - // inserisco la curva composita nello stesso posto del GeomDB - int nCrvId = ( bOk ? pGeomDB->InsertGeoObj( GDB_ID_NULL, nId, GDB_BEFORE, Release( pCC)) : GDB_ID_NULL) ; - bOk = bOk && ( nCrvId != GDB_ID_NULL) ; - // copio gli attributi - bOk = bOk && pGeomDB->CopyAttributes( nId, nCrvId) ; - // elimino la curva originale - bOk = bOk && pGeomDB->Erase( nId) ; + // sostituisco la vecchia curva con la nuova + bOk = bOk && pGeomDB->ReplaceGeoObj( nId, Release( pCC)) ; ExeSetModified() ; // se richiesto, salvo il comando Lua equivalente if ( IsCmdLog()) { string sLua = "EgtApproxCurve(" + ToString( nId) + "," + ApproxTypeToString( nApprType) + "," + ToString( dLinTol) + ")" + - " -- Id=" + ToString( nCrvId) ; + " -- Ok=" + ToString( bOk) ; LOG_INFO( GetCmdLogger(), sLua.c_str()) ; } // restituisco risultato - return nCrvId ; + return bOk ; } diff --git a/EXE_GdbPartLayers.cpp b/EXE_GdbPartLayers.cpp index a9c465d..7af4a84 100644 --- a/EXE_GdbPartLayers.cpp +++ b/EXE_GdbPartLayers.cpp @@ -51,6 +51,19 @@ ExeVerifyOrNext( IGeomDB* pGeomDB, int nId, bool bOnlyVisible) return GDB_ID_NULL ; } +//------------------------------------------------------------------------------- +static int +ExeVerifyOrPrev( IGeomDB* pGeomDB, int nId, bool bOnlyVisible) +{ + while ( nId != GDB_ID_NULL) { + if ( ExeIsUserObj( pGeomDB, nId) && + ( ! bOnlyVisible || ExeIsVisibleObj( pGeomDB, nId))) + return nId ; + nId = pGeomDB->GetPrevGroup( nId) ; + } + return GDB_ID_NULL ; +} + //------------------------------------------------------------------------------- bool ExeIsPart( int nPartId) @@ -224,6 +237,30 @@ ExeGetNextPart( int nId, bool bOnlyVisible) return ExeVerifyOrNext( pGeomDB, nPartId, bOnlyVisible) ; } +//------------------------------------------------------------------------------- +int +ExeGetLastPart( bool bOnlyVisible) +{ + IGeomDB* pGeomDB = GetCurrGeomDB() ; + VERIFY_GEOMDB( pGeomDB, GDB_ID_NULL) + // recupero l'ultimo gruppo sotto la radice + int nPartId = pGeomDB->GetLastGroupInGroup( GDB_ID_ROOT) ; + // verifico oppure passo al primo precedente valido + return ExeVerifyOrPrev( pGeomDB, nPartId, bOnlyVisible) ; +} + +//------------------------------------------------------------------------------- +int +ExeGetPrevPart( int nId, bool bOnlyVisible) +{ + IGeomDB* pGeomDB = GetCurrGeomDB() ; + VERIFY_GEOMDB( pGeomDB, GDB_ID_NULL) + // recupero il precedente gruppo + int nPartId = pGeomDB->GetPrevGroup( nId) ; + // verifico oppure passo al primo precedente valido + return ExeVerifyOrPrev( pGeomDB, nPartId, bOnlyVisible) ; +} + //------------------------------------------------------------------------------- int ExeGetFirstLayer( int nPartId, bool bOnlyVisible) @@ -252,6 +289,34 @@ ExeGetNextLayer( int nId, bool bOnlyVisible) return ExeVerifyOrNext( pGeomDB, nLayerId, bOnlyVisible) ; } +//------------------------------------------------------------------------------- +int +ExeGetLastLayer( int nPartId, bool bOnlyVisible) +{ + IGeomDB* pGeomDB = GetCurrGeomDB() ; + VERIFY_GEOMDB( pGeomDB, GDB_ID_NULL) + // verifico il pezzo (livello utente e se richiesto visibile) + if ( ! ExeIsUserObj( pGeomDB, nPartId) || + ( bOnlyVisible && ! ExeIsVisibleObj( pGeomDB, nPartId))) + return GDB_ID_NULL ; + // recupero l'ultimo layer nel pezzo + int nLayerId = pGeomDB->GetLastGroupInGroup( nPartId) ; + // verifico oppure passo al primo precedente valido + return ExeVerifyOrPrev( pGeomDB, nLayerId, bOnlyVisible) ; +} + +//------------------------------------------------------------------------------- +int +ExeGetPrevLayer( int nId, bool bOnlyVisible) +{ + IGeomDB* pGeomDB = GetCurrGeomDB() ; + VERIFY_GEOMDB( pGeomDB, GDB_ID_NULL) + // recupero il precedente gruppo + int nLayerId = pGeomDB->GetPrevGroup( nId) ; + // verifico sia visibile oppure passo al primo precedente visibile + return ExeVerifyOrPrev( pGeomDB, nLayerId, bOnlyVisible) ; +} + //------------------------------------------------------------------------------- bool ExeEraseEmptyParts( void) diff --git a/EXE_Nesting.cpp b/EXE_Nesting.cpp new file mode 100644 index 0000000..01e0f08 --- /dev/null +++ b/EXE_Nesting.cpp @@ -0,0 +1,524 @@ +//---------------------------------------------------------------------------- +// EgalTech 2015-2015 +//---------------------------------------------------------------------------- +// File : EXE_Nesting.cpp Data : 20.09.14 Versione : 1.6e1 +// Contenuto : Funzioni Nesting per EXE. +// +// +// +// Modifiche : 20.09.14 DS Creazione modulo. +// +// +//---------------------------------------------------------------------------- + +//--------------------------- Include ---------------------------------------- +#include "stdafx.h" +#include "EXE.h" +#include "EXE_Macro.h" +#include "/EgtDev/Include/EXeExecutor.h" +#include "/EgtDev/Include/EXeConst.h" +#include "/EgtDev/Include/EGkCurveComposite.h" +#include "/EgtDev/Include/EGkIntersCurves.h" +#include "/EgtDev/Include/EGkStmFromCurves.h" +#include "/EgtDev/Include/EGkGdbIterator.h" +#include "/EgtDev/Include/EGkIntervals.h" +#include "/EgtDev/Include/EgtPointerOwner.h" + +using namespace std ; + +//---------------------------------------------------------------------------- +static bool +ApproxCurveIfNeeded( IGdbIterator* pEnt) +{ + const double LIN_TOL_STD = 0.25 ; + const double ANG_TOL_STD_DEG = 15 ; + const double LIN_FEA_STD = 20 ; + // deve essere una curva + int nGeoType = pEnt->GetGeoType() ; + if ( (nGeoType & GEO_CURVE) == 0) + return false ; + // verifico se da approssimare + if ( nGeoType == CRV_LINE || nGeoType == CRV_ARC) + return true ; + else if ( nGeoType == CRV_COMPO) { + ICurveComposite* pCrvCo = GetCurveComposite( pEnt->GetGeoObj()) ; + double dLen ; + pCrvCo->GetLength( dLen) ; + int nCrvs = pCrvCo->GetCurveNumber() ; + if ( nCrvs <= 5 && dLen > nCrvs * LIN_FEA_STD) + return true ; + } + // esecuzione dell'approssimazione + ICurve* pCrv = GetCurve( pEnt->GetGeoObj()) ; + PtrOwner pCC( CreateCurveComposite()) ; + PolyArc PA ; + bool bOk = pCrv->ApproxWithArcsEx( LIN_TOL_STD, ANG_TOL_STD_DEG, LIN_FEA_STD, PA) && pCC->FromPolyArc( PA) ; + bOk = bOk && pEnt->GetGDB()->ReplaceGeoObj( pEnt->GetId(), Release( pCC)) ; + return bOk ; +} + +//---------------------------------------------------------------------------- +static bool +FilterAndApprox( void) +{ + IGeomDB* pGeomDB = GetCurrGeomDB() ; + VERIFY_GEOMDB( pGeomDB, false) + // preparo gli iteratori + PtrOwner pPar( CreateGdbIterator( pGeomDB)) ; + PtrOwner pLay( CreateGdbIterator( pGeomDB)) ; + PtrOwner pEnt( CreateGdbIterator( pGeomDB)) ; + if ( IsNull( pPar) || IsNull( pLay) || IsNull( pEnt)) + return false ; + // ciclo su tutti gli oggetti del DB geometrico + bool bPok = pPar->GoToFirstInGroup( GDB_ID_ROOT) ; + while ( bPok) { + // sotto la radice sono ammessi solo gruppi di livello User -> Pezzi + int nLev ; + if ( pPar->GetGdbType() != GDB_TY_GROUP || + ! pPar->GetCalcLevel( nLev) || nLev != GDB_LV_USER) { + bPok = pPar->EraseAndGoToNext() ; + continue ; + } + // ciclo su tutti gli oggetti del pezzo + bool bLok = pLay->GoToFirstInGroup( *Get( pPar)) ; + while ( bLok) { + // sotto ogni pezzo sono ammessi solo gruppi di livello User -> Layer + int nLev ; + if ( pLay->GetGdbType() != GDB_TY_GROUP || + ! pLay->GetCalcLevel( nLev) || nLev != GDB_LV_USER) { + bLok = pLay->EraseAndGoToNext() ; + continue ; + } + // ciclo su tutti gli oggetti del layer + bool bEok = pEnt->GoToFirstInGroup( *Get( pLay)) ; + while ( bEok) { + // sotto ogni layer sono ammesse solo curve di livello User + int nLev ; + if ( ( pEnt->GetGeoType() & GEO_CURVE) == 0 || + ! pEnt->GetCalcLevel( nLev) || nLev != GDB_LV_USER) { + bEok = pEnt->EraseAndGoToNext() ; + continue ; + } + // eventuale approx della curva se Bezier o Composita con molti piccoli segmenti + ApproxCurveIfNeeded( Get( pEnt)) ; + // passo alla successiva entità + bEok = pEnt->GoToNext() ; + } + // passo al successivo layer + bLok = pLay->GoToNext() ; + } + // passo al successivo pezzo + bPok = pPar->GoToNext() ; + } + return true ; +} + +//---------------------------------------------------------------------------- +static bool +ChainCurves( int& nLay) +{ + // seleziono tutte le curve + bool bOk = ExeSelectAll( false) ; + // creo un nuovo pezzo con layer in cui mettere tutti i concatenati + int nPart = ExeCreateGroup( GDB_ID_ROOT, Frame3d(), RTY_GLOB) ; + nLay = ExeCreateGroup( nPart, Frame3d(), RTY_GLOB) ; + bOk = bOk && nLay != GDB_ID_NULL ; + // concateno tutte le curve + INTVECTOR vIds ; + vIds.push_back( GDB_ID_SEL) ; + int nCount ; + int nFirstId = ( bOk ? ExeCreateCurveCompoByChain( nLay, vIds, ORIG, true, RTY_GLOB, &nCount) : GDB_ID_NULL) ; + bOk = bOk && nFirstId != GDB_ID_NULL ; + // cancello i gruppi rimasti vuoti + ExeEraseEmptyParts() ; + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +CreateFlatPartsByRegions( int nLay) +{ + IGeomDB* pGeomDB = GetCurrGeomDB() ; + VERIFY_GEOMDB( pGeomDB, false) + // recupero il padre del layer + int nParentId = pGeomDB->GetParentId( nLay) ; + // preparo gli iteratori + PtrOwner pEnt( CreateGdbIterator( pGeomDB)) ; + if ( IsNull( pEnt)) + return false ; + // separo le curve aperte da quelle chiuse e salvo vettore aree di quest ultime + INTVECTOR vOpenIds ; + INTVECTOR vClosedIds ; + typedef std::pair INDAREA ; // coppia indice, area + typedef std::vector INDAREAVECTOR ; // vettore di coppie indice, area + INDAREAVECTOR vArea ; + bool bEok = pEnt->GoToFirstInGroup( nLay) ; + while ( bEok) { + ICurve* pCrv = GetCurve( pEnt->GetGeoObj()) ; + if ( pCrv == nullptr) { + bEok = pEnt->EraseAndGoToNext() ; + } + else if ( ! pCrv->IsClosed()) { + vOpenIds.push_back( pEnt->GetId()) ; + bEok = pEnt->GoToNext() ; + } + else { + vClosedIds.push_back( pEnt->GetId()) ; + double dArea ; + pCrv->GetAreaXY( dArea) ; + if ( fabs( dArea) > 1) { + if ( dArea < 0) { + pCrv->Invert() ; + dArea = - dArea ; + } + vArea.emplace_back( pEnt->GetId(), dArea) ; + } + else + vOpenIds.push_back( pEnt->GetId()) ; + bEok = pEnt->GoToNext() ; + } + } + // ordino le aree in senso decrescente + sort( vArea.begin(), vArea.end(), + []( const INDAREA& a, const INDAREA&b) { return fabs( a.second) > fabs( b.second) ; }) ; + // creo i pezzi a partire dalle curve chiuse più grandi e dalle curve che vi sono contenute + for ( int i = 0 ; i < int( vArea.size()) ; ++ i) { + if ( vArea[i].first == GDB_ID_NULL) + continue ; + // creo pezzo con questa geometria + int nPartId = pGeomDB->InsertGroup( GDB_ID_NULL, nParentId, GDB_BEFORE, Frame3d()) ; + // creo layer nel pezzo + int nLayId = pGeomDB->AddGroup( GDB_ID_NULL, nPartId, Frame3d()) ; + // sposto il contorno nel pezzo + pGeomDB->RelocateGlob( vArea[i].first, nLayId) ; + // cerco altri contorni chiusi che siano contenuti completamente o parzialmente + ICurve* pCrv = GetCurve( pGeomDB->GetGeoObj( vArea[i].first)) ; + for ( int j = i + 1 ; j < int( vArea.size()) ; ++ j) { + if ( vArea[j].first == GDB_ID_NULL) + continue ; + ICurve* pCrv2 = GetCurve( pGeomDB->GetGeoObj( vArea[j].first)) ; + // intersezione e classificazione + CRVCVECTOR ccClass ; + IntersCurveCurve intCC( *pCrv2, *pCrv) ; + if ( ! intCC.GetCurveClassification( 0, ccClass)) + continue ; + // se completamente interna + if ( ccClass.size() == 1 && ccClass[0].nClass == CRVC_IN) { + pGeomDB->RelocateGlob( vArea[j].first, nLayId) ; + vArea[j].first = GDB_ID_NULL ; + } + // se più di un tratto + else if ( ccClass.size() > 1) { + // verifico se parzialmente interna + bool bIn = false ; + bool bOther = false ; + for ( int k = 0 ; k < int( ccClass.size()) ; ++ k) { + if ( ccClass[k].nClass == CRVC_IN) + bIn = true ; + else + bOther = true ; + } + // se parzialmente interna, la sposto negli aperti + if ( bIn && bOther) { + vOpenIds.push_back( vArea[j].first) ; + vArea[j].first = GDB_ID_NULL ; + } + } + } + // verifico i contorni aperti che siano contenuti completamente o parzialmente + for ( int j = i + 1 ; j < int( vOpenIds.size()) ; ++ j) { + if ( vOpenIds[j] == GDB_ID_NULL) + continue ; + ICurve* pCrv2 = GetCurve( pGeomDB->GetGeoObj( vOpenIds[j])) ; + Intervals inCrv ; + double dParS, dParE ; + pCrv2->GetDomain( dParS, dParE) ; + inCrv.Set( dParS, dParE) ; + // intersezione e classificazione + CRVCVECTOR ccClass ; + IntersCurveCurve intCC( *pCrv2, *pCrv) ; + if ( ! intCC.GetCurveClassification( 0, ccClass)) + continue ; + // conservo solo le parti interne + for ( int k = 0 ; k < int( ccClass.size()) ; ++ k) { + if ( ccClass[k].nClass != CRVC_IN) + inCrv.Remove( ccClass[k].dParS, ccClass[k].dParE) ; + } + // tratti di curva rimasti + int nNum = inCrv.GetNumbers() ; + // se rimangono uno o più tratti + if ( nNum >= 1) { + double dParS, dParE ; + bool bInt = inCrv.GetFirst( dParS, dParE) ; + while ( bInt) { + // copio la curva e la modifico + int nCopyId = pGeomDB->Copy( vOpenIds[j], GDB_ID_NULL, nLayId) ; + // modifico l'originale + ICurve* pOriCrv = GetCurve( pGeomDB->GetGeoObj( nCopyId)) ; + pOriCrv->TrimStartEndAtParam( dParS, dParE) ; + // passo al successivo intervallo + bInt = inCrv.GetNext( dParS, dParE) ; + } + } + } + } + // elimino la geometria originale rimasta + pGeomDB->Erase( nParentId) ; + + return true ; +} + +//---------------------------------------------------------------------------- +static bool +CreateFlatPartsByLayers( void) +{ + IGeomDB* pGeomDB = GetCurrGeomDB() ; + VERIFY_GEOMDB( pGeomDB, false) + // preparo gli iteratori + PtrOwner pPar( CreateGdbIterator( pGeomDB)) ; + PtrOwner pLay( CreateGdbIterator( pGeomDB)) ; + if ( IsNull( pPar) || IsNull( pLay)) + return false ; + // ciclo su tutti i gruppi della radice (pezzi) + bool bPok = pPar->GoToFirstGroupInGroup( GDB_ID_ROOT) ; + int nFirstId = pPar->GetId() ; + while ( bPok) { + // ciclo su tutti i sottogruppi (layer) + bool bLok = pLay->GoToFirstGroupInGroup( *Get( pPar)) ; + while ( bLok) { + // creo pezzo con questa geometria + int nPartId = pGeomDB->InsertGroup( GDB_ID_NULL, nFirstId, GDB_BEFORE, Frame3d()) ; + // passo al pezzo l'eventuale nome del layer + string sName ; + if ( pLay->GetName( sName)) { + pGeomDB->SetName( nPartId, sName) ; + pLay->RemoveName() ; + } + // sposto il layer sotto questo pezzo + if ( ! pGeomDB->RelocateGlob( pLay->GetId(), nPartId)) + return false ; + // altro layer del gruppo originale + bLok = pLay->GoToFirstGroupInGroup( *Get( pPar)) ; + } + // passo al successivo + bPok = pPar->GoToNextGroup() ; + } + // cancello i gruppi svuotati + bPok = pPar->GoTo( nFirstId) ; + while ( bPok) + bPok = pPar->EraseAndGoToNext() ; + return true ; +} + +//---------------------------------------------------------------------------- +static bool +VerifyAndAdjustFlatParts( void) +{ + IGeomDB* pGeomDB = GetCurrGeomDB() ; + VERIFY_GEOMDB( pGeomDB, false) + // preparo gli iteratori + PtrOwner pPar( CreateGdbIterator( pGeomDB)) ; + PtrOwner pEnt( CreateGdbIterator( pGeomDB)) ; + if ( IsNull( pPar) || IsNull( pEnt)) + return false ; + // ciclo sui pezzi + bool bPok = pPar->GoToFirstGroupInGroup( GDB_ID_ROOT) ; + while ( bPok) { + // seleziono tutte le curve del pezzo + bool bOk = ExeSelectPartObjs( pPar->GetId()) ; + // creo un nuovo layer in cui mettere tutti i concatenati + int nRegId = ExeCreateGroup( pPar->GetId(), Frame3d(), RTY_GLOB) ; + bOk = bOk && nRegId != GDB_ID_NULL ; + bOk = bOk && pGeomDB->SetName( nRegId, "Region") ; + bOk = bOk && pGeomDB->SetLevel( nRegId, GDB_LV_SYSTEM) ; + // concateno tutte le curve + INTVECTOR vIds ; + vIds.push_back( GDB_ID_SEL) ; + int nCount ; + int nFirstId = ( bOk ? ExeCreateCurveCompoByChain( nRegId, vIds, ORIG, false, RTY_GLOB, &nCount) : GDB_ID_NULL) ; + bOk = bOk && nFirstId != GDB_ID_NULL ; + // deseleziono tutto + pGeomDB->ClearSelection() ; + // elimino le curve non chiuse e salvo i puntatori alle altre + INTVECTOR vOpenIds ; + ICURVEPVECTOR vCrvP ; + bool bEok = pEnt->GoToFirstInGroup( nRegId) ; + while ( bEok) { + ICurve* pCrv = GetCurve( pEnt->GetGeoObj()) ; + if ( pCrv == nullptr) { + bEok = pEnt->EraseAndGoToNext() ; + } + else if ( ! pCrv->IsClosed()) { + string sOrig ; + INTVECTOR vTmpIds ; + if ( pGeomDB->GetInfo( pEnt->GetId(), "ORIG", vTmpIds)) { + for ( auto Id : vTmpIds) + vOpenIds.push_back( Id) ; + } + bEok = pEnt->EraseAndGoToNext() ; + } + else { + vCrvP.push_back( pCrv) ; + bEok = pEnt->GoToNext() ; + } + } + // ne calcolo le aree, le ordino in senso decrescente + typedef std::pair INDAREA ; // coppia indice, area + typedef std::vector INDAREAVECTOR ; // vettore di coppie indice, area + INDAREAVECTOR vArea ; + vArea.reserve( vCrvP.size()) ; + for ( int i = 0 ; i < int( vCrvP.size()) ; ++ i) { + double dArea ; + vCrvP[i]->GetAreaXY( dArea) ; + vArea.emplace_back( i, dArea) ; + } + sort( vArea.begin(), vArea.end(), + []( const INDAREA& a, const INDAREA&b) { return fabs( a.second) > fabs( b.second) ; }) ; + // verifico e sistemo il senso di rotazione delle curve + for ( int i = 0 ; i < int( vArea.size()) ; ++ i) { + if ( ( i == 0 && vArea[i].second < 0) || ( i > 0 && vArea[i].second > 0)) + vCrvP[vArea[i].first]->Invert() ; + } + // creo il riempimento + ISurfTriMesh* pSTM = ( bOk ? GetSurfTriMeshByRegion( vCrvP, 0.1) : nullptr) ; + bOk = bOk && ( pSTM != nullptr) ; + // elimino punti ripetuti + bOk = bOk && pSTM->DoCompacting() ; + // inserisco la superficie nel DB + int nNewId = ( bOk ? pGeomDB->AddGeoObj( GDB_ID_NULL, nRegId, pSTM) : GDB_ID_NULL) ; + // assegno il colore + Color cCol = AQUA ; + cCol.SetAlpha( 0.3) ; + bOk = bOk && pGeomDB->SetMaterial( nNewId, cCol) ; + // taglio le curve aperte con i contorni + for ( int i = 0 ; i < int( vOpenIds.size()) ; ++i) { + ICurve* pCrv = GetCurve( pGeomDB->GetGeoObj( vOpenIds[i])) ; + Intervals inCrv ; + double dParS, dParE ; + pCrv->GetDomain( dParS, dParE) ; + inCrv.Set( dParS, dParE) ; + for ( int j = 0 ; j < int( vCrvP.size()) ; ++ j) { + // intersezione e classificazione + CRVCVECTOR ccClass ; + IntersCurveCurve intCC( *pCrv, *vCrvP[j]) ; + if ( ! intCC.GetCurveClassification( 0, ccClass)) + continue ; + // conservo solo le parti interne + for ( int k = 0 ; k < int( ccClass.size()) ; ++ k) { + if ( ccClass[k].nClass != CRVC_IN) + inCrv.Remove( ccClass[k].dParS, ccClass[k].dParE) ; + } + } + // tratti di curva rimasti + int nNum = inCrv.GetNumbers() ; + // se non sono rimasti pezzi, elimino la curva + if ( nNum == 0) { + pGeomDB->Erase( vOpenIds[i]) ; + } + // se uno solo, lo adatto + else if ( nNum == 1) { + double dParS, dParE ; + inCrv.GetFirst( dParS, dParE) ; + pCrv->TrimStartEndAtParam( dParS, dParE) ; + } + // altrimenti creo le opportune copie parzializzate + else { + int nOriId = vOpenIds[i] ; + int nCopyId = GDB_ID_NULL ; + double dParS, dParE ; + bool bInt = inCrv.GetFirst( dParS, dParE) ; + while ( bInt) { + // copio la curva + nCopyId = pGeomDB->Copy( nOriId, GDB_ID_NULL, nOriId, GDB_AFTER) ; + // modifico l'originale + ICurve* pOriCrv = GetCurve( pGeomDB->GetGeoObj( nOriId)) ; + pOriCrv->TrimStartEndAtParam( dParS, dParE) ; + // la copia è il nuovo originale + nOriId = nCopyId ; + // passo al successivo intervallo + bInt = inCrv.GetNext( dParS, dParE) ; + } + // cancello l'ultima copia + if ( nCopyId != GDB_ID_NULL) + pGeomDB->Erase( nCopyId) ; + } + } + // se errore sul pezzo, lo elimino + if ( ! bOk) + bPok = pPar->EraseAndGoToNextGroup() ; + // passo al pezzo successivo + else + bPok = pPar->GoToNextGroup() ; + } + return true ; +} + +//---------------------------------------------------------------------------- +bool +ExeCreateFlatParts( int nType) +{ + // disabilito registrazione comandi + bool bOldCmdLog = SetCmdLog( false) ; + // filtro e approssimo le curve + bool bOk = FilterAndApprox() ; + // creazione basata sulle regioni + if ( nType == FPC_REGION) { + int nLay ; + // concateno + bOk = bOk && ChainCurves( nLay) ; + // costruisco i pezzi + bOk = bOk && CreateFlatPartsByRegions( nLay) ; + } + // creazione basata sui layer + else if ( nType == FPC_LAYER) { + // creazione dei pezzi + bOk = bOk && CreateFlatPartsByLayers() ; + } + // creazione basata sui pezzi NGE + // sono già a posto + // verifica e aggiustamento dei pezzi + bOk = bOk && VerifyAndAdjustFlatParts() ; + // ripristino stato registrazione comandi + bOldCmdLog = SetCmdLog( bOldCmdLog) ; + return bOk ; +} + +//---------------------------------------------------------------------------- +bool +ExePackPart( int nId, double dXmax, double dOffs) +{ + IGeomDB* pGeomDB = GetCurrGeomDB() ; + VERIFY_GEOMDB( pGeomDB, false) + // Determino il box del pezzo + BBox3d b3Part ; + if ( ! pGeomDB->GetGlobalBBox( nId, b3Part)) + return false ; + double dLarPz = b3Part.GetMax().x - b3Part.GetMin().x ; + // Cerco prima posizione utile + double dXok = 0 ; + double dYok = 0 ; + double dYtop = 0 ; + int nId2 = ExeGetFirstPart( false) ; + while ( nId2 != GDB_ID_NULL) { + if ( nId2 != nId) { + BBox3d b3Part2 ; + if ( pGeomDB->GetGlobalBBox( nId2, b3Part2)) { + if ( b3Part2.GetMin().y < dYtop + 0.5 * dOffs) { + dXok = max( dXok, b3Part2.GetMax().x + dOffs) ; + } + else { + dXok = b3Part2.GetMax().x + dOffs ; + dYok = dYtop + dOffs ; + } + dYtop = max( dYtop, b3Part2.GetMax().y) ; + } + } + nId2 = ExeGetNextPart( nId2, false) ; + } + if ( dXok + dLarPz > dXmax) { + dXok = 0 ; + dYok = dYtop + dOffs ; + } + // Porto il pezzo nella giusta posizione + return pGeomDB->TranslateGlob( nId, Point3d( dXok, dYok, 0) - b3Part.GetMin()) ; +} diff --git a/EgtExecutor.rc b/EgtExecutor.rc index b02d2c4..d5aa52f 100644 Binary files a/EgtExecutor.rc and b/EgtExecutor.rc differ diff --git a/EgtExecutor.vcxproj b/EgtExecutor.vcxproj index 129d3c4..f25325e 100644 --- a/EgtExecutor.vcxproj +++ b/EgtExecutor.vcxproj @@ -244,6 +244,7 @@ copy $(TargetPath) \EgtProg\Dll64 + diff --git a/EgtExecutor.vcxproj.filters b/EgtExecutor.vcxproj.filters index cdc1046..4df3cec 100644 --- a/EgtExecutor.vcxproj.filters +++ b/EgtExecutor.vcxproj.filters @@ -233,6 +233,9 @@ File di origine\LUA + + File di origine\EXE + diff --git a/LUA_GdbModifyCurve.cpp b/LUA_GdbModifyCurve.cpp index e145482..321fb78 100644 --- a/LUA_GdbModifyCurve.cpp +++ b/LUA_GdbModifyCurve.cpp @@ -54,6 +54,24 @@ LuaOffsetCurve( lua_State* L) return 1 ; } +//------------------------------------------------------------------------------- +static int +LuaApproxCurve( lua_State* L) +{ + // 2 o 3 parametri : Id, nApprType [, dLinTol] + int nId ; + LuaCheckParam( L, 1, nId) + int nApprType ; + LuaCheckParam( L, 2, nApprType) + double dLinTol = 0.01 ; + LuaGetParam( L, 3, dLinTol) ; + LuaClearStack( L) ; + // approssimazione della curva con rette + bool bOk = ExeApproxCurve( nId, nApprType, dLinTol) ; + LuaSetParam( L, bOk) ; + return 1 ; +} + //---------------------------------------------------------------------------- static int LuaChangeClosedCurveStartPoint( lua_State* L) @@ -305,27 +323,6 @@ LuaSplitCurveAtSelfInters( lua_State* L) return 2 ; } -//------------------------------------------------------------------------------- -static int -LuaApproxCurve( lua_State* L) -{ - // 2 o 3 parametri : Id, nApprType [, dLinTol] - int nId ; - LuaCheckParam( L, 1, nId) - int nApprType ; - LuaCheckParam( L, 2, nApprType) - double dLinTol = 0.01 ; - LuaGetParam( L, 3, dLinTol) ; - LuaClearStack( L) ; - // approssimazione della curva con rette - int nNewId = ExeApproxCurve( nId, nApprType, dLinTol) ; - if ( nNewId != GDB_ID_NULL) - LuaSetParam( L, nNewId) ; - else - LuaSetParam( L) ; - return 1 ; -} - //------------------------------------------------------------------------------- static int LuaModifyArcRadius( lua_State* L) @@ -412,6 +409,7 @@ LuaInstallGdbModifyCurve( LuaMgr& luaMgr) bool bOk = ( &luaMgr != nullptr) ; bOk = bOk && luaMgr.RegisterFunction( "EgtInvertCurve", LuaInvertCurve) ; bOk = bOk && luaMgr.RegisterFunction( "EgtOffsetCurve", LuaOffsetCurve) ; + bOk = bOk && luaMgr.RegisterFunction( "EgtApproxCurve", LuaApproxCurve) ; bOk = bOk && luaMgr.RegisterFunction( "EgtChangeClosedCurveStartPoint", LuaChangeClosedCurveStartPoint) ; bOk = bOk && luaMgr.RegisterFunction( "EgtModifyCurveStartPoint", LuaModifyCurveStartPoint) ; bOk = bOk && luaMgr.RegisterFunction( "EgtModifyCurveEndPoint", LuaModifyCurveEndPoint) ; @@ -426,7 +424,6 @@ LuaInstallGdbModifyCurve( LuaMgr& luaMgr) bOk = bOk && luaMgr.RegisterFunction( "EgtSplitCurve", LuaSplitCurve) ; bOk = bOk && luaMgr.RegisterFunction( "EgtSplitCurveAtPoint", LuaSplitCurveAtPoint) ; bOk = bOk && luaMgr.RegisterFunction( "EgtSplitCurveAtSelfInters", LuaSplitCurveAtSelfInters) ; - bOk = bOk && luaMgr.RegisterFunction( "EgtApproxCurve", LuaApproxCurve) ; bOk = bOk && luaMgr.RegisterFunction( "EgtModifyArcRadius", LuaModifyArcRadius) ; bOk = bOk && luaMgr.RegisterFunction( "EgtModifyArcToExplementary", LuaModifyArcToExplementary) ; bOk = bOk && luaMgr.RegisterFunction( "EgtModifyArcByFlip", LuaModifyArcByFlip) ;