-- FeatureData.lua by Egalware s.r.l. 2024/04/02 -- Libreria lettura o calcolo dati e proprietà della feature -- 2024/04/02 PRIMA VERSIONE CALCOLO LAVORAZIONI CON STRATEGIE -- Tabella per definizione modulo local FeatureData = {} -- Carico i dati globali local BD = require( 'BeamData') -- carico librerie local BL = require( 'BeamLib') local ID = require( 'Identity') ------------------------------------------------------------------------------------------------------------- -- recupero topologia della feature ------------------------------------------------------------------------------------------------------------- local function NeedTopologyFeature( Proc) -- richiedono calcolo topologia le feature tipo: if ID.IsCut( Proc) then return true elseif ID.IsDoubleCut( Proc) then return true elseif ID.IsSawCut( Proc) then return true elseif ID.IsLongitudinalCut( Proc) then return true elseif ID.IsDoubleLongitudinalCut( Proc) then return true elseif ID.IsChamfer( Proc) then return true elseif ID.IsSlot( Proc) then return true elseif ID.IsFrontSlot( Proc) then return true elseif ID.IsRidgeLap( Proc) then return true elseif ID.IsLapJoint( Proc) then return true elseif ID.IsNotchRabbet( Proc) then return true elseif ID.IsNotch( Proc) then return true elseif ID.IsPocket( Proc) then return true elseif ID.IsMortise( Proc) and Proc.Fct < 6 then -- calcolo topologia SOLO se non raggiata -- TODO oppure riconoscerla come feature speciale return true elseif ID.IsFrontMortise( Proc) and Proc.Fct < 6 then -- calcolo topologia SOLO se non raggiata -- TODO oppure riconoscerla come feature speciale return true end -- tutte le altre non richiedono calcolo topologia return false end --------------------------------------------------------------------- -- restituisce la matrice delle adiacenze di Proc dove i e j sono le facce e a(ij) è l'angolo tra di esse; 0 se nessuna adiacenza local function GetAdjacencyMatrix( Proc) local vAdj = {} -- essendo la matrice simmetrica a diagonale nulla, ne calcolo solo la metà superiore for i = 1, Proc.Fct do vAdj[i] = {} for j = i + 1, Proc.Fct do _, _, _, vAdj[i][j] = EgtSurfTmFacetsContact( Proc.Id, i - 1, j - 1, GDB_ID.ROOT) if not vAdj[i][j] then vAdj[i][j] = 0 end end end -- riempio di conseguenza il resto della matrice for i = 1, Proc.Fct do vAdj[i][i] = 0 for j = i + 1, Proc.Fct do vAdj[j][i] = vAdj[i][j] end end return vAdj end --------------------------------------------------------------------- -- restituisce true se Proc ha tutti gli angoli concavi (bAllConcave) e, nei casi in cui ha senso, se questi sono esattamente 90 deg (bAllRight) local function AreAllAnglesConcaveOrRight( vAdj) local bAllConcave, bAllRight = true, true local nFct = #( vAdj or {}) for i = 1, nFct do for j = 1, nFct do -- se trovo un angolo convesso restituisco falso e esco subito if vAdj[i][j] and vAdj[i][j] > 0 then bAllConcave = false bAllRight = false break elseif vAdj[i][j] and vAdj[i][j] ~= 0 and vAdj[i][j] + 90 > 500 * GEO.EPS_ANG_SMALL then bAllRight = false end end end -- se 1 faccia oppure 2 facce con angolo convesso non ha senso ritornare valori per bAllRight if nFct < 2 or ( nFct == 2 and vAdj[1][2] > 0) then return bAllConcave else return bAllConcave, bAllRight end end --------------------------------------------------------------------- -- retituisce un vettore con gli indici (0 based) delle facce triangolari (o quasi) di Proc local function GetTriangularFaces( Proc) local vTriangularFaces = {} for i = 1, Proc.Fct do if BL.Is3EdgesApprox( Proc, i - 1) then table.insert( vTriangularFaces, i - 1) end end return vTriangularFaces end --------------------------------------------------------------------- -- restituisce true se almeno una delle dimensioni della feature è maggiore o uguale ad una delle dimensioni principali del pezzo (tolleranza 1 mm) local function IsAnyDimensionLongAsPart( Proc) local bResult = false local nBoxSolidId = EgtGetFirstNameInGroup( Proc.PartId or GDB_ID.NULL, 'Box') local b3Solid = EgtGetBBoxGlob( nBoxSolidId, GDB_BB.STANDARD) if Proc.Box:getDimX() > b3Solid:getDimX() - 1000 * GEO.EPS_SMALL or Proc.Box:getDimY() > b3Solid:getDimY() - 1000 * GEO.EPS_SMALL or Proc.Box:getDimZ() > b3Solid:getDimZ() - 1000 * GEO.EPS_SMALL then bResult = true end return bResult end --------------------------------------------------------------------- -- restituisce gli id delle facce di Proc che hanno il numero di adiacenze nAdj local function GetFacesWithGivenAdjacencyNumber( Proc, vAdj) if not vAdj then vAdj = GetAdjacencyMatrix( Proc) end local nFct = #( vAdj or {}) local vFacesWithAdj = {} vFacesWithAdj[1] = {} vFacesWithAdj[2] = {} vFacesWithAdj[3] = {} vFacesWithAdj[4] = {} vFacesWithAdj[5] = {} for i = 1, nFct do local nAdjCount = 0 for j = 1, nFct do if vAdj[i][j] and vAdj[i][j] ~= 0 and i ~= j then nAdjCount = nAdjCount + 1 end end if nAdjCount > 0 then table.insert( vFacesWithAdj[nAdjCount], i - 1) end end return vFacesWithAdj end ------------------------------------------------------------------------------------------------------------- -- restituisce vero se la feature con box b3Proc taglia l'intera sezione della barra, rappresentata dalle sue dimensioni W e H local function IsFeatureCuttingEntireSection( b3Proc, b3Raw) return ( b3Proc:getDimY() > ( b3Raw:getDimY() - 500 * GEO.EPS_SMALL) and b3Proc:getDimZ() > ( b3Raw:getDimZ() - 500 * GEO.EPS_SMALL)) end ------------------------------------------------------------------------------------------------------------- -- restituisce vero se la feature con box b3Proc taglia l'intera lunghezza della barra, rappresentata dalle sue dimensioni W e L oppure H e L local function IsFeatureCuttingEntireLength( b3Proc, b3Raw) return ( ( b3Proc:getDimY() > ( b3Raw:getDimY() - 500 * GEO.EPS_SMALL) and b3Proc:getDimX() > ( b3Raw:getDimX() - 500 * GEO.EPS_SMALL)) or ( b3Proc:getDimZ() > ( b3Raw:getDimZ() - 500 * GEO.EPS_SMALL) and b3Proc:getDimX() > ( b3Raw:getDimX() - 500 * GEO.EPS_SMALL))) end --------------------------------------------------------------------- -- restituisce una stringa con il nome esteso della topologia della feature -- *famiglia - numero di facce - passante* local function GetTopologyName( sFamily, nNumberOfFaces, bIsThrough) return sFamily .. '-' .. tostring( nNumberOfFaces) .. '-' .. EgtIf( bIsThrough, 'Through', 'Blind') end --------------------------------------------------------------------- -- recupera topologia feature local function ClassifyTopology( Proc, b3Raw) local FeatureTopology = {} -- calcoli if not Proc.AffectedFaces then Proc.AffectedFaces = BL.GetProcessAffectedFaces( Proc) end local vAdj = GetAdjacencyMatrix( Proc) local bAllAnglesConcave, bAllRightAngles = AreAllAnglesConcaveOrRight( vAdj) local vTriangularFaces = GetTriangularFaces( Proc) local bIsAnyDimensionLongAsPart = IsAnyDimensionLongAsPart( Proc) local vFacesWithAdjNumber = GetFacesWithGivenAdjacencyNumber( Proc, vAdj) local bIsFeatureCuttingEntireSection = IsFeatureCuttingEntireSection( Proc.Box, b3Raw) local bIsFeatureCuttingEntireLength = IsFeatureCuttingEntireLength( Proc.Box, b3Raw) -- assegnazione tipologia local sFamily local bIsThrough if Proc.Fct == 1 and ( bIsFeatureCuttingEntireSection or bIsFeatureCuttingEntireLength) then sFamily = 'Cut' elseif Proc.Fct == 1 then sFamily = 'Bevel' bIsThrough = true elseif Proc.Fct == 2 and bAllAnglesConcave and #vTriangularFaces == 1 then sFamily = 'Bevel' bIsThrough = false elseif Proc.Fct == 2 and bAllAnglesConcave and ( Proc.AffectedFaces.Left or Proc.AffectedFaces.Right) and ( Proc.AffectedFaces.Front or Proc.AffectedFaces.Back) then sFamily = 'Rabbet' bIsThrough = true elseif Proc.Fct == 2 and bAllAnglesConcave then sFamily = 'V-Groove' bIsThrough = true elseif Proc.Fct == 2 and not bAllAnglesConcave and bIsAnyDimensionLongAsPart then sFamily = 'DoubleBevel' bIsThrough = true elseif Proc.Fct == 3 and bAllAnglesConcave and #vFacesWithAdjNumber[2] == 1 and #vTriangularFaces == 2 then sFamily = 'Bevel' bIsThrough = false elseif Proc.Fct == 3 and bAllAnglesConcave and #vFacesWithAdjNumber[2] == 1 and bIsAnyDimensionLongAsPart then sFamily = 'Groove' bIsThrough = true elseif Proc.Fct == 3 and bAllAnglesConcave and #vFacesWithAdjNumber[2] == 3 then sFamily = 'Groove' bIsThrough = false elseif Proc.Fct == 4 and #vFacesWithAdjNumber[2] == 4 and #vTriangularFaces == 2 then sFamily = 'DoubleBevel' bIsThrough = false elseif Proc.Fct == 4 and bAllAnglesConcave and #vFacesWithAdjNumber[3] == 2 then sFamily = 'Groove' bIsThrough = false elseif Proc.Fct == 4 and bAllAnglesConcave and #vFacesWithAdjNumber[2] == 4 and bIsAnyDimensionLongAsPart then sFamily = 'Tunnel' bIsThrough = true elseif Proc.Fct >= 4 and #vFacesWithAdjNumber[1] == 2 and bIsAnyDimensionLongAsPart then sFamily = 'Strip' bIsThrough = true elseif Proc.Fct == 5 and bAllAnglesConcave and #vFacesWithAdjNumber[4] == 1 then sFamily = 'Pocket' bIsThrough = false elseif Proc.Fct == 6 and #vFacesWithAdjNumber[2] == 4 and #vFacesWithAdjNumber[3] == 2 and #vTriangularFaces == 4 then sFamily = 'DoubleBevel' bIsThrough = false end -- assegnazioni if sFamily then FeatureTopology.Family = sFamily FeatureTopology.IsThrough = bIsThrough FeatureTopology.AllRightAngles = bAllRightAngles FeatureTopology.Name = GetTopologyName( sFamily, Proc.Fct, bIsThrough) FeatureTopology.vAdj = vAdj -- feature che necessita di essere catalogata, ma non si capisce come else FeatureTopology.Family = 'NOT_IMPLEMENTED' FeatureTopology.Name = FeatureTopology.Family end return FeatureTopology end ------------------------------------------------------------------------------------------------------------- function FeatureData.GetTopology( Proc, b3Raw) local FeatureTopology = {} -- calcolo topologia solo se necessario, altrimenti si sfruttano le informazioni della feature BTL if NeedTopologyFeature( Proc) then FeatureTopology = ClassifyTopology( Proc, b3Raw) -- se non richiesto, setto 'FEATURE' else FeatureTopology.Family = 'FEATURE' FeatureTopology.Name = FeatureTopology.Family end return FeatureTopology end ------------------------------------------------------------------------------------------------------------- -- recupero facce principali della feature, in base alla topologia ------------------------------------------------------------------------------------------------------------- function FeatureData.GetMainFaces( Proc, b3Raw) local MainFaces = {} return MainFaces end ------------------------------------------------------------------------------------------------------------- -- Recupero dati foro e adattamento se speciale ------------------------------------------------------------------------------------------------------------- function FeatureData.GetDataDrill( Proc) local AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i') -- verifico se foro da adattare if EgtExistsInfo( Proc.Id, 'DiamUser') then if AuxId then AuxId = AuxId + Proc.Id end if AuxId and EgtGetType( AuxId) == GDB_TY.CRV_ARC and BD.USER_HOLE_DIAM and BD.USER_HOLE_DIAM > 1 then EgtModifyArcRadius( AuxId, BD.USER_HOLE_DIAM / 2) end end -- recupero diametro e lunghezza local dDiam = EgtGetInfo( Proc.Id, 'P12', 'd') or 0 local dLen = abs( EgtCurveThickness( Proc.Id + AuxId)) or 0 -- recupero faccia di entrata e uscita local nFcs = EgtGetInfo( Proc.Id, 'FCS', 'i') or 0 local nFce = EgtGetInfo( Proc.Id, 'FCE', 'i') or 0 return dDiam, dLen, nFcs, nFce end ------------------------------------------------------------------------------------------------------------- return FeatureData