//---------------------------------------------------------------------------- // EgalTech 2015-2015 //---------------------------------------------------------------------------- // File : MachMgr.cpp Data : 16.04.15 Versione : 1.6d3 // Contenuto : Implementazione gestione grezzi e pezzi della classe MachMgr. // // // // Modifiche : 16.04.15 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "DllMain.h" #include "MachMgr.h" #include "MachConst.h" #include "Disposition.h" #include "/EgtDev/Include/EMkMachiningGeoConst.h" #include "/EgtDev/Include/EXeCmdLogOff.h" #include "/EgtDev/Include/EGkCurveComposite.h" #include "/EgtDev/Include/EGkGdbIterator.h" #include "/EgtDev/Include/EGkGeoPoint3d.h" #include "/EgtDev/Include/EGkCurveAux.h" #include "/EgtDev/Include/EGkOffsetCurve.h" #include "/EgtDev/Include/EGkDistPointCurve.h" #include "/EgtDev/Include/EGkSfrCreate.h" #include "/EgtDev/Include/EGkStmStandard.h" #include "/EgtDev/Include/EGkStmFromCurves.h" #include "/EgtDev/Include/EGkSurfBezier.h" #include "/EgtDev/Include/EGkSurfLocal.h" #include "/EgtDev/Include/EGkCAvSilhouetteSurfTm.h" #include "/EgtDev/Include/EgtPointerOwner.h" #include "/EgtDev/Include/EXeConst.h" using namespace std ; //---------------------------------------------------------------------------- int MachMgr::GetRawPartCount( void) const { // recupero il gruppo dei grezzi nella macchinata corrente int nRawGroupId = GetCurrRawGroupId() ; if ( nRawGroupId == GDB_ID_NULL) return 0 ; // ritorno numero dei grezzi della macchinata return m_pGeomDB->GetGroupObjs( nRawGroupId) ; } //---------------------------------------------------------------------------- int MachMgr::GetFirstRawPart( void) const { // recupero il gruppo dei grezzi nella macchinata corrente int nRawGroupId = GetCurrRawGroupId() ; if ( nRawGroupId == GDB_ID_NULL) return GDB_ID_NULL ; // recupero il primo sottogruppo int nId = m_pGeomDB->GetFirstGroupInGroup( nRawGroupId) ; return nId ; } //---------------------------------------------------------------------------- int MachMgr::GetNextRawPart( int nId) const { // recupero il gruppo dei grezzi nella macchinata corrente int nRawGroupId = GetCurrRawGroupId() ; if ( nRawGroupId == GDB_ID_NULL) return GDB_ID_NULL ; // verifico che il gruppo ricevuto sia corretto if ( m_pGeomDB->GetParentId( nId) != nRawGroupId) return GDB_ID_NULL ; // recupero il successivo sottogruppo int nNextId = m_pGeomDB->GetNextGroup( nId) ; return nNextId ; } //---------------------------------------------------------------------------- int MachMgr::AddRawPart( const Point3d& ptOrig, double dLen, double dWidth, double dHeight, Color cCol) { // recupero il gruppo dei grezzi nella macchinata corrente int nRawGroupId = GetCurrRawGroupId() ; if ( nRawGroupId == GDB_ID_NULL) return GDB_ID_NULL ; // se definita una tavola corrente, esprimo il punto rispetto alla sua prima origine Point3d ptMyOrig = ptOrig ; Point3d ptRef1 ; if ( GetTableRef( 1, ptRef1)) ptMyOrig += ptRef1 ; // inserisco il gruppo del grezzo nei grezzi della macchinata int nRawId = m_pGeomDB->AddGroup( GDB_ID_NULL, nRawGroupId, Frame3d( ptMyOrig)) ; if ( nRawId == GDB_ID_NULL) return GDB_ID_NULL ; // assegno il nome al gruppo bool bOk = m_pGeomDB->SetName( nRawId, MACH_RAW_PART) ; // assegno la fase al gruppo m_pGeomDB->SetInfo( nRawId, MACH_RAW_PHASE, m_nCurrPhase) ; // creo solido e outline bOk = bOk && ModifyRawPart( nRawId, ptOrig, dLen, dWidth, dHeight, cCol) ; // se qualcosa è andato storto, cancello tutto if ( ! bOk) { m_pGeomDB->Erase( nRawId) ; return GDB_ID_NULL ; } // tutto ok return nRawId ; } //---------------------------------------------------------------------------- bool MachMgr::ModifyRawPart( int nRawId, const Point3d& ptOrig, double dLen, double dWidth, double dHeight, Color cCol) { // le dimensioni non possono essere nulle if ( dLen < EPS_SMALL || dWidth < EPS_SMALL || dHeight < EPS_SMALL) return false ; // verifica validità grezzo if ( ! VerifyRawPart( nRawId)) return false ; // creo il solido PtrOwner pStm( GetSurfTriMeshBox( dLen, dWidth, dHeight)) ; if ( IsNull( pStm)) return false ; // creo il contorno esterno PolyLine PL ; PL.AddUPoint( 0, ORIG) ; PL.AddUPoint( 1, Point3d( dLen, 0, 0)) ; PL.AddUPoint( 2, Point3d( dLen, dWidth, 0)) ; PL.AddUPoint( 3, Point3d( 0, dWidth, 0)) ; PL.AddUPoint( 4, ORIG) ; // creo la curva PtrOwner pCrvCompo( CreateCurveComposite()) ; if ( IsNull( pCrvCompo) || ! pCrvCompo->FromPolyLine( PL) || ! pCrvCompo->SetExtrusion( Z_AX)) return false ; // cancello eventuali vecchi solidi e curve di outline int nOldRawSolId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ; if ( nOldRawSolId != GDB_ID_NULL) m_pGeomDB->Erase( nOldRawSolId) ; int nOldRawOutId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_OUTLINE) ; if ( nOldRawOutId != GDB_ID_NULL) m_pGeomDB->Erase( nOldRawOutId) ; // se definita una tavola corrente, esprimo il punto rispetto alla sua prima origine Point3d ptMyOrig = ptOrig ; Point3d ptRef1 ; if ( GetTableRef( 1, ptRef1)) ptMyOrig += ptRef1 ; // aggiorno l'origine del gruppo m_pGeomDB->GetGroupFrame( nRawId)->ChangeOrig( ptMyOrig) ; // inserisco il solido nel gruppo int nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nRawId, Release( pStm)) ; bool bOk = ( nId != GDB_ID_NULL) ; // assegno il nome al solido bOk = bOk && m_pGeomDB->SetName( nId, MACH_RAW_SOLID) ; // assegno il colore al solido bOk = bOk && m_pGeomDB->SetMaterial( nId, cCol) ; // calcolo il punto centro del solido bOk = bOk && SetRawPartCenter( nRawId) ; // inserisco la curva composita nel DB int nCrvId = ( bOk ? m_pGeomDB->AddGeoObj( GDB_ID_NULL, nRawId, Release( pCrvCompo)) : GDB_ID_NULL) ; bOk = bOk && ( nCrvId != GDB_ID_NULL) ; // assegno il nome al contorno bOk = bOk && m_pGeomDB->SetName( nCrvId, MACH_RAW_OUTLINE) ; // assegno il colore al contorno bOk = bOk && m_pGeomDB->SetMaterial( nCrvId, cCol) ; return bOk ; } //---------------------------------------------------------------------------- int MachMgr::AddRawPart( int nCrvSrfId, double dOverMat, Color cCol) { // verifico il gruppo dei grezzi nella macchinata corrente if ( GetCurrRawGroupId() == GDB_ID_NULL) return GDB_ID_NULL ; // recupero il tipo di oggetto per definire il grezzo int nGtype = m_pGeomDB->GetGeoType( nCrvSrfId) ; // costruzione del grezzo int nRawId = GDB_ID_NULL ; // se grezzo da superficie (per ora senza possibilità di offset) if ( ( nGtype & GEO_SURF) != 0) { // inserisco il grezzo nRawId = AddRawPart( nCrvSrfId, cCol) ; } // se altrimenti grezzo da contorno else if ( ( nGtype & GEO_CURVE) != 0) { // recupero la curva const ICurve* pCrv = GetCurve( m_pGeomDB->GetGeoObj( nCrvSrfId)) ; if ( pCrv == nullptr) return GDB_ID_NULL ; // copio la curva in una composita PtrOwner pMyCrv( ConvertCurveToComposite( pCrv->Clone())) ; if ( IsNull( pMyCrv)) return GDB_ID_NULL ; // se non è chiusa, la chiudo pMyCrv->Close() ; // recupero l'estrusione e lo spessore Vector3d vtExtr ; if ( ! pMyCrv->GetExtrusion( vtExtr) || vtExtr.IsSmall()) vtExtr = Z_AX ; double dThick = 0 ; pMyCrv->GetThickness( dThick) ; if ( abs( dThick) + 2 * dOverMat < 10 *EPS_SMALL) dThick = 1 ; // la oriento in senso CCW Plane3d plPlane ; double dArea ; if ( ! pMyCrv->GetArea( plPlane, dArea)) return GDB_ID_NULL ; if ( plPlane.GetVersN() * vtExtr * dArea < 0) pMyCrv->Invert() ; // ne eseguo l'offset OffsetCurve OffsCrv ; OffsCrv.Make( pMyCrv, dOverMat, ICurve::OFF_EXTEND) ; PtrOwner pOffsCrv( OffsCrv.GetLongerCurve()) ; if ( IsNull( pOffsCrv)) return GDB_ID_NULL ; // aggiusto per sovramateriale lungo estrusione pMyCrv->Translate( vtExtr * -copysign( dOverMat, dThick)) ; // creo il solido double dH = dThick + 2 * copysign( dOverMat, dThick) ; PtrOwner pStm( GetSurfTriMeshByExtrusion( pOffsCrv, vtExtr * dH, true, 50 * EPS_SMALL)) ; if ( IsNull( pStm)) return false ; // lo inserisco nel DB geometrico int nSrfId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, m_pGeomDB->GetParentId( nCrvSrfId), Release( pStm)) ; if ( nSrfId == GDB_ID_NULL) return GDB_ID_NULL ; // inserisco il grezzo nRawId = AddRawPart( nSrfId, cCol) ; // cancello la superficie m_pGeomDB->Erase( nSrfId) ; } // verifico costruzione grezzo if ( nRawId == GDB_ID_NULL) return GDB_ID_NULL ; // se definita tavola, aggiusto posizione del grezzo Point3d ptTabRef ; if ( GetTableRef( 1, ptTabRef)) { // recupero box del solido int nRawSolidId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ; BBox3d b3RawSolid ; // lo porto nell'angolo in basso a sinistra della tavola if ( m_pGeomDB->GetGlobalBBox( nRawSolidId, b3RawSolid)) m_pGeomDB->TranslateGlob( nRawId, ptTabRef - b3RawSolid.GetMin()) ; } return nRawId ; } //---------------------------------------------------------------------------- int MachMgr::AddRawPartWithPart( int nPartId, int nCrvSrfId, double dOverMat, Color cCol) { // verifico il gruppo dei grezzi nella macchinata corrente if ( GetCurrRawGroupId() == GDB_ID_NULL) return GDB_ID_NULL ; // verifico che il pezzo non sia già usato nella macchinata corrente if ( m_pGeomDB->GetParentId( nPartId) != GDB_ID_ROOT) return GDB_ID_NULL ; // recupero il tipo di oggetto per definire il grezzo int nGtype = m_pGeomDB->GetGeoType( nCrvSrfId) ; // punto di riferimento del pezzo nel grezzo Point3d ptRef ; // costruzione del grezzo int nRawId = GDB_ID_NULL ; // se grezzo da superficie (per ora senza possibilità di offset) if ( ( nGtype & GEO_SURF) != 0) { // inserisco il grezzo nRawId = AddRawPart( nCrvSrfId, cCol) ; // se inserimento riuscito, nascondo la superficie originale if ( nRawId != GDB_ID_NULL) m_pGeomDB->SetStatus( nCrvSrfId, GDB_ST_OFF) ; // annullo il sovra-materiale dOverMat = 0 ; // calcolo il punto di inserimento nel grezzo // determino l'ingombro del pezzo BBox3d b3Part ; if ( ! m_pGeomDB->GetGlobalBBox( nPartId, b3Part, BBF_EXACT)) return GDB_ID_NULL ; // recupero il box del solido del grezzo in globale int nRawSolidId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ; BBox3d b3RawSolid ; if ( ! m_pGeomDB->GetGlobalBBox( nRawSolidId, b3RawSolid)) return false ; // calcolo il punto di inserimento (come differenza tra i punti minimi) ptRef = b3Part.GetMin() + ( ORIG - b3RawSolid.GetMin()) ; } // se altrimenti grezzo da contorno else if ( ( nGtype & GEO_CURVE) != 0) { // determino l'ingombro del pezzo BBox3d b3Part ; if ( ! m_pGeomDB->GetGlobalBBox( nPartId, b3Part, BBF_EXACT)) return GDB_ID_NULL ; // inserisco il grezzo double dZmin = b3Part.GetMin().z ; double dH = ( b3Part.GetMax() - b3Part.GetMin()).z ; if ( dH < RAW_MIN_H) dH = RAW_MIN_H ; nRawId = AddRawPart( nCrvSrfId, dOverMat, dZmin, dH, cCol) ; // calcolo il punto di inserimento nel grezzo // recupero il box del solido del grezzo in globale int nRawSolidId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ; BBox3d b3RawSolid ; if ( ! m_pGeomDB->GetGlobalBBox( nRawSolidId, b3RawSolid)) return false ; // calcolo il punto di inserimento (come differenza tra i punti minimi) ptRef = b3Part.GetMin() + ( ORIG - b3RawSolid.GetMin()) ; } // altrimenti grezzo rettangolare da ingombro pezzo else { // determino l'ingombro del pezzo BBox3d b3Part ; if ( ! m_pGeomDB->GetGlobalBBox( nPartId, b3Part, BBF_EXACT)) return GDB_ID_NULL ; // deduco i dati del grezzo b3Part.Expand( dOverMat, dOverMat, 0) ; Vector3d vtDiff = b3Part.GetMax() - b3Part.GetMin() ; if ( vtDiff.z < RAW_MIN_H) vtDiff.z = RAW_MIN_H ; // inserisco il grezzo nRawId = AddRawPart( ORIG, vtDiff.x, vtDiff.y, vtDiff.z, cCol) ; // il riferimento deve tenere conto dell'offset ptRef = Point3d( dOverMat, dOverMat, 0) ; } // verifico costruzione grezzo if ( nRawId == GDB_ID_NULL) return GDB_ID_NULL ; // se definita tavola, aggiusto posizione del grezzo Point3d ptTabRef ; if ( GetTableRef( 1, ptTabRef)) { // recupero box del solido int nRawSolidId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ; BBox3d b3RawSolid ; // lo porto nell'angolo in basso a sinistra della tavola if ( m_pGeomDB->GetGlobalBBox( nRawSolidId, b3RawSolid)) m_pGeomDB->TranslateGlob( nRawId, ptTabRef - b3RawSolid.GetMin()) ; } // inserisco il pezzo nel grezzo if ( ! AddPartToRawPart( nPartId, ptRef, nRawId)) { RemoveRawPart( nRawId) ; return GDB_ID_NULL ; } return nRawId ; } //---------------------------------------------------------------------------- int MachMgr::AddRawPart( int nCrvId, double dOverMat, double dZmin, double dHeight, Color cCol) { // recupero il gruppo dei grezzi nella macchinata corrente int nRawGroupId = GetCurrRawGroupId() ; if ( nRawGroupId == GDB_ID_NULL) return GDB_ID_NULL ; // recupero l'ingombro della curva in globale BBox3d b3Crv ; if ( ! m_pGeomDB->GetGlobalBBox( nCrvId, b3Crv)) return GDB_ID_NULL ; // determino il riferimento del grezzo Point3d ptOrig = b3Crv.GetMin() ; ptOrig.z = dZmin ; Frame3d frRaw( ptOrig) ; // inserisco il gruppo del grezzo nella macchinata int nRawId = m_pGeomDB->AddGroup( GDB_ID_NULL, nRawGroupId, frRaw) ; if ( nRawId == GDB_ID_NULL) return GDB_ID_NULL ; // assegno il nome al gruppo bool bOk = m_pGeomDB->SetName( nRawId, MACH_RAW_PART) ; // assegno la fase al gruppo m_pGeomDB->SetInfo( nRawId, MACH_RAW_PHASE, m_nCurrPhase) ; // creo solido e outline bOk = bOk && ModifyRawPart( nRawId, nCrvId, dOverMat, dHeight, cCol) ; // se qualcosa è andato storto, cancello tutto if ( ! bOk) { m_pGeomDB->Erase( nRawId) ; return GDB_ID_NULL ; } // tutto ok return nRawId ; } //---------------------------------------------------------------------------- bool MachMgr::ModifyRawPart( int nRawId, int nCrvId, double dOverMat, double dHeight, Color cCol) { // verifica validità grezzo if ( ! VerifyRawPart( nRawId)) return false ; // recupero il riferimento della curva Frame3d frCrv ; if ( ! m_pGeomDB->GetGlobFrame( nCrvId, frCrv)) return false ; // recupero la curva const ICurve* pCrv = GetCurve( m_pGeomDB->GetGeoObj( nCrvId)) ; if ( pCrv == nullptr) return false ; // copio la curva in una composita PtrOwner pMyCrv( CreateCurveComposite()) ; if ( IsNull( pMyCrv) || ! pMyCrv->AddCurve( *pCrv)) return false ; // determino il riferimento del grezzo Frame3d frRaw ; if ( ! m_pGeomDB->GetGroupGlobFrame( nRawId, frRaw)) return false ; // porto la curva in questo riferimento pMyCrv->LocToLoc( frCrv, frRaw) ; // la schiaccio a Z = 0 if ( ! pMyCrv->Scale( Frame3d(), 1, 1, 0)) return false ; // se non è chiusa, la chiudo pMyCrv->Close() ; // la oriento in senso CCW double dAreaXY ; if ( ! pMyCrv->GetAreaXY( dAreaXY)) return false ; if ( dAreaXY < 0) pMyCrv->Invert() ; // ne eseguo l'offset OffsetCurve OffsCrv ; OffsCrv.Make( pMyCrv, dOverMat, ICurve::OFF_EXTEND) ; PtrOwner pOffsCrv( OffsCrv.GetLongerCurve()) ; if ( IsNull( pOffsCrv)) return false ; // creo il solido PtrOwner pStm( GetSurfTriMeshByExtrusion( pOffsCrv, Vector3d( 0, 0, dHeight), true)) ; if ( IsNull( pStm)) return false ; // cancello eventuali vecchi solidi e curve di outline int nOldRawSolId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ; if ( nOldRawSolId != GDB_ID_NULL) m_pGeomDB->Erase( nOldRawSolId) ; int nOldRawOutId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_OUTLINE) ; if ( nOldRawOutId != GDB_ID_NULL) m_pGeomDB->Erase( nOldRawOutId) ; // inserisco il solido nel gruppo int nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nRawId, Release( pStm)) ; bool bOk = ( nId != GDB_ID_NULL) ; // assegno il nome al solido bOk = bOk && m_pGeomDB->SetName( nId, MACH_RAW_SOLID) ; // assegno il colore al solido bOk = bOk && m_pGeomDB->SetMaterial( nId, cCol) ; // calcolo il punto centro del solido bOk = bOk && SetRawPartCenter( nRawId) ; // inserisco nel DB la curva di offset come contorno del grezzo int nOutCrvId = ( bOk ? m_pGeomDB->AddGeoObj( GDB_ID_NULL, nRawId, Release( pOffsCrv)) : GDB_ID_NULL) ; bOk = bOk && ( nOutCrvId != GDB_ID_NULL) ; // assegno il nome al contorno bOk = bOk && m_pGeomDB->SetName( nOutCrvId, MACH_RAW_OUTLINE) ; // assegno il colore al contorno bOk = bOk && m_pGeomDB->SetMaterial( nOutCrvId, cCol) ; return bOk ; } //---------------------------------------------------------------------------- int MachMgr::AddRawPart( int nSurfId, Color cCol) { // recupero il gruppo dei grezzi nella macchinata corrente int nRawGroupId = GetCurrRawGroupId() ; if ( nRawGroupId == GDB_ID_NULL) return GDB_ID_NULL ; // verifico che la superficie sia chiusa const ISurf* pSurf = GetSurf( m_pGeomDB->GetGeoObj( nSurfId)) ; if ( pSurf == nullptr || ! pSurf->IsClosed()) return GDB_ID_NULL ; // recupero l'ingombro della superficie in globale BBox3d b3Surf ; if ( ! m_pGeomDB->GetGlobalBBox( nSurfId, b3Surf)) return GDB_ID_NULL ; // inserisco il gruppo del grezzo nella macchinata Frame3d frRaw( b3Surf.GetMin()) ; int nRawId = m_pGeomDB->AddGroup( GDB_ID_NULL, nRawGroupId, frRaw) ; if ( nRawId == GDB_ID_NULL) return GDB_ID_NULL ; // assegno il nome al gruppo bool bOk = m_pGeomDB->SetName( nRawId, MACH_RAW_PART) ; // assegno la fase al gruppo m_pGeomDB->SetInfo( nRawId, MACH_RAW_PHASE, m_nCurrPhase) ; // creo il grezzo int nId = GDB_ID_NULL ; // partendo da superficie Trimesh copio if ( pSurf->GetType() == SRF_TRIMESH) nId = m_pGeomDB->CopyGlob( nSurfId, GDB_ID_NULL, nRawId) ; // partendo da superficie Bezier devo recuperare la Trimesh ausiliaria e copiarla else if ( pSurf->GetType() == SRF_BEZIER) { const ISurfBezier* pSbez = GetSurfBezier( pSurf) ; const ISurfTriMesh* pAuxStm = ( pSbez != nullptr ? pSbez->GetAuxSurf() : nullptr) ; PtrOwner pStm( pAuxStm != nullptr ? pAuxStm->Clone() : nullptr) ; if ( ! IsNull( pStm)) { Frame3d frSbez ; m_pGeomDB->GetGlobFrame( nSurfId, frSbez) ; pStm->LocToLoc( frSbez, frRaw) ; nId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nRawId, Release( pStm)) ; } } bOk = bOk && ( nId != GDB_ID_NULL) ; // assegno il nome al solido bOk = bOk && m_pGeomDB->SetName( nId, MACH_RAW_SOLID) ; // assegno il colore al solido bOk = bOk && m_pGeomDB->SetMaterial( nId, cCol) ; // rendo visibile il solido bOk = bOk && m_pGeomDB->SetStatus( nId, GDB_ST_ON) ; // calcolo il punto centro del solido bOk = bOk && SetRawPartCenter( nRawId) ; // calcolo la curva di contorno bOk = bOk && UpdateRawOutline( nRawId) ; // se qualcosa è andato storto, cancello tutto if ( ! bOk) { m_pGeomDB->Erase( nRawId) ; return GDB_ID_NULL ; } // tutto ok return nRawId ; } //---------------------------------------------------------------------------- int MachMgr::AddRawPart( int nSfrUpId, int nSfrDownId, double dHeight, Color cCol) { // recupero il gruppo dei grezzi nella macchinata corrente int nRawGroupId = GetCurrRawGroupId() ; if ( nRawGroupId == GDB_ID_NULL) return GDB_ID_NULL ; // recupero l'ingombro della superficie up in globale BBox3d b3Surf ; if ( ! m_pGeomDB->GetGlobalBBox( nSfrUpId, b3Surf)) return GDB_ID_NULL ; // inserisco il gruppo del grezzo nella macchinata Frame3d frRaw( b3Surf.GetMin()) ; int nRawId = m_pGeomDB->AddGroup( GDB_ID_NULL, nRawGroupId, frRaw) ; if ( nRawId == GDB_ID_NULL) return GDB_ID_NULL ; // assegno il nome al gruppo bool bOk = m_pGeomDB->SetName( nRawId, MACH_RAW_PART) ; // assegno la fase al gruppo bOk = bOk && m_pGeomDB->SetInfo( nRawId, MACH_RAW_PHASE, m_nCurrPhase) ; // recupero il frame originale della superficie up ( deve essere lo stesso della down) Frame3d frSurf ; bOk = bOk && m_pGeomDB->GetGlobFrame( nSfrUpId, frSurf) ; // creo il volume in modo approssimativo a partire dalle due superfici considerando soltanto un'approssimazione dei bordi esterni // regione up PtrOwner pSurfUp( CloneSurfFlatRegion( m_pGeomDB->GetGeoObj( nSfrUpId))) ; bOk = bOk && ( ! IsNull( pSurfUp)) ; // calcolo offset e contro-offset per unificare i chunk ed eliminare eventuali rientranze nella superficie double dOffs = 8 ; bOk = bOk && pSurfUp->Offset( dOffs, ICurve::OFF_FILLET) ; bOk = bOk && pSurfUp->Offset( -dOffs, ICurve::OFF_FILLET) ; // recupero il chunk di area maggiore int nKMax = 0 ; if ( bOk && pSurfUp->GetChunkCount() > 1) { double dAreaMax = -1 ; for ( int k = 0 ; k < pSurfUp->GetChunkCount() ; k ++) { PtrOwner pSfrChunk( pSurfUp->CloneChunk( k)) ; double dArea = -1 ; pSfrChunk->GetGrossArea( dArea) ; if ( dArea > dAreaMax) { nKMax = k ; dAreaMax = dArea ; } } } PtrOwner pCrvUp ; bOk = bOk && pCrvUp.Set( pSurfUp->GetLoop( nKMax, 0)) ; bOk = bOk && ( ! IsNull( pCrvUp)) ; // regione down PtrOwner pSurfDown( CloneSurfFlatRegion( m_pGeomDB->GetGeoObj( nSfrDownId))) ; bOk = bOk && ( ! IsNull( pSurfDown)) ; bOk = bOk && pSurfDown->Offset( dOffs, ICurve::OFF_FILLET) ; bOk = bOk && pSurfDown->Offset( -dOffs, ICurve::OFF_FILLET) ; nKMax = 0 ; if ( bOk && pSurfDown->GetChunkCount() > 1) { double dAreaMax = -1 ; for ( int k = 0 ; k < pSurfDown->GetChunkCount() ; k ++) { PtrOwner pSfrChunk( pSurfDown->CloneChunk( k)) ; double dArea = -1 ; pSfrChunk->GetGrossArea( dArea) ; if ( dArea > dAreaMax) { nKMax = k ; dAreaMax = dArea ; } } } PtrOwner pCrvDown ; bOk = bOk && pCrvDown.Set( ConvertCurveToComposite( pSurfDown->GetLoop( nKMax, 0))) ; bOk = bOk && ( ! IsNull( pCrvDown)) ; // sposto il punto di inizio il più vicino possibile a quello della curva up per migliorare il calcolo della rigata if ( bOk) { Point3d ptS ; pCrvUp->GetStartPoint( ptS) ; DistPointCurve distPC( ptS, *pCrvDown) ; double dPar ; int nFlag ; bOk = bOk && distPC.GetParamAtMinDistPoint( 0, dPar, nFlag) ; bOk = bOk && pCrvDown->ChangeStartPoint( dPar) ; } // volume PtrOwner pStmRaw ; bOk = bOk && pStmRaw.Set( GetSurfTriMeshByFlatContour( pCrvUp)) ; bOk = bOk && ( ! IsNull( pStmRaw)) ; PtrOwner pStmLat ; bOk = bOk && pStmLat.Set( GetSurfTriMeshRuled( pCrvDown, pCrvUp, ISurfTriMesh::RLT_MINDIST)) ; bOk = bOk && ( ! IsNull( pStmLat)) ; bOk = bOk && pStmRaw->DoSewing( *pStmLat) ; PtrOwner pStmDown ; bOk = bOk && pStmDown.Set( GetSurfTriMeshByFlatContour( pCrvDown)) ; bOk = bOk && pStmDown->Invert() ; bOk = bOk && pStmRaw->DoSewing( *pStmDown) ; bOk = bOk && pStmRaw->DoCompacting() ; bOk = bOk && pStmRaw->Repair() ; bOk = bOk && pStmRaw->LocToLoc( frSurf, frRaw) ; int nId = bOk ? m_pGeomDB->AddGeoObj( GDB_ID_NULL, nRawId, Release( pStmRaw)) : GDB_ID_NULL ; bOk = bOk && ( nId != GDB_ID_NULL) ; // assegno il nome al solido bOk = bOk && m_pGeomDB->SetName( nId, MACH_RAW_SOLID) ; // assegno il colore al solido bOk = bOk && m_pGeomDB->SetMaterial( nId, cCol) ; // rendo visibile il solido bOk = bOk && m_pGeomDB->SetStatus( nId, GDB_ST_ON) ; // calcolo il punto centro del solido bOk = bOk && SetRawPartCenter( nRawId) ; if ( bOk) { // costruisco la curva di contorno PtrOwner pSfrUp( CloneSurfFlatRegion( m_pGeomDB->GetGeoObj( nSfrUpId))) ; PtrOwner pSfrDown( CloneSurfFlatRegion( m_pGeomDB->GetGeoObj( nSfrDownId))) ; bOk = bOk && ( ! IsNull( pSfrUp)) && ( ! IsNull( pSfrDown)) ; if ( bOk) pSfrUp->Add( *pSfrDown) ; PtrOwner pCrv ; bOk = bOk && pCrv.Set( pSfrUp->GetLoop( 0, 0)) ; bOk = bOk && ( ! IsNull( pCrv)) ; bOk = bOk && pCrv->LocToLoc( frSurf, frRaw) ; int nLoop = bOk ? m_pGeomDB->AddGeoObj( GDB_ID_NULL, nRawId, Release( pCrv)) : GDB_ID_NULL ; bOk = bOk && ( nLoop != GDB_ID_NULL) ; bOk = bOk && ExeMove( {nLoop}, -dHeight * Z_AX, RTY_LOC) ; // assegno il nome alla curva bOk = bOk && m_pGeomDB->SetName( nLoop, MACH_RAW_OUTLINE) ; // assegno il colore alla curva bOk = bOk && m_pGeomDB->SetMaterial( nLoop, cCol) ; // recupero le superfici up e down int nSurfUpId = ( bOk ? m_pGeomDB->CopyGlob( nSfrUpId, GDB_ID_NULL, nRawId) : GDB_ID_NULL) ; bOk = bOk && ( nSurfUpId != GDB_ID_NULL) ; bOk = bOk && m_pGeomDB->SetName( nSurfUpId, MACH_RAW_UP_REG) ; bOk = bOk && m_pGeomDB->SetMaterial( nSurfUpId, cCol) ; bOk = bOk && m_pGeomDB->SetMode( nSurfUpId, GDB_MD_HIDDEN) ; int nSurfDownId = ( bOk ? m_pGeomDB->CopyGlob( nSfrDownId, GDB_ID_NULL, nRawId) : GDB_ID_NULL) ; bOk = bOk && ( nSurfDownId != GDB_ID_NULL) ; bOk = bOk && m_pGeomDB->SetName( nSurfDownId, MACH_RAW_DOWN_REG) ; bOk = bOk && m_pGeomDB->SetMaterial( nSurfDownId, cCol) ; bOk = bOk && m_pGeomDB->SetMode( nSurfDownId, GDB_MD_HIDDEN) ; } // se qualcosa è andato storto, cancello tutto if ( ! bOk) { m_pGeomDB->Erase( nRawId) ; return GDB_ID_NULL ; } // tutto ok return nRawId ; } //---------------------------------------------------------------------------- bool MachMgr::ModifyRawPartSize( int nRawId, double dLength, double dWidth, double dHeight) { // le nuove dimensioni non possono essere nulle if ( dLength < EPS_SMALL || dWidth < EPS_SMALL || dHeight < EPS_SMALL) return false ; // verifica validità grezzo if ( ! VerifyRawPart( nRawId)) return false ; // recupero il solido del grezzo int nRawSolId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ; if ( nRawSolId == GDB_ID_NULL) return false ; // recupero il contorno del grezzo int nRawOutId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_OUTLINE) ; if ( nRawOutId == GDB_ID_NULL) return false ; // recupero il box del grezzo BBox3d b3Raw ; if ( ! m_pGeomDB->GetLocalBBox( nRawSolId, b3Raw)) return false ; // determino il coefficente di scalatura in X double dOldL = b3Raw.GetMax().x - b3Raw.GetMin().x ; if ( dOldL < EPS_SMALL) return false ; double dCoeffX = dLength / dOldL ; // determino il coefficente di scalatura in Y double dOldW = b3Raw.GetMax().y - b3Raw.GetMin().y ; if ( dOldW < EPS_SMALL) return false ; double dCoeffY = dWidth / dOldW ; // determino il coefficente di scalatura in Z double dOldH = b3Raw.GetMax().z - b3Raw.GetMin().z ; if ( dOldH < EPS_SMALL) return false ; double dCoeffZ = dHeight / dOldH ; // eseguo scalature bool bOk = m_pGeomDB->Scale( nRawSolId, Frame3d( b3Raw.GetMin()), dCoeffX, dCoeffY, dCoeffZ) && m_pGeomDB->Scale( nRawOutId, Frame3d( b3Raw.GetMin()), dCoeffX, dCoeffY, dCoeffZ) ; // calcolo il punto centro del solido bOk = bOk && SetRawPartCenter( nRawId) ; return bOk ; } //---------------------------------------------------------------------------- bool MachMgr::ModifyRawPartHeight( int nRawId, double dHeight) { // la nuova altezza non può essere nulla if ( dHeight < EPS_SMALL) return false ; // verifica validità grezzo if ( ! VerifyRawPart( nRawId)) return false ; // recupero il solido del grezzo int nRawSolId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ; if ( nRawSolId == GDB_ID_NULL) return false ; // recupero il box del grezzo BBox3d b3Raw ; if ( ! m_pGeomDB->GetLocalBBox( nRawSolId, b3Raw)) return false ; // determino il coefficente di scalatura in Z double dOldH = b3Raw.GetMax().z - b3Raw.GetMin().z ; if ( dOldH < EPS_SMALL) return false ; double dCoeff = dHeight / dOldH ; // eseguo scalatura bool bOk = m_pGeomDB->Scale( nRawSolId, Frame3d( b3Raw.GetMin()), 1, 1, dCoeff) ; // calcolo il punto centro del solido bOk = bOk && SetRawPartCenter( nRawId) ; return bOk ; } //---------------------------------------------------------------------------- bool MachMgr::GetRawPartPhases( int nRawId, INTVECTOR& vPhase) const { // pulisco parametro di ritorno vPhase.clear() ; // verifica validità grezzo if ( ! VerifyRawPart( nRawId)) return false ; // recupero le fasi in cui è presente il grezzo (se manca è fase 1) if ( ! m_pGeomDB->GetInfo( nRawId, MACH_RAW_PHASE, vPhase) || vPhase.empty()) vPhase.emplace_back( 1) ; return true ; } //---------------------------------------------------------------------------- bool MachMgr::KeepRawPart( int nRawId, int nSouPhase) { // verifico validità e recupero fasi in cui è presente INTVECTOR vPhase ; if ( ! GetRawPartPhases( nRawId, vPhase)) return false ; // se fase corrente già presente, non devo fare alcunché if ( find( vPhase.begin(), vPhase.end(), m_nCurrPhase) != vPhase.end()) return true ; // aggiungo la fase corrente vPhase.emplace_back( m_nCurrPhase) ; if ( ! m_pGeomDB->SetInfo( nRawId, MACH_RAW_PHASE, vPhase)) return false ; // annullo eventuali movimenti del grezzo (riferimento riportato a globale) Frame3d* pfrRaw = m_pGeomDB->GetGroupFrame( nRawId) ; if ( pfrRaw == nullptr) return false ; pfrRaw->Reset() ; // visualizzo il grezzo e ne attivo i pezzi if ( ! m_pGeomDB->SetStatus( nRawId, GDB_ST_ON)) return false ; if ( ! SwapRawPartParts( nRawId, true)) return false ; // se fase di origine non definita o uguale alla corrente, esco con successo if ( nSouPhase == 0 || nSouPhase == m_nCurrPhase) return true ; // copio il posizionamento Disposition* pSouDisp = GetDisposition( m_pGeomDB->GetUserObj( GetPhaseDisposition( nSouPhase))) ; Disposition* pDisp = GetDisposition( m_pGeomDB->GetUserObj( GetPhaseDisposition( m_nCurrPhase))) ; if ( pSouDisp == nullptr || pDisp == nullptr) return false ; for ( int i = 0 ; ; ++ i) { int nId ; int nType ; Point3d ptPos ; int nFlag ; if ( pSouDisp->GetMoveRawData( i, nId, nType, ptPos, nFlag)) { if ( nId == nRawId) { switch ( nType) { case MoveRawData::COR : pDisp->MoveToCornerRawPart( nRawId, ptPos, nFlag, true, false) ; break ; case MoveRawData::CEN : pDisp->MoveToCenterRawPart( nRawId, ptPos, nFlag, true, false) ; break ; case MoveRawData::ROT : pDisp->ApplyRotationToRawPart( nRawId, ptPos.x, ptPos.y, ptPos.z, true) ; break ; } } } else break ; } return true ; } //---------------------------------------------------------------------------- bool MachMgr::VerifyRawPartPhase( int nRawId, int nPhase) const { // verifico validità e recupero fasi in cui è presente INTVECTOR vPhase ; if ( ! GetRawPartPhases( nRawId, vPhase)) return false ; // verifico presenza nella fase indicata return ( find( vPhase.begin(), vPhase.end(), nPhase) != vPhase.end()) ; } //---------------------------------------------------------------------------- bool MachMgr::RemoveRawPartFromCurrPhase( int nRawId) { // verifico validità e recupero fasi in cui è presente INTVECTOR vPhase ; if ( ! GetRawPartPhases( nRawId, vPhase)) return false ; // se non appartiene alla fase corrente, non devo fare alcunché auto iIter = find( vPhase.begin(), vPhase.end(), m_nCurrPhase) ; if ( iIter == vPhase.end()) return true ; // se appartiene solo a questa fase, lo elimino if ( vPhase.size() == 1) RemoveRawPart( nRawId) ; // altrimenti else { // tolgo dalla disposizione corrente gli eventuali movimenti registrati di questo grezzo Disposition* pDisp = GetDisposition( m_pGeomDB->GetUserObj( GetPhaseDisposition( m_nCurrPhase))) ; if ( pDisp != nullptr) pDisp->RemoveRawPart( nRawId) ; // aggiorno l'elenco delle fasi di appartenenza vPhase.erase( iIter) ; m_pGeomDB->SetInfo( nRawId, MACH_RAW_PHASE, vPhase) ; // tolgo i pezzi dal grezzo e lo nascondo SwapRawPartParts( nRawId, false) ; m_pGeomDB->SetStatus( nRawId, GDB_ST_OFF) ; } return true ; } //---------------------------------------------------------------------------- bool MachMgr::RemoveRawPart( int nRawId) { // verifica validità grezzo if ( ! VerifyRawPart( nRawId)) return false ; // tolgo dalle disposizioni in cui compare gli eventuali movimenti registrati di questo grezzo for ( int nPhase = 1 ; nPhase <= m_nPhasesCount ; ++ nPhase) { Disposition* pDisp = GetDisposition( m_pGeomDB->GetUserObj( GetPhaseDisposition( nPhase))) ; if ( pDisp != nullptr) pDisp->RemoveRawPart( nRawId) ; } // devo estrarre i pezzi e riportarli in lista generale SwapRawPartParts( nRawId, false) ; // cancello il grezzo m_pGeomDB->Erase( nRawId) ; return true ; } //---------------------------------------------------------------------------- bool MachMgr::VerifyRawPart( int nRawId, bool bLinkedAllowed) const { // se il grezzo fa parte del gruppo dei grezzi, va bene int nRawGroupId = GetCurrRawGroupId() ; if ( nRawGroupId != GDB_ID_NULL && m_pGeomDB->GetParentId( nRawId) == nRawGroupId) return true ; // se consentito linkaggio ed il grezzo è linkato ad un gruppo della macchina corrente, va bene if ( bLinkedAllowed) { Machine* pMch = GetCurrMachine() ; if ( pMch != nullptr && pMch->IsLinkedRawPart( nRawId)) return true ; } // altrimenti errore return false ; } //---------------------------------------------------------------------------- bool MachMgr::RotateRawPart( int nRawId, const Vector3d& vtAx, double dAngRotDeg) { // recupero l'oggetto disposizione corrente Disposition* pDisp = ::GetDisposition( m_pGeomDB->GetUserObj( m_nCurrDispId)) ; if ( pDisp == nullptr) return false ; // eseguo l'operazione if ( ! pDisp->RotateRawPart( nRawId, vtAx, dAngRotDeg)) { LOG_ERROR( GetEMkLogger(), "Error on RotateRawPart") ; return false ; } // se rotazione non è attorno a Z, aggiorno la curva di outline if ( abs( dAngRotDeg) > EPS_ANG_ZERO && ! vtAx.IsZ()) UpdateRawOutline( nRawId) ; return true ; } //---------------------------------------------------------------------------- bool MachMgr::MoveToCornerRawPart( int nRawId, const Point3d& ptP, int nFlag) { // recupero l'oggetto disposizione corrente Disposition* pDisp = ::GetDisposition( m_pGeomDB->GetUserObj( m_nCurrDispId)) ; if ( pDisp == nullptr) return false ; // eseguo l'operazione if ( ! pDisp->MoveToCornerRawPart( nRawId, ptP, nFlag)) { LOG_ERROR( GetEMkLogger(), "Error on MoveToCornerRawPart") ; return false ; } return true ; } //---------------------------------------------------------------------------- bool MachMgr::MoveToCenterRawPart( int nRawId, const Point3d& ptP, int nFlag) { // recupero l'oggetto disposizione corrente Disposition* pDisp = ::GetDisposition( m_pGeomDB->GetUserObj( m_nCurrDispId)) ; if ( pDisp == nullptr) return false ; // eseguo l'operazione if ( ! pDisp->MoveToCenterRawPart( nRawId, ptP, nFlag)) { LOG_ERROR( GetEMkLogger(), "Error on MoveToCenterRawPart") ; return false ; } return true ; } //---------------------------------------------------------------------------- bool MachMgr::MoveRawPart( int nRawId, const Vector3d& vtMove) { // recupero l'oggetto disposizione corrente Disposition* pDisp = ::GetDisposition( m_pGeomDB->GetUserObj( m_nCurrDispId)) ; if ( pDisp == nullptr) return false ; // eseguo l'operazione if ( ! pDisp->MoveRawPart( nRawId, vtMove)) { LOG_ERROR( GetEMkLogger(), "Error on MoveRawPart") ; return false ; } return true ; } //---------------------------------------------------------------------------- bool MachMgr::SetRawPartCenter( int nRawId) { // recupero il solido int nRawSolId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ; const ISurfTriMesh* pStm = GetSurfTriMesh( m_pGeomDB->GetGeoObj( nRawSolId)) ; if ( pStm == nullptr) return false ; // recupero il punto centro, se non esiste lo creo int nGPntId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_CENTER) ; if ( nGPntId == GDB_ID_NULL) { PtrOwner pGeoPnt( CreateGeoPoint3d()) ; nGPntId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nRawId, Release( pGeoPnt)) ; m_pGeomDB->SetName( nGPntId, MACH_RAW_CENTER) ; Color cCol ; if ( m_pGeomDB->GetCalcMaterial( nRawSolId, cCol)) m_pGeomDB->SetMaterial( nGPntId, cCol) ; } IGeoPoint3d* pGeoPnt = GetGeoPoint3d( m_pGeomDB->GetGeoObj( nGPntId)) ; if ( pGeoPnt == nullptr) return false ; // calcolo il valore del centro Point3d ptCen ; if ( ! pStm->GetCentroid( ptCen)) return false ; // aggiorno e imposto modo a standard return ( pGeoPnt->Set( ptCen) && m_pGeomDB->SetMode( nGPntId, GDB_MD_STD)) ; } //---------------------------------------------------------------------------- bool MachMgr::ResetRawPartCenter( int nRawId) { // recupero il punto centro int nGPntId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_CENTER) ; if ( nGPntId == GDB_ID_NULL) return true ; // imposto modo a bloccato return m_pGeomDB->SetMode( nGPntId, GDB_MD_HIDDEN) ; } //---------------------------------------------------------------------------- bool MachMgr::GetRawPartCenter( int nRawId, Point3d& ptCen) { // verifica validità grezzo if ( ! VerifyRawPart( nRawId)) return false ; // cerco di recuperare l'oggetto int nGPntId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_CENTER) ; // ne verifico la validità int nMode ; if ( nGPntId == GDB_ID_NULL || ! m_pGeomDB->GetMode( nGPntId, nMode) || nMode != GDB_MD_STD) { // provo a crearlo SetRawPartCenter( nRawId) ; nGPntId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_CENTER) ; // se non riesco, errore if ( nGPntId == GDB_ID_NULL) return false ; } // ne recupero il riferimento globale Frame3d frGPnt ; if ( ! m_pGeomDB->GetGlobFrame( nGPntId, frGPnt)) return false ; // recupero il punto IGeoPoint3d* pGeoPnt = GetGeoPoint3d( m_pGeomDB->GetGeoObj( nGPntId)) ; if ( pGeoPnt == nullptr) return false ; ptCen = pGeoPnt->GetPoint() ; ptCen.ToGlob( frGPnt) ; return true ; } //---------------------------------------------------------------------------- bool MachMgr::GetRawPartBBox( int nRawId, BBox3d& b3Raw) { // verifica validità grezzo if ( ! VerifyRawPart( nRawId)) return false ; // recupero solido del grezzo int nRawSolidId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ; return m_pGeomDB->GetGlobalBBox( nRawSolidId, b3Raw) ; } //---------------------------------------------------------------------------- bool MachMgr::UpdateRawOutline( int nRawId) { // cerco il solido del grezzo int nSolId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ; if ( nSolId == GDB_ID_NULL) return false ; // creo la curva PtrOwner pCrvCompo( CreateCurveComposite()) ; if ( IsNull( pCrvCompo)) return false ; // recupero la superficie trimesh in globale SurfLocal pStmG( m_pGeomDB, nSolId, GLOB_FRM) ; const ISurfTriMesh* pStm = GetSurfTriMesh( pStmG) ; if ( pStm == nullptr) return false ; // recupero l'ingombro della superficie BBox3d b3Srf ; pStm->GetLocalBBox( b3Srf) ; // ne calcolo la silhouette secondo Z+ globale bool bSilh = false ; const int NUM_TRIA_LIM = 500 ; if ( pStm->GetTriangleCount() < NUM_TRIA_LIM) { POLYLINEVECTOR vPL ; if ( pStm->GetSilhouette( Z_AX, 10.0, vPL) && ! vPL.empty()) { // cerco il contorno esterno int nInd = - 1 ; double dMaxArea = 0 ; for ( int i = 0 ; i < int( vPL.size()) ; ++ i) { double dArea ; if ( vPL[i].GetAreaXY( dArea) && abs( dArea) > dMaxArea) { if ( dArea < 0) vPL[i].Invert() ; dMaxArea = abs( dArea) ; nInd = i ; } } // ne deduco la curva PtrOwner pCrvSilh( CreateCurveComposite()) ; if ( nInd >= 0 && pCrvSilh->FromPolyLine( vPL[nInd])) { pCrvSilh->SetExtrusion( Z_AX) ; Plane3d plProj ; plProj.Set( b3Srf.GetMin(), Z_AX) ; pCrvCompo.Set( GetCurveComposite( ProjectCurveOnPlane( *pCrvSilh, plProj))) ; if ( ! IsNull( pCrvCompo)) { pCrvCompo->MergeCurves( 10 * EPS_SMALL, 10 * EPS_ANG_SMALL) ; bSilh = true ; } } } } else { PtrOwner pCavParSilh( CreateCAvParSilhouettesSurfTm()) ; if ( ! IsNull( pCavParSilh)) { Frame3d frSrf( b3Srf.GetMin()) ; const double SILH_TOL = 1.0 ; POLYLINEVECTOR vPL ; if ( pCavParSilh->SetData( { pStm}, frSrf, SILH_TOL) && pCavParSilh->GetSilhouette( 0, vPL)) { // cerco il contorno esterno int nInd = - 1 ; double dMaxArea = 0 ; for ( int i = 0 ; i < int( vPL.size()) ; ++ i) { double dArea ; if ( vPL[i].GetAreaXY( dArea) && abs( dArea) > dMaxArea) { if ( dArea < 0) vPL[i].Invert() ; dMaxArea = abs( dArea) ; nInd = i ; } } // ne deduco la curva if ( nInd >= 0 && pCrvCompo->FromPolyLine( vPL[nInd])) { pCrvCompo->SetExtrusion( Z_AX) ; bSilh = true ; } } } } // non riuscita, la calcolo come contorno del box if ( ! bSilh) { Point3d ptMin ; double dDimX, dDimY, dDimZ ; b3Srf.GetMinDim( ptMin, dDimX, dDimY, dDimZ) ; PolyLine PL ; PL.AddUPoint( 0, ptMin) ; PL.AddUPoint( 1, ptMin + Vector3d( dDimX, 0,0)) ; PL.AddUPoint( 2, ptMin + Vector3d( dDimX, dDimY,0)) ; PL.AddUPoint( 3, ptMin + Vector3d( 0, dDimY,0)) ; PL.AddUPoint( 4, ptMin) ; if ( pCrvCompo->FromPolyLine( PL)) pCrvCompo->SetExtrusion( Z_AX) ; else return false ; } // rimuovo eventuale vecchia curva int nOtlId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_OUTLINE) ; m_pGeomDB->Erase( nOtlId) ; // inserisco la curva composita nel DB Frame3d frRaw ; m_pGeomDB->GetGroupGlobFrame( nRawId, frRaw) ; pCrvCompo->ToLoc( frRaw) ; int nCrvId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nRawId, Release( pCrvCompo)) ; if ( nCrvId == GDB_ID_NULL) return false ; // assegno il nome alla curva m_pGeomDB->SetName( nCrvId, MACH_RAW_OUTLINE) ; // assegno il colore alla curva Color cCol ; if ( m_pGeomDB->GetMaterial( nSolId, cCol)) m_pGeomDB->SetMaterial( nCrvId, cCol) ; return true ; } //--------------------------------------------------------------------------- static bool AssociateSurfs( IGeomDB* pGeomDB, int nSurfUpId, int nSurfDownId, vector>& vRawSurfs) { // vRawSurfs contiene tutte le coppie ( id regioneUp, id regioneDown) che definiscono i nuovi grezzi vRawSurfs.clear() ; int nUpCnt = ExeSurfFrChunkCount( nSurfUpId) ; int nDownCnt = ExeSurfFrChunkCount( nSurfDownId) ; // se non sono stati creati più grezzi if ( nUpCnt == 1 || nDownCnt == 1) { vRawSurfs.emplace_back( nSurfUpId, nSurfDownId) ; return true ; } int nUpFirstId = ExeExplodeSurface( nSurfUpId, &nUpCnt) ; int nDownFirstId = ExeExplodeSurface( nSurfDownId, &nDownCnt) ; // ad ogni chunk della regione up associo i chunk corrispondenti della regione down INTVECTOR vChunks( nUpCnt, GDB_ID_NULL) ; for ( int nIdD = nDownFirstId ; nIdD < nDownFirstId + nDownCnt ; nIdD ++) { ISurfFlatRegion* pSfrD = GetSurfFlatRegion( pGeomDB->GetGeoObj( nIdD)) ; if ( pSfrD == nullptr) return false ; BBox3d bBoxD ; ExeGetBBox( nIdD, BBF_STANDARD, bBoxD) ; // inidividuo il chunk della superficie up che interagisce maggiormente con il chunk corrente della superficie down int k = -1 ; double dMaxArea = -1 ; for ( int j = 0 ; j < nUpCnt ; j ++) { BBox3d bBoxU ; ExeGetBBox( nUpFirstId + j, BBF_STANDARD, bBoxU) ; if ( bBoxU.OverlapsXY( bBoxD)) { PtrOwner pSfrU( CloneSurfFlatRegion( pGeomDB->GetGeoObj( nUpFirstId + j))) ; if ( IsNull( pSfrU)) return false ; // le due superfici sono nello stesso frame pSfrU->Intersect( *pSfrD) ; double dArea = -1 ; pSfrU->GetArea( dArea) ; if ( dArea > dMaxArea) { k = j ; dMaxArea = dArea ; } } } // aggiorno le superfici con l'associazione trovata if ( k == -1) return false ; if ( vChunks[k] == GDB_ID_NULL) vChunks[k] = nIdD ; else { ExeSurfFrAdd( vChunks[k], nIdD) ; ExeErase( {nIdD}) ; } } // controllo per ogni chunk della superficie up il corrispondente della nuova superficie down for ( int i = 0 ; i < nUpCnt ; i ++) { ISurfFlatRegion* pSfrU = GetSurfFlatRegion( pGeomDB->GetGeoObj( nUpFirstId + i)) ; if ( pSfrU == nullptr) return false ; BBox3d bBoxU ; ExeGetBBox( nUpFirstId + i, BBF_STANDARD, bBoxU) ; // individuo il chunk della superficie down che interagisce maggiormente con il chunk corrente della superficie up int k = -1 ; double dMaxArea = -1 ; for ( int j = 0 ; j < int( vChunks.size()) ; j ++) { BBox3d bBoxD ; ExeGetBBox( vChunks[j], BBF_STANDARD, bBoxD) ; // se i box interferiscono allora verifico di quanto si sovrappongono le due regioni if ( bBoxD.OverlapsXY( bBoxU)) { PtrOwner pSfrD( CloneSurfFlatRegion( pGeomDB->GetGeoObj( vChunks[j]))) ; if ( IsNull( pSfrD)) return false ; pSfrD->Intersect( *pSfrU) ; double dArea = -1 ; pSfrD->GetArea( dArea) ; if ( dArea > dMaxArea) { k = j ; dMaxArea = dArea ; } } } if ( k == -1) return false ; // se è la stessa associazione individuata da vChunks allora aggiorno il vettore finale dei grezzi if ( k == i) vRawSurfs.emplace_back( nUpFirstId + i, vChunks[i]) ; else { // altrimenti unisco le regioni associate appena individuate sia per la superficie up sia per la down ExeSurfFrAdd( nUpFirstId + k, nUpFirstId + i) ; ExeErase( {nUpFirstId + i}) ; ExeSurfFrAdd( vChunks[k], vChunks[i]) ; ExeErase( {vChunks[i]}) ; } } return true ; } //---------------------------------------------------------------------------- int MachMgr::SplitFlatRawPartWithMachinings( int nRawId, const INTVECTOR& vMchId) { if ( m_pGeomDB == nullptr) return GDB_ID_NULL ; // verifico sia un grezzo e non appartenga alla fase corrente if ( ! VerifyRawPart( nRawId) || VerifyRawPartPhase( nRawId, m_nCurrPhase)) return GDB_ID_NULL ; // disabilito eventuale registrazione comandi EXE (riabilitazione automatica) CmdLogOff cmdLogOff ; // recupero alcuni dati del grezzo // il solido del grezzo int nRawSolId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_SOLID) ; if ( nRawSolId == GDB_ID_NULL) return GDB_ID_NULL ; // il box del grezzo BBox3d b3Raw ; if ( ! m_pGeomDB->GetGlobalBBox( nRawSolId, b3Raw)) return GDB_ID_NULL ; double dHeight = b3Raw.GetMax().z - b3Raw.GetMin().z ; // il colore del grezzo Color cCol = AQUA ; m_pGeomDB->GetCalcMaterial( nRawSolId, cCol) ; // il riferimento del grezzo Frame3d frRaw ; if ( ! m_pGeomDB->GetGroupGlobFrame( nRawId, frRaw)) return GDB_ID_NULL ; // recupero il contorno int nOutCrvId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_OUTLINE) ; if ( nOutCrvId == GDB_ID_NULL) return GDB_ID_NULL ; // creo le regioni inferiore e superiore del grezzo da aggiornare con le lavorazioni int nSfrDownId = GDB_ID_NULL, nSfrUpId = GDB_ID_NULL ; int nSfrDownOrigId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_DOWN_REG) ; int nSfrUpOrigId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_UP_REG) ; if ( nSfrDownOrigId == GDB_ID_NULL || nSfrUpOrigId == GDB_ID_NULL) { // se le regioni del grezzo di partenza non sono definite, le creo a partire dall'outline nSfrDownId = ExeCreateSurfFlatRegion( nRawId, {nOutCrvId}, nullptr) ; if ( nSfrDownId == GDB_ID_NULL) return GDB_ID_NULL ; nSfrUpId = ExeCopyGlob( nSfrDownId, nRawId, GDB_LAST_SON) ; if ( nSfrUpId == GDB_ID_NULL) return GDB_ID_NULL ; ExeMove( { nSfrUpId}, dHeight * Z_AX, RTY_LOC) ; } else { nSfrDownId = ExeCopyGlob( nSfrDownOrigId, nRawId, GDB_LAST_SON) ; nSfrUpId = ExeCopyGlob( nSfrUpOrigId, nRawId, GDB_LAST_SON) ; if ( nSfrDownId == GDB_ID_NULL || nSfrUpId == GDB_ID_NULL) return GDB_ID_NULL ; } // se esiste il kerf, ne creo la regione PtrOwner pSfrKerf ; int nKerfId = m_pGeomDB->GetFirstNameInGroup( nRawId, MACH_RAW_KERF) ; ICurve* pKerfCrv = GetCurve( m_pGeomDB->GetGeoObj( nKerfId)) ; if ( pKerfCrv != nullptr) { SurfFlatRegionByContours SfrCntr ; SfrCntr.AddCurve( pKerfCrv->Clone()) ; pSfrKerf.Set( SfrCntr.GetSurf()) ; if ( IsNull( pSfrKerf)) return GDB_ID_NULL ; } // recupero le regioni delle lavorazioni INTVECTOR vMchRRegUp ; INTVECTOR vMchRRegDown ; for ( auto nMchId : vMchId) { // recupero gruppo preview lavorazioni nella lavorazione int nPVGrp = m_pGeomDB->GetFirstNameInGroup( nMchId, MCH_PV) ; if ( nPVGrp == GDB_ID_NULL) return GDB_ID_NULL ; // se vuoto, cerco il rimando al preview nel pezzo if ( m_pGeomDB->GetGroupObjs( nPVGrp) == 0 && ! m_pGeomDB->GetInfo( nPVGrp, MCH_PV_KEY_RELOCATE, nPVGrp)) return GDB_ID_NULL ; // ciclo sui percorsi utensile (CL) int nClId = m_pGeomDB->GetFirstGroupInGroup( nPVGrp) ; while ( nClId != GDB_ID_NULL) { // lavorazioni per regione inferiore int nCrDownId = m_pGeomDB->GetFirstNameInGroup( nClId, MCH_PV_DOWN_RAWCUT) ; // se non esiste la regione inferiore la lavorazione non è passante quindi può essere ignorata if ( nCrDownId != GDB_ID_NULL) { while ( nCrDownId != GDB_ID_NULL) { vMchRRegDown.emplace_back( nCrDownId) ; nCrDownId = m_pGeomDB->GetNextName( nCrDownId, MCH_PV_DOWN_RAWCUT) ; } // lavorazioni per regione superiore int nCrUpId = m_pGeomDB->GetFirstNameInGroup( nClId, MCH_PV_UP_RAWCUT) ; while ( nCrUpId != GDB_ID_NULL) { vMchRRegUp.emplace_back( nCrUpId) ; nCrUpId = m_pGeomDB->GetNextName( nCrUpId, MCH_PV_UP_RAWCUT) ; } } // passo al successivo percorso utensile nClId = m_pGeomDB->GetNextGroup( nClId) ; } } // sottraggo le lavorazioni alle superfici del grezzo for ( auto nMchRReg : vMchRRegUp) ExeSurfFrSubtract( nSfrUpId, nMchRReg) ; for ( auto nMchRReg : vMchRRegDown) ExeSurfFrSubtract( nSfrDownId, nMchRReg) ; // classifico i chunks della regione up e down per individuare le regioni che definiscono i nuovi grezzi vector> vSurfRaws ; AssociateSurfs( m_pGeomDB, nSfrUpId, nSfrDownId, vSurfRaws) ; // creo i grezzi risultanti INTVECTOR vNewIds ; for ( int i = 0 ; i < int( vSurfRaws.size()) ; i++) { // aggiungo il grezzo int nId = AddRawPart( vSurfRaws[i].first, vSurfRaws[i].second, dHeight, cCol) ; m_pGeomDB->Erase( vSurfRaws[i].first) ; m_pGeomDB->Erase( vSurfRaws[i].second) ; if ( nId == GDB_ID_NULL) return GDB_ID_NULL ; vNewIds.emplace_back( nId) ; // imposto lo stato del contorno di questo grezzo come quello del grezzo di partenza int nStat = GDB_ST_ON ; if ( m_pGeomDB->GetStatus( nOutCrvId, nStat) && nStat == GDB_ST_OFF) m_pGeomDB->SetStatus( m_pGeomDB->GetFirstNameInGroup( nId, MACH_RAW_OUTLINE), nStat) ; // assegno la fase al gruppo m_pGeomDB->SetInfo( nId, MACH_RAW_PHASE, m_nCurrPhase) ; // se esiste il kerf uso questa curva per creare il kerf del nuovo grezzo if ( ! IsNull( pSfrKerf)) { // riferimento del nuovo grezzo Frame3d frNewRaw ; if ( ! m_pGeomDB->GetGroupGlobFrame( nId, frNewRaw)) return GDB_ID_NULL ; // considero il nuovo kerf come la regione superiore del nuovo grezzo int nSfrUpId = m_pGeomDB->GetFirstNameInGroup( nId, MACH_RAW_UP_REG) ; if ( nSfrUpId == GDB_ID_NULL) return GDB_ID_NULL ; PtrOwner pSfrNewKerf( CloneSurfFlatRegion( m_pGeomDB->GetGeoObj( nSfrUpId))) ; if ( IsNull( pSfrNewKerf)) return GDB_ID_NULL ; // porto nello stesso riferimento del grezzo originale pSfrNewKerf->LocToLoc( frNewRaw, frRaw) ; // la limito con la regione di kerf precedente ( va bene anche se fallisce) pSfrNewKerf->Intersect( *pSfrKerf) ; // se risultato non vuoto if ( pSfrNewKerf->IsValid()) { // la porto dal riferimento del grezzo originale al riferimento di questo grezzo pSfrNewKerf->LocToLoc( frRaw, frNewRaw) ; // recupero il contorno esterno del chunk più grande e lo inserisco come kerf del nuovo grezzo double dAreaMax = -1 ; int nKMax = 0 ; for ( int k = 0 ; k < pSfrNewKerf->GetChunkCount() ; k ++) { PtrOwner pSfrChunk( pSfrNewKerf->CloneChunk( k)) ; double dArea = -1 ; pSfrChunk->GetGrossArea( dArea) ; if ( dArea > dAreaMax) { nKMax = k ; dAreaMax = dArea ; } } PtrOwner pCrv( pSfrNewKerf->GetLoop( nKMax, 0)) ; if ( IsNull( pCrv)) return GDB_ID_NULL ; int nNewKerfId = m_pGeomDB->AddGeoObj( GDB_ID_NULL, nId, Release( pCrv)) ; if ( nNewKerfId == GDB_ID_NULL) return GDB_ID_NULL ; m_pGeomDB->CopyMaterial( nKerfId, nNewKerfId) ; m_pGeomDB->SetName( nNewKerfId, MACH_RAW_KERF) ; } } } // cancello le regioni usate per i conti m_pGeomDB->Erase( nSfrUpId) ; m_pGeomDB->Erase( nSfrDownId) ; // verifico esista almeno un nuovo grezzo if ( vNewIds.empty()) return GDB_ID_NULL ; // inserisco i pezzi del grezzo originale nei nuovi grezzi int nGroupId = m_pGeomDB->GetFirstGroupInGroup( nRawId) ; while ( nGroupId != GDB_ID_NULL) { for ( auto nNewId : vNewIds) { // copio il gruppo int nNewGroupId = m_pGeomDB->CopyGlob( nGroupId, GDB_ID_NULL, nNewId) ; // scambio con pezzo int nPartId = SwapRawPartPart( nNewGroupId, true) ; // verifico se il pezzo sta nel grezzo int nLayerId = m_pGeomDB->GetFirstNameInGroup( nPartId, NST_PARTREG_LAYER) ; if ( nLayerId == GDB_ID_NULL || m_pGeomDB->GetGdbType( nLayerId) != GDB_TY_GROUP) nLayerId = m_pGeomDB->GetFirstGroupInGroup( nPartId) ; // cerco la regione del pezzo int nEntId = m_pGeomDB->GetFirstInGroup( nLayerId) ; while ( nEntId != GDB_ID_NULL) { int nEntGeoType = m_pGeomDB->GetGeoType( nEntId) ; if ( nEntGeoType == SRF_FLATRGN) break ; nEntId = m_pGeomDB->GetNext( nEntId) ; } if ( nEntId != GDB_ID_NULL) { // verifico se è interna al grezzo int nOutCrvId = m_pGeomDB->GetFirstNameInGroup( nNewId, MACH_RAW_OUTLINE) ; BBox3d b3Raw ; m_pGeomDB->GetGlobalBBox( nOutCrvId, b3Raw) ; double dRawDiam = 0 ; b3Raw.GetDiameter( dRawDiam) ; BBox3d b3Part ; m_pGeomDB->GetGlobalBBox( nEntId, b3Part) ; double dPartDiam = 0 ; b3Part.GetDiameter( dPartDiam) ; if ( dRawDiam > 0.9 * dPartDiam) { int nSfrUp = m_pGeomDB->GetFirstNameInGroup( nNewId, MACH_RAW_UP_REG) ; if ( ! ExeSurfFrTestExternal( nSfrUp, nEntId, EPS_SMALL)) break ; } } // altrimenti scambio pezzo ed elimino gruppo nNewGroupId = SwapRawPartPart( nPartId, false) ; m_pGeomDB->Erase( nNewGroupId) ; } nGroupId = m_pGeomDB->GetNextGroup( nGroupId) ; } return vNewIds[0] ; }