Files
DataBeam/LuaLibs/BeamLib.lua
T
luca.mazzoleni 44a36c4acd - In LapJoint corretto il recupero dati utensile che, in alcune funzioni, puntava all'utensile errato.
- In BeamLib ChangeOrOpenStart corretta ricerca segmento più lungo.
2023-06-12 16:44:51 +02:00

1063 lines
42 KiB
Lua

-- BeamLib.lua by Egaltech s.r.l. 2023/03/22
-- Libreria globale per Travi
-- 2020/07/28 Corretto calcolo attacchi e uscite di lame per non uscire dalla faccia sotto.
-- 2020/08/18 Aggiunto a GetNearestParalOpposite e GetNearestOrthoOpposite parametro opzionale vtNorm.
-- 2020/11/03 Aggiunta funzione IsEndOrEnd2Phase.
-- 2020/11/18 Correzioni a GetParallelOpposite e a GetFaceElevation.
-- 2021/06/27 Aggiunta funzione GetOtherFaceElevation.
-- 2021/07/01 In GetNearestOrthoOpposite premio direzioni destra/sinistra.
-- 2021/07/15 Aggiunta GetFaceElevationFromPointDir.
-- 2021/09/12 Aggiustamenti in GetNearestParalOpposite e GetNearestOrthoOpposite.
-- 2022/01/11 In GetNearest*Opposite ridotto vantaggio XY rispetto a Z da 1 -> 0.9 a 1 -> 0.99.
-- 2022/04/05 Modifiche a GetNzLimDownUp per FAST.
-- 2022/05/03 Ulteriore limitazione a GetNzLimDownUp per FAST.
-- 2022/05/18 Correzioni e migliorie a PutStartNearestToEdge.
-- 2022/06/25 Rese globali le funzioni GetChainSawBlockedAxis e GetChainSawInitAngs prima in ProcessLapJpoint.
-- 2022/07/12 A GetFaceHvRefDim aggiunta possibilità di confronto e limitazione dimensioni con grezzo/pezzo (conta solo la sezione).
-- 2022/07/26 Aggiunta la funzione FindFaceBestOrientedAsAxis, precedentemente in ProcessLapJoint
-- 2022/07/26 Alla funzione FindFaceBestOrientedAsAxis aggiunta la possibilità di escludere una faccia dalla ricerca
-- 2022/09/01 Aggiunte le funzioni GetTunnelDimension, CalcCollisionSafety, SetOpenSide, precedentemente in ProcessLapJoint.
-- 2023/01/10 In GetFaceWithMostAdj aggiunta verifica che la feature abbia almeno una faccia aperta.
-- 2023/01/20 Modificata PutStartNearestToEdge per gestire lato preferito come Y+, Y-, z*, Z-. Aggiunta funzione GetDistanceToNextPart.
-- 2023/01/31 Aggiunta funzione ConvertToClosedCurve, precedentemente parte di ProcessMortise.Make
-- 2023/02/22 Modifiche a SetOpenSide, aggiunte ChangeOrOpenStart e CurveWithOnlyStraightLines.
-- 2023/06/12 In ChangeOrOpenStart corretta ricerca segmento più lungo.
-- Tabella per definizione modulo
local BeamLib = {}
-- Include
require( 'EgtBase')
EgtOutLog( ' BeamLib started', 1)
-- Dati
local BD = require( 'BeamData')
-------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------
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
-------------------------------------------------------------------------------------------------------------
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.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.PutStartOnTop( nCrvId)
-- verifico che la curva sia chiusa
if not EgtCurveIsClosed( nCrvId) then return false end
-- cerco l'estremo più alto e lo imposto come inizio
local dUmax = 0
local dZmax = - GEO.INFINITO
local dUi, dUf = EgtCurveDomain( nCrvId)
for dU = dUi, dUf, 0.5 do
local ptP = EgtUP( nCrvId, dU, GDB_ID.ROOT)
if ptP and ptP:getZ() > dZmax + GEO.EPS_SMALL then
dZmax = ptP:getZ()
dUmax = dU
end
end
if abs( dUmax - dUi) > GEO.EPS_ZERO then
EgtChangeClosedCurveStart( nCrvId, dUmax)
end
return true
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.PutStartOnLonger( nCrvId)
-- verifico che la curva sia chiusa
if not EgtCurveIsClosed( nCrvId) then return false end
-- cerco l'entità più lunga e la imposto come inizio
local dUmax = 0
local dLmax = - GEO.INFINITO
local dUi, dUf = EgtCurveDomain( nCrvId)
for dU = dUi, dUf - 1 do
local ptP1 = EgtUP( nCrvId, dU, GDB_ID.ROOT)
local ptP2 = EgtUP( nCrvId, dU + 0.5, GDB_ID.ROOT)
local ptP3 = EgtUP( nCrvId, dU + 1.0, GDB_ID.ROOT)
local dL = dist( ptP1, ptP2) + dist( ptP2, ptP3)
if dL > dLmax + GEO.EPS_SMALL then
dLmax = dL
dUmax = dU
end
end
if abs( dUmax - dUi) > GEO.EPS_ZERO then
EgtChangeClosedCurveStart( nCrvId, dUmax)
end
return true
end
-------------------------------------------------------------------------------------------------------------
-- nNearSide : 2=Y+, -2=Y-, 3=Z+, -3=Z-
function BeamLib.PutStartNearestToEdge( nCrvId, b3Raw, dMaxDist, nNearSide)
-- verifico che la curva sia chiusa
if not EgtCurveIsClosed( nCrvId) then return false end
-- recupero il versore normale al piano di lavoro o estrusione
local vtN = EgtCurveExtrusion( nCrvId, GDB_ID.ROOT)
-- coefficienti per riportare la distanza nel piano di lavoro
local dCoeffY = 0
if abs( vtN:getY()) < 0.999 then dCoeffY= 1 / ( sqrt( 1 - vtN:getY() * vtN:getY())) end
local dCoeffZ = 0
if abs( vtN:getZ()) < 0.999 then dCoeffZ = 1 / ( sqrt( 1 - vtN:getZ() * vtN:getZ())) end
-- cerco l'estremo più vicino al box e lo imposto come inizio (se da sotto escludo Zmax e viceversa)
local dUopt = 0
local dDopt = GEO.INFINITO
local dSopt = GEO.INFINITO
local dUi, dUf = EgtCurveDomain( nCrvId)
for dU = dUi, dUf, 0.5 do
local ptP = EgtUP( nCrvId, dU, GDB_ID.ROOT)
local vtDp = EgtUV( nCrvId, dU, -1, GDB_ID.ROOT)
local vtDs = EgtUV( nCrvId, dU, 1, GDB_ID.ROOT)
local bTg = ( vtDp and vtDs and vtDp * vtDs > 0.96)
if ptP and bTg then
local vtMin = ptP - b3Raw:getMin()
local vtMax = ptP - b3Raw:getMax()
local dD = abs( vtMin:getY()) * dCoeffY
dD = min( abs( vtMax:getY()) * dCoeffY, dD)
dD = min( abs( vtMin:getZ()) * dCoeffZ, dD)
dD = min( abs( vtMax:getZ()) * dCoeffZ, dD)
local dS
if nNearSide == -2 then
dS = abs( vtMin:getY() * dCoeffY)
elseif nNearSide == 2 then
dS = abs( vtMax:getY() * dCoeffY)
elseif nNearSide == -3 then
dS = abs( vtMin:getZ() * dCoeffZ)
else --nNearSide == 3
dS = abs( vtMax:getZ() * dCoeffZ)
end
if dD < dMaxDist and dS < dSopt + GEO.EPS_SMALL then
dUopt = dU
dDopt = dD
dSopt = dS
end
end
end
if abs( dUopt - dUi) > GEO.EPS_ZERO and abs( dUopt - dUf) > GEO.EPS_ZERO then
EgtChangeClosedCurveStart( nCrvId, dUopt)
end
return true
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.GetPointDirDepth( nPartId, ptP, vtDir)
-- recupero il solido del grezzo
local nSolId = EgtGetFirstNameInGroup( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, 'Box')
if not nSolId then return end
-- interseco con la retta
local bOk, vType, vPar = EgtLineSurfTmInters( ptP, vtDir, nSolId, GDB_RT.GLOB)
if not bOk then return end
if not vPar or #vPar == 0 then return -2 end
local dLenIn, dLenOut
for i = 1, #vPar do
if vPar[i] < 0 then
if vType[i] == GDB_SLT.IN or vType[i] == GDB_SLT.TG_INI then
dLenIn = -1
end
if vType[i] == GDB_SLT.OUT or vType[i] == GDB_SLT.TG_FIN then
dLenIn = -2
end
else
if vType[i] == GDB_SLT.IN or vType[i] == GDB_SLT.TG_INI then
dLenIn = vPar[i]
end
if vType[i] == GDB_SLT.OUT or vType[i] == GDB_SLT.TG_FIN or vType[i] == GDB_SLT.TOUCH then
dLenOut = vPar[i]
end
end
end
return dLenIn, dLenOut
end
---------------------------------------------------------------------
function BeamLib.GetNearestParalOpposite( vtRef, vtNorm)
-- se definita anche la normale alla faccia, elimino la parte di vtRef parallela a questa
local vtMyRef = Vector3d( vtRef)
if vtNorm then
vtMyRef = vtMyRef - ( vtMyRef * vtNorm) * vtNorm
vtMyRef:normalize()
end
-- se prevalente una componente orizzontale (con piccolissimo vantaggio)
if abs( vtMyRef:getX()) > 0.95 * abs( vtMyRef:getZ()) or abs( vtMyRef:getY()) > 0.95 * abs( vtMyRef:getZ()) then
if abs( vtMyRef:getX()) > 0.95 * abs( vtMyRef:getY()) then
if vtMyRef:getX() > -GEO.EPS_SMALL then
return MCH_MILL_FU.PARAL_LEFT
else
return MCH_MILL_FU.PARAL_RIGHT
end
else
if vtMyRef:getY() > -GEO.EPS_SMALL then
return MCH_MILL_FU.PARAL_FRONT
else
return MCH_MILL_FU.PARAL_BACK
end
end
-- altrimenti prevale la verticale
else
if vtMyRef:getZ() > -GEO.EPS_SMALL then
return MCH_MILL_FU.PARAL_DOWN
else
return MCH_MILL_FU.PARAL_TOP
end
end
return nil
end
---------------------------------------------------------------------
function BeamLib.GetNearestOrthoOpposite( vtRef, vtNorm)
-- se definita anche la normale alla faccia, elimino la parte di vtRef parallela a questa
local vtMyRef = Vector3d( vtRef)
if vtNorm then
vtMyRef = vtMyRef - ( vtMyRef * vtNorm) * vtNorm
vtMyRef:normalize()
end
-- se prevalente una componente orizzontale (con piccolissimo vantaggio)
if abs( vtMyRef:getX()) > 0.91 * abs( vtMyRef:getZ()) or abs( vtMyRef:getY()) > 0.91 * abs( vtMyRef:getZ()) then
-- se prevale la componente destra/sinistra
if abs( vtMyRef:getX()) > 0.95 * abs( vtMyRef:getY()) then
if vtMyRef:getX() > -GEO.EPS_SMALL then
return MCH_MILL_FU.ORTHO_LEFT
else
return MCH_MILL_FU.ORTHO_RIGHT
end
else
if vtMyRef:getY() > -GEO.EPS_SMALL then
return MCH_MILL_FU.ORTHO_FRONT
else
return MCH_MILL_FU.ORTHO_BACK
end
end
-- altrimenti prevale la verticale
else
if vtMyRef:getZ() > -GEO.EPS_SMALL then
return MCH_MILL_FU.ORTHO_DOWN
else
return MCH_MILL_FU.ORTHO_TOP
end
end
return nil
end
---------------------------------------------------------------------
function BeamLib.GetOrtupOpposite( nOrthoOpposite)
if nOrthoOpposite == MCH_MILL_FU.ORTHO_LEFT then
return MCH_MILL_FU.ORTUP_LEFT
elseif nOrthoOpposite == MCH_MILL_FU.ORTHO_RIGHT then
return MCH_MILL_FU.ORTUP_RIGHT
elseif nOrthoOpposite == MCH_MILL_FU.ORTHO_FRONT then
return MCH_MILL_FU.ORTUP_FRONT
elseif nOrthoOpposite == MCH_MILL_FU.ORTHO_BACK then
return MCH_MILL_FU.ORTUP_BACK
elseif nOrthoOpposite == MCH_MILL_FU.ORTHO_DOWN then
return MCH_MILL_FU.ORTUP_DOWN
elseif nOrthoOpposite == MCH_MILL_FU.ORTHO_TOP then
return MCH_MILL_FU.ORTUP_TOP
end
return nil
end
---------------------------------------------------------------------
function BeamLib.GetParallelOpposite( nOrthoOpposite)
if nOrthoOpposite == MCH_MILL_FU.ORTHO_LEFT then
return MCH_MILL_FU.PARAL_LEFT
elseif nOrthoOpposite == MCH_MILL_FU.ORTHO_RIGHT then
return MCH_MILL_FU.PARAL_RIGHT
elseif nOrthoOpposite == MCH_MILL_FU.ORTHO_FRONT then
return MCH_MILL_FU.PARAL_FRONT
elseif nOrthoOpposite == MCH_MILL_FU.ORTHO_BACK then
return MCH_MILL_FU.PARAL_BACK
elseif nOrthoOpposite == MCH_MILL_FU.ORTHO_DOWN then
return MCH_MILL_FU.PARAL_DOWN
elseif nOrthoOpposite == MCH_MILL_FU.ORTHO_TOP then
return MCH_MILL_FU.PARAL_TOP
end
return nil
end
---------------------------------------------------------------------
function BeamLib.GetVersRef( nOrthoOpposite)
if nOrthoOpposite == MCH_MILL_FU.ORTHO_LEFT or nOrthoOpposite == MCH_MILL_FU.ORTUP_LEFT or nOrthoOpposite == MCH_MILL_FU.PARAL_LEFT then
return X_AX()
elseif nOrthoOpposite == MCH_MILL_FU.ORTHO_RIGHT or nOrthoOpposite == MCH_MILL_FU.ORTUP_RIGHT or nOrthoOpposite == MCH_MILL_FU.PARAL_RIGHT then
return -X_AX()
elseif nOrthoOpposite == MCH_MILL_FU.ORTHO_FRONT or nOrthoOpposite == MCH_MILL_FU.ORTUP_FRONT or nOrthoOpposite == MCH_MILL_FU.PARAL_FRONT then
return Y_AX()
elseif nOrthoOpposite == MCH_MILL_FU.ORTHO_BACK or nOrthoOpposite == MCH_MILL_FU.ORTUP_BACK or nOrthoOpposite == MCH_MILL_FU.PARAL_BACK then
return -Y_AX()
elseif nOrthoOpposite == MCH_MILL_FU.ORTHO_DOWN or nOrthoOpposite == MCH_MILL_FU.ORTUP_DOWN or nOrthoOpposite == MCH_MILL_FU.PARAL_DOWN then
return Z_AX()
elseif nOrthoOpposite == MCH_MILL_FU.ORTHO_TOP or nOrthoOpposite == MCH_MILL_FU.ORTUP_TOP or nOrthoOpposite == MCH_MILL_FU.PARAL_TOP then
return -Z_AX()
end
return nil
end
---------------------------------------------------------------------
function BeamLib.GetBoxFaceNorm( b3Box, ptP, vtV)
local vtNx = V_NULL()
if abs( ptP:getX() - b3Box:getMin():getX()) < 10 * GEO.EPS_SMALL then
vtNx = -X_AX()
elseif abs( ptP:getX() - b3Box:getMax():getX()) < 10 * GEO.EPS_SMALL then
vtNx = X_AX()
end
local vtNy = V_NULL()
if abs( ptP:getY() - b3Box:getMin():getY()) < 10 * GEO.EPS_SMALL then
vtNy = -Y_AX()
elseif abs( ptP:getY() - b3Box:getMax():getY()) < 10 * GEO.EPS_SMALL then
vtNy = Y_AX()
end
local vtNz = V_NULL()
if abs( ptP:getZ() - b3Box:getMin():getZ()) < 10 * GEO.EPS_SMALL then
vtNz = -Z_AX()
elseif abs( ptP:getZ() - b3Box:getMax():getZ()) < 10 * GEO.EPS_SMALL then
vtNz = Z_AX()
end
local dNxDotV = vtNx * vtV
local dNyDotV = vtNy * vtV
local dNzDotV = vtNz * vtV
if dNxDotV > dNyDotV and dNxDotV > dNzDotV then
return vtNx
elseif dNyDotV > dNzDotV then
return vtNy
else
return vtNz
end
end
---------------------------------------------------------------------
function BeamLib.GetFaceElevation( nSurfId, nFac, nPartId)
-- centro e normale della faccia
local ptC, vtN = EgtSurfTmFacetCenter( nSurfId, nFac, GDB_ID.ROOT)
if not ptC or not vtN then return 0 end
-- riferimento OCS della faccia per ricavare elevazione rispetto alla faccia della superficie
local frOCS = Frame3d( ptC, vtN)
local b3Box = EgtGetBBoxRef( nSurfId, GDB_BB.STANDARD, frOCS)
local dElev = b3Box:getMax():getZ()
-- se definito identificativo di pezzo
if nPartId then
-- se superficie con più facce
if EgtSurfTmFacetCount( nSurfId) > 1 then
-- determino elevazione del centro faccia rispetto al box del pezzo
local _, dCenElev = BeamLib.GetPointDirDepth( nPartId, ptC, vtN)
if dCenElev and dCenElev > dElev then
dElev = dCenElev
end
-- altrimenti superficie ad una sola faccia
else
-- determino elevazione box del pezzo rispetto alla faccia
local b3Solid = EgtGetBBoxRef( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD, frOCS)
local dSolidElev = b3Solid:getMax():getZ()
if b3Solid and dSolidElev > dElev then
dElev = dSolidElev
end
end
end
return dElev
end
---------------------------------------------------------------------
function BeamLib.GetOtherFaceElevation( nSurfId, nOtherSurfId, nOtherFac, nPartId)
-- centro e normale della faccia
local ptC, vtN = EgtSurfTmFacetCenter( nOtherSurfId, nOtherFac, GDB_ID.ROOT)
if not ptC or not vtN then return 0 end
-- riferimento OCS della faccia per ricavare elevazione rispetto alla faccia della superficie
local frOCS = Frame3d( ptC, vtN)
local b3Box = EgtGetBBoxRef( nSurfId, GDB_BB.STANDARD, frOCS)
local dElev = b3Box:getMax():getZ()
-- se definito identificativo di pezzo
if nPartId then
-- determino elevazione del centro faccia rispetto al box del pezzo
local _, dCenElev = BeamLib.GetPointDirDepth( nPartId, ptC, vtN)
if dCenElev and dCenElev > dElev then
dElev = dCenElev
end
end
return dElev
end
---------------------------------------------------------------------
function BeamLib.GetFaceElevationFromPointDir( nSurfId, nPartId, ptC, vtN, nIdGeomMaster)
if not ptC or not vtN then return 0 end
-- riferimento OCS della faccia per ricavare elevazione rispetto alla faccia della superficie
local frOCS = Frame3d( ptC, vtN)
local b3Box = EgtGetBBoxRef( nSurfId, GDB_BB.STANDARD, frOCS)
local dElev = b3Box:getMax():getZ()
-- se definito identificativo di pezzo
if nPartId then
-- se superficie con più facce
if EgtSurfTmFacetCount( nSurfId) > 1 then
_, dElev = BeamLib.GetPointDirDepth( nPartId, ptC, vtN)
else
local b3Solid = EgtGetBBoxRef( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD, frOCS)
if b3Solid and b3Solid:getMax():getZ() > dElev then
dElev = b3Solid:getMax():getZ()
end
end
end
return dElev
end
---------------------------------------------------------------------
function BeamLib.GetFaceWithMostAdj( nSurfId, nPartId, bCompare3Fc, dCosSideAng)
-- verifica che la superficie non sia chiusa e quindi non lavorabile
if EgtSurfIsClosed( nSurfId) then
return
end
-- recupero il numero di facce
local nFacCnt = EgtSurfTmFacetCount( nSurfId)
if not dCosSideAng then
dCosSideAng = -0.09
end
-- recupero le normali delle facce
local vvtN = {}
for i = 1, nFacCnt do
local vtN = EgtSurfTmFacetNormVersor( nSurfId, i - 1, GDB_ID.ROOT)
vvtN[i] = vtN ;
end
-- adiacenze e sottosquadra delle facce
local vAdj = {}
local vUcut = {}
local vOrtho = {}
for i = 1, nFacCnt do
-- recupero le adiacenze del loop esterno
local vFacAdj = EgtSurfTmFacetAdjacencies( nSurfId, i - 1)[1]
-- le conto
local nCount = 0
for j = 1, #vFacAdj do
if vFacAdj[j] >= 0 then
nCount = nCount + 1
end
end
vAdj[i] = nCount
-- ne determino eventuale sottosquadra ( dal valore passato o - 3deg) e ortogonalità
local bUcut = false
local bOrtho = true
for j = 1, #vFacAdj do
if vFacAdj[j] >= 0 then
local vtN = vvtN[i]
local vtN2 = vvtN[vFacAdj[j]+1]
local dResV = vtN * vtN2
if dResV < dCosSideAng - GEO.EPS_SMALL then
bUcut = true
end
if abs( dResV) > 2 * GEO.EPS_SMALL then
bOrtho = false
end
end
end
vUcut[i] = bUcut
vOrtho[i] = bOrtho
end
-- se 4 facce tutte con adiacenza 2, allora è un tunnel
if nFacCnt == 4 then
if vAdj[1] == 2 and vAdj[2] == 2 and vAdj[3] == 2 and vAdj[4] == 2 then
-- se tutte le facce sono ortogonali tra loro esco con un flag che ne indica questa propietà
if vOrtho[1] == true and vOrtho[2] == true and vOrtho[3] == true and vOrtho[4] == true then
return -1, GEO.INFINITO, true
else
return -1, GEO.INFINITO
end
end
end
-- se 3 facce con una che ha 2 adiacenze e le altre hanno 1 adiacenza, allora è una semi-fessura
if bCompare3Fc and nFacCnt == 3 then
local nCount2Adc = 0
local nCount1Adc = 0
-- ottengo il numero di facce con due adiacenze e il numero di facce con una adiacenza
for i = 1, #vAdj do
if vAdj[i] == 2 then
nCount2Adc = nCount2Adc + 1
elseif vAdj[i] == 1 then
nCount1Adc = nCount1Adc + 1
end
end
-- se il numero di adiacenze corrisponde
if nCount2Adc == 1 and nCount1Adc == 2 then
if vOrtho[1] == true and vOrtho[2] == true and vOrtho[3] == true then
return -1, GEO.INFINITO, true
else
return -1, GEO.INFINITO
end
end
end
-- recupero le facce non in sottosquadra e con il maggior numero di adiacenze
local nFacInd = {}
local nMaxAdj = -1
local nSupAdj = -1
for i = 1, nFacCnt do
if not vUcut[i] then
if vAdj[i] > nMaxAdj then
nFacInd = {}
nFacInd[1] = i - 1
nMaxAdj = vAdj[i]
elseif vAdj[i] == nMaxAdj and nMaxAdj > 0 then
table.insert( nFacInd, i - 1)
end
end
if vAdj[i] > nSupAdj then
nSupAdj = vAdj[i]
end
end
-- verifico non ci sia una faccia in sottosquadra con adiacenza superiore
if nSupAdj > nMaxAdj then
return -2, GEO.INFINITO
end
-- premio la faccia con minore elevazione
local nFacOpt, nFacOpt2
local dMinElev, dMinElev2 = GEO.INFINITO, GEO.INFINITO
local dtElev = {}
for i = 1, #nFacInd do
local dElev = BeamLib.GetFaceElevation( nSurfId, nFacInd[i], nPartId)
table.insert( dtElev, dElev)
if dElev < dMinElev then
if dMinElev < dMinElev2 then
nFacOpt2 = nFacOpt
dMinElev2 = dMinElev
end
nFacOpt = nFacInd[i]
dMinElev = dElev
elseif dElev < dMinElev2 then
nFacOpt2 = nFacInd[i]
dMinElev2 = dElev
end
end
-- faccio una ulteriore verifica
-- se le elevazioni di max 3 facce sono in un range minimo o al di sotto dell'elevazione ritenuta fattibile,
-- premio quella che non è sottosquadra e che ha la X minore
local bDiffSmall = true
for i = 1, #dtElev do
if dtElev[i] > dMinElev + 5 or dtElev[i] > 80 then
bDiffSmall = false
end
end
-- se tutte sono nel range minimo posso prendere la faccia che ha la componente Z magiore, e se sono uguali, prendo quella con componente X minore
local dMaxZ, dMaxZ2 = -1.1, -1.1
if bDiffSmall and #nFacInd <= 3 then
for i = 1, #nFacInd do
if vvtN[nFacInd[i]+1]:getZ() > dMaxZ then
if dMaxZ > dMaxZ2 then
nFacOpt2 = nFacOpt
dMinElev2 = dMinElev
dMaxZ2 = dMaxZ
end
nFacOpt = nFacInd[i]
dMinElev = dtElev[i]
dMaxZ = vvtN[nFacInd[i]+1]:getZ()
elseif vvtN[nFacInd[i]+1]:getZ() > dMaxZ2 then
nFacOpt2 = nFacInd[i]
dMinElev2 = dtElev[i]
dMaxZ2 = vvtN[nFacInd[i]+1]:getZ()
end
end
-- se hanno uguale Z premio quella con la componente X minore
if abs( dMaxZ - dMaxZ2) < 10*GEO.EPS_SMALL then
if abs(vvtN[nFacOpt+1]:getX()) > abs(vvtN[nFacOpt2+1]:getX()) then
nFacOpt, nFacOpt2 = nFacOpt2, nFacOpt
dMinElev, dMinElev2 = dMinElev2, dMinElev
end
end
end
return nFacOpt, dMinElev, nFacOpt2, dMinElev2
end
---------------------------------------------------------------------
function BeamLib.GetFaceHvRefDim( nSurfId, nFacet, b3Raw)
-- recupero centro e normale della faccia
local ptC, vtN = EgtSurfTmFacetCenter( nSurfId, nFacet, GDB_ID.ROOT)
if not ptC or not vtN then return end
-- riferimento tipo OCS della faccia (X orizz, Y max pendenza, Z normale)
local frHV = Frame3d( ptC, vtN)
if frHV:getVersY():getZ() < 0 then
frHV:rotate( ptC, vtN, 180)
end
-- determino l'ingombro in questo riferimento
local b3HV = EgtSurfTmGetFacetBBoxRef( nSurfId, nFacet, GDB_BB.STANDARD, frHV)
local dDimH = b3HV:getDimX()
local dDimV = b3HV:getDimY()
-- se definito grezzo (o solido), applico eventuali limiti
if b3Raw then
local dCoeffY = abs( frHV:getVersX():getY())
if dCoeffY > GEO.EPS_SMALL then
dDimH = min( dDimH, b3Raw:getDimY() / dCoeffY)
end
local dCoeffZ = abs( frHV:getVersY():getZ())
if dCoeffZ > GEO.EPS_SMALL then
dDimV = min( dDimV, b3Raw:getDimZ() / dCoeffZ)
end
end
-- restituisco i valori calcolati
return frHV, dDimH, dDimV
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.UpdateHCING( nRawId, dHCI, dDist)
local dOldHCI = EgtGetInfo( nRawId, 'HCING', 'd') or 0
if dDist and dDist > dOldHCI + 0.1 then
return
end
if dHCI > dOldHCI then
EgtSetInfo( nRawId, 'HCING', dHCI)
end
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.UpdateTCING( nRawId, dTCI)
local dOldTCI = EgtGetInfo( nRawId, 'TCING', 'd') or 0
if dTCI > dOldTCI then
EgtSetInfo( nRawId, 'TCING', dTCI)
end
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.GetNzLimDownUp( b3Raw, vtN, vtOrtho)
if BD.C_SIMM then
return -0.484
elseif BD.TURN then
return -2
else
if vtOrtho and vtOrtho:getZ() > 0.35 then
-- N_HorAng < 15° or N_HorAng > 55°
if vtN and ( abs( vtN:getY()) < 0.259 or abs( vtN:getY()) > 0.819) then
return -0.708
-- N_HorAng > 50°
elseif vtN and abs( vtN:getY()) > 0.766 then
return -0.383
else
return EgtIf( b3Raw:getDimZ() < BD.MIN_DIM_HBEAM, -0.609, -0.383)
end
else
-- N_HorAng > 60°
if vtN and ( abs( vtN:getY()) > 0.866) then
return -0.708
else
if b3Raw:getDimZ() < 120 then
return -0.708
elseif b3Raw:getDimZ() < 200 then
-- N_HorAng < 15° or N_HorAng > 55°
if vtN and ( abs( vtN:getY()) < 0.259 or abs( vtN:getY()) > 0.819) then
return -0.5
else
return -0.383
end
elseif b3Raw:getDimZ() < BD.MIN_DIM_HBEAM then
-- N_HorAng < 10°
if vtN and ( abs( vtN:getY()) < 0.174) then
return -0.5
else
return -0.259
end
else
-- N_HorAng < 10°
if vtN and ( abs( vtN:getY()) < 0.174) then
return -0.383
else
return -0.174
end
end
end
end
end
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.IsSplittedPartPhase( nPhase)
local sVal = BeamLib.GetPhaseType( nPhase)
return ( sVal == 'END' or sVal == 'MID2' or sVal == 'END2')
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.IsPartFinalPhase( nPhase)
local sVal = BeamLib.GetPhaseType( nPhase)
return ( sVal == 'END' or sVal == 'END2')
end
---------------------------------------------------------------------
function BeamLib.GetPhaseType( nPhase)
return ( EgtGetInfo( EgtGetPhaseDisposition( nPhase) or GDB_ID.NULL, 'TYPE') or '')
end
---------------------------------------------------------------------
function BeamLib.GetDistanceToNextPart( nRawId, nPhase)
-- Recupero la distanza tra la fine del pezzo e il pezzo successivo
local dDistToNextPiece = EgtGetInfo( nRawId, 'BDST', 'd') or BD.OVM_MID
-- se segue una parte rimanente riutilizzabile, modifico opportunamente questa distanza
if not BeamLib.IsSplittedPartPhase( nPhase) then
local nNextRawId = EgtGetNextRawPart( nRawId)
if nNextRawId and
EgtGetPartInRawPartCount( nNextRawId) <= 0 and
EgtGetRawPartBBox( nNextRawId):getDimX() >= BD.MinRaw then
dDistToNextPiece = BD.OVM_MID
end
end
return dDistToNextPiece
end
---------------------------------------------------------------------
function BeamLib.GetChainSawBlockedAxis( nInd)
if BD.GetChainSawBlockedAxis then
return BD.GetChainSawBlockedAxis( nInd)
else
if nInd == 1 then
return EgtIf( BD.C_SIMM, 'A=90', 'A=90')
else
return EgtIf( BD.C_SIMM, 'A=0', 'A=0')
end
end
end
---------------------------------------------------------------------
function BeamLib.GetChainSawInitAngs( vtN, vtO, nInd)
if BD.GetChainSawInitAngs then
return BD.GetChainSawInitAngs( vtN, vtO, nInd)
else
if BD.C_SIMM then
return EgtIf( vtN:getY() > 0, 'C=180', 'C=-180')
else
if nInd == 1 then
return ''
else
return EgtIf( vtN:getY() > 0, 'C=180', 'C=-180')
end
end
end
end
---------------------------------------------------------------------
-- Trova l'Ind (0 based) della faccia meglio orientata come l'asse vtAx. Restituisce anche vtN e ptC della faccia stessa. La faccia di indice (0 based) fctExclude non viene considerata nella ricerca.
function BeamLib.FindFaceBestOrientedAsAxis( Proc, vtAx, fctExclude)
local nFaceIndMax = 0
local dMaxComp = 0
fctExclude = fctExclude or -1
for i = 1, Proc.Fct do
local vtN = EgtSurfTmFacetNormVersor( Proc.Id, i - 1, GDB_ID.ROOT)
local dComp = abs( vtN * vtAx)
if dComp > dMaxComp and i ~= fctExclude + 1 then
nFaceIndMax = i -1
dMaxComp = dComp
end
end
local ptC, vtN = EgtSurfTmFacetCenter( Proc.Id, nFaceIndMax, GDB_ID.ROOT)
return nFaceIndMax, ptC, vtN
end
---------------------------------------------------------------------
function BeamLib.GetTunnelDimension( Proc, nPartId)
-- sono necessarie almeno due facce
if Proc.Fct < 2 then return 0, 0, 0 end
-- recupero l'ingombro della trave
local b3Solid = EgtGetBBoxGlob( EgtGetFirstNameInGroup( nPartId, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD)
-- recupero centro e normale delle facce
local ptC = {}
local vtN = {}
for i = 1, Proc.Fct do
ptC[i], vtN[i] = EgtSurfTmFacetCenter( Proc.Id, i - 1, GDB_ID.ROOT)
end
-- calcolo l'orientamento del tunnel
local vtOrtho
local bAdj = EgtSurfTmFacetsContact( Proc.Id, 0, 1)
if bAdj then
vtOrtho = vtN[1] ^ vtN[2]
else
if Proc.Fct >= 3 then
vtOrtho = vtN[1] ^ vtN[3]
else
return 0, 0, 0
end
end
-- ottengo il boundingBox e prendo le dimensioni lungo la direzione (Z locale) che rappresenta la profondità della fessura
local frFc = Frame3d( ptC[1], vtOrtho) ;
local b3BoxLoc = EgtGetBBoxRef( Proc.Id, GDB_BB.STANDARD, frFc)
local dDepth = b3BoxLoc:getDimZ()
-- recupero gruppo per geometria addizionale
local nAddGrpId = BeamLib.GetAddGroup( nPartId)
if not nAddGrpId then
EgtOutLog( 'Error : missing AddGroup')
return 0, 0, 0
end
-- centro del bounding box locale
local ptCen = b3BoxLoc:getCenter()
ptCen:toGlob( frFc)
-- creo superficie intermedia
local nSurfInt = EgtSurfTmPlaneInBBox( nAddGrpId, ptCen, vtOrtho, b3Solid, GDB_ID.ROOT)
if not nSurfInt then return 0, 0, 0 end
-- ritaglio la superficie con le facce della fessura
for i = 1, Proc.Fct do
EgtCutSurfTmPlane( nSurfInt, ptC[i], -vtN[i], false, GDB_ID.ROOT)
end
local frSurfInt, dDimMax, dDimMin = EgtSurfTmFacetMinAreaRectangle( nSurfInt, 0, GDB_ID.ROOT)
-- cerco la faccia con larghezza pari a dimensione massima della fessura
local nLongIdFace = 0
for i = 1, Proc.Fct do
if abs( vtN[i] * frSurfInt:getVersX()) < 0.5 then
nLongIdFace = i - 1
break
end
end
return dDimMin, dDimMax, dDepth, vtOrtho, nLongIdFace, nSurfInt
end
---------------------------------------------------------------------
function BeamLib.CalcCollisionSafety( vtDir)
local dCollSic = 10 * BD.COLL_SIC
if abs( vtDir:getX()) > 0.999 or abs( vtDir:getY()) > 0.999 or abs( vtDir:getZ()) > 0.999 then
dCollSic = 0
elseif abs( vtDir:getX()) > 0.996 or abs( vtDir:getY()) > 0.996 or abs( vtDir:getZ()) > 0.996 then
dCollSic = 1 * BD.COLL_SIC
elseif abs( vtDir:getX()) > 0.89 or abs( vtDir:getY()) > 0.89 or abs( vtDir:getZ()) > 0.89 then
dCollSic = 2.5 * BD.COLL_SIC
elseif abs( vtDir:getX()) > 0.86 or abs( vtDir:getY()) > 0.86 or abs( vtDir:getZ()) > 0.86 then
dCollSic = 4 * BD.COLL_SIC
elseif abs( vtDir:getX()) > 0.707 or abs( vtDir:getY()) > 0.707 or abs( vtDir:getZ()) > 0.707 then
dCollSic = 5.5 * BD.COLL_SIC
end
return dCollSic
end
---------------------------------------------------------------------
function BeamLib.SetOpenSide( nPathInt, b3Solid)
-- fondo tra loro le curve compatibili
EgtMergeCurvesInCurveCompo( nPathInt)
-- vettore indici lati aperti
local vOpen = {}
-- ciclo sulle curve elementari della composita
local _, nNumEnt = EgtCurveDomain( nPathInt)
for i = 0, nNumEnt - 1 do
-- se segmento di retta
if EgtCurveCompoRadius( nPathInt, i) == -1 then
-- verifico se giace in uno dei piani limite del pezzo quindi se è un lato aperto
local ptIni = EgtUP( nPathInt, i, GDB_RT.GLOB)
local ptFin = EgtUP( nPathInt, i + 1, GDB_RT.GLOB)
if ( abs( ptIni:getX() - b3Solid:getMax():getX()) < 100 * GEO.EPS_SMALL and abs( ptFin:getX() - b3Solid:getMax():getX()) < 100 * GEO.EPS_SMALL) or
( abs( ptIni:getX() - b3Solid:getMin():getX()) < 100 * GEO.EPS_SMALL and abs( ptFin:getX() - b3Solid:getMin():getX()) < 100 * GEO.EPS_SMALL) or
( abs( ptIni:getY() - b3Solid:getMax():getY()) < 100 * GEO.EPS_SMALL and abs( ptFin:getY() - b3Solid:getMax():getY()) < 100 * GEO.EPS_SMALL) or
( abs( ptIni:getY() - b3Solid:getMin():getY()) < 100 * GEO.EPS_SMALL and abs( ptFin:getY() - b3Solid:getMin():getY()) < 100 * GEO.EPS_SMALL) or
( abs( ptIni:getZ() - b3Solid:getMax():getZ()) < 100 * GEO.EPS_SMALL and abs( ptFin:getZ() - b3Solid:getMax():getZ()) < 100 * GEO.EPS_SMALL) or
( abs( ptIni:getZ() - b3Solid:getMin():getZ()) < 100 * GEO.EPS_SMALL and abs( ptFin:getZ() - b3Solid:getMin():getZ()) < 100 * GEO.EPS_SMALL) then
-- aggiorno il vettore dei lati aperti
table.insert( vOpen, i)
end
end
end
-- assegno gli indici dei lati aperti
EgtSetInfo( nPathInt, 'OPEN', vOpen)
return true
end
---------------------------------------------------------------------
function BeamLib.ChangeOrOpenStart( nPathInt, nStartPoint)
-- verifico richiesta
if nStartPoint ~= 1 and nStartPoint ~= 2 then
return false
end
-- verifico che la curva sia chiusa
if not EgtCurveIsClosed( nPathInt) then
return true
end
-- recupero l'indice del segmento aperto più lungo
local nMaxOpen, dMaxLen
local vOpen = EgtGetInfo( nPathInt or GDB_ID.NULL, 'OPEN', 'vi')
for i = 1, #( vOpen or {}) do
-- se primo o più lungo, lo salvo
local dLen = EgtCurveCompoLength( nPathInt, vOpen[i])
if not dMaxLen or dLen > dMaxLen then
dMaxLen = dLen
nMaxOpen = vOpen[i]
end
end
-- se esiste tratto aperto
if nMaxOpen then
-- sposto il punto di inizio a metà del tratto aperto più lungo (la curva deve essere chiusa)
EgtChangeClosedCurveStart( nPathInt, nMaxOpen + 0.5)
-- aggiorno il vettore dei lati aperti
for i = 1, #vOpen do
vOpen[i] = vOpen[i] - nMaxOpen
end
table.insert( vOpen, #vOpen)
-- se devo eliminare gli estremi aperti
if nStartPoint == 2 then
-- elimino gli estremi
EgtRemoveCurveCompoCurve( nPathInt, true)
EgtRemoveCurveCompoCurve( nPathInt, false)
-- aggiorno il vettore dei lati aperti
table.remove( vOpen, 1)
table.remove( vOpen)
for i = 1, #vOpen do
vOpen[i] = vOpen[i] - 1
end
end
end
-- assegno gli indici modificati dei lati aperti
EgtSetInfo( nPathInt, 'OPEN', vOpen)
-- restituisco flag percorso aperto
return ( not EgtCurveIsClosed( nPathInt))
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.ConvertToClosedCurve( Proc, AuxId)
local bCurveModified = false
if not EgtCurveIsClosed( AuxId) then
local NewId, nCount = EgtExtractSurfTmFacetLoops( Proc.Id, 0, EgtGetParent( Proc.Id))
if NewId then
-- elimino eventuali loop interni (non dovrebbero comunque esserci)
for i = 1, nCount - 1 do
EgtErase( NewId + i)
end
local vtExtr = EgtCurveExtrusion( AuxId, GDB_ID.ROOT)
-- sostituisco il loop esterno alla curva originale
EgtModifyCurveExtrusion( NewId, vtExtr, GDB_ID.ROOT)
EgtRelocate( NewId, AuxId, GDB_IN.AFTER)
EgtErase( AuxId)
EgtChangeId( NewId, AuxId)
bCurveModified = true
-- sistemo i lati aperti
local vFacAdj = EgtSurfTmFacetAdjacencies( Proc.Id, 0)[1]
if vFacAdj then
local vOpen = {}
for i = 1, #vFacAdj do
if vFacAdj[i] < 0 then
table.insert( vOpen, i - 1)
end
end
EgtSetInfo( AuxId, 'OPEN', vOpen)
end
end
end
return true, bCurveModified
end
---------------------------------------------------------------------
function BeamLib.CurveWithOnlyStraightLines( nPathInt)
-- verifico sia una retta oppure una curva composita
local nType = EgtGetType( nPathInt)
if nType == GDB_TY.CRV_LINE then
return true
elseif nType~= GDB_TY.CRV_COMPO then
return false
end
-- ciclo sulle curve elementari della composita
local _, nNumEnt = EgtCurveDomain( nPathInt)
for i = 0, nNumEnt - 1 do
-- se segmento di retta
if EgtCurveCompoRadius( nPathInt, i) ~= -1 then
return false
end
end
return true
end
-------------------------------------------------------------------------------------------------------------
return BeamLib