diff --git a/LuaLibs/BeamExec.lua b/LuaLibs/BeamExec.lua index e8e7b81..66167cc 100644 --- a/LuaLibs/BeamExec.lua +++ b/LuaLibs/BeamExec.lua @@ -62,6 +62,7 @@ -- 2024/03/11 In CollectFeatures si scrive ora Width e Height della faccia sia trimmate con il grezzo che intere. -- 2024/03/13 In CollectFeatures si scrive lunghezza foro su Proc e si controla se serve Predrill -- In OrderFeature, preforo sempre prima del foro +-- 2024/04/11 In CollectFeatures aggiunta lettura info PRID, scritta in Proc.FeatureId -- Tabella per definizione modulo local BeamExec = {} @@ -344,31 +345,13 @@ local function CollectFeatures( PartId, b3Raw, dCurrOvmH, dCurrOvmT) end Proc.Box = EgtGetBBoxGlob( ProcId, GDB_BB.STANDARD) if b3Raw then - local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( PartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD) + -- id della feature + Proc.FeatureId = EgtGetInfo( ProcId, 'PRID', 'i') or Proc.TaskId -- recupero l'elenco delle facce della parte interessate dalla feature Proc.AffectedFaces = BL.GetProcessAffectedFaces( Proc) -- recupero informazioni sulle facce della feature if not Proc.Face then - Proc.Face = {} - for i = 1, Proc.Fct do - Proc.Face[i] = { Id = i - 1, VtN = EgtSurfTmFacetNormVersor( Proc.Id, i - 1, GDB_ID.ROOT )} - if Proc.Fct < 10 then - local frHV, dFaceWidthTrimmed, dFaceHeightTrimmed = BL.GetFaceHvRefDim( Proc.Id, i - 1, b3Raw) - -- frame OCS faccia - Proc.Face[i].FrameHV = frHV - -- larghezza OCS faccia trimmata con grezzo - Proc.Face[i].WidthTrimmed = dFaceWidthTrimmed - -- altezza OCS faccia trimmata con grezzo - Proc.Face[i].HeightTrimmed = dFaceHeightTrimmed - local _, dFaceWidth, dFaceHeight = BL.GetFaceHvRefDim( Proc.Id, i - 1) - -- larghezza OCS faccia - Proc.Face[i].Width = dFaceWidth - -- altezza OCS faccia - Proc.Face[i].Height = dFaceHeight - -- elevazione calcolata rispetto al box della parte - Proc.Face[i].Elevation = EgtSurfTmFacetElevationInBBox( Proc.Id, i - 1, b3Solid, true, GDB_ID.ROOT) - end - end + Proc.Face = BL.GetFacetsInfo( Proc, b3Raw) end end if Proc.Box and not Proc.Box:isEmpty() then diff --git a/LuaLibs/BeamLib.lua b/LuaLibs/BeamLib.lua index f65dc8d..7373bd9 100644 --- a/LuaLibs/BeamLib.lua +++ b/LuaLibs/BeamLib.lua @@ -1169,4 +1169,47 @@ function BeamLib.IsFeatureCuttingEntireSection( b3Proc, dRawW, dRawH) end ------------------------------------------------------------------------------------------------------------- -return BeamLib +function BeamLib.GetAdjacentFaces( Proc, nFacet) + local AdjacentFaces = {} + local vFaceAdjacencies = EgtSurfTmFacetAdjacencies( Proc.Id, nFacet)[1] + for i = 1, #vFaceAdjacencies do + if vFaceAdjacencies[i] > -1 then + local _, ptP1, ptP2 = EgtSurfTmFacetsContact( Proc.Id, nFacet, vFaceAdjacencies[i], GDB_ID.ROOT) + local dLen = dist( ptP1, ptP2) + table.insert( AdjacentFaces, { Id = vFaceAdjacencies[i], LengthOnMainFace = dLen}) + end + end + + return AdjacentFaces +end + +------------------------------------------------------------------------------------------------------------- +function BeamLib.GetFacetsInfo( Proc, b3Raw) + Face = {} + local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( Proc.PartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD) + + for i = 1, Proc.Fct do + Face[i] = { Id = i - 1, VtN = EgtSurfTmFacetNormVersor( Proc.Id, i - 1, GDB_ID.ROOT )} + if Proc.Fct < 10 then + local frHV, dFaceWidthTrimmed, dFaceHeightTrimmed = BeamLib.GetFaceHvRefDim( Proc.Id, i - 1, b3Raw) + -- frame OCS faccia + Face[i].FrameHV = frHV + -- larghezza OCS faccia trimmata con grezzo + Face[i].WidthTrimmed = dFaceWidthTrimmed + -- altezza OCS faccia trimmata con grezzo + Face[i].HeightTrimmed = dFaceHeightTrimmed + local _, dFaceWidth, dFaceHeight = BeamLib.GetFaceHvRefDim( Proc.Id, i - 1) + -- larghezza OCS faccia + Face[i].Width = dFaceWidth + -- altezza OCS faccia + Face[i].Height = dFaceHeight + -- elevazione calcolata rispetto al box della parte + Face[i].Elevation = EgtSurfTmFacetElevationInBBox( Proc.Id, i - 1, b3Solid, true, GDB_ID.ROOT) + end + end + + return Face +end + +------------------------------------------------------------------------------------------------------------- +return BeamLib \ No newline at end of file diff --git a/LuaLibs/FeatureTopology.lua b/LuaLibs/FeatureTopology.lua index 5426c5d..c77d6b8 100644 --- a/LuaLibs/FeatureTopology.lua +++ b/LuaLibs/FeatureTopology.lua @@ -113,11 +113,11 @@ end --------------------------------------------------------------------- -- restituisce un vettore contenente gli indici delle facce di Proc parallele ad una delle direzioni principali; il check varia in base alla famiglia topologica -local function GetFacesParallelToPart( Proc, sFamily, bIsThrough) +local function GetFacesParallelToPart( Proc, sFamily) local vFacesParallelToPart = {} for i = 0, Proc.Fct - 1 do local vtN = EgtSurfTmFacetNormVersor( Proc.Id, i, GDB_ID.ROOT) - if sFamily == 'Rabbet' or sFamily == 'Bevel' or sFamily == 'DoubleBevel' or sFamily == 'Strip' or sFamily == 'Tunnel' or ( sFamily == 'Groove' and bIsThrough) then + if sFamily == 'Rabbet' or sFamily == 'Bevel' or sFamily == 'DoubleBevel' or sFamily == 'Strip' then local vTriangularFaces = GetTriangularFaces( Proc) local bIsTriangularFace = false -- verifico se la faccia è triangolare @@ -180,7 +180,12 @@ function FeatureTopology.Classify( Proc, b3Raw) end -- calcoli - if not Proc.AffectedFaces then Proc.AffectedFaces = BL.GetProcessAffectedFaces( Proc) end + if not Proc.AffectedFaces then + Proc.AffectedFaces = BL.GetProcessAffectedFaces( Proc) + end + if not Proc.Face then + Proc.Face = BL.GetFacetsInfo( Proc, b3Raw) + end local vAdj = GetAdjacencyMatrix( Proc) local bAllAnglesConcave, bAllRightAngles = AreAllAnglesConcaveOrRight( vAdj) @@ -239,7 +244,7 @@ function FeatureTopology.Classify( Proc, b3Raw) end -- verifico se facce parallele a quelle della trave - local vFacesParallelToPart = GetFacesParallelToPart( Proc, sFamily, bIsThrough) + local vFacesParallelToPart = GetFacesParallelToPart( Proc, sFamily) local bIsParallel = ( #vFacesParallelToPart == Proc.Fct) -- assegnazioni @@ -249,6 +254,7 @@ function FeatureTopology.Classify( Proc, b3Raw) Proc.IsThrough = bIsThrough Proc.AllRightAngles = bAllRightAngles Proc.IsParallel = bIsParallel + Proc.vAdj = vAdj return true else Proc.Topology = 'OTHER' diff --git a/LuaLibs/ProcessLapJoint.lua b/LuaLibs/ProcessLapJoint.lua index 5f8f27e..11178a2 100644 --- a/LuaLibs/ProcessLapJoint.lua +++ b/LuaLibs/ProcessLapJoint.lua @@ -101,6 +101,7 @@ -- 2024/03/04 Implementato attacco esterno se tasca 4 facce sulla coda ma nessun pezzo successivo. -- 2024/03/15 Correzione a calcolo ingombro per feature basse e lunghe dalla testa. -- 2024/04/02 In ForceSideMill escluso caso 4 facce senza possibilità di ingresso lungo Y. +-- 2024/04/11 Aggiunta strategia SawPlusChain per lavorazione tasche con lama + sega a catena opzionale. Attivata con Q11. -- Tabella per definizione modulo local ProcessLapJoint = {} @@ -174,6 +175,7 @@ local function AssignQIdent( Proc) Q_ANTISPLINT_TYPE = '' Q_MAX_ELEVATION = 'Q10' Q_STAIRCASE = '' + Q_SAW_PLUS_CHAIN = 'Q11' if ( Proc.Grp == 3 or Proc.Grp == 4) and Proc.Prc == 16 then Q_FORCE_BLADE = 'Q01' -- i @@ -4584,6 +4586,704 @@ local function MakeTunnelByChainSaw( Proc, sSawing, nLundIdFace, vtOrtho, dWorkD return true end +--------------------------------------------------------------------- +--#region SawPlusChain + +-- 5 facce: la faccia di fondo è il fondo della tasca, la faccia da lavorare è grande, le facce laterali sono le due piccole +-- 4 facce con faccia di fondo piccola: la faccia da lavorare è grande (2 adj) e l'unica faccia laterale è piccola +-- 4 facce con faccia di fondo grande: la faccia da lavorare è piccola (3 adj) e le facce laterali sono le due piccole +-- 3 facce: la faccia di fondo è il fondo della tasca, la faccia da lavorare è grande, non ci sono facce laterali + +-- TODO gestione messaggi in funzione apposita (almeno per append) + +-- TODO gestire topologia tunnel (anche da due lati) + +local SawPlusChain = {} +SawPlusChain.Saw = {} +SawPlusChain.Chainsaw = {} + + +function SawPlusChain.IsTopologyOk( Proc) + if Proc.TopologyLongName == 'Pocket-Blind-RightAngles-Parallel-5' or + Proc.TopologyLongName == 'Groove-Through-RightAngles-Parallel-3' or + Proc.TopologyLongName == 'Groove-Blind-RightAngles-Parallel-4' then + + return true + else + return false + end +end + + +function SawPlusChain.GetBottomFace( Proc) + -- la faccia di fondo ha sempre Fct - 1 adiacenze. Se si trovano più facce di fondo si sceglie quella con minor elevazione + local vBottomFace = Topology.GetFacesWithGivenAdjacencyNumber( Proc, Proc.vAdj, Proc.Fct - 1) + local nBottomFace + if #vBottomFace > 1 then + local dMinElevation = GEO.INFINITO + for i = 1, #vBottomFace do + for j = 1, Proc.Fct do + if vBottomFace[i] == Proc.Face[j].Id then + if Proc.Face[j].Elevation < dMinElevation then + dMinElevation = Proc.Face[j].Elevation + nBottomFace = Proc.Face[j].Id + end + end + end + end + else + nBottomFace = vBottomFace[1] + end + + local BottomFace = {} + BottomFace.Id = nBottomFace + BottomFace.Width = Proc.Face[nBottomFace + 1].Width + BottomFace.Height = Proc.Face[nBottomFace + 1].Height + BottomFace.Elevation = Proc.Face[nBottomFace + 1].Elevation + BottomFace.VtN = Proc.Face[nBottomFace + 1].VtN + if BottomFace.Height > BottomFace.Width then + BottomFace.Height, BottomFace.Width = BottomFace.Width, BottomFace.Height + end + + return BottomFace +end + + +function SawPlusChain.GetFaceToMachine( Proc) + if not Proc.Pocket.BottomFace or not Proc.Pocket.BottomFace.Id then + Proc.Pocket.BottomFace = SawPlusChain.GetBottomFace( Proc) + end + + -- facce adiacenti a quella di fondo, ordinate + local FacesAdjacentToBottom = BL.GetAdjacentFaces( Proc, Proc.Pocket.BottomFace.Id) + table.sort( FacesAdjacentToBottom, function( a, b) return a.LengthOnMainFace > b.LengthOnMainFace end) + + -- si sceglie la faccia adiacente sul lato più lungo + local FaceToMachine = {} + FaceToMachine.Id = FacesAdjacentToBottom[1].Id + for i = 1, Proc.Fct do + if FaceToMachine.Id == Proc.Face[i].Id then + FaceToMachine.Width = Proc.Face[i].Width + FaceToMachine.Height = Proc.Face[i].Height + FaceToMachine.Elevation = Proc.Face[i].Elevation + FaceToMachine.VtN = Proc.Face[i].VtN + if FaceToMachine.Height > FaceToMachine.Width then + FaceToMachine.Height, FaceToMachine.Width = FaceToMachine.Width, FaceToMachine.Height + end + end + end + + return FaceToMachine +end + + +function SawPlusChain.GetSideFaces( Proc) + if not Proc.Pocket.BottomFace or not Proc.Pocket.BottomFace.Id then + Proc.Pocket.BottomFace = SawPlusChain.GetBottomFace( Proc) + end + if not Proc.Pocket.FaceToMachine or not Proc.Pocket.FaceToMachine.Id then + Proc.Pocket.FaceToMachine = SawPlusChain.GetFaceToMachine( Proc) + end + + -- facce adiacenti a quella di fondo, ordinate + local FacesAdjacentToBottom = BL.GetAdjacentFaces( Proc, Proc.Pocket.BottomFace.Id) + table.sort( FacesAdjacentToBottom, function( a, b) return a.LengthOnMainFace > b.LengthOnMainFace end) + + -- si determina il criterio di scelta delle facce laterali + local FacesAdjacentToFaceToMachine = BL.GetAdjacentFaces( Proc, Proc.Pocket.FaceToMachine.Id) + local bIsFaceToMachineTheLargest = not ( Proc.Fct == 4 and #FacesAdjacentToFaceToMachine == 3) + + local SideFaces = {} + for i = 1, #FacesAdjacentToBottom do + if ( not bIsFaceToMachineTheLargest and i < #FacesAdjacentToBottom) or + ( bIsFaceToMachineTheLargest and i > 2) then + table.insert( SideFaces, FacesAdjacentToBottom[i]) + SideFaces[ #SideFaces].Id = FacesAdjacentToBottom[i].Id + SideFaces[ #SideFaces].Width = Proc.Face[FacesAdjacentToBottom[i].Id + 1].Width + SideFaces[ #SideFaces].Height = Proc.Face[FacesAdjacentToBottom[i].Id + 1].Height + SideFaces[ #SideFaces].Elevation = Proc.Face[FacesAdjacentToBottom[i].Id + 1].Elevation + SideFaces[ #SideFaces].VtN = Proc.Face[FacesAdjacentToBottom[i].Id + 1].VtN + if SideFaces[ #SideFaces].Height > SideFaces[ #SideFaces].Width then + SideFaces[ #SideFaces].Height, SideFaces[ #SideFaces].Width = SideFaces[ #SideFaces].Width, SideFaces[ #SideFaces].Height + end + end + end + + return SideFaces +end + + +function SawPlusChain.GetToolFromMachining( sMachiningName) + local Tool = {} + if EgtMdbSetCurrMachining( sMachiningName) then + local sTuuid = EgtMdbGetCurrMachiningParam( MCH_MP.TUUID) + if EgtTdbSetCurrTool( EgtTdbGetToolFromUUID( sTuuid) or '') then + Tool.Name = EgtTdbGetCurrToolParam( MCH_TP.NAME) + Tool.IsCCW = ( EgtMdbGetCurrMachiningParam( MCH_MP.SPEED) < 0) + Tool.Type = EgtTdbGetCurrToolParam( MCH_TP.TYPE) + Tool.Diameter = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or 0 + -- lama + if Tool.Type == MCH_TY.SAW_STD or Tool.Type == MCH_TY.SAW_FLAT then + Tool.Thickness = EgtTdbGetCurrToolParam(MCH_TP.THICK) or 0 + Tool.MaxDepth = EgtTdbGetCurrToolMaxDepth() or 0 + Tool.SideStep = EgtTdbGetCurrToolValInNotes( MCH_TP.USERNOTES, 'SIDESTEP', 'd') + -- sega a catena + elseif Tool.Type == MCH_TY.MORTISE_STD then + Tool.Length = EgtTdbGetCurrToolParam( MCH_TP.LEN) or 0 + Tool.MaxMat = EgtTdbGetCurrToolParam( MCH_TP.MAXMAT) or 0 + Tool.Width = EgtTdbGetCurrToolParam( MCH_TP.DIAM) or 0 + Tool.Thickness = EgtTdbGetCurrToolParam( MCH_TP.THICK) or 0 + Tool.CornerRadius = EgtTdbGetCurrToolParam( MCH_TP.CORNRAD) or 0 + -- altri utensili al momento non previsti + else + error( 'Wrong tool type') + end + end + end + + return Tool +end + + +function SawPlusChain.GetVerticalSteps( Proc, Machining) + if not Proc.Pocket or not Proc.Pocket.Height then + error( 'Missing pocket depth') + elseif not Machining.Tool or not Machining.Tool.Thickness then + error( 'Missing tool thickness') + end + local VerticalSteps = {} + VerticalSteps.StepLength = 0 + VerticalSteps.Count = ceil( ( Proc.Pocket.Height - 10 * GEO.EPS_SMALL) / Machining.Tool.Thickness) + if VerticalSteps.Count > 1 then + VerticalSteps.StepLength = ( Proc.Pocket.Height - Machining.Tool.Thickness) / ( VerticalSteps.Count - 1) + end + + return VerticalSteps +end + + +function SawPlusChain.GetHorizontalSteps( Machining) + if not Machining.Depth then + error( 'Missing machining depth') + end + local HorizontalSteps = {} + HorizontalSteps.StepLength = 0 + HorizontalSteps.Count = ceil( ( Machining.Depth - 10 * GEO.EPS_SMALL) / Machining.Tool.SideStep) + if HorizontalSteps.Count > 1 then + HorizontalSteps.StepLength = ( Machining.Depth - Machining.Tool.SideStep) / ( HorizontalSteps.Count - 1) + end + + return HorizontalSteps +end + + +function SawPlusChain.CalculateLeadInOut( Proc, Machining) + -- TODO implementare le funzioni di Tool Collision Avoidance (vedi wiki e FacesBysaw -> CalcLeadInOutPerpGeom) + + -- si determina se l'inizio o la fine della lavorazione sono chiusi e l'eventuale riduzione da applicare + local bIsStartClosed = false + local bIsEndClosed = false + local bIsMortising = ( Machining.Type == MCH_OY.MORTISING) + local dAddLengthToReduce = 0 + if bIsMortising then + dAddLengthToReduce = Machining.Tool.Diameter / 2 + else + dAddLengthToReduce = sqrt( Machining.Depth * Machining.Tool.Diameter - Machining.Depth * Machining.Depth) + end + if #( Proc.Pocket.SideFaces) == 2 then + bIsStartClosed = true + bIsEndClosed = true + elseif #( Proc.Pocket.SideFaces) == 1 then + local CCWDirection = ( Machining.FaceToMachine.VtN ^ Proc.Pocket.BottomFace.VtN) + if Machining.ToolInvert or bIsMortising then + CCWDirection = - CCWDirection + end + if CCWDirection * Proc.Pocket.SideFaces[1].VtN > 10 * GEO.EPS_SMALL then + if Machining.Tool.IsCCW then + bIsStartClosed = true + else + bIsEndClosed = true + end + else + if Machining.Tool.IsCCW then + bIsEndClosed = true + else + bIsStartClosed = true + end + end + end + + local LeadIn = {} + local LeadOut = {} + LeadIn.StartAddLength = 0 + LeadOut.EndAddLength = 0 + if not bIsMortising then + LeadIn.Type = MCH_MILL_LI.LINEAR + LeadOut.Type = MCH_MILL_LI.LINEAR + LeadIn.TangentDistance = 0 + LeadOut.TangentDistance = 0 + LeadIn.PerpDistance = Proc.Pocket.Depth + BD.CUT_SIC + LeadOut.PerpDistance = Proc.Pocket.Depth + BD.CUT_SIC + LeadIn.Elevation = 0 + LeadOut.Elevation = 0 + LeadIn.CompLength = 0 + LeadOut.CompLength = 0 + if bIsStartClosed and bIsEndClosed then + LeadIn.StartAddLength = -dAddLengthToReduce + LeadOut.EndAddLength = -dAddLengthToReduce + elseif bIsStartClosed then + LeadIn.StartAddLength = -dAddLengthToReduce + -- eventuale correzione per accorciamento maggiore di larghezza tasca + LeadOut.EndAddLength = max( -LeadIn.StartAddLength - Proc.Pocket.Width + 10 * BD.CUT_EXTRA, BD.CUT_EXTRA) + elseif bIsEndClosed then + LeadOut.EndAddLength = -dAddLengthToReduce + -- eventuale correzione per accorciamento maggiore di larghezza tasca + LeadIn.StartAddLength = max( -LeadOut.EndAddLength - Proc.Pocket.Width + 10 * BD.CUT_EXTRA, BD.CUT_EXTRA) + else + LeadIn.StartAddLength = BD.CUT_EXTRA + LeadOut.EndAddLength = BD.CUT_EXTRA + end + else + if bIsStartClosed then + LeadIn.StartAddLength = -dAddLengthToReduce + else + LeadIn.StartAddLength = BD.CUT_EXTRA + end + if bIsEndClosed then + LeadOut.EndAddLength = -dAddLengthToReduce + else + LeadOut.EndAddLength = BD.CUT_EXTRA + end + end + + return LeadIn, LeadOut +end + + +function SawPlusChain.ApplyMachining( Machining, b3Raw) + local sErr = '' + local nOperationId = EgtAddMachining( Machining.OperationName, Machining.Name) + if not nOperationId then + sErr = 'Error adding machining ' .. Machining.OperationName .. '-' .. Machining.Name + EgtOutLog( sErr) + return false, sErr + end + + -- impostazione parametri lavorazione + local sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES) + EgtSetMachiningGeometry( {{ Machining.ProcId, Machining.FaceToMachine.Id}}) + EgtSetMachiningParam( MCH_MP.FACEUSE, Machining.Faceuse) + EgtSetMachiningParam( MCH_MP.SCC, Machining.SCC) + EgtSetMachiningParam( MCH_MP.INVERT, Machining.Invert) + EgtSetMachiningParam( MCH_MP.WORKSIDE, Machining.Workside) + EgtSetMachiningParam( MCH_MP.TOOLINVERT, Machining.ToolInvert) + EgtSetMachiningParam( MCH_MP.OFFSR, Machining.RadialOffset) + EgtSetMachiningParam( MCH_MP.OFFSL, Machining.LongitudinalOffset) + if Machining.Type ~= MCH_OY.MORTISING then + EgtSetMachiningParam( MCH_MP.LEADINTYPE, Machining.LeadIn.Type) + EgtSetMachiningParam( MCH_MP.LEADOUTTYPE, Machining.LeadOut.Type) + EgtSetMachiningParam( MCH_MP.LITANG, Machining.LeadIn.TangentDistance) + EgtSetMachiningParam( MCH_MP.LOTANG, Machining.LeadOut.TangentDistance) + EgtSetMachiningParam( MCH_MP.LIPERP, Machining.LeadIn.PerpDistance) + EgtSetMachiningParam( MCH_MP.LOPERP, Machining.LeadOut.PerpDistance) + EgtSetMachiningParam( MCH_MP.LIELEV, Machining.LeadIn.Elevation) + EgtSetMachiningParam( MCH_MP.LOELEV, Machining.LeadOut.Elevation) + EgtSetMachiningParam( MCH_MP.LICOMPLEN, Machining.LeadIn.CompLength) + EgtSetMachiningParam( MCH_MP.LOCOMPLEN, Machining.LeadOut.CompLength) + end + EgtSetMachiningParam( MCH_MP.STARTADDLEN, Machining.LeadIn.StartAddLength) + EgtSetMachiningParam( MCH_MP.ENDADDLEN, Machining.LeadOut.EndAddLength) + if Machining.Steps then + if Machining.Steps.StepType then + EgtSetMachiningParam( MCH_MP.STEPTYPE, Machining.Steps.StepType) + end + if Machining.Steps.StepLength then + EgtSetMachiningParam( MCH_MP.STEP, Machining.Steps.StepLength) + end + end + EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, BL.GetBlockedAxis( Machining.Name, Machining.BlockedAxis.Orientation, b3Raw, Machining.FaceToMachine.VtN, Machining.BlockedAxis.VtOut)) + if Machining.Type == MCH_OY.MORTISING then + EgtSetMachiningParam( MCH_MP.INITANGS, BL.GetChainSawInitAngs( Machining.FaceToMachine.VtN, Machining.Direction, Machining.SuggestedAngles.Index)) + end + EgtSetMachiningParam( MCH_MP.OVERL, Machining.Overlap) + EgtSetMachiningParam( MCH_MP.STARTPOS, max( Machining.StartSafetyLength, EgtGetMachiningParam( MCH_MP.STARTPOS))) + if Machining.MaxElev then + sUserNotes = EgtSetValInNotes( sUserNotes, 'MaxElev', Machining.MaxElev) + end + EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes) + + local bIsApplyOk = ML.ApplyMachining( true, false) + if not bIsApplyOk then + local nErr + nErr, sErr = EgtGetLastMachMgrError() + -- se mortasatura e l'errore è compatibile (Axes values not calculable) si prova con l'altra configurazione dell'asse bloccato + -- TODO valutare se c'è modo di capire preventivamente la configurazione dell'asse bloccato e quindi rimuovere questa parte di codice + if Machining.Type == MCH_OY.MORTISING and nErr == 2507 then + if Machining.BlockedAxis.Orientation == 'perpendicular' then + Machining.BlockedAxis.Orientation = 'parallel' + else + Machining.BlockedAxis.Orientation = 'perpendicular' + end + EgtSetMachiningParam( MCH_MP.BLOCKEDAXIS, BL.GetBlockedAxis( Machining.Name, Machining.BlockedAxis.Orientation, b3Raw, Machining.FaceToMachine.VtN, Machining.BlockedAxis.VtOut)) + if Machining.SuggestedAngles.Index == 1 then + Machining.SuggestedAngles.Index = 2 + else + Machining.SuggestedAngles.Index = 1 + end + EgtSetMachiningParam( MCH_MP.INITANGS, BL.GetChainSawInitAngs( Machining.FaceToMachine.VtN, Machining.Direction, Machining.SuggestedAngles.Index)) + sErr = '' + bIsApplyOk = ML.ApplyMachining( true, false) + end + if not bIsApplyOk then + nErr, sErr = EgtGetLastMachMgrError() + EgtSetOperationMode( nOperationId, false) + return false, sErr + end + end + + return true, sErr +end + + +function SawPlusChain.Saw.GetSCC( vtMachiningDirection) + -- TODO implementare SCC come per FacesBySaw + local nSCC = MCH_SCC.NONE + if AreSameVectorApprox( vtMachiningDirection, Z_AX()) then + nSCC = MCH_SCC.ADIR_ZP + elseif AreOppositeVectorApprox( vtMachiningDirection, Z_AX()) then + nSCC = MCH_SCC.ADIR_ZM + elseif AreSameVectorApprox( vtMachiningDirection, Y_AX()) then + nSCC = MCH_SCC.ADIR_YP + elseif AreOppositeVectorApprox( vtMachiningDirection, Y_AX()) then + nSCC = MCH_SCC.ADIR_YM + elseif AreSameVectorApprox( vtMachiningDirection, X_AX()) then + nSCC = MCH_SCC.ADIR_XP + elseif AreOppositeVectorApprox( vtMachiningDirection, X_AX()) then + nSCC = MCH_SCC.ADIR_XM + end + + return nSCC +end + + +function SawPlusChain.Saw.CalculateMachiningParameters( Proc) + local Cutting = {} + Cutting.CanApply = true + Cutting.Message = '' + Cutting.ProcId = Proc.Id + + -- ricerca lavorazione + Cutting.Name = ML.FindCutting( 'HeadSide', true, false) + if not Cutting.Name then + Cutting.Message = 'Feature '.. Proc.FeatureId .. ' : strategy ' .. Proc.Pocket.Strategy .. ' not applicable - saw blade not found' + Cutting.CanApply = false + EgtOutLog( Cutting.Message) + return Cutting + end + Cutting.Type = MCH_OY.MILLING + Cutting.Tool = SawPlusChain.GetToolFromMachining( Cutting.Name) + Cutting.FaceToMachine = Proc.Pocket.FaceToMachine + + -- verifica dimensioni tasca compatibili + -- se tasca meno spessa della lama la strategia non è applicabile + if Cutting.Tool.Thickness > Proc.Pocket.Height + 10 * GEO.EPS_SMALL then + Cutting.Message = 'Feature '.. Proc.FeatureId .. ' : strategy ' .. Proc.Pocket.Strategy .. ' not applicable - pocket too narrow for saw blade thickness' + Cutting.CanApply = false + EgtOutLog( Cutting.Message) + return Cutting + end + if #( Proc.Pocket.SideFaces) > 1 then + -- se tasca più stretta della lama la strategia non è applicabile + if Cutting.Tool.Diameter > Proc.Pocket.Width + 10 * GEO.EPS_SMALL then + Cutting.Message = 'Feature '.. Proc.FeatureId .. ' : strategy ' .. Proc.Pocket.Strategy .. ' not applicable - pocket too narrow for saw blade diameter' + Cutting.CanApply = false + EgtOutLog( Cutting.Message) + return Cutting + end + end + + -- parametri della lavorazione + -- direzione utensile + Cutting.Direction = Proc.Pocket.Direction + -- lato di lavoro e inversioni + if Cutting.Tool.IsCCW then + Cutting.Workside = MCH_MILL_WS.RIGHT + Cutting.Invert = true + else + Cutting.Workside = MCH_MILL_WS.LEFT + Cutting.Invert = false + end + -- TODO gestire lama da sotto e lama downUp + if Cutting.FaceToMachine.VtN:getZ() < - 10 * GEO.EPS_SMALL then + Cutting.ToolInvert = true + Cutting.Invert = not Cutting.Invert + else + Cutting.ToolInvert = false + end + -- profondità e offset radiale + if Cutting.Tool.MaxDepth > Proc.Pocket.Depth - 10 * GEO.EPS_SMALL then + Cutting.Depth = Proc.Pocket.Depth + Cutting.RadialOffset = 0 + else + Cutting.Depth = Cutting.Tool.MaxDepth + Cutting.RadialOffset = Proc.Pocket.Depth - Cutting.Depth + if Proc.Pocket.ApplyOnlySawblade then + Cutting.Message = 'Feature '.. Proc.FeatureId .. ' : sawblade elevation (' .. EgtNumToString( Proc.Pocket.Depth, 1) .. ') bigger than max tool depth (' .. EgtNumToString( Cutting.Depth, 1) .. ')' + EgtOutLog( Cutting.Message) + end + end + -- step verticale e offset longitudinale + Cutting.Steps = SawPlusChain.GetVerticalSteps( Proc, Cutting) + Cutting.Steps.StepType = MCH_MILL_ST.ONEWAY + Cutting.MaxElev = Cutting.Steps.StepLength * Cutting.Steps.Count - 10 * GEO.EPS_SMALL + if Cutting.ToolInvert and Cutting.Steps.Count > 1 then + Cutting.LongitudinalOffset = - Proc.Pocket.Height + else + Cutting.LongitudinalOffset = 0 + end + -- distanza di sicurezza + Cutting.StartSafetyLength = 10 + -- overlap + Cutting.Overlap = 0 + -- faceuse + Cutting.Faceuse = BL.GetNearestOrthoOpposite( Cutting.Direction) + -- SCC + Cutting.SCC = SawPlusChain.Saw.GetSCC( Cutting.Direction) + -- angoli suggeriti + Cutting.SuggestedAngles = '' + -- asse bloccato + Cutting.BlockedAxis = {} + Cutting.BlockedAxis.Orientation = 'perpendicular' + Cutting.BlockedAxis.VtOut = EgtIf( Cutting.FaceToMachine.VtN:getX() > 0, X_AX(), -X_AX()) + -- approccio e retrazione + Cutting.LeadIn, Cutting.LeadOut = SawPlusChain.CalculateLeadInOut( Proc, Cutting) + -- eventuale step orizzontale + Cutting.HorizontalSteps = {} + if Cutting.Tool.SideStep then + Cutting.HorizontalSteps = SawPlusChain.GetHorizontalSteps( Cutting) + else + Cutting.HorizontalSteps.Count = 1 + Cutting.HorizontalSteps.StepLength = 0 + end + -- nome operazione + Cutting.OperationName = 'Cut_' .. ( EgtGetName( Cutting.ProcId) or tostring( Cutting.ProcId)) .. '_' .. tostring( Cutting.FaceToMachine.Id + 1) + + -- eventuale avviso di danneggiamento pezzo successivo + local dOffsideLength = max( Cutting.LeadIn.StartAddLength, Cutting.LeadOut.EndAddLength) + Cutting.Tool.Diameter / 2 + 10 * GEO.EPS_SMALL + if ( not Proc.Tail or Proc.AdvTail) and Proc.AffectedFaces.Left and ( Proc.Pocket.DistanceToNextPart < dOffsideLength) then + local sDamageNextPieceMessage = 'Feature '.. Proc.FeatureId .. ' : sawblade can damage next piece.' + if #Cutting.Message > 0 then + Cutting.Message = Cutting.Message .. '\n' .. sDamageNextPieceMessage + else + Cutting.Message = sDamageNextPieceMessage + end + EgtOutLog( sDamageNextPieceMessage) + end + + return Cutting +end + + +function SawPlusChain.Chainsaw.CalculateMachiningParameters( Proc) + local Chainsawing = {} + Chainsawing.CanApply = true + Chainsawing.Message = '' + Chainsawing.ProcId = Proc.Id + + -- ricerca lavorazione + Chainsawing.Name = ML.FindSawing( 'Sawing', Proc.Pocket.Depth) + if not Chainsawing.Name then + Chainsawing.Name = ML.FindSawing( 'Sawing', nil, nil, 'Longest') + end + if not Chainsawing.Name then + Chainsawing.Message = 'Feature '.. Proc.FeatureId .. ' : strategy ' .. Proc.Pocket.Strategy .. ' not applicable - chainsaw not found' + Chainsawing.CanApply = false + EgtOutLog( Chainsawing.Message) + return Chainsawing + end + Chainsawing.Type = MCH_OY.MORTISING + Chainsawing.Tool = SawPlusChain.GetToolFromMachining( Chainsawing.Name) + Chainsawing.FaceToMachine = Proc.Pocket.FaceToMachine + + -- verifica dimensioni tasca compatibili + -- se tasca meno spessa della sega a catena la strategia non è applicabile + if Chainsawing.Tool.Thickness > Proc.Pocket.Height + 10 * GEO.EPS_SMALL then + Chainsawing.Message = 'Feature '.. Proc.FeatureId .. ' : strategy ' .. Proc.Pocket.Strategy .. ' not applicable - pocket too narrow for chainsaw thickness' + Chainsawing.CanApply = false + EgtOutLog( Chainsawing.Message) + return Chainsawing + end + if #( Proc.Pocket.SideFaces) > 1 then + -- se tasca più stretta della sega a catena la strategia non è applicabile + if Chainsawing.Tool.Width > Proc.Pocket.Width + 10 * GEO.EPS_SMALL then + Chainsawing.Message = 'Feature '.. Proc.FeatureId .. ' : strategy ' .. Proc.Pocket.Strategy .. ' not applicable - pocket too narrow for chainsaw width' + Chainsawing.CanApply = false + EgtOutLog( Chainsawing.Message) + return Chainsawing + end + end + + -- parametri della lavorazione + -- direzione utensile + Chainsawing.Direction = Proc.Pocket.Direction + -- lato di lavoro e inversioni + if Chainsawing.Tool.IsCCW then + Chainsawing.Workside = MCH_MILL_WS.RIGHT + Chainsawing.Invert = false + else + Chainsawing.Workside = MCH_MILL_WS.LEFT + Chainsawing.Invert = true + end + Chainsawing.ToolInvert = false + -- profondità e offset longitudinale + if Chainsawing.Tool.MaxMat > Proc.Pocket.Depth - 10 * GEO.EPS_SMALL then + Chainsawing.Depth = Proc.Pocket.Depth + Chainsawing.LongitudinalOffset = 0 + else + Chainsawing.Depth = Chainsawing.Tool.MaxMat + Chainsawing.LongitudinalOffset = Proc.Pocket.Depth - Chainsawing.Depth + Chainsawing.Message = 'Feature '.. Proc.FeatureId .. ' : chainsaw elevation (' .. EgtNumToString( Proc.Pocket.Depth, 1) .. ') bigger than max tool depth (' .. EgtNumToString( Chainsawing.Depth, 1) .. ')' + EgtOutLog( Chainsawing.Message) + end + -- offset radiale + Chainsawing.RadialOffset = 0 + -- distanza di sicurezza + Chainsawing.StartSafetyLength = Proc.Pocket.Depth + -- overlap + Chainsawing.Overlap = 0 + -- faceuse + Chainsawing.Faceuse = BL.GetNearestParalOpposite( Chainsawing.Direction) + -- SCC + Chainsawing.SCC = MCH_SCC.NONE + -- asse bloccato e angoli suggeriti + Chainsawing.BlockedAxis = {} + Chainsawing.BlockedAxis.Orientation = 'perpendicular' + Chainsawing.SuggestedAngles = {} + Chainsawing.SuggestedAngles.Index = 1 + -- approccio e retrazione + Chainsawing.LeadIn, Chainsawing.LeadOut = SawPlusChain.CalculateLeadInOut( Proc, Chainsawing) + -- eventuale step verticale + Chainsawing.VerticalSteps = SawPlusChain.GetVerticalSteps( Proc, Chainsawing) + -- nome operazione + Chainsawing.OperationName = 'Chainsaw_' .. ( EgtGetName( Chainsawing.ProcId) or tostring( Chainsawing.ProcId)) .. '_' .. tostring( Chainsawing.FaceToMachine.Id + 1) + + -- eventuale avviso di danneggiamento pezzo successivo + local dOffsideLength = max( Chainsawing.LeadIn.StartAddLength, Chainsawing.LeadOut.EndAddLength) + Chainsawing.Tool.Width / 2 + 10 * GEO.EPS_SMALL + if ( not Proc.Tail or Proc.AdvTail) and Proc.AffectedFaces.Left and ( Proc.Pocket.DistanceToNextPart < dOffsideLength) then + local sDamageNextPieceMessage = 'Feature '.. Proc.FeatureId .. ' : chainsaw can damage next piece.' + if #Chainsawing.Message > 0 then + Chainsawing.Message = Chainsawing.Message .. '\n' .. sDamageNextPieceMessage + else + Chainsawing.Message = sDamageNextPieceMessage + end + EgtOutLog( sDamageNextPieceMessage) + end + + return Chainsawing +end + + +function SawPlusChain.Make( Proc, nRawId, nPhase, bOnlySaw) + Proc.Pocket = {} + Proc.Pocket.ApplyOnlySawblade = bOnlySaw + Proc.Pocket.Strategy = 'SawPlusChain' + local b3Raw = EgtGetRawPartBBox( nRawId) + + -- TODO per implementare la strategia con lapjoint lunghe bisogna prima riconoscere le topologie che arrivano + if Proc.IsSplittedLapJoint then + local sErr = 'Feature '.. Proc.FeatureId .. ' : strategy ' .. Proc.Pocket.Strategy .. ' not implemented for long lapjoint' + EgtOutLog( sErr) + return false, sErr + end + + if not SawPlusChain.IsTopologyOk( Proc) then + local sErr = 'Feature '.. Proc.FeatureId .. ' : strategy ' .. Proc.Pocket.Strategy .. ' not implemented' + EgtOutLog( sErr) + return false, sErr + end + + -- se tasca su faccia sotto la strategia non è applicabile (la sega a catena in generale non può lavorare da sotto) + -- TODO se OnlySaw questo test è da rimuovere ma bisogna considerare anche la lama da sotto + if Proc.AffectedFaces.Bottom and ( Proc.Fct > 3 or not Proc.AffectedFaces.Top) then + local sErr = 'Feature '.. Proc.FeatureId .. ' : strategy ' .. Proc.Pocket.Strategy .. ' not applicable - pocket on bottom face' + EgtOutLog( sErr) + return false, sErr + end + + -- caratteristiche della tasca + Proc.Pocket.BottomFace = SawPlusChain.GetBottomFace( Proc) + Proc.Pocket.FaceToMachine = SawPlusChain.GetFaceToMachine( Proc) + Proc.Pocket.SideFaces = SawPlusChain.GetSideFaces( Proc) + Proc.Pocket.Width = Proc.Pocket.BottomFace.Width + Proc.Pocket.Height = Proc.Pocket.BottomFace.Height + Proc.Pocket.Depth = Proc.Pocket.BottomFace.Elevation + Proc.Pocket.Direction = Proc.Pocket.BottomFace.VtN + Proc.Pocket.DistanceToNextPart = BL.GetDistanceToNextPart( nRawId, nPhase) + + -- parametri lavorazione di lama + local Cutting = SawPlusChain.Saw.CalculateMachiningParameters( Proc) + + -- applicazione lavorazione di lama con eventuali step XY + local bIsCuttingOk = false + local sCuttingApplyMessage = '' + if Cutting.CanApply then + local dOriginalRadialOffset = Cutting.RadialOffset + local dOriginalLeadInPerpDistance = Cutting.LeadIn.PerpDistance + local dOriginalLeadOutPerpDistance = Cutting.LeadOut.PerpDistance + for i = Cutting.HorizontalSteps.Count, 1, -1 do + Cutting.RadialOffset = dOriginalRadialOffset + Cutting.HorizontalSteps.StepLength * ( i - 1) + -- update distanza perpendicolare attacco per contemplare l'offset applicato + Cutting.LeadIn.PerpDistance = dOriginalLeadInPerpDistance - Cutting.RadialOffset + Cutting.LeadOut.PerpDistance = dOriginalLeadOutPerpDistance - Cutting.RadialOffset + -- applicazione lavorazione + bIsCuttingOk, sCuttingApplyMessage = SawPlusChain.ApplyMachining( Cutting, b3Raw) + -- update messaggi + if sCuttingApplyMessage and #sCuttingApplyMessage > 0 then + Cutting.Message = Cutting.Message .. 'Apply : ' .. sCuttingApplyMessage .. '\n' + end + end + end + + -- se tasca passante e la lama è arrivata sul fondo, non servono ulteriori lavorazioni + if #Proc.Pocket.SideFaces == 0 and Cutting.RadialOffset == 0 then + bOnlySaw = true + end + + if bOnlySaw or not bIsCuttingOk then + return bIsCuttingOk, Cutting.Message + end + + -- parametri lavorazione con sega a catena + local Chainsawing = SawPlusChain.Chainsaw.CalculateMachiningParameters( Proc) + -- si lavora solo quanto non lavorato dalla lama + Chainsawing.MaxElev = Cutting.RadialOffset + BD.CUT_EXTRA + + -- applicazione lavorazione con sega a catena con eventuali step in Z + local bIsChainsawingOk = false + local sChainsawingApplyMessage = '' + if Chainsawing.CanApply then + local dOriginalRadialOffsetChainsawing = Chainsawing.RadialOffset + for i = Chainsawing.VerticalSteps.Count, 1, -1 do + Chainsawing.RadialOffset = dOriginalRadialOffsetChainsawing + Chainsawing.VerticalSteps.StepLength * ( i - 1) + -- applicazione lavorazione + bIsChainsawingOk, sChainsawingApplyMessage = SawPlusChain.ApplyMachining( Chainsawing, b3Raw) + -- update messaggi + if sChainsawingApplyMessage and #sChainsawingApplyMessage > 0 then + Chainsawing.Message = Chainsawing.Message .. '\n' .. 'Apply : ' .. sChainsawingApplyMessage + end + end + end + + local sFinalMessage = '' + if #Cutting.Message > 0 or #Chainsawing.Message > 0 then + sFinalMessage = Cutting.Message .. '\n' .. Chainsawing.Message + end + + return bIsChainsawingOk, sFinalMessage +end + +--#endregion SawPlusChain + --------------------------------------------------------------------- local function MakeMoreFaces( Proc, nPhase, nRawId, nPartId, dOvmHead, bSinglePart, bPrevBhSideMill, bAllWithEndCap) if not BD.MAXDIAM_POCK_CORNER then @@ -4606,6 +5306,16 @@ local function MakeMoreFaces( Proc, nPhase, nRawId, nPartId, dOvmHead, bSinglePa EgtOutLog( sErr) return false, sErr end + + -- strategia lama + eventuale sega a catena + if ( EgtGetInfo( Proc.Id, Q_SAW_PLUS_CHAIN, 'i') or 0) > 0 then --TEST + local bOk + local sErr + local bOnlySaw = EgtGetInfo( Proc.Id, Q_SAW_PLUS_CHAIN, 'i') == 1 + bOk, sErr = SawPlusChain.Make ( Proc, nRawId, nPhase, bOnlySaw) + return bOk, sErr + end + local bClosedOrthoFaces local nFacInd, dFacElev, nFacInd2, dFacElev2 local nBottomFace @@ -5787,12 +6497,12 @@ local function MakeLongMoreFaces( Proc, nPhase, nRawId, nPartId, dOvmHead) for i = 1, #vAddId do local b3Box = EgtGetBBoxGlob( vAddId[i], GDB_BB.STANDARD) local nFct = EgtSurfTmFacetCount( vAddId[i]) - local AddProc = { Id = vAddId[i], Grp = Proc.Grp, Prc = Proc.Prc, Box = b3Box, TotBox = Proc.Box, Fct = nFct, Flg = Proc.Flg, PartId = Proc.PartId} + local AddProc = { Id = vAddId[i], Grp = Proc.Grp, Prc = Proc.Prc, Box = b3Box, TotBox = Proc.Box, Fct = nFct, Flg = Proc.Flg, PartId = Proc.PartId, TaskId = Proc.TaskId, FeatureId = Proc.FeatureId, IsSplittedLapJoint = true} Topology.Classify( AddProc, b3Raw) -- lasciare il false nel sesto parametro (perchè internamente viene verificato se diverso da nil) - local bOk, sMyWarn + local bOk, sMyWarn bOk, sMyWarn, bPrevBhSideMill = MakeMoreFaces( AddProc, nPhase, nRawId, nPartId, dOvmHead, bAllWithEndCap, bPrevBhSideMill, bAllWithEndCap) - if not sWarn then sWarn = sMyWarn end + if not sWarn or #sWarn == 0 then sWarn = sMyWarn end if not bOk then return bOk, sWarn end end return true, sWarn diff --git a/UpdateLog.txt b/UpdateLog.txt index 03b5c30..66cb719 100644 --- a/UpdateLog.txt +++ b/UpdateLog.txt @@ -1,5 +1,8 @@ ==== Beam Update Log ==== +Versione 2.6d2 (11/04/2024) +- Added : in LapJoint aggiunta strategia per fare tasche con lama + sega a catena, attivata da Q11 + Versione 2.6d1 (08/04/2024) - Fixed : in Long2Cut corretto nome passato alla BL.GetBlockedAxis - Fixed : in MakeTwo rimossa gestione calcolo differente su ultima passata in caso di macchina FAST diff --git a/Version.lua b/Version.lua index 2f64bf4..43512e9 100644 --- a/Version.lua +++ b/Version.lua @@ -2,5 +2,5 @@ -- Gestione della versione di Beam NAME = 'Beam' -VERSION = '2.6d1' +VERSION = '2.6d2' MIN_EXE = '2.6a1'