-- LeadInOutLib.lua by Egalware s.r.l. 2025/11/24 -- Libreria stima collisioni per travi -- Tabella per definizione modulo local LeadInOutLib = {} -- Include require( 'EgtBase') local BeamData = require( 'BeamDataNew') local FaceData = require( 'FaceData') local BeamLib = require( 'BeamLib') EgtOutLog( ' LeadInOutLib started', 1) ------------------------------------------------------------------------------------------------------------- local function GetExtraAddLengthInclinedSides( Face, Edge) -- se faccia rettangolare i lati sono tutti a 90deg, inutile fare conti if FaceData.IsFaceRectangle( Face) then return 0, 0 end local nPreviousEdgeIndex = Edge.id + 1 - 1 if nPreviousEdgeIndex < 1 then nPreviousEdgeIndex = #Face.Edges end local nNextEdgeIndex = Edge.id + 1 + 1 if nNextEdgeIndex > #Face.Edges then nNextEdgeIndex = 1 end local vtEdgePrevious = Face.Edges[nPreviousEdgeIndex].vtEdge local vtEdgeNext = Face.Edges[nNextEdgeIndex].vtEdge local dLengthEdgePrevious = Face.Edges[nPreviousEdgeIndex].dLength local dLengthEdgeNext = Face.Edges[nNextEdgeIndex].dLength local dExtraPrevious = dLengthEdgePrevious * ( Edge.vtEdge * -vtEdgePrevious) local dExtraNext = dLengthEdgeNext * ( -Edge.vtEdge * vtEdgeNext) return dExtraPrevious, dExtraNext end ------------------------------------------------------------------------------------------------------------- local function GetPerpendicularLeadInOutDirection( Face, Edge) -- informazioni lati adiacenti local nCurrentEdgeIndex = Edge.id + 1 local nPreviousEdgeIndex = ( nCurrentEdgeIndex == 1 and #Face.Edges) or nCurrentEdgeIndex - 1 local nNextEdgeIndex = ( nCurrentEdgeIndex == #Face.Edges and 1) or nCurrentEdgeIndex + 1 local EdgeNext = Face.Edges[nNextEdgeIndex] local EdgePrevious = Face.Edges[nPreviousEdgeIndex] -- tra le direzioni dei due lati adiacenti, si sceglie la migliore da cui attaccare, ossia quella più vicina alla perpendicolare al lato di lavoro local dCosAngleStart = -EdgePrevious.vtEdge * Edge.vtN local dCosAngleEnd = EdgeNext.vtEdge * Edge.vtN local vtLeadInOut -- se le due direzioni sono entro i 5° scelgo quella a Z assoluta minore, altrimenti quella più vicino alla perpendicolare -- massima differenza scalare per variazione di 5deg: cos(0) - cos(0 + 5) = 1 - cos(5) local dScalarTolerance = 1 - 0.996 if abs( dCosAngleStart - dCosAngleEnd) < dScalarTolerance then if abs( EdgePrevious.vtEdge:getZ()) < abs( EdgeNext.vtEdge:getZ()) then vtLeadInOut = Vector3d( -EdgePrevious.vtEdge) else vtLeadInOut = Vector3d( EdgeNext.vtEdge) end else if dCosAngleStart > dCosAngleEnd then vtLeadInOut = Vector3d( -EdgePrevious.vtEdge) else vtLeadInOut = Vector3d( EdgeNext.vtEdge) end end return vtLeadInOut end ------------------------------------------------------------------------------------------------------------- local function CalculateLeadInOutLength( ptToolCenter, vtNFace, b3Box, vtLeadInOut, Tool) -- al momento gestita solo lama if not Tool.sFamily == 'SawBlade' then error(' Tool family not implemented') end -- Box del pezzo espansi ortogonalmente alle tre direzioni canoniche X, Y e Z local b3BoxX = BBox3d( b3Box) ; b3BoxX:expand( 0, 1000, 1000) local b3BoxY = BBox3d( b3Box) ; b3BoxY:expand( 1000, 0, 1000) local b3BoxZ = BBox3d( b3Box) ; b3BoxZ:expand( 1000, 1000, 0) -- si setta utensile lama per il controllo collisione EgtCAvSetSawTool( Tool.dThickness, Tool.dDiameter, Tool.dThickness, 0, 0) -- calcolo distanza di cui retrarre con funzioni Tool Collision Avoidance local dLength = min( EgtCAvToolPosBox( ptToolCenter + Tool.dThickness * vtNFace, vtNFace, b3BoxX, vtLeadInOut), EgtCAvToolPosBox( ptToolCenter + Tool.dThickness * vtNFace, vtNFace, b3BoxY, vtLeadInOut), EgtCAvToolPosBox( ptToolCenter + Tool.dThickness * vtNFace, vtNFace, b3BoxZ, vtLeadInOut)) return dLength end ------------------------------------------------------------------------------------------------------------- function LeadInOutLib.CalculateLeadInOut( sLeadInOutType, Parameters, OptionalParameters) -- parametri obbligatori local Face = Parameters.Face local Edge = Parameters.Edge local Part = Parameters.Part local Tool = Parameters.Tool local dDepthToMachine = Parameters.dDepthToMachine -- parametri opzionali local sRestLengthSideForPreSimulation = OptionalParameters.sRestLengthSideForPreSimulation or 'Tail' local bCannotSplitRestLength = OptionalParameters.bCannotSplitRestLength or false local LeadInOut = {} local bIsStartClosed = not Edge.bIsStartOpen local bIsEndClosed = not Edge.bIsEndOpen -- accorciamento per lati chiusi LeadInOut.dToolMarkLength = sqrt( dDepthToMachine * Tool.dDiameter - dDepthToMachine * dDepthToMachine) LeadInOut.dExtraAddLengthStart, LeadInOut.dExtraAddLengthEnd = GetExtraAddLengthInclinedSides( Face, Edge) -- allungamento per faccia singola (aperta in tutte le direzioni) LeadInOut.dAddedLengthOpenFace = BeamData.CUT_EXTRA local LeadIn = {} local LeadOut = {} LeadIn.dStartAddLength = 0 LeadOut.dEndAddLength = 0 LeadIn.nType = MCH_MILL_LI.LINEAR LeadOut.nType = MCH_MILL_LI.LINEAR LeadIn.dPerpDistance = 0 LeadOut.dPerpDistance = 0 LeadIn.dTangentDistance = 0 LeadOut.dTangentDistance = 0 LeadIn.dElevation = 0 LeadOut.dElevation = 0 LeadIn.dCompLength = 0 LeadOut.dCompLength = 0 -- calcolo allungamenti / accorciamenti if bIsStartClosed and bIsEndClosed then LeadIn.dStartAddLength = -LeadInOut.dToolMarkLength - LeadInOut.dExtraAddLengthStart LeadOut.dEndAddLength = -LeadInOut.dToolMarkLength - LeadInOut.dExtraAddLengthEnd elseif bIsStartClosed then LeadIn.dStartAddLength = -LeadInOut.dToolMarkLength - LeadInOut.dExtraAddLengthStart -- eventuale correzione per accorciamento maggiore di larghezza tasca LeadOut.dEndAddLength = max( -LeadIn.dStartAddLength - Edge.dLength + 10 * BeamData.CUT_EXTRA, BeamData.CUT_EXTRA) elseif bIsEndClosed then LeadOut.dEndAddLength = -LeadInOut.dToolMarkLength - LeadInOut.dExtraAddLengthEnd -- eventuale correzione per accorciamento maggiore di larghezza tasca LeadIn.dStartAddLength = max( -LeadOut.dEndAddLength - Edge.dLength + 10 * BeamData.CUT_EXTRA, BeamData.CUT_EXTRA) else LeadIn.dStartAddLength = LeadInOut.dAddedLengthOpenFace LeadOut.dEndAddLength = LeadInOut.dAddedLengthOpenFace end -- calcolo punti notevoli della lavorazione -- punti di inizio e fine lavorazione alla profondità di lavoro reale, considerando allungamenti/accorciamenti local ptStartAtDepth = Edge.ptStart - Edge.vtEdge * LeadIn.dStartAddLength + Edge.vtN * ( Edge.dElevation - dDepthToMachine) local ptEndAtDepth = Edge.ptEnd + Edge.vtEdge * LeadOut.dEndAddLength + Edge.vtN * ( Edge.dElevation - dDepthToMachine) -- punti in centro lama local ptStartBladeCenter = ptStartAtDepth + Edge.vtN * Tool.dDiameter / 2 local ptEndBladeCenter = ptEndAtDepth + Edge.vtN * Tool.dDiameter / 2 -- box per calcolo uscita lama -- se è un taglio di testa o coda va aggiunto il sovramateriale local b3BoxPartExpanded = BBox3d( Part.b3Part) if bCannotSplitRestLength then b3BoxPartExpanded = BeamLib.GetPartBoxWithHeadTail( Part, sRestLengthSideForPreSimulation) end -- il box si espande in tutte le direzioni per contemplare la sicurezza CUT_SIC b3BoxPartExpanded:expand( BeamData.CUT_SIC) -- calcolo attacco scelto if sLeadInOutType == 'Perpendicular' then -- scelta direzione migliore per l'attacco local vtLeadInOut = GetPerpendicularLeadInOutDirection( Face, Edge) -- frame solidale al lato di lavoro (X lungo il lato, Y normale al lato) local frEdge = Frame3d( Edge.ptStart, Face.vtN, Edge.vtEdge) -- direzione nel frame solidale al lato di lavoro local vtLeadInOuttLoc = Vector3d( vtLeadInOut) vtLeadInOuttLoc:toLoc( frEdge) -- calcolo distanza per uscire dal box con questa lama nella direzione vtLeadInOut local dLeadInLength = CalculateLeadInOutLength( ptStartBladeCenter, Face.vtN, b3BoxPartExpanded, vtLeadInOut, Tool) local dLeadOutLength = CalculateLeadInOutLength( ptEndBladeCenter, Face.vtN, b3BoxPartExpanded, vtLeadInOut, Tool) -- componenti dell'attacco LeadIn.dPerpDistance = dLeadInLength * vtLeadInOuttLoc:getY() LeadIn.dTangentDistance = dLeadInLength * -vtLeadInOuttLoc:getX() LeadOut.dPerpDistance = dLeadOutLength * vtLeadInOuttLoc:getY() LeadOut.dTangentDistance = dLeadOutLength * vtLeadInOuttLoc:getX() -- punti dell'attacco LeadIn.ptPoint = Point3d( ptStartAtDepth + vtLeadInOut * dLeadInLength) LeadOut.ptPoint = Point3d( ptEndAtDepth + vtLeadInOut * dLeadOutLength) elseif sLeadInOutType == 'Tangent' then -- calcolo distanza per uscire dal box con questa lama nella direzione tangenziale local dLeadInLength = CalculateLeadInOutLength( ptStartBladeCenter, Face.vtN, b3BoxPartExpanded, -Edge.vtEdge, Tool) local dLeadOutLength = CalculateLeadInOutLength( ptEndBladeCenter, Face.vtN, b3BoxPartExpanded, Edge.vtEdge, Tool) -- componenti dell'attacco LeadIn.dPerpDistance = 0 LeadIn.dTangentDistance = dLeadInLength LeadOut.dPerpDistance = 0 LeadOut.dTangentDistance = dLeadOutLength -- punti dell'attacco LeadIn.ptPoint = Point3d( ptStartAtDepth - Edge.vtEdge * dLeadInLength) LeadOut.ptPoint = Point3d( ptEndAtDepth + Edge.vtEdge * dLeadOutLength) end -- lunghezza totale attacco LeadIn.dTotalLength = sqrt( LeadIn.dPerpDistance ^ 2 + LeadIn.dTangentDistance ^ 2) LeadOut.dTotalLength = sqrt( LeadOut.dPerpDistance ^ 2 + LeadOut.dTangentDistance ^ 2) LeadInOut.dTotalLength = LeadIn.dTotalLength + LeadOut.dTotalLength LeadInOut.LeadIn = LeadIn LeadInOut.LeadOut = LeadOut return LeadInOut end ------------------------------------------------------------------------------------------------------------- function LeadInOutLib.InvertLeadInOut( LeadIn, LeadOut) local dOriginalStartAddLength = LeadIn.dStartAddLength local dOriginalEndAddLength = LeadOut.dEndAddLength LeadIn, LeadOut = LeadOut, LeadIn LeadIn.dStartAddLength = dOriginalEndAddLength LeadOut.dEndAddLength = dOriginalStartAddLength LeadIn.dEndAddLength = nil LeadOut.dStartAddLength = nil return LeadIn, LeadOut end ------------------------------------------------------------------------------------------------------------- return LeadInOutLib