diff --git a/Beam.ini b/Beam.ini new file mode 100644 index 0000000..4870e23 --- /dev/null +++ b/Beam.ini @@ -0,0 +1,7 @@ +[Beam] +BtlEnable=1 +BaseDir=C:\EgtData\Beam +BtlExec=BatchProcess.lua +Button1=Process.lua,Images\Process.png,Lavora Travi +Button2=Swap.lua,Images\Swap.png,Scambia estremi trave +Button3=Rotate.lua,Images\Rotate.png,Ruota trave \ No newline at end of file diff --git a/Images/Process.png b/Images/Process.png new file mode 100644 index 0000000..13070d5 Binary files /dev/null and b/Images/Process.png differ diff --git a/Images/Rotate.png b/Images/Rotate.png new file mode 100644 index 0000000..bd1532e Binary files /dev/null and b/Images/Rotate.png differ diff --git a/Images/Swap.png b/Images/Swap.png new file mode 100644 index 0000000..04fa8f8 Binary files /dev/null and b/Images/Swap.png differ diff --git a/LuaLibs/BasicCustomerStrategies.lua b/LuaLibs/BasicCustomerStrategies.lua new file mode 100644 index 0000000..cd754ca --- /dev/null +++ b/LuaLibs/BasicCustomerStrategies.lua @@ -0,0 +1,59 @@ +--BasicCustomerStrategies.lua by Egalware s.r.l. 2024/04/02 +-- Libreria strategie di base disponibili per i clienti +-- 2024/04/02 PRIMA VERSIONE CALCOLO LAVORAZIONI CON STRATEGIE + +-- Tabella per definizione modulo +local BasicCustomerStrategies = {} + +-- Include +require( 'EgtBase') + +-- Carico i dati globali +local BD = require( 'BeamData') +local ID = require( 'Identity') + +---------------------------------------------------------------------------------- +-- *** Esecuzione *** +---------------------------------------------------------------------------------- + +-- si legge lo script delle strategie di base definito con cliente (statico e non modificabile) +function BasicCustomerStrategies.GetStrategiesFromBasicCustomerStrategies( Proc) + local StrategiesFromScript = {} + + -- se non esiste JSON e nessuan info in BeamData, si carica standard di default EGALWARE + if not STRATEGIES and not BD.STRATEGIES_SCRIPT then + StrategiesFromScript = GetStrategies_Egalware( Proc) + -- CLIENTE : ESSETRE + elseif BD.STRATEGIES_SCRIPT == 'Essetre' then + StrategiesFromScript = GetStrategies_Essetre( Proc) + else + StrategiesFromScript = nil + end + return StrategiesFromScript +end + +---------------------------------------------------------------------------------- +-- *** EGALWARE *** +---------------------------------------------------------------------------------- +local function GetStrategies_Egalware( Proc) + local Strategy_Egalware = {} + local Strategies_Egalware = {} + + -- TODO tabella da compleatare man mano che si inseriscono le varie strategie + return Strategies_Egalware +end + +---------------------------------------------------------------------------------- +-- *** ESSETRE *** +---------------------------------------------------------------------------------- +local function GetStrategies_Essetre( Proc) + local Strategy_Essetre = {} + local Strategies_Essetre = {} + + -- TODO tabella da compleatare man mano che si inseriscono le varie strategie + return Strategies_Essetre +end + +------------------------------------------------------------------------------------------------------------- + +return BasicCustomerStrategies \ No newline at end of file diff --git a/LuaLibs/BeamExec.lua b/LuaLibs/BeamExec.lua new file mode 100644 index 0000000..b97ff7f --- /dev/null +++ b/LuaLibs/BeamExec.lua @@ -0,0 +1,623 @@ +-- BeamExec.lua by Egalware s.r.l. 2024/04/02 +-- Libreria esecuzione lavorazioni per Travi +-- 2024/04/02 PRIMA VERSIONE CALCOLO LAVORAZIONI CON STRATEGIE + +-- Tabella per definizione modulo +local BeamExec = {} + +-- Include +require( 'EgtBase') + +-- Carico i dati globali +local BD = require( 'BeamData') + +-- carico librerie +local BL = require( 'BeamLib') +local ID = require( 'Identity') +local BCS = require( 'BasicCustomerStrategies') +local FD = require( 'FeatureData') + + +EgtOutLog( ' BeamExec started', 1) +EgtMdbSetGeneralParam( MCH_GP.MAXDEPTHSAFE, BD.COLL_SIC) +EgtMdbSave() + +------------------------------------------------------------------------------------------------------------- +-- *** variabili globali *** +------------------------------------------------------------------------------------------------------------- +TOOLS = nil +STRATEGIES = nil + +------------------------------------------------------------------------------------------------------------- +-- *** COSTANTI *** TODO -> DA SPOSTARE IN BEAMDATA??? +------------------------------------------------------------------------------------------------------------- +TH_DIAMETER_HSK63 = 63 +TH_LENGTH_HSK63 = 75 +SIDEANGLE_DOVETAIL = 15 + +------------------------------------------------------------------------------------------------------------- +-- *** funzioni di base *** +------------------------------------------------------------------------------------------------------------- +local function GetToolTypeNameFromToolTypeID( dToolTypeID) + if dToolTypeID == MCH_TY.DRILL_STD then + return 'DRILL_STD', 'DRILLBIT' + elseif dToolTypeID == MCH_TY.DRILL_LONG then + return 'DRILL_LONG', 'DRILLBIT' + elseif dToolTypeID == MCH_TY.SAW_STD then + return 'SAW_STD', 'SAWBLADE' + elseif dToolTypeID == MCH_TY.SAW_FLAT then + return 'SAW_FLAT', 'SAWBLADE' + elseif dToolTypeID == MCH_TY.MILL_STD then + return 'MILL_STD', 'MILL' + elseif dToolTypeID == MCH_TY.MILL_NOTIP then + return 'MILL_NOTIP', 'MILL' + elseif dToolTypeID == MCH_TY.MORTISE_STD then + return 'MORTISE_STD', 'MORTISE' + else + return nil + end +end + +------------------------------------------------------------------------------------------------------------- +local function IsToolOk( Tool) + -- controllo che i dati necessari siano impostati + if Tool.MaxMaterial and Tool.Diameter and Tool.Length and Tool.Head and Tool.UUID then + -- se DRILLBIT non ho altri dati + if Tool.Family == 'DRILLBIT' then + return true + -- altrimenti controllo dati aggiuntivi altre famiglie di utensili + else + if Tool.Thick then + return true + end + end + end + return false +end + +------------------------------------------------------------------------------------------------------------- +function BeamExec.GetToolsFromDB() + -- creo lista globale utensili disponibili + TOOLS = {} + -- lista appoggio utensile + local Tool = {} + + -- recupero tutti gli utensili : punte a forare, lame, frese e motoseghe + Tool.Name = EgtTdbGetFirstTool( MCH_TF.DRILLBIT + MCH_TF.SAWBLADE + MCH_TF.MILL + MCH_TF.MORTISE) + while Tool.Name ~= '' do + -- imposto utensile come corrente per recuperarne i dati + EgtTdbSetCurrTool( Tool.Name) + + -- verifico se utensile disponibile in attrezzaggio attuale e che abbia un tipo ben definito + local bToolLoadedOnSetup, sToolTCPos = EgtFindToolInCurrSetup( Tool.Name) + local dToolTypeID = EgtTdbGetCurrToolParam( MCH_TP.TYPE) + local sToolType, sToolFamily = GetToolTypeNameFromToolTypeID( dToolTypeID) + + -- se verifica condizioni minime, recupero tutti gli altri dati + if bToolLoadedOnSetup and sToolType then + Tool.AName = Tool.Name + Tool.TcPos = sToolTCPos + Tool.Family = sToolFamily + Tool.Type = sToolType + Tool.TypeID = dToolTypeID + Tool.MaxMaterial = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) + Tool.Diameter = EgtTdbGetCurrToolParam( MCH_TP.DIAM) + Tool.Length = EgtTdbGetCurrToolParam( MCH_TP.LEN) + Tool.Speed = EgtTdbGetCurrToolParam( MCH_TP.SPEED) + Tool.IsCCW = Tool.Speed < 0 + Tool.Feeds = {} + Tool.Feeds.Feed = EgtTdbGetCurrToolParam( MCH_TP.FEED) + Tool.Feeds.StartFeed = EgtTdbGetCurrToolParam( MCH_TP.STARTFEED) + Tool.Feeds.EndFeed = EgtTdbGetCurrToolParam( MCH_TP.ENDFEED) + Tool.Feeds.TipFeed = EgtTdbGetCurrToolParam( MCH_TP.TIPFEED) + Tool.Head = EgtTdbGetCurrToolParam( MCH_TP.HEAD) + Tool.UUID = EgtTdbGetCurrToolParam( MCH_TP.UUID) + Tool.UserNotes = EgtTdbGetCurrToolParam( MCH_TP.USERNOTES) + Tool.MaxDepth = EgtTdbGetCurrToolMaxDepth() or Tool.MaxMaterial + Tool.ToolHolder = {} + Tool.ToolHolder.Diameter = EgtTdbGetCurrToolThDiam() or TH_DIAMETER_HSK63 -- diametro standard HSK63 + Tool.ToolHolder.Length = EgtTdbGetCurrToolThLength() or TH_LENGTH_HSK63 -- lunghezza standard HSK63 + -- parametri scritti nelle note + Tool.Double = EgtGetValInNotes( Tool.UserNotes, 'DOUBLE') + + -- lettura parametri non comuni ( famiglia DRILLBIT non ha parametri specifici) + if sToolFamily ~= 'DRILLBIT' then + Tool.Thick = EgtTdbGetCurrToolParam( MCH_TP.THICK) + Tool.LongitudinalOffset = EgtTdbGetCurrToolParam( MCH_TP.LONOFFSET) + Tool.RadialOffset = EgtTdbGetCurrToolParam( MCH_TP.RADOFFSET) + -- recupero parametri propri delle frese + if sToolFamily == 'MILL' then + Tool.StemDiameter = EgtTdbGetCurrToolParam( MCH_TP.STEMDIAM) or Tool.ThDiameter -- se non settato, considero diametro come ToolHolder + Tool.SideAngle = EgtTdbGetCurrToolParam( MCH_TP.SIDEANG) or 0 + -- verifico che parametri siano compatibili con una fresa a coda di rondine ( angolo di fianco standard Coda di rondine -> 15°) + Tool.IsDoveTail = Tool.Type == 'MILL_NOTIP' and abs( abs( Tool.SideAngle) - SIDEANGLE_DOVETAIL) < 1 + -- verifico che sia una fresa tipo T-Mill o BlockHaus + Tool.SideDepth = EgtGetValInNotes( Tool.UserNotes, 'SIDEDEPTH') or 0 -- se non settato nell'utensile, dico che non ha massimo affondamento laterale + Tool.IsTMill = Tool.SideDepth > 0 + Tool.Step = EgtGetValInNotes( Tool.UserNotes, 'STEP') or ( Tool.MaxMaterial / 2) -- se non settato nell'utensile, considero metà del tagliente + Tool.SideStep = EgtGetValInNotes( Tool.UserNotes, 'SIDESTEP') or floor( Tool.Diameter / 2) -- se non settato nell'utensile, considero metà del diametro + -- recupero parametri propri delle lame + elseif sToolFamily == 'SAWBLADE' then + Tool.IsUsedForLongCut = EgtGetValInNotes( Tool.UserNotes, 'LONGCUT') == 1 or false -- false coem valore di default + Tool.Step = EgtGetValInNotes( Tool.UserNotes, 'STEP') or Tool.Thick -- se non settato nell'utensile, considero lo spessore lama + Tool.SideStep = EgtGetValInNotes( Tool.UserNotes, 'SIDESTEP') or floor( Tool.Diameter / 4) -- se non settato nell'utensile, considero un quarto del diametro + -- recupero parametri propri delle motoseghe + elseif sToolFamily == 'MORTISE' then + Tool.Distance = EgtTdbGetCurrToolParam( MCH_TP.DIST) or 90 -- 90mm dimensione standard aggregato catena + Tool.IsMortise = EgtGetValInNotes( Tool.UserNotes, 'MORTISE') == 1 + Tool.IsChainSaw = not Tool.IsMortise + Tool.Step = EgtGetValInNotes( Tool.UserNotes, 'STEP') or ( Tool.Thick - 1) -- se non settato nell'utensile, considero spessore catena meno 1mm di sicurezza + Tool.SideStep = EgtGetValInNotes( Tool.UserNotes, 'SIDESTEP') or floor( Tool.MaxMaterial / 3) -- se non settato nell'utensile, considero un terzo della lunghezza + end + end + + -- se tutti i dati necessari sono disponibili, inserisco utensile nella lista globale degli utensili disponibili + if IsToolOk( Tool) then + table.insert( TOOLS, Tool) + -- altrimenti scrivo nel log che l'utensile non è conforme + else + EgtOutLog( '*** ' .. Tool.Name .. ' : NOT-COMPLIANT ***', 1) + end + + -- reset dati + Tool = {} + end + + -- recupero utensile successivo ( punte a forare, lame, frese e motoseghe) + Tool.Name = EgtTdbGetNextTool( MCH_TF.DRILLBIT + MCH_TF.SAWBLADE + MCH_TF.MILL + MCH_TF.MORTISE) + end +end + +------------------------------------------------------------------------------------------------------------- +local function ImportFileJSON( sFileToImport) + local JSON = require( 'JSON') + + local function readAll( sFileToImport) + local f = io.open( sFileToImport, "rb") + local content = f:read( "*all") + f:close() + return content + end + + local content = readAll( sFileToImport) + + return JSON:decode( content) +end + +------------------------------------------------------------------------------------------------------------- +function BeamExec.GetStrategiesFromJSONinBD() + -- si legge il JSON contenente la configurazione da utilizzare (nome del file salvato nel BeamData) + local sMachDir = EgtGetCurrMachineDir() + if BD.STRATEGIES_CONFIG_FILE then + local sFile = sMachDir .. '\\Beam\\' .. BD.STRATEGIES_CONFIG_FILE + if not sFile then return end + + local FeaturesList = {} + FeaturesList = ImportFileJSON( sFile) + + -- metto la tabella letta nella lista globale STRATEGIES + STRATEGIES = {} + STRATEGIES.Features = FeaturesList + end +end + +------------------------------------------------------------------------------------------------------------- +-- *** funzioni posizionamento pezzi all'interno della barra *** +------------------------------------------------------------------------------------------------------------- +function BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, vBeam, bMachGroupOk) + + -- default per nuove costanti qualora non definite + BD.OVM_BLADE_HBEAM = ( BD.OVM_BLADE_HBEAM or 11) + BD.OVM_CHAIN_HBEAM = ( BD.OVM_CHAIN_HBEAM or 8) + + -- sovramateriale intermedio nullo se non definito + dOvmMid = ( dOvmMid or 0) + + -- Determinazione minimo grezzo scaricabile + BeamExec.CalcMinUnloadableRaw( dRawW, dRawH) + + -- Creazione nuovo gruppo di lavoro + if not bMachGroupOk then + local sMgName = EgtGetMachGroupNewName( 'Mach_1') + local NewMgId = EgtAddMachGroup( sMgName) + if not NewMgId then + local sOut = 'Errore nella creazione del gruppo di lavoro ' .. sMgName + return false, sOut + end + end + + -- Impostazione della tavola + EgtSetTable( 'Tab') + + -- salvo nota con lunghezza grezzo + -- Recupero l'identificativo del gruppo di lavoro corrente + local nMGrpId = EgtGetCurrMachGroup() + -- Lunghezza della barra + local dBarLen = EgtGetInfo( nMGrpId, 'BARLEN', 'd') + if not dBarLen then + EgtSetInfo( nMGrpId, 'BARLEN', dRawL) + end + + -- Area tavola + local b3Tab = EgtGetTableArea() + -- Calcolo posizione estremo TR/BR della tavola rispetto a sua origine in BL + local dPosY = EgtIf( BD.CENTER_BEAM, ( b3Tab:getDimY() + dRawW * EgtIf( BD.RIGHT_LOAD, -1, 1)) / 2, EgtIf( BD.RIGHT_LOAD, 0, b3Tab:getDimY())) + BD.OriXR = Point3d( b3Tab:getDimX(), dPosY, 0) + BD.PosXR = EgtIf( BD.RIGHT_LOAD, MCH_CR.BR, MCH_CR.TR) + + -- Impostazione dell'attrezzaggio di default + EgtImportSetup() + + -- Inserimento dei pezzi con il loro grezzo + local Cnt = 0 + local Len = dRawL + local nPrevRaw, dPrevDelta + local DeltaS = dOvmHead + local DeltaSMin = 0 + local DeltaE = BD.OVM_MID + for i = 1, #vBeam do + -- assegno identificativo pezzo + local Pz = vBeam[i].Id + -- dati del pezzo + local b3Part = EgtGetBBoxGlob( Pz or GDB_ID.NULL, GDB_BB.EXACT) + local b3Solid = vBeam[i].Box + if b3Part:isEmpty() or b3Solid:isEmpty() then break end + EgtOutLog( 'PartSez=' .. EgtNumToString( b3Part:getDimY(), 1) .. 'x' .. EgtNumToString( b3Part:getDimZ(), 1), 3) + -- se sezione compatibile e lunghezza disponibile sufficiente + local PartLen = b3Solid:getDimX() + local PartWidth = b3Solid:getDimY() + local PartHeight = b3Solid:getDimZ() + local NextLen = Len - DeltaS - PartLen - DeltaE + if (( abs( PartWidth - dRawW) < 100 * GEO.EPS_SMALL and abs( PartHeight - dRawH) < 100 * GEO.EPS_SMALL) or + ( abs( PartHeight - dRawW) < 100 * GEO.EPS_SMALL and abs( PartWidth - dRawH) < 100 * GEO.EPS_SMALL)) and + NextLen + DeltaE >= 0 then + -- eventuale sovramateriale di testa + if i > 1 then + if vBeam[i].PosX then + DeltaS = max( vBeam[i].PosX - ( dRawL - Len), DeltaSMin) + else + DeltaS = max( dOvmMid - DeltaE, 0) + end + end + -- dimensioni del grezzo + local CrawLen = min( PartLen + DeltaS + DeltaE, Len) + local Delta = CrawLen - PartLen - DeltaS + -- creo e posiziono il grezzo + local nRaw = EgtAddRawPart( Point3d(0,0,0), CrawLen, dRawW, dRawH, BD.RAWCOL) + EgtMoveToCornerRawPart( nRaw, BD.OriXR, BD.PosXR) + EgtMoveRawPart( nRaw, Vector3d( Len - dRawL, 0, 0)) + -- assegno ordine in lavorazione + Cnt = Cnt + 1 + EgtSetInfo( nRaw, 'ORD', Cnt) + -- creo o pulisco gruppo geometrie aggiuntive + if not BL.CreateOrEmptyAddGroup( Pz) then + local sOut = 'Error creating Additional Group in Part ' .. tostring( Pz) + return false, sOut + end + -- aggiungo faccia per taglio iniziale al pezzo + BL.AddPartStartFace( Pz, b3Solid) + -- se sovramateriale di testa, lo notifico + if DeltaS > 0.09 then + EgtSetInfo( nRaw, 'HOVM', DeltaS) + if nPrevRaw then + EgtSetInfo( nPrevRaw, 'BDST', DeltaS + dPrevDelta) + end + end + if DeltaE > 0.09 then + EgtSetInfo( nRaw, 'TOVM', DeltaE) + end + -- aggiungo faccia per taglio finale al pezzo + BL.AddPartEndFace( Pz, b3Solid) + -- inserisco il pezzo nel grezzo + EgtDeselectPartObjs( Pz) + local ptPos = b3Part:getMin() - b3Solid:getMin() + Vector3d( Delta, ( dRawW - PartWidth) / 2, ( dRawH - PartHeight) / 2) + EgtAddPartToRawPart( Pz, ptPos, nRaw) + if abs( PartWidth - dRawW) > 100 * GEO.EPS_SMALL then + -- rotazione attorno a centro geometria complessiva del pezzo + EgtRotatePartInRawPart( Pz, X_AX(), 90) + -- correggo per eccentricità solido rispetto a geometria complessiva del pezzo + local vtEccOri = b3Solid:getCenter() - b3Part:getCenter() + local vtEccRot = Vector3d( vtEccOri) + vtEccRot:rotate( X_AX(), 90) + EgtMovePartInRawPart( Pz, ( vtEccOri - vtEccRot)) + end + -- aggiorno la lunghezza residua della barra + Len = Len - CrawLen + -- aggiorno grezzo precedente + nPrevRaw = nRaw + dPrevDelta = Delta + else + local sOut = 'Error: part L(' .. EgtNumToString( PartLen, 1) .. ') too big for raw part L(' .. EgtNumToString( Len - 0.1, 1) .. ')' + return false, sOut + end + -- se rimasto troppo poco grezzo, esco + --if Len < BD.MinRaw then break end + DeltaS = 0 + end + if nPrevRaw then + EgtSetInfo( nPrevRaw, 'BDST', 10000) + end + + -- Se rimasto materiale aggiungo grezzo dell'avanzo + if Len > 10 then + local nRaw = EgtAddRawPart( Point3d(0,0,0), Len, dRawW, dRawH, BD.RAWCOL) + EgtMoveToCornerRawPart( nRaw, BD.OriXR, BD.PosXR) + EgtMoveRawPart( nRaw, Vector3d( Len - dRawL, 0, 0)) + -- assegno ordine in lavorazione + Cnt = Cnt + 1 + EgtSetInfo( nRaw, 'ORD', Cnt) + end + + return true +end + +------------------------------------------------------------------------------------------------------------- +function BeamExec.CalcMinUnloadableRaw( dRawW, dRawH) + if BD.GetMinUnloadableRaw then + BD.MinRaw = BD.GetMinUnloadableRaw( dRawW, dRawH) + else + local H_S = 200 + local H_L = 400 + -- Determinazione minimo grezzo scaricabile + if dRawH <= H_S then + BD.MinRaw = BD.MINRAW_S + elseif dRawH <= H_L then + local Coeff = ( dRawH - H_S) / ( H_L - H_S) + BD.MinRaw = ( 1 - Coeff) * BD.MINRAW_S + Coeff * BD.MINRAW_L + else + BD.MinRaw = BD.MINRAW_L + end + end +end + +------------------------------------------------------------------------------------------------------------- +-- *** Inserimento delle lavorazioni nelle travi *** +------------------------------------------------------------------------------------------------------------- + +local function GetStrategiesFromGlobalList( Proc) + -- cerco tra le feature + for i = 1, #STRATEGIES.Features do + -- se trovo la feature + if Proc.Prc == STRATEGIES.Features[i].Prc and Proc.Grp == STRATEGIES.Features[i].Grp then + -- cerco tra le topologie + for j = 1, #STRATEGIES.Features[i].Topologies do + -- se trovo la topologia + if Proc.Topology.Name == #STRATEGIES.Features[i].Topologies[j].Name then + -- ritorno le strategie disponibili per la feature che sto analizzando + return STRATEGIES.Features[i].Topologies[j].Strategies + end + end + end + end + return nil +end + +------------------------------------------------------------------------------------------------------------- +local function GetStrategies( Proc) + local AvailableStrategiesForProc = {} + -- se la lista STRATEGIES è stata letta da JSON (quindi non è vuota), ritorno le strategie possibili + if STRATEGIES then + AvailableStrategiesForProc = GetStrategiesFromGlobalList( Proc) + -- altrimenti lancio script che setta le strategie in modo statico, come definito con cliente + else + AvailableStrategiesForProc = BCS.GetStrategiesFromBasicCustomerStrategies( Proc) + end + -- TODO se ci sono strategie, posso caricare qui le varie librerie delle strategie + return AvailableStrategiesForProc +end + +------------------------------------------------------------------------------------------------------------- +local function GetFeatureForcedStrategy( Proc) + local ForcedStrategiesForProc = {} + local ForcedStrategyForProc = {} + local ForcedParametersForProc = {} + local ForcedParameter = {} + local sStrategyID = EgtGetInfo( Proc.Id, 'STRATEGY', 's') + -- se è presente la strategia forzata + if sStrategyID then + -- importo JSON della strategia per leggere nomi parametri configurabili + local sJSONFile = BEAM.BASEDIR .. '\\Strategies\\' .. sStrategyID .. '\\' .. sStrategyID .. '.lua' + -- se non trovo file esco + if not sJSONFile then return end + + local JSONStrategy = {} + JSONStrategy = ImportFileJSON( sJSONFile) + + -- cerco tra le feature del JSON strategia + for i = 1, #JSONStrategy.Features do + -- se trovo la feature + if Proc.Prc == JSONStrategy.Features[i].Prc and Proc.Grp == JSONStrategy.Features[i].Grp then + -- cerco tra le topologie + for j = 1, #JSONStrategy.Features[i].Topologies do + -- se trovo la topologia + if Proc.Topology.Name == JSONStrategy.Features[i].Topologies[j].Name then + -- leggo i parametri + for k = 1, #JSONStrategy.Features[i].Topologies[j].Parameters do + local sParameterNameToSearch = sStrategyID .. '_' .. JSONStrategy.Features[i].Topologies[j].Parameters[k].Name + -- leggo i parametri configurabili della strategia sulla Proc + local xValue = EgtGetInfo( Proc.Id, sParameterNameToSearch, JSONStrategy.Features[i].Topologies[j].Parameters[k].Type) + -- salvo in lista il parametro letto se presente, altrimenti prendo quello nel JSON di default. Teoricamernte dovrebbero esserci sempre tutti + if xValue then + ForcedParameter.Value = xValue + else + ForcedParameter.Value = JSONStrategy.Features[i].Topologies[j].Parameters[k].Name + end + ForcedParameter.Name = JSONStrategy.Features[i].Topologies[j].Parameters[k].Name + table.insert( ForcedStrategyForProc, ForcedParameter) + end + end + end + end + end + + ForcedStrategyForProc.StrategyID = sStrategyID + ForcedStrategyForProc.Parameters = ForcedParametersForProc + -- per il momento sarà sempre e solo una strategia, ma la inserisco comunque in una lista per analogia con gestione standard + table.insert( ForcedStrategiesForProc, ForcedStrategyForProc) + else + ForcedStrategiesForProc = nil + end + + return ForcedStrategiesForProc +end + +------------------------------------------------------------------------------------------------------------- +local function CollectFeatures( PartId, b3Raw) + -- recupero le feature + local vProc = {} + local LayerId = {} + LayerId[1] = BL.GetAddGroup( PartId) + LayerId[2] = EgtGetFirstNameInGroup( PartId or GDB_ID.NULL, 'Processings') + for nInd = 1, 2 do + local ProcId = EgtGetFirstInGroup( LayerId[nInd] or GDB_ID.NULL) + while ProcId do + local nEntType = EgtGetType( ProcId) + if nEntType == GDB_TY.SRF_MESH or nEntType == GDB_TY.EXT_TEXT or + nEntType == GDB_TY.CRV_LINE or nEntType == GDB_TY.CRV_ARC or nEntType == GDB_TY.CRV_BEZ or nEntType == GDB_TY.CRV_COMPO then + local nGrp = EgtGetInfo( ProcId, 'GRP', 'i') + local nPrc = EgtGetInfo( ProcId, 'PRC', 'i') + local nDo = EgtGetInfo( ProcId, 'DO', 'i') or 1 + local nCutId = EgtGetInfo( EgtGetParent( EgtGetParent( ProcId)), 'CUTID', 'i') or 0 + local nTaskId = EgtGetInfo( ProcId, 'TASKID', 'i') or 0 + -- leggo se ci sono feature collegate + local nAddAdjId = EgtGetInfo( ProcId, 'ADJID', 'i') + local nAddMainId = EgtGetInfo( ProcId, 'MAINID', 'i') + if nGrp and nPrc and nDo == 1 then + local Proc = {} + Proc.PartId = PartId + Proc.Id = ProcId + -- id della feature btl ( se non presente info, si prende id dell'entità geometrica) + Proc.FeatureId = EgtGetInfo( Proc.Id, 'PRID', 's') or Proc.Id + Proc.Grp = nGrp + Proc.Prc = nPrc + Proc.Flg = 1 + Proc.Fct = EgtSurfTmFacetCount( ProcId) or 0 + Proc.CutId = nCutId + Proc.TaskId = nTaskId + -- se ci sono feature collegate ne scrivo il riferimento nella Proc + if nAddAdjId then + Proc.AdjId = Proc.Id + nAddAdjId + elseif nAddMainId then + Proc.MainId = Proc.Id + nAddMainId + end + Proc.Box = EgtGetBBoxGlob( ProcId, GDB_BB.STANDARD) + -- se esiste la geometria + if Proc.Box and not Proc.Box:isEmpty() then + -- TODO fare una funzione per recuperare i dati delle feature che non passano dal calcolo della topologia? + -- se foro calcolo altri dati + if ID.IsDrilling( Proc) then + -- assegno diametro e facce di ingresso e uscita (dati tabelle sempre per riferimento) + Proc.Diam, Proc.Len, Proc.Fcs, Proc.Fce = FD.GetDataDrill( Proc) + end + -- si recupera la topologia della feature + Proc.Topology = FD.GetTopology( Proc, b3Raw) + -- se topologia feature riconosciuta, oppure da non calcolare perchè il riconoscimento topologico è basato sulla feature stessa + if Proc.Topology.Name ~= 'NOT_IMPLEMENTED' then + -- TODO Funzione 'GetMainFaces' da scrivere + Proc.MainFaces = FD.GetMainFaces( Proc) + -- se la processing ha una strategia forzata, riporto tutto nella proc + local vForcedStrategy = GetFeatureForcedStrategy( Proc) + if vForcedStrategy then + Proc.Strategies = vForcedStrategy + -- altrimenti cerco tra le strategie disponibili + else + Proc.Strategies = GetStrategies( Proc) + end + -- se ci sono strategie disponibili, aggiungo a lista delle feature da lavorare + if Proc.Strategies then + table.insert( vProc, Proc) + -- altrimenti errore (non ci sono strategie per lavorare la topologia riconosciuta) + else + EgtOutLog( ' Feature ' .. tostring( Proc.FeatureId) .. ' : NO available strategies') + end + -- altrimenti errore (serviva riconoscimento topologico, ma non è stato possibile farlo) + else + EgtOutLog( ' Feature ' .. tostring( Proc.FeatureId) .. ' : NO available strategies') + end + else + Proc.Flg = 0 + table.insert( vProc, Proc) + EgtOutLog( ' Feature ' .. tostring( Proc.FeatureId) .. ' is empty (no geometry)') + end + end + end + ProcId = EgtGetNext( ProcId) + end + end + return vProc +end + +------------------------------------------------------------------------------------------------------------- +local function GetFeatureInfoAndDependency( vProc, b3Raw) + -- ciclo tutte le feature + for i = 1, #vProc do + local Proc = vProc[i] + -- controllo la feature con tutte le altre per recuperare le dipendenze + for j = 1, #vProc do + -- non si controlla la feature con se stessa + if i ~= j then + local ProcB = vProc[j] + -- verifico se feature tipo LapJoint è attraversata da almeno un foro + if ( Proc.Topology.Family == 'Pocket' or Proc.Topology.Family == 'Tunnel' or Proc.Topology.Family == 'Groove' or ID.IsMortise( Proc)) and + ID.IsDrilling( ProcB) and Overlaps( Proc.Box, ProcB.Box) then + Proc.PassedByHole = true + end + -- verifiche per specchiature + if BD.DOWN_HEAD or BD.TWO_EQUAL_HEADS then + -- forature + if BD.DOUBLE_HEAD_DRILLING and ID.IsDrilling( Proc) and ID.IsDrilling( ProcB) and not Proc.Mirror then + if AreDrillingsMirrored( Proc, ProcB, b3Raw) then + Proc.Mirror = ProcB + end + end + end + end + end + end +end + +------------------------------------------------------------------------------------------------------------- +function BeamExec.ProcessFeatures() + -- ciclo sui pezzi + local nTotErr = 0 + local Stats = {} + local nOrd = 1 + local nRawId = EgtGetFirstRawPart() + while nRawId do + -- verifico che il grezzo contenga pezzi oppure sia abbastanza lungo da essere scaricato coi carrelli + local nPartId = EgtGetFirstPartInRawPart( nRawId) + if not nPartId and EgtGetRawPartBBox( nRawId):getDimX() < BD.MinRaw then break end + -- aggiungo la fase, se non è la prima + if nOrd == 1 then + EgtSetCurrPhase( 1) + else + BL.AddPhaseWithRawParts( nRawId, BD.OriXR, BD.PosXR, 0) + end + local nPhase = EgtGetCurrPhase() + local nDispId = EgtGetPhaseDisposition( nPhase) + EgtSetInfo( nDispId, 'TYPE', EgtIf( nPartId, 'START', 'REST')) + EgtSetInfo( nDispId, 'ORD', nOrd) + EgtOutLog( ' *** Phase=' .. tostring( nPhase) .. ' Raw=' .. tostring( nRawId) .. ' Part=' .. tostring( nPartId) .. ' ***', 1) + -- ingombro del grezzo + local b3Raw = EgtGetRawPartBBox( nRawId) + -- recupero le feature di lavorazione della trave + local vProc = CollectFeatures( nPartId, b3Raw) + -- recupero informazioni ausiliarie feature e dipendenze tra feature stesse + GetFeatureInfoAndDependency( vProc, b3Raw) + + -- TODO ordinare feature e decidere spezzoni + -- TODO applicare lavorazioni in base a strategie disponibili (prima applicabile o EgalwareIA in base a parametro) + -- TODO riordinare lavorazioni ottimizzando cambio utensile/spezzone ecc..., mantenendo dipendenze definite prima + + + EgtOutLog( ' *** End AddMachinings ***', 1) + -- passo al grezzo successivo + nOrd = nOrd + 1 + nRawId = EgtGetNextRawPart( nRawId) + end + + return ( nTotErr == 0), Stats +end + +------------------------------------------------------------------------------------------------------------- +return BeamExec diff --git a/LuaLibs/BeamLib.lua b/LuaLibs/BeamLib.lua new file mode 100644 index 0000000..e2f5142 --- /dev/null +++ b/LuaLibs/BeamLib.lua @@ -0,0 +1,196 @@ +-- BeamLib.lua by Egalware s.r.l. 2024/04/02 +-- Libreria globale per Travi +-- 2024/04/02 PRIMA VERSIONE CALCOLO LAVORAZIONI CON STRATEGIE + + +-- Tabella per definizione modulo +local BeamLib = {} + +-- Include +require( 'EgtBase') + +EgtOutLog( ' BeamLib started', 1) + +-- Dati +local BD = require( 'BeamData') + +------------------------------------------------------------------------------------------------------------- +function BeamLib.AddPartStartFace( PartId, b3Solid) + -- recupero gruppo per geometria aggiuntiva + local AddGrpId = BeamLib.GetAddGroup( PartId) + if not AddGrpId then + local sErr = 'Error on process StartFace impossible to find AddGroup' + EgtOutLog( sErr) + return false, sErr + end + -- aggiungo nuovo taglio iniziale + local nStmId = EgtSurfTmPlaneInBBox( AddGrpId, b3Solid:getMax(), X_AX(), b3Solid, GDB_RT.GLOB) + if not nStmId then + local sErr = 'Error on process StartFace impossible to create Face' + EgtOutLog( sErr) + return false, sErr + end + -- applico gli opportuni attributi di feature + EgtSetName( nStmId, 'StartCut') + EgtSetInfo( nStmId, 'GRP', 1) + EgtSetInfo( nStmId, 'PRC', 340) + -- verifico se sostituisce un taglio di testa già presente + local nProcId = EgtGetFirstInGroup( EgtGetFirstNameInGroup( PartId, 'Processings') or GDB_ID.NULL) + while nProcId do + local nGrp = EgtGetInfo( nProcId, 'GRP', 'i') or 0 + local nProc = EgtGetInfo( nProcId, 'PRC', 'i') or 0 + if ( nGrp == 1 or nGrp == 2) and nProc == 10 then + local ptC, vtN = EgtSurfTmFacetCenter( nProcId, 0, GDB_ID.ROOT) + if ptC and vtN and AreSameVectorApprox( vtN, X_AX()) and abs( ptC:getX() - b3Solid:getMax():getX()) < 10 * GEO.EPS_SMALL then + EgtSetInfo( nStmId, 'ORI', nProcId) + end + end + nProcId = EgtGetNext( nProcId) + end + return true +end + +------------------------------------------------------------------------------------------------------------- +function BeamLib.AddPartEndFace( PartId, b3Solid) + -- recupero gruppo per geometria aggiuntiva + local AddGrpId = BeamLib.GetAddGroup( PartId) + if not AddGrpId then + local sErr = 'Error on process EndFace impossible to find AddGroup' + EgtOutLog( sErr) + return false, sErr + end + -- aggiungo nuovo taglio finale + local nStmId = EgtSurfTmPlaneInBBox( AddGrpId, b3Solid:getMin(), -X_AX(), b3Solid, GDB_RT.GLOB) + if not nStmId then + local sErr = 'Error on process EndFace impossible to create Face' + EgtOutLog( sErr) + return false, sErr + end + -- applico gli opportuni attributi di feature + EgtSetName( nStmId, 'EndCut') + EgtSetInfo( nStmId, 'GRP', 2) + EgtSetInfo( nStmId, 'PRC', 350) + -- verifico se sostituisce un taglio di coda già presente + local nProcId = EgtGetFirstInGroup( EgtGetFirstNameInGroup( PartId, 'Processings') or GDB_ID.NULL) + while nProcId do + local nGrp = EgtGetInfo( nProcId, 'GRP', 'i') or 0 + local nProc = EgtGetInfo( nProcId, 'PRC', 'i') or 0 + if ( nGrp == 1 or nGrp == 2) and nProc == 10 then + local ptC, vtN = EgtSurfTmFacetCenter( nProcId, 0, GDB_ID.ROOT) + if ptC and vtN and AreSameVectorApprox( vtN, -X_AX()) and abs( ptC:getX() - b3Solid:getMin():getX()) < 10 * GEO.EPS_SMALL then + EgtSetInfo( nStmId, 'ORI', nProcId) + end + end + nProcId = EgtGetNext( nProcId) + end + return true +end + +------------------------------------------------------------------------------------------------------------- +function BeamLib.AddPhaseWithRawParts( nFirstRawId, OriXR, PosXR, dDeltaSucc) + EgtAddPhase() + local nRawId = nFirstRawId + local dRawMove = 0 + while nRawId do + EgtKeepRawPart( nRawId) + EgtMoveToCornerRawPart( nRawId, OriXR, PosXR) + EgtMoveRawPart( nRawId, Vector3d( - dRawMove, 0, 0)) + if dRawMove == 0 then dRawMove = dRawMove + dDeltaSucc end + dRawMove = dRawMove + EgtGetRawPartBBox( nRawId):getDimX() + nRawId = EgtGetNextRawPart( nRawId) + end +end + +------------------------------------------------------------------------------------------------------------- +function BeamLib.CreateOrEmptyAddGroup( PartId) + -- recupero i dati del gruppo aggiuntivo + local AddGrpId, sMchGrp = BeamLib.GetAddGroup( PartId) + if not sMchGrp then return false end + -- se esiste, aggiorno riferimento al gruppo di lavoro e lo svuoto + if AddGrpId then + EgtSetInfo( AddGrpId, GDB_SI.MGRPONLY, EgtGetCurrMachGroup()) + return EgtEmptyGroup( AddGrpId) + end + -- altrimenti lo creo + AddGrpId = EgtGroup( PartId or GDB_ID.NULL) + if not AddGrpId then return false end + -- assegno nome, flag di layer per gruppo di lavoro e colore + EgtSetName( AddGrpId, sMchGrp) + EgtSetInfo( AddGrpId, GDB_SI.MGRPONLY, EgtGetCurrMachGroup()) + EgtSetColor( AddGrpId, Color3d( 80, 160, 160, 50)) + return true +end + +------------------------------------------------------------------------------------------------------------- +function BeamLib.GetAddGroup( PartId) + -- recupero il nome del gruppo di lavoro corrente + local sMchGrp = EgtGetMachGroupName( EgtGetCurrMachGroup() or GDB_ID.NULL) + if not sMchGrp then return nil, nil end + -- cerco il gruppo aggiuntivo omonimo nel pezzo e se esiste lo restituisco + local AddGrpId = EgtGetFirstNameInGroup( PartId or GDB_ID.NULL, sMchGrp) + -- restituisco Id e Nome + return AddGrpId, sMchGrp +end + +------------------------------------------------------------------------------------------------------------- +-- restituisce le facce della parte interessate dalla feature Proc +function BeamLib.GetProcessAffectedFaces( Proc) + local nBoxSolidId = EgtGetFirstNameInGroup( Proc.PartId or GDB_ID.NULL, 'Box') + local b3Part = EgtGetBBoxGlob( nBoxSolidId, GDB_BB.STANDARD) + local vtFacesAffected = { Top = false, Bottom = false, Front = false, Back = false, Left = false, Right = false} + if Proc.Box and not Proc.Box:isEmpty() then + if Proc.Box:getMax():getZ() > b3Part:getMax():getZ() - 500 * GEO.EPS_SMALL then + vtFacesAffected.Top = true + end + if Proc.Box:getMin():getZ() < b3Part:getMin():getZ() + 500 * GEO.EPS_SMALL then + vtFacesAffected.Bottom = true + end + if Proc.Box:getMin():getY() < b3Part:getMin():getY() + 500 * GEO.EPS_SMALL then + vtFacesAffected.Front = true + end + if Proc.Box:getMax():getY() > b3Part:getMax():getY() - 500 * GEO.EPS_SMALL then + vtFacesAffected.Back = true + end + if Proc.Box:getMin():getX() < b3Part:getMin():getX() + 500 * GEO.EPS_SMALL then + vtFacesAffected.Left = true + end + if Proc.Box:getMax():getX() > b3Part:getMax():getX() - 500 * GEO.EPS_SMALL then + vtFacesAffected.Right = true + end + end + + return vtFacesAffected +end + +--------------------------------------------------------------------- +-- Funzione per determinare se la faccia ha lati molto corti (trascurabili) ed è quindi approssimabile ad una 3 facce +function BeamLib.Is3EdgesApprox( Proc, nFacet, nAddGrpId) + nAddGrpId = nAddGrpId or BeamLib.GetAddGroup( Proc.PartId) + if not nAddGrpId then + local nEdges = #(EgtSurfTmFacetAdjacencies( Proc.Id, nFacet)[1]) + return ( nEdges == 3) + end + local bResult = false + local nContourId, nContourCnt = EgtExtractSurfTmFacetLoops( Proc.Id, nFacet, nAddGrpId) + if not nContourId then return false end + EgtMergeCurvesInCurveCompo( nContourId) + -- recupero il numero effettivo di lati + local _, nEntityCount = EgtCurveDomain( nContourId) + local nEdges = nEntityCount + if nEntityCount and nEntityCount == 3 then + bResult = true + -- rimuovo i lati molto corti dal conteggio totale + elseif nEntityCount then + for i = 1, nEntityCount do + local dLength = EgtCurveCompoLength( nContourId, i - 1) + if dLength < 15 then nEdges = nEdges - 1 end + end + end + if nEdges == 3 then bResult = true end + -- cancello tutti i contorni appena creati + EgtErase( EgtTableFill( nContourId, nContourCnt)) + return bResult +end + +------------------------------------------------------------------------------------------------------------- +return BeamLib diff --git a/LuaLibs/FeatureData.lua b/LuaLibs/FeatureData.lua new file mode 100644 index 0000000..4fb67f6 --- /dev/null +++ b/LuaLibs/FeatureData.lua @@ -0,0 +1,295 @@ +-- FeatureData.lua by Egalware s.r.l. 2024/04/02 +-- Libreria lettura o calcolo dati e proprietà della feature +-- 2024/04/02 PRIMA VERSIONE CALCOLO LAVORAZIONI CON STRATEGIE + +-- Tabella per definizione modulo +local FeatureData = {} + +-- Carico i dati globali +local BD = require( 'BeamData') + +-- carico librerie +local BL = require( 'BeamLib') +local ID = require( 'Identity') + + +------------------------------------------------------------------------------------------------------------- +-- recupero topologia della feature +------------------------------------------------------------------------------------------------------------- +local function NeedTopologyFeature( Proc) + -- richiedono calcolo topologia le feature tipo: + if ID.IsCut( Proc) then + return true + elseif ID.IsDoubleCut( Proc) then + return true + elseif ID.IsSawCut( Proc) then + return true + elseif ID.IsLongitudinalCut( Proc) then + return true + elseif ID.IsDoubleLongitudinalCut( Proc) then + return true + elseif ID.IsChamfer( Proc) then + return true + elseif ID.IsSlot( Proc) then + return true + elseif ID.IsFrontSlot( Proc) then + return true + elseif ID.IsRidgeLap( Proc) then + return true + elseif ID.IsLapJoint( Proc) then + return true + elseif ID.IsNotchRabbet( Proc) then + return true + elseif ID.IsNotch( Proc) then + return true + elseif ID.IsPocket( Proc) then + return true + elseif ID.IsMortise( Proc) and Proc.Fct < 6 then -- calcolo topologia SOLO se non raggiata -- TODO oppure riconoscerla come feature speciale + return true + elseif ID.IsFrontMortise( Proc) and Proc.Fct < 6 then -- calcolo topologia SOLO se non raggiata -- TODO oppure riconoscerla come feature speciale + return true + end + -- tutte le altre non richiedono calcolo topologia + return false +end + +--------------------------------------------------------------------- +-- restituisce la matrice delle adiacenze di Proc dove i e j sono le facce e a(ij) è l'angolo tra di esse; 0 se nessuna adiacenza +local function GetAdjacencyMatrix( Proc) + local vAdj = {} + -- essendo la matrice simmetrica a diagonale nulla, ne calcolo solo la metà superiore + for i = 1, Proc.Fct do + vAdj[i] = {} + for j = i + 1, Proc.Fct do + _, _, _, vAdj[i][j] = EgtSurfTmFacetsContact( Proc.Id, i - 1, j - 1, GDB_ID.ROOT) + if not vAdj[i][j] then vAdj[i][j] = 0 end + end + end + -- riempio di conseguenza il resto della matrice + for i = 1, Proc.Fct do + vAdj[i][i] = 0 + for j = i + 1, Proc.Fct do + vAdj[j][i] = vAdj[i][j] + end + end + return vAdj +end + +--------------------------------------------------------------------- +-- restituisce true se Proc ha tutti gli angoli concavi (bAllConcave) e, nei casi in cui ha senso, se questi sono esattamente 90 deg (bAllRight) +local function AreAllAnglesConcaveOrRight( vAdj) + local bAllConcave, bAllRight = true, true + local nFct = #( vAdj or {}) + for i = 1, nFct do + for j = 1, nFct do + -- se trovo un angolo convesso restituisco falso e esco subito + if vAdj[i][j] and vAdj[i][j] > 0 then + bAllConcave = false + bAllRight = false + break + elseif vAdj[i][j] and vAdj[i][j] ~= 0 and vAdj[i][j] + 90 > 500 * GEO.EPS_ANG_SMALL then + bAllRight = false + end + end + end + -- se 1 faccia oppure 2 facce con angolo convesso non ha senso ritornare valori per bAllRight + if nFct < 2 or ( nFct == 2 and vAdj[1][2] > 0) then + return bAllConcave + else + return bAllConcave, bAllRight + end +end + +--------------------------------------------------------------------- +-- retituisce un vettore con gli indici (0 based) delle facce triangolari (o quasi) di Proc +local function GetTriangularFaces( Proc) + local vTriangularFaces = {} + for i = 1, Proc.Fct do + if BL.Is3EdgesApprox( Proc, i - 1) then + table.insert( vTriangularFaces, i - 1) + end + end + return vTriangularFaces +end + +--------------------------------------------------------------------- +-- restituisce true se almeno una delle dimensioni della feature è maggiore o uguale ad una delle dimensioni principali del pezzo (tolleranza 1 mm) +local function IsAnyDimensionLongAsPart( Proc) + local bResult = false + local nBoxSolidId = EgtGetFirstNameInGroup( Proc.PartId or GDB_ID.NULL, 'Box') + local b3Solid = EgtGetBBoxGlob( nBoxSolidId, GDB_BB.STANDARD) + if Proc.Box:getDimX() > b3Solid:getDimX() - 1000 * GEO.EPS_SMALL or + Proc.Box:getDimY() > b3Solid:getDimY() - 1000 * GEO.EPS_SMALL or + Proc.Box:getDimZ() > b3Solid:getDimZ() - 1000 * GEO.EPS_SMALL then + bResult = true + end + return bResult +end + +--------------------------------------------------------------------- +-- restituisce gli id delle facce di Proc che hanno il numero di adiacenze nAdj +local function GetFacesWithGivenAdjacencyNumber( Proc, vAdj) + if not vAdj then vAdj = GetAdjacencyMatrix( Proc) end + local nFct = #( vAdj or {}) + local vFacesWithAdj = {} + for i = 1, nFct do + local nAdjCount = 0 + for j = 1, nFct do + if vAdj[i][j] and vAdj[i][j] ~= 0 and i ~= j then + nAdjCount = nAdjCount + 1 + end + end + if nAdjCount > 0 then + table.insert( vFacesWithAdj[nAdjCount], i - 1) + end + end + return vFacesWithAdj +end + +------------------------------------------------------------------------------------------------------------- +-- restituisce vero se la feature con box b3Proc taglia l'intera sezione della barra, rappresentata dalle sue dimensioni W e H +local function IsFeatureCuttingEntireSection( b3Proc, b3Raw) + return ( b3Proc:getDimY() > ( b3Raw:getDimY() - 500 * GEO.EPS_SMALL) and b3Proc:getDimZ() > ( b3Raw:getDimZ() - 500 * GEO.EPS_SMALL)) +end + +------------------------------------------------------------------------------------------------------------- +-- restituisce vero se la feature con box b3Proc taglia l'intera lunghezza della barra, rappresentata dalle sue dimensioni W e L oppure H e L +local function IsFeatureCuttingEntireLength( b3Proc, b3Raw) + return ( ( b3Proc:getDimY() > ( b3Raw:getDimY() - 500 * GEO.EPS_SMALL) and b3Proc:getDimX() > ( b3Raw:getDimX() - 500 * GEO.EPS_SMALL)) or + ( b3Proc:getDimZ() > ( b3Raw:getDimZ() - 500 * GEO.EPS_SMALL) and b3Proc:getDimX() > ( b3Raw:getDimX() - 500 * GEO.EPS_SMALL))) +end + +--------------------------------------------------------------------- +-- restituisce una stringa con il nome esteso della topologia della feature +-- *famiglia - numero di facce - passante* +local function GetTopologyName( sFamily, nNumberOfFaces, bIsThrough) + return sFamily .. '-' .. nNumberOfFaces .. '-' .. EgtIf( bIsThrough, 'Through', 'Blind') +end +--------------------------------------------------------------------- +-- recupera topologia feature +local function ClassifyTopology( Proc, b3Raw) + local FeatureTopology = {} + + -- calcoli + if not Proc.AffectedFaces then Proc.AffectedFaces = BL.GetProcessAffectedFaces( Proc) end + + local vAdj = GetAdjacencyMatrix( Proc) + local bAllAnglesConcave, bAllRightAngles = AreAllAnglesConcaveOrRight( vAdj) + local vTriangularFaces = GetTriangularFaces( Proc) + local bIsAnyDimensionLongAsPart = IsAnyDimensionLongAsPart( Proc) + local vFacesWithAdjNumber = GetFacesWithGivenAdjacencyNumber( Proc, vAdj) + local bIsFeatureCuttingEntireSection = IsFeatureCuttingEntireSection( Proc.Box, b3Raw) + local bIsFeatureCuttingEntireLength = IsFeatureCuttingEntireLength( Proc.Box, b3Raw) + + -- assegnazione tipologia + local sFamily + local bIsThrough + if Proc.Fct == 1 and ( bIsFeatureCuttingEntireSection or bIsFeatureCuttingEntireLength) then + sFamily = 'Cut' + elseif Proc.Fct == 1 then + sFamily = 'Bevel' + bIsThrough = true + elseif Proc.Fct == 2 and bAllAnglesConcave and #vTriangularFaces == 1 then + sFamily = 'Bevel' + bIsThrough = false + elseif Proc.Fct == 2 and bAllAnglesConcave and ( Proc.AffectedFaces.Left or Proc.AffectedFaces.Right) and ( Proc.AffectedFaces.Front or Proc.AffectedFaces.Back) then + sFamily = 'Rabbet' + bIsThrough = true + elseif Proc.Fct == 2 and bAllAnglesConcave then + sFamily = 'V-Groove' + bIsThrough = true + elseif Proc.Fct == 2 and not bAllAnglesConcave and bIsAnyDimensionLongAsPart then + sFamily = 'DoubleBevel' + bIsThrough = true + elseif Proc.Fct == 3 and bAllAnglesConcave and #vFacesWithAdjNumber[2] == 1 and #vTriangularFaces == 2 then + sFamily = 'Bevel' + bIsThrough = false + elseif Proc.Fct == 3 and bAllAnglesConcave and #vFacesWithAdjNumber[2] == 1 and bIsAnyDimensionLongAsPart then + sFamily = 'Groove' + bIsThrough = true + elseif Proc.Fct == 3 and bAllAnglesConcave and #vFacesWithAdjNumber[2] == 3 then + sFamily = 'Groove' + bIsThrough = false + elseif Proc.Fct == 4 and #vFacesWithAdjNumber[2] == 4 and #vTriangularFaces == 2 then + sFamily = 'DoubleBevel' + bIsThrough = false + elseif Proc.Fct == 4 and bAllAnglesConcave and #vFacesWithAdjNumber[3] == 2 then + sFamily = 'Groove' + bIsThrough = false + elseif Proc.Fct == 4 and bAllAnglesConcave and #vFacesWithAdjNumber[2] == 4 and bIsAnyDimensionLongAsPart then + sFamily = 'Tunnel' + bIsThrough = true + elseif Proc.Fct >= 4 and #vFacesWithAdjNumber[1] == 2 and bIsAnyDimensionLongAsPart then + sFamily = 'Strip' + bIsThrough = true + elseif Proc.Fct == 5 and bAllAnglesConcave and #vFacesWithAdjNumber[4] == 1 then + sFamily = 'Pocket' + bIsThrough = false + elseif Proc.Fct == 6 and #vFacesWithAdjNumber[2] == 4 and #vFacesWithAdjNumber[3] == 2 and #vTriangularFaces == 4 then + sFamily = 'DoubleBevel' + bIsThrough = false + end + + -- assegnazioni + if sFamily then + FeatureTopology.Family = sFamily + FeatureTopology.IsThrough = bIsThrough + FeatureTopology.AllRightAngles = bAllRightAngles + FeatureTopology.Name = GetTopologyName( sFamily, bIsThrough, bAllRightAngles) + FeatureTopology.vAdj = vAdj + -- feature che necessita di essere catalogata, ma non si capisce come + else + FeatureTopology.Family = 'NOT_IMPLEMENTED' + FeatureTopology.Name = FeatureTopology.Family + end + return FeatureTopology +end + +------------------------------------------------------------------------------------------------------------- +function FeatureData.GetTopology( Proc, b3Raw) + local FeatureTopology = {} + + -- calcolo topologia solo se necessario, altrimenti si sfruttano le informazioni della feature BTL + if NeedTopologyFeature( Proc) then + FeatureTopology = ClassifyTopology( Proc, b3Raw) + -- se non richiesto, setto 'FEATURE' + else + FeatureTopology.Family = 'FEATURE' + FeatureTopology.Name = FeatureTopology.Family + end + + return FeatureTopology +end + +------------------------------------------------------------------------------------------------------------- +-- recupero facce principali della feature, in base alla topologia +------------------------------------------------------------------------------------------------------------- +function FeatureData.GetMainFaces( Proc, b3Raw) + local MainFaces = {} + + return MainFaces +end +------------------------------------------------------------------------------------------------------------- +-- Recupero dati foro e adattamento se speciale +------------------------------------------------------------------------------------------------------------- +function FeatureData.GetDataDrill( Proc) + local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') + -- verifico se foro da adattare + if EgtExistsInfo( Proc.Id, 'DiamUser') then + if AuxId then AuxId = AuxId + Proc.Id end + if AuxId and EgtGetType( AuxId) == GDB_TY.CRV_ARC and BD.USER_HOLE_DIAM and BD.USER_HOLE_DIAM > 1 then + EgtModifyArcRadius( AuxId, BD.USER_HOLE_DIAM / 2) + end + end + -- recupero diametro e lunghezza + local dDiam = EgtGetInfo( Proc.Id, 'P12', 'd') or 0 + local dLen = abs( EgtCurveThickness( Proc.Id + AuxId)) or 0 + -- recupero faccia di entrata e uscita + local nFcs = EgtGetInfo( Proc.Id, 'FCS', 'i') or 0 + local nFce = EgtGetInfo( Proc.Id, 'FCE', 'i') or 0 + return dDiam, dLen, nFcs, nFce +end + +------------------------------------------------------------------------------------------------------------- + +return FeatureData \ No newline at end of file diff --git a/LuaLibs/Identity.lua b/LuaLibs/Identity.lua new file mode 100644 index 0000000..31fd1e1 --- /dev/null +++ b/LuaLibs/Identity.lua @@ -0,0 +1,255 @@ +-- Identity.lua by Egalware s.r.l. 2024/04/02 +-- Libreria Riconoscimento della feature +-- 2024/04/02 PRIMA VERSIONE CALCOLO LAVORAZIONI CON STRATEGIE + +-- Tabella per definizione modulo +local Identity = {} + +--------------------------------------------------------------------- +-- Feature : Cut +function Identity.IsCut( Proc) + return ( ( Proc.Grp == 1 or Proc.Grp == 2) and Proc.Prc == 10) +end +--------------------------------------------------------------------- +-- Feature : Longitudinal Cut +function Identity.IsLongitudinalCut( Proc) + return (( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 10) +end +--------------------------------------------------------------------- +-- Feature : Double Cut +function Identity.IsDoubleCut( Proc) + return ( ( Proc.Grp == 1 or Proc.Grp == 2) and Proc.Prc == 11) +end +--------------------------------------------------------------------- +-- Feature : Ridge or Valley Cut +function Identity.IsDoubleLongitudinalCut( Proc) + return ( Proc.Grp == 0 and Proc.Prc == 12) +end +--------------------------------------------------------------------- +-- Feature : Saw Cut +function Identity.IsSawCut( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 13) +end +--------------------------------------------------------------------- +-- Feature : Slot +function Identity.IsSlot( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 16) +end +--------------------------------------------------------------------- +-- Feature : Front Slot +function Identity.IsFrontSlot( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 17) +end +--------------------------------------------------------------------- +-- Feature : Birds Mouth +function Identity.IsBirdsMouth( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 20) +end +--------------------------------------------------------------------- +-- Feature : Hip or Valley Rafter Notch +function Identity.IsHipValleyRafterNotch( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 25) +end +--------------------------------------------------------------------- +-- Feature : Ridge Lap +function Identity.IsRidgeLap( Proc) + return ( ( Proc.Grp == 1 or Proc.Grp == 2) and Proc.Prc == 30) +end +--------------------------------------------------------------------- +-- Feature : Lap Joint +function Identity.IsLapJoint( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 30) +end +--------------------------------------------------------------------- +-- Feature : Notch/Rabbet +function Identity.IsNotchRabbet( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 32) +end +--------------------------------------------------------------------- +-- Feature : Block Haus +function Identity.IsBlockHaus( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 33) +end +--------------------------------------------------------------------- +-- Feature : Notch +function Identity.IsNotch( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 34) +end +--------------------------------------------------------------------- +-- Feature : French Ridge Lap +function Identity.IsFrenchRidgeLap( Proc) + return ( ( Proc.Grp == 1 or Proc.Grp == 2) and Proc.Prc == 35) +end +--------------------------------------------------------------------- +-- Feature : Chamfer +function Identity.IsChamfer( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 36) +end +--------------------------------------------------------------------- +-- Feature : Block Haus Half Lap +function Identity.IsHalfBlockHaus( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 37) +end +--------------------------------------------------------------------- +-- Feature : Block Haus Front +function Identity.IsFrontBlockHaus( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 38) +end +--------------------------------------------------------------------- +-- Feature : Pocket +function Identity.IsPocket( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 39) +end +--------------------------------------------------------------------- +-- Feature : Drilling +function Identity.IsDrilling( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 40) +end +--------------------------------------------------------------------- +-- Feature : Tenon +function Identity.IsTenon( Proc) + return ( ( Proc.Grp == 1 or Proc.Grp == 2) and Proc.Prc == 50) +end +--------------------------------------------------------------------- +-- Feature : Mortise +function Identity.IsMortise( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 50) +end +--------------------------------------------------------------------- +-- Feature : Front Mortise +function Identity.IsFrontMortise( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 51) +end +--------------------------------------------------------------------- +-- Feature : House +function Identity.IsHouse( Proc) + return ( ( Proc.Grp == 1 or Proc.Grp == 2) and Proc.Prc == 52) +end +--------------------------------------------------------------------- +-- Feature : House Mortise +function Identity.IsHouseMortise( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 53) +end +--------------------------------------------------------------------- +-- Feature : Dovetail Tenon +function Identity.IsDovetailTenon( Proc) + return ( ( Proc.Grp == 1 or Proc.Grp == 2) and Proc.Prc == 55) +end +--------------------------------------------------------------------- +-- Feature : Dovetail Mortise +function Identity.IsDovetailMortise( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 55) +end +--------------------------------------------------------------------- +-- Feature : Dovetail Mortise Front +function Identity.IsFrontDovetailMortise( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 56) +end +--------------------------------------------------------------------- +-- Feature : Marking +function Identity.IsMarking( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 60) +end +--------------------------------------------------------------------- +-- Feature : Text +function Identity.IsText( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 61) +end +--------------------------------------------------------------------- +-- Feature : Scarf Simple +function Identity.IsScarfSimple( Proc) + return ( ( Proc.Grp == 1 or Proc.Grp == 2) and Proc.Prc == 70) +end +--------------------------------------------------------------------- +-- Feature : Scarf Joint +function Identity.IsScarfJoint( Proc) + return ( ( Proc.Grp == 1 or Proc.Grp == 2) and Proc.Prc == 71) +end +--------------------------------------------------------------------- +-- Feature : Step Joint +function Identity.IsStepJoint( Proc) + return ( ( Proc.Grp == 1 or Proc.Grp == 2) and Proc.Prc == 80) +end +--------------------------------------------------------------------- +-- Feature : Step Joint Notch +function Identity.IsStepJointNotch( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 80) +end +--------------------------------------------------------------------- +-- Feature : Planing +function Identity.IsPlaning( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 90) +end +--------------------------------------------------------------------- +-- Feature : Front Profile +function Identity.IsFrontProfile( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 100) +end +--------------------------------------------------------------------- +-- Feature : Head Concave Profile +function Identity.IsHeadConcaveProfile( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 101) +end +--------------------------------------------------------------------- +-- Feature : Head Convex Profile +function Identity.IsHeadConvexProfile( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 102) +end +--------------------------------------------------------------------- +-- Feature : Head Cambered Profile +function Identity.IsHeadCamberedProfile( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 103) +end +--------------------------------------------------------------------- +-- Feature : Round Arch +function Identity.IsRoundArch( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 104) +end +--------------------------------------------------------------------- +-- Feature : Head Profile +function Identity.IsHeadProfile( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 106) +end +--------------------------------------------------------------------- +-- Feature : Sphere +function Identity.IsSphere( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 107) +end +--------------------------------------------------------------------- +-- Feature : Triangle Cut +function Identity.IsTriangleCut( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 120) +end +--------------------------------------------------------------------- +-- Feature : TyroleanDovetail +function Identity.IsTyroleanDovetail( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 1 or Proc.Grp == 2 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 136) +end +--------------------------------------------------------------------- +-- Feature : Dovetail +function Identity.IsDovetail( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 1 or Proc.Grp == 2 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 138) +end +--------------------------------------------------------------------- +-- Feature : Free Contour +function Identity.IsFreeContour( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 250) +end +--------------------------------------------------------------------- +-- Feature : Outline +function Identity.IsOutline( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 251) +end +--------------------------------------------------------------------- +-- Feature : Aperture +function Identity.IsAperture( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 252) +end +--------------------------------------------------------------------- +-- Feature : Variant +function Identity.IsVariant( Proc) + return ( ( Proc.Grp == 0 or Proc.Grp == 1 or Proc.Grp == 2 or Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 900) +end +--------------------------------------------------------------------- + +return Identity diff --git a/LuaLibs/MachiningLib.lua b/LuaLibs/MachiningLib.lua new file mode 100644 index 0000000..2ce06e3 --- /dev/null +++ b/LuaLibs/MachiningLib.lua @@ -0,0 +1,17 @@ +-- MachiningLib.lua by Egalware s.r.l. 2024/04/02 +-- Libreria ricerca lavorazioni per Travi +-- 2024/04/02 PRIMA VERSIONE CALCOLO LAVORAZIONI CON STRATEGIE + +-- Tabella per definizione modulo +local MachiningLib = {} + +-- Include +require( 'EgtBase') + +EgtOutLog( ' MachiningLib started', 1) + +-- Dati +local BD = require( 'BeamData') + +------------------------------------------------------------------------------------------------------------- +return MachiningLib diff --git a/Process.lua b/Process.lua new file mode 100644 index 0000000..3c824bc --- /dev/null +++ b/Process.lua @@ -0,0 +1,310 @@ +-- Process.lua by Egalware s.r.l. 2024/04/02 +-- Gestione calcolo disposizione e lavorazioni per Travi +-- Si opera sulla macchina corrente +-- 2024/04/02 PRIMA VERSIONE + +-- Intestazioni +require( 'EgtBase') +_ENV = EgtProtectGlobal() +EgtEnableDebug( true) + +-- TODO caricare strategie come librerie +-- Imposto direttorio libreria specializzata per Travi +EgtAddToPackagePath( BEAM.BASEDIR .. '\\LuaLibs\\?.lua') + +-- Verifico che la macchina corrente sia abilitata per la lavorazione delle Travi +local sMachDir = EgtGetCurrMachineDir() +if not sMachDir then + EgtOutBox( 'Errore nel caricamento della macchina corrente', 'Lavora Travi', 'ERROR') + return +end +if not EgtExistsFile( sMachDir .. '\\Beam\\BeamData.lua') then + EgtOutBox( 'La macchina corrente non è configurata per lavorare travi', 'Lavora Travi', 'ERROR') + return +end + +-- Elimino direttori altre macchine e imposto direttorio macchina corrente per ricerca librerie +EgtRemoveBaseMachineDirFromPackagePath() +EgtAddToPackagePath( sMachDir .. '\\Beam\\?.lua') + +-- Segnalazione avvio +EgtOutLog( '*** Beam Process Start ***', 1) + +-- Carico le librerie +_G.package.loaded.BeamExec = nil +_G.package.loaded.BeamLib = nil +_G.package.loaded.BeamData = nil +local BE = require( 'BeamExec') +local BL = require( 'BeamLib') + +-- Carico i dati globali +local BD = require( 'BeamData') + +-- Variabili di modulo +local vBeam = {} +local dRawW +local dRawH + +------------------------------------------------------------------------------------------------------------- +-- *** Recupero le travi selezionate *** +------------------------------------------------------------------------------------------------------------- +local function MyProcessInputData() + + -- Recupero le travi selezionate + local nId = EgtGetFirstSelectedObj() + while nId do + local nPartId = EgtGetParent( EgtGetParent( nId or GDB_ID.NULL) or GDB_ID.NULL) + if nPartId then + local bFound = false + for i = 1, #vBeam do + if vBeam[i].Id == nPartId then + bFound = true + break + end + end + if not bFound then + table.insert( vBeam, { Ind = #vBeam + 1, Id = nPartId, Name = ( EgtGetName( nPartId) or ( 'Id=' .. tonumber( nPartId)))}) + end + end + nId = EgtGetNextSelectedObj() + end + if #vBeam == 0 then + EgtOutBox( 'Non sono state selezionate travi', 'Lavora Travi', 'ERROR') + return false + else + local sOut = '' + for i = 1, #vBeam do + sOut = sOut .. vBeam[i].Name .. ', ' + end + sOut = sOut:sub( 1, -3) + EgtOutLog( 'Travi selezionate : ' .. sOut, 1) + end + + -- Ne recupero e verifico le dimensioni + for i = 1, #vBeam do + local Ls = EgtGetFirstNameInGroup( vBeam[i].Id, 'Box') + local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD) + if not b3Solid then + EgtOutBox( 'Box non definito per la trave ' .. vBeam[i].Name, 'Lavora Travi', 'ERROR') + return false + else + vBeam[i].Box = b3Solid + end + end + dRawW = vBeam[1].Box:getDimY() + dRawH = vBeam[1].Box:getDimZ() + local vBeamErr = {} + for i = 2, #vBeam do + local dDimW = vBeam[i].Box:getDimY() + local dDimH = vBeam[i].Box:getDimZ() + if ( abs( dDimW - dRawW) > 10 * GEO.EPS_SMALL or abs( dDimH - dRawH) > 10 * GEO.EPS_SMALL) and + ( abs( dDimH - dRawW) > 10 * GEO.EPS_SMALL or abs( dDimW - dRawH) > 10 * GEO.EPS_SMALL) then + table.insert( vBeamErr, i) + end + end + if #vBeamErr > 0 then + local sOut = 'Rimosse travi con sezioni diverse dalla prima :\n' + for i = #vBeamErr, 1, -1 do + sOut = sOut .. vBeam[vBeamErr[i]].Name .. '\n' + EgtDeselectPartObjs( vBeam[vBeamErr[i]].Id) + table.remove( vBeam, vBeamErr[i]) + end + EgtOutLog( sOut, 1) + EgtOutBox( sOut, 'Lavora Travi', 'INFO') + EgtDraw() + return false + end + EgtDeselectAll() + + return true +end + + +------------------------------------------------------------------------------------------------------------- +local function GetDataConfig() + -- recupero utensili dal magazzino + BE.GetToolsFromDB() + -- se si utilizza interfaccia B&W, si carica il file JSON + local bIsBeamWall = true -- TODO serve parametro per capire se stiamo utilizzando B&W + if bIsBeamWall then + BE.GetStrategiesFromJSONinBD() + end + -- TODO da gestire eventuali errori bloccanti + return true +end + +------------------------------------------------------------------------------------------------------------- +-- *** Inserimento delle travi nel grezzo *** +------------------------------------------------------------------------------------------------------------- +local function MyProcessBeams() + -- Determinazione minimo grezzo scaricabile + BE.CalcMinUnloadableRaw( dRawW, dRawH) + + -- Lunghezza totale delle travi + local dTotLen = 0 + for i = 1, #vBeam - 1 do + dTotLen = dTotLen + vBeam[i].Box:getDimX() + end + dTotLen = dTotLen + max( vBeam[#vBeam].Box:getDimX(), BD.MinRaw) + local dAddLen = BD.OVM_HEAD + ( #vBeam - 1) * BD.OVM_MID + EgtOutLog( 'Ltot : '..EgtNumToString( dTotLen, 1) .. ' Lagg : '..EgtNumToString( dAddLen, 1)..' MinUnloadRaw : '.. EgtNumToString( BD.MinRaw + BD.OVM_MID, 1), 1) + + -- Richiedo lunghezza del grezzo, sovramateriale di testa, forzatura verticale e ordinamento automatico secondo la lunghezza + local vsVal = EgtDialogBox( 'Lavora Travi' .. ' (Ltot='..EgtNumToString( dTotLen + dAddLen + 0.5, 0).. + ', Lmax='..EgtNumToString( BD.MAX_RAW, 0)..',MinUlr='..EgtNumToString( BD.MinRaw + BD.OVM_MID, 0)..')', + {'Lunghezza grezzo', EgtNumToString( BD.STD_RAW, 0)}, + {'Sovramateriale di testa', EgtNumToString( BD.OVM_HEAD, 0)}, + {'Offset intermedio', EgtNumToString( BD.OVM_MID, 0)}, + {'Forza sezione verticale', ' CB:true,*false'}, + {'Ordina per lunghezza', ' CB:true,*false'}, + {'Calcolo Lavorazioni', ' CB:*Da progetto,Ricalcolo standard,Ricalcolo IA'}) + if not vsVal then + EgtDraw() + return + end + local dRawL = EgtEvalNumExpr( vsVal[1]) + if not dRawL then + local sOut = 'Lunghezza grezzo errata : ' .. vsVal[1] + EgtOutLog( sOut) + EgtOutBox( sOut, 'Lavora Travi', 'WARNING') + EgtDraw() + return false + end + if dRawL < GEO.EPS_SMALL then dRawL = dTotLen + dAddLen + 0.5 end + dRawL = min( dRawL, BD.MAX_RAW) + local dOvmHead = EgtEvalNumExpr( vsVal[2]) + if not dOvmHead then + local sOut = 'Sovramateriale di testa errato : ' .. vsVal[2] + EgtOutLog( sOut) + EgtOutBox( sOut, 'Lavora Travi', 'WARNING') + EgtDraw() + return false + end + local dOvmMid = EgtEvalNumExpr( vsVal[3]) + if not dOvmMid then + local sOut = 'Offset intermedio : ' .. vsVal[3] + EgtOutLog( sOut) + EgtOutBox( sOut, 'Lavora Travi', 'WARNING') + EgtDraw() + return false + end + + -- Sistemo sezione barra con travi + local bVert = ( vsVal[4] == 'true') + if bVert then + if dRawW > dRawH then dRawW, dRawH = dRawH, dRawW end + end + EgtOutLog( 'Lraw : ' .. EgtNumToString( dRawL, 1) .. ' Lovm : '.. EgtNumToString( dOvmHead, 1), 1) + + -- Verifico sezione barra non troppo grande + if not BD.MAX_WIDTH2 or not BD.MAX_HEIGHT2 then + if ( dRawW > BD.MAX_WIDTH + 10 * GEO.EPS_SMALL or dRawH > BD.MAX_HEIGHT + 10 * GEO.EPS_SMALL) then + local sOut = 'Sezione (' .. EgtNumToString( dRawW, 2) .. ' x ' .. EgtNumToString( dRawH, 2) .. ') ' .. + 'oltre i limiti della macchina (' .. EgtNumToString( BD.MAX_WIDTH, 2) .. ' x ' .. EgtNumToString( BD.MAX_HEIGHT, 2) .. ') ' + EgtOutLog( sOut) + EgtOutBox( sOut, 'Lavora Travi', 'WARNING') + EgtDraw() + return false + end + else + if ( dRawW > BD.MAX_WIDTH + 10 * GEO.EPS_SMALL or dRawH > BD.MAX_HEIGHT + 10 * GEO.EPS_SMALL) and + ( dRawW > BD.MAX_WIDTH2 + 10 * GEO.EPS_SMALL or dRawH > BD.MAX_HEIGHT2 + 10 * GEO.EPS_SMALL) then + local sOut = 'Sezione (' .. EgtNumToString( dRawW, 2) .. ' x ' .. EgtNumToString( dRawH, 2) .. ') ' .. + 'oltre i limiti della macchina (' .. EgtNumToString( BD.MAX_WIDTH, 2) .. ' x ' .. EgtNumToString( BD.MAX_HEIGHT, 2) .. ') ' .. + 'e (' .. EgtNumToString( BD.MAX_WIDTH2, 2) .. ' x ' .. EgtNumToString( BD.MAX_HEIGHT2, 2) .. ')' + EgtOutLog( sOut) + EgtOutBox( sOut, 'Lavora Travi', 'WARNING') + EgtDraw() + return false + end + end + + -- Verifico sezione barra non troppo piccola + if dRawW < BD.MIN_WIDTH - 10 * GEO.EPS_SMALL or dRawH < BD.MIN_HEIGHT - 10 * GEO.EPS_SMALL then + local sOut = 'Sezione (' .. EgtNumToString( dRawW, 2) .. ' x ' .. EgtNumToString( dRawH, 2) .. ') ' .. + 'sotto i limiti della macchina (' .. EgtNumToString( BD.MIN_WIDTH, 2) .. ' x ' .. EgtNumToString( BD.MIN_HEIGHT, 2) .. ')' + EgtOutLog( sOut) + EgtOutBox( sOut, 'Lavora Travi', 'WARNING') + EgtDraw() + return false + end + + -- Se richiesto, ordino le travi in senso di lunghezza crescente + local bOrd = ( vsVal[5] == 'true') + if bOrd then + table.sort( vBeam, function( B1, B2) + if abs( B1.Box:getDimX() - B2.Box:getDimX()) < 1 then + return B1.Ind < B2.Ind + else + return B1.Box:getDimX() < B2.Box:getDimX() + end + end) + end + do + local sOut = '' + for i = 1, #vBeam do + sOut = sOut .. vBeam[i].Name .. ', ' + end + sOut = sOut:sub( 1, -3) + EgtOutLog( 'Travi ordinate : ' .. sOut, 1) + end + + -- Sistemo le travi nel grezzo + local bOk, sErr = BE.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, vBeam) + if not bOk then + EgtOutLog( sErr) + EgtOutBox( sErr, 'Lavora Travi', 'ERROR') + return false + end + + return true +end + +------------------------------------------------------------------------------------------------------------- +-- *** Inserimento delle lavorazioni nelle travi *** +------------------------------------------------------------------------------------------------------------- +local function MyProcessFeatures() + + local bOk, Stats = BE.ProcessFeatures() + local nErrCnt = 0 + local nWarnCnt = 0 + local sOutput = '' + for i = 1, #Stats do + if Stats[i].Err > 0 then + nErrCnt = nErrCnt + 1 + sOutput = sOutput .. string.format( '[%d,%d] %s\n', Stats[i].CutId, Stats[i].TaskId, Stats[i].Msg) + elseif Stats[i].Err < 0 then + -- se segnalazione scarico pezzo standard, incompleto o a caduta + if Stats[i].Err == -100 or Stats[i].Err == -101 or Stats[i].Err == -102 then + -- non faccio niente + else + nWarnCnt = nWarnCnt + 1 + sOutput = sOutput .. string.format( '[%d,%d] %s\n', Stats[i].CutId, Stats[i].TaskId, Stats[i].Msg) + end + end + end + if #sOutput > 0 then EgtOutLog( sOutput) end + if nErrCnt > 0 then + EgtOutBox( sOutput, 'Lavora Travi', 'ERRORS') + return false + elseif nWarnCnt > 0 then + EgtOutBox( sOutput, 'Lavora Travi', 'WARNINGS') + return true + end + + return true +end + +------------------------------------------------------------------------------------------------------------- +-- *** Esecuzione *** +------------------------------------------------------------------------------------------------------------- +if not MyProcessInputData() then return end + +if not GetDataConfig() then return end + +if not MyProcessBeams() then return end + +-- Abilito Vmill +EgtSetInfo( EgtGetCurrMachGroup(), 'Vm', '1') + +if not MyProcessFeatures() then return end diff --git a/README.md b/README.md deleted file mode 100644 index 06beef0..0000000 --- a/README.md +++ /dev/null @@ -1,93 +0,0 @@ -# DataBeamNEW - - - -## Getting started - -To make it easy for you to get started with GitLab, here's a list of recommended next steps. - -Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)! - -## Add your files - -- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files -- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command: - -``` -cd existing_repo -git remote add origin https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew.git -git branch -M main -git push -uf origin main -``` - -## Integrate with your tools - -- [ ] [Set up project integrations](https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew/-/settings/integrations) - -## Collaborate with your team - -- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/) -- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html) -- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically) -- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/) -- [ ] [Set auto-merge](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html) - -## Test and Deploy - -Use the built-in continuous integration in GitLab. - -- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html) -- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/) -- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html) -- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/) -- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html) - -*** - -# Editing this README - -When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template. - -## Suggestions for a good README - -Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information. - -## Name -Choose a self-explaining name for your project. - -## Description -Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors. - -## Badges -On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge. - -## Visuals -Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method. - -## Installation -Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection. - -## Usage -Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README. - -## Support -Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc. - -## Roadmap -If you have ideas for releases in the future, it is a good idea to list them in the README. - -## Contributing -State if you are open to contributions and what your requirements are for accepting them. - -For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self. - -You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser. - -## Authors and acknowledgment -Show your appreciation to those who have contributed to the project. - -## License -For open source projects, say how it is licensed. - -## Project status -If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers. diff --git a/Rotate.lua b/Rotate.lua new file mode 100644 index 0000000..c7a6c9b --- /dev/null +++ b/Rotate.lua @@ -0,0 +1,32 @@ +-- Rotate.lua by Egaltech s.r.l. 2017/11/04 +-- Gestione rotazione di una Trave + +-- Intestazioni +require( 'EgtBase') +_ENV = EgtProtectGlobal() +EgtEnableDebug( false) + + +-- recupero il pezzo del primo oggetto selezionato +local nId = EgtGetFirstSelectedObj() +local nPartId = EgtGetParent( EgtGetParent( nId or GDB_ID.NULL) or GDB_ID.NULL) +if not nPartId or not EgtIsPart( nPartId) then + EgtOutBox( 'Nessuna trave selezionata', 'Rotate Trave', 'ERROR') + return +end + +-- recupero il box del pezzo +local Ls = EgtGetFirstNameInGroup( nPartId, 'Box') +local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD) +if not b3Solid then + local sName = EgtGetName( nPartId) or ( 'Id=' .. tonumber( nPartId)) + EgtOutBox( 'Box non definito per la trave ' .. sName, 'Rotate Trave', 'ERROR') + return +end + +-- eseguo rotazione di 90 gradi attorno asse X +local ptRot = b3Solid:getMin() + Vector3d( 0, b3Solid:getDimZ() / 2, b3Solid:getDimZ() / 2) +EgtRotate( nPartId, ptRot, X_AX(), 90, GDB_RT.GLOB) +EgtDraw() + +-- end \ No newline at end of file diff --git a/Swap.lua b/Swap.lua new file mode 100644 index 0000000..c5d74a3 --- /dev/null +++ b/Swap.lua @@ -0,0 +1,31 @@ +-- Swap.lua by Egaltech s.r.l. 2017/11/02 +-- Gestione scambio testa coda di una Trave + +-- Intestazioni +require( 'EgtBase') +_ENV = EgtProtectGlobal() +EgtEnableDebug( false) + + +-- recupero il pezzo del primo oggetto selezionato +local nId = EgtGetFirstSelectedObj() +local nPartId = EgtGetParent( EgtGetParent( nId or GDB_ID.NULL) or GDB_ID.NULL) +if not nPartId or not EgtIsPart( nPartId) then + EgtOutBox( 'Nessuna trave selezionata', 'Swap Trave', 'ERROR') + return +end + +-- recupero il box del pezzo +local Ls = EgtGetFirstNameInGroup( nPartId, 'Box') +local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD) +if not b3Solid then + local sName = EgtGetName( nPartId) or ( 'Id=' .. tonumber( nPartId)) + EgtOutBox( 'Box non definito per la trave ' .. sName, 'Swap Trave', 'ERROR') + return +end + +-- eseguo rotazione di 180 gradi attorno asse Z +EgtRotate( nPartId, b3Solid:getCenter(), Z_AX(), 180, GDB_RT.GLOB) +EgtDraw() + +-- end \ No newline at end of file diff --git a/UpdateLog.txt b/UpdateLog.txt new file mode 100644 index 0000000..ee69091 --- /dev/null +++ b/UpdateLog.txt @@ -0,0 +1,4 @@ + ==== Beam Update Log ==== + +Versione 2.6-- (--/--/2024) +- Primo commit creazione nuovo automatismo BEAM con strategie \ No newline at end of file diff --git a/Version.lua b/Version.lua new file mode 100644 index 0000000..d9ea3be --- /dev/null +++ b/Version.lua @@ -0,0 +1,6 @@ +-- Version.lua by EgalWare s.r.l. 2024/04/02 +-- Gestione della versione di Beam + +NAME = 'Beam' +VERSION = '2.6d1' +MIN_EXE = '2.6a1'