-- NestProcess.lua by Egaltech s.r.l. 2021/05/25 -- Gestione nesting automatico pareti -- Intestazioni require( 'EgtBase') _ENV = EgtProtectGlobal() EgtEnableDebug( false) -- Per test --NEST = {} --NEST.FILE = 'c:\\TechnoEssetre7\\EgtData\\Prods\\0010\\Bar_10_1.btl' --NEST.MACHINE = 'Essetre-90480019_MW' --NEST.FLAG = 3 local sLog = 'BatchProcess : ' .. NEST.FILE .. ', ' .. NEST.MACHINE .. ', ' .. LEN["1"] .. ', ' .. WIDTH["1"] EgtOutLog( sLog) -- Cancello file di log specifico local sLogFile = EgtChangePathExtension( NEST.FILE, '.txt') EgtEraseFile( sLogFile) -- Imposto direttorio libreria specializzata per Travi local sBaseDir = EgtGetSourceDir() EgtAddToPackagePath( sBaseDir .. 'LuaLibs\\?.lua') -- Verifico che la macchina corrente sia abilitata per la lavorazione delle Pareti local sMachDir = EgtGetCurrMachineDir() if not EgtExistsFile( sMachDir .. '\\Wall\\WallData.lua') then WALL.ERR = 12 WALL.MSG = 'Error not configured for walls machine : ' .. sMachine WriteErrToLogFile( WALL.ERR, WALL.MSG) PostErrView( WALL.ERR, WALL.MSG) return end -- Elimino direttori altre macchine e imposto direttorio macchina corrente per ricerca librerie EgtRemoveBaseMachineDirFromPackagePath() EgtAddToPackagePath( sMachDir .. '\\Wall\\?.lua') -- Carico le librerie _G.package.loaded.WallExec = nil local WE = require( 'WallExec') _G.package.loaded.WallLib = nil local WL = require( 'WallLib') _G.package.loaded.WProcessLapJoint = nil local LapJoint = require( 'WProcessLapJoint') _G.package.loaded.WProcessDrill = nil local Drill = require( 'WProcessDrill') _G.package.loaded.WProcessCut = nil local Cut = require( 'WProcessCut') _G.package.loaded.WProcessDoubleCut = nil local DoubleCut = require( 'WProcessDoubleCut') _G.package.loaded.WProcessSawCut = nil local SawCut = require( 'WProcessSawCut') _G.package.loaded.WProcessFreeContour = nil local FreeContour = require( 'WProcessFreeContour') _G.package.loaded.WProcessMortise = nil local Mortise = require( 'WProcessMortise') _G.package.loaded.WProcessDtMortise = nil local DtMortise = require( 'WProcessDtMortise') _G.package.loaded.WProcessMark = nil local Mark = require( 'WProcessMark') _G.package.loaded.WProcessText = nil local Text = require( 'WProcessText') -- Carico i dati globali local WD = require( 'WallData') -- lista dei pezzi con flip o rotazione local PartStates = {} -- Funzioni per scrittura su file di log specifico local function WriteErrToLogFile( nErr, sMsg, nRot, nCutId, nTaskId) local hFile = io.open( sLogFile, 'a') hFile:write( 'ERR=' .. tostring( nErr) .. '\n') hFile:write( sMsg .. '\n') hFile:write( 'ROT=' .. tostring( nRot or 0) .. '\n') hFile:write( 'CUTID=' .. tostring( nCutId or 0) .. '\n') hFile:write( 'TASKID=' .. tostring( nTaskId or 0) .. '\n') hFile:close() end local function WriteTimeToLogFile( dTime) local hFile = io.open( sLogFile, 'a') hFile:write( 'TIME=' .. EgtNumToString( dTime) .. '\n') hFile:close() end -- Funzione per gestire visualizzazione dopo errore local function PostErrView( nErr, sMsg) if nErr ~= 0 and ( NEST.FLAG == 1 or NEST.FLAG == 2 or NEST.FLAG == 5) then EgtSetView( SCE_VD.ISO_SW, false) EgtZoom( SCE_ZM.ALL) EgtOutBox( sMsg, 'BatchProcess (err=' .. tostring( nErr) .. ')', 'ERRORS') end end -- Funzione per gestire visualizzazione dopo warning local function PostWarnView( nWarn, sMsg) if nWarn ~= 0 and ( NEST.FLAG == 1 or NEST.FLAG == 2 or NEST.FLAG == 5) then EgtSetView( SCE_VD.ISO_SW, false) EgtZoom( SCE_ZM.ALL) EgtOutBox( sMsg, 'BatchProcess (wrn=' .. tostring( nWarn) .. ')', 'WARNINGS') end end -- Funzione per aggiornare dati ausiliari local function UpdateAuxData( sAuxFile) local bModif = false -- Se definito LOAD90, aggiorno local sLoad90 = EgtGetStringFromIni( 'AuxData', 'LOAD90', '', sAuxFile) if sLoad90 ~= '' then local BtlInfoId = EgtGetFirstNameInGroup( GDB_ID.ROOT, 'BtlInfo') or GDB_ID.NULL EgtSetInfo( BtlInfoId, 'LOAD90', sLoad90) bModif = true end return bModif end -- Funzione per trovare nome MachGroup local function NewMachGroupName() local nMachGroupId = EgtGetFirstMachGroup() if not nMachGroupId then return 1 end local nMaxMachGroup = 0 while nMachGroupId do sMachGroupName = EgtGetMachGroupName(nMachGroupId) local nMachGroupName = tonumber(sMachGroupName) if nMachGroupName > nMaxMachGroup then nMaxMachGroup = nMachGroupName end nMachGroupId = EgtGetNextMachGroup(nMachGroupId) end return nMaxMachGroup + 1 end -- Funzione che crea local function CreateToolRectangle( ptP1, ptP2, vtFace, nOutlineGrp) -- da inserire in WallData local MILL_DIAM = 350 local vtX = ptP2 - ptP1 vtX:normalize() -- creo il rettangolo della lavorazione ptP1 = ptP1 - vtX * 9000 ptP2 = ptP2 + vtX * ( MILL_DIAM / 2 + 100 * GEO.EPS_SMALL) ptP2 = ptP2 + vtFace * ( MILL_DIAM + 100 * GEO.EPS_SMALL) local nId = EgtRectangle2P( nOutlineGrp, Point3d(ptP2:getX(), ptP2:getY(), 0), Point3d( ptP1:getX(), ptP1:getY(), 0)) return nId end -- Funzione che crea le regioni occupate dalle lavorazioni local function ComputeToolOutlines( nPartId) local ToolOutlineId = {} -- recupero il gruppo con gli outlines degli utensili local nOutlineGrp = EgtGetFirstNameInGroup(GDB_ID.ROOT, "ToolOutlines") if not nOutlineGrp or nOutlineGrp == GDB_ID.NULL then nOutlineGrp = EgtGroup( GDB_ID.ROOT) EgtSetName( nOutlineGrp, "ToolOutlines") EgtSetStatus( nOutlineGrp, GDB_ST.OFF) end -- recupero i lap joint che sono fatti dal basso local vPartProc = WE.CollectFeatures( nPartId, b3Raw) for nInd = 1, #vPartProc do Proc = vPartProc[nInd] if LapJoint.Identify( vPartProc[nInd]) then if Proc.Fct == 2 then local vtN = {} vtN[1] = EgtSurfTmFacetNormVersor( Proc.Id, 0, GDB_ID.ROOT) vtN[2] = EgtSurfTmFacetNormVersor( Proc.Id, 1, GDB_ID.ROOT) if ( vtN[1]:getZ() <= - 0.95 or vtN[2]:getZ() <= - 0.95) then local vtFace = EgtIf( vtN[1]:getZ() <= -0.95, vtN[2], vtN[1]) local bAdj, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, 0, 1, GDB_ID.ROOT) -- creo il rettangolo della lavorazione local nId = CreateToolRectangle( ptP1, ptP2, vtFace, nOutlineGrp) if nId ~= GDB_ID.NULL then table.insert(ToolOutlineId, nId) end end end if Proc.Fct == 3 then local nFacInd, dElev = WL.GetFaceWithMostAdj( Proc.Id, Proc.PartId) if nFacInd ~= -2 then local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT) if not AreSameOrOppositeVectorApprox( vtN, Z_AX()) then local nOtherFace = EgtIf( nFacInd == 0, 1, 0) local bAdj, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, nFacInd, nOtherFace, GDB_ID.ROOT) if abs( ptP1:getZ() - ptP2:getZ()) < GEO.EPS_SMALL then local nId = CreateToolRectangle( ptP1, ptP2, vtN, nOutlineGrp) if nId ~= GDB_ID.NULL then table.insert(ToolOutlineId, nId) end end end end end end end return ToolOutlineId end -- Funzione che sposta e aggiunge pezzi per nesting local function AddRawParts(RawParts) -- creo tabella dei grezzi for nIndex, nLen in pairs( LEN) do table.insert(RawParts, {Len = nLen}) end for nIndex, nWidth in pairs( WIDTH) do RawParts[tonumber(nIndex)].Width = nWidth end for nIndex, nQty in pairs( QTY) do RawParts[tonumber(nIndex)].Qty = nQty end for nIndex, nMaterial in pairs( MATERIAL) do RawParts[tonumber(nIndex)].Material = nMaterial end local OUTLINE = "Outline" for nIndex = 1, #RawParts do -- creo pannello del materiale local SheetPartId = EgtGroup(GDB_ID.ROOT) RawParts[nIndex].PartId = SheetPartId EgtSetName(SheetPartId, "Sheet") local SheetLayerId = EgtGroup(SheetPartId) EgtSetName(SheetLayerId, OUTLINE) local SheetOutlineId = EgtRectangle2P(SheetLayerId, Point3d(0,0,0), Point3d(RawParts[nIndex].Len, RawParts[nIndex].Width, 0), GDB_RT.GLOB) -- EgtModifyCurveThickness(SheetOutlineId, -Material.T_mm) EgtSetName(SheetOutlineId, OUTLINE) -- creo foglio per nesting EgtAutoNestAddSheet( SheetPartId, SheetOutlineId, NEST.KERF, 0, RawParts[nIndex].Qty) -- EgtAutoNestAddSheet( SheetId, OutlineId, dKerf, nPriority, nCount) end end local function AddParts(RawParts) local nTotParts = 0 for _ in pairs( PART) do nTotParts = nTotParts + 1 end local nPartIndex = 0 -- ciclo su pezzi per aggiungerli al nesting for nPartId, nCount in pairs( PART) do nPartIndex = nPartIndex + 1 -- calcolo bbox pezzo per rotazioni local b3Part = EgtGetBBoxGlob( nPartId, GDB_BB.STANDARD) local vPartProc = WE.CollectFeatures( nPartId, b3Raw) -- verifico se possibile flip parete -- recupero stati di flip delle feature di lavorazione della parete local bFlip = false local FlipFeatureStates = {} for nInd = 1, #vPartProc do if LapJoint.Identify( vPartProc[nInd]) then local nFlip0, nFlip1 = LapJoint.FlipClassify(vPartProc[nInd]) if nFlip0 and nFlip1 and nFlip0 ~= nFlip1 then table.insert( FlipFeatureStates, { Flip0 = nFlip0, Flip1 = nFlip1}) end elseif Drill.Identify( vPartProc[nInd]) then local nFlip0, nFlip1 = Drill.FlipClassify(vPartProc[nInd], b3Part) if nFlip0 and nFlip1 and nFlip0 ~= nFlip1 then table.insert( FlipFeatureStates, { Flip0 = nFlip0, Flip1 = nFlip1}) end elseif Cut.Identify( vPartProc[nInd]) then local nFlip0, nFlip1 = Cut.FlipClassify(vPartProc[nInd], b3Part) if nFlip0 and nFlip1 and nFlip0 ~= nFlip1 then table.insert( FlipFeatureStates, { Flip0 = nFlip0, Flip1 = nFlip1}) end elseif DoubleCut.Identify( vPartProc[nInd]) then local nFlip0, nFlip1 = DoubleCut.FlipClassify(vPartProc[nInd], b3Part) if nFlip0 and nFlip1 and nFlip0 ~= nFlip1 then table.insert( FlipFeatureStates, { Flip0 = nFlip0, Flip1 = nFlip1}) end elseif SawCut.Identify( vPartProc[nInd]) then local nFlip0, nFlip1 = SawCut.FlipClassify(vPartProc[nInd], b3Part) if nFlip0 and nFlip1 and nFlip0 ~= nFlip1 then table.insert( FlipFeatureStates, { Flip0 = nFlip0, Flip1 = nFlip1}) end elseif FreeContour.Identify( vPartProc[nInd]) then local nFlip0, nFlip1 = FreeContour.FlipClassify(vPartProc[nInd], b3Part) if nFlip0 and nFlip1 and nFlip0 ~= nFlip1 then table.insert( FlipFeatureStates, { Flip0 = nFlip0, Flip1 = nFlip1}) end elseif Mortise.Identify( vPartProc[nInd]) then local nFlip0, nFlip1 = Mortise.FlipClassify(vPartProc[nInd], b3Part) if nFlip0 and nFlip1 and nFlip0 ~= nFlip1 then table.insert( FlipFeatureStates, { Flip0 = nFlip0, Flip1 = nFlip1}) end elseif DtMortise.Identify( vPartProc[nInd]) then local nFlip0, nFlip1 = DtMortise.FlipClassify(vPartProc[nInd], b3Part) if nFlip0 and nFlip1 and nFlip0 ~= nFlip1 then table.insert( FlipFeatureStates, { Flip0 = nFlip0, Flip1 = nFlip1}) end elseif Mark.Identify( vPartProc[nInd]) then local nFlip0, nFlip1 = Mark.FlipClassify(vPartProc[nInd], b3Part) if nFlip0 and nFlip1 and nFlip0 ~= nFlip1 then table.insert( FlipFeatureStates, { Flip0 = nFlip0, Flip1 = nFlip1}) end elseif Text.Identify( vPartProc[nInd]) then local nFlip0, nFlip1 = Text.FlipClassify(vPartProc[nInd], b3Part) if nFlip0 and nFlip1 and nFlip0 ~= nFlip1 then table.insert( FlipFeatureStates, { Flip0 = nFlip0, Flip1 = nFlip1}) end end end -- analizzo stati flip delle feature local nFlip0Min = 100 local nFlip0Cnt = 0 local nFlip1Min = 100 local nFlip1Cnt = 0 -- calcolo punteggio minimo e sua molteplicita' per entrambi i lati for nInd = 1, #FlipFeatureStates do if FlipFeatureStates[nInd].Flip0 < nFlip0Min then nFlip0Min = FlipFeatureStates[nInd].Flip0 nFlip0Cnt = 1 elseif FlipFeatureStates[nInd].Flip0 == nFlip0Min then nFlip0Cnt = nFlip0Cnt + 1 end if FlipFeatureStates[nInd].Flip1 < nFlip1Min then nFlip1Min = FlipFeatureStates[nInd].Flip1 nFlip1Cnt = 1 elseif FlipFeatureStates[nInd].Flip1 == nFlip1Min then nFlip1Cnt = nFlip1Cnt + 1 end end -- calcolo lato con punteggio minore o molteplicita' piu' alta if nFlip0Min == nFlip1Min then if nFlip0Cnt > nFlip1Cnt then bFlip = true end elseif nFlip0Min < nFlip1Min then bFlip = true end -- eseguo flip se necessario if bFlip then EgtRotate( nPartId, b3Part:getCenter(), X_AX(), 180, GDB_RT.GLOB) end -- verifico quali sono le rotazioni ammesse local ValidRotations = { bRot0 = true, bRot90 = true} local dPartL = b3Part:getDimX() local dPartW = b3Part:getDimY() local nOut0 = 0 -- numero di grezzi che non conterrebbero il pezzo ruotato di 0°/180° local nOut90 = 0 -- numero di grezzi che non conterrebbero il pezzo ruotato di 90°/270° for nInd = 1, #RawParts do if ( dPartL > RawParts[nInd]["Len"] or dPartW > RawParts[nInd]["Width"]) then nOut0 = nOut0 + 1 end if ( dPartW > RawParts[nInd]["Len"] or dPartL > RawParts[nInd]["Width"]) then nOut90 = nOut90 + 1 end end -- se il pezzo ruotato è fuori da tutti i grezzi, blocco quelle rotazioni if nOut0 == #RawParts then ValidRotations.bRot0 = false end if nOut90 == #RawParts then ValidRotations.bRot90 = false end local nRotate = 0 local RotateFeatureStates = {} for nInd = 1, #vPartProc do if Drill.Identify( vPartProc[nInd]) then local nRot0, nRot90, nRot180, nRot270 = Drill.RotateClassify(vPartProc[nInd], ValidRotations) if nRot0 and nRot0 >= 0 then table.insert( RotateFeatureStates, { Rot0 = nRot0, Rot90 = nRot90, Rot180 = nRot180, Rot270 = nRot270}) end end end -- analizzo stati rotazione delle feature local nRot0Min = 100 local nRot0Cnt = 0 local nRot90Min = 100 local nRot90Cnt = 0 local nRot180Min = 100 local nRot180Cnt = 0 local nRot270Min = 100 local nRot270Cnt = 0 -- calcolo punteggio minimo e sua molteplicita' per tutte le rotazioni for nInd = 1, #RotateFeatureStates do if RotateFeatureStates[nInd].Rot0 < nRot0Min then nRot0Min = RotateFeatureStates[nInd].Rot0 nRot0Cnt = 1 elseif RotateFeatureStates[nInd].Rot0 == nRot0Min then nRot0Cnt = nRot0Cnt + 1 end if RotateFeatureStates[nInd].Rot90 < nRot90Min then nRot90Min = RotateFeatureStates[nInd].Rot90 nRot90Cnt = 1 elseif RotateFeatureStates[nInd].Rot90 == nRot90Min then nRot90Cnt = nRot90Cnt + 1 end if RotateFeatureStates[nInd].Rot180 < nRot180Min then nRot180Min = RotateFeatureStates[nInd].Rot180 nRot180Cnt = 1 elseif RotateFeatureStates[nInd].Rot180 == nRot180Min then nRot180Cnt = nRot180Cnt + 1 end if RotateFeatureStates[nInd].Rot270 < nRot270Min then nRot270Min = RotateFeatureStates[nInd].Rot270 nRot270Cnt = 1 elseif RotateFeatureStates[nInd].Rot270 == nRot270Min then nRot270Cnt = nRot270Cnt + 1 end end -- se c'e' qualche stato di rotazione local MinList = { { Rot = 0, Score = nRot0Min, ScoreCnt = nRot0Cnt}, { Rot = 90, Score = nRot90Min, ScoreCnt = nRot90Cnt}, { Rot = 180, Score = nRot180Min, ScoreCnt = nRot180Cnt}, { Rot = 270, Score = nRot270Min, ScoreCnt = nRot270Cnt}} if #RotateFeatureStates > 0 then -- calcolo lato con punteggio minore o molteplicita' piu' alta local nRotMax = 0 local nScoreMax = 0 local nScoreCnt = 0 for nInd = 1, #MinList do if MinList[nInd].Score > nScoreMax then nRotMax = MinList[nInd].Rot nScoreMax = MinList[nInd].Score nScoreCnt = MinList[nInd].ScoreCnt elseif MinList[nInd].Score == nScoreMax then if MinList[nInd].ScoreCnt < nScoreCnt then nRotMax = MinList[nInd].Rot nScoreMax = MinList[nInd].Score nScoreCnt = MinList[nInd].ScoreCnt end end end nRotate = nRotMax else nRotate = 0 end -- eseguo rotazione se necessario if nRotate > 0 then EgtRotate( nPartId, b3Part:getCenter(), Z_AX(), nRotate, GDB_RT.GLOB) end -- -- calcolo rotazioni permesse a nesting -- local AdmittedRotation = {} -- for nInd = 1, #MinList do -- if MinList[nInd].Score >= 50 then -- table.insert( AdmittedRotation, MinList[nInd].Rot) -- end -- end local bRotNest = false local nStepRotNest = 0 -- se calcolate limitazioni su rotazioni if MinList and #MinList > 0 then -- verifico condizioni da permettere al nesting if MinList[1].Score >= 50 and MinList[2].Score >= 50 and MinList[3].Score >= 50 and MinList[4].Score >= 50 then bRotNest = true nStepRotNest = 90 elseif (nRotate == 0 and MinList[3].Score >= 50) or ( nRotate == 90 and MinList[4].Score >= 50) then bRotNest = true nStepRotNest = 180 end else -- altrimenti permetto tutto bRotNest = true nStepRotNest = 90 end -- aggiungo stato a lista stati del pezzo per ripristinare alla fine table.insert( PartStates, { PartId = tonumber(nPartId), Flip = bFlip, Rotate = nRotate}) -- local bFtDown = false -- local vPartProc = WE.CollectFeatures( nPartId, b3Raw) -- for nInd = 1, #vPartProc do -- if LapJoint.Identify( vPartProc[nInd]) then -- local nFacOpt, dMinElev, nFacOpt2, dMinElev2 = WL.GetFaceWithMostAdj( vPartProc[nInd].Id, vPartProc[nInd].PartId) -- if nFacOpt >= 0 then -- local vtN = EgtSurfTmFacetNormVersor( vPartProc[nInd].Id, nFacOpt, GDB_ID.ROOT) -- if vtN:getZ() < -0.09 then -- bFtDown = true -- break -- end -- end -- end -- LapJoint.FlipClassify(vPartProc[nInd]) -- end -- -- ruoto se necessario -- if bFtDown then -- local b3Solid = EgtGetBBoxGlob(nPartId, GDB_BB.IGNORE_TEXT) -- local ptRotCen = b3Solid:getCenter() -- EgtRotate( nPartId, ptRotCen, X_AX(), 180, GDB_RT.GLOB) -- end -- -- recupero le feature di lavorazione della parete -- local bFtDown = false -- local vPartProc = WE.CollectFeatures( nPartId, b3Raw) -- for nInd = 1, #vPartProc do -- if LapJoint.Identify( vPartProc[nInd]) then -- local nFacOpt, dMinElev, nFacOpt2, dMinElev2 = WL.GetFaceWithMostAdj( vPartProc[nInd].Id, vPartProc[nInd].PartId) -- if nFacOpt >= 0 then -- local vtN = EgtSurfTmFacetNormVersor( vPartProc[nInd].Id, nFacOpt, GDB_ID.ROOT) -- if vtN:getZ() < -0.09 then -- bFtDown = true -- break -- end -- end -- end -- end -- -- ruoto se necessario -- if bFtDown then -- local b3Solid = EgtGetBBoxGlob(nPartId, GDB_BB.IGNORE_TEXT) -- local ptRotCen = b3Solid:getCenter() -- EgtRotate( nPartId, ptRotCen, X_AX(), 180, GDB_RT.GLOB) -- end -- recupero contorno local nOutlineLayer = EgtGetFirstNameInGroup(nPartId, "Outline") -- elimino vecchio contorno se gia' presente local nOldOutline = EgtGetFirstNameInGroup(nOutlineLayer, 'ON_TMP') EgtErase(nOldOutline or GDB_ID.NULL) -- Recupero o ricalcolo il solido local SolidId = EgtBeamGetSolid( nPartId) if not SolidId or not EgtGetInfo( SolidId, 'VALID') then EgtBeamCalcSolid( nPartId, true) SolidId = EgtBeamGetSolid( nPartId) end local nOutline, nCnt = EgtGetSurfTmSilhouette( SolidId, Z_AX(), 10, nOutlineLayer, GDB_RT.GLOB) EgtBeamShowSolid( nPartId, false) --EgtSaveFile("c:\\Temp\\ProvaNesting.nge") local nCurrOutline = nOutline if nCnt > 0 then local frSum EgtScale( nOutline, GLOB_FRM(), 1, 1, 0, GDB_RT.GLOB) EgtModifyCurveExtrusion( nOutline, Z_AX(), GDB_RT.GLOB) -- verifico che la prima curva sia l'unico loop esterno local vCrvRef = EgtCurveArea( nOutline) for nInd = 1, nCnt - 1 do local vCrv = EgtCurveArea( nOutline + nInd) -- se trovo più loop esterni uso come contorno quello del box (quindi forzo nCurrOutline a nil) if abs( vCrv * vCrvRef - 1) < GEO.EPS_SMALL then nCurrOutline = nil break end end --local frSum = EgtSurfFlatRegion(nOutlineLayer, nOutline) --EgtSaveFile("c:\\Temp\\ProvaNesting.nge") -- -- per ogni contorno creo flat region e le sommo -- for nIndex = 0, nCnt - 1 do -- EgtScale( nOutline + nIndex, GLOB_FRM(), 1, 1, 0, GDB_RT.GLOB) -- EgtModifyCurveExtrusion( nOutline + nIndex, Z_AX(), GDB_RT.GLOB) -- local frCurr = EgtSurfFlatRegion(nOutlineLayer, nOutline + nIndex) -- if frCurr then -- if frSum then -- EgtSurfFrAdd(frSum, frCurr) -- else -- frSum = frCurr -- end -- end -- EgtErase(frCurr) -- end -- --EgtSaveFile("c:/Temp/ProvaNesting.nge") -- -- calcolo contorno della flat region somma -- nCurrOutline = EgtExtractSurfFrChunkLoops(frSum, 0, nOutlineLayer) -- EgtErase(frSum) -- -- cancello contorni -- for nIndex = 0, nCnt do -- EgtErase(nOutline + nIndex) -- end end if nCurrOutline and nCurrOutline ~= GDB_ID.NULL then nOutline = nCurrOutline else -- se non ho trovato contorno, lo recupero dal Box local nBoxLayer = EgtGetFirstNameInGroup(nPartId, "Box") local nBox = EgtGetFirstNameInGroup(nBoxLayer, "Box") local BBox = EgtGetBBoxGlob(nBox, GDB_BB.STANDARD) nOutline = EgtRectangle2P(nOutlineLayer, Point3d( BBox:getMin():getX(), BBox:getMin():getY(), 0), Point3d( BBox:getMax():getX(), BBox:getMax():getY(), 0), GDB_RT.GLOB) EgtOutLog("Impossible creating silhouette for part " .. tostring(nPartId)) end --if nCnt == 0 then -- -- se non ho trovato contorno, lo recupero dal Box -- local nBoxLayer = EgtGetFirstNameInGroup(nPartId, "Box") -- local nBox = EgtGetFirstNameInGroup(nBoxLayer, "Box") -- local BBox = EgtGetBBoxGlob(nBox, GDB_BB.STANDARD) -- nOutline = EgtRectangle2P(nOutlineLayer, Point3d( BBox:getMin():getX(), BBox:getMin():getY(), 0), Point3d( BBox:getMax():getX(), BBox:getMax():getY(), 0), GDB_RT.GLOB) -- EgtOutLog("Impossible creating silhouette for part " .. tostring(nPartId)) --else -- --EgtScale( nOutline, GLOB_FRM(), 1, 1, 0, GDB_RT.GLOB) -- --EgtModifyCurveExtrusion( nOutline, Z_AX(), GDB_RT.GLOB) -- --EgtSaveFile("c:/Temp/ProvaNesting.nge") -- EgtScale( nOutline, GLOB_FRM(), 1, 1, 0, GDB_RT.GLOB) -- EgtModifyCurveExtrusion( nOutline, Z_AX(), GDB_RT.GLOB) -- local frSum = EgtSurfFlatRegion(nOutlineLayer, nOutline) -- EgtSaveFile("c:\\Temp\\ProvaNesting.nge") -- -- per ogni contorno creo flat region e le sommo -- for nIndex = 1, nCnt - 1 do -- EgtScale( nOutline + nIndex, GLOB_FRM(), 1, 1, 0, GDB_RT.GLOB) -- EgtModifyCurveExtrusion( nOutline + nIndex, Z_AX(), GDB_RT.GLOB) -- local frCurr = EgtSurfFlatRegion(nOutlineLayer, nOutline + nIndex) -- if frCurr then -- EgtSurfFrAdd(frSum, frCurr) -- end -- end -- -- calcolo contorno della flat region somma -- nOutline = EgtExtractSurfFrChunkLoops(frSum, 0, nOutlineLayer) -- -- cancello contorni successivi -- for nIndex = 1, nCnt do -- EgtErase(nOutline + nIndex) -- end --end EgtSetName( nOutline, 'ON_TMP') --[[ local nOutline local nTrimesh local bFirst = true local bSecond = false local bUseBox = false nTrimesh = EgtGetFirstNameInGroup( nOutlineLayer, "1-Out") if not nTrimesh then nTrimesh = EgtGetFirstNameInGroup( nOutlineLayer, "2-Out") end if not nTrimesh then nTrimesh = EgtGetFirstNameInGroup( nOutlineLayer, "3-Out") end if not nTrimesh then nTrimesh = EgtGetFirstNameInGroup( nOutlineLayer, "4-Out") end -- se trovato contorno if nTrimesh then -- recupero la curva associata local nAuxId = EgtGetInfo(nTrimesh, "AUXID", 'i') nOutline = nTrimesh + nAuxId -- verifico che il contorno sia verticale local nFacetCount = EgtSurfTmFacetCount(nTrimesh) for nIndex = 0, nFacetCount - 1 do local vtNorm = EgtSurfTmFacetNormVersor(nTrimesh, nIndex, GDB_ID.ROOT) if abs( vtNorm:getZ()) > 10 * GEO.EPS_SMALL then bUseBox = true break end end -- se due compo o una e lati inclinati if bUseBox then -- calcolo box della trimesh local b3Outline = EgtGetBBoxGlob(nTrimesh, GDB_BB.IGNORE_TEXT) local ptP1 = Point3d( b3Outline:getMin():getX(), b3Outline:getMin():getY(), 0) local ptP2 = Point3d( b3Outline:getMax():getX(), b3Outline:getMax():getY(), 0) -- creo outline del box nOutline = EgtRectangle2P(nOutlineLayer, ptP1, ptP2, GDB_RT.GLOB) EgtSetStatus(nOutline, GDB_ST.OFF) end -- altrimenti cerco la regione sopra else -- cancello precedenti contorni calcolati local nOldONId = EgtGetFirstNameInGroup( nOutlineLayer, 'ON_TMP') if nOldONId then EgtErase( nOldONId) end -- cerco la regione sopra local nReg for i = 1, 4 do local sRegName = string.format( '%d-Top', i) nReg = EgtGetFirstNameInGroup( nOutlineLayer, sRegName) if nReg then local vtNorm = EgtSurfFrNormVersor( nReg, GDB_ID.ROOT) if vtNorm:getZ() > 0.99 then break end end end if not nReg then EgtOutLog("Errore: regione superiore non trovata") end -- recupero contorno della regione local OutId, nCnt = EgtExtractSurfFrChunkLoops( nReg, 0, nOutlineLayer) if OutId and nCnt > 1 then for i = 2, nCnt do EgtErase( OutId + i - 1) end end if OutId then EgtSetName( OutId, 'ON_TMP') nOutline = OutId end end ]]-- if nOutline then -- aggiungo pezzo al nesting EgtAutoNestAddPart( nPartId, nOutline, false, bRotNest, nStepRotNest, 0, nCount) -- EgtAutoNestAddPart( PartId, OutlineId, bCanFlip, bCanRotate, dRotStep, nPriority, nCount) end -- aggiungo aree di lavorazione del pezzo local nToolOutlineIds = ComputeToolOutlines( nPartId) for nInd = 1, #nToolOutlineIds do EgtAutoNestAddToolOutlineToPart( nPartId, nToolOutlineIds[nInd]) end -- verifico se anullato nesting if EgtProcessEvents( 100 + ( nPartIndex / nTotParts * 100), 0) == 1 then return false end -- se necessario ripristino flip e rotazioni del pezzo if bFlip then EgtRotate( nPartId, b3Part:getCenter(), X_AX(), -180, GDB_RT.GLOB) end if nRotate and nRotate > 0 then EgtRotate( nPartId, b3Part:getCenter(), Z_AX(), -nRotate, GDB_RT.GLOB) end end return true end -- Inizializzo contatori errori e avvisi local nErrCnt = 0 local nWarnCnt = 0 local bOk = true NEST.ERR = 0 -- resetto gruppo di lavorazione corrente EgtResetCurrMachGroup() -- inizio nesting automatico EgtAutoNestStart() -- lista dei grezzi local RawParts = {} -- creo grezzi e li aggiungo al nesting AddRawParts(RawParts) if not bOk then EgtOutLog("Interruzione nesting") NEST.ERR = 1 end -- calcolo rotazioni e flip ed aggiungo pezzi al nesting if bOk then bOk = AddParts(RawParts) end if not bOk then EgtOutLog("Interruzione nesting") NEST.ERR = 1 end if bOk then -- aggiungo offset tra pezzi EgtAutoNestSetInterpartGap(NEST.OFFSET) -- Impostazione corner di inizio del nesting (NST_CORNER.BL, TL, BR, TR) EgtAutoNestSetStartCorner( NST_CORNER.BR) -- imposto tempo di nesting e lo avvio EgtAutoNestCompute(true, NEST.TIME) end -- Variabili di calcolo local nNestedParts, nParts, nSheets, nNestings, dTotFillRatio local bNestingOk = bOk -- Attesa fine calcolo local nTime = 0 while bNestingOk do bNestingOk, nStat = EgtAutoNestGetComputationStatus() if nStat == 2 or nStat == 3 then nNestedParts, nParts, nSheets, nNestings, dTotFillRatio = EgtAutoNestGetResults() --EgtOutText( string.format( 'Parts : %d/%d Filling : %.2f%%', nNestedParts, nParts, 100 * dTotFillRatio)) end if nStat == 3 then break end nTime = nTime + 1 if EgtProcessEvents( nTime / NEST.TIME * 100, 995) == 1 then bNestingOk = EgtAutoNestCancelComputation() bOk = false EgtOutLog("Interruzione nesting") NEST.ERR = 1 break end end -- se nesting andato bene if bNestingOk then -- disposizione sheet e parts local SheetId = GDB_ID.NULL local vtAdd = V_NULL() local nMachGroup = GDB_ID.NULL local nPartCount = 0 local Sheet = {PartList = {}} local bFirstSheet = true for i = 0, 999 do local nType, nId, nFlag, dX, dY, dAngRot = EgtAutoNestGetOneResult( i) if not nType then break end -- se sheet if nType > 0 then -- creo gruppo di lavorazione local MachGroupName = NewMachGroupName() nMachGroup = EgtAddMachGroup(MachGroupName, sCurrMachName) for nIndex = 1, #RawParts do if RawParts[nIndex].PartId == nId then EgtSetInfo(nMachGroup, "PANELLEN", RawParts[nIndex].Len) EgtSetInfo(nMachGroup, "PANELWIDTH", RawParts[nIndex].Width) EgtSetInfo(nMachGroup, "MATERIAL", RawParts[nIndex].Material) EgtSetInfo(nMachGroup, "AUTONEST", 1) end end nPartCount = 0 -- altrimenti pezzo else nPartCount = nPartCount + 1 -- se c'e' un grezzo valido if nMachGroup and nMachGroup ~= GDB_ID.NULL then -- creo pezzo copia local nPartDuploId = EgtDuploNew( nId) -- applico flip e rotazioni fatte durante verifica posizionamento pezzo local b3Part = EgtGetBBoxGlob( nPartDuploId, GDB_BB.STANDARD) local nPartInd for nInd = 1, #PartStates do if PartStates[nInd].PartId == nId then if PartStates[nInd].Flip then EgtRotate( nPartDuploId, b3Part:getCenter(), X_AX(), 180, GDB_RT.GLOB) end if PartStates[nInd].Rotate and PartStates[nInd].Rotate > 0 then EgtRotate( nPartDuploId, b3Part:getCenter(), Z_AX(), PartStates[nInd].Rotate, GDB_RT.GLOB) end nPartInd = nInd end end -- applico rotazione e traslazione pezzo da nesting EgtRotate( nPartDuploId, ORIG(), Z_AX(), dAngRot, GDB_RT.GLOB) EgtMove( nPartDuploId, Vector3d( dX, dY, 0), GDB_RT.GLOB) local PartBBox = EgtGetBBoxGlob( nPartDuploId, GDB_BB.STANDARD) local ptPos = Point3d( PartBBox:getMin():getX(), PartBBox:getMin():getY(), 0) EgtSetInfo( nMachGroup, "PART" .. nPartCount, nPartDuploId .. "," .. EgtNumToString( ptPos:getX(), 3) .. "," .. EgtNumToString( ptPos:getY(), 3) .. "," .. 0 .."," .. 0) EgtSetInfo( nPartDuploId, "POSX", ptPos:getX()) EgtSetInfo( nPartDuploId, "POSY", ptPos:getY()) EgtSetInfo( nPartDuploId, "ROT", dAngRot + PartStates[nPartInd].Rotate) EgtSetInfo( nPartDuploId, "FLIP", PartStates[nPartInd].Flip) end end end -- creo grezzi per ogni gruppo di lavorazione local MachGroupToTCnt = EgtGetMachGroupCount() local MachGroupIndex = 0 _G.WALL = {} WALL.FILE = NEST.FILE WALL.MACHINE = NEST.MACHINE WALL.FLAG = 6 -- CREATE_PANEL nMachGroup = EgtGetFirstMachGroup() while nMachGroup do EgtSetCurrMachGroup(nMachGroup) if EgtGetInfo(nMachGroup, "AUTONEST",'i') == 1 then MachGroupIndex = MachGroupIndex + 1 EgtRemoveInfo(nMachGroup, "AUTONEST") EgtSetInfo(nMachGroup, "UPDATEUI", 1) dofile(EgtGetSourceDir() .. "BatchProcessNew.lua") -- aggiorno interfaccia EgtProcessEvents( 200 + ( MachGroupIndex / MachGroupToTCnt * 100), 0) end nMachGroup = EgtGetNextMachGroup(nMachGroup) end else EgtOutLog("Errore: nesting fallito") NEST.ERR = 2 end EgtResetCurrMachGroup() -- cancello rettangolo del materiale per nesting for RawPartId = 1, #RawParts do EgtErase(RawParts[RawPartId].PartId) end local nOutlineGrp = EgtGetFirstNameInGroup(GDB_ID.ROOT, "ToolOutlines") if nOutlineGrp and nOutlineGrp ~= GDB_ID.NULL then EgtErase( nOutlineGrp) end -- EgtSaveFile("c:\\Temp\\Prova1.nge") EgtOutLog( ' +++ NestProcess completed')