-- BeamData.lua by Egalware s.r.l. 2025/12/03
-- Raccolta dati generali per Travi

EgtOutLog( ' KAIROS-BeamData started', 1)

-- Tabella per definizione modulo
local BeamData = {
   RIGHT_LOAD = false,                      -- flag carico da destra
   ROT90 = false,                           -- flag abilitazione rotazione 90 gradi
   ROT180 = true,                           -- flag abilitazione rotazione 180 gradi
   MIN_WIDTH = 40,                          -- larghezza minima del grezzo
   MIN_HEIGHT = 40,                         -- altezza minima del grezzo
   MAX_WIDTH = 250,                         -- larghezza massima del grezzo
   MAX_HEIGHT = 620,                        -- altezza massima del grezzo
   MAX_WIDTH2 = 250,                        -- seconda larghezza massima del grezzo
   MAX_HEIGHT2 = 620,                       -- altezza massima per seconda larghezza massima del grezzo
   LEN_SHORT_PART = 1200,                   -- RENAME lunghezza massima pezzo corto
   LEN_VERY_SHORT_PART = 400,               -- RENAME lunghezza massima pezzo molto corto (molto probabile lo scarico a caduta)
   MAX_RAW = 30000,                         -- massima lunghezza grezzo (deve essere minore di LenTable - RAW_OFFSET)
   STD_RAW = 14000,                         -- lunghezza standard della barra di grezzo
   OVM_HEAD = 10,                           -- sovramateriale testa
   OVM_MID = 5.4,                           -- sovramateriale intermedio (spessore lama)
   MINRAW_S = 750,                          -- minimo grezzo in coda scaricabile per sezioni piccole
   MINRAW_L = 1070,                         -- minimo grezzo in coda scaricabile per sezioni grandi
   SAFE_DIM_DICE = 110,                     -- dimensione trasversale ridotta cubetto, valida in tutte le posizioni
   MAX_LEN_DICE = 400,                      -- SOLO DICE lunghezza massima cubetto
   COLL_SIC = 5,                            -- distanza di sicurezza per collisioni
   CUT_SIC = 20,                            -- distanza di sicurezza per tagli
   CUT_EXTRA = 5,                           -- affondamento extra standard per tagli di lama e fresature
   CUT_EXTRA_MIN = 1,                       -- affondamento extra ridotto per tagli di lama e fresature
   MILL_OVERLAP = 5,                        -- sovrapposizione tra due mezze fresature
   LONGCUT_ENDLEN = 600,                    -- RENAME??lunghezza lavoro estremi iniziale e finale (std=600)
   LONGCUT_MAXLEN = 1200,                   -- RENAME??lunghezza massima sezione di taglio longitudinale
   DIM_STRIP = -1,                          -- dimensione codolo sostegno parti lasciate su contorno libero o archi (-1 = da Q...)
   DIM_STRIP_SMALL = 1,                     -- dimensione codolo piccolo (quando le parti sostenute sono sicuramente sulla parte sopra del pezzo)
   RAWCOL = { 255, 160, 32, 30},            -- colore del grezzo
   RAW_OFFSET = 2000,                       -- spostamento grezzo rimanente dopo split
   VICE_MINH = 110,                         -- altezza minima della morsa
   VICE_MAXH = 370,                         -- altezza massima zona pinzaggio orizzontale
   USER_HOLE_DIAM = 0,                      -- diametro foro per L20
   FASTCLAMPING = true
}

-- costanti riportate da mlde non necessarie per automatismo (sostituire con GetParameters o simile)
local MldeParameters = {}
MldeParameters.NumericalControl = 'SIEMENS'                                      -- NUM o TPA o NUM_PLUS
MldeParameters.MinY = -823
MldeParameters.MaxY = 520
MldeParameters.MinZ = -298
MldeParameters.MaxZ = 915
MldeParameters.MillOffs = 211.0
MldeParameters.DeltaTabY = 0
MldeParameters.DeltaTabZ = 0

