//---------------------------------------------------------------------------- // EgalTech 2019-2019 //---------------------------------------------------------------------------- // File : AutoNester.cpp Data : 28.11.19 Versione : 2.1k6 // Contenuto : Implementazione della classe AutoNester. // // // // Modifiche : 28.11.19 DS Creazione modulo. // // //---------------------------------------------------------------------------- //--------------------------- Include ---------------------------------------- #include "stdafx.h" #include "AutoNester.h" #include "DllMain.h" #include "/EgtDev/Include/ENsDllMain.h" #include "/EgtDev/Include/EGkPolyArc.h" #include "/EgtDev/Extern/Optalog/Include/cns.h" #include "/EgtDev/Extern/Optalog/Include/cns_egaltech.h" #include "/EgtDev/Include/SELkLockId.h" using namespace std ; //---------------------------------------------------------------------------- IAutoNester* CreateAutoNester( void) { // verifico la chiave e le opzioni if ( ! TestKeyForENs( GetENsKey(), 0, GetENsLogger())) return false ; // creo il NestMgr return static_cast ( new(nothrow) AutoNester) ; } //---------------------------------------------------------------------------- // AutoNester //---------------------------------------------------------------------------- AutoNester::AutoNester( void) : m_pOrder( nullptr), m_pComp( nullptr) { } //---------------------------------------------------------------------------- AutoNester::~AutoNester( void) { Clear() ; } //---------------------------------------------------------------------------- bool AutoNester::Clear( void) { if ( m_pOrder != nullptr) { if ( m_pComp != nullptr) { CNS_ComputationStatus status = CNS_GetComputationStatus( m_pComp) ; if ( status != CNS_Ok && status != CNS_CancelledComputation) CNS_CancelComputation( m_pComp) ; } CNS_DeleteLaunchingOrder( m_pOrder) ; m_pOrder = nullptr ; m_pComp = nullptr ; } return true ; } //---------------------------------------------------------------------------- bool AutoNester::Start( void) { Clear() ; m_pOrder = CNS_NewLaunchingOrder() ; return ( m_pOrder != nullptr) ; } //---------------------------------------------------------------------------- bool AutoNester::AddSheet( int nSheetId, const PolyArc& Outline, int nPriority, int nCount) { if ( m_pOrder == nullptr) return false ; if ( ! Outline.IsClosed()) return false ; // contorno nel formato Optalog const int nElem = Outline.GetPointNbr() - 1 ; vector vElem ; vElem.reserve( nElem) ; Point3d ptIni, ptFin ; double dBulge ; bool bNext = Outline.GetFirstArc( ptIni, ptFin, dBulge) ; while ( bNext) { double dLeftDeflection = - dBulge * DistXY( ptIni, ptFin) / 2 ; vElem.push_back( { ptFin.x, ptFin.y, dLeftDeflection}) ; bNext = Outline.GetNextArc( ptIni, ptFin, dBulge) ; } // aggiungo CNS_SheetPtr pSheet = CNS_AddNonRectangularSheet( m_pOrder, nCount, int( vElem.size()), vElem.data()) ; if ( pSheet == nullptr) return false ; CNS_SetSheetUserString( pSheet, ToString( nSheetId).c_str()) ; CNS_SetSheetPriority( pSheet, nPriority) ; return true ; } //---------------------------------------------------------------------------- bool AutoNester::AddPart( int nPartId, const PolyArc& Outline, bool bCanFlip, bool bCanRotate, int nPriority, int nCount) { if ( m_pOrder == nullptr) return false ; if ( ! Outline.IsClosed()) return false ; // contorno nel formato Optalog const int nElem = Outline.GetPointNbr() - 1 ; vector vElem ; vElem.reserve( nElem) ; Point3d ptIni, ptFin ; double dBulge ; bool bNext = Outline.GetFirstArc( ptIni, ptFin, dBulge) ; while ( bNext) { double dLeftDeflection = - dBulge * DistXY( ptIni, ptFin) / 2 ; vElem.push_back( { ptFin.x, ptFin.y, dLeftDeflection}) ; bNext = Outline.GetNextArc( ptIni, ptFin, dBulge) ; } // aggiungo CNS_PartPtr pPart = CNS_AddPart( m_pOrder, nCount, int( vElem.size()), vElem.data()) ; if ( pPart == nullptr) return false ; CNS_SetPartUserString( pPart, ToString( nPartId).c_str()) ; CNS_SetPartAuthorizations( pPart, ( bCanFlip ? 1 : 0), ( bCanRotate ? 1 : 0), 0) ; CNS_SetPartPriority( pPart, nPriority) ; return true ; } //---------------------------------------------------------------------------- bool AutoNester::SetInterpartGap( double dGap) { if ( m_pOrder == nullptr) return false ; CNS_SetInterpartGap( m_pOrder, dGap) ; return true ; } //---------------------------------------------------------------------------- bool AutoNester::Compute( int nMaxTime) { if ( m_pOrder == nullptr) return false ; // recupero i codici di sblocco del nesting string sKeyId, sKeySign ; SplitFirst( GetENsKey2(), "-", sKeyId, sKeySign) ; // verifico si riferiscano alla chiave di protezione in uso int nKeySN, nKeyId ; if ( ! GetLockSN( nKeySN) || ! FromString( sKeyId, nKeyId) || nKeySN != nKeyId) return false ; // passo i codici al nester CNS_UnLockLaunchingOrderOxy( m_pOrder, sKeyId.c_str(), sKeySign.c_str()) ; // lancio l'esecuzione m_pComp = CNS_LaunchLocalComputation( m_pOrder, nMaxTime / 1000.) ; return ( m_pComp != nullptr) ; } //---------------------------------------------------------------------------- bool AutoNester::CancelComputation( void) { if ( m_pOrder == nullptr || m_pComp == nullptr) return false ; CNS_ComputationStatus status = CNS_CancelComputation( m_pComp) ; return ( status == CNS_CancelledComputation || status == CNS_Ok) ; } //---------------------------------------------------------------------------- bool AutoNester::GetComputationStatus( int& nStatus) { if ( m_pOrder == nullptr || m_pComp == nullptr) return false ; CNS_ComputationStatus status = CNS_GetComputationStatus( m_pComp) ; if ( status == CNS_CancelledComputation) nStatus = 0 ; else if ( status == CNS_PendingComputation) nStatus = 1 ; else if ( status == CNS_IntermediateResult) nStatus = 2 ; else if ( status == CNS_Ok) nStatus = 3 ; else nStatus = - 1 ; return ( nStatus >= 0) ; } //---------------------------------------------------------------------------- bool AutoNester::GetResults( double& dTotFillRatio, ANIVECT& vANI) { // verifico validità calcolo if ( m_pComp == nullptr) return false ; // recupero la soluzione CNS_SolutionPtr pSol = CNS_GetSolution( m_pComp) ; if ( pSol == nullptr) return false ; // percentuale di riempimento complessivo dTotFillRatio = CNS_GetFillRatio( pSol) ; // recupero i dati di nesting vANI.clear() ; int nNestCount = CNS_GetNumberOfNestings( pSol) ; for ( int i = 0 ; i < nNestCount ; ++ i) { // riferimento allo i-esimo nesting CNS_NestingPtr pNest = CNS_GetNesting( pSol, i) ; // dati dello sheet CNS_SheetPtr pSheet = CNS_GetSheet( pNest) ; const char* szSheetId = CNS_GetSheetUserString( pSheet) ; int nSheetId = 999 ; if ( szSheetId != nullptr) FromString( szSheetId, nSheetId) ; int nMult = CNS_GetMultiplicity( pNest) ; int nPartCount = CNS_GetNumberOfNestedParts( pNest) ; double dFillRatio = CNS_GetNestingFillRatio( pNest) ; vANI.push_back( { nMult, nSheetId, nPartCount, dFillRatio, 0, 0}) ; // ciclo sui pezzi nestati for ( int j = 0; j < nPartCount ; ++ j) { // dati del pezzo CNS_PartPtr pPart ; double dX, dY, dAngRot ; int nFlip ; CNS_GetNestedPart( pNest, j, &pPart, &dX, &dY, &nFlip, &dAngRot) ; const char* szPartId = CNS_GetPartUserString( pPart) ; int nPartId = 999 ; if ( szPartId != nullptr) FromString( szPartId, nPartId) ; vANI.push_back( { 0, nPartId, nFlip, dX, dY, dAngRot}) ; } } return true ; } //---------------------------------------------------------------------------- bool AutoNester::PrintResults( const string& sHtmlFile) { // verifico validità calcolo if ( m_pComp == nullptr) return false ; // recupero la soluzione CNS_SolutionPtr pSol = CNS_GetSolution( m_pComp) ; if ( pSol == nullptr) return false ; // se richiesto risultato in html if ( ! IsEmptyOrSpaces( sHtmlFile)) CNS_GenerateHtmlSolutionReport( pSol, sHtmlFile.c_str()) ; return true ; }