106 Commits

Author SHA1 Message Date
luca.mazzoleni 9edd39305f - STR0005 con codolo funzionante e con ordinamento lavorazioni 2025-01-24 17:21:19 +01:00
luca.mazzoleni 0c5373700e - in STR0003, 4 e 5 corretta gestione spezzatura 2025-01-24 15:17:10 +01:00
luca.mazzoleni 098244b109 - in SLOTBYBLADE e SLOTBYCHAINSAW corrette direzioni utensile 2025-01-24 12:26:22 +01:00
luca.mazzoleni e553197d61 - in Edges l'elevazione si tiene sempre positiva e la normale guarda sempre verso il centro.
- alle funzioni di base si può passare il parametro opzionale bOppositeToolDirection per invertire la direzione di lavoro dell'utensile
2025-01-23 16:39:43 +01:00
luca.mazzoleni c64aaade13 - in FaceData MainFaces non si crea se è vuota
- in SLOTBYBLADE e SLOTBYCHAINSAW piccole correzioni
2025-01-23 12:28:48 +01:00
luca.mazzoleni ffe2d07918 - negli egde vtToolDirection sostituita con vtN 2025-01-23 12:13:30 +01:00
luca.mazzoleni 89c315cdd8 - in MachiningLib corretta l'assegnazione del nFeatureSegment nei casi in cui la lavorazione non ha quasi componenti in X 2025-01-22 12:33:19 +01:00
luca.mazzoleni e3ab0b8f35 - correzione in SLOTBYCHAINSAW 2025-01-21 16:03:19 +01:00
luca.mazzoleni 40e76a23c9 - in FaceData Elevation è sempre positiva nelle facce standard (non MainFaces)
- in MachiningLib in GetSplitMachinings correzioni alla definizione dello stage della lavorazione; correzione a FindBlade
- in SLOTBYBLADE e SLOTBYCHAINSAW correzioni per poter passare la profondità di lavoro
- in STR0005 primo implemento di lavorazione con codolo
2025-01-21 15:27:33 +01:00
luca.mazzoleni fc6b50b345 - in FaceData struttura dati degli Edges della faccia uniformata a quella degli Edges della MainFaces
- tutte le chiamate a Edges aggiornate di conseguenza
2025-01-17 18:06:37 +01:00
luca.mazzoleni 8d2a9955ba - in MachiningLib GetMachiningSteps il numero minimo di step è sempre 1
- STR0004 corretta per passare altezza tasca alla SlotByChainsaw
- in SLOTBYBLADE e SLOTBYCHAINSAW si controlla se la tasca è meno spessa della lama solo nel caso in cui venga passata un'altezza tasca
2025-01-17 13:05:35 +01:00
luca.mazzoleni 87aa2a7ce6 - in SLOTBYCHAINSAW e SLOTBYBLADE spostato calcolo altezza tasca fuori; si deve passare come parametro opzionale: se non presente, si lavora la faccia senza step verticali
- STR0003 modificata per rispecchiare le modifiche sopra; STR0004 DA FARE
2025-01-16 18:28:52 +01:00
luca.mazzoleni 2be4a3fe0b - PROCESSINGS spostata in BeamExec
- aggiunte a STR0005, da completare
2025-01-16 12:52:15 +01:00
luca.mazzoleni d76ecbc9f6 - in Process require di BeamExec spostato dopo la dichiarazione delle variabili globali
- in BeamExec -> CollectFeatures si salva l'indice della Proc nel vProc
- in FeatureLib aggiunta funzione GetFeatureMaxNotClampableLengths
- correzioni e migliorie GetFeatureMaxNotClampableLengths
2025-01-14 15:17:18 +01:00
luca.mazzoleni cc8410b0c5 - in BeamExec -> CollectFeatures inserito calcolo riduzione lunghezza pinzabile
- in FeatureLib aggiunte funzioni GetFeatureVolume e CalculateFeatureNotClampableLengths
- in STR0005 aggiunta scelta strategie di taglio; al momento non contemplato massimo materiale lama
- aggiunta BLADETOWASTE, solo intestazione
2025-01-10 18:13:39 +01:00
luca.mazzoleni 3835f6f6e0 - in Strategies.ini e BasicCustomerStrategies aggiunta STR0005 2025-01-08 09:15:44 +01:00
luca.mazzoleni cf96eb7bc3 - aggiunta STR0005 - BladeToWaste 2025-01-07 17:30:47 +01:00
luca.mazzoleni 3287420f41 - in FaceData -> GetFacesInfo contemplato il caso in cui arrivi una Proc senza nFct 2025-01-07 15:27:25 +01:00
andrea.villa 3a5cba1c15 In FaceByBlade, il parametro 'FaceToMachine' deve essere una tabella, formattata tipo una Proc. 2025-01-07 12:52:16 +01:00
andrea.villa e443bd5813 - Tutte le librerie 'core' relative alle strategie sono state spostate nella cartella STRATEGYLIBS
- StrategyLib.lua che conteneva solo funzioni per lo split, è stata rinominata in SPLITCUT.lua e sarà relativa solo al taglio di seoparazione
2025-01-07 12:27:31 +01:00
andrea.villa ce7d87a5ac Aggiunta funzione GetAdditionalInfo in FeatureLib per recupero informazioni aggiuntive di feature che non richiedono topologia 2025-01-02 15:55:28 +01:00
andrea.villa 8238767f69 Piccola modifica STR0002 per spostare svuotatura dopo taglio di separazione 2025-01-02 14:51:15 +01:00
luca.mazzoleni ca4141515d - piccole correzioni varie 2024-12-24 11:13:32 +01:00
luca.mazzoleni 6ca555efc8 Merge branch 'SortingMachinings' into develop 2024-12-24 08:45:13 +01:00
luca.mazzoleni b882f23d3e - commenti 2024-12-24 08:44:46 +01:00
luca.mazzoleni 8c39c6a94f - in MachiningLib -> GetSplitMachinings correzione al calcolo FeatureSegment nel caso di lavorazione non spezzata 2024-12-23 18:25:30 +01:00
luca.mazzoleni e126e3f389 - in BeamLib introdotto algoritmo di sorting STABILE (merge sorting)
- piccole correzioni in SLOTBYBLADE e SLOTBYCHAINSAW
2024-12-23 16:11:25 +01:00
luca.mazzoleni 3bce7b5fd6 implementato sorting lavorazioni ma non corretto, serve un algoritmo di STABLE SORTING 2024-12-23 09:08:03 +01:00
luca.mazzoleni 99e0bd27d9 - funzioni di Sorting spostate in MachiningLib
- Sorting di base funzionante
2024-12-19 18:33:39 +01:00
luca.mazzoleni 456d8e903a - in BeamExec completata la funzione PrepareMachiningsForSorting
- in FaceData la lunghezza rispetto a X è ora in valore assoluto
- in MachiningLib -> GetSplitMachinings aggiunta la scrittura del centro della lavorazione
- in STR0003, STR0004, SlotByChainSaw e SlotByBLade nSegment diventa nFeatureSegment per distinguerla da nPartSegment
2024-12-19 15:04:17 +01:00
luca.mazzoleni 14f81da3df - in Process e BeamExec reinserito calcolo parte dopo spostamento pezzo 2024-12-18 12:23:04 +01:00
luca.mazzoleni eb4a5e521f - in BeamExec si evita di ricalcolare senza motivo il box del pezzo
- tutti i riferimenti a PARTS[i].b3Box o Part.b3Solid diventano Part.b3Part
- in BeamExec aggiunte funzioni PrepareMachiningsForSorting e SortMachiningsBySegment, da completare
- in BeamLib aggiunta funzione GetSplittingPoints
- nelle lavorazioni introdotta la variabile sStage che rappresenta la fase di lavoro a cui la lavorazione stessa appartiene (Head, Tail, AfterTail oppure vuota che significa sezione centrale, quella divisa in segments)
- piccole correzioni ad alcuni nomi di variabile
2024-12-18 11:59:08 +01:00
luca.mazzoleni 233a928dcd - in DiceCut modificati i commenti 2024-12-16 13:18:10 +01:00
luca.mazzoleni db88c7bb8d Merge branch 'feature/NewStrategyLib' into develop 2024-12-16 11:19:59 +01:00
luca.mazzoleni 992a115f93 Merge branch 'develop' into feature/NewStrategyLib 2024-12-10 16:14:55 +01:00
luca.mazzoleni 50753dda52 Merge branch 'STR0003_Splitting' into develop 2024-12-06 16:30:29 +01:00
luca.mazzoleni 9fcd805ed5 - in FeatureLib -> GetFeatureSplittingPoints correzioni e migliorie
- in MachiningLib -> GetSplitMachinings correzione all'assegnazione del segmento per gli edge non lavorati completamente
- in STR0003 gestito ordinamento lavorazioni lama + sega a catena
- altre piccole migliorie
2024-12-06 16:29:34 +01:00
luca.mazzoleni eccfb96c22 - in STR0003 aggiunto splitting lavorazioni lama e sega a catena e refactoring
- da testare
2024-12-05 17:54:30 +01:00
andrea.villa cff250ca37 - TAILCUT utilizza nuova libreria
- Prima versione funzionante tagli PRECUT
2024-12-05 08:09:50 +01:00
andrea.villa 7309ebb6a3 - Creazione (vuota) nuova libreria StrategyLib
- SPLITCUT non è più una strategia ma sarà una funzionalità della nuova libreria
- Nuova strategia TAILCUT, corrispettivo del HEADCUT sulla testa
- Alla feature 340 si applica la strategia TAILCUT
2024-12-04 10:52:59 +01:00
andrea.villa c649870518 Piccola modifica Splitcut 2024-12-04 10:18:40 +01:00
andrea.villa 3d8ec03c47 Merge branch 'feature/DiceCut' into develop 2024-12-04 10:17:24 +01:00
andrea.villa 42329d7688 Aggiunta libreria DiceCut. Funzione GetDice uniformata a nuovo standard, funzioni interne non modificate. 2024-12-04 10:17:09 +01:00
luca.mazzoleni a6ddaa8bbd - alcune correzioni nel calcolo approccio retrazione per lavorazioni di coda e split
- in STR0003 aggiunta gestione lavorazioni di coda per sega a catena
2024-12-03 16:47:47 +01:00
luca.mazzoleni bb82dcb724 - in MachiningLib -> StartsLeftSide contemplato ToolInvert
- in SLOTBYBLADE aggiunta gestione lavorazioni di coda
- in STR0003 > lama aggiunta gestione lavorazioni di coda
- in Config STR0003 e STR0004 aggiunto parametro dExtendAfterTail per decidere di quanto estendere una lavorazione oltre la coda
2024-12-03 14:55:46 +01:00
andrea.villa d58be78868 - Prima bozza separazione con doppia lavorazione lama e lama da sotto.
- HEADCUT derivata da SPLITCUT. Da verificare se mantenere separate o fondere in un'unica strategia
2024-12-02 14:46:08 +01:00
luca.mazzoleni 1cb9104404 Merge branch 'MachiningsOnTailManagement' into develop 2024-11-28 18:00:07 +01:00
luca.mazzoleni 19a47115ea - in BeamExec corretto calcolo della distanza dal pezzo successivo in caso di ultimo pezzo per tenere conto di grezzo scaricabile o meno 2024-11-28 17:59:50 +01:00
luca.mazzoleni 6da682dfed - in MachiningLib corretta CanMoveAfterSplit
- in SLOTBYCHAINSAW e STR0004 modifiche alla gestione delle lavorazioni in coda
2024-11-27 11:51:21 +01:00
luca.mazzoleni 08d3f7ff6d aggiunta la gestione delle lavorazioni in coda, per decidere se spostare dopo separazione o accorciarle:
- in MachiningLib aggiunte funzioni StartsLeftSide e CanExtendAfterTail; modificata GetSplitMachinings
- Machining.nPart rinominato nSegment
- in SLOTBYCHAINSAW.Make aggiunta sezione per gestire lavorazioni di coda
-  STR0004 adeguata per passare alla strategia di base le informazioni sulle lavorazioni di coda
2024-11-26 13:33:36 +01:00
luca.mazzoleni 229e98cf9d Merge branch 'NewParametersManagement' into develop 2024-11-22 17:56:01 +01:00
luca.mazzoleni d7096a8a68 - migliorie al tipo di parametro 'combo'
- aggiunto parametro sCanDamageNextPiece
2024-11-22 17:55:32 +01:00
andrea.villa b0f26bdea2 BOZZA sviluppo nuove tipologie di parametri
- tipo di parametro "Combo"
- nuovo campo sNameNge che verrà scritto nelle info nel Processing
2024-11-22 12:56:12 +01:00
luca.mazzoleni 2586407ec9 Merge branch 'STR0004_Splitting' into develop 2024-11-21 18:12:14 +01:00
luca.mazzoleni a34a62d635 Merge remote-tracking branch 'origin/develop' into STR0004_Splitting 2024-11-21 18:07:37 +01:00
luca.mazzoleni 44215b3b4e - in MachiningLib -> GetSplitMachinings correzione a inversione start/end 2024-11-21 18:04:18 +01:00
luca.mazzoleni a2b49fdf3e - in MachiningLib aggiunta la scrittura dello spezzone nella lavorazione
- in STR0004 aggiunto ordinamento lavorazioni
- piccole aggiunte varie
2024-11-21 17:53:24 +01:00
luca.mazzoleni 21b73e0031 - in MachiningLib aggiunta funzione GetSplitMachinings, estrapolata da STR0004 (modificata di conseguenza) 2024-11-20 14:58:04 +01:00
andrea.villa 54c86774b7 - Corretta creazione barra in caso di più pezzi
- Libreria specifica per Log
- Nuovo log feature con tutte le strategie disponibili
- Nel log della matrice rotazioni si indica se la strategia scelta è completa (C), parziale (P) o non applicabile (N)
2024-11-20 14:28:20 +01:00
luca.mazzoleni 80c5a5a393 - piccola correzione in SLOTBYCHAINSAW 2024-11-19 09:21:41 +01:00
luca.mazzoleni 13ae86b6a7 - in STR0004 miglioramenti a spezzatura 2024-11-18 18:29:18 +01:00
luca.mazzoleni 8119643221 Merge branch 'develop' into STR0004_Splitting 2024-11-18 17:32:26 +01:00
luca.mazzoleni 941954825d - in BeamLib aggiunta funzione TableCopyDeep per copiare una tabella mantenendo senza riferimenti le sottotabelle
- in STR0004 primo implemento di spezzatura lavorazioni, da completare
- in SLOTBYCHAINSAW scritti alcuni parametri realtivi al lato nel Machining
2024-11-18 17:32:10 +01:00
andrea.villa 8d1286dd71 Calcolo rotazione scritto in modo più comprensibile 2024-11-18 16:03:53 +01:00
andrea.villa 4abc2c01af Piccola modifica al nome delle variabili 2024-11-18 15:36:11 +01:00
andrea.villa 7e6d8f4172 Corretta gestione rotazione pezzo nel DISP in caso che la soluzione scelta sia una prerotazione 2024-11-18 15:29:32 +01:00
luca.mazzoleni 5aa2b5ac4d Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2024-11-14 10:52:36 +01:00
luca.mazzoleni ae4c3f9156 - in FeatureLib e STR0002 invertito ordine dei punti di spezzatura, ora è da testa a coda 2024-11-14 10:52:32 +01:00
andrea.villa a4f6e10dc3 Merge branch 'CollectBasedOnCombinations' into develop 2024-11-14 10:25:24 +01:00
andrea.villa fc047c2350 Ottimizzazione collect. Si calcola solo se la rotazione è abilitata, in base alle combinazioni disponibili 2024-11-14 10:23:58 +01:00
luca.mazzoleni 28946a0291 - in FaceData, nella trimesh generata TunnelAddedFaces.MiddleFaceTm, aggiunte le facce di contenimento laterali per garantire lati chiusi in svuotatura splittata 2024-11-13 18:42:01 +01:00
luca.mazzoleni 9375cd0868 Merge branch 'GetSplittingPoints' into develop 2024-11-11 14:50:50 +01:00
luca.mazzoleni 8bd772c96d - in STR0002 -> GetSplitSurfaces correzione a taglio superfici 2024-11-11 14:48:18 +01:00
luca.mazzoleni 2fff4438c0 - in STR0002 overlap tra le passate portato a 1/2 MILL_OVERLAP
- in FaceData in ogni Edge si scrive ora la lunghezza proiettata lungo X dLengthOnX
- in FeatureLib aggiunta la funzione MachiningNeedsSplitting per unificare il check di necessità spezzatura
2024-11-11 11:52:21 +01:00
luca.mazzoleni a17c62c15f - GetSplittedSurfaces convertita in GetSplitSurfaces 2024-11-11 08:59:49 +01:00
luca.mazzoleni 20c8518f1d - in STR0002 -> GetSplittedSurfaces aggiunto overlap tra le superfici 2024-11-08 18:32:40 +01:00
luca.mazzoleni 730d37c917 - in STR0002 miglioramenti vari 2024-11-08 18:00:28 +01:00
luca.mazzoleni 184a78d34c - in FeatureLib aggiunta funzione GetFeatureSplittingPoints che restituisce i punti di spezzatura di una feature, estrapolata da STR0002
- in STR0002 aggiunta funzione GetSplittedSurfaces per contemplare nuova funzione di restituzione punti e restituire direttamente le superfici trimmate alla Make
- piccole correzioni varie
2024-11-08 16:37:10 +01:00
luca.mazzoleni a33e794b1e Merge branch 'STR0004_SlotByChainsaw' into develop 2024-11-07 16:54:54 +01:00
luca.mazzoleni f212c0cede Merge branch 'develop' into STR0004_SlotByChainsaw 2024-11-07 16:53:38 +01:00
luca.mazzoleni 38fdaca7bf - FeatureData rinominata FeatureLib
- piccole migliorie stilistiche
2024-11-07 16:53:06 +01:00
andrea.villa 7b580b24bb Merge branch 'MachiningInRotation' into develop 2024-11-06 17:31:58 +01:00
andrea.villa 23bbd938fc Prima versione funzionante scelta soluzioni che contempla le pre-rotazioni 2024-11-06 17:31:38 +01:00
andrea.villa 21dd75b4a6 Migliorata identificazione combinazione disponibile. Ora 3 modi: Basic, NoRotation,Advanced 2024-11-06 12:17:56 +01:00
luca.mazzoleni a8ec76f451 Merge branch 'develop' into STR0004_SlotByChainsaw 2024-11-06 11:33:39 +01:00
luca.mazzoleni 9b5bb25c76 - implementata STR0004, strategia SlotByChainSaw 2024-11-06 11:32:51 +01:00
andrea.villa b9c492fe5a Merge branch 'develop' into MachiningInRotation 2024-11-06 10:12:36 +01:00
andrea.villa fdcb428002 Merge branch 'MachiningInRotation' into develop 2024-11-06 10:11:57 +01:00
andrea.villa 91c883b87c Completata funzione applicazione lavorazione in fase appropriata. MANCA prerotazione 2024-11-06 10:11:40 +01:00
luca.mazzoleni 8e151758b1 - creata STR0004 copiando do STR0003. Da implementare 2024-11-05 18:30:11 +01:00
luca.mazzoleni 1132369f1e - in STR0003 SawPlusChain corretto ordine passate orizzontali lama 2024-11-05 18:09:07 +01:00
luca.mazzoleni b9bb1aefdd - in BeamExec > GetToolsFromDB, in lettura parametri con EgtGetValInNotes, aggiunta 'd' se valori numerici
- in SPLITCUT > GetSplitStrategy gestito caso in cui GetMaxMatReductionBladeCut non è presente in BeamData anche per il Machining[2]
2024-11-05 17:20:44 +01:00
andrea.villa 2b9113347a Prima bozza (non funzionante) applicazione lavorazioni nella relativa rotazione 2024-11-05 16:37:50 +01:00
andrea.villa 7c80c4d3d8 Merge branch 'GetBestCombination' into develop 2024-11-05 13:27:48 +01:00
andrea.villa 69fc865452 Completata funzione scelta miglior combinazione 2024-11-05 13:27:36 +01:00
andrea.villa 88bc848966 Merge branch 'AvailableCombinations' into develop 2024-11-05 12:06:17 +01:00
andrea.villa 81a274563f Completata funzione identificazione combinazioni disponibili in base a configurazione 2024-11-05 12:06:06 +01:00
andrea.villa 32fa372012 Prima bozza scelta combinazioni disponibili in base a configurazione 2024-11-05 09:36:46 +01:00
andrea.villa 21da5f633d - Prima bozza gestione matrice delle rotazioni
- Adeguamento strategia 0002 e SPLITCUT a nuovo metodo gestione matrice
2024-11-04 16:52:42 +01:00
andrea.villa c24fef22a7 Merge branch 'ProcessAgainOnError' into develop 2024-10-09 13:16:22 +02:00
andrea.villa 35e8ef2482 - ProcessFeature divisa in GetProcessings(collect e raccolta strategie) e ProcessMachinings (scelta strategia migliore e applicazione lavorazioni)
- in ProcessMachinings predisposto ciclo per ricalcolare in caso di errore su Apply
- Nuova lista globale PROCESSINGS
- Calcolo tempi commentato, da riposizionare in base alle misure che si vogliono effettuare
- Predisposizione funzione per calcolo della matrice delle combinazioni (completamente da fare)
2024-10-09 13:16:11 +02:00
luca.mazzoleni 23d5f82403 Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2024-10-08 16:15:49 +02:00
luca.mazzoleni ec734ca99d - in MachiningLib aggiunta scrittura cloni geometria
- in STR0003 sistemati commenti
2024-10-08 16:11:54 +02:00
andrea.villa 34c5ecc5ec Merge branch 'SplitCut' into develop 2024-10-08 16:09:18 +02:00
andrea.villa 362f3fd2b0 - Prima implementazione creazioni fasi
- Piccole migliorie varie
- Corretta lettura info utensile profilato
- Su Proc, aggiunte alcune note pezzo
2024-08-09 16:46:51 +02:00
andrea.villa 9acd52ea10 - Prima versione strategia standard SPLITCUT e aggiunta chiamata della strategia
- Prima versione strategia core FACEBYBLADE
- Aggiunte altre UserNotes e corretto append se più note
2024-08-09 09:46:01 +02:00
30 changed files with 5233 additions and 1177 deletions
+83 -73
View File
@@ -13,23 +13,43 @@ local BeamData = require( 'BeamData')
local ID = require( 'Identity')
-- TODO tabella da compleatare man mano che si inseriscono le varie strategie
-- ESEMPIO SCRITTURA TABELLA CON STRATEGIE DISPONIBILI
---------------------------------------------------------------------
-- Feature : Cut
-- if ID.TipoFeature( Proc) then
-- if Proc.Topology.sName == 'QQQQQQQQQ' then
-- Strategies = {
-- { sStrategyId = 'STR9999',
-- Parameters = {
-- { sName = 'Val_1', sValue = '15', sType = 'd'},
-- { sName = 'Val_2', sValue = 'false', sType = 'b'}
-- }
-- }
-- { sStrategyId = 'STR9998'}
-- }
-- end
-- end
----------------------------------------------------------------------------------
-- *** EGALWARE ***
----------------------------------------------------------------------------------
local function GetStrategies_Egalware( Proc)
local Strategies = {}
-- TODO tabella da compleatare man mano che si inseriscono le varie strategie
---------------------------------------------------------------------
-- Feature : Cut
if ID.IsHeadCut( Proc) then
Strategies = { { sStrategyId = 'HEADCUT'}}
---------------------------------------------------------------------
-- Feature : Cut
elseif ID.IsSplitCut( Proc) then
elseif ID.IsTailCut( Proc) then
Strategies = { { sStrategyId = 'TAILCUT'}}
---------------------------------------------------------------------
-- Feature : Cut
elseif ID.IsCut( Proc) then
Strategies = { { sStrategyId = 'STR0005'}}
---------------------------------------------------------------------
-- Feature : Longitudinal Cut
elseif ID.IsLongitudinalCut( Proc) then
@@ -46,13 +66,13 @@ local function GetStrategies_Egalware( Proc)
-- Feature : Slot
elseif ID.IsSlot( Proc) then
if Proc.Topology.sName == 'Pocket-5-Blind' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-4-Blind' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-3-Through' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Tunnel-4-Through' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-3-Blind' then
Strategies = { { sStrategyId = 'STR0002'}}
elseif Proc.Topology.sName == 'Rabbet-2-Through' then
@@ -62,13 +82,13 @@ local function GetStrategies_Egalware( Proc)
-- Feature : Front Slot
elseif ID.IsFrontSlot( Proc) then
if Proc.Topology.sName == 'Pocket-5-Blind' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-4-Blind' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-3-Through' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Tunnel-4-Through' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-3-Blind' then
Strategies = { { sStrategyId = 'STR0002'}}
elseif Proc.Topology.sName == 'Rabbet-2-Through' then
@@ -84,13 +104,13 @@ local function GetStrategies_Egalware( Proc)
-- Feature : Ridge Lap
elseif ID.IsRidgeLap( Proc) then
if Proc.Topology.sName == 'Pocket-5-Blind' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-4-Blind' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-3-Through' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Tunnel-4-Through' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-3-Blind' then
Strategies = { { sStrategyId = 'STR0002'}}
elseif Proc.Topology.sName == 'Rabbet-2-Through' then
@@ -100,13 +120,13 @@ local function GetStrategies_Egalware( Proc)
-- Feature : Lap Joint
elseif ID.IsLapJoint( Proc) then
if Proc.Topology.sName == 'Pocket-5-Blind' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-4-Blind' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-3-Through' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Tunnel-4-Through' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-3-Blind' then
Strategies = { { sStrategyId = 'STR0002'}}
elseif Proc.Topology.sName == 'Rabbet-2-Through' then
@@ -116,13 +136,13 @@ local function GetStrategies_Egalware( Proc)
-- Feature : Notch/Rabbet
elseif ID.IsNotchRabbet( Proc) then
if Proc.Topology.sName == 'Pocket-5-Blind' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-4-Blind' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-3-Through' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Tunnel-4-Through' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-3-Blind' then
Strategies = { { sStrategyId = 'STR0002'}}
elseif Proc.Topology.sName == 'Rabbet-2-Through' then
@@ -135,13 +155,13 @@ local function GetStrategies_Egalware( Proc)
-- Feature : Notch
elseif ID.IsNotch( Proc) then
if Proc.Topology.sName == 'Pocket-5-Blind' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-4-Blind' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-3-Through' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Tunnel-4-Through' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-3-Blind' then
Strategies = { { sStrategyId = 'STR0002'}}
elseif Proc.Topology.sName == 'Rabbet-2-Through' then
@@ -163,13 +183,13 @@ local function GetStrategies_Egalware( Proc)
-- Feature : Pocket
elseif ID.IsPocket( Proc) then
if Proc.Topology.sName == 'Pocket-5-Blind' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-4-Blind' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-3-Through' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Tunnel-4-Through' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-3-Blind' then
Strategies = { { sStrategyId = 'STR0002'}}
elseif Proc.Topology.sName == 'Rabbet-2-Through' then
@@ -277,24 +297,14 @@ end
local function GetStrategies_Essetre( Proc)
local Strategies = {}
-- TODO tabella da compleatare man mano che si inseriscono le varie strategie
---------------------------------------------------------------------
-- Feature : Cut
if ID.IsHeadCut( Proc) then -- TODO TOGLIERE STRATEGIA. Inserita solo per mostrare come devono essere scritti i dati
if Proc.Topology.sName == 'QQQQQQQQQ' then
Strategies = {
{ sStrategyId = 'STR9999',
Parameters = {
{ sName = 'Step', sValue = '15', sType = 'd'},
{ sName = 'AntiSplint', sValue = 'false', sType = 'b'}
}
}
}
end
if ID.IsHeadCut( Proc) then
Strategies = { { sStrategyId = 'HEADCUT'}}
---------------------------------------------------------------------
-- Feature : Cut
elseif ID.IsSplitCut( Proc) then
elseif ID.IsTailCut( Proc) then
Strategies = { { sStrategyId = 'TAILCUT'}}
---------------------------------------------------------------------
-- Feature : Cut
elseif ID.IsCut( Proc) then
@@ -314,13 +324,13 @@ local function GetStrategies_Essetre( Proc)
-- Feature : Slot
elseif ID.IsSlot( Proc) then
if Proc.Topology.sName == 'Pocket-5-Blind' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-4-Blind' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-3-Through' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Tunnel-4-Through' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-3-Blind' then
Strategies = { { sStrategyId = 'STR0002'}}
elseif Proc.Topology.sName == 'Rabbet-2-Through' then
@@ -330,13 +340,13 @@ local function GetStrategies_Essetre( Proc)
-- Feature : Front Slot
elseif ID.IsFrontSlot( Proc) then
if Proc.Topology.sName == 'Pocket-5-Blind' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-4-Blind' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-3-Through' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Tunnel-4-Through' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-3-Blind' then
Strategies = { { sStrategyId = 'STR0002'}}
elseif Proc.Topology.sName == 'Rabbet-2-Through' then
@@ -352,13 +362,13 @@ local function GetStrategies_Essetre( Proc)
-- Feature : Ridge Lap
elseif ID.IsRidgeLap( Proc) then
if Proc.Topology.sName == 'Pocket-5-Blind' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-4-Blind' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-3-Through' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Tunnel-4-Through' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-3-Blind' then
Strategies = { { sStrategyId = 'STR0002'}}
elseif Proc.Topology.sName == 'Rabbet-2-Through' then
@@ -368,13 +378,13 @@ local function GetStrategies_Essetre( Proc)
-- Feature : Lap Joint
elseif ID.IsLapJoint( Proc) then
if Proc.Topology.sName == 'Pocket-5-Blind' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-4-Blind' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-3-Through' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Tunnel-4-Through' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-3-Blind' then
Strategies = { { sStrategyId = 'STR0002'}}
elseif Proc.Topology.sName == 'Rabbet-2-Through' then
@@ -384,13 +394,13 @@ local function GetStrategies_Essetre( Proc)
-- Feature : Notch/Rabbet
elseif ID.IsNotchRabbet( Proc) then
if Proc.Topology.sName == 'Pocket-5-Blind' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-4-Blind' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-3-Through' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Tunnel-4-Through' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-3-Blind' then
Strategies = { { sStrategyId = 'STR0002'}}
elseif Proc.Topology.sName == 'Rabbet-2-Through' then
@@ -403,13 +413,13 @@ local function GetStrategies_Essetre( Proc)
-- Feature : Notch
elseif ID.IsNotch( Proc) then
if Proc.Topology.sName == 'Pocket-5-Blind' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-4-Blind' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-3-Through' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Tunnel-4-Through' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-3-Blind' then
Strategies = { { sStrategyId = 'STR0002'}}
elseif Proc.Topology.sName == 'Rabbet-2-Through' then
@@ -431,13 +441,13 @@ local function GetStrategies_Essetre( Proc)
-- Feature : Pocket
elseif ID.IsPocket( Proc) then
if Proc.Topology.sName == 'Pocket-5-Blind' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-4-Blind' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-3-Through' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Tunnel-4-Through' then
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}}
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
elseif Proc.Topology.sName == 'Groove-3-Blind' then
Strategies = { { sStrategyId = 'STR0002'}}
elseif Proc.Topology.sName == 'Rabbet-2-Through' then
+677 -192
View File
File diff suppressed because it is too large Load Diff
+286 -10
View File
@@ -91,9 +91,50 @@ function BeamLib.AddPartEndFace( PartId, b3Solid)
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.AddPhaseWithRawParts( Part, OriXR, PosXR, dDeltaSucc)
function BeamLib.GetPartSplittingPoints( Part, OptionalParameters)
local PartSplittingPoints = {}
local dPartLength = Part.b3Part:getDimX()
-- parametri opzionali
if not OptionalParameters then
OptionalParameters = {}
end
local dMaxSegmentLength = OptionalParameters.dMaxSegmentLength or BeamData.LONGCUT_MAXLEN
local dMaxSegmentLengthOnEdges = OptionalParameters.dMaxSegmentLengthOnEdges or 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( nRawId, OriXR, PosXR, dDeltaSucc)
EgtAddPhase()
local nRawId = Part.idRaw
local dRawMove = 0
while nRawId do
EgtKeepRawPart( nRawId)
@@ -105,6 +146,49 @@ function BeamLib.AddPhaseWithRawParts( Part, OriXR, PosXR, dDeltaSucc)
end
end
-------------------------------------------------------------------------------------------------------------
--- funzione che ruota il pezzo, da lanciare per creare la disposizione corretta
function BeamLib.RotatePart( Part, nPosition)
-- primo posizionamento
if nPosition == 1 then
; -- il pezzo è già in posizione
-- rotazione 90°
elseif nPosition == 2 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
EgtRotateRawPart( nRId, X_AX(), EgtIf( BeamData.RIGHT_LOAD, -90, 90))
if not bPreMove then EgtMoveRawPart( nRId, vtMove) end
nRId = EgtGetNextRawPart( nRId)
end
-- rotazione 180°
elseif nPosition == 3 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 nPosition == 4 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
EgtRotateRawPart( nRId, X_AX(), EgtIf( BeamData.RIGHT_LOAD, 90, -90))
if not bPreMove then EgtMoveRawPart( nRId, vtMove) end
nRId = EgtGetNextRawPart( nRId)
end
end
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.CreateOrEmptyAddGroup( PartId)
-- recupero i dati del gruppo aggiuntivo
@@ -151,22 +235,22 @@ end
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.b3Solid:getMax():getZ() - 500 * GEO.EPS_SMALL 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.b3Solid:getMin():getZ() + 500 * GEO.EPS_SMALL then
if Proc.b3Box:getMin():getZ() < Part.b3Part:getMin():getZ() + 500 * GEO.EPS_SMALL then
vtFacesAffected.bBottom = true
end
if Proc.b3Box:getMin():getY() < Part.b3Solid:getMin():getY() + 500 * GEO.EPS_SMALL then
if Proc.b3Box:getMin():getY() < Part.b3Part:getMin():getY() + 500 * GEO.EPS_SMALL then
vtFacesAffected.bFront = true
end
if Proc.b3Box:getMax():getY() > Part.b3Solid:getMax():getY() - 500 * GEO.EPS_SMALL then
if Proc.b3Box:getMax():getY() > Part.b3Part:getMax():getY() - 500 * GEO.EPS_SMALL then
vtFacesAffected.bBack = true
end
if Proc.b3Box:getMin():getX() < Part.b3Solid:getMin():getX() + 500 * GEO.EPS_SMALL then
if Proc.b3Box:getMin():getX() < Part.b3Part:getMin():getX() + 500 * GEO.EPS_SMALL then
vtFacesAffected.bLeft = true
end
if Proc.b3Box:getMax():getX() > Part.b3Solid:getMax():getX() - 500 * GEO.EPS_SMALL then
if Proc.b3Box:getMax():getX() > Part.b3Part:getMax():getX() - 500 * GEO.EPS_SMALL then
vtFacesAffected.bRight = true
end
end
@@ -277,6 +361,66 @@ function BeamLib.Is3EdgesApprox( Proc, idFace, nAddGrpId)
return bResult
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.GetNzLimDownUp( b3Raw, vtN, vtOrtho)
if BeamData.GetNzLimDownUp then
return BeamData.GetNzLimDownUp( b3Raw, vtN, vtOrtho)
elseif BeamData.C_SIMM then
return -0.484
elseif BeamData.TURN then
return -2
else
if vtOrtho and vtOrtho:getZ() > 0.35 then
-- N_HorAng < 15° or N_HorAng > 55°
if vtN and ( abs( vtN:getY()) < 0.259 or abs( vtN:getY()) > 0.819) then
return -0.708
-- N_HorAng > 50°
elseif vtN and abs( vtN:getY()) > 0.766 then
return -0.383
else
return EgtIf( b3Raw:getDimZ() < BeamData.MIN_DIM_HBEAM, -0.609, -0.383)
end
else
-- N_HorAng > 60°
if vtN and ( abs( vtN:getY()) > 0.866) then
return -0.708
else
if b3Raw:getDimZ() < 120 then
return -0.708
elseif b3Raw:getDimZ() < 200 then
-- N_HorAng < 15° or N_HorAng > 55°
if vtN and ( abs( vtN:getY()) < 0.259 or abs( vtN:getY()) > 0.819) then
return -0.5
else
return -0.383
end
elseif b3Raw:getDimZ() < 300 then
-- N_HorAng < 10°
if vtN and ( abs( vtN:getY()) < 0.174) then
return -0.5
else
return -0.259
end
elseif b3Raw:getDimZ() < BeamData.MIN_DIM_HBEAM then
-- N_HorAng < 10°
if vtN and ( abs( vtN:getY()) < 0.174) then
return -0.342
else
return -0.259
end
else
-- N_HorAng < 10°
if vtN and ( abs( vtN:getY()) < 0.174) then
return -0.383
else
return -0.174
end
end
end
end
end
end
-------------------------------------------------------------------------------------------------------------
-- sovrascrivo i parametri personalizzati salvati su Proc a quelli di default dalla strategia
-- N.B. : I parametri personalizzati non più presenti tra i default della strategia, verranno ignorati. Quelli extra avranno valore di default
@@ -302,9 +446,9 @@ function BeamLib.LoadCustomParametersInStrategy( CustomParameters)
for i=1, #CustomParameters do
if CustomParameters[i].sType == 'b' then
Parameters[CustomParameters[i].sName] = CustomParameters[i].sValue == 'true'
elseif CustomParameters[i].Type == 'd' then
elseif CustomParameters[i].sType == 'd' then
Parameters[CustomParameters[i].sName] = tonumber( CustomParameters[i].sValue)
else -- CustomParameters.Type == 's'
else --CustomParameters[i].sType == 's' or CustomParameters[i].sType == 'combo'
Parameters[CustomParameters[i].sName] = CustomParameters[i].sValue
end
end
@@ -351,5 +495,137 @@ function BeamLib.GetBlockedAxis( nToolIndex, sBlockedAxis, b3Raw, vtTool, vtOut)
return ''
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)
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
---------------------------------------------------------------------
-- 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
+676
View File
@@ -0,0 +1,676 @@
-- DiceCut.lua by Egaltech s.r.l. 2024/01/23
-- Gestione dei piano paralleli nei tagli lunghi: equidistanziamento dei piani paralleli
-- Tabella per definizione modulo
local DiceCut = {}
-- Include
require( 'EgtBase')
local BeamLib = require( 'BeamLib')
EgtOutLog( ' DiceCut started', 1)
-- Dati
local BeamData = require( 'BeamData')
----------------------------------------------------------------------------------------------------------------------------------------------------
-- creo i piani paralleli
-- GetParallelPlanes: restituisce un vettore con gli indici delle superfici
-- nAddGrpId: il layer
-- b3BoxToDicing: il grezzo della barra
-- ptC: il punto centrale del piano della feature
-- vtN: il versore normale del piano della feature
-- nCopyPlane: 0 => genera una copia del piano passato, 1=> non genera una copia del piano passato
-- dOffset: offset dei piani paralleli
-- nStep: numero massimo di step
-- Color: colre del fascio di piani
-- dTolerance*: distanza tra i piani paralleli e i piani di taglio (se non esistono altre superfici può essere omesso)
-- bNoTolOnFirstCut*: elimina la tolleranza per il primo piano del fascio (se non esistono altre superfici può essere omesso)
-- ptCCut*: il punto centrale della superfice limitante (se non esistono altre superfici può essere omesso)
-- vtNCut*: il punto centrale della superfice limitante (se non esistono altre superfici può essere omesso)
-- ptCCut1*: il punto centrale della superfice limitante (se non esistono altre superfici può essere omesso)
-- vtNCut1*: il punto centrale della superfice limitante (se non esistono altre superfici può essere omesso)
local function GetParallelPlanes( nAddGrpId, b3BoxToDicing, ptC, vtN, nCopyPlane, dOffset, nStep, Color, dTolerance, bNoTolOnFirstCut, ptCCut, vtNCut, ptCCut1, vtNCut1 )
local ptMyCCut
local AreaMin = 5*5
if ptCCut and vtNCut then
if dTolerance then
ptMyCCut = Point3d( ptCCut + dTolerance * vtNCut)
end
ptMyCCut = Point3d( ptCCut)
end
local ptMyCCut1
if ptCCut1 and vtNCut1 then
ptMyCCut1 = Point3d( ptCCut1 + 0 * vtNCut1)
end
local TabellaTmSurfParallel = {}
local i = nCopyPlane
while i < nStep do
local SurfId = EgtSurfTmPlaneInBBox( nAddGrpId, ptC + ( i * dOffset) * vtN, vtN, b3BoxToDicing, GDB_RT.GLOB)
local nFacet = EgtSurfTmFacetCount( SurfId or GDB_ID.NULL)
if nFacet == 0 then
-- se sono al primo taglio do una possibilità in più di girare
if i > nCopyPlane then
break
end
end
if nFacet > 0 and vtNCut and ptMyCCut and EgtSurfArea(SurfId) > AreaMin then
if i == nCopyPlane and bNoTolOnFirstCut then
EgtCutSurfTmPlane( SurfId, ptCCut, -vtNCut, false, GDB_RT.GLOB)
else
EgtCutSurfTmPlane( SurfId, ptMyCCut, -vtNCut, false, GDB_RT.GLOB)
end
nFacet = EgtSurfTmFacetCount( SurfId)
end
if nFacet > 0 and vtNCut1 and ptMyCCut1 and EgtSurfArea(SurfId) > AreaMin then
if i == nCopyPlane and bNoTolOnFirstCut then
EgtCutSurfTmPlane( SurfId, ptCCut1, -vtNCut1, false, GDB_RT.GLOB)
else
EgtCutSurfTmPlane( SurfId, ptMyCCut1, -vtNCut1, false, GDB_RT.GLOB)
end
nFacet = EgtSurfTmFacetCount( SurfId)
end
if nFacet > 0 and EgtSurfArea(SurfId) > AreaMin then
table.insert( TabellaTmSurfParallel, SurfId)
EgtSetColor( SurfId, Color)
else
EgtErase( SurfId)
end
if dOffset == 0 then
break
end
i = i + 1
end
return TabellaTmSurfParallel
end
----------------------------------------------------------------------------------------------------------------------------------------------------
-- GetOrderedCutTable:
-- nAddGrpId: il layer
-- TabParallelPlanes: tabella delle superfici dei piani paralleli
-- TabOrtoPlanes: tabella delle superfici dei piani ortogonali
-- stampo l'ordine dei piani di taglio (prima tagli ortogonali piu' esterni poi taglio parallelo collettivo)
local function GetOrderedCutTable( nAddGrpId, TabParallelPlanes, TabOrtoPlanes)
local StepParallel = #TabParallelPlanes
local StepOrto = #TabOrtoPlanes
local TabellaOrderParallelCut1 = {}
for IndexTmP=1, StepParallel do
TabellaOrderParallelCut1[IndexTmP] = {}
for IndexOrto=1, StepOrto do
local ptOrtoN, vtNOrtoN = EgtSurfTmFacetCenter( TabOrtoPlanes[IndexOrto ], 0, GDB_ID.ROOT)
local Copy1Id = EgtCopySurfTmFacet( TabParallelPlanes[IndexTmP], 0, nAddGrpId)
local Copy2Id = EgtCopySurfTmFacet( TabParallelPlanes[IndexTmP], 0, nAddGrpId)
if Copy1Id and ptOrtoN then
EgtCutSurfTmPlane( Copy1Id, ptOrtoN, -vtNOrtoN, false, GDB_RT.GLOB)
EgtCutSurfTmPlane( Copy2Id, ptOrtoN, vtNOrtoN, false, GDB_RT.GLOB)
local nFacet1 = EgtSurfTmFacetCount( Copy1Id)
local nFacet2 = EgtSurfTmFacetCount( Copy2Id)
if nFacet1 < 1 then
EgtErase( Copy1Id)
EgtErase( Copy2Id)
EgtCutSurfTmPlane( TabParallelPlanes[IndexTmP], ptOrtoN, vtNOrtoN, false, GDB_RT.GLOB)
elseif nFacet2 < 1 then
EgtErase( Copy1Id)
EgtErase( Copy2Id)
break
else
table.insert( TabellaOrderParallelCut1[IndexTmP], Copy1Id)
EgtErase( Copy2Id)
EgtCutSurfTmPlane( TabParallelPlanes[IndexTmP], ptOrtoN, vtNOrtoN, false, GDB_RT.GLOB)
end
end
end
table.insert(TabellaOrderParallelCut1[IndexTmP], TabParallelPlanes[IndexTmP])
end
return TabellaOrderParallelCut1
end
----------------------------------------------------------------------------------------------------------------------------------------------------
-- GetOrtoCutCenter:
-- idFacet: l'id della faccia
-- ptC: il punto centrale della faccia
-- vtN: il versore normale della faccia
-- vtO: il versore dei piani ortogonali
-- dOffsetEff: offset della distanza dal punto centrale
-- Verifica se l'asse X del box costruito sopra la superficie è più grande di un certo offset
local function GetOrtoCutCenter( FacetId, ptC, vtN, vtO, dOffsetEff, dNzLimDwnUp)
local FrameLocal = Frame3d( EgtSurfTmFacetCenter( FacetId, 0, GDB_ID.ROOT))
EgtSetGridFrame(FrameLocal)
local IdAuxLocal = EgtGroup(EgtGetParent( FacetId), FrameLocal)
EgtSetName( IdAuxLocal, "AuxLocal")
local BoxLocal = EgtGetBBoxRef( FacetId, GDB_BB.STANDARD, FrameLocal)
local ptS = EgtGP( EgtSurfTmBBox( IdAuxLocal, BoxLocal, GDB_RT.GRID), GDB_ID.ROOT)
EgtErase( IdAuxLocal)
EgtSetGridFrame(Frame3d())
-- riferimento intrinseco
local asseX = Vector3d( vtO)
local asseY = vtN ^ asseX
local Frame = Frame3d( ptC, ptC + asseX, ptC + asseY)
-- ingombro della faccia secondo questo riferimento
local Box = EgtGetBBoxRef( FacetId, GDB_BB.STANDARD, Frame)
local dLen = Box:getDimX()
local dWidth = Box:getDimY()
-- se faccia non troppo lunga, con un lato piccolo e non diretta troppo verso il basso, non servono dice
local dMaxLen = BeamData.MAX_LEN_DICE or 600
if dLen < dMaxLen and dWidth < dMaxLen and
( dLen < dOffsetEff + 1.0 or dWidth < dOffsetEff + 1.0) and vtN:getZ() > dNzLimDwnUp then
return nil, nil, nil
end
local N = ceil( dLen / dOffsetEff)
local dOffsetRel = ( dLen / N) + 10 * GEO.EPS_SMALL
local dCopyPlane
local dCenOffs = ( Box:getMax():getX() + Box:getMin():getX()) / 2
if dLen <= dOffsetRel then
dCopyPlane = 1
elseif dLen <= 2 * dOffsetRel then
dOffsetRel = dOffsetEff
dCopyPlane = 0
else
if N % 2 == 0 then
dCopyPlane = 0
elseif N % 2 == 1 then
dCopyPlane = 0.5
end
end
return dOffsetRel, dCopyPlane, dCenOffs, ptS
end
----------------------------------------------------------------------------------------------------------------------------------------------------
-- TableMesh:
-- TableOrto: tabella delle superfici dei piani ortogonali
-- TableParallel: tabella delle superfici dei piani paralleli
-- Forma una tabella unica delle superfici di taglio inserendo strati di tagli ortogonali alternati da strati di taglio parallelo
local function TableMesh( TableOrto, TableParallel)
local TableUnited = {}
for i=1, #TableOrto do
table.insert( TableUnited, TableOrto[i])
table.insert( TableUnited, TableParallel[i])
end
return TableUnited
end
----------------------------------------------------------------------------------------------------------------------------------------------------
-- FindValue:
-- tab: tabella da scansionare
-- val: valore da cercare
-- Verifica se tab contiene val, a supporto della funzione SortOrtoCutsByNormalMethod
local function FindValue( tab, val)
for index, value in ipairs( tab) do
if value == val then
return true
end
end
return false
end
----------------------------------------------------------------------------------------------------------------------------------------------------
-- SortOrtoCutsByNormalMethod:
-- TabParallelPlanes: tabella delle superfici dei piani paralleli
-- TabOrtoPlanes: tabella delle superfici dei piani ortogonali
-- stampo l'ordine dei piani di taglio sfruttando il prodotto dei versori normali (prima tagli ortogonali piu' esterni poi taglio parallelo collettivo)
local function SortOrtoCutsByNormalMethod( TabParallelPlanes, TabOrtoPlanes)
-- tabella dei tagli ordinati
local TabOrderOrtoCut = {}
-- tabella ausiliaria dei dati inseriti nell'ordine
local TabAux = {}
-- ciclo di ordinamento
local StepParallel = #TabParallelPlanes
local StepOrto = #TabOrtoPlanes
for IndexTmP=1, StepParallel do
TabOrderOrtoCut[IndexTmP] = {}
local ptParalN, vtNParalN = EgtSurfTmFacetCenter( TabParallelPlanes[IndexTmP][1], 0, GDB_ID.ROOT)
for IndexOrto=1, StepOrto do
for i=1, #TabOrtoPlanes[IndexOrto] do
-- identificativo del taglio
local OrtoPlaneId = TabOrtoPlanes[IndexOrto][i]
-- controlla che l'elemento da valutare non sia gia' stato inserito nella tabella
if not FindValue( TabAux, OrtoPlaneId) then
local ptOrtoN, vtNOrtoN = EgtSurfTmFacetCenter( OrtoPlaneId, 0, GDB_ID.ROOT)
local scalarProduct = ( ptOrtoN - ptParalN) * vtNParalN
if scalarProduct > 0 then
table.insert( TabOrderOrtoCut[IndexTmP], OrtoPlaneId)
table.insert( TabAux, OrtoPlaneId)
end
end
end
end
end
-- cancello dal DB geometrico i tagli non inseriti
for IndexOrto=1, StepOrto do
for i=1, #TabOrtoPlanes[IndexOrto] do
-- identificativo del taglio
local OrtoPlaneId = TabOrtoPlanes[IndexOrto][i]
-- ricerco il taglio tra gli inseriti
if not FindValue( TabAux, OrtoPlaneId) then
EgtErase( OrtoPlaneId)
end
end
end
return TabOrderOrtoCut
end
----------------------------------------------------------------------------------------------------------------------------------------------------
-- VerifyFirstOrthoCut :
-- CutTable: tabella dei tagli
-- OffsetP: offset della distanza dal punto centrale
-- b3BoxToDicing: il grezzo della barra
-- Verifica se l'asse X del box costruito sopra le 2 facce è più piccolo di un certo offset e quindi la faccia O è superflua
local function VerifyFirstOrthoCut( CutTable, OffsetP, b3BoxToDicing, dNzLimDwnUp)
if not CutTable[1] or not CutTable[2] then return end
local CutOId = CutTable[1][1]
local Cut1Id = CutTable[2][1]
local Cut2Id = CutTable[2][2]
if CutOId and Cut1Id and Cut2Id then
-- centri e normali delle due semifacce
local ptC1, vtN1 = EgtSurfTmFacetCenter( Cut1Id, 0, GDB_ID.ROOT)
local ptC2, vtN2 = EgtSurfTmFacetCenter( Cut2Id, 0, GDB_ID.ROOT)
-- normale alla faccia ortogonale
local _, vtO = EgtSurfTmFacetCenter( CutOId, 0, GDB_ID.ROOT)
vtO = vtO - vtO * vtN1 * vtN1 ; vtO:normalize()
local dMaxElev = EgtSurfTmFacetElevationInBBox( CutOId, 0, b3BoxToDicing, true, GDB_ID.ROOT)
-- calcolo lunghezza prima semi-faccia
local asseX1 = vtO
local asseY1 = vtN1 ^ asseX1
local Frame1 = Frame3d( ptC1, ptC1+asseX1, ptC1+asseY1)
local Box1 = EgtGetBBoxRef( Cut1Id, GDB_BB.STANDARD, Frame1)
local x1 = Box1:getDimX()
-- prendo il massimo tra la lugnhezza della faccia parallela e l'elevazione della corrispondente ortogonale
x1 = max( x1, dMaxElev)
-- calcolo lunghezza seconda semi-faccia
local asseX2 = vtO
local asseY2 = vtN2 ^ asseX2
local Frame2 = Frame3d( ptC2, ptC2+asseX2, ptC2+asseY2)
local Box2 = EgtGetBBoxRef( Cut2Id, GDB_BB.STANDARD, Frame2)
local x2 = Box2:getDimX()
-- lunghezza totale faccia
local dLongSize = x1 + x2
-- se faccia piccola e non orientata verso il basso, elimino ortogonale e unisco le due parti
if dLongSize <= OffsetP + 1.0 and vtN1:getZ() > dNzLimDwnUp then
local nAddGrpId = EgtGetParent( Cut1Id)
local SurfId = EgtSurfTmBySewing( nAddGrpId, { Cut1Id, Cut2Id})
EgtSetColor( SurfId, Color3d( FUCHSIA(), 60))
EgtErase( CutOId)
table.remove( CutTable[1], 1)
table.remove( CutTable[2], 1)
table.remove( CutTable[2], 1)
table.insert( CutTable[2], 1, SurfId)
end
end
end
----------------------------------------------------------------------------------------------------------------------------------------------------
-- ricavo i vertici del box
local function CalcolaPuntiEstremiBox( b3BoxToDicing)
local ptMin = b3BoxToDicing:getMin()
local ptMax = b3BoxToDicing:getMax()
local TBoxPoint = {}
table.insert( TBoxPoint, { P = Point3d( ptMin:getX(), ptMin:getY(), ptMin:getZ()), On = true})
table.insert( TBoxPoint, { P = Point3d( ptMax:getX(), ptMin:getY(), ptMin:getZ()), On = true})
table.insert( TBoxPoint, { P = Point3d( ptMin:getX(), ptMax:getY(), ptMin:getZ()), On = true})
table.insert( TBoxPoint, { P = Point3d( ptMax:getX(), ptMax:getY(), ptMin:getZ()), On = true})
table.insert( TBoxPoint, { P = Point3d( ptMin:getX(), ptMin:getY(), ptMax:getZ()), On = true})
table.insert( TBoxPoint, { P = Point3d( ptMax:getX(), ptMin:getY(), ptMax:getZ()), On = true})
table.insert( TBoxPoint, { P = Point3d( ptMin:getX(), ptMax:getY(), ptMax:getZ()), On = true})
table.insert( TBoxPoint, { P = Point3d( ptMax:getX(), ptMax:getY(), ptMax:getZ()), On = true})
return TBoxPoint
end
----------------------------------------------------------------------------------------------------------------------------------------------------
-- restituisce i punti che devono essere presi in considerazione per la costruzione del BoundingBox
local function VerificaEstremiGrezzo( ptC, vtN, TPoint)
for i = 1, #TPoint do
if ( TPoint[i].P - ptC) * vtN < 0 then
TPoint[i].On = false
end
end
return TPoint
end
----------------------------------------------------------------------------------------------------------------------------------------------------
-- ricavo l'altezza del BoundingBox assegnati gli estremi del grezzo e la feature
-- le funzioni commentate permettono di vedere la creazione di BoundingBox
local function DistanzaMassima( nAddGrpId, ptC1, vtN1, ptC2, vtN2, b3BoxToDicing, TPoint)
-- calcolo il riferimento nel piano 1
local Frame1 = Frame3d( ptC1, vtN1)
-- determino l'ingombro in questo riferimento della parte di trave compresa nel o nei piani
local BB1 = BBox3d()
-- punti di vertice della trave compresi
for i = 1, #TPoint do
if TPoint[i].On then
local ptP = Point3d( TPoint[i].P)
ptP:toLoc( Frame1)
BB1:Add( ptP)
end
end
-- eventuale altra faccia
if ptC2 and vtN2 then
local IdAux = EgtGroup( nAddGrpId)
local IdSurf2 = EgtSurfTmPlaneInBBox( IdAux, ptC2, vtN2, b3BoxToDicing, GDB_RT.GLOB)
EgtCutSurfTmPlane( IdSurf2, ptC1, -vtN1, false, GDB_RT.GLOB)
if IdSurf2 then
local BB2 = EgtGetBBoxRef( IdSurf2, GDB_BB.STANDARD, Frame1)
BB1:Add( BB2)
end
EgtErase( IdAux)
end
if not BB1:isEmpty() then
return ( BB1:getMax():getZ() + 0.1)
end
return 0
end
----------------------------------------------------------------------------------------------------------------------------------------------------
-- DiceCut.GetDice :
-- nParent: il layer
-- BBoxRawPart: il grezzo della barra
-- ptCPlanes: il punto centrale del piano della feature
-- vtNPlanes: il versore normale del piano della feature
-- bGetOrtoPlanes*: se voglio calcolare i piani ortogonali al piano passato (se non esistono altre superfici può essere omesso)
-- ptCBond*: il punto centrale della superfice limitante (se non esistono altre superfici può essere omesso)
-- vtNBond*: il versore normale della superfice limitante (se non esistono altre superfici può essere omesso)
-- dOrthoMaxDim : massima profondità taglio se faccia singola perpendicolare facce laterali trave
-- dCustMaxDimDice: dimensione massima customizzata, sostituisce il parametro BeamData.MAX_DIM_DICE (se negativa qualunque, se positiva deve stare nel MAX)
-- bDownHead : taglio con testa da sotto
----------------------------------------------------------------------------------------------------------------------------------------------------
-- function DiceCut.GetDice( nParent, BBoxRawPart, ptCPlanes, vtNPlanes, bGetOrtoPlanes, ptCBond, vtNBond, dOrthoMaxDim, dCustMaxDimDice, bDownHead)
---------------------------------------------------------------------------------------------------------------
-- DiceCut.GetDice :
-- Part : pezzo
-- Face1 : table. Contiene tutti i dati della faccia principale. Obbligatori i campi '.ptCenter' e '.vtNormal'
-- Face2 : table. Contiene tutti i dati della faccia secondaria. Se non esiste, la table è vuota ({}). Se esiste, obbligatori i campi '.ptCenter' e '.vtNormal'
-- OptionaParameters : eventuali parametri opzionali
---------------------------------------------------------------------------------------------------------------
function DiceCut.GetDice( Part, Face1, Face2, OptionalParameters)
local dMaxDimDice = BeamData.MAX_DIM_DICE
local dTolerance = 0 -- distanza di sicurezza per i tagli ortogonali
local OffsetP = dMaxDimDice -- distanza tra i piani paralleli
local StepP = 100 -- numero massimo di piani paralleli da generare
local OffsetO = dMaxDimDice -- distanza tra i piani ortogonali
local StepO = 100 -- numero massimo di piani ortogonali da generare
-- recupero gruppo per geometria addizionale
local nAddGrpId = BeamLib.GetAddGroup( Part.id)
-- se il box non è passato tra i parametri opzionali, faccio i calcoli sul SOLID del Part
local b3BoxToDicing = OptionalParameters.b3BoxToDicing or Part.b3Part
-- copio dati passati su variabili locali
local ptCMainFace, vtNMainFace, ptCSubordinateFace, vtNSubordinateFace, bGetOrtoPlanes
if Face1.ptCenter and Face1.vtNormal then
ptCMainFace = Face1.ptCenter
vtNMainFace = Face1.vtNormal
end
-- se esiste faccia secondaria non esiste, forzo calcolo piani ortogonali
if Face2.ptCenter and Face2.vtNormal then
ptCSubordinateFace = Face2.ptCenter
vtNSubordinateFace = Face2.vtNormal
bGetOrtoPlanes = false
else
bGetOrtoPlanes = true
end
-- ricavo dimensione massima cubetti
if OptionalParameters.dCustMaxDimDice and OptionalParameters.dCustMaxDimDice < BeamData.MAX_DIM_DICE then
dMaxDimDice = abs( OptionalParameters.dCustMaxDimDice)
end
--Ricavo le altezze dei BoundingBox contenente feature e estremi del grezzo
local TBoxPoint = CalcolaPuntiEstremiBox( b3BoxToDicing)
TBoxPoint = VerificaEstremiGrezzo( ptCMainFace, vtNMainFace, TBoxPoint)
if ptCSubordinateFace and vtNSubordinateFace then
TBoxPoint = VerificaEstremiGrezzo( ptCSubordinateFace, vtNSubordinateFace, TBoxPoint)
end
local dElevP = DistanzaMassima( nAddGrpId, ptCMainFace, vtNMainFace, ptCSubordinateFace, vtNSubordinateFace, b3BoxToDicing, TBoxPoint)
local dElevO
if ptCSubordinateFace and vtNSubordinateFace and not AreOppositeVectorApprox( vtNSubordinateFace, vtNMainFace) then
dElevO = DistanzaMassima( nAddGrpId, ptCSubordinateFace, vtNSubordinateFace, ptCMainFace, vtNMainFace, b3BoxToDicing, TBoxPoint)
end
-- inclinazione limite per taglio da sotto
local dNzLimDwnUp = BeamLib.GetNzLimDownUp( b3BoxToDicing)
-- se non c'è testa da sotto e normali senza componenti in Y con faccia quasi verticale e trave non alta, uso per offset i limiti dei tagli di testa e coda
if not BeamData.DOWN_HEAD and abs( vtNMainFace:getY()) < 0.1 and vtNMainFace:getZ() < 0.7071 and ( not vtNSubordinateFace or abs( vtNSubordinateFace:getY()) < 0.1) and b3BoxToDicing:getDimZ() < BeamData.MIN_DIM_HBEAM then
OffsetO = OptionalParameters.dOrthoMaxDim or BeamData.MAX_DIM_HTCUT
end
-- aggiungo piccolo extra agli offset
OffsetP = OffsetP + 10 * GEO.EPS_SMALL
OffsetO = OffsetO + 10 * GEO.EPS_SMALL
-- se piani non ortogonali, diminuisco la distanza di offset opportunamente
local originalOffsetP = OffsetP
if not bGetOrtoPlanes then
local dCoeff = ( vtNMainFace ^ vtNSubordinateFace):len()
OffsetP = OffsetP * dCoeff
OffsetO = OffsetO * dCoeff
end
local n = ceil( dElevP / OffsetP)
OffsetP = dElevP / n
if dElevO then
local m = ceil( dElevO / OffsetO)
OffsetO = dElevO / m
end
-- elenco di tutte le superfici generate dai tagli
local TabFUCHSIA = {}
local TabGREEN = {}
-- PIANI PARALLELI alla faccia di taglio
local TabellaTmSurfP = {}
local TabFromIn = GetParallelPlanes( nAddGrpId, b3BoxToDicing, ptCMainFace, vtNMainFace, 0, OffsetP, StepP, Color3d( FUCHSIA(), 60), dTolerance, true, ptCSubordinateFace, vtNSubordinateFace)
for i = #TabFromIn, 1, -1 do
table.insert( TabellaTmSurfP, TabFromIn[i])
end
-- PIANI ORTOGONALI alla faccia di taglio
-- orientamento definito da seconda faccia
if not bGetOrtoPlanes then
local TabellaTmSurfOrto = {}
local TabFromIn = GetParallelPlanes( nAddGrpId, b3BoxToDicing, ptCSubordinateFace, vtNSubordinateFace, 0, OffsetO, StepO, Color3d( GREEN(), 60), dTolerance, false, ptCMainFace, vtNMainFace)
for i = #TabFromIn, 1, -1 do
table.insert( TabellaTmSurfOrto, TabFromIn[i])
end
local TabellaOrderParallelCut = GetOrderedCutTable( nAddGrpId, TabellaTmSurfP, TabellaTmSurfOrto) -- Ottiene la tabella dei tagli paralleli ordinati
local TabellaOrderOrtoCut = GetOrderedCutTable( nAddGrpId, TabellaTmSurfOrto, TabellaTmSurfP) -- Ottiene la tabella dei tagli ortogonali da riordinare per strato
TabGREEN = SortOrtoCutsByNormalMethod( TabellaOrderParallelCut, TabellaOrderOrtoCut) -- I tagli ortogonali vengono ordinati per strato
TabFUCHSIA = TabellaOrderParallelCut -- I tagli paralleli sono già ordinati
-- orientamento da definire
else
for PlnInd = 1, #TabellaTmSurfP do
-- piano interno
local ptCInner, vtNInner = EgtSurfTmFacetCenter( TabellaTmSurfP[PlnInd], 0, GDB_ID.ROOT)
-- eventuale piano esterno
local ptCOuter, vtNOuter = nil, nil
if PlnInd > 1 then
ptCOuter, vtNOuter = EgtSurfTmFacetCenter( TabellaTmSurfP[PlnInd-1], 0, GDB_ID.ROOT)
vtNOuter = -vtNOuter
end
-- calcolo la direzione dei piani ortogonali
local vtO = VectorFromUprightOrtho( vtNInner)
if vtNInner:getZ() > -0.0175 or vtNInner:getZ() < dNzLimDwnUp or abs( vtNInner:getY()) > 0.8 then
vtO:rotate( vtNInner, 90)
-- se diretto troppo ortogonalmente all'asse trave e taglio non da sotto, lo ruoto ulteriormente
if ( abs( vtO:getY()) > 4 * abs( vtO:getX()) or b3BoxToDicing:getDimZ() > 620) and vtNInner:getZ() > dNzLimDwnUp then
vtO:rotate( vtNInner, 90)
-- se faccia principale verso il basso (almeno -3deg), lo inverto per iniziare da sopra
if vtNInner:getZ() < -0.05 then
vtO = -vtO
end
else
if vtNInner:getX() > -0.017 then
if vtO:getX() < -0.001 then vtO = -vtO end
else
if vtO:getX() > 0.001 then vtO = -vtO end
end
end
end
-- se quasi verticale (fino a 20 gradi di distanza) su faccia inclinata in Y, ruoto di 90 gradi
if vtO:getZ() > 0.939 and abs( vtNInner:getY()) > 0.5 then
vtO:rotate( vtNInner, 90)
end
-- se taglio con testa da sotto
if OptionalParameters.bHeadFromBottom and vtO:getZ() > 0.05 then
vtO = -vtO
end
-- calcolo le dimensioni dell'offset e dove posizionare la prima faccia:
-- CopyPlane: 0 => crea la prima faccia direttamente sul punto passato
-- CopyPlane: 1 => crea la prima faccia e tutte le altre con l'offset passato
-- CopyPlane: 0.5 => crea la prima faccia a metà offset e tutte le altre con l'offest intero
local OffsetRel, CopyPlane, dCenOffs, ptCStart = GetOrtoCutCenter( TabellaTmSurfP[PlnInd], ptCInner, vtNInner, vtO, OffsetO, dNzLimDwnUp)
if OffsetRel and CopyPlane and dCenOffs then
ptCInner = ptCInner + dCenOffs * vtO
local TabRight = GetParallelPlanes( nAddGrpId, b3BoxToDicing, ptCStart, vtO, CopyPlane, -OffsetRel, StepO, Color3d( GREEN(), 60),
dTolerance, false, ptCInner, vtNInner, ptCOuter, vtNOuter)
if CopyPlane == 0 then
CopyPlane = 1
end
local TabLeft = GetParallelPlanes( nAddGrpId, b3BoxToDicing, ptCStart, vtO, CopyPlane, OffsetRel, StepO, Color3d( GREEN(), 60),
dTolerance, false, ptCInner, vtNInner, ptCOuter, vtNOuter)
-- carico la tabella con gli indici riordinati
local TempOrtoTab = {}
for i = #TabLeft, 1, -1 do
table.insert( TempOrtoTab, TabLeft[i])
end
for i = 1, #TabRight do
table.insert( TempOrtoTab, TabRight[i])
end
-- creo una tabella per ogni piano per generare i tagli sulla Inner
local TempParTab = GetOrderedCutTable( nAddGrpId, {TabellaTmSurfP[PlnInd]}, TempOrtoTab)
for i = 1, #TempParTab do
table.insert( TabFUCHSIA, TempParTab[i])
end
table.insert( TabGREEN, TempOrtoTab)
else
table.insert( TabFUCHSIA, {TabellaTmSurfP[PlnInd]})
table.insert( TabGREEN, {})
end
end
end
-- Se sono state costruite non più di una faccia parallela e una faccia perpendicolare, allora non servono e tengo le originali
if #TabGREEN == 1 and #TabGREEN[1] <= 1 and #TabFUCHSIA == 1 and #TabFUCHSIA[1] <= 1 then
if #TabGREEN[1] == 1 then
EgtErase( TabGREEN[1][1])
end
TabGREEN = {}
if #TabFUCHSIA[1] == 1 then
EgtErase( TabFUCHSIA[1][1])
end
TabFUCHSIA = {}
end
-- Si uniscono le tabelle dei tagli ortogonali e paralleli in una sola tabella
local UltimateTable = TableMesh( TabGREEN, TabFUCHSIA)
-- Se esiste la superficie limitante (nFacet == 2) verifica se il taglio più esterno è superfluo e quindi viene eliminato
if not bGetOrtoPlanes then
VerifyFirstOrthoCut( UltimateTable, originalOffsetP, b3BoxToDicing, dNzLimDwnUp)
-- se rimangono due sole facce, devono coincidere con le originali e quindi sono superflue
if #UltimateTable == 2 and #UltimateTable[1] == 1 and #UltimateTable[2] == 1 then
EgtErase( UltimateTable[1][1])
EgtErase( UltimateTable[2][1])
UltimateTable = {}
end
end
return UltimateTable
end
----------------------------------------------------------------------------------------------------------------------------------------------------
-- PrintOrderCut:
-- TabellaOrderCut: tabella delle superfici di taglio
-- stampo l'ordine dei piani di taglio ricevendo una tabella con gli strati parallelo/ortogonali già ordinati
function DiceCut.PrintOrderCut( TabellaOrderCut)
local Step = #TabellaOrderCut
if Step > 0 then
EgtOutLog( " L'ordine delle superfici da tagliare è il seguente:")
else
EgtOutLog( ' Non sono necessarie superfici aggiuntive di taglio.')
end
for i = 1, Step do
if i % 2 == 1 then
EgtOutLog( ' *** Strato di taglio ' .. EgtNumToString( ( i + 1) / 2, 0))
if #TabellaOrderCut[i] > 0 then
EgtOutLog( ' Tagli ortogonali: ')
else
EgtOutLog( ' Tagli ortogonali assenti')
end
else
if #TabellaOrderCut[i] > 0 then
EgtOutLog( ' Tagli paralleli: ')
else
EgtOutLog( ' Tagli paralleli assenti')
end
end
for j=1, #TabellaOrderCut[i] do
EgtOutLog( ' Indice faccia ' .. (TabellaOrderCut[i][j] or 0))
end
end
end
----------------------------------------------------------------------------------------------------------------------------------------------------
local function DiceCutTest()
-- salvo l'indice del layer Trimesh selezionato
local SelectedIndex = EgtGetFirstSelectedObj()
-- verifico che sia selezionato un elemento
if not SelectedIndex then return end
-- salvo l'indice del layer Processing
local nAddGrpId = EgtGetParent( SelectedIndex)
-- salvo l'indice del layer Part
local nRawPart = EgtGetParent( nAddGrpId)
local nBox = EgtGetFirstNameInGroup( nRawPart, 'Box')
-- carico il bounding box della trave
-- local b3BoxToDicing = EgtGetBBoxGlob( nRawPart, GDB_BB.STANDARD )
local b3BoxToDicing = EgtGetBBoxGlob( nBox, GDB_BB.STANDARD )
-- seleziono il Part e il Layer di destinazione
EgtSetCurrPartLayer( nRawPart, nAddGrpId)
-- conto il numero di facce da processare
local nFacet = EgtSurfTmFacetCount( SelectedIndex)
EgtOutLog( ' Numero facce ' .. nFacet, 1)
-- salvo
local TabPlanesFeatures = {}
for i = 1, nFacet do
local ptC, vtN = EgtSurfTmFacetCenter( SelectedIndex, i - 1, GDB_ID.ROOT)
table.insert( TabPlanesFeatures, { ptC = ptC, vtN = vtN})
end
local ptC1 = Point3d( TabPlanesFeatures[1].ptC)
local vtN1 = Vector3d( TabPlanesFeatures[1].vtN)
local CutTable = {}
if nFacet == 1 then
CutTable = DiceCut.GetDice( nAddGrpId, b3BoxToDicing, ptC1, vtN1, true)
elseif nFacet == 2 then
CutTable = DiceCut.GetDice( nAddGrpId, b3BoxToDicing, ptC1, vtN1, false, TabPlanesFeatures[2].ptC, TabPlanesFeatures[2].vtN)
end
if EgtGetDebugLevel() >= 3 then
DiceCut.PrintOrderCut( CutTable)
end
EgtDeselectAll()
EgtDraw()
end
----------------------------------------------------------------------------------------------------------------------------------------------------
--DiceCutTest()
return DiceCut
+90 -59
View File
@@ -7,6 +7,7 @@ local FaceData = {}
-- carico librerie
local BeamLib = require( 'BeamLib')
local Logs = require( 'Logs')
---------------------------------------------------------------------
@@ -81,7 +82,7 @@ end
function FaceData.GetFacesByAdjacencyNumber( Proc)
-- se la feature ha una sola faccia, esco subito
if Proc.nFct <= 1 then
return
return {}
end
local FacesByAdjacencyNumber = {}
@@ -96,6 +97,42 @@ function FaceData.GetFacesByAdjacencyNumber( Proc)
return FacesByAdjacencyNumber
end
-------------------------------------------------------------------------------------------------------------
local function GetEdgesInfo( Proc, idFace )
local Edges = {}
local nFaceType, EdgesEgt = EgtSurfTmGetFacetOutlineInfo( Proc.id, idFace, GDB_ID.ROOT)
for i = 1, #EdgesEgt do
local nPreviousEdgeIndex = i - 1
if i == 1 then
nPreviousEdgeIndex = #EdgesEgt
end
local nNextEdgeIndex = i + 1
if i == #EdgesEgt then
nNextEdgeIndex = 1
end
-- l'elevazione si tiene sempre positiva e la normale sempre diretta verso l'interno della faccia
-- per sapere se il lato è aperto c'è la proprietà apposita bIsOpen
local CurrentEdge = {}
CurrentEdge.idAdjacentFace = EdgesEgt[i].Adj
CurrentEdge.dLength = EdgesEgt[i].Len
CurrentEdge.dElevation = abs( EdgesEgt[i].Elev)
CurrentEdge.bIsOpen = EdgesEgt[i].Open
CurrentEdge.vtN = Vector3d( EdgesEgt[i].Norm)
if CurrentEdge.bIsOpen then
CurrentEdge.vtN = -CurrentEdge.vtN
end
CurrentEdge.bIsStartOpen = EdgesEgt[nPreviousEdgeIndex].Open
CurrentEdge.bIsEndOpen = EdgesEgt[nNextEdgeIndex].Open
CurrentEdge.sType = 'Standard'
table.insert( Edges, CurrentEdge)
end
return nFaceType, Edges
end
-------------------------------------------------------------------------------------------------------------
function FaceData.GetFacesInfo( Proc, Part)
EgtOutLog( '---Faces START---')
@@ -108,6 +145,10 @@ function FaceData.GetFacesInfo( Proc, Part)
vAdj = FaceData.GetAdjacencyMatrix( Proc)
end
if not Proc.nFct then
Proc.nFct = EgtSurfTmFacetCount( Proc.id) or 0
end
-- reset eventuali visualizzazioni facce a due colori
EgtSurfTmResetTwoColors( Proc.id)
@@ -119,14 +160,14 @@ function FaceData.GetFacesInfo( Proc, Part)
-- frame OCS faccia
Faces[i].vtFrameHV = Frame3d( Faces[i].ptCenter, Faces[i].vtN)
-- elevazione calcolata rispetto al box della parte
Faces[i].dElevation = EgtSurfTmFacetElevationInBBox( Proc.id, i - 1, Part.b3Solid, true, GDB_ID.ROOT)
Faces[i].dElevation = EgtSurfTmFacetElevationInBBox( Proc.id, i - 1, Part.b3Part, true, GDB_ID.ROOT)
-- TODO qui sarebbe meglio l'area vera e non quella del rettangolo minimo
local _, dLongEdgeDimension, dShortEdgeDimension = EgtSurfTmFacetMinAreaRectangle( Proc.id, i - 1, GDB_ID.ROOT)
Faces[i].dArea = dShortEdgeDimension * dLongEdgeDimension
local nFaceType, vEdges = EgtSurfTmGetFacetOutlineInfo( Proc.id, i - 1, GDB_ID.ROOT)
local nFaceType, Edges = GetEdgesInfo( Proc, i - 1)
Faces[i].bIsOkForMachining = nFaceType < 1
Faces[i].Edges = vEdges
Faces[i].Edges = Edges
-- TODO valutare se fare un output unico alla fine o gestire log in altro modo
EgtOutLog( 'Facet ' .. Faces[i].id .. ' of ' .. Proc.nFct - 1)
@@ -178,16 +219,25 @@ local function GetTunnelFaces( Proc, Part)
return TunnelAddedFaces
end
-- faccia centrale, si crea larga come la parte e poi si trimma
TunnelAddedFaces.MiddleFaceTm = {}
TunnelAddedFaces.MiddleFaceTm.id = EgtSurfTmPlaneInBBox( nAddGrpId, ptTunnelCenter, vtTunnelDirection, Part.b3Solid, GDB_ID.ROOT)
-- faccia centrale
local nMiddleTmId = EgtSurfTmPlaneInBBox( nAddGrpId, ptTunnelCenter, vtTunnelDirection, Part.b3Part, GDB_ID.ROOT)
-- TODO se non si riesce a costruire la faccia bisogna dare errore o semplicemente non ritornarla??
for i = 1, Proc.nFct do
EgtCutSurfTmPlane( TunnelAddedFaces.MiddleFaceTm.id, Proc.Faces[i].ptCenter, -Proc.Faces[i].vtN, false, GDB_ID.ROOT)
EgtCutSurfTmPlane( nMiddleTmId, Proc.Faces[i].ptCenter, -Proc.Faces[i].vtN, false, GDB_ID.ROOT)
end
-- facce laterali
local nLateralTmId = EgtCopyGlob( Proc.id, nAddGrpId) or GDB_ID.NULL
EgtCutSurfTmPlane( nLateralTmId, ptTunnelCenter, -vtTunnelDirection, false, GDB_ID.ROOT)
-- unione facce
-- TODO cambiare nome alla trimesh?? non contiene più solamente la faccia di mezzo
TunnelAddedFaces.MiddleFaceTm = {}
TunnelAddedFaces.MiddleFaceTm.id = EgtSurfTmBySewing( nAddGrpId, { nMiddleTmId, nLateralTmId}, true)
-- TODO c'è un modo più elegante per raccogliere le informazioni delle facce aggiunte
TunnelAddedFaces.MiddleFaceTm.sType = 'Tunnel'
TunnelAddedFaces.MiddleFaceTm.nFct = 1
TunnelAddedFaces.MiddleFaceTm.nFct = Proc.nFct + 1
TunnelAddedFaces.MiddleFaceTm.Faces = FaceData.GetFacesInfo( TunnelAddedFaces.MiddleFaceTm, Part)
return TunnelAddedFaces
@@ -232,10 +282,10 @@ local function GetBottomFaces( Proc)
local ClosedEdgesSortedByGreatestLength = {}
for i = 1, #BottomFaces[1].Edges do
if not BottomFaces[1].Edges[i].Open then
if not BottomFaces[1].Edges[i].bIsOpen then
table.insert( ClosedEdgesSortedByGreatestLength, {})
ClosedEdgesSortedByGreatestLength[#ClosedEdgesSortedByGreatestLength].nIndex = i
ClosedEdgesSortedByGreatestLength[#ClosedEdgesSortedByGreatestLength].dLength = BottomFaces[1].Edges[i].Len
ClosedEdgesSortedByGreatestLength[#ClosedEdgesSortedByGreatestLength].dLength = BottomFaces[1].Edges[i].dLength
end
end
table.sort( ClosedEdgesSortedByGreatestLength, function (a, b) return a.dLength > b.dLength end)
@@ -252,13 +302,13 @@ local function GetBottomFaces( Proc)
end
local CurrentEdge = {}
CurrentEdge.idAdjacentFace = BottomFaces[1].Edges[i].Adj
CurrentEdge.vtToolDirection = Vector3d( BottomFaces[1].Edges[i].Norm)
CurrentEdge.dLength = BottomFaces[1].Edges[i].Len
CurrentEdge.dElevation = BottomFaces[1].Edges[i].Elev
CurrentEdge.bIsOpen = BottomFaces[1].Edges[i].Open
CurrentEdge.bIsStartOpen = BottomFaces[1].Edges[nPreviousEdgeIndex].Open
CurrentEdge.bIsEndOpen = BottomFaces[1].Edges[nNextEdgeIndex].Open
CurrentEdge.idAdjacentFace = BottomFaces[1].Edges[i].idAdjacentFace
CurrentEdge.vtN = BottomFaces[1].Edges[i].vtN
CurrentEdge.dLength = BottomFaces[1].Edges[i].dLength
CurrentEdge.bIsOpen = BottomFaces[1].Edges[i].bIsOpen
CurrentEdge.dElevation = BottomFaces[1].Edges[i].dElevation
CurrentEdge.bIsStartOpen = BottomFaces[1].Edges[i].bIsStartOpen
CurrentEdge.bIsEndOpen = BottomFaces[1].Edges[i].bIsEndOpen
if i == nFirstLongEdgeIndex then
BottomFaces[1].MainEdges.LongEdges[1] = CurrentEdge
@@ -337,13 +387,13 @@ local function GetLongFaces( Proc, MainFaces)
end
local CurrentEdge = {}
CurrentEdge.idAdjacentFace = LongFaces[i].Edges[j].Adj
CurrentEdge.vtToolDirection = Vector3d( LongFaces[i].Edges[j].Norm)
CurrentEdge.dLength = LongFaces[i].Edges[j].Len
CurrentEdge.dElevation = LongFaces[i].Edges[j].Elev
CurrentEdge.bIsOpen = LongFaces[i].Edges[j].Open
CurrentEdge.bIsStartOpen = LongFaces[i].Edges[nPreviousEdgeIndex].Open
CurrentEdge.bIsEndOpen = LongFaces[i].Edges[nNextEdgeIndex].Open
CurrentEdge.idAdjacentFace = LongFaces[i].Edges[j].idAdjacentFace
CurrentEdge.vtN = LongFaces[i].Edges[j].vtN
CurrentEdge.dLength = LongFaces[i].Edges[j].dLength
CurrentEdge.bIsOpen = LongFaces[i].Edges[j].bIsOpen
CurrentEdge.dElevation = LongFaces[i].Edges[j].dElevation
CurrentEdge.bIsStartOpen = LongFaces[i].Edges[j].bIsStartOpen
CurrentEdge.bIsEndOpen = LongFaces[i].Edges[j].bIsEndOpen
if Proc.Topology.sFamily == 'Tunnel' then
if CurrentEdge.idAdjacentFace > -1 then
@@ -357,10 +407,10 @@ local function GetLongFaces( Proc, MainFaces)
if CurrentEdge.idAdjacentFace == BottomFace.id then
LongFaces[i].MainEdges.BottomEdge = CurrentEdge
LongFaces[i].MainEdges.BottomEdge.sType = 'Bottom'
elseif LongFaces[i].Edges[nNextEdgeIndex].Adj == BottomFace.id then
elseif LongFaces[i].Edges[nNextEdgeIndex].idAdjacentFace == BottomFace.id then
LongFaces[i].MainEdges.SideEdges[1] = CurrentEdge
LongFaces[i].MainEdges.SideEdges[1].sType = 'Side'
elseif LongFaces[i].Edges[nPreviousEdgeIndex].Adj == BottomFace.id then
elseif LongFaces[i].Edges[nPreviousEdgeIndex].idAdjacentFace == BottomFace.id then
LongFaces[i].MainEdges.SideEdges[2] = CurrentEdge
LongFaces[i].MainEdges.SideEdges[2].sType = 'Side'
else
@@ -423,13 +473,13 @@ local function GetSideFaces( Proc, MainFaces)
end
local CurrentEdge = {}
CurrentEdge.idAdjacentFace = SideFaces[i].Edges[j].Adj
CurrentEdge.vtToolDirection = Vector3d( SideFaces[i].Edges[j].Norm)
CurrentEdge.dLength = SideFaces[i].Edges[j].Len
CurrentEdge.dElevation = SideFaces[i].Edges[j].Elev
CurrentEdge.bIsOpen = SideFaces[i].Edges[j].Open
CurrentEdge.bIsStartOpen = SideFaces[i].Edges[nPreviousEdgeIndex].Open
CurrentEdge.bIsEndOpen = SideFaces[i].Edges[nNextEdgeIndex].Open
CurrentEdge.idAdjacentFace = SideFaces[i].Edges[j].idAdjacentFace
CurrentEdge.vtN = SideFaces[i].Edges[j].vtN
CurrentEdge.dLength = SideFaces[i].Edges[j].dLength
CurrentEdge.bIsOpen = SideFaces[i].Edges[j].bIsOpen
CurrentEdge.dElevation = SideFaces[i].Edges[j].dElevation
CurrentEdge.bIsStartOpen = SideFaces[i].Edges[j].bIsStartOpen
CurrentEdge.bIsEndOpen = SideFaces[i].Edges[j].bIsEndOpen
if Proc.Topology.sFamily == 'Tunnel' then
if CurrentEdge.idAdjacentFace > -1 then
@@ -441,10 +491,10 @@ local function GetSideFaces( Proc, MainFaces)
if CurrentEdge.idAdjacentFace == BottomFace.id then
SideFaces[i].MainEdges.BottomEdge = CurrentEdge
SideFaces[i].MainEdges.BottomEdge.sType = 'Bottom'
elseif SideFaces[i].Edges[nNextEdgeIndex].Adj == BottomFace.id then
elseif SideFaces[i].Edges[nNextEdgeIndex].idAdjacentFace == BottomFace.id then
SideFaces[i].MainEdges.LongEdges[1] = CurrentEdge
SideFaces[i].MainEdges.LongEdges[1].sType = 'Long'
elseif SideFaces[i].Edges[nPreviousEdgeIndex].Adj == BottomFace.id then
elseif SideFaces[i].Edges[nPreviousEdgeIndex].idAdjacentFace == BottomFace.id then
SideFaces[i].MainEdges.LongEdges[2] = CurrentEdge
SideFaces[i].MainEdges.LongEdges[2].sType = 'Long'
else
@@ -475,35 +525,16 @@ function FaceData.GetMainFaces( Proc, Part)
MainFaces.BottomFaces = GetBottomFaces( Proc)
MainFaces.LongFaces = GetLongFaces( Proc, MainFaces)
MainFaces.SideFaces = GetSideFaces( Proc, MainFaces)
-- TODO funzione apposita per informazioni log?
-- scrivo informazioni delle facce nel log
if EgtGetDebugLevel() >= 3 then
if MainFaces.BottomFaces then
for i = 1, #MainFaces.BottomFaces do
EgtOutLog( 'Bottom Face : ' .. MainFaces.BottomFaces[i].id)
end
-- colore differente per la faccia di fondo principale
EgtSurfTmSetFaceColor( Proc.id, MainFaces.BottomFaces[1].id, 1)
end
if MainFaces.LongFaces then
for i = 1, #MainFaces.LongFaces do
EgtOutLog( 'Long Face : ' .. MainFaces.LongFaces[i].id)
end
end
if MainFaces.SideFaces then
for i = 1, #MainFaces.SideFaces do
EgtOutLog( 'Side Face : ' .. MainFaces.SideFaces[i].id)
end
end
if MainFaces.TunnelAddedFaces then
EgtOutLog( 'Middle Face (Trimesh): ' .. MainFaces.TunnelAddedFaces.MiddleFaceTm.id)
end
Logs.WriteMainFacesLog( Proc, MainFaces)
end
else
MainFaces = nil
EgtOutLog( '---MainFaces NOT NEEDED---')
end
EgtOutLog( '---MainFaces END---')
return MainFaces
end
-282
View File
@@ -1,282 +0,0 @@
-- 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 BeamData = require( 'BeamData')
-- carico librerie
local BeamLib = require( 'BeamLib')
local FaceData = require( 'FaceData')
local ID = require( 'Identity')
-------------------------------------------------------------------------------------------------------------
-- recupero topologia della feature
function FeatureData.NeedTopologyFeature( Proc)
-- features tipo taglio
if ID.IsCut( Proc) then
return true
elseif ID.IsDoubleCut( Proc) then
return true
elseif ID.IsSawCut( Proc) then
return true
-- features tipo taglio longitudinale
elseif ID.IsLongitudinalCut( Proc) then
return true
elseif ID.IsDoubleLongitudinalCut( Proc) then
return true
elseif ID.IsChamfer( Proc) then
return true
-- features tipo LapJoint
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
-- calcolo topologia SOLO se non raggiata
-- TODO oppure riconoscerla come feature speciale; valutare se controllare il numero di facce è un metodo efficace
elseif ID.IsMortise( Proc) and Proc.nFct < 6 then
return true
-- calcolo topologia SOLO se non raggiata
-- TODO oppure riconoscerla come feature speciale; valutare se controllare il numero di facce è un metodo efficace
elseif ID.IsFrontMortise( Proc) and Proc.nFct < 6 then
return true
end
-- se feature non tra quelle sopra, riconoscimento topologico non necessario
return false
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)
-- se la feature ha una sola faccia, esco subito
if #vAdj <= 1 then
return
end
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
---------------------------------------------------------------------
-- 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.idPart or GDB_ID.NULL, 'Box')
local b3Solid = EgtGetBBoxGlob( nBoxSolidId, GDB_BB.STANDARD)
if Proc.b3Box:getDimX() > b3Solid:getDimX() - 1000 * GEO.EPS_SMALL or
Proc.b3Box:getDimY() > b3Solid:getDimY() - 1000 * GEO.EPS_SMALL or
Proc.b3Box:getDimZ() > b3Solid:getDimZ() - 1000 * GEO.EPS_SMALL then
bResult = true
end
return bResult
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, Part)
return ( b3Proc:getDimY() > ( Part.b3Raw:getDimY() - 500 * GEO.EPS_SMALL) and b3Proc:getDimZ() > ( Part.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, Part)
return ( ( b3Proc:getDimY() > ( Part.b3Raw:getDimY() - 500 * GEO.EPS_SMALL) and b3Proc:getDimX() > ( Part.b3Raw:getDimX() - 500 * GEO.EPS_SMALL)) or
( b3Proc:getDimZ() > ( Part.b3Raw:getDimZ() - 500 * GEO.EPS_SMALL) and b3Proc:getDimX() > ( Part.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
function FeatureData.ClassifyTopology( Proc, Part)
local FeatureTopology = {}
if not Proc.AffectedFaces then Proc.AffectedFaces = BeamLib.GetAffectedFaces( Proc, Part) end
local bIsFeatureCuttingEntireSection = IsFeatureCuttingEntireSection( Proc.b3Box, Part)
local bIsFeatureCuttingEntireLength = IsFeatureCuttingEntireLength( Proc.b3Box, Part)
local bIsAnyDimensionLongAsPart = IsAnyDimensionLongAsPart( Proc)
local vAdj = Proc.AdjacencyMatrix
local bAllAnglesConcave, bAllRightAngles = AreAllAnglesConcaveOrRight( vAdj)
local vTriangularFaces = FaceData.GetTriangularFaces( Proc)
local vFacesByAdjNumber = FaceData.GetFacesByAdjacencyNumber( Proc)
local sFamily
local bIsThrough
if Proc.nFct == 1 and ( bIsFeatureCuttingEntireSection or bIsFeatureCuttingEntireLength) then
sFamily = 'Cut'
bIsThrough = true
elseif Proc.nFct == 1 then
sFamily = 'Bevel'
bIsThrough = true
elseif Proc.nFct == 2 and bAllAnglesConcave and #vTriangularFaces == 1 then
sFamily = 'Bevel'
bIsThrough = false
elseif Proc.nFct == 2 and bAllAnglesConcave and ( Proc.AffectedFaces.bLeft or Proc.AffectedFaces.bRight) and ( Proc.AffectedFaces.bFront or Proc.AffectedFaces.bBack) then
sFamily = 'Rabbet'
bIsThrough = true
elseif Proc.nFct == 2 and bAllAnglesConcave then
sFamily = 'VGroove'
bIsThrough = true
elseif Proc.nFct == 2 and not bAllAnglesConcave and bIsAnyDimensionLongAsPart then
sFamily = 'DoubleBevel'
bIsThrough = true
elseif Proc.nFct == 3 and bAllAnglesConcave and #vFacesByAdjNumber[2] == 1 and #vTriangularFaces == 2 then
sFamily = 'Bevel'
bIsThrough = false
elseif Proc.nFct == 3 and bAllAnglesConcave and #vFacesByAdjNumber[2] == 1 and bIsAnyDimensionLongAsPart then
sFamily = 'Groove'
bIsThrough = true
elseif Proc.nFct == 3 and bAllAnglesConcave and #vFacesByAdjNumber[2] == 3 then
sFamily = 'Groove'
bIsThrough = false
elseif Proc.nFct == 4 and #vFacesByAdjNumber[2] == 4 and #vTriangularFaces == 2 then
sFamily = 'DoubleBevel'
bIsThrough = false
elseif Proc.nFct == 4 and bAllAnglesConcave and #vFacesByAdjNumber[3] == 2 then
sFamily = 'Groove'
bIsThrough = false
elseif Proc.nFct == 4 and bAllAnglesConcave and #vFacesByAdjNumber[2] == 4 and bIsAnyDimensionLongAsPart then
sFamily = 'Tunnel'
bIsThrough = true
elseif Proc.nFct >= 4 and #vFacesByAdjNumber[1] == 2 and bIsAnyDimensionLongAsPart then
sFamily = 'Strip'
bIsThrough = true
elseif Proc.nFct == 5 and bAllAnglesConcave and #vFacesByAdjNumber[4] == 1 then
sFamily = 'Pocket'
bIsThrough = false
elseif Proc.nFct == 6 and #vFacesByAdjNumber[2] == 4 and #vFacesByAdjNumber[3] == 2 and #vTriangularFaces == 4 then
sFamily = 'DoubleBevel'
bIsThrough = false
end
if sFamily then
FeatureTopology.sFamily = sFamily
FeatureTopology.bIsThrough = bIsThrough
FeatureTopology.bAllRightAngles = bAllRightAngles
FeatureTopology.sName = GetTopologyName( sFamily, Proc.nFct, bIsThrough)
FeatureTopology.AdjacencyMatrix = vAdj
-- feature che necessita di essere catalogata, ma non si capisce come
else
FeatureTopology.sFamily = 'NOT_IMPLEMENTED'
FeatureTopology.sName = FeatureTopology.sFamily
end
return FeatureTopology
end
-------------------------------------------------------------------------------------------------------------
-- Recupero dati foro e adattamento se speciale
function FeatureData.GetDrillingData( 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 BeamData.USER_HOLE_DIAM and BeamData.USER_HOLE_DIAM > 1 then
EgtModifyArcRadius( AuxId, BeamData.USER_HOLE_DIAM / 2)
end
end
local dDiam = EgtGetInfo( Proc.id, 'P12', 'd') or 0
local dLen = abs( EgtCurveThickness( Proc.id + AuxId)) or 0
local nFcs = EgtGetInfo( Proc.id, 'FCS', 'i') or 0
local nFce = EgtGetInfo( Proc.id, 'FCE', 'i') or 0
return dDiam, dLen, nFcs, nFce
end
-------------------------------------------------------------------------------------------------------------
-- funzione che restituisce indice di completamento in base alla percentuale di volume lavorato
function FeatureData.GetFeatureCompletionIndex( dCompletionPercentage)
-- indice di completamento
local nCompletionIndex = 0
-- nullo
if dCompletionPercentage < 5 then
nCompletionIndex = 0
-- Low
elseif dCompletionPercentage < 50 then
nCompletionIndex = 1
-- Medium
elseif dCompletionPercentage < 80 then
nCompletionIndex = 2
-- High / Complete
else
nCompletionIndex = 5
end
return nCompletionIndex
end
-------------------------------------------------------------------------------------------------------------
-- funzione che restituisce qualità della lavorazione in base agli utensili utilizzati
function FeatureData.GetFeatureQuality( sTypeTools)
local nQuality = 5
local TypeTools = EgtSplitString( sTypeTools)
-- indice in base a utensile
for i=1, #TypeTools do
if TypeTools[i] == 'Blade' then
nQuality = min( nQuality, 5)
elseif TypeTools[i] == 'Mill' then
nQuality = min( nQuality, 4)
elseif TypeTools[i] == 'Chainsaw' then
nQuality = min( nQuality, 2)
else
nQuality = min( nQuality, 1)
end
end
-- se si utilizzano più utensili si perde in qualità
if #TypeTools > 1 then
nQuality = nQuality - 1
end
return nQuality
end
-------------------------------------------------------------------------------------------------------------
return FeatureData
+523
View File
@@ -0,0 +1,523 @@
-- FeatureLib.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 FeatureLib = {}
-- Carico i dati globali
local BeamData = require( 'BeamData')
-- carico librerie
local BeamLib = require( 'BeamLib')
local FaceData = require( 'FaceData')
local ID = require( 'Identity')
-------------------------------------------------------------------------------------------------------------
-- recupero topologia della feature
function FeatureLib.NeedTopologyFeature( Proc)
-- features tipo taglio
if ID.IsCut( Proc) then
return true
elseif ID.IsHeadCut( Proc) then
return true
elseif ID.IsTailCut( Proc) then
return true
elseif ID.IsDoubleCut( Proc) then
return true
elseif ID.IsSawCut( Proc) then
return true
-- features tipo taglio longitudinale
elseif ID.IsLongitudinalCut( Proc) then
return true
elseif ID.IsDoubleLongitudinalCut( Proc) then
return true
elseif ID.IsChamfer( Proc) then
return true
-- features tipo LapJoint
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
-- calcolo topologia SOLO se non raggiata
-- TODO oppure riconoscerla come feature speciale; valutare se controllare il numero di facce è un metodo efficace
elseif ID.IsMortise( Proc) and Proc.nFct < 6 then
return true
-- calcolo topologia SOLO se non raggiata
-- TODO oppure riconoscerla come feature speciale; valutare se controllare il numero di facce è un metodo efficace
elseif ID.IsFrontMortise( Proc) and Proc.nFct < 6 then
return true
end
-- se feature non tra quelle sopra, riconoscimento topologico non necessario
return false
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)
-- se la feature ha una sola faccia, esco subito
if #vAdj <= 1 then
return
end
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
---------------------------------------------------------------------
-- 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, Part)
local bResult = false
if Proc.b3Box:getDimX() > Part.b3Part:getDimX() - 1000 * GEO.EPS_SMALL or
Proc.b3Box:getDimY() > Part.b3Part:getDimY() - 1000 * GEO.EPS_SMALL or
Proc.b3Box:getDimZ() > Part.b3Part:getDimZ() - 1000 * GEO.EPS_SMALL then
bResult = true
end
return bResult
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, Part)
return ( b3Proc:getDimY() > ( Part.b3Raw:getDimY() - 500 * GEO.EPS_SMALL) and b3Proc:getDimZ() > ( Part.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, Part)
return ( ( b3Proc:getDimY() > ( Part.b3Raw:getDimY() - 500 * GEO.EPS_SMALL) and b3Proc:getDimX() > ( Part.b3Raw:getDimX() - 500 * GEO.EPS_SMALL)) or
( b3Proc:getDimZ() > ( Part.b3Raw:getDimZ() - 500 * GEO.EPS_SMALL) and b3Proc:getDimX() > ( Part.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
function FeatureLib.ClassifyTopology( Proc, Part)
local FeatureTopology = {}
if not Proc.AffectedFaces then Proc.AffectedFaces = BeamLib.GetAffectedFaces( Proc, Part) end
local bIsFeatureCuttingEntireSection = IsFeatureCuttingEntireSection( Proc.b3Box, Part)
local bIsFeatureCuttingEntireLength = IsFeatureCuttingEntireLength( Proc.b3Box, Part)
local bIsAnyDimensionLongAsPart = IsAnyDimensionLongAsPart( Proc, Part)
local vAdj = Proc.AdjacencyMatrix
local bAllAnglesConcave, bAllRightAngles = AreAllAnglesConcaveOrRight( vAdj)
local vTriangularFaces = FaceData.GetTriangularFaces( Proc)
local vFacesByAdjNumber = FaceData.GetFacesByAdjacencyNumber( Proc)
local sFamily
local bIsThrough
if Proc.nFct == 1 and ( bIsFeatureCuttingEntireSection or bIsFeatureCuttingEntireLength) then
sFamily = 'Cut'
bIsThrough = true
elseif Proc.nFct == 1 then
sFamily = 'Bevel'
bIsThrough = true
elseif Proc.nFct == 2 and bAllAnglesConcave and #vTriangularFaces == 1 then
sFamily = 'Bevel'
bIsThrough = false
elseif Proc.nFct == 2 and bAllAnglesConcave and ( Proc.AffectedFaces.bLeft or Proc.AffectedFaces.bRight) and ( Proc.AffectedFaces.bFront or Proc.AffectedFaces.bBack) then
sFamily = 'Rabbet'
bIsThrough = true
elseif Proc.nFct == 2 and bAllAnglesConcave then
sFamily = 'VGroove'
bIsThrough = true
elseif Proc.nFct == 2 and not bAllAnglesConcave and bIsAnyDimensionLongAsPart then
sFamily = 'DoubleBevel'
bIsThrough = true
elseif Proc.nFct == 3 and bAllAnglesConcave and #vFacesByAdjNumber[2] == 1 and #vTriangularFaces == 2 then
sFamily = 'Bevel'
bIsThrough = false
elseif Proc.nFct == 3 and bAllAnglesConcave and #vFacesByAdjNumber[2] == 1 and bIsAnyDimensionLongAsPart then
sFamily = 'Groove'
bIsThrough = true
elseif Proc.nFct == 3 and bAllAnglesConcave and #vFacesByAdjNumber[2] == 3 then
sFamily = 'Groove'
bIsThrough = false
elseif Proc.nFct == 4 and #vFacesByAdjNumber[2] == 4 and #vTriangularFaces == 2 then
sFamily = 'DoubleBevel'
bIsThrough = false
elseif Proc.nFct == 4 and bAllAnglesConcave and #vFacesByAdjNumber[3] == 2 then
sFamily = 'Groove'
bIsThrough = false
elseif Proc.nFct == 4 and bAllAnglesConcave and #vFacesByAdjNumber[2] == 4 and bIsAnyDimensionLongAsPart then
sFamily = 'Tunnel'
bIsThrough = true
elseif Proc.nFct >= 4 and #vFacesByAdjNumber[1] == 2 and bIsAnyDimensionLongAsPart then
sFamily = 'Strip'
bIsThrough = true
elseif Proc.nFct == 5 and bAllAnglesConcave and #vFacesByAdjNumber[4] == 1 then
sFamily = 'Pocket'
bIsThrough = false
elseif Proc.nFct == 6 and #vFacesByAdjNumber[2] == 4 and #vFacesByAdjNumber[3] == 2 and #vTriangularFaces == 4 then
sFamily = 'DoubleBevel'
bIsThrough = false
end
if sFamily then
FeatureTopology.sFamily = sFamily
FeatureTopology.bIsThrough = bIsThrough
FeatureTopology.bAllRightAngles = bAllRightAngles
FeatureTopology.sName = GetTopologyName( sFamily, Proc.nFct, bIsThrough)
FeatureTopology.AdjacencyMatrix = vAdj
-- feature che necessita di essere catalogata, ma non si capisce come
else
FeatureTopology.sFamily = 'NOT_IMPLEMENTED'
FeatureTopology.sName = FeatureTopology.sFamily
end
return FeatureTopology
end
-------------------------------------------------------------------------------------------------------------
-- Recupero dati foro e adattamento se speciale
function FeatureLib.GetDrillingData( 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 BeamData.USER_HOLE_DIAM and BeamData.USER_HOLE_DIAM > 1 then
EgtModifyArcRadius( AuxId, BeamData.USER_HOLE_DIAM / 2)
end
end
local dDiam = EgtGetInfo( Proc.id, 'P12', 'd') or 0
local dLen = abs( EgtCurveThickness( Proc.id + AuxId)) or 0
local nFcs = EgtGetInfo( Proc.id, 'FCS', 'i') or 0
local nFce = EgtGetInfo( Proc.id, 'FCE', 'i') or 0
return dDiam, dLen, nFcs, nFce
end
-------------------------------------------------------------------------------------------------------------
-- funzione che restituisce indice di completamento in base alla percentuale di volume lavorato
function FeatureLib.GetFeatureCompletionIndex( dCompletionPercentage)
-- indice di completamento
local nCompletionIndex = 0
-- nullo
if dCompletionPercentage < 5 then
nCompletionIndex = 0
-- Low
elseif dCompletionPercentage < 50 then
nCompletionIndex = 1
-- Medium
elseif dCompletionPercentage < 80 then
nCompletionIndex = 2
-- High / Complete
else
nCompletionIndex = 5
end
return nCompletionIndex
end
-------------------------------------------------------------------------------------------------------------
-- funzione che restituisce qualità della lavorazione in base agli utensili utilizzati
function FeatureLib.GetFeatureQuality( sTypeTools)
local nQuality = 5
local TypeTools = EgtSplitString( sTypeTools)
-- indice in base a utensile
for i=1, #TypeTools do
if TypeTools[i] == 'Blade' then
nQuality = min( nQuality, 5)
elseif TypeTools[i] == 'Mill' then
nQuality = min( nQuality, 4)
elseif TypeTools[i] == 'Chainsaw' then
nQuality = min( nQuality, 2)
else
nQuality = min( nQuality, 1)
end
end
-- se si utilizzano più utensili si perde in qualità
if #TypeTools > 1 then
nQuality = max( nQuality - 1, 0.5)
end
return nQuality
end
-------------------------------------------------------------------------------------------------------------
-- funzione che calcola il 'CompositeRating' di ogni strategia
function FeatureLib.CalculateCompositeRating( StrategyResult)
-- se ho tutti i dati che mi servono calcolo il rating della strategia applicato alla feature
if StrategyResult and StrategyResult.nQuality and StrategyResult.nCompletionIndex and StrategyResult.dMRR then
StrategyResult.dCompositeRating = ceil( StrategyResult.nQuality * StrategyResult.nCompletionIndex * StrategyResult.dMRR)
else
StrategyResult.dCompositeRating = 0
end
return StrategyResult
end
-------------------------------------------------------------------------------------------------------------
function FeatureLib.IsMachiningLong( dMachiningLengthOnX, Part, OptionalParameters)
local bIsMachiningLong
-- parametri opzionali
if not OptionalParameters then
OptionalParameters = {}
end
local dMaxSegmentLength = OptionalParameters.dMaxSegmentLength or BeamData.LONGCUT_MAXLEN
bIsMachiningLong = ( dMachiningLengthOnX > dMaxSegmentLength + 10 * GEO.EPS_SMALL)
or ( dMachiningLengthOnX > 0.7 * Part.b3Part:getDimX() + 10 * GEO.EPS_SMALL)
return bIsMachiningLong
end
-------------------------------------------------------------------------------------------------------------
function FeatureLib.GetFeatureSplittingPoints( Proc, Part, OptionalParameters)
local FeatureSplittingPoints = {}
local bFeatureStartsOnEdgeLeft = false
local bFeatureStartsOnEdgeRight = false
local dSplitXLeft = Proc.b3Box:getMin():getX()
local dSplitXRight = Proc.b3Box:getMax():getX()
local dFeatureCentralLength = Proc.b3Box:getDimX()
-- parametri opzionali
if not OptionalParameters then
OptionalParameters = {}
end
local dMaxSegmentLength = OptionalParameters.dMaxSegmentLength or BeamData.LONGCUT_MAXLEN
local dMaxSegmentLengthOnEdges = OptionalParameters.dMaxSegmentLengthOnEdges or BeamData.LONGCUT_ENDLEN
local dMinSegmentLength = OptionalParameters.dMinSegmentLength or dMaxSegmentLengthOnEdges / 2
local dToolOverlapBetweenSegments = OptionalParameters.dToolOverlapBetweenSegments or BeamData.MILL_OVERLAP
-- verifica spezzatura necessaria
if not FeatureLib.IsMachiningLong( Proc.b3Box:getDimX(), Part) then
return {}
end
-- verifica se necessari spezzoni differenti sugli estremi
if Proc.b3Box:getMin():getX() < Part.b3Part:getMin():getX() + dMaxSegmentLengthOnEdges - 10 * GEO.EPS_SMALL then
bFeatureStartsOnEdgeLeft = true
end
if Proc.b3Box:getMax():getX() > Part.b3Part:getMax():getX() - dMaxSegmentLengthOnEdges + 10 * GEO.EPS_SMALL then
bFeatureStartsOnEdgeRight = true
end
-- calcolo punto estremo sinistro
local ptSplitXLeft
if bFeatureStartsOnEdgeLeft then
-- decido punto spezzatura verso la coda
if Proc.b3Box:getDimX() > dMaxSegmentLengthOnEdges * 2 then
dSplitXLeft = max( Part.b3Part:getMin():getX() + dMaxSegmentLengthOnEdges, Proc.b3Box:getMin():getX() + dMinSegmentLength)
else
-- se pezzo abbastanza piccolo, spezzo in mezzo al 'pezzo + grezzo restante'
if Part.dRestLength + Part.b3Part:getDimX() < BeamData.dMinRaw * 1.5 then
dSplitXLeft = Part.b3Part:getMax():getX() - ( ( Part.dRestLength + Part.b3Part:getDimX()) / 2)
else
dSplitXLeft = max( Proc.b3Box:getMin():getX() + ( BeamData.dMinRaw)/2 + 150, Part.b3Part:getMax():getX() - dMaxSegmentLengthOnEdges)
end
end
dFeatureCentralLength = abs( dSplitXRight - dSplitXLeft)
ptSplitXLeft = Point3d( dSplitXLeft, 0, 0)
end
-- calcolo punto estremo destro
local ptSplitXRight
if bFeatureStartsOnEdgeRight then
dSplitXRight = min( ( Proc.b3Box:getMax():getX() - dMinSegmentLength), Part.b3Part:getMax():getX() - dMaxSegmentLengthOnEdges)
if dSplitXRight - dSplitXLeft < 500 * GEO.EPS_SMALL then
dSplitXRight = dSplitXLeft - dToolOverlapBetweenSegments
dFeatureCentralLength = 0
else
dFeatureCentralLength = dSplitXRight - dSplitXLeft
end
ptSplitXRight = Point3d( dSplitXRight, 0, 0)
end
-- aggiungo eventuale punto estremo destro
if bFeatureStartsOnEdgeRight then
table.insert( FeatureSplittingPoints, ptSplitXRight)
end
-- aggiungo punti centrali della feature
if dFeatureCentralLength > 0 then
local nSplitParts = max( ceil( dFeatureCentralLength / dMaxSegmentLength + 10 * GEO.EPS_SMALL), 1)
local dSplitPartsLen = dFeatureCentralLength / nSplitParts
for i = 1, ( nSplitParts - 1) do
local ptOn
local dCurrentPointX = dSplitXRight - i * dSplitPartsLen
ptOn = Point3d( dCurrentPointX, 0, 0)
table.insert( FeatureSplittingPoints, ptOn)
end
end
-- aggiungo eventuale punto estemo sinistro
if bFeatureStartsOnEdgeLeft then
table.insert( FeatureSplittingPoints, ptSplitXLeft)
end
return FeatureSplittingPoints
end
-------------------------------------------------------------------------------------------------------------
function FeatureLib.GetAdditionalInfo( Proc, Part)
-- se foro calcolo altri dati
if ID.IsDrilling( Proc) then
-- assegno diametro e facce di ingresso e uscita (dati tabelle sempre per riferimento)
Proc.dDiam, Proc.dLen, Proc.nFcs, Proc.nFce = FeatureLib.GetDrillingData( Proc)
end
return Proc
end
-------------------------------------------------------------------------------------------------------------
function FeatureLib.GetFeatureVolume( Proc, Part)
local dProcVolume = 0
local nAddGrpId = BeamLib.GetAddGroup( Proc.idPart)
if not nAddGrpId then
-- TODO gestire meglio questo errore. Non conviene creare e verificare all'inizio se il gruppo esiste?
EgtOutLog( 'Error : missing AddGroup')
return 0
end
local idProcCopy = EgtCopyGlob( Proc.id, nAddGrpId) or GDB_ID.NULL
local b3PartCopy = BBox3d( Part.b3Part)
b3PartCopy:expand( -100 * GEO.EPS_SMALL)
local idPartCopy = EgtSurfTmBBox( nAddGrpId, b3PartCopy , false, GDB_RT.GLOB)
EgtSurfTmSubtract( idPartCopy, idProcCopy)
dProcVolume = EgtSurfVolume( idPartCopy)
EgtErase( { idProcCopy, idPartCopy})
return dProcVolume
end
-------------------------------------------------------------------------------------------------------------
-- TODO funzione copiata direttamente da automatismo vecchio, da migliorare / completare
function FeatureLib.CalculateFeatureNotClampableLengths( Proc, Part)
local NotClampableLength = {}
-- verifico siano una o due facce
if Proc.nFct > 2 then return end
-- eventuale segnalazione ingombro di testa o coda
local dMinHIng = min( 0.5 * BeamData.VICE_MINH, 0.5 * Part.b3Raw:getDimZ())
local dMinZ = max( BeamData.MIN_HEIGHT, 0.35 * Part.b3Raw:getDimZ())
-- calcolo punto massimo in Z fino a dove considerare il pinzaggio. Minimo tra pinzaggio massimo e altezza pezzo
local dMaxHZ = Part.b3Raw:getMin():getZ() + min( BeamData.VICE_MAXH or BeamData.MAX_HEIGHT, Part.b3Raw:getDimZ())
-- punto massimo in Z considerando anche la Z della feature
local dMaxHZFeat = min( dMaxHZ, Proc.b3Box:getMax():getZ())
-- dimensione Z del pinzaggio (differenza massima Z pinzabile e box feature)
local dDeltaZClamp = ( ( dMaxHZ - Part.b3Raw:getMin():getZ()) - max( 0, dMaxHZFeat - Proc.b3Box:getMin():getZ()))
-- se pinzaggio minimo è come il massimo (oppure come l'altezza massima del pezzo) significa che è verticale
local bIsVertClamps = BeamData.VICE_MINH > BeamData.MAX_HEIGHT - 100 * GEO.EPS_SMALL
-- condizioni per limitare pinzaggio testa/coda
local bUpdateIng = true
-- se dimensione del box della feature maggiore di metà pinzaggio minimo o metà spessore pezzo
bUpdateIng = bUpdateIng and Proc.b3Box:getDimZ() > dMinHIng
-- se la feature si trova più in basso del minimo pinzabile in Z o il 35% dello spessore pezzo
bUpdateIng = bUpdateIng and Proc.b3Box:getMin():getZ() < Part.b3Raw:getMin():getZ() + dMinZ
-- se feature è al di sotto del pinzaggio massimo
bUpdateIng = bUpdateIng and Proc.b3Box:getMin():getZ() < dMaxHZ
-- se ho le morse verticali, o se la feature è in centro o verso alto, controllo se non prendo abbastanza.
if bIsVertClamps or ( Proc.b3Box:getMin():getZ() - Part.b3Raw:getMin():getZ()) > BeamData.MIN_HEIGHT then
bUpdateIng = bUpdateIng and dDeltaZClamp < BeamData.VICE_MINH
end
local dNotClampableLengthHead = 0
local dNotClampableLengthTail = 0
if bUpdateIng then
if Proc.AffectedFaces.bRight then
local dOffs = Part.b3Part:getMax():getX() - Proc.b3Box:getMin():getX()
-- se pinze a 45° e pinza abbastanza materiale, compenso comunque, ma solo inclinazione morse
if not bIsVertClamps and dDeltaZClamp > BeamData.VICE_MINH and BeamData.VICE_MAXH then
dOffs = min( dOffs, BeamData.VICE_MAXH - BeamData.VICE_MINH)
end
dNotClampableLengthHead = dOffs
elseif Proc.AffectedFaces.bLeft then
local dOffs = Proc.b3Box:getMax():getX() - Part.b3Part:getMin():getX()
-- se pinze a 45° e pinza abbastanza materiale, compenso comunque, ma solo inclinazione morse
if not bIsVertClamps and dDeltaZClamp > BeamData.VICE_MINH and BeamData.VICE_MAXH then
dOffs = min( dOffs, BeamData.VICE_MAXH - BeamData.VICE_MINH)
end
dNotClampableLengthTail = dOffs
elseif Proc.b3Box:getCenter():getX() > Part.b3Part:getCenter():getX() then
local dOffs = Part.b3Part:getMax():getX() - Proc.b3Box:getMin():getX()
local dDist = Part.b3Part:getMax():getX() - Proc.b3Box:getMax():getX()
-- se pinze a 45° e pinza abbastanza materiale, compenso comunque, ma solo inclinazione morse
if not bIsVertClamps and dDeltaZClamp > BeamData.VICE_MINH and BeamData.VICE_MAXH then
dOffs = min( dOffs, BeamData.VICE_MAXH - BeamData.VICE_MINH)
end
-- dDist serve??
dNotClampableLengthHead = dOffs
end
end
NotClampableLength.dNotClampableLengthHead = dNotClampableLengthHead
NotClampableLength.dNotClampableLengthTail = dNotClampableLengthTail
return NotClampableLength
end
-------------------------------------------------------------------------------------------------------------
function FeatureLib.GetFeatureMaxNotClampableLengths( Proc, Part)
local nPartIndex = Part.nIndexInParts
local nProcIndex = Proc.nIndexInVProc
local Rotations = PROCESSINGS[nPartIndex].Rotation
local dMaxOnHead = 0
local dMaxOnTail = 0
for i = 1, #Part.CombinationList do
for j = 1, 4 do
-- controllo che la rotazione sia attiva
if string.sub( Part.CombinationList[i].sBitIndexCombination, j, j) == '1' then
dMaxOnHead = max( Rotations[j][nProcIndex].NotClampableLength.dNotClampableLengthHead, dMaxOnHead)
dMaxOnTail = max( Rotations[j][nProcIndex].NotClampableLength.dNotClampableLengthTail, dMaxOnTail)
end
end
end
return dMaxOnHead, dMaxOnTail
end
-------------------------------------------------------------------------------------------------------------
return FeatureLib
+2 -2
View File
@@ -13,8 +13,8 @@ function Identity.IsHeadCut( Proc)
return ( Proc.nGrp == 1 and Proc.nPrc == 340)
end
---------------------------------------------------------------------
-- Feature : Split Cut
function Identity.IsSplitCut( Proc)
-- Feature : Tail Cut
function Identity.IsTailCut( Proc)
return ( Proc.nGrp == 2 and Proc.nPrc == 350)
end
+213
View File
@@ -0,0 +1,213 @@
-- Logs.lua by Egalware s.r.l. 2024/11/20
-- Libreria per logs vari
-- Tabella per definizione modulo
local Logs = {}
-------------------------------------------------------------------------------------------------------------
function Logs.WriteFeaturesLog( ProcessingsOnPart, PartInfo)
EgtOutLog( ' === === === === === === === === === === FEATURES STRATEGIES === === === === === === === === === === === ===')
EgtOutLog( ' Feature ID | BTL POSITION | 90 ROTATION | 180 ROTATION | 270 ROTATION |')
EgtOutLog( '----------------------------------------------------------------------------------------------------------')
local nProcessingsNumber
local nFirstAvailableRotation
-- ricerco prima rotazione effettivamente calcolata. In genere è sempre la prima
for i = 1, 4 do
if PartInfo.CombinationList.Rotations[i] == 1 then
nProcessingsNumber = #ProcessingsOnPart.Rotation[i]
nFirstAvailableRotation = i
break
end
end
-- per ogni feature
for ProcLog = 1, nProcessingsNumber do
-- ricavo il massimo numero di strategie per feature
local nMaxStrategiesPerFeature = 0
for nRotLog = 1, 4 do
if PartInfo.CombinationList.Rotations[nRotLog] == 1 and ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies then
nMaxStrategiesPerFeature = max( nMaxStrategiesPerFeature, #ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies)
end
end
-- ciclo su tutte le strategie
for nCountStrategies = 1, nMaxStrategiesPerFeature do
local sLogLine = ''
-- al primo ciclo scrivo ID feature
if nCountStrategies == 1 then
sLogLine = ' ' .. tostring( ProcessingsOnPart.Rotation[nFirstAvailableRotation][ProcLog].id)
while string.len( sLogLine) <= 20 do
sLogLine = sLogLine .. ' '
end
sLogLine = sLogLine .. '|'
else
sLogLine = ' |'
end
for nRotLog = 1, 4 do
-- se rotazione abilitata
if PartInfo.CombinationList.Rotations[nRotLog] == 1 then
-- se ci sono strategie
if ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies and ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies] then
-- se la strategia è stat processata e ha un risultato
if ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies].Result then
-- leggo lo stato della strategia per aggiungere un suffisso
local sStatusStrategy = ' '
if not ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies].Result.sStatus or
ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies].Result.sStatus == 'Not-Applicable' then
sStatusStrategy = 'N'
elseif ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies].Result.sStatus == 'Completed' then
sStatusStrategy = 'C'
elseif ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies].Result.sStatus == 'Not-Completed' then
sStatusStrategy = 'P'
end
-- se c'è una chosen strategy, si aggiunge prefisso '*' per indicare nel log qual è la strategia che è stata scelta
local nIndexBestStrategy = ProcessingsOnPart.Rotation[nRotLog][ProcLog].nIndexBestStrategy or 0
local sLogLineProc = EgtIf( nIndexBestStrategy == nCountStrategies, '*', '') ..
tostring( ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies].Result.dCompositeRating) ..' (' ..
tostring( ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies].sStrategyId) .. ')' ..
sStatusStrategy .. ' |'
while string.len( sLogLineProc) <= 20 do
sLogLineProc = ' ' .. sLogLineProc
end
sLogLine = sLogLine .. sLogLineProc
else
sLogLine = sLogLine .. ' 0 (STR----)- |'
end
else
sLogLine = sLogLine .. ' |'
end
-- rotazione non presa in considerazione
else
if nCountStrategies == 1 then
sLogLine = sLogLine .. ' ---------- |'
else
sLogLine = sLogLine .. ' |'
end
end
end
EgtOutLog( sLogLine)
end
end
EgtOutLog( '----------------------------------------------------------------------------------------------------------')
end
-------------------------------------------------------------------------------------------------------------
function Logs.WriteMatrixLog( ProcessingsOnPart, PartInfo)
EgtOutLog( ' === === === === === === === === === === ROTATION MATRIX === === === === === === === === === === === === ===')
EgtOutLog( ' Feature ID | BTL POSITION | 90 ROTATION | 180 ROTATION | 270 ROTATION |')
EgtOutLog( '----------------------------------------------------------------------------------------------------------')
local nProcessingsNumber
local nFirstAvailableRotation
-- ricerco prima rotazione effettivamente calcolata. In genere è sempre la prima
for i = 1, 4 do
if PartInfo.CombinationList.Rotations[i] == 1 then
nProcessingsNumber = #ProcessingsOnPart.Rotation[i]
nFirstAvailableRotation = i
break
end
end
for ProcLog = 1, nProcessingsNumber do
local sLogLine = ' ' .. tostring( ProcessingsOnPart.Rotation[nFirstAvailableRotation][ProcLog].id)
while string.len( sLogLine) <= 20 do
sLogLine = sLogLine .. ' '
end
sLogLine = sLogLine .. '|'
for nRotLog = 1, 4 do
if PartInfo.CombinationList.Rotations[nRotLog] == 1 then
if ProcessingsOnPart.Rotation[nRotLog][ProcLog].ChosenStrategy then
local sStatusStrategy = EgtIf( ProcessingsOnPart.Rotation[nRotLog][ProcLog].ChosenStrategy.Result.sStatus == 'Completed', 'C', 'P')
local sLogLineProc = tostring( ProcessingsOnPart.Rotation[nRotLog][ProcLog].ChosenStrategy.Result.dCompositeRating) ..
' (' .. tostring( ProcessingsOnPart.Rotation[nRotLog][ProcLog].ChosenStrategy.sStrategyId) .. ')' .. sStatusStrategy .. ' |'
while string.len( sLogLineProc) <= 20 do
sLogLineProc = ' ' .. sLogLineProc
end
sLogLine = sLogLine .. sLogLineProc
else
sLogLine = sLogLine .. ' 0 (STR----)- |'
end
else
sLogLine = sLogLine .. ' ---------- |'
end
end
EgtOutLog( sLogLine)
end
EgtOutLog( '----------------------------------------------------------------------------------------------------------')
end
-------------------------------------------------------------------------------------------------------------
function Logs.WriteCombinationLog( CombinationsList, BestCombination)
EgtOutLog( ' === === === === === === === === === === COMBINATIONS === === === === === === ')
EgtOutLog( ' COMBI (UNL) | RATING | COMPLETE | NO COMPL | NO EXEC | ROTATE |')
EgtOutLog( '---------------------------------------------------------------------------')
for CombiLog = 1, #CombinationsList do
local sLogLine = ' ' .. CombinationsList[CombiLog].sBitIndexCombination .. ' (' .. CombinationsList[CombiLog].nUnloadPos .. ') |'
-- rating
local sOtherField = tostring( CombinationsList[CombiLog].dTotalRating) .. ' |'
while string.len( sOtherField) <= 11 do
sOtherField = ' ' .. sOtherField
end
sLogLine = sLogLine .. sOtherField
-- completed
sOtherField = tostring( CombinationsList[CombiLog].nComplete) .. ' |'
while string.len( sOtherField) <= 11 do
sOtherField = ' ' .. sOtherField
end
sLogLine = sLogLine .. sOtherField
-- not completed
sOtherField = tostring( CombinationsList[CombiLog].nNotComplete) .. ' |'
while string.len( sOtherField) <= 11 do
sOtherField = ' ' .. sOtherField
end
sLogLine = sLogLine .. sOtherField
-- not executed
sOtherField = tostring( CombinationsList[CombiLog].nNotExecute) .. ' |'
while string.len( sOtherField) <= 11 do
sOtherField = ' ' .. sOtherField
end
sLogLine = sLogLine .. sOtherField
-- rotations
sOtherField = tostring( CombinationsList[CombiLog].nRotations) .. ' |'
while string.len( sOtherField) <= 11 do
sOtherField = ' ' .. sOtherField
end
sLogLine = sLogLine .. sOtherField
EgtOutLog( sLogLine)
end
EgtOutLog( '---------------------------------------------------------------------------')
EgtOutLog( ' BEST ROTATION : ' .. BestCombination.sBitIndexCombination .. ' (' .. BestCombination.nUnloadPos .. ')')
EgtOutLog( '---------------------------')
end
-------------------------------------------------------------------------------------------------------------
function Logs.WriteMainFacesLog( Proc, MainFaces)
if MainFaces.BottomFaces then
for i = 1, #MainFaces.BottomFaces do
EgtOutLog( 'Bottom Face : ' .. MainFaces.BottomFaces[i].id)
end
-- colore differente per la faccia di fondo principale
EgtSurfTmSetFaceColor( Proc.id, MainFaces.BottomFaces[1].id, 1)
end
if MainFaces.LongFaces then
for i = 1, #MainFaces.LongFaces do
EgtOutLog( 'Long Face : ' .. MainFaces.LongFaces[i].id)
end
end
if MainFaces.SideFaces then
for i = 1, #MainFaces.SideFaces do
EgtOutLog( 'Side Face : ' .. MainFaces.SideFaces[i].id)
end
end
if MainFaces.TunnelAddedFaces then
EgtOutLog( 'Middle Face (Trimesh): ' .. MainFaces.TunnelAddedFaces.MiddleFaceTm.id)
end
end
---------------------------------------------------------------------
return Logs
+521 -120
View File
@@ -10,6 +10,8 @@ require( 'EgtBase')
-- Carico i dati globali
local BeamData = require( 'BeamData')
local BeamLib = require( 'BeamLib')
local FeatureLib = require( 'FeatureLib')
EgtOutLog( ' MachiningLib started', 1)
@@ -58,21 +60,143 @@ local function GetToolEntryAngle( Proc, vtTool)
Angle.dTan = dTanAngle
return Angle
end
end
-------------------------------------------------------------------------------------------------------------
function MachiningLib.StartsLeftSide( Machining)
local bStartsLeftSide = ( Machining.vtEdgeDirection:getX() > 10 * GEO.EPS_SMALL and not Machining.bInvert)
or ( not( Machining.vtEdgeDirection:getX() > 10 * GEO.EPS_SMALL) and Machining.bInvert)
return bStartsLeftSide
end
-------------------------------------------------------------------------------------------------------------
-- TODO valutare se c'è un modo più preciso di prevedere i casi in cui le lavorazioni dopo separazione sono da saltare
function MachiningLib.CanMoveAfterSplitcut( dLengthOnX, Part)
local bCanMoveAfterSplitcut = ( Part.dLength > BeamData.dMinRaw + 10 * GEO.EPS_SMALL)
and ( dLengthOnX < 0.7 * Part.dLength - 10 * GEO.EPS_SMALL)
return bCanMoveAfterSplitcut
end
-------------------------------------------------------------------------------------------------------------
function MachiningLib.CanExtendAfterTail( sCanDamageNextPiece, Part)
local bCanExtendAfterTail = false
if sCanDamageNextPiece == 'ALWAYS' then
bCanExtendAfterTail = true
elseif sCanDamageNextPiece == 'ONLY_IF_RAWPART' then
bCanExtendAfterTail = Part.bIsLastPart
end
return bCanExtendAfterTail
end
-------------------------------------------------------------------------------------------------------------
function MachiningLib.GetMachiningSteps( dMachiningDepth, dStep)
local MachiningSteps = {}
MachiningSteps.dStep = 0
MachiningSteps.nCount = ceil( ( dMachiningDepth - 10 * GEO.EPS_SMALL) / dStep)
if MachiningSteps.nCount > 1 then
MachiningSteps.dStep = ( dMachiningDepth - dStep) / ( MachiningSteps.nCount - 1)
else
MachiningSteps.nCount = 1
end
return MachiningSteps
end
-------------------------------------------------------------------------------------------------------------
function MachiningLib.GetSplitMachinings( Machinings, SplittingPoints, Part )
for i = #Machinings, 1, -1 do
local nParts = #SplittingPoints + 1
local dEdgeMaxX = Machinings[i].ptEdge1:getX()
local dEdgeMinX = Machinings[i].ptEdge2:getX()
if Machinings[i].ptEdge1:getX() < Machinings[i].ptEdge2:getX() - 10 * GEO.EPS_SMALL then
dEdgeMaxX = Machinings[i].ptEdge2:getX()
dEdgeMinX = Machinings[i].ptEdge1:getX()
end
local dOriginalStartAddLength = Machinings[i].LeadIn.dStartAddLength
local dOriginalEndAddLength = Machinings[i].LeadOut.dEndAddLength
local sOriginalStage = Machinings[i].sStage
if FeatureLib.IsMachiningLong( Machinings[i].dLengthOnX, Part) then
local nCurrentMachiningIndex = i
-- lo spezzone attivo è quello precedente al punto di spezzatura corrente
for j = 1, nParts do
-- check ultimo segmento della lavorazione (NON della feature)
local bIsLastSegment = ( nParts == 1)
or ( ( ( j ~= 1) and SplittingPoints[j - 1]:getX() > dEdgeMinX + 10 * GEO.EPS_SMALL)
and ( j == nParts or SplittingPoints[j]:getX() < dEdgeMinX + 10 * GEO.EPS_SMALL))
-- se non è l'ultimo segmento della lavorazione, il punto di spezzatura deve essere all'interno del lato che si sta lavorando
if ( j ~= nParts and ( SplittingPoints[j]:getX() > dEdgeMinX + 10 * GEO.EPS_SMALL and SplittingPoints[j]:getX() < dEdgeMaxX - 10 * GEO.EPS_SMALL))
or bIsLastSegment then
if j > 1 then
nCurrentMachiningIndex = nCurrentMachiningIndex + 1
table.insert( Machinings, nCurrentMachiningIndex, BeamLib.TableCopyDeep( Machinings[i]))
end
local dStartAddLength = dOriginalStartAddLength
local dEndAddLength = dOriginalEndAddLength
if MachiningLib.StartsLeftSide( Machinings[i]) then
dStartAddLength, dEndAddLength = dEndAddLength, dStartAddLength
end
if j == 1 then
dEndAddLength = - ( SplittingPoints[j]:getX() - dEdgeMinX) + BeamData.MILL_OVERLAP
Machinings[nCurrentMachiningIndex].ptCenter = Point3d( SplittingPoints[j]:getX() + ( dEdgeMaxX - SplittingPoints[j]:getX()) / 2, 0, 0)
elseif j == nParts then
dStartAddLength = - ( dEdgeMaxX - SplittingPoints[j - 1]:getX()) + BeamData.MILL_OVERLAP
Machinings[nCurrentMachiningIndex].ptCenter = Point3d( dEdgeMinX + ( SplittingPoints[j - 1]:getX() - dEdgeMinX) / 2, 0, 0)
else
dStartAddLength = - ( dEdgeMaxX - SplittingPoints[j - 1]:getX()) + BeamData.MILL_OVERLAP
dEndAddLength = - ( SplittingPoints[j]:getX() - dEdgeMinX) + BeamData.MILL_OVERLAP
Machinings[nCurrentMachiningIndex].ptCenter = Point3d( SplittingPoints[j]:getX() + ( SplittingPoints[j - 1]:getX() - SplittingPoints[j]:getX()) / 2, 0, 0)
end
if MachiningLib.StartsLeftSide( Machinings[nCurrentMachiningIndex]) then
dStartAddLength, dEndAddLength = dEndAddLength, dStartAddLength
end
Machinings[nCurrentMachiningIndex].LeadIn.dStartAddLength = dStartAddLength
Machinings[nCurrentMachiningIndex].LeadOut.dEndAddLength = dEndAddLength
end
if not bIsLastSegment then
Machinings[nCurrentMachiningIndex].sStage = ''
else
Machinings[nCurrentMachiningIndex].sStage = sOriginalStage
end
Machinings[nCurrentMachiningIndex].nFeatureSegment = j
end
-- anche le lavorazioni non splittate necessitano del segmento assegnato
else
local dRightAddLength = 0
local dLeftAddLength = 0
-- si considerano allungamenti e accorciamenti solo se la feature è orientata principalmente lungo X
-- TODO il modo corretto è proiettare tutto, allungamenti e accorciamenti compresi, sulla faccia frontale
if abs( Machinings[i].vtToolDirection:getX()) < 0.707 then
dRightAddLength = dOriginalStartAddLength
dLeftAddLength = dOriginalEndAddLength
if MachiningLib.StartsLeftSide( Machinings[i]) then
dRightAddLength, dLeftAddLength = dLeftAddLength, dRightAddLength
end
end
for j = 1, nParts do
local dNextSplitX = dEdgeMinX
local dPreviousSplitX = dEdgeMaxX
if j ~= 1 then
dPreviousSplitX = SplittingPoints[j - 1]:getX()
end
if j ~= nParts then
dNextSplitX = SplittingPoints[j]:getX()
end
if ( dEdgeMinX - dLeftAddLength) > dNextSplitX - 10 * GEO.EPS_SMALL and ( dEdgeMinX - dLeftAddLength) < dPreviousSplitX + 10 * GEO.EPS_SMALL then
Machinings[i].nFeatureSegment = j
Machinings[i].ptCenter = Point3d( dNextSplitX + ( dPreviousSplitX - dNextSplitX) / 2, 0, 0)
end
end
end
end
return Machinings
end
-------------------------------------------------------------------------------------------------------------
-- funzione per cercare utensile tipo FRESA con certe caratteristiche
function MachiningLib.FindMill( Proc, ToolSearchParameters)
@@ -146,7 +270,7 @@ function MachiningLib.FindMill( Proc, ToolSearchParameters)
-- se hanno stesso montaggio
elseif TOOLS[i].SetupInfo.bToolOnAggregate == TOOLS[nBestToolIndex].SetupInfo.bToolOnAggregate then
-- scelgo utensile con indice di bontà utensile calcolato come: lunghezza / massimo materiale / diametro
if ( TOOLS[i].dLength / TOOLS[i].dMaxMaterial) / TOOLS[i].dDiameter < ( TOOLS[nBestToolIndex].dLength / TOOLS[nBestToolIndex].dMaxMaterial) / TOOLS[nBestToolIndex].dDiameter then
if TOOLS[i].dPerformanceIndex > TOOLS[nBestToolIndex].dPerformanceIndex then
nBestToolIndex = i
dBestToolResidualDepth = dCurrentResidualDepth
end
@@ -202,12 +326,20 @@ function MachiningLib.FindBlade( Proc, ToolSearchParameters)
bIsToolCompatible = TOOLS[i].SetupInfo.bIsTopHead
elseif ToolSearchParameters.bAllowBottomHead and not ToolSearchParameters.bAllowTopHead then
bIsToolCompatible = TOOLS[i].SetupInfo.bIsBottomHead
else
bIsToolCompatible = true
end
end
if bIsToolCompatible then
nBestToolIndex = i
break
if not nBestToolIndex then
nBestToolIndex = i
else
-- prediligo utensile per tagli lunghi, se richiesto
if ToolSearchParameters.bForceLongcutBlade and not TOOLS[nBestToolIndex].bIsUsedForLongCut and TOOLS[i].bIsUsedForLongCut then
nBestToolIndex = i
end
end
end
end
@@ -230,16 +362,16 @@ function MachiningLib.FindChainSaw( Proc, ToolSearchParameters)
-- parametri obbligatori
if type( ToolSearchParameters.vtToolDirection) ~= 'table' then
error( 'FindBlade : missing tool direction')
error( 'FindChainSaw : missing tool direction')
end
if type( ToolSearchParameters.bAllowTopHead) ~= 'boolean' then
error( 'FindBlade : missing top head info')
error( 'FindChainSaw : missing top head info')
end
if type( ToolSearchParameters.bAllowBottomHead) ~= 'boolean' then
error( 'FindBlade : missing bottom head info')
error( 'FindChainSaw : missing bottom head info')
end
if not ToolSearchParameters.bAllowTopHead and not ToolSearchParameters.bAllowBottomHead then
error( 'FindBlade : wrong head info')
error( 'FindChainSaw : wrong head info')
end
-- parametri opzionali
@@ -277,7 +409,7 @@ function MachiningLib.FindChainSaw( Proc, ToolSearchParameters)
-- se entrambi completi
if dBestToolResidualDepth <= 0 and dCurrentResidualDepth <= 0 then
-- scelgo utensile con rapporto lunghezza / diametro minore
if ( TOOLS[i].dLength / pow( TOOLS[i].dDiameter, 1.5)) < ( TOOLS[nBestToolIndex].dLength / pow( TOOLS[nBestToolIndex].dDiameter, 1.5)) then
if TOOLS[i].dPerformanceIndex > TOOLS[nBestToolIndex].dPerformanceIndex then
nBestToolIndex = i
dBestToolResidualDepth = dCurrentResidualDepth
end
@@ -307,27 +439,27 @@ function MachiningLib.AddNewMachining( ProcToAdd, MachiningToAdd, AuxiliaryDataT
return false
end
-- Drilling
if MachiningToAdd.nType == MCH_MY.DRILLING then
MachiningToAdd.sTypeName = 'Drill_'
-- Milling
elseif MachiningToAdd.nType == MCH_MY.MILLING then
-- se utensile lama
if TOOLS[MachiningToAdd.nToolIndex].sFamily == 'SAWBLADE' then
MachiningToAdd.sTypeName = 'Cut_'
else
MachiningToAdd.sTypeName = 'Mill_'
end
-- Pocketing
elseif MachiningToAdd.nType == MCH_MY.POCKETING then
MachiningToAdd.sTypeName = 'Pocket_'
-- Mortising
elseif MachiningToAdd.nType == MCH_MY.MORTISING then
MachiningToAdd.sTypeName = 'ChSaw_'
end
-- se nome non definito, assegno alla lavorazioen un nome standard
if not MachiningToAdd.sOperationName then
MachiningToAdd.sOperationName = MachiningToAdd.sTypeName .. ( EgtGetName( ProcToAdd.id) or tostring( ProcToAdd.id)) .. '_' .. tostring( MachiningToAdd.Geometry[1][2])
-- Drilling
if MachiningToAdd.nType == MCH_MY.DRILLING then
MachiningToAdd.sTypeName = 'Drill_'
-- Milling
elseif MachiningToAdd.nType == MCH_MY.MILLING then
-- se utensile lama
if TOOLS[MachiningToAdd.nToolIndex].sFamily == 'SAWBLADE' then
MachiningToAdd.sTypeName = 'Cut_'
else
MachiningToAdd.sTypeName = 'Mill_'
end
-- Pocketing
elseif MachiningToAdd.nType == MCH_MY.POCKETING then
MachiningToAdd.sTypeName = 'Pocket_'
-- Mortising
elseif MachiningToAdd.nType == MCH_MY.MORTISING then
MachiningToAdd.sTypeName = 'ChSaw_'
end
MachiningToAdd.sOperationName = MachiningToAdd.sTypeName .. ( EgtGetName( ProcToAdd.id) or tostring( ProcToAdd.id)) -- .. '_' .. tostring( MachiningToAdd.Geometry)
end
if not MachiningToAdd.sToolName then
MachiningToAdd.sToolName = TOOLS[MachiningToAdd.nToolIndex].sName
@@ -337,15 +469,17 @@ function MachiningLib.AddNewMachining( ProcToAdd, MachiningToAdd, AuxiliaryDataT
Machining.Machining = MachiningToAdd
Machining.AuxiliaryData = AuxiliaryDataToAdd or {}
table.insert( MACHININGS, Machining)
return true
end
-------------------------------------------------------------------------------------------------------------
-- funzione per aggiungere una nuova lavorazione
function MachiningLib.AddOperations( vProc, Part)
function MachiningLib.AddOperations( vProc, Part, sRotation)
local nErr
local sErr = ''
local bAreAllMachiningApplyOk = true
local bSplitExecuted = false
-- parametri generali lavorazione
local MachiningParameters = {
@@ -401,7 +535,13 @@ function MachiningLib.AddOperations( vProc, Part)
-- parametri da scrivere nelle note utente
local UserNotes = {
{ sName = 'dMaxElev', sMchParam = 'MaxElev'}
{ sName = 'dMaxElev', sMchParam = 'MaxElev'},
{ sName = 'dOpenMinSafe', sMchParam = 'OpenMinSafe'},
{ sName = 'nVMRS', sMchParam = 'VMRS'},
{ sName = 'dStartZmax', sMchParam = 'StartZmax'},
{ sName = 'nOutRaw', sMchParam = 'OutRaw'},
{ sName = 'nOpenOutRaw', sMchParam = 'OpenOutRaw'},
{ sName = 'nPlunge', sMchParam = 'Plunge'}
}
-- parametri da scrivere nelle note di sistema
@@ -409,114 +549,159 @@ function MachiningLib.AddOperations( vProc, Part)
}
for i = 1, #MACHININGS do
local nClonesToAdd = 1
if MACHININGS[i].AuxiliaryData.Clones then
nClonesToAdd = #MACHININGS[i].AuxiliaryData.Clones
end
for j = 1, nClonesToAdd do
-- creazione lavorazione
local nOperationId = EgtCreateMachining( MACHININGS[i].Machining.sOperationName, MACHININGS[i].Machining.nType, MACHININGS[i].Machining.sToolName)
-- si aggiungono solo quelle della fase richiesta
if ( sRotation == 'STD' and not MACHININGS[i].Proc.bDown and not MACHININGS[i].Proc.bSide) or
( MACHININGS[i].Proc.bDown and sRotation == 'DOWN') or
( MACHININGS[i].Proc.bSide and sRotation == 'SIDE') then
local nClonesToAdd = 1
if MACHININGS[i].AuxiliaryData.Clones then
nClonesToAdd = #MACHININGS[i].AuxiliaryData.Clones
end
for j = 1, nClonesToAdd do
-- creazione lavorazione
local nOperationId = EgtCreateMachining( MACHININGS[i].Machining.sOperationName, MACHININGS[i].Machining.nType, MACHININGS[i].Machining.sToolName)
if nOperationId then
-- impostazione geometria
EgtSetMachiningGeometry( MACHININGS[i].Machining.Geometry)
if nOperationId then
-- impostazione geometria
local Geometry
if MACHININGS[i].AuxiliaryData.Clones and MACHININGS[i].AuxiliaryData.Clones[j].Geometry then
Geometry = MACHININGS[i].AuxiliaryData.Clones[j].Geometry
elseif MACHININGS[i].Machining.Geometry then
Geometry = MACHININGS[i].Machining.Geometry
end
EgtSetMachiningGeometry( Geometry)
-- impostazione parametri lavorazione
-- TODO scrivere sempre Steps, LeadIn, LeadOut nelle tabelle in modo da non dover controllare ogni volta che ci siano
for k = 1, #MachiningParameters do
local sValue
if MACHININGS[i].AuxiliaryData.Clones and MACHININGS[i].AuxiliaryData.Clones[j][MachiningParameters[k].sName] then
sValue = MACHININGS[i].AuxiliaryData.Clones[j][MachiningParameters[k].sName]
elseif MACHININGS[i].Machining[MachiningParameters[k].sName] then
sValue = MACHININGS[i].Machining[MachiningParameters[k].sName]
-- impostazione parametri lavorazione
-- TODO scrivere sempre Steps, LeadIn, LeadOut nelle tabelle in modo da non dover controllare ogni volta che ci siano
for k = 1, #MachiningParameters do
local sValue
if MACHININGS[i].AuxiliaryData.Clones and MACHININGS[i].AuxiliaryData.Clones[j][MachiningParameters[k].sName] then
sValue = MACHININGS[i].AuxiliaryData.Clones[j][MachiningParameters[k].sName]
elseif MACHININGS[i].Machining[MachiningParameters[k].sName] then
sValue = MACHININGS[i].Machining[MachiningParameters[k].sName]
end
if sValue then
EgtSetMachiningParam( MachiningParameters[k].nMchParam, sValue)
end
end
if sValue then
EgtSetMachiningParam( MachiningParameters[k].nMchParam, sValue)
for k = 1, #MachiningParameters.Steps do
local sValue
if MACHININGS[i].AuxiliaryData.Clones and MACHININGS[i].AuxiliaryData.Clones[j].Steps and MACHININGS[i].AuxiliaryData.Clones[j].Steps[MachiningParameters.Steps[k].sName] then
sValue = MACHININGS[i].AuxiliaryData.Clones[j].Steps[MachiningParameters.Steps[k].sName]
elseif MACHININGS[i].Machining.Steps and MACHININGS[i].Machining.Steps[MachiningParameters.Steps[k].sName] then
sValue = MACHININGS[i].Machining.Steps[MachiningParameters.Steps[k].sName]
end
if sValue then
EgtSetMachiningParam( MachiningParameters.Steps[k].nMchParam, sValue)
end
end
end
for k = 1, #MachiningParameters.Steps do
local sValue
if MACHININGS[i].AuxiliaryData.Clones and MACHININGS[i].AuxiliaryData.Clones[j].Steps and MACHININGS[i].AuxiliaryData.Clones[j].Steps[MachiningParameters.Steps[k].sName] then
sValue = MACHININGS[i].AuxiliaryData.Clones[j].Steps[MachiningParameters.Steps[k].sName]
elseif MACHININGS[i].Machining.Steps and MACHININGS[i].Machining.Steps[MachiningParameters.Steps[k].sName] then
sValue = MACHININGS[i].Machining.Steps[MachiningParameters.Steps[k].sName]
for k = 1, #MachiningParameters.LeadIn do
local sValue
if MACHININGS[i].AuxiliaryData.Clones and MACHININGS[i].AuxiliaryData.Clones[j].LeadIn and MACHININGS[i].AuxiliaryData.Clones[j].LeadIn[MachiningParameters.LeadIn[k].sName] then
sValue = MACHININGS[i].AuxiliaryData.Clones[j].LeadIn[MachiningParameters.LeadIn[k].sName]
elseif MACHININGS[i].Machining.LeadIn and MACHININGS[i].Machining.LeadIn[MachiningParameters.LeadIn[k].sName] then
sValue = MACHININGS[i].Machining.LeadIn[MachiningParameters.LeadIn[k].sName]
end
if sValue then
EgtSetMachiningParam( MachiningParameters.LeadIn[k].nMchParam, sValue)
end
end
if sValue then
EgtSetMachiningParam( MachiningParameters.Steps[k].nMchParam, sValue)
for k = 1, #MachiningParameters.LeadOut do
local sValue
if MACHININGS[i].AuxiliaryData.Clones and MACHININGS[i].AuxiliaryData.Clones[j].LeadOut and MACHININGS[i].AuxiliaryData.Clones[j].LeadOut[MachiningParameters.LeadOut[k].sName] then
sValue = MACHININGS[i].AuxiliaryData.Clones[j].LeadOut[MachiningParameters.LeadOut[k].sName]
elseif MACHININGS[i].Machining.LeadOut and MACHININGS[i].Machining.LeadOut[MachiningParameters.LeadOut[k].sName] then
sValue = MACHININGS[i].Machining.LeadOut[MachiningParameters.LeadOut[k].sName]
end
if sValue then
EgtSetMachiningParam( MachiningParameters.LeadOut[k].nMchParam, sValue)
end
end
end
for k = 1, #MachiningParameters.LeadIn do
local sValue
if MACHININGS[i].AuxiliaryData.Clones and MACHININGS[i].AuxiliaryData.Clones[j].LeadIn and MACHININGS[i].AuxiliaryData.Clones[j].LeadIn[MachiningParameters.LeadIn[k].sName] then
sValue = MACHININGS[i].AuxiliaryData.Clones[j].LeadIn[MachiningParameters.LeadIn[k].sName]
elseif MACHININGS[i].Machining.LeadIn and MACHININGS[i].Machining.LeadIn[MachiningParameters.LeadIn[k].sName] then
sValue = MACHININGS[i].Machining.LeadIn[MachiningParameters.LeadIn[k].sName]
for k = 1, #UserNotes do
local sValue
if MACHININGS[i].AuxiliaryData.Clones and MACHININGS[i].AuxiliaryData.Clones[j][UserNotes[k].sName] then
sValue = MACHININGS[i].AuxiliaryData.Clones[j][UserNotes[k].sName]
elseif MACHININGS[i].Machining[UserNotes[k].sName] then
sValue = MACHININGS[i].Machining[UserNotes[k].sName]
end
if sValue then
local sUserNotes = ''
sUserNotes = EgtGetMachiningParam( MCH_MP.USERNOTES)
sUserNotes = EgtSetValInNotes( sUserNotes, UserNotes[k].sMchParam, sValue)
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
end
end
if sValue then
EgtSetMachiningParam( MachiningParameters.LeadIn[k].nMchParam, sValue)
-- parametri da settare nelle note di sistema
-- TODO da decidere quali sono le note da salvare qui. Probabilmente tutte quelle relative all'ordine delle lavorazioni
--if MACHININGS[i].Machining.nMachiningOrder then
-- sSystemNotes = EgtSetValInNotes( sSystemNotes, 'MachiningOrder', MACHININGS[i].Machining.nMachiningOrder)
--end
for k = 1, #SystemNotes do
local sValue
if MACHININGS[i].AuxiliaryData.Clones and MACHININGS[i].AuxiliaryData.Clones[j][SystemNotes[k].sName] then
sValue = MACHININGS[i].AuxiliaryData.Clones[j][SystemNotes[k].sName]
elseif MACHININGS[i].Machining[SystemNotes[k].sName] then
sValue = MACHININGS[i].Machining[SystemNotes[k].sName]
end
if sValue then
local sSystemNotes = ''
sSystemNotes = EgtGetMachiningParam( MCH_MP.SYSNOTES)
sSystemNotes = EgtSetValInNotes( sSystemNotes, SystemNotes[k].sMchParam, sValue)
EgtSetMachiningParam( MCH_MP.SYSNOTES, sSystemNotes)
end
end
end
for k = 1, #MachiningParameters.LeadOut do
local sValue
if MACHININGS[i].AuxiliaryData.Clones and MACHININGS[i].AuxiliaryData.Clones[j].LeadOut and MACHININGS[i].AuxiliaryData.Clones[j].LeadOut[MachiningParameters.LeadOut[k].sName] then
sValue = MACHININGS[i].AuxiliaryData.Clones[j].LeadOut[MachiningParameters.LeadOut[k].sName]
elseif MACHININGS[i].Machining.LeadOut and MACHININGS[i].Machining.LeadOut[MachiningParameters.LeadOut[k].sName] then
sValue = MACHININGS[i].Machining.LeadOut[MachiningParameters.LeadOut[k].sName]
end
if sValue then
EgtSetMachiningParam( MachiningParameters.LeadOut[k].nMchParam, sValue)
end
end
for k = 1, #UserNotes do
local sValue
if MACHININGS[i].AuxiliaryData.Clones and MACHININGS[i].AuxiliaryData.Clones[j][UserNotes[k].sName] then
sValue = MACHININGS[i].AuxiliaryData.Clones[j][UserNotes[k].sName]
elseif MACHININGS[i].Machining[UserNotes[k].sName] then
sValue = MACHININGS[i].Machining[UserNotes[k].sName]
end
if sValue then
local sUserNotes = ''
sUserNotes = EgtSetValInNotes( sUserNotes, UserNotes[k].sMchParam, sValue)
EgtSetMachiningParam( MCH_MP.USERNOTES, sUserNotes)
end
end
-- parametri da settare nelle note di sistema
-- TODO da decidere quali sono le note da salvare qui. Probabilmente tutte quelle relative all'ordine delle lavorazioni
--if MACHININGS[i].Machining.nMachiningOrder then
-- sSystemNotes = EgtSetValInNotes( sSystemNotes, 'MachiningOrder', MACHININGS[i].Machining.nMachiningOrder)
--end
for k = 1, #SystemNotes do
local sValue
if MACHININGS[i].AuxiliaryData.Clones and MACHININGS[i].AuxiliaryData.Clones[j][SystemNotes[k].sName] then
sValue = MACHININGS[i].AuxiliaryData.Clones[j][SystemNotes[k].sName]
elseif MACHININGS[i].Machining[SystemNotes[k].sName] then
sValue = MACHININGS[i].Machining[SystemNotes[k].sName]
end
if sValue then
local sSystemNotes = ''
sSystemNotes = EgtSetValInNotes( sSystemNotes, SystemNotes[k].sMchParam, sValue)
EgtSetMachiningParam( MCH_MP.SYSNOTES, sSystemNotes)
end
end
local bIsApplyOk = MachiningLib.ApplyMachining( true, false)
if not bIsApplyOk then
bAreAllMachiningApplyOk = false
nErr, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nOperationId, false)
local bIsApplyOk = MachiningLib.ApplyMachining( true, false)
if not bIsApplyOk then
bAreAllMachiningApplyOk = false
nErr, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nOperationId, false)
end
-- TODO è giusto inserire queste info alla fine della lavorazione? oppure conviene creare un record in MACHININGS apposito per la disposizione?
-- se era taglio di separazione, aggiungo nuova fase
if MACHININGS[i].AuxiliaryData.bIsSplitOrCut then
bSplitExecuted = true
BeamLib.AddPhaseWithRawParts( MACHININGS[i].Proc.idRaw, BeamData.ptOriXR, BeamData.dPosXR, BeamData.RAW_OFFSET)
-- se grezzo successivo senza pezzi e finale, va tolto
local nNextRawId = EgtGetNextRawPart( MACHININGS[i].Proc.idRaw)
if nNextRawId and EgtGetPartInRawPartCount( nNextRawId) == 0 and EgtGetRawPartBBox( nNextRawId):getDimX() < BeamData.dMinRaw then
EgtRemoveRawPartFromCurrPhase( nNextRawId)
end
local nPhase = EgtGetCurrPhase()
local nDispId = EgtGetPhaseDisposition( nPhase)
if sRotation == 'DOWN' then
local nRotation = EgtIf( Part.nInitialPosition + 2 > 4, Part.nInitialPosition + 2 - 4, Part.nInitialPosition + 2)
BeamLib.RotatePart( Part, nRotation)
EgtSetInfo( nDispId, 'ROT', -2)
EgtSetInfo( nDispId, 'TYPE', 'MID2')
elseif sRotation == 'SIDE' then
local nRotation = EgtIf( Part.nInitialPosition + 1 > 4, Part.nInitialPosition + 1 - 4, Part.nInitialPosition + 1)
BeamLib.RotatePart( Part, nRotation)
EgtSetInfo( nDispId, 'ROT', -1)
EgtSetInfo( nDispId, 'TYPE', 'MID2')
else
local nRotation = Part.nInitialPosition
BeamLib.RotatePart( Part, nRotation)
EgtSetInfo( nDispId, 'TYPE', 'END')
end
EgtSetInfo( nDispId, 'ORD', MACHININGS[i].Proc.nIndexPartInParts)
end
else
return false, 'UNEXPECTED ERROR: Error on creating machining', bSplitExecuted
end
else
return false, 'UNEXPECTED ERROR: Error on creating machining'
end
end
end
return bAreAllMachiningApplyOk, sErr
return bAreAllMachiningApplyOk, sErr, bSplitExecuted
end
-------------------------------------------------------------------------------------------------------------
function MachiningLib.ApplyMachining( bRecalc, bApplyPost)
local bResult = EgtApplyMachining( bRecalc, bApplyPost)
return bResult
end
@@ -544,5 +729,221 @@ function MachiningLib.GetToolMRR( Parameters)
return dMRR / pow( 10, 6)
end
-------------------------------------------------------------------------------------------------------------
function MachiningLib.PrepareMachiningsForSorting( Part)
local nFeatureInternalIndex = 1
for i = 1, #MACHININGS do
local MachiningCurrent = MACHININGS[i].Machining
local ProcCurrent = MACHININGS[i].Proc
if not MachiningCurrent.ptCenter then
MachiningCurrent.ptCenter = Point3d( ProcCurrent.b3Box:getCenter():getX(), 0, 0)
end
-- conversione campo sStage in nStage, numerico e ordinabile
if not MachiningCurrent.sStage or MachiningCurrent.sStage == '' then
MachiningCurrent.sStage = 'Middle'
end
if MachiningCurrent.sStage == 'Head' then
MachiningCurrent.nStage = 1
elseif MachiningCurrent.sStage == 'Tail' then
MachiningCurrent.nStage = 3
elseif MachiningCurrent.sStage == 'AfterTail' then
MachiningCurrent.nStage = 4
else
MachiningCurrent.nStage = 2
end
if i > 1 then
local MachiningPrevious = MACHININGS[i - 1].Machining
local ProcPrevious = MACHININGS[i - 1].Proc
if ProcCurrent.id == ProcPrevious.id then
-- nStage devono essere sempre uguali o crescenti nella stessa feature
if MachiningCurrent.nStage < MachiningPrevious.nStage then
MachiningCurrent.nStage = MachiningPrevious.nStage
end
-- assegnazione indice interno alla feature
nFeatureInternalIndex = nFeatureInternalIndex + 1
else
nFeatureInternalIndex = 1
end
end
MachiningCurrent.nFeatureInternalIndex = nFeatureInternalIndex
-- se fase di lavoro standard, assegnazione dello spezzone
if MachiningCurrent.nStage == 2 then
local nParts = #Part.SplittingPoints + 1
local dPartMinX = Part.b3Part:getMin():getX()
local dPartMaxX = Part.b3Part:getMax():getX()
for j = 1, nParts do
local dNextSplitX = dPartMinX
local dPreviousSplitX = dPartMaxX
if j ~= 1 then
dPreviousSplitX = Part.SplittingPoints[j - 1]:getX()
end
if j ~= nParts then
dNextSplitX = Part.SplittingPoints[j]:getX()
end
if MachiningCurrent.ptCenter:getX() > dNextSplitX - 10 * GEO.EPS_SMALL and MachiningCurrent.ptCenter:getX() < dPreviousSplitX + 10 * GEO.EPS_SMALL then
MachiningCurrent.nPartSegment = j
end
end
else
MachiningCurrent.nPartSegment = -1
end
end
return MACHININGS
end
-- TODO convertire in tabella in cui si chiamano direttamente i nomi delle funzioni, in modo da poter cambiare l'ordine facilmente
-- TODO libreria Sorting??
-------------------------------------------------------------------------------------------------------------
local SortingComparisonRules = {
-- ordine interno alla feature
function( MachiningA, MachiningB)
if MachiningA.Proc.id == MachiningB.Proc.id then
if MachiningA.Machining.nFeatureInternalIndex < MachiningB.Machining.nFeatureInternalIndex then
return 1
elseif MachiningA.Machining.nFeatureInternalIndex > MachiningB.Machining.nFeatureInternalIndex then
return -1
end
end
return 0
end,
-- dipendenze solo spostamento stage 2->4
-- TODO da fare
-- stage
function( MachiningA, MachiningB)
if MachiningA.Machining.nStage < MachiningB.Machining.nStage then
return 1
elseif MachiningA.Machining.nStage > MachiningB.Machining.nStage then
return -1
else
return 0
end
end,
-- dipendenze
-- TODO da fare
-- segment
function ( MachiningA, MachiningB)
if MachiningA.Machining.nPartSegment < MachiningB.Machining.nPartSegment then
return 1
elseif MachiningA.Machining.nPartSegment > MachiningB.Machining.nPartSegment then
return -1
else
return 0
end
end,
-- testa
-- TODO da fare
-- famiglia utensile
function ( MachiningA, MachiningB)
-- TODO tirare fuori da qua??
local ToolFamilyOrder = {
SAWBLADE = 1,
DRILLBIT = 2,
MILL = 3,
MORTISE = 4
}
local nToolFamilyOrderA = ToolFamilyOrder[ TOOLS[ MachiningA.Machining.nToolIndex].sFamily]
local nToolFamilyOrderB = ToolFamilyOrder[ TOOLS[ MachiningB.Machining.nToolIndex].sFamily]
if nToolFamilyOrderA < nToolFamilyOrderB then
return 1
elseif nToolFamilyOrderA > nToolFamilyOrderB then
return -1
else
return 0
end
end,
-- performance utensile
function( MachiningA, MachiningB)
local dToolPerformanceIndexA = TOOLS[MachiningA.Machining.nToolIndex].dPerformanceIndex
local dToolPerformanceIndexB = TOOLS[MachiningB.Machining.nToolIndex].dPerformanceIndex
if dToolPerformanceIndexA > dToolPerformanceIndexB then
return 1
elseif dToolPerformanceIndexA < dToolPerformanceIndexB then
return -1
else
return 0
end
end,
-- probabilmente arrivati qui significa che gli utensili A e B sono gli stessi
-- se così non fosse e tutte le caratteristiche sopra sono uguali, ordine alfabetico
function( MachiningA, MachiningB)
local sToolNameA = TOOLS[MachiningA.Machining.nToolIndex].sName
local sToolNameB = TOOLS[MachiningB.Machining.nToolIndex].sName
if sToolNameA < sToolNameB then
return 1
elseif sToolNameA > sToolNameB then
return -1
else
return 0
end
end,
-- lato di lavoro
-- TODO questo, insieme all'ordinamento X, andrà sostituito dallo shortest path pesato sulla quantità di rotazione della testa
function( MachiningA, MachiningB)
if MachiningA.Machining.vtToolDirection:getY() < 10 * GEO.EPS_SMALL and MachiningB.Machining.vtToolDirection:getY() >= 10 * GEO.EPS_SMALL then
return 1
elseif MachiningA.Machining.vtToolDirection:getY() >= 10 * GEO.EPS_SMALL and MachiningB.Machining.vtToolDirection:getY() < 10 * GEO.EPS_SMALL then
return -1
else
return 0
end
end,
-- ordinamento X
-- TODO questo andrà sostituito dallo shortest path pesato sulla quantità di rotazione della testa
function( MachiningA, MachiningB)
local bIsMachiningOnFront = MachiningA.Machining.vtToolDirection:getY() < 10 * GEO.EPS_SMALL
local nResult = 0
-- se lavorazione davanti ordine testa->coda
if bIsMachiningOnFront then
if MachiningA.Machining.ptCenter:getX() > MachiningB.Machining.ptCenter:getX() + 10 * GEO.EPS_SMALL then
nResult = 1
elseif MachiningA.Machining.ptCenter:getX() < MachiningB.Machining.ptCenter:getX() - 10 * GEO.EPS_SMALL then
nResult = -1
end
-- se lavorazione dietro ordine coda->testa
else
if MachiningA.Machining.ptCenter:getX() < MachiningB.Machining.ptCenter:getX() - 10 * GEO.EPS_SMALL then
nResult = 1
elseif MachiningA.Machining.ptCenter:getX() > MachiningB.Machining.ptCenter:getX() + 10 * GEO.EPS_SMALL then
nResult = -1
end
end
return nResult
end
}
-------------------------------------------------------------------------------------------------------------
function MachiningLib.CompareMachinings( MachiningA, MachiningB)
-- itera le SortingComparisonRules una per volta. Se non vi è alcuna scelta va avanti (result = 0), altrimenti ritorna true/false in base al risultato
for i = 1, #SortingComparisonRules do
local CompareFunction = SortingComparisonRules[i]
local result = CompareFunction( MachiningA, MachiningB)
if result ~= 0 then
return result > 0
end
end
return false
end
-------------------------------------------------------------------------------------------------------------
return MachiningLib
+25 -16
View File
@@ -7,13 +7,13 @@
-- Intestazioni
require( 'EgtBase')
_ENV = EgtProtectGlobal()
EgtEnableDebug( false)
EgtEnableDebug( true)
-- Imposto direttorio libreria specializzata per Travi
EgtAddToPackagePath( BEAM.BASEDIR .. '\\LuaLibs\\?.lua')
-- Imposto direttorio strategie. N.B. Le strategie dovranno essere caricate con il nome del direttorio padre
EgtAddToPackagePath( BEAM.BASEDIR .. '\\Strategies\\Standard\\?.lua')
EgtAddToPackagePath( BEAM.BASEDIR .. '\\Strategies\\Core\\?.lua')
EgtAddToPackagePath( BEAM.BASEDIR .. '\\StrategyLibs\\?.lua')
-- Verifico che la macchina corrente sia abilitata per la lavorazione delle Travi
local sMachDir = EgtGetCurrMachineDir()
@@ -39,9 +39,16 @@ _G.package.loaded.BeamLib = nil
_G.package.loaded.BeamData = nil
_G.package.loaded.Identity = nil
_G.package.loaded.BasicCustomerStrategies = nil
_G.package.loaded.FeatureData = nil
_G.package.loaded.FeatureLib = nil
_G.package.loaded.FaceData = nil
_G.package.loaded.MachiningLib = nil
_G.package.loaded.DiceCut = nil
_G.package.loaded.Logs = nil
-- strategie di base sempre presenti
_G.package.loaded['HEADCUT\\HEADCUT'] = nil
_G.package.loaded['HEADCUT\\HEADCUTConfig'] = nil
_G.package.loaded['TAILCUT\\TAILCUT'] = nil
_G.package.loaded['TAILCUT\\TAILCUTConfig'] = nil
-- TODO controllare se c'è un modo migliore per resettare librerie delle strategie caricate precedentemente
-- Per ottimizzare potremmo anche ciclare solo fino al numero di strategie raggiunto per il momento.
@@ -58,7 +65,7 @@ for i = 1, 9999 do
_G.package.loaded[sLibraryConfigToReload] = nil
end
end
local vtCoreStrategiesNames = EgtFindAllFiles( BEAM.BASEDIR .. '\\Strategies\\Core\\*.lua')
local vtCoreStrategiesNames = EgtFindAllFiles( BEAM.BASEDIR .. '\\StrategyLibs\\*.lua')
for i = 1, #vtCoreStrategiesNames do
local sCurrentName = EgtSplitString( vtCoreStrategiesNames[i], '.')[1]
if _G.package.loaded[sCurrentName] then
@@ -66,13 +73,14 @@ for i = 1, #vtCoreStrategiesNames do
end
end
local BeamExec = require( 'BeamExec')
-- Variabili globali
PARTS = {}
PARTS = {} -- tabella contenente tutte le informazioni di ogni pezzo
-- Carico i dati globali
local BeamData = require( 'BeamData')
-- carico librerie
local BeamExec = require( 'BeamExec')
-- Variabili di modulo
local dRawW
@@ -121,15 +129,15 @@ local function MyProcessInputData()
EgtOutBox( 'Box non definito per la trave ' .. PARTS[i].sName, 'Lavora Travi', 'ERROR')
return false
else
PARTS[i].b3Box = b3Solid
PARTS[i].b3PartOriginal = b3Solid
end
end
dRawW = PARTS[1].b3Box:getDimY()
dRawH = PARTS[1].b3Box:getDimZ()
dRawW = PARTS[1].b3PartOriginal:getDimY()
dRawH = PARTS[1].b3PartOriginal:getDimZ()
local vBeamErr = {}
for i = 2, #PARTS do
local dDimW = PARTS[i].b3Box:getDimY()
local dDimH = PARTS[i].b3Box:getDimZ()
local dDimW = PARTS[i].b3PartOriginal:getDimY()
local dDimH = PARTS[i].b3PartOriginal:getDimZ()
if ( abs( dDimW - dRawW) > 10 * GEO.EPS_SMALL or abs( dDimH - dRawH) > 10 * GEO.EPS_SMALL) and
( abs( dDimH - dRawW) > 10 * GEO.EPS_SMALL or abs( dDimW - dRawH) > 10 * GEO.EPS_SMALL) then
table.insert( vBeamErr, i)
@@ -176,9 +184,9 @@ local function MyProcessBeams()
-- Lunghezza totale delle travi
local dTotLen = 0
for i = 1, #PARTS - 1 do
dTotLen = dTotLen + PARTS[i].b3Box:getDimX()
dTotLen = dTotLen + PARTS[i].b3PartOriginal:getDimX()
end
dTotLen = dTotLen + max( PARTS[#PARTS].b3Box:getDimX(), BeamData.dMinRaw)
dTotLen = dTotLen + max( PARTS[#PARTS].b3PartOriginal:getDimX(), BeamData.dMinRaw)
local dAddLen = BeamData.OVM_HEAD + ( #PARTS - 1) * BeamData.OVM_MID
EgtOutLog( 'Ltot : '..EgtNumToString( dTotLen, 1) .. ' Lagg : '..EgtNumToString( dAddLen, 1)..' MinUnloadRaw : '.. EgtNumToString( BeamData.dMinRaw + BeamData.OVM_MID, 1), 1)
@@ -267,10 +275,10 @@ local function MyProcessBeams()
local bOrd = ( vsVal[5] == 'true')
if bOrd then
table.sort( PARTS, function( B1, B2)
if abs( B1.b3Box:getDimX() - B2.b3Box:getDimX()) < 1 then
if abs( B1.b3PartOriginal:getDimX() - B2.b3PartOriginal:getDimX()) < 1 then
return B1.nInd < B2.nInd
else
return B1.b3Box:getDimX() < B2.b3Box:getDimX()
return B1.b3PartOriginal:getDimX() < B2.b3PartOriginal:getDimX()
end
end)
end
@@ -298,7 +306,8 @@ end
-- *** Inserimento delle lavorazioni nelle travi ***
-------------------------------------------------------------------------------------------------------------
local function MyProcessFeatures()
local bOk, Stats = BeamExec.ProcessFeatures( PARTS)
BeamExec.GetProcessings( PARTS)
local bOk, Stats = BeamExec.ProcessMachinings( PARTS)
local nErrCnt = 0
local nWarnCnt = 0
local sOutput = ''
+391
View File
@@ -0,0 +1,391 @@
-- Strategia: HEADCUT
-- Descrizione
-- HeadCut
-- Feature: HeadCut
---------------------------------------------------------------------------------------------------------
-- TODO: HEADCUT copiata da SPLITCUT. Da sistemare e capire se fare solo una strategia oppure due divise.
---------------------------------------------------------------------------------------------------------
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
-- strategie di base
local FaceByBlade = require('FACEBYBLADE')
-- Tabella per definizione modulo
local HEADCUT = {}
local Strategy = {}
-------------------------------------------------------------------------------------------------------------
local function LoadStrategyParameters( CustomParameters)
local StrategyLib = {}
StrategyLib.Config = require( 'HEADCUT\\HEADCUTConfig')
Strategy.sName = StrategyLib.Config.sStrategyId
CustomParameters = BeamLib.GetUpdateCustomParameters( CustomParameters, StrategyLib.Config.Parameters)
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( CustomParameters)
Strategy.Result = {}
Strategy.Machining = {}
Strategy.Result.sInfo = ''
return Strategy
end
-------------------------------------------------------------------------------------------------------------
local function CalculateLeadInOut( Machining, EdgeToMachine)
local LeadIn = {}
local LeadOut = {}
LeadIn.dStartAddLength = 0
LeadOut.dEndAddLength = 0
LeadIn.nType = MCH_MILL_LI.LINEAR
LeadOut.nType = MCH_MILL_LI.LINEAR
LeadIn.dTangentDistance = 0
LeadOut.dTangentDistance = 0
LeadIn.dPerpDistance = BeamData.CUT_SIC + EdgeToMachine.dElevation
LeadOut.dPerpDistance = BeamData.CUT_SIC + EdgeToMachine.dElevation
LeadIn.dElevation = 0
LeadOut.dElevation = 0
LeadIn.dCompLength = 0
LeadOut.dCompLength = 0
LeadIn.dStartAddLength = BeamData.CUT_EXTRA
LeadOut.dEndAddLength = BeamData.CUT_EXTRA
return LeadIn, LeadOut
end
-------------------------------------------------------------------------------------------------------------
local function MakeChamfer()
-- TODO funzionalit da aggiungere
end
-------------------------------------------------------------------------------------------------------------
local function GetEdgeToMachine( Proc, vtEdge)
local Edge
for i = 1, #Proc.Faces[1].Edges do
if AreSameVectorApprox( Proc.Faces[1].Edges[i].vtN, vtEdge) then
Edge = Proc.Faces[1].Edges[i]
end
end
return Edge
end
-------------------------------------------------------------------------------------------------------------
local function GetSplitStrategy( Proc, Part)
-- se non sono stati caricati i parametri, si ricaricano
if not Strategy.Parameters then
Strategy = LoadStrategyParameters()
end
-- separazione solo se esiste grezzo successivo con pezzi o scaricabile
local nNextRawId = EgtGetNextRawPart( Part.idRaw)
Strategy.bSplit = ( nNextRawId and ( EgtGetPartInRawPartCount( nNextRawId) > 0 or EgtGetRawPartBBox( nNextRawId):getDimX() >= BeamData.dMinRaw))
-- imposto paraemtri di ricerca utensile in base a topologia
local Machining = {}
-- sTypeMachining = BladeSideSingle\ BladeSideDouble\ BladeHorizontalSingle\ BladeHorizontalDouble\ ChainSawHorizontal\ ChainSawSideSingle\ ChainSawSideDouble\ ChainSawPlusBlade\ Mill\ None
Machining.sTypeMachining = 'None'
local Splitting = {}
local ToolSearchParameters = {}
ToolSearchParameters.vtToolDirection = Proc.Faces[1].vtN
-- ===== RICERCA UTENSILE =====
-- cerco lama sopra
Splitting.bIsApplicable = false
ToolSearchParameters.bAllowTopHead = true
ToolSearchParameters.bAllowBottomHead = false
Splitting.ToolInfo = {}
Splitting.ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters)
if Splitting.ToolInfo.nToolIndex then
Splitting.bIsApplicable = true
local ParametersMRR = {}
ParametersMRR.nToolIndex = Splitting.ToolInfo.nToolIndex
Splitting.dMRR = MachiningLib.GetToolMRR( ParametersMRR)
end
table.insert( Machining, Splitting)
-- cerco lama sotto
Splitting = {}
Splitting.bIsApplicable = false
ToolSearchParameters.bAllowTopHead = false
ToolSearchParameters.bAllowBottomHead = true
Splitting.ToolInfo = {}
Splitting.ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters)
if Splitting.ToolInfo.nToolIndex then
Splitting.bIsApplicable = true
local ParametersMRR = {}
ParametersMRR.nToolIndex = Splitting.ToolInfo.nToolIndex
Splitting.dMRR = MachiningLib.GetToolMRR( ParametersMRR)
end
table.insert( Machining, Splitting)
-- cerco motosega
Splitting = {}
Splitting.bIsApplicable = false
table.insert( Machining, Splitting)
-- cerco fresa
Splitting = {}
Splitting.bIsApplicable = false
table.insert( Machining, Splitting)
-- ===== SCELTA LAVORAZIONI =====
-- forzature da parametri
if Strategy.Parameters.bForceChainSaw then
Machining[1].bIsApplicable = false
Machining[2].bIsApplicable = false
end
-- setto valori di default. Impossibile che taglio di separazione sia incompleto
Strategy.Result.sStatus = 'Completed'
Strategy.Result.nCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
Strategy.Result.dMRR = 1
-- correzioni sul massimo materiale lama, considerando ingombri vari
local dMaxMatBladeSideSingle
local dMaxMatBladeSideDouble
local dMaxMatBladeHorizontalSingle
local dMaxMatBladeHorizontalDouble
if Machining[1].bIsApplicable then
local dMaxMat = TOOLS[Machining[1].ToolInfo.nToolIndex].dMaxMaterial
local dRadius = TOOLS[Machining[1].ToolInfo.nToolIndex].dDiameter / 2
local sHead = TOOLS[Machining[1].ToolInfo.nToolIndex].sHead
-- se taglio di fianco disponibile, si controlla il massimo materiale reale. Per pezzi alti, bisogna controllare anche l'ingombro asse Z nelle 4 direzioni.
if Part.dHeight < BeamData.MIN_DIM_HBEAM then
dMaxMat = min( dMaxMat, BeamData.MAX_DIM_HTCUT)
dMaxMatBladeSideSingle = dMaxMat
dMaxMatBladeSideDouble = dMaxMat * 2
else
if BeamData.GetMaxMatReductionBladeCut then
dMaxMatBladeSideSingle = min( max( dRadius - BeamData.GetMaxMatReductionBladeCut( sHead, Y_AX()), dRadius - BeamData.GetMaxMatReductionBladeCut( sHead, -Y_AX())),
TOOLS[Machining[1].ToolInfo.nToolIndex].dMaxMaterial)
dMaxMatBladeSideDouble = dRadius - BeamData.GetMaxMatReductionBladeCut( sHead, Y_AX()) + dRadius - BeamData.GetMaxMatReductionBladeCut( sHead, -Y_AX())
else
dMaxMatBladeSideSingle = abs( BeamData.MAX_DIM_HTCUT_HBEAM)
dMaxMatBladeSideDouble = abs( BeamData.MAX_DIM_HTCUT_HBEAM) * 2
end
end
-- se taglio orizzontale
if BeamData.GetMaxMatReductionBladeCut then
dMaxMatBladeHorizontalSingle = min( TOOLS[Machining[1].ToolInfo.nToolIndex].dMaxMaterial, dRadius - BeamData.GetMaxMatReductionBladeCut( TOOLS[Machining[1].ToolInfo.nToolIndex].sHead, -Z_AX()))
else
dMaxMatBladeHorizontalSingle = TOOLS[Machining[1].ToolInfo.nToolIndex].dMaxMaterial
end
end
if Machining[2].bIsApplicable then
if BeamData.GetMaxMatReductionBladeCut then
local dRadius = TOOLS[Machining[2].ToolInfo.nToolIndex].dDiameter / 2
dMaxMatBladeHorizontalDouble = min( TOOLS[Machining[2].ToolInfo.nToolIndex].dMaxMaterial, dRadius - BeamData.GetMaxMatReductionBladeCut( TOOLS[Machining[2].ToolInfo.nToolIndex].sHead, Z_AX()))
else
dMaxMatBladeHorizontalDouble = TOOLS[Machining[2].ToolInfo.nToolIndex].dMaxMaterial
end
end
-- TODO considerare di tagliare con il massimo materiale possibile per non salire troppo in Z (macchine tipo PF), oppure non scendere troppo (tipo Kairos)
-- BladeSideSingle (taglio di lama singolo di fianco)
if Machining[1].bIsApplicable and ( dMaxMatBladeSideSingle - BeamData.CUT_EXTRA) > Part.dWidth + 10 * GEO.EPS_SMALL then
Strategy.Result.nQuality = FeatureLib.GetFeatureQuality( 'Blade')
Machining.sTypeMachining = 'BladeSideSingle'
Machining[2].bIsApplicable = false
Machining[3].bIsApplicable = false
Machining[4].bIsApplicable = false
return Machining
-- TODO considerare di tagliare con il massimo materiale possibile per non salire troppo in Z (macchine tipo PF), oppure non scendere troppo (tipo Kairos)
-- BladeSideDouble (taglio di lama doppio di fianco)
elseif Machining[1].bIsApplicable and ( dMaxMatBladeSideDouble - BeamData.CUT_EXTRA) > Part.dWidth + 10 * GEO.EPS_SMALL then
Strategy.Result.nQuality = FeatureLib.GetFeatureQuality( 'Blade')
Strategy.Result.dMRR = Strategy.Result.dMRR/2
Machining.sTypeMachining = 'BladeSideDouble'
Machining[2].bIsApplicable = false
Machining[3].bIsApplicable = false
Machining[4].bIsApplicable = false
return Machining
-- BladeHorizontalSingle (taglio di lama singolo orizzontale)
elseif Machining[1].bIsApplicable and ( dMaxMatBladeHorizontalSingle - BeamData.CUT_EXTRA) > Part.dHeight + 10 * GEO.EPS_SMALL then
Strategy.Result.nQuality = FeatureLib.GetFeatureQuality( 'Blade')
Machining.sTypeMachining = 'BladeHorizontalSingle'
Machining[2].bIsApplicable = false
Machining[3].bIsApplicable = false
Machining[4].bIsApplicable = false
return Machining
-- BladeHorizontalDouble (taglio di lama doppio orizzontale)
elseif Machining[1].bIsApplicable and Machining[2].bIsApplicable and
( dMaxMatBladeHorizontalSingle + dMaxMatBladeHorizontalDouble - BeamData.CUT_EXTRA) > Part.dHeight + 10 * GEO.EPS_SMALL then
Strategy.Result.nQuality = FeatureLib.GetFeatureQuality( 'Blade')
Strategy.Result.dMRR = Strategy.Result.dMRR/2
Machining.sTypeMachining = 'BladeHorizontalDouble'
Machining[1].ToolInfo.dMaxMatBladeFromTop = dMaxMatBladeHorizontalSingle
Machining[2].ToolInfo.dMaxMatBladeFromDown = dMaxMatBladeHorizontalDouble
Machining[3].bIsApplicable = false
Machining[4].bIsApplicable = false
return Machining
-- TODO : casi con motosega da completare
-- ChainSawHorizontal (motosega)
-- ChainSawSideSingle (motosega)
-- ChainSawSideDouble (motosega)
-- ChainSawPlusBlade (motosega pi lama orizzontale)
-- Mill (svuotatura)
end
-- se non ho trovato neanche una lavorazione completa, non posso separare
if Machining.sTypeMachining == 'None' then
Strategy.Result.sStatus = 'Not-Applicable'
Strategy.Result.nCompletionIndex = 0
Strategy.Result.dMRR = 0
Strategy.Result.nQuality = 0
Strategy.Result.sInfo = 'Split not possible'
end
return Machining
end
-------------------------------------------------------------------------------------------------------------
function HEADCUT.Make( bAddMachining, Proc, Part, CustomParameters)
Strategy = LoadStrategyParameters( CustomParameters)
local bAreAllMachiningsAdded = true
local Splitting = {}
local AuxiliaryData = {}
Strategy.sSplitStrategy = GetSplitStrategy( Proc, Part)
if bAddMachining then
-- inserimento smussi su spigoli del taglio
if Strategy.Parameters.bMakeChamfer then
MakeChamfer()
end
local OptionalParameters = {}
-- applico le lavorazioni
----------------------------------------------------------------------------------
if Strategy.sSplitStrategy.sTypeMachining == 'BladeSideSingle' then
OptionalParameters = {}
OptionalParameters.nToolIndex = Strategy.sSplitStrategy[1].ToolInfo.nToolIndex
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_BACK
OptionalParameters.sDepth = 0
-- TODO gestire lavorazione a cubetti
local EdgeToMachine = GetEdgeToMachine( Proc, -Y_AX())
-- approccio e retrazione
OptionalParameters.LeadIn, OptionalParameters.LeadOut = CalculateLeadInOut( Splitting, EdgeToMachine)
Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1], EdgeToMachine, OptionalParameters)
Splitting.sStage = 'Head'
MachiningLib.AddNewMachining( Proc, Splitting, AuxiliaryData)
----------------------------------------------------------------------------------
elseif Strategy.sSplitStrategy.sTypeMachining == 'BladeSideDouble' then
OptionalParameters = {}
OptionalParameters.nToolIndex = Strategy.sSplitStrategy[1].ToolInfo.nToolIndex
-- Taglio lato frontale
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_BACK
OptionalParameters.sDepth = 0
OptionalParameters.dRadialOffset = ( Part.dWidth - BeamData.CUT_EXTRA) / 2
-- TODO gestire lavorazione a cubetti
local EdgeToMachine = GetEdgeToMachine( Proc, -Y_AX())
-- approccio e retrazione
OptionalParameters.LeadIn, OptionalParameters.LeadOut = CalculateLeadInOut( Splitting, EdgeToMachine)
Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1], EdgeToMachine, OptionalParameters)
Splitting.sStage = 'Head'
MachiningLib.AddNewMachining( Proc, Splitting, AuxiliaryData)
-- Taglio lato dietro
OptionalParameters = {}
Splitting = {}
AuxiliaryData = {}
OptionalParameters.nToolIndex = Strategy.sSplitStrategy[1].ToolInfo.nToolIndex
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_FRONT
OptionalParameters.sDepth = 0
OptionalParameters.dRadialOffset = ( Part.dWidth - BeamData.CUT_EXTRA) / 2
-- TODO gestire lavorazione a cubetti
EdgeToMachine = GetEdgeToMachine( Proc, Y_AX())
-- approccio e retrazione
OptionalParameters.LeadIn, OptionalParameters.LeadOut = CalculateLeadInOut( Splitting, EdgeToMachine)
Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1], EdgeToMachine, OptionalParameters)
Splitting.sStage = 'Head'
MachiningLib.AddNewMachining( Proc, Splitting, AuxiliaryData)
----------------------------------------------------------------------------------
elseif Strategy.sSplitStrategy.sTypeMachining == 'BladeHorizontalSingle' then
OptionalParameters = {}
OptionalParameters.nToolIndex = Strategy.sSplitStrategy[1].ToolInfo.nToolIndex
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_DOWN
OptionalParameters.sDepth = 0
OptionalParameters.dRadialOffset = -BeamData.CUT_EXTRA
-- TODO gestire lavorazione a cubetti
local EdgeToMachine = GetEdgeToMachine( Proc, Z_AX())
-- approccio e retrazione
OptionalParameters.LeadIn, OptionalParameters.LeadOut = CalculateLeadInOut( Splitting, EdgeToMachine)
Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1], EdgeToMachine, OptionalParameters)
Splitting.sStage = 'Head'
MachiningLib.AddNewMachining( Proc, Splitting, AuxiliaryData)
----------------------------------------------------------------------------------
elseif Strategy.sSplitStrategy.sTypeMachining == 'BladeHorizontalDouble' then
OptionalParameters = {}
OptionalParameters.nToolIndex = Strategy.sSplitStrategy[1].ToolInfo.nToolIndex
-- Taglio lato frontale
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_DOWN
OptionalParameters.sDepth = 0
local dExtraMaxMat = ( Strategy.sSplitStrategy[1].ToolInfo.dMaxMatBladeFromTop + Strategy.sSplitStrategy[2].ToolInfo.dMaxMatBladeFromDown - Part.dHeight - BeamData.CUT_EXTRA) / 2
OptionalParameters.dRadialOffset = Part.dHeight - Strategy.sSplitStrategy[1].ToolInfo.dMaxMatBladeFromTop + dExtraMaxMat
-- TODO gestire lavorazione a cubetti
local EdgeToMachine = GetEdgeToMachine( Proc, Z_AX())
-- approccio e retrazione
OptionalParameters.LeadIn, OptionalParameters.LeadOut = CalculateLeadInOut( Splitting, EdgeToMachine)
Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1], EdgeToMachine, OptionalParameters)
Splitting.sStage = 'Head'
MachiningLib.AddNewMachining( Proc, Splitting, AuxiliaryData)
-- Taglio lato dietro
OptionalParameters = {}
Splitting = {}
AuxiliaryData = {}
OptionalParameters.nToolIndex = Strategy.sSplitStrategy[2].ToolInfo.nToolIndex
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_TOP
OptionalParameters.sDepth = 0
OptionalParameters.dRadialOffset = Part.dHeight - Strategy.sSplitStrategy[2].ToolInfo.dMaxMatBladeFromDown + dExtraMaxMat
-- TODO gestire lavorazione a cubetti
EdgeToMachine = GetEdgeToMachine( Proc, -Z_AX())
-- approccio e retrazione
OptionalParameters.LeadIn, OptionalParameters.LeadOut = CalculateLeadInOut( Splitting, EdgeToMachine)
Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1], EdgeToMachine, OptionalParameters)
Splitting.sStage = 'Head'
MachiningLib.AddNewMachining( Proc, Splitting, AuxiliaryData)
----------------------------------------------------------------------------------
elseif Strategy.sSplitStrategy.sTypeMachining == 'ChainSawHorizontal' then
; -- TODO
----------------------------------------------------------------------------------
elseif Strategy.sSplitStrategy.sTypeMachining == 'ChainSawSideSingle' then
; -- TODO
----------------------------------------------------------------------------------
elseif Strategy.sSplitStrategy.sTypeMachining == 'ChainSawSideDouble' then
; -- TODO
----------------------------------------------------------------------------------
elseif Strategy.sSplitStrategy.sTypeMachining == 'ChainSawPlusBlade' then
; -- TODO
----------------------------------------------------------------------------------
elseif Strategy.sSplitStrategy.sTypeMachining == 'Mill' then
; -- TODO
----------------------------------------------------------------------------------
end
return bAreAllMachiningsAdded, Strategy.Result
else
return nil, Strategy.Result
end
end
-------------------------------------------------------------------------------------------------------------
return HEADCUT
@@ -0,0 +1,12 @@
-- Parametri configurabili da cliente per strategia: HEADCUT
local HEADCUTData = {
sStrategyId = 'HEADCUT',
Parameters = {
{ sName = 'bMakeChamfer', sValue = 'false', sDescriptionShort = 'Execute Chamfer', sDescriptionLong = 'Use the V-Mill to execute chamfers on cut-edges', sType = 'b', sMessageId = '', sMinUserLevel = '1'},
{ sName = 'bForceChainSaw', sValue = 'false', sDescriptionShort = 'Force to use chain saw', sDescriptionLong = 'Force to use chain saw', sType = 'b', sMessageId = '', sMinUserLevel = '1'},
{ sName = 'bFinishWithMill', sValue = 'true', sDescriptionShort = 'Finish with mill', sDescriptionLong = 'Use a mill to finish the surface if split with chain saw', sType = 'b', sMessageId = '', sMinUserLevel = '1'}
}
}
return HEADCUTData
@@ -3,10 +3,10 @@
local STR0001Data = {
sStrategyId = 'STR0001',
Parameters = {
{ sName = 'dOverMatOnLenght', sValue = '0', sDescription = 'Sovramateriale lunghezza tenone', sType = 'd'},
{ sName = 'dOverMatOnRadius', sValue = '0', sDescription = 'Sovramateriale larghezza tenone', sType = 'd'},
{ sName = 'nMaxMillingPaths', sValue = '3', sDescription = 'Numero massimo di passaggi di fresatura. Se richiesti più passaggi, si fa svuotatura', sType = 'd'},
{ sName = 'bUseDTToolOnPocketing', sValue = 'true', sDescription = 'Utilizza utensile a coda di rondimne per fare svuotatura', sType = 'b'}
{ sName = 'dOverMatOnLenght', sNameNge = 'OVM_LENGTH', sValue = '0', sDescription = 'Sovramateriale lunghezza tenone', sType = 'd'},
{ sName = 'dOverMatOnRadius', sNameNge = 'OVM_RADIUS', sValue = '0', sDescription = 'Sovramateriale larghezza tenone', sType = 'd'},
{ sName = 'nMaxMillingPaths', sNameNge = 'MAX_PATHS', sValue = '3', sDescription = 'Numero massimo di passaggi di fresatura. Se richiesti più passaggi, si fa svuotatura', sType = 'd'},
{ sName = 'bUseDTToolOnPocketing', sNameNge = 'ALLOW_DT_POCKET', sValue = 'true', sDescription = 'Utilizza utensile a coda di rondine per fare svuotatura', sType = 'b'}
}
}
+90 -155
View File
@@ -1,16 +1,15 @@
-- Strategia: STR0002
-- Descrizione
-- Svuotatura tasca
-- Feature tipo LapJpint
-- Feature tipo LapJoint
-------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------
-- TODO
-- 1 - Controllare lavorazioni in caso di feature lunga spezzata
-- 2 - Inserire antischeggia (fresa o lama)
-- 3 - Modalità svuotatura con fresa grande e spigoli con fresa piccola
-- 4 - Smusso a V
-- 5 - Finitura con motosega (se la fresa non completa)
-- 1 - Inserire antischeggia (fresa o lama)
-- 2 - Modalità svuotatura con fresa grande e spigoli con fresa piccola
-- 3 - Smusso a V
-- 4 - Finitura con motosega (se la fresa non completa)
-------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------
@@ -19,7 +18,7 @@
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local MachiningLib = require( 'MachiningLib')
local FeatureData = require( 'FeatureData')
local FeatureLib = require( 'FeatureLib')
-- Tabella per definizione modulo
local STR0002 = {}
@@ -82,13 +81,13 @@ end
-------------------------------------------------------------------------------------------------------------
local function GetBestPocketingStrategy( Proc)
-- imposto paraemtri di ricerca utensile in base a topologia
-- imposto parametri di ricerca utensile in base a topologia
local Machining = {}
local Milling = {}
local ToolSearchParameters = {}
ToolSearchParameters.sMillShape = 'STANDARD'
Machining.sTypeMachining = 'None' -- Bottom-Side1-Side2\ Bottom-Side1\ Bottom-Side2\ Side1-Side2\ Bottom\ Side1 \ Side2 \ None
Strategy.Result.nQuality = FeatureData.GetFeatureQuality( 'Mill')
Strategy.Result.nQuality = FeatureLib.GetFeatureQuality( 'Mill')
-- caso speciale Tunnel che non ha faccia bottom
if Proc.Topology.sName == 'Tunnel-4-Through' then
@@ -134,6 +133,10 @@ local function GetBestPocketingStrategy( Proc)
Milling.ToolInfo = {}
Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
if Milling.ToolInfo.nToolIndex then
-- se utensile scelto è su aggregato, ricalcolo la qualità
if TOOLS[Milling.ToolInfo.nToolIndex].SetupInfo.bToolOnAggregate then
Strategy.Result.nQuality = FeatureLib.GetFeatureQuality( 'MillOnAggregate')
end
Milling.bIsApplicable = true
local ParametersMRR = {}
ParametersMRR.nToolIndex = Milling.ToolInfo.nToolIndex
@@ -242,7 +245,7 @@ local function GetBestPocketingStrategy( Proc)
if Machining[1].bIsApplicable and Machining[1].ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then
Machining.sTypeMachining = 'Bottom'
Strategy.Result.sStatus = 'Completed'
Strategy.Result.nCompletionIndex = FeatureData.GetFeatureCompletionIndex( 100)
Strategy.Result.nCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
Strategy.Result.dMRR = Machining[1].dMRR
Machining[1].ToolInfo.dResidualDepth = 0
Machining[2].bIsApplicable = false
@@ -253,7 +256,7 @@ local function GetBestPocketingStrategy( Proc)
elseif Proc.Topology.sName == 'Rabbet-2-Through' and Machining[2].bIsApplicable and Machining[2].ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then
Machining.sTypeMachining = 'Bottom2'
Strategy.Result.sStatus = 'Completed'
Strategy.Result.nCompletionIndex = FeatureData.GetFeatureCompletionIndex( 100)
Strategy.Result.nCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
Strategy.Result.dMRR = Machining[2].dMRR
Machining[2].ToolInfo.dResidualDepth = 0
Machining[1].bIsApplicable = false
@@ -264,7 +267,7 @@ local function GetBestPocketingStrategy( Proc)
elseif Machining[3].bIsApplicable and Machining[3].ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then
Machining.sTypeMachining = 'Side1'
Strategy.Result.sStatus = 'Completed'
Strategy.Result.nCompletionIndex = FeatureData.GetFeatureCompletionIndex( 100)
Strategy.Result.nCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
Strategy.Result.dMRR = Machining[3].dMRR
if Proc.MainFaces.TunnelAddedFaces then
Machining[3].ToolInfo.dResidualDepth = -( Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation + BeamData.MILL_OVERLAP)
@@ -279,7 +282,7 @@ local function GetBestPocketingStrategy( Proc)
elseif Machining[4].bIsApplicable and Machining[4].ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then
Machining.sTypeMachining = 'Side2'
Strategy.Result.sStatus = 'Completed'
Strategy.Result.nCompletionIndex = FeatureData.GetFeatureCompletionIndex( 100)
Strategy.Result.nCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
Strategy.Result.dMRR = Machining[4].dMRR
if Proc.MainFaces.TunnelAddedFaces then
Machining[4].ToolInfo.dResidualDepth = -( Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation + BeamData.MILL_OVERLAP)
@@ -297,7 +300,7 @@ local function GetBestPocketingStrategy( Proc)
Strategy.Result.sStatus = 'Completed'
Machining[3].ToolInfo.dResidualDepth = Machining[3].ToolInfo.dResidualDepth - Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation
Machining[4].ToolInfo.dResidualDepth = -Machining[3].ToolInfo.dResidualDepth - BeamData.MILL_OVERLAP
Strategy.Result.nCompletionIndex = FeatureData.GetFeatureCompletionIndex( 100)
Strategy.Result.nCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
Strategy.Result.dMRR = ( Machining[3].dMRR + Machining[4].dMRR) / 2
Machining[1].bIsApplicable = false
Machining[2].bIsApplicable = false
@@ -330,7 +333,7 @@ local function GetBestPocketingStrategy( Proc)
end
local dMachinedPrercentage = CalcMachinedPercentage( Proc, Machining)
Strategy.Result.nCompletionIndex = FeatureData.GetFeatureCompletionIndex( dMachinedPrercentage)
Strategy.Result.nCompletionIndex = FeatureLib.GetFeatureCompletionIndex( dMachinedPrercentage)
Strategy.Result.sInfo = 'Machining not complete, left ' .. tostring( 100 - ceil( dMachinedPrercentage)) .. '%'
-- se non ho trovato neanche una lavorazione
@@ -346,142 +349,53 @@ local function GetBestPocketingStrategy( Proc)
end
-------------------------------------------------------------------------------------------------------------
local function VerifySplitMachiningNeeded( Proc, Part)
local function GetSplitSurfaces( Proc, Part)
local vAddId = {}
local vAddIdTunnel = {}
local bSplit
-- la lunghezza richiede spezzatura
if Proc.b3Box:getDimX() > BeamData.LONGCUT_MAXLEN or Proc.b3Box:getDimX() > 0.7 * Part.b3Solid:getDimX() then
bSplit = true
else
bSplit = false
local nAddGrpId = BeamLib.GetAddGroup( Part.id)
local nOriginalTmIdTunnel = GDB_ID.NULL
if Proc.MainFaces.TunnelAddedFaces then
nOriginalTmIdTunnel = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.id
end
-- la lunghezza richiede spezzatura
if ( bSplit) then
-- recupero gruppo per geometria aggiuntiva
local nAddGrpId = BeamLib.GetAddGroup( Part.id)
local bStartLeft, bStartRight
local nIdTunnel = nil
if Proc.MainFaces.TunnelAddedFaces then
nIdTunnel = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.id
end
-- recupero punti di spezzatura - da destra a sinistra
local FeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
-- se feature inizia al di sotto del limite sinistro (coda)
if Proc.b3Box:getMin():getX() < Part.b3Solid:getMin():getX() + BeamData.LONGCUT_ENDLEN then
bStartLeft = true
end
-- se feature inizia al di sotto del limite destro (testa)
if Proc.b3Box:getMax():getX() > Part.b3Solid:getMax():getX() - BeamData.LONGCUT_ENDLEN then
bStartRight = true
end
-- recupero utensile con massimo diametro
local dMaxDiam = 30
for t = 1, #Strategy.Machining do
if Strategy.Machining[t].bIsApplicable then
dMaxDiam = min( dMaxDiam, TOOLS[Strategy.Machining[t].ToolInfo.nToolIndex].dDiameter)
end
end
-- salvo valori
local dNewMinX = Proc.b3Box:getMin():getX()
local dNewMaxX = Proc.b3Box:getMax():getX()
local dNewRest = Proc.b3Box:getDimX()
-- creo primo spezzone sulla sinistra
if bStartLeft then
local AddId = EgtCopyGlob( Proc.id, nAddGrpId) or GDB_ID.NULL
-- copio faccia tunnel
local AddIdTunnel = EgtCopyGlob( nIdTunnel, nAddGrpId) or GDB_ID.NULL
-- decido punto spezzatura verso la coda
if Proc.b3Box:getDimX() > BeamData.LONGCUT_ENDLEN * 2 then
dNewMinX = max( Part.b3Solid:getMin():getX() + BeamData.LONGCUT_ENDLEN, Proc.b3Box:getMin():getX() + dMaxDiam * 3)
else
-- se pezzo abbastanza piccolo, spezzo in mezzo al 'pezzo + grezzo restante'
if Part.dRestLength + Part.b3Solid:getDimX() < BeamData.dMinRaw * 1.5 then
dNewMinX = Part.b3Solid:getMax():getX() - ( ( Part.dRestLength + Part.b3Solid:getDimX()) / 2)
else
dNewMinX = max( Proc.b3Box:getMin():getX() + ( BeamData.dMinRaw)/2 + 150, Part.b3Solid:getMax():getX() - BeamData.LONGCUT_ENDLEN)
end
end
local ptOn = Point3d( dNewMinX, 0, 0)
dNewRest = abs( dNewMaxX - dNewMinX)
-- taglio della superficie lato sinistro
EgtCutSurfTmPlane( AddId, ptOn, X_AX(), true, GDB_RT.GLOB)
EgtCutSurfTmPlane( AddIdTunnel, ptOn, X_AX(), true, GDB_RT.GLOB)
-- eseguo inserimento
table.insert( vAddId, AddId)
table.insert( vAddIdTunnel, AddIdTunnel)
end
-- creo spezzone sulla destra
if bStartRight then
local AddId = EgtCopyGlob( Proc.id, nAddGrpId) or GDB_ID.NULL
-- copio faccia tunnel
local AddIdTunnel = EgtCopyGlob( nIdTunnel, nAddGrpId) or GDB_ID.NULL
dNewMaxX = min( ( Proc.b3Box:getMax():getX() - dMaxDiam * 3), Part.b3Solid:getMax():getX() - BeamData.LONGCUT_ENDLEN)
if dNewMaxX - dNewMinX < 500 * GEO.EPS_SMALL then
dNewMaxX = dNewMinX - BeamData.MILL_OVERLAP
dNewRest = 0
else
dNewRest = dNewMaxX - dNewMinX
end
local ptOn = Point3d( dNewMaxX, 0, 0)
-- taglio della superficie lato destro
EgtCutSurfTmPlane( AddId, ptOn, -X_AX(), true, GDB_RT.GLOB)
EgtCutSurfTmPlane( AddIdTunnel, ptOn, -X_AX(), true, GDB_RT.GLOB)
-- eseguo inserimento
table.insert( vAddId, 1, AddId)
table.insert( vAddIdTunnel, AddIdTunnel)
end
-- lavoro il restante
if dNewRest > 0 then
local nSplitParts = max( ceil( dNewRest / BeamData.LONGCUT_MAXLEN + 10 * GEO.EPS_SMALL), 1)
local dSplitPartsLen = dNewRest / nSplitParts
for i = 1, nSplitParts do
local AddId = EgtCopyGlob( Proc.id, nAddGrpId) or GDB_ID.NULL
-- copio faccia tunnel
local AddIdTunnel = EgtCopyGlob( nIdTunnel, nAddGrpId) or GDB_ID.NULL
local ptOn
-- se un solo spezzone, prendo punto massimo e minimo
if nSplitParts == 1 then
ptOn = Point3d( dNewMinX, 0, 0)
-- taglio della superficie lato sinistro
EgtCutSurfTmPlane( AddId, ptOn, -X_AX(), true, GDB_RT.GLOB)
EgtCutSurfTmPlane( AddIdTunnel, ptOn, -X_AX(), true, GDB_RT.GLOB)
ptOn = Point3d( dNewMaxX, 0, 0)
-- taglio della superficie lato destro
EgtCutSurfTmPlane( AddId, ptOn, X_AX(), true, GDB_RT.GLOB)
EgtCutSurfTmPlane( AddIdTunnel, ptOn, X_AX(), true, GDB_RT.GLOB)
else
-- eseguo trim sinistro
if i ~= 1 or bStartLeft then
ptOn = Point3d( dNewMinX, 0, 0)
-- taglio della superficie lato sinistro
EgtCutSurfTmPlane( AddId, ptOn, -X_AX(), true, GDB_RT.GLOB)
EgtCutSurfTmPlane( AddIdTunnel, ptOn, -X_AX(), true, GDB_RT.GLOB)
end
-- eseguo trim destro
dNewMaxX = dNewMinX + dSplitPartsLen
if i ~= nSplitParts or bStartRight then
ptOn = Point3d( dNewMaxX, 0, 0)
-- taglio della superficie lato destro
EgtCutSurfTmPlane( AddId, ptOn, X_AX(), true, GDB_RT.GLOB)
EgtCutSurfTmPlane( AddIdTunnel, ptOn, X_AX(), true, GDB_RT.GLOB)
end
-- il nuovo minimo è il punto massimo del precedente
dNewMinX = dNewMaxX
end
-- eseguo inserimento in modo da ordinare da X- a X+
table.insert( vAddId, EgtIf( #vAddId == 0 or not bStartRight, 1, 2), AddId)
table.insert( vAddIdTunnel, EgtIf( #vAddIdTunnel == 0 or not bStartRight, 1, 2), AddIdTunnel)
end
end
if #FeatureSplittingPoints == 0 then
local nAddId = EgtCopyGlob( Proc.id, nAddGrpId) or GDB_ID.NULL
local nAddIdTunnel = EgtCopyGlob( nOriginalTmIdTunnel, nAddGrpId) or GDB_ID.NULL
table.insert( vAddId, nAddId)
table.insert( vAddIdTunnel, nAddIdTunnel)
else
-- TODO se è sulla coda, messaggio che posso rovinare
table.insert( vAddId, Proc.id)
for i = 1, #FeatureSplittingPoints do
local nAddId = EgtCopyGlob( Proc.id, nAddGrpId) or GDB_ID.NULL
local nAddIdTunnel = EgtCopyGlob( nOriginalTmIdTunnel, nAddGrpId) or GDB_ID.NULL
if i == 1 then
-- prima superficie, va tagliata solo a sinistra
local ptSplit = FeatureSplittingPoints[i] + Vector3d( -BeamData.MILL_OVERLAP / 2, 0, 0)
EgtCutSurfTmPlane( nAddId, ptSplit, -X_AX(), true, GDB_RT.GLOB)
EgtCutSurfTmPlane( nAddIdTunnel, ptSplit, -X_AX(), true, GDB_RT.GLOB)
else
-- taglio della superficie corrente - lato sinistro
local ptSplit = FeatureSplittingPoints[i] + Vector3d( -BeamData.MILL_OVERLAP / 2, 0, 0)
EgtCutSurfTmPlane( nAddId, ptSplit, -X_AX(), true, GDB_RT.GLOB)
EgtCutSurfTmPlane( nAddIdTunnel, ptSplit, -X_AX(), true, GDB_RT.GLOB)
-- taglio della superficie corrente - lato destro
ptSplit = FeatureSplittingPoints[i - 1] + Vector3d( BeamData.MILL_OVERLAP / 2, 0, 0)
EgtCutSurfTmPlane( nAddId, ptSplit, X_AX(), true, GDB_RT.GLOB)
EgtCutSurfTmPlane( nAddIdTunnel, ptSplit, X_AX(), true, GDB_RT.GLOB)
end
table.insert( vAddId, nAddId)
table.insert( vAddIdTunnel, nAddIdTunnel)
end
-- taglio ultima superficie, va tagliata solo a destra
local nAddId = EgtCopyGlob( Proc.id, nAddGrpId) or GDB_ID.NULL
local nAddIdTunnel = EgtCopyGlob( nOriginalTmIdTunnel, nAddGrpId) or GDB_ID.NULL
local ptSplit = FeatureSplittingPoints[#FeatureSplittingPoints] + Vector3d( BeamData.MILL_OVERLAP / 2, 0, 0)
EgtCutSurfTmPlane( nAddId, ptSplit, X_AX(), true, GDB_RT.GLOB)
EgtCutSurfTmPlane( nAddIdTunnel, ptSplit, X_AX(), true, GDB_RT.GLOB)
table.insert( vAddId, nAddId)
table.insert( vAddIdTunnel, nAddIdTunnel)
end
return vAddId, vAddIdTunnel
@@ -509,14 +423,18 @@ function STR0002.Make( bAddMachining, Proc, Part, CustomParameters)
return false, Strategy.Result
end
local bAreAllApplyOk = true
local bAreAllMachiningsAdded = true
local ToolInfo = {}
local Pocketing = {}
Strategy.Machining = GetBestPocketingStrategy( Proc)
if bAddMachining and Strategy.Result.sStatus ~= 'Not-Applicable' then
local vAddId, vAddIdTunnel = VerifySplitMachiningNeeded( Proc, Part)
local vAddId = {}
local vAddIdTunnel = {}
-- recupero superficie, se necessario trimmata sugli spezzoni
vAddId, vAddIdTunnel = GetSplitSurfaces( Proc, Part)
-- si applicano le lavorazioni
for i = 1, #vAddId do
@@ -541,16 +459,33 @@ function STR0002.Make( bAddMachining, Proc, Part, CustomParameters)
-- se ho una sola trimesh, sto lavorando la Proc direttamente e non ho spezzato. Applico direttamente alla geometria calcolata prima
if #vAddId == 1 then
Pocketing.Geometry = {{ Strategy.Machining[j].idProc, Strategy.Machining[j].idFaceToMachine}}
bAreAllApplyOk = MachiningLib.AddNewMachining( Proc, Pocketing)
Pocketing.vtToolDirection = Proc.Faces[ Strategy.Machining[j].idFaceToMachine + 1].vtN
if Pocketing.bToolInvert then
Pocketing.vtToolDirection = -Pocketing.vtToolDirection
end
-- TODO controllare parametro danneggiamento ammesso per decidere se spostare dopo taglio seprazione
-- se è aperta sulla coda, dico che deve essere fatta dopo la separazione
if Proc.AffectedFaces.bLeft then
Pocketing.sStage = 'AfterTail'
end
bAreAllMachiningsAdded = MachiningLib.AddNewMachining( Proc, Pocketing)
else
-- TODO settare parametro per indicare qual è lo spezzone che deve essere fatto dopo il taglio di separazione
-- TODO controllare parametro danneggiamento ammesso per decidere se spostare dopo taglio seprazione
-- se è aperta sulla coda, dico che deve essere fatta dopo la separazione
if Proc.AffectedFaces.bLeft and i == #vAddId then
Pocketing.sStage = 'AfterTail'
end
for k = 1, Proc.nFct do
local vtNSplitFace
local dIdTm = EgtIf( Strategy.Machining[j].bMachAppliedToTunnelFace, vAddIdTunnel[i], vAddId[i])
_, vtNSplitFace = EgtSurfTmFacetCenter( dIdTm, k - 1, GDB_ID.ROOT)
local nIdTm = EgtIf( Strategy.Machining[j].bMachAppliedToTunnelFace, vAddIdTunnel[i], vAddId[i])
Pocketing.ptCenter, vtNSplitFace = EgtSurfTmFacetCenter( nIdTm, k - 1, GDB_ID.ROOT)
Pocketing.vtToolDirection = vtNSplitFace
if Pocketing.bToolInvert then
Pocketing.vtToolDirection = -Pocketing.vtToolDirection
end
if vtNSplitFace and AreSameVectorApprox( vtNSplitFace * EgtIf( Pocketing.bToolInvert, -1, 1), Strategy.Machining[j].vtFaceNormal) then
Pocketing.Geometry = {{ dIdTm, k - 1}}
bAreAllApplyOk = bAreAllApplyOk and MachiningLib.AddNewMachining( Proc, Pocketing)
Pocketing.Geometry = {{ nIdTm, k - 1}}
bAreAllMachiningsAdded = bAreAllMachiningsAdded and MachiningLib.AddNewMachining( Proc, Pocketing)
break
end
end
@@ -559,10 +494,10 @@ function STR0002.Make( bAddMachining, Proc, Part, CustomParameters)
end
end
else
bAreAllApplyOk = false
bAreAllMachiningsAdded = false
end
return bAreAllApplyOk, Strategy.Result
return bAreAllMachiningsAdded, Strategy.Result
end
-------------------------------------------------------------------------------------------------------------
@@ -3,8 +3,8 @@
local STR0002Data = {
sStrategyId = 'STR0002',
Parameters = {
{ sName = 'dMaxCornerRadius', sValue = '15', sDescriptionShort = 'Max radius left on corners', sDescriptionLong = 'Radius-limit left by the tool at each corner of the feature', sType = 'd', sMinUserLevel = '1', sMessageId = ''},
{ sName = 'bAntiSplint', sValue = 'false', sDescriptionShort = 'Use Anti-Splint strategy', sDescriptionLong = 'The strategy will apply blade cuts on corner to avoid wood splint', sType = 'b', sMinUserLevel = '1', sMessageId = ''}
{ sName = 'dMaxCornerRadius', sNameNge = 'MAX_CORNER_RADIUS', sValue = '15', sDescriptionShort = 'Max radius left on corners', sDescriptionLong = 'Radius-limit left by the tool at each corner of the feature', sType = 'd', sMinUserLevel = '1', sMessageId = ''},
{ sName = 'bAntiSplint', sNameNge = 'ANTISPLINT', sValue = 'false', sDescriptionShort = 'Use Anti-Splint strategy', sDescriptionLong = 'The strategy will apply blade cuts on corner to avoid wood splint', sType = 'b', sMinUserLevel = '1', sMessageId = ''}
}
}
+221 -130
View File
@@ -3,11 +3,21 @@
-- Lama + motosega per slot
-- Feature: tipo lapjoint
-------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------
-- TODO
-- 1 - Gestire lavorazioni da sotto
-- 2 - Inserire antischeggia (fresa o lama)
-- 3 - Smusso a V
-- 4 - Implementare lavorazione di geometrie inclinate
-------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local MachiningLib = require( 'MachiningLib')
local FeatureData = require( 'FeatureData')
local FeatureLib = require( 'FeatureLib')
-- strategie di base
local SlotByBlade = require( 'SLOTBYBLADE')
local SlotByChainSaw = require( 'SLOTBYCHAINSAW')
@@ -60,6 +70,72 @@ local function GetCompletionPercentage( Proc, Result)
end
-- TODO si può unificare con eguale funzione in STR0004
local function SortMachiningsBySegment( MachiningA, MachiningB)
if MachiningA.nFeatureSegment > MachiningB.nFeatureSegment then
return false
elseif MachiningB.nFeatureSegment > MachiningA.nFeatureSegment then
return true
else
if TOOLS[ MachiningA.nToolIndex].sFamily == 'SAWBLADE' and TOOLS[ MachiningB.nToolIndex].sFamily == 'MORTISE' then
return true
elseif TOOLS[ MachiningA.nToolIndex].sFamily == 'MORTISE' and TOOLS[ MachiningB.nToolIndex].sFamily == 'SAWBLADE' then
return false
else
if MachiningA.sEdgeType == 'Side' and MachiningB.sEdgeType ~= 'Side' then
return true
elseif MachiningB.sEdgeType == 'Side' and MachiningA.sEdgeType ~= 'Side' then
return false
end
end
end
end
local function SortMachiningsByTool( MachiningA, MachiningB)
if TOOLS[ MachiningA.nToolIndex].sFamily == 'SAWBLADE' and TOOLS[ MachiningB.nToolIndex].sFamily == 'MORTISE' then
return true
elseif TOOLS[ MachiningA.nToolIndex].sFamily == 'MORTISE' and TOOLS[ MachiningB.nToolIndex].sFamily == 'SAWBLADE' then
return false
else
if MachiningA.nFeatureSegment > MachiningB.nFeatureSegment then
return false
elseif MachiningB.nFeatureSegment > MachiningA.nFeatureSegment then
return true
else
if MachiningA.sEdgeType == 'Side' and MachiningB.sEdgeType ~= 'Side' then
return true
elseif MachiningB.sEdgeType == 'Side' and MachiningA.sEdgeType ~= 'Side' then
return false
end
end
end
end
local function MergeResults( Result)
local SortedResult = {}
for i = 1, #Result.Side do
if Result.Side[i].bIsApplicable then
table.insert( SortedResult, Result.Side[i])
end
end
for i = 1, #Result.Bottom do
if Result.Bottom[i].bIsApplicable then
table.insert( SortedResult, Result.Bottom[i])
end
end
for i = 1, #Result.Opposite do
if Result.Opposite[i].bIsApplicable then
table.insert( SortedResult, Result.Opposite[i])
end
end
return SortedResult
end
local function AddResult( Machining, Result)
table.insert( Result, {})
if not Result.Bottom then
@@ -85,6 +161,34 @@ local function AddResult( Machining, Result)
end
local function AddMachinings( Proc, Machinings, bAddMachining)
local nIsApplicableCount = 0
local bAreAllMachiningsAdded = true
for i = 1, #Machinings do
if Machinings[i].bIsApplicable then
nIsApplicableCount = nIsApplicableCount + 1
if bAddMachining then
local bIsMachiningAdded
if TOOLS[ Machinings[i].nToolIndex].sFamily == 'SAWBLADE' then
Blade.AddMachiningAllSteps( Proc, Machinings[i])
elseif TOOLS[ Machinings[i].nToolIndex].sFamily == 'MORTISE' then
Chainsaw.AddMachiningAllSteps( Proc, Machinings[i])
else
error( 'AddMachinings : tool type not supported')
end
if not bIsMachiningAdded then
bAreAllMachiningsAdded = false
end
end
Strategy.Result.sInfo = Strategy.Result.sInfo .. '\n' .. Machinings[i].sMessage
end
end
return bAreAllMachiningsAdded, nIsApplicableCount
end
function Blade.AddResult( Cutting)
AddResult( Cutting, Blade.Result)
end
@@ -100,11 +204,11 @@ function Blade.AddMachiningAllSteps( Proc, Cutting, AuxiliaryData)
local dOriginalRadialOffset = Cutting.dRadialOffset
local dOriginalLeadInPerpDistance = Cutting.LeadIn.dPerpDistance
local dOriginalLeadOutPerpDistance = Cutting.LeadOut.dPerpDistance
for i = Cutting.HorizontalSteps.nCount, 1, -1 do
for i = 1, Cutting.HorizontalSteps.nCount do
AuxiliaryData.Clones[i] = {}
AuxiliaryData.Clones[i].LeadIn = {}
AuxiliaryData.Clones[i].LeadOut = {}
AuxiliaryData.Clones[i].dRadialOffset = dOriginalRadialOffset + Cutting.HorizontalSteps.dStep * ( i - 1)
AuxiliaryData.Clones[i].dRadialOffset = dOriginalRadialOffset + Cutting.HorizontalSteps.dStep * ( Cutting.HorizontalSteps.nCount - i)
-- update distanza perpendicolare attacco per contemplare l'offset applicato
AuxiliaryData.Clones[i].LeadIn.dPerpDistance = dOriginalLeadInPerpDistance - Cutting.dRadialOffset
AuxiliaryData.Clones[i].LeadOut.dPerpDistance = dOriginalLeadOutPerpDistance - Cutting.dRadialOffset
@@ -139,7 +243,6 @@ end
function STR0003.Make( bAddMachining, Proc, Part, CustomParameters)
-- TODO da implementare gestione feature lunghe e spezzatura
-- carico parametri da default e li aggiorno con quelli passati dal chiamante (potrebbero non essere congruenti)
local StrategyLib = {}
StrategyLib.Config = require( 'STR0003\\STR0003Config')
@@ -169,11 +272,31 @@ function STR0003.Make( bAddMachining, Proc, Part, CustomParameters)
return false, Strategy.Result
end
-- lama
-- lavorazione di lama - fondo della tasca o fino a massimo materiale se tunnel
local Cutting = {}
local OptionalParameters = { bForceLongcutBlade = Strategy.Parameters.bForceLongcutBlade}
local dExtendAfterTail = Strategy.Parameters.dExtendAfterTail or max( Part.dDistanceToNextPiece - BeamData.CUT_EXTRA, 0)
if MachiningLib.CanExtendAfterTail( Strategy.Parameters.sCanDamageNextPiece, Part) then
dExtendAfterTail = 10000
end
-- eventuali punti di spezzatura
local FeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
local bIsSplitFeature = false
if #FeatureSplittingPoints > 0 then
bIsSplitFeature = true
end
-- altezza tasca
local dPocketHeight = 0
if Proc.Topology.sFamily == 'Tunnel' then
dPocketHeight = Proc.MainFaces.SideFaces[1].MainEdges.OppositeEdges[1].dLength
else
dPocketHeight = Proc.MainFaces.BottomFaces[1].MainEdges.SideEdges[1].dLength
end
-- lama - calcolo lavorazioni
local Cutting = {}
local OptionalParameters = { bForceLongcutBlade = Strategy.Parameters.bForceLongcutBlade, dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bIsSplitFeature = bIsSplitFeature}
if Proc.Topology.sFamily == 'Tunnel' then
OptionalParameters.bOppositeToolDirection = true
Cutting = SlotByBlade.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1], OptionalParameters)
else
Cutting = SlotByBlade.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge, OptionalParameters)
@@ -181,6 +304,7 @@ function STR0003.Make( bAddMachining, Proc, Part, CustomParameters)
Blade.AddResult( Cutting)
-- lato opposto del tunnel
if Proc.Topology.sFamily == 'Tunnel' then
OptionalParameters.bOppositeToolDirection = true
Cutting = SlotByBlade.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[2], OptionalParameters)
Blade.AddResult( Cutting)
else
@@ -188,11 +312,13 @@ function STR0003.Make( bAddMachining, Proc, Part, CustomParameters)
if Blade.Result.Bottom[1].dResidualDepth > 10 * GEO.EPS_SMALL then
-- eventuale lavorazione di lama - lato della tasca da cui inizia la lavorazione
if Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.bIsStartOpen then
OptionalParameters.bOppositeToolDirection = true
Cutting = SlotByBlade.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1], OptionalParameters)
Blade.AddResult( Cutting)
end
-- eventuale lavorazione di lama - lato della tasca in cui finisce la lavorazione
if Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.bIsEndOpen then
OptionalParameters.bOppositeToolDirection = true
Cutting = SlotByBlade.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[2], OptionalParameters)
Blade.AddResult( Cutting)
end
@@ -202,63 +328,41 @@ function STR0003.Make( bAddMachining, Proc, Part, CustomParameters)
Strategy.Parameters.bNotCompleteWithBladeRadius = false
end
end
local nIsApplicableCount = 0
local dFinalCompletionPercentage = 100
local bAreAllMachiningsAdded = true
for i = 1, #Blade.Result.Bottom do
if Blade.Result.Bottom[i].bIsApplicable then
nIsApplicableCount = nIsApplicableCount + 1
if bAddMachining then
local bIsMachiningAdded = Blade.AddMachiningAllSteps( Proc, Blade.Result.Bottom[i])
if not bIsMachiningAdded then
bAreAllMachiningsAdded = false
end
end
Strategy.Result.sInfo = Strategy.Result.sInfo .. '\n' .. Blade.Result.Bottom[i].sMessage
end
-- lama - lavorazioni raggruppate in unica lista
Blade.Result.Sorted = MergeResults( Blade.Result)
-- lama - aggiunta eventuali lavorazioni splittate
if bIsSplitFeature then
Blade.Result.Sorted = MachiningLib.GetSplitMachinings( Blade.Result.Sorted, FeatureSplittingPoints, Part)
end
for i = 1, #Blade.Result.Side do
if Blade.Result.Side[i].bIsApplicable then
nIsApplicableCount = nIsApplicableCount + 1
if bAddMachining then
local bIsMachiningAdded = Blade.AddMachiningAllSteps( Proc, Blade.Result.Side[i])
if not bIsMachiningAdded then
bAreAllMachiningsAdded = false
end
end
Strategy.Result.sInfo = Strategy.Result.sInfo .. '\n' .. Blade.Result.Side[i].sMessage
end
end
for i = 1, #Blade.Result.Opposite do
if Blade.Result.Opposite[i].bIsApplicable then
nIsApplicableCount = nIsApplicableCount + 1
if bAddMachining then
local bIsMachiningAdded = Blade.AddMachiningAllSteps( Proc, Blade.Result.Opposite[i])
if not bIsMachiningAdded then
bAreAllMachiningsAdded = false
end
end
Strategy.Result.sInfo = Strategy.Result.sInfo .. '\n' .. Blade.Result.Opposite[i].sMessage
end
end
if nIsApplicableCount > 0 then
-- TODO sistemare il calcolo completamento - implementare calcolo area lavorata
if not Strategy.Parameters.bNotCompleteWithBladeRadius and Cutting.dCompletionPercentage > 100 - 10 * GEO.EPS_SMALL then
Strategy.Result.sStatus = 'Completed'
else
Strategy.Result.sStatus = 'Not-Completed'
-- TODO al momento si assume che la percentuale di completamento dell'ultima lavorazione sia quella rilevante
dFinalCompletionPercentage = Cutting.dCompletionPercentage
end
else
Strategy.Result.sStatus = 'Not-Applicable'
Strategy.Parameters.bFinishWithChainSaw = false
end
-- lama - nessuna lavorazione successiva - aggiunta lavorazioni e calcolo risultati
-- TODO bisogna uscire se la lama non può fare alcuna lavorazione; non ha senso che STR0003 lama+catena sia scelta se la lama non può lavorare, in quel caso deve essere scelta la STR0004 solo catena
if not Strategy.Parameters.bFinishWithChainSaw then
Strategy.Result.nCompletionIndex = FeatureData.GetFeatureCompletionIndex( dFinalCompletionPercentage)
Strategy.Result.nQuality = FeatureData.GetFeatureQuality( 'Blade')
-- ordinamento
if Strategy.Parameters.bSortBySegment then
table.sort( Blade.Result.Sorted, SortMachiningsBySegment)
else
table.sort( Blade.Result.Sorted, SortMachiningsByTool)
end
-- aggiunta lavorazioni
local nIsApplicableCount = 0
local bAreAllMachiningsAdded = true
local dFinalCompletionPercentage = 100
bAreAllMachiningsAdded, nIsApplicableCount = AddMachinings( Proc, Blade.Result.Sorted, bAddMachining)
if nIsApplicableCount > 0 then
-- TODO sistemare il calcolo completamento - implementare calcolo area lavorata
if not Strategy.Parameters.bNotCompleteWithBladeRadius and Cutting.dCompletionPercentage > 100 - 10 * GEO.EPS_SMALL then
Strategy.Result.sStatus = 'Completed'
else
Strategy.Result.sStatus = 'Not-Completed'
-- TODO al momento si assume che la percentuale di completamento dell'ultima lavorazione sia quella rilevante
dFinalCompletionPercentage = Cutting.dCompletionPercentage
end
else
Strategy.Result.sStatus = 'Not-Applicable'
Strategy.Parameters.bFinishWithChainSaw = false
end
Strategy.Result.nCompletionIndex = FeatureLib.GetFeatureCompletionIndex( dFinalCompletionPercentage)
Strategy.Result.nQuality = FeatureLib.GetFeatureQuality( 'Blade')
local MRRParametersBlade = {
dStep = TOOLS[Cutting.nToolIndex].dThickness,
dSideStep = min( TOOLS[Cutting.nToolIndex].dSideStep, Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength),
@@ -269,7 +373,7 @@ function STR0003.Make( bAddMachining, Proc, Part, CustomParameters)
return bAreAllMachiningsAdded, Strategy.Result
end
-- sega a catena
-- sega a catena - calcolo lavorazioni
local Mortising = {}
OptionalParameters = {}
if Proc.Topology.sName == 'Groove-4-Blind' or Proc.Topology.sName == 'Pocket-5-Blind' then
@@ -278,18 +382,18 @@ function STR0003.Make( bAddMachining, Proc, Part, CustomParameters)
( Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.dLength > 3 * Blade.Result.Bottom[1].dBladeMarkLength - 10 * GEO.EPS_SMALL) then
if not Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.bIsStartOpen then
local OptionalParameters = { sSideToMachine = 'Start', dLengthToMachine = Blade.Result.Bottom[1].dBladeMarkLength, dMaxElev = 0}
local OptionalParameters = { sSideToMachine = 'Start', dLengthToMachine = Blade.Result.Bottom[1].dBladeMarkLength, dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bIsSplitFeature = bIsSplitFeature}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge, OptionalParameters)
Chainsaw.AddResult( Mortising)
end
if not Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.bIsEndOpen then
local OptionalParameters = { sSideToMachine = 'End', dLengthToMachine = Blade.Result.Bottom[1].dBladeMarkLength, dMaxElev = 0}
local OptionalParameters = { sSideToMachine = 'End', dLengthToMachine = Blade.Result.Bottom[1].dBladeMarkLength, dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bIsSplitFeature = bIsSplitFeature}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge, OptionalParameters)
Chainsaw.AddResult( Mortising)
end
-- si lavora tutto il fondo
else
local OptionalParameters = { dMaxElev = Blade.Result.Bottom[1].dResidualDepth + BeamData.CUT_EXTRA}
local OptionalParameters = { dMaxElev = Blade.Result.Bottom[1].dResidualDepth + BeamData.CUT_EXTRA, dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bIsSplitFeature = bIsSplitFeature}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge, OptionalParameters)
Chainsaw.AddResult( Mortising)
end
@@ -298,10 +402,10 @@ function STR0003.Make( bAddMachining, Proc, Part, CustomParameters)
-- si lavora solamente l'impronta lama sul fondo
if ( #Blade.Result.Side > 0) and Blade.Result.Side[1].dResidualDepth < 10 * GEO.EPS_SMALL then
if ( Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.bIsStartOpen and Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength > 3 * Blade.Result.Side[1].dBladeMarkLength - 10 * GEO.EPS_SMALL) then
local OptionalParameters = { sSideToMachine = 'End', dLengthToMachine = Blade.Result.Side[1].dBladeMarkLength, dMaxElev = 0}
local OptionalParameters = { sSideToMachine = 'End', dLengthToMachine = Blade.Result.Side[1].dBladeMarkLength, dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bOppositeToolDirection = true, bIsSplitFeature = bIsSplitFeature}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1], OptionalParameters)
elseif ( Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.bIsEndOpen and Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[2].dLength > 3 * Blade.Result.Side[1].dBladeMarkLength - 10 * GEO.EPS_SMALL) then
local OptionalParameters = { sSideToMachine = 'Start', dLengthToMachine = Blade.Result.Side[1].dBladeMarkLength, dMaxElev = 0}
local OptionalParameters = { sSideToMachine = 'Start', dLengthToMachine = Blade.Result.Side[1].dBladeMarkLength, dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bOppositeToolDirection = true, bIsSplitFeature = bIsSplitFeature}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[2], OptionalParameters)
end
-- si lavora tutto il lato
@@ -313,10 +417,10 @@ function STR0003.Make( bAddMachining, Proc, Part, CustomParameters)
dBladeResidualDepth = Blade.Result.Bottom[1].dResidualDepth
end
if Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.bIsStartOpen then
local OptionalParameters = { dMaxElev = dBladeResidualDepth + BeamData.CUT_EXTRA}
local OptionalParameters = { dMaxElev = dBladeResidualDepth + BeamData.CUT_EXTRA, dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bOppositeToolDirection = true, bIsSplitFeature = bIsSplitFeature}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1], OptionalParameters)
elseif Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.bIsEndOpen then
local OptionalParameters = { dMaxElev = dBladeResidualDepth + BeamData.CUT_EXTRA}
local OptionalParameters = { dMaxElev = dBladeResidualDepth + BeamData.CUT_EXTRA, dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bOppositeToolDirection = true, bIsSplitFeature = bIsSplitFeature}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[2], OptionalParameters)
end
end
@@ -325,7 +429,7 @@ function STR0003.Make( bAddMachining, Proc, Part, CustomParameters)
elseif Proc.Topology.sName == 'Groove-3-Through' then
if Blade.Result.Bottom[1].dResidualDepth > 10 * GEO.EPS_SMALL then
-- si lavora tutto il fondo
local OptionalParameters = { dMaxElev = Blade.Result.Bottom[1].dResidualDepth + BeamData.CUT_EXTRA}
local OptionalParameters = { dMaxElev = Blade.Result.Bottom[1].dResidualDepth + BeamData.CUT_EXTRA, dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bIsSplitFeature = bIsSplitFeature}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge, OptionalParameters)
Chainsaw.AddResult( Mortising)
-- ancora materiale residuo - si lavorano i lati
@@ -334,16 +438,16 @@ function STR0003.Make( bAddMachining, Proc, Part, CustomParameters)
if ( Blade.Result.Side[1].dResidualDepth < 10 * GEO.EPS_SMALL and Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength > 3 * Blade.Result.Side[1].dBladeMarkLength - 10 * GEO.EPS_SMALL) and
( Blade.Result.Side[2].dResidualDepth < 10 * GEO.EPS_SMALL and Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[2].dLength > 3 * Blade.Result.Side[2].dBladeMarkLength - 10 * GEO.EPS_SMALL) then
local OptionalParameters = { sSideToMachine = 'End', dLengthToMachine = Blade.Result.Side[1].dBladeMarkLength, dMaxElev = 0}
local OptionalParameters = { sSideToMachine = 'End', dLengthToMachine = Blade.Result.Side[1].dBladeMarkLength, dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bOppositeToolDirection = true, bIsSplitFeature = bIsSplitFeature}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1], OptionalParameters)
Chainsaw.AddResult( Mortising)
-- ancora materiale residuo - si lavora da entrambi i lati
if Chainsaw.Result.Side[1].dResidualDepth > 10 * GEO.EPS_SMALL then
local OptionalParameters = { bStopAtHalfElevation = true, sSideToMachine = 'End', dLengthToMachine = Blade.Result.Side[1].dBladeMarkLength, dMaxElev = 0}
local OptionalParameters = { bStopAtHalfElevation = true, sSideToMachine = 'End', dLengthToMachine = Blade.Result.Side[1].dBladeMarkLength, dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bOppositeToolDirection = true, bIsSplitFeature = bIsSplitFeature}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1], OptionalParameters)
Chainsaw.AddResult( Mortising)
OptionalParameters = {}
OptionalParameters = { bStopAtHalfElevation = true, sSideToMachine = 'Start', dLengthToMachine = Blade.Result.Side[2].dBladeMarkLength, dMaxElev = 0}
OptionalParameters = { bStopAtHalfElevation = true, sSideToMachine = 'Start', dLengthToMachine = Blade.Result.Side[2].dBladeMarkLength, dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bOppositeToolDirection = true, bIsSplitFeature = bIsSplitFeature}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[2], OptionalParameters)
Chainsaw.AddResult( Mortising)
-- lavorando dai due lati non c'è materiale residuo - si può eliminare la lavorazione del fondo
@@ -353,17 +457,17 @@ function STR0003.Make( bAddMachining, Proc, Part, CustomParameters)
end
-- si lavora tutto il lato
else
local OptionalParameters = { dMaxElev = Blade.Result.Side[1].dResidualDepth + BeamData.CUT_EXTRA}
local OptionalParameters = { dMaxElev = Blade.Result.Side[1].dResidualDepth + BeamData.CUT_EXTRA, dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bOppositeToolDirection = true, bIsSplitFeature = bIsSplitFeature}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1], OptionalParameters)
Chainsaw.AddResult( Mortising)
-- ancora materiale residuo - si lavora da entrambi i lati
if Chainsaw.Result.Side[1].dResidualDepth > 10 * GEO.EPS_SMALL then
Chainsaw.Result.Side[1].bIsApplicable = false
local OptionalParameters = { bStopAtHalfElevation = true, dMaxElev = Blade.Result.Side[1].dResidualDepth + BeamData.CUT_EXTRA}
local OptionalParameters = { bStopAtHalfElevation = true, dMaxElev = Blade.Result.Side[1].dResidualDepth + BeamData.CUT_EXTRA, dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bOppositeToolDirection = true, bIsSplitFeature = bIsSplitFeature}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1], OptionalParameters)
Chainsaw.AddResult( Mortising)
OptionalParameters = {}
OptionalParameters = { bStopAtHalfElevation = true, dMaxElev = Blade.Result.Side[2].dResidualDepth + BeamData.CUT_EXTRA}
OptionalParameters = { bStopAtHalfElevation = true, dMaxElev = Blade.Result.Side[2].dResidualDepth + BeamData.CUT_EXTRA, dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bOppositeToolDirection = true, bIsSplitFeature = bIsSplitFeature}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[2], OptionalParameters)
Chainsaw.AddResult( Mortising)
-- lavorando dai due lati non c'è materiale residuo - si può disabilitare la lavorazione del fondo
@@ -379,88 +483,74 @@ function STR0003.Make( bAddMachining, Proc, Part, CustomParameters)
if ( Blade.Result.Opposite[1].dResidualDepth < 10 * GEO.EPS_SMALL and Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1].dLength > 3 * Blade.Result.Opposite[1].dBladeMarkLength - 10 * GEO.EPS_SMALL) and
( Blade.Result.Opposite[2].dResidualDepth < 10 * GEO.EPS_SMALL and Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[2].dLength > 3 * Blade.Result.Opposite[2].dBladeMarkLength - 10 * GEO.EPS_SMALL) then
local OptionalParameters = { sSideToMachine = 'Start', dLengthToMachine = Blade.Result.Opposite[1].dBladeMarkLength, dMaxElev = 0}
local OptionalParameters = { sSideToMachine = 'Start', dLengthToMachine = Blade.Result.Opposite[1].dBladeMarkLength, dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bOppositeToolDirection = true, bIsSplitFeature = bIsSplitFeature}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1], OptionalParameters)
Chainsaw.AddResult( Mortising)
OptionalParameters = {}
OptionalParameters = { sSideToMachine = 'End', dLengthToMachine = Blade.Result.Opposite[2].dBladeMarkLength, dMaxElev = 0}
OptionalParameters = { sSideToMachine = 'End', dLengthToMachine = Blade.Result.Opposite[2].dBladeMarkLength, dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bOppositeToolDirection = true, bIsSplitFeature = bIsSplitFeature}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1], OptionalParameters)
Chainsaw.AddResult( Mortising)
if Chainsaw.Result.Opposite[1].dResidualDepth > GEO.EPS_SMALL or Chainsaw.Result.Opposite[2].dResidualDepth > GEO.EPS_SMALL then
if Chainsaw.Result.Opposite[1].dResidualDepth > 10 * GEO.EPS_SMALL or Chainsaw.Result.Opposite[2].dResidualDepth > 10 * GEO.EPS_SMALL then
Chainsaw.Result.Opposite[1].bIsApplicable = false
Chainsaw.Result.Opposite[2].bIsApplicable = false
local OptionalParameters = { bStopAtHalfElevation = true, sSideToMachine = 'Start', dLengthToMachine = Blade.Result.Opposite[1].dBladeMarkLength, dMaxElev = 0}
local OptionalParameters = { bStopAtHalfElevation = true, sSideToMachine = 'Start', dLengthToMachine = Blade.Result.Opposite[1].dBladeMarkLength, dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bOppositeToolDirection = true, bIsSplitFeature = bIsSplitFeature}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1], OptionalParameters)
Chainsaw.AddResult( Mortising)
OptionalParameters = {}
OptionalParameters = { bStopAtHalfElevation = true, sSideToMachine = 'End', dLengthToMachine = Blade.Result.Opposite[1].dBladeMarkLength, dMaxElev = 0}
OptionalParameters = { bStopAtHalfElevation = true, sSideToMachine = 'End', dLengthToMachine = Blade.Result.Opposite[1].dBladeMarkLength, dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bOppositeToolDirection = true, bIsSplitFeature = bIsSplitFeature}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1], OptionalParameters)
Chainsaw.AddResult( Mortising)
OptionalParameters = {}
OptionalParameters = { bStopAtHalfElevation = true, sSideToMachine = 'Start', dLengthToMachine = Blade.Result.Opposite[2].dBladeMarkLength, dMaxElev = 0}
OptionalParameters = { bStopAtHalfElevation = true, sSideToMachine = 'Start', dLengthToMachine = Blade.Result.Opposite[2].dBladeMarkLength, dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bOppositeToolDirection = true, bIsSplitFeature = bIsSplitFeature}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[2], OptionalParameters)
Chainsaw.AddResult( Mortising)
OptionalParameters = {}
OptionalParameters = { bStopAtHalfElevation = true, sSideToMachine = 'End', dLengthToMachine = Blade.Result.Opposite[2].dBladeMarkLength, dMaxElev = 0}
OptionalParameters = { bStopAtHalfElevation = true, sSideToMachine = 'End', dLengthToMachine = Blade.Result.Opposite[2].dBladeMarkLength, dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bOppositeToolDirection = true, bIsSplitFeature = bIsSplitFeature}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[2], OptionalParameters)
Chainsaw.AddResult( Mortising)
end
else
local OptionalParameters = { dMaxElev = Blade.Result.Opposite[1].dResidualDepth + BeamData.CUT_EXTRA}
local OptionalParameters = { dMaxElev = Blade.Result.Opposite[1].dResidualDepth + BeamData.CUT_EXTRA, dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bOppositeToolDirection = true, bIsSplitFeature = bIsSplitFeature}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1], OptionalParameters)
Chainsaw.AddResult( Mortising)
if Chainsaw.Result.Opposite[1].dResidualDepth > GEO.EPS_SMALL then
if Chainsaw.Result.Opposite[1].dResidualDepth > 10 * GEO.EPS_SMALL then
Chainsaw.Result.Opposite[1].bIsApplicable = false
local OptionalParameters = { bStopAtHalfElevation = true, dMaxElev = Blade.Result.Opposite[1].dResidualDepth + BeamData.CUT_EXTRA}
SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1], OptionalParameters)
local OptionalParameters = { bStopAtHalfElevation = true, dMaxElev = Blade.Result.Opposite[1].dResidualDepth + BeamData.CUT_EXTRA, dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bOppositeToolDirection = true, bIsSplitFeature = bIsSplitFeature}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1], OptionalParameters)
Chainsaw.AddResult( Mortising)
OptionalParameters = {}
OptionalParameters = { bStopAtHalfElevation = true, dMaxElev = Blade.Result.Opposite[2].dResidualDepth + BeamData.CUT_EXTRA}
SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[2], OptionalParameters)
OptionalParameters = { bStopAtHalfElevation = true, dMaxElev = Blade.Result.Opposite[2].dResidualDepth + BeamData.CUT_EXTRA, dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bOppositeToolDirection = true, bIsSplitFeature = bIsSplitFeature}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[2], OptionalParameters)
Chainsaw.AddResult( Mortising)
end
end
end
-- sega a catena - lavorazioni raggruppate in unica lista
Chainsaw.Result.Sorted = MergeResults( Chainsaw.Result)
-- sega a catena - aggiunta eventuali lavorazioni splittate
if bIsSplitFeature then
Chainsaw.Result.Sorted = MachiningLib.GetSplitMachinings( Chainsaw.Result.Sorted, FeatureSplittingPoints, Part)
end
-- tutte le lavorazioni di tutti gli utensili in unica lista
local Result = {}
for i = 1, #Blade.Result.Sorted do
table.insert( Result, Blade.Result.Sorted[i])
end
for i = 1, #Chainsaw.Result.Sorted do
table.insert( Result, Chainsaw.Result.Sorted[i])
end
-- ordinamento
if Strategy.Parameters.bSortBySegment then
table.sort( Result, SortMachiningsBySegment)
else
table.sort( Result, SortMachiningsByTool)
end
-- aggiunta lavorazioni per tutti gli utensili
local nIsApplicableCount = 0
local dFinalCompletionPercentage = 100
local bAreAllMachiningsAdded = true
for i = 1, #Chainsaw.Result.Bottom do
if Chainsaw.Result.Bottom[i].bIsApplicable then
nIsApplicableCount = nIsApplicableCount + 1
if bAddMachining then
local bIsMachiningAdded = Chainsaw.AddMachiningAllSteps( Proc, Chainsaw.Result.Bottom[i])
if not bIsMachiningAdded then
bAreAllMachiningsAdded = false
end
end
Strategy.Result.sInfo = Strategy.Result.sInfo .. '\n' .. Chainsaw.Result.Bottom[i].sMessage
end
end
for i = 1, #Chainsaw.Result.Side do
if Chainsaw.Result.Side[i].bIsApplicable then
nIsApplicableCount = nIsApplicableCount + 1
if bAddMachining then
local bIsMachiningAdded = Chainsaw.AddMachiningAllSteps( Proc, Chainsaw.Result.Side[i])
if not bIsMachiningAdded then
bAreAllMachiningsAdded = false
end
end
Strategy.Result.sInfo = Strategy.Result.sInfo .. '\n' .. Chainsaw.Result.Side[i].sMessage
end
end
for i = 1, #Chainsaw.Result.Opposite do
if Chainsaw.Result.Opposite[i].bIsApplicable then
nIsApplicableCount = nIsApplicableCount + 1
if bAddMachining then
local bIsMachiningAdded = Chainsaw.AddMachiningAllSteps( Proc, Chainsaw.Result.Opposite[i])
if not bIsMachiningAdded then
bAreAllMachiningsAdded = false
end
end
Strategy.Result.sInfo = Strategy.Result.sInfo .. '\n' .. Chainsaw.Result.Opposite[i].sMessage
end
end
local dFinalCompletionPercentage = 100
bAreAllMachiningsAdded, nIsApplicableCount = AddMachinings( Proc, Result, bAddMachining)
if nIsApplicableCount > 0 then
if Mortising.dCompletionPercentage > 100 - 10 * GEO.EPS_SMALL then
Strategy.Result.sStatus = 'Completed'
@@ -472,8 +562,9 @@ function STR0003.Make( bAddMachining, Proc, Part, CustomParameters)
else
Strategy.Result.sStatus = 'Not-Applicable'
end
Strategy.Result.nCompletionIndex = FeatureData.GetFeatureCompletionIndex( dFinalCompletionPercentage)
Strategy.Result.nQuality = FeatureData.GetFeatureQuality( 'Chainsaw')
-- calcolo risultati
Strategy.Result.nCompletionIndex = FeatureLib.GetFeatureCompletionIndex( dFinalCompletionPercentage)
Strategy.Result.nQuality = FeatureLib.GetFeatureQuality( 'Chainsaw')
local MRRParametersBlade = {
dStep = TOOLS[Cutting.nToolIndex].dThickness,
dSideStep = min( TOOLS[Cutting.nToolIndex].dSideStep, Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength),
+11 -5
View File
@@ -1,12 +1,18 @@
-- Parametri configurabili da cliente per strategia: STR0001
-- Parametri configurabili da cliente per strategia: STR0003
local STR0003Data = {
sStrategyId = 'STR0003',
Parameters = {
{ sName = 'bFinishWithChainSaw', sValue = 'true', sDescriptionShort = 'Finish with chainsaw if needed', sDescriptionLong = 'Finish with chainsaw if needed', sType = 'b', sMessageId = '', sMinUserLevel = '1'},
{ sName = 'bForceLongcutBlade', sValue = 'false', sDescriptionShort = 'Force ripping blade', sDescriptionLong = 'Force the use of ripping blade, designed for cuts parallel to the grain', sType = 'b', sMessageId = '', sMinUserLevel = '1'},
{ sName = 'bNotCompleteWithBladeRadius', sValue = 'true', sDescriptionShort = '', sDescriptionLong = '', sType = 'b', sMessageId = '', sMinUserLevel = '1'},
{ sName = 'bUseZigZagMortising', sValue = 'false', sDescriptionShort = '', sDescriptionLong = '', sType = 'b', sMessageId = '', sMinUserLevel = '1'}
{ sName = 'bFinishWithChainSaw', sNameNge = 'ALLOW_FINISH_CHAINSAW', sValue = 'true', sDescriptionShort = 'Finish with chainsaw if needed', sDescriptionLong = 'Finish with chainsaw if needed', sType = 'b', sMessageId = '', sMinUserLevel = '1'},
{ sName = 'dExtendAfterTail', sNameNge = 'EXTEND_AFTER_TAIL', sValue = 'false', sDescriptionShort = '', sDescriptionLong = '', sType = 'd', sMessageId = '', sMinUserLevel = '1'},
{ sName = 'bForceLongcutBlade', sNameNge = 'USE_LONGCUT_BLADE', sValue = 'false', sDescriptionShort = 'Force ripping blade', sDescriptionLong = 'Force the use of ripping blade, designed for cuts parallel to the grain', sType = 'b', sMessageId = '', sMinUserLevel = '1'},
{ sName = 'bNotCompleteWithBladeRadius', sNameNge = 'NOT_COMPLETE_WITH_BLADE_RADIUS', sValue = 'true', sDescriptionShort = '', sDescriptionLong = '', sType = 'b', sMessageId = '', sMinUserLevel = '1'},
{ sName = 'bUseZigZagMortising', sNameNge = 'USE_ZIGZAG_CHAINSAW', sValue = 'false', sDescriptionShort = '', sDescriptionLong = '', sType = 'b', sMessageId = '', sMinUserLevel = '1'},
{ sName = 'bSortBySegment', sNameNge = 'SORT_BY_SEGMENT', sValue = 'true', sDescriptionShort = '', sDescriptionLong = '', sType = 'b', sMessageId = '', sMinUserLevel = '1'},
{ sName = 'sCanDamageNextPiece', sNameNge = 'DAMAGE_NEXT_PIECE', sValue = 'NEVER', sType = 'combo', sMinUserLevel = '1',
Choices = { sValue = 'NEVER', sDescriptionShort = '', sDescriptionLong = '', sMessageId = ''},
{ sValue = 'ONLY_IF_RAWPART', sDescriptionShort = '', sDescriptionLong = '', sMessageId = ''},
{ sValue = 'ALWAYS', sDescriptionShort = '', sDescriptionLong = '', sMessageId = ''}}
}
}
+311
View File
@@ -0,0 +1,311 @@
-- Strategia: STR0004
-- Descrizione
-- motosega per slot
-- Feature: tipo lapjoint
-------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------
-- TODO
-- 1 - Inserire antischeggia (fresa o lama)
-- 2 - Smusso a V
-- 3 - Implementare lavorazione di geometrie inclinate
-- 4 - Gestire lavorazioni da sotto (ove possibile, in generale la motosega non lavora da sotto)
-------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
-- strategie di base
local SlotByChainSaw = require( 'SLOTBYCHAINSAW')
-- Tabella per definizione modulo
local STR0004 = {}
local Strategy = {}
local Chainsaw = {}
Chainsaw.Result = {}
-------------------------------------------------------------------------------------------------------------
local function IsTopologyOk( Proc)
if Proc.Topology.bAllRightAngles and
( Proc.Topology.sName == 'Pocket-5-Blind' or
Proc.Topology.sName == 'Groove-3-Through' or
Proc.Topology.sName == 'Groove-4-Blind' or
Proc.Topology.sName == 'Tunnel-4-Through') then
return true
else
return false
end
end
local function GetCompletionPercentage( Proc, Result)
local dNotMachinedArea = 0
local dCompletionPercentage = 0
if Proc.Topology.sFamily == 'Tunnel' then
dNotMachinedArea = Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1].dLength * ( Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength - Result[1].dDepthMachined)
if #Result == 2 then
dNotMachinedArea = dNotMachinedArea - Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1].dLength * ( Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength - Result[2].dDepthMachined)
end
else
if #Result == 1 then
dNotMachinedArea = Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.dLength * ( Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength - Result[1].dDepthMachined)
elseif #Result == 2 then
dNotMachinedArea = ( Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.dLength - Result[2].dDepthMachined) * ( Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength - Result[1].dDepthMachined)
elseif #Result == 3 then
dNotMachinedArea = ( Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.dLength - Result[2].dDepthMachined - Result[3].dDepthMachined) * ( Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength - Result[1].dDepthMachined)
end
end
dCompletionPercentage = 100 - dNotMachinedArea / Proc.MainFaces.LongFaces[1].dArea * 100
return dCompletionPercentage
end
-- TODO si può unificare con Sorting generale
local function SortMachiningsBySegment( MachiningA, MachiningB)
if MachiningA.nFeatureSegment > MachiningB.nFeatureSegment then
return false
elseif MachiningB.nFeatureSegment > MachiningA.nFeatureSegment then
return true
else
if MachiningA.sEdgeType == 'Side' and MachiningB.sEdgeType ~= 'Side' then
return true
elseif MachiningB.sEdgeType == 'Side' and MachiningA.sEdgeType ~= 'Side' then
return false
end
end
end
local function AddResult( Machining, Result)
table.insert( Result, {})
if not Result.Bottom then
Result.Bottom = {}
end
if not Result.Side then
Result.Side = {}
end
if not Result.Opposite then
Result.Opposite = {}
end
if Machining.sEdgeType == 'Bottom' then
table.insert( Result.Bottom, Machining)
elseif Machining.sEdgeType == 'Side' then
table.insert( Result.Side, Machining)
elseif Machining.sEdgeType == 'Opposite' then
table.insert( Result.Opposite, Machining)
else
error('AddResult : unknown edge type')
end
return Result
end
function Chainsaw.AddResult( Mortising)
AddResult( Mortising, Chainsaw.Result)
end
function Chainsaw.AddMachiningAllSteps( Proc, Mortising, AuxiliaryData)
local bMachiningAdded = false
if not AuxiliaryData then
AuxiliaryData = {}
end
AuxiliaryData.Clones = {}
local dOriginalRadialOffsetMortising = Mortising.dRadialOffset
for i = Mortising.VerticalSteps.nCount, 1, -1 do
AuxiliaryData.Clones[i] = {}
AuxiliaryData.Clones[i].dRadialOffset = dOriginalRadialOffsetMortising + Mortising.VerticalSteps.dStep * ( i - 1)
end
bMachiningAdded = MachiningLib.AddNewMachining( Proc, Mortising, AuxiliaryData)
return bMachiningAdded
end
function STR0004.Make( bAddMachining, Proc, Part, CustomParameters)
-- carico parametri da default e li aggiorno con quelli passati dal chiamante (potrebbero non essere congruenti)
local StrategyLib = {}
StrategyLib.Config = require( 'STR0004\\STR0004Config')
Strategy.sName = StrategyLib.Config.sStrategyId
CustomParameters = BeamLib.GetUpdateCustomParameters( CustomParameters, StrategyLib.Config.Parameters)
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( CustomParameters)
Strategy.Result = {}
Strategy.Result.sInfo = ''
Chainsaw.Result = {}
if not IsTopologyOk( Proc) then
local sErr = 'Feature '.. Proc.idFeature .. ' : strategy ' .. Strategy.sName .. ' not implemented'
EgtOutLog( sErr)
Strategy.Result.sStatus = 'Not-Applicable'
Strategy.Result.sInfo = 'Topology'
return false, Strategy.Result
end
-- se tasca su faccia sotto la strategia non è applicabile (la sega a catena in generale non può lavorare da sotto)
if Proc.AffectedFaces.bBottom and ( Proc.nFct > 3 or not Proc.AffectedFaces.bTop) then
local sErr = 'Feature '.. Proc.idFeature .. ' : strategy ' .. Strategy.sName .. ' not applicable - pocket on bottom face'
EgtOutLog( sErr)
Strategy.Result.sStatus = 'Not-Applicable'
Strategy.Result.sInfo = 'Direction'
return false, Strategy.Result
end
-- calcolo estensione oltre la coda
local dExtendAfterTail = Strategy.Parameters.dExtendAfterTail or max( Part.dDistanceToNextPiece - BeamData.CUT_EXTRA, 0)
if MachiningLib.CanExtendAfterTail( Strategy.Parameters.sCanDamageNextPiece, Part) then
dExtendAfterTail = 10000
end
-- eventuali punti di spezzatura
local FeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
local bIsSplitFeature = false
if #FeatureSplittingPoints > 0 then
bIsSplitFeature = true
end
-- altezza tasca
local dPocketHeight = 0
if Proc.Topology.sFamily == 'Tunnel' then
dPocketHeight = Proc.MainFaces.SideFaces[1].MainEdges.OppositeEdges[1].dLength
else
dPocketHeight = Proc.MainFaces.BottomFaces[1].MainEdges.SideEdges[1].dLength
end
-- calcolo lavorazioni
local Mortising = {}
local OptionalParameters = { dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bIsSplitFeature = bIsSplitFeature}
if Proc.Topology.sName == 'Groove-4-Blind' or Proc.Topology.sName == 'Pocket-5-Blind' then
-- si lavora tutto il fondo
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge, OptionalParameters)
Chainsaw.AddResult( Mortising)
-- materiale residuo - se possibile si lavora dal lato
if ( Chainsaw.Result.Bottom[#Chainsaw.Result.Bottom].dResidualDepth > 10 * GEO.EPS_SMALL or not Chainsaw.Result.Bottom[#Chainsaw.Result.Bottom].bIsApplicable) and #Proc.MainFaces.SideFaces == 1 then
if Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.bIsStartOpen then
OptionalParameters.bOppositeToolDirection = true
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1], OptionalParameters)
elseif Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.bIsEndOpen then
OptionalParameters.bOppositeToolDirection = true
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[2], OptionalParameters)
end
Chainsaw.AddResult( Mortising)
end
elseif Proc.Topology.sName == 'Groove-3-Through' then
-- si lavora tutto il fondo
local OptionalParameters = { dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bIsSplitFeature = bIsSplitFeature}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge, OptionalParameters)
Chainsaw.AddResult( Mortising)
-- materiale residuo - si lavorano i lati
if ( Chainsaw.Result.Bottom[1].dResidualDepth > 10 * GEO.EPS_SMALL or not Chainsaw.Result.Bottom[#Chainsaw.Result.Bottom].bIsApplicable) then
local OptionalParameters = { dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bOppositeToolDirection = true, bIsSplitFeature = bIsSplitFeature}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1], OptionalParameters)
Chainsaw.AddResult( Mortising)
-- ancora materiale residuo - si lavora da entrambi i lati
if Chainsaw.Result.Side[1].dResidualDepth > 10 * GEO.EPS_SMALL then
Chainsaw.Result.Side[1].bIsApplicable = false
local OptionalParameters = { bStopAtHalfElevation = true, dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bOppositeToolDirection = true, bIsSplitFeature = bIsSplitFeature}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1], OptionalParameters)
Chainsaw.AddResult( Mortising)
OptionalParameters = {}
OptionalParameters = { bStopAtHalfElevation = true, dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bOppositeToolDirection = true, bIsSplitFeature = bIsSplitFeature}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[2], OptionalParameters)
Chainsaw.AddResult( Mortising)
-- lavorando dai due lati non c'è materiale residuo - si può disabilitare la lavorazione del fondo
if Chainsaw.Result.Side[2].dResidualDepth < 10 * GEO.EPS_SMALL then
Chainsaw.Result.Bottom[1].bIsApplicable = false
end
end
end
elseif Proc.Topology.sName == 'Tunnel-4-Through' then
local OptionalParameters = { dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bOppositeToolDirection = true, bIsSplitFeature = bIsSplitFeature}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1], OptionalParameters)
Chainsaw.AddResult( Mortising)
if Chainsaw.Result.Opposite[1].dResidualDepth > 10 * GEO.EPS_SMALL then
Chainsaw.Result.Opposite[1].bIsApplicable = false
local OptionalParameters = { bStopAtHalfElevation = true, dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bOppositeToolDirection = true, bIsSplitFeature = bIsSplitFeature}
SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1], OptionalParameters)
Chainsaw.AddResult( Mortising)
OptionalParameters = {}
OptionalParameters = { bStopAtHalfElevation = true, dExtendAfterTail = dExtendAfterTail, dPocketHeight = dPocketHeight, bOppositeToolDirection = true, bIsSplitFeature = bIsSplitFeature}
SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[2], OptionalParameters)
Chainsaw.AddResult( Mortising)
end
end
-- lavorazioni raggruppate in unica lista
Chainsaw.Result.Sorted = {}
for i = 1, #Chainsaw.Result.Side do
if Chainsaw.Result.Side[i].bIsApplicable then
table.insert( Chainsaw.Result.Sorted, Chainsaw.Result.Side[i])
end
end
for i = 1, #Chainsaw.Result.Bottom do
if Chainsaw.Result.Bottom[i].bIsApplicable then
table.insert( Chainsaw.Result.Sorted, Chainsaw.Result.Bottom[i])
end
end
for i = 1, #Chainsaw.Result.Opposite do
if Chainsaw.Result.Opposite[i].bIsApplicable then
table.insert( Chainsaw.Result.Sorted, Chainsaw.Result.Opposite[i])
end
end
-- aggiunta eventuali lavorazioni splittate
if bIsSplitFeature then
Chainsaw.Result.Sorted = MachiningLib.GetSplitMachinings( Chainsaw.Result.Sorted, FeatureSplittingPoints, Part)
end
-- ordinamento
-- TODO aggiungere ordinamento per utensile
table.sort( Chainsaw.Result.Sorted, SortMachiningsBySegment)
-- aggiunta lavorazioni
local nIsApplicableCount = 0
local dFinalCompletionPercentage = 100
local bAreAllMachiningsAdded = true
for i = 1, #Chainsaw.Result.Sorted do
if Chainsaw.Result.Sorted[i].bIsApplicable then
nIsApplicableCount = nIsApplicableCount + 1
if bAddMachining then
local bIsMachiningAdded = Chainsaw.AddMachiningAllSteps( Proc, Chainsaw.Result.Sorted[i])
if not bIsMachiningAdded then
bAreAllMachiningsAdded = false
end
end
Strategy.Result.sInfo = Strategy.Result.sInfo .. '\n' .. Chainsaw.Result.Sorted[i].sMessage
end
end
if nIsApplicableCount > 0 then
if Mortising.dCompletionPercentage > 100 - 10 * GEO.EPS_SMALL then
Strategy.Result.sStatus = 'Completed'
else
Strategy.Result.sStatus = 'Not-Completed'
-- TODO al momento si assume che la percentuale di completamento dell'ultima lavorazione sia quella rilevante
dFinalCompletionPercentage = Mortising.dCompletionPercentage
end
else
Strategy.Result.sStatus = 'Not-Applicable'
end
Strategy.Result.nCompletionIndex = FeatureLib.GetFeatureCompletionIndex( dFinalCompletionPercentage)
Strategy.Result.nQuality = FeatureLib.GetFeatureQuality( 'Chainsaw')
local MRRParametersChainsaw = {
dStep = min( TOOLS[Mortising.nToolIndex].dStep, Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength),
dSideStep = TOOLS[Mortising.nToolIndex].dThickness,
dFeed = TOOLS[Mortising.nToolIndex].Feeds.dFeed}
local dMRRChainsaw = MachiningLib.GetToolMRR( MRRParametersChainsaw)
Strategy.Result.dMRR = dMRRChainsaw
return bAreAllMachiningsAdded, Strategy.Result
end
-------------------------------------------------------------------------------------------------------------
return STR0004
@@ -0,0 +1,15 @@
-- Parametri configurabili da cliente per strategia: STR0004
local STR0004Data = {
sStrategyId = 'STR0004',
Parameters = {
{ sName = 'bUseZigZagMortising', sNameNge = 'USE_ZIGZAG_CHAINSAW', sValue = 'false', sDescriptionShort = '', sDescriptionLong = '', sType = 'b', sMessageId = '', sMinUserLevel = '1'},
{ sName = 'dExtendAfterTail', sNameNge = 'EXTEND_AFTER_TAIL', sValue = 'false', sDescriptionShort = '', sDescriptionLong = '', sType = 'd', sMessageId = '', sMinUserLevel = '1'},
{ sName = 'sCanDamageNextPiece', sNameNge = 'DAMAGE_NEXT_PIECE', sValue = 'NEVER', sType = 'combo', sMinUserLevel = '1',
Choices = { sValue = 'NEVER', sDescriptionShort = '', sDescriptionLong = '', sMessageId = ''},
{ sValue = 'ONLY_IF_RAWPART', sDescriptionShort = '', sDescriptionLong = '', sMessageId = ''},
{ sValue = 'ALWAYS', sDescriptionShort = '', sDescriptionLong = '', sMessageId = ''}}
}
}
return STR0004Data
+241
View File
@@ -0,0 +1,241 @@
-- Strategia: STR0005
-- Descrizione
-- lama per taglio facce con cubetti se necessario
-- Feature: tagli singoli con eventuali cubetti
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
-- strategie di base
local BladeToWaste = require( 'BLADETOWASTE')
local SlotByBlade = require( 'SLOTBYBLADE')
-- Tabella per definizione modulo
local STR0005 = {}
local Strategy = {}
local Blade = {}
Blade.Result = {}
-------------------------------------------------------------------------------------------------------------
local function CompareEdges( EdgeA, EdgeB)
-- prima i lati orientati lungo X
if abs( EdgeA.vtN:getX()) < abs( EdgeB.vtN:getX()) - 10 * GEO.EPS_SMALL then
return true
elseif abs( EdgeA.vtN:getX()) > abs( EdgeB.vtN:getX()) + 10 * GEO.EPS_SMALL then
return false
-- se stessa X si preferiscono i lati più in basso
else
if EdgeA.vtN:getZ() > EdgeB.vtN:getZ() + 10 * GEO.EPS_SMALL then
return true
elseif EdgeA.vtN:getZ() < EdgeB.vtN:getZ() - 10 * GEO.EPS_SMALL then
return false
-- se stessa Z si preferiscono i lati verso il fronte della trave
else
if EdgeA.vtN:getY() > EdgeB.vtN:getY() + 10 * GEO.EPS_SMALL then
return true
elseif EdgeA.vtN:getY() < EdgeB.vtN:getY() - 10 * GEO.EPS_SMALL then
return false
else
return false
end
end
end
end
local function SortMachiningsBySegment( MachiningA, MachiningB)
if MachiningA.nFeatureSegment > MachiningB.nFeatureSegment then
return false
elseif MachiningB.nFeatureSegment > MachiningA.nFeatureSegment then
return true
-- se segmento uguale, si minimizzano i cambi di lato
else
local bIsOddSegment = ( MachiningA.nFeatureSegment % 2 ~= 0)
if MachiningA.vtToolDirection:getY() < MachiningB.vtToolDirection:getY() - 10 * GEO.EPS_SMALL then
if bIsOddSegment then
return true
else
return false
end
elseif MachiningA.vtToolDirection:getY() > MachiningB.vtToolDirection:getY() + 10 * GEO.EPS_SMALL then
if bIsOddSegment then
return false
else
return true
end
else
return false
end
end
end
function Blade.AddResult( Cutting)
table.insert( Blade.Result, Cutting)
return Blade.Result
end
function Blade.AddMachiningAllSteps( Proc, Cutting, AuxiliaryData)
local bMachiningAdded = false
if not AuxiliaryData then
AuxiliaryData = {}
end
AuxiliaryData.Clones = {}
local dOriginalRadialOffset = Cutting.dRadialOffset
local dOriginalLeadInPerpDistance = Cutting.LeadIn.dPerpDistance
local dOriginalLeadOutPerpDistance = Cutting.LeadOut.dPerpDistance
for i = 1, Cutting.HorizontalSteps.nCount do
AuxiliaryData.Clones[i] = {}
AuxiliaryData.Clones[i].LeadIn = {}
AuxiliaryData.Clones[i].LeadOut = {}
AuxiliaryData.Clones[i].dRadialOffset = dOriginalRadialOffset + Cutting.HorizontalSteps.dStep * ( Cutting.HorizontalSteps.nCount - i)
-- update distanza perpendicolare attacco per contemplare l'offset applicato
AuxiliaryData.Clones[i].LeadIn.dPerpDistance = dOriginalLeadInPerpDistance - Cutting.dRadialOffset
AuxiliaryData.Clones[i].LeadOut.dPerpDistance = dOriginalLeadOutPerpDistance - Cutting.dRadialOffset
end
bMachiningAdded = MachiningLib.AddNewMachining( Proc, Cutting, AuxiliaryData)
return bMachiningAdded
end
function STR0005.Make( bAddMachining, Proc, Part, CustomParameters)
-- carico parametri da default e li aggiorno con quelli passati dal chiamante (potrebbero non essere congruenti)
local StrategyLib = {}
StrategyLib.Config = require( 'STR0005\\STR0005Config')
Strategy.sName = StrategyLib.Config.sStrategyId
CustomParameters = BeamLib.GetUpdateCustomParameters( CustomParameters, StrategyLib.Config.Parameters)
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( CustomParameters)
Strategy.Result = {}
Strategy.Result.sInfo = ''
Blade.Result = {}
local dExtendAfterTail = Strategy.Parameters.dExtendAfterTail or max( Part.dDistanceToNextPiece - BeamData.CUT_EXTRA, 0)
if MachiningLib.CanExtendAfterTail( Strategy.Parameters.sCanDamageNextPiece, Part) then
dExtendAfterTail = 10000
end
local dFeatureMaxNotClampableLengthHead, dFeatureMaxNotClampableLengthTail = FeatureLib.GetFeatureMaxNotClampableLengths( Proc, Part)
local bLeaveWasteAttached = Strategy.Parameters.sCuttingStrategy == 'LEAVE_WASTE_ATTACHED'
local bFeatureHindersClamping = FeatureLib.IsMachiningLong( max( dFeatureMaxNotClampableLengthHead, dFeatureMaxNotClampableLengthTail), Part, { dMaxSegmentLength = BeamData.LONGCUT_ENDLEN})
local Cutting = {}
local MRRParametersBlade = {}
if bFeatureHindersClamping or bLeaveWasteAttached then
-- TODO Lavorazione con codolo
-- attenzione perchè se l'inclinazione della faccia la fa finire oltre lo spigolo questo riduce il massimo calcolare (come calcolare????)
-- il FindBlade dovrà restituire di utilizzare sempre la lama sopra se l'angolo lo permette, ma avendo un'altezza massima (da macchina) oltre cui il DownUp non sarà fattibile (evita collisioni tra asse e pezzo)
-- si trovano i lati da lavorare
local EdgesSorted = {}
for i = 1, #Proc.Faces[1].Edges do
table.insert( EdgesSorted, Proc.Faces[1].Edges[i])
end
table.sort( EdgesSorted, CompareEdges)
local dDepthToMachine = EdgesSorted[1].dElevation / 2 - Strategy.Parameters.dStripWidth / 2
-- ricerca utensile
local ToolSearchParameters = {}
ToolSearchParameters.dElevation = dDepthToMachine
ToolSearchParameters.vtToolDirection = EdgesSorted[1].vtN
ToolSearchParameters.bAllowTopHead = true
ToolSearchParameters.bAllowBottomHead = true
ToolSearchParameters.bForceLongcutBlade = Strategy.Parameters.bForceLongcutBlade
local ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters)
Cutting.nToolIndex = ToolInfo.nToolIndex
Cutting.nType = MCH_OY.MILLING
if not TOOLS[Cutting.nToolIndex].sName then
Cutting.sMessage = 'Blade not found'
Cutting.bIsApplicable = false
EgtOutLog( Cutting.sMessage)
return Cutting, EdgesSorted[1].dElevation
end
-- parametri per il calcolo della velocità di asportazione
MRRParametersBlade = {
dStep = min( TOOLS[Cutting.nToolIndex].dStep, EdgesSorted[1].dElevation),
dSideStep = TOOLS[Cutting.nToolIndex].dThickness,
dFeed = TOOLS[Cutting.nToolIndex].Feeds.dFeed
}
-- eventuali punti di spezzatura
local FeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
local bIsSplitFeature = false
if #FeatureSplittingPoints > 0 then
bIsSplitFeature = true
end
-- primo lato
local OptionalParameters = { dDepthToMachine = dDepthToMachine, nToolIndex = Cutting.nToolIndex, bIsSplitFeature = bIsSplitFeature, dExtendAfterTail = dExtendAfterTail}
Cutting = SlotByBlade.Make( Proc, Part, Proc.Faces[1], EdgesSorted[1], OptionalParameters)
Blade.AddResult( Cutting)
-- secondo lato
Cutting = SlotByBlade.Make( Proc, Part, Proc.Faces[1], EdgesSorted[2], OptionalParameters)
Blade.AddResult( Cutting)
-- lavorazioni raggruppate in unica lista
Blade.Result.Sorted = {}
for i = 1, #Blade.Result do
if Blade.Result[i].bIsApplicable then
table.insert( Blade.Result.Sorted, Blade.Result[i])
end
end
-- aggiunta eventuali lavorazioni splittate
if bIsSplitFeature then
Blade.Result.Sorted = MachiningLib.GetSplitMachinings( Blade.Result.Sorted, FeatureSplittingPoints, Part)
end
table.sort( Blade.Result.Sorted, SortMachiningsBySegment)
-- se la lavorazione con codolo fallisce o non è possibile si proseguirà a quella con cubetti
end
if #Blade.Result == 0 and not bLeaveWasteAttached then
-- BladeToWaste
end
-- aggiunta lavorazioni
local nIsApplicableCount = 0
local dFinalCompletionPercentage = 100
local bAreAllMachiningsAdded = true
for i = 1, #Blade.Result.Sorted do
if Blade.Result.Sorted[i].bIsApplicable then
nIsApplicableCount = nIsApplicableCount + 1
if bAddMachining then
local bIsMachiningAdded = Blade.AddMachiningAllSteps( Proc, Blade.Result.Sorted[i])
if not bIsMachiningAdded then
bAreAllMachiningsAdded = false
end
end
Strategy.Result.sInfo = Strategy.Result.sInfo .. '\n' .. Blade.Result.Sorted[i].sMessage
end
end
if nIsApplicableCount > 0 then
if Cutting.dCompletionPercentage > 100 - 10 * GEO.EPS_SMALL then
Strategy.Result.sStatus = 'Completed'
else
Strategy.Result.sStatus = 'Not-Completed'
-- TODO al momento si assume che la percentuale di completamento dell'ultima lavorazione sia quella rilevante
dFinalCompletionPercentage = Cutting.dCompletionPercentage
end
else
Strategy.Result.sStatus = 'Not-Applicable'
end
Strategy.Result.nCompletionIndex = FeatureLib.GetFeatureCompletionIndex( dFinalCompletionPercentage)
Strategy.Result.nQuality = FeatureLib.GetFeatureQuality( 'Blade')
local dMRRBlade = MachiningLib.GetToolMRR( MRRParametersBlade)
Strategy.Result.dMRR = dMRRBlade
return bAreAllMachiningsAdded, Strategy.Result
end
-------------------------------------------------------------------------------------------------------------
return STR0005
@@ -0,0 +1,24 @@
-- Parametri configurabili da cliente per strategia: STR0004
-- TODO - sostituire dMaxWasteVolume con dMaxWasteWeight? Dove prendere la densità del materiale?
local STR0005Data = {
sStrategyId = 'STR0005',
Parameters = {
{ sName = 'bForceLongcutBlade', sNameNge = 'USE_LONGCUT_BLADE', sValue = 'false', sDescriptionShort = 'Force ripping blade', sDescriptionLong = 'Force the use of ripping blade, designed for cuts parallel to the grain', sType = 'b', sMessageId = '', sMinUserLevel = '1'},
{ sName = 'dExtendAfterTail', sNameNge = 'EXTEND_AFTER_TAIL', sValue = 'false', sDescriptionShort = '', sDescriptionLong = '', sType = 'd', sMessageId = '', sMinUserLevel = '1'},
{ sName = 'sCanDamageNextPiece', sNameNge = 'DAMAGE_NEXT_PIECE', sValue = 'NEVER', sType = 'combo', sMinUserLevel = '1',
Choices = { sValue = 'NEVER', sDescriptionShort = '', sDescriptionLong = '', sMessageId = ''},
{ sValue = 'ONLY_IF_RAWPART', sDescriptionShort = '', sDescriptionLong = '', sMessageId = ''},
{ sValue = 'ALWAYS', sDescriptionShort = '', sDescriptionLong = '', sMessageId = ''}},
{ sName = 'sCuttingStrategy', sNameNge = 'CUTTING_STRATEGY', sValue = 'AUTO', sType = 'combo', sMinUserLevel = '1',
Choices = { sValue = 'AUTO', sDescriptionShort = '', sDescriptionLong = '', sMessageId = ''},
{ sValue = 'DROP_WHOLE_WASTE', sDescriptionShort = '', sDescriptionLong = '', sMessageId = ''},
{ sValue = 'LEAVE_WASTE_ATTACHED', sDescriptionShort = '', sDescriptionLong = '', sMessageId = ''}},
{ sName = 'dMaxWasteLength', sNameNge = 'MAX_WASTE_LENGTH', sValue = '300', sDescriptionShort = '', sDescriptionLong = '', sType = 'd', sMessageId = '', sMinUserLevel = '1'},
{ sName = 'dMaxWasteVolume', sNameNge = 'MAX_WASTE_VOLUME', sValue = '6000000', sDescriptionShort = '', sDescriptionLong = '', sType = 'd', sMessageId = '', sMinUserLevel = '1'},
{ sName = 'dStripWidth', sNameNge = 'STRIP_WIDTH', sValue = '5', sDescriptionShort = '', sDescriptionLong = '', sType = 'd', sMessageId = '', sMinUserLevel = '1'}
}
}
return STR0005Data
+106
View File
@@ -0,0 +1,106 @@
-- Strategia: TAILCUT
-- Descrizione
-- Taglio di separazione
-- Feature: TailCut
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local MachiningLib = require( 'MachiningLib')
local SPLITCUT = require( 'SPLITCUT')
local DiceCut = require( 'DiceCut')
-- Tabella per definizione modulo
local TAILCUT = {}
local Strategy = {}
-------------------------------------------------------------------------------------------------------------
local function MakeChamfer()
-- TODO funzionalità da aggiungere
end
-------------------------------------------------------------------------------------------------------------
function TAILCUT.Make( bAddMachining, Proc, Part, CustomParameters)
local StrategyDefaultParam = {}
StrategyDefaultParam.Config = require( 'TAILCUT\\TAILCUTConfig')
Strategy.sName = StrategyDefaultParam.Config.sStrategyId
CustomParameters = BeamLib.GetUpdateCustomParameters( CustomParameters, StrategyDefaultParam.Config.Parameters)
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( CustomParameters)
Strategy.SplitStrategy = {}
Strategy.Result = {}
Strategy.Machining = {}
Strategy.Result.sInfo = ''
local bAreAllMachiningsAdded = true
-- separazione solo se esiste grezzo successivo con pezzi o scaricabile
Strategy.bSplit = not( Part.bIsLastPart) or Part.dRestLength >= BeamData.dMinRaw
-- se devo fare split perchè c'è un grezzo da scaricare o un altro pezzo
if Strategy.bSplit then
Strategy.SplitStrategy, Strategy.Result = SPLITCUT.GetStrategy( Proc, Part, Strategy.Parameters)
-- se devo rimuovere tutto il restante
else
-- se abilitato, faccio tagli di PRECUT a zero (come SPLIT)
if Strategy.Parameters.bExecutePreCut then
Strategy.SplitStrategy, Strategy.Result = SPLITCUT.GetStrategy( Proc, Part, Strategy.Parameters)
-- se non faccio tagli PRECUT, imposto tabella Result direttamente. Non serve verificare che riesca a rimuovere il materiale extra
else
Strategy.Result.sStatus = 'Completed'
Strategy.Result.nCompletionIndex = 5
Strategy.Result.dMRR = 1
Strategy.Result.nQuality = 5
Strategy.Result.sInfo = 'Split not possible'
end
end
-- se devo applicare le lavorazioni
if bAddMachining then
-- inserimento smussi su spigoli del taglio
if Strategy.Parameters.bMakeChamfer then
MakeChamfer()
end
local MachiningsToAdd = {}
-- se devo fare split perchè c'è un grezzo da scaricare o un altro pezzo
if Strategy.bSplit then
Strategy.dOffset = 0
MachiningsToAdd = SPLITCUT.Execute( Proc, Part, Strategy)
-- se devo rimuovere tutto il restante
else
-- se abilitato, faccio tagli di PRECUT a zero (come SPLIT)
if Strategy.Parameters.bExecutePreCut then
Strategy.dOffset = Part.dRestLength
MachiningsToAdd = SPLITCUT.Execute( Proc, Part, Strategy)
end
-- TODO: funzione che calcola tagli data una faccia
-- BladeToWaste( Proc, Part)
local Faces = {}
local Face1 = {}
local Face2 = {}
local OptionalParameters = {}
Face1.ptCenter = Proc.Faces[1].ptCenter
Face1.vtNormal = Proc.Faces[1].vtN
OptionalParameters.b3BoxToDicing = Part.b3Raw
Faces = DiceCut.GetDice( Part, Face1, Face2, OptionalParameters)
end
-- aggiungo lavorazioni trovate alla lista generale
for i = 1, #MachiningsToAdd do
MachiningsToAdd[i].Splitting.sStage = 'Tail'
MachiningLib.AddNewMachining( Proc, MachiningsToAdd[i].Splitting, MachiningsToAdd[i].AuxiliaryData)
end
return bAreAllMachiningsAdded, Strategy.Result
else
return nil, Strategy.Result
end
end
-------------------------------------------------------------------------------------------------------------
return TAILCUT
@@ -0,0 +1,13 @@
-- Parametri configurabili da cliente per strategia: TAILCUT
local TAILCUTData = {
sStrategyId = 'TAILCUT',
Parameters = {
{ sName = 'bMakeChamfer', sValue = 'false', sDescriptionShort = 'Execute Chamfer', sDescriptionLong = 'Use the V-Mill to execute chamfers on cut-edges', sType = 'b', sMessageId = '', sMinUserLevel = '1'},
{ sName = 'bForceChainSaw', sValue = 'false', sDescriptionShort = 'Force to use chain saw', sDescriptionLong = 'Force to use chain saw', sType = 'b', sMessageId = '', sMinUserLevel = '1'},
{ sName = 'bExecutePreCut', sValue = 'true', sDescriptionShort = 'Force to add PreCuts', sDescriptionLong = "Autocam will apply a machining on the theoric zero, to avoid collision if the theoric piece length doesn't correspond to the real length", sType = 'b', sMessageId = '', sMinUserLevel = '1'},
{ sName = 'bFinishWithMill', sValue = 'true', sDescriptionShort = 'Finish with mill', sDescriptionLong = 'Use a mill to finish the surface if split with chain saw', sType = 'b', sMessageId = '', sMinUserLevel = '1'}
}
}
return TAILCUTData
+35 -29
View File
@@ -3,11 +3,13 @@
STR0001 = Tenone a coda di rondine. Lama + fresa a coda di rondine
STR0002 = Topologia tipo LapJoint. Svuotatura con fresa
STR0003 = Topologia tipo LapJoint. Lama + motosega
STR0004 = Topologia tipo LapJoint. Motosega
STR0005 = Faccia singola o doppia. Lama, se necessario cubetti.
[Strategies]
; Processing , Gruppo , Topologia , Strategie
;Feature : Cut
10,1,Feature,
10,1,Feature,STR0005
;Feature : Longitudinal Cut
10,0,Feature,
;Feature : Double Cut
@@ -17,53 +19,53 @@ STR0003 = Topologia tipo LapJoint. Lama + motosega
; Feature : Saw Cut
13,0,Feature,
; Feature : Slot
16,0,Pocket-5-Blind,STR0002,STR0003
16,0,Groove-4-Blind,STR0002,STR0003
16,0,Groove-3-Through,STR0002,STR0003
16,0,Pocket-5-Blind,STR0002,STR0003,STR0004
16,0,Groove-4-Blind,STR0002,STR0003,STR0004
16,0,Groove-3-Through,STR0002,STR0003,STR0004
16,0,Groove-3-Blind,STR0002
16,0,Rabbet-2-Through,STR0002
16,0,Tunnel-4-Through,STR0003
16,0,Tunnel-4-Through,STR0003,STR0004
; Feature : Front Slot
17,0,Pocket-5-Blind,STR0002,STR0003
17,0,Groove-4-Blind,STR0002,STR0003
17,0,Pocket-5-Blind,STR0002,STR0003,STR0004
17,0,Groove-4-Blind,STR0002,STR0003,STR0004
17,0,Groove-3-Blind,STR0002
17,0,Groove-3-Through,STR0002,STR0003
17,0,Groove-3-Through,STR0002,STR0003,STR0004
17,0,Rabbet-2-Through,STR0002
17,0,Tunnel-4-Through,STR0003
17,0,Tunnel-4-Through,STR0003,STR0004
; Feature : Birds Mouth
20,0,Feature,
; Feature : Hip or Valley Rafter Notch
25,0,Feature,
; Feature : Ridge Lap
30,1,Pocket-5-Blind,STR0002,STR0003
30,1,Groove-4-Blind,STR0002,STR0003
30,1,Pocket-5-Blind,STR0002,STR0003,STR0004
30,1,Groove-4-Blind,STR0002,STR0003,STR0004
30,1,Groove-3-Blind,STR0002
30,1,Groove-3-Through,STR0002,STR0003
30,1,Groove-3-Through,STR0002,STR0003,STR0004
30,1,Rabbet-2-Through,STR0002
30,1,Tunnel-4-Through,STR0003
30,1,Tunnel-4-Through,STR0003,STR0004
; Feature : Lap Joint
30,0,Pocket-5-Blind,STR0002,STR0003
30,0,Groove-4-Blind,STR0002,STR0003
30,0,Pocket-5-Blind,STR0002,STR0003,STR0004
30,0,Groove-4-Blind,STR0002,STR0003,STR0004
30,0,Groove-3-Blind,STR0002
30,0,Groove-3-Through,STR0002,STR0003
30,0,Groove-3-Through,STR0002,STR0003,STR0004
30,0,Rabbet-2-Through,STR0002
30,0,Tunnel-4-Through,STR0003
30,0,Tunnel-4-Through,STR0003,STR0004
; Feature : Notch/Rabbet
32,0,Pocket-5-Blind,STR0002,STR0003
32,0,Groove-4-Blind,STR0002,STR0003
32,0,Pocket-5-Blind,STR0002,STR0003,STR0004
32,0,Groove-4-Blind,STR0002,STR0003,STR0004
32,0,Groove-3-Blind,STR0002
32,0,Groove-3-Through,STR0002,STR0003
32,0,Groove-3-Through,STR0002,STR0003,STR0004
32,0,Rabbet-2-Through,STR0002
32,0,Tunnel-4-Through,STR0003
32,0,Tunnel-4-Through,STR0003,STR0004
; Feature : Block Haus
33,0,Feature,
; Feature : Notch
34,0,Pocket-5-Blind,STR0002,STR0003
34,0,Groove-4-Blind,STR0002,STR0003
34,0,Pocket-5-Blind,STR0002,STR0003,STR0004
34,0,Groove-4-Blind,STR0002,STR0003,STR0004
34,0,Groove-3-Blind,STR0002
34,0,Groove-3-Through,STR0002,STR0003
34,0,Groove-3-Through,STR0002,STR0003,STR0004
34,0,Rabbet-2-Through,STR0002
34,0,Tunnel-4-Through,STR0003
34,0,Tunnel-4-Through,STR0003,STR0004
; Feature : French Ridge Lap
35,1,Feature,
; Feature : Chamfer
@@ -73,12 +75,12 @@ STR0003 = Topologia tipo LapJoint. Lama + motosega
; Feature : Block Haus Front
38,0,Feature,
; Feature : Pocket
39,0,Pocket-5-Blind,STR0002,STR0003
39,0,Groove-4-Blind,STR0002,STR0003
39,0,Pocket-5-Blind,STR0002,STR0003,STR0004
39,0,Groove-4-Blind,STR0002,STR0003,STR0004
39,0,Groove-3-Blind,STR0002
39,0,Groove-3-Through,STR0002,STR0003
39,0,Groove-3-Through,STR0002,STR0003,STR0004
39,0,Rabbet-2-Through,STR0002
39,0,Tunnel-4-Through,STR0003
39,0,Tunnel-4-Through,STR0003,STR0004
; Feature : Drilling
40,0,Feature,
; Feature : Tenon
@@ -137,6 +139,10 @@ STR0003 = Topologia tipo LapJoint. Lama + motosega
251,0,Feature,
; Feature : Aperture
252,0,Feature,
; Feature : HEADCUT
340,0,Feature,HEADCUT
; Feature : TAILCUT
350,0,Feature,TAILCUT
; Feature : Variant
900,0,Feature,
; Feature Decor
+26
View File
@@ -0,0 +1,26 @@
-- BLADETOWASTE.lua by Egalware s.r.l. 2025/01/08
-- Libreria di supporto a strategie con funzioni comune a strategie diverse.
-- Tabella per definizione modulo
local BLADETOWASTE = {}
-- Include
require( 'EgtBase')
-- Carico i dati globali
local BeamData = require( 'BeamData')
local FeatureLib = require( 'FeatureLib')
local MachiningLib = require( 'MachiningLib')
-- strategie di base
local FaceByBlade = require('FACEBYBLADE')
EgtOutLog( ' BLADETOWASTE started', 1)
-- if dFeatureVolume < StrategyParameters.dMaxWasteVolume + 10 * GEO.EPS_SMALL
-- and dFeatureMaxDimension < StrategyParameters.dMaxWasteLength + 10 * GEO.EPS_SMALL then
-- end
+116
View File
@@ -0,0 +1,116 @@
-- Strategia: FACEBYBLADE
-- Descrizione
-- Strategia di base per la lavorazione di una faccia con lama
-- Feature: tutte
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local MachiningLib = require( 'MachiningLib')
-- Tabella per definizione modulo
local FACEBYBLADE = {}
-------------------------------------------------------------------------------------------------------------
local function CalculateLeadInOut( EdgeToMachine)
local LeadIn = {}
local LeadOut = {}
LeadIn.dStartAddLength = 0
LeadOut.dEndAddLength = 0
LeadIn.nType = MCH_MILL_LI.LINEAR
LeadOut.nType = MCH_MILL_LI.LINEAR
LeadIn.dTangentDistance = 0
LeadOut.dTangentDistance = 0
-- elevazione sempre in negativo
LeadIn.dPerpDistance = BeamData.CUT_SIC + EdgeToMachine.dElevation
LeadOut.dPerpDistance = BeamData.CUT_SIC + EdgeToMachine.dElevation
LeadIn.dElevation = 0
LeadOut.dElevation = 0
LeadIn.dCompLength = 0
LeadOut.dCompLength = 0
LeadIn.dStartAddLength = BeamData.CUT_EXTRA
LeadOut.dEndAddLength = BeamData.CUT_EXTRA
return LeadIn, LeadOut
end
-------------------------------------------------------------------------------------------------------------
-- TODO da sistemare
local function GetSCC( vtMachiningDirection)
local nSCC = MCH_SCC.NONE
if vtMachiningDirection:getZ() < -0.9 then
nSCC = MCH_SCC.ADIR_ZM
elseif vtMachiningDirection:getZ() > 0.9 then
nSCC = MCH_SCC.ADIR_ZP
elseif vtMachiningDirection:getY() < -0.707 then
nSCC = MCH_SCC.ADIR_YM
elseif vtMachiningDirection:getY() > 0.707 then
nSCC = MCH_SCC.ADIR_YP
elseif vtMachiningDirection:getX() < -0.707 then
nSCC = MCH_SCC.ADIR_XM
elseif vtMachiningDirection:getX() > 0.707 then
nSCC = MCH_SCC.ADIR_XP
end
return nSCC
end
-------------------------------------------------------------------------------------------------------------
-- TODO da sistemare
function FACEBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalParameters)
local Cutting = {}
local vtMachiningDirection = EdgeToMachine.vtN
local vtN = Proc.Faces[FaceToMachine.id+1].vtN
Cutting.sDepth = OptionalParameters.sDepth or 0
Cutting.dLongitudinalOffset = OptionalParameters.dLongitudinalOffset or 0
Cutting.dRadialOffset = OptionalParameters.dRadialOffset or 0
Cutting.nType = MCH_MY.MILLING
Cutting.nToolIndex = OptionalParameters.nToolIndex
Cutting.Geometry = {{ Proc.id, FaceToMachine.id}}
Cutting.id = Proc.id
Cutting.vtToolDirection = vtMachiningDirection
-- TODO se l'utensile non arriva dai parametri opzionali va cercato!!
-- ===== calcolo LeadIn/out =====
if OptionalParameters.LeadIn and OptionalParameters.LeadOut then
Cutting.LeadIn, Cutting.LeadOut = OptionalParameters.LeadIn, OptionalParameters.LeadOut
else
Cutting.LeadIn, Cutting.LeadOut = CalculateLeadInOut( EdgeToMachine)
end
-- ===== scelta soluzione braccio C del motore =====
Cutting.nSCC = GetSCC( vtMachiningDirection)
-- ===== parametri da settare in UserNotes =====
Cutting.nFaceuse = OptionalParameters.nFaceuse
Cutting.sUserNotes = EgtSetValInNotes( Cutting.sUserNotes, 'VtFaceUse', vtMachiningDirection)
if OptionalParameters.sUserNotes then
Cutting.sUserNotes = Cutting.sUserNotes .. OptionalParameters.sUserNotes
end
-- ===== scelta senso di lavorazione =====
local bIsSawCCW = TOOLS[Cutting.nToolIndex].bIsCCW
local bInvert
-- se la lama ruota in senso antiorario inverto la direzione di lavorazione, per avere rotazione lama opposta a avanzamento
if bInvert == nil then
bInvert = ( not bIsSawCCW)
if bIsSawCCW then
bInvert = (( Cutting.nFaceuse == MCH_MILL_FU.ORTHO_FRONT and vtN:getX() < 0) or ( Cutting.nFaceuse == MCH_MILL_FU.ORTHO_BACK and vtN:getX() > 0))
else
bInvert = (( Cutting.nFaceuse == MCH_MILL_FU.ORTHO_FRONT and vtN:getX() > 0) or ( Cutting.nFaceuse == MCH_MILL_FU.ORTHO_BACK and vtN:getX() < 0))
end
end
Cutting.bInvert = bInvert
Cutting.nWorkside = EgtIf( bInvert, MCH_MILL_WS.RIGHT, MCH_MILL_WS.LEFT)
return Cutting
end
-------------------------------------------------------------------------------------------------------------
return FACEBYBLADE
@@ -17,8 +17,7 @@ local function CalculateLeadInOut( Machining, EdgeToMachine)
-- TODO implementare le funzioni di Tool Collision Avoidance (vedi wiki e FacesBysaw -> CalcLeadInOutPerpGeom)
-- si determina l'eventuale riduzione da applicare in caso di inizio o fine chiusi
local dAddLengthToReduce = 0
dAddLengthToReduce = sqrt( Machining.dDepthToMachine * TOOLS[Machining.nToolIndex].dDiameter - Machining.dDepthToMachine * Machining.dDepthToMachine)
local dAddLengthToReduce = sqrt( Machining.dDepthToMachine * TOOLS[Machining.nToolIndex].dDiameter - Machining.dDepthToMachine * Machining.dDepthToMachine)
if Machining.bInvert then
Machining.bIsStartClosed, Machining.bIsEndClosed = Machining.bIsEndClosed, Machining.bIsStartClosed
@@ -32,7 +31,7 @@ local function CalculateLeadInOut( Machining, EdgeToMachine)
LeadOut.nType = MCH_MILL_LI.LINEAR
LeadIn.dTangentDistance = 0
LeadOut.dTangentDistance = 0
if EdgeToMachine.dElevation > -10 * GEO.EPS_SMALL then
if AreSameVectorApprox( Machining.vtToolDirection, EdgeToMachine.vtN) then
LeadIn.dPerpDistance = EdgeToMachine.dElevation + BeamData.CUT_SIC
LeadOut.dPerpDistance = EdgeToMachine.dElevation + BeamData.CUT_SIC
else
@@ -91,28 +90,41 @@ function SLOTBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar
Cutting.dDepthToMachine = 0
Cutting.sMessage = ''
Cutting.idProc = Proc.id
Cutting.dResidualDepth = abs( EdgeToMachine.dElevation)
Cutting.dResidualDepth = EdgeToMachine.dElevation
Cutting.dBladeMarkLength = 0
Cutting.sEdgeType = EdgeToMachine.sType
Cutting.nFeatureSegment = 1
-- parametri opzionali
local bForceLongcutBlade = OptionalParameters.bForceLongcutBlade or false
local dPocketHeight = 0
if Proc.Topology.sFamily == 'Tunnel' then
dPocketHeight = Proc.MainFaces.SideFaces[1].MainEdges.OppositeEdges[1].dLength
else
if FaceToMachine.sType == 'Long' then
dPocketHeight = Proc.MainFaces.BottomFaces[1].MainEdges.SideEdges[1].dLength
elseif FaceToMachine.sType == 'Side' then
dPocketHeight = Proc.MainFaces.BottomFaces[1].MainEdges.LongEdges[1].dLength
end
if not OptionalParameters then
OptionalParameters = {}
end
local bForceLongcutBlade = OptionalParameters.bForceLongcutBlade or false
local dExtendAfterTail = OptionalParameters.dExtendAfterTail or 10000
local dPocketHeight = OptionalParameters.dPocketHeight or 0
local dDepthToMachine = min( OptionalParameters.dDepthToMachine or EdgeToMachine.dElevation, EdgeToMachine.dElevation)
local bIsSplitFeature = OptionalParameters.bIsSplitFeature or false
local bOppositeToolDirection = OptionalParameters.bOppositeToolDirection or false
-- lunghezze e punti caratteristici della lavorazione e del lato lavorato
Cutting.dLengthToMachine = EdgeToMachine.dLength
Cutting.dEdgeLength = EdgeToMachine.dLength
if bOppositeToolDirection then
Cutting.vtToolDirection = -EdgeToMachine.vtN
else
Cutting.vtToolDirection = EdgeToMachine.vtN
end
Cutting.vtEdgeDirection = EdgeToMachine.vtN ^ FaceToMachine.vtN
-- TODO conviene spostare questi calcoli nel FaceData?
Cutting.ptEdge1, _, Cutting.ptEdge2 = EgtSurfTmFacetOppositeSide( Proc.id, FaceToMachine.id, -Cutting.vtToolDirection, GDB_ID.ROOT)
local b3BoxEdge = BBox3d( Cutting.ptEdge1, Cutting.ptEdge2)
Cutting.dLengthOnX = b3BoxEdge:getDimX()
--
-- ricerca utensile
local ToolSearchParameters = {}
ToolSearchParameters.dElevation = abs( EdgeToMachine.dElevation)
ToolSearchParameters.vtToolDirection = EdgeToMachine.vtToolDirection
ToolSearchParameters.dElevation = EdgeToMachine.dElevation
ToolSearchParameters.vtToolDirection = Cutting.vtToolDirection
ToolSearchParameters.bAllowTopHead = true
ToolSearchParameters.bAllowBottomHead = false
ToolSearchParameters.bForceLongcutBlade = bForceLongcutBlade
@@ -128,13 +140,13 @@ function SLOTBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar
-- verifica dimensioni tasca compatibili
-- se tasca meno spessa della lama la strategia non è applicabile
if TOOLS[Cutting.nToolIndex].dThickness > dPocketHeight + 10 * GEO.EPS_SMALL then
if OptionalParameters.dPocketHeight and ( TOOLS[Cutting.nToolIndex].dThickness > dPocketHeight + 10 * GEO.EPS_SMALL) then
Cutting.sMessage = 'Pocket too narrow for blade thickness'
Cutting.bIsApplicable = false
EgtOutLog( Cutting.sMessage)
return Cutting, EdgeToMachine.dElevation
end
if #( Proc.MainFaces.SideFaces) > 1 then
if Proc.MainFaces and #( Proc.MainFaces.SideFaces) > 1 then
-- se tasca più stretta della lama la strategia non è applicabile
if TOOLS[Cutting.nToolIndex].dDiameter > EdgeToMachine.dLength + 10 * GEO.EPS_SMALL then
Cutting.sMessage = 'Pocket too narrow for blade diameter'
@@ -158,7 +170,7 @@ function SLOTBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar
Cutting.nWorkside = MCH_MILL_WS.LEFT
Cutting.bInvert = false
end
if EdgeToMachine.dElevation < -10 * GEO.EPS_SMALL then
if bOppositeToolDirection then
Cutting.bInvert = not Cutting.bInvert
end
-- TODO gestire lama da sotto e lama downUp
@@ -169,22 +181,22 @@ function SLOTBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar
Cutting.bToolInvert = false
end
-- profondità da lavorare e offset radiale
if TOOLS[Cutting.nToolIndex].dMaxDepth > abs( EdgeToMachine.dElevation) - 10 * GEO.EPS_SMALL then
if TOOLS[Cutting.nToolIndex].dMaxDepth > dDepthToMachine - 10 * GEO.EPS_SMALL then
-- TODO la depth dovrebbe essere quella del machining
Cutting.dDepthToMachine = abs( EdgeToMachine.dElevation)
Cutting.dDepthToMachine = dDepthToMachine
Cutting.dResidualDepth = 0
if EdgeToMachine.dElevation > -10 * GEO.EPS_SMALL then
Cutting.dRadialOffset = 0
if bOppositeToolDirection then
Cutting.dRadialOffset = -dDepthToMachine
else
Cutting.dRadialOffset = EdgeToMachine.dElevation
Cutting.dRadialOffset = EdgeToMachine.dElevation - dDepthToMachine
end
else
Cutting.dDepthToMachine = TOOLS[Cutting.nToolIndex].dMaxDepth - 1
Cutting.dResidualDepth = abs( EdgeToMachine.dElevation) - Cutting.dDepthToMachine
if EdgeToMachine.dElevation > -10 * GEO.EPS_SMALL then
Cutting.dRadialOffset = EdgeToMachine.dElevation - Cutting.dDepthToMachine
else
Cutting.dResidualDepth = EdgeToMachine.dElevation - Cutting.dDepthToMachine
if bOppositeToolDirection then
Cutting.dRadialOffset = -Cutting.dDepthToMachine
else
Cutting.dRadialOffset = EdgeToMachine.dElevation - Cutting.dDepthToMachine
end
end
-- completamento
@@ -203,13 +215,13 @@ function SLOTBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar
-- overlap
Cutting.dOverlap = 0
-- faceuse
if EdgeToMachine.dElevation > - 10 * GEO.EPS_SMALL then
Cutting.nFaceuse = BeamLib.GetNearestOrthoOpposite( EdgeToMachine.vtToolDirection)
if bOppositeToolDirection then
Cutting.nFaceuse = BeamLib.GetNearestOrthoOpposite( -Cutting.vtToolDirection)
else
Cutting.nFaceuse = BeamLib.GetNearestOrthoOpposite( -EdgeToMachine.vtToolDirection)
Cutting.nFaceuse = BeamLib.GetNearestOrthoOpposite( Cutting.vtToolDirection)
end
-- SCC
Cutting.nSCC = GetSCC( EdgeToMachine.vtToolDirection)
Cutting.nSCC = GetSCC( Cutting.vtToolDirection)
-- asse bloccato
Cutting.sBlockedAxis = BeamLib.GetBlockedAxis( Cutting.nToolIndex, 'perpendicular', Part.b3Raw, FaceToMachine.vtN, EgtIf( FaceToMachine.vtN:getX() > 0, X_AX(), -X_AX()))
-- approccio e retrazione
@@ -231,22 +243,42 @@ function SLOTBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar
Cutting.dBladeMarkLength = abs( Cutting.LeadOut.dEndAddLength)
end
-- geometria
Cutting.Geometry = {{Proc.id, FaceToMachine.id}}
Cutting.Geometry = {{Cutting.idProc, FaceToMachine.id}}
-- nome operazione
Cutting.sOperationName = 'Cut_' .. ( EgtGetName( Cutting.idProc) or tostring( Cutting.idProc)) .. '_' .. tostring( FaceToMachine.id + 1)
-- eventuale avviso di danneggiamento pezzo successivo
-- TODO da sostituire con check se si riesce a separare e il grezzo dietro è lungo a sufficienza
-- local dOffsideLength = max( Cutting.LeadIn.dStartAddLength, Cutting.LeadOut.dEndAddLength) + TOOLS[Cutting.nToolIndex].dDiameter / 2 + 10 * GEO.EPS_SMALL
-- if ( not Proc.bTail or Proc.bAdvTail) and Proc.AffectedFaces.bLeft and ( Proc.dDistanceToNextPart < dOffsideLength) then
-- local sDamageNextPieceMessage = 'Feature '.. Proc.idFeature .. ' : sawblade can damage next piece.'
-- if #Cutting.sMessage > 0 then
-- Cutting.sMessage = Cutting.sMessage .. '\n' .. sDamageNextPieceMessage
-- else
-- Cutting.sMessage = sDamageNextPieceMessage
-- end
-- EgtOutLog( sDamageNextPieceMessage)
-- end
-- se lavorazione aperta sulla coda, eventuali aggiustamenti
-- TODO valutare se fare funzione a parte
if Proc.AffectedFaces.bLeft and ( EdgeToMachine.sType == 'Bottom' or ( Cutting.vtToolDirection:getX() < 0.707)) then
local dLengthOnX = Cutting.dLengthOnX
-- se feature splittata non si considera la lunghezza della feature per il check spostamento dopo separazione
if bIsSplitFeature then
dLengthOnX = 0
end
local bStartLeft = MachiningLib.StartsLeftSide( Cutting)
local dAddLengthLeftSide = Cutting.LeadOut.dEndAddLength
local dAddLengthToReduce = sqrt( Cutting.dDepthToMachine * TOOLS[Cutting.nToolIndex].dDiameter - Cutting.dDepthToMachine * Cutting.dDepthToMachine)
if bStartLeft then
dAddLengthLeftSide = Cutting.LeadIn.dStartAddLength
end
if not AreSameOrOppositeVectorApprox( EdgeToMachine.vtN, Y_AX()) then
if MachiningLib.CanMoveAfterSplitcut( dLengthOnX, Part) then
Cutting.sStage = 'AfterTail'
else
Cutting.bIsApplicable = false
end
elseif dAddLengthLeftSide + dAddLengthToReduce > dExtendAfterTail then
if MachiningLib.CanMoveAfterSplitcut( dLengthOnX, Part) then
Cutting.sStage = 'AfterTail'
else
if bStartLeft then
Cutting.LeadIn.dStartAddLength = - dAddLengthToReduce + dExtendAfterTail
else
Cutting.LeadOut.dEndAddLength = - dAddLengthToReduce + dExtendAfterTail
end
end
end
end
return Cutting
@@ -52,29 +52,39 @@ function SLOTBYCHAINSAW.Make( Proc, Part, FaceToMachine, EdgeToMachine, Optional
local Mortising = {}
Mortising.bIsApplicable = true
Mortising.dDepthToMachine = 0
Mortising.dResidualDepth = abs( EdgeToMachine.dElevation)
Mortising.dResidualDepth = EdgeToMachine.dElevation
Mortising.sMessage = ''
Mortising.idProc = Proc.id
Mortising.sEdgeType = EdgeToMachine.sType
Mortising.nFeatureSegment = 1
-- parametri opzionali
if not OptionalParameters then
OptionalParameters = {}
end
local bUseZigZagMortising = OptionalParameters.bUseZigZagMortising or false
local sSideToMachine = OptionalParameters.sSideToMachine or ''
local dLengthToMachine = OptionalParameters.dLengthToMachine or EdgeToMachine.dLength
local dCustomMaxElev = OptionalParameters.dMaxElev or abs( EdgeToMachine.dElevation)
local dCustomMaxElev = OptionalParameters.dMaxElev or EdgeToMachine.dElevation
local bStopAtHalfElevation = OptionalParameters.bStopAtHalfElevation or false
local dExtendAfterTail = OptionalParameters.dExtendAfterTail or 10000
local dPocketHeight = OptionalParameters.dPocketHeight or 0
local bIsSplitFeature = OptionalParameters.bIsSplitFeature or false
local bOppositeToolDirection = OptionalParameters.bOppositeToolDirection or false
-- altezza tasca, in base alla topologia
local dPocketHeight = 0
if Proc.Topology.sFamily == 'Tunnel' then
dPocketHeight = Proc.MainFaces.SideFaces[1].MainEdges.OppositeEdges[1].dLength
-- lunghezze e punti caratteristici della lavorazione e del lato lavorato
Mortising.dLengthToMachine = dLengthToMachine
-- TODO serve un modo migliore di calcolare la lunghezza lungo X; attenzione che serve la lunghezza reale di lavoro, non quella del lato
-- TODO andrà aggiornata dopo il calcolo LeadIn/Out
Mortising.dLengthOnX = abs( dLengthToMachine * EdgeToMachine.vtN:getY())
Mortising.dEdgeLength = EdgeToMachine.dLength
if bOppositeToolDirection then
Mortising.vtToolDirection = -EdgeToMachine.vtN
else
if FaceToMachine.sType == 'Long' then
dPocketHeight = Proc.MainFaces.BottomFaces[1].MainEdges.SideEdges[1].dLength
elseif FaceToMachine.sType == 'Side' then
dPocketHeight = Proc.MainFaces.BottomFaces[1].MainEdges.LongEdges[1].dLength
end
Mortising.vtToolDirection = EdgeToMachine.vtN
end
Mortising.vtEdgeDirection = EdgeToMachine.vtN ^ FaceToMachine.vtN
Mortising.ptEdge1, _, Mortising.ptEdge2 = EgtSurfTmFacetOppositeSide( Proc.id, FaceToMachine.id, -Mortising.vtToolDirection, GDB_ID.ROOT)
-- ricerca utensile
local bExtendWithCornerRadius = false
@@ -83,17 +93,17 @@ function SLOTBYCHAINSAW.Make( Proc, Part, FaceToMachine, EdgeToMachine, Optional
( EdgeToMachine.sType == 'Opposite' and Proc.Topology.sFamily == 'Tunnel') then
bExtendWithCornerRadius = true
Mortising.dDepthToMachine = abs( EdgeToMachine.dElevation) + BeamData.CUT_EXTRA
Mortising.dDepthToMachine = EdgeToMachine.dElevation + BeamData.CUT_EXTRA
else
Mortising.dDepthToMachine = abs( EdgeToMachine.dElevation)
Mortising.dDepthToMachine = EdgeToMachine.dElevation
end
else
bExtendWithCornerRadius = true
Mortising.dDepthToMachine = abs( EdgeToMachine.dElevation) / 2 + BeamData.CUT_EXTRA_MIN
Mortising.dDepthToMachine = EdgeToMachine.dElevation / 2 + BeamData.CUT_EXTRA_MIN
end
local ToolSearchParameters = {}
local ToolInfo = {}
ToolSearchParameters.vtToolDirection = EdgeToMachine.vtToolDirection
ToolSearchParameters.vtToolDirection = Mortising.vtToolDirection
ToolSearchParameters.bAllowTopHead = true
ToolSearchParameters.bAllowBottomHead = true
ToolSearchParameters.dElevation = Mortising.dDepthToMachine
@@ -110,13 +120,13 @@ function SLOTBYCHAINSAW.Make( Proc, Part, FaceToMachine, EdgeToMachine, Optional
-- verifica dimensioni tasca compatibili
-- se tasca meno spessa della sega a catena la strategia non è applicabile
if TOOLS[Mortising.nToolIndex].dThickness > dPocketHeight + 10 * GEO.EPS_SMALL then
if OptionalParameters.dPocketHeight and ( TOOLS[Mortising.nToolIndex].dThickness > dPocketHeight + 10 * GEO.EPS_SMALL) then
Mortising.sMessage = 'Pocket too narrow for chainsaw thickness'
Mortising.bIsApplicable = false
EgtOutLog( Mortising.sMessage)
return Mortising
end
if #( Proc.MainFaces.SideFaces) > 1 then
if Proc.MainFaces and #( Proc.MainFaces.SideFaces) > 1 then
-- se tasca più stretta della sega a catena la strategia non è applicabile
if TOOLS[Mortising.nToolIndex].dWidth > EdgeToMachine.dLength + 10 * GEO.EPS_SMALL then
Mortising.sMessage = 'Pocket too narrow for chainsaw width'
@@ -135,12 +145,12 @@ function SLOTBYCHAINSAW.Make( Proc, Part, FaceToMachine, EdgeToMachine, Optional
Mortising.bIsEndClosed = not EdgeToMachine.bIsEndOpen
-- lato di lavoro e inversioni
Mortising.bInvert = false
if EdgeToMachine.dElevation > -10 * GEO.EPS_SMALL then
Mortising.nWorkside = MCH_MILL_WS.RIGHT
Mortising.bToolInvert = false
else
if bOppositeToolDirection then
Mortising.nWorkside = MCH_MILL_WS.LEFT
Mortising.bToolInvert = true
else
Mortising.nWorkside = MCH_MILL_WS.RIGHT
Mortising.bToolInvert = false
end
-- profondità e offset longitudinale
if bExtendWithCornerRadius then
@@ -148,19 +158,19 @@ function SLOTBYCHAINSAW.Make( Proc, Part, FaceToMachine, EdgeToMachine, Optional
end
if TOOLS[Mortising.nToolIndex].dMaxMaterial > Mortising.dDepthToMachine - 10 * GEO.EPS_SMALL then
Mortising.dResidualDepth = 0
if EdgeToMachine.dElevation > -10 * GEO.EPS_SMALL then
Mortising.dLongitudinalOffset = 0
else
Mortising.dLongitudinalOffset = abs( EdgeToMachine.dElevation) - Mortising.dDepthToMachine
end
else
Mortising.dDepthToMachine = TOOLS[Mortising.nToolIndex].dMaxMaterial - 1
Mortising.dResidualDepth = abs( EdgeToMachine.dElevation) - Mortising.dDepthToMachine
if EdgeToMachine.dElevation > -10 * GEO.EPS_SMALL then
if bOppositeToolDirection then
Mortising.dLongitudinalOffset = EdgeToMachine.dElevation - Mortising.dDepthToMachine
else
Mortising.dLongitudinalOffset = 0
end
else
Mortising.dDepthToMachine = TOOLS[Mortising.nToolIndex].dMaxMaterial - 1
Mortising.dResidualDepth = EdgeToMachine.dElevation - Mortising.dDepthToMachine
if bOppositeToolDirection then
Mortising.dLongitudinalOffset = 0
else
Mortising.dLongitudinalOffset = EdgeToMachine.dElevation - Mortising.dDepthToMachine
end
Mortising.sMessage = 'Feature '.. Proc.idFeature .. ' : chainsaw elevation (' .. EgtNumToString( EdgeToMachine.dElevation, 1) .. ') bigger than max tool depth (' .. EgtNumToString( Mortising.dDepthToMachine, 1) .. ')'
EgtOutLog( Mortising.sMessage)
end
@@ -168,12 +178,12 @@ function SLOTBYCHAINSAW.Make( Proc, Part, FaceToMachine, EdgeToMachine, Optional
Mortising.dCompletionPercentage = 100 - Mortising.dResidualDepth / Mortising.dDepthToMachine
-- massima elevazione
if dCustomMaxElev < Mortising.dDepthToMachine - 10 * GEO.EPS_SMALL then
Mortising.dMaxElev = dCustomMaxElev
Mortising.dMaxElev = max( dCustomMaxElev, dCustomMaxElev - Mortising.dLongitudinalOffset)
end
-- offset radiale
Mortising.dRadialOffset = 0
-- distanza di sicurezza
Mortising.dStartSafetyLength = max( EdgeToMachine.dElevation, 10)
Mortising.dStartSafetyLength = max( EdgeToMachine.dElevation, ( TOOLS[Mortising.nToolIndex].SetupInfo.dZSafeDelta or 60) + EgtMdbGetGeneralParam( MCH_GP.SAFEZ))
-- overlap
Mortising.dOverlap = 0
-- step
@@ -185,21 +195,21 @@ function SLOTBYCHAINSAW.Make( Proc, Part, FaceToMachine, EdgeToMachine, Optional
end
Mortising.Steps.dStep = TOOLS[Mortising.nToolIndex].dStep
-- faceuse
if EdgeToMachine.dElevation > - 10 * GEO.EPS_SMALL then
Mortising.nFaceuse = BeamLib.GetNearestParalOpposite( EdgeToMachine.vtToolDirection)
if bOppositeToolDirection then
Mortising.nFaceuse = BeamLib.GetNearestParalOpposite( -Mortising.vtToolDirection)
else
Mortising.nFaceuse = BeamLib.GetNearestParalOpposite( -EdgeToMachine.vtToolDirection)
Mortising.nFaceuse = BeamLib.GetNearestParalOpposite( Mortising.vtToolDirection)
end
-- SCC
Mortising.SCC = MCH_SCC.NONE
-- asse bloccato e angoli suggeriti
local vtRes = FaceToMachine.vtN ^ EdgeToMachine.vtToolDirection
local vtRes = FaceToMachine.vtN ^ EdgeToMachine.vtN
if abs( vtRes:getZ()) < 10 * GEO.EPS_SMALL then
Mortising.sBlockedAxis = BeamLib.GetBlockedAxis( Mortising.nToolIndex, 'perpendicular', Part.b3Raw, FaceToMachine.vtN)
Mortising.sSuggestedAngles = BeamLib.GetChainSawInitAngs( FaceToMachine.vtN, EdgeToMachine.vtToolDirection, 1)
elseif EdgeToMachine.vtToolDirection:getZ() < 10 * GEO.EPS_SMALL then
Mortising.sSuggestedAngles = BeamLib.GetChainSawInitAngs( FaceToMachine.vtN, EdgeToMachine.vtN, 1)
elseif EdgeToMachine.vtN:getZ() < 10 * GEO.EPS_SMALL then
Mortising.sBlockedAxis = BeamLib.GetBlockedAxis( Mortising.nToolIndex, 'parallel', Part.b3Raw, FaceToMachine.vtN)
Mortising.sSuggestedAngles = BeamLib.GetChainSawInitAngs( FaceToMachine.vtN, EdgeToMachine.vtToolDirection, 2)
Mortising.sSuggestedAngles = BeamLib.GetChainSawInitAngs( FaceToMachine.vtN, EdgeToMachine.vtN, 2)
end
-- approccio e retrazione
Mortising.LeadIn, Mortising.LeadOut = CalculateLeadInOut( Mortising, EdgeToMachine, sSideToMachine, dLengthToMachine)
@@ -210,21 +220,39 @@ function SLOTBYCHAINSAW.Make( Proc, Part, FaceToMachine, EdgeToMachine, Optional
-- nome operazione
Mortising.sOperationName = 'Chainsaw_' .. ( EgtGetName( Mortising.idProc) or tostring( Mortising.idProc)) .. '_' .. tostring( FaceToMachine.id + 1)
-- eventuale avviso di danneggiamento pezzo successivo
-- TODO da sostituire con check se si riesce a separare e il grezzo dietro è lungo a sufficienza
-- local dOffsideLength = max( Mortising.LeadIn.dStartAddLength, Mortising.LeadOut.dEndAddLength) + TOOLS[Mortising.nToolIndex].dWidth / 2 + 10 * GEO.EPS_SMALL
-- if ( not Proc.bTail or Proc.bAdvTail) and Proc.AffectedFaces.bLeft and ( Proc.dDistanceToNextPart < dOffsideLength) then
-- local sDamageNextPieceMessage = 'Feature '.. Proc.idFeature .. ' : chainsaw can damage next piece.'
-- if #Mortising.sMessage > 0 then
-- Mortising.sMessage = Mortising.sMessage .. '\n' .. sDamageNextPieceMessage
-- else
-- Mortising.sMessage = sDamageNextPieceMessage
-- end
-- EgtOutLog( sDamageNextPieceMessage)
-- end
-- se lavorazione aperta sulla coda, eventuali aggiustamenti
-- TODO valutare se fare funzione a parte
if Proc.AffectedFaces.bLeft and ( EdgeToMachine.sType == 'Bottom' or ( Mortising.vtToolDirection:getX() < 0.707)) then
local dLengthOnX = Mortising.dLengthOnX
-- se feature splittata non si considera la lunghezza della feature per il check spostamento dopo separazione
if bIsSplitFeature then
dLengthOnX = 0
end
local bStartLeft = MachiningLib.StartsLeftSide( Mortising)
local dAddLengthLeftSide = Mortising.LeadOut.dEndAddLength
if bStartLeft then
dAddLengthLeftSide = Mortising.LeadIn.dStartAddLength
end
if not AreSameOrOppositeVectorApprox( EdgeToMachine.vtN, Y_AX()) then
if MachiningLib.CanMoveAfterSplitcut( dLengthOnX, Part) then
Mortising.sStage = 'AfterTail'
else
Mortising.bIsApplicable = false
end
elseif dAddLengthLeftSide + TOOLS[Mortising.nToolIndex].dDiameter / 2 > dExtendAfterTail then
if MachiningLib.CanMoveAfterSplitcut( dLengthOnX, Part) then
Mortising.sStage = 'AfterTail'
else
if bStartLeft then
Mortising.LeadIn.dStartAddLength = - TOOLS[Mortising.nToolIndex].dDiameter / 2 + dExtendAfterTail
else
Mortising.LeadOut.dEndAddLength = - TOOLS[Mortising.nToolIndex].dDiameter / 2 + dExtendAfterTail
end
end
end
end
return Mortising
end
-------------------------------------------------------------------------------------------------------------
+361
View File
@@ -0,0 +1,361 @@
-- SPLITCUT.lua by Egalware s.r.l. 2024/04/02
-- Libreria di supporto a strategie con funzioni comune a strategie diverse.
-- Tabella per definizione modulo
local SPLITCUT = {}
-- Include
require( 'EgtBase')
-- Carico i dati globali
local BeamData = require( 'BeamData')
local FeatureLib = require( 'FeatureLib')
local MachiningLib = require( 'MachiningLib')
-- strategie di base
local FaceByBlade = require('FACEBYBLADE')
EgtOutLog( ' SPLITCUT started', 1)
-----------------------------------------------------------------------------------
---------------------- FUNZIONI DI SPLIT ------------------------------------------
-----------------------------------------------------------------------------------
function SPLITCUT.GetStrategy( Proc, Part, OptionalParameters)
local Machining = {}
local Result = {}
-- sTypeMachining = BladeSideSingle\ BladeSideDouble\ BladeHorizontalSingle\ BladeHorizontalDouble\ ChainSawHorizontal\ ChainSawSideSingle\ ChainSawSideDouble\ ChainSawPlusBlade\ Mill\ None
Machining.sTypeMachining = 'None'
local Splitting = {}
-- imposto parametri di ricerca utensile in base a topologia
local ToolSearchParameters = {}
ToolSearchParameters.vtToolDirection = Proc.Faces[1].vtN
-- ===== RICERCA UTENSILE =====
-- cerco lama sopra
Splitting.bIsApplicable = false
ToolSearchParameters.bAllowTopHead = true
ToolSearchParameters.bAllowBottomHead = false
Splitting.ToolInfo = {}
Splitting.ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters)
if Splitting.ToolInfo.nToolIndex then
Splitting.bIsApplicable = true
local ParametersMRR = {}
ParametersMRR.nToolIndex = Splitting.ToolInfo.nToolIndex
Splitting.dMRR = MachiningLib.GetToolMRR( ParametersMRR)
end
table.insert( Machining, Splitting)
-- cerco lama sotto
Splitting = {}
Splitting.bIsApplicable = false
ToolSearchParameters.bAllowTopHead = false
ToolSearchParameters.bAllowBottomHead = true
Splitting.ToolInfo = {}
Splitting.ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters)
if Splitting.ToolInfo.nToolIndex then
Splitting.bIsApplicable = true
local ParametersMRR = {}
ParametersMRR.nToolIndex = Splitting.ToolInfo.nToolIndex
Splitting.dMRR = MachiningLib.GetToolMRR( ParametersMRR)
end
table.insert( Machining, Splitting)
-- cerco motosega
Splitting = {}
Splitting.bIsApplicable = false
table.insert( Machining, Splitting)
-- cerco fresa
Splitting = {}
Splitting.bIsApplicable = false
table.insert( Machining, Splitting)
-- ===== SCELTA LAVORAZIONI =====
-- forzature da parametri
if OptionalParameters.bForceChainSaw then
Machining[1].bIsApplicable = false
Machining[2].bIsApplicable = false
end
-- setto valori di default. Impossibile che taglio di separazione sia incompleto
Result.sStatus = 'Completed'
Result.nCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
Result.dMRR = 1
-- correzioni sul massimo materiale lama, considerando ingombri vari
local dMaxMatBladeSideSingle
local dMaxMatBladeSideDouble
local dMaxMatBladeHorizontalSingle
local dMaxMatBladeHorizontalDouble
if Machining[1].bIsApplicable then
local dMaxMat = TOOLS[Machining[1].ToolInfo.nToolIndex].dMaxMaterial
local dRadius = TOOLS[Machining[1].ToolInfo.nToolIndex].dDiameter / 2
local sHead = TOOLS[Machining[1].ToolInfo.nToolIndex].sHead
-- se taglio di fianco disponibile, si controlla il massimo materiale reale. Per pezzi alti, bisogna controllare anche l'ingombro asse Z nelle 4 direzioni.
if Part.dHeight < BeamData.MIN_DIM_HBEAM then
dMaxMat = min( dMaxMat, BeamData.MAX_DIM_HTCUT)
dMaxMatBladeSideSingle = dMaxMat
dMaxMatBladeSideDouble = dMaxMat * 2
else
if BeamData.GetMaxMatReductionBladeCut then
dMaxMatBladeSideSingle = min( max( dRadius - BeamData.GetMaxMatReductionBladeCut( sHead, Y_AX()), dRadius - BeamData.GetMaxMatReductionBladeCut( sHead, -Y_AX())),
TOOLS[Machining[1].ToolInfo.nToolIndex].dMaxMaterial)
dMaxMatBladeSideDouble = dRadius - BeamData.GetMaxMatReductionBladeCut( sHead, Y_AX()) + dRadius - BeamData.GetMaxMatReductionBladeCut( sHead, -Y_AX())
else
dMaxMatBladeSideSingle = abs( BeamData.MAX_DIM_HTCUT_HBEAM)
dMaxMatBladeSideDouble = abs( BeamData.MAX_DIM_HTCUT_HBEAM) * 2
end
end
-- se taglio orizzontale
if BeamData.GetMaxMatReductionBladeCut then
dMaxMatBladeHorizontalSingle = min( TOOLS[Machining[1].ToolInfo.nToolIndex].dMaxMaterial, dRadius - BeamData.GetMaxMatReductionBladeCut( TOOLS[Machining[1].ToolInfo.nToolIndex].sHead, -Z_AX()))
else
dMaxMatBladeHorizontalSingle = TOOLS[Machining[1].ToolInfo.nToolIndex].dMaxMaterial
end
end
if Machining[2].bIsApplicable then
if BeamData.GetMaxMatReductionBladeCut then
local dRadius = TOOLS[Machining[2].ToolInfo.nToolIndex].dDiameter / 2
dMaxMatBladeHorizontalDouble = min( TOOLS[Machining[2].ToolInfo.nToolIndex].dMaxMaterial, dRadius - BeamData.GetMaxMatReductionBladeCut( TOOLS[Machining[2].ToolInfo.nToolIndex].sHead, Z_AX()))
else
dMaxMatBladeHorizontalDouble = TOOLS[Machining[2].ToolInfo.nToolIndex].dMaxMaterial
end
end
-- TODO considerare di tagliare con il massimo materiale possibile per non salire troppo in Z (macchine tipo PF), oppure non scendere troppo (tipo Kairos)
-- BladeSideSingle (taglio di lama singolo di fianco)
if Machining[1].bIsApplicable and ( dMaxMatBladeSideSingle - BeamData.CUT_EXTRA) > Part.dWidth + 10 * GEO.EPS_SMALL then
Result.nQuality = FeatureLib.GetFeatureQuality( 'Blade')
Machining.sTypeMachining = 'BladeSideSingle'
Machining[2].bIsApplicable = false
Machining[3].bIsApplicable = false
Machining[4].bIsApplicable = false
return Machining, Result
-- TODO considerare di tagliare con il massimo materiale possibile per non salire troppo in Z (macchine tipo PF), oppure non scendere troppo (tipo Kairos)
-- BladeSideDouble (taglio di lama doppio di fianco)
elseif Machining[1].bIsApplicable and ( dMaxMatBladeSideDouble - BeamData.CUT_EXTRA) > Part.dWidth + 10 * GEO.EPS_SMALL then
Result.nQuality = FeatureLib.GetFeatureQuality( 'Blade')
Result.dMRR = Result.dMRR/2
Machining.sTypeMachining = 'BladeSideDouble'
Machining[2].bIsApplicable = false
Machining[3].bIsApplicable = false
Machining[4].bIsApplicable = false
return Machining, Result
-- BladeHorizontalSingle (taglio di lama singolo orizzontale)
elseif Machining[1].bIsApplicable and ( dMaxMatBladeHorizontalSingle - BeamData.CUT_EXTRA) > Part.dHeight + 10 * GEO.EPS_SMALL then
Result.nQuality = FeatureLib.GetFeatureQuality( 'Blade')
Machining.sTypeMachining = 'BladeHorizontalSingle'
Machining[2].bIsApplicable = false
Machining[3].bIsApplicable = false
Machining[4].bIsApplicable = false
return Machining, Result
-- BladeHorizontalDouble (taglio di lama doppio orizzontale)
elseif Machining[1].bIsApplicable and Machining[2].bIsApplicable and
( dMaxMatBladeHorizontalSingle + dMaxMatBladeHorizontalDouble - BeamData.CUT_EXTRA) > Part.dHeight + 10 * GEO.EPS_SMALL then
Result.nQuality = FeatureLib.GetFeatureQuality( 'Blade')
Result.dMRR = Result.dMRR/2
Machining.sTypeMachining = 'BladeHorizontalDouble'
Machining[1].ToolInfo.dMaxMatBladeFromTop = dMaxMatBladeHorizontalSingle
Machining[2].ToolInfo.dMaxMatBladeFromDown = dMaxMatBladeHorizontalDouble
Machining[3].bIsApplicable = false
Machining[4].bIsApplicable = false
return Machining, Result
-- TODO : casi con motosega da completare
-- ChainSawHorizontal (motosega)
-- ChainSawSideSingle (motosega)
-- ChainSawSideDouble (motosega)
-- ChainSawPlusBlade (motosega più lama orizzontale)
-- Mill (svuotatura)
end
-- se non ho trovato neanche una lavorazione completa, non posso separare
if Machining.sTypeMachining == 'None' then
Result.sStatus = 'Not-Applicable'
Result.nCompletionIndex = 0
Result.dMRR = 0
Result.nQuality = 0
Result.sInfo = 'Split not possible'
end
return Machining, Result
end
-------------------------------------------------------------------------------------------------------------
function SPLITCUT.GetEdgeToMachine( Proc, vtEdge)
local Edge
for i = 1, #Proc.Faces[1].Edges do
if AreSameVectorApprox( Proc.Faces[1].Edges[i].vtN, vtEdge) then
Edge = Proc.Faces[1].Edges[i]
end
end
return Edge
end
-------------------------------------------------------------------------------------------------------------
function SPLITCUT.CalculateLeadInOut( EdgeToMachine)
local LeadIn = {}
local LeadOut = {}
LeadIn.dStartAddLength = 0
LeadOut.dEndAddLength = 0
LeadIn.nType = MCH_MILL_LI.LINEAR
LeadOut.nType = MCH_MILL_LI.LINEAR
LeadIn.dTangentDistance = 0
LeadOut.dTangentDistance = 0
LeadIn.dPerpDistance = BeamData.CUT_SIC + EdgeToMachine.dElevation
LeadOut.dPerpDistance = BeamData.CUT_SIC + EdgeToMachine.dElevation
LeadIn.dElevation = 0
LeadOut.dElevation = 0
LeadIn.dCompLength = 0
LeadOut.dCompLength = 0
LeadIn.dStartAddLength = BeamData.CUT_EXTRA
LeadOut.dEndAddLength = BeamData.CUT_EXTRA
return LeadIn, LeadOut
end
-----------------------------------------------------------------------------------
function SPLITCUT.Execute( Proc, Part, Strategy)
local Machinings = {}
-- applico le lavorazioni
--------------------------------------------------------------------------------
if Strategy.SplitStrategy.sTypeMachining == 'BladeSideSingle' then
local Machining = {}
Machining.Splitting = {}
Machining.AuxiliaryData = {}
local OptionalParameters = {}
OptionalParameters.nToolIndex = Strategy.SplitStrategy[1].ToolInfo.nToolIndex
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_BACK
OptionalParameters.sDepth = 0
OptionalParameters.dLongitudinalOffset = Strategy.dOffset or 0
OptionalParameters.sUserNotes = EgtIf( Strategy.bSplit, 'Split;', 'Cut;')
Machining.AuxiliaryData.bIsSplitOrCut = true
local EdgeToMachine = SPLITCUT.GetEdgeToMachine( Proc, -Y_AX())
-- approccio e retrazione
OptionalParameters.LeadIn, OptionalParameters.LeadOut = SPLITCUT.CalculateLeadInOut( EdgeToMachine)
Machining.Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1], EdgeToMachine, OptionalParameters)
table.insert( Machinings, Machining)
----------------------------------------------------------------------------------
elseif Strategy.SplitStrategy.sTypeMachining == 'BladeSideDouble' then
local Machining = {}
Machining.Splitting = {}
Machining.AuxiliaryData = {}
local OptionalParameters = {}
OptionalParameters.nToolIndex = Strategy.SplitStrategy[1].ToolInfo.nToolIndex
-- Taglio lato frontale
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_BACK
OptionalParameters.sDepth = 0
OptionalParameters.dLongitudinalOffset = Strategy.dOffset or 0
OptionalParameters.dRadialOffset = ( Part.dWidth - BeamData.CUT_EXTRA) / 2
OptionalParameters.sUserNotes = EgtIf( Strategy.bSplit, 'Presplit;', 'Precut;')
local EdgeToMachine = SPLITCUT.GetEdgeToMachine( Proc, -Y_AX())
-- approccio e retrazione
OptionalParameters.LeadIn, OptionalParameters.LeadOut = SPLITCUT.CalculateLeadInOut( EdgeToMachine)
Machining.Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1], EdgeToMachine, OptionalParameters)
table.insert( Machinings, Machining)
-- Taglio lato dietro
Machining = {}
Machining.Splitting = {}
Machining.AuxiliaryData = {}
OptionalParameters = {}
OptionalParameters.nToolIndex = Strategy.SplitStrategy[1].ToolInfo.nToolIndex
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_FRONT
OptionalParameters.sDepth = 0
OptionalParameters.dLongitudinalOffset = Strategy.dOffset or 0
OptionalParameters.dRadialOffset = ( Part.dWidth - BeamData.CUT_EXTRA) / 2
OptionalParameters.sUserNotes = EgtIf( Strategy.bSplit, 'Split;', 'Cut;')
Machining.AuxiliaryData.bIsSplitOrCut = true
EdgeToMachine = SPLITCUT.GetEdgeToMachine( Proc, Y_AX())
-- approccio e retrazione
OptionalParameters.LeadIn, OptionalParameters.LeadOut = SPLITCUT.CalculateLeadInOut( EdgeToMachine)
Machining.Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1], EdgeToMachine, OptionalParameters)
table.insert( Machinings, Machining)
----------------------------------------------------------------------------------
elseif Strategy.SplitStrategy.sTypeMachining == 'BladeHorizontalSingle' then
local Machining = {}
Machining.Splitting = {}
Machining.AuxiliaryData = {}
local OptionalParameters = {}
OptionalParameters.nToolIndex = Strategy.SplitStrategy[1].ToolInfo.nToolIndex
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_DOWN
OptionalParameters.sDepth = 0
OptionalParameters.dLongitudinalOffset = Strategy.dOffset or 0
OptionalParameters.dRadialOffset = -BeamData.CUT_EXTRA
OptionalParameters.sUserNotes = EgtIf( Strategy.bSplit, 'Split;', 'Cut;')
Machining.AuxiliaryData.bIsSplitOrCut = true
local EdgeToMachine = SPLITCUT.GetEdgeToMachine( Proc, Z_AX())
-- approccio e retrazione
OptionalParameters.LeadIn, OptionalParameters.LeadOut = SPLITCUT.CalculateLeadInOut( EdgeToMachine)
Machining.Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1], EdgeToMachine, OptionalParameters)
table.insert( Machinings, Machining)
----------------------------------------------------------------------------------
elseif Strategy.SplitStrategy.sTypeMachining == 'BladeHorizontalDouble' then
local Machining = {}
Machining.Splitting = {}
Machining.AuxiliaryData = {}
local OptionalParameters = {}
OptionalParameters.nToolIndex = Strategy.SplitStrategy[1].ToolInfo.nToolIndex
-- Taglio lato frontale
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_DOWN
OptionalParameters.sDepth = 0
OptionalParameters.dLongitudinalOffset = Strategy.dOffset or 0
local dExtraMaxMat = ( Strategy.SplitStrategy[1].ToolInfo.dMaxMatBladeFromTop + Strategy.SplitStrategy[2].ToolInfo.dMaxMatBladeFromDown - Part.dHeight - BeamData.CUT_EXTRA) / 2
OptionalParameters.dRadialOffset = Part.dHeight - Strategy.SplitStrategy[1].ToolInfo.dMaxMatBladeFromTop + dExtraMaxMat
OptionalParameters.sUserNotes = EgtIf( Strategy.bSplit, 'Presplit;', 'Precut;')
local EdgeToMachine = SPLITCUT.GetEdgeToMachine( Proc, Z_AX())
-- approccio e retrazione
OptionalParameters.LeadIn, OptionalParameters.LeadOut = SPLITCUT.CalculateLeadInOut( EdgeToMachine)
Machining.Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1], EdgeToMachine, OptionalParameters)
table.insert( Machinings, Machining)
-- Taglio lato dietro
Machining = {}
Machining.Splitting = {}
Machining.AuxiliaryData = {}
OptionalParameters = {}
OptionalParameters.nToolIndex = Strategy.SplitStrategy[2].ToolInfo.nToolIndex
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_TOP
OptionalParameters.sDepth = 0
OptionalParameters.dLongitudinalOffset = Strategy.dOffset or 0
OptionalParameters.dRadialOffset = Part.dHeight - Strategy.SplitStrategy[2].ToolInfo.dMaxMatBladeFromDown + dExtraMaxMat
OptionalParameters.sUserNotes = EgtIf( Strategy.bSplit, 'Split;', 'Cut;')
Machining.AuxiliaryData.bIsSplitOrCut = true
EdgeToMachine = SPLITCUT.GetEdgeToMachine( Proc, -Z_AX())
-- approccio e retrazione
OptionalParameters.LeadIn, OptionalParameters.LeadOut = SPLITCUT.CalculateLeadInOut( EdgeToMachine)
Machining.Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1], EdgeToMachine, OptionalParameters)
table.insert( Machinings, Machining)
----------------------------------------------------------------------------------
elseif Strategy.SplitStrategy.sTypeMachining == 'ChainSawHorizontal' then
; -- TODO
----------------------------------------------------------------------------------
elseif Strategy.SplitStrategy.sTypeMachining == 'ChainSawSideSingle' then
; -- TODO
----------------------------------------------------------------------------------
elseif Strategy.SplitStrategy.sTypeMachining == 'ChainSawSideDouble' then
; -- TODO
----------------------------------------------------------------------------------
elseif Strategy.SplitStrategy.sTypeMachining == 'ChainSawPlusBlade' then
; -- TODO
----------------------------------------------------------------------------------
end
return Machinings
end
-------------------------------------------------------------------------------------------------------------
return SPLITCUT