Files
DataWall/NestProcess.lua
T
DarioS fea5d18c06 DataWall :
- modifiche per nesting cliente belga
- in FreeContour aggiunta gestione marcatura (codice 10).
2021-11-04 13:53:36 +01:00

886 lines
35 KiB
Lua

-- 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')