-- PreSimulationLib.lua by Egalware s.r.l. 2025/11/24 -- Libreria stima collisioni per travi -- Tabella per definizione modulo local PreSimulationLib = {} -- Include require( 'EgtBase') local BeamLib = require( 'BeamLib') local BeamData = require( 'BeamDataNew') EgtOutLog( ' PreSimulationLib started', 1) ------------------------------------------------------------------------------------------------------------- local function GetMachineAxes() local LinearAxes = {} local RotativeAxes = {} -- si recuperano tutti gli assi, lineari e rotativi local AxesNames = EgtGetAllCurrAxesNames() for i = 1, #AxesNames do -- EgtGetAxisType restituisce vero se asse lineare, false se asse rotativo if EgtGetAxisType( AxesNames[i]) then LinearAxes[#LinearAxes + 1] = {} LinearAxes[#LinearAxes].sName = AxesNames[i] else RotativeAxes[#RotativeAxes + 1] = {} RotativeAxes[#RotativeAxes].sName = AxesNames[i] end end return LinearAxes, RotativeAxes end ------------------------------------------------------------------------------------------------------------- local function LogOutstroke( sToolName, ptOnToolTipCenter, vtHead, OptionalParameters) -- parametri opzionali OptionalParameters = OptionalParameters or {} local LinearAxesValues = OptionalParameters.LinearAxesValues local RotativeAxesValues = OptionalParameters.RotativeAxesValues -- gruppo per geometrie temporanee local idTempGroup = BeamLib.GetTempGroup() -- si disegnano punto e vettore local idPoint = EgtPoint( idTempGroup, ptOnToolTipCenter, GDB_RT.GLOB) local idVector = EgtVector( idTempGroup, vtHead, ptOnToolTipCenter, GDB_RT.GLOB) EgtSetColor( idPoint, RED()) EgtSetColor( idVector, RED()) -- nome utensile EgtOutLog( 'Tool ' .. sToolName) -- si loggano valori di punto e vettore EgtOutLog( ' Presimulation : OutStroke, Tip Point = ' .. tostring( ptOnToolTipCenter) .. ', id = ' .. idPoint .. ', vtHead = ' .. tostring( vtHead) .. ', id = ' .. idVector) -- se disponibili, si loggano anche i valori calcolati degli assi if LinearAxesValues then EgtOutLog( ' ' .. 'Lin1' .. ' = ' .. tostring( LinearAxesValues[1]) .. ', ' .. 'Lin2' .. ' = ' .. tostring( LinearAxesValues[2]) .. ', ' .. 'Lin3' .. ' = ' .. tostring( LinearAxesValues[3])) end if RotativeAxesValues then EgtOutLog( ' ' .. 'Rot1' .. ' = ' .. tostring( RotativeAxesValues[1]) .. ', ' .. 'Rot2' .. ' = ' .. tostring( RotativeAxesValues[2]) .. ', ' .. 'Rot3' .. ' = ' .. tostring( RotativeAxesValues[3])) end return end ------------------------------------------------------------------------------------------------------------- -- costruzione trimesh del grezzo restante in testa o in coda local function GetRestlengthSurfTm( Part, sSide) -- si costruisce il box in globale local b3RestLength if sSide == 'Head' then local b3PartWithOvermaterial = BeamLib.GetPartBoxWithHeadTail( Part, sSide) local ptStartRestLength = Point3d( Part.b3Part:getMax():getX(), Part.b3Part:getMax():getY(), Part.b3Part:getMax():getZ()) local ptEndRestLength = Point3d( b3PartWithOvermaterial:getMax():getX(), Part.b3Part:getMin():getY(), Part.b3Part:getMin():getZ()) b3RestLength = BBox3d( ptStartRestLength, ptEndRestLength) elseif sSide == 'Tail' then local b3PartWithOvermaterial = BeamLib.GetPartBoxWithHeadTail( Part, sSide) local dXMin = b3PartWithOvermaterial:getMin():getX() -- si evita sempre di lavorare col motore dietro la coda della barra (potrebbe succedere con barra restante molto corta): in quel caso si deve sempre separare prima dXMin = min( dXMin, Part.b3Part:getMin():getX() - 2000) local ptStartRestLength = Point3d( Part.b3Part:getMin():getX(), Part.b3Part:getMax():getY(), Part.b3Part:getMax():getZ()) local ptEndRestLength = Point3d( dXMin, Part.b3Part:getMin():getY(), Part.b3Part:getMin():getZ()) b3RestLength = BBox3d( ptStartRestLength, ptEndRestLength) -- caso non testato, non dovrebbe mai finire qui (il default che arriva da fuori è Tail) else return nil end -- si crea la trimesh dal box local idRestLengthBoxTm = EgtSurfTmBBox( Part.idTempGroup, b3RestLength , false, GDB_RT.GLOB) return idRestLengthBoxTm end ------------------------------------------------------------------------------------------------------------- function PreSimulationLib.GetPointOnToolTipCenter( ptPointAtDepth, vtHead, vtNFace, vtToolOffset, Tool) return ptPointAtDepth + vtToolOffset * Tool.dDiameter / 2 + vtNFace * EgtIf( AreSameVectorApprox( vtHead, vtNFace), 0, Tool.dThickness) end ------------------------------------------------------------------------------------------------------------- -- calcolo punto sull'uscita testa a partire dal punto di lavorazione o di attacco sul diametro utensile local function GetToolExitPoint( ptMachining, vtNEdge, vtHead, Tool, bIsDownUp) local ptToolExitPoint = Point3d( ptMachining + vtNEdge * Tool.dDiameter / 2) + vtHead * EgtIf( bIsDownUp, ( Tool.dLength - Tool.dThickness), Tool.dLength) return ptToolExitPoint end ------------------------------------------------------------------------------------------------------------- -- calcolo pivot in riferimento globale, dati punto sull'uscita utensile e direzioni local function GetGlobalPivot( ptToolExit, vtC, vtHead, vtMovePivot) -- frame solidale all'utensile (lo stesso in cui vtMovePivot è definito) local frTool = Frame3d( ptToolExit, vtHead, vtC) local vtMovePivotGlob = Vector3d( vtMovePivot) vtMovePivotGlob:toGlob( frTool) local ptPivot = ptToolExit + vtMovePivotGlob return ptPivot end ------------------------------------------------------------------------------------------------------------- -- restituisce i punti notevoli della lavorazioni in cui fare il controllo local function GetCollisionPointsToCheck( Edge, dDepthToMachine) local PointsToCheck = {} -- punti notevoli local ptStart = Edge.ptStart + Edge.vtN * ( Edge.dElevation - dDepthToMachine) local ptEnd = Edge.ptEnd + Edge.vtN * ( Edge.dElevation - dDepthToMachine) local ptMid = Point3d( ( ptStart + ptEnd) / 2) -- caso ottimizzato: lato parallelo ad una direzione principale local bIsEdgeParallelToMainDirection = AreSameOrOppositeVectorApprox( Edge.vtEdge, X_AX()) or AreSameOrOppositeVectorApprox( Edge.vtEdge, Y_AX()) or AreSameOrOppositeVectorApprox( Edge.vtEdge, Z_AX()) -- aggiunta punti table.insert( PointsToCheck, ptStart) if not bIsEdgeParallelToMainDirection then table.insert( PointsToCheck, ptMid) end table.insert( PointsToCheck, ptEnd) return PointsToCheck end ------------------------------------------------------------------------------------------------------------- local function CheckOutOfStrokePoint( ptOnToolTipCenter, vtHead, nSCC, Tool, vtAux, sBlockedAxis) -- impostazione utensile local bOkTool = EgtSetCalcTool( Tool.sName, Tool.sHead, Tool.nExit) if not bOkTool then error( 'CheckOutOfStrokePoint : cannot set calc tool') end -- settaggio SCC per discriminare soluzioni multiple EgtSetCalcSolCh( nSCC) -- se presente, settaggio asse bloccato if sBlockedAxis and type( sBlockedAxis) == "string" then local BlockedAxis = EgtSplitString( sBlockedAxis, '=') EgtSetRotAxisBlock( BlockedAxis[1], tonumber( BlockedAxis[2])) end -- calcolo assi rotativi local bOkAngles, nSolutionsAngles, RotativeAxesValues = EgtGetCalcAnglesEx( vtHead, vtAux) local dRotative1 = RotativeAxesValues[1] local dRotative2 = RotativeAxesValues[2] local dRotative3 = RotativeAxesValues[3] if not bOkAngles then error( ' CheckOutOfStrokePoint : error') end -- se nessuna soluzione dagli assi rotativi, è in extracorsa if nSolutionsAngles == 0 then if EgtGetDebugLevel() >= 3 then LogOutstroke( Tool.sName, ptOnToolTipCenter, vtHead, { RotativeAxesValues = { dRotative1, dRotative2, dRotative3}}) end return true end -- calcolo assi lineari local bOkPositions, _, dLinear1, dLinear2, dLinear3 = EgtGetCalcPositions( ptOnToolTipCenter, dRotative1, dRotative2, dRotative3) if not bOkPositions then error( ' CheckOutOfStrokePoint : error') end -- verifica finecorsa per assi lineari (assi rotativi già verificati) local bAllAxesInStroke = EgtVerifyOutstroke( dLinear1, dLinear2, dLinear3) -- extracorsa if not bAllAxesInStroke then if EgtGetDebugLevel() >= 3 then LogOutstroke( Tool.sName, ptOnToolTipCenter, vtHead, { LinearAxesValues = { dLinear1, dLinear2, dLinear3}, RotativeAxesValues = { dRotative1, dRotative2, dRotative3}}) end return true end -- EgtSetAxisPos( 'T', dT) -- EgtSetAxisPos( 'Y', dY) -- EgtSetAxisPos( 'Z', dZ) -- EgtSetAxisPos( 'C', dC1) -- EgtSetAxisPos( 'A', dA1) -- se si arriva qui, il punto non è in finecorsa return false end ------------------------------------------------------------------------------------------------------------- -- check extracorsa da punti sul tip dell'utensile function PreSimulationLib.CheckOutOfStrokeFromPoints( PointsOnToolTipCenter, vtHead, nSCC, Tool, vtAux, sBlockedAxis) for i = 1, #PointsOnToolTipCenter do local bOutOfStroke = CheckOutOfStrokePoint( PointsOnToolTipCenter[i], vtHead, nSCC, Tool, vtAux, sBlockedAxis) -- se trovato extracorsa inutile procedere con gli altri punti if bOutOfStroke then return true end end -- se arrivati qui, nessun extracorsa return false end ------------------------------------------------------------------------------------------------------------- -- check extracorsa da geometria -- TODO da considerare anche gli attacchi function PreSimulationLib.CheckOutOfStrokeFromGeometry( idGeometry, vtHead, nSCC, Tool, vtAux, sBlockedAxis) local b3GeomMaxOffset = EgtGetBBoxGlob( idGeometry, GDB_BB.STANDARD) local ptBoxCenter = b3GeomMaxOffset:getCenter() local dBoxDimX = b3GeomMaxOffset:getDimX() local dBoxDimY = b3GeomMaxOffset:getDimY() local dBoxDimZ = b3GeomMaxOffset:getDimZ() -- si controlla il finecorsa nei punti al centro delle 6 facce del box local PointsOnToolTipCenter = {} -- X+ table.insert( PointsOnToolTipCenter, Point3d( ptBoxCenter + dBoxDimX / 2 * X_AX())) -- X- table.insert( PointsOnToolTipCenter, Point3d( ptBoxCenter - dBoxDimX / 2 * X_AX())) -- Y+ table.insert( PointsOnToolTipCenter, Point3d( ptBoxCenter + dBoxDimY / 2 * Y_AX())) -- Y- table.insert( PointsOnToolTipCenter, Point3d( ptBoxCenter - dBoxDimY / 2 * Y_AX())) -- Z+ table.insert( PointsOnToolTipCenter, Point3d( ptBoxCenter + dBoxDimZ / 2 * Z_AX())) -- Z- table.insert( PointsOnToolTipCenter, Point3d( ptBoxCenter - dBoxDimZ / 2 * Z_AX())) local bOutOfStroke = PreSimulationLib.CheckOutOfStrokeFromPoints( PointsOnToolTipCenter, vtHead, nSCC, Tool, vtAux, sBlockedAxis) return bOutOfStroke end ------------------------------------------------------------------------------------------------------------- local function MoveMachineAxesToPosition( ptOnToolTipCenter, vtHead, vtAux) -- calcolo assi rotativi local bOkAngles, nSolutionsAngles, RotativeAxesValues = EgtGetCalcAnglesEx( vtHead, vtAux) local dRotative1 = RotativeAxesValues[1] local dRotative2 = RotativeAxesValues[2] local dRotative3 = RotativeAxesValues[3] if not bOkAngles then error( ' MoveMachineAxesToPosition : error') end -- calcolo assi lineari local bOkPositions, _, dLinear1, dLinear2, dLinear3 = EgtGetCalcPositions( ptOnToolTipCenter, dRotative1, dRotative2, dRotative3) if not bOkPositions then error( ' MoveMachineAxesToPosition : error') end local AxesNames = EgtGetAllCurrAxesNames() local dTHome = EgtGetAxisHomePos( AxesNames[1]) -- spostamento assi in posizione (la T non si sposta perchè si sposta il pezzo) EgtSetAxisPos( AxesNames[2], dLinear2) EgtSetAxisPos( AxesNames[3], dLinear3) EgtSetAxisPos( AxesNames[4], dRotative1) EgtSetAxisPos( AxesNames[5], dRotative2) if dRotative3 then EgtSetAxisPos( AxesNames[6], dRotative3) end return dLinear1 - dTHome end ------------------------------------------------------------------------------------------------------------- local function CheckCollisionPoint( sAxis, ptOnToolTipCenter, vtHead, vtAux, Part, bCannotSplitRestLength, sRestLengthSideForPreSimulation, bCheckOnlyRestlength) -- spostamento assi macchina in posizione local dDeltaXHeadOffset = MoveMachineAxesToPosition( ptOnToolTipCenter, vtHead, vtAux) -- si recuperano gli id delle geometrie dell'asse con cui controllare la collisione local idCollisionGroup = EgtGetFirstNameInGroup( EgtGetAxisId( sAxis), 'COLLISION') local idCollisionGroupOther = EgtGetFirstNameInGroup( EgtGetAxisId( sAxis), 'OTHER_COLLISION') or GDB_ID.NULL local CollisionGroupEntitiesId = EgtGetAllInGroup( idCollisionGroup) local CollisionGroupOtherEntitiesId = EgtGetAllInGroup( idCollisionGroupOther) -- si tengono solo gli elementi trimesh local CollisionSurfTmId = {} for i = 1, #CollisionGroupEntitiesId do if EgtGetType( CollisionGroupEntitiesId[i]) == GDB_TY.SRF_MESH then local idCollisionSurfTmCopy = EgtCopyGlob( CollisionGroupEntitiesId[i], Part.idTempGroup) EgtMove( idCollisionSurfTmCopy, Vector3d( dDeltaXHeadOffset, 0, 0), GDB_RT.GLOB) table.insert( CollisionSurfTmId, idCollisionSurfTmCopy) end end -- se presenti geometrie nel gruppo other si aggiungono anche quelle if CollisionGroupOtherEntitiesId and #CollisionGroupOtherEntitiesId > 0 then for i = 1, #CollisionGroupOtherEntitiesId do if EgtGetType( CollisionGroupOtherEntitiesId[i]) == GDB_TY.SRF_MESH then local idCollisionOtherSurfTmCopy = EgtCopyGlob( CollisionGroupOtherEntitiesId[i], Part.idTempGroup) EgtMove( idCollisionOtherSurfTmCopy, Vector3d( dDeltaXHeadOffset, 0, 0), GDB_RT.GLOB) table.insert( CollisionSurfTmId, idCollisionOtherSurfTmCopy) end end end -- check collisione con pezzo local bCollisionFoundPiece = false if not bCheckOnlyRestlength then local idCheckCollisionTm = Part.idBoxTm -- se testa o coda attaccate, si considerano nella superficie di collisione if bCannotSplitRestLength then local b3CheckCollision = BeamLib.GetPartBoxWithHeadTail( Part, sRestLengthSideForPreSimulation) idCheckCollisionTm = EgtSurfTmBBox( Part.idTempGroup, b3CheckCollision, false, GDB_RT.GLOB) end for i = 1, #CollisionSurfTmId do bCollisionFoundPiece = EgtCDeSolidSolid( idCheckCollisionTm, CollisionSurfTmId[i], BeamData.COLL_SIC) if not type( bCollisionFoundPiece) == "boolean" then error( 'Presimulation fail') end if EgtGetDebugLevel() >= 3 and bCollisionFoundPiece then EgtSetColor( CollisionSurfTmId[i], RED()) end if bCollisionFoundPiece then break end end -- se trovata collisione con pezzo è inutile procedere con il grezzo if bCollisionFoundPiece then return true end end -- check collisione con grezzo restante, se con il pezzo non c'è collisione e non è un taglio di testa o coda local bCollisionFoundRestLength = false if not ( bCollisionFoundPiece or bCannotSplitRestLength) then local idRestLengthSurfFr = GetRestlengthSurfTm( Part, sRestLengthSideForPreSimulation) if idRestLengthSurfFr then for i = 1, #CollisionSurfTmId do bCollisionFoundRestLength = EgtCDeSolidSolid( idRestLengthSurfFr, CollisionSurfTmId[i], BeamData.COLL_SIC) if not type( bCollisionFoundRestLength) == "boolean" then error( 'Presimulation fail') end if EgtGetDebugLevel() >= 3 and bCollisionFoundRestLength then EgtSetColor( CollisionSurfTmId[i], ORANGE()) end if bCollisionFoundRestLength then break end end end end return false, bCollisionFoundRestLength end ------------------------------------------------------------------------------------------------------------- -- controllo collisione con verifica intersezione trimesh e geometrie da macchina local function CheckCollisionWithAxis( sAxis, MachiningParameters, OptionalParameters) -- parametri obbligatori local Edge = MachiningParameters.Edge local vtNFace = MachiningParameters.vtNFace local vtHead = MachiningParameters.vtHead local Part = MachiningParameters.Part local Tool = MachiningParameters.Tool local dDepthToMachine = MachiningParameters.dDepthToMachine -- parametri opzionali OptionalParameters = OptionalParameters or {} local bCheckOnlyRestlength = OptionalParameters.bCheckOnlyRestlength or false local sRestLengthSideForPreSimulation = OptionalParameters.sRestLengthSideForPreSimulation or 'Tail' local bCannotSplitRestLength = OptionalParameters.bCannotSplitRestLength or false local vtAux = OptionalParameters.vtAux -- se normale faccia non parallela a direzione testa c'è qualcosa che non va if not AreSameOrOppositeVectorApprox( vtNFace, vtHead) then error( 'CheckCollisionWithAxis : invalid directions') end -- punti notevoli della lavorazione in cui fare il check local PointsToCheck = OptionalParameters.PointsToCheck or GetCollisionPointsToCheck( Edge, dDepthToMachine) -- punti sul tip dell'utensile, in centro local PointsOnToolTipCenter = {} for i = 1, #PointsToCheck do PointsOnToolTipCenter[i] = PreSimulationLib.GetPointOnToolTipCenter( PointsToCheck[i], vtHead, vtNFace, Edge.vtN, Tool) end local bMoveAfterSplit = false -- se almeno in un punto c'è collisione con il pezzo si ritorna collisione -- se non si trova collisione si ritorna se è necessario separare prima di effettuare la lavorazione (ossia non c'è collisione con il pezzo ma c'è con il grezzo restante) for i = 1, #PointsOnToolTipCenter do local bCollisionFoundPiece, bCollisionFoundRestLength = CheckCollisionPoint( sAxis, PointsOnToolTipCenter[i], vtHead, vtAux, Part, bCannotSplitRestLength, sRestLengthSideForPreSimulation, bCheckOnlyRestlength) -- se trovata collisione con pezzo è inutile controllare gli altri punti if bCollisionFoundPiece then return true -- se trovata collisione con grezzo si setta che la lavorazione è da fare dopo separazione e si prosegue con gli altri punti elseif bCollisionFoundRestLength then bMoveAfterSplit = true end end -- se si arriva qui significa che non è stata trovata alcuna collisione con pezzo return false, bMoveAfterSplit end ------------------------------------------------------------------------------------------------------------- function PreSimulationLib.CheckCollision( sBladeEngagement, Parameters, OptionalParameters) local bCollisionFound local bMoveAfterSplitL3, bMoveAfterSplitR3, bMoveAfterSplitR2, bMoveAfterSplitR1 -- parametri obbligatori local Edge = Parameters.Edge local vtNFace = Parameters.vtNFace local Tool = Parameters.Tool -- parametri opzionali, in parte da far transitare OptionalParameters = OptionalParameters or {} local OptionalParametersCheckCollisionWithAxis = {} OptionalParametersCheckCollisionWithAxis.bCheckOnlyRestlength = false OptionalParametersCheckCollisionWithAxis.PointsToCheck = OptionalParameters.PointsToCheck or nil OptionalParametersCheckCollisionWithAxis.sRestLengthSideForPreSimulation = OptionalParameters.sRestLengthSideForPreSimulation or 'Tail' OptionalParametersCheckCollisionWithAxis.bCannotSplitRestLength = OptionalParameters.bCannotSplitRestLength or false OptionalParametersCheckCollisionWithAxis.sBlockedAxis = OptionalParameters.sBlockedAxis OptionalParametersCheckCollisionWithAxis.vtAux = OptionalParameters.vtAux local sBlockedAxis = OptionalParameters.sBlockedAxis local bIsDicing = OptionalParameters.bIsDicing or false local bDisableRealElevationCheck = OptionalParameters.bDisableRealElevationCheck or false local bCheckOnlyRestlengthForAxisABC = false -- se cubetti in modalità standard (no DownUp) gli assi AB e C si controllano solo con grezzo (ci sarebbe collisione con il materiale già rimosso controllando AB e C con pezzo) if bIsDicing and ( sBladeEngagement == 'Standard') then bCheckOnlyRestlengthForAxisABC = true -- se l'elevazione reale (rispetto al pezzo + eventuale materiale in testa/coda) è maggiore del massimo materiale è sempre collisione -- TODO rifare con funzione elseif not bDisableRealElevationCheck then local Edge = Parameters.Edge local vtNFace = Parameters.vtNFace local dDepthToMachine = Parameters.dDepthToMachine local b3BoxForElevationCheck = BBox3d( Parameters.Part.b3Part) -- se è un taglio di testa o coda va aggiunto il sovramateriale if OptionalParametersCheckCollisionWithAxis.bCannotSplitRestLength then b3BoxForElevationCheck = BeamLib.GetPartBoxWithHeadTail( Parameters.Part, OptionalParametersCheckCollisionWithAxis.sRestLengthSideForPreSimulation) end -- trimesh rettangolare con un lato corrispondente al lato da lavorare e larghezza come spessore utensile local idTrimesh = EgtSurfTmRectangle( Parameters.Part.idTempGroup, Edge.ptStart, Edge.ptEnd, Edge.ptEnd + vtNFace * Parameters.Tool.dThickness, GDB_RT.GLOB) local vtNTrimesh = EgtSurfTmFacetNormVersor( idTrimesh, 0, GDB_ID.ROOT) -- se trimesh con normale opposta a quella del lato, si inverte (non si sa a priori che verso avrà) if not AreSameVectorApprox( Edge.vtN, vtNTrimesh) then EgtInvertSurf( idTrimesh) end local dRealElevation = EgtSurfTmFacetElevationInBBox( idTrimesh, 0, b3BoxForElevationCheck, true, GDB_ID.ROOT) local dRealDepthToMachine = ( dRealElevation - Parameters.Edge.dElevation + dDepthToMachine) if dRealDepthToMachine > Parameters.Tool.dMaxDepth + 10 * GEO.EPS_SMALL then return true end end -- SCC local nSCC = Tool.SetupInfo.GetSCC( Edge.vtN, Edge.vtEdge, vtNFace) -- si settano utensile, SCC e asse bloccato per il controllo collisione local bOkTool = EgtSetCalcTool( Tool.sName, Tool.sHead, Tool.nExit) if not bOkTool then error( 'CheckCollisionWithAxis : cannot set calc tool') end EgtSetCalcSolCh( nSCC) if sBlockedAxis and type( sBlockedAxis) == "string" then local BlockedAxis = EgtSplitString( sBlockedAxis, '=') EgtSetRotAxisBlock( BlockedAxis[1], tonumber( BlockedAxis[2])) end -- nomi degli assi con cui controllare la collisione local AxesNames = EgtGetAllCurrAxesNames() local sL3 = AxesNames[3] local sR3 = AxesNames[6] local sR2 = AxesNames[5] local sR1 = AxesNames[4] -- ultimo asse lineare prima dei rotativi (solitamente Z) si controlla sempre bCollisionFound, bMoveAfterSplitL3 = CheckCollisionWithAxis( sL3, Parameters, OptionalParametersCheckCollisionWithAxis) -- assi rotativi: se richiesto si controlla la collisione solo col grezzo OptionalParametersCheckCollisionWithAxis.bCheckOnlyRestlength = bCheckOnlyRestlengthForAxisABC if sR3 and not bCollisionFound then bCollisionFound, bMoveAfterSplitR3 = CheckCollisionWithAxis( sR3, Parameters, OptionalParametersCheckCollisionWithAxis) end if not bCollisionFound then bCollisionFound, bMoveAfterSplitR2 = CheckCollisionWithAxis( sR2, Parameters, OptionalParametersCheckCollisionWithAxis) end if not bCollisionFound then bCollisionFound, bMoveAfterSplitR1 = CheckCollisionWithAxis( sR1, Parameters, OptionalParametersCheckCollisionWithAxis) end local bMoveAfterSplit = bMoveAfterSplitL3 or bMoveAfterSplitR3 or bMoveAfterSplitR2 or bMoveAfterSplitR1 return bCollisionFound, bMoveAfterSplit end ------------------------------------------------------------------------------------------------------------- return PreSimulationLib