270 Commits

Author SHA1 Message Date
luca.mazzoleni b8299df247 - in BeamExec.ProcessAlternatives si passano correttamente le info a interfaccia da scrivere sul pezzo
- in BeamLib aggiunta funzione ConvertBitIndexToRotationIndex per convertire da BitIndex a RotationIndex
2026-05-13 18:42:01 +02:00
luca.mazzoleni 4a99f2bdf6 - in BeamExec.GetProcessings per HeadcutInfo e TailcutInfo si usano gli indici di rotazione canonici (1,2,3,4 per std e 5,6,7,8 per invertiti) 2026-05-13 16:28:04 +02:00
luca.mazzoleni 1e86180723 - in BeamExec si scrivono HeadcutInfo e TailcutInfo nel PARTS che serviranno per nesting; da completare output alternative 2026-05-13 16:00:20 +02:00
luca.mazzoleni f6d6043c0e - piccole modifiche per test nesting 2026-05-13 12:40:45 +02:00
luca.mazzoleni b048e2ebe2 - in BeamLib.GetSortedVertices piccola correzione 2026-05-13 11:58:28 +02:00
luca.mazzoleni fc47bca0f1 - in NestProcess prime modifiche per nesting obliquo (da completare)
- in BeamExec test BEAM.INFONGEPART per scrittura note pezzo in nge tramite Aedifica
- in BeamLib aggiunta funzione RotateTableFromIndex per reindicizzare una tabella passata
2026-05-13 11:47:25 +02:00
luca.mazzoleni 0274096f57 - in BeamExec.GetFeatureInfoAndDependency si salvano le info necessarie per nesting (offset X dei vertici dei tagli rispetto al box, normali delle facce) 2026-05-12 11:59:26 +02:00
luca.mazzoleni 983609397e - in BeamLib funzione GetSurfTmSortedVertices diventa GetSortedVertices e si passa la Proc direttamente
- in BeamLib aggiunta funzione GetAdjacentIndices per la ricerca degli indici precedente e successivo con circular indexing
2026-05-12 10:45:26 +02:00
luca.mazzoleni 05a8d23f6a - in BeamExec.GetFeatureInfoAndDependency si calcolano i punti ai vertici dei tagli di testa e coda
- in BeamLib aggiunta funzione GetSurfTmSortedVertices per restituire i punti ai vertici già ordinati; da correggere perchè i vertici non arrivano ordinati dalla funzione EgtSurfTmGetAllVertInFacet
2026-05-12 09:06:43 +02:00
luca.mazzoleni 40580cdc69 - NestProcess attuale rinominata Old per test nesting obliqui, con NestProcess ripulita 2026-05-11 12:42:34 +02:00
luca.mazzoleni f6b2477f2b - in BeamExec.GetFeatureInfoAndDependency correzione 2026-05-08 12:29:46 +02:00
luca.mazzoleni 69db74e30e - in BeamExec.ProcessBeams modifiche per accettare grezzi compenetranti
- in BeamExec.GetFeatureInfoAndDependency si scelgono taglio di testa e coda anche obliqui, quelli più verso il centro della trave. Gli altri tagli si disattivano
- da completare
2026-05-08 12:00:58 +02:00
luca.mazzoleni f58004dfeb - in PreSimulationLIb correzioni importanti in test collisione 2026-05-08 11:54:16 +02:00
luca.mazzoleni 7c485360de Merge branch 'ScarfJoint' into develop 2026-04-27 18:18:19 +02:00
luca.mazzoleni 967117cc23 - in FeatureLib, per ScarfJoint e ScarfSimple, si scrivono sempre AdjacencyMatrix e Faces
- in STR0009 aggiunto antischeggia di lama e, nel caso sia disattivato, lavorazione con lama dell'eventuale faccia inclinata
2026-04-27 18:18:07 +02:00
andrea.villa 64b2e86a2d Abbozzata gestione (non funzionante) passaggio supplementare in caso di angolo > 90° che necessita di passata extra 2026-04-24 16:47:40 +02:00
andrea.villa 89b342a564 Prima versione Scarf Joint. Manca:
- lavorazioni di antischeggia con fresa e lama
 - Il primo taglio de ve essere calcolato con 2 facce se il piano di taglio attraversa faccia 1
 - gestione caso con facce 4 e 5 mancanti
2026-04-24 14:45:31 +02:00
andrea.villa 117e475de5 STR0009 riutilizzata per ScarfJoint. Primo commit, da sviluppare completamente. 2026-04-24 08:52:56 +02:00
andrea.villa a7b817b211 STR0014 corretta lavorazione cloni 2026-04-24 08:41:25 +02:00
andrea.villa d8c6a8ad55 In STR0008 si aggiunge svuotatura con paraemtri di default 2026-04-23 10:35:03 +02:00
andrea.villa 9026acd9ca In STR0007 la faccia di taglio deve essere messa sul gruppo aggiuntivo. Prima era su quello temporaneo che però viene poi cancellato 2026-04-21 10:03:05 +02:00
andrea.villa 204346326f In STR0003 controllo delle MainFaces spostato a prima del controllo topologia 2026-04-21 08:13:41 +02:00
luca.mazzoleni 5d6e4c397d - in MachiningLib.FindMill si evita di lavorare troppo sotto con la fresa, a meno che sia in testa o coda; temporaneo in attesa di test collisione anche per fresa e attacco corretto dal lato 2026-04-20 18:09:22 +02:00
luca.mazzoleni 64bde8924d - in STR0002 si evita di lavorare la faccia tunnel se troppo piccola 2026-04-20 16:27:59 +02:00
luca.mazzoleni cb6115d23f - in STR0010 (fresatura) migliorata qualità se no lati chiusi 2026-04-20 15:25:19 +02:00
luca.mazzoleni 771c1367b1 - in PreSimulationLib, se taglio perpendicolare a cubetti, non si verifica l'elevazione reale del taglio 2026-04-20 10:47:41 +02:00
luca.mazzoleni 6092063daa - in BLADETOWASTE piccola correzione 2026-04-20 09:21:52 +02:00
luca.mazzoleni 44650c303c Merge branch 'test' into develop 2026-04-17 18:31:27 +02:00
luca.mazzoleni 69fa0d741d - piccole correzioni ai cubetti nel caso di due facce molto aperte 2026-04-17 18:31:22 +02:00
luca.mazzoleni 8e55ddda1f - in PreSimulationLib aggiunto check collisione anche per punti di attacco perpendicolare 2026-04-17 17:25:06 +02:00
andrea.villa 7a8fb04ebe In STR0013 (foro con fresa) si controlla che abbia trovato fresa prima di verificare se foro completo. Se non trovava fresa andava in crash 2026-04-17 12:36:26 +02:00
luca.mazzoleni 77c27d911c Merge branch 'PreSimulationV2' into develop 2026-04-16 17:02:43 +02:00
luca.mazzoleni 3a29f273c9 - in PreSimulationLib alcune correzioni 2026-04-16 17:02:39 +02:00
luca.mazzoleni bab5b07bd1 Merge remote-tracking branch 'origin/develop' into PreSimulationV2 2026-04-15 17:45:20 +02:00
luca.mazzoleni 683ae78c65 - in PreSimulationLib si usano le funzioni MachineCalc per la precollisione 2026-04-15 17:45:15 +02:00
andrea.villa 06d9529b7b Per ruotare il pezzo non lo si toglie più dalla barra, ma lo si gira in "Draw" 2026-04-14 09:05:46 +02:00
andrea.villa 922a7ac846 Correzioni varie in strategie per gestire casi strani dove non vengono calcolate le MainFaces 2026-04-14 07:57:59 +02:00
andrea.villa a21a3979f1 Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2026-04-13 13:02:10 +02:00
andrea.villa fcbed252e1 Merge branch 'PreRotationInterface' into develop 2026-04-13 13:02:06 +02:00
andrea.villa b68bbb2c48 - Report TXT ora gestisce bene le prerotazioni
- Corretta info indice rotazione su Proc
2026-04-13 13:01:56 +02:00
andrea.villa 6fe6b41e87 Migliorie calcolo prerotazioni 2026-04-13 12:28:09 +02:00
andrea.villa 78189631c1 Aggiunto inversione 2026-04-13 09:43:47 +02:00
andrea.villa 1a6433d5f8 Prima versione che sistema il pezzo in interfaccia come è stato preruotato 2026-04-13 08:08:14 +02:00
luca.mazzoleni 28026358b9 - aggiunto GetBeamData per lettura parametri macchina da interfaccia 2026-04-10 11:19:27 +02:00
luca.mazzoleni b73fb86be9 - in BatchProcessNew si sposta cancellazione gruppo temporaneo a dopo la ProcessAlternatives
- in BLADETOWASTE CalculateDiceMachinings commentata inversione facce per normale non raggiungibile (ci pensa già la FaceByBlade)
2026-04-09 15:59:30 +02:00
luca.mazzoleni 1032557782 Merge branch 'FlipRotInBatchProcessNew' into develop 2026-04-08 13:33:17 +02:00
andrea.villa 0ca5f92b96 - tolto paraemtro generale GEN_bTestAlternative, sostituito da GEN_sPiecesLoadingPosition == 'FULL_PRE_ROTATION'. Se utente abilita ricerca delle prerotazioni anche a 90°, significa che accetta anche ottimizzazioni nel nesting ruotando pezzo a 90°, probabilmente fibra non importante
- In BatchProcessNew, quando si crea la barra, il paraemtro FlipRot dipende dal BEAM.FLAG == 10
2026-04-03 16:13:15 +02:00
luca.mazzoleni 0f58c026d0 - in BatchProcessNew gestito Flag 10 per FlipRot 2026-04-03 15:05:15 +02:00
luca.mazzoleni 70d170b2a3 Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2026-04-02 18:13:38 +02:00
luca.mazzoleni 06bc0f77df Merge branch 'AntiSplintOnSTR0002' into develop 2026-04-02 18:13:34 +02:00
luca.mazzoleni a40cc026c9 - in STR0002 implementato AntiSplint
- in ANTISPLINTONFACE piccole modifiche
2026-04-02 18:13:25 +02:00
andrea.villa 34fb38ac00 Piccola correzione sul nome della feature StartCut e EndCut 2026-04-01 16:31:15 +02:00
andrea.villa aaa06c1af5 Corretto indice rotazione da verificare in caso di soluzione invertita. Si aggiunge un offset di 4, l'indice nella tabella delle rotazioni sono 5-6-7-8 2026-04-01 13:17:28 +02:00
luca.mazzoleni 98a48522ee Merge branch 'FlipRot' into develop 2026-04-01 11:41:42 +02:00
andrea.villa 6fd356f757 - Aggiunta tolleranza nella scelta della migliore combinazione di lavorazione. Se voto uguale non era chiaro quale avrebbe scelto prima
- Quando si processano alternative, si resetta flag bPartInCombiIsInverted
2026-04-01 11:06:15 +02:00
andrea.villa 83895cc3bf In STR0002 migliorata gestione topologia 'DoubleBevel-2-Through' 2026-03-31 17:44:49 +02:00
luca.mazzoleni d001273704 - in FlipRot e ProcessAlternatives si scrivono le variabili globali nella tabella Beam per l'interfaccia 2026-03-31 16:11:54 +02:00
luca.mazzoleni 621c9149b5 Merge branch 'ChainsawVerifyOutStroke' into develop 2026-03-26 17:44:22 +01:00
luca.mazzoleni f6f625c7cc - in FACEBYCHAINSAW si escludono casi in cui l'asse bloccato non è calcolato 2026-03-26 17:43:09 +01:00
luca.mazzoleni 9d8985093d - in PreSimulationLib.CheckOutStrokePoint modifiche per contemplare terzo asse rotativo 2026-03-26 17:25:56 +01:00
luca.mazzoleni fe8275f05a - in PreSimulationLib.CheckOutOfStrokeFromPoints e altri si contemplano vettore ausiliario e asse bloccato per verificare finecorsa sega a catena
- in STR0004 se non applicabile si cambia lato, se possibile
- in FACEBYCHAINSAW si verifica finecorsa
2026-03-24 14:36:52 +01:00
andrea.villa d32403f546 Il parametro GEN_nMaxReProcessCycles viene letto ora dal pezzo e non dalla lista dei parametri generali (la quale potrebbe avere quelli -sbagliati- di default). 2026-03-18 10:27:29 +01:00
luca.mazzoleni 63d4ca7176 - in PreSimulationLib correzione al calcolo vtC, vettore asse C 2026-03-17 17:07:42 +01:00
luca.mazzoleni 0889ae5c7a - in STR0002 corretti casi in cui non ci sono le LongFaces
- in STR0003 e STR0004 se non ci sono MainFaces e MainEdges necessari si esce
2026-03-17 16:37:00 +01:00
andrea.villa 0fc9e1dd09 - Se la lavorazione non ha percorso, la si disattiva
- Se rotazione impostata su "IF_NECESSARY", prima del numero rotazioni, si controllano il numero di feature non eseguite
2026-03-13 13:26:20 +01:00
luca.mazzoleni 63308c0349 - correzione in BLADEKEEPWASTE 2026-03-12 17:24:25 +01:00
luca.mazzoleni 7e5ab8ecd3 Merge branch 'BLADEKEEPWASTEImprovement' into develop 2026-03-12 17:08:19 +01:00
luca.mazzoleni bddaf91fb7 - in STR0003 si evita caso con Groove-3 passante e pareti oblique
- in STR0010 migliorie
- in BLADEKEEPWASTE aggiunta pulizia lati chiusi con sistema nuovo
2026-03-12 17:08:07 +01:00
luca.mazzoleni 2c77277c85 - alle StrategyLibs aggiunta ANTISPLINTONFACE per calcolare le lavorazioni antischeggia passando una faccia; STR0010 e BLADEKEEPWASTE modificate di conseguenza
- in BLADEKEEPWASTE migliorie e correzioni; manca ancora la pulitura con fresa
- in FACEBYBLADE rimossa dimensione minima lato maggiore del diametro lama. Si può avere un accorciamento massimo pari alla lunghezza lato
2026-03-06 18:23:24 +01:00
luca.mazzoleni 38a6ac237e Merge branch 'develop' into BLADEKEEPWASTEImprovement 2026-03-06 12:43:28 +01:00
luca.mazzoleni ed4d97ba51 Merge branch 'STR0010Improvement' into develop 2026-03-06 12:43:13 +01:00
luca.mazzoleni 7b12eaf331 - in BatchProcessNew -> GET_TOPOLOGY si legge anche nParts (serve nel Classify Topology)
- in STR0005 si ammettono feature a più di 3 lati se la topologia è DoubleBevel
- in BLADEKEEPWASTE si gestisce topologia DoubleBevel e migliorie varie
2026-03-06 12:42:53 +01:00
luca.mazzoleni 3e55af917e - in BLADETOWASTE gestito caso in cui arrivano due facce separate 2026-03-04 18:02:43 +01:00
luca.mazzoleni 73b6d80510 - in FeatureLib->ClassifyTopology correzione al riconoscimento DoubleBevel su più parti
- in FaceData correzioni per i casi DoubleBevel su più parti
- in BeamExec->CollectFeatures si scrive il numero di parti di cui è composta la trimesh
2026-03-04 16:13:31 +01:00
luca.mazzoleni 65c2c244d6 in STR0010 aggiunto antischeggia facce di chiusura 2026-03-04 12:19:29 +01:00
luca.mazzoleni 2ae547a24e - in FeatureLib correzioni a classificazione topologia DoubleBevel
- in STR0010 aggiunte passate di finitura con fresa e piccole correzioni
2026-03-04 09:26:47 +01:00
luca.mazzoleni aff61f1daa Merge remote-tracking branch 'origin/develop' into STR0010Improvement 2026-03-03 09:45:20 +01:00
luca.mazzoleni 0db6a74f8c - in FaceData e FeatureLib modifiche per gestire DoubleBevel
- in STR0010 modifiche per gestire casi non contemplati
2026-03-03 09:45:11 +01:00
andrea.villa f68533944c Merge branch 'NewRotationMng' into develop 2026-03-02 13:26:56 +01:00
andrea.villa 37e08e3f42 - Aggiunto tempo di calcolo delle alternative
- Di default la ricerca delle alternative è disattiva
- Piccole migliorie varie
2026-03-02 13:23:28 +01:00
andrea.villa c6ced91b14 - Aggiunti parametri configurabili GEN_bTestAlternative e GEN_bGetAlternativesNesting2D per testare altre alternative valide
- Aggiunta funzione dedicata alla creazione del gruppo ausiliario al MachGroup
- Alla funzione BeamExec.GetCombinationListFromMatrix si può passare una lista con le sole combinazioni da provare
- Nella BeamExec aggiunta funzione ProcessAlternatives solo per provare le alternative (simile alla ProcessFeatures, ma completamente slegata). La ProcessFeature decide il posizionamento iniziale, la ProcessAlternatives verifica solamente le alternative.
- FlipRot adeguata a nuovo funzionamento
- Altre piccole migliorie varie
- TODO :
   1) manca la parte per settare nelle info pezzo la rotazione iniziale (per vista in Aedifica) e le altre alternative (per ottimizzazione in nesting)
   2) In FlipRot gestire interazione con Aedifica, dato che verrà lanciato direttamente dal programma (per ora funziona lanciato come la Process)
2026-03-02 12:35:12 +01:00
luca.mazzoleni 8efb64810a - in FaceData si raccolgono informazioni sulle facce fino a 6 lati compresi 2026-02-26 17:56:12 +01:00
andrea.villa 02390c2e9b - Tolte pre-rotazioni dalla Process
- FlipRot modificata, ora ereditata dalla Process
2026-02-24 16:50:48 +01:00
andrea.villa 7f7d75c113 - BatchProcess non calcola più le prerotazioni
- Modifiche varie per nuova gestione pre-rotazioni
- Nuovo script FlipRot (per ora copiata da BatchProcess, poi dovrà ruotare i pezzi e posizionarli in base alla migliore posizione di lavoro)
2026-02-23 16:24:43 +01:00
andrea.villa ecd50c0fea Piccola correzione gestione ricalcolo lavorazioni dopo applicazione 2026-02-10 13:33:05 +01:00
andrea.villa 6f195e7fac Merge branch 'ReprocessOnApplyError' into develop 2026-02-10 09:45:49 +01:00
andrea.villa 626183f310 Se feature respinta per extracorsa, viene salvata nota nel LOG 2026-02-10 09:45:27 +01:00
andrea.villa fe6c0bb31c - GetBestStrategy suddivisa in : GetBestStrategyFromProcList e GetFeatureBestStrategy
- Se si deve riprocessare, si riporta il pezzo in posizione originale
- in GetCombinationListFromMatrix si ricalcola la migliore strategia in caso ChosenStrategy non presente (solo se ReProcess)
- Piccole migliorie
2026-02-10 09:02:31 +01:00
andrea.villa 1c24f1046d - Prima versione per riprocessare il calcolo lavorazioni in caso l'applicazione di una (o più lavorazioni) abbia dato errore.
- Per ora cancella la ChosenStrategy, come se non avesse trovato alcuna strategia di sponibile
2026-02-09 15:20:21 +01:00
andrea.villa 70cfdd056f Piccola correzione in STR0008 in caso non trovi neanche un utensile per lavorare la mortasa 2026-02-09 09:20:48 +01:00
andrea.villa 9ebb9c77db Merge remote-tracking branch 'origin/STR0011_Improve' into develop 2026-02-09 08:15:44 +01:00
andrea.villa a54fbb1259 - In STR0011 raggruppato scrittura paraemtri comuni in un solo punto
- In STR0011 sostituito calcolo MRR con TimeToMachine
- In MachiningLib, gestione calcolo tempo reale per lavorazioni di foratura
2026-02-09 08:14:02 +01:00
andrea.villa 1345c5a5cb - Rimossa gestione speciale per foro esattamente orizzontale
- Controllo extra-corse. Per ora SCC ignorato
- Per ricerca punta, si considera sempre 1centesimo di tolleranza (oltre alla tolleranza configurabile)
2026-02-06 15:12:12 +01:00
luca.mazzoleni 9add357cb6 -in FACEBYBLADE commentato OutRaw = 3 2026-02-04 22:34:37 +01:00
luca.mazzoleni b1ae9db859 - in MachiningLib aggiunto controllo collisione anche per attacco tangenziale 2026-02-04 22:27:55 +01:00
luca.mazzoleni 57d555fb0b - in STR0004 (catena) eliminato limite tasche verso il basso: andrà aggiunto il test finecorsa con cambio lato 2026-02-02 16:56:47 +01:00
luca.mazzoleni 28a6049c77 - correzioni e migliorie in STR0015 2026-02-02 16:41:14 +01:00
luca.mazzoleni c8848974a4 Merge branch 'AlternativeDiceSize' into develop 2026-02-02 13:27:46 +01:00
luca.mazzoleni 6591396009 - in TAILCUT e HEADCUT corretto box cubetti 2026-02-02 13:26:24 +01:00
luca.mazzoleni b0531f8df8 - in STR0012 la faccia aggiuntiva viene sempre estesa fino al grezzo 2026-02-02 09:50:52 +01:00
luca.mazzoleni 67a595e311 - sistemati box aggiunti in testa e coda per preSimulation e calcolo attacchi
- in FACEBYBLADE corretti attacchi a ghigliottina (verificare)
2026-01-30 18:58:15 +01:00
luca.mazzoleni 7a84f2c396 - in PreSimulationLib.GetRestlengthSurfTm se non è l'ultimo pezzo si aggiunge tutta la barra restante in coda 2026-01-30 10:20:20 +01:00
luca.mazzoleni 19f62cdc90 - correzioni varie per cubetti, in particolare sui tagli di testa e coda 2026-01-29 15:46:10 +01:00
luca.mazzoleni 0f20358607 - commenti 2026-01-29 12:10:53 +01:00
luca.mazzoleni 8875fc4c68 - in PartSimulationLib si usa solo il box del sovramateriale di coda/testa per il checlk collisione con rest length; il controllo con rest si fa solo se il pezzo è splittabile; in caso di pezzo non splittabile, il sovramateriale di testa/coda è aggiunto alla superficie del pezzo nel test di collisione principale
- in SPLITCUT, HEADCUT. TAILCUT se taglio non riuscito si prova con il riduci percorso
2026-01-29 11:11:27 +01:00
luca.mazzoleni ee4d443074 - in BeamLib creata funzione GetPartBoxWithHeadTailOvermaterial per recuperare il box della parte con aggiunto il sovramateriale di testa e/o coda; implementata in vari punti
- in LeadInOutLib e PreSimulationLib se necessario si estende il box per contemplare materiale in testa e in coda
2026-01-28 15:59:35 +01:00
luca.mazzoleni 995917672c - in BLADETOWASTE si ereditano i parametri sRestLengthSideForPreSimulation e bCannotSplitRestLength per gestire la PreSimulation sui tagli di testa e coda 2026-01-27 15:39:11 +01:00
andrea.villa d5b9612406 - STR0015 estesa anche a FreeContour. DA VERIFICARE: ora è controllato solo il caso simile a una feature di intestatura
- GetMachiningSteps migliorata, ora contempla il caso lavorazione di fresatura standard o di tipo slot
2026-01-27 12:21:29 +01:00
luca.mazzoleni 4521910c56 - in PreSimulationLib si gestiscono i due nuovi parametri sRestLengthSideForPreSimulation e bCannotSplitRestLength per tagli di testa e coda 2026-01-27 12:15:30 +01:00
luca.mazzoleni 267fc9daa3 - in PreSimulationLib modificata ottimizzazione punti di controllo 2026-01-26 15:42:42 +01:00
luca.mazzoleni c997cb4440 - in BLADETOWASTE se i cubetti falliscono si riprovano con la SAFE_DIM_DICE, se disponibile
- in PreSimulationLib per i test collisione con il grezzo si usa la vera dimensione della barra restante
2026-01-26 13:29:18 +01:00
luca.mazzoleni b98b03adba Merge branch 'develop' into AlternativeDiceSize 2026-01-26 10:52:47 +01:00
luca.mazzoleni f2f57be09f Merge branch 'AlternativeDiceSize' into develop 2026-01-26 10:52:33 +01:00
luca.mazzoleni efe7f2e0f9 - in cubetti rimossa dimensione diversa in base a direzione lama (si userà la dimensione ridotta se quella standard fallisce)
- in MAchiningLib.ShortestPathSorting si leggono le feed medie dalla macchina
- MAX_DIM_DICE sostituita da parametro generale GEN_MAX_DIM_DICE
- in STR0005 rimossi tutti i riferimenti a dMinZTopBlade e dMaxNyTopBlade; andrà corretta BLADETOWASTE in caso di lama sopra e sotto
2026-01-26 10:52:19 +01:00
luca.mazzoleni 8f04694232 Merge branch 'develop' into AlternativeDiceSize 2026-01-23 16:46:40 +01:00
luca.mazzoleni c14377fb67 - in MachiningLib corretto ordinamento nel caso di lavorazioni disattivate 2026-01-23 16:46:05 +01:00
luca.mazzoleni c491d635e7 Merge branch 'develop' into AlternativeDiceSize 2026-01-23 12:16:10 +01:00
luca.mazzoleni 18fe9ceccb Merge branch 'AlternativeDiceSize' into develop 2026-01-23 12:16:03 +01:00
luca.mazzoleni 86c36512a0 - in BLADETOWASTE piccola miglioria 2026-01-23 12:15:39 +01:00
luca.mazzoleni 4bdb1b32b1 - in BALDETOWASTE correzione 2026-01-22 18:53:45 +01:00
luca.mazzoleni 0a073ead4c - in BeamExec corretto indice salvato nell'utensile Tool.nIndex 2026-01-22 18:15:03 +01:00
luca.mazzoleni 76c8f45284 - in BLADETOWASTE.CutWithDicing refactor 2026-01-22 18:07:18 +01:00
luca.mazzoleni 5c463298da - in BLADETOWASTE correzione: se fallisce un cubetto, il dicing non è applicabile 2026-01-22 15:03:02 +01:00
luca.mazzoleni 7b16ace7a4 - in STR0002 se faccia singola e feature lavorata in unica lavorazione si può sempre affondare
- HeadCut saltato se corrisponde al taglio di separazione precedente
2026-01-22 10:08:18 +01:00
luca.mazzoleni 66159b25a8 - piccola correzione 2026-01-19 18:39:29 +01:00
luca.mazzoleni 518ad5e10a - in PreSimulationLib ora prima di testare per collisioni si verifica il massimo materiale con l'elevazione reale del lato (rispetto al pezzo). Risolve collisioni non intercettate con flangia 2026-01-19 18:38:32 +01:00
luca.mazzoleni fc7432a97a - in FACEBYBLADE migliorie ai tagli
- in STR0012 implementata funzione generale per verifica problemi pinzaggio
2026-01-19 09:15:40 +01:00
luca.mazzoleni 583aa789c4 Merge branch 'DEMO_SAOMAD_202601' into develop 2026-01-15 04:01:14 +01:00
luca.mazzoleni 92036b09b4 - in FACEBYBLADE, se cubetti, i tagli vanno sempre verso l'alto 2026-01-15 04:00:46 +01:00
luca.mazzoleni 6d2a1664ce - in BLADEKEEPWASTE migliorie 2026-01-15 03:17:01 +01:00
luca.mazzoleni 5934b07947 Merge branch 'develop' into DEMO_SAOMAD_202601 2026-01-15 00:34:23 +01:00
luca.mazzoleni 85147dc34a Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2026-01-15 00:34:17 +01:00
luca.mazzoleni 465ffc7e37 - in FaceData.GetEdgesInfo si scrivono anche gli angoli con la faccia adiacente
- in FACEBYBLADE correzioni
- in BLADEKEEPWASTE si lavorano anche i rabbet lungo X o v groove, da completare
2026-01-15 00:33:48 +01:00
luca.mazzoleni 31f1f50d04 - in FACEBYBLADE OutRaw=3 commentato, da usare solo per debug 2026-01-14 12:59:12 +01:00
andrea.villa 7867317982 Piccola modifica ai fori. Seaperti in coda, devono essere fatti dopo la separazione. Gestione da migliorare! 2026-01-14 12:40:08 +01:00
luca.mazzoleni ab9ea95b45 - in FACEBYBLADE correzione importante nella verifica finecorsa 2026-01-14 10:18:56 +01:00
luca.mazzoleni c52a3f4af6 Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2026-01-13 17:20:47 +01:00
luca.mazzoleni 598d717dbc - in FACEBYMILL implementato controllo finecorsa 2026-01-13 17:20:44 +01:00
Emmanuele Sassi ab606d759e Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2026-01-13 16:36:30 +01:00
Emmanuele Sassi a6d9a36dab - gestito BEAM.MACHINE con lista
- recupero indice di nesting barra precedente
2026-01-13 16:36:26 +01:00
luca.mazzoleni 8c573d25b2 Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2026-01-13 13:35:04 +01:00
luca.mazzoleni 5554977011 ripristinata STR0010 vecchia 2026-01-13 13:35:00 +01:00
andrea.villa d3a9284944 Piccoal correzione. C'era già il parametro 'idFeature' sulla Proc che indica l'indice della feature nella lista del BeamWall 2026-01-13 13:15:34 +01:00
andrea.villa 90f06cb7ec Gestione feature non lavorata perché slave di un'altra. Per ora gestito il caso speciale dei tagli in testa e coda 2026-01-13 13:04:03 +01:00
luca.mazzoleni 8897f3f00b Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2026-01-13 09:24:15 +01:00
luca.mazzoleni 1e4e75115c - in STR0010 corretta scelta lato nel caso 2 facce 2026-01-13 09:24:13 +01:00
andrea.villa d3bf465923 STR0002 e STR0010 non vengono eseguite se ostacolano il pinzaggio 2026-01-13 09:11:38 +01:00
luca.mazzoleni 9f6a89d5ae - in STR0006 e STR0007 gestito allungamento percorso LeadIn/Out per test finecorsa 2026-01-12 18:56:16 +01:00
Emmanuele Sassi 6f730dcaec - aggiunto NestProcessNew che crea i MachGroup del nesting su tutte le macchine elencate 2026-01-12 17:36:19 +01:00
luca.mazzoleni f1cdaa498d Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2026-01-12 17:30:09 +01:00
luca.mazzoleni 217a359ba0 - in BatchProcessNew nei risultati part riportati errori EgtApplyAllMachining (Clamp impossible) 2026-01-12 17:30:06 +01:00
andrea.villa da23b96a9c Funzione per verificare se la lavorazione ostacola il pinzaggio spostata nella MachiningLib 2026-01-12 16:48:10 +01:00
luca.mazzoleni fe358e3ca4 Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2026-01-09 18:30:24 +01:00
luca.mazzoleni 6a7f32b5c1 - in RidgeLap migliorie e aggiunta topologia DoubleBevel-2-Though
- in BLADETOWASTE se taglio doppio fallisce su feature piccola si passa ai cubetti
2026-01-09 18:30:21 +01:00
andrea.villa 9b9758fd2c - Aggiunto calcolo versore direzione inizio e fine percorso in DTMortise
- Alla funzione PreSimulationLib.CheckOutOfStrokeFromGeometry ora si passa la vtHead direttamente
- STR0001 e STR0006 modificate per compatibilità alla CheckOutOfStrokeFromGeometry
- STR0007 ristrutturata per contemplare gli extra-corsa. Per ora solo profilo e antischeggia. Extra-corsa su svuotature non ancora gestito.
2026-01-09 17:28:28 +01:00
luca.mazzoleni 667da4e3d1 - in LeadInOutLib corretto accorciamento per lati chiusi confinanti con lati inclinati 2026-01-09 16:22:10 +01:00
luca.mazzoleni fe309e338b - in FaceData migliorata la scelta della BottomFace 1 2026-01-08 16:49:22 +01:00
luca.mazzoleni 340a249948 - in BeamExec il volume della feature viene calcolato nel Collect direttamente: modificate le altre chiamate
- in STR0012 (RidgeLap) piccola correzione
2026-01-08 11:53:06 +01:00
luca.mazzoleni 0f5a1215f9 Merge branch 'CheckOutstrokeMilling' into develop 2026-01-07 18:40:45 +01:00
luca.mazzoleni 5d461bbc39 Merge remote-tracking branch 'origin/develop' into CheckOutstrokeMilling 2026-01-07 18:18:20 +01:00
luca.mazzoleni 4986d3bf67 - PreSimulationLib.CheckOutOfStroke rinominata CheckOutOfStrokeFromPoints
- check finecorsa aggiunto a STR0006 (tenone)
2026-01-07 18:17:41 +01:00
luca.mazzoleni d5243cda37 - in PreSimulationLib aggiunta funzione CheckOutOfStrokeFromGeometry, refactoring da STR0001 2026-01-07 18:05:13 +01:00
andrea.villa e1e46445b0 In ShortestPathSorting, si controlla che la lavorazione sia attiva 2026-01-07 12:39:31 +01:00
andrea.villa 570e41a40d - In ShortestPathSorting si settano ora inizio e fine di ogni gruppo per ordine lavorazioni
- In STR0010 in caso che la strategia sia stata forzata da utente, non viene bocciata a causa della sua posizione/forma. Se forzata il cliente si è preso al responsabilità della sua scelta ed è giusto che venga provata. Al massimo si avranno errori di extra-corsa o colisioni.
2025-12-23 16:42:04 +01:00
luca.mazzoleni f3938ee0b6 - in STR0001 prima versione, da verificare, controllo finecorsa per fresature 2025-12-23 14:26:01 +01:00
luca.mazzoleni 309bae0265 in PreSimulationLib.CheckOutOfStroke tabella Parameters sostituita dai parametri singoli 2025-12-23 12:42:49 +01:00
luca.mazzoleni c068479ec1 - in PreSimulationLib refactoring di CheckOutOfStroke e aggiunta la funzione GetPointOnToolTipCenter per calcolare il punto corretto da passare, a partire dal punto di lavorazione; adeguata MachiningLib 2025-12-23 11:27:56 +01:00
luca.mazzoleni 608a9c63c8 - in PreCollisionLib refactoring 2025-12-22 18:27:06 +01:00
luca.mazzoleni 38d432fd79 - correzione in RidgeLap a 3 facce 2025-12-22 17:36:11 +01:00
luca.mazzoleni 3b65f6233d - in PreSimulationLib si usa l'uscita utensile 2025-12-22 11:46:15 +01:00
luca.mazzoleni f1805625d3 - per lama implementata verifica finecorsa (PreSimulationLib, MachiningLib) con funzione Machine Calc
- nei timer si logga il tempo di apertura Json
2025-12-22 11:19:03 +01:00
luca.mazzoleni 568de09954 Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2025-12-19 16:27:06 +01:00
luca.mazzoleni 70025d1816 -in MachiningLib e BLADETOWASTE piccole correzioni 2025-12-19 16:27:01 +01:00
andrea.villa fb74d28926 - Lavorazioni in doppio solo se faccia rettangolare
- Corretta lettura e gestione parametri generali
- BLADETOWASTE, in CutWithDicing abilitato il taglio ridotto ( impostato da funzione chimaante)
2025-12-19 10:55:10 +01:00
luca.mazzoleni 73acee6695 - modificati commenti 2025-12-18 17:33:55 +01:00
luca.mazzoleni c3a82a0804 - in MachiningLib.TestEngagement, PreSimulationLib e LeadInOutLib predisposte funzioni per calcolo extracorsa 2025-12-18 17:32:50 +01:00
luca.mazzoleni 6d1cae6ff3 - in FACEBYBLADE rimosso ricalcolo inutile del migliore attacco 2025-12-18 15:04:16 +01:00
luca.mazzoleni 2bcaeca91f - in LeadInOutLib calcolo attacco tangenziale con funzioni Tool Collision Avoidance e refactoring
- in FACEBYBLADE GetLeadInOut si aggiorna se necessario la TotalLength
2025-12-18 14:45:37 +01:00
luca.mazzoleni 3136604e14 in LeadInOutLib migliorata scelta direzione attacco perpendicolare 2025-12-18 12:41:18 +01:00
luca.mazzoleni 82cd8f5d8c - in MachiningLib EgtOptMachGetResult diventa EgtOptMachCalculate 2025-12-18 09:41:38 +01:00
luca.mazzoleni e9493ead6b - in LeadInOutLib si usano le funzioni Tool Collision Avoidance per calcolare i LeadIn / Out per gli attacchi lama 2025-12-17 18:44:18 +01:00
luca.mazzoleni e9417ba322 - in LeadInOutLib LeadIn e Out sono entrambi nella direzione del lato adiacente migliore 2025-12-17 17:15:27 +01:00
luca.mazzoleni 79417998a2 - piccole correzioni ai tagli 2025-12-17 12:29:19 +01:00
luca.mazzoleni c290254bae Merge branch 'CuttingImprovements' into develop 2025-12-16 15:18:15 +01:00
luca.mazzoleni 604a2676ce - correzioni in FaceData e MachiningLib 2025-12-16 15:18:07 +01:00
luca.mazzoleni 827a709af0 - in LeadInOutLib correzione nel calcolo di ptStartAtDepth e ptEndAtDepth 2025-12-16 13:10:45 +01:00
luca.mazzoleni 05f729df45 - in FaceData si calcola vtEdge per ogni lato in modo da non doverlo calcolare ogni volta; sostituito in tutte le funzioni
- in LeadInOutLib.CalculateLeadInOut si calcola l'attacco perpendicolare in modo rigoroso
- in FACEBYBLADE correzioni al calcolo attacco
2025-12-16 13:04:42 +01:00
luca.mazzoleni 646e69e3af Merge remote-tracking branch 'origin/develop' into CuttingImprovements 2025-12-12 18:28:15 +01:00
luca.mazzoleni ef155ad1fb - nei tagli di lama implementata gestione attacchi creati da Engagement 2025-12-12 18:27:58 +01:00
andrea.villa 6609c7ee16 Corretto confronto su nFeatureInternalIndex. Se lalavorazione è un clone hanno lo stesso indice 2025-12-12 14:47:58 +01:00
luca.mazzoleni 5068d75362 Merge branch 'develop' into CuttingImprovements 2025-12-12 12:08:41 +01:00
andrea.villa e646351f3f Ripristinata funzione FinalizeSorting che garantisce che l'ordine delle lavorazioni interne alla feature sia rispettato 2025-12-12 11:53:01 +01:00
andrea.villa 660cca04ca - In ShortestPathSorting tolte le dipendenze tra lavorazioni in rotazioni diverse. Analizzando un DISP palla volta no c'è rischio che si possano mischiare
- Aggiunto TIMER per algoritmo di sorting
2025-12-12 10:44:27 +01:00
luca.mazzoleni 5d15189d59 - correzioni in Process e BatchProcessNew 2025-12-11 19:02:46 +01:00
luca.mazzoleni 50dee06493 Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2025-12-11 17:12:01 +01:00
luca.mazzoleni 3d3ae22f87 - correzione in BeamLib 2025-12-11 17:11:58 +01:00
andrea.villa 21b2e1cd0a Piccole migliorie varie 2025-12-11 15:53:55 +01:00
luca.mazzoleni 7bd18a8fb4 - creata LeadInOutLib per attacchi 2025-12-11 12:04:10 +01:00
luca.mazzoleni 1c4970fdb6 - in Process tolto debug 2025-12-10 19:09:58 +01:00
luca.mazzoleni 77d6d89e13 - in MachiningLib.TestEngagement si testa e restituisce il LeadInOut (funzioni da fare) per i casi perpendicular e tangent 2025-12-10 19:09:06 +01:00
luca.mazzoleni eb3cf0d7ff -modifiche parziali per PreSimulationLib 2025-12-10 11:21:55 +01:00
andrea.villa 5ad9e0bf4f Merge branch 'NewMachiningOrder' into develop 2025-12-09 16:40:28 +01:00
andrea.villa c3ea568d99 - Prima versione funzionante ottimizzazione shortest-path
- creata nuova tabella globale DB_MACH_APPLIED che rispecchia il DB delle lavorazioni e fasi (il MachGroup) aggiunte da automatismo
- ripristinata funzione di ordinamento StableSort, solo per lo stage
- adeguamento funzioni ordinamento per operare su nuova tabella DB_MACH_APPLIED
2025-12-09 16:40:14 +01:00
andrea.villa 30f59b0175 - Se lavorazione in positione standard, si setta bStd
- Prima versione ottimizzazione lavorazioni
!! Non funzionante in caso di cloni !!
2025-12-09 10:42:29 +01:00
luca.mazzoleni c18e80a70d - MachiningLib, PreSimulationLib e FACEBYBLADE modificate per introduzione check finecorsa (da completare) e check attacchi 2025-12-05 18:31:35 +01:00
luca.mazzoleni ae30cb5736 - in MachiningLib ennesimo refactoring 2025-12-05 15:09:18 +01:00
luca.mazzoleni cd586673c7 - MachiningLib.CheckCollision spostata in PreSimulationLib 2025-12-05 12:03:36 +01:00
luca.mazzoleni f426311b28 in MachiningLib.GetBladeEngagement refactoring 2025-12-05 11:42:00 +01:00
luca.mazzoleni e2a2d0fd4e - file libreria PreCollisionLib rinominato PreSimulationLib 2025-12-05 10:02:51 +01:00
luca.mazzoleni 69c31e4c2b - PreCollisionLib rinominata PreSimulationLib 2025-12-05 10:01:33 +01:00
luca.mazzoleni 56ca5a74b9 - in PreCollisionLib e MachiningLib refactoring di CheckCollisionWithAxis 2025-12-04 19:02:02 +01:00
luca.mazzoleni ad1ea741d0 - in MachiningLib.GetBladeEngagement refactoring 2025-12-04 18:39:29 +01:00
luca.mazzoleni 322412a1f3 - in PreCollisionLib.CheckCollisionWithAxis corretto calcolo vtC (non era normalizzato) 2025-12-04 15:07:38 +01:00
luca.mazzoleni c1a563351a - in PreCollisionLib corretto commento 2025-12-04 11:56:55 +01:00
luca.mazzoleni 327a5a960d - require ( 'BeamData') sostituito con require( 'BeamDataNew') in tutti i punti (temporaneo)
- in PreCollisionLib.CheckCollisionWithAxis refactoring
2025-12-04 11:55:40 +01:00
luca.mazzoleni fdfefaba74 Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2025-12-03 13:01:12 +01:00
luca.mazzoleni c76eba6e74 - in BeamLib.CreateTempGroup il gruppo temporaneo viene creato disabilitato di default, in modo che l'utente di livello basso non lo veda se il programma crasha e non lo possa riattivare 2025-12-03 13:01:08 +01:00
andrea.villa c6b3b5a003 In BeamLib, dalla lista strategie si prendono solo quelle che sono attive 2025-12-03 10:46:04 +01:00
luca.mazzoleni a4fbfcf2c9 Merge branch 'CuttingImprovements' into develop 2025-12-02 17:07:06 +01:00
luca.mazzoleni fa1a12b41c - in HEADCUT correzione 2025-12-02 17:06:55 +01:00
luca.mazzoleni d162b27493 Merge branch 'CuttingImprovements' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into CuttingImprovements 2025-12-02 16:44:55 +01:00
luca.mazzoleni 68da716da1 - in MachiningLib e PreCollision correzioni per controllare collisione con grezzo nei cubetti 2025-12-02 16:44:51 +01:00
andrea.villa d6900a2c59 Modifica a lettura parametri generali. Se il parametro non è salvato in NGE si salta subito, altrimenti se fosse stato un boolean veniva messo a false. 2025-12-02 15:59:53 +01:00
luca.mazzoleni 4bbadb8581 - in MachiningLib miglioramenti a GetBladeEngagement 2025-12-02 10:27:59 +01:00
luca.mazzoleni cb60773216 - in MachiningLib si GetBladeEngagement si controlla la collisione con tutti gli assi in modalità standard o DownUp 2025-12-01 18:54:03 +01:00
luca.mazzoleni 1e327819c6 - in PreCollisionLib corretta gestione SCC 2025-12-01 17:21:48 +01:00
luca.mazzoleni d5b4edea14 - PreCollisionLib rivista per testare costruire trimesh da punti e usare funzione EgtTestSurfaceSurface per verificare collisione 2025-12-01 12:44:23 +01:00
luca.mazzoleni 530dce3d0d - PreCollisionLib: ultima versione con controllo 3d fatto nelle 3 viste principali 2025-11-28 18:16:00 +01:00
luca.mazzoleni dc8c5e8ba2 - in PreCollisionLib piccola correzione 2025-11-28 16:03:00 +01:00
luca.mazzoleni a2ed6f5789 - in PreCollisionLib si gestisce correttamente la direzione SCC
- in FACEBYBLADE SCC preso da funzione macchina
- in BeamLib aggiunta funzione per convertire il valore SCC in direzione
2025-11-28 15:58:14 +01:00
luca.mazzoleni 198fa3a546 - piccole correzioni riguardanti PreCollision 2025-11-28 14:56:31 +01:00
luca.mazzoleni 1ad5a74a8b - in MachiningLib CheckCollisionAxisAB sostituito con CheckCollisionWithAxis 2025-11-28 13:15:16 +01:00
luca.mazzoleni a8c6424839 Merge branch 'develop' into CuttingImprovements 2025-11-28 12:54:27 +01:00
luca.mazzoleni 9ed315ab9b - in PreCollision varie modifiche e migliorie per rendere CheckCollisionWithAxis unica per ogni asse da testare
- in STR0006 si ritorna a usare dPivot da SetupInfo per check collisione asse Z, in attesa di implementare CheckCollisionWithAxis anche per fresa
2025-11-28 12:54:06 +01:00
Emmanuele Sassi 1c8049d9a9 - in BatchProcessNew gestito ritorno risultati in caso di errore e ritorno tempi
- in BeamExec resa non locale la funzione AddApplyResultToGlobalList
2025-11-26 16:47:09 +01:00
luca.mazzoleni 155fd09ee5 - in PreCollisionLib ottimizzazioni tempi di esecuzione
- in TempGroup  le geometrie sono settate azzurre con alpha 5
2025-11-26 15:00:12 +01:00
luca.mazzoleni 86adb74131 - in PreCollisionLib refactoring e ottimizzazioni tempo esecuzione
- in Process e simili aggiunto azzeramento PreCollisionLib
2025-11-26 12:26:37 +01:00
luca.mazzoleni 74a12a4a42 - funzioni di precollisione lama spostate in libreria apposita PreCollisionLib
- calcolo tempo esecuzione migliorato (TimeLib e riferimenti)
- idTempGroup ora è scritto nel Part per evitare di ricercarlo ogni volta
2025-11-25 15:19:09 +01:00
luca.mazzoleni 06a73a069f - aggiunta nuova modalità di pre calcolo collisioni, al momento lama e solo asse Z
- aggiunta libreria TimeLib per calcolare i tempi di esecuzione (sostituite chiamate a EgtStartCounter e Stop)
- rimosse chiamate a EgtOutLog deprecate
2025-11-24 17:30:57 +01:00
luca.mazzoleni e6a2ce3702 Merge branch 'develop' into CuttingImprovements 2025-11-12 17:36:56 +01:00
luca.mazzoleni e3cd0d3033 - in BLADETOWASTE piccola correzione 2025-11-12 17:36:47 +01:00
luca.mazzoleni eb0a46d545 Merge branch 'CuttingImprovements' into develop 2025-11-11 14:51:12 +01:00
luca.mazzoleni f9b1a957f6 - in BatchProcessNew corretta restituzione sMsg
- in BLADETOWASTE si assegna qualità bassa a tutti i tagli con lati brutti
- in FACEBYBLADE corretto typo in nome variabile
2025-11-11 13:49:54 +01:00
luca.mazzoleni 8f2a09e5c7 - in BLADEKEEPWASTE, se lavorazione fallisce da un lato, si fa codolo tutto da un lato alla massima profondità
- in BLADETOWASTE.CutWholeWaste, se fallisce il taglio doppio, si verificano i lati a minor elevazione
MachiningLib.GetBladeEngagement si restituisce anche se la lavorazione richiede separazione, verificata in Check2DBladeCollision
- in FACEBYBLADE gestita forzatura dopo split dall'esterno
- in BatchProcessNew e Process si restituisce sempre sMsg, anche se feature completa
- in FaceData rimosso logging MainFaces
2025-11-11 12:12:00 +01:00
luca.mazzoleni 711ac3930d - in FaceData corretta assegnazione ptStart e ptEnd nei MainEdges
- in FeatureLib.GetAdditionalInfo gestita correttamente 61 (Text)
2025-11-07 15:41:06 +01:00
luca.mazzoleni 4ce77a4792 - in MachiningLib.FindBlade si restituisce il BladeEngagement, se presente
- in BLADETOWASTE.GetEdgeToMachine aggiunta la possibilità di restituire l'n-esimo lato della lista ordinata; in GetSingleCutStrategy si tenta di cambiare lato se il con il primo set non si è trovato alcun utensile; altre piccole correzioni
- in FACEBYBLADE refactoring per contemplare i vari casi di inversione
2025-11-07 10:15:01 +01:00
luca.mazzoleni 15db75dfad - in FACEBYBLADE correzioni a chiamata Cutting.nToolIndex
- in MachiningLib.Check2DBladeCollision ora si controlla correttamente se c'è intersezione
2025-11-05 18:56:02 +01:00
luca.mazzoleni 6d319d17b6 - corretti alcuni casi in cui si calcolava il caso invertito anche se non necessario
- in MachiningLib.Check2DBladeCollision esclusi i casi in cui l'utensile arriva da una direzione principale
- in BLADETOWASTE.GetDualSideCutStrategy si verifica GetBladeEngagement anche per il lato opposto
- in FACEBYBLADE refactoring e verifica GetBladeEngagement quando necessario
2025-11-05 17:38:55 +01:00
luca.mazzoleni d8a3f257d8 - in BLADETOWASTE corrette chiamate a GetEdgeToMachine 2025-11-05 11:11:39 +01:00
luca.mazzoleni 43b096f531 - tutte le chiamate a EgtSurfTmFacetOppositeSide sostituite con i lati letti in EdgesInfo
- correzioni e migliorie legate e GetBladeEngagement
2025-11-05 11:02:02 +01:00
luca.mazzoleni d9d505fc44 - update versione minima Cam5
- in BeamExec corretto il calcolo di nCycles: ora il calcolo dell'inversione si fa solo se richiesto
- in BeamExec rimossa cancellazione entità temporanee: si mette tutto nel gruppo idTemp; adeguate le funzioni che creano geometrie temporanee
- in MachiningLib Check2DBladeCollision migliorata e ultimata: da testare
2025-11-04 17:40:48 +01:00
luca.mazzoleni ddff655240 - in BatchProcessNew e BeamExec, dove si salva il Box del Part si salva anche idBoxTm, id della trimesh del box
- in BeamLib rimosse funzioni GetPlaneOrientation e IsEdgeOnBox, non usate
- in MachiningLib rivista completamente GetBladeEngagement e aggiunta Check2DBladeCollision
2025-11-04 12:54:09 +01:00
luca.mazzoleni 2536244f1b in MachiningLib.GetBladeEngagement aggiunti i parametri dDepthToMachine e bAvoidCollisionCheckForStandardCut 2025-11-03 16:37:01 +01:00
luca.mazzoleni 7b4673acef - varie modifiche ai tagli di lama per DownUp, caso solo 2d
- in FaceData.GetEdgesInfo si scrivono anche i ptStart e ptEnd; IsFaceRhomboid diventa IsFaceParallelogram
- in BeamLib aggiunta IsEdgeOnBox
2025-11-03 16:29:12 +01:00
luca.mazzoleni 2d1abbb3cc - correzioni per tagli DownUp 2025-10-30 18:53:31 +01:00
luca.mazzoleni 25dbaed63b - funzioni IsFaceZOutOfRange, IsBladeOrientationOkForDownUp e GetBladeEngagement spostate in MachiningLib (da FACEBYBLADE) 2025-10-30 16:49:49 +01:00
luca.mazzoleni ecd2147e83 - in FACEBYBLADE modifiche e refactoring per contemplare nuova gestione DownUp 2025-10-30 13:20:15 +01:00
luca.mazzoleni 84cd799565 Merge branch 'develop' into CuttingImprovements 2025-10-29 15:30:57 +01:00
luca.mazzoleni 9468e3d013 - in FACEBYBLADE completata IsOrientationOkForDownUp; rimane da fare GetCorrectedElevationDownUp 2025-10-29 15:29:40 +01:00
andrea.villa e095806a7a Ripristinato funzionamento BLADEKEEPWASTE con codolo centrale 2025-10-29 15:11:39 +01:00
andrea.villa f21e1ea557 Merge branch 'SOLO_DEMO' into develop 2025-10-29 15:10:32 +01:00
luca.mazzoleni 21bb95c0e9 - in BeamLib aggiunta funzione GetPlaneOrientation per avere il modulo di un vettore nelle 3 direzioni e l'incidenza relativa di ogni componente sul totale
- in BLADETOWASTE, chiamate a FindBlade aggiornate
- in FACEBYBLADE numerose modifiche, da terminare, per determinare se la lavorazione è fattibile e se in DownUp (GetBladeEngagement)
2025-10-28 18:22:36 +01:00
luca.mazzoleni b8b71ff73a - in BLADETOWASTE chiamate a FindBlade aggiornate 2025-10-27 10:09:18 +01:00
luca.mazzoleni 0afcd786d1 - in FaceData, IsFaceRectangular e IsFaceRhomboid ricevono solamente il parametro Face; utilizzano il gruppo per geometrie temporanee invece di AddGroup 2025-10-24 18:54:49 +02:00
luca.mazzoleni 070ad50d73 - in FaceData IsFaceRectangular e IsFaceRhomboid si passa Face invece che idFace
- in FaceByBlade introdotta funzione GetBladeEngagement che sostituisce GetMinNzDownUp
2025-10-24 18:38:25 +02:00
luca.mazzoleni d6bdbab510 Merge branch 'develop' into CuttingImprovements 2025-10-24 17:31:20 +02:00
luca.mazzoleni 44273e15a7 - in FeatureLib correzione a GetProcFromTrimesh 2025-10-24 17:12:38 +02:00
luca.mazzoleni 711e0c82f7 Merge remote-tracking branch 'origin/develop' into CuttingImprovements 2025-10-24 12:51:54 +02:00
luca.mazzoleni c62f1818c7 - in BLADETOWASTE e DiceCut eliminati tutti i riferimenti al DownUp: il tipo di lavorazione si verificherà direttamente in FaceByBlade o FindBlade
- in FaceData.GetFacesInfo si salva l'id della trimesh nella faccia
- in HEADCUT il box per i cubetti viene copiato non per riferimento
2025-10-24 12:51:47 +02:00
andrea.villa 9fe22368cb - In preparazione della tabella Proc da una Trimesh, si salvano anche parametri pinzaggio
- AddMachinings copia deep di "AuxiliaryData" per evitare che venga inserita nella MACHININGS il riferimento
- STR0012 aggiunta gestione lavorazione con codolo
2025-10-24 11:53:36 +02:00
53 changed files with 6847 additions and 2734 deletions
+125 -29
View File
@@ -32,7 +32,7 @@ if not sMachDir then
EgtOutBox( 'Errore nel caricamento della macchina corrente', 'Lavora Travi', 'ERROR')
return
end
if not EgtExistsFile( sMachDir .. '\\Beam\\BeamData.lua') then
if not EgtExistsFile( sMachDir .. '\\Beam\\BeamDataNew.lua') then
EgtOutBox( 'La macchina corrente non è configurata per lavorare travi', 'Lavora Travi', 'ERROR')
BEAM.ERR = 12
BEAM.MSG = 'Error not configured for beams machine : ' .. sMachine
@@ -58,11 +58,15 @@ _G.package.loaded.FeatureLib = nil
_G.package.loaded.Identity = nil
_G.package.loaded.Logs = nil
_G.package.loaded.MachiningLib = nil
_G.package.loaded.PreSimulationLib = nil
_G.package.loaded.LeadInOutLib = nil
-- strategie di base sempre presenti
_G.package.loaded['HEADCUT\\HEADCUT'] = nil
_G.package.loaded['TAILCUT\\TAILCUT'] = nil
-- libreria macchina
_G.package.loaded.BeamData = nil
_G.package.loaded.BeamDataNew = nil
-- libreria calcolo tempo esecuzione
_G.package.loaded.TimeLib = 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.
@@ -88,7 +92,7 @@ end
PARTS = {} -- tabella contenente tutte le informazioni di ogni pezzo
-- Carico i dati globali
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
-- carico librerie
local BeamExec = require( 'BeamExec')
local BeamLib = require( 'BeamLib')
@@ -178,6 +182,13 @@ local function WriteResultToJson( RESULT)
end
-------------------------------------------------------------------------------------------------------------
-- calcolo tempo esecuzione
TIMER:start()
EgtOutLog( ' Execution timer started')
-- script principale
local sFlag = ''
if BEAM.FLAG == 0 then
sFlag = 'GENERATE'
@@ -200,12 +211,9 @@ elseif BEAM.FLAG == 10 then
else
sFlag = 'FLAG='..tostring( BEAM.FLAG)
end
local sLog = 'BatchProcess : ' .. BEAM.FILE .. ', ' .. BEAM.MACHINE .. ', ' .. sFlag
local sLog = 'BatchProcess : ' .. BEAM.FILE .. ', ' .. ( BEAM.MACHINE or EgtGetCurrMachineName()) .. ', ' .. sFlag
EgtOutLog( sLog)
-- TODO forzatura calcolo con prerotazioni. Cancellare dopo che è stata aggiunta la gestione corretta
local bCalcBestPieceUnloadPosition = true or BEAM.FLAG == 10
-- Dati dei file
-- TODO spostare a quando flag ~= 6 e 9
local sDir, sTitle = EgtSplitPath( BEAM.FILE)
@@ -235,11 +243,14 @@ elseif BEAM.FLAG == 9 then
local Part = {}
Part.id = EgtGetParent( EgtGetParent( BEAM.FEATUREID))
Part.b3Part = EgtGetBBoxGlob( EgtGetFirstNameInGroup( Part.id, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD)
Part.idBoxTm = EgtGetFirstInGroup( EgtGetFirstNameInGroup( Part.id, 'Box') or GDB_ID.NULL)
Part.b3Part = EgtGetBBoxGlob( Part.idBoxTm, GDB_BB.STANDARD)
Part.idTempGroup = idTempGroup
local Proc = FeatureLib.GetProcFromTrimesh( BEAM.FEATUREID, Part)
Proc.nGrp = EgtGetInfo( Proc.id, 'GRP', 'i')
Proc.nPrc = EgtGetInfo( Proc.id, 'PRC', 'i')
Proc.nParts = EgtSurfTmPartCount( Proc.id) or 1
Proc.Topology = {}
if FeatureLib.NeedTopologyFeature( Proc, Part) then
@@ -299,6 +310,9 @@ if bToProcess then
BEAM.MSG = 'Error opening BWE file : ' .. BEAM.FILE
WriteErrToLogFile( BEAM.ERR, BEAM.MSG)
PostErrView( BEAM.ERR, BEAM.MSG)
BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG)
BEAM.RESULT = BeamLib.TableCopyDeep( RESULT)
WriteResultToJson( RESULT)
return
end
-- Faccio copia del file originale
@@ -319,6 +333,9 @@ if bToProcess then
BEAM.MSG = 'Error no Raw Parts in the file : ' .. BEAM.FILE
WriteErrToLogFile( BEAM.ERR, BEAM.MSG)
PostErrView( BEAM.ERR, BEAM.MSG)
BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG)
BEAM.RESULT = BeamLib.TableCopyDeep( RESULT)
WriteResultToJson( RESULT)
return
end
local b3Raw = EgtGetRawPartBBox( nRawId)
@@ -343,6 +360,9 @@ if bToProcess then
BEAM.MSG = 'Error no beams in the file : ' .. BEAM.FILE
WriteErrToLogFile( BEAM.ERR, BEAM.MSG)
PostErrView( BEAM.ERR, BEAM.MSG)
BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG)
BEAM.RESULT = BeamLib.TableCopyDeep( RESULT)
WriteResultToJson( RESULT)
return
else
local sOut = ''
@@ -361,6 +381,9 @@ if bToProcess then
BEAM.MSG = 'Box undefined for beam ' .. PARTS[i].sName
WriteErrToLogFile( BEAM.ERR, BEAM.MSG)
PostErrView( BEAM.ERR, BEAM.MSG)
BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG)
BEAM.RESULT = BeamLib.TableCopyDeep( RESULT)
WriteResultToJson( RESULT)
return
else
PARTS[i].b3PartOriginal = b3Solid
@@ -397,6 +420,9 @@ if bToProcess then
BEAM.ERR = 14
BEAM.MSG = 'Error : no beams in the project'
WriteErrToLogFile( BEAM.ERR, BEAM.MSG)
BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG)
BEAM.RESULT = BeamLib.TableCopyDeep( RESULT)
WriteResultToJson( RESULT)
return
else
local sOut = ''
@@ -414,6 +440,9 @@ if bToProcess then
BEAM.ERR = 15
BEAM.MSG = 'Box undefined for beam ' .. PARTS[i].sName
WriteErrToLogFile( BEAM.ERR, BEAM.MSG)
BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG)
BEAM.RESULT = BeamLib.TableCopyDeep( RESULT)
WriteResultToJson( RESULT)
return
else
PARTS[i].b3PartOriginal = b3Solid
@@ -424,6 +453,9 @@ if bToProcess then
-- recupero parametri generali da progetto
BeamExec.GetGeneralParameters()
-- creo un gruppo temporaneo dove finiranno tutte le entità che non bisogna salvare, alla fine lo si cancella
local idTempGroup = BeamLib.CreateTempGroup()
-- Se devo creare la barra
if bCreateBar then
if #PARTS == 0 then
@@ -460,6 +492,7 @@ if bToProcess then
return
end
-- TODO in caso di "GEN_sPiecesLoadingPosition = FULL_PRE_ROTATION" bisogna controllare anche sezione ribaltata di 90°
-- Verifico sezione barra non troppo grande
if not BeamData.MAX_WIDTH2 or not BeamData.MAX_HEIGHT2 then
if ( dRawW > BeamData.MAX_WIDTH + 10 * GEO.EPS_SMALL or dRawH > BeamData.MAX_HEIGHT + 10 * GEO.EPS_SMALL) then
@@ -470,6 +503,9 @@ if bToProcess then
BEAM.MSG = sOut
WriteErrToLogFile( BEAM.ERR, BEAM.MSG)
PostErrView( BEAM.ERR, BEAM.MSG)
BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG)
BEAM.RESULT = BeamLib.TableCopyDeep( RESULT)
WriteResultToJson( RESULT)
return
end
else
@@ -483,6 +519,9 @@ if bToProcess then
BEAM.MSG = sOut
WriteErrToLogFile( BEAM.ERR, BEAM.MSG)
PostErrView( BEAM.ERR, BEAM.MSG)
BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG)
BEAM.RESULT = BeamLib.TableCopyDeep( RESULT)
WriteResultToJson( RESULT)
return
end
end
@@ -496,6 +535,9 @@ if bToProcess then
BEAM.MSG = sOut
WriteErrToLogFile( BEAM.ERR, BEAM.MSG)
PostErrView( BEAM.ERR, BEAM.MSG)
BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG)
BEAM.RESULT = BeamLib.TableCopyDeep( RESULT)
WriteResultToJson( RESULT)
return
end
@@ -508,12 +550,15 @@ if bToProcess then
end
-- Sistemo le travi nel grezzo
local bPbOk, sPbErr = BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, nil, PARTS, BEAM.FLAG ~= 6, bCalcBestPieceUnloadPosition)
local bPbOk, sPbErr = BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, nil, PARTS, BEAM.FLAG ~= 6, BEAM.FLAG == 10)
if not bPbOk then
BEAM.ERR = 18
BEAM.MSG = sPbErr
WriteErrToLogFile( BEAM.ERR, BEAM.MSG)
PostErrView( BEAM.ERR, BEAM.MSG)
BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG)
BEAM.RESULT = BeamLib.TableCopyDeep( RESULT)
WriteResultToJson( RESULT)
return
else
-- Scrivo altezza e larghezza barra nel gruppo di lavoro corrente
@@ -573,7 +618,8 @@ if bToProcess then
PARTS[i].dRawWidth = PARTS[i].b3Raw:getDimY()
PARTS[i].dRawHeight = PARTS[i].b3Raw:getDimZ()
-- dimensione pezzo finito
PARTS[i].b3Part = EgtGetBBoxGlob( EgtGetFirstNameInGroup( PARTS[i].id, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD)
PARTS[i].idBoxTm = EgtGetFirstInGroup( EgtGetFirstNameInGroup( PARTS[i].id, 'Box') or GDB_ID.NULL)
PARTS[i].b3Part = EgtGetBBoxGlob( PARTS[i].idBoxTm, GDB_BB.STANDARD)
PARTS[i].dLength = PARTS[i].b3Part:getDimX()
PARTS[i].dWidth = PARTS[i].b3Part:getDimY()
PARTS[i].dHeight = PARTS[i].b3Part:getDimZ()
@@ -582,15 +628,19 @@ if bToProcess then
PARTS[i].SplittingPoints = BeamLib.GetPartSplittingPoints( PARTS[i])
PARTS[i].NotClampableLength = { STD = { dHead = 0, dTail = 0}, SIDE = { dHead = 0, dTail = 0}, DOWN = { dHead = 0, dTail = 0}}
PARTS[i].sBTLInfo = EgtGetInfo( PARTS[i].id, 'PROJ', 's') or nil
PARTS[i].idTempGroup = idTempGroup
PARTS[i].sAISetupConfig = EgtGetInfo( PARTS[i].id, 'AISETUP', 's') or
( GENERAL_PARAMETERS.BTL[PARTS[i].sBTLInfo] and GENERAL_PARAMETERS.BTL[PARTS[i].sBTLInfo].sAISetupConfig) or -- i parametri BTL potrebbero non esistere
GENERAL_PARAMETERS.PROJECT.sAISetupConfig or nil
-- si carica configurazione lavorazioni
TIMER:startElapsed('Json')
BeamExec.GetStrategiesFromJSONinBD( PARTS[i].sAISetupConfig)
PARTS[i].GeneralParameters = BeamLib.GetPieceGeneralParameters( PARTS[i], GENERAL_PARAMETERS_JSON)
PARTS[i].CombinationList = BeamExec.GetAvailableCombinations( PARTS[i], bCalcBestPieceUnloadPosition)
TIMER:stopElapsed('Json')
-- parametro FlipRot sempre a false perchè a barra già creata non si possono più ruotare i pezzi
PARTS[i].CombinationList = BeamExec.GetAvailableCombinations( PARTS[i], false)
-- sovramateriale in testa al pezzo
local dDeltaS = max( PARTS[i].dPosX - ( dBarLen - dLen), 0)
@@ -621,6 +671,9 @@ if bToProcess then
BEAM.ERR = 0
BEAM.MSG = '---'
WriteErrToLogFile( BEAM.ERR, BEAM.MSG)
BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG)
BEAM.RESULT = BeamLib.TableCopyDeep( RESULT)
WriteResultToJson( RESULT)
end
EgtOutLog( ' +++ BatchProcess completed')
return
@@ -637,23 +690,15 @@ if bToProcess then
EgtImportSetup()
-- Lavoro le features
-- TODO gestire errori e messaggi di ritorno in questo caso
if not GetDataConfig() then return end
-- creo un gruppo temporaneo dove finiranno tutte le entità che non bisogna salvare, alla fine lo si cancella
BeamLib.CreateTempGroup()
BeamExec.GetProcessings( PARTS, bCalcBestPieceUnloadPosition)
BeamExec.GetCombinationMatrix( PARTS, bCalcBestPieceUnloadPosition)
BeamExec.ProcessMachinings( PARTS)
-- si cancella gruppo temporaneo contenente entità da cancellare
local idTempGroup = BeamLib.GetTempGroup()
EgtErase( idTempGroup)
BeamExec.GetProcessings( PARTS, BEAM.FLAG == 10)
BeamExec.GetCombinationMatrix( PARTS, BEAM.FLAG == 10)
BeamExec.ProcessMachinings( PARTS, BEAM.FLAG == 10)
local sOutput = ''
-- Scrittura json risultati
WriteResultToJson( RESULT)
-- scrittura txt risultati
for i = 1, #RESULT do
local sMsg = ''
@@ -670,9 +715,14 @@ if bToProcess then
sMsg = string.gsub( sMsg or '', '\r', ' ', 10)
-- trovata almeno una strategia e feature lavorata completamente
if RESULT[i].sType == 'Feature' and RESULT[i].ChosenStrategy.sStatus == 'Completed' then
BEAM.ERR = 0
BEAM.MSG = '---'
BEAM.ROT = -( RESULT[i].nRotation or 1) + 1
if #EgtTrim( sMsg) > 0 then
BEAM.ERR = -19
BEAM.MSG = sMsg
else
BEAM.ERR = 0
BEAM.MSG = '---'
end
BEAM.ROT = -( ( RESULT[i].nRotation - ( BEAM.PREROTATE90 or 0)) or 1) + 1
BEAM.CUTID = RESULT[i].idCut
BEAM.TASKID = RESULT[i].idTask
WriteErrToLogFile( BEAM.ERR, BEAM.MSG, BEAM.ROT, BEAM.CUTID, BEAM.TASKID)
@@ -688,7 +738,7 @@ if bToProcess then
sOutput = sOutput .. string.format( '[%d,%d] %s\n', RESULT[i].idCut, RESULT[i].idTask, sMsg)
BEAM.ERR = 19
BEAM.MSG = sMsg
BEAM.ROT = -( RESULT[i].nRotation or 1) + 1
BEAM.ROT = -( ( RESULT[i].nRotation - ( BEAM.PREROTATE90 or 0)) or 1) + 1
BEAM.CUTID = RESULT[i].idCut
BEAM.TASKID = RESULT[i].idTask
WriteErrToLogFile( BEAM.ERR, BEAM.MSG, BEAM.ROT, BEAM.CUTID, BEAM.TASKID)
@@ -700,13 +750,21 @@ if bToProcess then
BEAM.CUTID = RESULT[i].idCut
BEAM.FALL = abs( RESULT[i].nErr + 100)
WriteFallToLogFile( BEAM.ERR, BEAM.MSG, BEAM.CUTID, BEAM.FALL)
-- errore da post apply, al momento non specifico
elseif RESULT[i].sType == 'Part' and RESULT[i].nErr > 0 then
nErrCnt = nErrCnt + 1
sOutput = sOutput .. string.format( '[%d,%d] %s\n', RESULT[i].idCut, RESULT[i].idTask, sMsg)
BEAM.ERR = 19
BEAM.MSG = 'Clamp impossible'
WriteErrToLogFile( BEAM.ERR, BEAM.MSG)
return
-- feature incompleta e altro
elseif RESULT[i].sType == 'Feature' and RESULT[i].ChosenStrategy.sStatus == 'Not-Completed' then
nWarnCnt = nWarnCnt + 1
sOutput = sOutput .. string.format( '[%d,%d] %s\n', RESULT[i].idCut, RESULT[i].idTask, sMsg)
BEAM.ERR = -19
BEAM.MSG = 'Incomplete : Completion index ' .. RESULT[i].ChosenStrategy.dCompletionIndex .. '/5\n' .. sMsg
BEAM.ROT = -( RESULT[i].nRotation or 1) + 1
BEAM.ROT = -( ( RESULT[i].nRotation - ( BEAM.PREROTATE90 or 0)) or 1) + 1
BEAM.CUTID = RESULT[i].idCut
BEAM.TASKID = RESULT[i].idTask
WriteErrToLogFile( BEAM.ERR, BEAM.MSG, BEAM.ROT, BEAM.CUTID, BEAM.TASKID)
@@ -714,6 +772,18 @@ if bToProcess then
end
end
-- calcolo alternative (scrive già le variabili globali per interfaccia)
if BEAM.FLAG == 10 then
TIMER:startElapsed('Alternatives')
BeamExec.ProcessAlternatives( PARTS)
TIMER:stopElapsed('Alternatives')
end
-- si cancella gruppo temporaneo contenente entità da cancellare
EgtErase( idTempGroup)
-- TODO: se scarico a caduta (-101, -102) le lavorazioni dopo separazione vanno disattivate. Scrivere info feature incompleta su quelle feature
-- Salvo il progetto
EgtSaveFile( sNgeFile)
-- copio come originale (per dichiarare progetto ricalcolato)
@@ -746,6 +816,11 @@ else
end
end
-- log tempi di esecuzione
if EgtGetDebugLevel() >= 3 then
TIMER:logAllElapsed()
end
-- *** Eseguo simulazione con verifica collisione in cieco ***
if ( BEAM.FLAG == 0 and ( bToProcess or bToRecalc)) or BEAM.FLAG == 3 or BEAM.FLAG == 4 then
EgtOutLog( ' +++ Simulating with collision check >>>')
@@ -759,7 +834,12 @@ if ( BEAM.FLAG == 0 and ( bToProcess or bToRecalc)) or BEAM.FLAG == 3 or BEAM.F
sToolsList = sToolsList .. ", "
end
end
WriteErrToLogFile( 19, 'Error in setup: tool/s ' .. sToolsList .. ' not found', 0, 0, 0)
BEAM.ERR = 19
BEAM.MSG = 'Error in setup: tool/s ' .. sToolsList .. ' not found'
WriteErrToLogFile( BEAM.ERR, BEAM.MSG, 0, 0, 0)
BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG)
BEAM.RESULT = BeamLib.TableCopyDeep( RESULT)
WriteResultToJson( RESULT)
return
end
-- lancio simulazione
@@ -794,6 +874,10 @@ if ( BEAM.FLAG == 0 and ( bToProcess or bToRecalc)) or BEAM.FLAG == 3 or BEAM.F
end
end
WriteErrToLogFile( BEAM.ERR, BEAM.MSG, BEAM.ROT, BEAM.CUTID, BEAM.TASKID)
-- TODO gestire collisione su feature specifica!!!!!!!!!!!!!!!!!!!!!!!!!!!!
BeamExec.AddApplyResultToGlobalList( BEAM.ERR, BEAM.CUTID, BEAM.MSG)
BEAM.RESULT = BeamLib.TableCopyDeep( RESULT)
WriteResultToJson( RESULT)
return
end
end
@@ -813,6 +897,9 @@ if bIsGenerationEnabled and ( BEAM.FLAG == 0 or BEAM.FLAG == 4) then
BEAM.MSG = 'Error generating NC part program : ' .. sName
WriteErrToLogFile( BEAM.ERR, BEAM.MSG)
PostErrView( BEAM.ERR, BEAM.MSG)
BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG)
BEAM.RESULT = BeamLib.TableCopyDeep( RESULT)
WriteResultToJson( RESULT)
return
end
end
@@ -825,6 +912,9 @@ if not EgtEstimate( '', 'EgtCAM5 - ' .. sNgeFile) then
BEAM.MSG = 'Error estimating production time : ' .. sName
WriteErrToLogFile( BEAM.ERR, BEAM.MSG)
PostErrView( BEAM.ERR, BEAM.MSG)
BeamExec.AddApplyResultToGlobalList( BEAM.ERR, 0, BEAM.MSG)
BEAM.RESULT = BeamLib.TableCopyDeep( RESULT)
WriteResultToJson( RESULT)
return
end
local Ttot = EgtGetInfo( EgtGetCurrMachGroup(), 'Ttot', 'd')
@@ -847,5 +937,11 @@ end
-- Scrittura tempo totale stimato di lavorazione
WriteTimeToLogFile( Ttot)
RESULT[#RESULT+1] = { dTime = Ttot, sType = 'Time'}
-- Riporto risultati in tabella globale BEAM
BEAM.RESULT = BeamLib.TableCopyDeep( RESULT)
-- Scrittura json risultati
WriteResultToJson( RESULT)
EgtOutLog( ' +++ BatchProcess completed')
+247
View File
@@ -0,0 +1,247 @@
-- Process.lua by Egalware s.r.l. 2024/04/02
-- Gestione calcolo disposizione e lavorazioni per Travi
-- Si opera sulla macchina corrente
-- 2024/04/02 PRIMA VERSIONE
-- Intestazioni
require( 'EgtBase')
_ENV = EgtProtectGlobal()
EgtEnableDebug( false)
-- 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 .. '\\StrategyLibs\\?.lua')
-- Verifico che la macchina corrente sia abilitata per la lavorazione delle Travi
local sMachDir = EgtGetCurrMachineDir()
if not sMachDir then
EgtOutBox( 'Errore nel caricamento della macchina corrente', 'Lavora Travi', 'ERROR')
return
end
if not EgtExistsFile( sMachDir .. '\\Beam\\BeamDataNew.lua') then
EgtOutBox( 'La macchina corrente non è configurata per lavorare travi', 'Lavora Travi', 'ERROR')
return
end
-- Elimino direttori altre macchine e imposto direttorio macchina corrente per ricerca librerie
EgtRemoveBaseMachineDirFromPackagePath()
EgtAddToPackagePath( sMachDir .. '\\Beam\\?.lua')
-- Segnalazione avvio
EgtOutLog( '*** Beam Process Start ***', 1)
-- Carico le librerie
_G.package.loaded.BasicCustomerStrategies = nil
_G.package.loaded.BeamExec = nil
_G.package.loaded.BeamLib = nil
_G.package.loaded.DiceCut = nil
_G.package.loaded.FaceData = nil
_G.package.loaded.FeatureLib = nil
_G.package.loaded.Identity = nil
_G.package.loaded.Logs = nil
_G.package.loaded.MachiningLib = nil
_G.package.loaded.PreSimulationLib = nil
_G.package.loaded.LeadInOutLib = nil
-- strategie di base sempre presenti
_G.package.loaded['HEADCUT\\HEADCUT'] = nil
_G.package.loaded['TAILCUT\\TAILCUT'] = nil
-- libreria macchina
_G.package.loaded.BeamDataNew = nil
-- libreria calcolo tempo esecuzione
_G.package.loaded.TimeLib = 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.
-- Infatti difficile ci siano 9999 strategie.
-- reset strategie caricate come librerie
for i = 1, 9999 do
local idSTRTemp = EgtReplaceString( EgtNumToString( i/10000, -4), '0.', '')
local sLibraryToReload = "STR" .. idSTRTemp .. "\\STR" .. idSTRTemp
if _G.package.loaded[sLibraryToReload] then
_G.package.loaded[sLibraryToReload] = nil
end
end
local vtCoreStrategiesNames = EgtFindAllFiles( BEAM.BASEDIR .. '\\StrategyLibs\\*.lua')
for i = 1, #vtCoreStrategiesNames do
local sCurrentName = EgtSplitString( vtCoreStrategiesNames[i], '.')[1]
if _G.package.loaded[sCurrentName] then
_G.package.loaded[sCurrentName] = nil
end
end
-- Variabili globali
PARTS = {} -- tabella contenente tutte le informazioni di ogni pezzo
-- Carico i dati globali
local BeamData = require( 'BeamDataNew')
-- carico librerie
local BeamExec = require( 'BeamExec')
local BeamLib = require( 'BeamLib')
-------------------------------------------------------------------------------------------------------------
-- *** Recupero trave (E' SEMPRE E SOLO UNA) ***
-------------------------------------------------------------------------------------------------------------
local function MyProcessInputData()
-- Recupero il pezzo e i suoi dati
local nId = EgtGetFirstPart()
if nId then
table.insert( PARTS, { nInd = #PARTS + 1, id = nId, sName = ( EgtGetName( nId) or ( 'Id=' .. tonumber( nId)))})
local Ls = EgtGetFirstNameInGroup( PARTS[1].id, 'Box')
local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD)
if not b3Solid then
return false
end
PARTS[1].b3PartOriginal = b3Solid
else
return false
end
return true
end
-------------------------------------------------------------------------------------------------------------
local function GetDataConfig()
-- recupero utensili dal magazzino
BeamExec.GetToolsFromDB()
-- TODO da gestire eventuali errori bloccanti
return true
end
-------------------------------------------------------------------------------------------------------------
-- *** Inserimento delle travi nel grezzo ***
-------------------------------------------------------------------------------------------------------------
local function MyProcessBeams()
-- Lunghezza totale delle travi
local dLen = PARTS[1].b3PartOriginal:getDimX()
local dRawW = PARTS[1].b3PartOriginal:getDimY()
local dRawH = PARTS[1].b3PartOriginal:getDimZ()
-- Determinazione minimo grezzo scaricabile
BeamExec.CalcMinUnloadableRaw( dRawW, dRawH)
local dOvmHead = BeamData.OVM_HEAD or 10
local dOvmMid = BeamData.OVM_MID or 10
local dRawL = max( dLen + dOvmHead + dOvmMid, BeamData.dMinRaw)
-- Recupero info pezzi
local bOk, sErr = BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS, nil, true)
if not bOk then
EgtOutLog( sErr)
return false
end
return true
end
-------------------------------------------------------------------------------------------------------------
-- *** Inserimento delle lavorazioni nelle travi ***
-------------------------------------------------------------------------------------------------------------
local function MyProcessFeatures()
BeamExec.GetProcessings( PARTS, true)
BeamExec.GetCombinationMatrix( PARTS, true)
BeamExec.ProcessMachinings( PARTS, true)
-- scrittura variabili globali per interfaccia
BEAM.PREROTATE90 = PARTS[1].nInitialPosition - 1
BEAM.PREINVERT = EgtIf( PARTS[1].bPartInCombiIsInverted, 1, 0)
local nErrCnt = 0
local nWarnCnt = 0
local sOutput = ''
for i = 1, #RESULT do
local sMsg = ''
if RESULT[i].sType == 'Feature' then
sMsg = RESULT[i].ChosenStrategy.sInfo
elseif RESULT[i].sType == 'Part' then
sMsg = RESULT[i].sMsg
end
sMsg = string.gsub( sMsg or '', '\n', ' ', 10)
sMsg = string.gsub( sMsg or '', '\r', ' ', 10)
-- trovata almeno una strategia e feature lavorata completamente
if RESULT[i].sType == 'Feature' and RESULT[i].ChosenStrategy.sStatus == 'Completed' then
sOutput = sOutput .. string.format( '[%d,%d] %s\n', RESULT[i].idCut, RESULT[i].idTask, sMsg or '')
-- trovata almeno una strategia ma nessuna applicabile oppure non trovata alcuna strategia
elseif RESULT[i].sType == 'Feature'
and ( ( RESULT[i].ChosenStrategy.sStatus == 'Not-Applicable')
or ( not RESULT[i].ChosenStrategy.sStrategyName)) then
nErrCnt = nErrCnt + 1
if #sMsg == 0 then
sMsg = 'No applicable strategy found'
end
sOutput = sOutput .. string.format( '[%d,%d] %s\n', RESULT[i].idCut, RESULT[i].idTask, sMsg)
else
-- segnalazione scarico pezzo standard, incompleto o a caduta
if RESULT[i].sType == 'Part' and ( RESULT[i].nErr == -100 or RESULT[i].nErr == -101 or RESULT[i].nErr == -102) then
-- nulla da segnalare
-- feature incompleta e altro
elseif RESULT[i].sType == 'Feature' and RESULT[i].ChosenStrategy.sStatus == 'Not-Completed' then
nWarnCnt = nWarnCnt + 1
sMsg = 'Incomplete : Completion index ' .. RESULT[i].ChosenStrategy.dCompletionIndex .. '/5\n' .. sMsg
sOutput = sOutput .. string.format( '[%d,%d] %s\n', RESULT[i].idCut, RESULT[i].idTask, sMsg)
end
end
end
-- si calcolano alternative
TIMER:startElapsed('Alternatives')
BeamExec.ProcessAlternatives( PARTS)
TIMER:stopElapsed('Alternatives')
-- cancello gruppo temporaneo
local idTempGroup = BeamLib.GetTempGroup()
EgtErase( idTempGroup)
if #sOutput > 0 then EgtOutLog( sOutput) end
if nErrCnt > 0 then
EgtOutBox( sOutput, 'Lavora Travi', 'ERRORS')
return false
elseif nWarnCnt > 0 then
EgtOutBox( sOutput, 'Lavora Travi', 'WARNINGS')
return true
end
return true
end
-------------------------------------------------------------------------------------------------------------
-- *** Esecuzione ***
-------------------------------------------------------------------------------------------------------------
-- calcolo tempo esecuzione
TIMER:start()
EgtOutLog( ' Execution timer started')
-- script principale
if not MyProcessInputData() then return end
-- recupero parametri generali da progetto
BeamExec.GetGeneralParameters()
-- creo un gruppo temporaneo dove finiranno tutte le entità che non bisogna salvare, alla fine lo si cancella
BeamLib.CreateTempGroup()
if not MyProcessBeams() then return end
if not GetDataConfig() then return end
-- Abilito Vmill
EgtSetInfo( EgtGetCurrMachGroup(), 'Vm', '1')
MyProcessFeatures()
-- log tempi di esecuzione
if EgtGetDebugLevel() >= 3 then
TIMER:logAllElapsed()
end
+44
View File
@@ -0,0 +1,44 @@
-- GetWallData.lua by Egaltech s.r.l. 2022/06/28
-- Recupero dati da file WallData.lua di macchina
-- Intestazioni
require( 'EgtBase')
_ENV = EgtProtectGlobal()
EgtEnableDebug( false)
-- Per test
--GWD = {}
--GWD.MACHINE = 'Essetre-90480019_MW'
local sLog = 'GetBeamData : ' .. GWD.MACHINE
EgtOutLog( sLog)
-- Imposto direttorio libreria specializzata per Travi
EgtAddToPackagePath( GWD.BASEDIR .. '\\LuaLibs\\?.lua')
-- Verifico che la macchina corrente sia abilitata per la lavorazione delle Travi
local sMachDir = EgtGetCurrMachineDir()
if not EgtExistsFile( sMachDir .. '\\Beam\\BeamDataNew.lua') then
GWD.ERR = 12
GWD.MSG = 'Error not configured for beam machine : ' .. GWD.MACHINE
WriteErrToLogFile( GWD.ERR, GWD.MSG)
PostErrView( GWD.ERR, GWD.MSG)
return
end
-- Elimino direttori altre macchine e imposto direttorio macchina corrente per ricerca librerie
EgtRemoveBaseMachineDirFromPackagePath()
EgtAddToPackagePath( sMachDir .. '\\Beam\\?.lua')
-- Carico i dati globali
_G.package.loaded.BeamData = nil
local BD = require( 'BeamDataNew')
-- Assegno valori di interesse
GWD.SIMUL_VIEW_DIR = BD.SIMUL_VIEW_DIR
GWD.OVM_MID = BD.OVM_MID
-- Tutto ok
GWD.ERR = 0
EgtOutLog( ' +++ GetBeamData completed')
+1 -1
View File
@@ -9,7 +9,7 @@ local BasicCustomerStrategies = {}
require( 'EgtBase')
-- Carico i dati globali
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
local BeamLib = require( 'BeamLib')
local ID = require( 'Identity')
+1040 -404
View File
File diff suppressed because it is too large Load Diff
+251 -43
View File
@@ -8,7 +8,7 @@ local BeamLib = {}
-- Include
require( 'EgtBase')
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
EgtOutLog( ' BeamLib started', 1)
@@ -65,6 +65,64 @@ function BeamLib.AddPartEndFace( PartId, b3Solid)
return true
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.GetPartBoxWithHeadTail( Part, sSide)
local _sSide = sSide or ''
-- si può usare il box del grezzo che contiene sempre il sovramateriale di testa
if _sSide == 'Head' then
local b3WithHead = BBox3d( Part.b3Raw)
return b3WithHead
-- se è l'ultimo pezzo della barra si aggiunge il box dell'eventuale grezzo successivo
-- se non lo è, si estende il box del pezzo fino alla fine della barra
elseif _sSide == 'Tail' then
local b3WithTail = BBox3d( Part.b3Part)
if Part.bIsLastPart then
local nNextRawId = EgtGetNextRawPart( Part.idRaw)
if nNextRawId then
local b3Tail = EgtGetRawPartBBox( nNextRawId)
b3WithTail:Add( b3Tail)
end
else
-- per il punto di inizio barra si parte dal box del grezzo perchè contiene già il sovramateriale spessore lama/catena in coda (la restLength non lo comprende)
local ptXMin = Point3d( Part.b3Raw:getMin():getX() - Part.dRestLength, Part.b3Part:getMin():getY(), Part.b3Part:getMin():getZ())
b3WithTail:Add( ptXMin)
end
return b3WithTail
-- per aggiungere entrambi si procede come per la coda ma partendo dal box del grezzo, che già contiene la testa
elseif sSide == 'HeadTail' then
local b3WithHeadTail = BBox3d( Part.b3Raw)
if Part.bIsLastPart then
local nNextRawId = EgtGetNextRawPart( Part.idRaw)
if nNextRawId then
local b3Tail = EgtGetRawPartBBox( nNextRawId)
b3WithHeadTail:Add( b3Tail)
end
else
-- per il punto di inizio barra si parte dal box del grezzo perchè contiene già il sovramateriale spessore lama/catena in coda (la restLength non lo comprende)
local ptXMin = Point3d( Part.b3Raw:getMin():getX() - Part.dRestLength, Part.b3Part:getMin():getY(), Part.b3Part:getMin():getZ())
b3WithHeadTail:Add( ptXMin)
end
return b3WithHeadTail
-- sSide non definito, si restituisce il box del pezzo con l'aggiunta dello spessore lama/catena in coda
else
local b3WithSplit = BBox3d( Part.b3Part)
-- per il punto di inizio barra si parte dal box del grezzo perchè contiene già il sovramateriale spessore lama/catena in coda (la restLength non lo comprende)
local ptXMin = Point3d( Part.b3Raw:getMin():getX(), Part.b3Part:getMin():getY(), Part.b3Part:getMin():getZ())
b3WithSplit:Add( ptXMin)
return b3WithSplit
end
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.GetPartSplittingPoints( Part)
local PartSplittingPoints = {}
@@ -104,7 +162,7 @@ end
-------------------------------------------------------------------------------------------------------------
function BeamLib.AddPhaseWithRawParts( idRaw, OriXR, PosXR, dDeltaSucc)
EgtAddPhase()
local nPhase = EgtAddPhase()
-- si aprono i limiti tavola per permettere rotazioni di pezzi più larghi della tavola
EgtSetTableAreaOffset( 2000, 2000, 2000, 2000)
local dRawMove = 0
@@ -116,6 +174,10 @@ function BeamLib.AddPhaseWithRawParts( idRaw, OriXR, PosXR, dDeltaSucc)
dRawMove = dRawMove + EgtGetRawPartBBox( idRaw):getDimX()
idRaw = EgtGetNextRawPart( idRaw)
end
-- salvo info nuova fase aggiunta
local MachExtraInfo = { sType = 'DISP',
nPhase = nPhase}
table.insert( DB_MACH_APPLIED, MachExtraInfo)
end
-------------------------------------------------------------------------------------------------------------
@@ -266,6 +328,18 @@ function BeamLib.RotateRawPart( Part, nNumberOfRotations)
end
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.CreateAddGroup( PartId, sGroupName)
AddGrpId = EgtGroup( PartId or GDB_ID.NULL)
if not AddGrpId then
return false
end
-- assegno nome, flag di layer per gruppo di lavoro e colore
EgtSetName( AddGrpId, sGroupName)
EgtSetInfo( AddGrpId, GDB_SI.MGRPONLY, EgtGetCurrMachGroup())
EgtSetColor( AddGrpId, Color3d( 80, 160, 160, 25))
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.CreateOrEmptyAddGroup( PartId)
-- recupero i dati del gruppo aggiuntivo
@@ -279,15 +353,9 @@ function BeamLib.CreateOrEmptyAddGroup( PartId)
EgtSetInfo( AddGrpId, GDB_SI.MGRPONLY, EgtGetCurrMachGroup())
return EgtEmptyGroup( AddGrpId)
end
-- altrimenti lo creo
AddGrpId = EgtGroup( PartId or GDB_ID.NULL)
if not AddGrpId then
return false
end
-- assegno nome, flag di layer per gruppo di lavoro e colore
EgtSetName( AddGrpId, sMchGrp)
EgtSetInfo( AddGrpId, GDB_SI.MGRPONLY, EgtGetCurrMachGroup())
EgtSetColor( AddGrpId, Color3d( 80, 160, 160, 25))
BeamLib.CreateAddGroup( PartId, sMchGrp)
return true
end
@@ -299,7 +367,9 @@ function BeamLib.CreateTempGroup()
if not idTempGroup then
idTempGroup = EgtGroup( GDB_ID.ROOT)
EgtSetName( idTempGroup, "#TEMP_GROUP#")
EgtSetColor( idTempGroup, Color3d( 80, 160, 160, 1))
EgtSetLevel( idTempGroup, GDB_LV.TEMP)
EgtSetStatus( idTempGroup, GDB_ST.OFF)
end
return idTempGroup
end
@@ -424,6 +494,87 @@ function BeamLib.GetNearestParalOpposite( vtRef, vtNorm)
return nil
end
-------------------------------------------------------------------------------------------------------------
-- TODO gestire anche altri valori
function BeamLib.GetDirectionFromSCC( nSCC)
local vtSCC
if nSCC == MCH_SCC.ADIR_XP then
vtSCC = X_AX()
elseif nSCC == MCH_SCC.ADIR_XM then
vtSCC = -X_AX()
elseif nSCC == MCH_SCC.ADIR_YP then
vtSCC = Y_AX()
elseif nSCC == MCH_SCC.ADIR_YM then
vtSCC = -Y_AX()
elseif nSCC == MCH_SCC.ADIR_ZP then
vtSCC = Z_AX()
elseif nSCC == MCH_SCC.ADIR_ZM then
vtSCC = -Z_AX()
end
return vtSCC
end
-------------------------------------------------------------------------------------------------------------
-- Restituisce una tabella con i punti ai vertici della faccia, in globale
-- ordinati partendo da quello ai valori minimi degli assi e i successivi secondo rotazione destrorsa X+;
-- solo per Proc a 1 faccia
function BeamLib.GetSortedVertices( Proc)
local PtVerticesSorted = {}
-- se più di una faccia si esce subito
if Proc.nFct > 1 then
return
end
local PtVertices = {}
local nFirstIndex
local dMinYZ = GEO.INFINITO
for i = 1, #Proc.Faces[1].Edges do
local Edge = Proc.Faces[1].Edges[i]
table.insert( PtVertices, Edge.ptStart)
if ( Edge.ptStart:getY() + Edge.ptStart:getZ() < dMinYZ) then
nFirstIndex = i
dMinYZ = Edge.ptStart:getY() + Edge.ptStart:getZ()
end
end
table.insert( PtVerticesSorted, PtVertices[nFirstIndex])
local nCurrentIndex = nFirstIndex
-- faccia che guarda verso X+, ordine ok
if Proc.Faces[1].vtN:getX() > GEO.EPS_SMALL then
for _ = 1, #PtVertices - 1 do
_, nCurrentIndex = BeamLib.GetAdjacentIndices( nCurrentIndex, #PtVertices)
table.insert( PtVerticesSorted, PtVertices[nCurrentIndex])
end
-- faccia che guarda verso X-, ordine da invertire
else
for _ = 1, #PtVertices - 1 do
nCurrentIndex = BeamLib.GetAdjacentIndices( nCurrentIndex, #PtVertices)
table.insert( PtVerticesSorted, PtVertices[nCurrentIndex])
end
end
return PtVerticesSorted
end
-------------------------------------------------------------------------------------------------------------
-- restituisce il precedente e prossimo indice 1-based, tenendo conto del massimo indice
function BeamLib.GetAdjacentIndices( nCurrentIndex, nMaxIndex)
local nPreviousIndex, nNextIndex
if ( nCurrentIndex < 1) or ( nCurrentIndex > nMaxIndex) then
return
end
-- circular indexing 1-based
nPreviousIndex = ((nCurrentIndex - 2 + nMaxIndex) % nMaxIndex) + 1
nNextIndex = (nCurrentIndex % nMaxIndex) + 1
return nPreviousIndex, nNextIndex
end
-------------------------------------------------------------------------------------------------------------
-- Funzione per determinare se la faccia ha lati molto corti (trascurabili) ed è quindi approssimabile ad una 3 facce
function BeamLib.Is3EdgesApprox( Proc, idFace, nAddGrpId)
@@ -502,7 +653,7 @@ function BeamLib.GetPieceGeneralParameters( Part, DefaultGeneralParamList)
else
if GENERAL_PARAMETERS.BTL and GENERAL_PARAMETERS.BTL[Part.sBTLInfo] and GENERAL_PARAMETERS.BTL[Part.sBTLInfo][DefaultGeneralParamList[i].sName] ~= nil then
GeneralParameters[DefaultGeneralParamList[i].sName] = GENERAL_PARAMETERS.BTL[Part.sBTLInfo][DefaultGeneralParamList[i].sName]
elseif GENERAL_PARAMETERS.PROJECT[DefaultGeneralParamList[i].sName] then
elseif GENERAL_PARAMETERS.PROJECT[DefaultGeneralParamList[i].sName] ~= nil then
GeneralParameters[DefaultGeneralParamList[i].sName] = GENERAL_PARAMETERS.PROJECT[DefaultGeneralParamList[i].sName]
end
end
@@ -593,18 +744,21 @@ function BeamLib.LoadGeneralParametersInList( DefaultGeneralParamList)
for i = 1, #DefaultGeneralParamList do
local sParamNameNGE = DefaultGeneralParamList[i].sNameNge
local xParameterValue = EgtGetInfo( idProjectInfo, sParamNameNGE, 's') or DefaultGeneralParamList[i].sValue
-- salvataggio dato su lista con accesso diretto
if DefaultGeneralParamList[i].sType == 'b' then
UpdatedParameters.PROJECT[DefaultGeneralParamList[i].sName] = xParameterValue == 'true' or xParameterValue == '1' or xParameterValue == true
elseif DefaultGeneralParamList[i].sType == 'd' then
if #DefaultGeneralParamList[i].sValue > 0 then
UpdatedParameters.PROJECT[DefaultGeneralParamList[i].sName] = tonumber( xParameterValue)
-- stringa vuota equivale a non passare alcun valore (deciderà la strategia)
else
UpdatedParameters.PROJECT[DefaultGeneralParamList[i].sName] = nil
-- se parametro non trovato si salta tutto. N.B. = I parametri progetto non dovrebbero mai essere nil
if xParameterValue then
-- salvataggio dato su lista con accesso diretto
if DefaultGeneralParamList[i].sType == 'b' then
UpdatedParameters.PROJECT[DefaultGeneralParamList[i].sName] = xParameterValue == 'true' or xParameterValue == '1' or xParameterValue == true
elseif DefaultGeneralParamList[i].sType == 'd' then
if #DefaultGeneralParamList[i].sValue > 0 then
UpdatedParameters.PROJECT[DefaultGeneralParamList[i].sName] = tonumber( xParameterValue)
-- stringa vuota equivale a non passare alcun valore (deciderà la strategia)
else
UpdatedParameters.PROJECT[DefaultGeneralParamList[i].sName] = nil
end
else --DefaultGeneralParamList[i].sType == 's' or DefaultGeneralParamList[i].sType == 'combo'
UpdatedParameters.PROJECT[DefaultGeneralParamList[i].sName] = xParameterValue
end
else --DefaultGeneralParamList[i].sType == 's' or DefaultGeneralParamList[i].sType == 'combo'
UpdatedParameters.PROJECT[DefaultGeneralParamList[i].sName] = xParameterValue
end
end
@@ -618,18 +772,21 @@ function BeamLib.LoadGeneralParametersInList( DefaultGeneralParamList)
for i = 1, #DefaultGeneralParamList do
local sParamNameNGE = DefaultGeneralParamList[i].sNameNge
local xParameterValue = EgtGetInfo( BTLInfo[j], sParamNameNGE, 's')
-- salvataggio dato su lista con accesso diretto
if DefaultGeneralParamList[i].sType == 'b' then
UpdatedParameters.BTL[BTLName][DefaultGeneralParamList[i].sName] = xParameterValue == 'true' or xParameterValue == '1' or xParameterValue == true
elseif DefaultGeneralParamList[i].sType == 'd' then
if #DefaultGeneralParamList[i].sValue > 0 then
UpdatedParameters.BTL[BTLName][DefaultGeneralParamList[i].sName] = tonumber( xParameterValue)
-- stringa vuota equivale a non passare alcun valore (deciderà la strategia)
else
UpdatedParameters.BTL[BTLName][DefaultGeneralParamList[i].sName] = nil
-- se parametro non trovato si salta tutto
if xParameterValue then
-- salvataggio dato su lista con accesso diretto
if DefaultGeneralParamList[i].sType == 'b' then
UpdatedParameters.BTL[BTLName][DefaultGeneralParamList[i].sName] = xParameterValue == 'true' or xParameterValue == '1' or xParameterValue == true
elseif DefaultGeneralParamList[i].sType == 'd' then
if #DefaultGeneralParamList[i].sValue > 0 then
UpdatedParameters.BTL[BTLName][DefaultGeneralParamList[i].sName] = tonumber( xParameterValue)
-- stringa vuota equivale a non passare alcun valore (deciderà la strategia)
else
UpdatedParameters.BTL[BTLName][DefaultGeneralParamList[i].sName] = nil
end
else --DefaultGeneralParamList[i].sType == 's' or DefaultGeneralParamList[i].sType == 'combo'
UpdatedParameters.BTL[BTLName][DefaultGeneralParamList[i].sName] = xParameterValue
end
else --DefaultGeneralParamList[i].sType == 's' or DefaultGeneralParamList[i].sType == 'combo'
UpdatedParameters.BTL[BTLName][DefaultGeneralParamList[i].sName] = xParameterValue
end
end
end
@@ -677,6 +834,11 @@ function BeamLib.GetBlockedAxis( nToolIndex, sBlockedAxis, b3Raw, vtTool, vtOut)
return ''
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.StringReplaceChar( sOriginal, nPosition, sChar)
return sOriginal:sub( 1, nPosition-1) .. sChar .. sOriginal:sub( nPosition+1)
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.BinaryToDecimal( dNumber)
local sNumberToConvert = tostring( dNumber)
@@ -727,6 +889,43 @@ function BeamLib.CalculateStringBinaryFormat( dNumber, CharNumber)
return NumberString
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.ConvertBitIndexToRotationIndex( sBitIndexCombination)
local nRotationIndex
if sBitIndexCombination == '1000' then
return 1
elseif sBitIndexCombination == '0100' then
return 2
elseif sBitIndexCombination == '0010' then
return 3
elseif sBitIndexCombination == '0001' then
return 4
elseif sBitIndexCombination == '1000_INV' then
return 5
elseif sBitIndexCombination == '0100_INV' then
return 6
elseif sBitIndexCombination == '0010_INV' then
return 7
elseif sBitIndexCombination == '0001_INV' then
return 8
end
return nRotationIndex
end
-------------------------------------------------------------------------------------------------------------
-- reindicizza una tabella passata ripartendo dall'indice nStartIndex e mantenendo l'ordine
function BeamLib.RotateTableFromIndex( Table, nStartIndex)
local RotatedTable = {}
for i = 1, #Table do
RotatedTable[#RotatedTable + 1] = Table[((RotatedTable + i - 2) % #Table) + 1]
end
return RotatedTable
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
@@ -852,7 +1051,7 @@ end
-------------------------------------------------------------------------------------------------------------
function BeamLib.GetStrategiesFromList( Proc, StrategyList)
-- cerco tra le feature
-- cerco tra le feature
for i = 1, #StrategyList.FEATURE do
-- se trovo la feature
if Proc.nPrc == StrategyList.FEATURE[i].nPrc then
@@ -870,16 +1069,25 @@ function BeamLib.GetStrategiesFromList( Proc, StrategyList)
-- si controlla gruppo
if bGroupIsCompatible then
if #StrategyList.FEATURE[i].TopologyList == 1 and StrategyList.FEATURE[i].TopologyList[1].sName == 'Feature' then
return BeamLib.TableCopyDeep( StrategyList.FEATURE[i].TopologyList[1].StrategyList)
else
-- cerco tra le topologie
for j = 1, #StrategyList.FEATURE[i].TopologyList do
-- se trovo la topologia
if Proc.Topology.sName == StrategyList.FEATURE[i].TopologyList[j].sName then
-- ritorno le strategie disponibili per la feature che sto analizzando
return BeamLib.TableCopyDeep( StrategyList.FEATURE[i].TopologyList[j].StrategyList)
-- cerco tra le topologie
for j = 1, #StrategyList.FEATURE[i].TopologyList do
-- non si possono mischiare topologie specifiche con topologia 'Feature'. Se presente topologia 'Feature' allora deve essere esclusiva
if StrategyList.FEATURE[i].TopologyList[j].sName == 'Feature' and #StrategyList.FEATURE[i].TopologyList > 1 then
error( "UNEXPECTED ERROR: topology 'Feature' can't be mixed with others")
end
-- se trovo la topologia oppure se è 'Feature'
if Proc.Topology.sName == StrategyList.FEATURE[i].TopologyList[j].sName or StrategyList.FEATURE[i].TopologyList[j].sName == 'Feature' then
local ActiveStrategyList = {}
-- aggiungo in lista solo le strategie attive
if StrategyList.FEATURE[i].TopologyList[j].StrategyList then
for k = 1, #StrategyList.FEATURE[i].TopologyList[j].StrategyList do
if ( not StrategyList.FEATURE[i].TopologyList[j].StrategyList[k].nIndexInList) or ( StrategyList.FEATURE[i].TopologyList[j].StrategyList[k].nIndexInList) >= 0 then
table.insert( ActiveStrategyList, BeamLib.TableCopyDeep( StrategyList.FEATURE[i].TopologyList[j].StrategyList[k]))
end
end
end
-- ritorno le strategie disponibili per la feature che sto analizzando, altrimenti nil se non ho trovato nulla
return EgtIf( #ActiveStrategyList > 0, ActiveStrategyList, nil)
end
end
end
+36 -41
View File
@@ -11,12 +11,12 @@ local BeamLib = require( 'BeamLib')
EgtOutLog( ' DiceCut started', 1)
-- Dati
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
----------------------------------------------------------------------------------------------------------------------------------------------------
-- creo i piani paralleli
-- GetParallelPlanes: restituisce un vettore con gli indici delle superfici
-- nAddGrpId: il layer
-- idAddGroup: il layer
-- b3BoxDicing: il grezzo della barra
-- ptC: il punto centrale del piano della feature
-- vtN: il versore normale del piano della feature
@@ -30,7 +30,7 @@ local BeamData = require( 'BeamData')
-- 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, b3BoxDicing, ptC, vtN, nCopyPlane, dOffset, nStep, Color, dTolerance, bNoTolOnFirstCut, ptCCut, vtNCut, ptCCut1, vtNCut1 )
local function GetParallelPlanes( idAddGroup, b3BoxDicing, ptC, vtN, nCopyPlane, dOffset, nStep, Color, dTolerance, bNoTolOnFirstCut, ptCCut, vtNCut, ptCCut1, vtNCut1 )
local ptMyCCut
local AreaMin = 5*5
if ptCCut and vtNCut then
@@ -46,7 +46,7 @@ local function GetParallelPlanes( nAddGrpId, b3BoxDicing, ptC, vtN, nCopyPlane,
local TabellaTmSurfParallel = {}
local i = nCopyPlane
while i < nStep do
local SurfId = EgtSurfTmPlaneInBBox( nAddGrpId, ptC + ( i * dOffset) * vtN, vtN, b3BoxDicing, GDB_RT.GLOB)
local SurfId = EgtSurfTmPlaneInBBox( idAddGroup, ptC + ( i * dOffset) * vtN, vtN, b3BoxDicing, 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
@@ -86,11 +86,11 @@ end
----------------------------------------------------------------------------------------------------------------------------------------------------
-- GetOrderedCutTable:
-- nAddGrpId: il layer
-- idAddGroup: 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 function GetOrderedCutTable( idAddGroup, TabParallelPlanes, TabOrtoPlanes)
local StepParallel = #TabParallelPlanes
local StepOrto = #TabOrtoPlanes
local TabellaOrderParallelCut1 = {}
@@ -99,8 +99,8 @@ local function GetOrderedCutTable( nAddGrpId, TabParallelPlanes, TabOrtoPlanes)
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)
local Copy1Id = EgtCopySurfTmFacet( TabParallelPlanes[IndexTmP], 0, idAddGroup)
local Copy2Id = EgtCopySurfTmFacet( TabParallelPlanes[IndexTmP], 0, idAddGroup)
if Copy1Id and ptOrtoN then
EgtCutSurfTmPlane( Copy1Id, ptOrtoN, -vtNOrtoN, false, GDB_RT.GLOB)
EgtCutSurfTmPlane( Copy2Id, ptOrtoN, vtNOrtoN, false, GDB_RT.GLOB)
@@ -134,7 +134,7 @@ end
-- 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, dMinNzDownUp)
local function GetOrtoCutCenter( FacetId, ptC, vtN, vtO, dOffsetEff)
local FrameLocal = Frame3d( EgtSurfTmFacetCenter( FacetId, 0, GDB_ID.ROOT))
EgtSetGridFrame(FrameLocal)
local IdAuxLocal = EgtGroup(EgtGetParent( FacetId), FrameLocal)
@@ -156,7 +156,7 @@ local function GetOrtoCutCenter( FacetId, ptC, vtN, vtO, dOffsetEff, dMinNzDownU
-- TODO si può eliminare questo test dato che vengono verificate già volume e dimensione del cubetto??
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() > dMinNzDownUp then
( dLen < dOffsetEff + 1.0 or dWidth < dOffsetEff + 1.0) then
return nil, nil, nil
end
@@ -261,7 +261,7 @@ end
-- dOffsetParallel: offset della distanza dal punto centrale
-- b3BoxDicing: 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, dOffsetParallel, b3BoxDicing, dMinNzDownUp)
local function VerifyFirstOrthoCut( CutTable, dOffsetParallel, b3BoxDicing)
if not CutTable[1] or not CutTable[2] then return end
@@ -294,9 +294,9 @@ local function VerifyFirstOrthoCut( CutTable, dOffsetParallel, b3BoxDicing, dMin
-- 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 <= dOffsetParallel + 1.0 and vtN1:getZ() > dMinNzDownUp then
local nAddGrpId = EgtGetParent( Cut1Id)
local SurfId = EgtSurfTmBySewing( nAddGrpId, { Cut1Id, Cut2Id})
if dLongSize <= dOffsetParallel + 1.0 then
local idAddGroup = EgtGetParent( Cut1Id)
local SurfId = EgtSurfTmBySewing( idAddGroup, { Cut1Id, Cut2Id})
--EgtSetColor( SurfId, Color3d( FUCHSIA(), 60))
EgtErase( CutOId)
table.remove( CutTable[1], 1)
@@ -338,7 +338,7 @@ 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, b3BoxDicing, TPoint)
local function DistanzaMassima( idAddGroup, ptC1, vtN1, ptC2, vtN2, b3BoxDicing, 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
@@ -353,7 +353,7 @@ local function DistanzaMassima( nAddGrpId, ptC1, vtN1, ptC2, vtN2, b3BoxDicing,
end
-- eventuale altra faccia
if ptC2 and vtN2 then
local IdAux = EgtGroup( nAddGrpId)
local IdAux = EgtGroup( idAddGroup)
local IdSurf2 = EgtSurfTmPlaneInBBox( IdAux, ptC2, vtN2, b3BoxDicing, GDB_RT.GLOB)
EgtCutSurfTmPlane( IdSurf2, ptC1, -vtN1, false, GDB_RT.GLOB)
if IdSurf2 then
@@ -394,7 +394,12 @@ end
---------------------------------------------------------------------------------------------------------------
function DiceCut.GetDice( Part, Face1, Face2, OptionalParameters)
-- gruppo per geometria addizionale
local nAddGrpId = BeamLib.GetAddGroup( Part.id)
local idAddGroup
if OptionalParameters.bSaveAddedGeometries then
idAddGroup = BeamLib.GetAddGroup( Part.id)
else
idAddGroup = Part.idTempGroup
end
-- faccia primaria
local ptCMainFace
@@ -422,16 +427,12 @@ function DiceCut.GetDice( Part, Face1, Face2, OptionalParameters)
local dOffsetParallel = OptionalParameters.dOffsetParallel or BeamData.MAX_DIM_DICE
-- distanza tra piani ortogonali
local dOffsetOrthogonal = OptionalParameters.dOffsetOrthogonal or BeamData.MAX_DIM_DICE
-- distanza ridotta tra piani ortogonali - usato in tagli orizzontali con affondamento verticale
local dOffsetOrthogonalReduced = OptionalParameters.dOffsetOrthogonalReduced or BeamData.MAX_DIM_HTCUT
-- numero massimo piani paralleli
local nStepParallel = OptionalParameters.nStepParallel or 100
-- numero massimo piani perpendicolari
local nStepOrthogonal = OptionalParameters.nStepOrthogonal or 100
-- distanza tra piani paralleli e piani di taglio (era sempre 0, serve???)
local dTolerance = OptionalParameters.dTolerance or 0
-- inclinazione limite per taglio da sotto
local dMinNzDownUp = OptionalParameters.dMinNzDownUp or -2
--Ricavo le altezze dei BoundingBox contenente feature e estremi del grezzo
local TBoxPoint = CalcolaPuntiEstremiBox( b3BoxDicing)
@@ -439,18 +440,12 @@ function DiceCut.GetDice( Part, Face1, Face2, OptionalParameters)
if ptCSubordinateFace and vtNSubordinateFace then
TBoxPoint = VerificaEstremiGrezzo( ptCSubordinateFace, vtNSubordinateFace, TBoxPoint)
end
local dElevP = DistanzaMassima( nAddGrpId, ptCMainFace, vtNMainFace, ptCSubordinateFace, vtNSubordinateFace, b3BoxDicing, TBoxPoint)
local dElevP = DistanzaMassima( idAddGroup, ptCMainFace, vtNMainFace, ptCSubordinateFace, vtNSubordinateFace, b3BoxDicing, TBoxPoint)
local dElevO
if ptCSubordinateFace and vtNSubordinateFace and not AreOppositeVectorApprox( vtNSubordinateFace, vtNMainFace) then
dElevO = DistanzaMassima( nAddGrpId, ptCSubordinateFace, vtNSubordinateFace, ptCMainFace, vtNMainFace, b3BoxDicing, TBoxPoint)
dElevO = DistanzaMassima( idAddGroup, ptCSubordinateFace, vtNSubordinateFace, ptCMainFace, vtNMainFace, b3BoxDicing, TBoxPoint)
end
-- TODO parte sotto da aggiungere???? se sì va passata anche la dimensione cubetto ridotta dOffsetOrthogonalReduced
-- 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 BD.TURN and not BD.DOWN_HEAD and abs( vtNPlanes:getY()) < 0.1 and vtNPlanes:getZ() < 0.7071 and ( not vtNBond or abs( vtNBond:getY()) < 0.1) and BBoxRawPart:getDimZ() < BD.MIN_DIM_HBEAM then
-- dOffsetOrthogonal = dOffsetOrthogonalReduced
-- end
-- aggiungo piccolo extra agli offset
dOffsetParallel = dOffsetParallel + 10 * GEO.EPS_SMALL
dOffsetOrthogonal = dOffsetOrthogonal + 10 * GEO.EPS_SMALL
@@ -458,7 +453,7 @@ function DiceCut.GetDice( Part, Face1, Face2, OptionalParameters)
-- se piani non ortogonali, diminuisco la distanza di offset opportunamente
local dOffsetParallelOriginal = dOffsetParallel
if not bGetOrtoPlanes then
local dCoeff = ( vtNMainFace ^ vtNSubordinateFace):len()
local dCoeff = max( ( vtNMainFace ^ vtNSubordinateFace):len(), 0.5)
dOffsetParallel = dOffsetParallel * dCoeff
dOffsetOrthogonal = dOffsetOrthogonal * dCoeff
end
@@ -476,7 +471,7 @@ function DiceCut.GetDice( Part, Face1, Face2, OptionalParameters)
-- PIANI PARALLELI alla faccia di taglio
local TabellaTmSurfP = {}
local TabFromIn = GetParallelPlanes( nAddGrpId, b3BoxDicing, ptCMainFace, vtNMainFace, 0, dOffsetParallel, nStepParallel, Color3d( FUCHSIA(), 60), dTolerance, true, ptCSubordinateFace, vtNSubordinateFace)
local TabFromIn = GetParallelPlanes( idAddGroup, b3BoxDicing, ptCMainFace, vtNMainFace, 0, dOffsetParallel, nStepParallel, Color3d( FUCHSIA(), 60), dTolerance, true, ptCSubordinateFace, vtNSubordinateFace)
for i = #TabFromIn, 1, -1 do
table.insert( TabellaTmSurfP, TabFromIn[i])
end
@@ -485,12 +480,12 @@ function DiceCut.GetDice( Part, Face1, Face2, OptionalParameters)
-- orientamento definito da seconda faccia
if not bGetOrtoPlanes then
local TabellaTmSurfOrto = {}
local TabFromIn = GetParallelPlanes( nAddGrpId, b3BoxDicing, ptCSubordinateFace, vtNSubordinateFace, 0, dOffsetOrthogonal, nStepOrthogonal, Color3d( GREEN(), 60), dTolerance, false, ptCMainFace, vtNMainFace)
local TabFromIn = GetParallelPlanes( idAddGroup, b3BoxDicing, ptCSubordinateFace, vtNSubordinateFace, 0, dOffsetOrthogonal, nStepOrthogonal, 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
local TabellaOrderParallelCut = GetOrderedCutTable( idAddGroup, TabellaTmSurfP, TabellaTmSurfOrto) -- Ottiene la tabella dei tagli paralleli ordinati
local TabellaOrderOrtoCut = GetOrderedCutTable( idAddGroup, 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
@@ -508,10 +503,10 @@ function DiceCut.GetDice( Part, Face1, Face2, OptionalParameters)
end
-- calcolo la direzione dei piani ortogonali
local vtO = VectorFromUprightOrtho( vtNInner)
if vtNInner:getZ() > -0.0175 or vtNInner:getZ() < dMinNzDownUp or abs( vtNInner:getY()) > 0.8 then
if vtNInner:getZ() > -0.0175 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 b3BoxDicing:getDimZ() > 620) and vtNInner:getZ() > dMinNzDownUp then
if ( abs( vtO:getY()) > 4 * abs( vtO:getX()) or b3BoxDicing:getDimZ() > 620) 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
@@ -533,16 +528,16 @@ function DiceCut.GetDice( Part, Face1, Face2, OptionalParameters)
-- 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, dOffsetOrthogonal, dMinNzDownUp)
local OffsetRel, CopyPlane, dCenOffs, ptCStart = GetOrtoCutCenter( TabellaTmSurfP[PlnInd], ptCInner, vtNInner, vtO, dOffsetOrthogonal)
if OffsetRel and CopyPlane and dCenOffs then
ptCInner = ptCInner + dCenOffs * vtO
local TabRight = GetParallelPlanes( nAddGrpId, b3BoxDicing, ptCStart, vtO, CopyPlane, -OffsetRel, nStepOrthogonal, Color3d( GREEN(), 60),
local TabRight = GetParallelPlanes( idAddGroup, b3BoxDicing, ptCStart, vtO, CopyPlane, -OffsetRel, nStepOrthogonal, Color3d( GREEN(), 60),
dTolerance, false, ptCInner, vtNInner, ptCOuter, vtNOuter)
if CopyPlane == 0 then
CopyPlane = 1
end
local TabLeft = GetParallelPlanes( nAddGrpId, b3BoxDicing, ptCStart, vtO, CopyPlane, OffsetRel, nStepOrthogonal, Color3d( GREEN(), 60),
local TabLeft = GetParallelPlanes( idAddGroup, b3BoxDicing, ptCStart, vtO, CopyPlane, OffsetRel, nStepOrthogonal, Color3d( GREEN(), 60),
dTolerance, false, ptCInner, vtNInner, ptCOuter, vtNOuter)
-- carico la tabella con gli indici riordinati
local TempOrtoTab = {}
@@ -553,7 +548,7 @@ function DiceCut.GetDice( Part, Face1, Face2, OptionalParameters)
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)
local TempParTab = GetOrderedCutTable( idAddGroup, {TabellaTmSurfP[PlnInd]}, TempOrtoTab)
for i = 1, #TempParTab do
table.insert( TabFUCHSIA, TempParTab[i])
end
@@ -582,7 +577,7 @@ function DiceCut.GetDice( Part, Face1, Face2, OptionalParameters)
-- Se esiste la superficie limitante (nFacet == 2) verifica se il taglio più esterno è superfluo e quindi viene eliminato
if not bGetOrtoPlanes then
VerifyFirstOrthoCut( UltimateTable, dOffsetParallelOriginal, b3BoxDicing, dMinNzDownUp)
VerifyFirstOrthoCut( UltimateTable, dOffsetParallelOriginal, b3BoxDicing)
-- 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])
+97 -48
View File
@@ -91,7 +91,9 @@ function FaceData.GetFacesByAdjacencyNumber( Proc)
FacesByAdjacencyNumber[i] = {}
end
for i = 1, Proc.nFct do
table.insert( FacesByAdjacencyNumber[#Proc.Faces[i].Adjacencies], Proc.Faces[i])
if #Proc.Faces[i].Adjacencies > 0 then
table.insert( FacesByAdjacencyNumber[#Proc.Faces[i].Adjacencies], Proc.Faces[i])
end
end
return FacesByAdjacencyNumber
@@ -136,9 +138,19 @@ function FaceData.GetEdgesInfo( ProcOrId, idFace )
end
CurrentEdge.bIsStartOpen = EdgesEgt[nPreviousEdgeIndex].Open
CurrentEdge.bIsEndOpen = EdgesEgt[nNextEdgeIndex].Open
CurrentEdge.ptStart = Point3d( EdgesEgt[i].Start)
CurrentEdge.ptEnd = Point3d( EdgesEgt[nNextEdgeIndex].Start)
CurrentEdge.vtEdge = CurrentEdge.ptEnd - CurrentEdge.ptStart ; CurrentEdge.vtEdge:normalize()
CurrentEdge.sType = 'Standard'
CurrentEdge.id = i - 1
-- se nella Proc ci sono le adiacenze e il lato ha adiacenza, si salva l'angolo con la faccia adiacente
if Proc.AdjacencyMatrix then
if CurrentEdge.idAdjacentFace > -1 then
CurrentEdge.dAdjacencyAngle = Proc.AdjacencyMatrix[idFace + 1][CurrentEdge.idAdjacentFace + 1]
end
end
table.insert( Edges, CurrentEdge)
end
@@ -147,7 +159,6 @@ end
-------------------------------------------------------------------------------------------------------------
function FaceData.GetFacesInfo( Proc, Part, FacesToGet)
EgtOutLog( '---Faces START---')
local Faces = {}
local function FaceIsToGet( nIndex)
@@ -175,10 +186,11 @@ function FaceData.GetFacesInfo( Proc, Part, FacesToGet)
for i = 1, Proc.nFct do
Faces[i] = {}
Faces[i].id = i - 1
Faces[i].idTrimesh = Proc.id
Faces[i].ptCenter, Faces[i].vtN = EgtSurfTmFacetCenter( Proc.id, i - 1, GDB_ID.ROOT)
if Proc.nFct < 6 or FaceIsToGet( i) then
if Proc.nFct < 7 or FaceIsToGet( i) then
-- frame OCS faccia
Faces[i].vtFrameHV = Frame3d( Faces[i].ptCenter, Faces[i].vtN)
Faces[i].frFrameHV = Frame3d( Faces[i].ptCenter, Faces[i].vtN)
-- elevazione calcolata rispetto al box della parte
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
@@ -186,78 +198,86 @@ function FaceData.GetFacesInfo( Proc, Part, FacesToGet)
Faces[i].dArea = dShortDimension * dLongDimension
Faces[i].dLMinRectangle = dLongDimension
Faces[i].dWMinRectangle = dShortDimension
-- volume approssimato di materiale asportato lavorando questa faccia
Faces[i].dMachinedVolumeApprox = Faces[i].dArea * Faces[i].dElevation
local nFaceType, Edges = FaceData.GetEdgesInfo( Proc, i - 1)
Faces[i].bIsOkForMachining = nFaceType < 1
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)
EgtOutLog( ' vtN: ' .. tostring( Faces[i].vtN))
-- adiacenze della faccia
-- TODO chiamarle in modo che si capisca che sono solo gli id e non l'intero oggetto faccia
Faces[i].Adjacencies = {}
for j = 1, Proc.nFct do
if vAdj[i][j] and vAdj[i][j] ~= 0 and ( i ~= j) then
table.insert( Faces[i].Adjacencies, j - 1)
if EgtGetDebugLevel() >= 3 then
EgtOutLog( ' Adjacent to facet: ' .. j - 1)
end
end
end
end
end
EgtOutLog( '---Faces END---')
return Faces
end
-------------------------------------------------------------------------------------------------------------
function FaceData.IsFaceRectangular( Proc, idFace)
local nAddGrpId = BeamLib.GetAddGroup( Proc.idPart)
local nContourId, nContourCnt = EgtExtractSurfTmFacetLoops( Proc.id, idFace, nAddGrpId)
function FaceData.IsFaceRectangle( Face)
-- recupero gruppo per geometrie temporanee
local idTempGroup = BeamLib.GetTempGroup()
local nContourId, nContourCnt = EgtExtractSurfTmFacetLoops( Face.idTrimesh, Face.id, idTempGroup)
if nContourCnt > 1 then
error( 'IsFaceRectangular : too many loops')
error( 'IsFaceRectangle : too many loops')
end
local bIsRectangular = EgtCurveIsARectangle( nContourId)
-- elimino curve create
for i = 1, nContourCnt do
EgtErase( nContourId + i - 1)
end
return bIsRectangular
end
-------------------------------------------------------------------------------------------------------------
function FaceData.IsFaceRhomboid( Proc, idFace)
local nAddGrpId = BeamLib.GetAddGroup( Proc.idPart)
local nContourId, nContourCnt = EgtExtractSurfTmFacetLoops( Proc.id, idFace, nAddGrpId)
function FaceData.IsFaceParallelogram( Face)
-- recupero gruppo per geometrie temporanee
local idTempGroup = BeamLib.GetTempGroup()
local nContourId, nContourCnt = EgtExtractSurfTmFacetLoops( Face.idTrimesh, Face.id, idTempGroup)
if nContourCnt > 1 then
error( 'IsFaceRectangular : too many loops')
error( 'IsFaceParallelogram : too many loops')
end
local bIsTrapezoid = EgtCurveIsATrapezoid( nContourId)
local bIsRhomboid = false
-- un parallelogramma è un trapezoide con i lati paralleli a due a due
if bIsTrapezoid
and AreOppositeVectorApprox( Proc.Faces[idFace + 1].Edges[1].vtN, Proc.Faces[idFace + 1].Edges[3].vtN)
and AreOppositeVectorApprox( Proc.Faces[idFace + 1].Edges[2].vtN, Proc.Faces[idFace + 1].Edges[4].vtN) then
and AreOppositeVectorApprox( Face.Edges[1].vtN, Face.Edges[3].vtN)
and AreOppositeVectorApprox( Face.Edges[2].vtN, Face.Edges[4].vtN) then
bIsRhomboid = true
end
-- elimino curve create
for i = 1, nContourCnt do
EgtErase( nContourId + i - 1)
end
return bIsRhomboid
end
-------------------------------------------------------------------------------------------------------------
local function CompareBottomFaces( FaceA, FaceB)
local dMaxVolumeRelativeChange = 0.15
-- si prende la faccia con volume lavorato maggiore
if FaceA.dMachinedVolumeApprox > ( 1 + dMaxVolumeRelativeChange) * FaceB.dMachinedVolumeApprox + 10 * GEO.EPS_SMALL then
return true
elseif FaceB.dMachinedVolumeApprox > ( 1 + dMaxVolumeRelativeChange) * FaceA.dMachinedVolumeApprox + 10 * GEO.EPS_SMALL then
return false
-- se volume lavorato simile, si prende la faccia con minore elevazione
else
if FaceA.dElevation < FaceB.dElevation - 10 * GEO.EPS_SMALL then
return true
elseif FaceB.dElevation < FaceA.dElevation - 10 * GEO.EPS_SMALL then
return false
else
return false
end
end
end
-------------------------------------------------------------------------------------------------------------
local function CompareEdgesBottomFace( EdgeA, EdgeB)
-- prima i lati con facce adiacenti
@@ -365,10 +385,28 @@ local function GetBottomFaces( Proc)
return { Proc.Faces[1]}
end
-- la faccia di fondo ha sempre Fct - 1 adiacenze
-- la faccia di fondo ha sempre Fct - 1 adiacenze, tranne caso speciale DoubleBevel con facce di chiusura triangolari
local FacesByAdjacencyNumber = FaceData.GetFacesByAdjacencyNumber( Proc)
if FacesByAdjacencyNumber then
BottomFaces = FacesByAdjacencyNumber[ Proc.nFct - 1]
-- caso speciale DoubleBevel
if #BottomFaces == 0 then
if Proc.nParts == 1 then
BottomFaces = FacesByAdjacencyNumber[ Proc.nFct / 2]
-- DoubleBevel composto da più parti
else
for i = #FacesByAdjacencyNumber, 1, -1 do
if #FacesByAdjacencyNumber[i] > 0 then
BottomFaces = FacesByAdjacencyNumber[i]
break
end
end
-- se non sono state trovate facce di fondo significa che nessuna faccia ha adiacenze -> DoubleBevel-2
if #BottomFaces == 0 then
BottomFaces = Proc.Faces
end
end
end
-- si rimuovono le facce non adatte ad essere lavorate
local nBottomFaces = #BottomFaces
local nCurrentFace = 1
@@ -379,8 +417,8 @@ local function GetBottomFaces( Proc)
end
nCurrentFace = nCurrentFace + 1
end
-- la BottomFace 1 è sempre quella con minor elevazione
table.sort( BottomFaces, function (a, b) return a.dElevation < b.dElevation end)
-- la BottomFace 1 è quella che permette di asportare il volume maggiore; nei casi ambigui si sceglie quella a minor elevazione
table.sort( BottomFaces, CompareBottomFaces)
end
if #BottomFaces == 0 then
@@ -429,6 +467,10 @@ local function GetBottomFaces( Proc)
CurrentEdge.dElevation = BottomFaces[1].Edges[i].dElevation
CurrentEdge.bIsStartOpen = BottomFaces[1].Edges[i].bIsStartOpen
CurrentEdge.bIsEndOpen = BottomFaces[1].Edges[i].bIsEndOpen
CurrentEdge.ptStart = BottomFaces[1].Edges[i].ptStart
CurrentEdge.ptEnd = BottomFaces[1].Edges[i].ptEnd
CurrentEdge.vtEdge = BottomFaces[1].Edges[i].vtEdge
CurrentEdge.id = BottomFaces[1].Edges[i].id
if nFirstLongEdgeIndex then
if i == nFirstLongEdgeIndex then
@@ -454,7 +496,7 @@ end
local function GetLongFaces( Proc, MainFaces)
local LongFaces = {}
if Proc.nFct > 5 then
if Proc.nFct > 6 then
error( 'GetLongFaces : Topology not implemented')
elseif Proc.nFct == 1 then
return {}
@@ -524,6 +566,10 @@ local function GetLongFaces( Proc, MainFaces)
CurrentEdge.dElevation = LongFaces[i].Edges[j].dElevation
CurrentEdge.bIsStartOpen = LongFaces[i].Edges[j].bIsStartOpen
CurrentEdge.bIsEndOpen = LongFaces[i].Edges[j].bIsEndOpen
CurrentEdge.ptStart = LongFaces[i].Edges[j].ptStart
CurrentEdge.ptEnd = LongFaces[i].Edges[j].ptEnd
CurrentEdge.vtEdge = LongFaces[i].Edges[j].vtEdge
CurrentEdge.id = LongFaces[i].Edges[j].id
if Proc.Topology.sFamily == 'Tunnel' then
if CurrentEdge.idAdjacentFace > -1 then
@@ -558,7 +604,7 @@ end
local function GetSideFaces( Proc, MainFaces)
local SideFaces = {}
if Proc.nFct > 5 then
if Proc.nFct > 6 then
error( 'GetSideFaces : Topology not implemented')
elseif Proc.nFct == 1 then
return {}
@@ -620,6 +666,10 @@ local function GetSideFaces( Proc, MainFaces)
CurrentEdge.dElevation = SideFaces[i].Edges[j].dElevation
CurrentEdge.bIsStartOpen = SideFaces[i].Edges[j].bIsStartOpen
CurrentEdge.bIsEndOpen = SideFaces[i].Edges[j].bIsEndOpen
CurrentEdge.ptStart = SideFaces[i].Edges[j].ptStart
CurrentEdge.ptEnd = SideFaces[i].Edges[j].ptEnd
CurrentEdge.vtEdge = SideFaces[i].Edges[j].vtEdge
CurrentEdge.id = SideFaces[i].Edges[j].id
if Proc.Topology.sFamily == 'Tunnel' then
if CurrentEdge.idAdjacentFace > -1 then
@@ -653,7 +703,6 @@ end
-- TODO test iniziale replicato in GetTunnelFaces
function FaceData.GetMainFaces( Proc, Part)
EgtOutLog( '---MainFaces START---')
local MainFaces = {}
-- CASO 1 : Feature tipo LapJoint
@@ -661,26 +710,26 @@ function FaceData.GetMainFaces( Proc, Part)
Proc.Topology.sFamily == 'Pocket' or Proc.Topology.sFamily == 'Tunnel' or Proc.Topology.sFamily == 'Bevel' or
Proc.Topology.sFamily == 'DoubleBevel' or Proc.Topology.sFamily == 'Cut' or Proc.Topology.sFamily == 'HeadCut' or Proc.Topology.sFamily == 'TailCut' then
if ( Proc.Topology.bIsThrough and Proc.Topology.bAllRightAngles and Proc.nFct < 5)
or ( Proc.nFct == 1) or Proc.Topology.sName == 'Bevel-2-Blind' then
if Proc.nParts == 1 and ( ( Proc.Topology.bIsThrough and Proc.Topology.bAllRightAngles and Proc.nFct < 5)
or ( Proc.nFct == 1) or Proc.Topology.sName == 'Bevel-2-Blind') then
MainFaces.TunnelAddedFaces = GetTunnelFaces( Proc, Part)
end
MainFaces.BottomFaces = GetBottomFaces( Proc)
MainFaces.LongFaces = GetLongFaces( Proc, MainFaces)
MainFaces.SideFaces = GetSideFaces( Proc, MainFaces)
-- scrivo informazioni delle facce nel log
if EgtGetDebugLevel() >= 3 then
Logs.WriteMainFacesLog( Proc, MainFaces)
if Proc.nParts == 1 then
MainFaces.LongFaces = GetLongFaces( Proc, MainFaces)
MainFaces.SideFaces = GetSideFaces( Proc, MainFaces)
-- caso tipo DoubleBevel con facce separate
else
MainFaces.LongFaces = {}
MainFaces.SideFaces = {}
end
else
MainFaces = nil
EgtOutLog( '---MainFaces NOT NEEDED---')
end
EgtOutLog( '---MainFaces END---')
return MainFaces
end
+37 -37
View File
@@ -6,7 +6,7 @@
local FeatureLib = {}
-- Carico i dati globali
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
-- carico librerie
local BeamLib = require( 'BeamLib')
@@ -32,6 +32,10 @@ function FeatureLib.GetProcFromTrimesh( idTrimesh, Part, ProcToCopyFrom)
Proc.AffectedFaces = BeamLib.GetAffectedFaces( Proc, Part)
Proc.AdjacencyMatrix = FaceData.GetAdjacencyMatrix( Proc)
Proc.Faces = FaceData.GetFacesInfo( Proc, Part)
Proc.dVolume = FeatureLib.GetFeatureVolume( Proc, Part)
if ProcToCopyFrom and Proc.dVolume < 10 * GEO.EPS_SMALL then
Proc.dVolume = ProcToCopyFrom.dVolume
end
-- TODO servono anche altri dati raccolti nel collect??
return Proc
@@ -39,7 +43,7 @@ end
-------------------------------------------------------------------------------------------------------------
-- restituisce vero se la feature con box b3Proc taglia l'intera sezione della barra
local function IsFeatureCuttingEntireSection( b3Proc, Part)
function FeatureLib.IsFeatureCuttingEntireSection( b3Proc, Part)
return ( b3Proc:getDimY() > ( Part.b3Part:getDimY() - 500 * GEO.EPS_SMALL) and b3Proc:getDimZ() > ( Part.b3Part:getDimZ() - 500 * GEO.EPS_SMALL))
end
@@ -54,7 +58,7 @@ end
-- restituisce vero se tutti i lati della faccia passata si trovano sul grezzo
local function AreAllFaceEdgesOnRaw( Part, Proc, idFace)
local bEdgeOnRaw = true
local idTempGroup = BeamLib.GetTempGroup()
local idTempGroup = Part.idTempGroup
local nLoopId, nLoopCnt = EgtExtractSurfTmFacetLoops( Proc.id, idFace, idTempGroup)
if nLoopCnt > 1 then
error( 'AreAllFaceEdgesOnRaw : too many loops')
@@ -194,7 +198,7 @@ function FeatureLib.ClassifyTopology( Proc, Part)
if not Proc.AffectedFaces then Proc.AffectedFaces = BeamLib.GetAffectedFaces( Proc, Part) end
local bIsFeatureCuttingEntireSection = IsFeatureCuttingEntireSection( Proc.b3Box, Part)
local bIsFeatureCuttingEntireSection = FeatureLib.IsFeatureCuttingEntireSection( Proc.b3Box, Part)
local bIsFeatureCuttingEntireLength = IsFeatureCuttingEntireLength( Proc.b3Box, Part)
local bIsAnyDimensionLongAsPart = IsAnyDimensionLongAsPart( Proc, Part)
local vAdj = Proc.AdjacencyMatrix
@@ -222,13 +226,13 @@ function FeatureLib.ClassifyTopology( Proc, Part)
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
elseif Proc.nFct == 2 and bAllAnglesConcave and Proc.nParts == 1 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
elseif Proc.nFct == 2 and bAllAnglesConcave and Proc.nParts == 1 then
sFamily = 'VGroove'
bIsThrough = true
elseif Proc.nFct == 2 and not bAllAnglesConcave and bIsAnyDimensionLongAsPart then
elseif Proc.nFct == 2 and ( not bAllAnglesConcave or Proc.nParts == 2) and bIsAnyDimensionLongAsPart then
sFamily = 'DoubleBevel'
bIsThrough = true
elseif Proc.nFct == 3 and bAllAnglesConcave and #vFacesByAdjNumber[2] == 1 and #vTriangularFaces == 2 then
@@ -240,7 +244,9 @@ function FeatureLib.ClassifyTopology( Proc, Part)
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
elseif Proc.nFct == 4
and ( ( not bAllAnglesConcave and ( ( #vFacesByAdjNumber[2] == 2 and #vTriangularFaces == 2) or ( #vFacesByAdjNumber[3] == 2)))
or ( #vTriangularFaces == 2 and Proc.nParts == 2)) then
sFamily = 'DoubleBevel'
bIsThrough = false
elseif Proc.nFct == 4 and bAllAnglesConcave and #vFacesByAdjNumber[3] == 2 then
@@ -255,7 +261,9 @@ function FeatureLib.ClassifyTopology( Proc, Part)
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
elseif Proc.nFct == 6
and ( ( #vFacesByAdjNumber[1] == 4 and #vFacesByAdjNumber[3] == 2 and #vTriangularFaces == 4 and not bAllAnglesConcave)
or ( #vFacesByAdjNumber[1] == 4 and #vTriangularFaces == 4 and Proc.nParts == 2)) then
sFamily = 'DoubleBevel'
bIsThrough = false
end
@@ -323,12 +331,15 @@ function FeatureLib.GetAdditionalInfo( Proc, Part)
elseif ID.IsRidgeLap( Proc) then
Proc.AdjacencyMatrix = FaceData.GetAdjacencyMatrix( Proc)
Proc.Faces = FaceData.GetFacesInfo( Proc, Part)
elseif ID.IsMarking( Proc) then
elseif ID.IsMarking( Proc) or ID.IsText( Proc) then
Proc.FeatureInfo = FeatureLib.GetMarkTextData( Proc)
elseif ID.IsHipValleyRafterNotch( Proc) then
Proc.AdjacencyMatrix = FaceData.GetAdjacencyMatrix( Proc)
Proc.Faces = FaceData.GetFacesInfo( Proc, Part)
Proc.FeatureInfo, Proc.MainFaces = FeatureLib.GetRafterNotchData( Proc)
elseif ( ID.IsScarfJoint( Proc) or ID.IsScarfSimple( Proc)) then
Proc.AdjacencyMatrix = FaceData.GetAdjacencyMatrix( Proc)
Proc.Faces = FaceData.GetFacesInfo( Proc, Part)
end
return Proc
@@ -495,6 +506,7 @@ function FeatureLib.GetDTMortiseData( Proc)
-- distanza massima all'imbocco ortogonale all'asse
local vtDiff = EgtEP( idAux, GDB_RT.GLOB) - EgtSP( idAux, GDB_RT.GLOB)
local vtOrtDiff = vtDiff - vtDiff * vtAx * vtAx
local dMortiseMaxDist = min( vtOrtDiff:len(), dMortiseWidth)
@@ -505,6 +517,9 @@ function FeatureLib.GetDTMortiseData( Proc)
FeatureExtraInfo.dMortiseDepth = dMortiseDepth
FeatureExtraInfo.dMortiseMinRadius = dMortiseMinRadius
FeatureExtraInfo.vtMortiseN = vtMortiseN
vtDiff:normalize()
FeatureExtraInfo.vtMortisePathStart = EgtSV( idAux, GDB_RT.GLOB) * vtDiff
FeatureExtraInfo.vtMortisePathEnd = EgtEV( idAux, GDB_RT.GLOB) * vtDiff
FeatureExtraInfo.idAddAuxGeom = idAux
return FeatureExtraInfo
@@ -901,23 +916,16 @@ end
function FeatureLib.GetFeatureVolume( Proc, Part)
local dProcVolume = 0
local idAddGroup = BeamLib.GetAddGroup( Part.id)
if not idAddGroup 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 idTempGroup = Part.idTempGroup
local idProcCopy = EgtCopyGlob( Proc.id, idAddGroup) or GDB_ID.NULL
local idProcCopy = EgtCopyGlob( Proc.id, idTempGroup) or GDB_ID.NULL
local b3PartCopy = BBox3d( Part.b3Part)
b3PartCopy:expand( -100 * GEO.EPS_SMALL)
local idPartCopy = EgtSurfTmBBox( idAddGroup, b3PartCopy , false, GDB_RT.GLOB)
local idPartCopy = EgtSurfTmBBox( idTempGroup, b3PartCopy , false, GDB_RT.GLOB)
EgtSurfTmSubtract( idPartCopy, idProcCopy)
dProcVolume = EgtSurfVolume( idPartCopy)
EgtErase( { idProcCopy, idPartCopy})
return dProcVolume
end
@@ -925,8 +933,9 @@ end
-- funzione che verifica se la feature, lavorata in questa fase, compromette lettura misura laser
function FeatureLib.CalculateFeatureHindersLaserMeasure( Proc, Part)
local bFeatureHindersLaserMeasure = false
-- se la feature è aperta frontalmente, posteriormente e di testa, allora potrebbe impattare sulla misura laser, controllo caso per caso
if Proc.AffectedFaces.bRight and Proc.AffectedFaces.bFront and Proc.AffectedFaces.bBack then
-- se la feature è aperta frontalmente, posteriormente, di testa e più bassa di 40mm, allora potrebbe impattare sulla misura laser, controllo caso per caso
if Proc.AffectedFaces.bRight and Proc.AffectedFaces.bFront and Proc.AffectedFaces.bBack and
( Proc.b3Box:getMin():getZ() - Part.b3Raw:getMin():getZ()) < 40 then
bFeatureHindersLaserMeasure = true
end
return bFeatureHindersLaserMeasure
@@ -940,6 +949,7 @@ function FeatureLib.CalculateFeatureNotClampableLengths( Proc, Part)
local dNotClampableLengthTail = 0
-- se il grezzo non è definito, prendo il box del pezzo
-- TODO 1- si sta passando b3part per riferimento, 2- non dovrebbe essre sempre definito?
if not Part.b3Raw then
Part.b3Raw = Part.b3Part
end
@@ -961,13 +971,13 @@ function FeatureLib.CalculateFeatureNotClampableLengths( Proc, Part)
-- 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
-- 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
-- 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
@@ -979,24 +989,14 @@ function FeatureLib.CalculateFeatureNotClampableLengths( Proc, Part)
dOffs = min( dOffs, BeamData.VICE_MAXH - BeamData.VICE_MINH)
end
dNotClampableLengthHead = dOffs
elseif Proc.AffectedFaces.bLeft then
end
if 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
-- TODO il controllo sul punto centrale non è corretto, deve essere rivisto.
-- Si lascia qui commentato perchè era così anche in quello vecchio, quindi potrebbe essere che in qualche caso potesse funzionare
-- 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
end
+247
View File
@@ -0,0 +1,247 @@
-- LeadInOutLib.lua by Egalware s.r.l. 2025/11/24
-- Libreria stima collisioni per travi
-- Tabella per definizione modulo
local LeadInOutLib = {}
-- Include
require( 'EgtBase')
local BeamData = require( 'BeamDataNew')
local FaceData = require( 'FaceData')
local BeamLib = require( 'BeamLib')
EgtOutLog( ' LeadInOutLib started', 1)
-------------------------------------------------------------------------------------------------------------
local function GetExtraAddLengthInclinedSides( Face, Edge)
-- se faccia rettangolare i lati sono tutti a 90deg, inutile fare conti
if FaceData.IsFaceRectangle( Face) then
return 0, 0
end
local nPreviousEdgeIndex = Edge.id + 1 - 1
if nPreviousEdgeIndex < 1 then
nPreviousEdgeIndex = #Face.Edges
end
local nNextEdgeIndex = Edge.id + 1 + 1
if nNextEdgeIndex > #Face.Edges then
nNextEdgeIndex = 1
end
local vtEdgePrevious = Face.Edges[nPreviousEdgeIndex].vtEdge
local vtEdgeNext = Face.Edges[nNextEdgeIndex].vtEdge
local dLengthEdgePrevious = Face.Edges[nPreviousEdgeIndex].dLength
local dLengthEdgeNext = Face.Edges[nNextEdgeIndex].dLength
local dExtraPrevious = dLengthEdgePrevious * ( Edge.vtEdge * -vtEdgePrevious)
local dExtraNext = dLengthEdgeNext * ( -Edge.vtEdge * vtEdgeNext)
return dExtraPrevious, dExtraNext
end
-------------------------------------------------------------------------------------------------------------
local function GetPerpendicularLeadInOutDirection( Face, Edge)
-- informazioni lati adiacenti
local nCurrentEdgeIndex = Edge.id + 1
local nPreviousEdgeIndex = ( nCurrentEdgeIndex == 1 and #Face.Edges) or nCurrentEdgeIndex - 1
local nNextEdgeIndex = ( nCurrentEdgeIndex == #Face.Edges and 1) or nCurrentEdgeIndex + 1
local EdgeNext = Face.Edges[nNextEdgeIndex]
local EdgePrevious = Face.Edges[nPreviousEdgeIndex]
-- tra le direzioni dei due lati adiacenti, si sceglie la migliore da cui attaccare, ossia quella più vicina alla perpendicolare al lato di lavoro
local dCosAngleStart = -EdgePrevious.vtEdge * Edge.vtN
local dCosAngleEnd = EdgeNext.vtEdge * Edge.vtN
local vtLeadInOut
-- se le due direzioni sono entro i 5° scelgo quella a Z assoluta minore, altrimenti quella più vicino alla perpendicolare
-- massima differenza scalare per variazione di 5deg: cos(0) - cos(0 + 5) = 1 - cos(5)
local dScalarTolerance = 1 - 0.996
if abs( dCosAngleStart - dCosAngleEnd) < dScalarTolerance then
if abs( EdgePrevious.vtEdge:getZ()) < abs( EdgeNext.vtEdge:getZ()) then
vtLeadInOut = Vector3d( -EdgePrevious.vtEdge)
else
vtLeadInOut = Vector3d( EdgeNext.vtEdge)
end
else
if dCosAngleStart > dCosAngleEnd then
vtLeadInOut = Vector3d( -EdgePrevious.vtEdge)
else
vtLeadInOut = Vector3d( EdgeNext.vtEdge)
end
end
return vtLeadInOut
end
-------------------------------------------------------------------------------------------------------------
local function CalculateLeadInOutLength( ptToolCenter, vtNFace, b3Box, vtLeadInOut, Tool)
-- al momento gestita solo lama
if not Tool.sFamily == 'SawBlade' then
error(' Tool family not implemented')
end
-- Box del pezzo espansi ortogonalmente alle tre direzioni canoniche X, Y e Z
local b3BoxX = BBox3d( b3Box) ; b3BoxX:expand( 0, 1000, 1000)
local b3BoxY = BBox3d( b3Box) ; b3BoxY:expand( 1000, 0, 1000)
local b3BoxZ = BBox3d( b3Box) ; b3BoxZ:expand( 1000, 1000, 0)
-- si setta utensile lama per il controllo collisione
EgtCAvSetSawTool( Tool.dThickness, Tool.dDiameter, Tool.dThickness, 0, 0)
-- calcolo distanza di cui retrarre con funzioni Tool Collision Avoidance
local dLength = min( EgtCAvToolPosBox( ptToolCenter + Tool.dThickness * vtNFace, vtNFace, b3BoxX, vtLeadInOut),
EgtCAvToolPosBox( ptToolCenter + Tool.dThickness * vtNFace, vtNFace, b3BoxY, vtLeadInOut),
EgtCAvToolPosBox( ptToolCenter + Tool.dThickness * vtNFace, vtNFace, b3BoxZ, vtLeadInOut))
return dLength
end
-------------------------------------------------------------------------------------------------------------
function LeadInOutLib.CalculateLeadInOut( sLeadInOutType, Parameters, OptionalParameters)
-- parametri obbligatori
local Face = Parameters.Face
local Edge = Parameters.Edge
local Part = Parameters.Part
local Tool = Parameters.Tool
local dDepthToMachine = Parameters.dDepthToMachine
-- parametri opzionali
local sRestLengthSideForPreSimulation = OptionalParameters.sRestLengthSideForPreSimulation or 'Tail'
local bCannotSplitRestLength = OptionalParameters.bCannotSplitRestLength or false
local LeadInOut = {}
local bIsStartClosed = not Edge.bIsStartOpen
local bIsEndClosed = not Edge.bIsEndOpen
-- accorciamento per lati chiusi
LeadInOut.dToolMarkLength = sqrt( dDepthToMachine * Tool.dDiameter - dDepthToMachine * dDepthToMachine)
LeadInOut.dExtraAddLengthStart, LeadInOut.dExtraAddLengthEnd = GetExtraAddLengthInclinedSides( Face, Edge)
-- allungamento per faccia singola (aperta in tutte le direzioni)
LeadInOut.dAddedLengthOpenFace = BeamData.CUT_EXTRA
local LeadIn = {}
local LeadOut = {}
LeadIn.dStartAddLength = 0
LeadOut.dEndAddLength = 0
LeadIn.nType = MCH_MILL_LI.LINEAR
LeadOut.nType = MCH_MILL_LI.LINEAR
LeadIn.dPerpDistance = 0
LeadOut.dPerpDistance = 0
LeadIn.dTangentDistance = 0
LeadOut.dTangentDistance = 0
LeadIn.dElevation = 0
LeadOut.dElevation = 0
LeadIn.dCompLength = 0
LeadOut.dCompLength = 0
-- calcolo allungamenti / accorciamenti
if bIsStartClosed and bIsEndClosed then
LeadIn.dStartAddLength = -LeadInOut.dToolMarkLength - LeadInOut.dExtraAddLengthStart
LeadOut.dEndAddLength = -LeadInOut.dToolMarkLength - LeadInOut.dExtraAddLengthEnd
elseif bIsStartClosed then
LeadIn.dStartAddLength = -LeadInOut.dToolMarkLength - LeadInOut.dExtraAddLengthStart
-- eventuale correzione per accorciamento maggiore di larghezza tasca
LeadOut.dEndAddLength = max( -LeadIn.dStartAddLength - Edge.dLength + 10 * BeamData.CUT_EXTRA, BeamData.CUT_EXTRA)
elseif bIsEndClosed then
LeadOut.dEndAddLength = -LeadInOut.dToolMarkLength - LeadInOut.dExtraAddLengthEnd
-- eventuale correzione per accorciamento maggiore di larghezza tasca
LeadIn.dStartAddLength = max( -LeadOut.dEndAddLength - Edge.dLength + 10 * BeamData.CUT_EXTRA, BeamData.CUT_EXTRA)
else
LeadIn.dStartAddLength = LeadInOut.dAddedLengthOpenFace
LeadOut.dEndAddLength = LeadInOut.dAddedLengthOpenFace
end
-- calcolo punti notevoli della lavorazione
-- punti di inizio e fine lavorazione alla profondità di lavoro reale, considerando allungamenti/accorciamenti
local ptStartAtDepth = Edge.ptStart - Edge.vtEdge * LeadIn.dStartAddLength + Edge.vtN * ( Edge.dElevation - dDepthToMachine)
local ptEndAtDepth = Edge.ptEnd + Edge.vtEdge * LeadOut.dEndAddLength + Edge.vtN * ( Edge.dElevation - dDepthToMachine)
-- punti in centro lama
local ptStartBladeCenter = ptStartAtDepth + Edge.vtN * Tool.dDiameter / 2
local ptEndBladeCenter = ptEndAtDepth + Edge.vtN * Tool.dDiameter / 2
-- box per calcolo uscita lama
-- se è un taglio di testa o coda va aggiunto il sovramateriale
local b3BoxPartExpanded = BBox3d( Part.b3Part)
if bCannotSplitRestLength then
b3BoxPartExpanded = BeamLib.GetPartBoxWithHeadTail( Part, sRestLengthSideForPreSimulation)
end
-- il box si espande in tutte le direzioni per contemplare la sicurezza CUT_SIC
b3BoxPartExpanded:expand( BeamData.CUT_SIC)
-- calcolo attacco scelto
if sLeadInOutType == 'Perpendicular' then
-- scelta direzione migliore per l'attacco
local vtLeadInOut = GetPerpendicularLeadInOutDirection( Face, Edge)
-- frame solidale al lato di lavoro (X lungo il lato, Y normale al lato)
local frEdge = Frame3d( Edge.ptStart, Face.vtN, Edge.vtEdge)
-- direzione nel frame solidale al lato di lavoro
local vtLeadInOuttLoc = Vector3d( vtLeadInOut)
vtLeadInOuttLoc:toLoc( frEdge)
-- calcolo distanza per uscire dal box con questa lama nella direzione vtLeadInOut
local dLeadInLength = CalculateLeadInOutLength( ptStartBladeCenter, Face.vtN, b3BoxPartExpanded, vtLeadInOut, Tool)
local dLeadOutLength = CalculateLeadInOutLength( ptEndBladeCenter, Face.vtN, b3BoxPartExpanded, vtLeadInOut, Tool)
-- componenti dell'attacco
LeadIn.dPerpDistance = dLeadInLength * vtLeadInOuttLoc:getY()
LeadIn.dTangentDistance = dLeadInLength * -vtLeadInOuttLoc:getX()
LeadOut.dPerpDistance = dLeadOutLength * vtLeadInOuttLoc:getY()
LeadOut.dTangentDistance = dLeadOutLength * vtLeadInOuttLoc:getX()
-- punti dell'attacco
LeadIn.ptPoint = Point3d( ptStartAtDepth + vtLeadInOut * dLeadInLength)
LeadOut.ptPoint = Point3d( ptEndAtDepth + vtLeadInOut * dLeadOutLength)
elseif sLeadInOutType == 'Tangent' then
-- calcolo distanza per uscire dal box con questa lama nella direzione tangenziale
local dLeadInLength = CalculateLeadInOutLength( ptStartBladeCenter, Face.vtN, b3BoxPartExpanded, -Edge.vtEdge, Tool)
local dLeadOutLength = CalculateLeadInOutLength( ptEndBladeCenter, Face.vtN, b3BoxPartExpanded, Edge.vtEdge, Tool)
-- componenti dell'attacco
LeadIn.dPerpDistance = 0
LeadIn.dTangentDistance = dLeadInLength
LeadOut.dPerpDistance = 0
LeadOut.dTangentDistance = dLeadOutLength
-- punti dell'attacco
LeadIn.ptPoint = Point3d( ptStartAtDepth - Edge.vtEdge * dLeadInLength)
LeadOut.ptPoint = Point3d( ptEndAtDepth + Edge.vtEdge * dLeadOutLength)
end
-- lunghezza totale attacco
LeadIn.dTotalLength = sqrt( LeadIn.dPerpDistance ^ 2 + LeadIn.dTangentDistance ^ 2)
LeadOut.dTotalLength = sqrt( LeadOut.dPerpDistance ^ 2 + LeadOut.dTangentDistance ^ 2)
LeadInOut.dTotalLength = LeadIn.dTotalLength + LeadOut.dTotalLength
LeadInOut.LeadIn = LeadIn
LeadInOut.LeadOut = LeadOut
return LeadInOut
end
-------------------------------------------------------------------------------------------------------------
function LeadInOutLib.InvertLeadInOut( LeadIn, LeadOut)
local dOriginalStartAddLength = LeadIn.dStartAddLength
local dOriginalEndAddLength = LeadOut.dEndAddLength
LeadIn, LeadOut = LeadOut, LeadIn
LeadIn.dStartAddLength = dOriginalEndAddLength
LeadOut.dEndAddLength = dOriginalStartAddLength
LeadIn.dEndAddLength = nil
LeadOut.dStartAddLength = nil
return LeadIn, LeadOut
end
-------------------------------------------------------------------------------------------------------------
return LeadInOutLib
+11 -9
View File
@@ -5,7 +5,7 @@
local Logs = {}
-------------------------------------------------------------------------------------------------------------
function Logs.WriteFeaturesLog( ProcessingsOnPart, PartInfo)
function Logs.WriteFeaturesLog( ProcessingsOnPart, PartInfo, nReProcessCycles)
local nCycles = 1
local nOffsetIndex = 0
@@ -13,15 +13,13 @@ function Logs.WriteFeaturesLog( ProcessingsOnPart, PartInfo)
nCycles = 2
end
EgtOutLog( ' === === === === === === === === === === REPROCESS CYCLES ' .. EgtNumToString( nReProcessCycles) .. ' === === === === === === === === === === === ===')
EgtOutLog( ' === === === === === === === === === === FEATURES STRATEGIES === === === === === === === === === === === ===')
for nCycle = 1, nCycles do
local nStartIndex = 1 + nOffsetIndex
local nEndIndex = 4 + nOffsetIndex
if nCycle == 1 then
EgtOutLog( ' === === === === === === === === === === FEATURES STRATEGIES === === === === === === === === === === === ===')
else
EgtOutLog( ' === === === === === === === === === === === === === === === === === === === === === === === === === === ===')
EgtOutLog( ' === === === === === === === === FEATURES STRATEGIES PIECE INVERTED === === === === === === === === === ===')
end
EgtOutLog( ' === === === === === === === === === === === === === === === === === === === === === === === === === === ===')
EgtOutLog( ' === === === === === === === === FEATURES STRATEGIES PIECE INVERTED === === === === === === === === === ===')
EgtOutLog( ' Feature ID | BTL POSITION | 90 ROTATION | 180 ROTATION | 270 ROTATION |')
EgtOutLog( '----------------------------------------------------------------------------------------------------------')
@@ -74,7 +72,11 @@ function Logs.WriteFeaturesLog( ProcessingsOnPart, PartInfo)
ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies].Result.sStatus == 'Not-Applicable' then
sStatusStrategy = 'N'
sRating = '----'
sIndexes = ' (C:---|Q:---|T:---)'
if EgtStartsWith( ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies].Result.sInfo, 'REJECTED') then
sIndexes = ' ( --- REJECTED ---)'
else
sIndexes = ' (C:---|Q:---|T:---)'
end
else
if ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies].Result.sStatus == 'Completed' then
sStatusStrategy = 'C'
@@ -88,7 +90,7 @@ function Logs.WriteFeaturesLog( ProcessingsOnPart, PartInfo)
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, '*', '') .. sRating .. sIndexes .. ' (' ..
local sLogLineProc = EgtIf( nIndexBestStrategy == nCountStrategies, '*', '') .. sRating .. sIndexes .. ' (' ..
tostring( ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies].sStrategyId) .. ')' ..
sStatusStrategy .. ' |'
while string.len( sLogLineProc) <= 38 do
+545 -194
View File
@@ -9,11 +9,12 @@ local MachiningLib = {}
require( 'EgtBase')
-- Carico i dati globali
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
local BeamLib = require( 'BeamLib')
local FeatureLib = require( 'FeatureLib')
local BCS = require( 'BasicCustomerStrategies')
local FaceData = require ( 'FaceData')
local PreSimulationLib = require( 'PreSimulationLib')
local LeadInOutLib = require( 'LeadInOutLib')
EgtOutLog( ' MachiningLib started', 1)
@@ -96,15 +97,29 @@ function MachiningLib.CanExtendAfterTail( sCanDamageNextPiece, Part)
end
-------------------------------------------------------------------------------------------------------------
function MachiningLib.GetMachiningSteps( dMachiningDepth, dStep)
function MachiningLib.IsFeatureHinderingClamping( Proc, Part)
local bFeatureHindersClamping
local dFeatureMaxNotClampableLengthHead, dFeatureMaxNotClampableLengthTail = FeatureLib.GetFeatureMaxNotClampableLengths( Proc, Part)
bFeatureHindersClamping = FeatureLib.IsMachiningLong( max( dFeatureMaxNotClampableLengthHead, dFeatureMaxNotClampableLengthTail), Part, { dMaxSegmentLength = BeamData.LONGCUT_ENDLEN})
return bFeatureHindersClamping
end
-------------------------------------------------------------------------------------------------------------
function MachiningLib.GetMachiningSteps( bIsSlot, dMachiningDepth, dStep)
local MachiningSteps = {}
MachiningSteps.dStep = 0
MachiningSteps.nCount = ceil( ( dMachiningDepth - 50 * GEO.EPS_SMALL) / dStep)
if MachiningSteps.nCount > 1 then
MachiningSteps.dStep = ( dMachiningDepth - dStep) / ( MachiningSteps.nCount - 1)
-- se è una slot, dMachiningDepth è l'altezza della tasca e nel calcolo step si deve considerare lo spessore dell'utensile
if bIsSlot then
if MachiningSteps.nCount > 1 then
MachiningSteps.dStep = ( dMachiningDepth - dStep) / ( MachiningSteps.nCount - 1)
else
MachiningSteps.dStep = dMachiningDepth
MachiningSteps.nCount = 1
end
else
MachiningSteps.dStep = dMachiningDepth
MachiningSteps.nCount = 1
MachiningSteps.dStep = dStep
end
return MachiningSteps
@@ -267,12 +282,203 @@ local function IsToolInAvailableToolList( AvailableToolList, sTool)
return bToolFound
end
-------------------------------------------------------------------------------------------------------------
-- in base a tipo testa e angolo soglia, verifica se la faccia è troppo inclinata per la lavorazione scelta (per DownUp passare vtNFace opposta)
function MachiningLib.IsFaceZOutOfRange( vtNFace, Tool)
-- lama sopra: angolo negativo troppo basso
if Tool.SetupInfo.HeadType.bTop and vtNFace:getZ() < Tool.SetupInfo.GetMinNz( vtNFace, Tool) - GEO.EPS_ZERO then
return true
end
-- lama sotto: angolo positivo troppo elevato
if Tool.SetupInfo.HeadType.bBottom and vtNFace:getZ() > Tool.SetupInfo.GetMaxNz( vtNFace, Tool) + GEO.EPS_ZERO then
return true
end
return false
end
-------------------------------------------------------------------------------------------------------------
local function TestEngagement( sBladeEngagement, Parameters, OptionalParameters)
-- parametri obbligatori (parametri opzionali transitano solamente)
local Face = Parameters.Face
local Edge = Parameters.Edge
local Part = Parameters.Part
local Tool = Parameters.Tool
local dDepthToMachine = Parameters.dDepthToMachine
-- il lato della testa cambia in base all'Engagement
local vtHead
if sBladeEngagement == 'Standard' then
vtHead = Face.vtN
elseif sBladeEngagement == 'DownUp' then
vtHead = -Face.vtN
else
error( 'TestEngagement : unknown engagement')
end
-- se l'angolo non può essere raggiunto dall'utensile la lavorazione non è fattibile
if MachiningLib.IsFaceZOutOfRange( vtHead, Tool) then
return false
end
local CheckCollisionParameters = {
Edge = Edge,
vtNFace = Face.vtN,
vtHead = vtHead,
Part = Part,
Tool = Tool,
dDepthToMachine = dDepthToMachine
}
local CheckCollisionOptionalParameters = BeamLib.TableCopyDeep( OptionalParameters or {})
local nSCC = Tool.SetupInfo.GetSCC( Edge.vtN, Edge.vtEdge, Face.vtN)
-- check punti lavorazione
-- lavorazione oltre le corse: non fattibile
local PointsOnToolTipCenter = {
PreSimulationLib.GetPointOnToolTipCenter( Edge.ptStart + Edge.vtN * ( Edge.dElevation - dDepthToMachine), vtHead, Face.vtN, Edge.vtN, Tool),
PreSimulationLib.GetPointOnToolTipCenter( Edge.ptEnd + Edge.vtN * ( Edge.dElevation - dDepthToMachine), vtHead, Face.vtN, Edge.vtN, Tool)
}
local bOutOfStroke = PreSimulationLib.CheckOutOfStrokeFromPoints( PointsOnToolTipCenter, vtHead, nSCC, Tool)
if bOutOfStroke then
return false
end
-- lavorazione in collisione con il pezzo: non fattibile
local bCollisionFound, bMoveAfterSplit = PreSimulationLib.CheckCollision( sBladeEngagement, CheckCollisionParameters, CheckCollisionOptionalParameters)
if bCollisionFound then
return false
end
-- calcolo e check attacchi
local LeadInOut = {}
local LeadInOutOptionalParameters = {
sRestLengthSideForPreSimulation = OptionalParameters.sRestLengthSideForPreSimulation,
bCannotSplitRestLength = OptionalParameters.bCannotSplitRestLength,
bMoveAfterSplit = bMoveAfterSplit
}
-- attacco perpendicolare
local PerpendicularLeadInOut = LeadInOutLib.CalculateLeadInOut( 'Perpendicular', Parameters, LeadInOutOptionalParameters)
-- check extracorsa nei punti di attacco
PointsOnToolTipCenter = {
PreSimulationLib.GetPointOnToolTipCenter( PerpendicularLeadInOut.LeadIn.ptPoint, vtHead, Face.vtN, Edge.vtN, Tool),
PreSimulationLib.GetPointOnToolTipCenter( PerpendicularLeadInOut.LeadOut.ptPoint, vtHead, Face.vtN, Edge.vtN, Tool)
}
local bOutOfStrokePerpendicular = PreSimulationLib.CheckOutOfStrokeFromPoints( PointsOnToolTipCenter, vtHead, nSCC, Tool)
-- attacco perpendicolare non in extracorsa: si verifica se è in collisione
if not bOutOfStrokePerpendicular then
CheckCollisionOptionalParameters.PointsToCheck = {}
table.insert( CheckCollisionOptionalParameters.PointsToCheck, PerpendicularLeadInOut.LeadIn.ptPoint)
table.insert( CheckCollisionOptionalParameters.PointsToCheck, PerpendicularLeadInOut.LeadOut.ptPoint)
local bCollisionFoundPerpendicular, bMoveAfterSplitPerpendicular = PreSimulationLib.CheckCollision( sBladeEngagement, CheckCollisionParameters, CheckCollisionOptionalParameters)
-- attacco perpendicolare possibile
if not bCollisionFoundPerpendicular then
LeadInOut.Perpendicular = PerpendicularLeadInOut
LeadInOut.Perpendicular.bMoveAfterSplit = bMoveAfterSplitPerpendicular
end
end
-- se c'è almeno un lato chiuso l'unico attacco possibile è il perpendicolare
if not ( Edge.bIsStartOpen and Edge.bIsEndOpen) then
if bOutOfStrokePerpendicular then
return false
else
LeadInOut.sChosen = 'Perpendicular'
return true, bMoveAfterSplit, LeadInOut
end
end
-- attacco tangenziale
local TangentLeadInOut = LeadInOutLib.CalculateLeadInOut( 'Tangent', Parameters, LeadInOutOptionalParameters)
-- check extracorsa nei punti di attacco
PointsOnToolTipCenter = {
PreSimulationLib.GetPointOnToolTipCenter( TangentLeadInOut.LeadIn.ptPoint, vtHead, Face.vtN, Edge.vtN, Tool),
PreSimulationLib.GetPointOnToolTipCenter( TangentLeadInOut.LeadOut.ptPoint, vtHead, Face.vtN, Edge.vtN, Tool)
}
local bOutOfStrokeTangent = PreSimulationLib.CheckOutOfStrokeFromPoints( PointsOnToolTipCenter, vtHead, nSCC, Tool)
-- attacco tangenziale non in extracorsa: si verifica se è in collisione
if not bOutOfStrokeTangent then
CheckCollisionOptionalParameters.PointsToCheck = {}
table.insert( CheckCollisionOptionalParameters.PointsToCheck, TangentLeadInOut.LeadIn.ptPoint)
table.insert( CheckCollisionOptionalParameters.PointsToCheck, TangentLeadInOut.LeadOut.ptPoint)
local bCollisionFoundTangent, bMoveAfterSplitTangent = PreSimulationLib.CheckCollision( sBladeEngagement, CheckCollisionParameters, CheckCollisionOptionalParameters)
-- attacco tangenziale possibile
if not bCollisionFoundTangent then
LeadInOut.Tangent = TangentLeadInOut
LeadInOut.Tangent.bMoveAfterSplit = bMoveAfterSplitTangent
end
end
-- se disponibili più attacchi si sceglie il più corto, altrimenti quello possibile
if LeadInOut.Perpendicular and LeadInOut.Tangent then
if LeadInOut.Perpendicular.dTotalLength > LeadInOut.Tangent.dTotalLength + 10 then
LeadInOut.sChosen = 'Tangent'
else
LeadInOut.sChosen = 'Perpendicular'
end
elseif LeadInOut.Perpendicular and not LeadInOut.Tangent then
LeadInOut.sChosen = 'Perpendicular'
elseif LeadInOut.Tangent and not LeadInOut.Perpendicular then
LeadInOut.sChosen = 'Tangent'
-- nessun attacco possibile
-- TODO qui invece di uscire si dovranno provare i due attacchi SpecialTangent e SpecialTangentInverted
else
return false
end
return true, bMoveAfterSplit, LeadInOut
end
-------------------------------------------------------------------------------------------------------------
-- ritorna se la faccia e il lato sono lavorabili e, se sì, il modo di lavorare (standard/DownUp) e i tipi di attacco disponibili
-- TODO si dovrà decidere come tagliare anche se pezzo corto (il motore non deve ingombrare con il pinzaggio)
-- TODO da gestire riduzione percorso
function MachiningLib.GetBladeEngagement( Parameters, OptionalParameters)
local Engagement
-- test lavorazione faccia in modo standard (no DownUp)
local bIsEngagementOk, bMoveAfterSplit, LeadInOut = TestEngagement( 'Standard', Parameters, OptionalParameters)
if bIsEngagementOk then
Engagement = {
sBladeEngagement = 'Standard',
bMoveAfterSplit = bMoveAfterSplit,
LeadInOut = LeadInOut
}
return true, Engagement
end
-- faccia non lavorabile in modo standard: si verifica se il DownUp è fattibile
bIsEngagementOk, bMoveAfterSplit, LeadInOut = TestEngagement( 'DownUp', Parameters, OptionalParameters)
if bIsEngagementOk then
Engagement = {
sBladeEngagement = 'DownUp',
bMoveAfterSplit = bMoveAfterSplit,
LeadInOut = LeadInOut
}
return true, Engagement
end
return false
end
-------------------------------------------------------------------------------------------------------------
-- funzione per cercare utensile tipo FRESA con certe caratteristiche
-- TODO qui vtToolDirection è in realtà vtN
function MachiningLib.FindMill( Proc, ToolSearchParameters)
local ToolInfo = {}
-- direzione utensile e fipo fresa obbligatori, altrimenti si esce
if not ToolSearchParameters.vtToolDirection or not ToolSearchParameters.sMillShape then
return ToolInfo
end
local nBestToolIndex
local dBestToolResidualDepth = 0
for i = 1, #TOOLS do
@@ -316,6 +522,18 @@ function MachiningLib.FindMill( Proc, ToolSearchParameters)
bIsToolCompatible = false
end
end
-- TODO da sostituire con test collisione come lama
local bIsFromBottom = ToolSearchParameters.vtToolDirection:getZ() < - 10 * GEO.EPS_SMALL
local bIsFromTop = ToolSearchParameters.vtToolDirection:getZ() > 10 * GEO.EPS_SMALL
local bIsSlanted = abs( ToolSearchParameters.vtToolDirection:getY()) > 0.707
local bIsOnHeadOrTail = Proc.AffectedFaces.bLeft or Proc.AffectedFaces.bRight
if ( ( bIsFromBottom and TOOLS[i].SetupInfo.HeadType.bTop) or ( bIsFromTop and TOOLS[i].SetupInfo.HeadType.bBottom))
and ( not bIsSlanted)
and ( not bIsOnHeadOrTail) then
bIsToolCompatible = false
end
-- scelgo il migliore
if bIsToolCompatible then
@@ -383,14 +601,14 @@ end
-------------------------------------------------------------------------------------------------------------
-- funzione per cercare utensile tipo LAMA con certe caratteristiche
-- TODO da completare
-- TODO 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)
-- TODO da rivedere/completare
-- TODO per Engagement serviranno (opzionali) sBlockedAxis e vtAux
function MachiningLib.FindBlade( Proc, ToolSearchParameters)
local ToolInfo = {}
-- parametri obbligatori
if type( ToolSearchParameters.vtN) ~= 'table' then
error( 'FindBlade : missing tool direction')
if type( ToolSearchParameters.FaceToMachine) ~= 'table' then
error( 'FindBlade : missing face info')
end
if type( ToolSearchParameters.bAllowTopHead) ~= 'boolean' then
error( 'FindBlade : missing top head info')
@@ -401,32 +619,69 @@ function MachiningLib.FindBlade( Proc, ToolSearchParameters)
if not ToolSearchParameters.bAllowTopHead and not ToolSearchParameters.bAllowBottomHead then
error( 'FindBlade : wrong head info')
end
local FaceToMachine = ToolSearchParameters.FaceToMachine
local bAllowTopHead = ToolSearchParameters.bAllowTopHead
local bAllowBottomHead = ToolSearchParameters.bAllowBottomHead
-- parametri opzionali
ToolSearchParameters.dElevation = ToolSearchParameters.dElevation or 0
ToolSearchParameters.bForceLongcutBlade = ToolSearchParameters.bForceLongcutBlade or false
local dElevation = ToolSearchParameters.dElevation
local bForceLongcutBlade = ToolSearchParameters.bForceLongcutBlade or false
local EdgeToMachine = ToolSearchParameters.EdgeToMachine
local Part = ToolSearchParameters.Part
local bIsDicing = ToolSearchParameters.bIsDicing or false
local sRestLengthSideForPreSimulation = ToolSearchParameters.sRestLengthSideForPreSimulation or 'Tail'
local bCannotSplitRestLength = ToolSearchParameters.bCannotSplitRestLength or false
local bDisableRealElevationCheck = ToolSearchParameters.bDisableRealElevationCheck or false
local nBestToolIndex
local dBestToolResidualDepth = 0
local CurrentEngagement
local BestEngagement
for i = 1, #TOOLS do
local bIsToolCompatible = false
if TOOLS[i].sFamily == 'SAWBLADE' then
if ToolSearchParameters.bAllowTopHead and not ToolSearchParameters.bAllowBottomHead then
if bAllowTopHead and not bAllowBottomHead then
bIsToolCompatible = TOOLS[i].SetupInfo.HeadType.bTop
elseif ToolSearchParameters.bAllowBottomHead and not ToolSearchParameters.bAllowTopHead then
elseif bAllowBottomHead and not bAllowTopHead then
bIsToolCompatible = TOOLS[i].SetupInfo.HeadType.bBottom
else
bIsToolCompatible = true
end
end
-- check angolo limite lama
if TOOLS[i].SetupInfo.HeadType.bTop and ToolSearchParameters.vtN:getZ() < TOOLS[i].SetupInfo.GetMinNz( ToolSearchParameters.vtN, TOOLS[i]) - GEO.EPS_ZERO then
bIsToolCompatible = false
end
if TOOLS[i].SetupInfo.HeadType.bBottom and ToolSearchParameters.vtN:getZ() > TOOLS[i].SetupInfo.GetMaxNz( ToolSearchParameters.vtN, TOOLS[i]) + GEO.EPS_ZERO then
bIsToolCompatible = false
-- se dati sufficienti, si determina se con questo utensile il taglio è fattibile e il modo di lavorare della lama
-- TODO corretto il calcolo della dDepthToMachine? è comunque inutile calcolare per una profondità che so già andrà in collisione
if bIsToolCompatible then
if FaceToMachine and EdgeToMachine and Part and dElevation then
local bIsBladeOk = false
local BladeEngagementParameters = {
Face = FaceToMachine,
Edge = EdgeToMachine,
Part = Part,
Tool = TOOLS[i],
dDepthToMachine = min( dElevation, TOOLS[i].dMaxDepth)
}
local BladeEngagementOptionalParameters = {
bIsDicing = bIsDicing,
sRestLengthSideForPreSimulation = sRestLengthSideForPreSimulation,
bCannotSplitRestLength = bCannotSplitRestLength,
bDisableRealElevationCheck = bDisableRealElevationCheck
}
TIMER:startElapsed( 'GetBladeEngagement')
bIsBladeOk, CurrentEngagement = MachiningLib.GetBladeEngagement( BladeEngagementParameters, BladeEngagementOptionalParameters)
TIMER:stopElapsed( 'GetBladeEngagement')
-- orientamento non raggiungibile
if not bIsBladeOk then
bIsToolCompatible = false
end
-- se si ha solo la faccia si può verificare se questa è orientata correttamente
elseif FaceToMachine then
if MachiningLib.IsFaceZOutOfRange( FaceToMachine.vtN, TOOLS[i]) then
bIsToolCompatible = false
end
end
end
-- se c'è una lista di utensili disponibili, si verifica che l'utensile attuale sia tra quelli
@@ -436,15 +691,17 @@ function MachiningLib.FindBlade( Proc, ToolSearchParameters)
if bIsToolCompatible then
-- TODO gestire accorciamento massimo materiale per inclinazione
local dCurrentResidualDepth = ToolSearchParameters.dElevation - TOOLS[i].dMaxDepth
local dCurrentResidualDepth = ( dElevation or 0) - TOOLS[i].dMaxDepth
if not nBestToolIndex or ( dBestToolResidualDepth > 0 and dCurrentResidualDepth <= 10 * GEO.EPS_SMALL) then
nBestToolIndex = i
dBestToolResidualDepth = dCurrentResidualDepth
BestEngagement = CurrentEngagement
else
-- prediligo utensile per tagli lunghi, se richiesto
if ToolSearchParameters.bForceLongcutBlade and not TOOLS[nBestToolIndex].bIsUsedForLongCut and TOOLS[i].bIsUsedForLongCut then
-- prediligo utensile per tagli lungo vena, se richiesto
if bForceLongcutBlade and not TOOLS[nBestToolIndex].bIsUsedForLongCut and TOOLS[i].bIsUsedForLongCut then
nBestToolIndex = i
dBestToolResidualDepth = dCurrentResidualDepth
BestEngagement = CurrentEngagement
else
-- entrambi completi
if dBestToolResidualDepth <= 10 * GEO.EPS_SMALL and dCurrentResidualDepth <= 10 * GEO.EPS_SMALL then
@@ -455,11 +712,13 @@ function MachiningLib.FindBlade( Proc, ToolSearchParameters)
GetIndexToolInAvailableToolList( ToolSearchParameters.AvailableToolList, TOOLS[nBestToolIndex].sName) then
nBestToolIndex = i
dBestToolResidualDepth = dCurrentResidualDepth
BestEngagement = CurrentEngagement
end
-- si sceglie quello con le performance migliori
elseif TOOLS[i].dPerformanceIndex > TOOLS[nBestToolIndex].dPerformanceIndex + 10 * GEO.EPS_SMALL then
nBestToolIndex = i
dBestToolResidualDepth = dCurrentResidualDepth
BestEngagement = CurrentEngagement
end
-- entrambi incompleti
elseif dBestToolResidualDepth > 10 * GEO.EPS_SMALL and dCurrentResidualDepth > 10 * GEO.EPS_SMALL then
@@ -467,6 +726,7 @@ function MachiningLib.FindBlade( Proc, ToolSearchParameters)
if dCurrentResidualDepth > dBestToolResidualDepth then
nBestToolIndex = i
dBestToolResidualDepth = dCurrentResidualDepth
BestEngagement = CurrentEngagement
end
end
end
@@ -476,6 +736,7 @@ function MachiningLib.FindBlade( Proc, ToolSearchParameters)
ToolInfo.nToolIndex = nBestToolIndex
ToolInfo.dResidualDepth = dBestToolResidualDepth
ToolInfo.Engagement = BestEngagement
return ToolInfo
end
@@ -492,10 +753,10 @@ function MachiningLib.FindDrill( Proc, ToolSearchParameters)
ToolSearchParameters.dToolDiameter = Proc.FeatureInfo.dDrillDiam or 0
end
if not ToolSearchParameters.dMaxToolDiameter then
ToolSearchParameters.dMaxToolDiameter = ToolSearchParameters.dToolDiameter + ( ToolSearchParameters.dDiameterTolerance or ( 100 * GEO.EPS_SMALL))
ToolSearchParameters.dMaxToolDiameter = ToolSearchParameters.dToolDiameter + ( ToolSearchParameters.dDiameterTolerance or 0) + ( 10 * GEO.EPS_SMALL)
end
if not ToolSearchParameters.dMinToolDiameter then
ToolSearchParameters.dMinToolDiameter = ToolSearchParameters.dToolDiameter - ( ToolSearchParameters.dDiameterTolerance or ( 100 * GEO.EPS_SMALL))
ToolSearchParameters.dMinToolDiameter = ToolSearchParameters.dToolDiameter - ( ToolSearchParameters.dDiameterTolerance or 0) - ( 10 * GEO.EPS_SMALL)
end
for i = 1, #TOOLS do
@@ -521,6 +782,8 @@ function MachiningLib.FindDrill( Proc, ToolSearchParameters)
elseif TOOLS[i].SetupInfo.HeadType.bBottom and
ToolSearchParameters.vtToolDirection:getZ() > TOOLS[i].SetupInfo.GetMaxNz( ToolSearchParameters.vtToolDirection, TOOLS[i]) + GEO.EPS_ZERO then
bIsToolCompatible = false
elseif PreSimulationLib.CheckOutOfStrokeFromPoints( ToolSearchParameters.ptCheckOutStroke, ToolSearchParameters.vtToolDirection, 0, TOOLS[i]) then
bIsToolCompatible = false
end
-- scelgo il migliore
@@ -843,7 +1106,7 @@ local function AddNewMachining( ProcToAdd, MachiningToAdd, AuxiliaryDataToAdd)
nHeadCutRotation = 3
elseif ProcToAdd.bSide then
nHeadCutRotation = 2
else
else -- ProcToAdd.bStd
nHeadCutRotation = 1
end
MACHININGS.Info.nHeadCutRotation = max( MACHININGS.Info.nHeadCutRotation or 0, nHeadCutRotation)
@@ -853,7 +1116,7 @@ local function AddNewMachining( ProcToAdd, MachiningToAdd, AuxiliaryDataToAdd)
nSplitCutRotation = 3
elseif ProcToAdd.bSide and MachiningToAdd.sStage == 'AfterTail' then
nSplitCutRotation = 2
else
else -- ProcToAdd.bStd
nSplitCutRotation = 1
end
MACHININGS.Info.nSplitCutRotation = max( MACHININGS.Info.nSplitCutRotation or 0, nSplitCutRotation)
@@ -904,13 +1167,29 @@ function MachiningLib.AddMachinings( Proc, Machining, AuxiliaryData)
return bMachiningAdded
end
-------------------------------------------------------------------------------------------------------------
-- funzione che verifica se ha senso riprocessare tutto dall'inizio,
-- perchè ci sono buone probabilità che l'errore trovato in fase di applicazione si possa risolvere (escludendo la lavorazione scelta in precedenza)
local function IsReProcessWorthIt( nError)
local bReProcess = false
-- errori di Extra-corsa
if nError == 2110 or nError == 2216 or nError == 2318 or nError == 2424 or nError == 2508 then
bReProcess = true
end
return bReProcess
end
-------------------------------------------------------------------------------------------------------------
-- funzione per aggiungere una nuova lavorazione
function MachiningLib.AddOperations( vProc, Part, sRotation)
function MachiningLib.AddOperations( MACHININGS, Part, sRotation)
local nErr
local sErr = ''
local bAreAllMachiningApplyOk = true
local bSplitExecuted = false
local bTryToReProcess = false
-- parametri generali lavorazione
local MachiningParameters = {
@@ -983,17 +1262,20 @@ function MachiningLib.AddOperations( vProc, Part, sRotation)
for i = 1, #MACHININGS do
-- si aggiungono solo quelle della fase richiesta
if ( sRotation == 'STD' and not MACHININGS[i].Proc.bDown and not MACHININGS[i].Proc.bSide) or
if ( MACHININGS[i].Proc.bStd and sRotation == 'STD') 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
-- dati da salvare dopo applicazione della lavorazione
MACHININGS[i].Machining.MachStartAxesPos = {}
MACHININGS[i].Machining.MachEndAxesPos = {}
MACHININGS[i].Machining.nOperationId = {}
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
local Geometry
@@ -1091,45 +1373,74 @@ function MachiningLib.AddOperations( vProc, Part, sRotation)
end
local bIsApplyOk = MachiningLib.ApplyMachining( true, false)
-- si salva sulla lista info lavorazione applicata
local MachExtraInfo = { sType = 'MACH',
nIndexInMachinings = i,
nOperationId = nOperationId,
MachStartAxesPos = EgtGetMachiningStartAxes(),
MachEndAxesPos = EgtGetMachiningEndAxes()}
table.insert( DB_MACH_APPLIED, MachExtraInfo)
-- se non esistono punto iniziale o finale, si disattiva operazione
if not MachExtraInfo.MachStartAxesPos or not MachExtraInfo.MachEndAxesPos then
EgtSetOperationMode( nOperationId, false)
end
-- se errore in applicazione
if not bIsApplyOk then
bAreAllMachiningApplyOk = false
nErr, sErr = EgtGetLastMachMgrError()
EgtSetOperationMode( nOperationId, false)
local nOffsetIndex = EgtIf( Part.bPartInCombiIsInverted, 4, 0)
local CurrProc = PROCESSINGS[MACHININGS[i].Proc.nIndexPartInParts].Rotation[MACHININGS[i].Proc.nIndexRotation+nOffsetIndex][MACHININGS[i].Proc.nIndexInVProc]
-- si annulla la feature scelta, in modo che un successivo ricalcolo non la tenga in considerazione
CurrProc.AvailableStrategies[CurrProc.nIndexBestStrategy].Result.sStatus = 'Not-Applicable'
CurrProc.AvailableStrategies[CurrProc.nIndexBestStrategy].Result.sInfo = 'REJECTED (' .. sErr .. ')'
CurrProc.ChosenStrategy= nil
-- si verifica se vale la pena riprocessare tutto (perchè si pensa possa risolvere il problema)
if IsReProcessWorthIt( nErr) then
bTryToReProcess = true
end
-- update risultati
-- TODO è corretto mettere non applicabile????? disattivare e dare un'incompleta gialla?
RESULT[MACHININGS[i].Proc.nIndexInResult].ChosenStrategy.sStatus = 'Not-Applicable'
RESULT[MACHININGS[i].Proc.nIndexInResult].ChosenStrategy.sApplyInfo = sErr
RESULT[MACHININGS[i].Proc.nIndexInResult].ChosenStrategy.nApplyError = nErr
-- se non deve essere igniorato, si salva ingombro lavorazione attuale e fasi successive
elseif not MACHININGS[i].AuxiliaryData.bIgnoreNotClampableLength then
-- salvo ingombro non pinzabile testa/coda
local nCurrRotation = MACHININGS[i].Proc.nIndexRotation
local dNotClampHead, dNotClampTail = FeatureLib.GetFeatureRotationNotClampableLengths( MACHININGS[i].Proc, Part, nCurrRotation)
Part.NotClampableLength[sRotation].dHead = max( Part.NotClampableLength[sRotation].dHead, dNotClampHead)
Part.NotClampableLength[sRotation].dTail = max( Part.NotClampableLength[sRotation].dTail, dNotClampTail)
-- se applicazione andata a buon fine
else
if sRotation == 'DOWN' then
-- se non deve essere ignorato, si salva ingombro lavorazione attuale e fasi successive
if not MACHININGS[i].AuxiliaryData.bIgnoreNotClampableLength then
-- salvo ingombro non pinzabile testa/coda
local nCurrRotation = MACHININGS[i].Proc.nIndexRotation
local dNotClampHead, dNotClampTail = FeatureLib.GetFeatureRotationNotClampableLengths( MACHININGS[i].Proc, Part, nCurrRotation)
Part.NotClampableLength[sRotation].dHead = max( Part.NotClampableLength[sRotation].dHead, dNotClampHead)
Part.NotClampableLength[sRotation].dTail = max( Part.NotClampableLength[sRotation].dTail, dNotClampTail)
if sRotation == 'DOWN' then
local nNextRotation = EgtIf( nCurrRotation - 1 < 1, nCurrRotation - 1 + 4, nCurrRotation - 1)
-- se rotazione attiva (SIDE)
if string.sub( Part.ChosenCombination, nNextRotation, nNextRotation) == '1' then
dNotClampHead, dNotClampTail = FeatureLib.GetFeatureRotationNotClampableLengths( MACHININGS[i].Proc, Part, nNextRotation)
Part.NotClampableLength['SIDE'].dHead = max( Part.NotClampableLength['SIDE'].dHead, dNotClampHead)
Part.NotClampableLength['SIDE'].dTail = max( Part.NotClampableLength['SIDE'].dTail, dNotClampTail)
end
nNextRotation = EgtIf( nNextRotation - 1 < 1, nNextRotation - 1 + 4, nNextRotation - 1)
-- se rotazione attiva (STD)
if string.sub( Part.ChosenCombination, nNextRotation, nNextRotation) == '1' then
dNotClampHead, dNotClampTail = FeatureLib.GetFeatureRotationNotClampableLengths( MACHININGS[i].Proc, Part, nNextRotation)
Part.NotClampableLength['STD'].dHead = max( Part.NotClampableLength['STD'].dHead, dNotClampHead)
Part.NotClampableLength['STD'].dTail = max( Part.NotClampableLength['STD'].dTail, dNotClampTail)
end
elseif sRotation == 'SIDE' then
local nNextRotation = EgtIf( nCurrRotation - 1 < 1, nCurrRotation - 1 + 4, nCurrRotation - 1)
-- se rotazione attiva (SIDE)
if string.sub( Part.ChosenCombination, nNextRotation, nNextRotation) == '1' then
dNotClampHead, dNotClampTail = FeatureLib.GetFeatureRotationNotClampableLengths( MACHININGS[i].Proc, Part, nNextRotation)
Part.NotClampableLength['SIDE'].dHead = max( Part.NotClampableLength['SIDE'].dHead, dNotClampHead)
Part.NotClampableLength['SIDE'].dTail = max( Part.NotClampableLength['SIDE'].dTail, dNotClampTail)
end
nNextRotation = EgtIf( nNextRotation - 1 < 1, nNextRotation - 1 + 4, nNextRotation - 1)
-- se rotazione attiva (STD)
if string.sub( Part.ChosenCombination, nNextRotation, nNextRotation) == '1' then
dNotClampHead, dNotClampTail = FeatureLib.GetFeatureRotationNotClampableLengths( MACHININGS[i].Proc, Part, nNextRotation)
Part.NotClampableLength['STD'].dHead = max( Part.NotClampableLength['STD'].dHead, dNotClampHead)
Part.NotClampableLength['STD'].dTail = max( Part.NotClampableLength['STD'].dTail, dNotClampTail)
end
elseif sRotation == 'SIDE' then
local nNextRotation = EgtIf( nCurrRotation - 1 < 1, nCurrRotation - 1 + 4, nCurrRotation - 1)
-- se rotazione attiva (STD)
if string.sub( Part.ChosenCombination, nNextRotation, nNextRotation) == '1' then
dNotClampHead, dNotClampTail = FeatureLib.GetFeatureRotationNotClampableLengths( MACHININGS[i].Proc, Part, nNextRotation)
Part.NotClampableLength['STD'].dHead = max( Part.NotClampableLength['STD'].dHead, dNotClampHead)
Part.NotClampableLength['STD'].dTail = max( Part.NotClampableLength['STD'].dTail, dNotClampTail)
-- se rotazione attiva (STD)
if string.sub( Part.ChosenCombination, nNextRotation, nNextRotation) == '1' then
dNotClampHead, dNotClampTail = FeatureLib.GetFeatureRotationNotClampableLengths( MACHININGS[i].Proc, Part, nNextRotation)
Part.NotClampableLength['STD'].dHead = max( Part.NotClampableLength['STD'].dHead, dNotClampHead)
Part.NotClampableLength['STD'].dTail = max( Part.NotClampableLength['STD'].dTail, dNotClampTail)
end
end
end
end
@@ -1141,9 +1452,9 @@ function MachiningLib.AddOperations( vProc, Part, sRotation)
bSplitExecuted = true
MACHININGS.Info.bSplitExecuted = true
BeamLib.AddPhaseWithRawParts( MACHININGS[i].Proc.idRaw, BeamData.ptOriXR, BeamData.dPosXR, BeamData.RAW_OFFSET)
BeamLib.AddPhaseWithRawParts( Part.idRaw, BeamData.ptOriXR, BeamData.dPosXR, BeamData.RAW_OFFSET)
-- se grezzo successivo senza pezzi e finale, va tolto
local nNextRawId = EgtGetNextRawPart( MACHININGS[i].Proc.idRaw)
local nNextRawId = EgtGetNextRawPart( Part.idRaw)
if nNextRawId and EgtGetPartInRawPartCount( nNextRawId) == 0 and EgtGetRawPartBBox( nNextRawId):getDimX() < BeamData.dMinRaw then
EgtRemoveRawPartFromCurrPhase( nNextRawId)
end
@@ -1157,25 +1468,27 @@ function MachiningLib.AddOperations( vProc, Part, sRotation)
local nPhase = EgtGetCurrPhase()
local idDisp = EgtGetPhaseDisposition( nPhase)
-- posizione iniziale considerando eventuiali prerotazioni
local nRealInitialPosition = Part.nInitialPosition
if sRotation == 'DOWN' then
local nRotation = EgtIf( Part.nInitialPosition + 2 > 4, Part.nInitialPosition + 2 - 4, Part.nInitialPosition + 2) - 1
local nRotation = EgtIf( nRealInitialPosition + 2 > 4, nRealInitialPosition + 2 - 4, nRealInitialPosition + 2) - 1
BeamLib.RotateRawPart( Part, nRotation)
EgtSetInfo( idDisp, 'ROT', -2)
EgtSetInfo( idDisp, 'TYPE', 'MID2')
elseif sRotation == 'SIDE' then
local nRotation = EgtIf( Part.nInitialPosition + 1 > 4, Part.nInitialPosition + 1 - 4, Part.nInitialPosition + 1) - 1
local nRotation = EgtIf( nRealInitialPosition + 1 > 4, nRealInitialPosition + 1 - 4, nRealInitialPosition + 1) - 1
BeamLib.RotateRawPart( Part, nRotation)
EgtSetInfo( idDisp, 'ROT', -1)
EgtSetInfo( idDisp, 'TYPE', 'MID2')
else
local nRotation = Part.nInitialPosition - 1
local nRotation = nRealInitialPosition - 1
BeamLib.RotateRawPart( Part, nRotation)
EgtSetInfo( idDisp, 'TYPE', 'END')
end
EgtSetInfo( idDisp, 'ORD', MACHININGS[i].Proc.nIndexPartInParts)
end
else
return false, 'UNEXPECTED ERROR: Error on creating machining', bSplitExecuted
return false, 'UNEXPECTED ERROR: Error on creating machining', bSplitExecuted, false
end
end
end
@@ -1192,13 +1505,13 @@ function MachiningLib.AddOperations( vProc, Part, sRotation)
EgtSetInfo( idDisp, 'TCING', Part.NotClampableLength[sRotation].dTail or 0)
end
return bAreAllMachiningApplyOk, sErr, bSplitExecuted
return bAreAllMachiningApplyOk, sErr, bSplitExecuted, bTryToReProcess
end
-------------------------------------------------------------------------------------------------------------
function MachiningLib.ApplyMachining( bRecalc, bApplyPost)
local bResult = EgtApplyMachining( bRecalc, bApplyPost)
return bResult
end
@@ -1234,7 +1547,19 @@ function MachiningLib.GetTimeToMachineAllStepsWithLeadInOut( Machining, Part)
local dToolEndFeed = TOOLS[Machining.nToolIndex].Feeds.dEndFeed
local dToolFeed = TOOLS[Machining.nToolIndex].Feeds.dFeed
if Machining.nType == MCH_MY.MILLING then
if Machining.nType == MCH_MY.DRILLING then
local function fact(n) return n == 0 and 1 or n * fact(n - 1) end
local nSteps = ceil( Machining.sDepth / Machining.dStep)
local dLengthEachStep = Machining.sDepth / nSteps
-- numero dei movimenti a step, compresi andata e ritorno per scarico truciolo
local nTotStepMovement = 2 * fact( nSteps)
-- in feed si lavorano solo gli step
local dFeedTime = ( ( dLengthEachStep + Machining.dStartSafetyLength) * nSteps) / dToolFeed
-- ritorno per scaricare e approccio al prossimo step sono in feed finale
local dEndFeedTime = ( dLengthEachStep * ( nTotStepMovement - nSteps) + EgtMdbGetGeneralParam( MCH_GP.SAFEZ) * 2) / dToolEndFeed
dLengthToMachineAllStepsWithLeadInOut = dLengthEachStep * nTotStepMovement
dTimeToMachineTotal = dFeedTime + dEndFeedTime
elseif Machining.nType == MCH_MY.MILLING then
-- stima LeadIn e LeadOut; se non settati si impostano a valori di default
if not Machining.LeadIn.dTotalEstimatedDistance then
Machining.LeadIn.dTotalEstimatedDistance = sqrt( Machining.LeadIn.dPerpDistance ^ 2 + Machining.LeadIn.dTangentDistance ^ 2) + Machining.dStartSafetyLength
@@ -1284,9 +1609,9 @@ function MachiningLib.GetTimeToMachineAllStepsWithLeadInOut( Machining, Part)
local ProcTm = FeatureLib.GetProcFromTrimesh( Machining.Geometry[1][1], Part)
local dDepthToMachine = min( ProcTm.Faces[Machining.Geometry[1][2] + 1].dElevation, ( Machining.dMaxElev or ProcTm.Faces[Machining.Geometry[1][2] + 1].dElevation)) - ( max( 0, Machining.dResidualDepth or 0))
local nSteps = max( ceil( ( dDepthToMachine - 50 * GEO.EPS_SMALL) / TOOLS[Machining.nToolIndex].dStep), 1)
local nAddGroupId = BeamLib.GetAddGroup( Part.id)
local idTempGroup = Part.idTempGroup
-- TODO in futuro creare flatregion (se ci fossero isole il calcolo del percorso non sarebbe corretto)
local idFaceContour = EgtExtractSurfTmFacetLoops( ProcTm.id, Machining.Geometry[1][2], nAddGroupId)
local idFaceContour = EgtExtractSurfTmFacetLoops( ProcTm.id, Machining.Geometry[1][2], idTempGroup)
-- si settano i lati aperti della curva derivata dalla superficie
for i = 1, #ProcTm.Faces[Machining.Geometry[1][2] + 1].Edges do
if ProcTm.Faces[Machining.Geometry[1][2] + 1].Edges[i].bIsOpen then
@@ -1294,7 +1619,7 @@ function MachiningLib.GetTimeToMachineAllStepsWithLeadInOut( Machining, Part)
end
end
-- dal momento che la funzione EgtPocketing non considera il grezzo, nei casi ottimizzati si deve correggere l'offset
local idTestCurve = EgtCopyGlob( idFaceContour, nAddGroupId )
local idTestCurve = EgtCopyGlob( idFaceContour, idTempGroup )
local bIsOptimizedPocketing = ( TOOLS[Machining.nToolIndex].dDiameter > TOOLS[Machining.nToolIndex].dSideStep - 10 * GEO.EPS_SMALL)
and EgtOffsetCurve( idTestCurve, -TOOLS[Machining.nToolIndex].dDiameter / 2 - 10 * GEO.EPS_SMALL)
if not bIsOptimizedPocketing then
@@ -1310,7 +1635,7 @@ function MachiningLib.GetTimeToMachineAllStepsWithLeadInOut( Machining, Part)
end
end
-- calcolo percorso di svuotatura replicando il calcolo che fa la svuotatura
local idPocketingPath = EgtPocketing( idFaceContour, TOOLS[Machining.nToolIndex].dDiameter / 2, TOOLS[Machining.nToolIndex].dSideStep, 0, Machining.nSubType, true, nAddGroupId)
local idPocketingPath = EgtPocketing( idFaceContour, TOOLS[Machining.nToolIndex].dDiameter / 2, TOOLS[Machining.nToolIndex].dSideStep, 0, Machining.nSubType, true, idTempGroup)
local dPocketingPathLength = EgtCurveLength( idPocketingPath)
-- calcolo lunghezze e tempi totali
if dPocketingPathLength then
@@ -1322,10 +1647,6 @@ function MachiningLib.GetTimeToMachineAllStepsWithLeadInOut( Machining, Part)
dLengthToMachineAllStepsWithLeadInOut = 99999 * nSteps
dTimeToMachineTotal = dLengthToMachineAllStepsWithLeadInOut / dToolFeed
end
-- le geometrie create si settano da cancellare
EgtSetLevel( idFaceContour, GDB_LV.TEMP)
EgtSetLevel( idPocketingPath, GDB_LV.TEMP)
EgtSetLevel( idTestCurve, GDB_LV.TEMP)
else
error( 'GetTimeToMachineAllStepsWithLeadInOut : unknown machining type')
end
@@ -1429,19 +1750,6 @@ end
-- 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
@@ -1455,110 +1763,6 @@ local SortingComparisonRules = {
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() < -0.174 and MachiningB.Machining.vtToolDirection:getY() >= 0.174 then
return 1
elseif MachiningA.Machining.vtToolDirection:getY() >= 0.174 and MachiningB.Machining.vtToolDirection:getY() < -0.174 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
}
-------------------------------------------------------------------------------------------------------------
@@ -1575,5 +1779,152 @@ function MachiningLib.CompareMachinings( MachiningA, MachiningB)
return false
end
-------------------------------------------------------------------------------------------------------------
local function OrderMachining( MachiningOptList)
-- Recupero l'identificativo del gruppo di lavoro corrente
for i = 1, #MachiningOptList - 1 do
local idSource = DB_MACH_APPLIED[MachiningOptList[i+1]].nOperationId
local idRef = DB_MACH_APPLIED[MachiningOptList[i]].nOperationId
EgtRelocateGlob( idSource, idRef, GDB_IN.AFTER)
end
end
-------------------------------------------------------------------------------------------------------------
function MachiningLib.ShortestPathSorting()
local i = 1
while i <= #DB_MACH_APPLIED do
local nMachInDisp = 0
local MachiningOptList = {}
local GroupInfo = {}
-- se è una lavorazione
if DB_MACH_APPLIED[i].sType ~= 'DISP' then
-- inizio
EgtOptMachInit()
-- feed dalla macchina
-- TODO abbassare per considere accelerazioni??
SetupInfo = BeamData.GetSetupInfo()
EgtOptMachSetFeeds( SetupInfo.dFeedLinearAxesAverage or 10000, SetupInfo.dFeedRotativeAxesAverage or 1000)
-- tra gruppi (stage) non si può ottimizzare
EgtOptMachSetAllGroupsDependencesAsMandatory( true)
EgtOptMachSetOptimizationForGroups( true)
-- se è una lavorazione
while DB_MACH_APPLIED[i] and DB_MACH_APPLIED[i].sType ~= 'DISP' do
if DB_MACH_APPLIED[i].MachStartAxesPos and DB_MACH_APPLIED[i].MachEndAxesPos then
-- se lavorazione non attiva non va considerata
local nOperationId = DB_MACH_APPLIED[i].nOperationId
if EgtGetOperationMode( nOperationId) then
local ptMinX, ptMaxX
-- aggiungo lavorazioni
local nToolIndex = MACHININGS[DB_MACH_APPLIED[i].nIndexInMachinings].Machining.nToolIndex
EgtOptMachAddTool( nToolIndex, 2, 2) -- , [ num dTC_X, num dTC_Y, num dTC_Z, num dTC_A, num dTC_B, num dTC_C])
-- viene eseguito prima il gruppo con indice più alto, quindi si inverte indice dato che lo stage è dal più piccolo al più grande
local nGroup = 10 - MACHININGS[DB_MACH_APPLIED[i].nIndexInMachinings].Machining.nStage
local MachStartAxesPos = DB_MACH_APPLIED[i].MachStartAxesPos
local MachEndAxesPos = DB_MACH_APPLIED[i].MachEndAxesPos
EgtOptMachAddMachining( i, nToolIndex, nGroup, MachStartAxesPos, MachEndAxesPos)
table.insert( MachiningOptList, i)
-- si salvano i punti minimi e massimi tra tutte le lavorazioni di ogni gruppo
if MachStartAxesPos[1] < MachEndAxesPos[1] then
ptMinX = MachStartAxesPos
ptMaxX = MachEndAxesPos
else
ptMinX = MachEndAxesPos
ptMaxX = MachStartAxesPos
end
-- si aggiungono le info di gruppo
local bFound = false
for t = 1, #GroupInfo do
if GroupInfo[t].nGroup == nGroup then
if GroupInfo[t].ptMin[1] > ptMinX[1] then GroupInfo[t].ptMin = ptMinX end
if GroupInfo[t].ptMax[1] < ptMaxX[1] then GroupInfo[t].ptMax = ptMaxX end
bFound = true
end
end
-- se non ho trovato, si aggiunge in lista
if not bFound then
table.insert( GroupInfo, { nGroup = nGroup, nStage = MACHININGS[DB_MACH_APPLIED[i].nIndexInMachinings].Machining.nStage, ptMin = ptMinX, ptMax = ptMaxX})
end
nMachInDisp = nMachInDisp + 1
end
end
i = i + 1
end
-- cliclo su tutte le lavorazioni
for k = 1, #MachiningOptList do
if not DB_MACH_APPLIED[MachiningOptList[k]].Dependances then
DB_MACH_APPLIED[MachiningOptList[k]].Dependances = {}
end
for j = 1, #MachiningOptList do
-- se non è stessa lavorazione, imposto dati e dipendenze
if k ~= j then
local MachiningK = MACHININGS[DB_MACH_APPLIED[MachiningOptList[k]].nIndexInMachinings]
local MachiningJ = MACHININGS[DB_MACH_APPLIED[MachiningOptList[j]].nIndexInMachinings]
-- se stessa Proc
if MachiningK.Proc.id == MachiningJ.Proc.id then
-- se lavorazioni della stessa feature, obbligatorio rispettare ordine
if MachiningK.Machining.nFeatureInternalIndex < MachiningJ.Machining.nFeatureInternalIndex then
local bOk = EgtOptMachAddDependence( MachiningOptList[k], MachiningOptList[j])
if not bOk then
error( 'Machining sorting : error in dependencies')
end
table.insert( DB_MACH_APPLIED[MachiningOptList[k]].Dependances, MachiningOptList[j])
-- se l'indice interno è uguale, sono cloni: si ordinano in base all'ordine in tabella
elseif MachiningK.Machining.nFeatureInternalIndex == MachiningJ.Machining.nFeatureInternalIndex then
if k < j then
local bOk = EgtOptMachAddDependence( MachiningOptList[k], MachiningOptList[j])
if not bOk then
error( 'Machining sorting : error in dependencies')
end
table.insert( DB_MACH_APPLIED[MachiningOptList[k]].Dependances, MachiningOptList[j])
end
end
-- se tra due Proc diverse
else
-- TODO :
-- se ci sono dipendenze tra due feature diverse, la dipendenza è obbligatoria! ATTENZIONE A DIPENDENZE INCROCIATE A->B, B->C, C->A
end
end
end
end
-- definisco gruppo per gruppo la direzione preferita di ottimizzazione
for t = 1, #GroupInfo do
-- se gruppo "Taglio di coda" l'ordinamento è al contrario
if GroupInfo[t].nStage == 3 then
-- start point
EgtOptMachSetOpenBoundForGroups( GroupInfo[t].nGroup, true, SHP_OB.NEAR_PNT, GroupInfo[t].ptMin[1], GroupInfo[t].ptMin[2], GroupInfo[t].ptMin[3])
-- end point
EgtOptMachSetOpenBoundForGroups( GroupInfo[t].nGroup, false, SHP_OB.NEAR_PNT, GroupInfo[t].ptMax[1], GroupInfo[t].ptMax[2], GroupInfo[t].ptMax[3])
-- in tutti gli altri gruppi si ordina sempre dalla testa alla coda
else
-- start point
EgtOptMachSetOpenBoundForGroups( GroupInfo[t].nGroup, true, SHP_OB.NEAR_PNT, GroupInfo[t].ptMax[1], GroupInfo[t].ptMax[2], GroupInfo[t].ptMax[3])
-- end point
EgtOptMachSetOpenBoundForGroups( GroupInfo[t].nGroup, false, SHP_OB.NEAR_PNT, GroupInfo[t].ptMin[1], GroupInfo[t].ptMin[2], GroupInfo[t].ptMin[3])
end
end
-- calcolo ordine lavorazioni
MachiningOptList = EgtOptMachCalculate( MachiningOptList)
OrderMachining( MachiningOptList)
-- fine
EgtOptMachTerminate()
end
i = i + 1
end
end
-------------------------------------------------------------------------------------------------------------
return MachiningLib
+547
View File
@@ -0,0 +1,547 @@
-- PreSimulationLib.lua by Egalware s.r.l. 2025/11/24
-- Libreria stima collisioni per travi
-- Tabella per definizione modulo
local PreSimulationLib = {}
-- Include
require( 'EgtBase')
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamDataNew')
EgtOutLog( ' PreSimulationLib started', 1)
-------------------------------------------------------------------------------------------------------------
local function GetMachineAxes()
local LinearAxes = {}
local RotativeAxes = {}
-- si recuperano tutti gli assi, lineari e rotativi
local AxesNames = EgtGetAllCurrAxesNames()
for i = 1, #AxesNames do
-- EgtGetAxisType restituisce vero se asse lineare, false se asse rotativo
if EgtGetAxisType( AxesNames[i]) then
LinearAxes[#LinearAxes + 1] = {}
LinearAxes[#LinearAxes].sName = AxesNames[i]
else
RotativeAxes[#RotativeAxes + 1] = {}
RotativeAxes[#RotativeAxes].sName = AxesNames[i]
end
end
return LinearAxes, RotativeAxes
end
-------------------------------------------------------------------------------------------------------------
local function LogOutstroke( sToolName, ptOnToolTipCenter, vtHead, OptionalParameters)
-- parametri opzionali
OptionalParameters = OptionalParameters or {}
local LinearAxesValues = OptionalParameters.LinearAxesValues
local RotativeAxesValues = OptionalParameters.RotativeAxesValues
-- gruppo per geometrie temporanee
local idTempGroup = BeamLib.GetTempGroup()
-- si disegnano punto e vettore
local idPoint = EgtPoint( idTempGroup, ptOnToolTipCenter, GDB_RT.GLOB)
local idVector = EgtVector( idTempGroup, vtHead, ptOnToolTipCenter, GDB_RT.GLOB)
EgtSetColor( idPoint, RED())
EgtSetColor( idVector, RED())
-- nome utensile
EgtOutLog( 'Tool ' .. sToolName)
-- si loggano valori di punto e vettore
EgtOutLog( ' Presimulation : OutStroke, Tip Point = ' .. tostring( ptOnToolTipCenter) .. ', id = ' .. idPoint .. ', vtHead = ' .. tostring( vtHead) .. ', id = ' .. idVector)
-- se disponibili, si loggano anche i valori calcolati degli assi
if LinearAxesValues then
EgtOutLog( ' ' .. 'Lin1' .. ' = ' .. tostring( LinearAxesValues[1]) .. ', ' .. 'Lin2' .. ' = ' .. tostring( LinearAxesValues[2]) .. ', ' .. 'Lin3' .. ' = ' .. tostring( LinearAxesValues[3]))
end
if RotativeAxesValues then
EgtOutLog( ' ' .. 'Rot1' .. ' = ' .. tostring( RotativeAxesValues[1]) .. ', ' .. 'Rot2' .. ' = ' .. tostring( RotativeAxesValues[2]) .. ', ' .. 'Rot3' .. ' = ' .. tostring( RotativeAxesValues[3]))
end
return
end
-------------------------------------------------------------------------------------------------------------
-- costruzione trimesh del grezzo restante in testa o in coda
local function GetRestlengthSurfTm( Part, sSide)
-- si costruisce il box in globale
local b3RestLength
if sSide == 'Head' then
local b3PartWithOvermaterial = BeamLib.GetPartBoxWithHeadTail( Part, sSide)
local ptStartRestLength = Point3d( Part.b3Part:getMax():getX(), Part.b3Part:getMax():getY(), Part.b3Part:getMax():getZ())
local ptEndRestLength = Point3d( b3PartWithOvermaterial:getMax():getX(), Part.b3Part:getMin():getY(), Part.b3Part:getMin():getZ())
b3RestLength = BBox3d( ptStartRestLength, ptEndRestLength)
elseif sSide == 'Tail' then
local b3PartWithOvermaterial = BeamLib.GetPartBoxWithHeadTail( Part, sSide)
local dXMin = b3PartWithOvermaterial:getMin():getX()
-- si evita sempre di lavorare col motore dietro la coda della barra (potrebbe succedere con barra restante molto corta): in quel caso si deve sempre separare prima
dXMin = min( dXMin, Part.b3Part:getMin():getX() - 2000)
local ptStartRestLength = Point3d( Part.b3Part:getMin():getX(), Part.b3Part:getMax():getY(), Part.b3Part:getMax():getZ())
local ptEndRestLength = Point3d( dXMin, Part.b3Part:getMin():getY(), Part.b3Part:getMin():getZ())
b3RestLength = BBox3d( ptStartRestLength, ptEndRestLength)
-- caso non testato, non dovrebbe mai finire qui (il default che arriva da fuori è Tail)
else
return nil
end
-- si crea la trimesh dal box
local idRestLengthBoxTm = EgtSurfTmBBox( Part.idTempGroup, b3RestLength , false, GDB_RT.GLOB)
return idRestLengthBoxTm
end
-------------------------------------------------------------------------------------------------------------
function PreSimulationLib.GetPointOnToolTipCenter( ptPointAtDepth, vtHead, vtNFace, vtToolOffset, Tool)
return ptPointAtDepth + vtToolOffset * Tool.dDiameter / 2 + vtNFace * EgtIf( AreSameVectorApprox( vtHead, vtNFace), 0, Tool.dThickness)
end
-------------------------------------------------------------------------------------------------------------
-- calcolo punto sull'uscita testa a partire dal punto di lavorazione o di attacco sul diametro utensile
local function GetToolExitPoint( ptMachining, vtNEdge, vtHead, Tool, bIsDownUp)
local ptToolExitPoint = Point3d( ptMachining + vtNEdge * Tool.dDiameter / 2) + vtHead * EgtIf( bIsDownUp, ( Tool.dLength - Tool.dThickness), Tool.dLength)
return ptToolExitPoint
end
-------------------------------------------------------------------------------------------------------------
-- calcolo pivot in riferimento globale, dati punto sull'uscita utensile e direzioni
local function GetGlobalPivot( ptToolExit, vtC, vtHead, vtMovePivot)
-- frame solidale all'utensile (lo stesso in cui vtMovePivot è definito)
local frTool = Frame3d( ptToolExit, vtHead, vtC)
local vtMovePivotGlob = Vector3d( vtMovePivot)
vtMovePivotGlob:toGlob( frTool)
local ptPivot = ptToolExit + vtMovePivotGlob
return ptPivot
end
-------------------------------------------------------------------------------------------------------------
-- restituisce i punti notevoli della lavorazioni in cui fare il controllo
local function GetCollisionPointsToCheck( Edge, dDepthToMachine)
local PointsToCheck = {}
-- punti notevoli
local ptStart = Edge.ptStart + Edge.vtN * ( Edge.dElevation - dDepthToMachine)
local ptEnd = Edge.ptEnd + Edge.vtN * ( Edge.dElevation - dDepthToMachine)
local ptMid = Point3d( ( ptStart + ptEnd) / 2)
-- caso ottimizzato: lato parallelo ad una direzione principale
local bIsEdgeParallelToMainDirection =
AreSameOrOppositeVectorApprox( Edge.vtEdge, X_AX())
or AreSameOrOppositeVectorApprox( Edge.vtEdge, Y_AX())
or AreSameOrOppositeVectorApprox( Edge.vtEdge, Z_AX())
-- aggiunta punti
table.insert( PointsToCheck, ptStart)
if not bIsEdgeParallelToMainDirection then
table.insert( PointsToCheck, ptMid)
end
table.insert( PointsToCheck, ptEnd)
return PointsToCheck
end
-------------------------------------------------------------------------------------------------------------
local function CheckOutOfStrokePoint( ptOnToolTipCenter, vtHead, nSCC, Tool, vtAux, sBlockedAxis)
-- impostazione utensile
local bOkTool = EgtSetCalcTool( Tool.sName, Tool.sHead, Tool.nExit)
if not bOkTool then
error( 'CheckOutOfStrokePoint : cannot set calc tool')
end
-- settaggio SCC per discriminare soluzioni multiple
EgtSetCalcSolCh( nSCC)
-- se presente, settaggio asse bloccato
if sBlockedAxis and type( sBlockedAxis) == "string" then
local BlockedAxis = EgtSplitString( sBlockedAxis, '=')
EgtSetRotAxisBlock( BlockedAxis[1], tonumber( BlockedAxis[2]))
end
-- calcolo assi rotativi
local bOkAngles, nSolutionsAngles, RotativeAxesValues = EgtGetCalcAnglesEx( vtHead, vtAux)
local dRotative1 = RotativeAxesValues[1]
local dRotative2 = RotativeAxesValues[2]
local dRotative3 = RotativeAxesValues[3]
if not bOkAngles then
error( ' CheckOutOfStrokePoint : error')
end
-- se nessuna soluzione dagli assi rotativi, è in extracorsa
if nSolutionsAngles == 0 then
if EgtGetDebugLevel() >= 3 then
LogOutstroke( Tool.sName, ptOnToolTipCenter, vtHead, { RotativeAxesValues = { dRotative1, dRotative2, dRotative3}})
end
return true
end
-- calcolo assi lineari
local bOkPositions, _, dLinear1, dLinear2, dLinear3 = EgtGetCalcPositions( ptOnToolTipCenter, dRotative1, dRotative2, dRotative3)
if not bOkPositions then
error( ' CheckOutOfStrokePoint : error')
end
-- verifica finecorsa per assi lineari (assi rotativi già verificati)
local bAllAxesInStroke = EgtVerifyOutstroke( dLinear1, dLinear2, dLinear3)
-- extracorsa
if not bAllAxesInStroke then
if EgtGetDebugLevel() >= 3 then
LogOutstroke( Tool.sName, ptOnToolTipCenter, vtHead, { LinearAxesValues = { dLinear1, dLinear2, dLinear3}, RotativeAxesValues = { dRotative1, dRotative2, dRotative3}})
end
return true
end
-- EgtSetAxisPos( 'T', dT)
-- EgtSetAxisPos( 'Y', dY)
-- EgtSetAxisPos( 'Z', dZ)
-- EgtSetAxisPos( 'C', dC1)
-- EgtSetAxisPos( 'A', dA1)
-- se si arriva qui, il punto non è in finecorsa
return false
end
-------------------------------------------------------------------------------------------------------------
-- check extracorsa da punti sul tip dell'utensile
function PreSimulationLib.CheckOutOfStrokeFromPoints( PointsOnToolTipCenter, vtHead, nSCC, Tool, vtAux, sBlockedAxis)
for i = 1, #PointsOnToolTipCenter do
local bOutOfStroke = CheckOutOfStrokePoint( PointsOnToolTipCenter[i], vtHead, nSCC, Tool, vtAux, sBlockedAxis)
-- se trovato extracorsa inutile procedere con gli altri punti
if bOutOfStroke then
return true
end
end
-- se arrivati qui, nessun extracorsa
return false
end
-------------------------------------------------------------------------------------------------------------
-- check extracorsa da geometria
-- TODO da considerare anche gli attacchi
function PreSimulationLib.CheckOutOfStrokeFromGeometry( idGeometry, vtHead, nSCC, Tool, vtAux, sBlockedAxis)
local b3GeomMaxOffset = EgtGetBBoxGlob( idGeometry, GDB_BB.STANDARD)
local ptBoxCenter = b3GeomMaxOffset:getCenter()
local dBoxDimX = b3GeomMaxOffset:getDimX()
local dBoxDimY = b3GeomMaxOffset:getDimY()
local dBoxDimZ = b3GeomMaxOffset:getDimZ()
-- si controlla il finecorsa nei punti al centro delle 6 facce del box
local PointsOnToolTipCenter = {}
-- X+
table.insert( PointsOnToolTipCenter, Point3d( ptBoxCenter + dBoxDimX / 2 * X_AX()))
-- X-
table.insert( PointsOnToolTipCenter, Point3d( ptBoxCenter - dBoxDimX / 2 * X_AX()))
-- Y+
table.insert( PointsOnToolTipCenter, Point3d( ptBoxCenter + dBoxDimY / 2 * Y_AX()))
-- Y-
table.insert( PointsOnToolTipCenter, Point3d( ptBoxCenter - dBoxDimY / 2 * Y_AX()))
-- Z+
table.insert( PointsOnToolTipCenter, Point3d( ptBoxCenter + dBoxDimZ / 2 * Z_AX()))
-- Z-
table.insert( PointsOnToolTipCenter, Point3d( ptBoxCenter - dBoxDimZ / 2 * Z_AX()))
local bOutOfStroke = PreSimulationLib.CheckOutOfStrokeFromPoints( PointsOnToolTipCenter, vtHead, nSCC, Tool, vtAux, sBlockedAxis)
return bOutOfStroke
end
-------------------------------------------------------------------------------------------------------------
local function MoveMachineAxesToPosition( ptOnToolTipCenter, vtHead, vtAux)
-- calcolo assi rotativi
local bOkAngles, nSolutionsAngles, RotativeAxesValues = EgtGetCalcAnglesEx( vtHead, vtAux)
local dRotative1 = RotativeAxesValues[1]
local dRotative2 = RotativeAxesValues[2]
local dRotative3 = RotativeAxesValues[3]
if not bOkAngles then
error( ' MoveMachineAxesToPosition : error')
end
-- calcolo assi lineari
local bOkPositions, _, dLinear1, dLinear2, dLinear3 = EgtGetCalcPositions( ptOnToolTipCenter, dRotative1, dRotative2, dRotative3)
if not bOkPositions then
error( ' MoveMachineAxesToPosition : error')
end
local AxesNames = EgtGetAllCurrAxesNames()
local dTHome = EgtGetAxisHomePos( AxesNames[1])
-- spostamento assi in posizione (la T non si sposta perchè si sposta il pezzo)
EgtSetAxisPos( AxesNames[2], dLinear2)
EgtSetAxisPos( AxesNames[3], dLinear3)
EgtSetAxisPos( AxesNames[4], dRotative1)
EgtSetAxisPos( AxesNames[5], dRotative2)
if dRotative3 then
EgtSetAxisPos( AxesNames[6], dRotative3)
end
return dLinear1 - dTHome
end
-------------------------------------------------------------------------------------------------------------
local function CheckCollisionPoint( sAxis, ptOnToolTipCenter, vtHead, vtAux, Part, bCannotSplitRestLength, sRestLengthSideForPreSimulation, bCheckOnlyRestlength)
-- spostamento assi macchina in posizione
local dDeltaXHeadOffset = MoveMachineAxesToPosition( ptOnToolTipCenter, vtHead, vtAux)
-- si recuperano gli id delle geometrie dell'asse con cui controllare la collisione
local idCollisionGroup = EgtGetFirstNameInGroup( EgtGetAxisId( sAxis), 'COLLISION')
local idCollisionGroupOther = EgtGetFirstNameInGroup( EgtGetAxisId( sAxis), 'OTHER_COLLISION') or GDB_ID.NULL
local CollisionGroupEntitiesId = EgtGetAllInGroup( idCollisionGroup)
local CollisionGroupOtherEntitiesId = EgtGetAllInGroup( idCollisionGroupOther)
-- si tengono solo gli elementi trimesh
local CollisionSurfTmId = {}
for i = 1, #CollisionGroupEntitiesId do
if EgtGetType( CollisionGroupEntitiesId[i]) == GDB_TY.SRF_MESH then
local idCollisionSurfTmCopy = EgtCopyGlob( CollisionGroupEntitiesId[i], Part.idTempGroup)
EgtMove( idCollisionSurfTmCopy, Vector3d( dDeltaXHeadOffset, 0, 0), GDB_RT.GLOB)
table.insert( CollisionSurfTmId, idCollisionSurfTmCopy)
end
end
-- se presenti geometrie nel gruppo other si aggiungono anche quelle
if CollisionGroupOtherEntitiesId and #CollisionGroupOtherEntitiesId > 0 then
for i = 1, #CollisionGroupOtherEntitiesId do
if EgtGetType( CollisionGroupOtherEntitiesId[i]) == GDB_TY.SRF_MESH then
local idCollisionOtherSurfTmCopy = EgtCopyGlob( CollisionGroupOtherEntitiesId[i], Part.idTempGroup)
EgtMove( idCollisionOtherSurfTmCopy, Vector3d( dDeltaXHeadOffset, 0, 0), GDB_RT.GLOB)
table.insert( CollisionSurfTmId, idCollisionOtherSurfTmCopy)
end
end
end
-- check collisione con pezzo
local bCollisionFoundPiece = false
if not bCheckOnlyRestlength then
local idCheckCollisionTm = Part.idBoxTm
-- se testa o coda attaccate, si considerano nella superficie di collisione
if bCannotSplitRestLength then
local b3CheckCollision = BeamLib.GetPartBoxWithHeadTail( Part, sRestLengthSideForPreSimulation)
idCheckCollisionTm = EgtSurfTmBBox( Part.idTempGroup, b3CheckCollision, false, GDB_RT.GLOB)
end
for i = 1, #CollisionSurfTmId do
bCollisionFoundPiece = EgtCDeSolidSolid( idCheckCollisionTm, CollisionSurfTmId[i], BeamData.COLL_SIC)
if not type( bCollisionFoundPiece) == "boolean" then
error( 'Presimulation fail')
end
if EgtGetDebugLevel() >= 3 and bCollisionFoundPiece then
EgtSetColor( CollisionSurfTmId[i], RED())
end
if bCollisionFoundPiece then
break
end
end
-- se trovata collisione con pezzo è inutile procedere con il grezzo
if bCollisionFoundPiece then
return true
end
end
-- check collisione con grezzo restante, se con il pezzo non c'è collisione e non è un taglio di testa o coda
local bCollisionFoundRestLength = false
if not ( bCollisionFoundPiece or bCannotSplitRestLength) then
local idRestLengthSurfFr = GetRestlengthSurfTm( Part, sRestLengthSideForPreSimulation)
if idRestLengthSurfFr then
for i = 1, #CollisionSurfTmId do
bCollisionFoundRestLength = EgtCDeSolidSolid( idRestLengthSurfFr, CollisionSurfTmId[i], BeamData.COLL_SIC)
if not type( bCollisionFoundRestLength) == "boolean" then
error( 'Presimulation fail')
end
if EgtGetDebugLevel() >= 3 and bCollisionFoundRestLength then
EgtSetColor( CollisionSurfTmId[i], ORANGE())
end
if bCollisionFoundRestLength then
break
end
end
end
end
return false, bCollisionFoundRestLength
end
-------------------------------------------------------------------------------------------------------------
-- controllo collisione con verifica intersezione trimesh e geometrie da macchina
local function CheckCollisionWithAxis( sAxis, MachiningParameters, OptionalParameters)
-- parametri obbligatori
local Edge = MachiningParameters.Edge
local vtNFace = MachiningParameters.vtNFace
local vtHead = MachiningParameters.vtHead
local Part = MachiningParameters.Part
local Tool = MachiningParameters.Tool
local dDepthToMachine = MachiningParameters.dDepthToMachine
-- parametri opzionali
OptionalParameters = OptionalParameters or {}
local bCheckOnlyRestlength = OptionalParameters.bCheckOnlyRestlength or false
local sRestLengthSideForPreSimulation = OptionalParameters.sRestLengthSideForPreSimulation or 'Tail'
local bCannotSplitRestLength = OptionalParameters.bCannotSplitRestLength or false
local vtAux = OptionalParameters.vtAux
-- se normale faccia non parallela a direzione testa c'è qualcosa che non va
if not AreSameOrOppositeVectorApprox( vtNFace, vtHead) then
error( 'CheckCollisionWithAxis : invalid directions')
end
-- punti notevoli della lavorazione in cui fare il check
local PointsToCheck = OptionalParameters.PointsToCheck or GetCollisionPointsToCheck( Edge, dDepthToMachine)
-- punti sul tip dell'utensile, in centro
local PointsOnToolTipCenter = {}
for i = 1, #PointsToCheck do
PointsOnToolTipCenter[i] = PreSimulationLib.GetPointOnToolTipCenter( PointsToCheck[i], vtHead, vtNFace, Edge.vtN, Tool)
end
local bMoveAfterSplit = false
-- se almeno in un punto c'è collisione con il pezzo si ritorna collisione
-- se non si trova collisione si ritorna se è necessario separare prima di effettuare la lavorazione (ossia non c'è collisione con il pezzo ma c'è con il grezzo restante)
for i = 1, #PointsOnToolTipCenter do
local bCollisionFoundPiece, bCollisionFoundRestLength = CheckCollisionPoint( sAxis, PointsOnToolTipCenter[i], vtHead, vtAux, Part, bCannotSplitRestLength, sRestLengthSideForPreSimulation, bCheckOnlyRestlength)
-- se trovata collisione con pezzo è inutile controllare gli altri punti
if bCollisionFoundPiece then
return true
-- se trovata collisione con grezzo si setta che la lavorazione è da fare dopo separazione e si prosegue con gli altri punti
elseif bCollisionFoundRestLength then
bMoveAfterSplit = true
end
end
-- se si arriva qui significa che non è stata trovata alcuna collisione con pezzo
return false, bMoveAfterSplit
end
-------------------------------------------------------------------------------------------------------------
function PreSimulationLib.CheckCollision( sBladeEngagement, Parameters, OptionalParameters)
local bCollisionFound
local bMoveAfterSplitL3, bMoveAfterSplitR3, bMoveAfterSplitR2, bMoveAfterSplitR1
-- parametri obbligatori
local Edge = Parameters.Edge
local vtNFace = Parameters.vtNFace
local Tool = Parameters.Tool
-- parametri opzionali, in parte da far transitare
OptionalParameters = OptionalParameters or {}
local OptionalParametersCheckCollisionWithAxis = {}
OptionalParametersCheckCollisionWithAxis.bCheckOnlyRestlength = false
OptionalParametersCheckCollisionWithAxis.PointsToCheck = OptionalParameters.PointsToCheck or nil
OptionalParametersCheckCollisionWithAxis.sRestLengthSideForPreSimulation = OptionalParameters.sRestLengthSideForPreSimulation or 'Tail'
OptionalParametersCheckCollisionWithAxis.bCannotSplitRestLength = OptionalParameters.bCannotSplitRestLength or false
OptionalParametersCheckCollisionWithAxis.sBlockedAxis = OptionalParameters.sBlockedAxis
OptionalParametersCheckCollisionWithAxis.vtAux = OptionalParameters.vtAux
local sBlockedAxis = OptionalParameters.sBlockedAxis
local bIsDicing = OptionalParameters.bIsDicing or false
local bDisableRealElevationCheck = OptionalParameters.bDisableRealElevationCheck or false
local bCheckOnlyRestlengthForAxisABC = false
-- se cubetti in modalità standard (no DownUp) gli assi AB e C si controllano solo con grezzo (ci sarebbe collisione con il materiale già rimosso controllando AB e C con pezzo)
if bIsDicing and ( sBladeEngagement == 'Standard') then
bCheckOnlyRestlengthForAxisABC = true
-- se l'elevazione reale (rispetto al pezzo + eventuale materiale in testa/coda) è maggiore del massimo materiale è sempre collisione
-- TODO rifare con funzione
elseif not bDisableRealElevationCheck then
local Edge = Parameters.Edge
local vtNFace = Parameters.vtNFace
local dDepthToMachine = Parameters.dDepthToMachine
local b3BoxForElevationCheck = BBox3d( Parameters.Part.b3Part)
-- se è un taglio di testa o coda va aggiunto il sovramateriale
if OptionalParametersCheckCollisionWithAxis.bCannotSplitRestLength then
b3BoxForElevationCheck = BeamLib.GetPartBoxWithHeadTail( Parameters.Part, OptionalParametersCheckCollisionWithAxis.sRestLengthSideForPreSimulation)
end
-- trimesh rettangolare con un lato corrispondente al lato da lavorare e larghezza come spessore utensile
local idTrimesh = EgtSurfTmRectangle( Parameters.Part.idTempGroup, Edge.ptStart, Edge.ptEnd, Edge.ptEnd + vtNFace * Parameters.Tool.dThickness, GDB_RT.GLOB)
local vtNTrimesh = EgtSurfTmFacetNormVersor( idTrimesh, 0, GDB_ID.ROOT)
-- se trimesh con normale opposta a quella del lato, si inverte (non si sa a priori che verso avrà)
if not AreSameVectorApprox( Edge.vtN, vtNTrimesh) then
EgtInvertSurf( idTrimesh)
end
local dRealElevation = EgtSurfTmFacetElevationInBBox( idTrimesh, 0, b3BoxForElevationCheck, true, GDB_ID.ROOT)
local dRealDepthToMachine = ( dRealElevation - Parameters.Edge.dElevation + dDepthToMachine)
if dRealDepthToMachine > Parameters.Tool.dMaxDepth + 10 * GEO.EPS_SMALL then
return true
end
end
-- SCC
local nSCC = Tool.SetupInfo.GetSCC( Edge.vtN, Edge.vtEdge, vtNFace)
-- si settano utensile, SCC e asse bloccato per il controllo collisione
local bOkTool = EgtSetCalcTool( Tool.sName, Tool.sHead, Tool.nExit)
if not bOkTool then
error( 'CheckCollisionWithAxis : cannot set calc tool')
end
EgtSetCalcSolCh( nSCC)
if sBlockedAxis and type( sBlockedAxis) == "string" then
local BlockedAxis = EgtSplitString( sBlockedAxis, '=')
EgtSetRotAxisBlock( BlockedAxis[1], tonumber( BlockedAxis[2]))
end
-- nomi degli assi con cui controllare la collisione
local AxesNames = EgtGetAllCurrAxesNames()
local sL3 = AxesNames[3]
local sR3 = AxesNames[6]
local sR2 = AxesNames[5]
local sR1 = AxesNames[4]
-- ultimo asse lineare prima dei rotativi (solitamente Z) si controlla sempre
bCollisionFound, bMoveAfterSplitL3 = CheckCollisionWithAxis( sL3, Parameters, OptionalParametersCheckCollisionWithAxis)
-- assi rotativi: se richiesto si controlla la collisione solo col grezzo
OptionalParametersCheckCollisionWithAxis.bCheckOnlyRestlength = bCheckOnlyRestlengthForAxisABC
if sR3 and not bCollisionFound then
bCollisionFound, bMoveAfterSplitR3 = CheckCollisionWithAxis( sR3, Parameters, OptionalParametersCheckCollisionWithAxis)
end
if not bCollisionFound then
bCollisionFound, bMoveAfterSplitR2 = CheckCollisionWithAxis( sR2, Parameters, OptionalParametersCheckCollisionWithAxis)
end
if not bCollisionFound then
bCollisionFound, bMoveAfterSplitR1 = CheckCollisionWithAxis( sR1, Parameters, OptionalParametersCheckCollisionWithAxis)
end
local bMoveAfterSplit = bMoveAfterSplitL3 or bMoveAfterSplitR3 or bMoveAfterSplitR2 or bMoveAfterSplitR1
return bCollisionFound, bMoveAfterSplit
end
-------------------------------------------------------------------------------------------------------------
return PreSimulationLib
+122
View File
@@ -0,0 +1,122 @@
-- BeamLib.lua by Egalware s.r.l. 2025/11/24
-- Libreria calcolo tempo automatismo
-- Tabella per definizione modulo
local TimeLib = {}
EgtOutLog( ' TimeLib started', 1)
TimeLib.__index = TimeLib
function TimeLib.new()
local TimeLibInstance = setmetatable({}, TimeLib)
TimeLibInstance.dStartTime = os.clock()
TimeLibInstance.Measurements = {}
return TimeLibInstance
end
-- reset entire timer
function TimeLib:start()
self.dStartTime = os.clock()
self.Measurements = {}
end
-- start elapsed measurement for a specific name
function TimeLib:startElapsed(sName)
local sMeasurementName = sName or "Default"
local dNow = os.clock()
if not self.Measurements[sMeasurementName] then
self.Measurements[sMeasurementName] = {
dStart = dNow,
dLast = 0,
dCumulative = 0,
dRecent = 0,
nCount = 0
}
else
self.Measurements[sMeasurementName].dStart = dNow
end
end
-- stop elapsed measurement (increments count and updates cumulative)
function TimeLib:stopElapsed(sName)
local sMeasurementName = sName or "Default"
local dNow = os.clock()
local Measurement = self.Measurements[sMeasurementName]
if Measurement and Measurement.dStart then
local dDuration = dNow - Measurement.dStart
Measurement.dRecent = dDuration
Measurement.dCumulative = Measurement.dCumulative + dDuration
Measurement.dLast = dNow
Measurement.nCount = Measurement.nCount + 1
Measurement.dStart = nil
else
-- if stop called without start, initialize with zero
self.Measurements[sMeasurementName] = {
dStart = nil,
dLast = dNow,
dCumulative = 0,
dRecent = 0,
nCount = 0
}
end
end
-- reset elapsed for a specific measurement
function TimeLib:resetElapsed(sName)
local sMeasurementName = sName or "Default"
self.Measurements[sMeasurementName] = nil
end
-- return elapsed times: total, cumulative, recent, count
function TimeLib:getElapsed(sName)
local dTotal = os.clock() - self.dStartTime
local sMeasurementName = sName or "Default"
local Measurement = self.Measurements[sMeasurementName]
if Measurement then
return dTotal, Measurement.dCumulative, Measurement.dRecent, Measurement.nCount
else
return dTotal, nil, nil, 0
end
end
-- log elapsed times for one measurement
function TimeLib:logElapsed(sName)
local dTotal, dCumulative, dRecent, nCount = self:getElapsed(sName)
local sMeasurementName = sName or "Default"
if dCumulative then
EgtOutLog(string.format(
"%s(#%d): recent %.3f, cumulative %.3f, total %.3f",
sMeasurementName, nCount, dRecent, dCumulative, dTotal))
else
EgtOutLog(string.format("Total %.3f (no '%s' measurement started)",
dTotal, sMeasurementName))
end
end
-- log elapsed times for all measurements
function TimeLib:logAllElapsed()
local dTotal = os.clock() - self.dStartTime
if next(self.Measurements) == nil then
EgtOutLog(string.format("Total %.3f (no measurements started)", dTotal))
return
end
for sMeasurementName, Measurement in pairs(self.Measurements) do
local dCumulative = Measurement.dCumulative
local dRecent = Measurement.dRecent
local nCount = Measurement.nCount
EgtOutLog(string.format(
"%s(#%d): recent %.3f, cumulative %.3f, total %.3f",
sMeasurementName, nCount, dRecent, dCumulative, dTotal))
end
end
return TimeLib
+74 -457
View File
@@ -1,479 +1,96 @@
-- BeamNestProcess.lua by Egaltech s.r.l. 2023/01/15
-- Gestione nesting automatico travi
-- 2022/10/05 Piccole modifiche per far funzionare correttamente i compilati.
-- 2022/10/06 Corretto bug che moltiplicava i pezzi se erano presenti più grezzi della stessa sezione.
-- 2023/01/15 Piccole correzioni.
-- BeamNestProcess.lua by Egalware s.r.l. 2026/05/11
-- Gestione nesting automatico travi anche oblique
-- Intestazioni
require( 'EgtBase')
_ENV = EgtProtectGlobal()
EgtEnableDebug( false)
EgtEnableDebug( true)
-- Per test
--NEST = {}
--NEST.FILE = 'c:\\TechnoEssetre7\\EgtData\\Prods\\0010\\Bar_10_1.btl'
--NEST.MACHINE = 'Essetre-90480019_MW'
--NEST.FLAG = 3
-- Include
local BeamLib = require( 'BeamLib')
local sLog = ' +++ BeamNestProcess : ' .. NEST.FILE .. ', ' .. NEST.MACHINE .. ', ' .. LEN[1]
EgtOutLog( sLog)
----------------------------------------------------------------------------------------------------------
-- stati che definiscono rotazione / inversione della parte
local STATE = {
STD = 1, -- Standard
ROT180 = 2, -- Rotazione 180deg attorno a X+
INV = 3, -- Inversione (rotazione 180deg attorno a Z+)
INV_ROT180 = 4 -- Inversione + rotazione
}
-- flag per abilitare statistiche in log
local bLogStat = false
----------------------------------------------------------------------------------------------------------
-- inventario grezzi
local RawInventory = {
Stock = {},
ActiveBeams = {}
}
-- Cancello file di log specifico
local sLogFile = EgtChangePathExtension( NEST.FILE, '.txt')
EgtEraseFile( sLogFile)
-- Funzioni per scrittura su file di log specifico
local function WriteErrToLogFile( nErr, sMsg, nRot, nCutId, nTaskId)
local hFile = io.open( sLogFile, 'a')
hFile:write( 'ERR=' .. tostring( nErr) .. '\n')
hFile:write( sMsg .. '\n')
hFile:write( 'ROT=' .. tostring( nRot or 0) .. '\n')
hFile:write( 'CUTID=' .. tostring( nCutId or 0) .. '\n')
hFile:write( 'TASKID=' .. tostring( nTaskId or 0) .. '\n')
hFile:close()
end
local function WriteTimeToLogFile( dTime)
local hFile = io.open( sLogFile, 'a')
hFile:write( 'TIME=' .. EgtNumToString( dTime) .. '\n')
hFile:close()
end
-- Funzione per gestire visualizzazione dopo errore
local function PostErrView( nErr, sMsg)
if nErr ~= 0 and ( NEST.FLAG == 1 or NEST.FLAG == 2 or NEST.FLAG == 5) then
EgtSetView( SCE_VD.ISO_SW, false)
EgtZoom( SCE_ZM.ALL)
EgtOutBox( sMsg, 'BatchProcess (err=' .. tostring( nErr) .. ')', 'ERRORS')
end
end
-- Funzione per gestire visualizzazione dopo warning
local function PostWarnView( nWarn, sMsg)
if nWarn ~= 0 and ( NEST.FLAG == 1 or NEST.FLAG == 2 or NEST.FLAG == 5) then
EgtSetView( SCE_VD.ISO_SW, false)
EgtZoom( SCE_ZM.ALL)
EgtOutBox( sMsg, 'BatchProcess (wrn=' .. tostring( nWarn) .. ')', 'WARNINGS')
end
end
-- Funzione per aggiornare dati ausiliari
local function UpdateAuxData( sAuxFile)
local bModif = false
-- Se definito LOAD90, aggiorno
local sLoad90 = EgtGetStringFromIni( 'AuxData', 'LOAD90', '', sAuxFile)
if sLoad90 ~= '' then
local BtlInfoId = EgtGetFirstNameInGroup( GDB_ID.ROOT, 'BtlInfo') or GDB_ID.NULL
EgtSetInfo( BtlInfoId, 'LOAD90', sLoad90)
bModif = true
end
return bModif
end
local function PartsToFill( Parts)
local nToFill = 0
for i = 1, #Parts do
if Parts[i].Cnt > 0 then
nToFill = nToFill + Parts[i].Cnt
end
end
return nToFill
end
local function ExecMaximumFilling( Raw, Parts)
-- Inizializzo maximum filler
EgtMaxFillerStart()
-- Inserisco i pezzi
for i = 1, #Parts do
EgtMaxFillerAddPart( i, Parts[i].Len, Parts[i].DispLen or Parts[i].Len, Parts[i].Cnt or 1)
end
-- Eseguo l'ottimizzazione
--EgtStartCounter()
EgtMaxFillerCompute( Raw.LenToFill, Raw.StartGap, Raw.MidGap, Raw.EndGap, Raw.SortType)
--local dTime = EgtStopCounter()
-- Recupero i risultati
local nFilledParts, nDiffParts, dTotFillRatio = EgtMaxFillerGetResults()
local OneRes = {}
for i = 0, nDiffParts - 1 do
local nPartId, nCount = EgtMaxFillerGetOneResult( i)
table.insert( OneRes, { Id=nPartId, Count=nCount})
end
--return { FilledParts=nFilledParts, DiffParts=nDiffParts, FillRatio=dTotFillRatio, Time=dTime, Data=OneRes}
return { FilledParts=nFilledParts, DiffParts=nDiffParts, FillRatio=dTotFillRatio, Data=OneRes}
end
-- Funzione per trovare nome MachGroup
local function NewMachGroupName()
local nMachGroupId = EgtGetFirstMachGroup()
if not nMachGroupId then return 1 end
local nMaxMachGroup = 0
while nMachGroupId do
sMachGroupName = EgtGetMachGroupName(nMachGroupId)
local nMachGroupName = tonumber(sMachGroupName)
if nMachGroupName > nMaxMachGroup then
nMaxMachGroup = nMachGroupName
end
nMachGroupId = EgtGetNextMachGroup(nMachGroupId)
end
return nMaxMachGroup + 1
end
local function TotRawCount(Raws)
local nTotRaws = 0
for RawIndex = 1, #Raws do
nTotRaws = nTotRaws + Raws[RawIndex].Count
end
return nTotRaws
end
local function TotPartLen(Parts)
local nTotPartLen = 0
for PartIndex = 1, #Parts do
nTotPartLen = nTotPartLen + ( Parts[PartIndex].Len * Parts[PartIndex].Cnt)
end
return nTotPartLen
end
-- Imposto direttorio libreria specializzata per Travi
EgtAddToPackagePath( NEST.BASEDIR .. '\\LuaLibs\\?.lua')
-- Imposto la macchina corrente e verifico sia abilitata per la lavorazione delle Travi
EgtSetCurrMachine( NEST.MACHINE)
local sMachDir = EgtGetCurrMachineDir()
if not EgtExistsFile( sMachDir .. '\\Beam\\BeamData.lua') then
NEST.ERR = 12
NEST.MSG = 'Error not configured for beam machine : ' .. sMachine
WriteErrToLogFile( NEST.ERR, NEST.MSG)
PostErrView( NEST.ERR, NEST.MSG)
return
end
-- Elimino direttori altre macchine e imposto direttorio macchina corrente per ricerca librerie
EgtRemoveBaseMachineDirFromPackagePath()
EgtAddToPackagePath( sMachDir .. '\\Beam\\?.lua')
-- Inizializzo contatori errori e avvisi
local nErrCnt = 0
local nWarnCnt = 0
-- Grezzi
local Raws = {}
-- creo tabella dei grezzi
for nIndex, nLen in pairs( LEN) do
Raws[tonumber(nIndex)] = {LenToFill = nLen, StartGap = NEST.STARTOFFSET, MidGap = NEST.OFFSET, EndGap = 0, SortType = -1}
end
for nIndex, nQty in pairs( QTY) do
Raws[tonumber(nIndex)].Count = nQty
end
-- cerco il grezzo con la lunghezza maggiore, epurata dello start gap
local maxRawLenToFillNoStartGap = 0
for RawIndex = 1, #Raws do
if Raws[RawIndex].Count > 0 then
maxRawLenToFillNoStartGap = max( maxRawLenToFillNoStartGap, Raws[RawIndex].LenToFill - Raws[RawIndex].StartGap)
end
end
-- Pezzi
local Parts = {}
-- ciclo su pezzi per aggiungerli al nesting
local dTotLen = 0
for nPartId, nCount in pairs( PART) do
-- recupero lunghezza pezzo
local Len = EgtGetInfo( nPartId, "L", 'd')
local DispLen = EgtIf( Len <= 1000, 2000, 0) --EgtIf( Len <= 2000, max( 2000, 6000 - Len), 0)
-- aggiungo il pezzo solo se ci sta nel grezzo più lungo a disposizione
if Len < maxRawLenToFillNoStartGap then
for nCntIndex = 1 , nCount do
table.insert( Parts, {Id = nPartId, Len = Len, DispLen = DispLen, Cnt = 1})
dTotLen = dTotLen + Len
end
end
end
-- lunghezza totale pezzi
local dTotPartLen = TotPartLen( Parts)
-- calcolo media delle barre necessarie
local NeededRawsForType = {}
for RawIndex = 1, #Raws do
NeededRawsForType[RawIndex] = min( ceil( dTotPartLen / Raws[RawIndex].LenToFill), Raws[RawIndex].Count)
end
local RawQtySum = 0
for NeededRawIndex = 1, #NeededRawsForType do
RawQtySum = RawQtySum + NeededRawsForType[NeededRawIndex]
end
local MediumRawQty = ceil( RawQtySum / #NeededRawsForType)
if MediumRawQty > 1 then
MediumRawQty = MediumRawQty - 1
end
-- lista dei risultati
local ResultList = {}
local BestResult = nil
local BestResultIndex = nil
-- riordino lista pezzi per lunghezza
table.sort( Parts, function( B1, B2) return B1.Len < B2.Len end)
local function NestSolutionByIndex( Index)
-- creo copia lista raw
local TempRaws = {}
for TempRawIndex = 1, #Raws do
table.insert(TempRaws, {LenToFill = Raws[TempRawIndex].LenToFill, StartGap = Raws[TempRawIndex].StartGap, MidGap = Raws[TempRawIndex].MidGap, EndGap = Raws[TempRawIndex].EndGap, SortType = Raws[TempRawIndex].SortType, Count = Raws[TempRawIndex].Count})
end
-- recupero pezzi corti
local ShortList = {}
local LongList = {}
for PartIndex = 1, #Parts do
if PartIndex <= Index then
table.insert( ShortList, Parts[PartIndex])
else
table.insert( LongList, Parts[PartIndex])
end
Parts[PartIndex].Cnt = 1
end
-- numero di pezzi piccoli per barra
local ShortCount = Index
local ShortForRaw = floor( ShortCount / MediumRawQty)
local ExtraShortForRaw = 0
if MediumRawQty > 0 then
ExtraShortForRaw = fmod( ShortCount, MediumRawQty)
end
-- creo lista pezzi corti singoli
local SingleShortList = {}
for ShortIndex = 1, #ShortList do
for ShortCount = 1, ShortList[ShortIndex].Cnt do
table.insert( SingleShortList, {Id = ShortList[ShortIndex].Id, Len = ShortList[ShortIndex].Len, DispLen = ShortList[ShortIndex].DispLen, Cnt = 1})
end
end
-- li divido per le barre previste
local RawsShortList = {}
local RawIndex = 0
local ShortRawIndex = 0
for ShortIndex = 1, #SingleShortList do
if ShortRawIndex > 0 then
table.insert( RawsShortList[RawIndex], SingleShortList[ShortIndex])
ShortRawIndex = ShortRawIndex - 1
else
table.insert( RawsShortList, {SingleShortList[ShortIndex]})
RawIndex = RawIndex + 1
ShortRawIndex = ShortForRaw + EgtIf( RawIndex <= ExtraShortForRaw, 1, 0) - 1
end
function RawInventory:BuildStock()
if #LEN ~= #QTY then
error( 'NestProcess: invalid stock data')
end
-- Ciclo fino ad esaurimento pezzi o barre
local dTotPartInRawLen = 0
local nRawTot = 0
local dRawTotLen = 0
local dTime = 0
local nCycle = 1
local CurrResult = {}
while TotRawCount( TempRaws) > 0 and PartsToFill( Parts) > 0 do
-- creo lista con pezzi lunghi e pezzi corti di questo Cycle
local PartsToNest = {}
for PartIndex = 1, #LongList do
table.insert( PartsToNest, LongList[PartIndex])
end
for CycleIndex = 1, #RawsShortList do
if CycleIndex <= nCycle then
for PartIndex = 1, #RawsShortList[CycleIndex] do
table.insert( PartsToNest, RawsShortList[CycleIndex][PartIndex])
end
end
end
-- se non ci sono pezzi da nestare, esco
if PartsToFill( PartsToNest) <= 0 then
break
end
-- Eseguo ottimizzazione per ogni lunghezza di barra
local Results = {}
for RawIndex = 1, #TempRaws do
if TempRaws[RawIndex].Count > 0 then
Results[RawIndex] = ExecMaximumFilling( TempRaws[RawIndex], PartsToNest)
else
Results[RawIndex] = { FillRatio = 0.001, LenToFill = 1000, DiffParts = 0}
end
end
-- verifico quale e' quella con meno scarto
local nMinWasteRawIndex = GDB_ID.NULL
local dMinWaste = 100000
for ResultIndex = 1, #Results do
if Results[ResultIndex] then
local dWaste = (1 - Results[ResultIndex].FillRatio) * TempRaws[ResultIndex].LenToFill
if Results[ResultIndex].DiffParts > 0 and dWaste < dMinWaste then
dMinWaste = dWaste
nMinWasteRawIndex = ResultIndex
end
end
end
-- verifico se ci sono pezzi
if nMinWasteRawIndex > 0 and Results[nMinWasteRawIndex] and Results[nMinWasteRawIndex].DiffParts > 0 then
-- riporto barra e pezzi nel risultato corrente
local CurrBar = { BarLen = TempRaws[nMinWasteRawIndex].LenToFill, Parts = {}}
local CurrX = TempRaws[nMinWasteRawIndex].StartGap
local nInfoIndex = 1
for i = 1, Results[nMinWasteRawIndex].DiffParts do
local PartIndex = Results[nMinWasteRawIndex].Data[i].Id
local PartId = PartsToNest[PartIndex].Id
local dLen = PartsToNest[PartIndex].Len
for j = 1, Results[nMinWasteRawIndex].Data[i].Count do
-- creo pezzo copia
CurrPart = { Index = nInfoIndex, PartId = PartId, PosX = CurrX}
table.insert( CurrBar.Parts, CurrPart)
CurrX = CurrX + dLen + TempRaws[nMinWasteRawIndex].MidGap
nInfoIndex = nInfoIndex + 1
end
end
table.insert( CurrResult, CurrBar)
dTotPartInRawLen = dTotPartInRawLen + ( Results[nMinWasteRawIndex].FillRatio * TempRaws[nMinWasteRawIndex].LenToFill)
nRawTot = nRawTot + 1
dRawTotLen = dRawTotLen + TempRaws[nMinWasteRawIndex].LenToFill
-- Aggiorno per prossima iterazione
TempRaws[nMinWasteRawIndex].Count = TempRaws[nMinWasteRawIndex].Count - 1
for i = 1, Results[nMinWasteRawIndex].DiffParts do
local PartId = Results[nMinWasteRawIndex].Data[i].Id
PartsToNest[PartId].Cnt = PartsToNest[PartId].Cnt - Results[nMinWasteRawIndex].Data[i].Count
end
else
-- se non sono riuscito ad inserire alcun pezzo esco dal ciclo perche' non ci sono pezzi inseribili
break
end
nCycle = nCycle + 1
end
-- riporto risultato in lista
ResultList[Index] = dTotPartInRawLen
if not BestResult or not BestResultIndex or
( dTotPartInRawLen > ResultList[BestResultIndex] + 0.02 or ( abs( dTotPartInRawLen - ResultList[BestResultIndex]) < 0.02 and dRawTotLen < BestResult.RawTotLen - 0.02)) then
BestResult = CurrResult
BestResult.RawTotLen = dRawTotLen
BestResultIndex = Index
for i = 1, #LEN do
self.Stock[#self.Stock + 1] = {
Length = LEN[i],
Count = QTY[i]
}
end
return RawInventory
end
local CycleCount = 0
function RawInventory:AddActiveBeam()
-- TODO da fare
end
local MinTime = 10 + pow( 3, ceil( log10( #Parts)) - 1)
if bLogStat then EgtOutLog('MinTime: ' .. MinTime ) end
local MaxTime = 30 + pow( 7, ceil( log10( #Parts)) - 1)
if bLogStat then EgtOutLog('MaxTime: ' .. MaxTime ) end
local TargetRatio = 0.98
local dTargetRatioLen = TargetRatio * dTotLen
if bLogStat then EgtOutLog('TargetRatioLen: ' .. dTargetRatioLen ) end
local CurrTime = 0
----------------------------------------------------------------------------------------------------------
-- PartTemplates (informazioni geometriche pezzi univoci) e JobPool (lista di tutti i singoli pezzi, multipli compresi, da nestare)
local PartTemplates = {}
local JobPool = {}
local function NestSolutionFromSP( StartingPoint, OscillationStep)
-- ciclo sulle possibilita' da un punto di origine con uno step fisso
local CurrResultIndex = StartingPoint
NestSolutionByIndex( StartingPoint)
if OscillationStep == 0 then return end
local CycleIndex = 1
local nOutOfBoundary = 0
while nOutOfBoundary ~= 3 do
CurrTime = EgtStopCounter() / 1000
if bLogStat then EgtOutLog('CurrTime: ' .. CurrTime ) end
if bLogStat then EgtOutLog('BestRatio: ' .. dTotLen / BestResult.RawTotLen ) end
-- se e' passato il tempo massimo, o e' passato il tempo minimo, ha inserito tutti i pezzi e la percentuale di utilizzo del materiale e' maggiore della soglia
if CurrTime > MaxTime or ( CurrTime > MinTime and ResultList[BestResultIndex] > dTotLen - 0.1 and ( dTotLen / BestResult.RawTotLen ) >= TargetRatio) then
if bLogStat then EgtOutLog('Brake') end
break
end
local bCurrOutOfBoundary = false
if CurrResultIndex < 0 then
bCurrOutOfBoundary = true
if nOutOfBoundary == 2 then
nOutOfBoundary = 3
else
nOutOfBoundary = 1
end
end
if CurrResultIndex > #Parts then
bCurrOutOfBoundary = true
if nOutOfBoundary == 1 then
nOutOfBoundary = 3
else
nOutOfBoundary = 2
end
end
if not bCurrOutOfBoundary and not ResultList[CurrResultIndex] then
NestSolutionByIndex( CurrResultIndex)
if bLogStat then EgtOutLog('CurrResultIndex: ' .. CurrResultIndex ) end
if bLogStat then EgtOutLog('Result: ' .. ResultList[CurrResultIndex]) end
CycleCount = CycleCount + 1
end
CurrResultIndex = StartingPoint + EgtIf( CycleIndex % 2 == 0, (CycleIndex / 2) * OscillationStep, -( ( CycleIndex + 1) / 2) * OscillationStep )
CycleIndex = CycleIndex + 1
function PartTemplates:AddPart( id)
PartTemplates[id] = {}
PartTemplates[id].dLength = EgtGetInfo( id, 'L', 'd')
-- TODO qua gli stati abilitati dovranno arrivare dalle alternatives
local VerticesHead = EgtSplitString( EgtGetInfo( id, 'HEADOFFSETX', 'd'))
local vtNHead = Vector3d( EgtSplitString( EgtGetInfo( id, 'HEADVTN', 'd')))
local VerticesTail = EgtSplitString( EgtGetInfo( id, 'TAILOFFSETX', 'd'))
local vtNTail = Vector3d( EgtSplitString( EgtGetInfo( id, 'TAILVTN', 'd')))
PartTemplates[id].States = {
[STATE.STD] = {
Head = { Vertices = VerticesHead, vtN = vtNHead},
Tail = { Vertices = VerticesTail, vtN = vtNTail}
},
[STATE.ROT180] = {
Head = { Vertices = BeamLib.RotateTableFromIndex( VerticesHead, 3), vtN = vtNHead},
Tail = { Vertices = BeamLib.RotateTableFromIndex( VerticesTail, 3), vtN = vtNHead}
},
[STATE.INV] = {
Head = { Vertices = VerticesTail, vtN = vtNTail},
Tail = { Vertices = VerticesHead, vtN = vtNHead}
},
[STATE.INV_ROT180] = {
Head = { Vertices = BeamLib.RotateTableFromIndex( VerticesTail, 3), vtN = vtNHead},
Tail = { Vertices = BeamLib.RotateTableFromIndex( VerticesHead, 3), vtN = vtNHead}
}
}
end
-- creazione combinata (si cicla una sola volta) di entrambe le tabelle
local function BuildPartTemplatesAndJobPool()
for id, nCount in pairs( PART) do
PartTemplates:AddPart( id)
end
end
-- lancio calcolo
EgtStartCounter()
local StartingResult = floor( #Parts * 0.3)
if bLogStat then EgtOutLog('StartingResult: ' .. StartingResult ) end
--local Step = floor( #Parts / 10) * floor( log10( #Parts))
local nDividendo = pow( 10, floor( log10( #Parts)) - 1)
nDividendo = EgtIf( nDividendo ~= 1, nDividendo, 10)
local Step = floor( #Parts / nDividendo) * floor( log10( #Parts))
if bLogStat then EgtOutLog('Step: ' .. Step ) end
NestSolutionFromSP( StartingResult, Step)
if Step > 1 then
NestSolutionFromSP( StartingResult, 1)
return PartTemplates, JobPool
end
-- creo gruppi di lavorazione per risultato
for MachGroupIndex = 1, #BestResult do
local CurrMachGroup = BestResult[ MachGroupIndex]
-- creo gruppo di lavorazione
local MachGroupName = NewMachGroupName()
nMachGroup = EgtAddMachGroup( MachGroupName)
EgtSetInfo( nMachGroup, "BARLEN", CurrMachGroup.BarLen)
EgtSetInfo( nMachGroup, "MATERIAL", NEST.MATERIAL)
EgtSetInfo( nMachGroup, "AUTONEST", 1)
-- scrivo dati per variabili P di comunicazione con la macchina in gruppo di lavorazione
EgtSetInfo( nMachGroup, "PRODID", NEST.PRODID)
EgtSetInfo( nMachGroup, "PATTID", nMachGroup)
-- Disegno i pezzi
for i = 1, #CurrMachGroup.Parts do
local CurrPart = CurrMachGroup.Parts[ i]
-- creo pezzo copia
local nPartDuploId = EgtDuploNew( CurrPart.PartId)
EgtSetInfo( nMachGroup, "PART" .. CurrPart.Index, nPartDuploId .. "," .. CurrPart.PosX)
end
end
-- creo grezzi per ogni gruppo di lavorazione
local nRawCnt = 0
local nRawTot = ResultList[BestResultIndex]
_G.BEAM = {}
BEAM.FILE = NEST.FILE
BEAM.MACHINE = NEST.MACHINE
BEAM.FLAG = 6 -- CREATE_PANEL
BEAM.BASEDIR = NEST.BASEDIR
nMachGroup = EgtGetFirstMachGroup()
while nMachGroup do
local nNextMachGroup = EgtGetNextMachGroup( nMachGroup)
EgtSetCurrMachGroup( nMachGroup)
if EgtGetInfo( nMachGroup, "AUTONEST",'i') == 1 then
EgtRemoveInfo( nMachGroup, "AUTONEST")
EgtSetInfo( nMachGroup, "UPDATEUI", 1)
local bOk, sErr = pcall( dofile, BEAM.BASEDIR .. "\\BatchProcessNew.lua")
if not bOk then
EgtOutLog( 'Error in BatchProcessNew.lua call (' .. ( sErr or '') ..')')
end
nRawCnt = nRawCnt + 1
-- aggiorno interfaccia
EgtProcessEvents( 200 + ( nRawCnt / nRawTot * 100), 0)
end
nMachGroup = nNextMachGroup
end
EgtResetCurrMachGroup()
NEST.ERR = 0
EgtOutLog( ' +++ BeamNestProcess completed')
RawInventory:BuildStock()
BuildPartTemplatesAndJobPool()
+556
View File
@@ -0,0 +1,556 @@
-- BeamNestProcess.lua by Egaltech s.r.l. 2023/01/15
-- Gestione nesting automatico travi
-- 2022/10/05 Piccole modifiche per far funzionare correttamente i compilati.
-- 2022/10/06 Corretto bug che moltiplicava i pezzi se erano presenti più grezzi della stessa sezione.
-- 2023/01/15 Piccole correzioni.
-- Intestazioni
require( 'EgtBase')
_ENV = EgtProtectGlobal()
EgtEnableDebug( false)
-- Per test
--NEST = {}
--NEST.FILE = 'c:\\TechnoEssetre7\\EgtData\\Prods\\0010\\Bar_10_1.btl'
--NEST.MACHINE = 'Essetre-90480019_MW'
--NEST.FLAG = 3
local sLog = ' +++ BeamNestProcess : ' .. NEST.FILE
EgtOutLog( sLog)
-- flag per abilitare statistiche in log
local bLogStat = false
-- Cancello file di log specifico
local sLogFile = EgtChangePathExtension( NEST.FILE, '.txt')
EgtEraseFile( sLogFile)
-- Funzioni per scrittura su file di log specifico
local function WriteErrToLogFile( nErr, sMsg, nRot, nCutId, nTaskId)
local hFile = io.open( sLogFile, 'a')
hFile:write( 'ERR=' .. tostring( nErr) .. '\n')
hFile:write( sMsg .. '\n')
hFile:write( 'ROT=' .. tostring( nRot or 0) .. '\n')
hFile:write( 'CUTID=' .. tostring( nCutId or 0) .. '\n')
hFile:write( 'TASKID=' .. tostring( nTaskId or 0) .. '\n')
hFile:close()
end
local function WriteTimeToLogFile( dTime)
local hFile = io.open( sLogFile, 'a')
hFile:write( 'TIME=' .. EgtNumToString( dTime) .. '\n')
hFile:close()
end
-- Funzione per gestire visualizzazione dopo errore
local function PostErrView( nErr, sMsg)
if nErr ~= 0 and ( NEST.FLAG == 1 or NEST.FLAG == 2 or NEST.FLAG == 5) then
EgtSetView( SCE_VD.ISO_SW, false)
EgtZoom( SCE_ZM.ALL)
EgtOutBox( sMsg, 'BatchProcess (err=' .. tostring( nErr) .. ')', 'ERRORS')
end
end
-- Funzione per gestire visualizzazione dopo warning
local function PostWarnView( nWarn, sMsg)
if nWarn ~= 0 and ( NEST.FLAG == 1 or NEST.FLAG == 2 or NEST.FLAG == 5) then
EgtSetView( SCE_VD.ISO_SW, false)
EgtZoom( SCE_ZM.ALL)
EgtOutBox( sMsg, 'BatchProcess (wrn=' .. tostring( nWarn) .. ')', 'WARNINGS')
end
end
-- Funzione per aggiornare dati ausiliari
local function UpdateAuxData( sAuxFile)
local bModif = false
-- Se definito LOAD90, aggiorno
local sLoad90 = EgtGetStringFromIni( 'AuxData', 'LOAD90', '', sAuxFile)
if sLoad90 ~= '' then
local BtlInfoId = EgtGetFirstNameInGroup( GDB_ID.ROOT, 'BtlInfo') or GDB_ID.NULL
EgtSetInfo( BtlInfoId, 'LOAD90', sLoad90)
bModif = true
end
return bModif
end
local function PartsToFill( Parts)
local nToFill = 0
for i = 1, #Parts do
if Parts[i].Cnt > 0 then
nToFill = nToFill + Parts[i].Cnt
end
end
return nToFill
end
local function ExecMaximumFilling( Raw, Parts)
-- Inizializzo maximum filler
EgtMaxFillerStart()
-- Inserisco i pezzi
for i = 1, #Parts do
EgtMaxFillerAddPart( i, Parts[i].Len, Parts[i].DispLen or Parts[i].Len, Parts[i].Cnt or 1)
end
-- Eseguo l'ottimizzazione
EgtMaxFillerCompute( Raw.LenToFill, Raw.StartGap, Raw.MidGap, Raw.EndGap, Raw.SortType)
-- Recupero i risultati
local nFilledParts, nDiffParts, dTotFillRatio = EgtMaxFillerGetResults()
local OneRes = {}
for i = 0, nDiffParts - 1 do
local nPartId, nCount = EgtMaxFillerGetOneResult( i)
table.insert( OneRes, { Id=nPartId, Count=nCount})
end
--return { FilledParts=nFilledParts, DiffParts=nDiffParts, FillRatio=dTotFillRatio, Time=dTime, Data=OneRes}
return { FilledParts=nFilledParts, DiffParts=nDiffParts, FillRatio=dTotFillRatio, Data=OneRes}
end
-- Funzione per trovare nome MachGroup
local function NewMachGroupName()
local nMachGroupId = EgtGetFirstMachGroup()
if not nMachGroupId then return 1 end
local nMaxMachGroup = 0
while nMachGroupId do
sMachGroupName = EgtGetMachGroupName(nMachGroupId)
local nMachGroupName = tonumber(sMachGroupName)
if nMachGroupName > nMaxMachGroup then
nMaxMachGroup = nMachGroupName
end
nMachGroupId = EgtGetNextMachGroup(nMachGroupId)
end
return nMaxMachGroup + 1
end
local function TotRawCount(Raws)
local nTotRaws = 0
for RawIndex = 1, #Raws do
nTotRaws = nTotRaws + Raws[RawIndex].Count
end
return nTotRaws
end
local function TotPartLen(Parts)
local nTotPartLen = 0
for PartIndex = 1, #Parts do
nTotPartLen = nTotPartLen + ( Parts[PartIndex].Len * Parts[PartIndex].Cnt)
end
return nTotPartLen
end
-- Imposto direttorio libreria specializzata per Travi
EgtAddToPackagePath( NEST.BASEDIR .. '\\LuaLibs\\?.lua')
-- recupero cartella macchine
local sIniFilePath = EgtGetIniFile()
local MachineDirPath = EgtGetStringFromIni( 'Mach', 'MachinesDir', '', sIniFilePath)
-- Verifico che tutte le macchine siano abilitate per la lavorazione delle Travi
for MachineIndex = 1, #NEST.MACHINELIST do
local sMachDir = MachineDirPath .. '\\' .. NEST.MACHINELIST[MachineIndex]
if not EgtExistsFile( sMachDir .. '\\Beam\\BeamData.lua') then
NEST.ERR = 12
NEST.MSG = 'Error not configured for beam machine : ' .. sMachine
WriteErrToLogFile( NEST.ERR, NEST.MSG)
PostErrView( NEST.ERR, NEST.MSG)
return
end
end
---- Imposto la macchina corrente e verifico sia abilitata per la lavorazione delle Travi
--EgtSetCurrMachine( NEST.MACHINE)
--local sMachDir = EgtGetCurrMachineDir()
--if not EgtExistsFile( sMachDir .. '\\Beam\\BeamData.lua') then
-- NEST.ERR = 12
-- NEST.MSG = 'Error not configured for beam machine : ' .. sMachine
-- WriteErrToLogFile( NEST.ERR, NEST.MSG)
-- PostErrView( NEST.ERR, NEST.MSG)
-- return
--end
---- Elimino direttori altre macchine e imposto direttorio macchina corrente per ricerca librerie
--EgtRemoveBaseMachineDirFromPackagePath()
--EgtAddToPackagePath( sMachDir .. '\\Beam\\?.lua')
-- Inizializzo contatori errori e avvisi
local nErrCnt = 0
local nWarnCnt = 0
-- Grezzi
local Raws = {}
for nRawIndex = 1, #RAWLIST do
local Raw = RAWLIST[nRawIndex]
table.insert( Raws, {LenToFill = Raw.Len, StartGap = NEST.STARTOFFSET, MidGap = NEST.OFFSET, EndGap = 0, SortType = -1, Count = Raw.Qty})
end
-- cerco il grezzo con la lunghezza maggiore, epurata dello start gap
local maxRawLenToFillNoStartGap = 0
for RawIndex = 1, #Raws do
if Raws[RawIndex].Count > 0 then
maxRawLenToFillNoStartGap = max( maxRawLenToFillNoStartGap, Raws[RawIndex].LenToFill - Raws[RawIndex].StartGap)
end
end
-- Pezzi
local Parts = {}
-- ciclo su pezzi per aggiungerli al nesting
local dTotLen = 0
for nPartId, nCount in pairs( PARTLIST) do
-- recupero lunghezza pezzo
local Len = EgtGetInfo( nPartId, "L", 'd')
local DispLen = EgtIf( Len <= 1000, 2000, 0) --EgtIf( Len <= 2000, max( 2000, 6000 - Len), 0)
-- aggiungo il pezzo solo se ci sta nel grezzo più lungo a disposizione
if Len < maxRawLenToFillNoStartGap then
for nCntIndex = 1 , nCount do
table.insert( Parts, {Id = nPartId, Len = Len, DispLen = DispLen, Cnt = 1})
dTotLen = dTotLen + Len
end
end
end
-- lunghezza totale pezzi
local dTotPartLen = TotPartLen( Parts)
-- calcolo media delle barre necessarie
local NeededRawsForType = {}
for RawIndex = 1, #Raws do
NeededRawsForType[RawIndex] = min( ceil( dTotPartLen / Raws[RawIndex].LenToFill), Raws[RawIndex].Count)
end
local RawQtySum = 0
for NeededRawIndex = 1, #NeededRawsForType do
RawQtySum = RawQtySum + NeededRawsForType[NeededRawIndex]
end
local MediumRawQty = ceil( RawQtySum / #NeededRawsForType)
if MediumRawQty > 1 then
MediumRawQty = MediumRawQty - 1
end
-- lista dei risultati
local ResultList = {}
local BestResult = nil
local BestResultIndex = nil
-- riordino lista pezzi per lunghezza
table.sort( Parts, function( B1, B2) return B1.Len < B2.Len end)
local function NestSolutionByIndex( Index)
-- creo copia lista raw
local TempRaws = {}
for TempRawIndex = 1, #Raws do
table.insert(TempRaws, {LenToFill = Raws[TempRawIndex].LenToFill, StartGap = Raws[TempRawIndex].StartGap, MidGap = Raws[TempRawIndex].MidGap, EndGap = Raws[TempRawIndex].EndGap, SortType = Raws[TempRawIndex].SortType, Count = Raws[TempRawIndex].Count})
end
-- recupero pezzi corti
local ShortList = {}
local LongList = {}
for PartIndex = 1, #Parts do
if PartIndex <= Index then
table.insert( ShortList, Parts[PartIndex])
else
table.insert( LongList, Parts[PartIndex])
end
Parts[PartIndex].Cnt = 1
end
-- numero di pezzi piccoli per barra
local ShortCount = Index
local ShortForRaw = floor( ShortCount / MediumRawQty)
local ExtraShortForRaw = 0
if MediumRawQty > 0 then
ExtraShortForRaw = fmod( ShortCount, MediumRawQty)
end
-- creo lista pezzi corti singoli
local SingleShortList = {}
for ShortIndex = 1, #ShortList do
for ShortCount = 1, ShortList[ShortIndex].Cnt do
table.insert( SingleShortList, {Id = ShortList[ShortIndex].Id, Len = ShortList[ShortIndex].Len, DispLen = ShortList[ShortIndex].DispLen, Cnt = 1})
end
end
-- li divido per le barre previste
local RawsShortList = {}
local RawIndex = 0
local ShortRawIndex = 0
for ShortIndex = 1, #SingleShortList do
if ShortRawIndex > 0 then
table.insert( RawsShortList[RawIndex], SingleShortList[ShortIndex])
ShortRawIndex = ShortRawIndex - 1
else
table.insert( RawsShortList, {SingleShortList[ShortIndex]})
RawIndex = RawIndex + 1
ShortRawIndex = ShortForRaw + EgtIf( RawIndex <= ExtraShortForRaw, 1, 0) - 1
end
end
-- Ciclo fino ad esaurimento pezzi o barre
local dTotPartInRawLen = 0
local nRawTot = 0
local dRawTotLen = 0
local dTime = 0
local nCycle = 1
local CurrResult = {}
while TotRawCount( TempRaws) > 0 and PartsToFill( Parts) > 0 do
-- creo lista con pezzi lunghi e pezzi corti di questo Cycle
local PartsToNest = {}
for PartIndex = 1, #LongList do
table.insert( PartsToNest, LongList[PartIndex])
end
for CycleIndex = 1, #RawsShortList do
if CycleIndex <= nCycle then
for PartIndex = 1, #RawsShortList[CycleIndex] do
table.insert( PartsToNest, RawsShortList[CycleIndex][PartIndex])
end
end
end
-- se non ci sono pezzi da nestare, esco
if PartsToFill( PartsToNest) <= 0 then
break
end
-- Eseguo ottimizzazione per ogni lunghezza di barra
local Results = {}
for RawIndex = 1, #TempRaws do
if TempRaws[RawIndex].Count > 0 then
Results[RawIndex] = ExecMaximumFilling( TempRaws[RawIndex], PartsToNest)
else
Results[RawIndex] = { FillRatio = 0.001, LenToFill = 1000, DiffParts = 0}
end
end
-- verifico quale e' quella con meno scarto
local nMinWasteRawIndex = GDB_ID.NULL
local dMinWaste = 100000
for ResultIndex = 1, #Results do
if Results[ResultIndex] then
local dWaste = (1 - Results[ResultIndex].FillRatio) * TempRaws[ResultIndex].LenToFill
if Results[ResultIndex].DiffParts > 0 and dWaste < dMinWaste then
dMinWaste = dWaste
nMinWasteRawIndex = ResultIndex
end
end
end
-- verifico se ci sono pezzi
if nMinWasteRawIndex > 0 and Results[nMinWasteRawIndex] and Results[nMinWasteRawIndex].DiffParts > 0 then
-- riporto barra e pezzi nel risultato corrente
local CurrBar = { BarLen = TempRaws[nMinWasteRawIndex].LenToFill, Parts = {}}
local CurrX = TempRaws[nMinWasteRawIndex].StartGap
local nInfoIndex = 1
for i = 1, Results[nMinWasteRawIndex].DiffParts do
local PartIndex = Results[nMinWasteRawIndex].Data[i].Id
local PartId = PartsToNest[PartIndex].Id
local dLen = PartsToNest[PartIndex].Len
for j = 1, Results[nMinWasteRawIndex].Data[i].Count do
-- creo pezzo copia
CurrPart = { Index = nInfoIndex, PartId = PartId, PosX = CurrX}
table.insert( CurrBar.Parts, CurrPart)
CurrX = CurrX + dLen + TempRaws[nMinWasteRawIndex].MidGap
nInfoIndex = nInfoIndex + 1
end
end
table.insert( CurrResult, CurrBar)
dTotPartInRawLen = dTotPartInRawLen + ( Results[nMinWasteRawIndex].FillRatio * TempRaws[nMinWasteRawIndex].LenToFill)
nRawTot = nRawTot + 1
dRawTotLen = dRawTotLen + TempRaws[nMinWasteRawIndex].LenToFill
-- Aggiorno per prossima iterazione
TempRaws[nMinWasteRawIndex].Count = TempRaws[nMinWasteRawIndex].Count - 1
for i = 1, Results[nMinWasteRawIndex].DiffParts do
local PartId = Results[nMinWasteRawIndex].Data[i].Id
PartsToNest[PartId].Cnt = PartsToNest[PartId].Cnt - Results[nMinWasteRawIndex].Data[i].Count
end
else
-- se non sono riuscito ad inserire alcun pezzo esco dal ciclo perche' non ci sono pezzi inseribili
break
end
nCycle = nCycle + 1
end
-- riporto risultato in lista
ResultList[Index] = dTotPartInRawLen
if not BestResult or not BestResultIndex or
( dTotPartInRawLen > ResultList[BestResultIndex] + 0.02 or ( abs( dTotPartInRawLen - ResultList[BestResultIndex]) < 0.02 and dRawTotLen < BestResult.RawTotLen - 0.02)) then
BestResult = CurrResult
BestResult.RawTotLen = dRawTotLen
BestResultIndex = Index
end
end
local CycleCount = 0
local MinTime = 10 + pow( 3, ceil( log10( #Parts)) - 1)
if bLogStat then EgtOutLog('MinTime: ' .. MinTime ) end
local MaxTime = 30 + pow( 7, ceil( log10( #Parts)) - 1)
if bLogStat then EgtOutLog('MaxTime: ' .. MaxTime ) end
local TargetRatio = 0.98
local dTargetRatioLen = TargetRatio * dTotLen
if bLogStat then EgtOutLog('TargetRatioLen: ' .. dTargetRatioLen ) end
local CurrTime = 0
local function NestSolutionFromSP( StartingPoint, OscillationStep)
-- ciclo sulle possibilita' da un punto di origine con uno step fisso
local CurrResultIndex = StartingPoint
NestSolutionByIndex( StartingPoint)
if OscillationStep == 0 then return end
local CycleIndex = 1
local nOutOfBoundary = 0
while nOutOfBoundary ~= 3 do
CurrTime = EgtStopCounter() / 1000
if bLogStat then EgtOutLog('CurrTime: ' .. CurrTime ) end
if bLogStat then EgtOutLog('BestRatio: ' .. dTotLen / BestResult.RawTotLen ) end
-- se e' passato il tempo massimo, o e' passato il tempo minimo, ha inserito tutti i pezzi e la percentuale di utilizzo del materiale e' maggiore della soglia
if CurrTime > MaxTime or ( CurrTime > MinTime and ResultList[BestResultIndex] > dTotLen - 0.1 and ( dTotLen / BestResult.RawTotLen ) >= TargetRatio) then
if bLogStat then EgtOutLog('Brake') end
break
end
local bCurrOutOfBoundary = false
if CurrResultIndex < 0 then
bCurrOutOfBoundary = true
if nOutOfBoundary == 2 then
nOutOfBoundary = 3
else
nOutOfBoundary = 1
end
end
if CurrResultIndex > #Parts then
bCurrOutOfBoundary = true
if nOutOfBoundary == 1 then
nOutOfBoundary = 3
else
nOutOfBoundary = 2
end
end
if not bCurrOutOfBoundary and not ResultList[CurrResultIndex] then
NestSolutionByIndex( CurrResultIndex)
if bLogStat then EgtOutLog('CurrResultIndex: ' .. CurrResultIndex ) end
if bLogStat then EgtOutLog('Result: ' .. ResultList[CurrResultIndex]) end
CycleCount = CycleCount + 1
end
CurrResultIndex = StartingPoint + EgtIf( CycleIndex % 2 == 0, (CycleIndex / 2) * OscillationStep, -( ( CycleIndex + 1) / 2) * OscillationStep )
CycleIndex = CycleIndex + 1
end
end
-- lancio calcolo
EgtStartCounter()
local StartingResult = floor( #Parts * 0.3)
if bLogStat then EgtOutLog('StartingResult: ' .. StartingResult ) end
--local Step = floor( #Parts / 10) * floor( log10( #Parts))
local nDividendo = pow( 10, floor( log10( #Parts)) - 1)
nDividendo = EgtIf( nDividendo ~= 1, nDividendo, 10)
local Step = floor( #Parts / nDividendo) * floor( log10( #Parts))
if bLogStat then EgtOutLog('Step: ' .. Step ) end
NestSolutionFromSP( StartingResult, Step)
if Step > 1 then
NestSolutionFromSP( StartingResult, 1)
end
-- se esiste un MachGorup precedente
local nPreviousNestIndex = 0
local nLastMachGroupId = EgtGetLastMachGroup()
if nLastMachGroupId then
nPreviousNestIndex = EgtGetInfo( nLastMachGroupId, "NestIndex", 'i')
end
for nMachineIndex = 1, #NEST.MACHINELIST do
local sMachineName = NEST.MACHINELIST[nMachineIndex]
-- imposto macchina corrente
EgtSetCurrMachine( sMachineName)
-- elimino direttori altre macchine e imposto direttorio macchina corrente per ricerca librerie
local sMachDir = EgtGetCurrMachineDir()
EgtRemoveBaseMachineDirFromPackagePath()
EgtAddToPackagePath( sMachDir .. '\\Beam\\?.lua')
-- creo gruppi di lavorazione per risultato
for nMachGroupIndex = 1, #BestResult do
local CurrMachGroup = BestResult[nMachGroupIndex]
-- creo gruppo di lavorazione
local MachGroupName = NewMachGroupName()
nMachGroup = EgtAddMachGroup( MachGroupName)
EgtSetInfo( nMachGroup, "NestIndex", nPreviousNestIndex + nMachGroupIndex)
EgtSetInfo( nMachGroup, "BARLEN", CurrMachGroup.BarLen)
EgtSetInfo( nMachGroup, "MATERIAL", NEST.MATERIAL)
EgtSetInfo( nMachGroup, "AUTONEST", 1)
-- scrivo dati per variabili P di comunicazione con la macchina in gruppo di lavorazione
EgtSetInfo( nMachGroup, "PRODID", NEST.PRODID)
EgtSetInfo( nMachGroup, "PATTID", nMachGroup)
-- Disegno i pezzi
for i = 1, #CurrMachGroup.Parts do
local CurrPart = CurrMachGroup.Parts[ i]
-- creo pezzo copia
local nPartDuploId = EgtDuploNew( CurrPart.PartId)
EgtSetInfo( nMachGroup, "PART" .. CurrPart.Index, nPartDuploId .. "," .. CurrPart.PosX)
-- se esiste lista etichette
local sTagList = ''
if #NEST.MACHINELIST == 1 then
sTagList = EgtGetInfo( CurrPart.PartId, 'LuxTagList')
else
sTagList = EgtGetInfo( CurrPart.PartId, 'LuxTagList' .. nMachineIndex)
if not sTagList or #sTagList <= 0 then
sTagList = EgtGetInfo( CurrPart.PartId, 'LuxTagList')
EgtSetInfo( CurrPart.PartId, 'LuxTagList' .. nMachineIndex, sTagList)
end
end
if sTagList and #sTagList then
-- elimino eventuali liste etichette da duplo
EgtRemoveInfo( nPartDuploId, 'LuxTagList')
for nRemoveTagMachineIndex = 1, nMachineIndex - 1 do
EgtRemoveInfo( nPartDuploId, 'LuxTagList' .. nRemoveTagMachineIndex)
end
-- recupero liste etichette usate e non
local TagTypeList = EgtSplitString( sTagList, ';')
local UnusedTagList = {}
local UsedTagList = {}
if #TagTypeList == 1 then
UnusedTagList = EgtSplitString( sTagList, ',')
else
if TagTypeList[1] and #TagTypeList[1] > 0 then
UnusedTagList = EgtSplitString( TagTypeList[1], ',')
end
if TagTypeList[2] and #TagTypeList[2] > 0 then
UsedTagList = EgtSplitString( TagTypeList[2], ',')
end
end
local nAssignedTagIndex = #UnusedTagList
local sAssignedTag = UnusedTagList[nAssignedTagIndex]
-- creo stringa per info etichette aggiornata
local sNewTagList = ''
for nUnusedTagIndex = 1, nAssignedTagIndex - 1 do
sNewTagList = sNewTagList .. UnusedTagList[nUnusedTagIndex] .. EgtIf( nUnusedTagIndex < nAssignedTagIndex - 1, ',', '')
end
sNewTagList = sNewTagList .. ';' .. UnusedTagList[nAssignedTagIndex] .. EgtIf( #UsedTagList > 0, ',', '')
for nUsedTagIndex = 1, #UsedTagList do
sNewTagList = sNewTagList .. UsedTagList[nUsedTagIndex] .. EgtIf( nUsedTagIndex < #UsedTagList, ',', '')
end
-- assegno etichetta a nuovo duplo
EgtSetInfo( nPartDuploId, 'LuxTag', sAssignedTag)
if #NEST.MACHINELIST == 1 then
EgtSetInfo( CurrPart.PartId, 'LuxTagList', sNewTagList)
else
EgtSetInfo( CurrPart.PartId, 'LuxTagList' .. nMachineIndex, sNewTagList)
end
end
end
end
EgtResetCurrMachGroup()
end
-- creo grezzi per ogni gruppo di lavorazione
local nRawCnt = 0
local nRawTot = ResultList[BestResultIndex]
_G.BEAM = {}
BEAM.FILE = NEST.FILE
--BEAM.MACHINE = NEST.MACHINE
BEAM.FLAG = 6 -- CREATE_PANEL
BEAM.BASEDIR = NEST.BASEDIR
nMachGroup = EgtGetFirstMachGroup()
while nMachGroup do
local nNextMachGroup = EgtGetNextMachGroup( nMachGroup)
EgtSetCurrMachGroup( nMachGroup)
if EgtGetInfo( nMachGroup, "AUTONEST",'i') == 1 then
EgtRemoveInfo( nMachGroup, "AUTONEST")
EgtSetInfo( nMachGroup, "UPDATEUI", 1)
local bOk, sErr = pcall( dofile, BEAM.BASEDIR .. "\\BatchProcessNew.lua")
if not bOk then
EgtOutLog( 'Error in BatchProcessNew.lua call (' .. ( sErr or '') ..')')
end
nRawCnt = nRawCnt + 1
-- aggiorno interfaccia
EgtProcessEvents( 200 + ( nRawCnt / nRawTot * 100), 0)
end
nMachGroup = nNextMachGroup
end
EgtResetCurrMachGroup()
NEST.ERR = 0
EgtOutLog( ' +++ BeamNestProcess completed')
+477
View File
@@ -0,0 +1,477 @@
-- BeamNestProcess.lua by Egaltech s.r.l. 2023/01/15
-- Gestione nesting automatico travi
-- 2022/10/05 Piccole modifiche per far funzionare correttamente i compilati.
-- 2022/10/06 Corretto bug che moltiplicava i pezzi se erano presenti più grezzi della stessa sezione.
-- 2023/01/15 Piccole correzioni.
-- Intestazioni
require( 'EgtBase')
_ENV = EgtProtectGlobal()
EgtEnableDebug( false)
-- Per test
--NEST = {}
--NEST.FILE = 'c:\\TechnoEssetre7\\EgtData\\Prods\\0010\\Bar_10_1.btl'
--NEST.MACHINE = 'Essetre-90480019_MW'
--NEST.FLAG = 3
local sLog = ' +++ BeamNestProcess : ' .. NEST.FILE .. ', ' .. NEST.MACHINE .. ', ' .. LEN[1]
EgtOutLog( sLog)
-- flag per abilitare statistiche in log
local bLogStat = false
-- Cancello file di log specifico
local sLogFile = EgtChangePathExtension( NEST.FILE, '.txt')
EgtEraseFile( sLogFile)
-- Funzioni per scrittura su file di log specifico
local function WriteErrToLogFile( nErr, sMsg, nRot, nCutId, nTaskId)
local hFile = io.open( sLogFile, 'a')
hFile:write( 'ERR=' .. tostring( nErr) .. '\n')
hFile:write( sMsg .. '\n')
hFile:write( 'ROT=' .. tostring( nRot or 0) .. '\n')
hFile:write( 'CUTID=' .. tostring( nCutId or 0) .. '\n')
hFile:write( 'TASKID=' .. tostring( nTaskId or 0) .. '\n')
hFile:close()
end
local function WriteTimeToLogFile( dTime)
local hFile = io.open( sLogFile, 'a')
hFile:write( 'TIME=' .. EgtNumToString( dTime) .. '\n')
hFile:close()
end
-- Funzione per gestire visualizzazione dopo errore
local function PostErrView( nErr, sMsg)
if nErr ~= 0 and ( NEST.FLAG == 1 or NEST.FLAG == 2 or NEST.FLAG == 5) then
EgtSetView( SCE_VD.ISO_SW, false)
EgtZoom( SCE_ZM.ALL)
EgtOutBox( sMsg, 'BatchProcess (err=' .. tostring( nErr) .. ')', 'ERRORS')
end
end
-- Funzione per gestire visualizzazione dopo warning
local function PostWarnView( nWarn, sMsg)
if nWarn ~= 0 and ( NEST.FLAG == 1 or NEST.FLAG == 2 or NEST.FLAG == 5) then
EgtSetView( SCE_VD.ISO_SW, false)
EgtZoom( SCE_ZM.ALL)
EgtOutBox( sMsg, 'BatchProcess (wrn=' .. tostring( nWarn) .. ')', 'WARNINGS')
end
end
-- Funzione per aggiornare dati ausiliari
local function UpdateAuxData( sAuxFile)
local bModif = false
-- Se definito LOAD90, aggiorno
local sLoad90 = EgtGetStringFromIni( 'AuxData', 'LOAD90', '', sAuxFile)
if sLoad90 ~= '' then
local BtlInfoId = EgtGetFirstNameInGroup( GDB_ID.ROOT, 'BtlInfo') or GDB_ID.NULL
EgtSetInfo( BtlInfoId, 'LOAD90', sLoad90)
bModif = true
end
return bModif
end
local function PartsToFill( Parts)
local nToFill = 0
for i = 1, #Parts do
if Parts[i].Cnt > 0 then
nToFill = nToFill + Parts[i].Cnt
end
end
return nToFill
end
local function ExecMaximumFilling( Raw, Parts)
-- Inizializzo maximum filler
EgtMaxFillerStart()
-- Inserisco i pezzi
for i = 1, #Parts do
EgtMaxFillerAddPart( i, Parts[i].Len, Parts[i].DispLen or Parts[i].Len, Parts[i].Cnt or 1)
end
-- Eseguo l'ottimizzazione
EgtMaxFillerCompute( Raw.LenToFill, Raw.StartGap, Raw.MidGap, Raw.EndGap, Raw.SortType)
-- Recupero i risultati
local nFilledParts, nDiffParts, dTotFillRatio = EgtMaxFillerGetResults()
local OneRes = {}
for i = 0, nDiffParts - 1 do
local nPartId, nCount = EgtMaxFillerGetOneResult( i)
table.insert( OneRes, { Id=nPartId, Count=nCount})
end
--return { FilledParts=nFilledParts, DiffParts=nDiffParts, FillRatio=dTotFillRatio, Time=dTime, Data=OneRes}
return { FilledParts=nFilledParts, DiffParts=nDiffParts, FillRatio=dTotFillRatio, Data=OneRes}
end
-- Funzione per trovare nome MachGroup
local function NewMachGroupName()
local nMachGroupId = EgtGetFirstMachGroup()
if not nMachGroupId then return 1 end
local nMaxMachGroup = 0
while nMachGroupId do
sMachGroupName = EgtGetMachGroupName(nMachGroupId)
local nMachGroupName = tonumber(sMachGroupName)
if nMachGroupName > nMaxMachGroup then
nMaxMachGroup = nMachGroupName
end
nMachGroupId = EgtGetNextMachGroup(nMachGroupId)
end
return nMaxMachGroup + 1
end
local function TotRawCount(Raws)
local nTotRaws = 0
for RawIndex = 1, #Raws do
nTotRaws = nTotRaws + Raws[RawIndex].Count
end
return nTotRaws
end
local function TotPartLen(Parts)
local nTotPartLen = 0
for PartIndex = 1, #Parts do
nTotPartLen = nTotPartLen + ( Parts[PartIndex].Len * Parts[PartIndex].Cnt)
end
return nTotPartLen
end
-- Imposto direttorio libreria specializzata per Travi
EgtAddToPackagePath( NEST.BASEDIR .. '\\LuaLibs\\?.lua')
-- Imposto la macchina corrente e verifico sia abilitata per la lavorazione delle Travi
EgtSetCurrMachine( NEST.MACHINE)
local sMachDir = EgtGetCurrMachineDir()
if not EgtExistsFile( sMachDir .. '\\Beam\\BeamData.lua') then
NEST.ERR = 12
NEST.MSG = 'Error not configured for beam machine : ' .. sMachine
WriteErrToLogFile( NEST.ERR, NEST.MSG)
PostErrView( NEST.ERR, NEST.MSG)
return
end
-- Elimino direttori altre macchine e imposto direttorio macchina corrente per ricerca librerie
EgtRemoveBaseMachineDirFromPackagePath()
EgtAddToPackagePath( sMachDir .. '\\Beam\\?.lua')
-- Inizializzo contatori errori e avvisi
local nErrCnt = 0
local nWarnCnt = 0
-- Grezzi
local Raws = {}
-- creo tabella dei grezzi
for nIndex, nLen in pairs( LEN) do
Raws[tonumber(nIndex)] = {LenToFill = nLen, StartGap = NEST.STARTOFFSET, MidGap = NEST.OFFSET, EndGap = 0, SortType = -1}
end
for nIndex, nQty in pairs( QTY) do
Raws[tonumber(nIndex)].Count = nQty
end
-- cerco il grezzo con la lunghezza maggiore, epurata dello start gap
local maxRawLenToFillNoStartGap = 0
for RawIndex = 1, #Raws do
if Raws[RawIndex].Count > 0 then
maxRawLenToFillNoStartGap = max( maxRawLenToFillNoStartGap, Raws[RawIndex].LenToFill - Raws[RawIndex].StartGap)
end
end
-- Pezzi
local Parts = {}
-- ciclo su pezzi per aggiungerli al nesting
local dTotLen = 0
for nPartId, nCount in pairs( PART) do
-- recupero lunghezza pezzo
local Len = EgtGetInfo( nPartId, "L", 'd')
local DispLen = EgtIf( Len <= 1000, 2000, 0) --EgtIf( Len <= 2000, max( 2000, 6000 - Len), 0)
-- aggiungo il pezzo solo se ci sta nel grezzo più lungo a disposizione
if Len < maxRawLenToFillNoStartGap then
for nCntIndex = 1 , nCount do
table.insert( Parts, {Id = nPartId, Len = Len, DispLen = DispLen, Cnt = 1})
dTotLen = dTotLen + Len
end
end
end
-- lunghezza totale pezzi
local dTotPartLen = TotPartLen( Parts)
-- calcolo media delle barre necessarie
local NeededRawsForType = {}
for RawIndex = 1, #Raws do
NeededRawsForType[RawIndex] = min( ceil( dTotPartLen / Raws[RawIndex].LenToFill), Raws[RawIndex].Count)
end
local RawQtySum = 0
for NeededRawIndex = 1, #NeededRawsForType do
RawQtySum = RawQtySum + NeededRawsForType[NeededRawIndex]
end
local MediumRawQty = ceil( RawQtySum / #NeededRawsForType)
if MediumRawQty > 1 then
MediumRawQty = MediumRawQty - 1
end
-- lista dei risultati
local ResultList = {}
local BestResult = nil
local BestResultIndex = nil
-- riordino lista pezzi per lunghezza
table.sort( Parts, function( B1, B2) return B1.Len < B2.Len end)
local function NestSolutionByIndex( Index)
-- creo copia lista raw
local TempRaws = {}
for TempRawIndex = 1, #Raws do
table.insert(TempRaws, {LenToFill = Raws[TempRawIndex].LenToFill, StartGap = Raws[TempRawIndex].StartGap, MidGap = Raws[TempRawIndex].MidGap, EndGap = Raws[TempRawIndex].EndGap, SortType = Raws[TempRawIndex].SortType, Count = Raws[TempRawIndex].Count})
end
-- recupero pezzi corti
local ShortList = {}
local LongList = {}
for PartIndex = 1, #Parts do
if PartIndex <= Index then
table.insert( ShortList, Parts[PartIndex])
else
table.insert( LongList, Parts[PartIndex])
end
Parts[PartIndex].Cnt = 1
end
-- numero di pezzi piccoli per barra
local ShortCount = Index
local ShortForRaw = floor( ShortCount / MediumRawQty)
local ExtraShortForRaw = 0
if MediumRawQty > 0 then
ExtraShortForRaw = fmod( ShortCount, MediumRawQty)
end
-- creo lista pezzi corti singoli
local SingleShortList = {}
for ShortIndex = 1, #ShortList do
for ShortCount = 1, ShortList[ShortIndex].Cnt do
table.insert( SingleShortList, {Id = ShortList[ShortIndex].Id, Len = ShortList[ShortIndex].Len, DispLen = ShortList[ShortIndex].DispLen, Cnt = 1})
end
end
-- li divido per le barre previste
local RawsShortList = {}
local RawIndex = 0
local ShortRawIndex = 0
for ShortIndex = 1, #SingleShortList do
if ShortRawIndex > 0 then
table.insert( RawsShortList[RawIndex], SingleShortList[ShortIndex])
ShortRawIndex = ShortRawIndex - 1
else
table.insert( RawsShortList, {SingleShortList[ShortIndex]})
RawIndex = RawIndex + 1
ShortRawIndex = ShortForRaw + EgtIf( RawIndex <= ExtraShortForRaw, 1, 0) - 1
end
end
-- Ciclo fino ad esaurimento pezzi o barre
local dTotPartInRawLen = 0
local nRawTot = 0
local dRawTotLen = 0
local dTime = 0
local nCycle = 1
local CurrResult = {}
while TotRawCount( TempRaws) > 0 and PartsToFill( Parts) > 0 do
-- creo lista con pezzi lunghi e pezzi corti di questo Cycle
local PartsToNest = {}
for PartIndex = 1, #LongList do
table.insert( PartsToNest, LongList[PartIndex])
end
for CycleIndex = 1, #RawsShortList do
if CycleIndex <= nCycle then
for PartIndex = 1, #RawsShortList[CycleIndex] do
table.insert( PartsToNest, RawsShortList[CycleIndex][PartIndex])
end
end
end
-- se non ci sono pezzi da nestare, esco
if PartsToFill( PartsToNest) <= 0 then
break
end
-- Eseguo ottimizzazione per ogni lunghezza di barra
local Results = {}
for RawIndex = 1, #TempRaws do
if TempRaws[RawIndex].Count > 0 then
Results[RawIndex] = ExecMaximumFilling( TempRaws[RawIndex], PartsToNest)
else
Results[RawIndex] = { FillRatio = 0.001, LenToFill = 1000, DiffParts = 0}
end
end
-- verifico quale e' quella con meno scarto
local nMinWasteRawIndex = GDB_ID.NULL
local dMinWaste = 100000
for ResultIndex = 1, #Results do
if Results[ResultIndex] then
local dWaste = (1 - Results[ResultIndex].FillRatio) * TempRaws[ResultIndex].LenToFill
if Results[ResultIndex].DiffParts > 0 and dWaste < dMinWaste then
dMinWaste = dWaste
nMinWasteRawIndex = ResultIndex
end
end
end
-- verifico se ci sono pezzi
if nMinWasteRawIndex > 0 and Results[nMinWasteRawIndex] and Results[nMinWasteRawIndex].DiffParts > 0 then
-- riporto barra e pezzi nel risultato corrente
local CurrBar = { BarLen = TempRaws[nMinWasteRawIndex].LenToFill, Parts = {}}
local CurrX = TempRaws[nMinWasteRawIndex].StartGap
local nInfoIndex = 1
for i = 1, Results[nMinWasteRawIndex].DiffParts do
local PartIndex = Results[nMinWasteRawIndex].Data[i].Id
local PartId = PartsToNest[PartIndex].Id
local dLen = PartsToNest[PartIndex].Len
for j = 1, Results[nMinWasteRawIndex].Data[i].Count do
-- creo pezzo copia
CurrPart = { Index = nInfoIndex, PartId = PartId, PosX = CurrX}
table.insert( CurrBar.Parts, CurrPart)
CurrX = CurrX + dLen + TempRaws[nMinWasteRawIndex].MidGap
nInfoIndex = nInfoIndex + 1
end
end
table.insert( CurrResult, CurrBar)
dTotPartInRawLen = dTotPartInRawLen + ( Results[nMinWasteRawIndex].FillRatio * TempRaws[nMinWasteRawIndex].LenToFill)
nRawTot = nRawTot + 1
dRawTotLen = dRawTotLen + TempRaws[nMinWasteRawIndex].LenToFill
-- Aggiorno per prossima iterazione
TempRaws[nMinWasteRawIndex].Count = TempRaws[nMinWasteRawIndex].Count - 1
for i = 1, Results[nMinWasteRawIndex].DiffParts do
local PartId = Results[nMinWasteRawIndex].Data[i].Id
PartsToNest[PartId].Cnt = PartsToNest[PartId].Cnt - Results[nMinWasteRawIndex].Data[i].Count
end
else
-- se non sono riuscito ad inserire alcun pezzo esco dal ciclo perche' non ci sono pezzi inseribili
break
end
nCycle = nCycle + 1
end
-- riporto risultato in lista
ResultList[Index] = dTotPartInRawLen
if not BestResult or not BestResultIndex or
( dTotPartInRawLen > ResultList[BestResultIndex] + 0.02 or ( abs( dTotPartInRawLen - ResultList[BestResultIndex]) < 0.02 and dRawTotLen < BestResult.RawTotLen - 0.02)) then
BestResult = CurrResult
BestResult.RawTotLen = dRawTotLen
BestResultIndex = Index
end
end
local CycleCount = 0
local MinTime = 10 + pow( 3, ceil( log10( #Parts)) - 1)
if bLogStat then EgtOutLog('MinTime: ' .. MinTime ) end
local MaxTime = 30 + pow( 7, ceil( log10( #Parts)) - 1)
if bLogStat then EgtOutLog('MaxTime: ' .. MaxTime ) end
local TargetRatio = 0.98
local dTargetRatioLen = TargetRatio * dTotLen
if bLogStat then EgtOutLog('TargetRatioLen: ' .. dTargetRatioLen ) end
local CurrTime = 0
local function NestSolutionFromSP( StartingPoint, OscillationStep)
-- ciclo sulle possibilita' da un punto di origine con uno step fisso
local CurrResultIndex = StartingPoint
NestSolutionByIndex( StartingPoint)
if OscillationStep == 0 then return end
local CycleIndex = 1
local nOutOfBoundary = 0
while nOutOfBoundary ~= 3 do
CurrTime = EgtStopCounter() / 1000
if bLogStat then EgtOutLog('CurrTime: ' .. CurrTime ) end
if bLogStat then EgtOutLog('BestRatio: ' .. dTotLen / BestResult.RawTotLen ) end
-- se e' passato il tempo massimo, o e' passato il tempo minimo, ha inserito tutti i pezzi e la percentuale di utilizzo del materiale e' maggiore della soglia
if CurrTime > MaxTime or ( CurrTime > MinTime and ResultList[BestResultIndex] > dTotLen - 0.1 and ( dTotLen / BestResult.RawTotLen ) >= TargetRatio) then
if bLogStat then EgtOutLog('Brake') end
break
end
local bCurrOutOfBoundary = false
if CurrResultIndex < 0 then
bCurrOutOfBoundary = true
if nOutOfBoundary == 2 then
nOutOfBoundary = 3
else
nOutOfBoundary = 1
end
end
if CurrResultIndex > #Parts then
bCurrOutOfBoundary = true
if nOutOfBoundary == 1 then
nOutOfBoundary = 3
else
nOutOfBoundary = 2
end
end
if not bCurrOutOfBoundary and not ResultList[CurrResultIndex] then
NestSolutionByIndex( CurrResultIndex)
if bLogStat then EgtOutLog('CurrResultIndex: ' .. CurrResultIndex ) end
if bLogStat then EgtOutLog('Result: ' .. ResultList[CurrResultIndex]) end
CycleCount = CycleCount + 1
end
CurrResultIndex = StartingPoint + EgtIf( CycleIndex % 2 == 0, (CycleIndex / 2) * OscillationStep, -( ( CycleIndex + 1) / 2) * OscillationStep )
CycleIndex = CycleIndex + 1
end
end
-- lancio calcolo
EgtStartCounter()
local StartingResult = floor( #Parts * 0.3)
if bLogStat then EgtOutLog('StartingResult: ' .. StartingResult ) end
--local Step = floor( #Parts / 10) * floor( log10( #Parts))
local nDividendo = pow( 10, floor( log10( #Parts)) - 1)
nDividendo = EgtIf( nDividendo ~= 1, nDividendo, 10)
local Step = floor( #Parts / nDividendo) * floor( log10( #Parts))
if bLogStat then EgtOutLog('Step: ' .. Step ) end
NestSolutionFromSP( StartingResult, Step)
if Step > 1 then
NestSolutionFromSP( StartingResult, 1)
end
-- creo gruppi di lavorazione per risultato
for MachGroupIndex = 1, #BestResult do
local CurrMachGroup = BestResult[ MachGroupIndex]
-- creo gruppo di lavorazione
local MachGroupName = NewMachGroupName()
nMachGroup = EgtAddMachGroup( MachGroupName)
EgtSetInfo( nMachGroup, "BARLEN", CurrMachGroup.BarLen)
EgtSetInfo( nMachGroup, "MATERIAL", NEST.MATERIAL)
EgtSetInfo( nMachGroup, "AUTONEST", 1)
-- scrivo dati per variabili P di comunicazione con la macchina in gruppo di lavorazione
EgtSetInfo( nMachGroup, "PRODID", NEST.PRODID)
EgtSetInfo( nMachGroup, "PATTID", nMachGroup)
-- Disegno i pezzi
for i = 1, #CurrMachGroup.Parts do
local CurrPart = CurrMachGroup.Parts[ i]
-- creo pezzo copia
local nPartDuploId = EgtDuploNew( CurrPart.PartId)
EgtSetInfo( nMachGroup, "PART" .. CurrPart.Index, nPartDuploId .. "," .. CurrPart.PosX)
end
end
-- creo grezzi per ogni gruppo di lavorazione
local nRawCnt = 0
local nRawTot = ResultList[BestResultIndex]
_G.BEAM = {}
BEAM.FILE = NEST.FILE
BEAM.MACHINE = NEST.MACHINE
BEAM.FLAG = 6 -- CREATE_PANEL
BEAM.BASEDIR = NEST.BASEDIR
nMachGroup = EgtGetFirstMachGroup()
while nMachGroup do
local nNextMachGroup = EgtGetNextMachGroup( nMachGroup)
EgtSetCurrMachGroup( nMachGroup)
if EgtGetInfo( nMachGroup, "AUTONEST",'i') == 1 then
EgtRemoveInfo( nMachGroup, "AUTONEST")
EgtSetInfo( nMachGroup, "UPDATEUI", 1)
local bOk, sErr = pcall( dofile, BEAM.BASEDIR .. "\\BatchProcessNew.lua")
if not bOk then
EgtOutLog( 'Error in BatchProcessNew.lua call (' .. ( sErr or '') ..')')
end
nRawCnt = nRawCnt + 1
-- aggiorno interfaccia
EgtProcessEvents( 200 + ( nRawCnt / nRawTot * 100), 0)
end
nMachGroup = nNextMachGroup
end
EgtResetCurrMachGroup()
NEST.ERR = 0
EgtOutLog( ' +++ BeamNestProcess completed')
+31 -15
View File
@@ -7,7 +7,7 @@
-- Intestazioni
require( 'EgtBase')
_ENV = EgtProtectGlobal()
EgtEnableDebug( true)
EgtEnableDebug( false)
-- Imposto direttorio libreria specializzata per Travi
EgtAddToPackagePath( BEAM.BASEDIR .. '\\LuaLibs\\?.lua')
@@ -15,16 +15,13 @@ EgtAddToPackagePath( BEAM.BASEDIR .. '\\LuaLibs\\?.lua')
EgtAddToPackagePath( BEAM.BASEDIR .. '\\Strategies\\Standard\\?.lua')
EgtAddToPackagePath( BEAM.BASEDIR .. '\\StrategyLibs\\?.lua')
-- TODO forzatura calcolo con prerotazioni. Cancellare dopo che è stata aggiunta la gestione corretta
local bCalcBestPieceUnloadPosition = true
-- Verifico che la macchina corrente sia abilitata per la lavorazione delle Travi
local sMachDir = EgtGetCurrMachineDir()
if not sMachDir then
EgtOutBox( 'Errore nel caricamento della macchina corrente', 'Lavora Travi', 'ERROR')
return
end
if not EgtExistsFile( sMachDir .. '\\Beam\\BeamData.lua') then
if not EgtExistsFile( sMachDir .. '\\Beam\\BeamDataNew.lua') then
EgtOutBox( 'La macchina corrente non è configurata per lavorare travi', 'Lavora Travi', 'ERROR')
return
end
@@ -46,11 +43,15 @@ _G.package.loaded.FeatureLib = nil
_G.package.loaded.Identity = nil
_G.package.loaded.Logs = nil
_G.package.loaded.MachiningLib = nil
_G.package.loaded.PreSimulationLib = nil
_G.package.loaded.LeadInOutLib = nil
-- strategie di base sempre presenti
_G.package.loaded['HEADCUT\\HEADCUT'] = nil
_G.package.loaded['TAILCUT\\TAILCUT'] = nil
-- libreria macchina
_G.package.loaded.BeamData = nil
_G.package.loaded.BeamDataNew = nil
-- libreria calcolo tempo esecuzione
_G.package.loaded.TimeLib = 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.
@@ -76,7 +77,7 @@ end
PARTS = {} -- tabella contenente tutte le informazioni di ogni pezzo
-- Carico i dati globali
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
-- carico librerie
local BeamExec = require( 'BeamExec')
local BeamLib = require( 'BeamLib')
@@ -286,7 +287,7 @@ local function MyProcessBeams()
end
-- Sistemo le travi nel grezzo
local bOk, sErr = BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS, nil, bCalcBestPieceUnloadPosition)
local bOk, sErr = BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS, nil, false)
if not bOk then
EgtOutLog( sErr)
EgtOutBox( sErr, 'Lavora Travi', 'ERROR')
@@ -300,12 +301,10 @@ end
-- *** Inserimento delle lavorazioni nelle travi ***
-------------------------------------------------------------------------------------------------------------
local function MyProcessFeatures()
-- creo un gruppo temporaneo dove finiranno tutte le entità che non bisogna salvare, alla fine lo si cancella
local idTempGroup = BeamLib.CreateTempGroup()
BeamExec.GetProcessings( PARTS, bCalcBestPieceUnloadPosition)
BeamExec.GetCombinationMatrix( PARTS, bCalcBestPieceUnloadPosition)
BeamExec.ProcessMachinings( PARTS)
BeamExec.GetProcessings( PARTS, false)
BeamExec.GetCombinationMatrix( PARTS, false)
BeamExec.ProcessMachinings( PARTS, false)
local nErrCnt = 0
local nWarnCnt = 0
local sOutput = ''
@@ -320,7 +319,7 @@ local function MyProcessFeatures()
sMsg = string.gsub( sMsg or '', '\r', ' ', 10)
-- trovata almeno una strategia e feature lavorata completamente
if RESULT[i].sType == 'Feature' and RESULT[i].ChosenStrategy.sStatus == 'Completed' then
-- nulla da segnalare
sOutput = sOutput .. string.format( '[%d,%d] %s\n', RESULT[i].idCut, RESULT[i].idTask, sMsg or '')
-- trovata almeno una strategia ma nessuna applicabile oppure non trovata alcuna strategia
elseif RESULT[i].sType == 'Feature'
@@ -348,6 +347,7 @@ local function MyProcessFeatures()
end
-- cancello gruppo temporaneo
local idTempGroup = BeamLib.GetTempGroup()
EgtErase( idTempGroup)
if #sOutput > 0 then EgtOutLog( sOutput) end
@@ -365,11 +365,21 @@ end
-------------------------------------------------------------------------------------------------------------
-- *** Esecuzione ***
-------------------------------------------------------------------------------------------------------------
-- calcolo tempo esecuzione
TIMER:start()
EgtOutLog( ' Execution timer started')
-- script principale
if not MyProcessInputData() then return end
-- recupero parametri generali da progetto
BeamExec.GetGeneralParameters()
-- creo un gruppo temporaneo dove finiranno tutte le entità che non bisogna salvare, alla fine lo si cancella
BeamLib.CreateTempGroup()
if not MyProcessBeams() then return end
if not GetDataConfig() then return end
@@ -377,4 +387,10 @@ if not GetDataConfig() then return end
-- Abilito Vmill
EgtSetInfo( EgtGetCurrMachGroup(), 'Vm', '1')
if not MyProcessFeatures() then return end
MyProcessFeatures()
-- log tempi di esecuzione
if EgtGetDebugLevel() >= 3 then
TIMER:logAllElapsed()
end
+8 -4
View File
@@ -66,7 +66,7 @@
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" }, { "sStrategyId": "STR0010" } ]
},
{ "sName": "Bevel-1-Through",
"sImage": "ConfigStrategy\\Cut-1-Through.png",
"sImage": "ConfigStrategy\\Bevel-1-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" }, { "sStrategyId": "STR0010" } ]
}
]
@@ -227,6 +227,10 @@
{ "sName": "Cut-1-Through",
"sImage": "ConfigStrategy\\Cut-1-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" } ]
},
{ "sName": "DoubleBevel-2-Through",
"sImage": "ConfigStrategy\\DoubleBevel-2-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" }, { "sStrategyId": "STR0010"} ]
}
]
},
@@ -684,7 +688,7 @@
"TopologyList" : [
{ "sName": "Feature",
"sImage": "ConfigStrategy\\ScarfJoint.png",
"StrategyList" : [ ]
"StrategyList" : [ { "sStrategyId": "STR0009" }]
}
]
},
@@ -837,8 +841,8 @@
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "",
"StrategyList" : [ ]
"sImage": "ConfigStrategy\\ProfileHead.png",
"StrategyList" : [ { "sStrategyId": "STR0015" } ]
}
]
},
+53 -9
View File
@@ -1,10 +1,10 @@
[
{
"nGroup": "MACHINE",
"nGroup": "PIECE LOADING",
"sName": "GEN_sPiecesLoadingPosition",
"sNameNge": "GEN_PIECES_LOADING",
"sValue": "BEST_POSITION",
"sValue": "BTL_POSITION",
"sDescriptionShort": "Part loading position",
"sDescriptionLong": "",
"sType": "combo",
@@ -12,24 +12,46 @@
"Choices": [
{
"sValue": "BTL_POSITION",
"sDescriptionShort": "Last piece position as BTL",
"sDescriptionShort": "Loading position from BTL, no pre-rotation",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "BEST_ROTATION",
"sDescriptionShort": "Allow piece rotations",
"sValue": "STD_PRE_ROTATION",
"sDescriptionShort": "Get Best loading position from 0° and 180°",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "BEST_POSITION",
"sDescriptionShort": "Allow piece rotation and inversion",
"sValue": "FULL_PRE_ROTATION",
"sDescriptionShort": "Get Best loading position in each piece rotation",
"sDescriptionLong": "",
"sMessageId": ""
}
]
},
{
"nGroup": "PIECE LOADING",
"sName": "GEN_bAllowPieceInversion",
"sNameNge": "ADMIT_INVERSION",
"sValue": "false",
"sDescriptionShort": "Allow piece inversion",
"sDescriptionLong": "",
"sType": "b",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"nGroup": "PIECE LOADING",
"sName": "GEN_bGetAlternativesNesting2D",
"sNameNge": "GET_ALTERNATIVES_NEST2D",
"sValue": "false",
"sDescriptionShort": "Enable material optimization function in nesting",
"sDescriptionLong": "",
"sType": "b",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"nGroup": "MACHINE",
"sName": "GEN_sPieceRotation",
@@ -90,6 +112,17 @@
}
]
},
{
"nGroup": "MACHINING STRATEGY",
"sName": "GEN_nMaxReProcessCycles",
"sNameNge": "MAX_REPROCESS_CYCLES",
"sValue": "1",
"sDescriptionShort": "Max number of reprocessing cycles",
"sDescriptionLong": "",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "10"
},
{
"nGroup": "MACHINING STRATEGY",
"sName": "GEN_bReduceBladePath",
@@ -106,7 +139,7 @@
"sName": "GEN_dMaxWasteLength",
"sNameNge": "GEN_MAX_WASTE_LENGTH",
"sValue": "300",
"sDescriptionShort": "Maximum Waste Length for Dice-cut",
"sDescriptionShort": "Maximum length for dropped waste",
"sDescriptionLong": "",
"sType": "d",
"sMessageId": " ",
@@ -117,7 +150,18 @@
"sName": "GEN_dMaxWasteVolume",
"sNameNge": "GEN_MAX_WASTE_VOLUME",
"sValue": "6000000",
"sDescriptionShort": "Maximum Waste Volume for Dice-cut",
"sDescriptionShort": "Maximum volume for dropped waste",
"sDescriptionLong": "",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "5"
},
{
"nGroup": "MACHINING STRATEGY",
"sName": "GEN_dMaxDimDice",
"sNameNge": "GEN_MAX_DIM_DICE",
"sValue": "150",
"sDescriptionShort": "Maximum dice dimension",
"sDescriptionLong": "",
"sType": "d",
"sMessageId": " ",
+43 -20
View File
@@ -5,7 +5,7 @@
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
local FeatureLib = require( 'FeatureLib')
local MachiningLib = require( 'MachiningLib')
local SPLITCUT = require( 'SPLITCUT')
@@ -34,17 +34,28 @@ function HEADCUT.Make( bAddMachining, Proc, Part, CustomParameters)
Strategy.Result.sInfo = ''
local OptionalParameters = { bForceChainSaw = Strategy.Parameters.bForceChainSaw, bReduceBladePath = Strategy.Parameters.bReduceBladePath,
dMaxWasteLength = Strategy.Parameters.dMaxWasteLength, dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume }
OptionalParameters.sRestLengthSideForPreSimulation = 'Head'
OptionalParameters.bCannotSplitRestLength = true
local bAreAllMachiningsAdded = true
-- si setta che è taglio di coda
-- si setta che è taglio di testa
Strategy.bIsHeadCut = true
-- quando si aggiunge la lavorazione, si cambia il nome della feature
if bAddMachining then
-- si forza il nome della feature
EgtSetName( Proc.id, 'StartCut')
end
-- se abilitato, faccio tagli di PRECUT a zero (come SPLIT)
if Strategy.Parameters.bExecutePreCut then
Strategy.SplitStrategy, Strategy.Result = SPLITCUT.GetMachining( Proc, Part, OptionalParameters)
-- se non faccio tagli PRECUT, imposto tabella Result direttamente. Non serve verificare che riesca a rimuovere il materiale extra
if not Strategy.SplitStrategy or #Strategy.SplitStrategy == 0 then
Strategy.Result.sInfo = 'PreCut on head not possible'
-- if not Strategy.SplitStrategy or #Strategy.SplitStrategy == 0 then
-- Strategy.Result.sInfo = 'PreCut on head not possible'
-- end
if Strategy.Result.sStatus ~= 'Completed' then
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( 'Precut Head not possible')
return false, Strategy.Result
end
end
@@ -54,22 +65,24 @@ function HEADCUT.Make( bAddMachining, Proc, Part, CustomParameters)
-- TODO di quale utensile si deve impostare la qualità qui?
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'SAWBLADE')
-- se coincide con inizio grezzo, non va fatto
if abs( Proc.b3Box:getCenter():getX() - Part.b3Raw:getMax():getX()) < 10 * GEO.EPS_SMALL then
return true, Strategy.Result
end
-- se devo applicare le lavorazioni
if bAddMachining then
-- si forza il nome della feature
EgtSetName( Proc.id, 'StartCut')
-- inserimento smussi su spigoli del taglio
if Strategy.Parameters.bMakeChamfer then
MakeChamfer()
end
local MachiningsToAdd = {}
local bExecutePrecutOnly = Part.dHeadOverMaterial < 20
local bExecutePrecutOnly = false
-- se abilitato, faccio tagli di PRECUT a zero (come SPLIT)
if Strategy.Parameters.bExecutePreCut then
bExecutePrecutOnly = Part.dHeadOverMaterial < 20
if Strategy.SplitStrategy and #Strategy.SplitStrategy > 0 then
for i = 1, #Strategy.SplitStrategy do
local TempList = {}
@@ -87,25 +100,35 @@ function HEADCUT.Make( bAddMachining, Proc, Part, CustomParameters)
end
if not bExecutePrecutOnly then
local OptionalParameters = {}
-- si parte dal box della feature e si aggiunge il punto estremo del grezzo
-- ATTENZIONE : Proc.b3Box viene modificata dato che il tipo Box è come se fosse una tabella, ma da qui passa solo 1 volta per pezzo quindi non dovrebbero esserci problemi
local b3BoxDicing = Proc.b3Box
b3BoxDicing:Add( Part.b3Raw:getMax())
b3BoxDicing:expand( 1000 * GEO.EPS_SMALL)
OptionalParameters.b3BoxDicing = b3BoxDicing
OptionalParameters.dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume
OptionalParameters.dMaxWasteLength = Strategy.Parameters.dMaxWasteLength
OptionalParameters.bReduceBladePath = Strategy.Parameters.bReduceBladePath
-- si recuperano gli estremi del box del materiale di testa da togliere
local b3PartWithHead = BeamLib.GetPartBoxWithHeadTail( Part, 'Head')
local ptStartRestLength = Point3d( Part.b3Part:getMax():getX() - 1, Part.b3Part:getMax():getY(), Part.b3Part:getMax():getZ())
local ptEndRestLength = Point3d( b3PartWithHead:getMax():getX(), Part.b3Part:getMin():getY(), Part.b3Part:getMin():getZ())
Strategy.Machining, _ = BladeToWaste.Make( Proc, Part, OptionalParameters)
local OptionalParametersBladeToWaste = {}
OptionalParametersBladeToWaste.b3BoxDicing = BBox3d( ptStartRestLength, ptEndRestLength)
OptionalParametersBladeToWaste.dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume
OptionalParametersBladeToWaste.dMaxWasteLength = Strategy.Parameters.dMaxWasteLength
OptionalParametersBladeToWaste.bReduceBladePath = Strategy.Parameters.bReduceBladePath
OptionalParametersBladeToWaste.sRestLengthSideForPreSimulation = 'Head'
OptionalParametersBladeToWaste.bCannotSplitRestLength = true
Strategy.Machining, _ = BladeToWaste.Make( Proc, Part, OptionalParametersBladeToWaste)
-- se taglio non riuscito, si riprova con il riduci percorso forzato (collisione possibile in separazione pezzi alti)
if ( not Strategy.Machining) or ( #Strategy.Machining == 0) then
OptionalParametersBladeToWaste.bReduceBladePath = true
Strategy.Machining, _ = BladeToWaste.Make( Proc, Part, OptionalParametersBladeToWaste)
end
if Strategy.Machining and #Strategy.Machining > 0 then
for i = 1, #Strategy.Machining do
local TempList = {}
TempList = Strategy.Machining[i]
table.insert( MachiningsToAdd, TempList)
end
else
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( 'Head machining not possible')
return false, Strategy.Result
end
end
+19 -1
View File
@@ -5,9 +5,10 @@
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
local PreSimulationLib = require( 'PreSimulationLib')
-- strategie di base
local BladeToWaste = require('BLADETOWASTE')
@@ -183,6 +184,23 @@ local function GetTenonStrategy( Proc, Part)
Machining.Milling.AuxiliaryData.Clones[nIndexClones].dRadialOffset = ( i - 1) * dRealSideStep
end
end
-- test finecorsa sulla passata più esterna: se extracorsa, la lavorazione non è fattibile
-- TODO sostituire con applicazione della lavorazione?
-- TODO funzione per allungare il percorso??????
local idGeomMaxOffset = EgtCopyGlob( Proc.FeatureInfo.idAddAuxGeom, Part.idTempGroup)
EgtOffsetCurve( idGeomMaxOffset, Machining.Milling.AuxiliaryData.Clones[1].dRadialOffset + TOOLS[Machining.Milling.ToolInfo.nToolIndex].dDiameter / 2, Part.idTempGroup)
local vtCurveStart = EgtSV( idGeomMaxOffset, GDB_ID.ROOT)
local vtCurveEnd = EgtEV( idGeomMaxOffset, GDB_ID.ROOT)
local ptCurveStart = EgtSP( idGeomMaxOffset, GDB_ID.ROOT) + -vtCurveStart * Machining.Milling.LeadIn.dTangentDistance + ( Proc.FeatureInfo.vtTenonN ^ -vtCurveStart) * Machining.Milling.LeadIn.dPerpDistance
local ptCurveEnd = EgtEP( idGeomMaxOffset, GDB_ID.ROOT) + vtCurveEnd * Machining.Milling.LeadOut.dTangentDistance + ( vtCurveEnd ^ Proc.FeatureInfo.vtTenonN) * Machining.Milling.LeadOut.dPerpDistance
EgtAddCurveCompoArcTg( idGeomMaxOffset, ptCurveStart, false, GDB_RT.GLOB)
EgtAddCurveCompoArcTg( idGeomMaxOffset, ptCurveEnd, true, GDB_RT.GLOB)
local bOutOfStroke = PreSimulationLib.CheckOutOfStrokeFromGeometry( idGeomMaxOffset, Proc.FeatureInfo.vtTenonN, Machining.Milling.nSCC, TOOLS[Machining.Milling.ToolInfo.nToolIndex])
if bOutOfStroke then
Machining.Milling.bIsApplicable = false
end
-- tempo di svuotatura
Result.Milling.dTimeToMachine = MachiningLib.GetTimeToMachineAllStepsWithLeadInOut( Machining.Milling, Part)
else
+11 -1
View File
@@ -22,10 +22,20 @@
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "dExtendAfterTail",
"sNameNge": "EXTEND_AFTER_TAIL",
"sValue": "",
"sDescriptionShort": "Extend after tail",
"sDescriptionLong": "The automatism considers this length as machinable. This means you accept to damage the next piece in the bar",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "dOpenMinSafe",
"sNameNge": "OPENMINSAFE",
"sValue": "40",
"sValue": "10",
"sDescriptionShort": "Minimum approach distance on open sides",
"sDescriptionLong": "Minimum approach distance on open sides",
"sType": "d",
+156 -39
View File
@@ -16,9 +16,10 @@
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
local AntiSplintOnFace = require( 'ANTISPLINTONFACE')
-- Tabella per definizione modulo
local STR0002 = {}
@@ -101,13 +102,13 @@ end
-------------------------------------------------------------------------------------------------------------
-- TODO va gestita meglio la decisione delle facce da lavorare
local function GetBestPocketingStrategy( Proc)
local function GetBestPocketingStrategy( Proc, Part)
-- 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
Machining.sTypeMachining = 'None' -- Bottom-Side1-Side2\ Bottom-Bottom2\ Bottom-Side1\ Bottom-Side2\ Side1-Side2\ Bottom\ Side1 \ Side2 \ None
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'STD')
-- caso speciale Tunnel che non ha faccia bottom
@@ -170,16 +171,33 @@ local function GetBestPocketingStrategy( Proc)
-- cerco utensile per lavorare faccia Bottom
Milling.bIsApplicable = false
if Proc.Topology.sName ~= 'Tunnel-4-Through' then
-- TODO in caso che la faccia crei un piano asportando tutto il materiale, si potrebbe forzare elevazione a zero e scegliere quindi fresa di diametro maggiore.
-- Il discorso non vale se la feature viene spezzata o se non ancora separata, in quanto ci sarebbe comunque del materiale da considerare nell'elevazione.
-- In quel caso, un 'Bevel-1-Through' è come se fosse un 'Bevel-2-Blind', quindi l'elevazione deve essere considerata.
ToolSearchParameters.dElevation = Proc.MainFaces.BottomFaces[1].dElevation
ToolSearchParameters.vtToolDirection = Proc.MainFaces.BottomFaces[1].vtN
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sPocketingList, 'Pocketing')
Milling.idFaceToMachine = Proc.MainFaces.BottomFaces[1].id
Milling.bAddAntiSplint = Strategy.Parameters.bAntiSplint
Milling.idProc = Proc.id
Milling.vtFaceNormal = Proc.MainFaces.BottomFaces[1].vtN
Milling.dElevation = Proc.MainFaces.BottomFaces[1].dElevation
Milling.ToolInfo = {}
Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
if Milling.ToolInfo.nToolIndex then
-- se faccia singola e feature lavorata in unica lavorazione si può sempre affondare
if Proc.Topology.sName == 'Cut-1-Through'
or Proc.Topology.sName == 'Bevel-1-Through' then
-- eventuali punti di spezzatura
local FeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
local bIsSplitFeature = false
if #FeatureSplittingPoints > 0 then
bIsSplitFeature = true
end
if not bIsSplitFeature then
Milling.ToolInfo.dResidualDepth = 0
end
end
Milling.bIsApplicable = true
local ParametersMRR = {}
ParametersMRR.nToolIndex = Milling.ToolInfo.nToolIndex
@@ -191,13 +209,14 @@ local function GetBestPocketingStrategy( Proc)
-- caso speciale 'Rabbet-2-Through' seconda faccia principale
Milling = {}
Milling.bIsApplicable = false
if Proc.Topology.sName == 'Rabbet-2-Through' or Proc.Topology.sName == 'Bevel-2-Blind' or
if Proc.Topology.sName == 'Rabbet-2-Through' or Proc.Topology.sName == 'Bevel-2-Blind' or
Proc.Topology.sName == 'DoubleBevel-2-Through' or Proc.Topology.sName == 'VGroove-2-Through' then
ToolSearchParameters.dElevation = Proc.MainFaces.BottomFaces[2].dElevation
ToolSearchParameters.vtToolDirection = Proc.MainFaces.BottomFaces[2].vtN
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sPocketingList, 'Pocketing')
Milling.vtFaceNormal = Proc.MainFaces.BottomFaces[2].vtN
Milling.idFaceToMachine = Proc.MainFaces.BottomFaces[2].id
Milling.bAddAntiSplint = Strategy.Parameters.bAntiSplint
Milling.idProc = Proc.id
Milling.dElevation = Proc.MainFaces.BottomFaces[2].dElevation
Milling.ToolInfo = {}
@@ -225,12 +244,21 @@ local function GetBestPocketingStrategy( Proc)
Milling.idProc = Proc.id
Milling.dElevation = Proc.MainFaces.BottomFaces[2].dElevation
elseif Proc.Topology.sName == 'Groove-3-Blind' or Proc.Topology.sName == 'Bevel-3-Blind' then
ToolSearchParameters.dElevation = Proc.MainFaces.LongFaces[1].dElevation
ToolSearchParameters.vtToolDirection = Proc.MainFaces.LongFaces[1].vtN
Milling.vtFaceNormal = Proc.MainFaces.LongFaces[1].vtN
Milling.idFaceToMachine = Proc.MainFaces.LongFaces[1].id
Milling.idProc = Proc.id
Milling.dElevation = Proc.MainFaces.LongFaces[1].dElevation
if Proc.MainFaces.LongFaces and Proc.MainFaces.LongFaces[1] then
ToolSearchParameters.dElevation = Proc.MainFaces.LongFaces[1].dElevation
ToolSearchParameters.vtToolDirection = Proc.MainFaces.LongFaces[1].vtN
Milling.vtFaceNormal = Proc.MainFaces.LongFaces[1].vtN
Milling.idFaceToMachine = Proc.MainFaces.LongFaces[1].id
Milling.idProc = Proc.id
Milling.dElevation = Proc.MainFaces.LongFaces[1].dElevation
elseif Proc.MainFaces.BottomFaces[2] then
ToolSearchParameters.dElevation = Proc.MainFaces.BottomFaces[2].dElevation
ToolSearchParameters.vtToolDirection = Proc.MainFaces.BottomFaces[2].vtN
Milling.vtFaceNormal = Proc.MainFaces.BottomFaces[2].vtN
Milling.idFaceToMachine = Proc.MainFaces.BottomFaces[2].id
Milling.idProc = Proc.id
Milling.dElevation = Proc.MainFaces.BottomFaces[2].dElevation
end
elseif Proc.MainFaces.TunnelAddedFaces then -- 'Tunnel-4-Through', 'Groove-3-Through', 'Rabbet-2-Through', 'VGroove-2-Through', 'Bevel-2-Blind'
-- se lavoro di fianco, devo comunque rispettare il raggio massimo
ToolSearchParameters.dMaxToolDiameter = min( ToolSearchParameters.dMaxToolDiameter, Strategy.Parameters.dMaxCornerRadius * 2)
@@ -241,6 +269,8 @@ local function GetBestPocketingStrategy( Proc)
Milling.idProc = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.id
Milling.dElevation = ( Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation * 2) + BeamData.MILL_OVERLAP
Milling.bMachAppliedToTunnelFace = true
else
ToolSearchParameters.vtToolDirection = nil
end
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sPocketingList, 'Pocketing')
Milling.ToolInfo = {}
@@ -250,6 +280,19 @@ local function GetBestPocketingStrategy( Proc)
local ParametersMRR = {}
ParametersMRR.nToolIndex = Milling.ToolInfo.nToolIndex
Milling.dMRR = MachiningLib.GetToolMRR( ParametersMRR)
-- se la faccia tunnel è troppo piccola non si lavora
if Milling.bMachAppliedToTunnelFace then
local dLongestEdgeLength = 0
for i = 1, #Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].Edges do
if Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].Edges[i].dLength > dLongestEdgeLength + 10 * GEO.EPS_SMALL then
dLongestEdgeLength = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].Edges[i].dLength
end
end
if dLongestEdgeLength < TOOLS[Milling.ToolInfo.nToolIndex].dDiameter then
Milling.bIsApplicable = false
ParametersMRR = {}
end
end
end
end
table.insert( Machining, Milling)
@@ -281,6 +324,8 @@ local function GetBestPocketingStrategy( Proc)
Milling.idFaceToMachine = Proc.MainFaces.SideFaces[1].id
Milling.idProc = Proc.id
Milling.dElevation = Proc.MainFaces.SideFaces[1].dElevation
else
ToolSearchParameters.vtToolDirection = nil
end
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sPocketingList, 'Pocketing')
Milling.ToolInfo = {}
@@ -290,13 +335,60 @@ local function GetBestPocketingStrategy( Proc)
local ParametersMRR = {}
ParametersMRR.nToolIndex = Milling.ToolInfo.nToolIndex
Milling.dMRR = MachiningLib.GetToolMRR( ParametersMRR)
-- se la faccia tunnel è troppo piccola non si lavora
if Milling.bMachAppliedToTunnelFace then
local dLongestEdgeLength = 0
for i = 1, #Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].Edges do
if Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].Edges[i].dLength > dLongestEdgeLength + 10 * GEO.EPS_SMALL then
dLongestEdgeLength = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].Edges[i].dLength
end
end
if dLongestEdgeLength < TOOLS[Milling.ToolInfo.nToolIndex].dDiameter then
Milling.bIsApplicable = false
ParametersMRR = {}
end
end
end
end
table.insert( Machining, Milling)
-- ===== SCELTA LAVORAZIONI =====
-- TODO per DoubleBevel-2-Through si potrebbe lavorare la faccia tunnel su ogni faccia. Bisogna calcolarla!!
-- caso speciale DoubleBevel-2-Through bisogna lavorare entrambe le bottom
if Proc.Topology.sName == 'DoubleBevel-2-Through' then
-- se entrambe applicabili significa che è completo
if Machining[1].bIsApplicable and Machining[2].bIsApplicable then
Machining.sTypeMachining = 'Bottom-Bottom2'
Strategy.Result.sStatus = 'Completed'
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
Strategy.Result.dMRR = Machining[1].dMRR + Machining[2].dMRR / 2
Machining[1].ToolInfo.dResidualDepth = 0
Machining[2].ToolInfo.dResidualDepth = 0
return Machining
else
local dMachinedPrercentage = 0
-- se applicabile solo Bottom
if Machining[1].bIsApplicable then
Machining.sTypeMachining = 'Bottom'
Strategy.Result.sStatus = 'Not-Completed'
Machining[1].ToolInfo.dResidualDepth = 0
Strategy.Result.dMRR = Machining[1].dMRR
dMachinedPrercentage = ( Machining[1].dElevation / ( Machining[1].dElevation + Machining[2].dElevation)) * 100
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( dMachinedPrercentage)
-- se applicabile solo Bottom2
elseif Machining[2].bIsApplicable then
Machining.sTypeMachining = 'Bottom2'
Strategy.Result.sStatus = 'Not-Completed'
Machining[2].ToolInfo.dResidualDepth = 0
Strategy.Result.dMRR = Machining[2].dMRR
dMachinedPrercentage = ( Machining[2].dElevation / ( Machining[1].dElevation + Machining[2].dElevation)) * 100
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( dMachinedPrercentage)
end
Strategy.Result.sInfo = 'Machining not complete, left ' .. tostring( 100 - ceil( dMachinedPrercentage)) .. '%'
end
return Machining
-- se bottom completa tutto
if Machining[1].bIsApplicable and Machining[1].ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then
elseif Machining[1].bIsApplicable and Machining[1].ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then
Machining.sTypeMachining = 'Bottom'
Strategy.Result.sStatus = 'Completed'
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
@@ -308,10 +400,10 @@ local function GetBestPocketingStrategy( Proc)
if ( Proc.nFct == 2 and Proc.AdjacencyMatrix[1][2] >= -89.9)
and Machining[2].bIsApplicable and Machining[2].ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then
Machining.sTypeMachining = 'Bottom2'
Machining.sTypeMachining = 'Bottom-Bottom2'
Strategy.Result.sStatus = 'Completed'
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
Strategy.Result.dMRR = Machining[2].dMRR
Strategy.Result.dMRR = Machining[1].dMRR + Machining[2].dMRR / 2
Machining[2].ToolInfo.dResidualDepth = 0
else
Machining[2].bIsApplicable = false
@@ -428,7 +520,12 @@ end
local function GetSplitSurfaces( Proc, Part, bAddMachining)
local vAddId = {}
local vAddIdTunnel = {}
local nAddGrpId = BeamLib.GetAddGroup( Part.id)
local idAddGroup
if bAddMachining then
idAddGroup = BeamLib.GetAddGroup( Part.id)
else
idAddGroup = Part.idTempGroup
end
local nOriginalTmIdTunnel = GDB_ID.NULL
if Proc.MainFaces.TunnelAddedFaces then
nOriginalTmIdTunnel = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.id
@@ -438,18 +535,14 @@ local function GetSplitSurfaces( Proc, Part, bAddMachining)
local FeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
if #FeatureSplittingPoints == 0 then
local nAddId = EgtCopyGlob( Proc.id, nAddGrpId) or GDB_ID.NULL
local nAddIdTunnel = EgtCopyGlob( nOriginalTmIdTunnel, nAddGrpId) or GDB_ID.NULL
if not bAddMachining then
EgtSetLevel( nAddId, GDB_LV.TEMP)
EgtSetLevel( nAddIdTunnel, GDB_LV.TEMP)
end
local nAddId = EgtCopyGlob( Proc.id, idAddGroup) or GDB_ID.NULL
local nAddIdTunnel = EgtCopyGlob( nOriginalTmIdTunnel, idAddGroup) or GDB_ID.NULL
table.insert( vAddId, nAddId)
table.insert( vAddIdTunnel, nAddIdTunnel)
else
for i = 1, #FeatureSplittingPoints do
local nAddId = EgtCopyGlob( Proc.id, nAddGrpId) or GDB_ID.NULL
local nAddIdTunnel = EgtCopyGlob( nOriginalTmIdTunnel, nAddGrpId) or GDB_ID.NULL
local nAddId = EgtCopyGlob( Proc.id, idAddGroup) or GDB_ID.NULL
local nAddIdTunnel = EgtCopyGlob( nOriginalTmIdTunnel, idAddGroup) 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)
@@ -465,23 +558,15 @@ local function GetSplitSurfaces( Proc, Part, bAddMachining)
EgtCutSurfTmPlane( nAddId, ptSplit, X_AX(), true, GDB_RT.GLOB)
EgtCutSurfTmPlane( nAddIdTunnel, ptSplit, X_AX(), true, GDB_RT.GLOB)
end
if not bAddMachining then
EgtSetLevel( nAddId, GDB_LV.TEMP)
EgtSetLevel( nAddIdTunnel, GDB_LV.TEMP)
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 nAddId = EgtCopyGlob( Proc.id, idAddGroup) or GDB_ID.NULL
local nAddIdTunnel = EgtCopyGlob( nOriginalTmIdTunnel, idAddGroup) 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)
if not bAddMachining then
EgtSetLevel( nAddId, GDB_LV.TEMP)
EgtSetLevel( nAddIdTunnel, GDB_LV.TEMP)
end
table.insert( vAddId, nAddId)
table.insert( vAddIdTunnel, nAddIdTunnel)
end
@@ -501,19 +586,27 @@ function STR0002.Make( bAddMachining, Proc, Part, CustomParameters)
Strategy.Result = {}
Strategy.Result.dTimeToMachine = 0
-- se la lavorazione ostacola il pinzaggio, non posso farla
if not IsTopologyOk( Proc) then
local sErr = 'Feature '.. Proc.idFeature .. ' : strategy ' .. StrategyLib.Config.sStrategyId .. ' not implemented'
EgtOutLog( sErr)
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( sErr)
return false, Strategy.Result
end
-- se la lavorazione ostacola il pinzaggio, non posso farla, serve una lavorazioen che lasci il testimone
if MachiningLib.IsFeatureHinderingClamping( Proc, Part) then
local sErr = 'Feature '.. Proc.idFeature .. ' : strategy ' .. StrategyLib.Config.sStrategyId .. ' not applicable ( Feature hinders clamping)'
EgtOutLog( sErr)
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( sErr)
return false, Strategy.Result
end
local bAreAllMachiningsAdded = true
local dFeatureVolume = FeatureLib.GetFeatureVolume( Proc, Part)
local dFeatureVolume = Proc.dVolume
local ToolInfo = {}
local Pocketing = {}
Strategy.Machining = GetBestPocketingStrategy( Proc)
Strategy.Machining = GetBestPocketingStrategy( Proc, Part)
if Strategy.Result.sStatus ~= 'Not-Applicable' then
local vAddId = {}
@@ -535,8 +628,8 @@ function STR0002.Make( bAddMachining, Proc, Part, CustomParameters)
Pocketing.Steps.dStep = TOOLS[Strategy.Machining[j].ToolInfo.nToolIndex].dStep
Pocketing.Steps.dSideStep = TOOLS[Strategy.Machining[j].ToolInfo.nToolIndex].dSideStep
Pocketing.nToolIndex = Strategy.Machining[j].ToolInfo.nToolIndex
Pocketing.LeadIn.dTangentDistance = TOOLS[Strategy.Machining[j].ToolInfo.nToolIndex].dDiameter/2
Pocketing.LeadIn.dElevation = TOOLS[Strategy.Machining[j].ToolInfo.nToolIndex].dDiameter/2
Pocketing.LeadIn.dTangentDistance = TOOLS[Strategy.Machining[j].ToolInfo.nToolIndex].dDiameter / 2
Pocketing.LeadIn.dElevation = TOOLS[Strategy.Machining[j].ToolInfo.nToolIndex].dDiameter / 2
Pocketing.sDepth = -Strategy.Machining[j].ToolInfo.dResidualDepth
Pocketing.dResidualDepth = Strategy.Machining[j].ToolInfo.dResidualDepth
-- TODO vedere se questo parametro con svuotature nuove si può rimuovere
@@ -545,11 +638,35 @@ function STR0002.Make( bAddMachining, Proc, Part, CustomParameters)
if Strategy.Machining[j].bToolInvert then
Pocketing.bToolInvert = true
end
-- eventuali antischeggia
if Strategy.Machining[j].bAddAntiSplint then
local OptionalParametersAntiSplint = {
bIsSplitFeature = ( #vAddId > 1),
dExtendAfterTail = Strategy.Parameters.dExtendAfterTail
}
local AntiSplints = AntiSplintOnFace.Make( Proc, Part, Proc.Faces[ Strategy.Machining[j].idFaceToMachine + 1], OptionalParametersAntiSplint)
local bAreAllAntisplintsApplicable = true
for k = 1, #AntiSplints do
if AntiSplints[k].bIsApplicable then
if bAddMachining then
bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, AntiSplints[k])
end
else
bAreAllAntisplintsApplicable = false
end
end
if bAreAllAntisplintsApplicable then
-- TODO qui si dovrà distinguere tra antischeggia di lama e di fresa; al momento è solo di lama
if Strategy.Result.dQuality == FeatureLib.GetStrategyQuality( 'STD') then
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'BEST')
end
end
end
-- 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}}
Pocketing.vtToolDirection = Strategy.Machining[j].vtFaceNormal
-- 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
@@ -579,10 +696,10 @@ function STR0002.Make( bAddMachining, Proc, Part, CustomParameters)
end
if vtNSplitFace and AreSameVectorApprox( vtNSplitFace * EgtIf( Pocketing.bToolInvert, -1, 1), Strategy.Machining[j].vtFaceNormal) then
Pocketing.Geometry = {{ nIdTm, k - 1}}
Pocketing.dTimeToMachine = MachiningLib.GetTimeToMachineAllStepsWithLeadInOut( Pocketing, Part)
Strategy.Result.dTimeToMachine = Strategy.Result.dTimeToMachine + Pocketing.dTimeToMachine
if bAddMachining then
bAreAllMachiningsAdded = bAreAllMachiningsAdded and MachiningLib.AddMachinings( Proc, Pocketing)
end
+1 -1
View File
@@ -17,7 +17,7 @@
"sNameNge": "EXTEND_AFTER_TAIL",
"sValue": "",
"sDescriptionShort": "Extend after tail",
"sDescriptionLong": "The automatism considers this lenght as machinable. This means you accept to damage the next piece in the bar",
"sDescriptionLong": "The automatism considers this length as machinable. This means you accept to damage the next piece in the bar",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
+37 -12
View File
@@ -15,7 +15,7 @@
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
-- strategie di base
@@ -35,12 +35,19 @@ 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
-- canale ammesso solo se lati paralleli a 2 a 2
elseif Proc.Topology.sName == 'Groove-3-Through'
and ( AreOppositeVectorApprox( Proc.MainFaces.BottomFaces[1].MainEdges.LongEdges[1].vtN, Proc.MainFaces.BottomFaces[1].MainEdges.LongEdges[2].vtN)) then
return true
else
return false
end
end
@@ -188,6 +195,17 @@ function STR0003.Make( bAddMachining, Proc, Part, CustomParameters)
Blade.Result = {}
Chainsaw.Result = {}
-- se arriva una feature senza MainFaces o MainEdges necessari la strategia non è applicabile
-- TODO riuniure a IsTopologyOk?
if not Proc.MainFaces
or not Proc.MainFaces.LongFaces[1]
or not Proc.MainFaces.LongFaces[1].MainEdges then
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( 'Topology')
return false, Strategy.Result
end
if not IsTopologyOk( Proc) then
local sErr = 'Feature '.. Proc.idFeature .. ' : strategy ' .. Strategy.sName .. ' not implemented'
EgtOutLog( sErr)
@@ -195,13 +213,15 @@ function STR0003.Make( bAddMachining, Proc, Part, CustomParameters)
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)
-- TODO se OnlySaw questo test è da rimuovere ma bisogna considerare anche la lama 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 = FeatureLib.GetStrategyResultNotApplicable( 'Direction')
return false, Strategy.Result
-- se canale e lati non a 90deg la strategia non è applicabile
-- TODO questo è temporaneo finchè non si gestiscono correttamente i lati obliqui per le groove-3-through
-- la dPocketHeight è già gestita, ma va allungato il percorso dove c'è l'angolo > 90
if Proc.Topology.sName == 'Groove-3-Through' then
local BottomFace = Proc.MainFaces.BottomFaces[1]
if abs( BottomFace.Edges[1].vtEdge * BottomFace.Edges[2].vtEdge) > 10 * GEO.EPS_SMALL then
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( 'Topology')
return false, Strategy.Result
end
end
local dExtendAfterTail = Strategy.Parameters.dExtendAfterTail or max( Part.dDistanceToNextPiece - BeamData.CUT_EXTRA, 0)
@@ -210,7 +230,7 @@ function STR0003.Make( bAddMachining, Proc, Part, CustomParameters)
end
-- volume della feature
local dFeatureVolume = FeatureLib.GetFeatureVolume( Proc, Part)
local dFeatureVolume = Proc.dVolume
-- eventuali punti di spezzatura
local FeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
@@ -223,6 +243,11 @@ function STR0003.Make( bAddMachining, Proc, Part, CustomParameters)
local dPocketHeight = 0
if Proc.Topology.sFamily == 'Tunnel' then
dPocketHeight = Proc.MainFaces.SideFaces[1].MainEdges.OppositeEdges[1].dLength
elseif Proc.Topology.sName == 'Groove-3-Through' then
local BottomFace = Proc.MainFaces.BottomFaces[1]
local frFrame = Frame3d( BottomFace.ptCenter, BottomFace.vtN, BottomFace.MainEdges.LongEdges[1].vtEdge)
local b3BottomFace = EgtSurfTmGetFacetBBoxRef( Proc.id, BottomFace.id, GDB_BB.STANDARD, frFrame)
dPocketHeight = b3BottomFace:getDimY()
else
dPocketHeight = Proc.MainFaces.BottomFaces[1].MainEdges.SideEdges[1].dLength
end
@@ -236,6 +261,7 @@ function STR0003.Make( bAddMachining, Proc, Part, CustomParameters)
local BottomEdge = LongFace.MainEdges.BottomEdge
-- TODO funzione separata
-- TODO è meglio cercare la lama qui e passarla alla FACEBYBLADE, la scelta è più precisa
-- lama - calcolo lavorazioni
local Cutting = {}
-- parametri comuni a tutte le lavorazioni cutting
@@ -243,8 +269,7 @@ function STR0003.Make( bAddMachining, Proc, Part, CustomParameters)
bForceLongcutBlade = Strategy.Parameters.bForceLongcutBlade,
dExtendAfterTail = dExtendAfterTail,
dPocketHeight = dPocketHeight,
bIsSplitFeature = bIsSplitFeature,
dMinNzDownUp = 0
bIsSplitFeature = bIsSplitFeature
}
-- primo lato del tunnel o lato di fondo
+1 -1
View File
@@ -17,7 +17,7 @@
"sNameNge": "EXTEND_AFTER_TAIL",
"sValue": "",
"sDescriptionShort": "Extend after tail",
"sDescriptionLong": "The automatism considers this lenght as machinable. This means you accept to damage the next piece in the bar",
"sDescriptionLong": "The automatism considers this length as machinable. This means you accept to damage the next piece in the bar",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
+36 -15
View File
@@ -15,7 +15,7 @@
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
-- strategie di base
@@ -112,20 +112,10 @@ function STR0004.Make( bAddMachining, Proc, Part, CustomParameters)
Chainsaw.Result = {}
if not IsTopologyOk( Proc) then
local sErr = 'Feature '.. Proc.idFeature .. ' : strategy ' .. Strategy.sName .. ' not implemented'
EgtOutLog( sErr)
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( '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 = FeatureLib.GetStrategyResultNotApplicable( '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
@@ -133,7 +123,7 @@ function STR0004.Make( bAddMachining, Proc, Part, CustomParameters)
end
-- volume della feature
local dFeatureVolume = FeatureLib.GetFeatureVolume( Proc, Part)
local dFeatureVolume = Proc.dVolume
-- eventuali punti di spezzatura
local FeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
@@ -142,10 +132,25 @@ function STR0004.Make( bAddMachining, Proc, Part, CustomParameters)
bIsSplitFeature = true
end
-- se arriva una feature senza MainFaces o MainEdges necessari la strategia non è applicabile
-- TODO riuniure a IsTopologyOk?
if not Proc.MainFaces
or not Proc.MainFaces.LongFaces[1]
or not Proc.MainFaces.LongFaces[1].MainEdges then
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( 'Topology')
return false, Strategy.Result
end
-- altezza tasca
local dPocketHeight = 0
if Proc.Topology.sFamily == 'Tunnel' then
dPocketHeight = Proc.MainFaces.SideFaces[1].MainEdges.OppositeEdges[1].dLength
elseif Proc.Topology.sName == 'Groove-3-Through' then
local BottomFace = Proc.MainFaces.BottomFaces[1]
local frFrame = Frame3d( BottomFace.ptCenter, BottomFace.vtN, BottomFace.MainEdges.LongEdges[1].vtEdge)
local b3BottomFace = EgtSurfTmGetFacetBBoxRef( Proc.id, BottomFace.id, GDB_BB.STANDARD, frFrame)
dPocketHeight = b3BottomFace:getDimY()
else
dPocketHeight = Proc.MainFaces.BottomFaces[1].MainEdges.SideEdges[1].dLength
end
@@ -167,6 +172,7 @@ function STR0004.Make( bAddMachining, Proc, Part, CustomParameters)
bIsSplitFeature = bIsSplitFeature
}
-- TODO aggiungere verifica finecorsa e nel caso cambio lato
if Proc.Topology.sName == 'Groove-4-Blind' or Proc.Topology.sName == 'Pocket-5-Blind' then
-- si lavora tutto il fondo
@@ -179,13 +185,17 @@ function STR0004.Make( bAddMachining, Proc, Part, CustomParameters)
and #Proc.MainFaces.SideFaces == 1 then
OptionalParameters.OppositeToolDirectionMode = 'Enabled'
local dLengthAlreadyMachined = 0
if Chainsaw.Result.Bottom[1].bIsApplicable then
dLengthAlreadyMachined = Chainsaw.Result.Bottom[1].dDepthToMachine
end
if BottomEdge.bIsStartOpen then
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, SideEdge1, OptionalParameters)
Mortising.dAreaToMachine = Mortising.dDepthToMachine * ( Mortising.dEdgeLength - Chainsaw.Result.Bottom[1].dDepthToMachine)
Mortising.dAreaToMachine = Mortising.dDepthToMachine * ( Mortising.dEdgeLength - dLengthAlreadyMachined)
elseif BottomEdge.bIsEndOpen then
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, SideEdge2, OptionalParameters)
Mortising.dAreaToMachine = Mortising.dDepthToMachine * ( Mortising.dEdgeLength - Chainsaw.Result.Bottom[1].dDepthToMachine)
Mortising.dAreaToMachine = Mortising.dDepthToMachine * ( Mortising.dEdgeLength - dLengthAlreadyMachined)
end
Chainsaw.AddResult( Mortising)
@@ -242,10 +252,21 @@ function STR0004.Make( bAddMachining, Proc, Part, CustomParameters)
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, OppositeEdge1, OptionalParameters)
Chainsaw.AddResult( Mortising)
-- se dal lato OppositeEdge1 non è applicabile (solitamente per finecorsa) si prova dal lato opposto
if not Chainsaw.Result.Opposite[1].bIsApplicable then
OptionalParameters.dDepthToMachine = OppositeEdge2.dElevation + BeamData.CUT_EXTRA
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, OppositeEdge2, OptionalParameters)
Chainsaw.AddResult( Mortising)
end
-- se lavorando solo da un lato rimane materiale residuo, si lavora da entrambi
if Chainsaw.Result.Opposite[1].dResidualDepth > 10 * GEO.EPS_SMALL then
if Chainsaw.Result.Opposite[1].dResidualDepth > 10 * GEO.EPS_SMALL
or ( Chainsaw.Result.Opposite[2] and Chainsaw.Result.Opposite[2].dResidualDepth > 10 * GEO.EPS_SMALL) then
Chainsaw.Result.Opposite[1].bIsApplicable = false
if Chainsaw.Result.Opposite[2] then
Chainsaw.Result.Opposite[2].bIsApplicable = false
end
OptionalParameters.dDepthToMachine = OppositeEdge1.dElevation / 2 + BeamData.CUT_EXTRA_MIN
+6 -21
View File
@@ -17,7 +17,7 @@
"sNameNge": "EXTEND_AFTER_TAIL",
"sValue": "",
"sDescriptionShort": "Extend after tail",
"sDescriptionLong": "The automatism considers this lenght as machinable. This means you accept to damage the next piece in the bar",
"sDescriptionLong": "The automatism considers this length as machinable. This means you accept to damage the next piece in the bar",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
@@ -110,26 +110,6 @@
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "dMinZAngleTopBlade",
"sNameNge": "MIN_Z_ANGLE_TOP_BLADE",
"sValue": "",
"sDescriptionShort": "Min Z angle top blade",
"sDescriptionLong": "",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "dMaxYAngleTopBlade",
"sNameNge": "MAX_Y_ANGLE_TOP_BLADE",
"sValue": "",
"sDescriptionShort": "Max Y angle top blade",
"sDescriptionLong": "",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "bFinishWithMill",
"sNameNge": "ALLOW_FINISH_MILL",
@@ -160,6 +140,11 @@
"sSource": "GEN_dMaxWasteVolume",
"sMinUserLevel": "5"
},
{
"sName": "dMaxDimDice",
"sSource": "GEN_dMaxDimDice",
"sMinUserLevel": "5"
},
{
"sName": "bReduceBladePath",
"sSource": "GEN_bReduceBladePath",
+10 -29
View File
@@ -5,7 +5,7 @@
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
-- strategie di base
@@ -36,7 +36,7 @@ local function IsTwoFacesCommonEdgeTooLong( Proc, Part)
end
-- se due facce, cubetti troppo lunghi in X non si possono fare
local ptEdge1, _, ptEdge2 = EgtSurfTmFacetOppositeSide( Proc.id, Proc.Faces[1].id, -Proc.Faces[1].Edges[nCommonEdge].vtN, GDB_ID.ROOT)
local ptEdge1, ptEdge2 = Proc.Faces[1].Edges[nCommonEdge].ptStart, Proc.Faces[1].Edges[nCommonEdge].ptEnd
local b3BoxEdge = BBox3d( ptEdge1, ptEdge2)
local dEdgeLengthOnX = b3BoxEdge:getDimX()
if FeatureLib.IsMachiningLong( dEdgeLengthOnX, Part) then
@@ -66,7 +66,7 @@ function STR0005.Make( bAddMachining, Proc, Part, CustomParameters)
local dQualityAddedFace = 0
-- più di 3 facce non supportate
if Proc.nFct > 3 then
if Proc.nFct > 3 and ( not Proc.Topology.sFamily == 'DoubleBevel') then
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( 'More than 3 faces not supported')
end
@@ -80,9 +80,9 @@ function STR0005.Make( bAddMachining, Proc, Part, CustomParameters)
local idAddedTmFace
local nAddedFace
if Proc.nFct == 3 and not Proc.Topology.sName == 'Groove-3-Through' then
if Proc.AdjacencyMatrix[1][2] > 10 * GEO.EPS_ANG_SMALL and Proc.AdjacencyMatrix[2][3] < 10 * GEO.EPS_ANG_SMALL then
if Proc.AdjacencyMatrix[2][3] < 0 then
nAddedFace = 1 - 1
elseif Proc.AdjacencyMatrix[2][3] > 10 * GEO.EPS_ANG_SMALL and Proc.AdjacencyMatrix[3][1] < 10 * GEO.EPS_ANG_SMALL then
elseif Proc.AdjacencyMatrix[1][3] < 0 then
nAddedFace = 2 - 1
else
nAddedFace = 3 - 1
@@ -100,8 +100,9 @@ function STR0005.Make( bAddMachining, Proc, Part, CustomParameters)
-- considerazioni necessarie a determinare se lavorare con codolo oppure no
local bKeepWasteAttached = ( Strategy.Parameters.sCuttingStrategy == 'KEEP_WASTE_ATTACHED')
local bDropWaste = ( Strategy.Parameters.sCuttingStrategy == 'DROP_WASTE')
local dFeatureMaxNotClampableLengthHead, dFeatureMaxNotClampableLengthTail = FeatureLib.GetFeatureMaxNotClampableLengths( Proc, Part)
local bFeatureHindersClamping = FeatureLib.IsMachiningLong( max( dFeatureMaxNotClampableLengthHead, dFeatureMaxNotClampableLengthTail), Part, { dMaxSegmentLength = BeamData.LONGCUT_ENDLEN})
local bFeatureHindersClamping = MachiningLib.IsFeatureHinderingClamping( Proc, Part)
local bIsFeatureLong = FeatureLib.IsMachiningLong( Proc.b3Box:getDimX(), Part, { dMaxSegmentLength = BeamData.LONGCUT_ENDLEN})
local bIsTwoFacesCommonEdgeTooLong = ( ( Proc.Topology and ( Proc.Topology.sName == 'Rabbet-2-Through' or Proc.Topology.sName == 'Bevel-2-Blind')) and IsTwoFacesCommonEdgeTooLong( Proc, Part))
@@ -111,13 +112,14 @@ function STR0005.Make( bAddMachining, Proc, Part, CustomParameters)
or bKeepWasteAttached then
local BladeKeepWasteResult
local OptionalParameters = { dExtendAfterTail = dExtendAfterTail, dStripWidth = Strategy.Parameters.dStripWidth}
local OptionalParameters = { dExtendAfterTail = dExtendAfterTail, dStripWidth = Strategy.Parameters.dStripWidth, bForced = bKeepWasteAttached}
AuxiliaryData.bIgnoreNotClampableLength = true
Blade.Result, BladeKeepWasteResult = BladeKeepWaste.Make( Proc, Part, OptionalParameters)
dTimeToMachine = BladeKeepWasteResult.dTimeToMachine
dMRRBlade = BladeKeepWasteResult.dMRR
dCompletionPercentage = BladeKeepWasteResult.dCompletionPercentage
dQuality = BladeKeepWasteResult.dQuality
Strategy.Result.sInfo = BladeKeepWasteResult.sInfo or ''
end
-- lavorazione a cubetti / taglio singolo
@@ -127,20 +129,9 @@ function STR0005.Make( bAddMachining, Proc, Part, CustomParameters)
and not bIsTwoFacesCommonEdgeTooLong then
AuxiliaryData.bIgnoreNotClampableLength = false
local dMinZTopBlade
local dMaxNyTopBlade
local BladeToWasteResult
if Strategy.Parameters.dMinZAngleTopBlade then
dMinZTopBlade = sin( Strategy.Parameters.dMinZAngleTopBlade)
end
if Strategy.Parameters.dMaxYAngleTopBlade then
dMaxNyTopBlade = sin( Strategy.Parameters.dMaxYAngleTopBlade)
end
-- TODO rimuovere dMinNzTopBlade e dMaxNyTopBlade opzionali? non sono gestiti ovunque e probabilmente hanno utilizzo limitato
local OptionalParameters = { dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume,
dMaxWasteLength = Strategy.Parameters.dMaxWasteLength,
dMinNzTopBlade = dMinZTopBlade,
dMaxNyTopBlade = dMaxNyTopBlade,
bSaveAddedGeometries = bAddMachining,
dExtendAfterTail = dExtendAfterTail,
bAllowFastCuts = Strategy.Parameters.bAllowFastCuts,
@@ -172,19 +163,9 @@ function STR0005.Make( bAddMachining, Proc, Part, CustomParameters)
-- TODO da completare
-- TODO va messa per prima????????
if idAddedTmFace then
local dMinZTopBlade
local dMaxNyTopBlade
local BladeToWasteResult
if Strategy.Parameters.dMinZAngleTopBlade then
dMinZTopBlade = sin( Strategy.Parameters.dMinZAngleTopBlade)
end
if Strategy.Parameters.dMaxYAngleTopBlade then
dMaxNyTopBlade = sin( Strategy.Parameters.dMaxYAngleTopBlade)
end
local OptionalParameters = { dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume,
dMaxWasteLength = Strategy.Parameters.dMaxWasteLength,
dMinNzTopBlade = dMinZTopBlade,
dMaxNyTopBlade = dMaxNyTopBlade,
bSaveAddedGeometries = bAddMachining,
dExtendAfterTail = dExtendAfterTail
}
+20 -1
View File
@@ -5,9 +5,10 @@
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
local PreSimulationLib = require( 'PreSimulationLib')
-- strategie di base
local BladeToWaste = require( 'BLADETOWASTE')
@@ -74,6 +75,7 @@ local function GetTenonStrategy( Proc, Part)
local bMachIsOk = true
if ( Proc.FeatureInfo.vtTenonN:getZ() < 0 and TOOLS[Machining.Milling.ToolInfo.nToolIndex].SetupInfo.HeadType.bTop) or
( Proc.FeatureInfo.vtTenonN:getZ() > 0 and TOOLS[Machining.Milling.ToolInfo.nToolIndex].SetupInfo.HeadType.bBottom) then
-- TODO questo test va sostituito con check collisione asse Z (PreCollision)
local dTotalLen = TOOLS[Machining.Milling.ToolInfo.nToolIndex].dLength + TOOLS[Machining.Milling.ToolInfo.nToolIndex].SetupInfo.dPivot
local dHorizSpace = dTotalLen * sqrt( 1 - ( Proc.FeatureInfo.vtTenonN:getZ() * Proc.FeatureInfo.vtTenonN:getZ()))
if dHorizSpace - ( TOOLS[Machining.Milling.ToolInfo.nToolIndex].SetupInfo.dCAxisSideEncumbrance / 2) < Proc.b3Box:getDimX() then
@@ -158,6 +160,23 @@ local function GetTenonStrategy( Proc, Part)
Machining.Milling.AuxiliaryData.Clones[nIndexClones].dRadialOffset = ( i - 1) * dRealSideStep
end
end
-- test finecorsa sulla passata più esterna: se extracorsa, la lavorazione non è fattibile
-- TODO sostituire con applicazione della lavorazione?
-- TODO funzione per allungare il percorso??????
local idGeomMaxOffset = EgtCopyGlob( Proc.FeatureInfo.idAddAuxGeom, Part.idTempGroup)
EgtOffsetCurve( idGeomMaxOffset, Machining.Milling.AuxiliaryData.Clones[1].dRadialOffset + TOOLS[Machining.Milling.ToolInfo.nToolIndex].dDiameter / 2, Part.idTempGroup)
local vtCurveStart = EgtSV( idGeomMaxOffset, GDB_ID.ROOT)
local vtCurveEnd = EgtEV( idGeomMaxOffset, GDB_ID.ROOT)
local ptCurveStart = EgtSP( idGeomMaxOffset, GDB_ID.ROOT) + -vtCurveStart * Machining.Milling.LeadIn.dTangentDistance + ( Proc.FeatureInfo.vtTenonN ^ -vtCurveStart) * Machining.Milling.LeadIn.dPerpDistance
local ptCurveEnd = EgtEP( idGeomMaxOffset, GDB_ID.ROOT) + vtCurveEnd * Machining.Milling.LeadOut.dTangentDistance + ( vtCurveEnd ^ Proc.FeatureInfo.vtTenonN) * Machining.Milling.LeadOut.dPerpDistance
EgtAddCurveCompoArcTg( idGeomMaxOffset, ptCurveStart, false, GDB_RT.GLOB)
EgtAddCurveCompoArcTg( idGeomMaxOffset, ptCurveEnd, true, GDB_RT.GLOB)
local bOutOfStroke = PreSimulationLib.CheckOutOfStrokeFromGeometry( idGeomMaxOffset, Proc.FeatureInfo.vtTenonN, Machining.Milling.nSCC, TOOLS[Machining.Milling.ToolInfo.nToolIndex])
if bOutOfStroke then
Machining.Milling.bIsApplicable = false
end
-- tempo di svuotatura
Result.Milling.dTimeToMachine = MachiningLib.GetTimeToMachineAllStepsWithLeadInOut( Machining.Milling, Part)
end
+130 -82
View File
@@ -5,9 +5,10 @@
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
local PreSimulationLib = require( 'PreSimulationLib')
-- strategie di base
local BladeToWaste = require('BLADETOWASTE')
@@ -15,6 +16,19 @@ local BladeToWaste = require('BLADETOWASTE')
local STR0007 = {}
local Strategy = {}
-------------------------------------------------------------------------------------------------------------
local function GetSCC( Machining)
local nSCC
if Machining.vtToolDirection:getX() > 0 then
nSCC = MCH_SCC.ADIR_XP
else
nSCC = MCH_SCC.ADIR_XM
end
return nSCC
end
-------------------------------------------------------------------------------------------------------------
function GetMortiseStrategy( Proc, Part)
local Machining = {}
@@ -94,11 +108,16 @@ function GetMortiseStrategy( Proc, Part)
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sMillingList, 'Milling')
Machining.Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
if Machining.Milling.ToolInfo.nToolIndex then
Machining.Milling.bIsApplicable = true
local dToolDiam = TOOLS[Machining.Milling.ToolInfo.nToolIndex].dDiameter
-- se richiesta passata antischeggia
if Strategy.Parameters.bAntiSplint then
Machining.AntiSplint = GetMortiseAntiSplint( Proc, Part, Machining.Milling.ToolInfo)
end
Machining.Milling.bIsApplicable = true
-- calcolo numero passate necessarie
if Proc.FeatureInfo.dMortiseMaxDist > TOOLS[Machining.Milling.ToolInfo.nToolIndex].dDiameter * 1.9 then
local dToolDiam = TOOLS[Machining.Milling.ToolInfo.nToolIndex].dDiameter
if Proc.FeatureInfo.dMortiseMaxDist > dToolDiam * 1.9 then
local sSideStep = TOOLS[Machining.Milling.ToolInfo.nToolIndex].dSideStep
Machining.nMillingPathsNeeded = 1 + ceil( ( Proc.FeatureInfo.dMortiseMaxDist - dToolDiam * 1.9) / ( sSideStep * 2))
-- suddivido step in base al numero passate da fare
@@ -107,6 +126,55 @@ function GetMortiseStrategy( Proc, Part)
Machining.nMillingPathsNeeded = 1
end
-- aggiungo geometria
Machining.Milling.Geometry = {{ Proc.FeatureInfo.idAddAuxGeom, -1}}
Machining.Milling.nToolIndex = Machining.Milling.ToolInfo.nToolIndex
Machining.Milling.nType = MCH_MY.MILLING
Machining.Milling.vtToolDirection = Proc.FeatureInfo.vtMortiseN
Machining.Milling.sDepth = Strategy.Parameters.dOverMatOnLength
-- LeadIn / LeadOut
Machining.Milling.LeadIn = {}
Machining.Milling.LeadOut = {}
Machining.Milling.LeadIn.nType = MCH_MILL_LI.TANGENT
Machining.Milling.LeadOut.nType = MCH_MILL_LI.TANGENT
local dDeltaAngledEntry = Proc.FeatureInfo.vtMortisePathStart * dToolDiam / 2
local dDeltaAngledExit = Proc.FeatureInfo.vtMortisePathEnd * dToolDiam / 2
Machining.Milling.LeadIn.dTangentDistance = dToolDiam / 2 + dDeltaAngledEntry + BeamData.COLL_SIC
Machining.Milling.LeadIn.dPerpDistance = 0
Machining.Milling.LeadOut.dTangentDistance = dToolDiam / 2 + dDeltaAngledExit + BeamData.COLL_SIC
Machining.Milling.LeadOut.dPerpDistance = 0
if Proc.AffectedFaces.bLeft and Strategy.bCanMoveAfterSplit then
Machining.Milling.sStage = 'AfterTail'
end
-- sistemo il lato e la direzione di lavoro
Machining.Milling.bInvert = EgtIf( TOOLS[Machining.Milling.ToolInfo.nToolIndex].bIsCCW, false, true)
Machining.Milling.nWorkside = EgtIf( TOOLS[Machining.Milling.ToolInfo.nToolIndex].bIsCCW, MCH_MILL_WS.LEFT, MCH_MILL_WS.RIGHT)
Machining.Milling.dMaxElev = Proc.FeatureInfo.dMortiseDepth
Machining.Milling.nSCC = GetSCC( Machining.Milling)
-- passate con sovramateriale
Machining.Milling.AuxiliaryData = { Clones = {}}
for i = Machining.nMillingPathsNeeded, 1, -1 do
-- il primo è il passaggio più esterno
local nIndexClones = Machining.nMillingPathsNeeded - i + 1
-- cambia solo sovrmateriale radiale
Machining.Milling.AuxiliaryData.Clones[nIndexClones] = {}
-- ultima passata con sovramateriale impostato
if i == 1 then
Machining.Milling.AuxiliaryData.Clones[nIndexClones].dRadialOffset = Strategy.Parameters.dOverMatOnRadius
else
-- suddivido step in base al numero passate da fare
Machining.Milling.AuxiliaryData.Clones[nIndexClones].dRadialOffset = ( i - 1) * Machining.Milling.dRealSideStep
end
end
local ParametersMRR = {}
ParametersMRR.nToolIndex = Machining.Milling.ToolInfo.nToolIndex
Result.Milling.dMRR = MachiningLib.GetToolMRR( ParametersMRR)
@@ -116,6 +184,17 @@ function GetMortiseStrategy( Proc, Part)
else
Machining.Milling.bIsApplicable = false
end
-- test finecorsa sulla passata più esterna: se extracorsa, la lavorazione non è fattibile
local idGeomMaxOffset = EgtCopyGlob( Proc.FeatureInfo.idAddAuxGeom, Part.idTempGroup)
-- TODO funzione per allungare il percorso??????
EgtAddCurveCompoLineTg( idGeomMaxOffset, Machining.Milling.LeadIn.dTangentDistance, false)
EgtAddCurveCompoLineTg( idGeomMaxOffset, Machining.Milling.LeadOut.dTangentDistance, true)
EgtOffsetCurve( idGeomMaxOffset, Machining.Milling.AuxiliaryData.Clones[1].dRadialOffset + TOOLS[Machining.Milling.ToolInfo.nToolIndex].dDiameter / 2, Part.idTempGroup)
local bOutOfStroke = PreSimulationLib.CheckOutOfStrokeFromGeometry( idGeomMaxOffset, Proc.FeatureInfo.vtMortiseN, Machining.Milling.nSCC, TOOLS[Machining.Milling.ToolInfo.nToolIndex])
if bOutOfStroke then
Machining.Milling.bIsApplicable = false
end
end
end
@@ -161,9 +240,9 @@ function GetMortiseMachiningResult( Proc, Result)
TotalResult.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
TotalResult.dMRR = ( Result.Milling.dMRR + Result.Cutting.dMRR) / 2
local sQuality
if not Strategy.Machining.bCuttingWithMill and Strategy.Machining.bAntiSplint then
if not Strategy.Machining.bCuttingWithMill and Strategy.Machining.AntiSplint.bIsApplicable then
sQuality = 'BEST'
elseif Strategy.Machining.bAntiSplint then
elseif Strategy.Machining.AntiSplint.bIsApplicable then
sQuality = 'FINE'
else
sQuality = 'STD'
@@ -176,7 +255,7 @@ function GetMortiseMachiningResult( Proc, Result)
TotalResult.sStatus = Result.Milling.sStatus
TotalResult.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
TotalResult.dMRR = Result.Milling.dMRR
local sQuality = EgtIf( Strategy.Parameters.bAntiSplint, 'BEST', 'STD')
local sQuality = EgtIf( Strategy.Machining.AntiSplint.bIsApplicable, 'BEST', 'STD')
TotalResult.dQuality = FeatureLib.GetStrategyQuality( sQuality)
TotalResult.nFeatureRotationIndex = GetFeatureRotationIndex( Proc)
TotalResult.sInfo = ''
@@ -233,14 +312,15 @@ local function CalcTopPath( nProcId, AuxId, nAddGrpId, dAltMort, dSideAng, b3Sol
end
-------------------------------------------------------------------------------------------------------------
function ApplyMortiseAntiSplint( Proc, Part)
function GetMortiseAntiSplint( Proc, Part, ToolInfo)
local AntiSplint = { bIsApplicable = false}
-- se il percorso non è chiuso, aggiungo percorso e lavorazione antischeggia
if not EgtCurveIsClosed( Proc.FeatureInfo.idAddAuxGeom) then
-- recupero gruppo per geometria addizionale
local nAddGrpId = BeamLib.GetAddGroup( Part.id)
-- calcolo il percorso top mortise
local dSideAng = TOOLS[Strategy.Machining.Milling.ToolInfo.nToolIndex].dSideAngle
local dToolDiam = TOOLS[Strategy.Machining.Milling.ToolInfo.nToolIndex].dDiameter
local dSideAng = TOOLS[ToolInfo.nToolIndex].dSideAngle
local dToolDiam = TOOLS[ToolInfo.nToolIndex].dDiameter
local vtExtr = Proc.FeatureInfo.vtMortiseN
local nAuxId1 = CalcTopPath( Proc.id, Proc.FeatureInfo.idAddAuxGeom, nAddGrpId, Proc.FeatureInfo.dMortiseDepth, dSideAng, Part.b3Part)
-- se esiste il percorso
@@ -275,48 +355,62 @@ function ApplyMortiseAntiSplint( Proc, Part)
if not nId1 then
local sErr = 'Wrong geometry : Error on DtMortise '
EgtOutLog( sErr)
return false, sErr
return AntiSplint
end
EgtModifyCurveExtrusion( nId1, vtExtr, GDB_RT.GLOB)
local Machining = {}
Machining.nToolIndex = Strategy.Machining.Milling.ToolInfo.nToolIndex
Machining.nType = MCH_MY.MILLING
Machining.vtToolDirection = Proc.FeatureInfo.vtMortiseN
AntiSplint.nToolIndex = ToolInfo.nToolIndex
AntiSplint.nType = MCH_MY.MILLING
AntiSplint.vtToolDirection = Proc.FeatureInfo.vtMortiseN
-- LeadIn / LeadOut
Machining.LeadIn = {}
Machining.LeadOut = {}
Machining.LeadIn.nType = MCH_MILL_LI.TANGENT
Machining.LeadOut.nType = MCH_MILL_LI.TANGENT
Machining.LeadIn.dTangentDistance = TOOLS[Strategy.Machining.Milling.ToolInfo.nToolIndex].dDiameter / 2 + BeamData.COLL_SIC
Machining.LeadIn.dPerpDistance = 0
Machining.LeadOut.dTangentDistance = TOOLS[Strategy.Machining.Milling.ToolInfo.nToolIndex].dDiameter / 2 + BeamData.COLL_SIC
Machining.LeadOut.dPerpDistance = 0
AntiSplint.LeadIn = {}
AntiSplint.LeadOut = {}
AntiSplint.LeadIn.nType = MCH_MILL_LI.TANGENT
AntiSplint.LeadOut.nType = MCH_MILL_LI.TANGENT
AntiSplint.LeadIn.dTangentDistance = TOOLS[ToolInfo.nToolIndex].dDiameter / 2 + BeamData.COLL_SIC
AntiSplint.LeadIn.dPerpDistance = 0
AntiSplint.LeadOut.dTangentDistance = TOOLS[ToolInfo.nToolIndex].dDiameter / 2 + BeamData.COLL_SIC
AntiSplint.LeadOut.dPerpDistance = 0
Machining.dRadialOffset = dToolRadDelta - 1
Machining.sDepth = Proc.FeatureInfo.dMortiseDepth - Strategy.Parameters.dOverMatOnLength
Machining.Geometry = {{ nId1, -1}}
Machining.bInvert = EgtIf( TOOLS[Strategy.Machining.Milling.ToolInfo.nToolIndex].bIsCCW, false, true)
Machining.nWorkside = EgtIf( TOOLS[Strategy.Machining.Milling.ToolInfo.nToolIndex].bIsCCW, MCH_MILL_WS.LEFT, MCH_MILL_WS.RIGHT)
Machining.dMaxElev = Proc.FeatureInfo.dMortiseDepth
AntiSplint.dRadialOffset = dToolRadDelta - 1
AntiSplint.sDepth = Proc.FeatureInfo.dMortiseDepth - Strategy.Parameters.dOverMatOnLength
AntiSplint.Geometry = {{ nId1, -1}}
AntiSplint.bInvert = EgtIf( TOOLS[ToolInfo.nToolIndex].bIsCCW, false, true)
AntiSplint.nWorkside = EgtIf( TOOLS[ToolInfo.nToolIndex].bIsCCW, MCH_MILL_WS.LEFT, MCH_MILL_WS.RIGHT)
AntiSplint.dMaxElev = Proc.FeatureInfo.dMortiseDepth
AntiSplint.nSCC = GetSCC( AntiSplint)
if Proc.AffectedFaces.bLeft and Strategy.bCanMoveAfterSplit then
Machining.sStage = 'AfterTail'
AntiSplint.sStage = 'AfterTail'
end
-- test finecorsa sulla passata più esterna: se extracorsa, la lavorazione non è fattibile
local idGeomOffset = EgtCopyGlob( nId1, Part.idTempGroup)
EgtOffsetCurve( idGeomOffset, EgtIf( AntiSplint.bInvert, -TOOLS[ToolInfo.nToolIndex].dDiameter / 2, TOOLS[ToolInfo.nToolIndex].dDiameter / 2), Part.idTempGroup)
-- trasformo arco in una curva compo per poi allungarla in direzione tangente
-- TODO funzione per allungare il percorso??????
idGeomOffset = EgtCurveCompo( Part.idTempGroup, idGeomOffset)
EgtAddCurveCompoLineTg( idGeomOffset, AntiSplint.LeadIn.dTangentDistance, false)
EgtAddCurveCompoLineTg( idGeomOffset, AntiSplint.LeadOut.dTangentDistance, true)
local bOutOfStroke = PreSimulationLib.CheckOutOfStrokeFromGeometry( idGeomOffset, Proc.FeatureInfo.vtMortiseN, AntiSplint.nSCC, TOOLS[ToolInfo.nToolIndex])
-- se soddisfa tutti i requisiti, posso applicare
if bOutOfStroke then
AntiSplint.bIsApplicable = false
else
AntiSplint.bIsApplicable = true
end
MachiningLib.AddMachinings( Proc, Machining)
else
local sErr = 'Wrong geometry : Error on DtMortise ' .. tostring( Proc.id)
EgtOutLog( sErr)
return false, sErr
end
else
local sErr = 'Wrong geometry : Error on DtMortise ' .. tostring( Proc.id)
EgtOutLog( sErr)
return false, sErr
end
end
return AntiSplint
end
@@ -400,65 +494,19 @@ function STR0007.Make( bAddMachining, Proc, Part, CustomParameters)
end
-- se richiesta passata antischeggia
if Strategy.Parameters.bAntiSplint then
ApplyMortiseAntiSplint( Proc, Part)
if Strategy.Machining.AntiSplint.bIsApplicable then
bAreAllMachiningsAdded = bAreAllMachiningsAdded and MachiningLib.AddMachinings( Proc, Strategy.Machining.AntiSplint)
end
-- passaggio sul profilo
if Strategy.Machining.Milling.bIsApplicable then
local AuxiliaryData = {}
-- se molti passaggi richiesti, si fa svuotatura
-- TODO in attesa delle svuotature, si fanno passaggi senza limiti sul numero massimo. Poi togliere il FALSE nella condizione.
if false and Strategy.Machining.nMillingPathsNeeded > Strategy.Parameters.nMaxMillingPaths then
-- TODO. SERVONO NUOVE SVUOTATURE!!!!
else
-- aggiungo geometria
Strategy.Machining.Milling.Geometry = {{ Proc.FeatureInfo.idAddAuxGeom, -1}}
Strategy.Machining.Milling.nToolIndex = Strategy.Machining.Milling.ToolInfo.nToolIndex
Strategy.Machining.Milling.nType = MCH_MY.MILLING
Strategy.Machining.Milling.vtToolDirection = Proc.FeatureInfo.vtMortiseN
Strategy.Machining.Milling.sDepth = Strategy.Parameters.dOverMatOnLength
-- LeadIn / LeadOut
Strategy.Machining.Milling.LeadIn = {}
Strategy.Machining.Milling.LeadOut = {}
Strategy.Machining.Milling.LeadIn.nType = MCH_MILL_LI.TANGENT
Strategy.Machining.Milling.LeadOut.nType = MCH_MILL_LI.TANGENT
Strategy.Machining.Milling.LeadIn.dTangentDistance = TOOLS[Strategy.Machining.Milling.ToolInfo.nToolIndex].dDiameter / 2 + BeamData.COLL_SIC
Strategy.Machining.Milling.LeadIn.dPerpDistance = 0
Strategy.Machining.Milling.LeadOut.dTangentDistance = TOOLS[Strategy.Machining.Milling.ToolInfo.nToolIndex].dDiameter / 2 + BeamData.COLL_SIC
Strategy.Machining.Milling.LeadOut.dPerpDistance = 0
if Proc.AffectedFaces.bLeft and Strategy.bCanMoveAfterSplit then
Strategy.Machining.Milling.sStage = 'AfterTail'
end
-- sistemo il lato e la direzione di lavoro
Strategy.Machining.Milling.bInvert = EgtIf( TOOLS[Strategy.Machining.Milling.ToolInfo.nToolIndex].bIsCCW, false, true)
Strategy.Machining.Milling.nWorkside = EgtIf( TOOLS[Strategy.Machining.Milling.ToolInfo.nToolIndex].bIsCCW, MCH_MILL_WS.LEFT, MCH_MILL_WS.RIGHT)
Strategy.Machining.Milling.dMaxElev = Proc.FeatureInfo.dMortiseDepth
-- TODO calcolare SCC
-- passate con sovramateriale
AuxiliaryData.Clones = {}
for i = Strategy.Machining.nMillingPathsNeeded, 1, -1 do
-- il primo è il passaggio più esterno
local nIndexClones = Strategy.Machining.nMillingPathsNeeded - i + 1
-- cambia solo sovrmateriale radiale
AuxiliaryData.Clones[nIndexClones] = {}
-- ultima passata con sovramateriale impostato
if i == 1 then
AuxiliaryData.Clones[nIndexClones].dRadialOffset = Strategy.Parameters.dOverMatOnRadius
else
-- suddivido step in base al numero passate da fare
AuxiliaryData.Clones[nIndexClones].dRadialOffset = ( i - 1) * Strategy.Machining.Milling.dRealSideStep
end
end
-- aggiunge lavorazione
bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, Strategy.Machining.Milling, AuxiliaryData)
bAreAllMachiningsAdded = bAreAllMachiningsAdded and MachiningLib.AddMachinings( Proc, Strategy.Machining.Milling, Strategy.Machining.Milling.AuxiliaryData)
end
end
end
+4 -7
View File
@@ -6,7 +6,7 @@
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
-- strategie di base
@@ -174,13 +174,13 @@ local function GetBestPocketingStrategy( Proc, Part)
Strategy.Result.dMRR = MachiningLib.GetToolMRR( Machining.Pocketing[2].ToolInfo)
Machining.Pocketing[1].bIsApplicable = false
-- solo svuotatura diretta come normale mortasa, incompleta
elseif not Machining.Pocketing[2].bIsApplicable then
elseif Machining.Pocketing[1].bIsApplicable and not Machining.Pocketing[2].bIsApplicable then
Machining.sTypeMachining = 'Side1'
Machining.dResidual = Machining.Pocketing[1].ToolInfo.dResidualDepth
Machining.Pocketing[1].sDepth = -Machining.dResidual
Strategy.Result.dMRR = MachiningLib.GetToolMRR( Machining.Pocketing[1].ToolInfo)
-- solo svuotatura diretta come normale mortasa, incompleta
elseif not Machining.Pocketing[1].bIsApplicable then
elseif Machining.Pocketing[2].bIsApplicable and not Machining.Pocketing[1].bIsApplicable then
Machining.sTypeMachining = 'Side2'
Machining.dResidual = Machining.Pocketing[2].ToolInfo.dResidualDepth
Machining.Pocketing[2].sDepth = Proc.FeatureInfo.dMortiseDepth - Machining.dResidual
@@ -311,10 +311,7 @@ function STR0008.Make( bAddMachining, Proc, Part, CustomParameters)
-- si applicano le lavorazioni di svuotatura
for i = 1, #Strategy.Machining.Pocketing do
if Strategy.Machining.Pocketing[i].bIsApplicable then
Pocketing = {}
Pocketing.Steps = {}
Pocketing.LeadIn = {}
Pocketing.nType = MCH_MY.POCKETING
Pocketing = MachiningLib.InitMachiningParameters( MCH_MY.POCKETING)
Pocketing.nSubType = MCH_POCK_SUB.SPIRALOUT
Pocketing.LeadIn.nType = MCH_POCK_LI.ZIGZAG
Pocketing.Steps.dStep = TOOLS[Strategy.Machining.Pocketing[i].ToolInfo.nToolIndex].dStep
+5 -25
View File
@@ -1,6 +1,6 @@
{
"sStrategyId": "STR0009",
"sStrategyName": "Mill Heading",
"sStrategyName": "ScarfJoint",
"ParameterList" : [
{
"sName": "dDepthChamfer",
@@ -13,35 +13,15 @@
"sMinUserLevel": "1"
},
{
"sName": "dOverMaterial",
"sNameNge": "OVERMAT",
"sValue": "0",
"sDescriptionShort": "Overmaterial",
"sDescriptionLong": "",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "bForceStrip",
"sNameNge": "FORCE_STRIP",
"sName": "bAntiSplint",
"sNameNge": "ANTISPLINT",
"sValue": "false",
"sDescriptionShort": "Force strip",
"sDescriptionLong": "Enable the parameter to force the software to leave a strip to sustain the piece",
"sDescriptionShort": "Use Anti-Splint strategy",
"sDescriptionLong": "The strategy will apply blade cuts on corner to avoid wood splint",
"sType": "b",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "dStripWidth",
"sNameNge": "STRIP_WIDTH",
"sValue": "0",
"sDescriptionShort": "Strip width",
"sDescriptionLong": "Width of the strip in case if foreseen from the machining",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "sMillingList",
"sNameNge": "PROFILE_TOOL_LIST",
+179 -201
View File
@@ -1,165 +1,190 @@
-- Strategia: STR0009
-- Descrizione
-- Fresatura di contorno
-- Feature tipo Arco
-- Feature tipo ScarfJoint
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
-- strategie di base
local BladeToWaste = require('BLADETOWASTE')
local BladeToWaste = require( 'BLADETOWASTE')
local FaceByMill = require( 'FACEBYMILL')
local FaceByBlade = require( 'FACEBYBLADE')
local AntiSplintOnFace = require( 'ANTISPLINTONFACE')
-- Tabella per definizione modulo
local STR0009 = {}
local Strategy = {}
-------------------------------------------------------------------------------------------------------------
-- TODO gestire il caso in cui non si trova l'utensile
local function GetArcStrategy( Proc, Part)
local Machining = {}
local ToolSearchParameters = {}
local function GetFacesIdOrder( Proc, Part)
local Faces = {}
if Proc.nFct == 5 then
-- carico gli id delle facce
for i = 1, Proc.nFct do
Faces[#Faces + 1] = BeamLib.TableCopyDeep( Proc.Faces[i])
end
elseif Proc.nFct == 4 then
local vtN1 = Proc.Faces[1].vtN
local vtN2 = Proc.Faces[2].vtN
local nIndex = EgtIf( abs( vtN1:getX()) > abs( vtN2:getX()), 1, 2)
for i = nIndex, Proc.nFct do
Faces[#Faces + 1] = BeamLib.TableCopyDeep( Proc.Faces[i])
end
-- TODO manca il caso in cui mancano facce 4 e 5
else -- Proc.nFct == 3
for i = 2, Proc.nFct do
Faces[#Faces + 1] = BeamLib.TableCopyDeep( Proc.Faces[i])
end
end
-- recupero e verifico l'entità curva
local idAux = EgtGetInfo( Proc.id, 'AUXID', 'i')
if idAux then idAux = idAux + Proc.id end
if not idAux or ( EgtGetType( idAux) & GDB_FY.GEO_CURVE) == 0 then
local sErr = 'Error on process ' .. tostring( Proc.id) .. ' missing profile geometry'
return Faces
end
-------------------------------------------------------------------------------------------------------------
local function GetEdgeToMachine( ClosingFace, idBottomFace)
local EdgeToMachine
for i = 1, #ClosingFace.Edges do
if ClosingFace.Edges[i].idAdjacentFace == idBottomFace then
EdgeToMachine = ClosingFace.Edges[i]
break
end
end
return EdgeToMachine
end
-------------------------------------------------------------------------------------------------------------
local function GetScarfJointStrategy( Proc, Part)
-- ordino le facce in base al loro numero e al parallelismo delle due facce principali
-- faccia 0: superficie tappo (*potrebbe non esserci)
-- faccia 1: superficie principale di fondo
-- faccia 2: superficie opposta alla faccia 1
-- faccia 3: superficie principale superiore
-- faccia 4: superficie di testa (*potrebbe non esserci)
-- creo una tabella unica contenente tutte le lavorazioni
local Result = {}
local Cutting = { Machinings = {}, Result = {}}
local AntiSplints = {}
local Pocketing = {}
Result.dTimeToMachine = 0
local Faces = GetFacesIdOrder( Proc)
-- taglio su faccia 4
if Faces[4] and Faces[4].vtN then
-- recupero gruppo per geometria addizionale
local nAddGrpId = BeamLib.GetAddGroup( Part.id)
-- TODO la nuova faccia creata sulla 4 può tagliare faccia 1. In caso tagliasse faccia 1, bisogna calcolare i cubetti con 2 facce
Strategy.idFeatureCutPlane = EgtSurfTmPlaneInBBox( nAddGrpId, Faces[4].ptCenter, Faces[4].vtN, Part.b3Part, GDB_RT.GLOB)
Cutting.Machinings, Cutting.Result = BladeToWaste.Make( Strategy.idFeatureCutPlane, Part)
if Cutting.Result.sStatus == 'Completed' then
Cutting.Machinings.bIsApplicable = true
end
end
-- antischeggia facce 1 e 3
local bAreAllAntisplintsApplicable = true
if Strategy.Parameters.bAntiSplint then
AntiSplints = AntiSplintOnFace.Make( Proc, Part, Faces[2])
for k = 1, #AntiSplints do
if not AntiSplints[k].bIsApplicable then
bAreAllAntisplintsApplicable = false
break
end
end
end
-- svuotatura faccia 2
if Faces[2] then
local frPock, dL, dW = EgtSurfTmFacetMinAreaRectangle( Proc.id, Faces[2].id, GDB_ID.ROOT)
local ToolSearchParameters = {}
ToolSearchParameters.sMillShape = 'STANDARD'
ToolSearchParameters.vtToolDirection = Faces[2].vtN
ToolSearchParameters.dElevation = abs( ( Faces[2].ptCenter - Faces[4].ptCenter) * Faces[2].vtN)
ToolSearchParameters.dMaxToolDiameter = min( dL, dW)
ToolSearchParameters.ToolInfo = {}
ToolSearchParameters.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
if ToolSearchParameters.ToolInfo.nToolIndex then
local Machining = MachiningLib.InitMachiningParameters( MCH_MY.POCKETING)
Machining.Geometry = {{ Proc.id, Faces[2].id}}
Machining.dElevation = ToolSearchParameters.dElevation
Machining.dMaxElev = Machining.dElevation
Machining.vtToolDirection = ToolSearchParameters.vtToolDirection
Machining.nSubType = MCH_POCK_SUB.SPIRALIN
Machining.LeadIn.nType = MCH_POCK_LI.ZIGZAG
Machining.Steps.dStep = TOOLS[ToolSearchParameters.ToolInfo.nToolIndex].dStep
Machining.Steps.dSideStep = TOOLS[ToolSearchParameters.ToolInfo.nToolIndex].dSideStep
Machining.nToolIndex = ToolSearchParameters.ToolInfo.nToolIndex
Machining.LeadIn.dTangentDistance = TOOLS[ToolSearchParameters.ToolInfo.nToolIndex].dDiameter / 2
Machining.LeadIn.dElevation = TOOLS[ToolSearchParameters.ToolInfo.nToolIndex].dDiameter / 2
Machining.sDepth = 0
Machining.dResidualDepth = ToolSearchParameters.ToolInfo.dResidualDepth
-- TODO vedere se questo parametro con svuotature nuove si può rimuovere
Machining.dOpenMinSafe = Strategy.Parameters.dOpenMinSafe
Machining.dTimeToMachine = MachiningLib.GetTimeToMachineAllStepsWithLeadInOut( Machining, Part)
Result.dTimeToMachine = Result.dTimeToMachine + Machining.dTimeToMachine
table.insert( Pocketing, Machining)
Pocketing.bIsApplicable = true
-- se non sono stati fatti i passaggi antischeggia si verifica che le facce siano a 90°, altrimenti serve passaggio con fresa
if not Strategy.Parameters.bAntiSplint or not bAreAllAntisplintsApplicable then
local dAngleBetweenFaces = Proc.AdjacencyMatrix[1][2] or 0
-- si fa passaggio con fresa
if dAngleBetweenFaces > -90 then
local EdgeToMachine = GetEdgeToMachine( Faces[1], Faces[2].id)
local CuttingClosingFace = FaceByBlade.Make( Proc, Part, Faces[1], EdgeToMachine)
if CuttingClosingFace.bIsApplicable then
table.insert( AntiSplints, CuttingClosingFace)
end
end
end
end
end
-- se manca taglio principale, feature non eseguibile
if not Cutting.Machinings.bIsApplicable then
local sErr = 'Feature '.. Proc.idFeature .. ' : strategy ' .. Strategy.sName .. ' not applicable'
EgtOutLog( sErr)
return false, sErr
end
Proc.idAddAuxGeom = idAux
-- recupero i dati della curva e del profilo
local dDepth = abs( EgtCurveThickness( idAux))
local vtExtr = EgtCurveExtrusion( idAux, GDB_RT.GLOB)
local bToolInvert = ( vtExtr:getZ() < -0.1)
local bIsHorizontal = abs( vtExtr:getZ()) < 10 * GEO.EPS_SMALL
local bIsFeatureDown = Proc.AffectedFaces.bBottom and not Proc.AffectedFaces.bTop
local bIsFeatureBack = Proc.AffectedFaces.bBack and not Proc.AffectedFaces.bFront
local bForceStrip = Strategy.Parameters.bForceStrip
local dDimStrip = EgtIf( Strategy.Parameters.dStripWidth < 100 * GEO.EPS_SMALL, nil, Strategy.Parameters.dStripWidth)
local bExecStrip = false
-- se la lavorazione si trova nella parte inferiore o in battuta dietro, il codolo va sempre lasciato
if bIsFeatureDown or bIsFeatureBack or bForceStrip then
if bIsFeatureDown or bIsFeatureBack then
dDimStrip = dDimStrip or max( BeamData.DIM_STRIP or 5, 5)
else
dDimStrip = dDimStrip or max( BeamData.DIM_STRIP_SMALL or 5, 1)
end
bExecStrip = true
end
if not bExecStrip then
dDimStrip = 0
end
-- se lavorazione orizzontale
if bIsHorizontal then
local bDouble
local Milling = MachiningLib.InitMachiningParameters( MCH_MY.MILLING)
Milling.bIsApplicable = false
ToolSearchParameters = {}
ToolSearchParameters.sMillShape = 'STANDARD'
ToolSearchParameters.dElevation = EgtIf( bExecStrip, ( dDepth - dDimStrip) / 2, dDepth + BeamData.MILL_OVERLAP)
ToolSearchParameters.vtToolDirection = EgtIf( bToolInvert, -vtExtr, vtExtr)
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sMillingList, 'Milling')
Milling.ToolInfo = {}
Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
-- se posso lavorare in una passata, ma utensile trovato non completa la lavorazione,
-- allora provo a cercare utensile con massimo materiale sufficiente per fare le due passate, magari trova un utensile più prestante
if Milling.ToolInfo.dResidualDepth > 10 * GEO.EPS_SMALL and not bExecStrip then
bDouble = true
ToolSearchParameters.dElevation = ( dDepth + BeamData.MILL_OVERLAP) / 2
ToolSearchParameters.vtToolDirection = EgtIf( bToolInvert, -vtExtr, vtExtr)
end
Milling.bToolInvert = bToolInvert
Milling.vtToolDirection = vtExtr
if bDouble or bExecStrip then
if bDouble then
Milling.sDepth = ( dDepth + BeamData.MILL_OVERLAP) / 2
else
Milling.sDepth = ( dDepth - dDimStrip) / 2
end
table.insert( Machining, Milling)
local Milling2 = BeamLib.TableCopyDeep( Milling)
table.insert( Machining, Milling2)
else
Milling.sDepth = dDepth + BeamData.MILL_OVERLAP
table.insert( Machining, Milling)
end
-- se lavorazione verticale
Result = FeatureLib.GetStrategyResultNotApplicable( sErr)
else
-- si cerca utensile 1
local Milling = {}
Milling.bIsApplicable = false
ToolSearchParameters = {}
ToolSearchParameters.sMillShape = 'STANDARD'
ToolSearchParameters.dElevation = dDepth + BeamData.MILL_OVERLAP
ToolSearchParameters.vtToolDirection = EgtIf( bToolInvert, -vtExtr, vtExtr)
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sMillingList, 'Milling')
Milling.ToolInfo = {}
Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
-- si cerca utensile 2
local Milling2 = {}
Milling2.bIsApplicable = false
ToolSearchParameters = {}
ToolSearchParameters.sMillShape = 'STANDARD'
ToolSearchParameters.dElevation = dDepth + BeamData.MILL_OVERLAP
ToolSearchParameters.vtToolDirection = EgtIf( bToolInvert, vtExtr, -vtExtr)
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sMillingList, 'Milling')
Milling2.ToolInfo = {}
Milling2.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
-- se serve codolo
if bExecStrip then
-- se a disposizione entrambi gli utensili
if Milling.ToolInfo.nToolIndex and Milling2.ToolInfo.nToolIndex then
table.insert( Machining, Milling)
table.insert( Machining, Milling2)
-- se disponibile solo primo utensile
elseif Milling.ToolInfo.nToolIndex then
table.insert( Machining, Milling)
-- se disponibile solo secondo utensile
elseif Milling2.ToolInfo.nToolIndex then
table.insert( Machining, Milling2)
-- nessun utensile disponibile
local dCompletionPercentage = 100
-- completa se svuotatura eseguita e antisplit eseguiti (o non richiesti)
if Pocketing.bIsApplicable and ( bAreAllAntisplintsApplicable or not Strategy.Parameters.bAntiSplint) then
Result.sStatus = 'Completed'
if bAreAllAntisplintsApplicable then
Result.dQuality = FeatureLib.GetStrategyQuality( 'FINE')
else
-- non si fa nulla
Result.dQuality = FeatureLib.GetStrategyQuality( 'STD')
end
-- altrimenti senza codolo
-- altrimenti non completa
else
-- se utensile 1 esegue completamente
if Milling.ToolInfo.nToolIndex and Milling.ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then
table.insert( Machining, Milling)
-- se utensile 2 esegue completamente
elseif Milling2.ToolInfo.nToolIndex and Milling2.ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then
table.insert( Machining, Milling2)
-- se possono lavorare entrambi
elseif Milling.ToolInfo.nToolIndex and Milling2.ToolInfo.nToolIndex then
table.insert( Machining, Milling)
table.insert( Machining, Milling2)
-- se utensile 1 non completo
elseif Milling.ToolInfo.nToolIndex then
table.insert( Machining, Milling)
-- se utensile 2 non completo
elseif Milling2.ToolInfo.nToolIndex then
table.insert( Machining, Milling2)
Result.dQuality = FeatureLib.GetStrategyQuality( 'STD')
Result.sStatus = 'Not-Completed'
-- se fa solo svuotatura
if Pocketing.bIsApplicable then
dCompletionPercentage = 90
Result.sInfo = 'Anti-Split not executed'
elseif Strategy.Parameters.bAntiSplint and bAreAllAntisplintsApplicable then
dCompletionPercentage = 75
Result.sInfo = 'Pocketing not executed'
else
dCompletionPercentage = 50
Result.sInfo = 'Only the cut has been executed'
end
end
Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( dCompletionPercentage)
end
-- TODO VOTO DA FARE!!!!
Strategy.Result.sStatus = 'Completed'
Strategy.Result.dCompletionIndex = 5
Strategy.Result.dMRR = MachiningLib.GetToolMRR( Machining[1].ToolInfo or Machining[2].ToolInfo)
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'MILL')
Strategy.Result.sInfo = ''
-- creo una tabella unica contenente tutte le lavorazioni
local Machinings = {}
EgtJoinTables( Machinings, Cutting.Machinings)
EgtJoinTables( Machinings, AntiSplints)
EgtJoinTables( Machinings, Pocketing)
return Machining
return Machinings, Result
end
-------------------------------------------------------------------------------------------------------------
@@ -173,80 +198,33 @@ function STR0009.Make( bAddMachining, Proc, Part, CustomParameters)
Strategy.Result = {}
local bAreAllMachiningsAdded = true
local Milling = {}
Strategy.Machinings = GetArcStrategy( Proc, Part)
-- controlli preliminari
if Proc.nFct < 3 or Proc.nFct > 5 then
local sErr = 'Feature '.. Proc.idFeature .. ' : strategy ' .. StrategyLib.Config.sStrategyId .. ' not applicable'
EgtOutLog( sErr)
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( sErr)
return false, Strategy.Result
end
if bAddMachining and Strategy.Result.sStatus ~= 'Not-Applicable' then
-- eventuali punti di spezzatura
local FeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
Strategy.Machinings, Strategy.Result = GetScarfJointStrategy( Proc, Part)
for i = 1, #Strategy.Machinings do
Strategy.Machinings[i].Geometry = {{ Proc.idAddAuxGeom, -1}}
Strategy.Machinings[i].nToolIndex = Strategy.Machinings[i].ToolInfo.nToolIndex
Strategy.Machinings[i].nType = MCH_MY.MILLING
Strategy.Machinings[i].dStartSafetyLength = 0
Strategy.Machinings[i].Steps = {}
Strategy.Machinings[i].Steps.dStep = TOOLS[Strategy.Machinings[i].ToolInfo.nToolIndex].dStep
Strategy.Machinings[i].Steps = MachiningLib.GetMachiningSteps( tonumber( Strategy.Machinings[i].sDepth), TOOLS[Strategy.Machinings[i].nToolIndex].dStep)
-- LeadIn / LeadOut
Strategy.Machinings[i].LeadIn = {}
Strategy.Machinings[i].LeadOut = {}
Strategy.Machinings[i].LeadIn.nType = MCH_MILL_LI.TANGENT
Strategy.Machinings[i].LeadOut.nType = MCH_MILL_LI.TANGENT
Strategy.Machinings[i].LeadIn.dTangentDistance = TOOLS[Strategy.Machinings[i].ToolInfo.nToolIndex].dDiameter / 2 + BeamData.COLL_SIC
Strategy.Machinings[i].LeadIn.dPerpDistance = 0
Strategy.Machinings[i].LeadIn.dStartAddLength = 0
Strategy.Machinings[i].LeadOut.dTangentDistance = TOOLS[Strategy.Machinings[i].ToolInfo.nToolIndex].dDiameter / 2 + BeamData.COLL_SIC
Strategy.Machinings[i].LeadOut.dPerpDistance = 0
Strategy.Machinings[i].LeadOut.dEndAddLength = 0
local dLengthOnX = Proc.b3Box:getDimX()
Strategy.bCanMoveAfterSplit = MachiningLib.CanMoveAfterSplitcut( dLengthOnX, Part)
if Proc.AffectedFaces.bLeft and Strategy.bCanMoveAfterSplit then
Strategy.Machinings[i].sStage = 'AfterTail'
end
-- preparo attacco/uscita in caso di spezzatura arco
Strategy.Machinings[i].LeadInForSplit = BeamLib.TableCopyDeep( Strategy.Machinings[i].LeadIn)
Strategy.Machinings[i].LeadOutForSplit = BeamLib.TableCopyDeep( Strategy.Machinings[i].LeadOut)
Strategy.Machinings[i].LeadInForSplit.nType = MCH_MILL_LI.LINEAR
Strategy.Machinings[i].LeadOutForSplit.nType = MCH_MILL_LI.LINEAR
Strategy.Machinings[i].LeadInForSplit.dTangentDistance = 0
Strategy.Machinings[i].LeadInForSplit.dPerpDistance = TOOLS[Strategy.Machinings[i].ToolInfo.nToolIndex].dDiameter / 2 + BeamData.COLL_SIC
Strategy.Machinings[i].LeadOutForSplit.dTangentDistance = 0
Strategy.Machinings[i].LeadOutForSplit.dPerpDistance = TOOLS[Strategy.Machinings[i].ToolInfo.nToolIndex].dDiameter / 2 + BeamData.COLL_SIC
-- sistemo il lato e la direzione di lavoro
if i == 1 then
Strategy.Machinings[i].bInvert = EgtIf( TOOLS[Strategy.Machinings[i].ToolInfo.nToolIndex].bIsCCW, false, true)
Strategy.Machinings[i].nWorkside = EgtIf( TOOLS[Strategy.Machinings[i].ToolInfo.nToolIndex].bIsCCW, MCH_MILL_WS.RIGHT, MCH_MILL_WS.LEFT)
else
Strategy.Machinings[i].bToolInvert = true
Strategy.Machinings[i].bInvert = EgtIf( TOOLS[Strategy.Machinings[i].ToolInfo.nToolIndex].bIsCCW, true, false)
Strategy.Machinings[i].nWorkside = EgtIf( TOOLS[Strategy.Machinings[i].ToolInfo.nToolIndex].bIsCCW, MCH_MILL_WS.RIGHT, MCH_MILL_WS.LEFT)
end
Strategy.Machinings[i].ptEdge1 = EgtSP( Proc.idAddAuxGeom, GDB_ID.ROOT)
Strategy.Machinings[i].ptEdge2 = EgtEP( Proc.idAddAuxGeom, GDB_ID.ROOT)
Strategy.Machinings[i].dEdgeLength = EgtCurveLength( Proc.idAddAuxGeom)
Strategy.Machinings[i].vtEdgeDirection = EgtSV( Proc.idAddAuxGeom, GDB_ID.ROOT) + EgtMV( Proc.idAddAuxGeom, GDB_ID.ROOT) + EgtEV( Proc.idAddAuxGeom, GDB_ID.ROOT)
Strategy.Machinings[i].dLengthOnX = Proc.b3Box:getDimX()
local MachiningToSplit = {}
table.insert( MachiningToSplit, Strategy.Machinings[i])
local MachiningResult = MachiningLib.GetSplitMachinings( MachiningToSplit, FeatureSplittingPoints, Part)
-- aggiunta lavorazioni
if #Strategy.Machinings > 0 then
if bAddMachining and Strategy.Result.sStatus ~= 'Not-Applicable' then
-- aggiunge lavorazione
for j = 1, #MachiningResult do
bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, MachiningResult[j])
for j = 1, #Strategy.Machinings do
if Proc.AffectedFaces.bLeft then
Strategy.Machinings[j].sStage = 'AfterTail'
end
bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, Strategy.Machinings[j])
end
end
else
bAreAllMachiningsAdded = false
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable()
end
return bAreAllMachiningsAdded, Strategy.Result
end
+22 -2
View File
@@ -3,7 +3,7 @@
"sStrategyName": "Milling",
"ParameterList" : [
{
"sName": "dAntiSplintWithBlade",
"sName": "bAntiSplintWithBlade",
"sNameNge": "ANTISPLINT_BLADE",
"sValue": "false",
"sDescriptionShort": "Antisplint with blade",
@@ -17,7 +17,27 @@
"sNameNge": "EXTEND_AFTER_TAIL",
"sValue": "",
"sDescriptionShort": "Extend after tail",
"sDescriptionLong": "The automatism considers this lenght as machinable. This means you accept to damage the next piece in the bar",
"sDescriptionLong": "The automatism considers this length as machinable. This means you accept to damage the next piece in the bar",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "bFinishWithMill",
"sNameNge": "ALLOW_FINISH_MILL",
"sValue": "true",
"sDescriptionShort": "Clean radius with mill",
"sDescriptionLong": "Clean radius with mill",
"sType": "b",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "dMillingOffsetFromSide",
"sNameNge": "MILLING_OFFSET_SIDE",
"sValue": "1",
"sDescriptionShort": "Milling offset from side",
"sDescriptionLong": "",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
+248 -85
View File
@@ -5,11 +5,13 @@
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
-- strategie di base
local FaceByMill = require('FACEBYMILL')
local FaceByMill = require( 'FACEBYMILL')
local FaceByBlade = require( 'FACEBYBLADE')
local AntiSplintOnFace = require( 'ANTISPLINTONFACE')
-- Tabella per definizione modulo
local STR0010 = {}
@@ -34,7 +36,7 @@ local function GetStrategyCompletionPercentage( Machinings)
if nWeightsCount ~= 0 and nWeightsCount ~= i then
error( 'GetWeightedCompletionPercentage : inconsistent weights')
end
local dWeightedCompletionPercentage = Machining.dCompletionPercentage / 100 * dWeight
local dWeightedCompletionPercentage = ( Machining.dCompletionPercentage or 0) / 100 * dWeight
if Machining.bIsApplicable then
dCompletionPercentageNumerator = dCompletionPercentageNumerator + dWeightedCompletionPercentage
end
@@ -47,34 +49,52 @@ local function GetStrategyCompletionPercentage( Machinings)
end
-------------------------------------------------------------------------------------------------------------
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
local function CompareEdgesLongestTop( EdgeA, EdgeB)
-- si preferiscono i lati più lunghi
if EdgeA.dLength > EdgeB.dLength + 10 * GEO.EPS_SMALL then
return true
elseif abs( EdgeA.vtN:getX()) > abs( EdgeB.vtN:getX()) + 10 * GEO.EPS_SMALL then
elseif EdgeA.dLength < EdgeB.dLength - 10 * GEO.EPS_SMALL then
return false
-- se stessa X si preferiscono i lati più lunghi (nel caso di 5 lati è quello non spezzato)
-- se stessa lunghezza si preferiscono i lati più in basso
else
if EdgeA.dLength > EdgeB.dLength + 10 * GEO.EPS_SMALL then
if EdgeA.vtN:getZ() > EdgeB.vtN:getZ() + 10 * GEO.EPS_SMALL then
return true
elseif EdgeA.dLength < EdgeB.dLength - 10 * GEO.EPS_SMALL then
elseif EdgeA.vtN:getZ() < EdgeB.vtN:getZ() - 10 * GEO.EPS_SMALL then
return false
-- se stessa lunghezza si preferiscono i lati più in basso
-- TODO qui dipenderà dalla lama scelta
-- se stessa Z si preferiscono i lati verso il fronte della trave
else
if EdgeA.vtN:getZ() > EdgeB.vtN:getZ() + 10 * GEO.EPS_SMALL then
if EdgeA.vtN:getY() > EdgeB.vtN:getY() + 10 * GEO.EPS_SMALL then
return true
elseif EdgeA.vtN:getZ() < EdgeB.vtN:getZ() - 10 * GEO.EPS_SMALL then
elseif EdgeA.vtN:getY() < EdgeB.vtN:getY() - 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
return false
end
end
end
end
-------------------------------------------------------------------------------------------------------------
local function CompareEdgesLongestBottom( EdgeA, EdgeB)
-- si preferiscono i lati più lunghi
if EdgeA.dLength > EdgeB.dLength + 10 * GEO.EPS_SMALL then
return true
elseif EdgeA.dLength < EdgeB.dLength - 10 * GEO.EPS_SMALL then
return false
-- se stessa lunghezza si preferiscono i lati più in alto
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
@@ -83,7 +103,8 @@ end
-------------------------------------------------------------------------------------------------------------
local function IsTopologyOk( Proc)
if Proc.Topology.sFamily == 'Bevel' or Proc.Topology.sFamily == 'DoubleBevel' or
Proc.Topology.sName == 'VGroove-2-Through' or Proc.Topology.sName == 'Rabbet-2-Through' then
Proc.Topology.sName == 'VGroove-2-Through' or Proc.Topology.sName == 'Rabbet-2-Through' or
Proc.Topology.sName == 'Cut-1-Through' then
return true
else
return false
@@ -92,7 +113,7 @@ end
-------------------------------------------------------------------------------------------------------------
-- TODO modificare funzione e verificare pinzaggio con regioni e area outline
local function IsPositionOK( Proc, Part)
local function IsPositionOk( Proc, Part)
local bIsFeatureLong = FeatureLib.IsMachiningLong( Proc.b3Box:getDimX(), Part, { dMaxSegmentLength = BeamData.LONGCUT_ENDLEN})
-- se impatta su faccia retro o sotto, controllo fattibilità
if Proc.AffectedFaces.bBack then
@@ -111,31 +132,24 @@ local function IsPositionOK( Proc, Part)
end
-------------------------------------------------------------------------------------------------------------
-- TODO da sistemare
local function GetBottomFaceEdge( Proc, nIndexFace)
local function GetLongEdgeToMachine( Face, bHeadType)
local Edge = {}
-- si lavora la bottom longitudinalmente
if Proc.nFct == 1 or Proc.Topology.sFamily == 'DoubleBevel' then
local BottomEdgesSorted = {}
for i = 1, #Proc.MainFaces.BottomFaces[nIndexFace].Edges do
table.insert( BottomEdgesSorted, Proc.MainFaces.BottomFaces[nIndexFace].Edges[i])
end
table.sort( BottomEdgesSorted, CompareEdges)
Edge = BottomEdgesSorted[1]
-- edge in comune tra le due facce
elseif Proc.nFct == 2 then
if nIndexFace == 1 then
Edge = Proc.MainFaces.BottomFaces[nIndexFace].MainEdges.LongEdges[1]
elseif nIndexFace == 2 then
Edge = Proc.MainFaces.BottomFaces[nIndexFace].MainEdges.BottomEdge
end
local EdgesSorted = {}
for i = 1, #Face.Edges do
table.insert( EdgesSorted, Face.Edges[i])
end
if bHeadType.bBottom then
table.sort( EdgesSorted, CompareEdgesLongestBottom)
else
if nIndexFace == 1 then
Edge = Proc.MainFaces.BottomFaces[nIndexFace].MainEdges.LongEdges[1]
elseif nIndexFace == 2 then
Edge = Proc.MainFaces.BottomFaces[nIndexFace].MainEdges.BottomEdge
end
table.sort( EdgesSorted, CompareEdgesLongestTop)
end
-- se il lato migliore è accessibile si sceglie questo, altrimenti il lato opposto; se entrambi non accessibili (faccia chiusa da due lati) si mantiene il lato scelto
Edge = EdgesSorted[1]
local EdgeOpposite = BeamLib.FindEdgeBestOrientedAsDirection( Face.Edges, -Edge.vtN)
if ( not EdgeOpposite.bIsOpen) and Edge.bIsOpen then
Edge = EdgeOpposite
end
return Edge
@@ -147,15 +161,28 @@ local function SortMachiningsBySegment( MachiningA, MachiningB)
return false
elseif MachiningB.nFeatureSegment > MachiningA.nFeatureSegment then
return true
-- se segmento uguale, si guarda la priorità
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
if MachiningA.nInternalSortingPriority > MachiningB.nInternalSortingPriority then
return false
elseif MachiningB.nInternalSortingPriority > MachiningA.nInternalSortingPriority then
return true
-- se priorità uguale, si minimizzano i cambi di lato
else
if MachiningA.sEdgeType == 'Side' and MachiningB.sEdgeType ~= 'Side' then
return true
elseif MachiningB.sEdgeType == 'Side' and MachiningA.sEdgeType ~= 'Side' then
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
@@ -171,6 +198,7 @@ function STR0010.Make( bAddMachining, Proc, Part, CustomParameters)
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( Proc, Part, CustomParameters, StrategyLib.Config)
Strategy.Machinings = {}
Strategy.Result = {}
local CalculatedMachinings = {}
-- controllo su topologia
if not IsTopologyOk( Proc) then
@@ -178,16 +206,24 @@ function STR0010.Make( bAddMachining, Proc, Part, CustomParameters)
return false, Strategy.Result
end
-- controllo dimensioni
if not IsPositionOK( Proc, Part) then
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( 'Feature not machinable in this position')
-- controllo dimensioni solo se non è forzata
if not CustomParameters.bForcedStrategy then
if not IsPositionOk( Proc, Part) then
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( 'Feature not machinable in this position')
return false, Strategy.Result
end
end
-- se la lavorazione ostacola il pinzaggio, non posso farla, serve una lavorazioen che lasci il testimone
if MachiningLib.IsFeatureHinderingClamping( Proc, Part) then
local sErr = 'Feature '.. Proc.idFeature .. ' : strategy ' .. StrategyLib.Config.sStrategyId .. ' not applicable ( Feature hinders clamping)'
EgtOutLog( sErr)
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( sErr)
return false, Strategy.Result
end
-- volume della feature
local dFeatureVolume = FeatureLib.GetFeatureVolume( Proc, Part)
-- TODO taglio su eventuali facce di chiusura
local dFeatureVolume = Proc.dVolume
-- eventuali punti di spezzatura
local FeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
@@ -201,45 +237,167 @@ function STR0010.Make( bAddMachining, Proc, Part, CustomParameters)
dExtendAfterTail = 10000
end
-- lavorazione della BottomFace
local bAreAllMachiningsAdded = true
local Milling = {}
local OptionalParametersFaceByMill = { nStepType = MCH_MILL_ST.ONEWAY, bIsSplitFeature = bIsSplitFeature, dExtendAfterTail = dExtendAfterTail}
local EdgeToMachine = GetBottomFaceEdge( Proc, 1)
if EdgeToMachine.bIsOpen then
OptionalParametersFaceByMill.dDepthToMachine = EdgeToMachine.dElevation + BeamData.CUT_EXTRA
end
Milling = FaceByMill.Make( Proc, Part, Proc.MainFaces.BottomFaces[1], EdgeToMachine, OptionalParametersFaceByMill)
if Milling.bIsApplicable then
table.insert( Strategy.Machinings, Milling)
-- ricerca delle Bottom (la principale deve avere 4 lati esatti)
local BottomFace1 = Proc.MainFaces.BottomFaces[1]
local BottomFace2 = Proc.MainFaces.BottomFaces[2]
if #BottomFace1.Edges ~= 4 then
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable()
return false, Strategy.Result
end
-- si lavora seconda BottomFace
if Proc.Topology.sFamily == 'DoubleBevel' or Proc.Topology.sName == 'Rabbet-2-Through' or Proc.Topology.sName == 'Bevel-2-Blind' then
local dAngleBetweenFaces = Proc.AdjacencyMatrix[1][2]
-- se convesso o concavo maggiore di angolo retto
if dAngleBetweenFaces >= -91 then
Milling = {}
OptionalParametersFaceByMill = { nStepType = MCH_MILL_ST.ONEWAY, bIsSplitFeature = bIsSplitFeature, dExtendAfterTail = dExtendAfterTail}
EdgeToMachine = GetBottomFaceEdge( Proc, 2)
if EdgeToMachine.bIsOpen then
OptionalParametersFaceByMill.dDepthToMachine = EdgeToMachine.dElevation + BeamData.CUT_EXTRA
-- ricerca utensile
local ToolSearchParameters = {}
ToolSearchParameters.dElevation = BottomFace1.dElevation
ToolSearchParameters.vtToolDirection = BottomFace1.vtN
ToolSearchParameters.bAllowTopHead = true
ToolSearchParameters.bAllowBottomHead = true
ToolSearchParameters.sMillShape = 'STANDARD'
local ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
local nToolIndex = ToolInfo.nToolIndex
-- se utensile non trovato si esce subito
if not TOOLS[nToolIndex] or not TOOLS[nToolIndex].sName then
local sMessage = 'Mill not found'
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( sMessage)
return false, Strategy.Result
end
-- per prima si lavora sempre la Bottom principale
local Milling1 = {}
local OptionalParametersMilling1 = { nStepType = MCH_MILL_ST.ONEWAY, bIsSplitFeature = bIsSplitFeature, dExtendAfterTail = dExtendAfterTail}
local BottomEdgeToMachine1 = GetLongEdgeToMachine( BottomFace1, TOOLS[nToolIndex].SetupInfo.HeadType)
if BottomEdgeToMachine1.bIsOpen then
OptionalParametersMilling1.dDepthToMachine = BottomEdgeToMachine1.dElevation + BeamData.CUT_EXTRA
end
Milling1 = FaceByMill.Make( Proc, Part, BottomFace1, BottomEdgeToMachine1, OptionalParametersMilling1)
Milling1.nInternalSortingPriority = 2
Milling1.dResultWeight = 0.3
table.insert( CalculatedMachinings, Milling1)
-- se necessario si lavora la seconda Bottom (solo se ha 4 lati esatti)
local Milling2
local BottomEdgeToMachine2
if BottomFace2 then
local dAngleBetweenFaces = Proc.AdjacencyMatrix[BottomFace1.id + 1][BottomFace2.id + 1]
if dAngleBetweenFaces >= -89.5 then
Milling2 = {}
if #BottomFace2.Edges == 4 then
local OptionalParametersMilling2 = { nStepType = MCH_MILL_ST.ONEWAY, bIsSplitFeature = bIsSplitFeature, dExtendAfterTail = dExtendAfterTail}
BottomEdgeToMachine2 = GetLongEdgeToMachine( BottomFace2, TOOLS[nToolIndex].SetupInfo.HeadType)
if BottomEdgeToMachine2.bIsOpen then
OptionalParametersMilling2.dDepthToMachine = BottomEdgeToMachine2.dElevation + BeamData.CUT_EXTRA
end
Milling2 = FaceByMill.Make( Proc, Part, BottomFace2, BottomEdgeToMachine2, OptionalParametersMilling2)
Milling2.nInternalSortingPriority = 2
Milling2.dResultWeight = 0.3
else
Milling2.bIsApplicable = false
end
Milling = FaceByMill.Make( Proc, Part, Proc.MainFaces.BottomFaces[2], EdgeToMachine, OptionalParametersFaceByMill)
if Milling.bIsApplicable then
table.insert( Strategy.Machinings, Milling)
table.insert( CalculatedMachinings, Milling2)
end
end
-- fresatura eventuali facce di chiusura (se non già lavorate)
-- TODO funzione
if Strategy.Parameters.bFinishWithMill then
if Milling1 then
-- si recuperano i lati chiusi non lavorati
local EdgesClosedNotMachined = {}
for i = 1, #BottomFace1.Edges do
if not( ( BottomFace1.Edges[i].id == BottomEdgeToMachine1.id) or BottomFace1.Edges[i].bIsOpen) then
table.insert( EdgesClosedNotMachined, BottomFace1.Edges[i])
end
end
-- su ognuno si fa la fresatura di pulizia
for i = 1, #EdgesClosedNotMachined do
local dMillingOffsetFromSide = Strategy.Parameters.bAntiSplintWithBlade and Strategy.Parameters.dMillingOffsetFromSide or 0
local dDepthToMachine = EdgesClosedNotMachined[i].dElevation - dMillingOffsetFromSide
local dToolMarkLength = Milling1.dToolMarkLength or 0
local OptionalParameters = {
bIsSplitFeature = bIsSplitFeature,
dExtendAfterTail = dExtendAfterTail,
dRadialStepSpan = dToolMarkLength,
dDepthToMachine = dDepthToMachine
}
local Milling = FaceByMill.Make( Proc, Part, BottomFace1, EdgesClosedNotMachined[i], OptionalParameters)
Milling.nInternalSortingPriority = 3
Milling.dResultWeight = 0.05
table.insert( CalculatedMachinings, Milling)
end
end
if Milling2 then
-- si recuperano i lati chiusi non lavorati
local EdgesClosedNotMachined = {}
for i = 1, #BottomFace2.Edges do
if not( ( BottomFace2.Edges[i].id == BottomEdgeToMachine2.id) or BottomFace2.Edges[i].bIsOpen) then
table.insert( EdgesClosedNotMachined, BottomFace2.Edges[i])
end
end
-- su ognuno si fa la fresatura di pulizia
for i = 1, #EdgesClosedNotMachined do
local dMillingOffsetFromSide = Strategy.Parameters.bAntiSplintWithBlade and Strategy.Parameters.dMillingOffsetFromSide or 0
local dDepthToMachine = EdgesClosedNotMachined[i].dElevation - dMillingOffsetFromSide
local dToolMarkLength = Milling2.dToolMarkLength or 0
local OptionalParameters = {
bIsSplitFeature = bIsSplitFeature,
dExtendAfterTail = dExtendAfterTail,
dRadialStepSpan = dToolMarkLength,
dDepthToMachine = dDepthToMachine
}
local Milling = FaceByMill.Make( Proc, Part, BottomFace2, EdgesClosedNotMachined[i], OptionalParameters)
Milling.nInternalSortingPriority = 3
Milling.dResultWeight = 0.05
table.insert( CalculatedMachinings, Milling)
end
end
end
-- calcolo completamento, serve la lista di lavorazioni che comprende le non applicabili
Strategy.Result.dCompletionPercentage = GetStrategyCompletionPercentage( Strategy.Machinings)
-- antischeggia sulle facce di chiusura delle facce lavorate
local CalculatedMachiningsNoAntisplint = BeamLib.TableCopyDeep( CalculatedMachinings)
if Strategy.Parameters.bAntiSplintWithBlade then
local OptionalParametersAntiSplint = {
bIsSplitFeature = bIsSplitFeature,
dExtendAfterTail = dExtendAfterTail,
nInternalSortingPriority = 1,
dResultWeight = 0.15
}
local AntiSplints1 = AntiSplintOnFace.Make( Proc, Part, BottomFace1, OptionalParametersAntiSplint)
for i = 1, #AntiSplints1 do
table.insert( CalculatedMachinings, AntiSplints1[i])
end
if Milling2 then
local AntiSplints2 = AntiSplintOnFace.Make( Proc, Part, BottomFace2, OptionalParametersAntiSplint)
for i = 1, #AntiSplints2 do
table.insert( CalculatedMachinings, AntiSplints2[i])
end
end
end
-- calcolo completamento, serve la lista di lavorazioni che comprende le non applicabili, ma non gli antischeggia (quelle alzano la qualità e sono già contemplate)
Strategy.Result.dCompletionPercentage = GetStrategyCompletionPercentage( CalculatedMachiningsNoAntisplint)
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( Strategy.Result.dCompletionPercentage)
-- lavorazioni da applicare spostate in lista finale
for i = 1, #CalculatedMachinings do
if CalculatedMachinings[i].bIsApplicable then
table.insert( Strategy.Machinings, CalculatedMachinings[i])
end
end
Strategy.Machinings = MachiningLib.GetSplitMachinings( Strategy.Machinings, FeatureSplittingPoints, Part)
table.sort( Strategy.Machinings, SortMachiningsBySegment)
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( Strategy.Machinings)
-- se non ci sono lati chiusi, la qualità è migliore
if Proc.Topology.sName == 'Bevel-1-Through' or Proc.Topology.sName == 'DoubleBevel-2-Through' or Proc.Topology.sName == 'Cut-1-Through' then
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'FINE')
else
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( Strategy.Machinings)
end
Strategy.Result.dTimeToMachine = FeatureLib.GetStrategyTimeToMachine( Strategy.Machinings)
Strategy.Result.dMRR = ( dFeatureVolume / Strategy.Result.dTimeToMachine) / pow( 10, 6)
if Strategy.Result.dCompletionPercentage > 100 - 10 * GEO.EPS_SMALL then
@@ -253,7 +411,12 @@ function STR0010.Make( bAddMachining, Proc, Part, CustomParameters)
if bAddMachining and Strategy.Result.sStatus ~= 'Not-Applicable' then
-- aggiunge lavorazione
for j = 1, #Strategy.Machinings do
bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, Strategy.Machinings[j])
local AuxiliaryData = {}
-- se strategia forzata non considero area non pinzabile
if CustomParameters.bForcedStrategy then
AuxiliaryData.bIgnoreNotClampableLength = true
end
bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, Strategy.Machinings[j], AuxiliaryData)
end
end
else
+143 -208
View File
@@ -5,7 +5,7 @@
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
-- strategie di base
@@ -20,224 +20,159 @@ local Strategy = {}
local function GetDrillingStrategy( Proc, Part)
local ToolSearchParameters = {}
local Machining = {}
local sQuality
-- se lavorazione orizzontale
if Proc.FeatureInfo.bIsDrillHorizontal then
local bDouble = false
local Drilling = MachiningLib.InitMachiningParameters( MCH_MY.DRILLING)
Drilling.bIsApplicable = false
-- si cerca utensile 1
local Drilling = MachiningLib.InitMachiningParameters( MCH_MY.DRILLING)
ToolSearchParameters = {}
ToolSearchParameters.dElevation = Proc.FeatureInfo.dDrillLen + BeamData.MILL_OVERLAP
ToolSearchParameters.vtToolDirection = Proc.FeatureInfo.vtDrillExtrusion
ToolSearchParameters.dToolDiameter = Proc.FeatureInfo.dDrillDiam
ToolSearchParameters.dDiameterTolerance = Strategy.Parameters.dDiameterTolerance
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sDrillBitList, 'Drilling')
ToolSearchParameters.ptCheckOutStroke = { Proc.FeatureInfo.ptDrillCenter + ( EgtMdbGetGeneralParam( MCH_GP.SAFEZ) * ToolSearchParameters.vtToolDirection)}
Drilling.ToolInfo = {}
Drilling.ToolInfo = MachiningLib.FindDrill( Proc, ToolSearchParameters)
-- se trovato utensile si settano i parametri comuni
if Drilling.ToolInfo.nToolIndex then
Drilling.Geometry = {{ Proc.FeatureInfo.idAddAuxGeom, -1}}
Drilling.nToolIndex = Drilling.ToolInfo.nToolIndex
Drilling.vtToolDirection = Proc.FeatureInfo.vtDrillExtrusion
Drilling.dStep = TOOLS[Drilling.nToolIndex].dStep
end
-- TODO se utensile 2 che si torverà è il gemello da usare nelle lavorazioni in doppio, allora gestire di conseguenza l'applicazione delle lavorazioni in doppio
-- si cerca utensile 2
local Drilling2 = MachiningLib.InitMachiningParameters( MCH_MY.DRILLING)
Drilling2.ToolInfo = {}
if Proc.FeatureInfo.bIsDrillOpen then
ToolSearchParameters = {}
ToolSearchParameters.dElevation = Proc.FeatureInfo.dDrillLen + BeamData.MILL_OVERLAP
ToolSearchParameters.vtToolDirection = Proc.FeatureInfo.vtDrillExtrusion
ToolSearchParameters.dToolDiameter = Proc.FeatureInfo.dDrillDiam
ToolSearchParameters.vtToolDirection = -Proc.FeatureInfo.vtDrillExtrusion
ToolSearchParameters.dDiameterTolerance = Strategy.Parameters.dDiameterTolerance
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sDrillBitList, 'Drilling')
Drilling.ToolInfo = {}
Drilling.ToolInfo = MachiningLib.FindDrill( Proc, ToolSearchParameters)
if Drilling.ToolInfo.nToolIndex then
Drilling.nToolIndex = Drilling.ToolInfo.nToolIndex
Drilling.Geometry = {{ Proc.FeatureInfo.idAddAuxGeom, -1}}
Drilling.dStep = TOOLS[Drilling.ToolInfo.nToolIndex].dStep
-- se lavorazione non completa o se si deve forare dai due lati
if Proc.FeatureInfo.bIsDrillOpen and
( Drilling.ToolInfo.dResidualDepth > 10 * GEO.EPS_SMALL or Strategy.Parameters.sDrillingMode == 'FORCE_TWO' or Strategy.Parameters.sDrillingMode == 'AUTO') then
bDouble = true
local dHalfDrill = ( Proc.FeatureInfo.dDrillLen + BeamData.MILL_OVERLAP) / 2
Drilling.sDepth = min( dHalfDrill, Proc.FeatureInfo.dDrillLen - Drilling.ToolInfo.dResidualDepth)
Drilling.vtFaceNormal = Proc.FeatureInfo.vtDrillExtrusion
Drilling.bInvert = false
Drilling.vtToolDirection = Proc.FeatureInfo.vtDrillExtrusion
table.insert( Machining, Drilling)
local Drilling2 = BeamLib.TableCopyDeep( Drilling)
Drilling2.bInvert = true
Drilling2.vtToolDirection = -Proc.FeatureInfo.vtDrillExtrusion
table.insert( Machining, Drilling2)
else
Drilling.sDepth = 'TH'
Drilling.vtFaceNormal = Proc.FeatureInfo.vtDrillExtrusion
Drilling.bInvert = false
Drilling.vtToolDirection = Proc.FeatureInfo.vtDrillExtrusion
table.insert( Machining, Drilling)
end
ToolSearchParameters.ptCheckOutStroke = { Proc.FeatureInfo.ptDrillCenter + ( ( Proc.FeatureInfo.dDrillLen + EgtMdbGetGeneralParam( MCH_GP.SAFEZ)) * ToolSearchParameters.vtToolDirection)}
-- voto
if Drilling.ToolInfo.dResidualDepth < 0 or ( Proc.FeatureInfo.dDrillLen + BeamData.MILL_OVERLAP) / 2 > Drilling.ToolInfo.dResidualDepth then
Strategy.Result.sStatus = 'Completed'
Strategy.Result.dCompletionIndex = 5
Strategy.Result.dMRR = MachiningLib.GetToolMRR( Machining[1].ToolInfo or Machining[2].ToolInfo)
if bDouble or not Proc.FeatureInfo.bIsDrillOpen then
sQuality = 'FINE'
else
sQuality = 'ROUGH'
end
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( sQuality)
Strategy.Result.sInfo = ''
else
Strategy.Result.sStatus = 'Not-Completed'
local dMachinedLen = EgtIf( bDouble, Machining[1].sDepth * 2, Proc.FeatureInfo.dDrillLen)
local dMachinedPrercentage = 100 * ( dMachinedLen / Proc.FeatureInfo.dDrillLen)
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( dMachinedPrercentage)
Strategy.Result.sInfo = 'Drill not complete, left ' .. tostring( 100 - ceil( dMachinedPrercentage)) .. '%'
Strategy.Result.dMRR = MachiningLib.GetToolMRR( Machining[1].ToolInfo or Machining[2].ToolInfo)
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'FINE') -- se non completo, anche se fosse foro singolo, comunque non esce dall'altra parte, quindi non scheggia
end
else
local sMessage = 'Drillbit not found'
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( sMessage)
end
-- se lavorazione verticale
else
-- si cerca utensile 1
local Drilling = MachiningLib.InitMachiningParameters( MCH_MY.DRILLING)
ToolSearchParameters = {}
ToolSearchParameters.dElevation = Proc.FeatureInfo.dDrillLen + BeamData.MILL_OVERLAP
ToolSearchParameters.vtToolDirection = Proc.FeatureInfo.vtDrillExtrusion
ToolSearchParameters.dToolDiameter = Proc.FeatureInfo.dDrillDiam
ToolSearchParameters.dDiameterTolerance = Strategy.Parameters.dDiameterTolerance
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sDrillBitList, 'Drilling')
Drilling.ToolInfo = {}
Drilling.ToolInfo = MachiningLib.FindDrill( Proc, ToolSearchParameters)
-- si cerca utensile 2
local Drilling2 = MachiningLib.InitMachiningParameters( MCH_MY.DRILLING)
Drilling2.ToolInfo = {}
if Proc.FeatureInfo.bIsDrillOpen then
ToolSearchParameters = {}
ToolSearchParameters.dElevation = Proc.FeatureInfo.dDrillLen + BeamData.MILL_OVERLAP
ToolSearchParameters.vtToolDirection = -Proc.FeatureInfo.vtDrillExtrusion
ToolSearchParameters.dDiameterTolerance = Strategy.Parameters.dDiameterTolerance
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sDrillBitList, 'Drilling')
Drilling2.ToolInfo = MachiningLib.FindDrill( Proc, ToolSearchParameters)
end
-- se possono lavorare entrambi e si deve fare lavorazione doppia e si riesce a completare
if Drilling.ToolInfo.nToolIndex and Drilling2.ToolInfo.nToolIndex and
( Strategy.Parameters.sDrillingMode == 'FORCE_TWO' or Strategy.Parameters.sDrillingMode == 'AUTO') and
Drilling.ToolInfo.dResidualDepth + Drilling2.ToolInfo.dResidualDepth < Proc.FeatureInfo.dDrillLen then
local dExtraDrill = ( Proc.FeatureInfo.dDrillLen - BeamData.MILL_OVERLAP - ( Drilling.ToolInfo.dResidualDepth + Drilling2.ToolInfo.dResidualDepth)) / 2
Drilling.nToolIndex = Drilling.ToolInfo.nToolIndex
Drilling.Geometry = {{ Proc.FeatureInfo.idAddAuxGeom, -1}}
Drilling.vtToolDirection = Proc.FeatureInfo.vtDrillExtrusion
Drilling.sDepth = Proc.FeatureInfo.dDrillLen - Drilling.ToolInfo.dResidualDepth - dExtraDrill
table.insert( Machining, Drilling)
Drilling2.nToolIndex = Drilling2.ToolInfo.nToolIndex
Drilling2.ToolInfo = MachiningLib.FindDrill( Proc, ToolSearchParameters)
-- se trovato utensile si settano i parametri comuni
if Drilling2.ToolInfo.nToolIndex then
Drilling2.Geometry = {{ Proc.FeatureInfo.idAddAuxGeom, -1}}
Drilling2.nToolIndex = Drilling2.ToolInfo.nToolIndex
Drilling2.bInvert = true
Drilling2.vtToolDirection = -Proc.FeatureInfo.vtDrillExtrusion
Drilling2.sDepth = Proc.FeatureInfo.dDrillLen - Drilling2.ToolInfo.dResidualDepth - dExtraDrill
table.insert( Machining, Drilling2)
-- voto
Strategy.Result.sStatus = 'Completed'
Strategy.Result.dCompletionIndex = 5
Strategy.Result.sInfo = ''
Strategy.Result.dMRR = MachiningLib.GetToolMRR( Machining[1].ToolInfo)
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'FINE')
-- se utensile 1 esegue completamente
elseif Drilling.ToolInfo.nToolIndex and Drilling.ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL and
( Strategy.Parameters.sDrillingMode == 'PREFER_ONE' or ( not Drilling2.ToolInfo.nToolIndex and Strategy.Parameters.sDrillingMode == 'AUTO') or not Proc.FeatureInfo.bIsDrillOpen) then
Drilling.sDepth = 'TH'
Drilling.nToolIndex = Drilling.ToolInfo.nToolIndex
Drilling.Geometry = {{ Proc.FeatureInfo.idAddAuxGeom, -1}}
Drilling.vtToolDirection = Proc.FeatureInfo.vtDrillExtrusion
table.insert( Machining, Drilling)
-- voto
Strategy.Result.sStatus = 'Completed'
Strategy.Result.dCompletionIndex = 5
Strategy.Result.dMRR = MachiningLib.GetToolMRR( Machining[1].ToolInfo)
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( EgtIf( Proc.FeatureInfo.bIsDrillOpen, 'ROUGH', 'FINE'))
Strategy.Result.sInfo = ''
-- se utensile 2 esegue completamente
elseif Drilling2.ToolInfo.nToolIndex and Drilling2.ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL and
( Strategy.Parameters.sDrillingMode == 'PREFER_ONE' or ( not Drilling.ToolInfo.nToolIndex and Strategy.Parameters.sDrillingMode == 'AUTO')) then
Drilling2.sDepth = 'TH'
Drilling2.nToolIndex = Drilling2.ToolInfo.nToolIndex
Drilling2.Geometry = {{ Proc.FeatureInfo.idAddAuxGeom, -1}}
Drilling2.bInvert = true
Drilling2.vtToolDirection = -Proc.FeatureInfo.vtDrillExtrusion
table.insert( Machining, Drilling2)
-- voto
Strategy.Result.sStatus = 'Completed'
Strategy.Result.dCompletionIndex = 5
Strategy.Result.dMRR = MachiningLib.GetToolMRR( Machining[1].ToolInfo)
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( EgtIf( Proc.FeatureInfo.bIsDrillOpen, 'ROUGH', 'FINE'))
Strategy.Result.sInfo = ''
-- se possono lavorare entrambi
elseif Drilling.ToolInfo.nToolIndex and Drilling2.ToolInfo.nToolIndex then
Drilling.nToolIndex = Drilling.ToolInfo.nToolIndex
Drilling.Geometry = {{ Proc.FeatureInfo.idAddAuxGeom, -1}}
Drilling.vtToolDirection = Proc.FeatureInfo.vtDrillExtrusion
Drilling.sDepth = Proc.FeatureInfo.dDrillLen - Drilling.ToolInfo.dResidualDepth
table.insert( Machining, Drilling)
Drilling2.nToolIndex = Drilling2.ToolInfo.nToolIndex
Drilling2.Geometry = {{ Proc.FeatureInfo.idAddAuxGeom, -1}}
Drilling2.bInvert = true
Drilling2.vtToolDirection = -Proc.FeatureInfo.vtDrillExtrusion
Drilling2.sDepth = Proc.FeatureInfo.dDrillLen - Drilling2.ToolInfo.dResidualDepth
table.insert( Machining, Drilling2)
if Drilling.ToolInfo.dResidualDepth + Drilling2.ToolInfo.dResidualDepth < Proc.FeatureInfo.dDrillLen then
Strategy.Result.sStatus = 'Not-Completed'
local dMachinedLen = Machining[1].sDepth + Machining[2].sDepth
local dMachinedPrercentage = 100 * ( dMachinedLen / Proc.FeatureInfo.dDrillLen)
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( dMachinedPrercentage)
Strategy.Result.sInfo = 'Drill not complete, left ' .. tostring( 100 - ceil( dMachinedPrercentage)) .. '%'
else
Strategy.Result.sStatus = 'Completed'
Strategy.Result.dCompletionIndex = 5
Strategy.Result.sInfo = ''
end
-- voto
Strategy.Result.dMRR = MachiningLib.GetToolMRR( Machining[1].ToolInfo)
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'FINE')
-- se utensile 1 non completo
elseif Drilling.ToolInfo.nToolIndex and ( Strategy.Parameters.sDrillingMode ~= 'FORCE_TWO' or Proc.FeatureInfo.bIsDrillOpen) then
Drilling.sDepth = Proc.FeatureInfo.dDrillLen - Drilling.ToolInfo.dResidualDepth
Drilling.nToolIndex = Drilling.ToolInfo.nToolIndex
Drilling.Geometry = {{ Proc.FeatureInfo.idAddAuxGeom, -1}}
Drilling.vtToolDirection = Proc.FeatureInfo.vtDrillExtrusion
Drilling.sDepth = Proc.FeatureInfo.dDrillLen - Drilling.ToolInfo.dResidualDepth
table.insert( Machining, Drilling)
-- voto
Strategy.Result.sStatus = 'Not-Completed'
local dMachinedLen = Machining[1].sDepth
local dMachinedPrercentage = 100 * ( dMachinedLen / Proc.FeatureInfo.dDrillLen)
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( dMachinedPrercentage)
Strategy.Result.sInfo = 'Drill not complete, left ' .. tostring( 100 - ceil( dMachinedPrercentage)) .. '%'
Strategy.Result.dMRR = MachiningLib.GetToolMRR( Machining[1].ToolInfo)
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'FINE')
-- se utensile 2 non completo
elseif Drilling2.ToolInfo.nToolIndex and Strategy.Parameters.sDrillingMode ~= 'FORCE_TWO' then
Drilling2.sDepth = Proc.FeatureInfo.dDrillLen - Drilling2.ToolInfo.dResidualDepth
Drilling2.nToolIndex = Drilling2.ToolInfo.nToolIndex
Drilling2.Geometry = {{ Proc.FeatureInfo.idAddAuxGeom, -1}}
Drilling2.bInvert = true
Drilling2.vtToolDirection = -Proc.FeatureInfo.vtDrillExtrusion
Drilling2.sDepth = Proc.FeatureInfo.dDrillLen - Drilling2.ToolInfo.dResidualDepth
table.insert( Machining, Drilling2)
-- voto
Strategy.Result.sStatus = 'Not-Completed'
local dMachinedLen = Machining[1].sDepth
local dMachinedPrercentage = 100 * ( dMachinedLen / Proc.FeatureInfo.dDrillLen)
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( dMachinedPrercentage)
Strategy.Result.sInfo = 'Drill not complete, left ' .. tostring( 100 - ceil( dMachinedPrercentage)) .. '%'
Strategy.Result.dMRR = MachiningLib.GetToolMRR( Machining[1].ToolInfo)
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'FINE')
else
local sMessage
-- se non sono state trovate punte
if not Drilling.ToolInfo.nToolIndex and not Drilling2.ToolInfo.nToolIndex then
sMessage = 'Drillbit not found'
-- se son state trovate delle punte, ma non è stato possibile forare da entrambe le parti
elseif Strategy.Parameters.sDrillingMode == 'FORCE_TWO' then
sMessage = "Not possible to force machining from both sides. Please change drilling mode to AUTO"
end
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( sMessage)
Drilling2.dStep = TOOLS[Drilling2.nToolIndex].dStep
end
end
-- se possono lavorare entrambi e si deve fare lavorazione doppia e si riesce a completare
if Drilling.ToolInfo.nToolIndex and Drilling2.ToolInfo.nToolIndex and
( Strategy.Parameters.sDrillingMode == 'FORCE_TWO' or Strategy.Parameters.sDrillingMode == 'AUTO') and
Drilling.ToolInfo.dResidualDepth + Drilling2.ToolInfo.dResidualDepth < Proc.FeatureInfo.dDrillLen then
local dExtraDrill = ( Proc.FeatureInfo.dDrillLen - BeamData.MILL_OVERLAP - ( Drilling.ToolInfo.dResidualDepth + Drilling2.ToolInfo.dResidualDepth)) / 2
Drilling.sDepth = Proc.FeatureInfo.dDrillLen - Drilling.ToolInfo.dResidualDepth - dExtraDrill
table.insert( Machining, Drilling)
Drilling2.sDepth = Proc.FeatureInfo.dDrillLen - Drilling2.ToolInfo.dResidualDepth - dExtraDrill
table.insert( Machining, Drilling2)
-- voto
Strategy.Result.sStatus = 'Completed'
Strategy.Result.dCompletionIndex = 5
Strategy.Result.sInfo = ''
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'FINE')
-- se utensile 1 esegue completamente
elseif Drilling.ToolInfo.nToolIndex and Drilling.ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL and
( Strategy.Parameters.sDrillingMode == 'PREFER_ONE' or ( not Drilling2.ToolInfo.nToolIndex and Strategy.Parameters.sDrillingMode == 'AUTO') or not Proc.FeatureInfo.bIsDrillOpen) then
Drilling.sDepth = Proc.FeatureInfo.dDrillLen
table.insert( Machining, Drilling)
-- voto
Strategy.Result.sStatus = 'Completed'
Strategy.Result.dCompletionIndex = 5
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( EgtIf( Proc.FeatureInfo.bIsDrillOpen, 'ROUGH', 'FINE'))
Strategy.Result.sInfo = ''
-- annullo altra lavorazione
Drilling2.ToolInfo.nToolIndex = nil
-- se utensile 2 esegue completamente
elseif Drilling2.ToolInfo.nToolIndex and Drilling2.ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL and
( Strategy.Parameters.sDrillingMode == 'PREFER_ONE' or ( not Drilling.ToolInfo.nToolIndex and Strategy.Parameters.sDrillingMode == 'AUTO')) then
Drilling2.sDepth = Proc.FeatureInfo.dDrillLen
table.insert( Machining, Drilling2)
-- voto
Strategy.Result.sStatus = 'Completed'
Strategy.Result.dCompletionIndex = 5
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( EgtIf( Proc.FeatureInfo.bIsDrillOpen, 'ROUGH', 'FINE'))
Strategy.Result.sInfo = ''
-- annullo altra lavorazione
Drilling.ToolInfo.nToolIndex = nil
-- se possono lavorare entrambi
elseif Drilling.ToolInfo.nToolIndex and Drilling2.ToolInfo.nToolIndex then
Drilling.sDepth = Proc.FeatureInfo.dDrillLen - Drilling.ToolInfo.dResidualDepth
table.insert( Machining, Drilling)
Drilling2.sDepth = Proc.FeatureInfo.dDrillLen - Drilling2.ToolInfo.dResidualDepth
table.insert( Machining, Drilling2)
if Drilling.ToolInfo.dResidualDepth + Drilling2.ToolInfo.dResidualDepth < Proc.FeatureInfo.dDrillLen then
Strategy.Result.sStatus = 'Not-Completed'
local dMachinedLen = Machining[1].sDepth + Machining[2].sDepth
local dMachinedPrercentage = 100 * ( dMachinedLen / Proc.FeatureInfo.dDrillLen)
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( dMachinedPrercentage)
Strategy.Result.sInfo = 'Drill not complete, left ' .. tostring( 100 - ceil( dMachinedPrercentage)) .. '%'
else
Strategy.Result.sStatus = 'Completed'
Strategy.Result.dCompletionIndex = 5
Strategy.Result.sInfo = ''
end
-- voto
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'FINE')
-- se utensile 1 non completo
elseif Drilling.ToolInfo.nToolIndex and ( Strategy.Parameters.sDrillingMode ~= 'FORCE_TWO' or Proc.FeatureInfo.bIsDrillOpen) then
Drilling.sDepth = Proc.FeatureInfo.dDrillLen - Drilling.ToolInfo.dResidualDepth
table.insert( Machining, Drilling)
-- voto
Strategy.Result.sStatus = 'Not-Completed'
local dMachinedLen = Machining[1].sDepth
local dMachinedPrercentage = 100 * ( dMachinedLen / Proc.FeatureInfo.dDrillLen)
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( dMachinedPrercentage)
Strategy.Result.sInfo = 'Drill not complete, left ' .. tostring( 100 - ceil( dMachinedPrercentage)) .. '%'
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'FINE')
-- annullo altra lavorazione
Drilling2.ToolInfo.nToolIndex = nil
-- se utensile 2 non completo
elseif Drilling2.ToolInfo.nToolIndex and Strategy.Parameters.sDrillingMode ~= 'FORCE_TWO' then
Drilling2.sDepth = Proc.FeatureInfo.dDrillLen - Drilling2.ToolInfo.dResidualDepth
table.insert( Machining, Drilling2)
-- voto
Strategy.Result.sStatus = 'Not-Completed'
local dMachinedLen = Machining[1].sDepth
local dMachinedPrercentage = 100 * ( dMachinedLen / Proc.FeatureInfo.dDrillLen)
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( dMachinedPrercentage)
Strategy.Result.sInfo = 'Drill not complete, left ' .. tostring( 100 - ceil( dMachinedPrercentage)) .. '%'
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'FINE')
-- annullo altra lavorazione
Drilling.ToolInfo.nToolIndex = nil
else
local sMessage
-- se non sono state trovate punte
if not Drilling.ToolInfo.nToolIndex and not Drilling2.ToolInfo.nToolIndex then
sMessage = 'Drillbit not found'
-- se son state trovate delle punte, ma non è stato possibile forare da entrambe le parti
elseif Strategy.Parameters.sDrillingMode == 'FORCE_TWO' then
sMessage = "Not possible to force machining from both sides. Please change drilling mode to AUTO"
end
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( sMessage)
end
-- calcolo tempo di lavorazione
Strategy.Result.dTimeToMachine = 0
if Drilling.ToolInfo.nToolIndex then
Strategy.Result.dTimeToMachine = MachiningLib.GetTimeToMachineAllStepsWithLeadInOut( Drilling, Part)
end
if Drilling2.ToolInfo.nToolIndex then
Strategy.Result.dTimeToMachine = Strategy.Result.dTimeToMachine + MachiningLib.GetTimeToMachineAllStepsWithLeadInOut( Drilling2, Part)
end
return Machining, Strategy.Result
end
+1 -21
View File
@@ -7,7 +7,7 @@
"sNameNge": "EXTEND_AFTER_TAIL",
"sValue": "",
"sDescriptionShort": "Extend after tail",
"sDescriptionLong": "The automatism considers this lenght as machinable. This means you accept to damage the next piece in the bar",
"sDescriptionLong": "The automatism considers this length as machinable. This means you accept to damage the next piece in the bar",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
@@ -70,26 +70,6 @@
}
]
},
{
"sName": "dMinZAngleTopBlade",
"sNameNge": "MIN_Z_ANGLE_TOP_BLADE",
"sValue": "",
"sDescriptionShort": "Min Z angle top blade",
"sDescriptionLong": "",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "dMaxYAngleTopBlade",
"sNameNge": "MAX_Y_ANGLE_TOP_BLADE",
"sValue": "",
"sDescriptionShort": "Max Y angle top blade",
"sDescriptionLong": "",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "dMaxWasteLength",
"sSource": "GEN_dMaxWasteLength",
+13 -31
View File
@@ -5,7 +5,7 @@
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
-- strategie di base
@@ -59,9 +59,9 @@ function STR0012.Make( bAddMachining, Proc, Part, CustomParameters)
-- separazione della terza faccia
local idAddedTmFace
local nAddedFace
if Proc.AdjacencyMatrix[1][2] > 10 * GEO.EPS_ANG_SMALL and Proc.AdjacencyMatrix[2][3] < 10 * GEO.EPS_ANG_SMALL then
if Proc.AdjacencyMatrix[2][3] < 0 then
nAddedFace = 1 - 1
elseif Proc.AdjacencyMatrix[2][3] > 10 * GEO.EPS_ANG_SMALL and Proc.AdjacencyMatrix[3][1] < 10 * GEO.EPS_ANG_SMALL then
elseif Proc.AdjacencyMatrix[1][3] < 0 then
nAddedFace = 2 - 1
else
nAddedFace = 3 - 1
@@ -73,8 +73,14 @@ function STR0012.Make( bAddMachining, Proc, Part, CustomParameters)
if not( AreSameVectorApprox( Proc.Faces[nAddedFace + 1].vtN, X_AX()) and abs( Proc.Faces[nAddedFace + 1].ptCenter:getX() - Part.b3Part:getMax():getX()) < 10 * GEO.EPS_SMALL)
and not( AreSameVectorApprox( Proc.Faces[nAddedFace + 1].vtN, -X_AX()) and abs( Proc.Faces[nAddedFace + 1].ptCenter:getX() - Part.b3Part:getMin():getX()) < 10 * GEO.EPS_SMALL) then
-- faccia aggiuntiva da lavorare
idAddedTmFace = EgtCopySurfTmFacet( Proc.id, nAddedFace, nAddGrpId)
-- faccia aggiuntiva da lavorare: si estende fino al box della parte
local idAddGroup
if bAddMachining then
idAddGroup = BeamLib.GetAddGroup( Part.id)
else
idAddGroup = Part.idTempGroup
end
idAddedTmFace = EgtSurfTmPlaneInBBox( idAddGroup, Proc.Faces[nAddedFace + 1].ptCenter, Proc.Faces[nAddedFace + 1].vtN, Part.b3Part, GDB_ID.ROOT)
end
-- rimozione della terza faccia dalla Proc
@@ -85,17 +91,13 @@ function STR0012.Make( bAddMachining, Proc, Part, CustomParameters)
NewProc.NotClampableLength = FeatureLib.CalculateFeatureNotClampableLengths( NewProc, Part)
NewProc.bHindersLaserMeasure = FeatureLib.CalculateFeatureHindersLaserMeasure( NewProc, Part)
-- TODO rimuovere??? codolo da implementare o no??
-- considerazioni necessarie a determinare se lavorare con codolo oppure no
local bKeepWasteAttached = ( Strategy.Parameters.sCuttingStrategy == 'KEEP_WASTE_ATTACHED')
local bDropWaste = ( Strategy.Parameters.sCuttingStrategy == 'DROP_WASTE')
local dFeatureMaxNotClampableLengthHead, dFeatureMaxNotClampableLengthTail = FeatureLib.GetFeatureMaxNotClampableLengths( NewProc, Part)
local bFeatureHindersClamping = FeatureLib.IsMachiningLong( max( dFeatureMaxNotClampableLengthHead, dFeatureMaxNotClampableLengthTail), Part, { dMaxSegmentLength = BeamData.LONGCUT_ENDLEN})
local bIsFeatureLong = FeatureLib.IsMachiningLong( NewProc.b3Box:getDimX(), Part, { dMaxSegmentLength = BeamData.LONGCUT_ENDLEN})
local bFeatureHindersClamping = MachiningLib.IsFeatureHinderingClamping( Proc, Part)
-- lavorazione con codolo
if ( bIsFeatureLong)
or ( bFeatureHindersClamping and not bDropWaste)
if ( bFeatureHindersClamping and not bDropWaste)
or bKeepWasteAttached then
local BladeKeepWasteResult
@@ -109,19 +111,9 @@ function STR0012.Make( bAddMachining, Proc, Part, CustomParameters)
-- lavorazione a cubetti facce concave
else
local dMinZTopBlade
local dMaxNyTopBlade
local BladeToWasteResult
if Strategy.Parameters.dMinZAngleTopBlade then
dMinZTopBlade = sin( Strategy.Parameters.dMinZAngleTopBlade)
end
if Strategy.Parameters.dMaxYAngleTopBlade then
dMaxNyTopBlade = sin( Strategy.Parameters.dMaxYAngleTopBlade)
end
local OptionalParameters = { dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume,
dMaxWasteLength = Strategy.Parameters.dMaxWasteLength,
dMinNzTopBlade = dMinZTopBlade,
dMaxNyTopBlade = dMaxNyTopBlade,
bSaveAddedGeometries = bAddMachining,
dExtendAfterTail = dExtendAfterTail,
bReduceBladePath = Strategy.Parameters.bReduceBladePath
@@ -138,19 +130,9 @@ function STR0012.Make( bAddMachining, Proc, Part, CustomParameters)
-- TODO da completare
-- TODO va messa per prima????????
if idAddedTmFace then
local dMinZTopBlade
local dMaxNyTopBlade
local BladeToWasteResult
if Strategy.Parameters.dMinZAngleTopBlade then
dMinZTopBlade = sin( Strategy.Parameters.dMinZAngleTopBlade)
end
if Strategy.Parameters.dMaxYAngleTopBlade then
dMaxNyTopBlade = sin( Strategy.Parameters.dMaxYAngleTopBlade)
end
local OptionalParameters = { dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume,
dMaxWasteLength = Strategy.Parameters.dMaxWasteLength,
dMinNzTopBlade = dMinZTopBlade,
dMaxNyTopBlade = dMaxNyTopBlade,
bSaveAddedGeometries = bAddMachining,
dExtendAfterTail = dExtendAfterTail,
bReduceBladePath = Strategy.Parameters.bReduceBladePath
+6 -2
View File
@@ -5,7 +5,7 @@
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
-- strategie di base
@@ -74,7 +74,7 @@ local function GetDrillingWithMillStrategy( Proc, Part)
HalfMilling2.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
-- se entrambi gli utensili lavorano in modo completo fino alla metà del foro, li sostituisco a qeulli trovati in precedenza
if HalfMilling.ToolInfo.dResidualDepth < 0 and HalfMilling2.ToolInfo.dResidualDepth < 0 then
if HalfMilling.ToolInfo.dResidualDepth and HalfMilling2.ToolInfo.dResidualDepth and HalfMilling.ToolInfo.dResidualDepth < 0 and HalfMilling2.ToolInfo.dResidualDepth < 0 then
if Milling.ToolInfo.nToolIndex ~= HalfMilling.ToolInfo.nToolIndex then
Milling.ToolInfo.nToolIndex, Milling.ToolInfo.dResidualDepth = HalfMilling.ToolInfo.nToolIndex, HalfMilling.ToolInfo.dResidualDepth
end
@@ -198,6 +198,10 @@ function STR0013.Make( bAddMachining, Proc, Part, CustomParameters)
MachiningToAdd.nToolIndex = nIndexTool
MachiningToAdd.Geometry = {{ Proc.FeatureInfo.idAddAuxGeom, -1}}
if Proc.AffectedFaces.bLeft and not Proc.FeatureInfo.bIsDrillOpen then
MachiningToAdd.sStage = 'AfterTail'
end
bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, MachiningToAdd)
end
end
+2 -2
View File
@@ -9,7 +9,7 @@
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
local ID = require( 'Identity')
@@ -109,7 +109,7 @@ function STR0014.Make( bAddMachining, Proc, Part, CustomParameters)
for i = 1, #Proc.FeatureInfo.AdditionalGeometries do
local AuxId = Proc.id + Proc.FeatureInfo.AdditionalGeometries[i]
Strategy.AuxiliaryData.Clones[i+1] = {}
Strategy.AuxiliaryData.Clones[i+1].Geometry = EgtSetMachiningGeometry( {{ AuxId, -1}})
Strategy.AuxiliaryData.Clones[i+1].Geometry = {{ AuxId, -1}}
end
bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, Strategy.Machining, Strategy.AuxiliaryData)
+40 -23
View File
@@ -6,7 +6,7 @@
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
local FaceData = require( 'FaceData')
@@ -108,15 +108,17 @@ local function GetRoughStrategy( Proc, Part, bSaveAddedGeometries)
local nMidFacet = Proc.nFct // 2 -- faccia a metà circa
local vtN = EgtSurfTmFacetNormVersor( Proc.id, nMidFacet, GDB_ID.ROOT)
local nAddGroupId = BeamLib.GetAddGroup( Part.id)
local idAddGroup
if bSaveAddedGeometries then
idAddGroup = BeamLib.GetAddGroup( Part.id)
else
idAddGroup = Part.idTempGroup
end
-- aggiungo piano di sgrossatura e lo lavoro
local ptStart, vtNP = GetSawCutData( Proc, Proc.idAddAuxGeom, vtNF, vtN)
local AddId = EgtSurfTmPlaneInBBox( nAddGroupId, ptStart, vtNP, Part.b3Part, GDB_RT.GLOB)
local AddId = EgtSurfTmPlaneInBBox( idAddGroup, ptStart, vtNP, Part.b3Part, GDB_RT.GLOB)
-- se la faccia è stata creata
if AddId then
if not bSaveAddedGeometries then
EgtSetLevel( AddId, GDB_LV.TEMP)
end
-- creo piano di taglio sulla testa del tenone
local OptionalParameters = { dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume,
@@ -209,7 +211,7 @@ local function GetEdgeWithCornerStrategy( Proc, Part)
-- direzioni di lavorazione
local vtCutDir1
-- se è diretta verso alto o basso
if vtN:getZ() > vtN:getY() then
if abs( vtN:getZ()) > abs( vtN:getY()) then
if vtN:getZ() > 0 then
vtCutDir1 = Z_AX()
else
@@ -231,81 +233,99 @@ local function GetEdgeWithCornerStrategy( Proc, Part)
vtCutDir2 = -X_AX()
end
local nMachiningsToAdd
-- AUTO = preferisce lama. Se non è possibile prende fresa
-- BLADE_FORCED = solo lama, altriemnti non applica nulla (potrebbe essere necessario un ribaltamento)
-- MILL_FORCED = solo fresa, altriemnti non applica nulla (potrebbe essere necessario un ribaltamento)
if Strategy.Parameters.sConcaveFaceStrategy == 'AUTO' or Strategy.Parameters.sConcaveFaceStrategy == 'BLADE_FORCED' then
nMachiningsToAdd = 0
-- TODO c'è una funzione che ritorni l'edge di connessione tra una faccia e un'altra?
-- lavorazione faccia 1 spigolo finale
if bLastTrim then
nMachiningsToAdd = nMachiningsToAdd + 1
local EdgeToMachine = GetEdgeToMachine( Proc, nLastFacet+1, vtCutDir1)
local Cutting = FaceByBlade.Make( Proc, Part, Proc.Faces[nLastFacet+1], EdgeToMachine)
if Proc.AffectedFaces.bLeft and Strategy.bCanMoveAfterSplit then
Cutting.sStage = 'AfterTail'
end
if Cutting then
if Cutting.bIsApplicable then
table.insert( Machining, Cutting)
end
end
-- lavorazione faccia 1 spigolo iniziale
if bFirstTrim then
nMachiningsToAdd = nMachiningsToAdd + 1
local EdgeToMachine = GetEdgeToMachine( Proc, nFirstFacet+2, vtCutDir1)
local Cutting = FaceByBlade.Make( Proc, Part, Proc.Faces[nFirstFacet+2], EdgeToMachine)
if Proc.AffectedFaces.bLeft and Strategy.bCanMoveAfterSplit then
Cutting.sStage = 'AfterTail'
end
if Cutting then
if Cutting.bIsApplicable then
table.insert( Machining, Cutting)
end
end
-- lavorazione faccia 2 spigolo finale
if bLastTrim then
nMachiningsToAdd = nMachiningsToAdd + 1
EdgeToMachine = GetEdgeToMachine( Proc, nLastFacet, vtCutDir2)
Cutting = FaceByBlade.Make( Proc, Part, Proc.Faces[nLastFacet], EdgeToMachine)
if Cutting then
if Cutting.bIsApplicable then
table.insert( Machining, Cutting)
end
end
-- lavorazione faccia 2 spigolo iniziale
if bFirstTrim then
nMachiningsToAdd = nMachiningsToAdd + 1
local EdgeToMachine = GetEdgeToMachine( Proc, nFirstFacet+1, vtCutDir2)
local Cutting = FaceByBlade.Make( Proc, Part, Proc.Faces[nFirstFacet+1], EdgeToMachine)
if Cutting then
if Cutting.bIsApplicable then
table.insert( Machining, Cutting)
end
end
end
-- se non ci sono lavorazioni provo a pulire spigoli con fresa, a patto che non sia stato forzato con lama
if #Machining == 0 and Strategy.Parameters.sConcaveFaceStrategy ~= 'BLADE_FORCED' then
if ( not nMachiningsToAdd or ( #Machining < nMachiningsToAdd)) and Strategy.Parameters.sConcaveFaceStrategy ~= 'BLADE_FORCED' then
Machining = {}
nMachiningsToAdd = 0
-- TODO c'è una funzione che ritorni l'edge di connessione tra una faccia e un'altra?
-- lavorazione faccia 1 spigolo iniziale
if bFirstTrim then
nMachiningsToAdd = nMachiningsToAdd + 1
local EdgeToMachine = GetEdgeToMachine( Proc, nFirstFacet+2, vtCutDir1)
local Milling = FaceByMill.Make( Proc, Part, Proc.Faces[nFirstFacet+2], EdgeToMachine)
if Proc.AffectedFaces.bLeft and Strategy.bCanMoveAfterSplit then
Milling.sStage = 'AfterTail'
end
if Milling then
if Milling.bIsApplicable then
table.insert( Machining, Milling)
end
end
-- lavorazione faccia 2 spigolo finale
if bLastTrim then
nMachiningsToAdd = nMachiningsToAdd + 1
EdgeToMachine = GetEdgeToMachine( Proc, nLastFacet, vtCutDir2)
local Milling = FaceByMill.Make( Proc, Part, Proc.Faces[nLastFacet], EdgeToMachine)
if Proc.AffectedFaces.bLeft and Strategy.bCanMoveAfterSplit then
Milling.sStage = 'AfterTail'
end
if Milling then
if Milling.bIsApplicable then
table.insert( Machining, Milling)
end
end
end
if nMachiningsToAdd and ( #Machining < nMachiningsToAdd) then
Result = { dCompletionPercentage = ( #Machining / nMachiningsToAdd)}
end
return Machining, Result
@@ -439,7 +459,7 @@ local function GetArcStrategy( Proc, Part)
local bExecStrip = false
-- se la lavorazione si trova nella parte inferiore o in battuta dietro, il codolo va sempre lasciato
if bIsFeatureDown or bIsFeatureBack or bForceStrip then
if ID.IsRoundArch( Proc) and ( bIsFeatureDown or bIsFeatureBack or bForceStrip) then
if bIsFeatureDown or bIsFeatureBack then
dDimStrip = dDimStrip or max( BeamData.DIM_STRIP or 5, 5)
else
@@ -637,7 +657,7 @@ local function GetFeatureResult( Proc)
-- se richieste anche le altre lavorazioni
if not Strategy.Parameters.bOnlyChamfer then
-- per tutti tranne che per feature RoundArc
if not ID.IsRoundArch( Proc) then
if not ID.IsRoundArch( Proc) and not ID.IsFreeContour( Proc) then
-- se sgrossatura da eseguire
if Strategy.Parameters.bExecRough then
if not Strategy.RoughCut.Machinings or #Strategy.RoughCut.Machinings == 0 then
@@ -698,7 +718,7 @@ function STR0015.Make( bAddMachining, Proc, Part, CustomParameters)
local bAreAllMachiningsAdded = true
-- calcolo se la lavorazione del tenone può essere spostata dopo taglio di coda
-- verifico se la lavorazione può essere spostata dopo taglio di coda
local dLengthOnX = Proc.b3Box:getDimX()
Strategy.bCanMoveAfterSplit = MachiningLib.CanMoveAfterSplitcut( dLengthOnX, Part)
@@ -718,7 +738,7 @@ function STR0015.Make( bAddMachining, Proc, Part, CustomParameters)
-- se non bisogna fare solo gli smussi, si calcolano le altre lavorazioni
if not Strategy.Parameters.bOnlyChamfer then
-- per tutti tranne che per feature RoundArc
if not ID.IsRoundArch( Proc) then
if not ID.IsRoundArch( Proc) and not ID.IsFreeContour( Proc) then
-- lavorazione taglio per sgrossare
if Strategy.Parameters.bExecRough then
Strategy.RoughCut = {}
@@ -760,7 +780,7 @@ function STR0015.Make( bAddMachining, Proc, Part, CustomParameters)
end
-- per tutti tranne che per feature RoundArc
if not ID.IsRoundArch( Proc) then
if not ID.IsRoundArch( Proc) and not ID.IsFreeContour( Proc) then
-- lavorazione di sgrezzatura di lama
if Strategy.Parameters.bExecRough and Strategy.RoughCut.Machinings then
-- se cutting da fare come svuotatura
@@ -797,10 +817,7 @@ function STR0015.Make( bAddMachining, Proc, Part, CustomParameters)
Strategy.Profile.Machinings[i].Geometry = {{ Proc.idAddAuxGeom, -1}}
Strategy.Profile.Machinings[i].nToolIndex = Strategy.Profile.Machinings[i].ToolInfo.nToolIndex
Strategy.Profile.Machinings[i].nType = MCH_MY.MILLING
Strategy.Profile.Machinings[i].Steps = {}
Strategy.Profile.Machinings[i].Steps.dStep = TOOLS[Strategy.Profile.Machinings[i].ToolInfo.nToolIndex].dStep
Strategy.Profile.Machinings[i].Steps = MachiningLib.GetMachiningSteps( tonumber( Strategy.Profile.Machinings[i].sDepth), TOOLS[Strategy.Profile.Machinings[i].nToolIndex].dStep)
Strategy.Profile.Machinings[i].Steps = MachiningLib.GetMachiningSteps( false, tonumber( Strategy.Profile.Machinings[i].sDepth), TOOLS[Strategy.Profile.Machinings[i].nToolIndex].dStep)
Strategy.Profile.Machinings[i].Steps.nStepType = MCH_MILL_ST.ONEWAY
-- LeadIn / LeadOut
+42 -17
View File
@@ -5,7 +5,7 @@
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
local FeatureLib = require( 'FeatureLib')
local MachiningLib = require( 'MachiningLib')
local SPLITCUT = require( 'SPLITCUT')
@@ -34,11 +34,18 @@ function TAILCUT.Make( bAddMachining, Proc, Part, CustomParameters)
Strategy.Result.sInfo = ''
local OptionalParameters = { bForceChainSaw = Strategy.Parameters.bForceChainSaw, bReduceBladePath = Strategy.Parameters.bReduceBladePath,
dMaxWasteLength = Strategy.Parameters.dMaxWasteLength, dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume }
OptionalParameters.sRestLengthSideForPreSimulation = 'Tail'
OptionalParameters.bCannotSplitRestLength = true
local bAreAllMachiningsAdded = true
local bExecutePrecutOnly = false
-- si setta che è taglio di coda
Strategy.bIsTailCut = true
-- quando si aggiunge la lavorazione, si cambia il nome della feature
if bAddMachining then
-- si forza il nome della feature
EgtSetName( Proc.id, 'EndCut')
end
-- separazione solo se esiste grezzo successivo con pezzi o scaricabile
Strategy.bSplit = not( Part.bIsLastPart) or Part.dRestLength >= BeamData.dMinRaw
@@ -49,6 +56,11 @@ function TAILCUT.Make( bAddMachining, Proc, Part, CustomParameters)
OptionalParameters.bDisableDicing = true
Strategy.SplitStrategy, Strategy.Result = SPLITCUT.GetMachining( Proc, Part, OptionalParameters)
if Strategy.Result.sStatus ~= 'Completed' then
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( 'Split not possible')
return false, Strategy.Result
end
-- se devo rimuovere tutto il restante
else
-- se abilitato, faccio tagli di PRECUT a zero (come SPLIT)
@@ -58,10 +70,18 @@ function TAILCUT.Make( bAddMachining, Proc, Part, CustomParameters)
OptionalParameters.dOffset = 0
else
Strategy.bIsPreCut = true
-- TODO questo dOffset è errato, va creata una nuova faccia oppure usare dLongitudinalOffset e farlo transitare per tutti, anche Engagement
-- TODO a dRestLength va anche aggiunto lo spessore lama se c'è a fine grezzo?
OptionalParameters.dOffset = Part.dRestLength
end
OptionalParameters.bDisableDicing = true
Strategy.SplitStrategy, Strategy.Result = SPLITCUT.GetMachining( Proc, Part, OptionalParameters)
if Strategy.Result.sStatus ~= 'Completed' then
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( 'Precut Tail not possible')
return false, Strategy.Result
end
-- se non faccio tagli PRECUT, imposto tabella Result direttamente. Non serve verificare che riesca a rimuovere il materiale extra
else
Strategy.Result.sStatus = 'Completed'
@@ -74,9 +94,6 @@ function TAILCUT.Make( bAddMachining, Proc, Part, CustomParameters)
-- se devo applicare le lavorazioni
if bAddMachining then
-- si forza il nome della feature
EgtSetName( Proc.id, 'EndCut')
-- inserimento smussi su spigoli del taglio
if Strategy.Parameters.bMakeChamfer then
MakeChamfer()
@@ -122,21 +139,26 @@ function TAILCUT.Make( bAddMachining, Proc, Part, CustomParameters)
end
if not bExecutePrecutOnly then
OptionalParameters = {}
-- eventuale grezzo custom per dicing (grezzo attuale + grezzo di coda)
local nNextRawId = EgtGetNextRawPart( Part.idRaw)
if nNextRawId then
local b3BoxDicing = EgtGetRawPartBBox( nNextRawId)
b3BoxDicing:Add( Part.b3Raw)
OptionalParameters.b3BoxDicing = b3BoxDicing
-- si recuperano gli estremi del box del materiale di coda da rimuovere
local b3PartWithTail = BeamLib.GetPartBoxWithHeadTail( Part, 'Tail')
local ptStartRestLength = Point3d( Part.b3Part:getMin():getX() + 1, Part.b3Part:getMax():getY(), Part.b3Part:getMax():getZ())
local ptEndRestLength = Point3d( b3PartWithTail:getMin():getX(), Part.b3Part:getMin():getY(), Part.b3Part:getMin():getZ())
local OptionalParametersBladeToWaste = {}
OptionalParametersBladeToWaste.b3BoxDicing = BBox3d( ptStartRestLength, ptEndRestLength)
OptionalParametersBladeToWaste.dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume
OptionalParametersBladeToWaste.dMaxWasteLength = Strategy.Parameters.dMaxWasteLength
OptionalParametersBladeToWaste.bReduceBladePath = Strategy.Parameters.bReduceBladePath
OptionalParametersBladeToWaste.sRestLengthSideForPreSimulation = 'Tail'
OptionalParametersBladeToWaste.bCannotSplitRestLength = true
Strategy.Machining, _ = BladeToWaste.Make( Proc, Part, OptionalParametersBladeToWaste)
-- se taglio non riuscito, si riprova con il riduci percorso forzato (collisione possibile in separazione pezzi alti)
if ( not Strategy.Machining) or ( #Strategy.Machining == 0) then
OptionalParametersBladeToWaste.bReduceBladePath = true
Strategy.Machining, _ = BladeToWaste.Make( Proc, Part, OptionalParametersBladeToWaste)
end
OptionalParameters.dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume
OptionalParameters.dMaxWasteLength = Strategy.Parameters.dMaxWasteLength
OptionalParameters.bReduceBladePath = Strategy.Parameters.bReduceBladePath
Strategy.Machining, _ = BladeToWaste.Make( Proc, Part, OptionalParameters)
if Strategy.Machining and #Strategy.Machining > 0 then
for i = 1, #Strategy.Machining do
local TempList = {}
@@ -149,6 +171,9 @@ function TAILCUT.Make( bAddMachining, Proc, Part, CustomParameters)
end
table.insert( MachiningsToAdd, TempList)
end
else
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( 'Tail machining not possible')
return false, Strategy.Result
end
end
end
+2 -2
View File
@@ -7,8 +7,8 @@ STR0004 = Topologia tipo LapJoint. Motosega
STR0005 = 1, 2 o 3 facce. Lama con taglio singolo o cubetti. Se richiesto o necessario codolo.
STR0006 = Tenone. Lama + fresa
STR0007 = Mortasa a coda di rondine e mortasa frontale a coda di rondine
STR0008 = Svuotatura tasca
STR0009 = !!DEPRECATA!! Sostituita da STR0015. RIUTILIZZABILE!
STR0008 = Svuotatura mortasa (raggiata)
STR0009 = ScarfJoint
STR0010 = Fresatura perpendicolare (tipo cut, longcut)
STR0011 = Foratura
STR0012 = RidgeLap
+55
View File
@@ -0,0 +1,55 @@
-- Strategia: FACEBYBLADE
-- Descrizione
-- Strategia di base per la lavorazione delle facce con lama
-- carico librerie
local FaceByBlade = require( 'FACEBYBLADE')
-- Tabella per definizione modulo
local ANTISPLINTONFACE = {}
-------------------------------------------------------------------------------------------------------------
function ANTISPLINTONFACE.Make( Proc, Part, Face, OptionalParameters)
local Machinings = {}
-- parametri opzionali
if not OptionalParameters then
OptionalParameters = {}
end
local bIsSplitFeature = OptionalParameters.bIsSplitFeature or false
local dExtendAfterTail = OptionalParameters.dExtendAfterTail or 10000
local nInternalSortingPriority = OptionalParameters.nInternalSortingPriority or 1
local dResultWeight = OptionalParameters.dResultWeight or 0.15
local bMachineAllClosedEdges = OptionalParameters.bMachineAllClosedEdges or false
local ClosingFacesAgainstGrain = {}
for i = 1, #Face.Edges do
local CurrentFace = Proc.Faces[Face.Edges[i].idAdjacentFace + 1]
if ( not Face.Edges[i].bIsOpen) and ( Face.Edges[i].bIsStartOpen or Face.Edges[i].bIsEndOpen or bMachineAllClosedEdges) then
table.insert( ClosingFacesAgainstGrain, CurrentFace)
end
end
for i = 1, #ClosingFacesAgainstGrain do
local EdgeToMachine = {}
for j = 1, #ClosingFacesAgainstGrain[i].Edges do
if ClosingFacesAgainstGrain[i].Edges[j].idAdjacentFace == Face.id then
EdgeToMachine = ClosingFacesAgainstGrain[i].Edges[j]
break
end
end
local Cutting = {}
local OptionalParametersFaceByBlade = { bIsSplitFeature = bIsSplitFeature, dExtendAfterTail = dExtendAfterTail}
Cutting = FaceByBlade.Make( Proc, Part, ClosingFacesAgainstGrain[i], EdgeToMachine, OptionalParametersFaceByBlade)
Cutting.nInternalSortingPriority = nInternalSortingPriority
Cutting.dResultWeight = dResultWeight
table.insert( Machinings, Cutting)
end
return Machinings
end
-------------------------------------------------------------------------------------------------------------
return ANTISPLINTONFACE
+262 -92
View File
@@ -11,47 +11,66 @@ require( 'EgtBase')
local FeatureLib = require( 'FeatureLib')
local FaceData = require( 'FaceData')
local MachiningLib = require( 'MachiningLib')
local BeamLib = require('BeamLib')
-- strategie di base
local FaceByBlade = require('FACEBYBLADE')
local FaceByMill = require('FACEBYMILL')
local FaceByMill = require( 'FACEBYMILL')
local AntiSplintOnFace = require( 'ANTISPLINTONFACE')
-- tabelle per definizione modulo
-------------------------------------------------------------------------------------------------------------
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
local function CompareEdgesLongestTop( EdgeA, EdgeB)
-- si preferiscono i lati più lunghi
if EdgeA.dLength > EdgeB.dLength + 10 * GEO.EPS_SMALL then
return true
elseif abs( EdgeA.vtN:getX()) > abs( EdgeB.vtN:getX()) + 10 * GEO.EPS_SMALL then
elseif EdgeA.dLength < EdgeB.dLength - 10 * GEO.EPS_SMALL then
return false
-- se stessa X si preferiscono i lati più lunghi (nel caso di 5 lati è quello non spezzato)
-- se stessa lunghezza si preferiscono i lati più in basso
else
if EdgeA.dLength > EdgeB.dLength + 10 * GEO.EPS_SMALL then
if EdgeA.vtN:getZ() > EdgeB.vtN:getZ() + 10 * GEO.EPS_SMALL then
return true
elseif EdgeA.dLength < EdgeB.dLength - 10 * GEO.EPS_SMALL then
elseif EdgeA.vtN:getZ() < EdgeB.vtN:getZ() - 10 * GEO.EPS_SMALL then
return false
-- se stessa lunghezza si preferiscono i lati più in basso
-- TODO qui dipenderà dalla lama scelta
-- se stessa Z si preferiscono i lati verso il fronte della trave
else
if EdgeA.vtN:getZ() > EdgeB.vtN:getZ() + 10 * GEO.EPS_SMALL then
if EdgeA.vtN:getY() > EdgeB.vtN:getY() + 10 * GEO.EPS_SMALL then
return true
elseif EdgeA.vtN:getZ() < EdgeB.vtN:getZ() - 10 * GEO.EPS_SMALL then
elseif EdgeA.vtN:getY() < EdgeB.vtN:getY() - 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
return false
end
end
end
end
local function GetLongEdgeToMachine( Face, bHeadType)
local Edge = {}
local EdgesSorted = {}
for i = 1, #Face.Edges do
table.insert( EdgesSorted, Face.Edges[i])
end
table.sort( EdgesSorted, CompareEdgesLongestTop)
-- se il lato migliore è accessibile si sceglie questo, altrimenti il lato opposto; se entrambi non accessibili (faccia chiusa da due lati) la lavorazione non è applicabile
Edge = EdgesSorted[1]
local EdgeOpposite = BeamLib.FindEdgeBestOrientedAsDirection( Face.Edges, -Edge.vtN)
if not EdgeOpposite.bIsOpen then
if Edge.bIsOpen then
Edge = EdgeOpposite
-- entrambi i lati non accessibili: codolo non applicabile
else
return nil
end
end
return Edge
end
local function SortMachiningsBySegment( MachiningA, MachiningB)
if MachiningA.nFeatureSegment > MachiningB.nFeatureSegment then
return false
@@ -104,7 +123,7 @@ local function GetStrategyCompletionPercentage( Machinings)
if nWeightsCount ~= 0 and nWeightsCount ~= i then
error( 'GetWeightedCompletionPercentage : inconsistent weights')
end
local dWeightedCompletionPercentage = Machining.dCompletionPercentage / 100 * dWeight
local dWeightedCompletionPercentage = ( Machining.dCompletionPercentage or 0) / 100 * dWeight
if Machining.bIsApplicable then
dCompletionPercentageNumerator = dCompletionPercentageNumerator + dWeightedCompletionPercentage
end
@@ -117,31 +136,95 @@ local function GetStrategyCompletionPercentage( Machinings)
end
local function MakeBottomFace( Proc, Part, BottomFace, EdgeToMachine, Parameters)
local Cuttings = {}
local Cutting1 = {}
local Cutting2 = {}
-- parametri dal chiamante
local bIsSplitFeature = Parameters.bIsSplitFeature
local dExtendAfterTail = Parameters.dExtendAfterTail
local nToolIndex = Parameters.nToolIndex
local dStripWidth = Parameters.dStripWidth
local OtherBottomFace = Parameters.OtherBottomFace
local dDepthToMachine = EdgeToMachine.dElevation / 2 - dStripWidth / 2
local OptionalParametersFaceByBlade1 = { dDepthToMachine = dDepthToMachine, bIsSplitFeature = bIsSplitFeature, dExtendAfterTail = dExtendAfterTail, nToolIndex = nToolIndex}
local EdgeToMachineOpposite = BeamLib.FindEdgeBestOrientedAsDirection( BottomFace.Edges, -EdgeToMachine.vtN)
-- primo lato
if EdgeToMachineOpposite.bIsOpen then
Cutting1 = FaceByBlade.Make( Proc, Part, BottomFace, EdgeToMachine, OptionalParametersFaceByBlade1)
end
Cutting1.nInternalSortingPriority = 2
Cutting1.dResultWeight = 0.3
-- secondo lato
local OptionalParametersFaceByBlade2 = BeamLib.TableCopyDeep( OptionalParametersFaceByBlade1)
OptionalParametersFaceByBlade2.OppositeToolDirectionMode = 'Enabled'
if EdgeToMachine.bIsOpen then
Cutting2 = FaceByBlade.Make( Proc, Part, BottomFace, EdgeToMachine, OptionalParametersFaceByBlade2)
end
Cutting2.nInternalSortingPriority = 2
Cutting2.dResultWeight = 0.3
-- se uno dei due lati non è riuscito, si estende il più possibile il lato rimasto
if not Cutting1.bIsApplicable and Cutting2.bIsApplicable then
-- se si lavora il lato in comune con l'altra BottomFace significa ci si deve fermare piú indietro
if OtherBottomFace and ( EdgeToMachine.idAdjacentFace == OtherBottomFace.id) then
dStripWidth = TOOLS[Cutting2.nToolIndex].dThickness + 2 * dStripWidth
end
dDepthToMachine = min( TOOLS[Cutting2.nToolIndex].dMaxMaterial, EdgeToMachine.dElevation - dStripWidth)
OptionalParametersFaceByBlade2.dDepthToMachine = dDepthToMachine
Cutting2 = FaceByBlade.Make( Proc, Part, BottomFace, EdgeToMachine, OptionalParametersFaceByBlade2)
Cutting2.nInternalSortingPriority = 2
Cutting2.dResultWeight = 0.3
table.insert( Cuttings, Cutting2)
elseif not Cutting2.bIsApplicable and Cutting1.bIsApplicable then
-- se si lavora il lato in comune con l'altra BottomFace significa ci si deve fermare piú indietro
if OtherBottomFace and ( EdgeToMachine.idAdjacentFace == OtherBottomFace.id) then
dStripWidth = TOOLS[Cutting1.nToolIndex].dThickness + 2 * dStripWidth
end
dDepthToMachine = min( TOOLS[Cutting1.nToolIndex].dMaxMaterial, EdgeToMachine.dElevation - dStripWidth)
OptionalParametersFaceByBlade1.dDepthToMachine = dDepthToMachine
Cutting1 = FaceByBlade.Make( Proc, Part, BottomFace, EdgeToMachine, OptionalParametersFaceByBlade1)
Cutting1.nInternalSortingPriority = 2
Cutting1.dResultWeight = 0.3
table.insert( Cuttings, Cutting1)
else
table.insert( Cuttings, Cutting1)
table.insert( Cuttings, Cutting2)
end
return Cuttings
end
function BLADEKEEPWASTE.Make( Proc, Part, OptionalParameters)
-- TODO verificare funzionamento con lama da sotto
-- attenzione perchè se l'inclinazione della faccia la fa finire oltre lo spigolo questo riduce il massimo (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)
-- TODO scelta utensile è corretto lasciarla a FaceByBlade?
-- TODO aggiungere accorciamento se angolo < 90
local Result = {}
local Machinings = {}
local CalculatedMachinings = {}
local Cutting1 = {}
local Cutting2 = {}
-- controlli preventivi
if Proc.nFct > 3 then
error( 'BladeKeepWaste : max 3 faces supported')
if Proc.nFct > 3 and ( not Proc.Topology.sFamily == 'DoubleBevel') then
Result = FeatureLib.GetStrategyResultNotApplicable( 'BladeKeepWaste : max 3 faces supported')
return Machinings, Result
elseif Proc.nFct == 2 then
-- per angolo tra le facce >= 90deg (feature convessa) non applicabile
if Proc.AdjacencyMatrix[1][2] > 10 * GEO.EPS_SMALL or Proc.AdjacencyMatrix[1][2] < -91 then
Result = FeatureLib.GetStrategyResultNotApplicable( 'BladeKeepWaste : angle between faces must be concave and >= 90deg')
return Machinings, Result
end
-- Rabbet lungo X non gestito
if Proc.Topology.sName == 'Rabbet-2-Through' and Proc.AffectedFaces.bLeft and Proc.AffectedFaces.bRight then
Result = FeatureLib.GetStrategyResultNotApplicable( 'BladeKeepWaste : Rabbet along X not managed')
return Machinings, Result
end
elseif Proc.nFct == 3 then
-- caso speciale RidgeLap - per angolo tra le facce >= 90deg (feature convessa) non applicabile
if Proc.AdjacencyMatrix[1][2] > 10 * GEO.EPS_SMALL or Proc.AdjacencyMatrix[1][2] < -91 then
@@ -164,39 +247,34 @@ function BLADEKEEPWASTE.Make( Proc, Part, OptionalParameters)
end
local nToolIndex = OptionalParameters.nToolIndex
local dExtendAfterTail = OptionalParameters.dExtendAfterTail or 10000
local bFinishWithMill
if OptionalParameters.bFinishWithMill == nil then
bFinishWithMill = true
else
bFinishWithMill = OptionalParameters.bFinishWithMill
end
local bFinishWithMill = ( OptionalParameters.bFinishWithMill ~= false)
local dMillingOffsetFromSide = OptionalParameters.dMillingOffsetFromSide or 1
local dStripWidth = OptionalParameters.dStripWidth or 5
local bForced = OptionalParameters.bForced or false
-- volume della feature
local dFeatureVolume = FeatureLib.GetFeatureVolume( Proc, Part)
local dFeatureVolume = Proc.dVolume
-- si trovano le facce da lavorare
local BottomFace = {}
local LongFaces = {}
-- si trovano le facce da lavorare (solo 4 lati esatti)
local BottomFace1
local BottomFace2
if Proc.nFct == 1 then
BottomFace = Proc.Faces[1]
BottomFace1 = Proc.Faces[1]
else
if not Proc.MainFaces then
Proc.MainFaces = FaceData.GetMainFaces( Proc, Part)
end
BottomFace = Proc.MainFaces.BottomFaces[1]
LongFaces = Proc.MainFaces.LongFaces
BottomFace1 = Proc.MainFaces.BottomFaces[1]
BottomFace2 = Proc.MainFaces.BottomFaces[2]
end
-- si trova il lato della faccia di fondo da lavorare
local BottomEdgeToMachine = {}
local BottomEdgesSorted = {}
for i = 1, #BottomFace.Edges do
table.insert( BottomEdgesSorted, BottomFace.Edges[i])
if #BottomFace1.Edges ~= 4 then
Result = FeatureLib.GetStrategyResultNotApplicable()
return Machinings, Result
end
local bConvexAngle
if BottomFace2 then
bConvexAngle = ( Proc.AdjacencyMatrix[BottomFace1.id + 1][BottomFace2.id + 1]) > 0
end
table.sort( BottomEdgesSorted, CompareEdges)
BottomEdgeToMachine = BottomEdgesSorted[1]
-- eventuali punti di spezzatura
local FeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
@@ -205,44 +283,129 @@ function BLADEKEEPWASTE.Make( Proc, Part, OptionalParameters)
bIsSplitFeature = true
end
-- calcolo lavorazioni
-- taglio eventuali facce di chiusura
for i = 1, #LongFaces do
local Cutting = {}
local OptionalParametersFaceByBlade = { bIsSplitFeature = bIsSplitFeature, dExtendAfterTail = 9999, nToolIndex = nToolIndex}
Cutting = FaceByBlade.Make( Proc, Part, LongFaces[i], LongFaces[i].MainEdges.BottomEdge, OptionalParametersFaceByBlade)
Cutting.nInternalSortingPriority = 1
Cutting.dResultWeight = 0.15
table.insert( CalculatedMachinings, Cutting)
-- calcolo lavorazioni faccia principale
-- ricerca lato da lavorare
local BottomEdgeToMachine1 = GetLongEdgeToMachine( BottomFace1, { bTop = true})
if not BottomEdgeToMachine1 then
Result = FeatureLib.GetStrategyResultNotApplicable()
return Machinings, Result
end
-- calcolo lavorazione
local Parameters1 = {
bIsSplitFeature = bIsSplitFeature,
dExtendAfterTail = dExtendAfterTail,
nToolIndex = nToolIndex,
dStripWidth = dStripWidth,
OtherBottomFace = BottomFace2
}
local Cuttings1 = MakeBottomFace( Proc, Part, BottomFace1, BottomEdgeToMachine1, Parameters1)
-- aggiunta lavorazioni alla lista principale
for i = 1, #Cuttings1 do
table.insert( CalculatedMachinings, Cuttings1[i])
end
-- taglio con codolo faccia di fondo
local dDepthToMachine = BottomEdgeToMachine.dElevation - OptionalParameters.dStripWidth
local OptionalParametersFaceByBlade = { dDepthToMachine = dDepthToMachine, bIsSplitFeature = bIsSplitFeature, dExtendAfterTail = dExtendAfterTail, nToolIndex = nToolIndex}
-- primo lato
Cutting1 = FaceByBlade.Make( Proc, Part, BottomFace, BottomEdgeToMachine, OptionalParametersFaceByBlade)
Cutting1.nInternalSortingPriority = 3
Cutting1.dResultWeight = 0.3
table.insert( CalculatedMachinings, Cutting1)
-- secondo lato
OptionalParametersFaceByBlade.OppositeToolDirectionMode = 'Enabled'
Cutting2 = FaceByBlade.Make( Proc, Part, BottomFace, BottomEdgeToMachine, OptionalParametersFaceByBlade)
Cutting2.nInternalSortingPriority = 3
Cutting2.dResultWeight = 0.3
--table.insert( CalculatedMachinings, Cutting2)
-- fresatura eventuali facce di chiusura
-- calcolo lavorazioni faccia secondaria, solo se lato convesso; se concavo, sarà lavorato come antisplint
local Cuttings2
local BottomEdgeToMachine2
if BottomFace2 then
if bConvexAngle then
-- ricerca lato da lavorare
BottomEdgeToMachine2 = GetLongEdgeToMachine( BottomFace2, { bTop = true})
if BottomEdgeToMachine2 then
-- calcolo lavorazione
local Parameters2 = BeamLib.TableCopyDeep( Parameters1)
Parameters2.OtherBottomFace = BottomFace1
Cuttings2 = MakeBottomFace( Proc, Part, BottomFace2, BottomEdgeToMachine2, Parameters2)
for i = 1, #Cuttings2 do
table.insert( CalculatedMachinings, Cuttings2[i])
end
end
end
end
-- antischeggia sulle facce di chiusura delle facce lavorate
local OptionalParametersAntiSplint = {
bIsSplitFeature = bIsSplitFeature,
dExtendAfterTail = dExtendAfterTail,
nInternalSortingPriority = 1,
dResultWeight = 0.15,
bMachineAllClosedEdges = true
}
local AntiSplints1 = AntiSplintOnFace.Make( Proc, Part, BottomFace1, OptionalParametersAntiSplint)
for i = 1, #AntiSplints1 do
table.insert( CalculatedMachinings, AntiSplints1[i])
end
if BottomFace2 and bConvexAngle then
OptionalParametersAntiSplint.bMachineAllClosedEdges = false
local AntiSplints2 = AntiSplintOnFace.Make( Proc, Part, BottomFace2, OptionalParametersAntiSplint)
for i = 1, #AntiSplints2 do
table.insert( CalculatedMachinings, AntiSplints2[i])
end
end
-- pulitura con fresa dei lati chiusi non lavorati
-- TODO funzione
if bFinishWithMill then
for i = 1, #LongFaces do
local dDepthToMachineMill = BottomFace.MainEdges.LongEdges[i].dElevation - dMillingOffsetFromSide
local dToolMarkLength = max( Cutting1.dToolMarkLength, Cutting2.dToolMarkLength)
local OptionalParametersFaceByMill = { bIsSplitFeature = bIsSplitFeature, dExtendAfterTail = dExtendAfterTail,
dRadialStepSpan = dToolMarkLength, dDepthToMachine = dDepthToMachineMill
}
local Milling = FaceByMill.Make( Proc, Part, BottomFace, BottomFace.MainEdges.LongEdges[i], OptionalParametersFaceByMill)
Milling.nInternalSortingPriority = 2
Milling.dResultWeight = 0.05
table.insert( CalculatedMachinings, Milling)
if Cuttings1 then
-- si recuperano i lati chiusi non lavorati
local EdgesClosedNotMachined = {}
for i = 1, #BottomFace1.Edges do
if not( ( BottomFace1.Edges[i].id == BottomEdgeToMachine1.id) or BottomFace1.Edges[i].bIsOpen) then
table.insert( EdgesClosedNotMachined, BottomFace1.Edges[i])
end
end
-- su ognuno si fa la fresatura di pulizia
for i = 1, #EdgesClosedNotMachined do
local dDepthToMachine = EdgesClosedNotMachined[i].dElevation - dMillingOffsetFromSide
local dToolMarkLength = 0
-- si prende l'impronta dell'utensile più grande
for j = 1, #Cuttings1 do
if Cuttings1[j].dToolMarkLength > dToolMarkLength + 10 * GEO.EPS_SMALL then
dToolMarkLength = Cuttings1[j].dToolMarkLength
end
end
local OptionalParametersMilling = {
bIsSplitFeature = bIsSplitFeature,
dExtendAfterTail = dExtendAfterTail,
dRadialStepSpan = dToolMarkLength,
dDepthToMachine = dDepthToMachine
}
local Milling = FaceByMill.Make( Proc, Part, BottomFace1, EdgesClosedNotMachined[i], OptionalParametersMilling)
Milling.nInternalSortingPriority = 3
Milling.dResultWeight = 0.05
table.insert( CalculatedMachinings, Milling)
end
end
if Cuttings2 and BottomEdgeToMachine2 then
-- si recuperano i lati chiusi non lavorati
local EdgesClosedNotMachined = {}
for i = 1, #BottomFace2.Edges do
if not( ( BottomFace2.Edges[i].id == BottomEdgeToMachine2.id) or BottomFace2.Edges[i].bIsOpen) then
table.insert( EdgesClosedNotMachined, BottomFace2.Edges[i])
end
end
-- su ognuno si fa la fresatura di pulizia
for i = 1, #EdgesClosedNotMachined do
local dDepthToMachine = EdgesClosedNotMachined[i].dElevation - dMillingOffsetFromSide
local dToolMarkLength = 0
-- si prende l'impronta dell'utensile più grande
for j = 1, #Cuttings2 do
if Cuttings2[j].dToolMarkLength > dToolMarkLength + 10 * GEO.EPS_SMALL then
dToolMarkLength = Cuttings2[j].dToolMarkLength
end
end
local OptionalParametersMilling = {
bIsSplitFeature = bIsSplitFeature,
dExtendAfterTail = dExtendAfterTail,
dRadialStepSpan = dToolMarkLength,
dDepthToMachine = dDepthToMachine
}
local Milling = FaceByMill.Make( Proc, Part, BottomFace2, EdgesClosedNotMachined[i], OptionalParametersMilling)
Milling.nInternalSortingPriority = 3
Milling.dResultWeight = 0.05
table.insert( CalculatedMachinings, Milling)
end
end
end
@@ -253,8 +416,10 @@ function BLADEKEEPWASTE.Make( Proc, Part, OptionalParameters)
end
end
-- calcolo completamento, serve la lista di lavorazioni che comprende le non applicabili
Result.dCompletionPercentage = GetStrategyCompletionPercentage( CalculatedMachinings)
-- calcolo completamento (non applicabili devono essere incluse)
-- se codolo non forzato si ritorna completa max al 94% (completion index 4)
local dCalculatedCompletionPercentage = GetStrategyCompletionPercentage( CalculatedMachinings)
Result.dCompletionPercentage = bForced and dCalculatedCompletionPercentage or min( 94, dCalculatedCompletionPercentage)
Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( Result.dCompletionPercentage)
-- aggiunta eventuali lavorazioni splittate
@@ -266,12 +431,17 @@ function BLADEKEEPWASTE.Make( Proc, Part, OptionalParameters)
table.sort( Machinings, SortMachiningsBySegment)
-- calcolo risultati
if Cutting1.bIsApplicable or Cutting2.bIsApplicable then
if ( Cuttings1 and ( ( Cuttings1[1] and Cuttings1[1].bIsApplicable) or ( Cuttings1[2] and Cuttings1[2].bIsApplicable)))
or ( Cuttings2 and ( ( Cuttings2[1] and Cuttings2[1].bIsApplicable) or ( Cuttings2[2] and Cuttings2[2].bIsApplicable))) then
Result.dQuality = FeatureLib.GetStrategyQuality( Machinings)
Result.dTimeToMachine = FeatureLib.GetStrategyTimeToMachine( Machinings)
Result.dMRR = ( dFeatureVolume / Result.dTimeToMachine) / pow( 10, 6)
if Result.dCompletionPercentage > 100 - 10 * GEO.EPS_SMALL then
Result.sStatus = 'Completed'
if bForced then
Result.sInfo = 'Waste attached. Remove manually.'
end
else
Result.sStatus = 'Not-Completed'
end
File diff suppressed because it is too large Load Diff
+301 -206
View File
@@ -4,142 +4,90 @@
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FaceData = require( 'FaceData')
local LeadInOutLib = require( 'LeadInOutLib')
-- Tabella per definizione modulo
local FACEBYBLADE = {}
-------------------------------------------------------------------------------------------------------------
local function GetLeadInOutType( Machining)
local sLeadInOutType = ''
-- i parametri si leggono da LeadInOut (engagement) e si modificano solo se necessario
local function GetLeadInOut( Machining, EdgeToMachine, bIsSplitFeature)
if Machining.bIsStartClosed or Machining.bIsEndClosed
or Machining.sCutType == 'Guillotine'
or Machining.sCutType == 'Reduced' then
sLeadInOutType = 'Perpendicular'
else
-- testa sopra
if TOOLS[Machining.nToolIndex].SetupInfo.HeadType.bTop then
if abs( Machining.vtToolDirection:getX()) < 0.7 then
if Machining.vtToolDirection:getZ() > -0.087
or ( abs( Machining.vtToolDirection:getX()) < 0.34202 and abs( Machining.vtToolDirection:getZ()) < 0.7) then
sLeadInOutType = 'Perpendicular'
else
sLeadInOutType = 'Tangent'
end
elseif abs( Machining.vtEdgeDirection:getZ()) > 0.7 then
sLeadInOutType = 'Perpendicular'
else
-- TODO qui attacco tangenziale speciale tutto da un lato
sLeadInOutType = 'Tangent'
end
-- testa sotto
elseif TOOLS[Machining.nToolIndex].SetupInfo.HeadType.bBottom then
if abs( Machining.vtToolDirection:getX()) < 0.7 then
if Machining.vtToolDirection:getZ() < -GEO.EPS_SMALL
or ( abs( Machining.vtToolDirection:getX()) < 0.34202 and abs( Machining.vtToolDirection:getZ()) < 0.7) then
sLeadInOutType = 'Perpendicular'
else
sLeadInOutType = 'Tangent'
end
elseif abs( Machining.vtEdgeDirection:getZ()) > 0.7 then
sLeadInOutType = 'Perpendicular'
else
-- TODO qui attacco tangenziale speciale tutto da un lato
sLeadInOutType = 'Tangent'
end
-- se testa senza preferenza Top e Bottom si fa sempre attacco tangenziale
else
sLeadInOutType = 'Tangent'
end
end
local LeadIn
local LeadOut
return sLeadInOutType
end
local function CalculateLeadInOut( Machining, EdgeToMachine, bIsSplitFeature)
-- TODO implementare le funzioni di Tool Collision Avoidance (vedi wiki e FacesBysaw -> CalcLeadInOutPerpGeom)
-- accorciamento per lati chiusi (è sempre l'impronta utensile)
local dToolMarkLength = sqrt( Machining.dDepthToMachine * TOOLS[Machining.nToolIndex].dDiameter - Machining.dDepthToMachine * Machining.dDepthToMachine)
-- allungamento per faccia singola (aperta in tutte le direzioni)
local dAddedLengthOpenFace = BeamData.CUT_EXTRA
if Machining.sCutType == 'Guillotine' then
local dGuillotineLengthToMachine = 1
dAddedLengthOpenFace = ( - EdgeToMachine.dLength + dGuillotineLengthToMachine) / 2
elseif Machining.sCutType == 'Reduced' then
dAddedLengthOpenFace = - FACEBYBLADE.GetPathReductionLength( Machining.nToolIndex, Machining.dMaxRadialOffset)
end
if Machining.bInvert then
Machining.bIsStartClosed, Machining.bIsEndClosed = Machining.bIsEndClosed, Machining.bIsStartClosed
end
local LeadIn = {}
local LeadOut = {}
Machining.sLeadInOutType = ''
LeadIn.dStartAddLength = 0
LeadOut.dEndAddLength = 0
LeadIn.nType = MCH_MILL_LI.LINEAR
LeadOut.nType = MCH_MILL_LI.LINEAR
LeadIn.dPerpDistance = 0
LeadOut.dPerpDistance = 0
LeadIn.dTangentDistance = 0
LeadOut.dTangentDistance = 0
-- in certe condizioni si deve forzare attacco perpendicolare
if Machining.bIsStartClosed
or Machining.bIsEndClosed
or Machining.CloneStepsRadial.nCount > 1
or Machining.Steps.nCount > 1
or bIsSplitFeature then
Machining.sLeadInOutType = 'Perpendicular'
if AreSameVectorApprox( Machining.vtToolDirection, EdgeToMachine.vtN) then
LeadIn.dPerpDistance = EdgeToMachine.dElevation + BeamData.CUT_SIC - Machining.dRadialOffset
LeadOut.dPerpDistance = EdgeToMachine.dElevation + BeamData.CUT_SIC - Machining.dRadialOffset
if Machining.LeadInOut.Perpendicular then
Machining.sLeadInOutType = 'Perpendicular'
-- se attacco perpendicolare richiesto ma non disponibile, la lavorazione non è fattibile
else
LeadIn.dPerpDistance = BeamData.CUT_SIC - Machining.dRadialOffset
LeadOut.dPerpDistance = BeamData.CUT_SIC - Machining.dRadialOffset
return
end
else
Machining.sLeadInOutType = GetLeadInOutType( Machining)
if Machining.sLeadInOutType == 'Perpendicular' then
LeadIn.dPerpDistance = 1
LeadOut.dPerpDistance = 1
else
-- TODO da rimuovere, già inserito in GetLeadInOutType
if abs( Machining.vtEdgeDirection:getZ()) > 0.707 then
LeadIn.dPerpDistance = 1
LeadOut.dPerpDistance = 1
else
LeadIn.dTangentDistance = TOOLS[Machining.nToolIndex].dDiameter / 2 + BeamData.CUT_SIC
LeadOut.dTangentDistance = TOOLS[Machining.nToolIndex].dDiameter / 2 + BeamData.CUT_SIC
end
end
Machining.sLeadInOutType = Machining.LeadInOut.sChosen
end
LeadIn.dElevation = 0
LeadOut.dElevation = 0
LeadIn.dCompLength = 0
LeadOut.dCompLength = 0
if Machining.bIsStartClosed and Machining.bIsEndClosed then
LeadIn.dStartAddLength = -dToolMarkLength
LeadOut.dEndAddLength = -dToolMarkLength
elseif Machining.bIsStartClosed then
LeadIn.dStartAddLength = -dToolMarkLength
-- eventuale correzione per accorciamento maggiore di larghezza tasca
LeadOut.dEndAddLength = max( -LeadIn.dStartAddLength - EdgeToMachine.dLength + 10 * BeamData.CUT_EXTRA, BeamData.CUT_EXTRA)
elseif Machining.bIsEndClosed then
LeadOut.dEndAddLength = -dToolMarkLength
-- eventuale correzione per accorciamento maggiore di larghezza tasca
LeadIn.dStartAddLength = max( -LeadOut.dEndAddLength - EdgeToMachine.dLength + 10 * BeamData.CUT_EXTRA, BeamData.CUT_EXTRA)
else
LeadIn.dStartAddLength = dAddedLengthOpenFace
LeadOut.dEndAddLength = dAddedLengthOpenFace
-- si prendono i valori che arrivano da LeadInOut (engagement)
LeadIn = BeamLib.TableCopyDeep( Machining.LeadInOut[Machining.sLeadInOutType].LeadIn)
LeadOut = BeamLib.TableCopyDeep( Machining.LeadInOut[Machining.sLeadInOutType].LeadOut)
-- se senso di percorrenza invertito si invertono anche gli attacchi
if Machining.bInvert then
Machining.bIsStartClosed, Machining.bIsEndClosed = Machining.bIsEndClosed, Machining.bIsStartClosed
LeadIn, LeadOut = LeadInOutLib.InvertLeadInOut( LeadIn, LeadOut)
end
-- in caso di percorso ridotto gli attacchi vanno adeguati
if Machining.sEdgeUsage == 'Guillotine' then
local dGuillotineLengthToMachine = 1
LeadIn.dStartAddLength = ( - EdgeToMachine.dLength + dGuillotineLengthToMachine) / 2
LeadOut.dEndAddLength = ( - EdgeToMachine.dLength + dGuillotineLengthToMachine) / 2
LeadIn.dPerpDistance = EdgeToMachine.dElevation + BeamData.CUT_SIC - Machining.dRadialOffset
LeadIn.dTangentDistance = 0
LeadOut.dPerpDistance = EdgeToMachine.dElevation + BeamData.CUT_SIC - Machining.dRadialOffset
LeadOut.dTangentDistance = 0
LeadIn.dTotalLength = sqrt( LeadIn.dPerpDistance ^ 2 + LeadIn.dTangentDistance ^ 2)
LeadOut.dTotalLength = sqrt( LeadOut.dPerpDistance ^ 2 + LeadOut.dTangentDistance ^ 2)
elseif Machining.sEdgeUsage == 'Reduced' then
LeadIn.dStartAddLength = - FACEBYBLADE.GetPathReductionLength( Machining.nToolIndex, Machining.dMaxRadialOffset)
LeadOut.dEndAddLength = - FACEBYBLADE.GetPathReductionLength( Machining.nToolIndex, Machining.dMaxRadialOffset)
LeadIn.dPerpDistance = EdgeToMachine.dElevation + BeamData.CUT_SIC - Machining.dRadialOffset
LeadIn.dTangentDistance = 0
LeadOut.dPerpDistance = EdgeToMachine.dElevation + BeamData.CUT_SIC - Machining.dRadialOffset
LeadOut.dTangentDistance = 0
LeadIn.dTotalLength = sqrt( LeadIn.dPerpDistance ^ 2 + LeadIn.dTangentDistance ^ 2)
LeadOut.dTotalLength = sqrt( LeadOut.dPerpDistance ^ 2 + LeadOut.dTangentDistance ^ 2)
end
-- se accorciamenti maggiori della lunghezza lato, la lavorazione non è fattibile
if LeadIn.dStartAddLength + LeadOut.dEndAddLength + EdgeToMachine.dLength < 1 then
return
end
-- se lavorazione con OppositeToolDirection o ridotta l'attacco va corretto
if not AreSameVectorApprox( Machining.vtToolDirection, EdgeToMachine.vtN) then
LeadIn.dPerpDistance = BeamData.CUT_SIC - Machining.dRadialOffset
LeadOut.dPerpDistance = BeamData.CUT_SIC - Machining.dRadialOffset
LeadIn.dTangentDistance = 0
LeadOut.dTangentDistance = 0
end
-- stima lunghezza reale attacchi per calcolo lunghezza lavorata
-- TODO sistemare per nuovi attacchi
local dEstimatedLeadInPerpDistance = 0
local dEstimatedLeadInTangentDistance = 0
local dEstimatedLeadOutPerpDistance = 0
@@ -163,8 +111,8 @@ local function CalculateLeadInOut( Machining, EdgeToMachine, bIsSplitFeature)
end
-- TODO implementare SCC in funzione macchina
local function GetSCC( vtMachiningDirection, vtEdgeDirection, vtNFace)
-- TODO da eliminare, sostituita da funzione macchina
function FACEBYBLADE.GetSCC( vtMachiningDirection, vtEdgeDirection, vtNFace)
local nSCC = MCH_SCC.NONE
if abs( vtMachiningDirection:getX()) > abs( vtMachiningDirection:getY()) - GEO.EPS_SMALL then
@@ -259,60 +207,84 @@ function FACEBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar
dLongitudinalOffset = 0
end
local dRadialStepSpan = OptionalParameters.dRadialStepSpan
local dMinNzDownUp = OptionalParameters.dMinNzDownUp
local sUserNotes = OptionalParameters.sUserNotes or ''
local bIsDicing = OptionalParameters.bIsDicing or false
local sRestLengthSideForPreSimulation = OptionalParameters.sRestLengthSideForPreSimulation or 'Tail'
local bCannotSplitRestLength = OptionalParameters.bCannotSplitRestLength or false
local bDisableRealElevationCheck = OptionalParameters.bDisableRealElevationCheck or false
-- lunghezze, direzioni e punti caratteristici della lavorazione e del lato lavorato
Cutting.dEdgeLength = EdgeToMachine.dLength
if OppositeToolDirectionMode == 'Enabled' 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)
-- TODO gestire lama da sotto
-- se si conosce il limite downUp (utensile forzato o downUp forzato) si decide se invertire (ToolInvert)
-- TODO esiste un limite downUp massimo per la lama da sopra??
if nToolIndex and not dMinNzDownUp then
dMinNzDownUp = TOOLS[nToolIndex].SetupInfo.GetMinNzDownUp( Part.b3Raw, FaceToMachine.vtN, Cutting.vtToolDirection, TOOLS[nToolIndex])
end
if dMinNzDownUp and FaceToMachine.vtN:getZ() < dMinNzDownUp then
Cutting.bToolInvert = true
else
Cutting.bToolInvert = false
end
-- TODO questa deve essere ptEnd - ptStart
Cutting.vtEdgeDirection = Vector3d( EdgeToMachine.vtEdge)
Cutting.vtToolDirection = EdgeToMachine.vtN
Cutting.ptEdge1, Cutting.ptEdge2 = EdgeToMachine.ptStart, EdgeToMachine.ptEnd
local EdgeToMachineOpposite = BeamLib.FindEdgeBestOrientedAsDirection( FaceToMachine.Edges, -EdgeToMachine.vtN)
-- ricerca utensile
-- l'utensile arriva da fuori: si determina se il taglio è fattibile e il modo di lavorare della lama
if nToolIndex then
Cutting.nToolIndex = nToolIndex
local BladeEngagementParameters = {
Face = FaceToMachine,
Edge = EdgeToMachine,
Part = Part,
Tool = TOOLS[Cutting.nToolIndex],
dDepthToMachine = dDepthToMachine
}
if OppositeToolDirectionMode == 'Enabled' then
BladeEngagementParameters.Edge = EdgeToMachineOpposite
end
local BladeEngagementOptionalParameters = {
bIsDicing = bIsDicing,
sRestLengthSideForPreSimulation = sRestLengthSideForPreSimulation,
bCannotSplitRestLength = bCannotSplitRestLength,
bDisableRealElevationCheck = bDisableRealElevationCheck
}
local Engagement
TIMER:startElapsed( 'GetBladeEngagement')
Cutting.bIsApplicable, Engagement = MachiningLib.GetBladeEngagement( BladeEngagementParameters, BladeEngagementOptionalParameters)
TIMER:stopElapsed( 'GetBladeEngagement')
if Cutting.bIsApplicable then
Cutting.sBladeEngagement = Engagement.sBladeEngagement
Cutting.bMoveAfterSplit = Engagement.bMoveAfterSplit
Cutting.LeadInOut = Engagement.LeadInOut
end
-- utensile da cercare: si prende la lama migliore che può effettuare questo taglio, senza particolari analisi
else
local ToolSearchParameters = {}
ToolSearchParameters.dElevation = dDepthToMachine
if Cutting.bToolInvert then
ToolSearchParameters.vtN = -FaceToMachine.vtN
else
ToolSearchParameters.vtN = FaceToMachine.vtN
end
ToolSearchParameters.bAllowTopHead = true
-- TODO bisognerà implementare anche la lama da sotto
ToolSearchParameters.bAllowBottomHead = false
ToolSearchParameters.bAllowBottomHead = true
ToolSearchParameters.bForceLongcutBlade = bForceLongcutBlade
ToolSearchParameters.FaceToMachine = FaceToMachine
ToolSearchParameters.EdgeToMachine = EdgeToMachine
ToolSearchParameters.Part = Part
ToolSearchParameters.sRestLengthSideForPreSimulation = sRestLengthSideForPreSimulation
ToolSearchParameters.bCannotSplitRestLength = bCannotSplitRestLength
ToolSearchParameters.bDisableRealElevationCheck = bDisableRealElevationCheck
local ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters)
-- ora che l'utensile è scelto, se non era definito l'angolo di DownUp lo verifico per decidere se invertire
if ToolInfo.nToolIndex and not dMinNzDownUp then
dMinNzDownUp = TOOLS[ToolInfo.nToolIndex].SetupInfo.GetMinNzDownUp( Part.b3Raw, FaceToMachine.vtN, Cutting.vtToolDirection, TOOLS[ToolInfo.nToolIndex])
if FaceToMachine.vtN:getZ() < dMinNzDownUp then
Cutting.bToolInvert = true
end
end
Cutting.nToolIndex = ToolInfo.nToolIndex
if Cutting.nToolIndex then
Cutting.sBladeEngagement = ToolInfo.Engagement.sBladeEngagement
Cutting.bMoveAfterSplit = ToolInfo.Engagement.bMoveAfterSplit
Cutting.LeadInOut = ToolInfo.Engagement.LeadInOut
end
-- se non trovato utensile, la lavorazione non è applicabile
if not Cutting.nToolIndex then
Cutting.bIsApplicable = false
end
end
if not TOOLS[Cutting.nToolIndex] or not TOOLS[Cutting.nToolIndex].sName then
-- orientamento non raggiungibile o lama non trovata: non applicabile
if not Cutting.bIsApplicable then
Cutting.sMessage = 'Blade not found'
Cutting.bIsApplicable = false
EgtOutLog( Cutting.sMessage)
return Cutting, EdgeToMachine.dElevation
end
@@ -322,25 +294,32 @@ function FACEBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar
Cutting.sMessage = 'Pocket too narrow for blade thickness'
Cutting.bIsApplicable = false
EgtOutLog( Cutting.sMessage)
return Cutting, EdgeToMachine.dElevation
end
-- TODO vedere se la rimozione di questo crea problemi
-- se tasca chiusa da entrambi i lati e più stretta della lama la lavorazione non è applicabile
if not ( EdgeToMachine.bIsStartOpen or EdgeToMachine.bIsEndOpen) then
if TOOLS[Cutting.nToolIndex].dDiameter > EdgeToMachine.dLength + 10 * GEO.EPS_SMALL then
Cutting.sMessage = 'Pocket too narrow for blade diameter'
Cutting.bIsApplicable = false
EgtOutLog( Cutting.sMessage)
return Cutting, EdgeToMachine.dElevation
end
end
-- if not ( EdgeToMachine.bIsStartOpen or EdgeToMachine.bIsEndOpen) then
-- if TOOLS[Cutting.nToolIndex].dDiameter > EdgeToMachine.dLength + 10 * GEO.EPS_SMALL then
-- Cutting.sMessage = 'Pocket too narrow for blade diameter'
-- Cutting.bIsApplicable = false
-- EgtOutLog( Cutting.sMessage)
-- return Cutting, EdgeToMachine.dElevation
-- end
-- end
-- parametri della lavorazione
-- profondità (parametro DEPTH)
Cutting.sDepth = sDepth
Cutting.sDepth = sDepth
-- inizio e fine aperti o chiusi
Cutting.bIsStartClosed = not EdgeToMachine.bIsStartOpen
Cutting.bIsEndClosed = not EdgeToMachine.bIsEndOpen
-- lato di lavoro e inversione per avere taglio concorde
Cutting.bIsStartClosed = not EdgeToMachine.bIsStartOpen
Cutting.bIsEndClosed = not EdgeToMachine.bIsEndOpen
-- si settano lato di lavoro e inversione per avere concordanza
if TOOLS[Cutting.nToolIndex].bIsCCW then
Cutting.nWorkside = MCH_MILL_WS.RIGHT
Cutting.bInvert = true
@@ -348,37 +327,95 @@ function FACEBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar
Cutting.nWorkside = MCH_MILL_WS.LEFT
Cutting.bInvert = false
end
-- se OppositeToolDirectionMode è Optimized, se possibile e necessario, si attiva per garantire taglio concorde e verso l'alto (massima qualità)
if ( OppositeToolDirectionMode == 'Optimized') and ( Proc.nFct == 1) and ( FaceData.IsFaceRhomboid( Proc, FaceToMachine.id)) then
OppositeToolDirectionMode = 'Disabled'
-- la direzione di percorrenza del lato deve essere verso l'alto; bInvert va considerata perchè inverte la direzione di percorrenza.
if ( Cutting.bInvert and Cutting.vtEdgeDirection:getZ() > 100 * GEO.EPS_SMALL)
or ( ( not Cutting.bInvert) and Cutting.vtEdgeDirection:getZ() < -100 * GEO.EPS_SMALL) then
-- si attiva OppositeToolDirection solo se non cambiano le condizioni di taglio downUp
local dNewMinNzDownUp = TOOLS[nToolIndex].SetupInfo.GetMinNzDownUp( Part.b3Raw, FaceToMachine.vtN, -Cutting.vtToolDirection, TOOLS[nToolIndex])
if ( FaceToMachine.vtN:getZ() < dMinNzDownUp) == ( FaceToMachine.vtN:getZ() < dNewMinNzDownUp) then
OppositeToolDirectionMode = 'Enabled'
Cutting.vtToolDirection = -EdgeToMachine.vtN
Cutting.ptEdge1, _, Cutting.ptEdge2 = EgtSurfTmFacetOppositeSide( Proc.id, FaceToMachine.id, -Cutting.vtToolDirection, GDB_ID.ROOT)
Cutting.bInvert = not Cutting.bInvert
-- se le condizioni downUp cambiano, si setta per tagliare verso l'alto
else
if Cutting.nWorkside == MCH_MILL_WS.RIGHT then
Cutting.nWorkside = MCH_MILL_WS.LEFT
Cutting.bInvert = false
else
Cutting.nWorkside = MCH_MILL_WS.RIGHT
Cutting.bInvert = true
end
-- ToolInvert
if Cutting.sBladeEngagement == 'DownUp' then
Cutting.bToolInvert = true
Cutting.bInvert = not Cutting.bInvert
end
-- se dicing, lato di lavoro e inversione per avere taglio sempre verso l'alto
if bIsDicing
and ( Cutting.bInvert and Cutting.vtEdgeDirection:getZ() > 100 * GEO.EPS_SMALL)
or ( ( not Cutting.bInvert) and Cutting.vtEdgeDirection:getZ() < -100 * GEO.EPS_SMALL) then
Cutting.bInvert = not Cutting.bInvert
if Cutting.nWorkside == MCH_MILL_WS.LEFT then
Cutting.nWorkside = MCH_MILL_WS.RIGHT
else
Cutting.nWorkside = MCH_MILL_WS.LEFT
end
end
-- analisi fattibilità lavorazione dal lato opposto
if OppositeToolDirectionMode ~= 'Disabled' then
-- lavorando dalla direzione opposta si verifica come se si lavorasse il lato opposto
local BladeEngagementParameters = {
Face = FaceToMachine,
Edge = EdgeToMachineOpposite,
Part = Part,
Tool = TOOLS[Cutting.nToolIndex],
dDepthToMachine = dDepthToMachine
}
local BladeEngagementOptionalParameters = {
bIsDicing = bIsDicing,
sRestLengthSideForPreSimulation = sRestLengthSideForPreSimulation,
bCannotSplitRestLength = bCannotSplitRestLength,
bDisableRealElevationCheck = bDisableRealElevationCheck
}
TIMER:startElapsed( 'GetBladeEngagement')
local bIsApplicableOpposite, EngagementOpposite = MachiningLib.GetBladeEngagement( BladeEngagementParameters, BladeEngagementOptionalParameters)
TIMER:stopElapsed( 'GetBladeEngagement')
-- taglio opposto non fattibile
if not bIsApplicableOpposite then
-- se richiesto, si ritorna non applicabile
if OppositeToolDirectionMode == 'Enabled' then
Cutting.sMessage = 'Orientation not reachable'
Cutting.bIsApplicable = false
return Cutting, EdgeToMachine.dElevation
-- se opzionale, si disabilita
elseif OppositeToolDirectionMode == 'Optimized' then
OppositeToolDirectionMode = 'Disabled'
end
end
-- se OppositeToolDirectionMode è Optimized, se possibile e necessario, si attiva la lavorazione dal lato opposto per garantire taglio concorde e verso l'alto (massima qualità)
if ( OppositeToolDirectionMode == 'Optimized') and ( Proc.nFct == 1) and ( FaceData.IsFaceRectangle( FaceToMachine)) then
OppositeToolDirectionMode = 'Disabled'
-- la direzione di percorrenza del lato deve essere verso l'alto; bInvert va considerata perchè inverte la direzione di percorrenza
-- il BladeEngagement non deve cambiare, altrimenti è inutile invertire la direzione
if ( EngagementOpposite.sBladeEngagement == Cutting.sBladeEngagement)
and ( EngagementOpposite.bMoveAfterSplit == Cutting.bMoveAfterSplit)
and ( Cutting.bInvert and Cutting.vtEdgeDirection:getZ() > 100 * GEO.EPS_SMALL)
or ( ( not Cutting.bInvert) and Cutting.vtEdgeDirection:getZ() < -100 * GEO.EPS_SMALL) then
OppositeToolDirectionMode = 'Enabled'
end
end
if OppositeToolDirectionMode == 'Enabled' then
Cutting.vtToolDirection = EdgeToMachineOpposite.vtN
Cutting.ptEdge1, Cutting.ptEdge2 = EdgeToMachineOpposite.ptStart, EdgeToMachineOpposite.ptEnd
Cutting.bInvert = not Cutting.bInvert
-- TODO da migliorare!!!!!!!!!
if not EngagementOpposite.LeadInOut.Perpendicular then
Cutting.LeadInOut.Perpendicular = nil
end
if not EngagementOpposite.LeadInOut.Tangent then
Cutting.LeadInOut.Tangent = nil
end
end
elseif OppositeToolDirectionMode == 'Enabled' then
Cutting.bInvert = not Cutting.bInvert
end
if Cutting.bToolInvert then
Cutting.bInvert = not Cutting.bInvert
end
-- TODO implementare lavorazione in DownUp se non è già DownUp e non si è riusciti a mantenere verso l'alto e concorde (testare solo DownUp))
-- profondità da lavorare e offset radiale
if OptionalParameters.dPocketHeight then
if TOOLS[Cutting.nToolIndex].dMaxDepth > dDepthToMachine - 10 * GEO.EPS_SMALL then
@@ -402,36 +439,73 @@ function FACEBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar
else
Cutting.dDepthToMachine = dDepthToMachine
Cutting.dResidualDepth = 0
Cutting.sCutType = 'Standard'
Cutting.sEdgeUsage = 'Standard'
if bReduceBladePath
and ( Proc.nFct == 1)
and FaceData.IsFaceRectangular( Proc, FaceToMachine.id) then
and FaceData.IsFaceRectangle( FaceToMachine) then
local bIsTopBlade = TOOLS[nToolIndex].SetupInfo.HeadType.bTop
Cutting.dMaxRadialOffset = TOOLS[nToolIndex].dMaxMaterial - Cutting.dDepthToMachine - BeamData.CUT_SIC
Cutting.dRadialOffsetGuillotine = FACEBYBLADE.GetRadialOffsetForGuillotine( nToolIndex, EdgeToMachine.dLength)
-- TODO la lama sotto deve poter ridurre. Ghigliottina sì o no?
local bIsTopBlade = TOOLS[Cutting.nToolIndex].SetupInfo.HeadType.bTop
Cutting.dMaxRadialOffset = TOOLS[Cutting.nToolIndex].dMaxMaterial - Cutting.dDepthToMachine - BeamData.CUT_SIC
Cutting.dRadialOffsetGuillotine = FACEBYBLADE.GetRadialOffsetForGuillotine( Cutting.nToolIndex, EdgeToMachine.dLength)
if Cutting.dMaxRadialOffset > 10 * GEO.EPS_SMALL then
-- taglio a ghigliottina
if bIsTopBlade and ( Cutting.dRadialOffsetGuillotine < Cutting.dMaxRadialOffset - 10 * GEO.EPS_SMALL) then
dDepthToMachine = Cutting.dDepthToMachine + Cutting.dRadialOffsetGuillotine
Cutting.sCutType = 'Guillotine'
Cutting.sEdgeUsage = 'Guillotine'
-- taglio ridotto
else
dDepthToMachine = Cutting.dDepthToMachine + Cutting.dMaxRadialOffset
Cutting.sCutType = 'Reduced'
Cutting.sEdgeUsage = 'Reduced'
end
end
end
-- se cambiata la profondità dDepthToMachine, si ritesta la fattibilità del taglio
if Cutting.sEdgeUsage ~= 'Standard' then
local EdgeToMachineForEngagement = EdgeToMachine
if OppositeToolDirectionMode == 'Enabled' then
EdgeToMachineForEngagement = EdgeToMachineOpposite
end
local BladeEngagementParameters = {
Face = FaceToMachine,
Edge = EdgeToMachineForEngagement,
Part = Part,
Tool = TOOLS[Cutting.nToolIndex],
dDepthToMachine = dDepthToMachine
}
local BladeEngagementOptionalParameters = {
bIsDicing = bIsDicing,
sRestLengthSideForPreSimulation = sRestLengthSideForPreSimulation,
bCannotSplitRestLength = bCannotSplitRestLength,
bDisableRealElevationCheck = bDisableRealElevationCheck
}
TIMER:startElapsed( 'GetBladeEngagement')
local bIsApplicable, CurrentEngagement = MachiningLib.GetBladeEngagement( BladeEngagementParameters, BladeEngagementOptionalParameters )
TIMER:stopElapsed( 'GetBladeEngagement')
-- se non fattibile o cambiano le condizioni BladeEngagement, non si riduce
if not ( bIsApplicable and ( CurrentEngagement.sBladeEngagement == Cutting.sBladeEngagement) and ( CurrentEngagement.bMoveAfterSplit == Cutting.bMoveAfterSplit)) then
Cutting.sEdgeUsage = 'Standard'
dDepthToMachine = Cutting.dDepthToMachine
end
end
-- offset radiale (cambia se taglio opposto)
if OppositeToolDirectionMode == 'Enabled' then
Cutting.dRadialOffset = -dDepthToMachine
else
Cutting.dRadialOffset = EdgeToMachine.dElevation - dDepthToMachine
end
end
-- completamento
Cutting.dCompletionPercentage = ( 1 - Cutting.dResidualDepth / Cutting.dDepthToMachine) * 100
-- step verticale e offset longitudinale
Cutting.Steps = MachiningLib.GetMachiningSteps( dPocketHeight, TOOLS[Cutting.nToolIndex].dThickness)
Cutting.Steps = MachiningLib.GetMachiningSteps( true, dPocketHeight, TOOLS[Cutting.nToolIndex].dThickness)
Cutting.Steps.nStepType = MCH_MILL_ST.ONEWAY
Cutting.dMaxElev = Cutting.Steps.dStep * Cutting.Steps.nCount - 10 * GEO.EPS_SMALL
if Cutting.bToolInvert then
@@ -443,10 +517,13 @@ function FACEBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar
else
Cutting.dLongitudinalOffset = dLongitudinalOffset
end
-- distanza di sicurezza
Cutting.dStartSafetyLength = BeamData.CUT_SIC
-- overlap
Cutting.dOverlap = 0
-- EdgeUse e frame lavorazione
if OppositeToolDirectionMode == 'Enabled' then
Cutting.nFaceuse = BeamLib.GetNearestOrthoOpposite( -Cutting.vtToolDirection)
@@ -457,23 +534,37 @@ function FACEBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar
--Cutting.vtFaceUse = Cutting.vtToolDirection
Cutting.nEdgesFaceUse = EdgeToMachine.id
end
-- SCC
Cutting.nSCC = GetSCC( Cutting.vtToolDirection, Cutting.vtEdgeDirection, FaceToMachine.vtN)
Cutting.nSCC = TOOLS[Cutting.nToolIndex].SetupInfo.GetSCC( Cutting.vtToolDirection, Cutting.vtEdgeDirection, FaceToMachine.vtN)
-- asse bloccato
Cutting.sBlockedAxis = BeamLib.GetBlockedAxis( Cutting.nToolIndex, 'perpendicular', Part.b3Raw, FaceToMachine.vtN, EgtIf( FaceToMachine.vtN:getX() > 0, X_AX(), -X_AX()))
-- eventuale step orizzontale
Cutting.CloneStepsRadial = {}
if not dRadialStepSpan then
dRadialStepSpan = Cutting.dDepthToMachine
end
if dRadialStepSpan > 10 * GEO.EPS_SMALL and TOOLS[Cutting.nToolIndex].dSideStep then
Cutting.CloneStepsRadial = MachiningLib.GetMachiningSteps( dRadialStepSpan, TOOLS[Cutting.nToolIndex].dSideStep)
Cutting.CloneStepsRadial = MachiningLib.GetMachiningSteps( true, dRadialStepSpan, TOOLS[Cutting.nToolIndex].dSideStep)
else
Cutting.CloneStepsRadial.nCount = 1
Cutting.CloneStepsRadial.dStep = Cutting.dDepthToMachine
end
-- approccio e retrazione
Cutting.LeadIn, Cutting.LeadOut = CalculateLeadInOut( Cutting, EdgeToMachine, bIsSplitFeature)
Cutting.LeadIn, Cutting.LeadOut = GetLeadInOut( Cutting, EdgeToMachine, bIsSplitFeature)
-- se il calcolo attacchi fallisce, la lavorazione non è fattibile
if not Cutting.LeadIn or not Cutting.LeadOut then
Cutting.bIsApplicable = false
return Cutting
end
-- solo per debug
--Cutting.nOutRaw = 3
-- lunghezza lavorata
-- TODO per il calcolo del dLengthOnX si deve correggere con allungamento / accorciamento percorso
Cutting.dLengthToMachine = EdgeToMachine.dLength + Cutting.LeadIn.dStartAddLength + Cutting.LeadOut.dEndAddLength
@@ -481,6 +572,7 @@ function FACEBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar
Cutting.dLengthOnX = b3BoxEdge:getDimX()
Cutting.dTimeToMachine, Cutting.dLengthToMachineAllStepsWithLeadInOut = MachiningLib.GetTimeToMachineAllStepsWithLeadInOut( Cutting, Part)
-- lunghezza impronta lama
-- TODO rimpiazzare con LeadInOut.dToolMarkLength
if Cutting.bIsStartClosed and Cutting.bIsEndClosed then
Cutting.dToolMarkLength = abs( min( Cutting.LeadIn.dStartAddLength, Cutting.LeadOut.dEndAddLength))
elseif Cutting.bIsStartClosed then
@@ -499,8 +591,9 @@ function FACEBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar
-- se lavorazione aperta sulla coda, eventuali aggiustamenti
-- TODO valutare se fare funzione a parte
local bIsTruncatingCutOnTail = Proc.Topology and ( Proc.Topology.sName == 'Cut-1-Through' or Proc.Topology.sName == 'TailCut') and Proc.AffectedFaces.bLeft
if bIsTruncatingCutOnTail then
Cutting.bMoveAfterSplit = Cutting.bMoveAfterSplit or Cutting.LeadIn.bMoveAfterSplit or Cutting.LeadOut.bMoveAfterSplit
local bIsTruncatingCutOnTail = Proc.Topology and ( Proc.Topology.sName == 'Cut-1-Through' or Proc.Topology.sName == 'TailCut') and Proc.AffectedFaces.bLeft
if Cutting.bMoveAfterSplit or bIsTruncatingCutOnTail then
Cutting.sStage = 'AfterTail'
elseif Proc.AffectedFaces.bLeft and ( EdgeToMachine.sType == 'Bottom' or ( Cutting.vtToolDirection:getX() < 0.707)) then
local dLengthOnX = Cutting.dLengthOnX
@@ -517,12 +610,14 @@ function FACEBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPar
if not AreSameOrOppositeVectorApprox( EdgeToMachine.vtN, Y_AX()) then
if MachiningLib.CanMoveAfterSplitcut( dLengthOnX, Part) then
Cutting.sStage = 'AfterTail'
Cutting.bMoveAfterSplit = true
else
Cutting.bIsApplicable = false
end
elseif dAddLengthLeftSide + dAddLengthToReduce > dExtendAfterTail then
if MachiningLib.CanMoveAfterSplitcut( dLengthOnX, Part) then
Cutting.sStage = 'AfterTail'
Cutting.bMoveAfterSplit = true
else
if bStartLeft then
Cutting.LeadIn.dStartAddLength = - dAddLengthToReduce + dExtendAfterTail
+29 -5
View File
@@ -4,8 +4,9 @@
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local PreSimulationLib = require( 'PreSimulationLib')
-- Tabella per definizione modulo
local FACEBYCHAINSAW = {}
@@ -42,6 +43,10 @@ local function CalculateLeadInOut( Machining, EdgeToMachine, sSideToMachine, dLe
LeadOut.dEndAddLength = BeamData.CUT_EXTRA
end
-- punti dell'attacco
LeadIn.ptPoint = EdgeToMachine.ptStart - EdgeToMachine.vtEdge * LeadIn.dStartAddLength + EdgeToMachine.vtN * ( EdgeToMachine.dElevation - Machining.dDepthToMachine)
LeadOut.ptPoint = EdgeToMachine.ptEnd + EdgeToMachine.vtEdge * LeadOut.dEndAddLength + EdgeToMachine.vtN * ( EdgeToMachine.dElevation - Machining.dDepthToMachine)
return LeadIn, LeadOut
end
@@ -82,8 +87,8 @@ function FACEBYCHAINSAW.Make( Proc, Part, FaceToMachine, EdgeToMachine, Optional
else
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)
Mortising.vtEdgeDirection = Vector3d( EdgeToMachine.vtEdge)
Mortising.ptEdge1, Mortising.ptEdge2 = EdgeToMachine.ptStart, EdgeToMachine.ptEnd
-- ricerca utensile
local ToolSearchParameters = {}
@@ -196,22 +201,41 @@ function FACEBYCHAINSAW.Make( Proc, Part, FaceToMachine, EdgeToMachine, Optional
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.vtN, 2)
-- TODO al momento si contempla solo sega a catena con asse bloccato
else
Mortising.bIsApplicable = false
return Mortising
end
-- approccio e retrazione
Mortising.LeadIn, Mortising.LeadOut = CalculateLeadInOut( Mortising, EdgeToMachine, sSideToMachine, dLengthToMachine)
-- check finecorsa nei punti di attacco
local PointsOnToolTipCenter = {
Mortising.LeadIn.ptPoint,
Mortising.LeadOut.ptPoint
}
local vtAux = FaceToMachine.vtN
if Mortising.bToolInvert then
vtAux = -FaceToMachine.vtN
end
local bOutOfStroke = PreSimulationLib.CheckOutOfStrokeFromPoints( PointsOnToolTipCenter, Mortising.vtToolDirection, Mortising.nSCC, TOOLS[Mortising.nToolIndex], vtAux, Mortising.sBlockedAxis)
if bOutOfStroke then
Mortising.sMessage = 'Out of stroke'
Mortising.bIsApplicable = false
return Mortising
end
-- eventuale step verticale
Mortising.CloneStepsLongitudinal = {}
if not dLongitudinalStepSpan then
dLongitudinalStepSpan = dPocketHeight
end
if dLongitudinalStepSpan > 10 * GEO.EPS_SMALL then
Mortising.CloneStepsLongitudinal = MachiningLib.GetMachiningSteps( dLongitudinalStepSpan, TOOLS[Mortising.nToolIndex].dThickness)
Mortising.CloneStepsLongitudinal = MachiningLib.GetMachiningSteps( true, dLongitudinalStepSpan, TOOLS[Mortising.nToolIndex].dThickness)
else
Mortising.CloneStepsLongitudinal.nCount = 1
Mortising.CloneStepsLongitudinal.dStep = dPocketHeight
end
-- lunghezza lavorata
-- TODO per il calcolo della dLenghtOnX ripetere il calcolo del FACEBYBLADE con proiezione del lato; serve prolungare con la Add Length secondo la vtEdgeDirection
-- TODO per il calcolo della dlengthOnX ripetere il calcolo del FACEBYBLADE con proiezione del lato; serve prolungare con la Add Length secondo la vtEdgeDirection
-- TODO fare funzione EstimatePathLength o simile
Mortising.dLengthToMachine = Mortising.dEdgeLength + Mortising.LeadIn.dStartAddLength + Mortising.LeadOut.dEndAddLength
Mortising.dLengthOnX = abs( dLengthToMachine * EdgeToMachine.vtN:getY())
+25 -12
View File
@@ -4,8 +4,9 @@
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local PreSimulationLib = require('PreSimulationLib')
-- Tabella per definizione modulo
local FACEBYMILL = {}
@@ -119,6 +120,10 @@ local function CalculateLeadInOut( Machining, EdgeToMachine, bIsSplitFeature)
LeadIn.dStartAddLength = BeamData.CUT_EXTRA
LeadOut.dEndAddLength = BeamData.CUT_EXTRA
end
-- punti dell'attacco
LeadIn.ptPoint = EdgeToMachine.ptStart - EdgeToMachine.vtEdge * ( LeadIn.dStartAddLength + LeadIn.dTangentDistance) + EdgeToMachine.vtN * ( EdgeToMachine.dElevation - Machining.dDepthToMachine + LeadIn.dPerpDistance)
LeadOut.ptPoint = EdgeToMachine.ptEnd + EdgeToMachine.vtEdge * ( LeadOut.dEndAddLength + LeadOut.dTangentDistance) + EdgeToMachine.vtN * ( EdgeToMachine.dElevation - Machining.dDepthToMachine + LeadOut.dPerpDistance)
-- stima lunghezza reale attacchi per calcolo lunghezza lavorata
local dEstimatedLeadInPerpDistance = 0
local dEstimatedLeadInTangentDistance = 0
@@ -203,9 +208,8 @@ function FACEBYMILL.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPara
else
Milling.vtToolDirection = EdgeToMachine.vtN
end
Milling.vtEdgeDirection = EdgeToMachine.vtN ^ FaceToMachine.vtN
-- TODO conviene spostare questi calcoli nel FaceData?
Milling.ptEdge1, _, Milling.ptEdge2 = EgtSurfTmFacetOppositeSide( Proc.id, FaceToMachine.id, -Milling.vtToolDirection, GDB_ID.ROOT)
Milling.vtEdgeDirection = Vector3d( EdgeToMachine.vtEdge)
Milling.ptEdge1, Milling.ptEdge2 = EdgeToMachine.ptStart, EdgeToMachine.ptEnd
-- se si conosce il limite downUp (utensile forzato o downUp forzato) si decide se invertire (ToolInvert)
if nToolIndex and not dMinNzDownUp then
@@ -251,7 +255,7 @@ function FACEBYMILL.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPara
Milling.sMessage = 'Mill not found'
Milling.bIsApplicable = false
EgtOutLog( Milling.sMessage)
return Milling, EdgeToMachine.dElevation
return Milling
end
-- verifica dimensioni tasca compatibili
@@ -260,7 +264,7 @@ function FACEBYMILL.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPara
Milling.sMessage = 'Pocket too narrow for blade thickness'
Milling.bIsApplicable = false
EgtOutLog( Milling.sMessage)
return Milling, EdgeToMachine.dElevation
return Milling
end
-- se tasca chiusa da entrambi i lati e più stretta della fresa la lavorazione non è applicabile
if not ( EdgeToMachine.bIsStartOpen or EdgeToMachine.bIsEndOpen) then
@@ -268,7 +272,7 @@ function FACEBYMILL.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPara
Milling.sMessage = 'Pocket too narrow for blade diameter'
Milling.bIsApplicable = false
EgtOutLog( Milling.sMessage)
return Milling, EdgeToMachine.dElevation
return Milling
end
end
@@ -325,13 +329,11 @@ function FACEBYMILL.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPara
Milling.dCompletionPercentage = ( 1 - Milling.dResidualDepth / Milling.dDepthToMachine) * 100
-- step verticale e offset longitudinale
if OptionalParameters.dPocketHeight then
Milling.Steps = MachiningLib.GetMachiningSteps( dPocketHeight, TOOLS[Milling.nToolIndex].dMaxMaterial)
Milling.Steps = MachiningLib.GetMachiningSteps( true, dPocketHeight, TOOLS[Milling.nToolIndex].dMaxMaterial)
Milling.Steps.nStepType = OptionalParameters.nStepType or MCH_MILL_ST.ONEWAY
Milling.dMaxElev = Milling.Steps.dStep * Milling.Steps.nCount - 10 * GEO.EPS_SMALL
else
Milling.Steps = {}
Milling.Steps.dStep = TOOLS[Milling.nToolIndex].dStep
Milling.Steps.nCount = ceil( ( FaceToMachine.dElevation - 50 * GEO.EPS_SMALL) / Milling.Steps.dStep)
Milling.Steps = MachiningLib.GetMachiningSteps( false, FaceToMachine.dElevation, TOOLS[Milling.nToolIndex].dStep)
Milling.Steps.nStepType = OptionalParameters.nStepType or MCH_MILL_ST.ZIGZAG
Milling.dMaxElev = FaceToMachine.dElevation
end
@@ -368,13 +370,24 @@ function FACEBYMILL.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalPara
dRadialStepSpan = Milling.dDepthToMachine
end
if dRadialStepSpan > 10 * GEO.EPS_SMALL and TOOLS[Milling.nToolIndex].dSideStep then
Milling.CloneStepsRadial = MachiningLib.GetMachiningSteps( dRadialStepSpan, TOOLS[Milling.nToolIndex].dSideStep)
Milling.CloneStepsRadial = MachiningLib.GetMachiningSteps( true, dRadialStepSpan, TOOLS[Milling.nToolIndex].dSideStep)
else
Milling.CloneStepsRadial.nCount = 1
Milling.CloneStepsRadial.dStep = 0
end
-- approccio e retrazione
Milling.LeadIn, Milling.LeadOut = CalculateLeadInOut( Milling, EdgeToMachine, bIsSplitFeature)
-- check finecorsa nei punti di attacco
PointsOnToolTipCenter = {
PreSimulationLib.GetPointOnToolTipCenter( Milling.LeadIn.ptPoint, FaceToMachine.vtN, FaceToMachine.vtN, EdgeToMachine.vtN, TOOLS[Milling.nToolIndex]),
PreSimulationLib.GetPointOnToolTipCenter( Milling.LeadOut.ptPoint, FaceToMachine.vtN, FaceToMachine.vtN, EdgeToMachine.vtN, TOOLS[Milling.nToolIndex])
}
local bOutOfStroke = PreSimulationLib.CheckOutOfStrokeFromPoints( PointsOnToolTipCenter, FaceToMachine.vtN, Milling.nSCC, TOOLS[Milling.nToolIndex])
if bOutOfStroke then
Milling.sMessage = 'Out of stroke'
Milling.bIsApplicable = false
return Milling
end
-- lunghezza lavorata
-- TODO per il calcolo del dLengthOnX si deve correggere con allungamento / accorciamento percorso
Milling.dLengthToMachine = EdgeToMachine.dLength + Milling.LeadIn.dStartAddLength + Milling.LeadOut.dEndAddLength
+8 -1
View File
@@ -9,6 +9,7 @@ require( 'EgtBase')
-- Carico i dati globali
local FeatureLib = require( 'FeatureLib')
local BeamLib = require( 'BeamLib')
-- strategie di base
local BladeToWaste = require('BLADETOWASTE')
@@ -31,7 +32,13 @@ function SPLITCUT.GetMachining( Proc, Part, ParametersFromStrategy)
else
-- Blade
Machining, Result = BladeToWaste.Make( Proc, Part, ParametersFromStrategy)
if Machining and #Machining > 0 then
-- se taglio non riuscito, si riprova con il riduci percorso forzato (collisione possibile in separazione pezzi alti)
if ( not Machining) or ( #Machining == 0) then
local NewParametersFromStrategy = BeamLib.TableCopyDeep( ParametersFromStrategy)
NewParametersFromStrategy.bReduceBladePath = true
Machining, Result = BladeToWaste.Make( Proc, Part, NewParametersFromStrategy)
end
if Machining and ( #Machining > 0) then
Machining.sTypeMachining = 'Blade'
end
-- TODO : casi con motosega da completare
+2 -2
View File
@@ -2,5 +2,5 @@
-- Gestione della versione di Beam
NAME = 'Beam'
VERSION = '2.6d1'
MIN_EXE = '2.6g1'
VERSION = '2.8a1'
MIN_EXE = '2.7j2'