-- Aggiornamento con dati macchina personalizzati
-- TODO sostituire con GetParameters o simile
local sData = EgtGetCurrMachineDir().."\\Beam\\EbwData.lua"
if EgtExistsFile( sData) then
   local Machine = dofile( sData)
   if Machine then
      if Machine.Offsets then
         if Machine.Offsets.TIPO_CN == 0 then
            NumericalControl =  'SIEMENS'
         end
         if Machine.Offsets.MAX_Y then MldeParameters.MinY = - Machine.Offsets.MAX_Y end
         if Machine.Offsets.MIN_Y then MldeParameters.MaxY = - Machine.Offsets.MIN_Y end
         if Machine.Offsets.MIN_Z then MldeParameters.MinZ = Machine.Offsets.MIN_Z end
         if Machine.Offsets.MAX_Z then MldeParameters.MaxZ = Machine.Offsets.MAX_Z end
         if Machine.Offsets.MILL_PIVOT then MldeParameters.MillOffs = - Machine.Offsets.MILL_PIVOT end
         if Machine.Offsets.TAB_OFFSET_Y then MldeParameters.DeltaTabY = Machine.Offsets.TAB_OFFSET_Y end
         if Machine.Offsets.TAB_OFFSET_Z then MldeParameters.DeltaTabZ = Machine.Offsets.TAB_OFFSET_Z end
      end
      if Machine.Trave then
         BeamData.MIN_WIDTH = Machine.Trave.YMIN or BeamData.MIN_WIDTH
         BeamData.MIN_HEIGHT = Machine.Trave.ZMIN or BeamData.MIN_HEIGHT
         BeamData.MAX_WIDTH = Machine.Trave.YMAX or BeamData.MAX_WIDTH
         BeamData.MAX_HEIGHT = Machine.Trave.ZMAX or BeamData.MAX_HEIGHT
         BeamData.MAX_WIDTH2 = Machine.Trave.YMAX or BeamData.MAX_WIDTH2
         BeamData.MAX_HEIGHT2 = Machine.Trave.ZMAX or BeamData.MAX_HEIGHT2
      end
      if Machine.User then
         BeamData.USER_HOLE_DIAM = Machine.User.L020_DIAM_HOLE or BeamData.USER_HOLE_DIAM
      end
   end
end

---------------------------------------------------------------------
local function GetBlockedAxis( sHead, nToolType, sBlockedAxis)
   -- lama
   if nToolType == MCH_TY.SAW_STD or nToolType == MCH_TY.SAW_FLAT then
      return ''
   -- sega a catena
   elseif nToolType == MCH_TY.MORTISE_STD then
      if sHead == 'H3' then
         if sBlockedAxis == 'parallel' then
            return 'CS=90'
         elseif sBlockedAxis == 'perpendicular' then
            return 'CS=0'
         end
      else
         return ''
      end
   -- fresa
   elseif nToolType == MCH_TY.MILL_STD or nToolType == MCH_TY.MILL_NOTIP then
      return ''
   -- punta
   elseif nToolType == MCH_TY.DRILL_STD or nToolType == MCH_TY.DRILL_LONG then
      return ''
   else
      return ''
   end
end
BeamData.GetBlockedAxis = GetBlockedAxis

---------------------------------------------------------------------
local function GetChainSawInitAngs( vtN, vtO, nInd)
   if nInd == 1 then
      return ''
   else
      return EgtIf( vtN:getY() > 0, 'C=180', 'C=-180')
   end
end
BeamData.GetChainSawInitAngs = GetChainSawInitAngs

