//---------------------------------------------------------------------------- // EgalTech 2015-2015 //---------------------------------------------------------------------------- // File : EXE_NstPartNesting.cpp Data : 30.12.15 Versione : 1.6l5 // Contenuto : Funzioni Nesting di Pezzi per EXE. // // // // Modifiche : 30.12.15 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "EXE.h" #include "EXE_Const.h" #include "EXE_Macro.h" #include "/EgtDev/Include/EXeExecutor.h" #include "/EgtDev/Include/EXeConst.h" #include "/EgtDev/Include/EGkCurveComposite.h" #include "/EgtDev/Include/EGkSfrCreate.h" #include "/EgtDev/Include/EMkMachiningGeoConst.h" #include "/EgtDev/Include/EgtPointerOwner.h" #include using namespace std ; //---------------------------------------------------------------------------- static int GetFlatPartRegion( IGeomDB* pGeomDB, int nId) { // recupero regione del pezzo (è la prima del sottogruppo di nome Region) int nRegGrp = pGeomDB->GetFirstNameInGroup( nId, NST_PART_REG) ; int nRegId = pGeomDB->GetFirstInGroup( nRegGrp) ; while ( nRegId != GDB_ID_NULL) { if ( pGeomDB->GetGeoType( nRegId) == SRF_FLATRGN) break ; nRegId = pGeomDB->GetNext( nRegId) ; } return nRegId ; } //---------------------------------------------------------------------------- static bool GetFlatPartCutRegions( IGeomDB* pGeomDB, int nId, bool bReduced, INTVECTOR& vCrId) { // recupero gruppo preview lavorazioni del pezzo int nPVGrp = pGeomDB->GetFirstNameInGroup( nId, MCH_PV) ; if ( nPVGrp == GDB_ID_NULL) return false ; // ciclo sulle lavorazioni int nMchId = pGeomDB->GetFirstGroupInGroup( nPVGrp) ; while ( nMchId != GDB_ID_NULL) { int nClId = pGeomDB->GetFirstGroupInGroup( nMchId) ; while ( nClId != GDB_ID_NULL) { int nCrId = pGeomDB->GetFirstNameInGroup( nClId, ( bReduced ? MCH_PV_RRCUT : MCH_PV_RCUT)) ; while ( nCrId != GDB_ID_NULL) { vCrId.emplace_back( nCrId) ; nCrId = pGeomDB->GetNextName( nCrId, ( bReduced ? MCH_PV_RRCUT : MCH_PV_RCUT)) ; } nClId = pGeomDB->GetNextGroup( nClId) ; } nMchId = pGeomDB->GetNextGroup( nMchId) ; } return true ; } //---------------------------------------------------------------------------- static int CreateOutBoxRegion( IGeomDB* pGeomDB, int nParentId, double dXmin, double dYmin, double dXmax, double dYmax) { // creo polilinea attorno al box (avvolta a serpente) const double SPESS = 100 ; const double DELTA = 1 ; PolyLine PL ; PL.AddUPoint( 0, Point3d( dXmin, dYmin, 0)) ; PL.AddUPoint( 1, Point3d( dXmin, dYmax, 0)) ; PL.AddUPoint( 2, Point3d( dXmax, dYmax, 0)) ; PL.AddUPoint( 3, Point3d( dXmax, dYmin + DELTA + 2 * EPS_SMALL, 0)) ; PL.AddUPoint( 4, Point3d( dXmax + SPESS, dYmin + DELTA + 2 * EPS_SMALL, 0)) ; PL.AddUPoint( 5, Point3d( dXmax + SPESS, dYmax + SPESS, 0)) ; PL.AddUPoint( 6, Point3d( dXmin - SPESS, dYmax + SPESS, 0)) ; PL.AddUPoint( 7, Point3d( dXmin - SPESS, dYmin - SPESS, 0)) ; PL.AddUPoint( 8, Point3d( dXmax + SPESS, dYmin - SPESS, 0)) ; PL.AddUPoint( 9, Point3d( dXmax + SPESS, dYmin + DELTA, 0)) ; PL.AddUPoint( 10, Point3d( dXmax, dYmin + DELTA, 0)) ; PL.AddUPoint( 11, Point3d( dXmax, dYmin, 0)) ; PL.Close() ; // la converto in curva composita PtrOwner pCompo( CreateCurveComposite()) ; if ( IsNull( pCompo) || ! pCompo->FromPolyLine( PL)) return GDB_ID_NULL ; // costruisco la regione piana SurfFlatRegionByContours SfrCntr ; SfrCntr.AddCurve( Release( pCompo)) ; ISurfFlatRegion* pSfr = SfrCntr.GetSurf() ; if ( pSfr == nullptr) return GDB_ID_NULL ; // inserisco la superficie nel DB int nId = pGeomDB->AddGeoObj( GDB_ID_NULL, nParentId, pSfr) ; if ( nId == GDB_ID_NULL) return GDB_ID_NULL ; // la dichiaro temporanea e invisibile pGeomDB->SetLevel( nId, GDB_LV_TEMP) ; pGeomDB->SetMaterial( nId, INVISIBLE) ; return nId ; } //---------------------------------------------------------------------------- static bool SetPreviewStatus( IGeomDB* pGeomDB, const INTVECTOR& vIds, bool bShow) { for ( const auto nId : vIds) { int nPvId = pGeomDB->GetFirstNameInGroup(nId, MCH_PV) ; pGeomDB->SetStatus( nPvId, ( bShow ? GDB_ST_ON : GDB_ST_OFF)) ; } return true ; } //---------------------------------------------------------------------------- static bool UpdateToolOffset( IGeomDB* pGeomDB, const INTVECTOR& vIds, bool bReducedCut, double& dOffs) { for ( const auto nId : vIds) { int nPvId = pGeomDB->GetFirstNameInGroup(nId, MCH_PV) ; int nCutId = pGeomDB->GetFirstGroupInGroup( nPvId) ; while ( nCutId != GDB_ID_NULL) { int nPathId = pGeomDB->GetFirstGroupInGroup( nCutId) ; while ( nPathId != GDB_ID_NULL) { double dVal ; if ( pGeomDB->GetInfo( nPathId, MCH_PV_KEY_WT, dVal) && dVal > dOffs) dOffs = dVal ; if ( ! bReducedCut && pGeomDB->GetInfo( nPathId, MCH_PV_KEY_DT, dVal) && dVal > dOffs) dOffs = dVal ; nPathId = pGeomDB->GetNextGroup( nPathId) ; } nCutId = pGeomDB->GetNextGroup( nCutId) ; } } return true ; } //---------------------------------------------------------------------------- bool ExeVerifyPartCluster( const INTVECTOR& vIds, bool bReducedCut, double dXmin, double dYmin, double dXmax, double dYmax) { IGeomDB* pGeomDB = GetCurrGeomDB() ; VERIFY_GEOMDB( pGeomDB, false) // Box della regione di interesse BBox3d b3Region( dXmin, dYmin, 0, dXmax, dYmax, 0) ; // Flag per calcolo box const int BBF_MY_FLAG = BBF_ONLY_VISIBLE | BBF_IGNORE_TEXT | BBF_IGNORE_DIM ; // Risolvo eventuali riferimenti a oggetti selezionati, compresi nella regione e // calcolo il box del cluster risultante INTVECTOR vTrueIds ; vTrueIds.reserve( vIds.size()) ; BBox3d b3Cluster ; for ( auto nId : vIds) { int nTrueId = (( nId != GDB_ID_SEL) ? nId : pGeomDB->GetFirstSelectedObj()) ; while ( nTrueId != GDB_ID_NULL) { BBox3d b3Part ; if ( pGeomDB->GetGlobalBBox( nTrueId, b3Part, BBF_MY_FLAG)) { // inserisco l'identificativo nel vettore dei validi vTrueIds.push_back( nTrueId) ; // aggiorno il box del cluster b3Cluster.Add( b3Part) ; } // passo al successivo nTrueId = (( nId != GDB_ID_SEL) ? GDB_ID_NULL : pGeomDB->GetNextSelectedObj()) ; } } // Se non sono rimasti oggetti, esco con successo if ( vTrueIds.empty()) return true ; // Determino le regioni dei pezzi rimasti INTVECTOR vReg ; INTVECTOR vCutReg ; BBox3d b3RegCluster ; for ( int nId : vTrueIds) { // recupero regione del pezzo int nRegId = GetFlatPartRegion( pGeomDB, nId) ; BBox3d b3Reg ; if ( pGeomDB->GetGlobalBBox( nRegId, b3Reg, BBF_MY_FLAG)) { vReg.emplace_back( nRegId) ; b3RegCluster.Add( b3Reg) ; } else return false ; // recupero regioni dei tagli del pezzo if ( ! GetFlatPartCutRegions( pGeomDB, nId, bReducedCut, vCutReg)) return false ; } // Verifico di essere all'interno del box esterno if ( ! b3Region.EnclosesXY( b3RegCluster)) return false ; // Verifico se pezzi sotto la radice o pezzi in altro gruppo int nGroupId = pGeomDB->GetParentId( vTrueIds[0]) ; bool bInRoot = ( nGroupId == GDB_ID_ROOT) ; // Determino le regioni di tutti gli altri pezzi compresi nella regione di interesse INTVECTOR vOthReg ; INTVECTOR vOthCutReg ; int nId2 = ( bInRoot ? ExeGetFirstPart( true) : ExeGetFirstGroupInGroup( nGroupId)) ; while ( nId2 != GDB_ID_NULL) { if ( find( vTrueIds.begin(), vTrueIds.end(), nId2) == vTrueIds.end()) { BBox3d b3Part2 ; if ( pGeomDB->GetGlobalBBox( nId2, b3Part2, BBF_MY_FLAG) && b3Cluster.OverlapsXY( b3Part2)) { // recupero regione del pezzo int nRegId = GetFlatPartRegion( pGeomDB, nId2) ; if ( nRegId != GDB_ID_NULL) vOthReg.emplace_back( nRegId) ; else return false ; // recupero regioni dei tagli del pezzo if ( ! GetFlatPartCutRegions( pGeomDB, nId2, bReducedCut, vOthCutReg)) return false ; } } nId2 = ( bInRoot ? ExeGetNextPart( nId2, true) : ExeGetNextGroup( nId2)) ; } // Eseguo verifiche bool bOk = true ; // regioni dei pezzi for ( int nRegId : vReg) { // verifico con le regioni degli altri pezzi for ( int nOthRegId : vOthReg) { if ( ExeSurfFrChunkSimpleClassify( nRegId, 0, nOthRegId, 0) != REGC_OUT) bOk = false ; } // e con le regioni dei tagli degli altri pezzi for ( int nOthCutRegId : vOthCutReg) { if ( ExeSurfFrChunkSimpleClassify( nRegId, 0, nOthCutRegId, 0) != REGC_OUT) bOk = false ; } } // regioni delle lavorazioni dei pezzi for ( int nCutRegId : vCutReg) { // le confronto con le regioni degli altri pezzi for ( int nOthRegId : vOthReg) { if ( ExeSurfFrChunkSimpleClassify( nCutRegId, 0, nOthRegId, 0) != REGC_OUT) bOk = false ; } } return bOk ; } //---------------------------------------------------------------------------- static bool MyPackPartCluster( const INTVECTOR& vIds, bool bReducedCut, double dXmin, double dYmin, double dXmax, double dYmax, bool bBottomUp) { IGeomDB* pGeomDB = GetCurrGeomDB() ; VERIFY_GEOMDB( pGeomDB, false) // Verifiche sui parametri if ( dXmax < dXmin + EPS_SMALL || dYmax < dYmin + EPS_SMALL) return false ; // Risolvo eventuali riferimenti a oggetti selezionati INTVECTOR vTrueIds ; vTrueIds.reserve( vIds.size()) ; for ( auto nId : vIds) { int nTrueId = (( nId != GDB_ID_SEL) ? nId : pGeomDB->GetFirstSelectedObj()) ; while ( nTrueId != GDB_ID_NULL) { vTrueIds.push_back( nTrueId) ; // passo al successivo nTrueId = (( nId != GDB_ID_SEL) ? GDB_ID_NULL : pGeomDB->GetNextSelectedObj()) ; } } // Se non sono rimasti oggetti, esco con successo if ( vTrueIds.empty()) return true ; // Verifico se pezzi sotto la radice o pezzi in altro gruppo int nGroupId = pGeomDB->GetParentId( vTrueIds[0]) ; bool bInRoot = ( nGroupId == GDB_ID_ROOT) ; // Box della regione di interesse BBox3d b3Region( dXmin, dYmin, 0, dXmax, dYmax, 0) ; // Flag per calcolo box const int BBF_MY_FLAG = BBF_ONLY_VISIBLE | BBF_IGNORE_TEXT | BBF_IGNORE_DIM ; // Determino tutti gli altri pezzi compresi nella regione di interesse INTVECTOR vOtherIds ; int nId2 = ( bInRoot ? ExeGetFirstPart( true) : ExeGetFirstGroupInGroup( nGroupId)) ; while ( nId2 != GDB_ID_NULL) { if ( find( vTrueIds.begin(), vTrueIds.end(), nId2) == vTrueIds.end()) { BBox3d b3Part2 ; if ( pGeomDB->GetGlobalBBox( nId2, b3Part2, BBF_MY_FLAG) && b3Region.OverlapsXY( b3Part2)) { vOtherIds.emplace_back( nId2) ; } } nId2 = ( bInRoot ? ExeGetNextPart( nId2, true) : ExeGetNextGroup( nId2)) ; } // nascondo preview delle lavorazioni SetPreviewStatus( pGeomDB, vTrueIds, false) ; SetPreviewStatus( pGeomDB, vOtherIds, false) ; // calcolo offset per ingombro lavorazioni double dOffs = 0 ; UpdateToolOffset( pGeomDB, vTrueIds, bReducedCut, dOffs) ; UpdateToolOffset( pGeomDB, vOtherIds, bReducedCut, dOffs) ; // eseguo primo movimento come box bool bOk = ExePackBoxCluster( vTrueIds, dXmin, dYmin, dXmax, dYmax, dOffs, bBottomUp) ; // se inserimento di massima riuscito, provo a migliorare if ( bOk) { const double BIG_MOVE = 1000 ; ExeMovePartCluster( vTrueIds, bReducedCut, ( bBottomUp ? - 1 : 1) * BIG_MOVE * Y_AX, dXmin, dYmin, dXmax, dYmax) ; ExeMovePartCluster( vTrueIds, bReducedCut, - BIG_MOVE * X_AX, dXmin, dYmin, dXmax, dYmax) ; } // ripristino preview delle lavorazioni SetPreviewStatus( pGeomDB, vTrueIds, true) ; SetPreviewStatus( pGeomDB, vOtherIds, true) ; return bOk ; } //---------------------------------------------------------------------------- bool ExePackPartCluster( const INTVECTOR& vIds, bool bReducedCut, double dXmin, double dYmin, double dXmax, double dYmax, bool bBottomUp) { IGeomDB* pGeomDB = GetCurrGeomDB() ; VERIFY_GEOMDB( pGeomDB, false) // Risolvo eventuali riferimenti a oggetti selezionati INTVECTOR vTrueIds ; vTrueIds.reserve( vIds.size()) ; for ( auto nId : vIds) { int nTrueId = (( nId != GDB_ID_SEL) ? nId : pGeomDB->GetFirstSelectedObj()) ; while ( nTrueId != GDB_ID_NULL) { vTrueIds.push_back( nTrueId) ; // passo al successivo nTrueId = (( nId != GDB_ID_SEL) ? GDB_ID_NULL : pGeomDB->GetNextSelectedObj()) ; } } // se con tagli ridotti if ( bReducedCut) { return MyPackPartCluster( vTrueIds, true, dXmin, dYmin, dXmax, dYmax, bBottomUp) ; } // altrimenti else { // provo con tagli ridotti if ( ! MyPackPartCluster( vTrueIds, true, dXmin, dYmin, dXmax, dYmax, bBottomUp)) return false ; // se posizione valida if ( ExeVerifyPartCluster( vTrueIds, false, dXmin, dYmin, dXmax, dYmax)) { return true ; } // altrimenti, riprovo con tagli standard else { return MyPackPartCluster( vTrueIds, false, dXmin, dYmin, dXmax, dYmax, bBottomUp) ; } } } //---------------------------------------------------------------------------- static bool MyMovePartCluster( const INTVECTOR& vIds, bool bReducedCut, Vector3d& vtMove, double dXmin, double dYmin, double dXmax, double dYmax) { IGeomDB* pGeomDB = GetCurrGeomDB() ; VERIFY_GEOMDB( pGeomDB, false) // Verifiche sui parametri if ( dXmax < dXmin + EPS_SMALL || dYmax < dYmin + EPS_SMALL) return false ; // Vettore movimento nel piano XY globale Vector3d vtMoveXY( vtMove.x, vtMove.y, 0) ; vtMove = V_NULL ; if ( vtMoveXY.IsSmall()) return true ; // Box della regione di interesse BBox3d b3Region( dXmin, dYmin, 0, dXmax, dYmax, 0) ; // Flag per calcolo box const int BBF_MY_FLAG = BBF_ONLY_VISIBLE | BBF_IGNORE_TEXT | BBF_IGNORE_DIM ; // Risolvo eventuali riferimenti a oggetti selezionati, compresi nella regione e // calcolo il box del cluster risultante INTVECTOR vTrueIds ; vTrueIds.reserve( vIds.size()) ; BBox3d b3Cluster ; for ( auto nId : vIds) { int nTrueId = (( nId != GDB_ID_SEL) ? nId : pGeomDB->GetFirstSelectedObj()) ; while ( nTrueId != GDB_ID_NULL) { BBox3d b3Part ; if ( pGeomDB->GetGlobalBBox( nTrueId, b3Part, BBF_MY_FLAG) && b3Region.OverlapsXY( b3Part)) { // inserisco l'identificativo nel vettore dei validi vTrueIds.push_back( nTrueId) ; // aggiorno il box del cluster b3Cluster.Add( b3Part) ; } // passo al successivo nTrueId = (( nId != GDB_ID_SEL) ? GDB_ID_NULL : pGeomDB->GetNextSelectedObj()) ; } } // Se non sono rimasti oggetti, esco con successo if ( vTrueIds.empty()) return true ; // Verifico se pezzi sotto la radice o pezzi in altro gruppo int nGroupId = pGeomDB->GetParentId( vTrueIds[0]) ; bool bInRoot = ( nGroupId == GDB_ID_ROOT) ; // Determino le regioni di tutti gli altri pezzi compresi nella regione di interesse INTVECTOR vOthReg ; INTVECTOR vOthCutReg ; int nId2 = ( bInRoot ? ExeGetFirstPart( true) : ExeGetFirstGroupInGroup( nGroupId)) ; while ( nId2 != GDB_ID_NULL) { if ( find( vTrueIds.begin(), vTrueIds.end(), nId2) == vTrueIds.end()) { BBox3d b3Part2 ; if ( pGeomDB->GetGlobalBBox( nId2, b3Part2, BBF_MY_FLAG) && b3Region.OverlapsXY( b3Part2)) { // recupero regione del pezzo int nRegId = GetFlatPartRegion( pGeomDB, nId2) ; if ( nRegId != GDB_ID_NULL) vOthReg.emplace_back( nRegId) ; else return false ; // recupero regioni dei tagli del pezzo if ( ! GetFlatPartCutRegions( pGeomDB, nId2, bReducedCut, vOthCutReg)) return false ; } } nId2 = ( bInRoot ? ExeGetNextPart( nId2, true) : ExeGetNextGroup( nId2)) ; } // Creo SurfFlatRegion che delimita la regione valida int nBoxId = CreateOutBoxRegion( pGeomDB, GDB_ID_ROOT, dXmin, dYmin, dXmax, dYmax) ; if ( nBoxId == GDB_ID_NULL) return false ; // Verifico movimento dei pezzi del cluster rispetto agli altri pezzi bool bOk = true ; double dLen = vtMoveXY.Len() ; Vector3d vtDir = ( dLen > EPS_SMALL ? vtMoveXY / dLen : V_NULL) ; for ( auto nTrueId : vTrueIds) { // recupero regione del pezzo int nRegId = GetFlatPartRegion( pGeomDB, nTrueId) ; if ( nRegId == GDB_ID_NULL) { bOk = false ; break ; } // la confronto con il box ExeSurfFrMoveSimpleNoCollision( nRegId, nBoxId, vtDir, dLen, RTY_GLOB) ; // la confronto con le regioni degli altri pezzi for ( int nOthRegId : vOthReg) { ExeSurfFrMoveSimpleNoCollision( nRegId, nOthRegId, vtDir, dLen, RTY_GLOB) ; } // e con le regioni dei tagli degli altri pezzi for ( int nOthCutRegId : vOthCutReg) { ExeSurfFrMoveSimpleNoCollision( nRegId, nOthCutRegId, vtDir, dLen, RTY_GLOB) ; } // recupero regioni di lavorazione del pezzo INTVECTOR vCrId ; if ( ! GetFlatPartCutRegions( pGeomDB, nTrueId, bReducedCut, vCrId)) { bOk = false ; break ; } // le confronto con le regioni degli altri pezzi for ( int nCrId : vCrId) { for ( int nOthRegId : vOthReg) { ExeSurfFrMoveSimpleNoCollision( nCrId, nOthRegId, vtDir, dLen, RTY_GLOB) ; } } } // Elimino la regione aggiunta per il Box pGeomDB->Erase( nBoxId) ; // Se errore if ( ! bOk) return false ; // Se movimento risultante nullo, non faccio alcunché vtMoveXY = vtDir * dLen ; if ( vtMoveXY.IsSmall()) return true ; // Eseguo movimento dei pezzi del cluster for ( auto nTrueId : vTrueIds) pGeomDB->TranslateGlob( nTrueId, vtMoveXY) ; ExeSetModified() ; vtMove = vtMoveXY ; return true ; } //---------------------------------------------------------------------------- bool ExeMovePartCluster( const INTVECTOR& vIds, bool bReducedCut, Vector3d& vtMove, double dXmin, double dYmin, double dXmax, double dYmax) { IGeomDB* pGeomDB = GetCurrGeomDB() ; VERIFY_GEOMDB( pGeomDB, false) // Risolvo eventuali riferimenti a oggetti selezionati INTVECTOR vTrueIds ; vTrueIds.reserve( vIds.size()) ; for ( auto nId : vIds) { int nTrueId = (( nId != GDB_ID_SEL) ? nId : pGeomDB->GetFirstSelectedObj()) ; while ( nTrueId != GDB_ID_NULL) { vTrueIds.push_back( nTrueId) ; // passo al successivo nTrueId = (( nId != GDB_ID_SEL) ? GDB_ID_NULL : pGeomDB->GetNextSelectedObj()) ; } } // se con tagli ridotti if ( bReducedCut) { return MyMovePartCluster( vTrueIds, true, vtMove, dXmin, dYmin, dXmax, dYmax) ; } // altrimenti else { // provo con tagli ridotti Vector3d vtM = vtMove ; if ( ! MyMovePartCluster( vTrueIds, true, vtM, dXmin, dYmin, dXmax, dYmax)) return false ; // se posizione valida if ( ExeVerifyPartCluster( vTrueIds, false, dXmin, dYmin, dXmax, dYmax)) { vtMove = vtM ; return true ; } // altrimenti, riprovo con tagli standard else { // annullo il movimento for ( int nId : vTrueIds) pGeomDB->TranslateGlob( nId, - vtM) ; // riprovo return MyMovePartCluster( vTrueIds, false, vtMove, dXmin, dYmin, dXmax, dYmax) ; } } } //---------------------------------------------------------------------------- bool ExeRotatePartCluster( const INTVECTOR& vIds, bool bReducedCut, const Point3d& ptCen, double& dRotAngDeg, double dXmin, double dYmin, double dXmax, double dYmax) { IGeomDB* pGeomDB = GetCurrGeomDB() ; VERIFY_GEOMDB( pGeomDB, false) // Verifiche sui parametri if ( dXmax < dXmin + EPS_SMALL || dYmax < dYmin + EPS_SMALL) return false ; // Rotazione nel piano XY globale // Box della regione di interesse BBox3d b3Region( dXmin, dYmin, 0, dXmax, dYmax, 0) ; // Flag per calcolo box const int BBF_MY_FLAG = BBF_ONLY_VISIBLE | BBF_IGNORE_TEXT | BBF_IGNORE_DIM ; // Risolvo eventuali riferimenti a oggetti selezionati, compresi nella regione e // calcolo il box del cluster risultante INTVECTOR vTrueIds ; vTrueIds.reserve( vIds.size()) ; BBox3d b3Cluster ; for ( auto nId : vIds) { int nTrueId = (( nId != GDB_ID_SEL) ? nId : pGeomDB->GetFirstSelectedObj()) ; while ( nTrueId != GDB_ID_NULL) { BBox3d b3Part ; if ( pGeomDB->GetGlobalBBox( nTrueId, b3Part, BBF_MY_FLAG) && b3Region.OverlapsXY( b3Part)) { // inserisco l'identificativo nel vettore dei validi vTrueIds.push_back( nTrueId) ; // aggiorno il box del cluster b3Cluster.Add( b3Part) ; } // passo al successivo nTrueId = (( nId != GDB_ID_SEL) ? GDB_ID_NULL : pGeomDB->GetNextSelectedObj()) ; } } // Se non sono rimasti oggetti, esco con successo if ( vTrueIds.empty()) return true ; // Verifico se pezzi sotto la radice o pezzi in altro gruppo int nGroupId = pGeomDB->GetParentId( vTrueIds[0]) ; bool bInRoot = ( nGroupId == GDB_ID_ROOT) ; // Determino le regioni di tutti gli altri pezzi compresi nella regione di interesse INTVECTOR vReg ; INTVECTOR vCutReg ; int nId2 = ( bInRoot ? ExeGetFirstPart( true) : ExeGetFirstGroupInGroup( nGroupId)) ; while ( nId2 != GDB_ID_NULL) { if ( find( vTrueIds.begin(), vTrueIds.end(), nId2) == vTrueIds.end()) { BBox3d b3Part2 ; if ( pGeomDB->GetGlobalBBox( nId2, b3Part2, BBF_MY_FLAG) && b3Region.OverlapsXY( b3Part2)) { // recupero regione del pezzo int nRegId = GetFlatPartRegion( pGeomDB, nId2) ; if ( nRegId != GDB_ID_NULL) vReg.emplace_back( nRegId) ; else return false ; // recupero regioni dei tagli del pezzo if ( ! GetFlatPartCutRegions( pGeomDB, nId2, bReducedCut, vCutReg)) return false ; } } nId2 = ( bInRoot ? ExeGetNextPart( nId2, true) : ExeGetNextGroup( nId2)) ; } // Creo SurfFlatRegion che delimita la regione valida int nBoxId = CreateOutBoxRegion( pGeomDB, GDB_ID_ROOT, dXmin, dYmin, dXmax, dYmax) ; if ( nBoxId == GDB_ID_NULL) return false ; // Verifico rotazione dei pezzi del cluster rispetto agli altri pezzi bool bOk = true ; double dAng = dRotAngDeg ; for ( auto nTrueId : vTrueIds) { // recupero regione del pezzo int nRegId = GetFlatPartRegion( pGeomDB, nTrueId) ; if ( nRegId == GDB_ID_NULL) { bOk = false ; break ; } // la confronto con il box ExeSurfFrRotateSimpleNoCollision( nRegId, nBoxId, ptCen, dAng, RTY_GLOB) ; // la confronto con le regioni degli altri pezzi for ( int nOthRegId : vReg) { ExeSurfFrRotateSimpleNoCollision( nRegId, nOthRegId, ptCen, dAng, RTY_GLOB) ; } // e con le regioni dei tagli degli altri pezzi for ( int nOthCutRegId : vCutReg) { ExeSurfFrRotateSimpleNoCollision( nRegId, nOthCutRegId, ptCen, dAng, RTY_GLOB) ; } // recupero regioni di lavorazione del pezzo INTVECTOR vCrId ; if ( ! GetFlatPartCutRegions( pGeomDB, nTrueId, bReducedCut, vCrId)) { bOk = false ; break ; } // le confronto con le regioni degli altri pezzi for ( int nCrId : vCrId) { for ( int nOthRegId : vReg) { ExeSurfFrRotateSimpleNoCollision( nCrId, nOthRegId, ptCen, dAng, RTY_GLOB) ; } } } // Elimino la regione aggiunta per il Box pGeomDB->Erase( nBoxId) ; // Se errore if ( ! bOk) return false ; // Se movimento risultante nullo, non faccio alcunché dRotAngDeg = dAng ; if ( fabs( dAng) < EPS_ANG_SMALL) return true ; // Eseguo rotazione dei pezzi del cluster for ( auto nTrueId : vTrueIds) pGeomDB->RotateGlob( nTrueId, ptCen, Z_AX, dRotAngDeg) ; ExeSetModified() ; return true ; } //----------------------------------------------------------------------------- bool ExeGetPartClusterCenterGlob( const INTVECTOR& vIds, Point3d& ptCen) { IGeomDB* pGeomDB = GetCurrGeomDB() ; VERIFY_GEOMDB( pGeomDB, false) // Risolvo eventuali riferimenti a oggetti selezionati INTVECTOR vTrueIds ; vTrueIds.reserve( vIds.size()) ; for ( auto nId : vIds) { int nTrueId = (( nId != GDB_ID_SEL) ? nId : pGeomDB->GetFirstSelectedObj()) ; while ( nTrueId != GDB_ID_NULL) { vTrueIds.push_back( nTrueId) ; // passo al successivo nTrueId = (( nId != GDB_ID_SEL) ? GDB_ID_NULL : pGeomDB->GetNextSelectedObj()) ; } } // Se non sono rimasti oggetti, esco con errore if ( vTrueIds.empty()) return false ; // Recupero il centro della regione associata ad ogni oggetto int nCount = 0 ; ptCen = ORIG ; for ( auto nTrueId : vTrueIds) { // recupero regione del pezzo int nRegId = GetFlatPartRegion( pGeomDB, nTrueId) ; ISurfFlatRegion* pSfr = GetSurfFlatRegion( pGeomDB->GetGeoObj( nRegId)) ; if ( pSfr == nullptr) return false ; // ne ricavo il centro Point3d ptRcen ; if ( ! pSfr->GetCentroid( ptRcen)) return false ; // lo porto in globale Frame3d frRef ; if ( ! pGeomDB->GetGlobFrame( nRegId, frRef)) return false ; ptRcen.ToGlob( frRef) ; // lo sommo al centro complessivo ptCen += ptRcen ; ++ nCount ; } // Verifico di aver trovato qualcosa if ( nCount == 0) return false ; // Medio il centro ptCen /= nCount ; return true ; }