c6ced91b14
- Aggiunta funzione dedicata alla creazione del gruppo ausiliario al MachGroup - Alla funzione BeamExec.GetCombinationListFromMatrix si può passare una lista con le sole combinazioni da provare - Nella BeamExec aggiunta funzione ProcessAlternatives solo per provare le alternative (simile alla ProcessFeatures, ma completamente slegata). La ProcessFeature decide il posizionamento iniziale, la ProcessAlternatives verifica solamente le alternative. - FlipRot adeguata a nuovo funzionamento - Altre piccole migliorie varie - TODO : 1) manca la parte per settare nelle info pezzo la rotazione iniziale (per vista in Aedifica) e le altre alternative (per ottimizzazione in nesting) 2) In FlipRot gestire interazione con Aedifica, dato che verrà lanciato direttamente dal programma (per ora funziona lanciato come la Process)
1058 lines
44 KiB
Lua
1058 lines
44 KiB
Lua
-- 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( 'BeamDataNew')
|
|
|
|
|
|
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
|
|
EgtSetInfo( nStmId, 'HEAD_ADD_CUT', 1)
|
|
EgtSetInfo( nStmId, 'GRP', 1)
|
|
EgtSetInfo( nStmId, 'PRC', 10) -- ex 340
|
|
|
|
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
|
|
EgtSetInfo( nStmId, 'HEAD_ADD_CUT', 1)
|
|
EgtSetInfo( nStmId, 'GRP', 2)
|
|
EgtSetInfo( nStmId, 'PRC', 10) -- ex 350
|
|
|
|
return true
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
function BeamLib.GetPartBoxWithHeadTail( Part, sSide)
|
|
local _sSide = sSide or ''
|
|
|
|
-- si può usare il box del grezzo che contiene sempre il sovramateriale di testa
|
|
if _sSide == 'Head' then
|
|
|
|
local b3WithHead = BBox3d( Part.b3Raw)
|
|
return b3WithHead
|
|
|
|
-- se è l'ultimo pezzo della barra si aggiunge il box dell'eventuale grezzo successivo
|
|
-- se non lo è, si estende il box del pezzo fino alla fine della barra
|
|
elseif _sSide == 'Tail' then
|
|
|
|
local b3WithTail = BBox3d( Part.b3Part)
|
|
if Part.bIsLastPart then
|
|
local nNextRawId = EgtGetNextRawPart( Part.idRaw)
|
|
if nNextRawId then
|
|
local b3Tail = EgtGetRawPartBBox( nNextRawId)
|
|
b3WithTail:Add( b3Tail)
|
|
end
|
|
else
|
|
-- per il punto di inizio barra si parte dal box del grezzo perchè contiene già il sovramateriale spessore lama/catena in coda (la restLength non lo comprende)
|
|
local ptXMin = Point3d( Part.b3Raw:getMin():getX() - Part.dRestLength, Part.b3Part:getMin():getY(), Part.b3Part:getMin():getZ())
|
|
b3WithTail:Add( ptXMin)
|
|
end
|
|
|
|
return b3WithTail
|
|
|
|
-- per aggiungere entrambi si procede come per la coda ma partendo dal box del grezzo, che già contiene la testa
|
|
elseif sSide == 'HeadTail' then
|
|
|
|
local b3WithHeadTail = BBox3d( Part.b3Raw)
|
|
if Part.bIsLastPart then
|
|
local nNextRawId = EgtGetNextRawPart( Part.idRaw)
|
|
if nNextRawId then
|
|
local b3Tail = EgtGetRawPartBBox( nNextRawId)
|
|
b3WithHeadTail:Add( b3Tail)
|
|
end
|
|
else
|
|
-- per il punto di inizio barra si parte dal box del grezzo perchè contiene già il sovramateriale spessore lama/catena in coda (la restLength non lo comprende)
|
|
local ptXMin = Point3d( Part.b3Raw:getMin():getX() - Part.dRestLength, Part.b3Part:getMin():getY(), Part.b3Part:getMin():getZ())
|
|
b3WithHeadTail:Add( ptXMin)
|
|
end
|
|
|
|
return b3WithHeadTail
|
|
|
|
-- sSide non definito, si restituisce il box del pezzo con l'aggiunta dello spessore lama/catena in coda
|
|
else
|
|
local b3WithSplit = BBox3d( Part.b3Part)
|
|
-- per il punto di inizio barra si parte dal box del grezzo perchè contiene già il sovramateriale spessore lama/catena in coda (la restLength non lo comprende)
|
|
local ptXMin = Point3d( Part.b3Raw:getMin():getX(), Part.b3Part:getMin():getY(), Part.b3Part:getMin():getZ())
|
|
b3WithSplit:Add( ptXMin)
|
|
|
|
return b3WithSplit
|
|
end
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
function BeamLib.GetPartSplittingPoints( Part)
|
|
local PartSplittingPoints = {}
|
|
local dPartLength = Part.b3Part:getDimX()
|
|
local dMaxSegmentLength = BeamData.LONGCUT_MAXLEN
|
|
local dMaxSegmentLengthOnEdges = BeamData.LONGCUT_ENDLEN
|
|
|
|
if dPartLength < dMaxSegmentLength + 10 * GEO.EPS_SMALL then
|
|
return {}
|
|
elseif dPartLength >= dMaxSegmentLength + 10 * GEO.EPS_SMALL
|
|
and dPartLength < 3 * dMaxSegmentLengthOnEdges + 10 * GEO.EPS_SMALL then
|
|
local dXPartCentralPoint = ( Part.b3Part:getMax():getX() - Part.b3Part:getMin():getX()) / 2
|
|
table.insert( PartSplittingPoints, Point3d( dXPartCentralPoint, 0, 0))
|
|
else
|
|
-- punto estremo destro
|
|
local dSplitXRight = Part.b3Part:getMax():getX() - dMaxSegmentLengthOnEdges
|
|
table.insert( PartSplittingPoints, Point3d( dSplitXRight, 0, 0))
|
|
|
|
-- punti centrali
|
|
local dPartCentralLength = dPartLength - 2 * dMaxSegmentLengthOnEdges
|
|
local nSplitParts = max( ceil( dPartCentralLength / dMaxSegmentLength + 10 * GEO.EPS_SMALL), 1)
|
|
local dSplitPartsLen = dPartCentralLength / nSplitParts
|
|
for i = 1, ( nSplitParts - 1) do
|
|
local ptOn
|
|
local dCurrentPointX = dSplitXRight - i * dSplitPartsLen
|
|
ptOn = Point3d( dCurrentPointX, 0, 0)
|
|
table.insert( PartSplittingPoints, ptOn)
|
|
end
|
|
|
|
-- punto estremo sinistro
|
|
local dSplitXLeft = Part.b3Part:getMin():getX() + dMaxSegmentLengthOnEdges
|
|
table.insert( PartSplittingPoints, Point3d( dSplitXLeft, 0, 0))
|
|
end
|
|
|
|
return PartSplittingPoints
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
function BeamLib.AddPhaseWithRawParts( idRaw, OriXR, PosXR, dDeltaSucc)
|
|
local nPhase = EgtAddPhase()
|
|
-- si aprono i limiti tavola per permettere rotazioni di pezzi più larghi della tavola
|
|
EgtSetTableAreaOffset( 2000, 2000, 2000, 2000)
|
|
local dRawMove = 0
|
|
while idRaw do
|
|
EgtKeepRawPart( idRaw)
|
|
EgtMoveToCornerRawPart( idRaw, OriXR, PosXR)
|
|
EgtMoveRawPart( idRaw, Vector3d( - dRawMove, 0, 0))
|
|
if dRawMove == 0 then dRawMove = dRawMove + dDeltaSucc end
|
|
dRawMove = dRawMove + EgtGetRawPartBBox( idRaw):getDimX()
|
|
idRaw = EgtGetNextRawPart( idRaw)
|
|
end
|
|
-- salvo info nuova fase aggiunta
|
|
local MachExtraInfo = { sType = 'DISP',
|
|
nPhase = nPhase}
|
|
table.insert( DB_MACH_APPLIED, MachExtraInfo)
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
function BeamLib.IsPointOnBoxLimit( ptPointToCheck, b3Solid)
|
|
local bOnBoxLimit = false
|
|
if abs( ptPointToCheck:getX() - b3Solid:getMax():getX()) < 100 * GEO.EPS_SMALL or
|
|
abs( ptPointToCheck:getX() - b3Solid:getMin():getX()) < 100 * GEO.EPS_SMALL or
|
|
abs( ptPointToCheck:getY() - b3Solid:getMax():getY()) < 100 * GEO.EPS_SMALL or
|
|
abs( ptPointToCheck:getY() - b3Solid:getMin():getY()) < 100 * GEO.EPS_SMALL or
|
|
abs( ptPointToCheck:getZ() - b3Solid:getMax():getZ()) < 100 * GEO.EPS_SMALL or
|
|
abs( ptPointToCheck:getZ() - b3Solid:getMin():getZ()) < 100 * GEO.EPS_SMALL then
|
|
bOnBoxLimit = true
|
|
end
|
|
return bOnBoxLimit
|
|
end
|
|
-------------------------------------------------------------------------------------------------------------
|
|
function BeamLib.SetOpenSide( nPathInt, b3Solid)
|
|
-- fondo tra loro le curve compatibili
|
|
EgtMergeCurvesInCurveCompo( nPathInt)
|
|
-- vettore indici lati aperti
|
|
local vOpen = {}
|
|
-- ciclo sulle curve elementari della composita
|
|
local _, nNumEnt = EgtCurveDomain( nPathInt)
|
|
for i = 0, nNumEnt - 1 do
|
|
-- se segmento di retta
|
|
if EgtCurveCompoRadius( nPathInt, i) == -1 then
|
|
-- verifico se giace in uno dei piani limite del pezzo quindi se è un lato aperto
|
|
local ptIni = EgtUP( nPathInt, i, GDB_RT.GLOB)
|
|
local ptFin = EgtUP( nPathInt, i + 1, GDB_RT.GLOB)
|
|
if BeamLib.IsPointOnBoxLimit( ptIni, b3Solid) and BeamLib.IsPointOnBoxLimit( ptFin, b3Solid) then
|
|
-- aggiorno il vettore dei lati aperti
|
|
table.insert( vOpen, i)
|
|
end
|
|
end
|
|
end
|
|
-- assegno gli indici dei lati aperti
|
|
EgtSetInfo( nPathInt, 'OPEN', vOpen)
|
|
return true
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
function BeamLib.ConvertToClosedCurve( Proc, AuxId)
|
|
local bCurveModified = false
|
|
if not EgtCurveIsClosed( AuxId) then
|
|
local NewId, nCount = EgtExtractSurfTmFacetLoops( Proc.id, 0, EgtGetParent( Proc.id))
|
|
if NewId then
|
|
-- elimino eventuali loop interni (non dovrebbero comunque esserci)
|
|
for i = 1, nCount - 1 do
|
|
EgtErase( NewId + i)
|
|
end
|
|
local vtExtr = EgtCurveExtrusion( AuxId, GDB_ID.ROOT)
|
|
-- sostituisco il loop esterno alla curva originale
|
|
EgtModifyCurveExtrusion( NewId, vtExtr, GDB_ID.ROOT)
|
|
EgtRelocate( NewId, AuxId, GDB_IN.AFTER)
|
|
EgtErase( AuxId)
|
|
EgtChangeId( NewId, AuxId)
|
|
bCurveModified = true
|
|
-- sistemo i lati aperti
|
|
local vFacAdj = EgtSurfTmFacetAdjacencies( Proc.id, 0)[1]
|
|
if vFacAdj then
|
|
local vOpen = {}
|
|
for i = 1, #vFacAdj do
|
|
if vFacAdj[i] < 0 then
|
|
table.insert( vOpen, i - 1)
|
|
end
|
|
end
|
|
EgtSetInfo( AuxId, 'OPEN', vOpen)
|
|
end
|
|
end
|
|
end
|
|
|
|
return true, bCurveModified
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
--- funzione che inverte il grezzo testa-coda
|
|
function BeamLib.InvertRawPart( Part, nNumberOfRotations)
|
|
-- se non si deve ruotare, si esce subito
|
|
if nNumberOfRotations == 0 then
|
|
return
|
|
end
|
|
-- box del solido
|
|
local b3BoxPart = EgtGetBBoxGlob( EgtGetFirstNameInGroup( Part.id or GDB_ID.NULL, 'Box') or GDB_ID.NULL, GDB_BB.EXACT)
|
|
-- box esatto del pezzo
|
|
local b3BoxExact = EgtGetBBoxGlob( Part.id or GDB_ID.NULL, GDB_BB.EXACT)
|
|
-- rotazione
|
|
local dAngRot = nNumberOfRotations * 90
|
|
EgtRotatePartInRawPart( Part.id, Z_AX(), dAngRot)
|
|
-- correggo per eccentricità solido rispetto a geometria complessiva del pezzo
|
|
local vtEccOri = b3BoxPart:getCenter() - b3BoxExact:getCenter()
|
|
local vtEccRot = Vector3d( vtEccOri)
|
|
vtEccRot:rotate( Z_AX(), dAngRot)
|
|
EgtMovePartInRawPart( Part.id, ( vtEccOri - vtEccRot))
|
|
-- si salva posizione corrente
|
|
if Part.bIsInverted then
|
|
Part.bIsInverted = false
|
|
else
|
|
Part.bIsInverted = true
|
|
end
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
--- funzione che ruota il grezzo
|
|
function BeamLib.RotateRawPart( Part, nNumberOfRotations)
|
|
-- sistemo numero rotazioni in caso sia negativa
|
|
if nNumberOfRotations < 0 then
|
|
nNumberOfRotations = nNumberOfRotations + 4
|
|
end
|
|
-- primo posizionamento
|
|
if nNumberOfRotations == 0 then
|
|
; -- il pezzo è già in posizione
|
|
-- rotazione 90°
|
|
elseif nNumberOfRotations == 1 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
|
|
local bIsRotationOK = EgtRotateRawPart( nRId, X_AX(), EgtIf( BeamData.RIGHT_LOAD, -90, 90))
|
|
if not bIsRotationOK then error( 'UNEXPECTED ERROR: rotation of the raw not executed') end
|
|
if not bPreMove then EgtMoveRawPart( nRId, vtMove) end
|
|
nRId = EgtGetNextRawPart( nRId)
|
|
end
|
|
-- rotazione 180°
|
|
elseif nNumberOfRotations == 2 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 nNumberOfRotations == 3 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
|
|
local bIsRotationOK = EgtRotateRawPart( nRId, X_AX(), EgtIf( BeamData.RIGHT_LOAD, 90, -90))
|
|
if not bIsRotationOK then error( 'UNEXPECTED ERROR: rotation of the raw not executed') end
|
|
if not bPreMove then EgtMoveRawPart( nRId, vtMove) end
|
|
nRId = EgtGetNextRawPart( nRId)
|
|
end
|
|
end
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
function BeamLib.CreateAddGroup( PartId, sGroupName)
|
|
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, sGroupName)
|
|
EgtSetInfo( AddGrpId, GDB_SI.MGRPONLY, EgtGetCurrMachGroup())
|
|
EgtSetColor( AddGrpId, Color3d( 80, 160, 160, 25))
|
|
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
|
|
BeamLib.CreateAddGroup( PartId, sMchGrp)
|
|
|
|
return true
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
function BeamLib.CreateTempGroup()
|
|
local idTempGroup = BeamLib.GetTempGroup()
|
|
-- se non esiste, lo creo
|
|
if not idTempGroup then
|
|
idTempGroup = EgtGroup( GDB_ID.ROOT)
|
|
EgtSetName( idTempGroup, "#TEMP_GROUP#")
|
|
EgtSetColor( idTempGroup, Color3d( 80, 160, 160, 1))
|
|
EgtSetLevel( idTempGroup, GDB_LV.TEMP)
|
|
EgtSetStatus( idTempGroup, GDB_ST.OFF)
|
|
end
|
|
return idTempGroup
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
function BeamLib.GetTempGroup()
|
|
local idTempGroup = EgtGetFirstNameInGroup( GDB_ID.ROOT, "#TEMP_GROUP#") or nil
|
|
return idTempGroup
|
|
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
|
|
-- TODO da spostare in FeatureLib???
|
|
-- TODO le feature 1 faccia devono essere settate aperte sulla faccia indicata dalla normale
|
|
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.b3Part:getMax():getZ() - 500 * GEO.EPS_SMALL then
|
|
vtFacesAffected.bTop = true
|
|
end
|
|
if Proc.b3Box:getMin():getZ() < Part.b3Part:getMin():getZ() + 500 * GEO.EPS_SMALL then
|
|
vtFacesAffected.bBottom = true
|
|
end
|
|
if Proc.b3Box:getMin():getY() < Part.b3Part:getMin():getY() + 500 * GEO.EPS_SMALL then
|
|
vtFacesAffected.bFront = true
|
|
end
|
|
if Proc.b3Box:getMax():getY() > Part.b3Part:getMax():getY() - 500 * GEO.EPS_SMALL then
|
|
vtFacesAffected.bBack = true
|
|
end
|
|
if Proc.b3Box:getMin():getX() < Part.b3Part:getMin():getX() + 500 * GEO.EPS_SMALL then
|
|
vtFacesAffected.bLeft = true
|
|
end
|
|
if Proc.b3Box:getMax():getX() > Part.b3Part: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
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
-- TODO gestire anche altri valori
|
|
function BeamLib.GetDirectionFromSCC( nSCC)
|
|
local vtSCC
|
|
|
|
if nSCC == MCH_SCC.ADIR_XP then
|
|
vtSCC = X_AX()
|
|
elseif nSCC == MCH_SCC.ADIR_XM then
|
|
vtSCC = -X_AX()
|
|
elseif nSCC == MCH_SCC.ADIR_YP then
|
|
vtSCC = Y_AX()
|
|
elseif nSCC == MCH_SCC.ADIR_YM then
|
|
vtSCC = -Y_AX()
|
|
elseif nSCC == MCH_SCC.ADIR_ZP then
|
|
vtSCC = Z_AX()
|
|
elseif nSCC == MCH_SCC.ADIR_ZM then
|
|
vtSCC = -Z_AX()
|
|
end
|
|
|
|
return vtSCC
|
|
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 < 5 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
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
-- funzione con valore di default in caso la GetSetupInfo della testa della macchina non avesse la funzione definita
|
|
function BeamLib.GetMinNzDownUpDefault( b3Raw, vtNFace, vtToolDirection, Tool)
|
|
return -2
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
-- funzione con valore di default in caso la GetSetupInfo della testa della macchina non avesse la funzione definita
|
|
function BeamLib.GetMinNzDefault( vtNFace, Tool)
|
|
return 0
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
-- funzione con valore di default in caso la GetSetupInfo della testa della macchina non avesse la funzione definita
|
|
function BeamLib.GetMaxNzDefault( vtNFace, Tool)
|
|
return 0
|
|
end
|
|
|
|
-- TODO bisogna recuperare il nome del parametro NGE, perchè in questo caso è forzato
|
|
-------------------------------------------------------------------------------------------------------------
|
|
function BeamLib.GetPieceGeneralParameters( Part, DefaultGeneralParamList)
|
|
local GeneralParameters = {}
|
|
|
|
-- si salvano sul pezzo le note forzate, altrimenti si leggeranno dopo, quando si prendono i dati della strategia
|
|
for i = 1, #DefaultGeneralParamList do
|
|
local sParamNameNGE = DefaultGeneralParamList[i].sNameNge
|
|
local xParameterValue = EgtGetInfo( Part.id, sParamNameNGE, 's') or nil
|
|
-- se il paraemtro esiste, salvataggio dato su lista con accesso diretto
|
|
if xParameterValue then
|
|
if DefaultGeneralParamList[i].sType == 'b' then
|
|
GeneralParameters[DefaultGeneralParamList[i].sName] = xParameterValue == 'true' or xParameterValue == '1' or xParameterValue == true
|
|
elseif DefaultGeneralParamList[i].sType == 'd' then
|
|
if #DefaultGeneralParamList[i].sValue > 0 then
|
|
GeneralParameters[DefaultGeneralParamList[i].sName] = tonumber( xParameterValue)
|
|
-- stringa vuota equivale a non passare alcun valore (deciderà la strategia)
|
|
else
|
|
GeneralParameters[DefaultGeneralParamList[i].sName] = nil
|
|
end
|
|
else --DefaultGeneralParamList[i].sType == 's' or DefaultGeneralParamList[i].sType == 'combo'
|
|
GeneralParameters[DefaultGeneralParamList[i].sName] = xParameterValue
|
|
end
|
|
else
|
|
if GENERAL_PARAMETERS.BTL and GENERAL_PARAMETERS.BTL[Part.sBTLInfo] and GENERAL_PARAMETERS.BTL[Part.sBTLInfo][DefaultGeneralParamList[i].sName] ~= nil then
|
|
GeneralParameters[DefaultGeneralParamList[i].sName] = GENERAL_PARAMETERS.BTL[Part.sBTLInfo][DefaultGeneralParamList[i].sName]
|
|
elseif GENERAL_PARAMETERS.PROJECT[DefaultGeneralParamList[i].sName] ~= nil then
|
|
GeneralParameters[DefaultGeneralParamList[i].sName] = GENERAL_PARAMETERS.PROJECT[DefaultGeneralParamList[i].sName]
|
|
end
|
|
end
|
|
end
|
|
|
|
return GeneralParameters
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
local function GetInheritedParameter( Part, sSourceParamName)
|
|
local sValue = nil
|
|
if sSourceParamName and #sSourceParamName > 0 then
|
|
if Part.GeneralParameters[sSourceParamName] ~= nil then
|
|
sValue = Part.GeneralParameters[sSourceParamName]
|
|
elseif GENERAL_PARAMETERS.BTL and GENERAL_PARAMETERS.BTL[Part.sBTLInfo] and GENERAL_PARAMETERS.BTL[Part.sBTLInfo][sSourceParamName] ~= nil then
|
|
sValue = GENERAL_PARAMETERS.BTL[Part.sBTLInfo][sSourceParamName]
|
|
elseif GENERAL_PARAMETERS.PROJECT[sSourceParamName] ~= nil then
|
|
sValue = GENERAL_PARAMETERS.PROJECT[sSourceParamName]
|
|
end
|
|
end
|
|
return sValue
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
-- si traduce la tabella dei parametri con tutte le informazioni in una lista contenente i parametri utilizzabili con accesso diretto
|
|
function BeamLib.LoadCustomParametersInStrategy( Proc, Part, CustomParameters, DefaultStrategyParamList)
|
|
local UpdatedParameters = {}
|
|
-- TODO serve controllare se campo 'sStrategyId' congruente tra il Config (DefaultStrategyParamList) e i parametri custom (CustomParameters)?
|
|
if DefaultStrategyParamList and DefaultStrategyParamList.ParameterList and #DefaultStrategyParamList.ParameterList > 0 then
|
|
-- lettura e settaggio parametri finali per la strategia (customizzati o default)
|
|
for i = 1, #DefaultStrategyParamList.ParameterList do
|
|
local xParameterValue = nil
|
|
-- se strategia forzata, leggo eventuali parametri nelle info
|
|
if CustomParameters and CustomParameters.bForcedStrategy and DefaultStrategyParamList.ParameterList[i].sNameNge then
|
|
local sParameterToRead = DefaultStrategyParamList.sStrategyId .. '_' .. DefaultStrategyParamList.ParameterList[i].sNameNge
|
|
local sForcedParameterForProc = EgtGetInfo( Proc.id, sParameterToRead, 's')
|
|
-- se ho trovato il valore, lo sovrascrivo al default
|
|
if sForcedParameterForProc then
|
|
xParameterValue = sForcedParameterForProc
|
|
end
|
|
-- altrimenti i parametri custom si trovano già su questa lista
|
|
elseif CustomParameters and CustomParameters.ParameterList then
|
|
for j = 1, #CustomParameters.ParameterList do
|
|
if CustomParameters.ParameterList[j].sName == DefaultStrategyParamList.ParameterList[i].sName or
|
|
CustomParameters.ParameterList[j].sName == DefaultStrategyParamList.ParameterList[i].sNameNge then
|
|
xParameterValue = CustomParameters.ParameterList[j].sValue
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
-- se non arriva forzato da strategia, oppure se non è stato configurato da cliente, si prende default
|
|
if xParameterValue == nil then
|
|
-- se il parametro strategia è da ereditare da un parametro globale
|
|
if DefaultStrategyParamList.ParameterList[i].sSource and #DefaultStrategyParamList.ParameterList[i].sSource > 0 then
|
|
xParameterValue = GetInheritedParameter( Part, DefaultStrategyParamList.ParameterList[i].sSource)
|
|
else
|
|
xParameterValue = DefaultStrategyParamList.ParameterList[i].sValue
|
|
end
|
|
end
|
|
|
|
if DefaultStrategyParamList.ParameterList[i].sType == 'b' then
|
|
UpdatedParameters[DefaultStrategyParamList.ParameterList[i].sName] = xParameterValue == 'true' or xParameterValue == '1' or xParameterValue == true
|
|
elseif DefaultStrategyParamList.ParameterList[i].sType == 'd' then
|
|
if #DefaultStrategyParamList.ParameterList[i].sValue > 0 then
|
|
UpdatedParameters[DefaultStrategyParamList.ParameterList[i].sName] = tonumber( xParameterValue)
|
|
-- stringa vuota equivale a non passare alcun valore (deciderà la strategia)
|
|
else
|
|
UpdatedParameters[DefaultStrategyParamList.ParameterList[i].sName] = nil
|
|
end
|
|
else --DefaultStrategyParamList[i].sType == 's' or DefaultStrategyParamList[i].sType == 'combo'
|
|
UpdatedParameters[DefaultStrategyParamList.ParameterList[i].sName] = xParameterValue
|
|
end
|
|
end
|
|
end
|
|
|
|
return UpdatedParameters
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
-- si traduce la tabella dei parametri con tutte le informazioni in una lista contenente i parametri utilizzabili con accesso diretto
|
|
function BeamLib.LoadGeneralParametersInList( DefaultGeneralParamList)
|
|
local UpdatedParameters = { PROJECT = {}, BTL = {}}
|
|
-- aggiornamento parametri PROJECT
|
|
if DefaultGeneralParamList then
|
|
local idProjectInfo = EgtGetFirstNameInGroup( GDB_ID.ROOT, 'ProjectInfo') or GDB_ID.NULL
|
|
UpdatedParameters.PROJECT.sAISetupConfig = EgtGetInfo( idProjectInfo, 'AISETUP', 's') or nil
|
|
for i = 1, #DefaultGeneralParamList do
|
|
local sParamNameNGE = DefaultGeneralParamList[i].sNameNge
|
|
local xParameterValue = EgtGetInfo( idProjectInfo, sParamNameNGE, 's') or DefaultGeneralParamList[i].sValue
|
|
-- se parametro non trovato si salta tutto. N.B. = I parametri progetto non dovrebbero mai essere nil
|
|
if xParameterValue then
|
|
-- salvataggio dato su lista con accesso diretto
|
|
if DefaultGeneralParamList[i].sType == 'b' then
|
|
UpdatedParameters.PROJECT[DefaultGeneralParamList[i].sName] = xParameterValue == 'true' or xParameterValue == '1' or xParameterValue == true
|
|
elseif DefaultGeneralParamList[i].sType == 'd' then
|
|
if #DefaultGeneralParamList[i].sValue > 0 then
|
|
UpdatedParameters.PROJECT[DefaultGeneralParamList[i].sName] = tonumber( xParameterValue)
|
|
-- stringa vuota equivale a non passare alcun valore (deciderà la strategia)
|
|
else
|
|
UpdatedParameters.PROJECT[DefaultGeneralParamList[i].sName] = nil
|
|
end
|
|
else --DefaultGeneralParamList[i].sType == 's' or DefaultGeneralParamList[i].sType == 'combo'
|
|
UpdatedParameters.PROJECT[DefaultGeneralParamList[i].sName] = xParameterValue
|
|
end
|
|
end
|
|
end
|
|
|
|
-- aggiornamento parametri BTL
|
|
local BTLInfo = EgtGetNameInGroup( GDB_ID.ROOT, 'BtlInfo') or GDB_ID.NULL
|
|
for j = 1, #BTLInfo do
|
|
local BTLName = EgtGetInfo( BTLInfo[j], 'PROJ', 's')
|
|
if BTLName then
|
|
UpdatedParameters.BTL[BTLName] = {}
|
|
UpdatedParameters.BTL[BTLName].sAISetupConfig = EgtGetInfo( BTLInfo[j], 'AISETUP', 's') or nil
|
|
for i = 1, #DefaultGeneralParamList do
|
|
local sParamNameNGE = DefaultGeneralParamList[i].sNameNge
|
|
local xParameterValue = EgtGetInfo( BTLInfo[j], sParamNameNGE, 's')
|
|
-- se parametro non trovato si salta tutto
|
|
if xParameterValue then
|
|
-- salvataggio dato su lista con accesso diretto
|
|
if DefaultGeneralParamList[i].sType == 'b' then
|
|
UpdatedParameters.BTL[BTLName][DefaultGeneralParamList[i].sName] = xParameterValue == 'true' or xParameterValue == '1' or xParameterValue == true
|
|
elseif DefaultGeneralParamList[i].sType == 'd' then
|
|
if #DefaultGeneralParamList[i].sValue > 0 then
|
|
UpdatedParameters.BTL[BTLName][DefaultGeneralParamList[i].sName] = tonumber( xParameterValue)
|
|
-- stringa vuota equivale a non passare alcun valore (deciderà la strategia)
|
|
else
|
|
UpdatedParameters.BTL[BTLName][DefaultGeneralParamList[i].sName] = nil
|
|
end
|
|
else --DefaultGeneralParamList[i].sType == 's' or DefaultGeneralParamList[i].sType == 'combo'
|
|
UpdatedParameters.BTL[BTLName][DefaultGeneralParamList[i].sName] = xParameterValue
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
return UpdatedParameters
|
|
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.StringReplaceChar( sOriginal, nPosition, sChar)
|
|
return sOriginal:sub( 1, nPosition-1) .. sChar .. sOriginal:sub( nPosition+1)
|
|
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)
|
|
-- controllo se oggetto passato è valido, altrimenti errore. Non deve mai succedere
|
|
if not OriginalTable then
|
|
error( "TableCopyDeep : can't copy nil object")
|
|
end
|
|
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
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
function BeamLib.MergeTables( OriginalTable, InputTable)
|
|
local result = {}
|
|
for k, v in pairs( OriginalTable) do result[k] = v end
|
|
for k, v in pairs( InputTable) do result[k] = v end
|
|
return result
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
function BeamLib.FindEdgeBestOrientedAsDirection( Edges, vtDirection)
|
|
local BestEdge = {}
|
|
|
|
local dMaxDotProduct = GEO.INFINITO
|
|
for i = 1, #Edges do
|
|
local dCurrentDotProduct = ( Edges[i].vtN * vtDirection)
|
|
if ( i == 1) or ( dCurrentDotProduct > dMaxDotProduct + 10 * GEO.EPS_SMALL) then
|
|
dMaxDotProduct = dCurrentDotProduct
|
|
BestEdge = Edges[i]
|
|
end
|
|
end
|
|
|
|
return BestEdge
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
-- nNearSide : 3=Z+, -3=Z-
|
|
function BeamLib.PutStartNearestToEdge( nCrvId, b3Raw, dMaxDist, nNearSide)
|
|
-- 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 dSopt = 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 dS
|
|
if nNearSide == -3 then
|
|
dS = abs( vtMin:getZ() * dCoeffZ)
|
|
else --nNearSide == 3
|
|
dS = abs( vtMax:getZ() * dCoeffZ)
|
|
end
|
|
if dD < dMaxDist and dS < dSopt + GEO.EPS_SMALL then
|
|
dUopt = dU
|
|
dDopt = dD
|
|
dSopt = dS
|
|
end
|
|
end
|
|
end
|
|
if abs( dUopt - dUi) > GEO.EPS_ZERO and abs( dUopt - dUf) > GEO.EPS_ZERO then
|
|
-- TODO. Non utilizzare la funzione EgtChangeClosedCurveStart perchè cambia proprietà della geometria.
|
|
-- dopo aver trovato l'entità di partenza, calcolare l'offset da aggiungere alla lavorazione per poter cominciare da questa entità (senza modifica della geometria)
|
|
EgtChangeClosedCurveStart( nCrvId, dUopt)
|
|
end
|
|
return true
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
function BeamLib.ImportFileJSON( sFileToImport)
|
|
local JSON = require( 'JSON')
|
|
|
|
local function readAll( sFileToImport)
|
|
local f = io.open( sFileToImport, "rb")
|
|
local content = f:read( "*all")
|
|
f:close()
|
|
return content
|
|
end
|
|
|
|
local content = readAll( sFileToImport)
|
|
return JSON:decode( content)
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
function BeamLib.GetStrategiesFromList( Proc, StrategyList)
|
|
-- cerco tra le feature
|
|
for i = 1, #StrategyList.FEATURE do
|
|
-- se trovo la feature
|
|
if Proc.nPrc == StrategyList.FEATURE[i].nPrc then
|
|
local bGroupIsCompatible = false
|
|
-- nel JSON il gruppo è sempre 0/1, mente da BTL possono arrivare altri valori.
|
|
if StrategyList.FEATURE[i].nGrp == 0 then
|
|
if Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4 then
|
|
bGroupIsCompatible = true
|
|
end
|
|
elseif StrategyList.FEATURE[i].nGrp == 1 then
|
|
if Proc.nGrp == 1 or Proc.nGrp == 2 then
|
|
bGroupIsCompatible = true
|
|
end
|
|
end
|
|
|
|
-- si controlla gruppo
|
|
if bGroupIsCompatible then
|
|
-- cerco tra le topologie
|
|
for j = 1, #StrategyList.FEATURE[i].TopologyList do
|
|
-- non si possono mischiare topologie specifiche con topologia 'Feature'. Se presente topologia 'Feature' allora deve essere esclusiva
|
|
if StrategyList.FEATURE[i].TopologyList[j].sName == 'Feature' and #StrategyList.FEATURE[i].TopologyList > 1 then
|
|
error( "UNEXPECTED ERROR: topology 'Feature' can't be mixed with others")
|
|
end
|
|
-- se trovo la topologia oppure se è 'Feature'
|
|
if Proc.Topology.sName == StrategyList.FEATURE[i].TopologyList[j].sName or StrategyList.FEATURE[i].TopologyList[j].sName == 'Feature' then
|
|
local ActiveStrategyList = {}
|
|
-- aggiungo in lista solo le strategie attive
|
|
if StrategyList.FEATURE[i].TopologyList[j].StrategyList then
|
|
for k = 1, #StrategyList.FEATURE[i].TopologyList[j].StrategyList do
|
|
if ( not StrategyList.FEATURE[i].TopologyList[j].StrategyList[k].nIndexInList) or ( StrategyList.FEATURE[i].TopologyList[j].StrategyList[k].nIndexInList) >= 0 then
|
|
table.insert( ActiveStrategyList, BeamLib.TableCopyDeep( StrategyList.FEATURE[i].TopologyList[j].StrategyList[k]))
|
|
end
|
|
end
|
|
end
|
|
-- ritorno le strategie disponibili per la feature che sto analizzando, altrimenti nil se non ho trovato nulla
|
|
return EgtIf( #ActiveStrategyList > 0, ActiveStrategyList, nil)
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
return nil
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
-- Merge sorting - algoritmo di sorting stabile, ossia che mantiene l'ordine relativo se gli elementi sono equivalenti
|
|
-- TODO vedere come riordinare (tutto in tabella MergeSort??)
|
|
-- TODO libreria Sorting??
|
|
do
|
|
-- unisce due liste ordinate
|
|
local function MergeHalves(Left, Right, Compare)
|
|
local result = {}
|
|
local i, j = 1, 1
|
|
|
|
while i <= #Left and j <= #Right do
|
|
if Compare( Left[i], Right[j]) then
|
|
table.insert( result, Left[i])
|
|
i = i + 1
|
|
else
|
|
table.insert( result, Right[j])
|
|
j = j + 1
|
|
end
|
|
end
|
|
|
|
-- Append degli elementi rimanenti a sinistra o destra
|
|
while i <= #Left do
|
|
table.insert( result, Left[i])
|
|
i = i + 1
|
|
end
|
|
while j <= #Right do
|
|
table.insert( result, Right[j])
|
|
j = j + 1
|
|
end
|
|
|
|
return result
|
|
end
|
|
|
|
-- Merge sort
|
|
local function MergeSort( List, Compare)
|
|
if #List <= 1 then
|
|
return List
|
|
end
|
|
|
|
local mid = floor( #List / 2)
|
|
local Left = MergeSort( { table.unpack( List, 1, mid)}, Compare)
|
|
local Right = MergeSort( { table.unpack( List, mid + 1)}, Compare)
|
|
|
|
return MergeHalves( Left, Right, Compare)
|
|
end
|
|
|
|
-- chiamata accessibile dall'esterno
|
|
function BeamLib.StableSort( List, Compare)
|
|
return MergeSort( List, Compare)
|
|
end
|
|
end
|
|
|
|
|
|
-------------------------------------------------------------------------------------------------------------
|
|
return BeamLib
|