---------------------------------------------------------------------
local function GetSCC( vtToolDirection, vtEdgeDirection, vtNFace)
   local nSCC = MCH_SCC.NONE

   if abs( vtToolDirection:getX()) > abs( vtToolDirection:getY()) - GEO.EPS_SMALL then
      -- se il taglio è orizzontale, si gira aggregato lama per facilitare caduta del legno
      if abs( vtEdgeDirection:getZ()) < 10 * GEO.EPS_SMALL and not AreSameOrOppositeVectorApprox( vtNFace, Z_AX()) then
         nSCC = EgtIf( ( vtToolDirection:getX() > -GEO.EPS_SMALL), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP)
      else
         nSCC = EgtIf( ( vtToolDirection:getX() > -GEO.EPS_SMALL), MCH_SCC.ADIR_XP, MCH_SCC.ADIR_XM)
      end
   else
      -- se il taglio è orizzontale, si gira aggregato lama per facilitare caduta del legno
      if abs( vtEdgeDirection:getZ()) < 10 * GEO.EPS_SMALL and not AreSameOrOppositeVectorApprox( vtNFace, Z_AX()) then
         nSCC = EgtIf( ( vtToolDirection:getY() > -GEO.EPS_SMALL), MCH_SCC.ADIR_YM, MCH_SCC.ADIR_YP)
      else
         nSCC = EgtIf( ( vtToolDirection:getY() > -GEO.EPS_SMALL), MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM)
      end
   end

   return nSCC
end

---------------------------------------------------------------------
-- TODO leggere direttamente MinA, MinSawA, ...
local function GetMinNzTopHead( vtNFace, Tool)
   if Tool and Tool.sFamily ~= 'SAWBLADE' then
      return sin( -15)
   else
      return sin( -11)
   end
end

---------------------------------------------------------------------
-- sAxis può essere AB, C, Z; restituisce direzioni, profondità di estrusione e punti per il controllo precollisione
local function GetPreCollisionData( sAxis, vtC, vtHead)

   local PreCollisionData = {}

   -- Pivot uguale per tutti; non c'è aggregato quindi non dipende da SCC
   -- riferimento vtPivot
