- Facce e adiacenze calcolate solo per feature con topologia

- Prima versione GetMainFaces funzionante
- Prima bozza struttura codice per scelta strategie
- Calcolo delle 4 rotazioni per il recupero dei dati
- Prima bozza struttura calcolo voto strategie
- Modificate strategie di prova STR0001 e STR0002 con nuovo standard
This commit is contained in:
andrea.villa
2024-04-30 16:30:49 +02:00
parent 385143fb00
commit 80dcdb0003
11 changed files with 411 additions and 104 deletions
+221 -35
View File
@@ -17,6 +17,7 @@ local ID = require( 'Identity')
local BCS = require( 'BasicCustomerStrategies')
local FeatureData = require( 'FeatureData')
local FaceData = require( 'FaceData')
local MachiningLib = require( 'MachiningLib')
EgtOutLog( ' BeamExec started', 1)
@@ -411,33 +412,31 @@ local function GetStrategies( Proc)
if not AvailableStrategiesForProc then
AvailableStrategiesForProc = BCS.GetStrategiesFromBasicCustomerStrategies( Proc)
end
-- TODO se ci sono strategie, le carichiamo qui o quando si lanciano effettivamente?
-- TODO2 Probabilmente meglio lanciarle solo quando serve. Nel caso standard infatti, la prima completa è quella buona, quindi non serve precaricare tutte le altre
return AvailableStrategiesForProc
end
-------------------------------------------------------------------------------------------------------------
local function GetFeatureForcedStrategy( Proc)
-- cerco nelle note se è stata forzata una strategia specifica
local sStrategyID = EgtGetInfo( Proc.Id, 'STRATEGY', 's')
local sStrategyId = EgtGetInfo( Proc.Id, 'STRATEGY', 's')
-- se è presente la strategia forzata
if sStrategyID then
-- eseguo file config con i parametri di default
local StrategyData = require( sStrategyID .. '\\' .. sStrategyID .. 'Config')
if sStrategyId then
-- eseguo file config con i parametri di default
local StrategyData = require( sStrategyId .. '\\' .. sStrategyId .. 'Config')
-- se ID strategia non esiste oppure ID letto in NGE è differente da quello letto nella strategia, esco subito
if not StrategyData or StrategyData.StrategyID ~= sStrategyID then
if not StrategyData or StrategyData.StrategyId ~= sStrategyId then
return nil
end
-- salvo che questa strategia è stata forzata, e che quindi ho già letto il file config con i parametri di default
-- quando si calcolerà la lavorazione non servirà riverificare i dati
-- quando si calcolerà la lavorazione non servirà leggere/riverificare i parametri di default
StrategyData.ForcedStrategy = true
-- cerco e aggiorno i parametri come sono settati nel processing
for i = 1, #StrategyData.Parameters do
local sParameterToRead = StrategyData.StrategyID .. '_' .. StrategyData.Parameters[i].Name
local sParameterToRead = StrategyData.StrategyId .. '_' .. StrategyData.Parameters[i].Name
ForcedParameterForProc = EgtGetInfo( Proc.Id, sParameterToRead, 's')
-- se ho trovato il valore, lo sovrascrivo al default
if ForcedParameterForProc then
@@ -469,11 +468,6 @@ local function CollectFeatures( PartId, b3Raw)
local nGrp = EgtGetInfo( ProcId, 'GRP', 'i')
local nPrc = EgtGetInfo( ProcId, 'PRC', 'i')
local nDo = EgtGetInfo( ProcId, 'DO', 'i') or 1
local nCutId = EgtGetInfo( EgtGetParent( EgtGetParent( ProcId)), 'CUTID', 'i') or 0
local nTaskId = EgtGetInfo( ProcId, 'TASKID', 'i') or 0
-- leggo se ci sono feature collegate
local nAddAdjId = EgtGetInfo( ProcId, 'ADJID', 'i')
local nAddMainId = EgtGetInfo( ProcId, 'MAINID', 'i')
if nGrp and nPrc and nDo == 1 then
local Proc = {}
Proc.PartId = PartId
@@ -484,15 +478,8 @@ local function CollectFeatures( PartId, b3Raw)
Proc.Prc = nPrc
Proc.Flg = 1
Proc.Fct = EgtSurfTmFacetCount( ProcId) or 0
Proc.CutId = nCutId
Proc.TaskId = nTaskId
-- se ci sono feature collegate ne scrivo il riferimento nella Proc
-- TODO AdjId e MainId servono a qualcosa???
if nAddAdjId then
Proc.AdjId = Proc.Id + nAddAdjId
elseif nAddMainId then
Proc.MainId = Proc.Id + nAddMainId
end
Proc.CutId = EgtGetInfo( EgtGetParent( EgtGetParent( ProcId)), 'CUTID', 'i') or 0
Proc.TaskId = EgtGetInfo( ProcId, 'TASKID', 'i') or 0
Proc.Box = EgtGetBBoxGlob( ProcId, GDB_BB.STANDARD)
EgtOutLog( '------Feature ' .. Proc.FeatureId .. '------')
-- se esiste la geometria
@@ -504,23 +491,30 @@ local function CollectFeatures( PartId, b3Raw)
Proc.Diam, Proc.Len, Proc.Fcs, Proc.Fce = FeatureData.GetDrillingData( Proc)
end
-- informazioni facce e topologia
Proc.AdjacencyMatrix = FaceData.GetAdjacencyMatrix( Proc)
Proc.Faces = FaceData.GetFacesInfo( Proc)
Proc.Topology = FeatureData.GetTopology( Proc, b3Raw)
-- calcolo topologia solo se necessario, altrimenti si sfruttano le informazioni della feature BTL
Proc.Topology = {}
if FeatureData.NeedTopologyFeature( Proc) then
Proc.AdjacencyMatrix = FaceData.GetAdjacencyMatrix( Proc)
Proc.Faces = FaceData.GetFacesInfo( Proc)
Proc.Topology = FeatureData.ClassifyTopology( Proc, b3Raw)
else
Proc.Topology.Family = 'FEATURE'
Proc.Topology.Name = 'FEATURE'
end
-- se topologia feature riconosciuta, oppure da non calcolare perchè il riconoscimento topologico è basato sulla feature stessa
if Proc.Topology.Name ~= 'NOT_IMPLEMENTED' then
-- TODO Funzione 'GetMainFaces' da scrivere
-- Proc.MainFaces = FaceData.GetMainFaces( Proc)
Proc.MainFaces = FaceData.GetMainFaces( Proc)
-- se la processing ha una strategia forzata, riporto tutto nella proc
local vForcedStrategy = GetFeatureForcedStrategy( Proc)
if vForcedStrategy then
Proc.Strategies = vForcedStrategy
Proc.AvailableStrategies = vForcedStrategy
-- altrimenti cerco tra le strategie disponibili
else
Proc.Strategies = GetStrategies( Proc)
Proc.AvailableStrategies = GetStrategies( Proc)
end
-- se ci sono strategie disponibili, aggiungo a lista delle feature da lavorare
if Proc.Strategies and #Proc.Strategies > 0 then
if Proc.AvailableStrategies and #Proc.AvailableStrategies > 0 then
table.insert( vProc, Proc)
-- altrimenti errore (non ci sono strategie per lavorare la topologia riconosciuta)
else
@@ -543,6 +537,70 @@ local function CollectFeatures( PartId, b3Raw)
return vProc
end
-------------------------------------------------------------------------------------------------------------
local function AreDrillingsMirrored( Proc, ProcMirror, b3Raw)
if Proc.Id == ProcMirror.Id then return false end
-- geometria ausiliaria foro principale
AuxId = EgtGetInfo( Proc.Id, 'AUXID', 'i')
if AuxId then AuxId = AuxId + Proc.Id end
if not AuxId or EgtGetType( AuxId ) ~= GDB_TY.CRV_ARC then return false end
-- geometria ausiliaria foro specchiato
local AuxIdMirror = EgtGetInfo( ProcMirror.Id, 'AUXID', 'i')
if AuxIdMirror then AuxIdMirror = AuxIdMirror + ProcMirror.Id end
if not AuxIdMirror or EgtGetType( AuxIdMirror ) ~= GDB_TY.CRV_ARC then return false end
-- dati del foro principale
local vtExtr = EgtCurveExtrusion( AuxId, GDB_RT.GLOB)
local ptBC = EgtGP( AuxId, GDB_RT.GLOB)
-- dati del foro specchiato
local vtExtrMirror = EgtCurveExtrusion( AuxIdMirror, GDB_RT.GLOB)
local ptBCMirror = EgtGP( AuxIdMirror, GDB_RT.GLOB)
-- direzione fori
local nDouble
if AreOppositeVectorApprox( vtExtr, vtExtrMirror) then
-- fori lungo Y
-- per macchine tipo PF il foro principale è sul lato back, per macchine tipo PF1250 è sul lato front
if ( BD.TWO_EQUAL_HEADS and AreSameVectorApprox( vtExtr, Y_AX())) or
( BD.DOWN_HEAD and AreOppositeVectorApprox( vtExtr, Y_AX())) then
nDouble = 2
-- fori lungo Z
elseif BD.DOWN_HEAD and AreSameVectorApprox( vtExtr, Z_AX()) then
nDouble = 3
else
return false
end
else
return false
end
-- centri allineati, equidistanti dalla mezzeria trave, non troppo vicini
local vtDisplacement = ptBC - ptBCMirror
local ptCenRaw = b3Raw:getCenter()
if nDouble == 2 then
local dYMinDistance = max( Proc.Box:getMin():getY(), ProcMirror.Box:getMin():getY()) - min( Proc.Box:getMax():getY(), ProcMirror.Box:getMax():getY())
if not ( abs( vtDisplacement:getX()) < 100 * GEO.EPS_SMALL and abs( vtDisplacement:getZ()) < 100 * GEO.EPS_SMALL and
( abs( ptBC:getY() - ptCenRaw:getY()) - abs( ptBCMirror:getY() - ptCenRaw:getY())) < 100 * GEO.EPS_SMALL and
dYMinDistance > MIRROR_DRILLINGS_MIN_DISTANCE + 10 * GEO.EPS_SMALL) then
return false
end
else
local dZMinDistance = max( Proc.Box:getMin():getZ(), ProcMirror.Box:getMin():getZ()) - min( Proc.Box:getMax():getZ(), ProcMirror.Box:getMax():getZ())
if not ( abs( vtDisplacement:getX()) < 100 * GEO.EPS_SMALL and abs( vtDisplacement:getY()) < 100 * GEO.EPS_SMALL and
( abs( ptBC:getZ() - ptCenRaw:getZ()) - abs( ptBCMirror:getZ() - ptCenRaw:getZ())) < 100 * GEO.EPS_SMALL and
dZMinDistance > MIRROR_DRILLINGS_MIN_DISTANCE + 10 * GEO.EPS_SMALL) then
return false
end
end
-- fori della stessa profondità
if abs( Proc.Len - ProcMirror.Len) > 10 * GEO.EPS_SMALL then
return false
end
return true
end
-------------------------------------------------------------------------------------------------------------
local function GetFeatureInfoAndDependency( vProc, b3Raw)
-- ciclo tutte le feature
@@ -572,6 +630,79 @@ local function GetFeatureInfoAndDependency( vProc, b3Raw)
end
end
-------------------------------------------------------------------------------------------------------------
-- -- sceglie la strategia migliore tra quelle disponibili ( presenti nella tabella vProcRot[dRotIndex].AvailableStrategies)
local function ChooseStrategy( Proc, b3Raw)
-- ciclo tutte le strategia
local nIndexBestStrategy = 0
for i = 1, #Proc.AvailableStrategies do
end
-- salvo sulla proc la migliore strategia
if nIndexBestStrategy ~= 0 then
Proc.ChosenStrategy = Proc.AvailableStrategies[nIndexBestStrategy]
end
return Proc
end
-------------------------------------------------------------------------------------------------------------
-- funzione che processa tutte le feature sul pezzo e trova la miglior strategia di lavorazione tra quelle disponibili
local function ProcessPieceFeatures( vProcSingleRot, b3Raw)
-- scelgo la strategia migliore
for i = 1, #vProcSingleRot do
-- processo tutte le feature attive
local Proc = vProcSingleRot[i]
if Proc.Flg ~= 0 then
-- processa le strategie disponibili e salva sulla Proc il voto e info varie per ogni startegia
Proc = MachiningLib.CalculateRatingStrategies( Proc, b3Raw)
-- sceglie la strategia migliore tra quelle disponibili ( presenti nella tabella vProcRot[dRotIndex].AvailableStrategies)
Proc = ChooseStrategy( Proc, b3Raw)
end
end
return vProcSingleRot
end
-------------------------------------------------------------------------------------------------------------
-- esegue le strategie migliori che ha precedentemente scelto
local function ExecPieceFeatures( vProc, b3Raw)
-- flag per applicare realmente le lavorazioni quando viene lanciata la make delle strategie
local bAddMachining = true
-- applico le strategie scelte
for i = 1, #vProc do
-- processo tutte le feature attive applicando le lavorazioni
local Proc = vProc[i]
if Proc.Flg ~= 0 and Proc.ChosenStrategy then
-- carico file script strategia (non serve verificare presenza del file perchè già fatto durante scelta strategia)
local StrategyScriptName = '\\Strategies\\' .. Proc.ChosenStrategy.StrategyId .. '\\' .. Proc.ChosenStrategy.StrategyId
local StrategyScript = require( StrategyScriptName)
-- eseguo la strategia solo come calcolo fattibilità e voto. Non si applicano le lavorazioni. Si passa la Proc e i parametri personalizzati
Proc = StrategyScript.Make( bAddMachining, Proc, Proc.ChosenStrategy.Parameters)
end
end
return vProc
end
-------------------------------------------------------------------------------------------------------------
local function PrintFeatures( vProc, b3Raw)
EgtOutLog( ' RawBox=' .. tostring( b3Raw))
for i = 1, #vProc do
local Proc = vProc[i]
local sOut = string.format( ' Id=%3d Grp=%1d Prc=%3d TC=%2d/%d Flg=%2d Down=%s Side=%s Head=%s Tail=%s Fcse=%1d,%1d Diam=%.2f Fct=%2d Box=%s TopoName=%s',
Proc.Id, Proc.Grp, Proc.Prc, Proc.TaskId, Proc.CutId,
Proc.Flg, EgtIf( Proc.Down, 'T', 'F'), EgtIf( Proc.Side, 'T', 'F'),
EgtIf( Proc.Head, 'T', 'F'), EgtIf( Proc.Tail, 'T', EgtIf( Proc.AdvTail, 'A', 'F')),
Proc.Fcs, Proc.Fce, Proc.Diam, Proc.Fct, tostring( Proc.Box), Proc.Topology.Name or '')
-- info speciali per Block Haus Half Lap
if Proc.Prc == 37 then
local sSpec = string.format( ' N=%s Hd=%s', tostring( Proc.vtN or V_NULL()), EgtIf( Proc.HeadDir, 'T', 'F'))
sOut = sOut .. sSpec
end
EgtOutLog( sOut)
end
end
-------------------------------------------------------------------------------------------------------------
function BeamExec.ProcessFeatures()
-- ciclo sui pezzi
@@ -583,6 +714,49 @@ function BeamExec.ProcessFeatures()
-- verifico che il grezzo contenga pezzi oppure sia abbastanza lungo da essere scaricato coi carrelli
local nPartId = EgtGetFirstPartInRawPart( nRawId)
if not nPartId and EgtGetRawPartBBox( nRawId):getDimX() < BeamData.MinRaw then break end
local vProc = {}
-- per ogni rotazione, calcolo come lavorare le feature per decidere posizionamento iniziale e in che rotazione verranno lavorate le singole feature
local vProcRot = {}
-- TODO da rimuovere o lasciare solo per debug
EgtStartCounter()
-- TODO Il numero di rotazioni da calcolare deve dipendere dalle impostazionei del cliente. Per adesso si calcolano tutte e 4, ma può essere ottimizzato
for dRotIndex = 1, 4 do
-- ingombro del grezzo
local b3Raw = EgtGetRawPartBBox( nRawId)
-- recupero le feature di lavorazione della trave
table.insert( vProcRot, CollectFeatures( nPartId, b3Raw))
-- recupero informazioni ausiliarie feature e dipendenze tra feature stesse
-- TODO le dipendenze cambiano in base alla rotazione del pezzo? probabilmente no
GetFeatureInfoAndDependency( vProcRot[dRotIndex], b3Raw)
-- sceglie la strategia migliore tra quelle disponibili ( presenti nella tabella vProcRot[dRotIndex].AvailableStrategies)
ProcessPieceFeatures( vProcRot[dRotIndex], b3Raw)
-- ruoto il grezzo per calcolare la fattibilità delle lavorazioni nella prossima rotazione
-- vettore movimento grezzi per rotazione di 90deg ogni step
local dDeltaYZ = EgtGetRawPartBBox( nRawId):getDimY() - EgtGetRawPartBBox( nRawId):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
if bPreMove then
EgtMoveRawPart( nRawId, vtMove)
end
EgtRotateRawPart( nRawId, X_AX(), EgtIf( BeamData.RIGHT_LOAD, -90, 90))
if not bPreMove then
EgtMoveRawPart( nRawId, vtMove)
end
end
-- TODO da rimuovere o lasciare solo per debug
local time = EgtStopCounter()
-- TODO decidere come lavorare ogni feature in base alla matrice delle rotazioni
-- la matrice delle rotazioni deve già salvare sulla proc la strategia da utilizzare
-- Conviene salvarsi tutti i dati fino alla lavorazione e il ciclo di applicazione va ad applicare senza calcolare?
-- aggiungo la fase, se non è la prima
if nOrd == 1 then
EgtSetCurrPhase( 1)
@@ -596,14 +770,26 @@ function BeamExec.ProcessFeatures()
EgtOutLog( ' *** Phase=' .. tostring( nPhase) .. ' Raw=' .. tostring( nRawId) .. ' Part=' .. tostring( nPartId) .. ' ***', 1)
-- ingombro del grezzo
local b3Raw = EgtGetRawPartBBox( nRawId)
-- recupero le feature di lavorazione della trave
local vProc = CollectFeatures( nPartId, b3Raw)
-- recupero informazioni ausiliarie feature e dipendenze tra feature stesse
GetFeatureInfoAndDependency( vProc, b3Raw)
-- debug
if EgtGetDebugLevel() >= 1 then
PrintFeatures( vProc, b3Raw)
end
EgtOutLog( ' *** AddMachinings ***', 1)
-- TODO ordinare feature e decidere spezzoni
-- TODO applicare lavorazioni in base a strategie disponibili (prima applicabile o EgalwareIA in base a parametro)
-- ordino le features
-- OrderFeatures( vProc, b3Raw)
-- TODO da fare
-- esegue le strategie migliori che ha precedentemente scelto
ExecPieceFeatures( vProc, b3Raw)
-- TODO riordinare lavorazioni ottimizzando cambio utensile/spezzone ecc..., mantenendo dipendenze definite prima
-- ordino le lavorazioni
-- OrderMachining( vProc, b3Raw)
EgtOutLog( ' *** End AddMachinings ***', 1)