-- BeamLib.lua by Egalware s.r.l. 2024/04/02 -- Libreria globale per Travi -- 2024/04/02 PRIMA VERSIONE CALCOLO LAVORAZIONI CON STRATEGIE -- Tabella per definizione modulo local BeamLib = {} -- Include require( 'EgtBase') local BeamData = require( 'BeamData') EgtOutLog( ' BeamLib started', 1) --TODO refactoring di queste funzioni ------------------------------------------------------------------------------------------------------------- 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( nRawId, OriXR, PosXR, dDeltaSucc) EgtAddPhase() 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 ------------------------------------------------------------------------------------------------------------- --- funzione che ruota il pezzo, da lanciare per creare la disposizione corretta function BeamLib.RotatePart( Part, nPosition) -- primo posizionamento if nPosition == 1 then ; -- il pezzo è già in posizione -- rotazione 90° elseif nPosition == 2 then local dDeltaYZ = EgtGetRawPartBBox( Part.idRaw):getDimY() - EgtGetRawPartBBox( Part.idRaw):getDimZ() local vtMove = Vector3d( 0, dDeltaYZ / 2 * EgtIf( BeamData.RIGHT_LOAD, -1, 1), dDeltaYZ / 2) local bPreMove = dDeltaYZ < 0 -- ruoto le travi della fase corrente local nRId = Part.idRaw while nRId do if bPreMove then EgtMoveRawPart( nRId, vtMove) end EgtRotateRawPart( nRId, X_AX(), EgtIf( BeamData.RIGHT_LOAD, -90, 90)) if not bPreMove then EgtMoveRawPart( nRId, vtMove) end nRId = EgtGetNextRawPart( nRId) end -- rotazione 180° elseif nPosition == 3 then -- ribalto le travi della fase corrente local nRId = Part.idRaw while nRId do EgtRotateRawPart( nRId, X_AX(), 180) nRId = EgtGetNextRawPart( nRId) end -- rotazione 270° elseif nPosition == 4 then local dDeltaYZ = EgtGetRawPartBBox( Part.idRaw):getDimY() - EgtGetRawPartBBox( Part.idRaw):getDimZ() local vtMove = Vector3d( 0, dDeltaYZ / 2 * EgtIf( BeamData.RIGHT_LOAD, -1, 1), dDeltaYZ / 2) local bPreMove = dDeltaYZ < 0 -- ruoto le travi della fase corrente local nRId = Part.idRaw while nRId do if bPreMove then EgtMoveRawPart( nRId, vtMove) end EgtRotateRawPart( nRId, X_AX(), EgtIf( BeamData.RIGHT_LOAD, 90, -90)) if not bPreMove then EgtMoveRawPart( nRId, vtMove) end nRId = EgtGetNextRawPart( nRId) end end 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.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 ------------------------------------------------------------------------------------------------------------- -- restituisce le facce della parte interessate dalla feature Proc function BeamLib.GetAffectedFaces( Proc, Part) local vtFacesAffected = { bTop = false, bBottom = false, bFront = false, bBack = false, bLeft = false, bRight = false} if Proc.b3Box and not Proc.b3Box:isEmpty() then if Proc.b3Box:getMax():getZ() > Part.b3Solid:getMax():getZ() - 500 * GEO.EPS_SMALL then vtFacesAffected.bTop = true end if Proc.b3Box:getMin():getZ() < Part.b3Solid:getMin():getZ() + 500 * GEO.EPS_SMALL then vtFacesAffected.bBottom = true end if Proc.b3Box:getMin():getY() < Part.b3Solid:getMin():getY() + 500 * GEO.EPS_SMALL then vtFacesAffected.bFront = true end if Proc.b3Box:getMax():getY() > Part.b3Solid:getMax():getY() - 500 * GEO.EPS_SMALL then vtFacesAffected.bBack = true end if Proc.b3Box:getMin():getX() < Part.b3Solid:getMin():getX() + 500 * GEO.EPS_SMALL then vtFacesAffected.bLeft = true end if Proc.b3Box:getMax():getX() > Part.b3Solid:getMax():getX() - 500 * GEO.EPS_SMALL then vtFacesAffected.bRight = true end end return vtFacesAffected 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.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 --------------------------------------------------------------------- -- Funzione per determinare se la faccia ha lati molto corti (trascurabili) ed è quindi approssimabile ad una 3 facce function BeamLib.Is3EdgesApprox( Proc, idFace, nAddGrpId) nAddGrpId = nAddGrpId or BeamLib.GetAddGroup( Proc.idPart) if not nAddGrpId then local nEdges = #(EgtSurfTmFacetAdjacencies( Proc.id, idFace)[1]) return ( nEdges == 3) end local bResult = false local nContourId, nContourCnt = EgtExtractSurfTmFacetLoops( Proc.id, idFace, nAddGrpId) if not nContourId then return false end EgtMergeCurvesInCurveCompo( nContourId) -- recupero il numero effettivo di lati local _, nEntityCount = EgtCurveDomain( nContourId) local nEdges = nEntityCount if nEntityCount and nEntityCount == 3 then bResult = true -- rimuovo i lati molto corti dal conteggio totale elseif nEntityCount then for i = 1, nEntityCount do local dLength = EgtCurveCompoLength( nContourId, i - 1) if dLength < 15 then nEdges = nEdges - 1 end end end if nEdges == 3 then bResult = true end -- cancello tutti i contorni appena creati EgtErase( EgtTableFill( nContourId, nContourCnt)) return bResult end ------------------------------------------------------------------------------------------------------------- -- sovrascrivo i parametri personalizzati salvati su Proc a quelli di default dalla strategia -- N.B. : I parametri personalizzati non più presenti tra i default della strategia, verranno ignorati. Quelli extra avranno valore di default -- Il controllo deve essere fatto SEMPRE all'inizio di ogni strategia, per controllare conformità parametri custom function BeamLib.GetUpdateCustomParameters( CustomStrategyParamList, DefaultStrategyParamList) if CustomStrategyParamList and #CustomStrategyParamList > 0 then for i = 1, #DefaultStrategyParamList do for j = 1, #CustomStrategyParamList do if DefaultStrategyParamList[i].sName == CustomStrategyParamList[j].sName then DefaultStrategyParamList[i].sValue = CustomStrategyParamList[j].sValue end end end end return DefaultStrategyParamList end ------------------------------------------------------------------------------------------------------------- -- si traduce la tabella dei parametri con tutte le informazioni in una lista contenente i parametri utilizzabili con accesso diretto function BeamLib.LoadCustomParametersInStrategy( CustomParameters) local Parameters = {} if CustomParameters and #CustomParameters > 0 then for i=1, #CustomParameters do if CustomParameters[i].sType == 'b' then Parameters[CustomParameters[i].sName] = CustomParameters[i].sValue == 'true' elseif CustomParameters[i].sType == 'd' then Parameters[CustomParameters[i].sName] = tonumber( CustomParameters[i].sValue) else --CustomParameters[i].sType == 's' or CustomParameters[i].sType == 'combo' Parameters[CustomParameters[i].sName] = CustomParameters[i].sValue end end end return Parameters end --------------------------------------------------------------------- function BeamLib.GetChainSawInitAngs( vtN, vtO, nInd) if BeamData.GetChainSawInitAngs then return BeamData.GetChainSawInitAngs( vtN, vtO, nInd) else if BeamData.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 --------------------------------------------------------------------- function BeamLib.GetBlockedAxis( nToolIndex, sBlockedAxis, b3Raw, vtTool, vtOut) -- se presente funzione specifica nella macchina, la richiamo if BeamData.GetBlockedAxis then return BeamData.GetBlockedAxis( TOOLS[nToolIndex].sHead, TOOLS[nToolIndex].nTypeId, sBlockedAxis, b3Raw, vtTool, vtOut) or '' -- sezione mantenuta per retrocompatibilità con GetChainSawBlockedAxis elseif TOOLS[nToolIndex].nTypeId == MCH_TY.MORTISE_STD then local nInd = EgtIf( sBlockedAxis == 'parallel', 0, 1) if BeamData.GetChainSawBlockedAxis then return BeamData.GetChainSawBlockedAxis( nInd) else if nInd == 1 then return EgtIf( BeamData.C_SIMM, 'A=90', 'A=90') else return EgtIf( BeamData.C_SIMM, 'A=0', 'A=0') end end end return '' end --------------------------------------------------------------------- function BeamLib.BinaryToDecimal( dNumber) local sNumberToConvert = tostring( dNumber) local dResult = 0 local k = 0 for i = #sNumberToConvert, 1, -1 do k = k + 1 local n = string.sub(sNumberToConvert, k, k) dResult = dResult + n*(2^(i-1)) end return dResult end --------------------------------------------------------------------- function BeamLib.DecimalToBinary( dNumber) local sNumberToConvert = tostring( dNumber) local n = sNumberToConvert local tmp = {} local sResult = "" for i = sNumberToConvert, 0, -1 do local q = math.modf(n) n = n/2 local b = q%2 table.insert(tmp, b) if (q == 1) then break end end for i = #tmp, 1, -1 do sResult = sResult..tmp[i] end return tonumber( sResult) end --------------------------------------------------------------------- function BeamLib.CalculateStringBinaryFormat( dNumber, CharNumber) local NumberString = tostring( dNumber) while #NumberString < CharNumber do NumberString = '0' .. NumberString end return NumberString end --------------------------------------------------------------------- --- copia una tabella lua in modo ricorsivo, ossia mantiene indipendenti anche tutte le sottotabelle --- ATTENZIONE: in caso di modifiche vanno gestiti anche i tipi custom; sarebbe meglio metterla nel LuaLibs function BeamLib.TableCopyDeep( OriginalTable) local CopiedTable = {} for key, value in pairs( OriginalTable) do if type( value) == "table" then if isBBox3d( value) then CopiedTable[ key] = BBox3d( value) elseif isColor3d( value) then CopiedTable[ key] = Color3d( value) elseif isFrame3d( value) then CopiedTable[ key] = Frame3d( value) elseif isPoint3d( value) then CopiedTable[ key] = Point3d( value) elseif isQuaternion( value) then CopiedTable[ key] = Quaternion( value) elseif isVector3d( value) then CopiedTable[ key] = Vector3d( value) else CopiedTable[ key] = BeamLib.TableCopyDeep( value) end else CopiedTable[ key] = value end end return CopiedTable end ------------------------------------------------------------------------------------------------------------- return BeamLib