9c0d2111f5
- in BeamLib aggiunte funzioni Is3EdgesApprox e GetProcessAffectedFaces, clonate da Wall - in BeamExec aggiunta ClassifyTopology e la raccolta preliminare di alcune informazioni nel CollectFeatures
234 lines
9.5 KiB
Lua
234 lines
9.5 KiB
Lua
-- FeatureTopology.lua by Egaltech s.r.l. 2023/09/12
|
|
-- Libreria per classificazione topologica feature travi
|
|
|
|
-- Tabella per definizione modulo
|
|
local FeatureTopology = {}
|
|
|
|
-- Include
|
|
require( 'EgtBase')
|
|
|
|
-- Carico le librerie
|
|
local BL = require( 'BeamLib')
|
|
|
|
EgtOutLog( ' FeatureTopology started', 1)
|
|
|
|
---------------------------------------------------------------------
|
|
-- 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 = {}
|
|
for i = 1, Proc.Fct do
|
|
vAdj[i] = {}
|
|
for j = 1, Proc.Fct do
|
|
if i == j then
|
|
vAdj[i][j] = 0
|
|
else
|
|
_, _, _, 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
|
|
j = j + 1
|
|
end
|
|
i = i + 1
|
|
end
|
|
return vAdj
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
-- restituisce gli id delle facce di Proc che hanno il numero di adiacenze nAdj
|
|
function FeatureTopology.GetFacesWithGivenAdjacencyNumber( Proc, nAdj)
|
|
local vAdj = GetAdjacencyMatrix( Proc)
|
|
local vFacesWithGivenAdj = {}
|
|
for i = 1, Proc.Fct do
|
|
local nAdjCount = 0
|
|
for j = 1, Proc.Fct do
|
|
if vAdj[i][j] and vAdj[i][j] ~= 0 then
|
|
nAdjCount = nAdjCount + 1
|
|
end
|
|
end
|
|
if nAdjCount == nAdj then
|
|
table.insert( vFacesWithGivenAdj, i - 1)
|
|
end
|
|
end
|
|
return vFacesWithGivenAdj
|
|
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( Proc)
|
|
local vAdj = GetAdjacencyMatrix( Proc)
|
|
local bAllConcave, bAllRight = true, true
|
|
for i = 1, Proc.Fct do
|
|
for j = 1, Proc.Fct 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 Proc.Fct < 2 or ( Proc.Fct == 2 and vAdj[1][2] > 0) then
|
|
return bAllConcave
|
|
else
|
|
return bAllConcave, bAllRight
|
|
end
|
|
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
|
|
|
|
---------------------------------------------------------------------
|
|
-- 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 un vettore contenente gli indici delle facce di Proc parallele ad una delle direzioni principali; il check varia in base alla famiglia topologica
|
|
local function GetFacesParallelToPart( Proc, sFamily)
|
|
local vFacesParallelToPart = {}
|
|
for i = 0, Proc.Fct - 1 do
|
|
local vtN = EgtSurfTmFacetNormVersor( Proc.Id, i, GDB_ID.ROOT)
|
|
if sFamily == 'Bevel' or sFamily == 'DoubleBevel' then
|
|
local vTriangularFaces = GetTriangularFaces( Proc)
|
|
local bIsTriangularFace = false
|
|
-- verifico se la faccia è triangolare
|
|
for j = 1, #vTriangularFaces do
|
|
if i == vTriangularFaces[j] then
|
|
bIsTriangularFace = true
|
|
end
|
|
end
|
|
-- se faccia triangolare deve avere la normale parallela ad una direzione principale
|
|
if bIsTriangularFace then
|
|
if AreSameOrOppositeVectorApprox( vtN, X_AX()) or AreSameOrOppositeVectorApprox( vtN, Y_AX()) or AreSameOrOppositeVectorApprox( vtN, Z_AX()) then
|
|
table.insert( vFacesParallelToPart, i)
|
|
end
|
|
-- altrimenti deve avere una componente della normale nulla
|
|
else
|
|
if abs( vtN:getX()) < 10 * GEO.EPS_SMALL or abs( vtN:getY()) < 10 * GEO.EPS_SMALL or abs( vtN:getZ()) < 10 * GEO.EPS_SMALL then
|
|
table.insert( vFacesParallelToPart, i)
|
|
end
|
|
end
|
|
else
|
|
-- la normale deve essere parallela ad una direzione principale
|
|
if AreSameOrOppositeVectorApprox( vtN, X_AX()) or AreSameOrOppositeVectorApprox( vtN, Y_AX()) or AreSameOrOppositeVectorApprox( vtN, Z_AX()) then
|
|
table.insert( vFacesParallelToPart, i)
|
|
end
|
|
end
|
|
end
|
|
return vFacesParallelToPart
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
-- restituisce una stringa con il nome esteso della topologia della feature
|
|
-- *famiglia-passante-angoli tutti concavi a 90deg-facce tutte parallele alle dimensioni principali-numero di facce*
|
|
local function GetTopologyLongName( sFamily, bIsThrough, bAllRightAngles, bIsParallel, nNumberOfFaces)
|
|
-- feature passante o cieca
|
|
local sThrough = '_'
|
|
if bIsThrough ~= nil then sThrough = EgtIf( bIsThrough, 'Through', 'Blind') end
|
|
-- tutti gli angoli della feature sono retti oppure no
|
|
local sAllRightAngles = '_'
|
|
if bAllRightAngles ~= nil then sAllRightAngles = EgtIf( bAllRightAngles, 'RightAngles', 'NotRightAngles') end
|
|
-- tutte le dimensioni della feature sono parallele agli assi principali del pezzo oppure no
|
|
local sParallel = '_'
|
|
if bIsParallel ~= nil then sParallel = EgtIf( bIsParallel, 'Parallel', 'NotParallel') end
|
|
|
|
local sLongName = sFamily .. '-' .. sThrough .. '-' .. sAllRightAngles .. '-' .. sParallel .. '-' .. nNumberOfFaces
|
|
return sLongName
|
|
end
|
|
|
|
---------------------------------------------------------------------
|
|
-- riconosce se Proc è una delle topologie standard e, in caso positivo, ne scrive le caratteristiche in campi specifici della Proc stessa restituendo true
|
|
function FeatureTopology.Classify( Proc)
|
|
local bRecognized = false
|
|
local sFamily
|
|
local bIsThrough
|
|
local bAllRightAngles
|
|
local bIsParallel
|
|
local sLongName = ''
|
|
|
|
-- SE NON HA TUTTE LE FACCE PIANE RITORNARE NIL!!
|
|
|
|
local bAllAnglesConcave
|
|
bAllAnglesConcave, bAllRightAngles = AreAllAnglesConcaveOrRight( Proc)
|
|
local vTriangularFaces = GetTriangularFaces( Proc)
|
|
local bIsAnyDimensionLongAsPart = IsAnyDimensionLongAsPart( Proc)
|
|
local vFacesWithTwoAdj = FeatureTopology.GetFacesWithGivenAdjacencyNumber( Proc, 2)
|
|
local vFacesWithThreeAdj = FeatureTopology.GetFacesWithGivenAdjacencyNumber( Proc, 3)
|
|
local vFacesWithFourAdj = FeatureTopology.GetFacesWithGivenAdjacencyNumber( Proc, 4)
|
|
|
|
if Proc.IsOutline then
|
|
sFamily = 'OUTLINE'
|
|
elseif Proc.Prc == 40 then
|
|
sFamily = 'DRILLING'
|
|
elseif Proc.Fct == 1 and bIsAnyDimensionLongAsPart 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 then
|
|
sFamily = 'Rabbet'
|
|
bIsThrough = true
|
|
elseif Proc.Fct == 2 and not bAllAnglesConcave and bIsAnyDimensionLongAsPart then
|
|
sFamily = 'DoubleBevel'
|
|
bIsThrough = true
|
|
elseif Proc.Fct == 3 and bAllAnglesConcave and #vFacesWithTwoAdj == 1 and #vTriangularFaces == 2 then
|
|
sFamily = 'Bevel'
|
|
bIsThrough = false
|
|
elseif Proc.Fct == 3 and bAllAnglesConcave and #vFacesWithTwoAdj == 1 and bIsAnyDimensionLongAsPart then
|
|
sFamily = 'Groove'
|
|
bIsThrough = true
|
|
elseif Proc.Fct == 3 and bAllAnglesConcave and #vFacesWithTwoAdj == 3 then
|
|
sFamily = 'Groove'
|
|
bIsThrough = false
|
|
elseif Proc.Fct == 4 and bAllAnglesConcave and #vFacesWithThreeAdj == 2 then
|
|
sFamily = 'Groove'
|
|
bIsThrough = false
|
|
elseif Proc.Fct == 4 and bAllAnglesConcave and #vFacesWithTwoAdj == 4 and bIsAnyDimensionLongAsPart then
|
|
sFamily = 'Tunnel'
|
|
bIsThrough = true
|
|
elseif Proc.Fct == 5 and bAllAnglesConcave and #vFacesWithFourAdj == 1 then
|
|
sFamily = 'Pocket'
|
|
bIsThrough = false
|
|
end
|
|
local vFacesParallelToPart = GetFacesParallelToPart( Proc, sFamily)
|
|
bIsParallel = ( #vFacesParallelToPart == Proc.Fct)
|
|
|
|
if sFamily == 'OUTLINE' or sFamily == 'DRILLING' then
|
|
Proc.Topology = sFamily
|
|
Proc.TopologyLongName = sFamily
|
|
bRecognized = true
|
|
elseif sFamily then
|
|
sLongName = GetTopologyLongName( sFamily, bIsThrough, bAllRightAngles, bIsParallel, Proc.Fct)
|
|
Proc.Topology, Proc.IsThrough, Proc.AllRightAngles, Proc.IsParallel, Proc.TopologyLongName = sFamily, bIsThrough, bAllRightAngles, bIsParallel, sLongName
|
|
bRecognized = true
|
|
else
|
|
Proc.Topology = 'OTHER'
|
|
Proc.TopologyLongName = 'OTHER'
|
|
end
|
|
|
|
return bRecognized
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
return FeatureTopology |