Files
Carlo Baronchelli 741791a0e4 Copia locale Iniziale
2022-05-19 16:04:07 +02:00

321 lines
11 KiB
Lua

-- WallLib.lua by Egaltech s.r.l. 2022/04/04
-- Libreria globale per Pareti
-- Tabella per definizione modulo
local WallLib = {}
-- Include
require( 'EgtBase')
EgtOutLog( ' WallLib started', 1)
-------------------------------------------------------------------------------------------------------------
function WallLib.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 WallLib.CreateOrEmptyAddGroup( PartId)
-- recupero i dati del gruppo aggiuntivo
local AddGrpId, sMchGrp = WallLib.GetAddGroup( PartId)
if not sMchGrp then return false end
-- se esiste lo svuoto
if AddGrpId then
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 WallLib.GetPointDirDepth( nRawId, ptP, vtDir)
-- recupero il solido del grezzo
local nSolId = EgtGetFirstNameInGroup( nRawId, 'RawSolid')
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 WallLib.GetFaceElevation( nSurfId, nFac, nRawId)
local ptC, vtN = EgtSurfTmFacetCenter( nSurfId, nFac, GDB_ID.ROOT)
if not ptC or not vtN then return 0 end
local frOCS = Frame3d( ptC, vtN) ;
local b3Box = EgtGetBBoxRef( nSurfId, GDB_BB.STANDARD, frOCS)
local dElev = b3Box:getMax():getZ()
if nRawId then
local _, dCenElev = WallLib.GetPointDirDepth( nRawId, ptC, vtN)
if dCenElev and dCenElev > dElev then dElev = dCenElev end
local dOffsX = min( 20, b3Box:getDimX() / 4)
local _, dP1Elev = WallLib.GetPointDirDepth( nRawId, ptC + dOffsX * frOCS:getVersX(), vtN)
if dP1Elev and dP1Elev > dElev then dElev = dP1Elev end
local _, dP2Elev = WallLib.GetPointDirDepth( nRawId, ptC - dOffsX * frOCS:getVersX(), vtN)
if dP2Elev and dP2Elev > dElev then dElev = dP2Elev end
local dOffsY = min( 20, b3Box:getDimY() / 4)
local _, dP3Elev = WallLib.GetPointDirDepth( nRawId, ptC + dOffsY * frOCS:getVersY(), vtN)
if dP3Elev and dP3Elev > dElev then dElev = dP3Elev end
local _, dP4Elev = WallLib.GetPointDirDepth( nRawId, ptC - dOffsY * frOCS:getVersY(), vtN)
if dP4Elev and dP4Elev > dElev then dElev = dP4Elev end
end
return dElev
end
---------------------------------------------------------------------
function WallLib.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 = EgtSurfTmFacetCenter( nSurfId, i - 1, GDB_ID.ROOT)
vvtN[i] = vtN ;
end
-- adiacenze e sottosquadra delle facce
local vAdj = {}
local vUcut = {}
local vOrtho = {}
local vBlind = {}
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
-- verifico se schermata da altra faccia
local bBlind = false
for j = 1, nFacCnt do
if i ~= j then
if vvtN[i] * vvtN[j] < -0.5 then
bBlind = true
end
end
end
-- assegno i risultati
vUcut[i] = bUcut
vOrtho[i] = bOrtho
vBlind[i] = bBlind
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] and not vBlind[i] then
if vAdj[i] >= nMaxAdj and vAdj[i] > 0 then
table.insert( nFacInd, i - 1)
nMaxAdj = vAdj[i]
elseif vAdj[i] > 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 nOptAdj, nOptAdj2
local dMinElev, dMinElev2 = GEO.INFINITO, GEO.INFINITO
for i = 1, #nFacInd do
local dElev = WallLib.GetFaceElevation( nSurfId, nFacInd[i], nPartId)
if dElev < dMinElev and ( not nOptAdj or vAdj[nFacInd[i]+1] >= nOptAdj) then
if dMinElev < dMinElev2 then
nFacOpt2 = nFacOpt
nOptAdj2 = nOptAdj
dMinElev2 = dMinElev
end
nFacOpt = nFacInd[i]
nOptAdj = vAdj[nFacInd[i]+1]
dMinElev = dElev
elseif dElev < dMinElev2 and ( not nOptAdj2 or vAdj[nFacInd[i]+1] >= nOptAdj2) then
nFacOpt2 = nFacInd[i]
nOptAdj2 = vAdj[nFacInd[i]+1]
dMinElev2 = dElev
end
end
return nFacOpt, dMinElev, nFacOpt2, dMinElev2
end
---------------------------------------------------------------------
function WallLib.GetFaceHvRefDim( nSurfId, nFacet)
-- 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)
-- aggiusto l'origine del riferimento per metterlo nel centro del box
local ptBoxCen = b3HV:getCenter()
frHV:move( ptBoxCen:getX() * frHV:getVersX() + ptBoxCen:getY() * frHV:getVersY())
-- restituisco i valori calcolati
return frHV, b3HV:getDimX(), b3HV:getDimY()
end
---------------------------------------------------------------------
function WallLib.GetNearestParalOpposite( vtRef)
-- devo confrontare la componente orizzontale con quella verticale
local dHorSq = vtRef:getX() * vtRef:getX() + vtRef:getY() * vtRef:getY()
local dVertSq =vtRef:getZ() * vtRef:getZ()
-- se prevalente la componente orizzontale
if dHorSq >= dVertSq then
if abs( vtRef:getX()) > abs( vtRef:getY()) then
if vtRef:getX() > 0 then
return MCH_MILL_FU.PARAL_LEFT
else
return MCH_MILL_FU.PARAL_RIGHT
end
else
if vtRef:getY() > 0 then
return MCH_MILL_FU.PARAL_FRONT
else
return MCH_MILL_FU.PARAL_BACK
end
end
-- altrimenti prevale la verticale
else
if vtRef:getZ() > 0 then
return MCH_MILL_FU.PARAL_DOWN
else
return MCH_MILL_FU.PARAL_TOP
end
end
return nil
end
---------------------------------------------------------------------
function WallLib.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
-- devo confrontare la componente orizzontale con quella verticale
local dHorSq = vtMyRef:getX() * vtMyRef:getX() + vtMyRef:getY() * vtMyRef:getY()
local dVertSq = vtMyRef:getZ() * vtMyRef:getZ()
-- se prevalente la componente orizzontale
if dHorSq >= dVertSq then
if abs( vtMyRef:getX()) >= abs( vtMyRef:getY()) then
if vtMyRef:getX() > 0 then
return MCH_MILL_FU.ORTHO_LEFT
else
return MCH_MILL_FU.ORTHO_RIGHT
end
else
if vtMyRef:getY() > 0 then
return MCH_MILL_FU.ORTHO_FRONT
else
return MCH_MILL_FU.ORTHO_BACK
end
end
-- altrimenti prevale la verticale
else
if vtMyRef:getZ() > 0 then
return MCH_MILL_FU.ORTHO_DOWN
else
return MCH_MILL_FU.ORTHO_TOP
end
end
return nil
end
-------------------------------------------------------------------------------------------------------------
return WallLib