Files
DataWall/NestProcess.lua

2200 lines
93 KiB
Lua

-- NestProcess.lua by Egaltech s.r.l. 2022/11/24
-- 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
--NEST.MIN_ANGLE_PNT = 60
--NEST.DRILL_MACH_AREA = 0
NEST.LAP_JOINT_U_MACH_AREA = 1 -- 0
NEST.MACH_AREA_USE_OTHER_DIAM = 1 -- 0
NEST.MACH_AREA_OTHER_DIAM = 200
NEST.MACH_AREA_IGNORE_3rdFACE = 1 -- 0
if NEST.FLAG ~= 11 then
local sLog = 'NestProcess : ' .. NEST.FILE .. ', ' .. NEST.MACHINE .. ', ' .. LEN[1] .. ', ' .. WIDTH[1]
EgtOutLog( sLog)
-- Cancello file di log specifico
local sLogFile = EgtChangePathExtension( NEST.FILE, '.txt')
EgtEraseFile( sLogFile)
end
-- Imposto direttorio libreria specializzata per Travi
EgtAddToPackagePath( NEST.BASEDIR .. '\\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
NEST.ERR = 12
NEST.MSG = 'Error not configured for walls machine : ' .. sMachine
WriteErrToLogFile( NEST.ERR, NEST.MSG)
PostErrView( NEST.ERR, NEST.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.WProcessDoubleCut = nil
local DoubleCut = require( 'WProcessDoubleCut')
_G.package.loaded.WProcessFreeContour = nil
local FreeContour = require( 'WProcessFreeContour')
_G.package.loaded.PanelSaw = nil
local PanelSaw = require( 'PanelSaw')
-- Carico i dati globali
local WD = require( 'WallData')
-- Recupero alcuni dati dal WallData o li setto a valori di default
local s_dSideMillDiamDown = WD.SIDEMILL_DIAM_DOWN or 350
local s_dSideMillDiamUp = WD.SIDEMILL_DIAM_UP or 65
local s_dHorDrillLen = WD.HOR_DRILL_LEN or 1780
local s_dHorDrillDiam = WD.HOR_DRILL_DIAM or 35
local s_dHorDrillDiam5Axes = WD.HOR_DRILL_DIAM_5AX or 0
local s_sOrigCorner = WD.ORIG_CORNER or 'TL'
local s_dIntRulli = WD.INTRULLI or 1200
local s_dMinRawYHorDrill = WD.MINRAWY_HOR_DRILL or 2800
local s_dNestHoleMinArea = WD.NEST_HOLE_MIN_AREA or 200000
local s_dInsideRawTol = WD.INSIDE_RAW_TOL or 30
-- 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 il rettangolo della lavorazione
local function CreateToolRectangle( ptP1, dValP1, ptP2, dValP2, vtFace, dValFace, nOutlineGrp)
local dExtra = 5
local vtX = ptP2 - ptP1
vtX:normalize()
-- creo il rettangolo della lavorazione
ptP1 = ptP1 - vtX * ( dValP1 + dExtra)
ptP2 = ptP2 + vtX * ( dValP2 + dExtra)
ptP2 = ptP2 + vtFace * ( dValFace + dExtra)
--local nId = EgtRectangle2P( nOutlineGrp, Point3d(ptP2:getX(), ptP2:getY(), 0), Point3d( ptP1:getX(), ptP1:getY(), 0))
local nId = EgtRectangle2P( nOutlineGrp, ptP2, ptP1)
return nId
end
------------------------------------------------------------------
-- Funzione che verifica se la lavorazione è lap joint dal basso ed eventualmente ne calcola l'area di lavorazione
local function IdentifyLJFromBottom( Proc, bCompute, nOutlineGrp)
local bLJFromBottom = false
local nRectId
local vtFace
local dMinCompZ = 0.95
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)
-- se rivolto verso il basso
if ( vtN[1]:getZ() < - dMinCompZ or vtN[2]:getZ() < - dMinCompZ) then
vtFace = EgtIf( vtN[1]:getZ() < - dMinCompZ, vtN[2], vtN[1])
if not ( vtFace:getZ() > dMinCompZ or vtFace:getZ() < - dMinCompZ) then
bLJFromBottom = true
if bCompute then
local bAdj, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, 0, 1, GDB_ID.ROOT)
-- creo il rettangolo della lavorazione
nRectId = CreateToolRectangle( ptP1, s_dSideMillDiamDown / 2, ptP2, s_dSideMillDiamDown / 2, vtFace, s_dSideMillDiamDown, nOutlineGrp)
end
end
end
elseif Proc.Fct == 3 then
local nFacInd, dElev, nFacInd2 = WL.GetFaceWithMostAdj( Proc.Id, Proc.PartId)
-- se nel mezzo di una faccia
if not nFacInd2 then
if nFacInd ~= -2 and nFacInd ~= GDB_ID.NULL then
vtFace = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT)
if not ( vtFace:getZ() > dMinCompZ or vtFace:getZ() < - dMinCompZ) 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
bLJFromBottom = true
if bCompute then
nRectId = CreateToolRectangle( ptP1, s_dSideMillDiamDown / 2, ptP2, s_dSideMillDiamDown / 2, vtFace, s_dSideMillDiamDown, nOutlineGrp)
end
end
end
end
-- se dal basso
else
local nFaceZ = -1
for nIdx = 0, 2 do
local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, nIdx, GDB_ID.ROOT)
if vtN2:getZ() < - dMinCompZ then
nFaceZ = nIdx
break
end
end
if nFaceZ ~= -1 then
local nFace = EgtIf( nFaceZ == nFacInd, nFacInd2, nFacInd)
local nOtherFace = EgtIf( nFaceZ + nFace == 3, 0, EgtIf( nFaceZ + nFace == 2, 1, 2))
vtFace = EgtSurfTmFacetNormVersor( Proc.Id, nFace, GDB_ID.ROOT)
--vtFace[2] = EgtSurfTmFacetNormVersor( Proc.Id, nOtherFace, GDB_ID.ROOT)
bLJFromBottom = true
if bCompute then
local bAdj, ptP1, ptP2 = EgtSurfTmFacetsContact( Proc.Id, nFace, nFaceZ, GDB_ID.ROOT)
local bAdj2, ptP3, ptP4 = EgtSurfTmFacetsContact( Proc.Id, nFace, nOtherFace, GDB_ID.ROOT)
if AreSamePointApprox( ptP2, ptP3) or AreSamePointApprox( ptP2, ptP4) then
ptP1, ptP2 = ptP2, ptP1
end
local dVal = EgtIf( NEST.MACH_AREA_IGNORE_3rdFACE == 1, s_dSideMillDiamDown / 2, 0)
nRectId = CreateToolRectangle( ptP1, dVal, ptP2, s_dSideMillDiamDown / 2, vtFace, s_dSideMillDiamDown, nOutlineGrp)
end
end
end
elseif Proc.Fct == 4 then
local nFacInd, dElev, nFacInd2, dElev2 = WL.GetFaceWithMostAdj( Proc.Id, Proc.PartId)
if nFacInd ~= -2 and nFacInd ~= GDB_ID.NULL then
vtFace = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT)
if not ( vtFace:getZ() > dMinCompZ or vtFace:getZ() < - dMinCompZ) then
local nOtherFace = -1
for nIdx = 0, 3 do
local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, nIdx, GDB_ID.ROOT)
if vtN2:getZ() > dMinCompZ or vtN2:getZ() < - dMinCompZ then
nOtherFace = nIdx
break
end
end
if nOtherFace ~= -1 and nOtherFace ~= nFacInd and nOtherFace ~= nFacInd2 then
bLJFromBottom = true
if bCompute then
local bAdj, ptP1, ptP2 = EgtSurfTmFacetsContact( Proc.Id, nFacInd, nOtherFace, GDB_ID.ROOT)
local bAdj2, ptP3, ptP4 = EgtSurfTmFacetsContact( Proc.Id, nFacInd, nFacInd2, GDB_ID.ROOT)
if AreSamePointApprox( ptP2, ptP3) or AreSamePointApprox( ptP2, ptP4) then
ptP1, ptP2 = ptP2, ptP1
end
nRectId = CreateToolRectangle( ptP1, 0, ptP2, s_dSideMillDiamDown / 2, vtFace, s_dSideMillDiamDown, nOutlineGrp)
end
end
end
if nFacInd2 and nFacInd2 ~= GDB_ID.NULL then
local vtFace2 = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd2, GDB_ID.ROOT)
if ( vtFace2:getZ() < - dMinCompZ or vtFace:getZ() < - dMinCompZ) then
bLJFromBottom = true
if vtFace:getZ() < -dMinCompZ then vtFace = vtFace2 end
if bCompute then
local bAdj, ptP1, ptP2 = EgtSurfTmFacetsContact( Proc.Id, nFacInd, nFacInd2, GDB_ID.ROOT)
nRectId = CreateToolRectangle( ptP1, 0, ptP2, 0, vtFace, s_dSideMillDiamDown, nOutlineGrp)
end
end
end
end
end
if bLJFromBottom then
return vtFace, nRectId
else
return
end
end
------------------------------------------------------------------
-- Funzione che verifica se la lavorazione è lap joint da sopra ed eventualmente ne calcola l'area di lavorazione
local function IdentifyLJFromTop( Proc, bCompute, nOutlineGrp)
local bLJFromTop = false
local vtFace, nRectId
if s_dSideMillDiamUp < GEO.EPS_SMALL then return end
local dMinComp = 0.95
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)
-- se rivolto verso l'alto
if (vtN[1]:getZ() > dMinComp or vtN[2]:getZ() > dMinComp) then
bLJFromTop = true
vtFace = EgtIf( vtN[1]:getZ() > dMinComp, vtN[2], vtN[1])
if bCompute then
local bAdj, ptP1, ptP2, dAng = EgtSurfTmFacetsContact( Proc.Id, 0, 1, GDB_ID.ROOT)
local b3Face = EgtSurfTmGetFacetBBoxGlob( Proc.Id, EgtIf( vtN[1]:getZ() > dMinComp, 0, 1), GDB_BB.STANDARD)
local dDim = 0
if vtFace:getX() > dMinComp or vtFace:getX() < - dMinComp then
dDim = b3Face:getDimX()
elseif vtFace:getY() > dMinComp or vtFace:getY() < - dMinComp then
dDim = b3Face:getDimY()
end
local dValFace = max( dDim + s_dSideMillDiamUp / 2, s_dSideMillDiamUp)
local dVal = s_dSideMillDiamUp / 2
if NEST.MACH_AREA_USE_OTHER_DIAM == 1 then
dVal = NEST.MACH_AREA_OTHER_DIAM / 2
end
nRectId = CreateToolRectangle( ptP1, dVal, ptP2, dVal, vtFace, dValFace, nOutlineGrp)
end
end
-- caso 3 facce
elseif Proc.Fct == 3 then
local nFacInd, dElev, nFacInd2 = WL.GetFaceWithMostAdj( Proc.Id, Proc.PartId)
-- forma ad U
if not nFacInd2 and nFacInd ~= GDB_ID.NULL and NEST.LAP_JOINT_U_MACH_AREA == 1 then
local vtFace = EgtSurfTmFacetNormVersor( Proc.Id, nFacInd, GDB_ID.ROOT)
if vtFace:getZ() > dMinComp then
bLJFromTop = true
if bCompute then
local b3Face = EgtSurfTmGetFacetBBoxGlob( Proc.Id, nFacInd, GDB_BB.STANDARD)
local nOtherFace = EgtIf( nFacInd == 0, 1, 0)
local vtNOther = EgtSurfTmFacetNormVersor( Proc.Id, nOtherFace, GDB_ID.ROOT)
local vtDir = EgtIf( AreSameOrOppositeVectorApprox( vtNOther, X_AX()), Y_AX(), X_AX())
local dVal = s_dSideMillDiamUp / 2 + 5
local ptMin = b3Face:getMin() - dVal * vtDir
local ptMax = b3Face:getMax() + dVal * vtDir
-- nRectId = EgtRectangle2P( nOutlineGrp, Point3d(ptMax:getX(), ptMax:getY(), 0), Point3d( ptMin:getX(), ptMin:getY(), 0))
nRectId = EgtRectangle2P( nOutlineGrp, ptMax, ptMin)
end
end
elseif nFacInd2 then
local nFaceZ = -1
for nIdx = 0, 2 do
local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, nIdx, GDB_ID.ROOT)
if vtN2:getZ() > dMinComp then
nFaceZ = nIdx
break
end
end
if nFaceZ ~= -1 then
local nFace = EgtIf( nFaceZ == nFacInd, nFacInd2, nFacInd)
local nOtherFace = EgtIf( nFaceZ + nFace == 3, 0, EgtIf( nFaceZ + nFace == 2, 1, 2))
local vtFace = {}
vtFace = EgtSurfTmFacetNormVersor( Proc.Id, nFace, GDB_ID.ROOT)
--vtFace = EgtSurfTmFacetNormVersor( Proc.Id, nOtherFace, GDB_ID.ROOT)
bLJFromTop = true
if bCompute then
local bAdj, ptP1, ptP2 = EgtSurfTmFacetsContact( Proc.Id, nFace, nFaceZ, GDB_ID.ROOT)
local bAdj2, ptP3, ptP4 = EgtSurfTmFacetsContact( Proc.Id, nFace, nOtherFace, GDB_ID.ROOT)
if AreSamePointApprox( ptP2, ptP3) or AreSamePointApprox( ptP2, ptP4) then
ptP1, ptP2 = ptP2, ptP1
end
local b3Face = EgtSurfTmGetFacetBBoxGlob( Proc.Id, nFaceZ, GDB_BB.STANDARD)
local dDim = 0
if vtFace:getX() > dMinComp or vtFace:getX() < - dMinComp then
dDim = b3Face:getDimX()
elseif vtFace:getY() > dMinComp or vtFace:getY() < - dMinComp then
dDim = b3Face:getDimY()
end
local dValFace = max( dDim + s_dSideMillDiamUp / 2, s_dSideMillDiamUp)
local dVal = s_dSideMillDiamUp / 2
if NEST.MACH_AREA_USE_OTHER_DIAM == 1 then
dVal = NEST.MACH_AREA_OTHER_DIAM / 2
end
nRectId = CreateToolRectangle( ptP1, 0, ptP2, dVal, vtFace, dValFace, nOutlineGrp)
end
end
end
end
if bLJFromTop then
return vtFace, nRectId
else
return
end
end
------------------------------------------------------------------
-- Funzione che crea le regioni occupate dalle lavorazioni
local function ComputeToolOutlines( nPartId)
local ToolOutlineId = {}
EgtRemoveInfo( nPartId, "ToolOutlines")
-- 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
local vPartProc = WE.CollectFeatures( nPartId, b3Raw)
for nInd = 1, #vPartProc do
local Proc = vPartProc[nInd]
-- lap joint
if LapJoint.Identify( Proc) then
-- verifico se dal basso
local _ , nRectId = IdentifyLJFromBottom( Proc, true, nOutlineGrp)
if nRectId then
EgtSetColor( nRectId, EgtStdColor("BLUE"))
table.insert( ToolOutlineId, nRectId)
else
-- verifico se dall'alto
local _ , nRectId = IdentifyLJFromTop( Proc, true, nOutlineGrp)
if nRectId then
EgtSetColor( nRectId, EgtStdColor("AQUA"))
local nPrId = EgtGetInfo( Proc.Id, "PRID", 'i')
EgtSetInfo( nRectId, "PRID", nPrId)
table.insert( ToolOutlineId, nRectId)
end
end
end
-- fori
if NEST.DRILL_MACH_AREA == 1 and Drill.Identify( Proc) then
-- recupero dati del foro
local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') or 0
if AuxId then AuxId = AuxId + Proc.Id end
local dLen = abs( EgtCurveThickness( AuxId))
local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB)
local bOpen = ( Proc.Fcs ~= 0 and Proc.Fce ~= 0)
local dDiam = 2 * EgtArcRadius( AuxId)
-- verifico se la lunghezza del foro è maggiore della lunghezza della punta
if bOpen and AreSameOrOppositeVectorApprox( vtExtr, Y_AX()) and dLen > s_dHorDrillLen - 1 then
local ptP1 = Proc.Box:getMin()
local ptP2 = Proc.Box:getMax()
local dExtra = 10
ptP1 = ptP1 - ( WD.MAX_WIDTH - dLen + dExtra) * Y_AX()
ptP2 = ptP2 + ( WD.MAX_WIDTH - dLen + dExtra) * Y_AX()
--local nId = EgtRectangle2P( nOutlineGrp, Point3d(ptP2:getX(), ptP2:getY(), 0), Point3d( ptP1:getX(), ptP1:getY(), 0))
local nId = EgtRectangle2P( nOutlineGrp, ptP2, ptP1)
EgtSetColor( nId, EgtStdColor("AQUA"))
if nId ~= GDB_ID.NULL then table.insert(ToolOutlineId, nId) end
end
end
-- lati inclinati free contour
if FreeContour.Identify( Proc) then
local bPocket = EgtGetInfo( Proc.Id, 'PCKT', 'b')
if not bPocket then
for nInd = 0, Proc.Fct - 1 do
local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nInd, GDB_ID.ROOT)
-- se inclinato
if abs( vtN:getZ()) > GEO.EPS_SMALL then
local bUnderCut = vtN:getZ() < - GEO.EPS_SMALL
local dCosAlpha = (vtN ^ Z_AX()):len()
local dVal
if bUnderCut then
dVal = ( NEST.OFFSET + 0.1) / dCosAlpha
else
dVal = ( NEST.OFFSET + 0.1) * dCosAlpha
end
local frLoc, dDimX, dDimY = EgtSurfTmFacetMinAreaRectangle( Proc.Id, nInd, GDB_ID.ROOT)
local b3Face = EgtSurfTmGetFacetBBoxRef( Proc.Id, nInd, GDB_BB.STANDARD, frLoc)
local ptA = b3Face:getMin()
local ptC = b3Face:getMax()
local ptB = ptA + dDimY * Y_AX()
local ptD = ptA + dDimX * X_AX()
ptA:toGlob( frLoc)
ptB:toGlob( frLoc)
ptC:toGlob( frLoc)
ptD:toGlob( frLoc)
local ptP1, ptP2
if bUnderCut then
ptP1 = EgtIf( ptA:getZ() > ptC:getZ(), ptA, ptC)
ptP2 = EgtIf( ptB:getZ() > ptD:getZ(), ptB, ptD)
else
ptP1 = EgtIf( ptA:getZ() < ptC:getZ(), ptA, ptC)
ptP2 = EgtIf( ptB:getZ() < ptD:getZ(), ptB, ptD)
end
local vtDir = ptP2 - ptP1
vtDir:normalize()
ptP1 = ptP1 - vtDir * 0.5 * NEST.OFFSET
ptP2 = ptP2 + vtDir * 0.5 * NEST.OFFSET
local vtNxy = Vector3d( vtN:getX(), vtN:getY(), 0)
vtNxy:normalize()
local ptP4 = ptP2 + dVal * vtNxy
local nRectId = EgtRectangle3P( nOutlineGrp, ptP1, ptP4, ptP2)
EgtSetColor( nRectId, EgtStdColor("AQUA"))
if nRectId ~= GDB_ID.NULL then table.insert( ToolOutlineId, nRectId) end
end
end
end
end
end
return ToolOutlineId
end
------------------------------------------------------------------
local function ClassifyDrillsOnLateralFaces( nPartId, dMinSheetWidth)
local dDeltaRaw = WD.MAX_WIDTH - dMinSheetWidth + NEST.KERF
local DrillClassif
local DrillOnFaces = { F = {nbr = 0, closed = false, long = false, OnlyOnRef = false}, B = {nbr = 0, closed = false, long = false, OnlyOnRef = false},
L = {nbr = 0, closed = false, long = false, OnlyOnRef = false}, R = {nbr = 0, closed = false, long = false, OnlyOnRef = false}}
local nBoxLayerId = EgtGetFirstNameInGroup( nPartId, "Box")
local nBoxId = EgtGetFirstNameInGroup( nBoxLayerId, "Box")
local b3Part = EgtGetBBoxGlob(nBoxId, GDB_BB.STANDARD)
local ptPartMin = b3Part:getMin()
local ptPartMax = b3Part:getMax()
local vPartProc = WE.CollectFeatures( nPartId)
for nInd = 1, #vPartProc do repeat
if Drill.Identify( vPartProc[nInd]) then
-- identifico su quali facce si trova il foro
local bOpen = ( vPartProc[nInd].Fcs ~= 0 and vPartProc[nInd].Fce ~= 0)
local AuxId = EgtGetInfo( vPartProc[nInd].Id, 'AUXID', 'i') or 0
if AuxId then AuxId = AuxId + vPartProc[nInd].Id end
if not AuxId or EgtGetType( AuxId) ~= GDB_TY.CRV_ARC then break end
-- verifico se diametro compatibile con la punta
local dDiam = 2 * EgtArcRadius( AuxId)
if ( abs( dDiam - s_dHorDrillDiam5Axes) < WD.DRILL_TOL + GEO.EPS_SMALL) or ( abs( dDiam - s_dHorDrillDiam) < WD.DRILL_TOL + GEO.EPS_SMALL) then
local ptDrill = EgtCP( AuxId, GDB_RT.GLOB)
local dLen = abs( EgtCurveThickness( AuxId))
local bLong = dLen > s_dHorDrillLen - 1
local bOnlyOnRef = dLen + dDeltaRaw > s_dHorDrillLen - GEO.EPS_SMALL and not bLong
-- faccia Front
local dTol = GEO.EPS_SMALL
if ( abs( ptDrill:getY() - ptPartMin:getY()) < dTol) then
DrillOnFaces.F.nbr = DrillOnFaces.F.nbr + 1
if bOnlyOnRef then DrillOnFaces.F.OnlyOnRef = true end
if bOpen then
DrillOnFaces.B.nbr = DrillOnFaces.B.nbr + 1
if bOnlyOnRef then DrillOnFaces.B.OnlyOnRef = true end
else
DrillOnFaces.F.closed = true
end
if bLong then
DrillOnFaces.F.long = true
if bOpen then DrillOnFaces.B.long = true end
end
-- faccia Back
elseif ( abs( ptDrill:getY() - ptPartMax:getY()) < dTol) then
DrillOnFaces.B.nbr = DrillOnFaces.B.nbr + 1
if bOnlyOnRef then DrillOnFaces.B.OnlyOnRef = true end
if bOpen then
DrillOnFaces.F.nbr = DrillOnFaces.F.nbr + 1
if bOnlyOnRef then DrillOnFaces.F.OnlyOnRef = true end
else
DrillOnFaces.B.closed = true
end
if bLong then
DrillOnFaces.B.long = true
if bOpen then DrillOnFaces.F.long = true end
end
-- faccia Left
elseif ( abs( ptDrill:getX() - ptPartMin:getX()) < dTol) then
DrillOnFaces.L.nbr = DrillOnFaces.L.nbr + 1
if bOnlyOnRef then DrillOnFaces.L.OnlyOnRef = true end
if bOpen then
DrillOnFaces.R.nbr = DrillOnFaces.R.nbr + 1
if bOnlyOnRef then DrillOnFaces.R.OnlyOnRef = true end
else
DrillOnFaces.L.closed = true
end
if bLong then
DrillOnFaces.L.long = true
if bOpen then DrillOnFaces.R.long = true end
end
-- faccia Right
elseif ( abs( ptDrill:getX() - ptPartMax:getX()) < dTol) then
DrillOnFaces.R.nbr = DrillOnFaces.R.nbr + 1
if bOnlyOnRef then DrillOnFaces.R.OnlyOnRef = true end
if bOpen then
DrillOnFaces.L.nbr = DrillOnFaces.L.nbr + 1
if bOnlyOnRef then DrillOnFaces.L.OnlyOnRef = true end
else
DrillOnFaces.R.closed = true
end
if bLong then
DrillOnFaces.R.long = true
if bOpen then DrillOnFaces.L.long = true end
end
end
end
end
until true
end
-- identifico la faccia da mettere sul lato del grezzo
local sDrillFace, nMax = '', -100
for k, v in pairs( DrillOnFaces) do
if v.nbr > nMax or ( v.nbr == nMax and not DrillOnFaces[sDrillFace].OnlyOnRef and v.OnlyOnRef) then
sDrillFace, nMax = k, v.nbr
end
end
local sDrillFace2
if nMax > 0 then
if sDrillFace == 'F' or sDrillFace == 'B' then
-- cerco chi vince tra faccia left e right
if DrillOnFaces.L.nbr > DrillOnFaces.R.nbr then
sDrillFace2 = 'L'
elseif DrillOnFaces.L.nbr < DrillOnFaces.R.nbr then
sDrillFace2 = 'R'
elseif DrillOnFaces.L.nbr == DrillOnFaces.R.nbr and DrillOnFaces.L.nbr > 0 then
if DrillOnFaces.L.OnlyOnRef then
sDrillFace2 = 'L'
else
sDrillFace2 = 'R'
end
end
else
-- cerco chi vince tra faccia front e back
if DrillOnFaces.F.nbr > DrillOnFaces.B.nbr then
sDrillFace2 = 'F'
elseif DrillOnFaces.F.nbr < DrillOnFaces.B.nbr then
sDrillFace2 = 'B'
elseif DrillOnFaces.F.nbr == DrillOnFaces.B.nbr and DrillOnFaces.F.nbr > 0 then
if DrillOnFaces.F.OnlyOnRef then
sDrillFace2 = 'F'
else
sDrillFace2 = 'B'
end
end
end
end
if NEST.DRILL_MACH_AREA == 0 then
DrillOnFaces[sDrillFace].long = false
end
if nMax > 0 then
DrillClassif = { sCase = sDrillFace, bClosed = DrillOnFaces[sDrillFace].closed, bLong = DrillOnFaces[sDrillFace].long, bOnlyOnRef = DrillOnFaces[sDrillFace].OnlyOnRef}
end
local DrillClassif2
if sDrillFace2 then
if NEST.DRILL_MACH_AREA == 0 then
DrillOnFaces[sDrillFace2].long = false
end
DrillClassif2 = { sCase = sDrillFace2, bClosed = DrillOnFaces[sDrillFace2].closed, bLong = DrillOnFaces[sDrillFace2].long, bOnlyOnRef = DrillOnFaces[sDrillFace2].OnlyOnRef}
end
return DrillClassif, DrillClassif2
end
------------------------------------------------------------------
local function ClassifyLapJointsFromBottom( nPartId)
local res = { Nbr = 0, sCase = '', bParall = false}
local b3Part = EgtGetBBoxGlob( nPartId, GDB_BB.STANDARD)
local ptPartMin = b3Part:getMin()
local ptPartMax = b3Part:getMax()
local vtLapJoints = {}
local dMinComponentVal = 0.95
local vPartProc = WE.CollectFeatures( nPartId)
for nInd = 1, #vPartProc do
if LapJoint.Identify( vPartProc[nInd]) then
-- verifico se LJ da sotto
local vtFace = IdentifyLJFromBottom( vPartProc[nInd], false)
if vtFace then
if vtFace:getX() > dMinComponentVal then
vtLapJoints["R"] = 1
elseif vtFace:getX() < - dMinComponentVal then
vtLapJoints["L"] = 1
elseif vtFace:getY() > dMinComponentVal then
vtLapJoints["B"] = 1
elseif vtFace:getY() < - dMinComponentVal then
vtLapJoints["F"] = 1
end
end
end
end
local nCnt = 0
for _ in pairs(vtLapJoints) do nCnt = nCnt + 1 end
if nCnt == 1 then
res.Nbr = 1
for k, _ in pairs( vtLapJoints) do
res.sCase = k
end
elseif nCnt == 2 then
res.Nbr = 2
if vtLapJoints["F"] and vtLapJoints["B"] then
res.bParall = true
res.sCase = "F"
elseif vtLapJoints["R"] and vtLapJoints["L"] then
res.bParall = true
res.sCase = "R"
else
res.bParall = false
if vtLapJoints["B"] and vtLapJoints["R"] then
res.sCase = 'BR'
elseif vtLapJoints["B"] and vtLapJoints["L"] then
res.sCase = 'BL'
elseif vtLapJoints["F"] and vtLapJoints["R"] then
res.sCase = 'FR'
elseif vtLapJoints["F"] and vtLapJoints["L"] then
res.sCase = 'FL'
end
end
elseif nCnt == 3 then
res.Nbr = 3
if not vtLapJoints["F"] then
res.sCase = "F"
elseif not vtLapJoints["B"] then
res.sCase = "B"
elseif not vtLapJoints["R"] then
res.sCase = "R"
elseif not vtLapJoints["L"] then
res.sCase = "L"
end
elseif nCnt == 4 then
res.Nbr = 4
elseif nCnt ~= 0 then
return
end
return res
end
------------------------------------------------------------------
local function CreateDefectOnAngle( nPartId, RawPart, bDrillLong, bOnOppositeAng)
local PartTab = {}
-- recupero il gruppo dove salvo i defects
local nOutlineGrp = EgtGetFirstNameInGroup(GDB_ID.ROOT, "SheetDefects")
if not nOutlineGrp or nOutlineGrp == GDB_ID.NULL then
nOutlineGrp = EgtGroup( GDB_ID.ROOT)
EgtSetName( nOutlineGrp, "SheetDefects")
EgtSetStatus( nOutlineGrp, GDB_ST.OFF)
end
local dExtraMachArea = s_dSideMillDiamDown -- per tenere conto dell'area di lavorazione
local dExtra = NEST.KERF
-- local b3Part = EgtGetBBoxGlob( nPartId, GDB_BB.STANDARD)
local nBoxLayerId = EgtGetFirstNameInGroup( nPartId, "Box")
local nBoxId = EgtGetFirstNameInGroup( nBoxLayerId, "Box")
local b3Part = EgtGetBBoxGlob(nBoxId, GDB_BB.STANDARD)
local b3PartX = b3Part:getDimX()
local b3PartY = b3Part:getDimY()
-- se ho fori lunghi devo riservare tutto lo spazio
if bDrillLong then
b3PartY = RawPart.Width
end
-- calcolo i punti che definiscono il rettangolo
local ptP1, ptP2
if ( s_sOrigCorner == 'TL' and not bOnOppositeAng) or ( s_sOrigCorner == 'BL' and bOnOppositeAng) then
-- angolo TL
ptP1 = Point3d( 0, RawPart.Width - b3PartY - dExtra, 0)
ptP2 = Point3d( b3PartX + dExtra, RawPart.Width, 0)
PartTab.posX = NEST.KERF
PartTab.posY = RawPart.Width - b3Part:getDimY() - NEST.KERF
elseif ( s_sOrigCorner == 'BL' and not bOnOppositeAng) or ( s_sOrigCorner == 'TL' and bOnOppositeAng) then
-- angolo BL
ptP1 = Point3d( 0, 0, 0)
ptP2 = Point3d( b3PartX + dExtra, b3PartY + dExtra, 0)
PartTab.posX = NEST.KERF
PartTab.posY = NEST.KERF
elseif ( s_sOrigCorner == 'TR' and not bOnOppositeAng) or ( s_sOrigCorner == 'BR' and bOnOppositeAng) then
-- angolo TR
ptP1 = Point3d( RawPart.Len - b3PartX - dExtra, RawPart.Width - b3PartY - dExtra, 0)
ptP2 = Point3d( RawPart.Len, RawPart.Width, 0)
PartTab.posX = RawPart.Len - b3Part:getDimX() - NEST.KERF
PartTab.posY = RawPart.Width - b3Part:getDimY() - NEST.KERF
elseif ( s_sOrigCorner == 'BR' and not bOnOppositeAng) or ( s_sOrigCorner == 'TR' and bOnOppositeAng) then
-- angolo BR
ptP1 = Point3d( RawPart.Len - b3PartX - dExtra, 0, 0)
ptP2 = Point3d( RawPart.Len, b3PartY + dExtra, 0)
PartTab.posX = RawPart.Len - b3Part:getDimX() - NEST.KERF
PartTab.posY = NEST.KERF
end
PartTab.Id = tonumber(nPartId)
PartTab.DefectId = EgtRectangle2P( nOutlineGrp, Point3d(ptP2:getX() + dExtraMachArea, ptP2:getY() + dExtraMachArea , 0), Point3d( ptP1:getX() - dExtraMachArea , ptP1:getY() - dExtraMachArea, 0))
EgtSetName( PartTab.DefectId, "Defect")
return PartTab
end
------------------------------------------------------------------
local function RotateOptimalCase( nPartId, nAngle, nAngleValidRot, RawPart, nPnt1, nPnt2)
local bOptimal = false
local b3Part = EgtGetBBoxGlob( nPartId, GDB_BB.STANDARD)
EgtRotate( nPartId, b3Part:getCenter(), Z_AX(), nAngle, GDB_RT.GLOB)
local nRotate = nAngle
local nAnglePnt
local nBoxLayerId = EgtGetFirstNameInGroup( nPartId, "Box")
local nBoxId = EgtGetFirstNameInGroup( nBoxLayerId, "Box")
b3Part = EgtGetBBoxGlob(nBoxId, GDB_BB.STANDARD)
-- b3Part = EgtGetBBoxGlob( nPartId, GDB_BB.STANDARD)
local bIsValidRotation = b3Part:getDimX() < RawPart.Len - 2 * NEST.KERF + GEO.EPS_SMALL and b3Part:getDimY() < RawPart.Width - 2 * NEST.KERF + GEO.EPS_SMALL
if bIsValidRotation then
bOptimal = true
nAnglePnt = nPnt1
else
bOptimal = false
-- ruoto nella migliore posizione ammissibile
EgtRotate( nPartId, b3Part:getCenter(), Z_AX(), nAngleValidRot, GDB_RT.GLOB)
nRotate = nRotate + nAngleValidRot
nAnglePnt = nPnt2
end
if nRotate >= 360 then
nRotate = nRotate - 360
end
return nAnglePnt, nRotate, bOptimal
end
------------------------------------------------------------------
local function RotateOptimalCaseDrill( nPartId, bCanRotate, nPnt1, nPnt2)
local nRotate = 0
local nAnglePnt
if bCanRotate then
local b3Part = EgtGetBBoxGlob( nPartId, GDB_BB.STANDARD)
EgtRotate( nPartId, b3Part:getCenter(), Z_AX(), 180, GDB_RT.GLOB)
nRotate = 180
nAnglePnt = nPnt1
else
nAnglePnt = nPnt2
end
return nAnglePnt, nRotate
end
------------------------------------------------------------------
-- Funzione che classifica i pezzi in base alla loro necessità di stare negli angoli
local function ClassifyAngles( nPartId, RawPart, sRefOrig, bLockedRot, dMinSheetWidth)
-- elimino eventuali info
EgtSetInfo( nPartId, "NestOnEdge", 0)
EgtSetInfo( nPartId, "NestOnAngle", 0)
EgtSetInfo( nPartId, "OnlyOnRefSide", 0)
local nAngle
local nRotate = 0
local bOptimal
local bManual = false
local bOnly180Rot = EgtGetInfo( nPartId, "HasGrainDirection", 'b') or false
local b3Part = EgtGetBBoxGlob( nPartId, GDB_BB.STANDARD)
-- fori
local DrillClassif, DrillClassif2 = ClassifyDrillsOnLateralFaces( nPartId, dMinSheetWidth)
local bDrill = false
local bDrillOpen = false
local bLongDrill = false
if DrillClassif then
bDrill = true
bDrillOpen = not DrillClassif.bClosed
bLongDrill = DrillClassif.bLong
if DrillClassif.bOnlyOnRef then
EgtSetInfo( nPartId, "OnlyOnRefSide", 1)
end
end
-- oriento il pezzo in base al foro
if bDrill and not bLockedRot then
local RotationAngles
if sRefOrig == 'TL' or sRefOrig == 'TR' then
RotationAngles = { F = 180, B = 0, L = 270, R = 90}
else
RotationAngles = { F = 0, B = 180, L = 90, R = 270}
end
-- se rotazione è libera
if not bOnly180Rot then
EgtRotate( nPartId, b3Part:getCenter(), Z_AX(), RotationAngles[DrillClassif.sCase], GDB_RT.GLOB)
nRotate = nRotate + RotationAngles[DrillClassif.sCase]
-- verifico se la rotazione è valida
local nBoxLayerId = EgtGetFirstNameInGroup( nPartId, "Box")
local nBoxId = EgtGetFirstNameInGroup( nBoxLayerId, "Box")
local b3Part = EgtGetBBoxGlob(nBoxId, GDB_BB.STANDARD)
-- b3Part = EgtGetBBoxGlob( nPartId, GDB_BB.STANDARD)
local bIsValidRotation = b3Part:getDimX() < RawPart.Len - 2 * NEST.KERF + GEO.EPS_SMALL and b3Part:getDimY() < RawPart.Width - 2 * NEST.KERF + GEO.EPS_SMALL
if not bIsValidRotation then
-- ritorno nella posizione originaria
EgtRotate( nPartId, b3Part:getCenter(), Z_AX(), - RotationAngles[DrillClassif.sCase], GDB_RT.GLOB)
nRotate = nRotate - RotationAngles[DrillClassif.sCase]
-- se ho un'altra posizione possibile ruoto in quella
if DrillClassif2 then
EgtRotate( nPartId, b3Part:getCenter(), Z_AX(), RotationAngles[DrillClassif2.sCase], GDB_RT.GLOB)
nRotate = nRotate + RotationAngles[DrillClassif2.sCase]
bDrillOpen = not DrillClassif2.bClosed
bLongDrill = DrillClassif2.bLong
if DrillClassif2.bOnlyOnRef then
EgtSetInfo( nPartId, "OnlyOnRefSide", 1)
end
else
-- dimentico di avere il foro
bDrill = false
end
end
-- se posso ruotare solo di 180° per venatura
else
if RotationAngles[DrillClassif.sCase] == 0 or RotationAngles[DrillClassif.sCase] == 180 then
EgtRotate( nPartId, b3Part:getCenter(), Z_AX(), RotationAngles[DrillClassif.sCase], GDB_RT.GLOB)
nRotate = nRotate + RotationAngles[DrillClassif.sCase]
else
-- vedo se ho un'altra posizione possibile
if DrillClassif2 and ( RotationAngles[DrillClassif2.sCase] == 0 or RotationAngles[DrillClassif2.sCase] == 180) then
EgtRotate( nPartId, b3Part:getCenter(), Z_AX(), RotationAngles[DrillClassif2.sCase], GDB_RT.GLOB)
nRotate = nRotate + RotationAngles[DrillClassif2.sCase]
bDrillOpen = not DrillClassif2.bClosed
bLongDrill = DrillClassif2.bLong
if DrillClassif2.bOnlyOnRef then
EgtSetInfo( nPartId, "OnlyOnRefSide", 1)
end
else
-- dimentico di avere il foro
bDrill = false
end
end
end
end
-- se non ho venature e fori scelgo una posizione che non faccia cadere il pezzo
if not bDrill and not bOnly180Rot and not bLockedRot then
b3Part = EgtGetBBoxGlob( nPartId, GDB_BB.STANDARD)
local bIsValid = b3Part:getDimX() > s_dIntRulli
local bRotatedIsValid = b3Part:getDimY() > s_dIntRulli
if not bIsValid and not bRotatedIsValid then
EgtSetInfo( nPartId, "REDUCECUT", 1)
elseif not bIsValid or not bRotatedIsValid then
bOnly180Rot = true
EgtSetInfo( nPartId, "NestStepRot", 180)
end
if not bIsValid and bRotatedIsValid then
EgtRotate( nPartId, b3Part:getCenter(), Z_AX(), 90, GDB_RT.GLOB)
nRotate = nRotate + 90
end
end
-- lap joints
local ResLapJoints = ClassifyLapJointsFromBottom( nPartId)
b3Part = EgtGetBBoxGlob( nPartId, GDB_BB.STANDARD)
local bAdd = true
if ResLapJoints.Nbr > 0 and bLockedRot then
b3Part = EgtGetBBoxGlob( nPartId, GDB_BB.STANDARD)
if b3Part:getDimX() > s_dIntRulli then
EgtSetInfo( nPartId, "REDUCECUT", 1)
end
local PartAngleClassification = { PartId = tostring( nPartId), Angle = 100, nRotate = 0, bDrill = true, bLongDrill = true}
return PartAngleClassification
end
-- se anche fori oppure possibile solo rotazione di 180° per non far cadere il pezzo
if bDrill or bOnly180Rot then
local bCanRotate = not bDrill or ( bDrill and bDrillOpen)
if ResLapJoints.Nbr == 0 then
nAngle = 0
if not bDrill then bAdd = false end
elseif ResLapJoints.Nbr == 1 then
if (( sRefOrig == 'TL' or sRefOrig == 'TR') and ResLapJoints.sCase == 'B' ) or
(( sRefOrig == 'BL' or sRefOrig == 'BR') and ResLapJoints.sCase == 'F' ) then
nAngle = 20
elseif (( sRefOrig == 'TL' or sRefOrig == 'TR') and ResLapJoints.sCase == 'F' ) or
(( sRefOrig == 'BL' or sRefOrig == 'BR') and ResLapJoints.sCase == 'B' ) then
nAngle, nRotate2 = RotateOptimalCaseDrill( nPartId, bCanRotate, 20, 100)
nRotate = nRotate + nRotate2
elseif ResLapJoints.sCase == 'R' then
if bCanRotate then bManual = true end
if sRefOrig == 'TL' or sRefOrig == 'BL'then
nAngle, nRotate2 = RotateOptimalCaseDrill( nPartId, bCanRotate, 40, 0)
nRotate = nRotate + nRotate2
else
nAngle = 40
end
elseif ResLapJoints.sCase == 'L' then
if bCanRotate then bManual = true end
if sRefOrig == 'TR' or sRefOrig == 'BR' then
nAngle, nRotate2 = RotateOptimalCaseDrill( nPartId, bCanRotate, 40, 0)
nRotate = nRotate + nRotate2
else
nAngle = 40
end
end
elseif ResLapJoints.Nbr == 2 then
if ResLapJoints.bParall then
if ResLapJoints.sCase == 'F' then
nAngle = 100
else
nAngle = 80
end
else
if (( sRefOrig == 'TL' or sRefOrig == 'TR') and (ResLapJoints.sCase == 'BL' or ResLapJoints.sCase == 'BR')) or
(( sRefOrig == 'BL' or sRefOrig == 'BR') and (ResLapJoints.sCase == 'FL' or ResLapJoints.sCase == 'FR')) then
nAngle = 40
else
nAngle, nRotate2 = RotateOptimalCaseDrill( nPartId, bCanRotate, 40, 100)
nRotate = nRotate + nRotate2
end
end
elseif ResLapJoints.Nbr == 3 then
if (( sRefOrig == 'TL' or sRefOrig == 'TR') and ResLapJoints.sCase == 'F' ) or
(( sRefOrig == 'BL' or sRefOrig == 'BR') and ResLapJoints.sCase == 'B' ) then
nAngle = 80
elseif (( sRefOrig == 'TL' or sRefOrig == 'TR') and ResLapJoints.sCase == 'B' ) or
(( sRefOrig == 'BL' or sRefOrig == 'BR') and ResLapJoints.sCase == 'F' ) then
nAngle, nRotate2 = RotateOptimalCaseDrill( nPartId, bCanRotate, 80, 100)
nRotate = nRotate + nRotate2
elseif ResLapJoints.sCase == 'R' then
if bCanRotate then bManual = true end
if sRefOrig == 'TR' or sRefOrig == 'BR' then
nAngle, nRotate2 = RotateOptimalCaseDrill( nPartId, bCanRotate, 100, 100)
nRotate = nRotate + nRotate2
end
nAngle = 100
elseif ResLapJoints.sCase == 'L' then
if bCanRotate then bManual = true end
if sRefOrig == 'TL' or sRefOrig == 'BL' then
nAngle, nRotate2 = RotateOptimalCaseDrill( nPartId, bCanRotate, 100, 100)
nRotate = nRotate + nRotate2
end
nAngle = 100
end
elseif ResLapJoints.Nbr == 4 then
nAngle = 100
end
-- no fori
else
if ResLapJoints.Nbr == 0 then
bAdd = false
elseif ResLapJoints.Nbr == 1 then
if sRefOrig == 'TL' or sRefOrig == 'TR' then
RotationAngles = { F = 180, B = 0, R = 90, L = 270}
elseif sRefOrig == 'BL'or sRefOrig == 'BR' then
RotationAngles = { F = 0, B = 180, R = 270, L = 90}
end
local nAngleValidRot = EgtIf( sRefOrig == 'TL' or sRefOrig == 'BR', 90, 270)
nAngle, nRotate2, bOptimal = RotateOptimalCase( nPartId, RotationAngles[ResLapJoints.sCase], nAngleValidRot, RawPart, 20, 40)
nRotate = nRotate + nRotate2
if not bOptimal then bManual = true end
elseif ResLapJoints.Nbr == 2 then
if ResLapJoints.bParall then
-- se lap joints su lati paralleli
RotationAngles = { F = 90, R = 0}
nAngle, nRotate2 = RotateOptimalCase( nPartId, RotationAngles[ResLapJoints.sCase], 90, RawPart, 80, 100)
nRotate = nRotate + nRotate2
else
-- se lap joints su lati adiacenti
if sRefOrig == 'TR' then
RotationAngles = { FR = 90, BR = 0, BL = 270, FL = 180}
elseif sRefOrig == 'TL' then
RotationAngles = { FR = 180, BR = 90, BL = 0, FL = 270}
elseif sRefOrig == 'BR' then
RotationAngles = { FR = 0, BR = 270, BL = 180, FL = 90}
elseif sRefOrig == 'BL' then
RotationAngles = { FR = 270, BR = 180, BL = 90, FL = 0}
end
local nAngleValidRot = EgtIf( sRefOrig == 'TL' or sRefOrig == 'BR', 270, 90)
nAngle, nRotate2, bOptimal = RotateOptimalCase( nPartId, RotationAngles[ResLapJoints.sCase], nAngleValidRot, RawPart, 40, 40)
nRotate = nRotate + nRotate2
local b3Part = EgtGetBBoxGlob( nPartId, GDB_BB.STANDARD)
local bCanRotate = b3Part:getDimX() < RawPart.Width
if bOptimal and bCanRotate then bManual = true end
end
elseif ResLapJoints.Nbr == 3 then
if sRefOrig == 'TL' or sRefOrig == 'TR' then
RotationAngles = { F = 0, B = 180, R = 270, L = 90}
elseif sRefOrig == 'BL' or sRefOrig == 'BR' then
RotationAngles = { F = 180, B = 0, R = 90, L = 270}
end
local nAngleValidRot = EgtIf( sRefOrig == 'TL' or sRefOrig == 'BR', 90, 270)
nAngle, nRotate2, bOptimal = RotateOptimalCase( nPartId, RotationAngles[ResLapJoints.sCase], nAngleValidRot, RawPart, 80, 100)
nRotate = nRotate + nRotate2
if not bOptimal then bManual = true end
elseif ResLapJoints.Nbr == 4 then
nAngle, nRotate2 = RotateOptimalCase( nPartId, 0, 90, RawPart, 100, 100)
nRotate = nRotate + nRotate2
end
end
-- aggiorno le info di rotazione del pezzo
if nRotate >= 360 then
nRotate = nRotate - 360
end
if nRotate > 0 then
local bPartFlip = ( ( EgtGetInfo( nPartId, "INVERTED", 'i') or 0) == 180)
local nPartRot = EgtGetInfo( nPartId, "ROTATED", 'i') or 0
local nTotRot = nPartRot - EgtIf( bPartFlip, -nRotate, nRotate)
nTotRot = EgtIf( nTotRot < 0, nTotRot + 360, nTotRot)
EgtSetInfo( nPartId, "ROTATED", nTotRot)
EgtSetInfo( nPartId, "MODIFIEDFORNEST", 1)
end
if not bAdd then
return
end
local PartAngleClassification = { PartId = tostring( nPartId), Angle = nAngle, nRotate = nRotate, bDrill = bDrill, bLongDrill = bLongDrill, bManual = bManual}
local bCanBeOnOtherEdge = not bDrill or ( bDrill and RawPart.Width > s_dMinRawYHorDrill - GEO.EPS_SMALL)
if bOnly180Rot then
if bCanBeOnOtherEdge then
EgtSetInfo( nPartId, "NestAllowRot", 1)
EgtSetInfo( nPartId, "NestStepRot", 180)
else
EgtSetInfo( nPartId, "NestAllowRot", 0)
EgtSetInfo( nPartId, "NestStepRot", 0)
end
end
-- verifico se il pezzo cade (caso di foro)
b3Part = EgtGetBBoxGlob( nPartId, GDB_BB.STANDARD)
if b3Part:getDimX() > s_dIntRulli then
EgtSetInfo( nPartId, "REDUCECUT", 1)
end
return PartAngleClassification
end
------------------------------------------------------------------
local function ComputeRestrictedZones( RawParts)
local dTotArea = 0
-- area totale dei pezzi
for nPartId, nCount in pairs( PART) do
local b3Part = EgtGetBBoxGlob( nPartId, GDB_BB.STANDARD)
local dPartArea = b3Part:getDimX() * b3Part:getDimY()
dTotArea = dTotArea + dPartArea * nCount
end
-- stimo il numero di angoli disponibili
local vSheetNbrEstimate = {}
local nSheetNbrEstimate = 0
local nSheetNbrCorrection = - 2
local nAnglesNbrEstimate = 0
local nAngelsNbrCorrection = 0
local vRawDistrib = {}
if #RawParts == 1 then
vRawDistrib = {1}
elseif #RawParts == 2 then
vRawDistrib = {0.7, 0.3}
else
for nInd = 1, #RawParts do
table.insert( vRawDistrib, 1 / #RawParts)
end
end
local dMaxSheetWidth = -100
local nMaxSheet = 1
local dMinSheetWidth = WD.MAX_WIDTH
for nInd = 1, #RawParts do
local dSheetArea = RawParts[nInd].Len * RawParts[nInd].Width
if RawParts[nInd].Width > dMaxSheetWidth + GEO.EPS_SMALL then
dMaxSheetWidth = RawParts[nInd].Width
nMaxSheet = nInd
elseif abs( RawParts[nInd].Width - dMaxSheetWidth) < GEO.EPS_SMALL then
if RawParts[nInd].Len > RawParts[nMaxSheet].Len then
nMaxSheet = nInd
end
end
if RawParts[nInd].Width < dMinSheetWidth then
dMinSheetWidth = RawParts[nInd].Width
end
vSheetNbrEstimate[nInd] = min( ceil( dTotArea * vRawDistrib[nInd] / dSheetArea) + nSheetNbrCorrection, RawParts[nInd].Qty)
if vSheetNbrEstimate[nInd] <= 0 then
vSheetNbrEstimate[nInd] = min( RawParts[nInd].Qty, 1)
end
nSheetNbrEstimate = nSheetNbrEstimate + vSheetNbrEstimate[nInd]
nAnglesNbrEstimate = nAnglesNbrEstimate + vSheetNbrEstimate[nInd] * 2
end
nAnglesNbrEstimate = nAnglesNbrEstimate + nAngelsNbrCorrection
-- classificazione dei pezzi in base alla loro necessità di stare negli angoli
local nTotParts = 0
for _ in pairs( PART) do nTotParts = nTotParts + 1 end
local nPartIndex = 0
local AngleClassification = {}
for nPartId, nCount in pairs( PART) do
nPartIndex = nPartIndex + 1
local bManualRot = EgtGetInfo( nPartId, "MANUALROT", 'b')
local PartClassif = ClassifyAngles(tonumber(nPartId), RawParts[nMaxSheet], s_sOrigCorner, bManualRot, dMinSheetWidth)
if PartClassif then
for nI = 1, nCount do
local newTab = {PartId = PartClassif.PartId, Angle = PartClassif.Angle, nRotate = PartClassif.nRotate, bDrill = PartClassif.bDrill, bLongDrill = PartClassif.bLongDrill, bManual = PartClassif.bManual}
table.insert( AngleClassification, newTab)
end
end
if EgtProcessEvents( nPartIndex / nTotParts * 100, 0) == 1 then
return false
end
end
table.sort( AngleClassification, function(a, b) return a.Angle > b.Angle end)
local vManuallyDone = {}
local vPartsManuallyDone = {}
for nInd = 1, #vSheetNbrEstimate do
for nInd2 = 1, vSheetNbrEstimate[nInd] do
table.insert( vManuallyDone, { RawPartId = nInd, Done = 0, Parts = {}})
end
end
local nSheetNbr = #vManuallyDone
local vFilledSheets = {}
for nInd = 1, #vSheetNbrEstimate do
for nInd2 = 1, vSheetNbrEstimate[nInd] do
table.insert( vFilledSheets, { Width = RawParts[nInd].Width, OrigWidth = RawParts[nInd].Width})
end
end
for nInd = 1, #AngleClassification do
if AngleClassification[nInd].Angle >= NEST.MIN_ANGLE_PNT and AngleClassification[nInd].Angle > 0 then
-- verifico di avere ancora angoli a disposizione secondo la stima dei grezzi
local bFound = false
local nBoxLayerId = EgtGetFirstNameInGroup( AngleClassification[nInd].PartId, "Box")
local nBoxId = EgtGetFirstNameInGroup( nBoxLayerId, "Box")
local b3Part = EgtGetBBoxGlob(nBoxId, GDB_BB.STANDARD)
local dPartWidth = b3Part:getDimY() + NEST.KERF
for nInd2 = 1, #vFilledSheets do
if dPartWidth < vFilledSheets[nInd2].Width then
-- verifico se il grezzo aveva già un pezzo in un angolo
if abs( vFilledSheets[nInd2].Width - vFilledSheets[nInd2].OrigWidth) < GEO.EPS_SMALL then
vFilledSheets[nInd2].Width = vFilledSheets[nInd2].Width - dPartWidth - s_dSideMillDiamDown
else
-- se il grezzo aveva già un pezzo nell'angolo, dopo il pezzo corrente non ne posso mettere altri
vFilledSheets[nInd2].Width = 0
end
bFound = true
break
end
end
-- se ho ancora angoli a disposizione oppure il pezzo deve stare necessariamente sull'angolo per essere lavorato
if bFound or AngleClassification[nInd].Angle == 100 then
-- verifico se va nestato manualmente
if AngleClassification[nInd].bManual then
-- trovo il punto della lista dove inserirlo
local nIdx = -1
local bOnOppositeSide = false
for nInd2 = 1, #vManuallyDone do
-- verifico se il pezzo può stare sull'altro angolo
local bOnlyOnRef = EgtGetInfo( AngleClassification[nInd].PartId, "OnlyOnRefSide", 'b')
local bCanBeOnOtherAngle = not bOnlyOnRef and
( not AngleClassification[nInd].bDrill or
( AngleClassification[nInd].bDrill and not AngleClassification[nInd].bLongDrill and
RawParts[vManuallyDone[nInd2].RawPartId].Width > s_dMinRawYHorDrill - GEO.EPS_SMALL))
if #(vManuallyDone[nInd2].Parts) == 0 then
-- verifico che il pezzo stia in questo grezzo
local b3Part = EgtGetBBoxGlob( AngleClassification[nInd].PartId, GDB_BB.STANDARD)
if b3Part:getDimX() < RawParts[vManuallyDone[nInd2].RawPartId].Len and b3Part:getDimY() < RawParts[vManuallyDone[nInd2].RawPartId].Width then
nIdx = nInd2
break
end
elseif #(vManuallyDone[nInd2].Parts) == 1 and bCanBeOnOtherAngle then
-- verifico se il pezzo già posizionato nell'angolo non ha fori lunghi
if not vManuallyDone[nInd2].Parts[1].bLongDrill then
-- oriento il pezzo in modo ottimale per andare su quell'angolo
local sRefOrig
if s_sOrigCorner == 'TL' then sRefOrig = 'BL' end
if s_sOrigCorner == 'BL' then sRefOrig = 'TL' end
if s_sOrigCorner == 'TR' then sRefOrig = 'BR' end
if s_sOrigCorner == 'BR' then sRefOrig = 'TR' end
local bManTmp
local res = ClassifyAngles( AngleClassification[nInd].PartId, RawParts[vManuallyDone[nInd2].RawPartId], sRefOrig, bManTmp, dMinSheetWidth)
-- verifico sia compatibile con pezzo già inserito
local b3OtherPart = EgtGetBBoxGlob( vManuallyDone[nInd2].Parts[1].Id, GDB_BB.STANDARD)
local b3Part = EgtGetBBoxGlob( AngleClassification[nInd].PartId, GDB_BB.STANDARD)
local dExtra = 2 * NEST.KERF + s_dSideMillDiamDown + 1
-- se è compatibile assegno questa rotazione al pezzo
if b3Part:getDimY() + b3OtherPart:getDimY() + dExtra < RawParts[vManuallyDone[nInd2].RawPartId].Width then
nIdx = nInd2
bOnOppositeSide = true
-- aggiorno le info di rotazione
if res.nRotate > 0 then
local bPartFlip = ( ( EgtGetInfo( AngleClassification[nInd].PartId, "INVERTED", 'i') or 0) == 180)
local nPartRot = EgtGetInfo( AngleClassification[nInd].PartId, "ROTATED", 'i') or 0
local nTotRot = nPartRot - EgtIf( bPartFlip, -res.nRotate, res.nRotate)
nTotRot = EgtIf( nTotRot < 0, nTotRot + 360, nTotRot)
EgtSetInfo( AngleClassification[nInd].PartId, "ROTATED", nTotRot)
EgtSetInfo( AngleClassification[nInd].PartId, "MODIFIEDFORNEST", 1)
end
break
end
-- altrimenti lo riporto nella sua posizione originaria
EgtRotate( AngleClassification[nInd].PartId, b3Part:getCenter(), Z_AX(), - res.nRotate, GDB_RT.GLOB)
end
end
end
-- nesto il pezzo a mano
if nIdx ~= -1 then
-- aree di lavorazione
local nToolOutlineIds = ComputeToolOutlines( AngleClassification[nInd].PartId)
local sInfo = ""
for nInd = 1, #nToolOutlineIds do
sInfo = sInfo .. tostring(nToolOutlineIds[nInd]) .. ","
end
-- salvo tra le info del pezzo gli id delle sue aree di lavorazione
if sInfo ~= "" then
EgtSetInfo( AngleClassification[nInd].PartId, "ToolOutlines", sInfo)
end
-- calcolo defect corrispondente al pezzo
local PartTab = CreateDefectOnAngle( AngleClassification[nInd].PartId, RawParts[vManuallyDone[nIdx].RawPartId], AngleClassification[nInd].bLongDrill, bOnOppositeSide)
PartTab.bLongDrill = AngleClassification[nInd].bLongDrill
table.insert( vManuallyDone[nIdx].Parts, PartTab)
table.insert( vPartsManuallyDone, tonumber( AngleClassification[nInd].PartId))
else
-- aggiungo info per il nesting per ricordare che andrà su angolo
EgtSetInfo( AngleClassification[nInd].PartId, "NestOnAngle", 1)
end
else
-- se non va nestato manualmente segno info per nesting
EgtSetInfo( AngleClassification[nInd].PartId, "NestOnAngle", 1)
end
else
-- se non ho più angoli a disposizione lo metto sul lato
EgtSetInfo(AngleClassification[nInd].PartId, "NestOnEdge", 1)
end
else
EgtSetInfo(AngleClassification[nInd].PartId, "NestOnEdge", 1)
end
end
local nInd = 1
while nInd <= #vManuallyDone do
if #(vManuallyDone[nInd].Parts) == 0 then
table.remove( vManuallyDone, nInd)
else
nInd = nInd + 1
end
end
return vManuallyDone, vPartsManuallyDone
end
------------------------------------------------------------------
-- Funzione che sposta e aggiunge pezzi per nesting
local function AddRawParts(RawParts, vDoneManually)
local OUTLINE = "Outline"
for nIndex = 1, #RawParts do
RawParts[nIndex].PartId = {}
-- pannelli con pezzi inseriti manualmente
local nTotSheetWithDefects = 0
for nInd = 1, #vDoneManually do
if vDoneManually[nInd].RawPartId == nIndex then
-- creo pannello del materiale
local SheetPartId = EgtGroup(GDB_ID.ROOT)
table.insert( 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 + 0.1, RawParts[nIndex].Width + 0.1, 0), GDB_RT.GLOB)
EgtSetName(SheetOutlineId, OUTLINE)
-- creo foglio per nesting
EgtAutoNestAddSheet( SheetPartId, SheetOutlineId, NEST.KERF, 0, 1)
-- aggiungo defects
for nInd2 = 1, #(vDoneManually[nInd].Parts) do
EgtAutoNestAddDefectToSheet( SheetPartId, vDoneManually[nInd].Parts[nInd2].DefectId)
end
vDoneManually[nInd].SheetId = SheetPartId
nTotSheetWithDefects = nTotSheetWithDefects + 1
end
end
-- pannelli senza pezzi inseriti manualmente
local SheetPartId = EgtGroup(GDB_ID.ROOT)
table.insert( 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 + 0.1, RawParts[nIndex].Width + 0.1, 0), GDB_RT.GLOB)
-- EgtModifyCurveThickness(SheetOutlineId, -Material.T_mm)
EgtSetName(SheetOutlineId, OUTLINE)
-- creo foglio per nesting
EgtAutoNestAddSheet( SheetPartId, SheetOutlineId, NEST.KERF, 1, RawParts[nIndex].Qty - nTotSheetWithDefects)
-- EgtAutoNestAddSheet( SheetId, OutlineId, dKerf, nPriority, nCount)
end
end
------------------------------------------------------------------
local function AddParts(RawParts, vPartsDoneManually)
-- cerco la width massima dei grezzi
local dRawMaxWidth = - 100
for nIndex = 1, #RawParts do
if RawParts[nIndex].Width > dRawMaxWidth then
dRawMaxWidth = RawParts[nIndex].Width
end
end
-- valori correttivi per vincoli StripX e StripY
local dStripYCorr = GEO.EPS_SMALL
local dStripXCorr = GEO.EPS_SMALL
if NEST.CORNER == NST_CORNER.TL or NEST.CORNER == NST_CORNER.TR then
dStripYCorr = 0.1 - GEO.EPS_SMALL
end
if NEST.CORNER == NST_CORNER.BR or NEST.CORNER == NST_CORNER.TR then
dStripXCorr = 0.1 - GEO.EPS_SMALL
end
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 repeat
-- conto quanti pezzi di questo tipo sono già stati posizionati a mano
nManuallyDone = 0
for nJ = 1, #vPartsDoneManually do
if vPartsDoneManually[nJ] == tonumber( nPartId) then
nManuallyDone = nManuallyDone + 1
end
end
if nManuallyDone == nCount then
-- se tutti posizionati passo al pezzo successivo
break
else
-- posiziono con il nesting solo quelli mancanti
nCount = nCount - nManuallyDone
end
nPartIndex = nPartIndex + 1
-- calcolo bbox pezzo per rotazioni
local b3Part = EgtGetBBoxGlob( nPartId, GDB_BB.STANDARD)
-- recupero eventuali stati di flip e rotazione dalle info del pezzo
local bFlipNest = true
local bFlip = false
local bRotNest = true
local nStepRotNest = 90
local nRotate = 0
-- flip
local bManualFlip = EgtGetInfo( nPartId, "MANUALFLIP", 'b')
if bManualFlip then
bFlipNest = false
elseif EgtExistsInfo( nPartId, "NestFlip") then
bFlipNest = EgtGetInfo( nPartId, "NestAllowFlip", 'b')
bFlip = EgtGetInfo( nPartId, "NestFlip", 'b')
end
-- rotation
local bManualRot = EgtGetInfo( nPartId, "MANUALROT", 'b')
if bManualRot then
bRotNest = false
elseif EgtExistsInfo( nPartId, "NestRot") then
nStepRotNest = EgtGetInfo( nPartId, "NestStepRot", 'i')
bRotNest = EgtGetInfo( nPartId, "NestAllowRot", 'b')
-- verifico se rotazione è valida (pezzo è contenuto nel grezzo)
local bValidRotationInRaw = b3Part:getDimX() < RawParts[1].Len - 2 * NEST.KERF + GEO.EPS_SMALL and b3Part:getDimY() < dRawMaxWidth - 2 * NEST.KERF + GEO.EPS_SMALL
if not bValidRotationInRaw then
bRotNest = true
nStepRotNest = 90
end
end
-- recupero vecchio contorno se già presente
local nOutlineLayer = EgtGetFirstNameInGroup(nPartId, "Outline")
local nOldOutline = EgtGetFirstNameInGroup(nOutlineLayer, 'ON_TMP')
local nOutline, nCnt
-- se l'outline non è stato calcolato oppure il pezzo è stato modificato, lo ricalcolo
local bPartIsModified = EgtGetInfo( nPartId, "MODIFIEDFORNEST", 'b')
if not nOldOutline or bPartIsModified then
-- elimino il vecchio contorno se pesente
while ( nOldOutline) do
EgtErase(nOldOutline or GDB_ID.NULL)
nOldOutline = EgtGetFirstNameInGroup( nOutlineLayer, 'ON_TMP')
end
-- 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
nOutline, nCnt = EgtGetSurfTmSilhouette( SolidId, Z_AX(), 10, nOutlineLayer, GDB_RT.GLOB)
EgtBeamShowSolid( nPartId, false)
for nInd = 0, nCnt - 1 do
EgtSetName( nOutline + nInd, 'ON_TMP')
EgtSetStatus( nOutline + nInd, 0)
end
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 vtCrvRefN = EgtCurveArea( nOutline)
for nInd = 1, nCnt - 1 do
local vtCrvN = EgtCurveArea( nOutline + nInd)
-- se trovo più loop esterni uso come contorno quello del box (quindi forzo nCurrOutline a nil)
if vtCrvN and vtCrvRefN and AreSameVectorApprox( vtCrvN, vtCrvRefN) then
nCurrOutline = nil
for nInd2 = 0, nCnt - 1 do
EgtErase( nOutline + nInd2)
end
nCnt = 1
break
end
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))
nCnt = 1
end
EgtSetName( nOutline, 'ON_TMP')
EgtSetStatus( nOutline, 0)
else
-- altrimenti uso l'outline già calcolato
nOutline = nOldOutline
-- recupero il valore di nCnt
local vOutlinesIds = EgtGetNameInGroup( nOutlineLayer, 'ON_TMP')
nCnt = #vOutlinesIds
end
-- calcolo aree lavorazione
local nToolOutlineIds = ComputeToolOutlines( nPartId)
if bFlipNest and #nToolOutlineIds > 0 then
bFlipNest = false
end
if nOutline then
-- aggiungo pezzo al nesting
EgtAutoNestAddPart( nPartId, nOutline, bFlipNest, bRotNest, nStepRotNest, 0, nCount)
-- EgtAutoNestAddPart( PartId, OutlineId, bCanFlip, bCanRotate, dRotStep, nPriority, nCount)
end
-- aggiungo finestre
for nInd = 1, nCnt - 1 do
local _, _, dArea = EgtCurveArea( nOutline + nInd)
if dArea and dArea > s_dNestHoleMinArea then
EgtModifyCurveExtrusion( nOutline + nInd, Z_AX(), GDB_RT.GLOB)
EgtAutoNestAddHoleToPart( nPartId, nOutline + nInd)
end
end
-- aggiungo aree di lavorazione del pezzo
local sInfo = ""
for nInd = 1, #nToolOutlineIds do
EgtAutoNestAddToolOutlineToPart( nPartId, nToolOutlineIds[nInd])
sInfo = sInfo .. tostring(nToolOutlineIds[nInd]) .. ","
end
-- salvo tra le info del pezzo gli id delle sue aree di lavorazione
if sInfo ~= "" then
EgtSetInfo( nPartId, "ToolOutlines", sInfo)
end
-- Eventuali vincoli StripX e StripY
local bOnEdge = EgtGetInfo(nPartId, "NestOnEdge", 'b')
local bOnAngle = EgtGetInfo(nPartId, "NestOnAngle", 'b')
if bOnEdge or bOnAngle then
local nBoxLayerId = EgtGetFirstNameInGroup( nPartId, "Box")
local nBoxId = EgtGetFirstNameInGroup( nBoxLayerId, "Box")
local b3Part = EgtGetBBoxGlob(nBoxId, GDB_BB.STANDARD)
-- punto di riferimento sul pezzo
local ptRef
local dval = 10
if ( s_sOrigCorner == 'TL' or s_sOrigCorner == 'TR') then
ptRef = Point3d( b3Part:getMax():getX() - b3Part:getDimX() / 2, b3Part:getMax():getY() - dval, 0)
else
ptRef = Point3d( b3Part:getMin():getX() + b3Part:getDimX() / 2, b3Part:getMin():getY() + dval, 0)
end
-- vincolo StripY
local bOnlyOnRefSide = EgtGetInfo( nPartId, "OnlyOnRefSide", 'b')
if bOnlyOnRefSide then
if s_sOrigCorner == 'BL' or s_sOrigCorner == 'BR' then
EgtAutoNestSetStripYconstraintToPart( nPartId, ptRef, NEST.KERF + dval + dStripYCorr, 100000)
else
EgtAutoNestSetStripYconstraintToPart( nPartId, ptRef, - 1000, dRawMaxWidth + 1000 - ( NEST.KERF + dval - dStripYCorr))
end
else
EgtAutoNestSetStripYconstraintToPart( nPartId, ptRef, NEST.KERF + dval + dStripYCorr, dRawMaxWidth - 2 * ( NEST.KERF + dval))
end
-- se sull'angolo aggiungo anche vincolo StripX
if bOnAngle then
if s_sOrigCorner == 'TL' or s_sOrigCorner == 'BL' then
EgtAutoNestSetStripXconstraintToPart( nPartId, ptRef, NEST.KERF + b3Part:getDimX() / 2 + dStripXCorr, 100000)
else
EgtAutoNestSetStripXconstraintToPart( nPartId, ptRef, -100, RawParts[1].Len + 100 - NEST.KERF - b3Part:getDimX() / 2 + dStripXCorr)
end
end
end
-- verifico se anullato nesting
if EgtProcessEvents( 100 + ( nPartIndex / nTotParts * 100), 0) == 1 then
return false
end
until true
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()
-- modalità nesting utile per cabinet: un grezzo per ogni pezzo, pezzo centrato nel grezzo. Il grezzo non viene preso da magazzino ma creato ad hoc, con un dato sovramateriale.
-- il numero del MachGroup deve coincidere con il PDN del pezzo originale
if NEST.FLAG ~= 11 and WD.ENABLE_SIMPLE_NESTING then
-- sovramateriale richiesto
local dOverMaterial = max( 0, NEST.KERF or 2)
-- inizializzazione parametri per creazione grezzo tramite BatchProcessNew
_G.WALL = {}
WALL.FILE = NEST.FILE
WALL.MACHINE = NEST.MACHINE
WALL.BASEDIR = NEST.BASEDIR
WALL.FLAG = 6 -- CREATE_PANEL
WALL.NESTING_REF = 'BL'
-- si ricrea la lista pezzi ordinata
local PartList = {}
local nPartCounter = 0
for nPartId, nCount in pairs( PART) do
nPartCounter = nPartCounter + 1
PartList[nPartCounter] = {}
PartList[nPartCounter].nId = nPartId
PartList[nPartCounter].nCount = nCount
PartList[nPartCounter].nPdn = EgtGetInfo( nPartId, "PDN", 'i')
PartList[nPartCounter].bAddCounterToNaming = false
-- se presente un pezzo con multipli il PDN sarà seguito da un contatore
if nCount > 1 then
PartList[nPartCounter].bAddCounterToNaming = true
end
end
-- si riordina in base al PDN
table.sort( PartList, function(a, b) return tonumber( a.nPdn) < tonumber( b.nPdn) end)
-- per ogni singolo pezzo si chiama la fliprot per avere la migliore orientazione
-- si creano duplo e machgroup e si settano le note opportune per poi creare i grezzi richiamando la BatchProcessNew (flag 6)
for i = 1, #PartList do
local nPartId = PartList[i].nId
local nPartCount = PartList[i].nCount
local nPdn = PartList[i].nPdn
local bAddCounterToNaming = PartList[i].bAddCounterToNaming
-- si ruotano e invertono i pezzi per avere la migliore posizione di lavorazione
_G.NFAR = {}
NFAR.ERR = 0
NFAR.MSG = ''
NFAR.PARTID = nPartId
NFAR.BASEDIR = NEST.BASEDIR
dofile( NEST.BASEDIR .. "\\NestFlipAndRotate.lua")
-- informazioni dalla parte originale
-- box e relative dimensioni
local nBoxLayerId = EgtGetFirstNameInGroup( nPartId, "Box")
local nBoxId = EgtGetFirstNameInGroup( nBoxLayerId, "Box")
local b3Part = EgtGetBBoxGlob( nBoxId, GDB_BB.STANDARD)
-- inversione e rotazione
local nPartFlip = EgtGetInfo( nPartId, "INVERTED", 'i') or 0
local nPartRotation = EgtGetInfo( nPartId, "ROTATED", 'i') or 0
-- dimensioni grezzo, considerando sovramateriale
local dRawLength = b3Part:getDimX() + 2 * dOverMaterial
local dRawWidth = b3Part:getDimY() + 2 * dOverMaterial
for j = 1, nPartCount do
-- creazione gruppo di lavoro
local sMachGroupName = nPdn
if bAddCounterToNaming then
sMachGroupName = nPdn .. '_' .. string.format("%02d", j)
end
local nMachGroupId = EgtAddMachGroup( sMachGroupName)
if not nMachGroupId then
EgtOutLog( "Errore: MachGroup " .. nPdn .. " già presente")
EgtOutBox( 'Error : MachGroup ' .. nPdn .. ' already existing', 'Nesting failed')
NEST.ERR = 2
return
end
-- settaggio note in gruppo di lavoro
EgtSetInfo( nMachGroupId, "PANELLEN", dRawLength)
EgtSetInfo( nMachGroupId, "PANELWIDTH", dRawWidth)
EgtSetInfo( nMachGroupId, "MATERIAL", NEST.MATERIAL)
EgtSetInfo( nMachGroupId, "PRODID", NEST.PRODID)
EgtSetInfo( nMachGroupId, "PATTID", nMachGroupId)
-- creazione duplo
local nPartDuploId = EgtDuploNew( nPartId)
-- settaggio note in duplo
EgtSetInfo( nMachGroupId, "PART" .. 1, nPartDuploId .. "," .. EgtNumToString( dOverMaterial) .. "," .. EgtNumToString( dOverMaterial) .. "," .. 0 .."," .. 0)
EgtSetInfo( nPartDuploId, "POSY", dOverMaterial)
EgtSetInfo( nPartDuploId, "POSX", dOverMaterial)
EgtSetInfo( nPartDuploId, "FLIP", nPartFlip)
EgtSetInfo( nPartDuploId, "ROT", nPartRotation)
-- creazione grezzi tramite BatchProcessNew
EgtSetCurrMachGroup( nMachGroupId)
EgtSetInfo( nMachGroupId, "UPDATEUI", 1)
dofile( NEST.BASEDIR .. "\\BatchProcessNew.lua")
end
end
EgtProcessEvents( 200 + 100, 0)
EgtResetCurrMachGroup()
EgtOutLog( ' +++ NestProcess completed')
EgtOutLog( ' +++ Generating Cutting List')
return
elseif NEST.FLAG == 11 then
local vCuttingListType = EgtSplitString( WD.PANELSAW_TYPE)
for i = 1, #vCuttingListType do
local sCuttingListType = vCuttingListType[i]
PanelSaw.GenerateCuttingList( sCuttingListType)
end
return
end
-- inizio nesting automatico
EgtAutoNestStart()
-- lista dei grezzi
local RawParts = {}
-- creo tabella dei grezzi
for sIndex, dLen in pairs( LEN) do
RawParts[tonumber(sIndex)] = { Len = dLen}
end
for sIndex, dWidth in pairs( WIDTH) do
RawParts[tonumber(sIndex)].Width = dWidth
end
for sIndex, nQty in pairs( QTY) do
RawParts[tonumber(sIndex)].Qty = nQty
end
for sIndex, sMaterial in pairs( MATERIAL) do
RawParts[tonumber(sIndex)].Material = sMaterial
end
--
local vDoneManually, vPartsDoneManually = ComputeRestrictedZones( RawParts)
-- creo grezzi e li aggiungo al nesting
AddRawParts(RawParts, vDoneManually)
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, vPartsDoneManually)
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( NEST.CORNER)
-- Report dei dati di nesting per debug
EgtAutoNestSetReportFile( EgtGetTempDir() .. '\\LastNest.json')
-- 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
local dXCorr = 0
local dYCorr = 0
if NEST.CORNER == NST_CORNER.TL then
dYCorr = - 0.1
elseif NEST.CORNER == NST_CORNER.TR then
dYCorr = - 0.1
dXCorr = - 0.1
elseif NEST.CORNER == NST_CORNER.BR then
dXCorr = - 0.1
end
-- se nesting andato bene
if bNestingOk then
-- disposizione sheet e parts
local SheetId = GDB_ID.NULL
local vtAdd = V_NULL()
local MachGroupList = {}
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
MachGroupList = {}
for MGIndex = 1, nType do
-- creo gruppo di lavorazione
local MachGroupName = NewMachGroupName()
local nMachGroup = EgtAddMachGroup(MachGroupName, sCurrMachName)
table.insert( MachGroupList, { MGId = nMachGroup})
for nIndex = 1, #RawParts do
for nInd2 = 1, #(RawParts[nIndex].PartId) do
if RawParts[nIndex].PartId[nInd2] == nId then
EgtSetInfo(nMachGroup, "PANELLEN", RawParts[nIndex].Len)
EgtSetInfo(nMachGroup, "PANELWIDTH", RawParts[nIndex].Width)
EgtSetInfo(nMachGroup, "MATERIAL", NEST.MATERIAL)
EgtSetInfo(nMachGroup, "AUTONEST", 1)
-- scrivo dati per variabili P di comunicazione con la macchina in gruppo di lavorazione
EgtSetInfo( nMachGroup, "PRODID", NEST.PRODID)
EgtSetInfo( nMachGroup, "PATTID", nMachGroup)
end
end
end
-- aggiungo pezzi nestati a mano
nPartCount = 0
for nInd = 1, #vDoneManually do
if vDoneManually[nInd].SheetId == nId then
vDoneManually[nInd].Done = 1
for nInd2 = 1, #(vDoneManually[nInd].Parts) do
nPartCount = nPartCount + 1
local nPartDuploId = EgtDuploNew( vDoneManually[nInd].Parts[nInd2].Id)
-- aggiungo le curve corrispondenti alle aree di lavorazione del pezzo
local sToolOutlines = EgtGetInfo( vDoneManually[nInd].Parts[nInd2].Id, "ToolOutlines", 's')
if sToolOutlines then
-- recupero o creo il gruppo per gli outlines
local nToolOutlinesGrp = EgtGetFirstNameInGroup( nPartDuploId, "ToolOutlines")
if not nToolOutlinesGrp then
nToolOutlinesGrp = EgtGroup( nPartDuploId)
EgtSetName( nToolOutlinesGrp, "ToolOutlines")
EgtSetStatus( nToolOutlinesGrp, GDB_ST.ON)
end
for str in string.gmatch(sToolOutlines, "([^"..",".."]+)") do
EgtCopyGlob( tonumber(str), nToolOutlinesGrp)
end
end
-- applico flip, rotazione e traslazione pezzo e box da nesting
EgtSetInfo( nMachGroup, "PART" .. nPartCount, nPartDuploId .. "," .. EgtNumToString( vDoneManually[nInd].Parts[nInd2].posX, 3) .. "," .. EgtNumToString( vDoneManually[nInd].Parts[nInd2].posY, 3) .. "," .. 0 .."," .. 0)
EgtSetInfo( nPartDuploId, "POSX", vDoneManually[nInd].Parts[nInd2].posX)
EgtSetInfo( nPartDuploId, "POSY", vDoneManually[nInd].Parts[nInd2].posY)
end
end
end
end
-- altrimenti pezzo
else
nPartCount = nPartCount + 1
for MGIndex = 1, #MachGroupList do
local nMachGroup = MachGroupList[MGIndex].MGId
--EgtSetCurrMachGroup(nMachGroup)
-- se c'e' un grezzo valido
if nMachGroup and nMachGroup ~= GDB_ID.NULL then
-- creo pezzo copia
local nPartDuploId = EgtDuploNew( nId)
local nPartInd
-- aggiungo le curve corrispondenti alle aree di lavorazione del pezzo
local sToolOutlines = EgtGetInfo( nId, "ToolOutlines", 's')
if sToolOutlines then
-- recupero o creo il gruppo per gli outlines
local nToolOutlinesGrp = EgtGetFirstNameInGroup( nPartDuploId, "ToolOutlines")
if not nToolOutlinesGrp then
nToolOutlinesGrp = EgtGroup( nPartDuploId)
EgtSetName( nToolOutlinesGrp, "ToolOutlines")
EgtSetStatus( nToolOutlinesGrp, GDB_ST.ON)
end
for str in string.gmatch(sToolOutlines, "([^"..",".."]+)") do
EgtCopyGlob( tonumber(str), nToolOutlinesGrp)
end
end
-- applico flip, rotazione e traslazione pezzo e box da nesting
if nFlag == 1 then
EgtRotate( nPartDuploId, ORIG(), X_AX(), 180, GDB_RT.GLOB)
end
EgtRotate( nPartDuploId, ORIG(), Z_AX(), dAngRot, GDB_RT.GLOB)
EgtMove( nPartDuploId, Vector3d( dX, dY, 0), GDB_RT.GLOB)
local nBoxLayerId = EgtGetFirstNameInGroup( nPartDuploId, "Box")
local nBoxId = EgtGetFirstNameInGroup( nBoxLayerId, "Box")
local PartBBox = EgtGetBBoxGlob(nBoxId, GDB_BB.STANDARD)
local ptPos = Point3d( PartBBox:getMin():getX(), PartBBox:getMin():getY(), 0)
EgtSetInfo( nMachGroup, "PART" .. nPartCount, nPartDuploId .. "," .. EgtNumToString( ptPos:getX() + dXCorr, 3) .. "," .. EgtNumToString( ptPos:getY() + dYCorr, 3) .. "," .. 0 .."," .. 0)
EgtSetInfo( nPartDuploId, "POSX", ptPos:getX() + dXCorr)
EgtSetInfo( nPartDuploId, "POSY", ptPos:getY() + dYCorr)
local nPartFlip = EgtGetInfo( nId, "INVERTED", 'i') or 0
nPartFlip = EgtIf( nPartFlip == 180, 1, 0)
local nTotFlip = EgtIf( nPartFlip ~= nFlag, 180, 0)
EgtSetInfo( nPartDuploId, "FLIP", nTotFlip)
local bPartFlip = ( nTotFlip == 180)
local nPartRot = EgtGetInfo( nId, "ROTATED", 'i') or 0
local nTotRot = nPartRot - EgtIf( bPartFlip, -dAngRot, dAngRot)
if nTotRot < 0 then
nTotRot = nTotRot + 360
elseif nTotRot >= 360 then
nTotRot = nTotRot - 360
end
EgtSetInfo( nPartDuploId, "ROT", nTotRot)
end
end
end
end
-- creo gruppi di lavorazione per fogli con pezzi nestati solo a mano
for nInd = 1, #vDoneManually do
if vDoneManually[nInd].Done == 0 then
-- creo gruppo di lavorazione
local MachGroupName = NewMachGroupName()
local nMachGroup = EgtAddMachGroup(MachGroupName, sCurrMachName)
table.insert( MachGroupList, { MGId = nMachGroup})
for nIndex = 1, #RawParts do
for nInd2 = 1, #(RawParts[nIndex].PartId) do
if RawParts[nIndex].PartId[nInd2] == vDoneManually[nInd].SheetId then
EgtSetInfo(nMachGroup, "PANELLEN", RawParts[nIndex].Len)
EgtSetInfo(nMachGroup, "PANELWIDTH", RawParts[nIndex].Width)
EgtSetInfo(nMachGroup, "MATERIAL", NEST.MATERIAL)
EgtSetInfo(nMachGroup, "AUTONEST", 1)
-- scrivo dati per variabili P di comunicazione con la macchina in gruppo di lavorazione
EgtSetInfo( nMachGroup, "PRODID", NEST.PRODID)
EgtSetInfo( nMachGroup, "PATTID", nMachGroup)
end
end
end
-- aggiungo pezzi nestati a mano
nPartCount = 0
for nInd2 = 1, #(vDoneManually[nInd].Parts) do
nPartCount = nPartCount + 1
local nPartDuploId = EgtDuploNew( vDoneManually[nInd].Parts[nInd2].Id)
-- aggiungo le curve corrispondenti alle aree di lavorazione del pezzo
local sToolOutlines = EgtGetInfo( vDoneManually[nInd].Parts[nInd2].Id, "ToolOutlines", 's')
if sToolOutlines then
-- recupero o creo il gruppo per gli outlines
local nToolOutlinesGrp = EgtGetFirstNameInGroup( nPartDuploId, "ToolOutlines")
if not nToolOutlinesGrp then
nToolOutlinesGrp = EgtGroup( nPartDuploId)
EgtSetName( nToolOutlinesGrp, "ToolOutlines")
EgtSetStatus( nToolOutlinesGrp, GDB_ST.ON)
end
for str in string.gmatch(sToolOutlines, "([^"..",".."]+)") do
EgtCopyGlob( tonumber(str), nToolOutlinesGrp)
end
end
-- applico flip, rotazione e traslazione pezzo e box da nesting
EgtSetInfo( nMachGroup, "PART" .. nPartCount, nPartDuploId .. "," .. EgtNumToString( vDoneManually[nInd].Parts[nInd2].posX, 3) .. "," .. EgtNumToString( vDoneManually[nInd].Parts[nInd2].posY, 3) .. "," .. 0 .."," .. 0)
EgtSetInfo( nPartDuploId, "POSX", vDoneManually[nInd].Parts[nInd2].posX)
EgtSetInfo( nPartDuploId, "POSY", vDoneManually[nInd].Parts[nInd2].posY)
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.BASEDIR = NEST.BASEDIR
WALL.FLAG = 6 -- CREATE_PANEL
WALL.NESTING_REF = 'BL'
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( NEST.BASEDIR .. "\\BatchProcessNew.lua")
-- aggiorno interfaccia
EgtProcessEvents( 200 + ( MachGroupIndex / MachGroupToTCnt * 100), 0)
end
-- ciclo sui duplo per sistemare Q
local nRawPartId = EgtGetFirstRawPart()
-- recupero box grezzo ridotto della tolleranza
local b3Raw = EgtGetRawPartBBox( nRawPartId)
b3Raw:expand( - s_dInsideRawTol)
EgtOutLog( 'RawBox='..tostring( b3Raw))
local nPartDuploId = EgtGetFirstPartInRawPart( nRawPartId)
while nPartDuploId do
local vPartProc = WE.CollectFeatures( nPartDuploId)
for ProcIndex = 1, #vPartProc do
local Proc = vPartProc[ProcIndex]
if LapJoint.Identify( Proc) then
-- cerco la faccia rivolta verso l'alto e la faccia rivolta verso il basso
local nFaceInd = -1
local nFaceDownInd = -1
for nIdx = 0, Proc.Fct - 1 do
local vtN = EgtSurfTmFacetNormVersor( Proc.Id, nIdx, GDB_ID.ROOT)
if vtN:getZ() > 0.95 then
nFaceInd = nIdx
elseif vtN:getZ() < - 0.95 then
nFaceDownInd = nIdx
end
end
-- se è lap joint dall'alto
if nFaceInd ~= -1 and nFaceDownInd == -1 then
local bResetQ = false
local ptCen = EgtSurfTmFacetCenter( Proc.Id, nFaceInd, GDB_ID.ROOT)
-- se all'interno rimuovo info Q
if EnclosesPointXY( b3Raw, ptCen) then
bResetQ = true
elseif Proc.Fct == 2 then
-- se non è interno ma ha 2 facce non ortogonali rimuovo info Q
local vtN1 = EgtSurfTmFacetNormVersor( Proc.Id, 0, GDB_ID.ROOT)
local vtN2 = EgtSurfTmFacetNormVersor( Proc.Id, 1, GDB_ID.ROOT)
if abs( vtN1 * vtN2) > GEO.EPS_SMALL then
bResetQ = true
end
end
if bResetQ then
-- resetto parametro Q
if Proc.Prc == 30 then
EgtRemoveInfo( Proc.Id, "Q08")
EgtRemoveInfo( Proc.Id, "Q08A")
else
EgtRemoveInfo( Proc.Id, "Q03")
EgtRemoveInfo( Proc.Id, "Q03A")
end
end
end
elseif DoubleCut.Identify( Proc) then
-- verifico se due facce e rivolto verso l'alto
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 nFaceInd = EgtIf( vtN[1]:getZ() >= 0.95, 0, 1)
local ptCen = EgtSurfTmFacetCenter( Proc.Id, nFaceInd, GDB_ID.ROOT)
-- se all'interno rimuovo info Q
if EnclosesPointXY( b3Raw, ptCen) then
-- resetto parametro Q
if Proc.Prc == 12 then
EgtRemoveInfo( Proc.Id, "Q02")
EgtRemoveInfo( Proc.Id, "Q02A")
end
end
end
end
end
end
nPartDuploId = EgtGetNextPartInRawPart(nPartDuploId)
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
local nSheetDefectsGrp = EgtGetFirstNameInGroup(GDB_ID.ROOT, "SheetDefects")
if nSheetDefectsGrp and nSheetDefectsGrp ~= GDB_ID.NULL then EgtErase( nSheetDefectsGrp) end
-- EgtSaveFile( "C:\\EgtData\\EgtBEAMWALL\\Temp\\file.nge")
EgtOutLog( ' +++ NestProcess completed')