ff953deaff
- Raggruppate funzioni riguardati i pezzi in PartData.
333 lines
12 KiB
Lua
333 lines
12 KiB
Lua
-- CreateMachGroups.lua by Egalware s.r.l. 2026/02/09
|
|
-- Creazione dei MachGroup del file già aperto
|
|
|
|
|
|
-- Intestazioni
|
|
require( 'EgtBase')
|
|
_ENV = EgtProtectGlobal()
|
|
EgtEnableDebug( false)
|
|
|
|
-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
-- TODO DA CANCELLARE!!!! quando verrà passato automaticamente da programma
|
|
--local WIN = {}
|
|
--WIN.MACHINELIST = {}
|
|
--WIN.MACHINELIST[1] = 'Saomad-Just3500'
|
|
--WIN.OPT_TYPE = 'WINDOW'
|
|
-- * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
|
|
|
|
--Libero eventuali librerie rimaste caricate
|
|
_G.package.loaded.WinData = nil
|
|
_G.package.loaded.WinLib = nil
|
|
|
|
-- Verifico che la macchina corrente sia abilitata per la lavorazione delle finestre
|
|
if not WIN.MACHINELIST or #WIN.MACHINELIST == 0 or #WIN.MACHINELIST[1] == 0 then
|
|
EgtOutLog( 'Errore! Macchina non impostata!')
|
|
return
|
|
end
|
|
if not EgtSetCurrMachine( WIN.MACHINELIST[1]) then
|
|
EgtOutLog( 'Errore! Macchina impostata non trovata!')
|
|
return
|
|
end
|
|
local sMachDir = EgtGetCurrMachineDir()
|
|
if not sMachDir then
|
|
EgtOutBox( 'Errore nel caricamento della macchina corrente', 'Lavora Serramenti', 'ERROR')
|
|
return
|
|
end
|
|
if not EgtExistsFile( sMachDir .. '\\Window\\WinData.lua') then
|
|
EgtOutBox( 'La macchina corrente non è configurata per lavorare serramenti', 'Lavora Serramenti', 'ERROR')
|
|
return
|
|
end
|
|
|
|
-- Elimino direttori altre macchine e imposto direttorio macchina corrente per ricerca librerie
|
|
EgtRemoveBaseMachineDirFromPackagePath()
|
|
EgtAddToPackagePath( sMachDir .. '\\Window\\?.lua')
|
|
|
|
-- Segnalazione avvio
|
|
EgtOutLog( '*** Window Process Start ***', 1)
|
|
|
|
-- Carico le librerie
|
|
EgtAddToPackagePath( EgtGetSourceDir() .. 'LuaLibs\\?.lua')
|
|
local WinLib = require( 'WinLib')
|
|
local PartData = require( 'PartData')
|
|
|
|
-- Carico i dati globali
|
|
local WinData = require( 'WinData')
|
|
|
|
-- Variabili globali
|
|
PARTS = {}
|
|
GROUPS = {}
|
|
|
|
-- Colore del grezzo
|
|
local ColA = Color3d( 255, 165, 0, 30)
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
-- *** Recupero i pezzi da processare ***
|
|
-------------------------------------------------------------------------------------------------------------
|
|
local function GetInfoPieces()
|
|
-- Recupero i pezzi delle finestre
|
|
local nId = EgtGetFirstPart()
|
|
while nId do
|
|
-- TODO caricare il file di costanti
|
|
-- si processano solo BOTTOMRAIL (WIN_PART_TYPES.BOTTOMRAIL = 2) o STANDARD (WIN_PART_TYPES.STD = 3)
|
|
if EgtGetInfo( nId, 'PART_TYPE', 'd') == 2 or EgtGetInfo( nId, 'PART_TYPE', 'd') == 3 then
|
|
table.insert( PARTS, { id = nId, sName = ( EgtGetName( nId) or ( 'Id=' .. tonumber( nId)))})
|
|
end
|
|
nId = EgtGetNextPart( nId)
|
|
end
|
|
if #PARTS == 0 then
|
|
EgtOutBox( 'Non ci sono pezzi', 'Lavora Pezzi', 'ERROR')
|
|
return false
|
|
else
|
|
-- recupero tutte le dimensioni necessarie
|
|
local sOut = ''
|
|
for i = 1, #PARTS do
|
|
PARTS[i].b3Raw = EgtGetBBoxGlob( EgtGetFirstNameInGroup( PARTS[i].id, 'GeoRaw') or GDB_ID.NULL, GDB_BB.STANDARD)
|
|
local idFrame = EgtGetFirstNameInGroup( EgtGetFirstNameInGroup( PARTS[i].id, 'GeoRaw'), 'AuxFrame')
|
|
PARTS[i].frame = EgtFR( idFrame)
|
|
|
|
-- recupero offset per posizionamento
|
|
PARTS[i].DispOffsets = {}
|
|
PARTS[i].DispOffsets.Phase1 = {}
|
|
PARTS[i].DispOffsets.Phase2 = {}
|
|
|
|
local bInsertedAllOffs = PartData.GetDispOffsetFromNotes( PARTS, i)
|
|
|
|
-- recupero info profili
|
|
PARTS[i].SemiProfiles = {}
|
|
table.insert( PARTS[i].SemiProfiles, EgtGetInfo( PARTS[i].id, 'PROFILE_IN', 's') or '')
|
|
table.insert( PARTS[i].SemiProfiles, EgtGetInfo( PARTS[i].id, 'PROFILE_OUT', 's') or '')
|
|
table.insert( PARTS[i].SemiProfiles, EgtGetInfo( PARTS[i].id, 'PROFILE_LEFT', 's') or '')
|
|
table.insert( PARTS[i].SemiProfiles, EgtGetInfo( PARTS[i].id, 'PROFILE_RIGHT', 's') or '')
|
|
|
|
-- TODO info deve essere passata da programma
|
|
-- recupero info finestra
|
|
PARTS[i].sWindow = EgtGetInfo( PARTS[i].id, 'WIN_ID', 's') or ''
|
|
|
|
-- TODO è lo stesso del PART_TYPE o serve altro??? da verificare!
|
|
-- tipo di pezzo
|
|
PARTS[i].sPieceType = EgtGetInfo( PARTS[i].id, 'PART_TYPE', 'd') or ''
|
|
|
|
-- definisco il pezzo per famiglia ( TODO da recuperare dal nome del pezzo, o da una nota)
|
|
|
|
-- se non sono stati inseriti o c'è stato un errore esco subito
|
|
if not bInsertedAllOffs then
|
|
EgtOutBox( 'Errore offset non trovati', 'BatchProcessWin', 'ERROR', 'OK')
|
|
return false
|
|
end
|
|
|
|
sOut = sOut .. PARTS[i].sName .. ', '
|
|
end
|
|
sOut = sOut:sub( 1, -3)
|
|
EgtOutLog( 'Pezzi : ' .. sOut, 1)
|
|
end
|
|
|
|
EgtDeselectAll()
|
|
|
|
return true
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
-- Crea il grezzo che verrà messo in macchina
|
|
---------------------------------------------------------------------
|
|
local function CreateRaws( PiecesInMachGroup)
|
|
for i = 1, #PiecesInMachGroup do
|
|
-- si crea un grezzo "finto" (un cubo da 100mm) nell'origine del pezzo, verrà poi dimensionato uan volta adeguato con i vari sovramateriali
|
|
PiecesInMachGroup[i].idRaw = EgtAddRawPart( PiecesInMachGroup[i].frame:getOrigin(), 100, 100, 100, ColA)
|
|
EgtAddPartToRawPart( PiecesInMachGroup[i].id, ORIG(), PiecesInMachGroup[i].idRaw)
|
|
end
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
-- Allinea i pezzi in base a come devono essere disposti sulla tavola
|
|
---------------------------------------------------------------------
|
|
-- TODO in questa fase bisogna già sapere qual è la prima fase e posizionare il pezzo di conseguenza
|
|
-- TODO (bassa priorità) adesso allinea sempre in X, ma bisognerebbe farlo in base ad un parametro in WINDATA che dice come si dispongono in macchina
|
|
local function AlignRawsToTable( PiecesInMachGroup)
|
|
for i = 1, #PiecesInMachGroup do
|
|
-- allineo il pezzo all'interno del grezzo
|
|
local dRotX, dRotY, dRotZ = GetFixedAxesRotABCFromFrame( PiecesInMachGroup[i].frame)
|
|
-- se devo ruotare
|
|
if abs( dRotZ) > GEO.EPS_ANG_SMALL then
|
|
EgtRotatePartInRawPart( PiecesInMachGroup[i].id, Z_AX(), -dRotZ)
|
|
end
|
|
-- sposto punto in basso a sinistra del pezzo sul punto in basso a sinistra del grezzo
|
|
local b3Part = EgtGetBBoxGlob( PiecesInMachGroup[i].id, GDB_BB.ONLY_VISIBLE)
|
|
local dPartPosX = b3Part:getMin():getX()
|
|
local dPartPosY = b3Part:getMin():getY()
|
|
local dPartPosZ = b3Part:getMin():getZ()
|
|
local b3Raw = EgtGetRawPartBBox( PiecesInMachGroup[i].idRaw)
|
|
local dRawPosX = b3Raw:getMin():getX()
|
|
local dRawPosY = b3Raw:getMin():getY()
|
|
local dRawPosZ = b3Raw:getMin():getZ()
|
|
local vtMove = Vector3d( dRawPosX - dPartPosX, dRawPosY - dPartPosY, dRawPosZ - dPartPosZ)
|
|
EgtMovePartInRawPart( PiecesInMachGroup[i].id, vtMove)
|
|
end
|
|
return true
|
|
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
|
|
local sMachGroupName = EgtGetMachGroupName( nMachGroupId)
|
|
local nMachGroupName = tonumber( sMachGroupName)
|
|
if nMachGroupName > nMaxMachGroup then
|
|
nMaxMachGroup = nMachGroupName
|
|
end
|
|
nMachGroupId = EgtGetNextMachGroup( nMachGroupId)
|
|
end
|
|
return tostring( nMaxMachGroup + 1)
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
-- *** Funzione per raggruppamento pezzi ***
|
|
-------------------------------------------------------------------------------------------------------------
|
|
|
|
-- TODO punteggio da verificare!!
|
|
-- Calcolo un punteggio di similitudine tra due pezzi
|
|
local function CalculateSimilarity( Part1, Part2)
|
|
-- peso lati: IN, OUT, LEFT, RIGHT (i lati lunghi hanno più peso rispetto alle teste)
|
|
local ProfilesWeights = { 3, 3, 1, 1}
|
|
local dScore = 0
|
|
|
|
for i = 1, 4 do
|
|
if Part1.SemiProfiles[i] == Part2.SemiProfiles[i] then
|
|
dScore = dScore + ProfilesWeights[i]
|
|
end
|
|
end
|
|
|
|
-- punteggio "bonus" se il tipo di pezzo è lo stesso
|
|
if Part1.sPieceType and Part2.sPieceType and Part1.sPieceType == Part2.sPieceType then
|
|
dScore = dScore + 2
|
|
end
|
|
|
|
return dScore
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
-- raggruppamento con vincoli ( lunghezza / numero pezzi)
|
|
local function GroupParts( PartsList, sOptimisationType)
|
|
-- TIPI DI OTTIMIZZAZIONE (sOptimisationType)
|
|
-- 'PIECE' : pezzo singolo
|
|
-- 'WINDOW' : ottimizza finestra
|
|
-- 'FULL_LIST': ottimizza progetto
|
|
|
|
local Groups = {}
|
|
local Used = {}
|
|
|
|
for i = 1, #PartsList do
|
|
if not Used[i] then
|
|
local Group = {}
|
|
|
|
-- Add the main part
|
|
table.insert( Group, PartsList[i])
|
|
Used[i] = true
|
|
|
|
-- se non è ottimizzazione pezzo singolo, cerco altri pezzi che possono essere lavorati nella stessa macchinata
|
|
if sOptimisationType ~= 'PIECE' then
|
|
-- cerca un altro pezzo compatibile
|
|
while true do
|
|
local nBestIndex = nil
|
|
local nBestScore = -1
|
|
|
|
for j = 1, #PartsList do
|
|
if not Used[j] then
|
|
local bCanBeGrouped = not( sOptimisationType == 'WINDOW' and PartsList[i].sWindow ~= PartsList[j].sWindow)
|
|
-- se possono essere raggruppati per tipo di ottimizzazione
|
|
if bCanBeGrouped then
|
|
local VirtualList = WinLib.TableCopyDeep( Group)
|
|
table.insert( VirtualList, PartsList[j])
|
|
bCanBeGrouped = WinData.VerifyPieces( VirtualList)
|
|
-- se possono effettivamente essere messi nella stessa macchinata
|
|
if bCanBeGrouped then
|
|
-- il punteggio è sempre calcolato rispetto al primo pezzo del gruppo
|
|
local nScore = CalculateSimilarity( PartsList[i], PartsList[j])
|
|
if nScore > nBestScore then
|
|
nBestScore = nScore
|
|
nBestIndex = j
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
if not nBestIndex then
|
|
break
|
|
end
|
|
|
|
-- Add the best matching part
|
|
table.insert( Group, PartsList[nBestIndex])
|
|
Used[nBestIndex] = true
|
|
end
|
|
end
|
|
|
|
table.insert( Groups, Group)
|
|
end
|
|
end
|
|
|
|
return Groups
|
|
end
|
|
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
-- *** Inserimento dei pezzi nelle macchinate ***
|
|
-------------------------------------------------------------------------------------------------------------
|
|
local function CreateMachGroups()
|
|
|
|
for j = 1, #GROUPS do
|
|
-- creo macchinata
|
|
local MachGroupName = NewMachGroupName()
|
|
local nMachGroup = EgtAddMachGroup( MachGroupName)
|
|
|
|
-- si setta gruppo appena creato come corrente
|
|
EgtSetCurrMachGroup( nMachGroup)
|
|
|
|
-- si crea il grezzo
|
|
CreateRaws( GROUPS[j])
|
|
|
|
-- allineo i pezzi come orientamento richiesto dalla macchina
|
|
AlignRawsToTable( GROUPS[j])
|
|
|
|
-- aggiungo sovramateriale ai grezzi
|
|
PartData.AddOverMaterialToRaw( GROUPS[j])
|
|
|
|
-- si dispongono i pezzi sulla tavola
|
|
local bDispOk, sErr = WinData.ExecDisposition( GROUPS[j])
|
|
if not bDispOk then
|
|
if not sErr then
|
|
sErr = 'Errore non gestito in WinData.ExecDisposition'
|
|
end
|
|
return false
|
|
end
|
|
|
|
-- Impostazione dell'attrezzaggio di default
|
|
local bOk = EgtImportSetup()
|
|
if not bOk then
|
|
EgtImportSetup( 'Default')
|
|
end
|
|
end
|
|
|
|
return true
|
|
end
|
|
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
-- *** Esecuzione ***
|
|
-------------------------------------------------------------------------------------------------------------
|
|
|
|
if not GetInfoPieces() then return end
|
|
|
|
GROUPS = GroupParts( PARTS, WIN.OPT_TYPE)
|
|
|
|
if not GROUPS or #GROUPS == 0 then
|
|
return
|
|
end
|
|
|
|
if not CreateMachGroups() then return end
|
|
|
|
|