-- BeamLib.lua by Egaltech s.r.l. 2022/07/12 -- 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 -- 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 ------------------------------------------------------------------------------------------------------------- function BeamLib.PutStartNearestToEdge( nCrvId, b3Raw, dMaxDist, bDown) -- 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 dZopt = 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 dZ = abs( EgtIf( bDown, vtMin:getZ(), vtMax:getZ())) * dCoeffZ if dD < dMaxDist and dZ < dZopt + GEO.EPS_SMALL then dUopt = dU dDopt = dD dZopt = dZ 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.95 * abs( vtMyRef:getZ()) or abs( vtMyRef:getY()) > 0.95 * 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) -- 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 or BD.TURN then return -0.484 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.24 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.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 ------------------------------------------------------------------------------------------------------------- return BeamLib