--    - vtHead (Z): asse rotazione utensile, guarda il mandrino
--    - vtToolSCC (X): direzione asse C o aggregato
--    - vtEdge (Y): direzione lato, verso in base a X e Z
--    - punto di applicazione: naso mandrino o aggregato
   PreCollisionData.vtMovePivot = Vector3d( 0, 0, MldeParameters.MillOffs)

   -- carro Z
   if sAxis == 'Z' then

      PreCollisionData.Directions = { vtDirectionX = Y_AX(), vtDirectionY = Z_AX(), vtDirectionZ = X_AX()}
      PreCollisionData.dExtrusionDepth = 300
      PreCollisionData.Points = {
         Point3d( -150.001, 2209.004, 0),
         Point3d( 150.001, 2209.004, 0),
         Point3d( 150.001, 2204.955, 0),
         Point3d( 194.679, 2204.955, 0),
         Point3d( 195.004, 362.996, 0),
         Point3d( 149.998, 362.996, 0),
         Point3d( 149.998, 324.754, 0),
         Point3d( 104.999, 324.754, 0),
         Point3d( 104.999, 313.754, 0),
         Point3d( -104.999, 313.754, 0),
         Point3d( -104.999, 324.754, 0),
         Point3d( -149.998, 324.754, 0),
         Point3d( -149.998, 362.996, 0),
         Point3d( -195.001, 362.996, 0),
         Point3d( -194.679, 2204.955, 0),
         Point3d( -150.001, 2204.995, 0),
         Point3d( -150.001, 2209.004, 0)
      }

   -- motore (asse A o B)
   elseif sAxis == 'AB' then

      PreCollisionData.Directions = { vtDirectionX = vtHead ^ vtC, vtDirectionY = vtHead, vtDirectionZ = vtC}
      PreCollisionData.dExtrusionDepth = 167
      PreCollisionData.Points = {
         Point3d( 35.5, -211.06, 0),
         Point3d( -35.5, -211.06, 0),
         Point3d( -35.5, -198.06, 0),
         Point3d( -59.912, -198.06, 0),
         Point3d( -60.012, -135.897, 0),
         Point3d( -73.033, -135.897, 0),
         Point3d( -73.033, -129, 0),
         Point3d( -76.679, -129, 0),
         Point3d( -94, -99, 0),
         Point3d( -94, 36, 0),
         Point3d( -79.854, 60.5, 0),
         Point3d( -75.544, 60.5, 0),
         Point3d( -75.544, 201.158, 0),
         Point3d( -46.616, 209.792, 0),
         Point3d( -6, 215.5, 0),
         Point3d( 6, 215.5, 0),
         Point3d( 46.616, 209.792, 0),
         Point3d( 75.001, 201.158, 0),
         Point3d( 75.001, 60.5, 0),
         Point3d( 79.855, 60.5, 0),
         Point3d( 94, 36, 0),
         Point3d( 94, -99, 0),
         Point3d( 76.68, -129, 0),
         Point3d( 75.967, -129, 0),
         Point3d( 75.967, -136.224, 0),
         Point3d( 59.938, -136.224, 0),
         Point3d( 59.938, -198.06, 0),
         Point3d( 35.5, -198.06, 0),
         Point3d( 35.5, -211.06, 0)
      }

   -- asse C
   elseif sAxis == 'C' then

      PreCollisionData.Directions = { vtDirectionX = vtC, vtDirectionY = Z_AX(), vtDirectionZ = vtC ^ Z_AX()}
      PreCollisionData.dExtrusionDepth = 260
      PreCollisionData.Points = {
         Point3d( 91.5, 163.55, 0),
         Point3d( 92.75, -103.001, 0),
         Point3d( 304.669, -103.001, 0),
         Point3d( 311.446, -79.727, 0),
         Point3d( 318.015, -45.806, 0),
         Point3d( 320.875, -2.072, 0),
         Point3d( 320.875, 290, 0),
         Point3d( 310, 314.5, 0),
         Point3d( -110, 314.5, 0),
         Point3d( -110, 235, 0),
         Point3d( -49.992, 211.022, 0),
         Point3d( 19.775, 199.927, 0),
         Point3d( 65, 199.927, 0),
         Point3d( 77, 190, 0),
         Point3d( 77, 163.852, 0),
         Point3d( 78, 163.55, 0),
         Point3d( 91.5, 163.55, 0)
      }
   end

   return PreCollisionData
end

---------------------------------------------------------------------
local function GetSetupInfo( sHead)
   local SetupInfo = {}

   -- dati comuni
   SetupInfo.bIsCSymmetrical = false
   SetupInfo.dCAxisEncumbrance = 180
   SetupInfo.dCAxisSideEncumbrance = 200
   SetupInfo.bToolOnAggregate = false
   SetupInfo.vtRotationAxisC = EgtGetAxisDir( 'C')
   SetupInfo.vtRotationAxisAB = EgtGetAxisDir( 'A')

   -- TODO da rimuovere quando si fara PreSimulation di asse Z per frese
   SetupInfo.dPivot = MldeParameters.MillOffs

   -- testa 5 assi da sopra
   if sHead == 'H1' then
      SetupInfo.HeadType = { bTop = true, bBottom = false}
      SetupInfo.PreferredSide = {}
      SetupInfo.GetMinNz = GetMinNzTopHead
      SetupInfo.GetPreCollisionData = GetPreCollisionData
      SetupInfo.GetSCC = GetSCC
   -- sega a catena
   elseif sHead == 'H3' then
      SetupInfo.HeadType = { bTop = true, bBottom = false}
      SetupInfo.PreferredSide = {}
   -- rinvio angolare 90° (considerato come fosse una testa da sotto)
   elseif sHead == 'H5' then
      SetupInfo.bToolOnAggregate = true
      SetupInfo.HeadType = { bTop = false, bBottom = true}
      SetupInfo.PreferredSide = {}
      SetupInfo.GetMaxNz = function() return 0 end
   end

   return SetupInfo
end
BeamData.GetSetupInfo = GetSetupInfo

---------------------------------------------------------------------
return BeamData
