795 Commits

Author SHA1 Message Date
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
andrea.villa 6ce4af9884 I parametri generici BTL non è detto che ci siano, quindi bisogna controllare se effettivamente siano stati impostati 2025-10-29 14:58:37 +01:00
andrea.villa fa36c51de0 - Corretto ID strategia STR0015
- Paramtri generali sono pre-processati quindi si deve controllare che non siano nil, perchè potrebbero esserci, ma essere falsi
2025-10-29 13:11:53 +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
andrea.villa dd0b39df71 Settato il gruppo temporaneo come effettivamente temporaneo per evitare che venga salvato 2025-10-27 16:55:32 +01:00
andrea.villa ee54c32918 Migliorata gestione del gruppo temporaneo. DA RIVEDERE! 2025-10-27 16:39:28 +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
andrea.villa 746eb9efe9 - Creazione gruppo temporaneo (da riportare)
- Riconoscimento Topologico SawCut se attraversa la trave (da riportare)
- Dati di pinzaggio feature spostato in STR0012
2025-10-24 17:10:22 +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
andrea.villa fac9fd8877 Piccole modifiche per demo 2025-10-24 11:46:41 +02:00
andrea.villa 28696ff4e5 Merge branch 'develop' into SOLO_DEMO 2025-10-23 12:57:23 +02:00
andrea.villa befc942be8 Corretto controllo parametri configurabili strategia in caso di feature forzata 2025-10-23 12:56:58 +02:00
andrea.villa 334680d3d6 Revert modifica fatta su strategia STR0002 2025-10-23 10:42:58 +02:00
andrea.villa a3a29dc5bf - Feature taglio di testa e coda rinominate con 'StartCut' e 'EndCut'
- Migliorata gestione tagli testa e coda
- Log result scrivono indici dettagliati per voto feature
- Piccole sistemazioni varie
2025-10-23 10:15:42 +02:00
andrea.villa 50336bfad6 - in BCS aggiunta strategia STR0005 per feature 0-20
- modifiche a lunghezza non pinzabile
- in STR0002 se svuotatura su faccia tunnel, lavorazione è considerata ora completa, ma si abbassa qualità
2025-10-22 10:44:48 +02:00
andrea.villa 9c4fab2d3c Aggiunte immagini per mostrare topologia in configurazione strategie 2025-10-21 15:29:42 +02:00
andrea.villa 00eeb482dd - dMaxWasteLength, dMaxWasteVolume, bReduceBladePath diventano parametri generali
- SPLITCUT chiama BladeToWaste in caso di taglio con lama ( Motosega e casi speciali ancora da gestire)
- HEADCUT e TAILCUT adeguate a nuovo funzionamento SPLITCUT
2025-10-21 09:40:19 +02:00
andrea.villa 83ab68b075 Merge branch 'NewHeadTailCut' into develop 2025-10-20 10:34:16 +02:00
andrea.villa 66b273354e Tagli testa e coda si riconoscono da topologia e non più da Prc=340/350 2025-10-20 10:33:35 +02:00
andrea.villa 5c41793b70 Merge remote-tracking branch 'origin/develop' into NewHeadTailCut 2025-10-20 08:26:27 +02:00
luca.mazzoleni bc40db6a6e Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2025-10-16 18:57:00 +02:00
luca.mazzoleni c0cab77689 - in BLADETOWASTE peggioramento tempo cubetti portato a 2 2025-10-16 18:56:55 +02:00
andrea.villa d7fac47297 Piccola modifica al log con scrittura del rating con 1 decimale. Il rating non è più un intero 2025-10-16 16:08:12 +02:00
luca.mazzoleni c8431a4584 - in BLADEKEEPWASTE codolo solo da un lato 2025-10-15 19:01:04 +02:00
luca.mazzoleni 232a112036 - in FeatureLib.GetFeatureSplittingPoints messa una pezza nel caso di pezzi corti (i punti uscivano dal pezzo). Da sistemare 2025-10-15 18:46:53 +02:00
luca.mazzoleni 58a98231ad - a FeatureLib.NeedTopologyFeature si passa anche il Part
- aggiunta gestione SawCut 1 faccia, troncante
2025-10-15 17:45:49 +02:00
luca.mazzoleni b3bf317780 - in BLADETOWASTE piccola correzione 2025-10-15 16:36:32 +02:00
luca.mazzoleni f9b62f4026 Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2025-10-15 16:22:57 +02:00
luca.mazzoleni f304df4d5b - in BLADETOWASTE corretta ghigliottina in DownUp 2025-10-15 16:22:19 +02:00
andrea.villa 2d2b492fd0 In STR0002 svuotatura, corretta lettura direzione utensile in lavorazione 2025-10-15 15:41:24 +02:00
luca.mazzoleni 01d4ac1c27 - in BLADETOWASTE si fanno tagli a ghigliottina anche in DownUp
- in STR0005 attivati di default tagli ridotti e veloci. Andrà rimesso a false quando funzionerà la lettura del json
2025-10-15 15:32:18 +02:00
andrea.villa 69f9669a5c Prime modifiche nuova gestione tagli testa e coda 2025-10-15 08:26:27 +02:00
luca.mazzoleni 1ac003c57c - in HEADCUT si scrive sStage per l'ordinamento, erroneamente rimosso 2025-10-14 13:10:36 +02:00
andrea.villa 3b59b8f37a In caso si lasci il codolo, non si considera riduzione pinzaggio testa e coda. 2025-10-14 10:55:57 +02:00
luca.mazzoleni 415e539e71 - in STR0005 e BLADETOWASTE aggiunto bAllowFastCuts per scegliere il lato a minore elevazione invece di quello che permette la qualità migliore 2025-10-13 18:42:28 +02:00
luca.mazzoleni ac774c2e2f Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2025-10-13 17:52:45 +02:00
luca.mazzoleni 716ebf7046 - in FaceData si calcolano i MainEdges solo per le facce che hanno esattamente 4 lati
- in STR0005 corretto calcolo dExtendAfterTail
- in FACEBYBLADE si i tagli troncanti in coda sono sempre dichiarati AfterTail; eliminata assegnazione a posteriori in BLADETOWASTE
2025-10-13 17:52:39 +02:00
andrea.villa 677e11d1e2 In STR0002 per decidere quale utensile utilizzare in svuotatura si controllano prima i MainEdges, altrimenti i lati del minimo rettangolo (poco preciso, sarà da rivedere) 2025-10-13 17:00:20 +02:00
andrea.villa 911113e853 - Migliorato calcolo tempo per rating strategia/soluzione
- 'dTimeToMachine' ora obbligatorio nei Result (da sistemare tutte le strategie)
- Piccola modifica ai nomi delle variabili, qualità e completamento diventano double e non più interi
- Riduzione numero scelte in parametri generici
2025-10-10 11:56:51 +02:00
andrea.villa f7462a47f4 Merge branch 'GeneralParameter' into develop 2025-10-09 11:03:00 +02:00
andrea.villa 810bf4f7ab Modificate funzioni per lettura e gestione parametri generali 2025-10-09 08:33:52 +02:00
luca.mazzoleni 20b9da785e - in BLADETOWASTE e FACEBYBLADE correzioni per tagli con riduzione percorso 2025-10-08 12:45:37 +02:00
andrea.villa 738b2af502 Nuova JSON dei parametri generali (FUNZIONI DA FARE), non esiste più distinzione PROJECT/BTL/PIECE, ma tutti i parametri sono settabili a tutti i livelli 2025-10-08 11:53:01 +02:00
andrea.villa 0f4f245827 In GetPieceGeneralParameters si leggono parametri forzati su pezzo 2025-10-06 10:43:53 +02:00
andrea.villa ddbbc894fd - Lettura parametri globali PROJECT e BTL
- Possibilità di leggere più file BTLInfo
- Creata funzione GetPieceGeneralParameters (DA FARE) per aggiornamento parametri su pezzo
2025-10-03 17:14:10 +02:00
andrea.villa a508b4bb94 - Prima versione con gestione parametri generali
- Possibilità di aprire più configurazioni delle strategie
- Gestione parametri ereditati
- Nuovo JSON parametri generali
- Adeguamento strategie per gestione parametri generali
2025-10-03 11:15:17 +02:00
andrea.villa 1a14d156cf - Aggiunta ricerca utensile anche per UUID
- In BCS piccola modifica in caso di TAG "Cutting"
- Aggiunto parametro sStrategyName a TAILCUT e HEADCUT
2025-10-01 13:25:18 +02:00
andrea.villa cbb6e11515 Merge remote-tracking branch 'origin/RefactoringHeadCut' into develop 2025-09-29 12:35:28 +02:00
andrea.villa 4cc0b6e2b3 - HEADCUT ore chiama SPLITCUT in caso di PreCut e BLADETOWASTE per materiale residuo.
- Modifiche varie minori per gestire HEADCUT con librerie standard
2025-09-29 12:35:17 +02:00
andrea.villa 6fc055de57 Aggiornati parametri campo SubType 2025-09-29 08:13:02 +02:00
andrea.villa 29c2c461ac Merge branch 'STR0015_HeadCambProfile' into develop 2025-09-26 16:10:16 +02:00
andrea.villa e6d9060b80 - Aggiunta finitura spigoli con fresa
- In AvailableStrategyList STR0009 è stata sostituita dalla STR0015. STR0009 è riutilizzabile per altro.
2025-09-26 16:09:57 +02:00
andrea.villa 45bfcdbcfc - In STR0015:
- Corretta creazione faccia per sgrossare con lama
      - Corretto riconoscimento EdgeCorner da lavorare
      - Altre modifiche minori
- In FeatureLib aggiunto un nuovo indice completamento
- In BCS STR0009 è stata sostituita dalla STR0015
- In BCS lettura parametri Q per feature tipo intestatura, feature che lavoreranno con STR0015
2025-09-26 15:18:49 +02:00
andrea.villa 5f663d3362 - Prima versione pulizia corner con lama
- Funzione "FaceData.GetFacesInfo" accetta ora una lista di facce sulle quali calcolare le info, per evitare di calcolarle tutte in caso siano molte
- In "BCS.GetToolsFromMachDataFile", se lista tag vuota, si esce subito
2025-09-26 10:04:30 +02:00
andrea.villa b65a5b758b - In MachiningLib : Aggiunto parametro rotazione per ricerca utensile
- Gestione smussi completa
- Piccole modifiche calcolo Result strategia
2025-09-22 11:33:03 +02:00
andrea.villa 9ed6cf8c30 - Aggiunti smussi se intestatura orizzontale
- In BCS aggiunta lettura parametri Q
2025-09-19 16:51:35 +02:00
andrea.villa ed1de946c1 - Aggiunta possibilità di fare taglio di sgrezzatura con fresa
- Prima versione gestione Result
- Altre modifiche minori
2025-09-19 12:47:20 +02:00
andrea.villa aa543fdf2d Merge branch 'develop' into STR0015_HeadCambProfile 2025-09-19 12:45:09 +02:00
luca.mazzoleni a8f000fe75 Merge branch 'feature/Cuts2FacesLessThan90deg' into develop 2025-09-16 13:03:49 +02:00
andrea.villa edeb99bdb9 - In GetStrategyQuality rimossi stati lavorazione dettagliati, si utilizzano quelli aggregati.
- Adeguate strategia che utilizzavano i dati dettagliati
2025-09-16 10:11:56 +02:00
luca.mazzoleni c9dd712e70 Merge remote-tracking branch 'origin/develop' into feature/Cuts2FacesLessThan90deg 2025-09-15 17:58:23 +02:00
luca.mazzoleni b43eca9f27 - in BLADETOWASTE gestito il caso di feature concave < 90deg e piccoli aggiustamenti 2025-09-15 17:53:49 +02:00
andrea.villa 4215b3f5b0 Merge branch 'develop' into STR0015_HeadCambProfile 2025-09-15 14:44:51 +02:00
andrea.villa e1bce72db5 Nuova gestione qualità lavorazione unificata 2025-09-15 14:42:29 +02:00
andrea.villa 0290547a93 Merge branch 'STR0015_HeadCambProfile' into develop 2025-09-15 14:26:43 +02:00
andrea.villa d7c3bd83de - Aggiunto taglio sgrossatura
- Aggiunta passata di sgrossatura con fresa
- Nuovi parametri per completare la gestione
2025-09-12 17:51:49 +02:00
andrea.villa cb81dc1d15 - Lettura parametri Q
- Nuovi parametri configurabili
2025-09-12 11:33:32 +02:00
andrea.villa 8f2e10fc22 Merge remote-tracking branch 'origin/develop' into STR0015_HeadCambProfile 2025-09-09 09:56:31 +02:00
andrea.villa 9e2bef3192 - Si salvano su ogni faccia L e W
- In STR0002 si utilizzano dimensioni faccia anziché gli edge. Più affidabile in caso di feature non standard
2025-09-09 09:53:37 +02:00
andrea.villa d48d392c58 Primo commit per nuova strategia STR0015 per lavorazione profilo arcuato.
Strategia copiata da STR0009 come partenza
2025-09-08 16:07:19 +02:00
luca.mazzoleni dcf61e0442 in BLADETOWASTE -> CutWithDice correzione al calcolo cubetti nel caso in cui si tenta il taglio singolo 2025-09-08 15:34:24 +02:00
andrea.villa 3634af8f29 Si calcola faccia Tunnel anche per topologia Bevel-2-Blind 2025-09-08 14:47:43 +02:00
andrea.villa f84f0a6569 Aggiunta gestione nuova topologia, già riconosciuta, ma mai gestita nelle strategie: Bevel-2-Blind 2025-09-08 13:26:14 +02:00
andrea.villa 3836764c51 Merge branch 'STR0014_Marking' into develop 2025-09-05 13:15:47 +02:00
andrea.villa 51dec026ec - Completato strategia STR0014
- Migliorata gestione pezzo invertito
- Corretto problema scelta combinazione migliore
- In STR0001 corretto nome variabile
- In STR0011 (foro) cambiato messaggio warning in caso di lavorazione non completa
- In BLADETOWASTE se taglio troncante, si setta da fare dopo taglio coda
2025-09-05 13:14:50 +02:00
andrea.villa 3a4b29070e Prima versione funzionante STR0014 2025-09-04 11:46:50 +02:00
andrea.villa 1eb839fce4 Nuova strategia Markink 2025-09-03 16:02:01 +02:00
andrea.villa d642a5ebae Piccole correzioni STR0001 e STR0002 2025-09-03 15:39:37 +02:00
andrea.villa f459cf94b2 Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2025-09-03 09:15:06 +02:00
andrea.villa 0e4aeb49b8 - In STR0001 aggiunta lavorazione ti riduzione tenone in caso di P14>0
- Aggiornata gestione in BCS per Essetre
- Aggiunta funzione che verifica se un punto si trova su estremità box del pezzo
2025-09-03 09:15:02 +02:00
luca.mazzoleni dbe0a04434 update commenti 2025-09-01 15:05:36 +02:00
andrea.villa 7eff64d3bb Tutte le strategie standard tengono ora in considerazione le liste MachData con TAG per scelta utensile (per Essetre). Prima versione, da completare!
!!TODO : fare lo stesso anche nelle strategie di base quando si cercano utensili
2025-09-01 13:30:16 +02:00
andrea.villa 8e960954ef - Calcolo tempo lavorazione in strategie STR0001 e STR0006
- Modifiche minori per compatibilità nel calcolo tempo strategie precedenti
2025-09-01 12:10:19 +02:00
andrea.villa 70b4927fd2 - Migliorato recupero utensili Essetre in base a TAG
- Aggiunta lettura di qualche parametro Q di Essetre
- Piccole modifiche a strategie
2025-08-29 10:55:45 +02:00
andrea.villa 5a02c08965 Cambio nome funzione per identificare se feature foro 2025-08-27 17:10:47 +02:00
andrea.villa c6353aadc1 Merge branch 'QParamEssetre' into develop 2025-08-27 16:38:17 +02:00
andrea.villa 8e49d0afcc - In MachiningLib aggiunte funzioni per ricerca utensile nella lista passata anziché in tutta la tabella TOOLS
- In BCS aggiunte funzioni per recuperare lavorazioni attive dai file  *machining*Data.lua, per Essetre
- Per capire dove recuperare strategie e utensili si legge ora il nome della macchina. Il parametro STRATEGIES_SCRIPT poteva essere modificabile in quanto in chiaro
- STR0011 e STR0013 prevedono lettura lista utensili. ( Le altre strategie sono da fare!)
2025-08-27 16:37:41 +02:00
andrea.villa a0e595e58d La scelta utensile contempla la lista parziale passata alle funzioni Find(Tool) 2025-08-25 16:52:00 +02:00
andrea.villa 43aa2f1b3b - La lettura dei parametri configurabili strategia (salvati su NGE) sono stati spostati in CalculateStrategies, dopo che sono state decise le dipendenze
- Piccole correzioni minori
2025-08-25 13:21:43 +02:00
andrea.villa fca9eff9a7 Prima versione gestione lettura parametri Q per Essetre 2025-08-25 12:39:50 +02:00
andrea.villa af1a7b768d STR0013 : Corretto movimento uscita in foro eseguito con milling 2025-07-21 09:22:24 +02:00
luca.mazzoleni 0be9defb0f Merge branch 'feature/BetterCuts' into develop 2025-07-18 17:15:47 +02:00
luca.mazzoleni 814a0feefa Merge branch 'develop' into feature/BetterCuts 2025-07-18 17:01:22 +02:00
andrea.villa 8f7969d93f Merge branch 'STR0013_DrillWithMill' into develop 2025-07-18 17:00:25 +02:00
andrea.villa acf53145b4 Piccole modifiche dopo test 2025-07-18 16:59:38 +02:00
luca.mazzoleni caf8e5f144 - in BLADETOWASTE -> CutWholeWaste, in caso di taglio da due lati, si fa per ultima la lavorazione che va verso l'alto 2025-07-18 16:20:57 +02:00
andrea.villa 967df73f43 Prima versione semi-funzionante forature con fresa, ancora in fase di test 2025-07-18 15:51:00 +02:00
luca.mazzoleni bba5d13084 - in BLADETOWASTE -> CutWithDicing, nei tagli paralleli si usa la CutWholeWaste invece dei tagli standard, se possibile 2025-07-18 15:29:58 +02:00
luca.mazzoleni a15b5621c7 Merge branch 'develop' into feature/BetterCuts 2025-07-18 11:41:01 +02:00
luca.mazzoleni 6b0714ca36 Merge branch 'feature/BetterCuts' into develop 2025-07-18 11:36:14 +02:00
luca.mazzoleni f7a07e0cc1 - in BLADETOWASTE -> CutWithDicing e altre rimossi i riferimenti a EdgeToMachineAlternative, non usato 2025-07-18 11:35:50 +02:00
luca.mazzoleni ae3a0ef148 Merge branch 'develop' into feature/BetterCuts 2025-07-17 18:35:11 +02:00
luca.mazzoleni af971f70fc - in BLADETOWASTE aggiunto CutWholeWaste da due lati anche verticali (GetDualSideCutStrategy)
- in FACEBYBLADE correzione ai tagli ridotti
2025-07-17 18:34:31 +02:00
andrea.villa ed0098efef Merge remote-tracking branch 'origin/develop' into STR0013_DrillWithMill 2025-07-17 16:23:20 +02:00
andrea.villa a0d44ed1e4 -- Corretta gestione rotazioni in caso di feature da eseguire ma applicazione non andata a buon fine
- Piccole correzioni a STR0011
2025-07-17 16:23:01 +02:00
andrea.villa 3c1925ed29 Nuovo parametro configurabile 2025-07-17 16:20:34 +02:00
andrea.villa fd4e761c36 STR0013 - Nuova strategia, foratura con fresa.
Copiata da foratura con punta STR0011.
2025-07-17 13:04:54 +02:00
andrea.villa 232751fd5d In STR0011:
- aggiunta possibilità di forare da due lati
      - aggiunta gestione tolleranza su diametro foro
Altre piccole modifiche
2025-07-17 13:00:33 +02:00
luca.mazzoleni 69259e3f80 Merge branch 'develop' into feature/BetterCuts 2025-07-16 12:23:59 +02:00
luca.mazzoleni d72517df6b Merge branch 'develop' into feature/BetterCuts 2025-07-16 12:22:20 +02:00
luca.mazzoleni 719d3b61af - in BeamExec correzione a CalcMinUnloadableRaw
-in FaceData aggiunta IsFaceRhomboid per verificare se una faccia è un parallelogramma
- in BLADETOWASTE refactoring
- in BLADETOWASTE aggiunta gestione tagli da due lati, al momento solo caso con suddivisione orizzontale
- in FACEBYBLADE si permette OppositeToolDirection ottimizzata anche per parallelogrammi (prima era solo per rettangoli)
- in FACEBYBLADE correzione a tagli ridotti e ghigliottina in caso in cui non si lavori l'intera elevazione del lato
2025-07-16 12:22:07 +02:00
andrea.villa 5bbde3e60f Corretta gestione tagli testa/coda in caso di soluzione con pezzo invertito 2025-07-15 09:30:17 +02:00
luca.mazzoleni dc3d534cb4 Merge branch 'feature/BetterCuts' into develop 2025-07-14 17:25:47 +02:00
luca.mazzoleni a4c20cee6c - in BLADETOWASTE-> CompareEdgesTopHeadGuillotine ora sceglie di preferenza il lato sotto 2025-07-14 17:24:39 +02:00
andrea.villa fd070db4d0 Corretto inversione pezzo 2025-07-14 10:26:09 +02:00
luca.mazzoleni b27bb97e50 Merge branch 'develop' into feature/BetterCuts 2025-07-11 18:50:35 +02:00
luca.mazzoleni c5c45a8dd0 - bReduceBladePath disattivato di default nelle strategie che usano i tagli di lama
- in FACEBYBLADE la scelta ottimizzata dell'OppositeToolDirection viene fatta solo per le facce rettangolari
2025-07-11 18:49:42 +02:00
andrea.villa b298bd24e7 Controlli se taglio testa e coda fatti con Identify 2025-07-11 18:05:06 +02:00
luca.mazzoleni b0ca47880f Merge remote-tracking branch 'origin/develop' into feature/BetterCuts 2025-07-11 15:24:49 +02:00
luca.mazzoleni 6d9e987bc7 - piccola correzione in BLADETOWASTE 2025-07-11 15:24:37 +02:00
luca.mazzoleni 698e7d1639 - in BALDETOWASTE -> CutWholeWaste in caso di feature lunga si ritorna non applicabile 2025-07-11 15:08:21 +02:00
andrea.villa 8585797cc0 PROVVISORIO: rotazione rawpart anziché del pezzo. Da correggere non appena sistemata funzione di rotazione pezzo nel grezzo. 2025-07-11 14:04:32 +02:00
andrea.villa 4c5f620117 Dopo inversione pezzo si ricalcola il box del pezzo 2025-07-11 12:20:30 +02:00
luca.mazzoleni 87d39d747e - in json STR0005 cubetti riabilitati (disabilitati per errore) 2025-07-10 18:04:12 +02:00
luca.mazzoleni eb551742d1 Merge branch 'develop' into feature/BetterCuts 2025-07-10 17:38:18 +02:00
andrea.villa 188ddce206 - Aggiunta inversione pezzo
- Modificati Log
2025-07-10 17:37:30 +02:00
luca.mazzoleni 0825cc7a62 Merge branch 'develop' into feature/BetterCuts 2025-07-10 15:51:39 +02:00
luca.mazzoleni 6b2c267dfe - in FACEBYBLADE/MILL/CHAINSAW il parametro bOppositeToolDirection diventa OppositeToolDirectionMode (Enabled, Disabled, Optimized solo per blade); strategie modificate di conseguenza
- in FACEBYBLADE se OppositeToolDirectionMode = 'Optimized', la funzione sceglie se lavorare il lato in negativo per far combaciare concordanza e lavorazione verso l'alto
2025-07-10 15:51:03 +02:00
andrea.villa d51f2bc7d5 In Process e BatchProcess forzato flag bCalcBestPieceUnloadPosition a true per calcolo prerotazioni in attesa della gestione completa da parte di Aedifica 2025-07-10 12:53:34 +02:00
luca.mazzoleni 3d25ba23cc Merge remote-tracking branch 'origin/develop' into feature/BetterCuts 2025-07-10 09:03:59 +02:00
andrea.villa 48e449d85a Corretta gestione sovramateriale in testa e tra le travi in interfaccia 2025-07-09 18:30:03 +02:00
andrea.villa 2b634dbb96 Merge branch 'NewCoreRotationMatrix' into develop 2025-07-09 18:28:52 +02:00
andrea.villa 91dc770f92 Ripristinato (e corretto) calcolo rotazioni dopo separazione in caso la posizione iniziale sia una prerotazione. In realtà con nuovo metodo non esiste più la pre-rotazione, ma è stata ripristinata la gestione in caso in futuro debba servire ancora. 2025-07-09 16:20:08 +02:00
luca.mazzoleni 825d8596dd Merge branch 'develop' into feature/BetterCuts 2025-07-09 14:40:25 +02:00
andrea.villa e4b0955846 Corretto rotazioni e posizionamento iniziale 2025-07-09 11:49:22 +02:00
andrea.villa 0d5d97a58a Merge remote-tracking branch 'origin/develop' into NewCoreRotationMatrix 2025-07-08 18:05:04 +02:00
andrea.villa 8211fbc4b0 - Aggiunto FLAG = 10 per QUICK_VERIFY (ancora da fare)
- Gestione inversione pezzo solo se durante la fase di QUICK_VERIFY
- Gestione rotazioni ADVANCED, verrà utilizzata solo durante QUICK_VERIFY. In tutti gli altri casi è standard (come ha sempre funzionato) senza calcolo prerotazioni.
2025-07-08 18:03:04 +02:00
luca.mazzoleni f0e56275b9 Merge branch 'feature/BetterCuts' into develop 2025-07-08 17:49:40 +02:00
luca.mazzoleni 5af77cff10 - in FACEBYMILL correzione attacchi 2025-07-08 17:47:30 +02:00
luca.mazzoleni 1e4388c091 - in BLADETOWASTE.CompareEdgesTopHead si scelgono di preferenza i lati più verticali
- in tutte le strategie che contemplano la lama gestita bReduceBladePath come parametro strategia
2025-07-08 12:29:03 +02:00
andrea.villa 702d4617a0 - Calcolo strategie spostato in funzione dedicata
- Migliorato ciclo di calcolo in GetBestResultFromCombinationsMatrix
- Rimossi cicli per ricominciare il calcolo in caso di errore (non erano funzionanti e non compatibili con prossime modifiche rifacimento core)
2025-07-07 18:37:36 +02:00
luca.mazzoleni 6adb856b7a - in STR0005 aggiunto parametro bDisableDicing (valutare se nascondere all'utente o unificare a CUTTING_STRATEGY) per disabilitare i cubetti
- in BLADETOWASTE introdotta gestione lati separata per ghigliottina; gestitobDisableDicing
2025-07-07 16:56:24 +02:00
luca.mazzoleni e155fee802 Merge branch 'feature/BetterCuts' into develop 2025-07-04 18:15:09 +02:00
luca.mazzoleni 792cb4feb4 - correzioni in tagli ridotti e a ghigliottina 2025-07-04 18:14:37 +02:00
luca.mazzoleni 0d981a3d4f - correzioni per taglio a ghigliottina 2025-07-04 17:40:27 +02:00
luca.mazzoleni fdb4bd405e - in STR0005 si passa correttamente il parametro bReduceBladePath a BLADETOWASTE
- in FACEBYBLADE si assegna correttamente dGuillotineLengthToMachine
2025-07-04 16:29:17 +02:00
luca.mazzoleni 4edd45a355 Merge remote-tracking branch 'origin/develop' into feature/BetterCuts 2025-07-04 16:21:25 +02:00
luca.mazzoleni 4a9db5d986 - in BLADETOWASTE e FACEBYBLADE implementato taglio ridotto e a ghigliottina, solo per facce rettangolari
- in FaceData introdotta funzione IsFaceRectangular
- in STR0005 aggiunto il parametro bReduceBladePath (gestito in BLADETOWASTE)
2025-07-04 16:20:45 +02:00
andrea.villa 5f06b160b9 - BasicCustomerStrategies Egalware sono lette ora da JSON. Quelle Essetre restano nel lua.
- Corretta formattazione AvailableStrategyList.json
2025-07-03 15:35:00 +02:00
luca.mazzoleni c7b3668418 - in FACEBYBLADE se feature spezzata si forza attacco perpendicolare
- in STR0005 e BLADETOWASTE l'esclusione per lato in comune troppo lungo si fa solo se rabbet
2025-05-26 16:39:37 +02:00
andrea.villa 05cc611dae - Piccole modifiche strategia STR0011 (foro)
- Aggiunta a AvailableStrategyList strategia per Feature 102
2025-05-23 16:05:29 +02:00
andrea.villa 56ad7bb04c - Quando si leggono strategia da JSON, si fa copia della tabella 2025-05-23 15:30:12 +02:00
andrea.villa a772113107 - Correzioni varie per compatibilità con lettura file JSON di configurazione
- In GetBestStrategy si fa copia della tabella che prima era passata come riferimento
2025-05-23 14:55:26 +02:00
andrea.villa 97dfd6f2e1 Corretto messaggio in strategia 2025-05-23 11:57:03 +02:00
andrea.villa d580a0fe08 Aggiunta gestione nuova feature 1/0-80 2025-05-23 09:21:12 +02:00
luca.mazzoleni bbd5c67f65 - in BatchProcessNew correzione
- in STR0002 aggiunta OpenMinSafe
2025-05-22 18:58:04 +02:00
andrea.villa cff6dbcd7b Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2025-05-22 17:45:12 +02:00
andrea.villa ee39724618 In svuotatura, si crea lavorazione con apposita funzione 2025-05-22 17:45:06 +02:00
luca.mazzoleni 85f14504aa - modificato gitignore e aggiunto compile 2025-05-22 17:30:07 +02:00
luca.mazzoleni 564a17fb35 - in BatchProcessNew gestito flag 8 CHECK_NOSIM per check senza simulazione; GET_TOPOLOGY diventa 9 2025-05-22 15:40:02 +02:00
luca.mazzoleni 27e900c944 Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2025-05-22 10:48:54 +02:00
luca.mazzoleni 7a27212cb8 - in BeamExec.CollectFeatures si salva la rotazione in cui è stata costruita la Proc
- in BasicCustomerStrategies correzione in lettura Q
- in STR0002 in caso di 2 facce > 90° si lavorano sempre entrambe
2025-05-22 10:48:48 +02:00
andrea.villa 5b10e28f07 Aggiunto nuovo campo "sStrategyName" alle strategie per nome visualizzato in BeamWall 2025-05-22 09:09:30 +02:00
luca.mazzoleni eb05b74a44 - aggiornate AvailableStrategies 2025-05-21 17:05:28 +02:00
luca.mazzoleni ff8a753d65 - in STR0010 corretto caso DoubleBevel 2025-05-21 16:22:14 +02:00
luca.mazzoleni af761c95bf - in BeamExec corretto nome variabile che identifica il BeamWall
- in BLADETOWASTE e STR0005 aggiunto controllo cubetti troppo lunghi in X
2025-05-21 14:07:27 +02:00
andrea.villa 970fb60d66 - Aggiunto NestProcess per ottimizzazione pezzi nelle barre
- Aggiunto tabella NotClampableLength su nuovo pezzo
2025-05-21 12:11:34 +02:00
andrea.villa 3aecde91b9 - Strategia STR0010 ora gestisce topologia Rabbet-2-Through
- STR0002 setta SCC solo verso Y+/-. Da migliorare.
2025-05-21 10:04:44 +02:00
luca.mazzoleni 05dfa1da6c - in FaceData e STR0002 gestito tunnel per topologie a 1 faccia con qualunque inclinazione 2025-05-21 01:47:43 +02:00
luca.mazzoleni e2532b29f6 - modificate STR0002 e FaceData per lavorare facce tunnel per Bevel-1-Through con vtNY o vtNZ = 0 2025-05-20 19:26:56 +02:00
andrea.villa 9d961977b2 HCING e TCING della fase precedente alla separazione vengono comunque scritti equivalenti a quelli dopo la separazione 2025-05-20 17:58:05 +02:00
andrea.villa 8c95d5d27e In BeamLib.AddPhaseWithRawParts, si passa direttamente l' idRaw 2025-05-20 17:29:42 +02:00
andrea.villa b4a1df8110 Piccola correzionein caso di feature non lavorabile durante calcolo matrice 2025-05-20 17:14:25 +02:00
andrea.villa da7d3cc08f Se la feature potrebbe essere lavorata, ma ciò non è possibile a causa della posizione e dalla presenza di altre feature (ad esempio due feature che impattano sulla testa che non possono essere lavorate nella stessa fase) , viene settato flag a zero 2025-05-20 16:20:23 +02:00
luca.mazzoleni 1739634c58 - in BLADETOWASTE - cubetti si moltiplicano per 1.3 i tempi per stimare anche i movimenti testa e i passaggi tra una lavorazione e l'altra 2025-05-20 16:00:35 +02:00
andrea.villa fd4de3742f Merge branch 'HCINGTCING' into develop 2025-05-20 15:45:04 +02:00
andrea.villa cdfebf83fb Completata gestione scrittura dati nelle info del DISP 2025-05-20 15:44:32 +02:00
luca.mazzoleni d3a4ff1cd3 - in BatchProcessNew correzione 2025-05-20 12:55:35 +02:00
luca.mazzoleni 861384b5bb - in BatchProcessNew piccola correzione al caso FLAG = 6
- in STR0012 RidgeLap si taglia la faccia aggiuntiva solo se non corrisponde al taglio di testa o coda
2025-05-20 12:51:20 +02:00
luca.mazzoleni e1b4089bfc - in BatchProcessNew si scrive Json risultati 2025-05-20 11:57:07 +02:00
luca.mazzoleni 3198287dfe - modifiche parziali per scrittura ingombri su disposizione 2025-05-20 11:16:40 +02:00
luca.mazzoleni f947f761f1 - in BLADETOWASTE corretto affondamento nel caso di cubetti per feature 2 facce 2025-05-19 18:51:28 +02:00
luca.mazzoleni 9eeccf67a0 - RidgeLap usa strategia STR0012 solo se 3 facce; 1 o 2 passano dalle strategie standard
- BasicCustomerStrategies e AvailableStrategies modificate di conseguenza
- in STR0012 correzioni varie
2025-05-19 18:22:10 +02:00
luca.mazzoleni 0a1c658b20 Merge branch 'feature/STR0012_RidgeLap' into develop 2025-05-19 17:46:50 +02:00
luca.mazzoleni a1f8339724 Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2025-05-19 17:46:25 +02:00
luca.mazzoleni 13f73a5363 - da FaceData.GetFacesInfo rimossa EgtSurfTmResetTwoColors e spostata in Logs.WriteMainFacesLog 2025-05-19 17:46:20 +02:00
luca.mazzoleni dd40555bbe - correzioni per RidgeLap; da sistemare profondità taglio cubetti e mancata scrittura indice in RESULT 2025-05-19 17:44:54 +02:00
andrea.villa d9e2bdb44a - In STR0001 e STR0006 per lavorazione tenone, settato funzioni come locali
- In STR0009 gestione CanMoveAfterSplit
2025-05-19 16:24:15 +02:00
luca.mazzoleni 19ce519fa6 Merge branch 'develop' into feature/STR0012_RidgeLap 2025-05-19 15:08:36 +02:00
luca.mazzoleni edf030367e - introdotta STR0012 per RidgeLap, da completare e testare 2025-05-19 15:08:12 +02:00
andrea.villa 691fbc516e Corretta creazione lavorazione di base tipo Drilling 2025-05-19 15:03:57 +02:00
andrea.villa cc066f9b4f Merge branch 'STR0011_Drilling' into develop 2025-05-19 14:48:33 +02:00
andrea.villa 7ee7b63224 Prima versione funzionante foratura. Per ora gestisce solo lavorazione con punta a forare 2025-05-19 14:47:45 +02:00
luca.mazzoleni 927550f438 - in FeatureLib IsFeatureCuttingEntireSection e IsFeatureCuttingEntireLength si usa sempre il box del pezzo
- aggiornato AvailableStrategyList
2025-05-19 12:28:17 +02:00
andrea.villa 41e70ccbd4 Creazione STR0011, strategia per foratura 2025-05-19 09:03:11 +02:00
Emmanuele Sassi e0d1a2905d - in BatchProcessNew correzioni per il funzionamento del Flag 7
- in BeamExec lettura JSON modifiche per allineamento con interfaccia. Il nome del JSON al momento  si legge da BeamData ma andrà modificato
2025-05-17 12:53:47 +02:00
luca.mazzoleni cfc2260997 - in BatchProcessNew aggiunto flag 7 per la restituzione della topologia
- in FeatureLib IsFeatureCuttingEntireSection e IsFeatureCuttingEntireLength se non c'è il box del grezzo si usa quello della parte
2025-05-17 11:13:53 +02:00
luca.mazzoleni e12fd6824e - in STR0002 modifiche per topologia Cut 2025-05-17 08:44:09 +02:00
luca.mazzoleni 48aa1477f1 - in STR0002 correzione 2025-05-16 17:44:03 +02:00
andrea.villa 060b919f5b Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2025-05-16 16:18:51 +02:00
andrea.villa dd7c98229c - Aggiunto offset tavola per permettere rotazioni
- Cambio nome da RotatePart a RotateRawPart perchè in effetti viene ruotato il grezzo e non il pezzo
2025-05-16 16:18:45 +02:00
luca.mazzoleni 8d8f66fd77 - in BeamLib.Is3EdgesApprox tolleranza portata a 5 (era 15 mm)
- in DiceCut piccola correzione
2025-05-16 14:35:31 +02:00
andrea.villa 8a127f39ee In STR0007, corretto Offset per antischeggia su mortasa a coda di rondine 2025-05-16 11:27:11 +02:00
luca.mazzoleni d9665b4ca9 - in funzioni GetMinNzDownUp si passa anche Tool
- in MainFaces correzioni per casi convessi
2025-05-16 11:22:47 +02:00
andrea.villa d46b466f71 In STR0002 prima versione gestione SCC 2025-05-16 09:16:49 +02:00
luca.mazzoleni 10aa2352ae Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2025-05-15 19:00:30 +02:00
luca.mazzoleni fb59349345 - in BeamExec di default si attiva la modalità di rotazione avanzata
- in tutte le funzioni GetMinNz, GetMaxNz, GetMinNzDefault, GetMaxNzDefault si passa anche Tool (per discriminare il tipo utensile in macchina)
- in FaceData si settano le MainFaces e i MainEdges anche per DoubleBevel
- in STR0001 (TenonDT) si controlla la ResidualDepth
- in BLADEKEEPWASTE escluso il caso di Rabbet passante lungo X
2025-05-15 19:00:26 +02:00
andrea.villa 03e37702e6 - In FACEBYMILL aggiunto parametro StepType
- STR0010 gestisce ora nuove topologie
- Modificata scelta strategie, se enrambe incomplete, predilige quella con più feature complete
- Corretta gestione feature da saltare perchè sostituta da altra. Prima la segnava come incompleta
2025-05-15 17:14:59 +02:00
luca.mazzoleni 957269abf1 - in DoubleCutAbilitata STR0005 (lama)
- in FAEBYBLADE e FACEBYMILL si scrive EdgesFaceUse per la scelta precisa del lato
- per EdgesFaceUse, modificate MachiningLib.AddOperations e BLADETOWASTE.CutWithDicing
2025-05-14 18:52:57 +02:00
luca.mazzoleni 4aae1dbb54 Merge remote-tracking branch 'origin/develop' into develop 2025-05-14 16:20:40 +02:00
andrea.villa 607a3e61af Piccole modifiche alle strategie 2025-05-14 16:16:32 +02:00
luca.mazzoleni 717dca1089 - in MachiningLib.GetTimeToMachineAllStepsWithLeadInOut migliorato calcolo tempi svuotatura 2025-05-14 14:45:09 +02:00
luca.mazzoleni 4b49ebad7f - STR0002 (svuotatura) riabilitata per taglio longitudinale
- in MachiningLib.GetTimeToMachineAllStepsWithLeadInOut migliorato calcolo tempi svuotatura
2025-05-14 14:44:44 +02:00
andrea.villa ca95265ee9 - Aggiunta topologia VGroove a strategia svuotatura
- Migliorie lavorazione tenone
2025-05-14 09:09:39 +02:00
luca.mazzoleni 53fb0bdf0d Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2025-05-09 16:03:34 +02:00
luca.mazzoleni 340345725f - in BeamExec corretta eliminazione geometrie temporanee
- in MachiningLib.GetTimeToMachineAllStepsWithLeadInOut i tempi di svuotatura ora sono precisi (si usa EgtPocketing)
2025-05-09 16:03:30 +02:00
andrea.villa 0c0f6cf73b Aggiunta descrizione messaggi parametri personalizzabili da strategia 2025-05-09 14:41:16 +02:00
luca.mazzoleni 24245e8bd6 - in FaceData.GetEdgesInfo si scrive l'id del lato
- in MachiningLib.GetTimeToMachineAllStepsWithLeadInOut refactoring che utilizza FaceData
2025-05-09 10:40:12 +02:00
luca.mazzoleni a1528576b9 Merge branch 'STR0002_TimeEstimation' into develop 2025-05-08 19:01:34 +02:00
luca.mazzoleni e584c90c71 - in MachiningLib.GetTimeToMachineAllStepsWithLeadInOut migliorato calcolo per svuotature (ancora da milgiorare)
- in STR0002 correzioni
- in FACEBYBLADE piccola correzione nel calcolo LeadIn/Out
2025-05-08 19:01:15 +02:00
luca.mazzoleni 3b785a0907 - in MachiningLib.GetTimeToMachineAllStepsWithLeadInOut contemplata Pocketing
- in STR0002 modifiche per migliorare il calcolo tempi
2025-05-08 17:55:10 +02:00
andrea.villa 4cd1bf526a - Corretto STR0010 in caso non abbia trovato la lavorazione
- Corretto calcolo step in FACEBYMILL
- In BLADEKEEPWASTE corretto calcolo completamento nel caso in sui non c'è il peso sulla lavorazione
2025-05-08 11:33:11 +02:00
andrea.villa 86bb2e6651 Merge branch 'STR0010_BevelWithMilling' into develop 2025-05-08 09:11:30 +02:00
andrea.villa 9dbee99eca - Strategia semplificata. Ora contempla solo topologia 'Bevel'
- Correzione calcolo LeadIn/Out in FACEBYMILL
- Corretto reset strategia caricata come libreria
2025-05-08 09:07:57 +02:00
luca.mazzoleni db231be6ed Merge branch 'STR0002_DoubleCut' into develop 2025-05-07 18:50:56 +02:00
luca.mazzoleni f5638e522f - per T010, L010 e T11 abilitata STR0002 (svuotatura)
- in FaceData.GetMainFaces gestita DoubleBevel
- in STR0002 gestita topologia DoubleBevel-2-Through e topologie 1 faccia (Bevel, Cut) - TEMPI NON OK DA SISTEMARE
- in STR0005 si restituisce anche TimeToMachine
- in FABYBLADE e FACEBYMILL piccola correzione in calcolo LeadIn/Out
2025-05-07 18:50:46 +02:00
andrea.villa 1cce5ca69a - Primo commit strategia STR0010 (non funzionante)
- Altre modifiche irrilevanti
2025-05-07 12:34:29 +02:00
luca.mazzoleni 037e07921c - in FACEBYBLADE implementata funzione calcolo SCC migliore. Da gestire casi split e da implementare funzione specifica per ogni macchina 2025-05-06 18:35:27 +02:00
luca.mazzoleni 95fdb3a250 - in FACEBYBLADE piccola correzione agli attacchi 2025-05-06 18:33:39 +02:00
luca.mazzoleni 1ef1c22337 - in geometrie AddGroup aumentata trasparenza
- in DiceCut le superifici create non hanno un colore specifico (prendono quello dell'AddGroup come le altre)
- in TAILCUT corretto box da passare alla cubettatura (ora è il grezzo attuale unito a quello di coda successivo)
- in FACEBYBLADE.GetLeadInOutType migliorata scelta attacco
2025-05-06 16:45:01 +02:00
luca.mazzoleni bd3a5fd318 Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2025-05-05 18:09:57 +02:00
andrea.villa fe51d2746c - Aggiunti parametri dMaxWasteLength e dMaxWasteVolume in TailCut e HeadCut
- In TailCut modificata gestione taglio restante e PreCut
2025-05-05 18:09:37 +02:00
luca.mazzoleni b9310cdeb0 - in BLADETOWASTE se arriva il parametro opzionale b3BoxDicing si usa questo per calcolare le dimensioni della feature e il suo volume 2025-05-05 18:09:07 +02:00
luca.mazzoleni edebdb26d3 Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2025-05-05 16:02:01 +02:00
luca.mazzoleni 335604b8f2 - in FaceData, nella ricerca delle MainFaces gestito caso a 1 faccia
- in STR0001 piccole correzioni
- in BLADEKEEPWASTE ora se arrivano 2 facce con angoli sbaligati si ritorna non applicabile, invece di dare errore lua
2025-05-05 16:01:57 +02:00
andrea.villa 53bcb4c74d In BladeToWaste, corretto scelta edge da lavorare nella funzione GetEdgeToMachine. Era solamente invertita una chiamata 2025-05-05 12:43:29 +02:00
andrea.villa f2f1317fdf Gestione Topologia 'Bevel-3-Blind' per STR0002, svuotatura 2025-05-05 09:06:27 +02:00
luca.mazzoleni 40259ba8d7 Merge branch 'feature/DoubleCut' into develop 2025-05-04 23:31:53 +02:00
luca.mazzoleni 444ba1cc6c - in FACEBYBLADE modificati attacchi 2025-05-01 15:52:58 +02:00
luca.mazzoleni e1bc32c22f Merge branch 'develop' into feature/DoubleCut 2025-04-30 23:56:03 +02:00
luca.mazzoleni 85734fb7a3 - gestito ritorno messaggi apply in risultati in caso di errore
- BLADETOWASTE miglikorata e modificata per gestire DOUBLECUT (da completare)
- in BeamExec si eliminano le entità aggiunte non usate
2025-04-30 23:54:35 +02:00
andrea.villa 8be4a152b7 In TAILCUT, aggiunto chiamata alla BLADETOWASTE 2025-04-30 16:58:19 +02:00
luca.mazzoleni 60ffe9da73 - in BLADETOWASTE refactoring e aggiunta funzione CutWithDicing 2025-04-30 14:46:20 +02:00
luca.mazzoleni d3f88c44a9 Merge branch 'develop' into feature/DoubleCut 2025-04-29 19:30:09 +02:00
luca.mazzoleni 46bfae300f - il calcolo tempi è ora fatto direttamente nella lavorazione e contempla anche le feed start end 2025-04-29 19:29:58 +02:00
luca.mazzoleni 81d7794b6d Merge branch 'develop' into feature/DoubleCut 2025-04-29 15:06:52 +02:00
andrea.villa c234978cab - Corretta chiamata della funzione GetAvailableCombinations
- Piccole correzioni varie
2025-04-29 15:03:29 +02:00
andrea.villa 390c2cd14e Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2025-04-29 12:53:22 +02:00
andrea.villa 81ab09a122 In BatchProcessNew, si ricavano tutte le informazioni dei pezzi nestati nella barra 2025-04-29 12:53:19 +02:00
luca.mazzoleni 6dbf203d4d - in BeamExec piccole modifiche a AddFeatureResultToGlobalList e gestito ritorno risultati anche in caso di nessuna feature lavorabile 2025-04-29 09:50:12 +02:00
luca.mazzoleni 3e2541bd87 - in BatchProcessNew aggiunta costruzione tabella PARTS, da completare 2025-04-28 19:09:22 +02:00
luca.mazzoleni 8d4212c926 - in BatchProcessNew piccola correzione alla scrittura log txt
- Process modificata per essere coerente con la nuova restituzione risultati
2025-04-28 16:49:11 +02:00
luca.mazzoleni 603043b9d2 - in BeamExec e BatchProcessNew contemplate feature senza strategia e sostituite in restituzione risultati 2025-04-28 15:02:29 +02:00
luca.mazzoleni dca28cbe1b - in BatchProcessNew, in scrittura log txt, gestito caso in cui non sono state trovate strategie (ma al momento non possibile perchè quelle feature sono escluse a priori dal collect)
- in BeamExec -> AddFeatureResultToGlobalList refactoring e aggiunta gestione feature sostituita (ma al momento non possibile per problemi di riferimenti incrociati nella stessa tabella)
2025-04-27 22:20:58 +02:00
luca.mazzoleni d77cdd6c7d - in BatchProcessNew corretto valore ROT in log txt 2025-04-26 02:35:41 +02:00
luca.mazzoleni 837969e0a7 - modificate BatchProcessNew e BeamExec per contemplare nuova tabella RESULTS 2025-04-26 02:05:33 +02:00
luca.mazzoleni 3bc9ef4688 - in BatchProcessNew varie modifiche per renderla compatibile con nuovo automatismo; manca restituzione risultati
- in BeamExec prima versione della tabella globale RESULT per la restituzione risultati
2025-04-25 19:39:37 +02:00
luca.mazzoleni 64c800ab3e - in BatchProcessNew refactoring e rinominate alcune variabili per essere coerenti con Process
- in BeamExec aggiunta bCreateMachGroup per gestire caso creazione barra in BatchProcessNew
- da testare e ultimare!!
2025-04-24 18:13:39 +02:00
luca.mazzoleni 1dae899c6e - aggiunta BatchProcessNew copiata da automatismo vecchio, con poche modifiche 2025-04-24 15:08:33 +02:00
luca.mazzoleni 27a8e785fd Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2025-04-24 10:04:36 +02:00
luca.mazzoleni 4a5e7a2af8 - in STR0004 correzione a caso Tunnel (la lavorazione non veniva prolungata del raggio catena in caso di lato singolo)
- in lavorazioni di base piccola correzione al calcolo distanza totale
2025-04-24 10:04:31 +02:00
andrea.villa a25f1b18b9 Corretto nome AvailableStrategyList secondo standard 2025-04-24 09:44:40 +02:00
andrea.villa 88ee8759a3 Aggiornamento con nuovo standard nomencalatura 2025-04-24 09:02:21 +02:00
andrea.villa 0d3cc467a9 - I file della strategia si chiamano tutti allo stesso modo secondo standard STRxxxx, cambia estensione. LUA = Script, JSON=Parametri di default configurabili
- Aggiunto file AvailableStrategyList.json che sostituisce il file Strategies.INI
2025-04-24 08:49:16 +02:00
andrea.villa c0eeb01321 Corretta gestione errore in caso non venga trovato taglio testa o coda. Manca messaggio per interfaccia. 2025-04-23 13:05:03 +02:00
luca.mazzoleni 16c74add6f - nei risultati si restituisce anche il timetomachine, dove calcolato 2025-04-23 13:03:53 +02:00
luca.mazzoleni 011830fb59 Merge branch 'BetterChainsawResults' into develop 2025-04-23 12:12:26 +02:00
luca.mazzoleni c9fd830dff Merge remote-tracking branch 'origin/develop' into BetterChainsawResults 2025-04-23 12:12:12 +02:00
luca.mazzoleni 74611f99c5 - in STR0003 correzione a restituzione risultati
- in STR0004 implementata restituzione risultati nuova
- in strategie di base corretto calcolo area lavorata (ora contempla che il percorso è in centro utensile e che l'area lavorata non può superare quella della faccia)
2025-04-23 12:12:00 +02:00
andrea.villa e028c9cd01 In GetSplitMachinings corretta impostazione dei leadIn/out in caso di split 2025-04-23 09:39:16 +02:00
andrea.villa ef6981f1b5 Merge branch 'StrategyConfigFromLuaToJson' into develop 2025-04-23 08:53:12 +02:00
andrea.villa 3837354ab8 - Creazione tabella globale STRATEGIES_CONFIG contenente i parametri di default delle strategie
- Nei file Config, tolto un livello di annidamento
- Nelle strategie sostituita require dei config con lettura tebella STRATEGIES_CONFIG
2025-04-23 08:46:26 +02:00
andrea.villa 28c9df081a File config con nuova sintassi JSON. Riportati tutti i valori di default dai file LUA 2025-04-22 16:27:14 +02:00
luca.mazzoleni ab19bbdb6a - in STR0003 gestione ritorno risultati nuovo e completamento con area lavorata 2025-04-22 11:47:54 +02:00
luca.mazzoleni b2917f8b37 - in MachiningLib modificata GetMachiningSteps per rispecchiare il calcolo della lavorazione Egt
- in STR0003 modifiche al calcolo risultati per la sola lama utilizzando le aree lavorate ( da completare per sega a catena)
2025-04-21 15:51:09 +02:00
luca.mazzoleni 8c2d9653d7 Merge branch 'FACEBYCHAINSAW_depthToMachine' into develop 2025-04-19 17:19:31 +02:00
luca.mazzoleni 2e12b09eb2 - in BLADETOWASTE implementato calcolo MRR con tempo di lavorazione 2025-04-19 17:19:20 +02:00
luca.mazzoleni ad652e1cd8 - in FeatureLib aggiunte funzioni GetStrategyQuality e GetStrategyTimeToMachine per calcolo risultati strategia
- in BLADEKEEPWASTE aggiunta la funzione GetStrategyCompletionPercentage per calcolare il completamento; si usano le funzioni nuove per il calcolo risultati
- in strategie di base si calcola l'area lavorata dAreaToMachine
2025-04-19 16:17:56 +02:00
luca.mazzoleni a532bbf481 - in STR0003 e STR0004 refactoring spaziatura per migliorare leggibilità 2025-04-16 07:00:17 +02:00
luca.mazzoleni a0d79c4d0f - in FACEBYCHAINSAW bStopAtHalfElevation sostituito con dDepthToMachine (ora analoga a FACEBYBLADE)
- STR0003 e STR0004 modificate di conseguenza
2025-04-14 13:13:51 +02:00
luca.mazzoleni 652141fd1d - in STR0004 refactoring 2025-04-13 15:14:35 +02:00
luca.mazzoleni 824f89b43f - in STR0004 refactoring parziale 2025-04-13 14:55:05 +02:00
luca.mazzoleni 9a436bfdcf - in MachiningsLib.GetSplitMachinings correzione al caso di lavorazione non splittabile
- in STR0003 refactoring
- in FACEBYCHAINSAW correzione agli step longitudinali
2025-04-13 14:46:22 +02:00
luca.mazzoleni d9a081f95e - in FACEBYCHAINSAW bDisableVerticalSteps sostituita da dLongitudinalStepSpan 2025-04-11 15:55:08 +02:00
luca.mazzoleni ce661864a7 - in FACEBYBLADE dHorizontalStepSpan sostituito da dRadialStepSpan 2025-04-11 15:45:28 +02:00
luca.mazzoleni 165230374e - in MachiningLib corretta GetSplitMachinings 2025-04-11 15:25:20 +02:00
luca.mazzoleni 9888bc7f4e - in MachiningLib.GetSplitMachinings corretta lettura LeadIn / Out per split
- in STR0009 si usa InitMachiningParameters per creare la lavorazione; il LeadIn / Out per split si inizializza copiando quelli originali
2025-04-09 19:07:42 +02:00
luca.mazzoleni fed75861be - in MachiningLib aggiunta InitMachiningParameters per inizializzarae i parametri della lavorazione a valori di default; FACEBYBLADE / CHAINSAW / MILL usano la nuova funzione invece di creare tabelle vuote
- tutti i riferimenti al tipo di lavorazione MCH_OY diventano MCH_MY
2025-04-09 16:39:19 +02:00
luca.mazzoleni 0c0d52afcb - CloneStepsHorizontal / Vertical rinominati CloneStepsRadial / Longitudinal 2025-04-09 10:28:25 +02:00
andrea.villa 05f1130e02 - In MachininLib si settano valori di default per calcolare lunghezza percorso
- in STR0009 piccole migliorie settaggi attacchi/uscite
2025-04-09 10:17:03 +02:00
andrea.villa 4b1c598141 Merge branch 'STR0009_RoundArc' into develop 2025-04-09 07:39:13 +02:00
andrea.villa ad1f28d670 - Gestione spezzatura tramite apposita funzione GetSplitMachinings
- In FeatureLib, se i punti di spezzatura feature si sovrappongono, se ne scrive solo uno
2025-04-09 07:38:45 +02:00
luca.mazzoleni 9b5bd46972 Merge branch 'STR0005_MultipleFaces' into develop 2025-04-08 19:02:14 +02:00
luca.mazzoleni bec6ef3ea3 - in MachiningLib.GetSplitMachinings aggiunta lettura di LeadInForSplit e LeadOutForSplit dal Machining, per customizzare approcci e retrazioni in caso di split 2025-04-08 18:50:21 +02:00
luca.mazzoleni 36f1ae5513 - calcolo lunghezza stimata del percorso con attacchi centralizzata, in MachiningLib
- calcolo lunghezza stimata aggiunto anche nel caso di lavorazione splittata
2025-04-08 17:51:01 +02:00
luca.mazzoleni d17673e65d - varie modifiche in FACEBYBLADE, FACEBYMILL, FACEBYCHAINSAW per implementare il calcolo della lunghezza del percorso con LeadIn/Out. Da completare per lavorazioni spezzate
- in BLADEKEEPWASTE migliorato calcolo risultati (poi da generalizzare)
2025-04-07 18:29:24 +02:00
andrea.villa ada7d5d870 Merge branch 'develop' into STR0009_RoundArc 2025-04-07 17:08:18 +02:00
andrea.villa 0023706024 Prima versione nuova strategia per Arco 2025-04-07 17:07:54 +02:00
andrea.villa 05326f30bb Piccole modifiche 2025-04-07 17:07:07 +02:00
luca.mazzoleni e37b3d3c3e - corretta nQuality in HeadCut e SplitCut 2025-03-31 09:27:35 +02:00
luca.mazzoleni fb68dd28a0 - creata funzione GetStrategyResult per restituzione risultati e varie modifiche relative
- uniformata la restituzione dei risultati in caso di strategia non applicabile (FeatureLib.GetStrategyResultNotApplicable, a cui si può passare il messaggio da ritornare)
2025-03-28 18:47:21 +01:00
andrea.villa 5443173068 Funzione GetFeatureRotationIndex settata come locale 2025-03-28 15:39:01 +01:00
andrea.villa 6f7ed8961f Merge branch 'STR0008_MortiseThrough' into develop 2025-03-28 15:25:41 +01:00
andrea.villa 1c1d0f7b96 Prima versione funzionante mortasa passante 2025-03-28 15:25:30 +01:00
andrea.villa 68a6c7d897 - Nella BasicCustomerStrategies aggiunte funzioni per leggere parametri Q per cliente Essetre
- I parametri delle BasicCustomerStrategies vengono letti all'inizio della Make di ogni strategia dalla BeamLib.LoadCustomParametersInStrategy
- Se feature taglio compatibile con taglio testa/coda viene saltato ( controllo nella InfoAndDependency)
2025-03-27 15:07:09 +01:00
luca.mazzoleni 63006b913a Merge branch 'develop' into STR0005_MultipleFaces 2025-03-26 11:51:59 +01:00
luca.mazzoleni ed9dde9bec Merge branch 'STR0005_MultipleFaces' into develop 2025-03-26 11:51:44 +01:00
luca.mazzoleni 943f4f7501 Merge remote-tracking branch 'origin/develop' into STR0005_MultipleFaces 2025-03-26 11:41:11 +01:00
luca.mazzoleni 09200303b3 - in FACEBYBLADE e FACEBYMILL bdisablehorizontalsteps sostituito da dHorizontalStepSpan per determinare da dove partono gli step orizzontali
- in BLADEKEEPWASTE implementazione finale della pulizia di fresa. Previsto parametro opzionale dMillingOffsetFromSide per far rimanere la fresa staccata dalla parete
2025-03-26 11:18:42 +01:00
luca.mazzoleni edd00a7b8f - in MachiningLib.AddMachinings gestito attacco non perpendicolare
- in BLADEKEEPWASTE sistemato sorting lavorazioni
- in FACEBYBLADE e FACEBYMILL correzioni per lavorazione facce non chiuse sopra
2025-03-25 18:59:29 +01:00
andrea.villa 3b9aee2ba3 Merge branch 'STR0008_Mortise' into develop 2025-03-25 14:36:15 +01:00
andrea.villa f23085c483 Aggiunta dimensioni limite per creazione cubettatura 2025-03-25 14:33:41 +01:00
luca.mazzoleni 1dac802cc0 - in BLADEKEEPWASTE aggiunta pulitura con fresa del raggio lama 2025-03-25 13:05:21 +01:00
andrea.villa f36ab53755 Cambiato indice ciclo for 2025-03-25 12:55:18 +01:00
andrea.villa e141a0f4a9 - In FeatureLib nel caso speciale feature Mortise si adeguano le AffectedFaces se feature troncante
- Gestione sovramateriali
- Gestione se feature di coda
2025-03-25 12:48:59 +01:00
andrea.villa 13c227ee0b Prima bozza gestione feature frontale 2025-03-25 11:20:19 +01:00
andrea.villa 7a2d6696b8 Prima versione strategia per lavorazione feature mortasa come svuotatura 2025-03-24 17:01:10 +01:00
luca.mazzoleni 8ed49c5cd1 Merge branch 'develop' into STR0005_MultipleFaces 2025-03-21 15:21:29 +01:00
luca.mazzoleni e947fb9384 - creata FACEBYMILL da testare 2025-03-21 09:35:50 +01:00
andrea.villa f0f0187de5 Nuova funziona ClassifyFeature per aver riconoscimento topologico non dalle geometrie ma dalle info BTL 2025-03-21 09:04:51 +01:00
luca.mazzoleni 0a419e9b3e Merge branch 'develop' into STR0005_MultipleFaces 2025-03-20 17:50:43 +01:00
luca.mazzoleni ae802c8afb - in BLADEKEEPWASTE corretto calcolo percentuale lavorata se incompleta 2025-03-20 17:49:41 +01:00
andrea.villa 2be6204725 Riportato commento numero feature BTL in libreria 2025-03-20 15:12:31 +01:00
luca.mazzoleni b82e40d8ff Merge branch 'develop' into STR0005_MultipleFaces 2025-03-20 15:09:17 +01:00
luca.mazzoleni 80e309721e Merge branch 'STR0005_MultipleFaces' into develop 2025-03-20 12:54:24 +01:00
luca.mazzoleni 62c384a171 - in FACEBYBLADE la distanza di sicurezza è ora CUT_SIC 2025-03-20 12:54:08 +01:00
luca.mazzoleni 589e32cf92 Merge remote-tracking branch 'origin/develop' into STR0005_MultipleFaces 2025-03-20 12:52:39 +01:00
andrea.villa e03359b4d1 Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2025-03-20 12:51:08 +01:00
andrea.villa 603edc9417 Merge branch 'STR0007_DTMortaise' into develop 2025-03-20 12:51:05 +01:00
andrea.villa 5032edc79a - Prima versione strategia Mortasa a coda di rondine STR0007
- Modifiche a librerie per gestione strategia
2025-03-20 12:50:54 +01:00
andrea.villa 4e9ab24192 Correzione nome variabile in STR0001 2025-03-20 12:49:32 +01:00
andrea.villa 848e8ecd2c - In STR0006 corretto nome variabile
- Modifica a due commenti
2025-03-20 12:48:06 +01:00
luca.mazzoleni 5a0fb8ca86 - in FACEBYBLADE e FACEBYCHAINSAW modificato check tasca troppo stretta 2025-03-20 11:51:03 +01:00
luca.mazzoleni 02d12d7106 Merge branch 'develop' into STR0005_MultipleFaces 2025-03-20 11:38:17 +01:00
luca.mazzoleni 67ceda8599 - in MachiningLib migliorata funzione FinalizeSorting 2025-03-20 11:38:08 +01:00
luca.mazzoleni a89f09b572 Merge branch 'STR0005_MultipleFaces' into develop 2025-03-19 19:01:07 +01:00
luca.mazzoleni eff84f5f4d - in BeamExec si usa la funzione MachiningLib.FinalizeSorting per ripristinare l'ordine delle lavorazioni interno alla feature, se il sorting l'ha violato 2025-03-19 19:00:52 +01:00
luca.mazzoleni c512def05d Merge branch 'develop' into STR0005_MultipleFaces 2025-03-19 16:13:41 +01:00
luca.mazzoleni c29d2beec6 Merge branch 'STR0005_MultipleFaces' into develop 2025-03-19 16:13:31 +01:00
luca.mazzoleni 81270c324f - in FeatureLib.CalculateFeatureNotClampableLengths si ritorna 0 se 3 facce
- in STR0005 aggiunto controllo numero massimo di facce
- in STR0005 modifiche per conemplare più di una faccia
- in BLADETOWASTE piccola correzione
2025-03-19 16:13:18 +01:00
luca.mazzoleni e47d9ac6df Merge branch 'develop' into STR0005_MultipleFaces 2025-03-19 09:30:53 +01:00
andrea.villa 76e00c211e Cambio punto di partenza del tenone 2025-03-19 08:21:52 +01:00
andrea.villa 6f215f9849 Corretta gestione indice rotazione iniziale in caso di pezzo senza lavorazioni (solo taglio testa e coda) 2025-03-19 07:56:36 +01:00
luca.mazzoleni c06c2378ce - in BLADEKEEPWASTE aggiunta lavorazione eventuali facce di chiusura 2025-03-18 19:31:55 +01:00
luca.mazzoleni e7a08b330b - per LongCut L010 abilitata STR0005
- in FACEBYBLADE corretti attacchi
2025-03-18 18:33:49 +01:00
luca.mazzoleni a0140dae55 - in MachiningLib piccole modifiche a ordinamento
- in BLADETOWASTE si settano i centri delle facce dei cubetti per l'ordinamento
2025-03-18 18:08:40 +01:00
luca.mazzoleni 26dff39619 in BLADEKEEPWASTE aggiunti controlli preventivi 2025-03-18 15:40:39 +01:00
luca.mazzoleni 6e45be2538 - In FeatureLib.GetProcFromTrimesh si permette di passare una Proc da cui copiare i dati
- in STR0005 gestito caso 3 facce tipo RidgeLap (da testare)
- in BLADEKEEPWASTE gestito caso 2 facce
2025-03-18 15:29:29 +01:00
luca.mazzoleni 9cc0121229 Merge branch 'develop' into STR0005_MultipleFaces 2025-03-18 11:33:49 +01:00
luca.mazzoleni 0d9381b6ae - modifiche commenti 2025-03-18 11:33:34 +01:00
andrea.villa d674eec6ff - Correzione posizione pezzi in caso di split con rotazione del pezzo singolo
- Correzione rotazioni del pezzo quando c'è pre-rotazione
2025-03-18 08:51:52 +01:00
luca.mazzoleni 5977a4c6db - create BLADEKEEPWASTE per taglio con codolo; STR0005 modificata di conseguenza
- a BLADETOWASTE si passa la dExtendAfterTail opzionale
2025-03-17 17:39:46 +01:00
andrea.villa 5233d89a5b Gestione lavorazioni di testa che ostacolano misura laser in ultima rotazione. 2025-03-17 15:44:29 +01:00
luca.mazzoleni 0c70d6f812 - in STR0005 DROP_WHOLE_WASTE sostituita da DROP_WASTE 2025-03-17 15:29:05 +01:00
andrea.villa 2b929974dc Piccole migliorie strategie Tenone e TenoneDT 2025-03-17 13:03:17 +01:00
andrea.villa 07236b51cf Corretta gestione posizione pezzi durante le fasi di lavorazione. Prima della modifica, le posizione salvate nella Collect, non corrispondevano a quelle attuali del pezzo durante la CalculateStrategies 2025-03-14 17:19:53 +01:00
andrea.villa a4ed9b5b5b Piccola correzione lettura parametri strategia 2025-03-14 12:29:51 +01:00
andrea.villa 5f930e2e21 - Miglioramento lettura parametri strategia custom o forzati. Si fa tutto all'esecuzione della strategia
- Si è evitata la chiamata della DeepCopy su libreria Config delle strategie
- se strategia forzata, si salva solo l'id. I parametri verranno letti dopo
2025-03-14 12:00:24 +01:00
andrea.villa 1a455e66de Aggiunta DeepCopy libreria Config delle strategie 2025-03-14 08:42:48 +01:00
luca.mazzoleni 89d92bdcb4 Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2025-03-13 16:54:39 +01:00
luca.mazzoleni 99cbeca5c9 - in FACEBYBLADE aggiunta GetLeadInOutType per scelta attacco perpendicolare vs tangenziale, da migliorare 2025-03-13 16:54:35 +01:00
andrea.villa 62efd89018 - Corretto valore default per MinNz e MaxNx
- Corretto scelta utensile che considera deviazione angolare massima
- Migliorata gestione calcolo strategie
2025-03-13 15:17:54 +01:00
luca.mazzoleni 38eaed18cf - in BLADETOWASTE se un cubetto finisce dopo separazione si spostano tutti 2025-03-12 16:22:49 +01:00
luca.mazzoleni dcefd35cc9 - in tutte le strategie, tutte le chiamate a funzioni interne AddMachiningAllSteps o a MachiningLib.AddNewMachining sostituite con chiamate a funzione AddMachinings in MachiningLib
- in FACEBYBLADE  e FACEBYCHAINSAW contemplata opzione bDisableHorizontalSteps e bDisableVerticalSteps, rispettivamente, per non creare i cloni orizzontali / verticali
2025-03-12 15:19:27 +01:00
luca.mazzoleni a7759e3b37 - HorizontalSteps rinominata CloneStepsHorizontal
- VerticalSteps rinominata CloneStepsVertical
2025-03-12 12:45:24 +01:00
luca.mazzoleni 45712e604b - in STR0005 piccola correzione 2025-03-12 12:21:48 +01:00
luca.mazzoleni 44628dfa13 Merge branch 'STR0005_BladeToWaste' into develop 2025-03-11 13:33:49 +01:00
luca.mazzoleni fe9aaf0439 - SetupInfo.dMinNz sostituito con funzione GetMinNz (anche GetMaxNz); tutti hanno default in BeamLib
- in BLADETOWASTE refactoring
2025-03-11 13:33:33 +01:00
andrea.villa 703fefa973 Piccola correzione rotazione pezzo per calcolo strategie 2025-03-11 12:03:11 +01:00
andrea.villa 35e8e921f3 Merge branch 'STR0001_UpgradeTenonDT' into develop 2025-03-11 12:02:10 +01:00
andrea.villa 4a948aa61a Adeguamento strategia con ultime novità della BLADETOWASTE, come per tenone normale 2025-03-11 12:00:28 +01:00
luca.mazzoleni 5894e98047 Merge branch 'develop' into STR0005_BladeToWaste 2025-03-11 11:27:28 +01:00
luca.mazzoleni 18a4529ed4 Merge branch 'STR0005_BladeToWaste' into develop 2025-03-11 11:11:47 +01:00
luca.mazzoleni 99c2950ab9 - in BLADETOWASTE piccola modifica 2025-03-11 09:49:02 +01:00
luca.mazzoleni 1cd85c85b6 Merge branch 'develop' into STR0005_BladeToWaste 2025-03-11 09:40:49 +01:00
luca.mazzoleni 1dc1aa5a7c - in BLADETOWASTE varie modifiche; cubetti funzionanti, da testare
- in BeamLib aggiunta funzione FindEdgeBestOrientedAsDirection
- in FeatureLib aggiunta funzione GetProcFromTrimesh per costruire il pacchetto Proc a partire da una trimesh
2025-03-11 09:40:20 +01:00
andrea.villa c34f3dccd8 Adeguamento strategia STR0006 a nuovi parametri di ritorno dell BLADETOWASTE 2025-03-10 16:01:50 +01:00
luca.mazzoleni d47343aba9 - in FACEBYBLADE piccola correzione 2025-03-10 10:05:25 +01:00
luca.mazzoleni 8807760db7 -in BLADETOWASTE piccola correzione 2025-03-07 17:54:53 +01:00
luca.mazzoleni 0ccfb2bfe6 - in FaceData GetEdgesInfo accetta anche l'id della trimesh
- in BLADETOWASTE varie modifiche per tagli a cubetti e tagli singoli
2025-03-07 17:42:21 +01:00
andrea.villa 562a219ffd Se non ci sono feature da lavorare, i tagli testa e coda vengono forzati da essere eseguiti in prima fase 2025-03-07 09:35:49 +01:00
andrea.villa 67d7ce2dd9 Prima versione funzionante feature Tenone STR0006 2025-03-07 07:54:52 +01:00
luca.mazzoleni ab2a381808 Merge remote-tracking branch 'origin/develop' into STR0005_BladeToWaste 2025-03-06 19:00:38 +01:00
luca.mazzoleni 2c1b0c7c79 - in BeamExec.GetToolsFromDB, se non presente la funzione GetMinNzDownUp in GetSetupInfo, si usa la funzione di default BeamLib.GetMinNzDownUpDefault
- in FACEBYBLADE invece del parametro bAllowToolInvert si passa opzionalmente dMinNzDownUp
- in BLADETOWASTE parzialmente aggiunta la gestione dei tagli a cubetti, da completare
2025-03-06 19:00:25 +01:00
andrea.villa 2c410008fd - Corrette rotazioni pezzo durante le varie fasi di calcolo
- Prima versione tagli testa/split in fase corretta
2025-03-06 17:31:56 +01:00
luca.mazzoleni d548cc1b43 Merge branch 'develop' into STR0005_BladeToWaste 2025-03-04 18:42:35 +01:00
luca.mazzoleni ac4b2ff262 Merge branch 'STR0005_BladeToWaste' into develop 2025-03-04 18:40:12 +01:00
luca.mazzoleni 0b6bb3fe71 Merge remote-tracking branch 'origin/develop' into STR0005_BladeToWaste 2025-03-04 18:38:25 +01:00
luca.mazzoleni adab6ab342 - in BLADETOWASTE si restituiscono, oltre alle lavorazioni, i risultati (status, completion, MRR) 2025-03-04 18:37:43 +01:00
andrea.villa e37d29fae3 Piccola correzione ricerca utensile nella FindMill 2025-03-04 09:48:50 +01:00
luca.mazzoleni eafc1bec3f Merge remote-tracking branch 'origin/develop' into STR0005_BladeToWaste 2025-03-04 08:52:46 +01:00
andrea.villa c2b30d8ed9 Per calcolo del Composite Rating, aggiunto parametro 'FeatureRotationIndex' per bontà lavorazione in base al posizionamento della feature sulla trave (sopra, di fianco, sotto) 2025-03-04 08:18:28 +01:00
andrea.villa 6b7d15e503 Piccola modifica rotazione pezzo 2025-03-03 15:27:40 +01:00
andrea.villa 46cdaa494b - Per CalculateStrategies e CalculateMachinings si ribalta pezzo per averlo in posizione corretta nel momento dell'esecuzione della Proc
- Modificata RotatePart. Adesso bisogna passare il numero di rotazioni da fare
2025-03-03 15:03:18 +01:00
luca.mazzoleni bbf28a2ed7 - in BLADETOWASTE si passano i dati corretti alla DiceCut; manca calcolo lavorazioni su facce con relativo calcolo vtToolDirection ad ogni faccia
- in DiceCut aggiunta condizione, al momento commentata, per usare la dimensione cubetto ridotta in caso di faccia quasi verticale senza componenti in Y
2025-02-28 16:40:49 +01:00
luca.mazzoleni 8f1f99a628 Merge remote-tracking branch 'origin/develop' into STR0005_BladeToWaste 2025-02-28 09:16:00 +01:00
andrea.villa 6251c070ee Corretto nome parametro per aggiornamento grezzo durante le rotazioni 2025-02-28 09:03:39 +01:00
luca.mazzoleni 3e1c7e3698 Merge remote-tracking branch 'origin/develop' into STR0005_BladeToWaste 2025-02-28 08:48:05 +01:00
andrea.villa e14e196a35 Merge branch 'STR0006_Tenon' into develop 2025-02-27 17:38:40 +01:00
andrea.villa 8800369b1e - STR0006 gestisce ora taglio di lama su lunghezza tenone
- altre piccole modifiche
2025-02-27 17:38:20 +01:00
andrea.villa 8dd3485048 Merge remote-tracking branch 'origin/develop' into STR0006_Tenon 2025-02-27 16:18:20 +01:00
andrea.villa b7fdf8531a - Unificato calcolo parametri aggiuntivi per tenone e tenone coda di rondine
- In AddOperation si setta su nota geometria Taskid e Cutid
- In FeatureLib parametri feature aggiuntivi si trovano ora nella tabella "FeatureInfo"
- Piccole modifiche STR0006 per gestione nuova struttura dati
- In FeatureLib cancellato doppione GetAdditionalInfo
2025-02-27 16:18:08 +01:00
luca.mazzoleni 117dfa097f Merge branch 'develop' into STR0005_BladeToWaste 2025-02-27 15:54:24 +01:00
luca.mazzoleni fa9625b65c - in BLADETOWASTE se passata trimesh si calcolano anche le AffectedFaces 2025-02-27 15:54:13 +01:00
luca.mazzoleni feda17bd17 Merge branch 'develop' into STR0005_BladeToWaste 2025-02-27 15:47:39 +01:00
luca.mazzoleni 7b37da048a - in BLADETOWASTE si può ora passare sia una Proc che direttamente l'id di una trimesh 2025-02-27 15:43:55 +01:00
luca.mazzoleni 42b7decc48 in DiceCut piccole correzioni 2025-02-27 15:01:33 +01:00
andrea.villa 15eab9b508 Merge remote-tracking branch 'origin/develop' into STR0006_Tenon 2025-02-27 14:39:45 +01:00
andrea.villa 2256c15015 Prima versione strategia tenone, non funzionante 2025-02-27 14:36:11 +01:00
luca.mazzoleni f7201c32ed Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2025-02-27 14:29:58 +01:00
luca.mazzoleni fbfef76c64 Merge branch 'STR0005_BladeToWaste' into develop 2025-02-27 14:29:54 +01:00
luca.mazzoleni 7ccf3f888f - nei parametri opzionali di tipo double ('d') ora se la stringa è vuota si considera come parametro non passato (nil)
- alcune modifiche all'angolo min/max testa da GetSetupInfo di macchina
- in MachiningLib -> FindBlade ora si controlla se la normale della faccia da lavorare è compatibile con eventuali angoli Max/Min da SetupInfo; si passa vtN e non più vtToolDirection
- in tutte le strategia sistemati i parametri Config di tipo combo
- in STR0005 -> codolo si verifica che le 2 lavorazioni siano state fatte altrimenti si restituisce non applicabile
- aggiunta GetBestBladeForDicing per scelta lama in caso di cubetti
- in FACEBYBLADE se ToolInvert si passa la vtN invertita alla ricerca lama
2025-02-27 12:54:16 +01:00
andrea.villa 64145e62cf Merge branch 'STR0001_TenonDT' into develop 2025-02-26 07:43:04 +01:00
luca.mazzoleni cf037fb574 Merge branch 'STR0005_BladeToWaste' into develop 2025-02-25 18:30:45 +01:00
luca.mazzoleni 20c10f495d - aggiornati riferimenti a GetSetupInfo con nuovi nomi 2025-02-25 18:30:20 +01:00
andrea.villa cf4b504733 Merge branch 'develop' into STR0001_TenonDT 2025-02-25 16:12:12 +01:00
luca.mazzoleni b229b21e64 - in BLADETOWASTE primo implemento di lavorazione a cubetti, non funzionante 2025-02-24 17:41:39 +01:00
luca.mazzoleni 81c0acbde1 - in FACEBYBLADE di default si inverte l'utensile per rispettare la concordanza (ToolInvert) solo se è vero il parametro opzionale bAllowToolInvert
- parametro opzionale passato in STR0003 -> Blade
2025-01-31 18:06:00 +01:00
luca.mazzoleni 7eb83ccf79 - in MachiningLib migliorie a FindBlade
- migliorata BLADETOWASTE
- in FACEBYBLADE la residualDepth si esprime rispetto alla DephToMachine passata e non rispetto all'elevazione del lato
2025-01-31 17:23:11 +01:00
luca.mazzoleni 2f1b56ddc6 - in BLADETOWASTE taglio singolo funzionante, da completare 2025-01-31 13:08:27 +01:00
luca.mazzoleni 1271205f2c - in BLADETOWASTE primo implemento, non completo, del taglio singolo 2025-01-31 12:40:35 +01:00
luca.mazzoleni b8a694db60 - in DiceCut alcune modifiche nomi variabili 2025-01-30 09:22:16 +01:00
luca.mazzoleni a7664d5743 - in DiceCut refactoring 2025-01-29 16:31:49 +01:00
luca.mazzoleni 665113929a - in FACEBYBLADE aggiunta scrittura del frame lavorazione vtFaceUse
- picoole migliorie varie
2025-01-29 10:18:37 +01:00
luca.mazzoleni f1baaa9842 Merge branch 'develop' into STR0005_BladeToWaste 2025-01-28 10:55:05 +01:00
luca.mazzoleni 084b6758a3 - SLOTBYBLADE rinominata FACEBYBLADE; vecchia FACEBYBLADE eliminata
- SLOTBYCHAINSAW rinominata FACEBYCHAINSAW
- in SPLITCUT modifiche alle chiamate di FACEBYBLADE per contemplare la nuova funzione
- in STR0005 - codolo l'utensile non viene passato ma viene lasciato scegliere alla FACEBYBLADE
2025-01-28 10:54:16 +01:00
luca.mazzoleni a8c2e2fe98 - in HEADCUT si chiama la SLOTBYBLADE e non più la FACEBYBLADE
- in STR0003 e SLOTBYBLADE modifiche al calcolo LeadIn / LeadOut
2025-01-27 18:03:47 +01:00
luca.mazzoleni e37486db1d - in STR0003 correzione nel calcolo LeadIn/Out per i cloni 2025-01-27 15:57:12 +01:00
luca.mazzoleni f9168e8380 Merge branch 'STR0005_Codolo' into develop 2025-01-27 11:55:36 +01:00
luca.mazzoleni 9edd39305f - STR0005 con codolo funzionante e con ordinamento lavorazioni 2025-01-24 17:21:19 +01:00
luca.mazzoleni 0c5373700e - in STR0003, 4 e 5 corretta gestione spezzatura 2025-01-24 15:17:10 +01:00
luca.mazzoleni 098244b109 - in SLOTBYBLADE e SLOTBYCHAINSAW corrette direzioni utensile 2025-01-24 12:26:22 +01:00
luca.mazzoleni e553197d61 - in Edges l'elevazione si tiene sempre positiva e la normale guarda sempre verso il centro.
- alle funzioni di base si può passare il parametro opzionale bOppositeToolDirection per invertire la direzione di lavoro dell'utensile
2025-01-23 16:39:43 +01:00
luca.mazzoleni c64aaade13 - in FaceData MainFaces non si crea se è vuota
- in SLOTBYBLADE e SLOTBYCHAINSAW piccole correzioni
2025-01-23 12:28:48 +01:00
luca.mazzoleni ffe2d07918 - negli egde vtToolDirection sostituita con vtN 2025-01-23 12:13:30 +01:00
luca.mazzoleni 89c315cdd8 - in MachiningLib corretta l'assegnazione del nFeatureSegment nei casi in cui la lavorazione non ha quasi componenti in X 2025-01-22 12:33:19 +01:00
luca.mazzoleni e3ab0b8f35 - correzione in SLOTBYCHAINSAW 2025-01-21 16:03:19 +01:00
luca.mazzoleni 40e76a23c9 - in FaceData Elevation è sempre positiva nelle facce standard (non MainFaces)
- in MachiningLib in GetSplitMachinings correzioni alla definizione dello stage della lavorazione; correzione a FindBlade
- in SLOTBYBLADE e SLOTBYCHAINSAW correzioni per poter passare la profondità di lavoro
- in STR0005 primo implemento di lavorazione con codolo
2025-01-21 15:27:33 +01:00
luca.mazzoleni fc6b50b345 - in FaceData struttura dati degli Edges della faccia uniformata a quella degli Edges della MainFaces
- tutte le chiamate a Edges aggiornate di conseguenza
2025-01-17 18:06:37 +01:00
luca.mazzoleni 8d2a9955ba - in MachiningLib GetMachiningSteps il numero minimo di step è sempre 1
- STR0004 corretta per passare altezza tasca alla SlotByChainsaw
- in SLOTBYBLADE e SLOTBYCHAINSAW si controlla se la tasca è meno spessa della lama solo nel caso in cui venga passata un'altezza tasca
2025-01-17 13:05:35 +01:00
luca.mazzoleni 87aa2a7ce6 - in SLOTBYCHAINSAW e SLOTBYBLADE spostato calcolo altezza tasca fuori; si deve passare come parametro opzionale: se non presente, si lavora la faccia senza step verticali
- STR0003 modificata per rispecchiare le modifiche sopra; STR0004 DA FARE
2025-01-16 18:28:52 +01:00
luca.mazzoleni 2be4a3fe0b - PROCESSINGS spostata in BeamExec
- aggiunte a STR0005, da completare
2025-01-16 12:52:15 +01:00
luca.mazzoleni d76ecbc9f6 - in Process require di BeamExec spostato dopo la dichiarazione delle variabili globali
- in BeamExec -> CollectFeatures si salva l'indice della Proc nel vProc
- in FeatureLib aggiunta funzione GetFeatureMaxNotClampableLengths
- correzioni e migliorie GetFeatureMaxNotClampableLengths
2025-01-14 15:17:18 +01:00
luca.mazzoleni cc8410b0c5 - in BeamExec -> CollectFeatures inserito calcolo riduzione lunghezza pinzabile
- in FeatureLib aggiunte funzioni GetFeatureVolume e CalculateFeatureNotClampableLengths
- in STR0005 aggiunta scelta strategie di taglio; al momento non contemplato massimo materiale lama
- aggiunta BLADETOWASTE, solo intestazione
2025-01-10 18:13:39 +01:00
luca.mazzoleni 3835f6f6e0 - in Strategies.ini e BasicCustomerStrategies aggiunta STR0005 2025-01-08 09:15:44 +01:00
luca.mazzoleni cf96eb7bc3 - aggiunta STR0005 - BladeToWaste 2025-01-07 17:30:47 +01:00
luca.mazzoleni 3287420f41 - in FaceData -> GetFacesInfo contemplato il caso in cui arrivi una Proc senza nFct 2025-01-07 15:27:25 +01:00
andrea.villa d013e836a0 Merge remote-tracking branch 'origin/develop' into STR0001_TenonDT 2025-01-07 12:52:28 +01:00
andrea.villa 3a5cba1c15 In FaceByBlade, il parametro 'FaceToMachine' deve essere una tabella, formattata tipo una Proc. 2025-01-07 12:52:16 +01:00
andrea.villa 0c8d5516e1 Merge remote-tracking branch 'origin/develop' into STR0001_TenonDT 2025-01-07 12:27:41 +01:00
andrea.villa e443bd5813 - Tutte le librerie 'core' relative alle strategie sono state spostate nella cartella STRATEGYLIBS
- StrategyLib.lua che conteneva solo funzioni per lo split, è stata rinominata in SPLITCUT.lua e sarà relativa solo al taglio di seoparazione
2025-01-07 12:27:31 +01:00
andrea.villa 37f85bccec - Gestione cloni
- Aggiunta attacco lineare
2025-01-07 09:16:06 +01:00
andrea.villa 512b907aae - Aggiunto passaggio di contornatura su profilo
- Prima bozza struttura lavorazioni
- Piccole modifiche in altre librerie
2025-01-03 17:19:15 +01:00
andrea.villa e9d71ab75e - Aggiunta chiamata strategia in BasicCustomerStrategies
- Calcolo parametri aggiuntivi
- Prima bozza (non funzionante) della strategia
2025-01-02 16:41:36 +01:00
andrea.villa ad112ca6c3 Merge remote-tracking branch 'origin/develop' into STR0001_TenonDT 2025-01-02 15:55:50 +01:00
andrea.villa ce7d87a5ac Aggiunta funzione GetAdditionalInfo in FeatureLib per recupero informazioni aggiuntive di feature che non richiedono topologia 2025-01-02 15:55:28 +01:00
andrea.villa 8238767f69 Piccola modifica STR0002 per spostare svuotatura dopo taglio di separazione 2025-01-02 14:51:15 +01:00
luca.mazzoleni ca4141515d - piccole correzioni varie 2024-12-24 11:13:32 +01:00
luca.mazzoleni 6ca555efc8 Merge branch 'SortingMachinings' into develop 2024-12-24 08:45:13 +01:00
luca.mazzoleni b882f23d3e - commenti 2024-12-24 08:44:46 +01:00
luca.mazzoleni 8c39c6a94f - in MachiningLib -> GetSplitMachinings correzione al calcolo FeatureSegment nel caso di lavorazione non spezzata 2024-12-23 18:25:30 +01:00
luca.mazzoleni e126e3f389 - in BeamLib introdotto algoritmo di sorting STABILE (merge sorting)
- piccole correzioni in SLOTBYBLADE e SLOTBYCHAINSAW
2024-12-23 16:11:25 +01:00
luca.mazzoleni 3bce7b5fd6 implementato sorting lavorazioni ma non corretto, serve un algoritmo di STABLE SORTING 2024-12-23 09:08:03 +01:00
luca.mazzoleni 99e0bd27d9 - funzioni di Sorting spostate in MachiningLib
- Sorting di base funzionante
2024-12-19 18:33:39 +01:00
luca.mazzoleni 456d8e903a - in BeamExec completata la funzione PrepareMachiningsForSorting
- in FaceData la lunghezza rispetto a X è ora in valore assoluto
- in MachiningLib -> GetSplitMachinings aggiunta la scrittura del centro della lavorazione
- in STR0003, STR0004, SlotByChainSaw e SlotByBLade nSegment diventa nFeatureSegment per distinguerla da nPartSegment
2024-12-19 15:04:17 +01:00
luca.mazzoleni 14f81da3df - in Process e BeamExec reinserito calcolo parte dopo spostamento pezzo 2024-12-18 12:23:04 +01:00
luca.mazzoleni eb4a5e521f - in BeamExec si evita di ricalcolare senza motivo il box del pezzo
- tutti i riferimenti a PARTS[i].b3Box o Part.b3Solid diventano Part.b3Part
- in BeamExec aggiunte funzioni PrepareMachiningsForSorting e SortMachiningsBySegment, da completare
- in BeamLib aggiunta funzione GetSplittingPoints
- nelle lavorazioni introdotta la variabile sStage che rappresenta la fase di lavoro a cui la lavorazione stessa appartiene (Head, Tail, AfterTail oppure vuota che significa sezione centrale, quella divisa in segments)
- piccole correzioni ad alcuni nomi di variabile
2024-12-18 11:59:08 +01:00
luca.mazzoleni 233a928dcd - in DiceCut modificati i commenti 2024-12-16 13:18:10 +01:00
luca.mazzoleni db88c7bb8d Merge branch 'feature/NewStrategyLib' into develop 2024-12-16 11:19:59 +01:00
luca.mazzoleni 992a115f93 Merge branch 'develop' into feature/NewStrategyLib 2024-12-10 16:14:55 +01:00
luca.mazzoleni 50753dda52 Merge branch 'STR0003_Splitting' into develop 2024-12-06 16:30:29 +01:00
luca.mazzoleni 9fcd805ed5 - in FeatureLib -> GetFeatureSplittingPoints correzioni e migliorie
- in MachiningLib -> GetSplitMachinings correzione all'assegnazione del segmento per gli edge non lavorati completamente
- in STR0003 gestito ordinamento lavorazioni lama + sega a catena
- altre piccole migliorie
2024-12-06 16:29:34 +01:00
luca.mazzoleni eccfb96c22 - in STR0003 aggiunto splitting lavorazioni lama e sega a catena e refactoring
- da testare
2024-12-05 17:54:30 +01:00
andrea.villa cff250ca37 - TAILCUT utilizza nuova libreria
- Prima versione funzionante tagli PRECUT
2024-12-05 08:09:50 +01:00
andrea.villa 7309ebb6a3 - Creazione (vuota) nuova libreria StrategyLib
- SPLITCUT non è più una strategia ma sarà una funzionalità della nuova libreria
- Nuova strategia TAILCUT, corrispettivo del HEADCUT sulla testa
- Alla feature 340 si applica la strategia TAILCUT
2024-12-04 10:52:59 +01:00
andrea.villa c649870518 Piccola modifica Splitcut 2024-12-04 10:18:40 +01:00
andrea.villa 3d8ec03c47 Merge branch 'feature/DiceCut' into develop 2024-12-04 10:17:24 +01:00
andrea.villa 42329d7688 Aggiunta libreria DiceCut. Funzione GetDice uniformata a nuovo standard, funzioni interne non modificate. 2024-12-04 10:17:09 +01:00
luca.mazzoleni a6ddaa8bbd - alcune correzioni nel calcolo approccio retrazione per lavorazioni di coda e split
- in STR0003 aggiunta gestione lavorazioni di coda per sega a catena
2024-12-03 16:47:47 +01:00
luca.mazzoleni bb82dcb724 - in MachiningLib -> StartsLeftSide contemplato ToolInvert
- in SLOTBYBLADE aggiunta gestione lavorazioni di coda
- in STR0003 > lama aggiunta gestione lavorazioni di coda
- in Config STR0003 e STR0004 aggiunto parametro dExtendAfterTail per decidere di quanto estendere una lavorazione oltre la coda
2024-12-03 14:55:46 +01:00
andrea.villa d58be78868 - Prima bozza separazione con doppia lavorazione lama e lama da sotto.
- HEADCUT derivata da SPLITCUT. Da verificare se mantenere separate o fondere in un'unica strategia
2024-12-02 14:46:08 +01:00
luca.mazzoleni 1cb9104404 Merge branch 'MachiningsOnTailManagement' into develop 2024-11-28 18:00:07 +01:00
luca.mazzoleni 19a47115ea - in BeamExec corretto calcolo della distanza dal pezzo successivo in caso di ultimo pezzo per tenere conto di grezzo scaricabile o meno 2024-11-28 17:59:50 +01:00
luca.mazzoleni 6da682dfed - in MachiningLib corretta CanMoveAfterSplit
- in SLOTBYCHAINSAW e STR0004 modifiche alla gestione delle lavorazioni in coda
2024-11-27 11:51:21 +01:00
luca.mazzoleni 08d3f7ff6d aggiunta la gestione delle lavorazioni in coda, per decidere se spostare dopo separazione o accorciarle:
- in MachiningLib aggiunte funzioni StartsLeftSide e CanExtendAfterTail; modificata GetSplitMachinings
- Machining.nPart rinominato nSegment
- in SLOTBYCHAINSAW.Make aggiunta sezione per gestire lavorazioni di coda
-  STR0004 adeguata per passare alla strategia di base le informazioni sulle lavorazioni di coda
2024-11-26 13:33:36 +01:00
luca.mazzoleni 229e98cf9d Merge branch 'NewParametersManagement' into develop 2024-11-22 17:56:01 +01:00
luca.mazzoleni d7096a8a68 - migliorie al tipo di parametro 'combo'
- aggiunto parametro sCanDamageNextPiece
2024-11-22 17:55:32 +01:00
andrea.villa b0f26bdea2 BOZZA sviluppo nuove tipologie di parametri
- tipo di parametro "Combo"
- nuovo campo sNameNge che verrà scritto nelle info nel Processing
2024-11-22 12:56:12 +01:00
luca.mazzoleni 2586407ec9 Merge branch 'STR0004_Splitting' into develop 2024-11-21 18:12:14 +01:00
luca.mazzoleni a34a62d635 Merge remote-tracking branch 'origin/develop' into STR0004_Splitting 2024-11-21 18:07:37 +01:00
luca.mazzoleni 44215b3b4e - in MachiningLib -> GetSplitMachinings correzione a inversione start/end 2024-11-21 18:04:18 +01:00
luca.mazzoleni a2b49fdf3e - in MachiningLib aggiunta la scrittura dello spezzone nella lavorazione
- in STR0004 aggiunto ordinamento lavorazioni
- piccole aggiunte varie
2024-11-21 17:53:24 +01:00
luca.mazzoleni 21b73e0031 - in MachiningLib aggiunta funzione GetSplitMachinings, estrapolata da STR0004 (modificata di conseguenza) 2024-11-20 14:58:04 +01:00
andrea.villa 54c86774b7 - Corretta creazione barra in caso di più pezzi
- Libreria specifica per Log
- Nuovo log feature con tutte le strategie disponibili
- Nel log della matrice rotazioni si indica se la strategia scelta è completa (C), parziale (P) o non applicabile (N)
2024-11-20 14:28:20 +01:00
luca.mazzoleni 80c5a5a393 - piccola correzione in SLOTBYCHAINSAW 2024-11-19 09:21:41 +01:00
luca.mazzoleni 13ae86b6a7 - in STR0004 miglioramenti a spezzatura 2024-11-18 18:29:18 +01:00
luca.mazzoleni 8119643221 Merge branch 'develop' into STR0004_Splitting 2024-11-18 17:32:26 +01:00
luca.mazzoleni 941954825d - in BeamLib aggiunta funzione TableCopyDeep per copiare una tabella mantenendo senza riferimenti le sottotabelle
- in STR0004 primo implemento di spezzatura lavorazioni, da completare
- in SLOTBYCHAINSAW scritti alcuni parametri realtivi al lato nel Machining
2024-11-18 17:32:10 +01:00
andrea.villa 8d1286dd71 Calcolo rotazione scritto in modo più comprensibile 2024-11-18 16:03:53 +01:00
andrea.villa 4abc2c01af Piccola modifica al nome delle variabili 2024-11-18 15:36:11 +01:00
andrea.villa 7e6d8f4172 Corretta gestione rotazione pezzo nel DISP in caso che la soluzione scelta sia una prerotazione 2024-11-18 15:29:32 +01:00
luca.mazzoleni 5aa2b5ac4d Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2024-11-14 10:52:36 +01:00
luca.mazzoleni ae4c3f9156 - in FeatureLib e STR0002 invertito ordine dei punti di spezzatura, ora è da testa a coda 2024-11-14 10:52:32 +01:00
andrea.villa a4f6e10dc3 Merge branch 'CollectBasedOnCombinations' into develop 2024-11-14 10:25:24 +01:00
andrea.villa fc047c2350 Ottimizzazione collect. Si calcola solo se la rotazione è abilitata, in base alle combinazioni disponibili 2024-11-14 10:23:58 +01:00
luca.mazzoleni 28946a0291 - in FaceData, nella trimesh generata TunnelAddedFaces.MiddleFaceTm, aggiunte le facce di contenimento laterali per garantire lati chiusi in svuotatura splittata 2024-11-13 18:42:01 +01:00
luca.mazzoleni 9375cd0868 Merge branch 'GetSplittingPoints' into develop 2024-11-11 14:50:50 +01:00
luca.mazzoleni 8bd772c96d - in STR0002 -> GetSplitSurfaces correzione a taglio superfici 2024-11-11 14:48:18 +01:00
luca.mazzoleni 2fff4438c0 - in STR0002 overlap tra le passate portato a 1/2 MILL_OVERLAP
- in FaceData in ogni Edge si scrive ora la lunghezza proiettata lungo X dLengthOnX
- in FeatureLib aggiunta la funzione MachiningNeedsSplitting per unificare il check di necessità spezzatura
2024-11-11 11:52:21 +01:00
luca.mazzoleni a17c62c15f - GetSplittedSurfaces convertita in GetSplitSurfaces 2024-11-11 08:59:49 +01:00
luca.mazzoleni 20c8518f1d - in STR0002 -> GetSplittedSurfaces aggiunto overlap tra le superfici 2024-11-08 18:32:40 +01:00
luca.mazzoleni 730d37c917 - in STR0002 miglioramenti vari 2024-11-08 18:00:28 +01:00
luca.mazzoleni 184a78d34c - in FeatureLib aggiunta funzione GetFeatureSplittingPoints che restituisce i punti di spezzatura di una feature, estrapolata da STR0002
- in STR0002 aggiunta funzione GetSplittedSurfaces per contemplare nuova funzione di restituzione punti e restituire direttamente le superfici trimmate alla Make
- piccole correzioni varie
2024-11-08 16:37:10 +01:00
luca.mazzoleni a33e794b1e Merge branch 'STR0004_SlotByChainsaw' into develop 2024-11-07 16:54:54 +01:00
luca.mazzoleni f212c0cede Merge branch 'develop' into STR0004_SlotByChainsaw 2024-11-07 16:53:38 +01:00
luca.mazzoleni 38fdaca7bf - FeatureData rinominata FeatureLib
- piccole migliorie stilistiche
2024-11-07 16:53:06 +01:00
andrea.villa 7b580b24bb Merge branch 'MachiningInRotation' into develop 2024-11-06 17:31:58 +01:00
andrea.villa 23bbd938fc Prima versione funzionante scelta soluzioni che contempla le pre-rotazioni 2024-11-06 17:31:38 +01:00
andrea.villa 21dd75b4a6 Migliorata identificazione combinazione disponibile. Ora 3 modi: Basic, NoRotation,Advanced 2024-11-06 12:17:56 +01:00
luca.mazzoleni a8ec76f451 Merge branch 'develop' into STR0004_SlotByChainsaw 2024-11-06 11:33:39 +01:00
luca.mazzoleni 9b5bb25c76 - implementata STR0004, strategia SlotByChainSaw 2024-11-06 11:32:51 +01:00
andrea.villa b9c492fe5a Merge branch 'develop' into MachiningInRotation 2024-11-06 10:12:36 +01:00
andrea.villa fdcb428002 Merge branch 'MachiningInRotation' into develop 2024-11-06 10:11:57 +01:00
andrea.villa 91c883b87c Completata funzione applicazione lavorazione in fase appropriata. MANCA prerotazione 2024-11-06 10:11:40 +01:00
luca.mazzoleni 8e151758b1 - creata STR0004 copiando do STR0003. Da implementare 2024-11-05 18:30:11 +01:00
luca.mazzoleni 1132369f1e - in STR0003 SawPlusChain corretto ordine passate orizzontali lama 2024-11-05 18:09:07 +01:00
luca.mazzoleni b9bb1aefdd - in BeamExec > GetToolsFromDB, in lettura parametri con EgtGetValInNotes, aggiunta 'd' se valori numerici
- in SPLITCUT > GetSplitStrategy gestito caso in cui GetMaxMatReductionBladeCut non è presente in BeamData anche per il Machining[2]
2024-11-05 17:20:44 +01:00
andrea.villa 2b9113347a Prima bozza (non funzionante) applicazione lavorazioni nella relativa rotazione 2024-11-05 16:37:50 +01:00
andrea.villa 7c80c4d3d8 Merge branch 'GetBestCombination' into develop 2024-11-05 13:27:48 +01:00
andrea.villa 69fc865452 Completata funzione scelta miglior combinazione 2024-11-05 13:27:36 +01:00
andrea.villa 88bc848966 Merge branch 'AvailableCombinations' into develop 2024-11-05 12:06:17 +01:00
andrea.villa 81a274563f Completata funzione identificazione combinazioni disponibili in base a configurazione 2024-11-05 12:06:06 +01:00
andrea.villa 32fa372012 Prima bozza scelta combinazioni disponibili in base a configurazione 2024-11-05 09:36:46 +01:00
andrea.villa 21da5f633d - Prima bozza gestione matrice delle rotazioni
- Adeguamento strategia 0002 e SPLITCUT a nuovo metodo gestione matrice
2024-11-04 16:52:42 +01:00
andrea.villa c24fef22a7 Merge branch 'ProcessAgainOnError' into develop 2024-10-09 13:16:22 +02:00
andrea.villa 35e8ef2482 - ProcessFeature divisa in GetProcessings(collect e raccolta strategie) e ProcessMachinings (scelta strategia migliore e applicazione lavorazioni)
- in ProcessMachinings predisposto ciclo per ricalcolare in caso di errore su Apply
- Nuova lista globale PROCESSINGS
- Calcolo tempi commentato, da riposizionare in base alle misure che si vogliono effettuare
- Predisposizione funzione per calcolo della matrice delle combinazioni (completamente da fare)
2024-10-09 13:16:11 +02:00
luca.mazzoleni 23d5f82403 Merge branch 'develop' of https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew into develop 2024-10-08 16:15:49 +02:00
luca.mazzoleni ec734ca99d - in MachiningLib aggiunta scrittura cloni geometria
- in STR0003 sistemati commenti
2024-10-08 16:11:54 +02:00
andrea.villa 34c5ecc5ec Merge branch 'SplitCut' into develop 2024-10-08 16:09:18 +02:00
andrea.villa 362f3fd2b0 - Prima implementazione creazioni fasi
- Piccole migliorie varie
- Corretta lettura info utensile profilato
- Su Proc, aggiunte alcune note pezzo
2024-08-09 16:46:51 +02:00
andrea.villa 9acd52ea10 - Prima versione strategia standard SPLITCUT e aggiunta chiamata della strategia
- Prima versione strategia core FACEBYBLADE
- Aggiunte altre UserNotes e corretto append se più note
2024-08-09 09:46:01 +02:00
107 changed files with 21653 additions and 2383 deletions
+2
View File
@@ -1 +1,3 @@
.vscode/settings.json
Compile.bat.old
/bin
+947
View File
@@ -0,0 +1,947 @@
-- BatchProcessNew.lua by Egalware s.r.l. 2025/04/24
-- 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 e carico log txt
local sMachine = BEAM.MACHINE
local sTxtLogFile
if ( BEAM.FLAG ~= 6) and ( BEAM.FLAG ~= 9) then
EgtResetCurrMachGroup()
if not EgtSetCurrMachine( sMachine) then
BEAM.ERR = 11
BEAM.MSG = 'Error selecting machine : ' .. sMachine
WriteErrToLogFile( BEAM.ERR, BEAM.MSG)
PostErrView( BEAM.ERR, BEAM.MSG)
return
end
end
if BEAM.FLAG ~= 9 then
sTxtLogFile = EgtChangePathExtension( BEAM.FILE, '.txt')
end
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')
BEAM.ERR = 12
BEAM.MSG = 'Error not configured for beams machine : ' .. sMachine
WriteErrToLogFile( BEAM.ERR, BEAM.MSG)
PostErrView( BEAM.ERR, BEAM.MSG)
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')
local FeatureLib = require( 'FeatureLib')
local JSON = require( 'JSON')
-- Variabili di modulo
local dRawW
local dRawH
-------------------------------------------------------------------------------------------------------------
-- Funzioni di supporto
local function GetDataConfig()
-- recupero utensili dal magazzino
BeamExec.GetToolsFromDB()
-- TODO da gestire eventuali errori bloccanti
return true
end
local function WriteErrToLogFile( nErr, sMsg, nRot, idCut, idTask)
local hFile = io.open( sTxtLogFile, 'a')
hFile:write( 'ERR=' .. tostring( nErr) .. '\n')
hFile:write( sMsg .. '\n')
hFile:write( 'ROT=' .. tostring( nRot or 0) .. '\n')
hFile:write( 'CUTID=' .. tostring( idCut or 0) .. '\n')
hFile:write( 'TASKID=' .. tostring( idTask or 0) .. '\n')
hFile:close()
end
local function WriteFallToLogFile( nErr, sMsg, idCut, nFall)
local hFile = io.open( sTxtLogFile, 'a')
hFile:write( 'ERR=' .. tostring( nErr) .. '\n')
hFile:write( sMsg .. '\n')
hFile:write( 'CUTID=' .. tostring( idCut or 0) .. '\n')
hFile:write( 'FALL=' .. tostring( nFall or 0) .. '\n')
hFile:close()
end
local function WriteTimeToLogFile( dTime)
local hFile = io.open( sTxtLogFile, 'a')
hFile:write( 'TIME=' .. EgtNumToString( dTime) .. '\n')
hFile:close()
end
-- Funzioni per gestire visualizzazione dopo errore e dopo warning
local function PostErrView( nErr, sMsg)
if nErr ~= 0 and ( BEAM.FLAG == 1 or BEAM.FLAG == 2) then
EgtSetView( SCE_VD.ISO_SW, false)
EgtZoom( SCE_ZM.ALL)
EgtOutBox( sMsg, 'BatchProcess (err=' .. tostring( nErr) .. ')', 'ERRORS')
end
end
local function PostWarnView( nWarn, sMsg)
if nWarn ~= 0 and ( BEAM.FLAG == 1 or BEAM.FLAG == 2) then
EgtSetView( SCE_VD.ISO_SW, false)
EgtZoom( SCE_ZM.ALL)
EgtOutBox( sMsg, 'BatchProcess (wrn=' .. tostring( nWarn) .. ')', 'WARNINGS')
end
end
-- Funzione di reset gruppo di lavoro in caso di impossibilità di inserire i pezzi
local function ResetMachGroup( PARTS)
for i = 1, #PARTS do
EgtErase( PARTS[i].id)
end
EgtRemoveMachGroup( EgtGetCurrMachGroup() or GDB_ID.NULL)
end
-- scrittura JSON risultati
-- TODO da migliorare/completare
local function WriteResultToJson( RESULT)
local sData = JSON:encode_pretty( RESULT)
-- Salvataggio e visualizzazione tabella
local sOutFile = EgtChangePathExtension( BEAM.FILE, '.json')
local DestFh = io.open( sOutFile, 'w+')
if not DestFh then
EgtOutBox( 'Error opening ' .. sOutFile, 'TestJson', 'ERROR')
return false
end
DestFh:write( sData)
DestFh:close()
return true
end
-------------------------------------------------------------------------------------------------------------
-- calcolo tempo esecuzione
TIMER:start()
EgtOutLog( ' Execution timer started')
-- script principale
local sFlag = ''
if BEAM.FLAG == 0 then
sFlag = 'GENERATE'
elseif BEAM.FLAG == 1 then
sFlag = 'MODIFY'
elseif BEAM.FLAG == 2 then
sFlag = 'SIMULATE'
elseif BEAM.FLAG == 3 then
sFlag = 'CHECK'
elseif BEAM.FLAG == 4 then
sFlag = 'CHECK+GENERATE'
elseif BEAM.FLAG == 6 then
sFlag = 'CREATE_BAR'
elseif BEAM.FLAG == 8 then
sFlag = 'CHECK_NOSIM'
elseif BEAM.FLAG == 9 then
sFlag = 'GET_TOPOLOGY'
elseif BEAM.FLAG == 10 then
sFlag = 'FLIP_ROT'
else
sFlag = 'FLAG='..tostring( BEAM.FLAG)
end
local sLog = 'BatchProcess : ' .. BEAM.FILE .. ', ' .. ( BEAM.MACHINE or EgtGetCurrMachineName()) .. ', ' .. sFlag
EgtOutLog( sLog)
-- Dati dei file
-- TODO spostare a quando flag ~= 6 e 9
local sDir, sTitle = EgtSplitPath( BEAM.FILE)
local sOriFile = sDir..sTitle..'.ori.bwe'
local sNgeFile = sDir..sTitle..'.bwe'
-- cancellazione file log txt precedente
-- in caso sia richiesta generazione senza check, verifico prima che il file log specifico non contenga errori: se sì, forzo il check
-- TODO serve ancora?? forzare sempre il check e simulazione?
if BEAM.FLAG == 0 then
local hLogFile = io.open( sTxtLogFile, 'r')
if hLogFile then
for line in hLogFile:lines() do
if EgtStartsWith( line, 'ERR') and tonumber( EgtSplitString( line, '=')[2] or 0) > 0 then
BEAM.FLAG = 4
break
end
end
hLogFile:close()
end
-- restituisce all'interfaccia il nome della topologia della feature di id passato
-- TODO valutare se fare script separato
elseif BEAM.FLAG == 9 then
if type( BEAM.FEATUREID) == 'number' then
-- creo un gruppo temporaneo dove finiranno tutte le entità che non bisogna salvare, alla fine lo si cancella
local idTempGroup = BeamLib.CreateTempGroup()
local Part = {}
Part.id = EgtGetParent( EgtGetParent( BEAM.FEATUREID))
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
Proc.Topology = FeatureLib.ClassifyTopology( Proc, Part)
else
Proc = FeatureLib.GetAdditionalInfo( Proc, Part)
Proc.Topology = FeatureLib.GetTopologyFromFeature( Proc, Part)
end
if Proc.Topology and Proc.Topology.sName then
BEAM.TOPOLOGY = Proc.Topology.sName
else
BEAM.TOPOLOGY = 'NOT_IMPLEMENTED'
end
-- si cancella gruppo temporaneo contenente entità da cancellare
EgtErase( idTempGroup)
end
return
end
-- Cancello file di log specifico
EgtEraseFile( sTxtLogFile)
-- In generale va completamente riprocessato
local bToProcess = true
local bToRecalc = false
-- se BTL, barra ed esiste già il corrispondente progetto Nge
if EgtExistsFile( sOriFile) then
bToProcess = false
EgtCopyFile( sOriFile, sNgeFile)
-- se cambiata configurazione macchina da ultima elaborazione, devo aggiornare
if EgtCompareFilesLastWriteTime( sOriFile, sMachDir .. '\\Beam\\TS3Data.lua') == -1 or
EgtCompareFilesLastWriteTime( sOriFile, sMachDir .. '\\Tools\\Tools.data') == -1 or
EgtCompareFilesLastWriteTime( sOriFile, sMachDir .. '\\' .. sMachine ..'.mlde') == -1 then
bToRecalc = true
end
end
-- Inizializzo contatori errori e avvisi
local nErrCnt = 0
local nWarnCnt = 0
-- Se da elaborare
if bToProcess then
EgtOutLog( ' +++ Processing Parts >>>')
-- Flag di barra da creare
local bCreateBar
-- Lunghezza della barra ed elenco travi
local dBarLen
-- Se necessario, apro il file Bwe
if BEAM.FLAG ~= 6 then
if not EgtOpenFile( BEAM.FILE) then
BEAM.ERR = 13
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
EgtCopyFile( BEAM.FILE, sOriFile)
-- Se già presente un gruppo di lavoro
if EgtGetFirstMachGroup() then
-- Barra già presente
bCreateBar = false
-- Rendo corrente il gruppo di lavoro
EgtSetCurrMachGroup()
-- Area tavola
local b3Tab = EgtGetTableArea()
-- Sezione del grezzo
local nRawId = EgtGetFirstRawPart()
if not nRawId then
BEAM.ERR = 14
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)
-- Calcolo posizione estremo TR o BR della tavola rispetto a sua origine in BL
local dPosY = EgtIf( BeamData.CENTER_BEAM, ( b3Tab:getDimY() + b3Raw:getDimY() * EgtIf( BeamData.RIGHT_LOAD, -1, 1)) / 2, EgtIf( BeamData.RIGHT_LOAD, 0, b3Tab:getDimY()))
BeamData.ptOriXR = Point3d( b3Tab:getDimX(), dPosY, 0)
BeamData.dPosXR = EgtIf( BeamData.RIGHT_LOAD, MCH_CR.BR, MCH_CR.TR)
-- Calcolo minimo grezzo scaricabile
BeamExec.CalcMinUnloadableRaw( b3Raw:getDimY(), b3Raw:getDimZ())
-- altrimenti devo recuperare i pezzi per creare la barra
else
-- Barra da creare
bCreateBar = true
-- Recupero l'elenco ordinato delle travi
local nPartId = EgtGetFirstPart()
while nPartId do
table.insert( PARTS, { id = nPartId, sName = ( EgtGetName( nPartId) or ( 'Id=' .. tonumber( nPartId)))})
nPartId = EgtGetNextPart( nPartId)
end
if #PARTS == 0 then
BEAM.ERR = 14
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 = ''
for i = 1, #PARTS do
sOut = sOut .. PARTS[i].sName .. ', '
end
sOut = sOut:sub( 1, -3)
EgtOutLog( 'Travi trovate : ' .. sOut, 1)
end
-- Ne recupero le dimensioni
for i = 1, #PARTS do
local Ls = EgtGetFirstNameInGroup( PARTS[i].id, 'Box')
local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD)
if not b3Solid then
BEAM.ERR = 15
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
end
end
-- Assegno lunghezza della barra
dBarLen = PARTS[1].b3PartOriginal:getDimX() + 10
if dBarLen < 2200 then
dBarLen = dBarLen + 1800
end
-- Assegno posizione prima ed unica trave
PARTS[1].dPosX = 10
end
-- Altrimenti, opero sul progetto corrente
else
-- Recupero l'identificativo del gruppo di lavoro corrente
local nMGrpId = EgtGetCurrMachGroup()
-- Barra da creare
bCreateBar = true
-- Lunghezza della barra
dBarLen = EgtGetInfo( nMGrpId, 'BARLEN', 'd')
-- Recupero l'elenco ordinato delle travi da inserire nella barra
for i = 1, 100 do
local sKey = 'PART'..tostring( i)
local sVal = EgtGetInfo( nMGrpId, sKey)
local vVal = EgtSplitString( sVal or '')
if not vVal or #vVal < 2 then break end
local nPartId = tonumber( vVal[1])
local dPosX = tonumber( vVal[2])
table.insert( PARTS, { id = nPartId, dPosX = dPosX, sName = ( EgtGetName( nPartId) or ( 'Id=' .. tonumber( nPartId)))})
end
if #PARTS == 0 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 = ''
for i = 1, #PARTS do
sOut = sOut .. PARTS[i].sName .. ', '
end
sOut = sOut:sub( 1, -3)
EgtOutLog( 'Travi trovate : ' .. sOut, 1)
end
-- Ne recupero le dimensioni
for i = 1, #PARTS do
local Ls = EgtGetFirstNameInGroup( PARTS[i].id, 'Box')
local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD)
if not b3Solid 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
end
end
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
local idTempGroup = BeamLib.CreateTempGroup()
-- Se devo creare la barra
if bCreateBar then
if #PARTS == 0 then
-- Recupero l'identificativo del gruppo di lavoro corrente
local nMGrpId = EgtGetCurrMachGroup()
-- Recupero le dimensioni della barra
dRawW = EgtGetInfo(nMGrpId, 'BARWIDTH', 'd')
dRawH = EgtGetInfo(nMGrpId, 'BARHEIGHT', 'd')
else
-- Ne verifico le dimensioni
dRawW = PARTS[1].b3PartOriginal:getDimY()
dRawH = PARTS[1].b3PartOriginal:getDimZ()
end
local vBeamErr = {}
for i = 2, #PARTS do
local dDimW = PARTS[i].b3PartOriginal:getDimY()
local dDimH = PARTS[i].b3PartOriginal:getDimZ()
if ( abs( dDimW - dRawW) > 100 * GEO.EPS_SMALL or abs( dDimH - dRawH) > 100 * GEO.EPS_SMALL) and
( abs( dDimH - dRawW) > 100 * GEO.EPS_SMALL or abs( dDimW - dRawH) > 100 * GEO.EPS_SMALL) then
table.insert( vBeamErr, i)
end
end
if #vBeamErr > 0 then
local sOut = 'Rimosse travi con sezioni diverse dalla prima :\n'
for i = #vBeamErr, 1, -1 do
sOut = sOut .. PARTS[vBeamErr[i]].sName .. '\n'
table.remove( PARTS, vBeamErr[i])
end
ResetMachGroup( PARTS)
BEAM.ERR = 16
BEAM.MSG = sOut
WriteErrToLogFile( BEAM.ERR, BEAM.MSG)
PostErrView( BEAM.ERR, BEAM.MSG)
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
ResetMachGroup( PARTS)
local sOut = 'Sezione (' .. EgtNumToString( dRawW, 2) .. ' x ' .. EgtNumToString( dRawH, 2) .. ') ' ..
'oltre i limiti della macchina (' .. EgtNumToString( BeamData.MAX_WIDTH, 2) .. ' x ' .. EgtNumToString( BeamData.MAX_HEIGHT, 2) .. ') '
BEAM.ERR = 17
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
if ( dRawW > BeamData.MAX_WIDTH + 10 * GEO.EPS_SMALL or dRawH > BeamData.MAX_HEIGHT + 10 * GEO.EPS_SMALL) and
( dRawW > BeamData.MAX_WIDTH2 + 10 * GEO.EPS_SMALL or dRawH > BeamData.MAX_HEIGHT2 + 10 * GEO.EPS_SMALL) then
ResetMachGroup( PARTS)
local sOut = 'Sezione (' .. EgtNumToString( dRawW, 2) .. ' x ' .. EgtNumToString( dRawH, 2) .. ') ' ..
'oltre i limiti della macchina (' .. EgtNumToString( BeamData.MAX_WIDTH, 2) .. ' x ' .. EgtNumToString( BeamData.MAX_HEIGHT, 2) .. ') ' ..
'e (' .. EgtNumToString( BeamData.MAX_WIDTH2, 2) .. ' x ' .. EgtNumToString( BeamData.MAX_HEIGHT2, 2) .. ')'
BEAM.ERR = 17
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
-- Verifico sezione barra non troppo piccola
if dRawW < BeamData.MIN_WIDTH - 10 * GEO.EPS_SMALL or dRawH < BeamData.MIN_HEIGHT - 10 * GEO.EPS_SMALL then
ResetMachGroup( PARTS)
local sOut = 'Sezione (' .. EgtNumToString( dRawW, 2) .. ' x ' .. EgtNumToString( dRawH, 2) .. ') ' ..
'sotto i limiti della macchina (' .. EgtNumToString( BeamData.MIN_WIDTH, 2) .. ' x ' .. EgtNumToString( BeamData.MIN_HEIGHT, 2) .. ')'
BEAM.ERR = 17
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
-- Lunghezza della barra
local dRawL = dBarLen + 0.1
-- Sovramateriale di testa
local dOvmHead = 0
if #PARTS > 0 then
dOvmHead = PARTS[1].dPosX or 0
end
-- Sistemo le travi nel grezzo
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
local nMGrpId = EgtGetCurrMachGroup()
EgtSetInfo(nMGrpId, 'BARHEIGHT', dRawH)
EgtSetInfo(nMGrpId, 'BARWIDTH', dRawW)
end
-- sistemazioni per pezzi nella barra
else
-- ciclo sui grezzi
local nRawId = EgtGetFirstRawPart()
while nRawId do
-- massimo un pezzo per grezzo
local nPartId = EgtGetFirstPartInRawPart( nRawId)
-- box del pezzo
local Ls = EgtGetFirstNameInGroup( nPartId, 'Box')
local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD)
-- se nel grezzo c'è un pezzo
if nPartId then
-- creo o pulisco gruppo geometrie aggiuntive
BeamLib.CreateOrEmptyAddGroup( nPartId)
-- aggiungo faccia per taglio iniziale al pezzo
BeamLib.AddPartStartFace( nPartId, b3Solid)
-- aggiungo faccia per taglio finale al pezzo
BeamLib.AddPartEndFace( nPartId, b3Solid)
end
-- passo al successivo grezzo
nRawId = EgtGetNextRawPart( nRawId)
end
-- elimino le lavorazioni
EgtRemoveAllOperations()
-- Recupero l'identificativo del gruppo di lavoro corrente
local nMGrpId = EgtGetCurrMachGroup()
-- Recupero l'elenco ordinato delle travi da inserire nella barra
for i = 1, 100 do
local sKey = 'PART'..tostring( i)
local sVal = EgtGetInfo( nMGrpId, sKey)
local vVal = EgtSplitString( sVal or '')
if not vVal or #vVal < 2 then break end
local nPartId = tonumber( vVal[1])
local dPosX = tonumber( vVal[2])
table.insert( PARTS, { nInd = #PARTS + 1, id = nPartId, dPosX = dPosX, sName = ( EgtGetName( nPartId) or ( 'Id=' .. tonumber( nPartId)))})
end
-- se lunghezza barra non settata, la leggo ora
if not dBarLen then
dBarLen = EgtGetInfo( nMGrpId, 'BARLEN', 'd')
end
-- Recupero tutte le informazioni dei pezzi
local dLen = dBarLen
for i = 1, #PARTS do
-- aggiorno grezzo precedente
PARTS[i].idRaw = EgtGetRawPartFromPart( PARTS[i].id)
PARTS[i].bIsLastPart = ( i == #PARTS)
-- dimensioni del grezzo ( comprende sovramateriale di testa e lavorazione di coda per separazione)
PARTS[i].b3Raw = EgtGetRawPartBBox( PARTS[i].idRaw)
PARTS[i].dRawLength = PARTS[i].b3Raw:getDimX()
PARTS[i].dRawWidth = PARTS[i].b3Raw:getDimY()
PARTS[i].dRawHeight = PARTS[i].b3Raw:getDimZ()
-- dimensione pezzo finito
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()
PARTS[i].bSquareSection = abs( PARTS[i].dWidth - PARTS[i].dHeight) < 100 * GEO.EPS_SMALL
PARTS[i].nIndexInParts = i
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)
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)
PARTS[i].dHeadOverMaterial = dDeltaS
-- lunghezza grezzo (comprende sovramateriale di testa e mm tagliati in coda dalla lavorazione, tipicamente 5.4mm dello spessore lama)
local dCrawLen = PARTS[i].dRawLength
-- materiale tolto in coda dalla lavorazione di separazione
local dDeltaE = dCrawLen - PARTS[i].dLength - dDeltaS
local dDeltaNextPiece
if PARTS[i+1] then
dDeltaNextPiece = PARTS[i+1].dPosX - ( dBarLen - dLen) - dCrawLen + dDeltaE
else
dDeltaNextPiece = 10000
end
PARTS[i].dDistanceToNextPiece = dDeltaNextPiece
-- aggiorno la lunghezza residua della barra
dLen = dLen - dCrawLen
PARTS[i].dRestLength = dLen
end
end
-- Se richiesta solo barra, esco
if BEAM.FLAG == 6 then
-- Completamento senza errori e avvisi
if nWarnCnt == 0 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
end
-- Imposto Nome file CN
local _, sName, _ = EgtSplitPath( BEAM.FILE)
EgtSetInfo( EgtGetCurrMachGroup(), 'NcName', sName .. '.cnc')
-- Abilito Vmill
EgtSetInfo( EgtGetCurrMachGroup(), 'Vm', '1')
-- Aggiorno Setup utensili
EgtImportSetup()
-- Lavoro le features
-- TODO gestire errori e messaggi di ritorno in questo caso
if not GetDataConfig() then return end
BeamExec.GetProcessings( PARTS, BEAM.FLAG == 10)
BeamExec.GetCombinationMatrix( PARTS, BEAM.FLAG == 10)
BeamExec.ProcessMachinings( PARTS, BEAM.FLAG == 10)
local sOutput = ''
-- scrittura txt risultati
for i = 1, #RESULT do
local sMsg = ''
if RESULT[i].sType == 'Feature' then
if RESULT[i].ChosenStrategy.bIsApplyOk then
sMsg = RESULT[i].ChosenStrategy.sInfo
else
sMsg = RESULT[i].ChosenStrategy.sApplyInfo
end
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
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)
-- 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)
BEAM.ERR = 19
BEAM.MSG = sMsg
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)
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
BEAM.ERR = 0
BEAM.MSG = sMsg
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 - ( 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)
end
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)
EgtCopyFile( sNgeFile, sOriFile)
-- Visualizzazione avvisi o errori
if #sOutput > 0 then EgtOutLog( sOutput) end
if nErrCnt > 0 then
PostErrView( 19, sOutput)
elseif nWarnCnt > 0 then
PostWarnView( 19, sOutput)
end
-- Altrimenti carico il progetto salvato e dichiaro nessun errore
else
EgtOutLog( ' +++ Loading Project already processed >>>')
-- Carico il progetto già fatto
EgtOpenFile( sNgeFile)
-- Passo in modalità lavora
EgtSetCurrMachGroup( EgtGetLastMachGroup())
-- Se necessario eseguo aggiornamento con setup corrente e ricalcolo delle lavorazioni
if bToRecalc or BEAM.FLAG == 3 or BEAM.FLAG == 4 or BEAM.FLAG == 8 then
EgtOutLog( ' +++ Recalculating all dispositions and machinings >>>')
EgtImportSetup()
EgtApplyAllMachinings()
-- Salvo il progetto
EgtSaveFile( sNgeFile)
-- copio come originale (per dichiarare progetto ricalcolato)
EgtCopyFile( sNgeFile, sOriFile)
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 >>>')
-- verifico setup
local bSetUpOk, SetUpErrors = EgtVerifyCurrSetup()
if not bSetUpOk then
local sToolsList = ""
for ToolIndex = 1, #SetUpErrors do
sToolsList = sToolsList .. SetUpErrors[ToolIndex]
if ToolIndex ~= #SetUpErrors then
sToolsList = sToolsList .. ", "
end
end
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
local bSimOk, nErr, sErr = EgtSimulate()
if not bSimOk then
if nErr == MCH_SHE.INIT then
BEAM.ERR = 19
BEAM.MSG = 'Error starting simulation'
elseif nErr == MCH_SHE.COLLISION then
BEAM.ERR = 22
BEAM.MSG = 'Head-part collision'
elseif nErr == MCH_SHE.OUTSTROKE then
BEAM.ERR = 23
BEAM.MSG = 'Axis outstroke ' .. sErr
elseif nErr == MCH_SHE.SPECIAL then
BEAM.ERR = 24
BEAM.MSG = 'Special error ' .. sErr
else
BEAM.ERR = 25
BEAM.MSG = 'General failure (contact supplier)'
end
BEAM.ROT = 0
BEAM.CUTID = 0
BEAM.TASKID = 0
local vItem = EgtSplitString( sErr, ';') or {}
for i = 1, #vItem do
vItem[i] = EgtTrim( vItem[i] or '')
if string.find( vItem[i], 'CUTID', 1, true) then
BEAM.CUTID = EgtGetVal( vItem[i], 'CUTID', 'i') or 0
elseif string.find( vItem[i], 'TASKID', 1, true) then
BEAM.TASKID = EgtGetVal( vItem[i], 'TASKID', 'i') or 0
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
-- *** Genero programma CN *** ( se richiesto)
local bIsGenerationEnabled = ( EgtVerifyKeyOption( 110) == false)
if bIsGenerationEnabled and ( BEAM.FLAG == 0 or BEAM.FLAG == 4) then
EgtOutLog( ' +++ Generating NC part program >>>')
local sInfo = 'EgtCAM5' .. EgtIf( EgtIs64bit(), ' 64bit', '')
if EgtGetExeVersion then
sInfo = sInfo .. ' ver.' .. EgtGetExeVersion()
end
sInfo = sInfo .. ' - '
if not EgtGenerate( '', sInfo .. sNgeFile) then
BEAM.ERR = 20
local _, sName, _ = EgtSplitPath( BEAM.FILE)
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
-- *** Eseguo stima tempi ***
EgtOutLog( ' +++ Estimating T&L >>>')
if not EgtEstimate( '', 'EgtCAM5 - ' .. sNgeFile) then
BEAM.ERR = 21
local _, sName, _ = EgtSplitPath( BEAM.FILE)
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')
local sTime = 'Total Time = ' .. EgtNumToString( Ttot, 1)
EgtOutLog( sTime)
-- Se modifica o simula, imposto la vista ISO 3d opportuna
if BEAM.FLAG == 1 or BEAM.FLAG == 2 then
local vView = { SCE_VD.ISO_NW, SCE_VD.ISO_SW, SCE_VD.ISO_NE, SCE_VD.ISO_SE}
local nV = min( max( BeamData.SIMUL_VIEW_DIR or 2, 1), 4)
EgtSetView( vView[nV], false)
end
-- Completamento senza errori e avvisi
if nWarnCnt == 0 then
BEAM.ERR = 0
BEAM.MSG = '---'
WriteErrToLogFile( BEAM.ERR, BEAM.MSG)
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')
+49
View File
@@ -0,0 +1,49 @@
@echo off
setlocal enabledelayedexpansion
set LUAC=C:\EgtProg\Dll32\luac54.exe
set ROOT=%cd%\
set OUTBASE=bin
if not exist %OUTBASE% mkdir %OUTBASE%
REM Compile all .lua files excluding bin\ and any dot folders/files
for /f "delims=" %%F in ('dir /b /s /a-d *.lua ^| findstr /v /i /c:"\%OUTBASE%\"') do (
set FULL=%%F
set REL=!FULL:%ROOT%=!
REM Skip if REL starts with '.' or contains '\.'
echo !REL! | findstr /r /c:"^\." /c:"\\\." >nul
if errorlevel 1 (
set OUT=%OUTBASE%\!REL!
for %%D in ("!OUT!") do mkdir "%%~dpD" 2>nul
echo Compiling: !REL!
%LUAC% -o "!OUT!" -s "!FULL!"
) else (
echo Skipping hidden/dot path: !REL!
)
)
REM Copy all .json files excluding bin\ and any dot folders/files
for /f "delims=" %%F in ('dir /b /s /a-d *.json ^| findstr /v /i /c:"\%OUTBASE%\"') do (
set FULL=%%F
set REL=!FULL:%ROOT%=!
REM Skip if REL starts with '.' or contains '\.'
echo !REL! | findstr /r /c:"^\." /c:"\\\." >nul
if errorlevel 1 (
set OUT=%OUTBASE%\!REL!
for %%D in ("!OUT!") do mkdir "%%~dpD" 2>nul
echo Copying: !REL!
copy /Y "!FULL!" "!OUT!" >nul
) else (
echo Skipping hidden/dot path: !REL!
)
)
echo Done.
pause
+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')
Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.0 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.6 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.8 KiB

File diff suppressed because it is too large Load Diff
+1607 -296
View File
File diff suppressed because it is too large Load Diff
+785 -83
View File
@@ -8,7 +8,8 @@ local BeamLib = {}
-- Include
require( 'EgtBase')
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
EgtOutLog( ' BeamLib started', 1)
@@ -32,22 +33,9 @@ function BeamLib.AddPartStartFace( PartId, b3Solid)
return false, sErr
end
-- applico gli opportuni attributi di feature
EgtSetName( nStmId, 'StartCut')
EgtSetInfo( nStmId, 'HEAD_ADD_CUT', 1)
EgtSetInfo( nStmId, 'GRP', 1)
EgtSetInfo( nStmId, 'PRC', 340)
-- verifico se sostituisce un taglio di testa già presente
local nProcId = EgtGetFirstInGroup( EgtGetFirstNameInGroup( PartId, 'Processings') or GDB_ID.NULL)
while nProcId do
local nGrp = EgtGetInfo( nProcId, 'GRP', 'i') or 0
local nProc = EgtGetInfo( nProcId, 'PRC', 'i') or 0
if ( nGrp == 1 or nGrp == 2) and nProc == 10 then
local ptC, vtN = EgtSurfTmFacetCenter( nProcId, 0, GDB_ID.ROOT)
if ptC and vtN and AreSameVectorApprox( vtN, X_AX()) and abs( ptC:getX() - b3Solid:getMax():getX()) < 10 * GEO.EPS_SMALL then
EgtSetInfo( nStmId, 'ORI', nProcId)
end
end
nProcId = EgtGetNext( nProcId)
end
EgtSetInfo( nStmId, 'PRC', 10) -- ex 340
return true
end
@@ -70,41 +58,288 @@ function BeamLib.AddPartEndFace( PartId, b3Solid)
return false, sErr
end
-- applico gli opportuni attributi di feature
EgtSetName( nStmId, 'EndCut')
EgtSetInfo( nStmId, 'HEAD_ADD_CUT', 1)
EgtSetInfo( nStmId, 'GRP', 2)
EgtSetInfo( nStmId, 'PRC', 350)
-- verifico se sostituisce un taglio di coda già presente
local nProcId = EgtGetFirstInGroup( EgtGetFirstNameInGroup( PartId, 'Processings') or GDB_ID.NULL)
while nProcId do
local nGrp = EgtGetInfo( nProcId, 'GRP', 'i') or 0
local nProc = EgtGetInfo( nProcId, 'PRC', 'i') or 0
if ( nGrp == 1 or nGrp == 2) and nProc == 10 then
local ptC, vtN = EgtSurfTmFacetCenter( nProcId, 0, GDB_ID.ROOT)
if ptC and vtN and AreSameVectorApprox( vtN, -X_AX()) and abs( ptC:getX() - b3Solid:getMin():getX()) < 10 * GEO.EPS_SMALL then
EgtSetInfo( nStmId, 'ORI', nProcId)
end
end
nProcId = EgtGetNext( nProcId)
end
EgtSetInfo( nStmId, 'PRC', 10) -- ex 350
return true
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.AddPhaseWithRawParts( Part, OriXR, PosXR, dDeltaSucc)
EgtAddPhase()
local nRawId = Part.idRaw
local dRawMove = 0
while nRawId do
EgtKeepRawPart( nRawId)
EgtMoveToCornerRawPart( nRawId, OriXR, PosXR)
EgtMoveRawPart( nRawId, Vector3d( - dRawMove, 0, 0))
if dRawMove == 0 then dRawMove = dRawMove + dDeltaSucc end
dRawMove = dRawMove + EgtGetRawPartBBox( nRawId):getDimX()
nRawId = EgtGetNextRawPart( nRawId)
function BeamLib.GetPartBoxWithHeadTail( Part, sSide)
local _sSide = sSide or ''
-- si può usare il box del grezzo che contiene sempre il sovramateriale di testa
if _sSide == 'Head' then
local b3WithHead = BBox3d( Part.b3Raw)
return b3WithHead
-- se è l'ultimo pezzo della barra si aggiunge il box dell'eventuale grezzo successivo
-- se non lo è, si estende il box del pezzo fino alla fine della barra
elseif _sSide == 'Tail' then
local b3WithTail = BBox3d( Part.b3Part)
if Part.bIsLastPart then
local nNextRawId = EgtGetNextRawPart( Part.idRaw)
if nNextRawId then
local b3Tail = EgtGetRawPartBBox( nNextRawId)
b3WithTail:Add( b3Tail)
end
else
-- per il punto di inizio barra si parte dal box del grezzo perchè contiene già il sovramateriale spessore lama/catena in coda (la restLength non lo comprende)
local ptXMin = Point3d( Part.b3Raw:getMin():getX() - Part.dRestLength, Part.b3Part:getMin():getY(), Part.b3Part:getMin():getZ())
b3WithTail:Add( ptXMin)
end
return b3WithTail
-- per aggiungere entrambi si procede come per la coda ma partendo dal box del grezzo, che già contiene la testa
elseif sSide == 'HeadTail' then
local b3WithHeadTail = BBox3d( Part.b3Raw)
if Part.bIsLastPart then
local nNextRawId = EgtGetNextRawPart( Part.idRaw)
if nNextRawId then
local b3Tail = EgtGetRawPartBBox( nNextRawId)
b3WithHeadTail:Add( b3Tail)
end
else
-- per il punto di inizio barra si parte dal box del grezzo perchè contiene già il sovramateriale spessore lama/catena in coda (la restLength non lo comprende)
local ptXMin = Point3d( Part.b3Raw:getMin():getX() - Part.dRestLength, Part.b3Part:getMin():getY(), Part.b3Part:getMin():getZ())
b3WithHeadTail:Add( ptXMin)
end
return b3WithHeadTail
-- sSide non definito, si restituisce il box del pezzo con l'aggiunta dello spessore lama/catena in coda
else
local b3WithSplit = BBox3d( Part.b3Part)
-- per il punto di inizio barra si parte dal box del grezzo perchè contiene già il sovramateriale spessore lama/catena in coda (la restLength non lo comprende)
local ptXMin = Point3d( Part.b3Raw:getMin():getX(), Part.b3Part:getMin():getY(), Part.b3Part:getMin():getZ())
b3WithSplit:Add( ptXMin)
return b3WithSplit
end
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.GetPartSplittingPoints( Part)
local PartSplittingPoints = {}
local dPartLength = Part.b3Part:getDimX()
local dMaxSegmentLength = BeamData.LONGCUT_MAXLEN
local dMaxSegmentLengthOnEdges = BeamData.LONGCUT_ENDLEN
if dPartLength < dMaxSegmentLength + 10 * GEO.EPS_SMALL then
return {}
elseif dPartLength >= dMaxSegmentLength + 10 * GEO.EPS_SMALL
and dPartLength < 3 * dMaxSegmentLengthOnEdges + 10 * GEO.EPS_SMALL then
local dXPartCentralPoint = ( Part.b3Part:getMax():getX() - Part.b3Part:getMin():getX()) / 2
table.insert( PartSplittingPoints, Point3d( dXPartCentralPoint, 0, 0))
else
-- punto estremo destro
local dSplitXRight = Part.b3Part:getMax():getX() - dMaxSegmentLengthOnEdges
table.insert( PartSplittingPoints, Point3d( dSplitXRight, 0, 0))
-- punti centrali
local dPartCentralLength = dPartLength - 2 * dMaxSegmentLengthOnEdges
local nSplitParts = max( ceil( dPartCentralLength / dMaxSegmentLength + 10 * GEO.EPS_SMALL), 1)
local dSplitPartsLen = dPartCentralLength / nSplitParts
for i = 1, ( nSplitParts - 1) do
local ptOn
local dCurrentPointX = dSplitXRight - i * dSplitPartsLen
ptOn = Point3d( dCurrentPointX, 0, 0)
table.insert( PartSplittingPoints, ptOn)
end
-- punto estremo sinistro
local dSplitXLeft = Part.b3Part:getMin():getX() + dMaxSegmentLengthOnEdges
table.insert( PartSplittingPoints, Point3d( dSplitXLeft, 0, 0))
end
return PartSplittingPoints
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.AddPhaseWithRawParts( idRaw, OriXR, PosXR, dDeltaSucc)
local nPhase = EgtAddPhase()
-- si aprono i limiti tavola per permettere rotazioni di pezzi più larghi della tavola
EgtSetTableAreaOffset( 2000, 2000, 2000, 2000)
local dRawMove = 0
while idRaw do
EgtKeepRawPart( idRaw)
EgtMoveToCornerRawPart( idRaw, OriXR, PosXR)
EgtMoveRawPart( idRaw, Vector3d( - dRawMove, 0, 0))
if dRawMove == 0 then dRawMove = dRawMove + dDeltaSucc end
dRawMove = dRawMove + EgtGetRawPartBBox( idRaw):getDimX()
idRaw = EgtGetNextRawPart( idRaw)
end
-- salvo info nuova fase aggiunta
local MachExtraInfo = { sType = 'DISP',
nPhase = nPhase}
table.insert( DB_MACH_APPLIED, MachExtraInfo)
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.IsPointOnBoxLimit( ptPointToCheck, b3Solid)
local bOnBoxLimit = false
if abs( ptPointToCheck:getX() - b3Solid:getMax():getX()) < 100 * GEO.EPS_SMALL or
abs( ptPointToCheck:getX() - b3Solid:getMin():getX()) < 100 * GEO.EPS_SMALL or
abs( ptPointToCheck:getY() - b3Solid:getMax():getY()) < 100 * GEO.EPS_SMALL or
abs( ptPointToCheck:getY() - b3Solid:getMin():getY()) < 100 * GEO.EPS_SMALL or
abs( ptPointToCheck:getZ() - b3Solid:getMax():getZ()) < 100 * GEO.EPS_SMALL or
abs( ptPointToCheck:getZ() - b3Solid:getMin():getZ()) < 100 * GEO.EPS_SMALL then
bOnBoxLimit = true
end
return bOnBoxLimit
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.SetOpenSide( nPathInt, b3Solid)
-- fondo tra loro le curve compatibili
EgtMergeCurvesInCurveCompo( nPathInt)
-- vettore indici lati aperti
local vOpen = {}
-- ciclo sulle curve elementari della composita
local _, nNumEnt = EgtCurveDomain( nPathInt)
for i = 0, nNumEnt - 1 do
-- se segmento di retta
if EgtCurveCompoRadius( nPathInt, i) == -1 then
-- verifico se giace in uno dei piani limite del pezzo quindi se è un lato aperto
local ptIni = EgtUP( nPathInt, i, GDB_RT.GLOB)
local ptFin = EgtUP( nPathInt, i + 1, GDB_RT.GLOB)
if BeamLib.IsPointOnBoxLimit( ptIni, b3Solid) and BeamLib.IsPointOnBoxLimit( ptFin, b3Solid) then
-- aggiorno il vettore dei lati aperti
table.insert( vOpen, i)
end
end
end
-- assegno gli indici dei lati aperti
EgtSetInfo( nPathInt, 'OPEN', vOpen)
return true
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.ConvertToClosedCurve( Proc, AuxId)
local bCurveModified = false
if not EgtCurveIsClosed( AuxId) then
local NewId, nCount = EgtExtractSurfTmFacetLoops( Proc.id, 0, EgtGetParent( Proc.id))
if NewId then
-- elimino eventuali loop interni (non dovrebbero comunque esserci)
for i = 1, nCount - 1 do
EgtErase( NewId + i)
end
local vtExtr = EgtCurveExtrusion( AuxId, GDB_ID.ROOT)
-- sostituisco il loop esterno alla curva originale
EgtModifyCurveExtrusion( NewId, vtExtr, GDB_ID.ROOT)
EgtRelocate( NewId, AuxId, GDB_IN.AFTER)
EgtErase( AuxId)
EgtChangeId( NewId, AuxId)
bCurveModified = true
-- sistemo i lati aperti
local vFacAdj = EgtSurfTmFacetAdjacencies( Proc.id, 0)[1]
if vFacAdj then
local vOpen = {}
for i = 1, #vFacAdj do
if vFacAdj[i] < 0 then
table.insert( vOpen, i - 1)
end
end
EgtSetInfo( AuxId, 'OPEN', vOpen)
end
end
end
return true, bCurveModified
end
-------------------------------------------------------------------------------------------------------------
--- funzione che inverte il grezzo testa-coda
function BeamLib.InvertRawPart( Part, nNumberOfRotations)
-- se non si deve ruotare, si esce subito
if nNumberOfRotations == 0 then
return
end
-- box del solido
local b3BoxPart = EgtGetBBoxGlob( EgtGetFirstNameInGroup( Part.id or GDB_ID.NULL, 'Box') or GDB_ID.NULL, GDB_BB.EXACT)
-- box esatto del pezzo
local b3BoxExact = EgtGetBBoxGlob( Part.id or GDB_ID.NULL, GDB_BB.EXACT)
-- rotazione
local dAngRot = nNumberOfRotations * 90
EgtRotatePartInRawPart( Part.id, Z_AX(), dAngRot)
-- correggo per eccentricità solido rispetto a geometria complessiva del pezzo
local vtEccOri = b3BoxPart:getCenter() - b3BoxExact:getCenter()
local vtEccRot = Vector3d( vtEccOri)
vtEccRot:rotate( Z_AX(), dAngRot)
EgtMovePartInRawPart( Part.id, ( vtEccOri - vtEccRot))
-- si salva posizione corrente
if Part.bIsInverted then
Part.bIsInverted = false
else
Part.bIsInverted = true
end
end
-------------------------------------------------------------------------------------------------------------
--- funzione che ruota il grezzo
function BeamLib.RotateRawPart( Part, nNumberOfRotations)
-- sistemo numero rotazioni in caso sia negativa
if nNumberOfRotations < 0 then
nNumberOfRotations = nNumberOfRotations + 4
end
-- primo posizionamento
if nNumberOfRotations == 0 then
; -- il pezzo è già in posizione
-- rotazione 90°
elseif nNumberOfRotations == 1 then
local dDeltaYZ = EgtGetRawPartBBox( Part.idRaw):getDimY() - EgtGetRawPartBBox( Part.idRaw):getDimZ()
local vtMove = Vector3d( 0, dDeltaYZ / 2 * EgtIf( BeamData.RIGHT_LOAD, -1, 1), dDeltaYZ / 2)
local bPreMove = dDeltaYZ < 0
-- ruoto le travi della fase corrente
local nRId = Part.idRaw
while nRId do
if bPreMove then EgtMoveRawPart( nRId, vtMove) end
local bIsRotationOK = EgtRotateRawPart( nRId, X_AX(), EgtIf( BeamData.RIGHT_LOAD, -90, 90))
if not bIsRotationOK then error( 'UNEXPECTED ERROR: rotation of the raw not executed') end
if not bPreMove then EgtMoveRawPart( nRId, vtMove) end
nRId = EgtGetNextRawPart( nRId)
end
-- rotazione 180°
elseif nNumberOfRotations == 2 then
-- ribalto le travi della fase corrente
local nRId = Part.idRaw
while nRId do
EgtRotateRawPart( nRId, X_AX(), 180)
nRId = EgtGetNextRawPart( nRId)
end
-- rotazione 270°
elseif nNumberOfRotations == 3 then
local dDeltaYZ = EgtGetRawPartBBox( Part.idRaw):getDimY() - EgtGetRawPartBBox( Part.idRaw):getDimZ()
local vtMove = Vector3d( 0, dDeltaYZ / 2 * EgtIf( BeamData.RIGHT_LOAD, -1, 1), dDeltaYZ / 2)
local bPreMove = dDeltaYZ < 0
-- ruoto le travi della fase corrente
local nRId = Part.idRaw
while nRId do
if bPreMove then EgtMoveRawPart( nRId, vtMove) end
local bIsRotationOK = EgtRotateRawPart( nRId, X_AX(), EgtIf( BeamData.RIGHT_LOAD, 90, -90))
if not bIsRotationOK then error( 'UNEXPECTED ERROR: rotation of the raw not executed') end
if not bPreMove then EgtMoveRawPart( nRId, vtMove) end
nRId = EgtGetNextRawPart( nRId)
end
end
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.CreateAddGroup( PartId, sGroupName)
AddGrpId = EgtGroup( PartId or GDB_ID.NULL)
if not AddGrpId then
return false
end
-- assegno nome, flag di layer per gruppo di lavoro e colore
EgtSetName( AddGrpId, sGroupName)
EgtSetInfo( AddGrpId, GDB_SI.MGRPONLY, EgtGetCurrMachGroup())
EgtSetColor( AddGrpId, Color3d( 80, 160, 160, 25))
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.CreateOrEmptyAddGroup( PartId)
-- recupero i dati del gruppo aggiuntivo
@@ -118,19 +353,33 @@ 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, 50))
BeamLib.CreateAddGroup( PartId, sMchGrp)
return true
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.CreateTempGroup()
local idTempGroup = BeamLib.GetTempGroup()
-- se non esiste, lo creo
if not idTempGroup then
idTempGroup = EgtGroup( GDB_ID.ROOT)
EgtSetName( idTempGroup, "#TEMP_GROUP#")
EgtSetColor( idTempGroup, Color3d( 80, 160, 160, 1))
EgtSetLevel( idTempGroup, GDB_LV.TEMP)
EgtSetStatus( idTempGroup, GDB_ST.OFF)
end
return idTempGroup
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.GetTempGroup()
local idTempGroup = EgtGetFirstNameInGroup( GDB_ID.ROOT, "#TEMP_GROUP#") or nil
return idTempGroup
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.GetAddGroup( PartId)
-- recupero il nome del gruppo di lavoro corrente
@@ -148,25 +397,27 @@ end
-------------------------------------------------------------------------------------------------------------
-- restituisce le facce della parte interessate dalla feature Proc
-- TODO da spostare in FeatureLib???
-- TODO le feature 1 faccia devono essere settate aperte sulla faccia indicata dalla normale
function BeamLib.GetAffectedFaces( Proc, Part)
local vtFacesAffected = { bTop = false, bBottom = false, bFront = false, bBack = false, bLeft = false, bRight = false}
if Proc.b3Box and not Proc.b3Box:isEmpty() then
if Proc.b3Box:getMax():getZ() > Part.b3Solid:getMax():getZ() - 500 * GEO.EPS_SMALL then
if Proc.b3Box:getMax():getZ() > Part.b3Part:getMax():getZ() - 500 * GEO.EPS_SMALL then
vtFacesAffected.bTop = true
end
if Proc.b3Box:getMin():getZ() < Part.b3Solid:getMin():getZ() + 500 * GEO.EPS_SMALL then
if Proc.b3Box:getMin():getZ() < Part.b3Part:getMin():getZ() + 500 * GEO.EPS_SMALL then
vtFacesAffected.bBottom = true
end
if Proc.b3Box:getMin():getY() < Part.b3Solid:getMin():getY() + 500 * GEO.EPS_SMALL then
if Proc.b3Box:getMin():getY() < Part.b3Part:getMin():getY() + 500 * GEO.EPS_SMALL then
vtFacesAffected.bFront = true
end
if Proc.b3Box:getMax():getY() > Part.b3Solid:getMax():getY() - 500 * GEO.EPS_SMALL then
if Proc.b3Box:getMax():getY() > Part.b3Part:getMax():getY() - 500 * GEO.EPS_SMALL then
vtFacesAffected.bBack = true
end
if Proc.b3Box:getMin():getX() < Part.b3Solid:getMin():getX() + 500 * GEO.EPS_SMALL then
if Proc.b3Box:getMin():getX() < Part.b3Part:getMin():getX() + 500 * GEO.EPS_SMALL then
vtFacesAffected.bLeft = true
end
if Proc.b3Box:getMax():getX() > Part.b3Solid:getMax():getX() - 500 * GEO.EPS_SMALL then
if Proc.b3Box:getMax():getX() > Part.b3Part:getMax():getX() - 500 * GEO.EPS_SMALL then
vtFacesAffected.bRight = true
end
end
@@ -174,7 +425,7 @@ function BeamLib.GetAffectedFaces( Proc, Part)
return vtFacesAffected
end
---------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------
function BeamLib.GetNearestOrthoOpposite( vtRef, vtNorm)
-- se definita anche la normale alla faccia, elimino la parte di vtRef parallela a questa
local vtMyRef = Vector3d( vtRef)
@@ -209,7 +460,7 @@ function BeamLib.GetNearestOrthoOpposite( vtRef, vtNorm)
return nil
end
---------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------
function BeamLib.GetNearestParalOpposite( vtRef, vtNorm)
-- se definita anche la normale alla faccia, elimino la parte di vtRef parallela a questa
local vtMyRef = Vector3d( vtRef)
@@ -243,7 +494,29 @@ 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
-------------------------------------------------------------------------------------------------------------
-- Funzione per determinare se la faccia ha lati molto corti (trascurabili) ed è quindi approssimabile ad una 3 facce
function BeamLib.Is3EdgesApprox( Proc, idFace, nAddGrpId)
nAddGrpId = nAddGrpId or BeamLib.GetAddGroup( Proc.idPart)
@@ -267,7 +540,7 @@ function BeamLib.Is3EdgesApprox( Proc, idFace, nAddGrpId)
elseif nEntityCount then
for i = 1, nEntityCount do
local dLength = EgtCurveCompoLength( nContourId, i - 1)
if dLength < 15 then nEdges = nEdges - 1 end
if dLength < 5 then nEdges = nEdges - 1 end
end
end
if nEdges == 3 then bResult = true end
@@ -278,41 +551,192 @@ function BeamLib.Is3EdgesApprox( Proc, idFace, nAddGrpId)
end
-------------------------------------------------------------------------------------------------------------
-- sovrascrivo i parametri personalizzati salvati su Proc a quelli di default dalla strategia
-- N.B. : I parametri personalizzati non più presenti tra i default della strategia, verranno ignorati. Quelli extra avranno valore di default
-- Il controllo deve essere fatto SEMPRE all'inizio di ogni strategia, per controllare conformità parametri custom
function BeamLib.GetUpdateCustomParameters( CustomStrategyParamList, DefaultStrategyParamList)
if CustomStrategyParamList and #CustomStrategyParamList > 0 then
for i = 1, #DefaultStrategyParamList do
for j = 1, #CustomStrategyParamList do
if DefaultStrategyParamList[i].sName == CustomStrategyParamList[j].sName then
DefaultStrategyParamList[i].sValue = CustomStrategyParamList[j].sValue
-- funzione con valore di default in caso la GetSetupInfo della testa della macchina non avesse la funzione definita
function BeamLib.GetMinNzDownUpDefault( b3Raw, vtNFace, vtToolDirection, Tool)
return -2
end
-------------------------------------------------------------------------------------------------------------
-- funzione con valore di default in caso la GetSetupInfo della testa della macchina non avesse la funzione definita
function BeamLib.GetMinNzDefault( vtNFace, Tool)
return 0
end
-------------------------------------------------------------------------------------------------------------
-- funzione con valore di default in caso la GetSetupInfo della testa della macchina non avesse la funzione definita
function BeamLib.GetMaxNzDefault( vtNFace, Tool)
return 0
end
-- TODO bisogna recuperare il nome del parametro NGE, perchè in questo caso è forzato
-------------------------------------------------------------------------------------------------------------
function BeamLib.GetPieceGeneralParameters( Part, DefaultGeneralParamList)
local GeneralParameters = {}
-- si salvano sul pezzo le note forzate, altrimenti si leggeranno dopo, quando si prendono i dati della strategia
for i = 1, #DefaultGeneralParamList do
local sParamNameNGE = DefaultGeneralParamList[i].sNameNge
local xParameterValue = EgtGetInfo( Part.id, sParamNameNGE, 's') or nil
-- se il paraemtro esiste, salvataggio dato su lista con accesso diretto
if xParameterValue then
if DefaultGeneralParamList[i].sType == 'b' then
GeneralParameters[DefaultGeneralParamList[i].sName] = xParameterValue == 'true' or xParameterValue == '1' or xParameterValue == true
elseif DefaultGeneralParamList[i].sType == 'd' then
if #DefaultGeneralParamList[i].sValue > 0 then
GeneralParameters[DefaultGeneralParamList[i].sName] = tonumber( xParameterValue)
-- stringa vuota equivale a non passare alcun valore (deciderà la strategia)
else
GeneralParameters[DefaultGeneralParamList[i].sName] = nil
end
else --DefaultGeneralParamList[i].sType == 's' or DefaultGeneralParamList[i].sType == 'combo'
GeneralParameters[DefaultGeneralParamList[i].sName] = xParameterValue
end
else
if GENERAL_PARAMETERS.BTL and GENERAL_PARAMETERS.BTL[Part.sBTLInfo] and GENERAL_PARAMETERS.BTL[Part.sBTLInfo][DefaultGeneralParamList[i].sName] ~= nil then
GeneralParameters[DefaultGeneralParamList[i].sName] = GENERAL_PARAMETERS.BTL[Part.sBTLInfo][DefaultGeneralParamList[i].sName]
elseif GENERAL_PARAMETERS.PROJECT[DefaultGeneralParamList[i].sName] ~= nil then
GeneralParameters[DefaultGeneralParamList[i].sName] = GENERAL_PARAMETERS.PROJECT[DefaultGeneralParamList[i].sName]
end
end
end
return DefaultStrategyParamList
return GeneralParameters
end
-------------------------------------------------------------------------------------------------------------
local function GetInheritedParameter( Part, sSourceParamName)
local sValue = nil
if sSourceParamName and #sSourceParamName > 0 then
if Part.GeneralParameters[sSourceParamName] ~= nil then
sValue = Part.GeneralParameters[sSourceParamName]
elseif GENERAL_PARAMETERS.BTL and GENERAL_PARAMETERS.BTL[Part.sBTLInfo] and GENERAL_PARAMETERS.BTL[Part.sBTLInfo][sSourceParamName] ~= nil then
sValue = GENERAL_PARAMETERS.BTL[Part.sBTLInfo][sSourceParamName]
elseif GENERAL_PARAMETERS.PROJECT[sSourceParamName] ~= nil then
sValue = GENERAL_PARAMETERS.PROJECT[sSourceParamName]
end
end
return sValue
end
-------------------------------------------------------------------------------------------------------------
-- si traduce la tabella dei parametri con tutte le informazioni in una lista contenente i parametri utilizzabili con accesso diretto
function BeamLib.LoadCustomParametersInStrategy( CustomParameters)
local Parameters = {}
if CustomParameters and #CustomParameters > 0 then
for i=1, #CustomParameters do
if CustomParameters[i].sType == 'b' then
Parameters[CustomParameters[i].sName] = CustomParameters[i].sValue == 'true'
elseif CustomParameters[i].Type == 'd' then
Parameters[CustomParameters[i].sName] = tonumber( CustomParameters[i].sValue)
else -- CustomParameters.Type == 's'
Parameters[CustomParameters[i].sName] = CustomParameters[i].sValue
function BeamLib.LoadCustomParametersInStrategy( Proc, Part, CustomParameters, DefaultStrategyParamList)
local UpdatedParameters = {}
-- TODO serve controllare se campo 'sStrategyId' congruente tra il Config (DefaultStrategyParamList) e i parametri custom (CustomParameters)?
if DefaultStrategyParamList and DefaultStrategyParamList.ParameterList and #DefaultStrategyParamList.ParameterList > 0 then
-- lettura e settaggio parametri finali per la strategia (customizzati o default)
for i = 1, #DefaultStrategyParamList.ParameterList do
local xParameterValue = nil
-- se strategia forzata, leggo eventuali parametri nelle info
if CustomParameters and CustomParameters.bForcedStrategy and DefaultStrategyParamList.ParameterList[i].sNameNge then
local sParameterToRead = DefaultStrategyParamList.sStrategyId .. '_' .. DefaultStrategyParamList.ParameterList[i].sNameNge
local sForcedParameterForProc = EgtGetInfo( Proc.id, sParameterToRead, 's')
-- se ho trovato il valore, lo sovrascrivo al default
if sForcedParameterForProc then
xParameterValue = sForcedParameterForProc
end
-- altrimenti i parametri custom si trovano già su questa lista
elseif CustomParameters and CustomParameters.ParameterList then
for j = 1, #CustomParameters.ParameterList do
if CustomParameters.ParameterList[j].sName == DefaultStrategyParamList.ParameterList[i].sName or
CustomParameters.ParameterList[j].sName == DefaultStrategyParamList.ParameterList[i].sNameNge then
xParameterValue = CustomParameters.ParameterList[j].sValue
break
end
end
end
-- se non arriva forzato da strategia, oppure se non è stato configurato da cliente, si prende default
if xParameterValue == nil then
-- se il parametro strategia è da ereditare da un parametro globale
if DefaultStrategyParamList.ParameterList[i].sSource and #DefaultStrategyParamList.ParameterList[i].sSource > 0 then
xParameterValue = GetInheritedParameter( Part, DefaultStrategyParamList.ParameterList[i].sSource)
else
xParameterValue = DefaultStrategyParamList.ParameterList[i].sValue
end
end
if DefaultStrategyParamList.ParameterList[i].sType == 'b' then
UpdatedParameters[DefaultStrategyParamList.ParameterList[i].sName] = xParameterValue == 'true' or xParameterValue == '1' or xParameterValue == true
elseif DefaultStrategyParamList.ParameterList[i].sType == 'd' then
if #DefaultStrategyParamList.ParameterList[i].sValue > 0 then
UpdatedParameters[DefaultStrategyParamList.ParameterList[i].sName] = tonumber( xParameterValue)
-- stringa vuota equivale a non passare alcun valore (deciderà la strategia)
else
UpdatedParameters[DefaultStrategyParamList.ParameterList[i].sName] = nil
end
else --DefaultStrategyParamList[i].sType == 's' or DefaultStrategyParamList[i].sType == 'combo'
UpdatedParameters[DefaultStrategyParamList.ParameterList[i].sName] = xParameterValue
end
end
end
return Parameters
return UpdatedParameters
end
---------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------
-- si traduce la tabella dei parametri con tutte le informazioni in una lista contenente i parametri utilizzabili con accesso diretto
function BeamLib.LoadGeneralParametersInList( DefaultGeneralParamList)
local UpdatedParameters = { PROJECT = {}, BTL = {}}
-- aggiornamento parametri PROJECT
if DefaultGeneralParamList then
local idProjectInfo = EgtGetFirstNameInGroup( GDB_ID.ROOT, 'ProjectInfo') or GDB_ID.NULL
UpdatedParameters.PROJECT.sAISetupConfig = EgtGetInfo( idProjectInfo, 'AISETUP', 's') or nil
for i = 1, #DefaultGeneralParamList do
local sParamNameNGE = DefaultGeneralParamList[i].sNameNge
local xParameterValue = EgtGetInfo( idProjectInfo, sParamNameNGE, 's') or DefaultGeneralParamList[i].sValue
-- se parametro non trovato si salta tutto. N.B. = I parametri progetto non dovrebbero mai essere nil
if xParameterValue then
-- salvataggio dato su lista con accesso diretto
if DefaultGeneralParamList[i].sType == 'b' then
UpdatedParameters.PROJECT[DefaultGeneralParamList[i].sName] = xParameterValue == 'true' or xParameterValue == '1' or xParameterValue == true
elseif DefaultGeneralParamList[i].sType == 'd' then
if #DefaultGeneralParamList[i].sValue > 0 then
UpdatedParameters.PROJECT[DefaultGeneralParamList[i].sName] = tonumber( xParameterValue)
-- stringa vuota equivale a non passare alcun valore (deciderà la strategia)
else
UpdatedParameters.PROJECT[DefaultGeneralParamList[i].sName] = nil
end
else --DefaultGeneralParamList[i].sType == 's' or DefaultGeneralParamList[i].sType == 'combo'
UpdatedParameters.PROJECT[DefaultGeneralParamList[i].sName] = xParameterValue
end
end
end
-- aggiornamento parametri BTL
local BTLInfo = EgtGetNameInGroup( GDB_ID.ROOT, 'BtlInfo') or GDB_ID.NULL
for j = 1, #BTLInfo do
local BTLName = EgtGetInfo( BTLInfo[j], 'PROJ', 's')
if BTLName then
UpdatedParameters.BTL[BTLName] = {}
UpdatedParameters.BTL[BTLName].sAISetupConfig = EgtGetInfo( BTLInfo[j], 'AISETUP', 's') or nil
for i = 1, #DefaultGeneralParamList do
local sParamNameNGE = DefaultGeneralParamList[i].sNameNge
local xParameterValue = EgtGetInfo( BTLInfo[j], sParamNameNGE, 's')
-- se parametro non trovato si salta tutto
if xParameterValue then
-- salvataggio dato su lista con accesso diretto
if DefaultGeneralParamList[i].sType == 'b' then
UpdatedParameters.BTL[BTLName][DefaultGeneralParamList[i].sName] = xParameterValue == 'true' or xParameterValue == '1' or xParameterValue == true
elseif DefaultGeneralParamList[i].sType == 'd' then
if #DefaultGeneralParamList[i].sValue > 0 then
UpdatedParameters.BTL[BTLName][DefaultGeneralParamList[i].sName] = tonumber( xParameterValue)
-- stringa vuota equivale a non passare alcun valore (deciderà la strategia)
else
UpdatedParameters.BTL[BTLName][DefaultGeneralParamList[i].sName] = nil
end
else --DefaultGeneralParamList[i].sType == 's' or DefaultGeneralParamList[i].sType == 'combo'
UpdatedParameters.BTL[BTLName][DefaultGeneralParamList[i].sName] = xParameterValue
end
end
end
end
end
end
return UpdatedParameters
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.GetChainSawInitAngs( vtN, vtO, nInd)
if BeamData.GetChainSawInitAngs then
return BeamData.GetChainSawInitAngs( vtN, vtO, nInd)
@@ -329,7 +753,7 @@ function BeamLib.GetChainSawInitAngs( vtN, vtO, nInd)
end
end
---------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------
function BeamLib.GetBlockedAxis( nToolIndex, sBlockedAxis, b3Raw, vtTool, vtOut)
-- se presente funzione specifica nella macchina, la richiamo
if BeamData.GetBlockedAxis then
@@ -351,5 +775,283 @@ 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)
local dResult = 0
local k = 0
for i = #sNumberToConvert, 1, -1 do
k = k + 1
local n = string.sub(sNumberToConvert, k, k)
dResult = dResult + n*(2^(i-1))
end
return dResult
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.DecimalToBinary( dNumber)
local sNumberToConvert = tostring( dNumber)
local n = sNumberToConvert
local tmp = {}
local sResult = ""
for i = sNumberToConvert, 0, -1 do
local q = math.modf(n)
n = n/2
local b = q%2
table.insert(tmp, b)
if (q == 1) then
break
end
end
for i = #tmp, 1, -1 do
sResult = sResult..tmp[i]
end
return tonumber( sResult)
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.CalculateStringBinaryFormat( dNumber, CharNumber)
local NumberString = tostring( dNumber)
while #NumberString < CharNumber do
NumberString = '0' .. NumberString
end
return NumberString
end
-------------------------------------------------------------------------------------------------------------
--- copia una tabella lua in modo ricorsivo, ossia mantiene indipendenti anche tutte le sottotabelle
--- ATTENZIONE: in caso di modifiche vanno gestiti anche i tipi custom; sarebbe meglio metterla nel LuaLibs
function BeamLib.TableCopyDeep( OriginalTable)
-- controllo se oggetto passato è valido, altrimenti errore. Non deve mai succedere
if not OriginalTable then
error( "TableCopyDeep : can't copy nil object")
end
local CopiedTable = {}
for key, value in pairs( OriginalTable) do
if type( value) == "table" then
if isBBox3d( value) then
CopiedTable[ key] = BBox3d( value)
elseif isColor3d( value) then
CopiedTable[ key] = Color3d( value)
elseif isFrame3d( value) then
CopiedTable[ key] = Frame3d( value)
elseif isPoint3d( value) then
CopiedTable[ key] = Point3d( value)
elseif isQuaternion( value) then
CopiedTable[ key] = Quaternion( value)
elseif isVector3d( value) then
CopiedTable[ key] = Vector3d( value)
else
CopiedTable[ key] = BeamLib.TableCopyDeep( value)
end
else
CopiedTable[ key] = value
end
end
return CopiedTable
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.MergeTables( OriginalTable, InputTable)
local result = {}
for k, v in pairs( OriginalTable) do result[k] = v end
for k, v in pairs( InputTable) do result[k] = v end
return result
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.FindEdgeBestOrientedAsDirection( Edges, vtDirection)
local BestEdge = {}
local dMaxDotProduct = GEO.INFINITO
for i = 1, #Edges do
local dCurrentDotProduct = ( Edges[i].vtN * vtDirection)
if ( i == 1) or ( dCurrentDotProduct > dMaxDotProduct + 10 * GEO.EPS_SMALL) then
dMaxDotProduct = dCurrentDotProduct
BestEdge = Edges[i]
end
end
return BestEdge
end
-------------------------------------------------------------------------------------------------------------
-- nNearSide : 3=Z+, -3=Z-
function BeamLib.PutStartNearestToEdge( nCrvId, b3Raw, dMaxDist, nNearSide)
-- verifico che la curva sia chiusa
if not EgtCurveIsClosed( nCrvId) then return false end
-- recupero il versore normale al piano di lavoro o estrusione
local vtN = EgtCurveExtrusion( nCrvId, GDB_ID.ROOT)
-- coefficienti per riportare la distanza nel piano di lavoro
local dCoeffY = 0
if abs( vtN:getY()) < 0.999 then dCoeffY= 1 / ( sqrt( 1 - vtN:getY() * vtN:getY())) end
local dCoeffZ = 0
if abs( vtN:getZ()) < 0.999 then dCoeffZ = 1 / ( sqrt( 1 - vtN:getZ() * vtN:getZ())) end
-- cerco l'estremo più vicino al box e lo imposto come inizio (se da sotto escludo Zmax e viceversa)
local dUopt = 0
local dDopt = GEO.INFINITO
local dSopt = GEO.INFINITO
local dUi, dUf = EgtCurveDomain( nCrvId)
for dU = dUi, dUf, 0.5 do
local ptP = EgtUP( nCrvId, dU, GDB_ID.ROOT)
local vtDp = EgtUV( nCrvId, dU, -1, GDB_ID.ROOT)
local vtDs = EgtUV( nCrvId, dU, 1, GDB_ID.ROOT)
local bTg = ( vtDp and vtDs and vtDp * vtDs > 0.96)
if ptP and bTg then
local vtMin = ptP - b3Raw:getMin()
local vtMax = ptP - b3Raw:getMax()
local dD = abs( vtMin:getY()) * dCoeffY
dD = min( abs( vtMax:getY()) * dCoeffY, dD)
dD = min( abs( vtMin:getZ()) * dCoeffZ, dD)
dD = min( abs( vtMax:getZ()) * dCoeffZ, dD)
local dS
if nNearSide == -3 then
dS = abs( vtMin:getZ() * dCoeffZ)
else --nNearSide == 3
dS = abs( vtMax:getZ() * dCoeffZ)
end
if dD < dMaxDist and dS < dSopt + GEO.EPS_SMALL then
dUopt = dU
dDopt = dD
dSopt = dS
end
end
end
if abs( dUopt - dUi) > GEO.EPS_ZERO and abs( dUopt - dUf) > GEO.EPS_ZERO then
-- TODO. Non utilizzare la funzione EgtChangeClosedCurveStart perchè cambia proprietà della geometria.
-- dopo aver trovato l'entità di partenza, calcolare l'offset da aggiungere alla lavorazione per poter cominciare da questa entità (senza modifica della geometria)
EgtChangeClosedCurveStart( nCrvId, dUopt)
end
return true
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.ImportFileJSON( sFileToImport)
local JSON = require( 'JSON')
local function readAll( sFileToImport)
local f = io.open( sFileToImport, "rb")
local content = f:read( "*all")
f:close()
return content
end
local content = readAll( sFileToImport)
return JSON:decode( content)
end
-------------------------------------------------------------------------------------------------------------
function BeamLib.GetStrategiesFromList( Proc, StrategyList)
-- cerco tra le feature
for i = 1, #StrategyList.FEATURE do
-- se trovo la feature
if Proc.nPrc == StrategyList.FEATURE[i].nPrc then
local bGroupIsCompatible = false
-- nel JSON il gruppo è sempre 0/1, mente da BTL possono arrivare altri valori.
if StrategyList.FEATURE[i].nGrp == 0 then
if Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4 then
bGroupIsCompatible = true
end
elseif StrategyList.FEATURE[i].nGrp == 1 then
if Proc.nGrp == 1 or Proc.nGrp == 2 then
bGroupIsCompatible = true
end
end
-- si controlla gruppo
if bGroupIsCompatible then
-- cerco tra le topologie
for j = 1, #StrategyList.FEATURE[i].TopologyList do
-- non si possono mischiare topologie specifiche con topologia 'Feature'. Se presente topologia 'Feature' allora deve essere esclusiva
if StrategyList.FEATURE[i].TopologyList[j].sName == 'Feature' and #StrategyList.FEATURE[i].TopologyList > 1 then
error( "UNEXPECTED ERROR: topology 'Feature' can't be mixed with others")
end
-- se trovo la topologia oppure se è 'Feature'
if Proc.Topology.sName == StrategyList.FEATURE[i].TopologyList[j].sName or StrategyList.FEATURE[i].TopologyList[j].sName == 'Feature' then
local ActiveStrategyList = {}
-- aggiungo in lista solo le strategie attive
if StrategyList.FEATURE[i].TopologyList[j].StrategyList then
for k = 1, #StrategyList.FEATURE[i].TopologyList[j].StrategyList do
if ( not StrategyList.FEATURE[i].TopologyList[j].StrategyList[k].nIndexInList) or ( StrategyList.FEATURE[i].TopologyList[j].StrategyList[k].nIndexInList) >= 0 then
table.insert( ActiveStrategyList, BeamLib.TableCopyDeep( StrategyList.FEATURE[i].TopologyList[j].StrategyList[k]))
end
end
end
-- ritorno le strategie disponibili per la feature che sto analizzando, altrimenti nil se non ho trovato nulla
return EgtIf( #ActiveStrategyList > 0, ActiveStrategyList, nil)
end
end
end
end
end
return nil
end
-------------------------------------------------------------------------------------------------------------
-- Merge sorting - algoritmo di sorting stabile, ossia che mantiene l'ordine relativo se gli elementi sono equivalenti
-- TODO vedere come riordinare (tutto in tabella MergeSort??)
-- TODO libreria Sorting??
do
-- unisce due liste ordinate
local function MergeHalves(Left, Right, Compare)
local result = {}
local i, j = 1, 1
while i <= #Left and j <= #Right do
if Compare( Left[i], Right[j]) then
table.insert( result, Left[i])
i = i + 1
else
table.insert( result, Right[j])
j = j + 1
end
end
-- Append degli elementi rimanenti a sinistra o destra
while i <= #Left do
table.insert( result, Left[i])
i = i + 1
end
while j <= #Right do
table.insert( result, Right[j])
j = j + 1
end
return result
end
-- Merge sort
local function MergeSort( List, Compare)
if #List <= 1 then
return List
end
local mid = floor( #List / 2)
local Left = MergeSort( { table.unpack( List, 1, mid)}, Compare)
local Right = MergeSort( { table.unpack( List, mid + 1)}, Compare)
return MergeHalves( Left, Right, Compare)
end
-- chiamata accessibile dall'esterno
function BeamLib.StableSort( List, Compare)
return MergeSort( List, Compare)
end
end
-------------------------------------------------------------------------------------------------------------
return BeamLib
+675
View File
@@ -0,0 +1,675 @@
-- DiceCut.lua by Egalware s.r.l. 2024/01/23
-- Gestione dei piano paralleli nei tagli lunghi: equidistanziamento dei piani paralleli
-- Tabella per definizione modulo
local DiceCut = {}
-- Include
require( 'EgtBase')
local BeamLib = require( 'BeamLib')
EgtOutLog( ' DiceCut started', 1)
-- Dati
local BeamData = require( 'BeamDataNew')
----------------------------------------------------------------------------------------------------------------------------------------------------
-- creo i piani paralleli
-- GetParallelPlanes: restituisce un vettore con gli indici delle superfici
-- idAddGroup: il layer
-- b3BoxDicing: il grezzo della barra
-- ptC: il punto centrale del piano della feature
-- vtN: il versore normale del piano della feature
-- nCopyPlane: 0 => genera una copia del piano passato, 1=> non genera una copia del piano passato
-- dOffset: offset dei piani paralleli
-- nStep: numero massimo di step
-- Color: colre del fascio di piani
-- dTolerance*: distanza tra i piani paralleli e i piani di taglio (se non esistono altre superfici può essere omesso)
-- bNoTolOnFirstCut*: elimina la tolleranza per il primo piano del fascio (se non esistono altre superfici può essere omesso)
-- ptCCut*: il punto centrale della superfice limitante (se non esistono altre superfici può essere omesso)
-- vtNCut*: il punto centrale della superfice limitante (se non esistono altre superfici può essere omesso)
-- ptCCut1*: il punto centrale della superfice limitante (se non esistono altre superfici può essere omesso)
-- vtNCut1*: il punto centrale della superfice limitante (se non esistono altre superfici può essere omesso)
local function GetParallelPlanes( 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
if dTolerance then
ptMyCCut = Point3d( ptCCut + dTolerance * vtNCut)
end
ptMyCCut = Point3d( ptCCut)
end
local ptMyCCut1
if ptCCut1 and vtNCut1 then
ptMyCCut1 = Point3d( ptCCut1 + 0 * vtNCut1)
end
local TabellaTmSurfParallel = {}
local i = nCopyPlane
while i < nStep do
local SurfId = EgtSurfTmPlaneInBBox( 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
if i > nCopyPlane then
break
end
end
if nFacet > 0 and vtNCut and ptMyCCut and EgtSurfArea(SurfId) > AreaMin then
if i == nCopyPlane and bNoTolOnFirstCut then
EgtCutSurfTmPlane( SurfId, ptCCut, -vtNCut, false, GDB_RT.GLOB)
else
EgtCutSurfTmPlane( SurfId, ptMyCCut, -vtNCut, false, GDB_RT.GLOB)
end
nFacet = EgtSurfTmFacetCount( SurfId)
end
if nFacet > 0 and vtNCut1 and ptMyCCut1 and EgtSurfArea(SurfId) > AreaMin then
if i == nCopyPlane and bNoTolOnFirstCut then
EgtCutSurfTmPlane( SurfId, ptCCut1, -vtNCut1, false, GDB_RT.GLOB)
else
EgtCutSurfTmPlane( SurfId, ptMyCCut1, -vtNCut1, false, GDB_RT.GLOB)
end
nFacet = EgtSurfTmFacetCount( SurfId)
end
if nFacet > 0 and EgtSurfArea(SurfId) > AreaMin then
table.insert( TabellaTmSurfParallel, SurfId)
--EgtSetColor( SurfId, Color)
else
EgtErase( SurfId)
end
if dOffset == 0 then
break
end
i = i + 1
end
return TabellaTmSurfParallel
end
----------------------------------------------------------------------------------------------------------------------------------------------------
-- GetOrderedCutTable:
-- 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( idAddGroup, TabParallelPlanes, TabOrtoPlanes)
local StepParallel = #TabParallelPlanes
local StepOrto = #TabOrtoPlanes
local TabellaOrderParallelCut1 = {}
for IndexTmP=1, StepParallel do
TabellaOrderParallelCut1[IndexTmP] = {}
for IndexOrto=1, StepOrto do
local ptOrtoN, vtNOrtoN = EgtSurfTmFacetCenter( TabOrtoPlanes[IndexOrto ], 0, GDB_ID.ROOT)
local Copy1Id = EgtCopySurfTmFacet( TabParallelPlanes[IndexTmP], 0, 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)
local nFacet1 = EgtSurfTmFacetCount( Copy1Id)
local nFacet2 = EgtSurfTmFacetCount( Copy2Id)
if nFacet1 < 1 then
EgtErase( Copy1Id)
EgtErase( Copy2Id)
EgtCutSurfTmPlane( TabParallelPlanes[IndexTmP], ptOrtoN, vtNOrtoN, false, GDB_RT.GLOB)
elseif nFacet2 < 1 then
EgtErase( Copy1Id)
EgtErase( Copy2Id)
break
else
table.insert( TabellaOrderParallelCut1[IndexTmP], Copy1Id)
EgtErase( Copy2Id)
EgtCutSurfTmPlane( TabParallelPlanes[IndexTmP], ptOrtoN, vtNOrtoN, false, GDB_RT.GLOB)
end
end
end
table.insert(TabellaOrderParallelCut1[IndexTmP], TabParallelPlanes[IndexTmP])
end
return TabellaOrderParallelCut1
end
----------------------------------------------------------------------------------------------------------------------------------------------------
-- GetOrtoCutCenter:
-- idFacet: l'id della faccia
-- ptC: il punto centrale della faccia
-- vtN: il versore normale della faccia
-- vtO: il versore dei piani ortogonali
-- dOffsetEff: offset della distanza dal punto centrale
-- Verifica se l'asse X del box costruito sopra la superficie è più grande di un certo offset
local function GetOrtoCutCenter( FacetId, ptC, vtN, vtO, dOffsetEff)
local FrameLocal = Frame3d( EgtSurfTmFacetCenter( FacetId, 0, GDB_ID.ROOT))
EgtSetGridFrame(FrameLocal)
local IdAuxLocal = EgtGroup(EgtGetParent( FacetId), FrameLocal)
EgtSetName( IdAuxLocal, "AuxLocal")
local BoxLocal = EgtGetBBoxRef( FacetId, GDB_BB.STANDARD, FrameLocal)
local ptS = EgtGP( EgtSurfTmBBox( IdAuxLocal, BoxLocal, GDB_RT.GRID), GDB_ID.ROOT)
EgtErase( IdAuxLocal)
EgtSetGridFrame(Frame3d())
-- riferimento intrinseco
local asseX = Vector3d( vtO)
local asseY = vtN ^ asseX
local Frame = Frame3d( ptC, ptC + asseX, ptC + asseY)
-- ingombro della faccia secondo questo riferimento
local Box = EgtGetBBoxRef( FacetId, GDB_BB.STANDARD, Frame)
local dLen = Box:getDimX()
local dWidth = Box:getDimY()
-- se faccia non troppo lunga, con un lato piccolo e non diretta troppo verso il basso, non servono dice
-- 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) then
return nil, nil, nil
end
local N = ceil( dLen / dOffsetEff)
local dOffsetRel = ( dLen / N) + 10 * GEO.EPS_SMALL
local dCopyPlane
local dCenOffs = ( Box:getMax():getX() + Box:getMin():getX()) / 2
if dLen <= dOffsetRel then
dCopyPlane = 1
elseif dLen <= 2 * dOffsetRel then
dOffsetRel = dOffsetEff
dCopyPlane = 0
else
if N % 2 == 0 then
dCopyPlane = 0
elseif N % 2 == 1 then
dCopyPlane = 0.5
end
end
return dOffsetRel, dCopyPlane, dCenOffs, ptS
end
----------------------------------------------------------------------------------------------------------------------------------------------------
-- TableMesh:
-- TableOrto: tabella delle superfici dei piani ortogonali
-- TableParallel: tabella delle superfici dei piani paralleli
-- Forma una tabella unica delle superfici di taglio inserendo strati di tagli ortogonali alternati da strati di taglio parallelo
local function TableMesh( TableOrto, TableParallel)
local TableUnited = {}
for i=1, #TableOrto do
table.insert( TableUnited, TableOrto[i])
table.insert( TableUnited, TableParallel[i])
end
return TableUnited
end
----------------------------------------------------------------------------------------------------------------------------------------------------
-- FindValue:
-- tab: tabella da scansionare
-- val: valore da cercare
-- Verifica se tab contiene val, a supporto della funzione SortOrtoCutsByNormalMethod
local function FindValue( tab, val)
for index, value in ipairs( tab) do
if value == val then
return true
end
end
return false
end
----------------------------------------------------------------------------------------------------------------------------------------------------
-- SortOrtoCutsByNormalMethod:
-- TabParallelPlanes: tabella delle superfici dei piani paralleli
-- TabOrtoPlanes: tabella delle superfici dei piani ortogonali
-- stampo l'ordine dei piani di taglio sfruttando il prodotto dei versori normali (prima tagli ortogonali piu' esterni poi taglio parallelo collettivo)
local function SortOrtoCutsByNormalMethod( TabParallelPlanes, TabOrtoPlanes)
-- tabella dei tagli ordinati
local TabOrderOrtoCut = {}
-- tabella ausiliaria dei dati inseriti nell'ordine
local TabAux = {}
-- ciclo di ordinamento
local StepParallel = #TabParallelPlanes
local StepOrto = #TabOrtoPlanes
for IndexTmP=1, StepParallel do
TabOrderOrtoCut[IndexTmP] = {}
local ptParalN, vtNParalN = EgtSurfTmFacetCenter( TabParallelPlanes[IndexTmP][1], 0, GDB_ID.ROOT)
for IndexOrto=1, StepOrto do
for i=1, #TabOrtoPlanes[IndexOrto] do
-- identificativo del taglio
local OrtoPlaneId = TabOrtoPlanes[IndexOrto][i]
-- controlla che l'elemento da valutare non sia gia' stato inserito nella tabella
if not FindValue( TabAux, OrtoPlaneId) then
local ptOrtoN, vtNOrtoN = EgtSurfTmFacetCenter( OrtoPlaneId, 0, GDB_ID.ROOT)
local scalarProduct = ( ptOrtoN - ptParalN) * vtNParalN
if scalarProduct > 0 then
table.insert( TabOrderOrtoCut[IndexTmP], OrtoPlaneId)
table.insert( TabAux, OrtoPlaneId)
end
end
end
end
end
-- cancello dal DB geometrico i tagli non inseriti
for IndexOrto=1, StepOrto do
for i=1, #TabOrtoPlanes[IndexOrto] do
-- identificativo del taglio
local OrtoPlaneId = TabOrtoPlanes[IndexOrto][i]
-- ricerco il taglio tra gli inseriti
if not FindValue( TabAux, OrtoPlaneId) then
EgtErase( OrtoPlaneId)
end
end
end
return TabOrderOrtoCut
end
----------------------------------------------------------------------------------------------------------------------------------------------------
-- VerifyFirstOrthoCut :
-- CutTable: tabella dei tagli
-- 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)
if not CutTable[1] or not CutTable[2] then return end
local CutOId = CutTable[1][1]
local Cut1Id = CutTable[2][1]
local Cut2Id = CutTable[2][2]
if CutOId and Cut1Id and Cut2Id then
-- centri e normali delle due semifacce
local ptC1, vtN1 = EgtSurfTmFacetCenter( Cut1Id, 0, GDB_ID.ROOT)
local ptC2, vtN2 = EgtSurfTmFacetCenter( Cut2Id, 0, GDB_ID.ROOT)
-- normale alla faccia ortogonale
local _, vtO = EgtSurfTmFacetCenter( CutOId, 0, GDB_ID.ROOT)
vtO = vtO - vtO * vtN1 * vtN1 ; vtO:normalize()
local dMaxElev = EgtSurfTmFacetElevationInBBox( CutOId, 0, b3BoxDicing, true, GDB_ID.ROOT)
-- calcolo lunghezza prima semi-faccia
local asseX1 = vtO
local asseY1 = vtN1 ^ asseX1
local Frame1 = Frame3d( ptC1, ptC1+asseX1, ptC1+asseY1)
local Box1 = EgtGetBBoxRef( Cut1Id, GDB_BB.STANDARD, Frame1)
local x1 = Box1:getDimX()
-- prendo il massimo tra la lugnhezza della faccia parallela e l'elevazione della corrispondente ortogonale
x1 = max( x1, dMaxElev)
-- calcolo lunghezza seconda semi-faccia
local asseX2 = vtO
local asseY2 = vtN2 ^ asseX2
local Frame2 = Frame3d( ptC2, ptC2+asseX2, ptC2+asseY2)
local Box2 = EgtGetBBoxRef( Cut2Id, GDB_BB.STANDARD, Frame2)
local x2 = Box2:getDimX()
-- lunghezza totale faccia
local dLongSize = x1 + x2
-- se faccia piccola e non orientata verso il basso, elimino ortogonale e unisco le due parti
if dLongSize <= 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)
table.remove( CutTable[2], 1)
table.remove( CutTable[2], 1)
table.insert( CutTable[2], 1, SurfId)
end
end
end
----------------------------------------------------------------------------------------------------------------------------------------------------
-- ricavo i vertici del box
local function CalcolaPuntiEstremiBox( b3BoxDicing)
local ptMin = b3BoxDicing:getMin()
local ptMax = b3BoxDicing:getMax()
local TBoxPoint = {}
table.insert( TBoxPoint, { P = Point3d( ptMin:getX(), ptMin:getY(), ptMin:getZ()), On = true})
table.insert( TBoxPoint, { P = Point3d( ptMax:getX(), ptMin:getY(), ptMin:getZ()), On = true})
table.insert( TBoxPoint, { P = Point3d( ptMin:getX(), ptMax:getY(), ptMin:getZ()), On = true})
table.insert( TBoxPoint, { P = Point3d( ptMax:getX(), ptMax:getY(), ptMin:getZ()), On = true})
table.insert( TBoxPoint, { P = Point3d( ptMin:getX(), ptMin:getY(), ptMax:getZ()), On = true})
table.insert( TBoxPoint, { P = Point3d( ptMax:getX(), ptMin:getY(), ptMax:getZ()), On = true})
table.insert( TBoxPoint, { P = Point3d( ptMin:getX(), ptMax:getY(), ptMax:getZ()), On = true})
table.insert( TBoxPoint, { P = Point3d( ptMax:getX(), ptMax:getY(), ptMax:getZ()), On = true})
return TBoxPoint
end
----------------------------------------------------------------------------------------------------------------------------------------------------
-- restituisce i punti che devono essere presi in considerazione per la costruzione del BoundingBox
local function VerificaEstremiGrezzo( ptC, vtN, TPoint)
for i = 1, #TPoint do
if ( TPoint[i].P - ptC) * vtN < 0 then
TPoint[i].On = false
end
end
return TPoint
end
----------------------------------------------------------------------------------------------------------------------------------------------------
-- ricavo l'altezza del BoundingBox assegnati gli estremi del grezzo e la feature
-- le funzioni commentate permettono di vedere la creazione di BoundingBox
local function DistanzaMassima( 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
local BB1 = BBox3d()
-- punti di vertice della trave compresi
for i = 1, #TPoint do
if TPoint[i].On then
local ptP = Point3d( TPoint[i].P)
ptP:toLoc( Frame1)
BB1:Add( ptP)
end
end
-- eventuale altra faccia
if ptC2 and vtN2 then
local IdAux = EgtGroup( idAddGroup)
local IdSurf2 = EgtSurfTmPlaneInBBox( IdAux, ptC2, vtN2, b3BoxDicing, GDB_RT.GLOB)
EgtCutSurfTmPlane( IdSurf2, ptC1, -vtN1, false, GDB_RT.GLOB)
if IdSurf2 then
local BB2 = EgtGetBBoxRef( IdSurf2, GDB_BB.STANDARD, Frame1)
BB1:Add( BB2)
end
EgtErase( IdAux)
end
if not BB1:isEmpty() then
return ( BB1:getMax():getZ() + 0.1)
end
return 0
end
----------------------------------------------------------------------------------------------------------------------------------------------------
-- DiceCut.GetDice :
-- nParent: il layer
-- BBoxRawPart: il grezzo della barra
-- ptCPlanes: il punto centrale del piano della feature
-- vtNPlanes: il versore normale del piano della feature
-- bGetOrtoPlanes*: se voglio calcolare i piani ortogonali al piano passato (se non esistono altre superfici può essere omesso)
-- ptCBond*: il punto centrale della superfice limitante (se non esistono altre superfici può essere omesso)
-- vtNBond*: il versore normale della superfice limitante (se non esistono altre superfici può essere omesso)
-- dOrthoMaxDim : massima profondità taglio se faccia singola perpendicolare facce laterali trave
-- dCustMaxDimDice: dimensione massima customizzata, sostituisce il parametro BeamData.MAX_DIM_DICE (se negativa qualunque, se positiva deve stare nel MAX)
-- bDownHead : taglio con testa da sotto
----------------------------------------------------------------------------------------------------------------------------------------------------
-- function DiceCut.GetDice( nParent, BBoxRawPart, ptCPlanes, vtNPlanes, bGetOrtoPlanes, ptCBond, vtNBond, dOrthoMaxDim, dCustMaxDimDice, bDownHead)
---------------------------------------------------------------------------------------------------------------
-- DiceCut.GetDice :
-- Part : pezzo
-- Face1 : table. Contiene tutti i dati della faccia principale. Obbligatori i campi '.ptCenter' e '.vtN'
-- Face2 : table. Contiene tutti i dati della faccia secondaria. Se non esiste, la table è vuota ({}). Se esiste, obbligatori i campi '.ptCenter' e '.vtN'
-- OptionaParameters : eventuali parametri opzionali
---------------------------------------------------------------------------------------------------------------
function DiceCut.GetDice( Part, Face1, Face2, OptionalParameters)
-- gruppo per geometria addizionale
local idAddGroup
if OptionalParameters.bSaveAddedGeometries then
idAddGroup = BeamLib.GetAddGroup( Part.id)
else
idAddGroup = Part.idTempGroup
end
-- faccia primaria
local ptCMainFace
local vtNMainFace
if Face1.ptCenter and Face1.vtN then
ptCMainFace = Point3d( Face1.ptCenter)
vtNMainFace = Vector3d( Face1.vtN)
end
-- faccia secondaria; se non esiste, si forza il calcolo dei piani ortogonali
local ptCSubordinateFace
local vtNSubordinateFace
local bGetOrtoPlanes
if Face2.ptCenter and Face2.vtN then
ptCSubordinateFace = Point3d( Face2.ptCenter)
vtNSubordinateFace = Vector3d( Face2.vtN)
bGetOrtoPlanes = false
else
bGetOrtoPlanes = true
end
-- parametri opzionali e default
-- box per dicing
local b3BoxDicing = OptionalParameters.b3BoxDicing or Part.b3Part
-- distanza tra piani paralleli
local dOffsetParallel = OptionalParameters.dOffsetParallel or BeamData.MAX_DIM_DICE
-- distanza tra piani ortogonali
local dOffsetOrthogonal = OptionalParameters.dOffsetOrthogonal or BeamData.MAX_DIM_DICE
-- 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
--Ricavo le altezze dei BoundingBox contenente feature e estremi del grezzo
local TBoxPoint = CalcolaPuntiEstremiBox( b3BoxDicing)
TBoxPoint = VerificaEstremiGrezzo( ptCMainFace, vtNMainFace, TBoxPoint)
if ptCSubordinateFace and vtNSubordinateFace then
TBoxPoint = VerificaEstremiGrezzo( ptCSubordinateFace, vtNSubordinateFace, TBoxPoint)
end
local dElevP = DistanzaMassima( idAddGroup, ptCMainFace, vtNMainFace, ptCSubordinateFace, vtNSubordinateFace, b3BoxDicing, TBoxPoint)
local dElevO
if ptCSubordinateFace and vtNSubordinateFace and not AreOppositeVectorApprox( vtNSubordinateFace, vtNMainFace) then
dElevO = DistanzaMassima( idAddGroup, ptCSubordinateFace, vtNSubordinateFace, ptCMainFace, vtNMainFace, b3BoxDicing, TBoxPoint)
end
-- aggiungo piccolo extra agli offset
dOffsetParallel = dOffsetParallel + 10 * GEO.EPS_SMALL
dOffsetOrthogonal = dOffsetOrthogonal + 10 * GEO.EPS_SMALL
-- se piani non ortogonali, diminuisco la distanza di offset opportunamente
local dOffsetParallelOriginal = dOffsetParallel
if not bGetOrtoPlanes then
local dCoeff = max( ( vtNMainFace ^ vtNSubordinateFace):len(), 0.5)
dOffsetParallel = dOffsetParallel * dCoeff
dOffsetOrthogonal = dOffsetOrthogonal * dCoeff
end
local n = ceil( dElevP / dOffsetParallel)
dOffsetParallel = dElevP / n
if dElevO then
local m = ceil( dElevO / dOffsetOrthogonal)
dOffsetOrthogonal = dElevO / m
end
-- elenco di tutte le superfici generate dai tagli
local TabFUCHSIA = {}
local TabGREEN = {}
-- PIANI PARALLELI alla faccia di taglio
local TabellaTmSurfP = {}
local TabFromIn = GetParallelPlanes( 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
-- PIANI ORTOGONALI alla faccia di taglio
-- orientamento definito da seconda faccia
if not bGetOrtoPlanes then
local TabellaTmSurfOrto = {}
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( 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
-- orientamento da definire
else
for PlnInd = 1, #TabellaTmSurfP do
-- piano interno
local ptCInner, vtNInner = EgtSurfTmFacetCenter( TabellaTmSurfP[PlnInd], 0, GDB_ID.ROOT)
-- eventuale piano esterno
local ptCOuter, vtNOuter = nil, nil
if PlnInd > 1 then
ptCOuter, vtNOuter = EgtSurfTmFacetCenter( TabellaTmSurfP[PlnInd-1], 0, GDB_ID.ROOT)
vtNOuter = -vtNOuter
end
-- calcolo la direzione dei piani ortogonali
local vtO = VectorFromUprightOrtho( vtNInner)
if vtNInner:getZ() > -0.0175 or 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) then
vtO:rotate( vtNInner, 90)
-- se faccia principale verso il basso (almeno -3deg), lo inverto per iniziare da sopra
if vtNInner:getZ() < -0.05 then
vtO = -vtO
end
else
if vtNInner:getX() > -0.017 then
if vtO:getX() < -0.001 then vtO = -vtO end
else
if vtO:getX() > 0.001 then vtO = -vtO end
end
end
end
-- se quasi verticale (fino a 20 gradi di distanza) su faccia inclinata in Y, ruoto di 90 gradi
if vtO:getZ() > 0.939 and abs( vtNInner:getY()) > 0.5 then
vtO:rotate( vtNInner, 90)
end
-- calcolo le dimensioni dell'offset e dove posizionare la prima faccia:
-- CopyPlane: 0 => crea la prima faccia direttamente sul punto passato
-- CopyPlane: 1 => crea la prima faccia e tutte le altre con l'offset passato
-- CopyPlane: 0.5 => crea la prima faccia a metà offset e tutte le altre con l'offest intero
local OffsetRel, CopyPlane, dCenOffs, ptCStart = GetOrtoCutCenter( TabellaTmSurfP[PlnInd], ptCInner, vtNInner, vtO, dOffsetOrthogonal)
if OffsetRel and CopyPlane and dCenOffs then
ptCInner = ptCInner + dCenOffs * vtO
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( 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 = {}
for i = #TabLeft, 1, -1 do
table.insert( TempOrtoTab, TabLeft[i])
end
for i = 1, #TabRight do
table.insert( TempOrtoTab, TabRight[i])
end
-- creo una tabella per ogni piano per generare i tagli sulla Inner
local TempParTab = GetOrderedCutTable( idAddGroup, {TabellaTmSurfP[PlnInd]}, TempOrtoTab)
for i = 1, #TempParTab do
table.insert( TabFUCHSIA, TempParTab[i])
end
table.insert( TabGREEN, TempOrtoTab)
else
table.insert( TabFUCHSIA, {TabellaTmSurfP[PlnInd]})
table.insert( TabGREEN, {})
end
end
end
-- Se sono state costruite non più di una faccia parallela e una faccia perpendicolare, allora non servono e tengo le originali
if #TabGREEN == 1 and #TabGREEN[1] <= 1 and #TabFUCHSIA == 1 and #TabFUCHSIA[1] <= 1 then
if #TabGREEN[1] == 1 then
EgtErase( TabGREEN[1][1])
end
TabGREEN = {}
if #TabFUCHSIA[1] == 1 then
EgtErase( TabFUCHSIA[1][1])
end
TabFUCHSIA = {}
end
-- Si uniscono le tabelle dei tagli ortogonali e paralleli in una sola tabella
local UltimateTable = TableMesh( TabGREEN, TabFUCHSIA)
-- Se esiste la superficie limitante (nFacet == 2) verifica se il taglio più esterno è superfluo e quindi viene eliminato
if not bGetOrtoPlanes then
VerifyFirstOrthoCut( UltimateTable, 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])
EgtErase( UltimateTable[2][1])
UltimateTable = {}
end
end
return UltimateTable
end
----------------------------------------------------------------------------------------------------------------------------------------------------
-- PrintOrderCut:
-- TabellaOrderCut: tabella delle superfici di taglio
-- stampo l'ordine dei piani di taglio ricevendo una tabella con gli strati parallelo/ortogonali già ordinati
function DiceCut.PrintOrderCut( TabellaOrderCut)
local Step = #TabellaOrderCut
if Step > 0 then
EgtOutLog( " L'ordine delle superfici da tagliare è il seguente:")
else
EgtOutLog( ' Non sono necessarie superfici aggiuntive di taglio.')
end
for i = 1, Step do
if i % 2 == 1 then
EgtOutLog( ' *** Strato di taglio ' .. EgtNumToString( ( i + 1) / 2, 0))
if #TabellaOrderCut[i] > 0 then
EgtOutLog( ' Tagli ortogonali: ')
else
EgtOutLog( ' Tagli ortogonali assenti')
end
else
if #TabellaOrderCut[i] > 0 then
EgtOutLog( ' Tagli paralleli: ')
else
EgtOutLog( ' Tagli paralleli assenti')
end
end
for j=1, #TabellaOrderCut[i] do
EgtOutLog( ' Indice faccia ' .. (TabellaOrderCut[i][j] or 0))
end
end
end
----------------------------------------------------------------------------------------------------------------------------------------------------
local function DiceCutTest()
-- salvo l'indice del layer Trimesh selezionato
local SelectedIndex = EgtGetFirstSelectedObj()
-- verifico che sia selezionato un elemento
if not SelectedIndex then return end
-- salvo l'indice del layer Processing
local nAddGrpId = EgtGetParent( SelectedIndex)
-- salvo l'indice del layer Part
local nRawPart = EgtGetParent( nAddGrpId)
local nBox = EgtGetFirstNameInGroup( nRawPart, 'Box')
-- carico il bounding box della trave
-- local b3BoxDicing = EgtGetBBoxGlob( nRawPart, GDB_BB.STANDARD )
local b3BoxDicing = EgtGetBBoxGlob( nBox, GDB_BB.STANDARD )
-- seleziono il Part e il Layer di destinazione
EgtSetCurrPartLayer( nRawPart, nAddGrpId)
-- conto il numero di facce da processare
local nFacet = EgtSurfTmFacetCount( SelectedIndex)
EgtOutLog( ' Numero facce ' .. nFacet, 1)
-- salvo
local TabPlanesFeatures = {}
for i = 1, nFacet do
local ptC, vtN = EgtSurfTmFacetCenter( SelectedIndex, i - 1, GDB_ID.ROOT)
table.insert( TabPlanesFeatures, { ptC = ptC, vtN = vtN})
end
local ptC1 = Point3d( TabPlanesFeatures[1].ptC)
local vtN1 = Vector3d( TabPlanesFeatures[1].vtN)
local CutTable = {}
if nFacet == 1 then
CutTable = DiceCut.GetDice( nAddGrpId, b3BoxDicing, ptC1, vtN1, true)
elseif nFacet == 2 then
CutTable = DiceCut.GetDice( nAddGrpId, b3BoxDicing, ptC1, vtN1, false, TabPlanesFeatures[2].ptC, TabPlanesFeatures[2].vtN)
end
if EgtGetDebugLevel() >= 3 then
DiceCut.PrintOrderCut( CutTable)
end
EgtDeselectAll()
EgtDraw()
end
----------------------------------------------------------------------------------------------------------------------------------------------------
--DiceCutTest()
return DiceCut
+343 -118
View File
@@ -7,6 +7,7 @@ local FaceData = {}
-- carico librerie
local BeamLib = require( 'BeamLib')
local Logs = require( 'Logs')
---------------------------------------------------------------------
@@ -81,7 +82,7 @@ end
function FaceData.GetFacesByAdjacencyNumber( Proc)
-- se la feature ha una sola faccia, esco subito
if Proc.nFct <= 1 then
return
return {}
end
local FacesByAdjacencyNumber = {}
@@ -90,17 +91,87 @@ 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
end
-------------------------------------------------------------------------------------------------------------
function FaceData.GetFacesInfo( Proc, Part)
EgtOutLog( '---Faces START---')
function FaceData.GetEdgesInfo( ProcOrId, idFace )
local Edges = {}
-- disambiguazione feature vs id trimesh
local Proc = {}
if type( ProcOrId) == "table" then
Proc = ProcOrId
elseif type( ProcOrId) == "number" then
Proc.id = ProcOrId
else
error( 'GetEdgesInfo : Only feature or trimesh supported')
end
local nFaceType, EdgesEgt = EgtSurfTmGetFacetOutlineInfo( Proc.id, idFace, GDB_ID.ROOT)
for i = 1, #EdgesEgt do
local nPreviousEdgeIndex = i - 1
if i == 1 then
nPreviousEdgeIndex = #EdgesEgt
end
local nNextEdgeIndex = i + 1
if i == #EdgesEgt then
nNextEdgeIndex = 1
end
-- l'elevazione si tiene sempre positiva e la normale sempre diretta verso l'interno della faccia
-- per sapere se il lato è aperto c'è la proprietà apposita bIsOpen
local CurrentEdge = {}
CurrentEdge.idAdjacentFace = EdgesEgt[i].Adj
CurrentEdge.dLength = EdgesEgt[i].Len
CurrentEdge.dElevation = abs( EdgesEgt[i].Elev)
CurrentEdge.bIsOpen = EdgesEgt[i].Open
CurrentEdge.vtN = Vector3d( EdgesEgt[i].Norm)
if CurrentEdge.bIsOpen then
CurrentEdge.vtN = -CurrentEdge.vtN
end
CurrentEdge.bIsStartOpen = EdgesEgt[nPreviousEdgeIndex].Open
CurrentEdge.bIsEndOpen = EdgesEgt[nNextEdgeIndex].Open
CurrentEdge.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
return nFaceType, Edges
end
-------------------------------------------------------------------------------------------------------------
function FaceData.GetFacesInfo( Proc, Part, FacesToGet)
local Faces = {}
local function FaceIsToGet( nIndex)
if not FacesToGet then return false end
for i = 1, #FacesToGet do
-- correggo indice perche' id delle facce è 0-based
if FacesToGet[i] == nIndex - 1 then
return true
end
end
return false
end
local vAdj
if Proc.AdjacencyMatrix then
vAdj = Proc.AdjacencyMatrix
@@ -108,29 +179,31 @@ function FaceData.GetFacesInfo( Proc, Part)
vAdj = FaceData.GetAdjacencyMatrix( Proc)
end
-- reset eventuali visualizzazioni facce a due colori
EgtSurfTmResetTwoColors( Proc.id)
if not Proc.nFct then
Proc.nFct = EgtSurfTmFacetCount( Proc.id) or 0
end
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 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.b3Solid, true, GDB_ID.ROOT)
Faces[i].dElevation = EgtSurfTmFacetElevationInBBox( Proc.id, i - 1, Part.b3Part, true, GDB_ID.ROOT)
-- TODO qui sarebbe meglio l'area vera e non quella del rettangolo minimo
local _, dLongEdgeDimension, dShortEdgeDimension = EgtSurfTmFacetMinAreaRectangle( Proc.id, i - 1, GDB_ID.ROOT)
Faces[i].dArea = dShortEdgeDimension * dLongEdgeDimension
local _, dLongDimension, dShortDimension = EgtSurfTmFacetMinAreaRectangle( Proc.id, i - 1, GDB_ID.ROOT)
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, vEdges = EgtSurfTmGetFacetOutlineInfo( Proc.id, i - 1, GDB_ID.ROOT)
local nFaceType, Edges = FaceData.GetEdgesInfo( Proc, i - 1)
Faces[i].bIsOkForMachining = nFaceType < 1
Faces[i].Edges = vEdges
-- 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))
Faces[i].Edges = Edges
-- adiacenze della faccia
-- TODO chiamarle in modo che si capisca che sono solo gli id e non l'intero oggetto faccia
@@ -138,31 +211,119 @@ function FaceData.GetFacesInfo( Proc, Part)
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.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( 'IsFaceRectangle : too many loops')
end
local bIsRectangular = EgtCurveIsARectangle( nContourId)
return bIsRectangular
end
-------------------------------------------------------------------------------------------------------------
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( '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( Face.Edges[1].vtN, Face.Edges[3].vtN)
and AreOppositeVectorApprox( Face.Edges[2].vtN, Face.Edges[4].vtN) then
bIsRhomboid = true
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
if ( EdgeA.idAdjacentFace > -1) and ( EdgeB.idAdjacentFace < 0) then
return true
elseif ( EdgeA.idAdjacentFace < 0) and ( EdgeB.idAdjacentFace > -1) then
return false
-- se entrambi con facce adiacenti, si sceglie quello convesso (non chiuso)
else
if EdgeA.bIsOpen and not ( EdgeB.bIsOpen) then
return true
elseif not ( EdgeA.bIsOpen) and EdgeB.bIsOpen then
return false
-- se entrambi aperti o entrambi chiusi, si sceglie quello più lungo
else
if EdgeA.dLength > EdgeB.dLength then
return true
elseif EdgeA.dLength < EdgeB.dLength then
return false
end
end
end
end
-------------------------------------------------------------------------------------------------------------
-- TODO valutare refactoring per mettere i calcoli del tunnel in una funzione
-- TODO creare le facce tunnel solo se non ci sono già. Verirficare all'inizio se già presente in AddGrpId e nel caso riferire all'id di quella esistente e ricalcolare solo le informazioni della faccia.
-- TODO test iniziale replicato in GetMainFaces
local function GetTunnelFaces( Proc, Part)
local TunnelAddedFaces = {}
if not ( Proc.Topology.bIsThrough and Proc.Topology.bAllRightAngles and Proc.nFct < 5) then
if not ( ( Proc.Topology.bIsThrough and Proc.Topology.bAllRightAngles and Proc.nFct < 5)
or ( Proc.nFct == 1 ) or Proc.Topology.sName == 'Bevel-2-Blind') then
error( 'GetTunnelFaces : Topology not implemented')
end
-- direzione del tunnel
local vtTunnelDirection = Proc.Faces[1].vtN ^ Proc.Faces[ Proc.Faces[1].Adjacencies[1] + 1].vtN
local vtTunnelDirection = V_NULL()
if Proc.nFct == 1 then
local EdgesSortedByElevation = BeamLib.TableCopyDeep( Proc.Faces[1].Edges)
table.sort( EdgesSortedByElevation, function (a, b) return a.dElevation > b.dElevation end )
vtTunnelDirection = Proc.Faces[1].vtN ^ EdgesSortedByElevation[1].vtN
else
vtTunnelDirection = Proc.Faces[1].vtN ^ Proc.Faces[ Proc.Faces[1].Adjacencies[1] + 1].vtN
end
-- centro del tunnel
local frTunnel = Frame3d( Proc.Faces[1].ptCenter, vtTunnelDirection)
@@ -178,16 +339,25 @@ local function GetTunnelFaces( Proc, Part)
return TunnelAddedFaces
end
-- faccia centrale, si crea larga come la parte e poi si trimma
TunnelAddedFaces.MiddleFaceTm = {}
TunnelAddedFaces.MiddleFaceTm.id = EgtSurfTmPlaneInBBox( nAddGrpId, ptTunnelCenter, vtTunnelDirection, Part.b3Solid, GDB_ID.ROOT)
-- faccia centrale
local nMiddleTmId = EgtSurfTmPlaneInBBox( nAddGrpId, ptTunnelCenter, vtTunnelDirection, Part.b3Part, GDB_ID.ROOT)
-- TODO se non si riesce a costruire la faccia bisogna dare errore o semplicemente non ritornarla??
for i = 1, Proc.nFct do
EgtCutSurfTmPlane( TunnelAddedFaces.MiddleFaceTm.id, Proc.Faces[i].ptCenter, -Proc.Faces[i].vtN, false, GDB_ID.ROOT)
EgtCutSurfTmPlane( nMiddleTmId, Proc.Faces[i].ptCenter, -Proc.Faces[i].vtN, false, GDB_ID.ROOT)
end
-- facce laterali
local nLateralTmId = EgtCopyGlob( Proc.id, nAddGrpId) or GDB_ID.NULL
EgtCutSurfTmPlane( nLateralTmId, ptTunnelCenter, -vtTunnelDirection, false, GDB_ID.ROOT)
-- unione facce
-- TODO cambiare nome alla trimesh?? non contiene più solamente la faccia di mezzo
TunnelAddedFaces.MiddleFaceTm = {}
TunnelAddedFaces.MiddleFaceTm.id = EgtSurfTmBySewing( nAddGrpId, { nMiddleTmId, nLateralTmId}, true)
-- TODO c'è un modo più elegante per raccogliere le informazioni delle facce aggiunte
TunnelAddedFaces.MiddleFaceTm.sType = 'Tunnel'
TunnelAddedFaces.MiddleFaceTm.nFct = 1
TunnelAddedFaces.MiddleFaceTm.nFct = EgtSurfTmFacetCount( TunnelAddedFaces.MiddleFaceTm.id)
TunnelAddedFaces.MiddleFaceTm.Faces = FaceData.GetFacesInfo( TunnelAddedFaces.MiddleFaceTm, Part)
return TunnelAddedFaces
@@ -199,14 +369,44 @@ local function GetBottomFaces( Proc)
if Proc.Topology.sFamily == 'Tunnel' then
return nil
elseif not ( Proc.Topology.sFamily == 'Rabbet' or Proc.Topology.sFamily == 'VGroove' or Proc.Topology.sFamily == 'Groove' or Proc.Topology.sFamily == 'Pocket') then
elseif not ( Proc.Topology.sFamily == 'Rabbet'
or Proc.Topology.sFamily == 'VGroove'
or Proc.Topology.sFamily == 'Groove'
or Proc.Topology.sFamily == 'Pocket'
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
error( 'GetBottomFace : Topology not implemented')
end
-- la faccia di fondo ha sempre Fct - 1 adiacenze
if Proc.nFct == 1 then
return { Proc.Faces[1]}
end
-- 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
@@ -217,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
@@ -226,20 +426,28 @@ local function GetBottomFaces( Proc)
end
BottomFaces[1].sType = 'Bottom'
-- calcolo MainEdges implementato solo se 4 lati esatti
if #BottomFaces[1].Edges ~= 4 then
return BottomFaces
end
BottomFaces[1].MainEdges = {}
BottomFaces[1].MainEdges.LongEdges = {}
BottomFaces[1].MainEdges.SideEdges = {}
local ClosedEdgesSortedByGreatestLength = {}
local EdgesSorted = {}
for i = 1, #BottomFaces[1].Edges do
if not BottomFaces[1].Edges[i].Open then
table.insert( ClosedEdgesSortedByGreatestLength, {})
ClosedEdgesSortedByGreatestLength[#ClosedEdgesSortedByGreatestLength].nIndex = i
ClosedEdgesSortedByGreatestLength[#ClosedEdgesSortedByGreatestLength].dLength = BottomFaces[1].Edges[i].Len
end
table.insert( EdgesSorted, {})
EdgesSorted[#EdgesSorted].nIndex = i
EdgesSorted[#EdgesSorted].dLength = BottomFaces[1].Edges[i].dLength
EdgesSorted[#EdgesSorted].idAdjacentFace = BottomFaces[1].Edges[i].idAdjacentFace
end
table.sort( EdgesSorted, CompareEdgesBottomFace)
local nFirstLongEdgeIndex
if #EdgesSorted > 0 then
nFirstLongEdgeIndex = EdgesSorted[1].nIndex
end
table.sort( ClosedEdgesSortedByGreatestLength, function (a, b) return a.dLength > b.dLength end)
local nFirstLongEdgeIndex = ClosedEdgesSortedByGreatestLength[1].nIndex
for i = 1, #BottomFaces[1].Edges do
local nPreviousEdgeIndex = i - 1
@@ -252,26 +460,32 @@ local function GetBottomFaces( Proc)
end
local CurrentEdge = {}
CurrentEdge.idAdjacentFace = BottomFaces[1].Edges[i].Adj
CurrentEdge.vtToolDirection = Vector3d( BottomFaces[1].Edges[i].Norm)
CurrentEdge.dLength = BottomFaces[1].Edges[i].Len
CurrentEdge.dElevation = BottomFaces[1].Edges[i].Elev
CurrentEdge.bIsOpen = BottomFaces[1].Edges[i].Open
CurrentEdge.bIsStartOpen = BottomFaces[1].Edges[nPreviousEdgeIndex].Open
CurrentEdge.bIsEndOpen = BottomFaces[1].Edges[nNextEdgeIndex].Open
CurrentEdge.idAdjacentFace = BottomFaces[1].Edges[i].idAdjacentFace
CurrentEdge.vtN = BottomFaces[1].Edges[i].vtN
CurrentEdge.dLength = BottomFaces[1].Edges[i].dLength
CurrentEdge.bIsOpen = BottomFaces[1].Edges[i].bIsOpen
CurrentEdge.dElevation = BottomFaces[1].Edges[i].dElevation
CurrentEdge.bIsStartOpen = BottomFaces[1].Edges[i].bIsStartOpen
CurrentEdge.bIsEndOpen = BottomFaces[1].Edges[i].bIsEndOpen
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 i == nFirstLongEdgeIndex then
BottomFaces[1].MainEdges.LongEdges[1] = CurrentEdge
BottomFaces[1].MainEdges.LongEdges[1].sType = 'Long'
elseif nNextEdgeIndex == nFirstLongEdgeIndex then
BottomFaces[1].MainEdges.SideEdges[1] = CurrentEdge
BottomFaces[1].MainEdges.SideEdges[1].sType = 'Side'
elseif nPreviousEdgeIndex == nFirstLongEdgeIndex then
BottomFaces[1].MainEdges.SideEdges[2] = CurrentEdge
BottomFaces[1].MainEdges.SideEdges[2].sType = 'Side'
else
BottomFaces[1].MainEdges.LongEdges[2] = CurrentEdge
BottomFaces[1].MainEdges.LongEdges[2].sType = 'Long'
if nFirstLongEdgeIndex then
if i == nFirstLongEdgeIndex then
BottomFaces[1].MainEdges.LongEdges[1] = CurrentEdge
BottomFaces[1].MainEdges.LongEdges[1].sType = 'Long'
elseif nNextEdgeIndex == nFirstLongEdgeIndex then
BottomFaces[1].MainEdges.SideEdges[1] = CurrentEdge
BottomFaces[1].MainEdges.SideEdges[1].sType = 'Side'
elseif nPreviousEdgeIndex == nFirstLongEdgeIndex then
BottomFaces[1].MainEdges.SideEdges[2] = CurrentEdge
BottomFaces[1].MainEdges.SideEdges[2].sType = 'Side'
else
BottomFaces[1].MainEdges.LongEdges[2] = CurrentEdge
BottomFaces[1].MainEdges.LongEdges[2].sType = 'Long'
end
end
end
@@ -282,8 +496,10 @@ 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 {}
end
local BottomFace
@@ -305,11 +521,11 @@ local function GetLongFaces( Proc, MainFaces)
idFirstLongFace = FacesSortedByGreatestArea[1].id
local FacesNotAdjacent = GetNotAdjacentFaces( Proc, idFirstLongFace)
idSecondLongFace = FacesNotAdjacent[1].id
else
if not BottomFace.MainEdges.LongEdges[1].bIsOpen then
elseif BottomFace.MainEdges then
if BottomFace.MainEdges.LongEdges[1].idAdjacentFace > -1 then
idFirstLongFace = BottomFace.MainEdges.LongEdges[1].idAdjacentFace
end
if not BottomFace.MainEdges.LongEdges[2].bIsOpen then
if BottomFace.MainEdges.LongEdges[2].idAdjacentFace > -1 then
idSecondLongFace = BottomFace.MainEdges.LongEdges[2].idAdjacentFace
end
end
@@ -322,6 +538,12 @@ local function GetLongFaces( Proc, MainFaces)
for i = 1, #LongFaces do
LongFaces[i].sType = 'Long'
-- calcolo MainEdges possibile solo se 4 lati esatti
if #LongFaces[i].Edges ~= 4 then
break
end
LongFaces[i].MainEdges = {}
LongFaces[i].MainEdges.SideEdges = {}
LongFaces[i].MainEdges.OppositeEdges = {}
@@ -337,13 +559,17 @@ local function GetLongFaces( Proc, MainFaces)
end
local CurrentEdge = {}
CurrentEdge.idAdjacentFace = LongFaces[i].Edges[j].Adj
CurrentEdge.vtToolDirection = Vector3d( LongFaces[i].Edges[j].Norm)
CurrentEdge.dLength = LongFaces[i].Edges[j].Len
CurrentEdge.dElevation = LongFaces[i].Edges[j].Elev
CurrentEdge.bIsOpen = LongFaces[i].Edges[j].Open
CurrentEdge.bIsStartOpen = LongFaces[i].Edges[nPreviousEdgeIndex].Open
CurrentEdge.bIsEndOpen = LongFaces[i].Edges[nNextEdgeIndex].Open
CurrentEdge.idAdjacentFace = LongFaces[i].Edges[j].idAdjacentFace
CurrentEdge.vtN = LongFaces[i].Edges[j].vtN
CurrentEdge.dLength = LongFaces[i].Edges[j].dLength
CurrentEdge.bIsOpen = LongFaces[i].Edges[j].bIsOpen
CurrentEdge.dElevation = LongFaces[i].Edges[j].dElevation
CurrentEdge.bIsStartOpen = LongFaces[i].Edges[j].bIsStartOpen
CurrentEdge.bIsEndOpen = LongFaces[i].Edges[j].bIsEndOpen
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
@@ -357,10 +583,10 @@ local function GetLongFaces( Proc, MainFaces)
if CurrentEdge.idAdjacentFace == BottomFace.id then
LongFaces[i].MainEdges.BottomEdge = CurrentEdge
LongFaces[i].MainEdges.BottomEdge.sType = 'Bottom'
elseif LongFaces[i].Edges[nNextEdgeIndex].Adj == BottomFace.id then
elseif LongFaces[i].Edges[nNextEdgeIndex].idAdjacentFace == BottomFace.id then
LongFaces[i].MainEdges.SideEdges[1] = CurrentEdge
LongFaces[i].MainEdges.SideEdges[1].sType = 'Side'
elseif LongFaces[i].Edges[nPreviousEdgeIndex].Adj == BottomFace.id then
elseif LongFaces[i].Edges[nPreviousEdgeIndex].idAdjacentFace == BottomFace.id then
LongFaces[i].MainEdges.SideEdges[2] = CurrentEdge
LongFaces[i].MainEdges.SideEdges[2].sType = 'Side'
else
@@ -378,8 +604,10 @@ 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 {}
end
local BottomFace
@@ -391,11 +619,13 @@ local function GetSideFaces( Proc, MainFaces)
local idFirstSideFace = GDB_ID.NULL
local idSecondSideFace = GDB_ID.NULL
if not LongFaces[1].MainEdges.SideEdges[1].bIsOpen then
idFirstSideFace = LongFaces[1].MainEdges.SideEdges[1].idAdjacentFace
end
if not LongFaces[1].MainEdges.SideEdges[2].bIsOpen then
idSecondSideFace = LongFaces[1].MainEdges.SideEdges[2].idAdjacentFace
if LongFaces[1] and LongFaces[1].MainEdges then
if not LongFaces[1].MainEdges.SideEdges[1].bIsOpen then
idFirstSideFace = LongFaces[1].MainEdges.SideEdges[1].idAdjacentFace
end
if not LongFaces[1].MainEdges.SideEdges[2].bIsOpen then
idSecondSideFace = LongFaces[1].MainEdges.SideEdges[2].idAdjacentFace
end
end
if idFirstSideFace > -1 and Proc.Faces[idFirstSideFace + 1].bIsOkForMachining then
table.insert( SideFaces, Proc.Faces[idFirstSideFace + 1])
@@ -408,6 +638,12 @@ local function GetSideFaces( Proc, MainFaces)
for i = 1, #SideFaces do
SideFaces[i].sType = 'Side'
-- calcolo MainEdges possibile solo se 4 lati esatti
if #SideFaces[i].Edges ~= 4 then
break
end
SideFaces[i].MainEdges = {}
SideFaces[i].MainEdges.LongEdges = {}
SideFaces[i].MainEdges.OppositeEdges = {}
@@ -423,13 +659,17 @@ local function GetSideFaces( Proc, MainFaces)
end
local CurrentEdge = {}
CurrentEdge.idAdjacentFace = SideFaces[i].Edges[j].Adj
CurrentEdge.vtToolDirection = Vector3d( SideFaces[i].Edges[j].Norm)
CurrentEdge.dLength = SideFaces[i].Edges[j].Len
CurrentEdge.dElevation = SideFaces[i].Edges[j].Elev
CurrentEdge.bIsOpen = SideFaces[i].Edges[j].Open
CurrentEdge.bIsStartOpen = SideFaces[i].Edges[nPreviousEdgeIndex].Open
CurrentEdge.bIsEndOpen = SideFaces[i].Edges[nNextEdgeIndex].Open
CurrentEdge.idAdjacentFace = SideFaces[i].Edges[j].idAdjacentFace
CurrentEdge.vtN = SideFaces[i].Edges[j].vtN
CurrentEdge.dLength = SideFaces[i].Edges[j].dLength
CurrentEdge.bIsOpen = SideFaces[i].Edges[j].bIsOpen
CurrentEdge.dElevation = SideFaces[i].Edges[j].dElevation
CurrentEdge.bIsStartOpen = SideFaces[i].Edges[j].bIsStartOpen
CurrentEdge.bIsEndOpen = SideFaces[i].Edges[j].bIsEndOpen
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
@@ -441,10 +681,10 @@ local function GetSideFaces( Proc, MainFaces)
if CurrentEdge.idAdjacentFace == BottomFace.id then
SideFaces[i].MainEdges.BottomEdge = CurrentEdge
SideFaces[i].MainEdges.BottomEdge.sType = 'Bottom'
elseif SideFaces[i].Edges[nNextEdgeIndex].Adj == BottomFace.id then
elseif SideFaces[i].Edges[nNextEdgeIndex].idAdjacentFace == BottomFace.id then
SideFaces[i].MainEdges.LongEdges[1] = CurrentEdge
SideFaces[i].MainEdges.LongEdges[1].sType = 'Long'
elseif SideFaces[i].Edges[nPreviousEdgeIndex].Adj == BottomFace.id then
elseif SideFaces[i].Edges[nPreviousEdgeIndex].idAdjacentFace == BottomFace.id then
SideFaces[i].MainEdges.LongEdges[2] = CurrentEdge
SideFaces[i].MainEdges.LongEdges[2].sType = 'Long'
else
@@ -460,51 +700,36 @@ end
-------------------------------------------------------------------------------------------------------------
-- recupero facce principali della feature, in base alla topologia
-- TODO test iniziale replicato in GetTunnelFaces
function FaceData.GetMainFaces( Proc, Part)
EgtOutLog( '---MainFaces START---')
local MainFaces = {}
-- CASO 1 : Feature tipo LapJoint
if Proc.Topology.sFamily == 'Rabbet' or Proc.Topology.sFamily == 'VGroove' or Proc.Topology.sFamily == 'Groove' or Proc.Topology.sFamily == 'Pocket' or Proc.Topology.sFamily == 'Tunnel' then
if Proc.Topology.sFamily == 'Rabbet' or Proc.Topology.sFamily == 'VGroove' or Proc.Topology.sFamily == 'Groove' or
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 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)
-- TODO funzione apposita per informazioni log?
if EgtGetDebugLevel() >= 3 then
if MainFaces.BottomFaces then
for i = 1, #MainFaces.BottomFaces do
EgtOutLog( 'Bottom Face : ' .. MainFaces.BottomFaces[i].id)
end
-- colore differente per la faccia di fondo principale
EgtSurfTmSetFaceColor( Proc.id, MainFaces.BottomFaces[1].id, 1)
end
if MainFaces.LongFaces then
for i = 1, #MainFaces.LongFaces do
EgtOutLog( 'Long Face : ' .. MainFaces.LongFaces[i].id)
end
end
if MainFaces.SideFaces then
for i = 1, #MainFaces.SideFaces do
EgtOutLog( 'Side Face : ' .. MainFaces.SideFaces[i].id)
end
end
if MainFaces.TunnelAddedFaces then
EgtOutLog( 'Middle Face (Trimesh): ' .. MainFaces.TunnelAddedFaces.MiddleFaceTm.id)
end
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
EgtOutLog( '---MainFaces NOT NEEDED---')
MainFaces = nil
end
EgtOutLog( '---MainFaces END---')
return MainFaces
end
-282
View File
@@ -1,282 +0,0 @@
-- FeatureData.lua by Egalware s.r.l. 2024/04/02
-- Libreria lettura o calcolo dati e proprietà della feature
-- 2024/04/02 PRIMA VERSIONE CALCOLO LAVORAZIONI CON STRATEGIE
-- Tabella per definizione modulo
local FeatureData = {}
-- Carico i dati globali
local BeamData = require( 'BeamData')
-- carico librerie
local BeamLib = require( 'BeamLib')
local FaceData = require( 'FaceData')
local ID = require( 'Identity')
-------------------------------------------------------------------------------------------------------------
-- recupero topologia della feature
function FeatureData.NeedTopologyFeature( Proc)
-- features tipo taglio
if ID.IsCut( Proc) then
return true
elseif ID.IsDoubleCut( Proc) then
return true
elseif ID.IsSawCut( Proc) then
return true
-- features tipo taglio longitudinale
elseif ID.IsLongitudinalCut( Proc) then
return true
elseif ID.IsDoubleLongitudinalCut( Proc) then
return true
elseif ID.IsChamfer( Proc) then
return true
-- features tipo LapJoint
elseif ID.IsSlot( Proc) then
return true
elseif ID.IsFrontSlot( Proc) then
return true
elseif ID.IsRidgeLap( Proc) then
return true
elseif ID.IsLapJoint( Proc) then
return true
elseif ID.IsNotchRabbet( Proc) then
return true
elseif ID.IsNotch( Proc) then
return true
elseif ID.IsPocket( Proc) then
return true
-- calcolo topologia SOLO se non raggiata
-- TODO oppure riconoscerla come feature speciale; valutare se controllare il numero di facce è un metodo efficace
elseif ID.IsMortise( Proc) and Proc.nFct < 6 then
return true
-- calcolo topologia SOLO se non raggiata
-- TODO oppure riconoscerla come feature speciale; valutare se controllare il numero di facce è un metodo efficace
elseif ID.IsFrontMortise( Proc) and Proc.nFct < 6 then
return true
end
-- se feature non tra quelle sopra, riconoscimento topologico non necessario
return false
end
---------------------------------------------------------------------
-- restituisce true se Proc ha tutti gli angoli concavi (bAllConcave) e, nei casi in cui ha senso, se questi sono esattamente 90 deg (bAllRight)
local function AreAllAnglesConcaveOrRight( vAdj)
-- se la feature ha una sola faccia, esco subito
if #vAdj <= 1 then
return
end
local bAllConcave, bAllRight = true, true
local nFct = #( vAdj or {})
for i = 1, nFct do
for j = 1, nFct do
-- se trovo un angolo convesso restituisco falso e esco subito
if vAdj[i][j] and vAdj[i][j] > 0 then
bAllConcave = false
bAllRight = false
break
elseif vAdj[i][j] and vAdj[i][j] ~= 0 and vAdj[i][j] + 90 > 500 * GEO.EPS_ANG_SMALL then
bAllRight = false
end
end
end
-- se 1 faccia oppure 2 facce con angolo convesso non ha senso ritornare valori per bAllRight
if nFct < 2 or ( nFct == 2 and vAdj[1][2] > 0) then
return bAllConcave
else
return bAllConcave, bAllRight
end
end
---------------------------------------------------------------------
-- restituisce true se almeno una delle dimensioni della feature è maggiore o uguale ad una delle dimensioni principali del pezzo (tolleranza 1 mm)
local function IsAnyDimensionLongAsPart( Proc)
local bResult = false
local nBoxSolidId = EgtGetFirstNameInGroup( Proc.idPart or GDB_ID.NULL, 'Box')
local b3Solid = EgtGetBBoxGlob( nBoxSolidId, GDB_BB.STANDARD)
if Proc.b3Box:getDimX() > b3Solid:getDimX() - 1000 * GEO.EPS_SMALL or
Proc.b3Box:getDimY() > b3Solid:getDimY() - 1000 * GEO.EPS_SMALL or
Proc.b3Box:getDimZ() > b3Solid:getDimZ() - 1000 * GEO.EPS_SMALL then
bResult = true
end
return bResult
end
-------------------------------------------------------------------------------------------------------------
-- restituisce vero se la feature con box b3Proc taglia l'intera sezione della barra, rappresentata dalle sue dimensioni W e H
local function IsFeatureCuttingEntireSection( b3Proc, Part)
return ( b3Proc:getDimY() > ( Part.b3Raw:getDimY() - 500 * GEO.EPS_SMALL) and b3Proc:getDimZ() > ( Part.b3Raw:getDimZ() - 500 * GEO.EPS_SMALL))
end
-------------------------------------------------------------------------------------------------------------
-- restituisce vero se la feature con box b3Proc taglia l'intera lunghezza della barra, rappresentata dalle sue dimensioni W e L oppure H e L
local function IsFeatureCuttingEntireLength( b3Proc, Part)
return ( ( b3Proc:getDimY() > ( Part.b3Raw:getDimY() - 500 * GEO.EPS_SMALL) and b3Proc:getDimX() > ( Part.b3Raw:getDimX() - 500 * GEO.EPS_SMALL)) or
( b3Proc:getDimZ() > ( Part.b3Raw:getDimZ() - 500 * GEO.EPS_SMALL) and b3Proc:getDimX() > ( Part.b3Raw:getDimX() - 500 * GEO.EPS_SMALL)))
end
---------------------------------------------------------------------
-- restituisce una stringa con il nome esteso della topologia della feature
-- *famiglia - numero di facce - passante*
local function GetTopologyName( sFamily, nNumberOfFaces, bIsThrough)
return sFamily .. '-' .. tostring( nNumberOfFaces) .. '-' .. EgtIf( bIsThrough, 'Through', 'Blind')
end
---------------------------------------------------------------------
-- recupera topologia feature
function FeatureData.ClassifyTopology( Proc, Part)
local FeatureTopology = {}
if not Proc.AffectedFaces then Proc.AffectedFaces = BeamLib.GetAffectedFaces( Proc, Part) end
local bIsFeatureCuttingEntireSection = IsFeatureCuttingEntireSection( Proc.b3Box, Part)
local bIsFeatureCuttingEntireLength = IsFeatureCuttingEntireLength( Proc.b3Box, Part)
local bIsAnyDimensionLongAsPart = IsAnyDimensionLongAsPart( Proc)
local vAdj = Proc.AdjacencyMatrix
local bAllAnglesConcave, bAllRightAngles = AreAllAnglesConcaveOrRight( vAdj)
local vTriangularFaces = FaceData.GetTriangularFaces( Proc)
local vFacesByAdjNumber = FaceData.GetFacesByAdjacencyNumber( Proc)
local sFamily
local bIsThrough
if Proc.nFct == 1 and ( bIsFeatureCuttingEntireSection or bIsFeatureCuttingEntireLength) then
sFamily = 'Cut'
bIsThrough = true
elseif Proc.nFct == 1 then
sFamily = 'Bevel'
bIsThrough = true
elseif Proc.nFct == 2 and bAllAnglesConcave and #vTriangularFaces == 1 then
sFamily = 'Bevel'
bIsThrough = false
elseif Proc.nFct == 2 and bAllAnglesConcave and ( Proc.AffectedFaces.bLeft or Proc.AffectedFaces.bRight) and ( Proc.AffectedFaces.bFront or Proc.AffectedFaces.bBack) then
sFamily = 'Rabbet'
bIsThrough = true
elseif Proc.nFct == 2 and bAllAnglesConcave then
sFamily = 'VGroove'
bIsThrough = true
elseif Proc.nFct == 2 and not bAllAnglesConcave and bIsAnyDimensionLongAsPart then
sFamily = 'DoubleBevel'
bIsThrough = true
elseif Proc.nFct == 3 and bAllAnglesConcave and #vFacesByAdjNumber[2] == 1 and #vTriangularFaces == 2 then
sFamily = 'Bevel'
bIsThrough = false
elseif Proc.nFct == 3 and bAllAnglesConcave and #vFacesByAdjNumber[2] == 1 and bIsAnyDimensionLongAsPart then
sFamily = 'Groove'
bIsThrough = true
elseif Proc.nFct == 3 and bAllAnglesConcave and #vFacesByAdjNumber[2] == 3 then
sFamily = 'Groove'
bIsThrough = false
elseif Proc.nFct == 4 and #vFacesByAdjNumber[2] == 4 and #vTriangularFaces == 2 then
sFamily = 'DoubleBevel'
bIsThrough = false
elseif Proc.nFct == 4 and bAllAnglesConcave and #vFacesByAdjNumber[3] == 2 then
sFamily = 'Groove'
bIsThrough = false
elseif Proc.nFct == 4 and bAllAnglesConcave and #vFacesByAdjNumber[2] == 4 and bIsAnyDimensionLongAsPart then
sFamily = 'Tunnel'
bIsThrough = true
elseif Proc.nFct >= 4 and #vFacesByAdjNumber[1] == 2 and bIsAnyDimensionLongAsPart then
sFamily = 'Strip'
bIsThrough = true
elseif Proc.nFct == 5 and bAllAnglesConcave and #vFacesByAdjNumber[4] == 1 then
sFamily = 'Pocket'
bIsThrough = false
elseif Proc.nFct == 6 and #vFacesByAdjNumber[2] == 4 and #vFacesByAdjNumber[3] == 2 and #vTriangularFaces == 4 then
sFamily = 'DoubleBevel'
bIsThrough = false
end
if sFamily then
FeatureTopology.sFamily = sFamily
FeatureTopology.bIsThrough = bIsThrough
FeatureTopology.bAllRightAngles = bAllRightAngles
FeatureTopology.sName = GetTopologyName( sFamily, Proc.nFct, bIsThrough)
FeatureTopology.AdjacencyMatrix = vAdj
-- feature che necessita di essere catalogata, ma non si capisce come
else
FeatureTopology.sFamily = 'NOT_IMPLEMENTED'
FeatureTopology.sName = FeatureTopology.sFamily
end
return FeatureTopology
end
-------------------------------------------------------------------------------------------------------------
-- Recupero dati foro e adattamento se speciale
function FeatureData.GetDrillingData( Proc)
local AuxId = EgtGetInfo( Proc.id, 'AUXID', 'i')
-- verifico se foro da adattare
if EgtExistsInfo( Proc.id, 'DiamUser') then
if AuxId then AuxId = AuxId + Proc.id end
if AuxId and EgtGetType( AuxId) == GDB_TY.CRV_ARC and BeamData.USER_HOLE_DIAM and BeamData.USER_HOLE_DIAM > 1 then
EgtModifyArcRadius( AuxId, BeamData.USER_HOLE_DIAM / 2)
end
end
local dDiam = EgtGetInfo( Proc.id, 'P12', 'd') or 0
local dLen = abs( EgtCurveThickness( Proc.id + AuxId)) or 0
local nFcs = EgtGetInfo( Proc.id, 'FCS', 'i') or 0
local nFce = EgtGetInfo( Proc.id, 'FCE', 'i') or 0
return dDiam, dLen, nFcs, nFce
end
-------------------------------------------------------------------------------------------------------------
-- funzione che restituisce indice di completamento in base alla percentuale di volume lavorato
function FeatureData.GetFeatureCompletionIndex( dCompletionPercentage)
-- indice di completamento
local nCompletionIndex = 0
-- nullo
if dCompletionPercentage < 5 then
nCompletionIndex = 0
-- Low
elseif dCompletionPercentage < 50 then
nCompletionIndex = 1
-- Medium
elseif dCompletionPercentage < 80 then
nCompletionIndex = 2
-- High / Complete
else
nCompletionIndex = 5
end
return nCompletionIndex
end
-------------------------------------------------------------------------------------------------------------
-- funzione che restituisce qualità della lavorazione in base agli utensili utilizzati
function FeatureData.GetFeatureQuality( sTypeTools)
local nQuality = 5
local TypeTools = EgtSplitString( sTypeTools)
-- indice in base a utensile
for i=1, #TypeTools do
if TypeTools[i] == 'Blade' then
nQuality = min( nQuality, 5)
elseif TypeTools[i] == 'Mill' then
nQuality = min( nQuality, 4)
elseif TypeTools[i] == 'Chainsaw' then
nQuality = min( nQuality, 2)
else
nQuality = min( nQuality, 1)
end
end
-- se si utilizzano più utensili si perde in qualità
if #TypeTools > 1 then
nQuality = nQuality - 1
end
return nQuality
end
-------------------------------------------------------------------------------------------------------------
return FeatureData
File diff suppressed because it is too large Load Diff
+6 -6
View File
@@ -6,16 +6,16 @@
local Identity = {}
---------------------------------------------------------------------
------------------------ EGALWARE FEATURES ------------------------
------------------------ SPECIAL TOPOLOGY -------------------------
---------------------------------------------------------------------
-- Feature : Head Cut
function Identity.IsHeadCut( Proc)
return ( Proc.nGrp == 1 and Proc.nPrc == 340)
return Identity.IsCut( Proc) and Proc.Topology.sName == 'HeadCut'
end
---------------------------------------------------------------------
-- Feature : Split Cut
function Identity.IsSplitCut( Proc)
return ( Proc.nGrp == 2 and Proc.nPrc == 350)
-- Feature : Tail Cut
function Identity.IsTailCut( Proc)
return Identity.IsCut( Proc) and Proc.Topology.sName == 'TailCut'
end
---------------------------------------------------------------------
@@ -117,7 +117,7 @@ function Identity.IsPocket( Proc)
end
---------------------------------------------------------------------
-- Feature : Drilling
function Identity.IsDrilling( Proc)
function Identity.IsDrill( Proc)
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 40)
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
+200
View File
@@ -0,0 +1,200 @@
-- Logs.lua by Egalware s.r.l. 2024/11/20
-- Libreria per logs vari
-- Tabella per definizione modulo
local Logs = {}
-------------------------------------------------------------------------------------------------------------
function Logs.WriteFeaturesLog( ProcessingsOnPart, PartInfo, nReProcessCycles)
local nCycles = 1
local nOffsetIndex = 0
if #ProcessingsOnPart.Rotation > 4 then
nCycles = 2
end
EgtOutLog( ' === === === === === === === === === === REPROCESS CYCLES ' .. EgtNumToString( nReProcessCycles) .. ' === === === === === === === === === === === ===')
EgtOutLog( ' === === === === === === === === === === FEATURES STRATEGIES === === === === === === === === === === === ===')
for nCycle = 1, nCycles do
local nStartIndex = 1 + nOffsetIndex
local nEndIndex = 4 + nOffsetIndex
EgtOutLog( ' === === === === === === === === === === === === === === === === === === === === === === === === === === ===')
EgtOutLog( ' === === === === === === === === FEATURES STRATEGIES PIECE INVERTED === === === === === === === === === ===')
EgtOutLog( ' Feature ID | BTL POSITION | 90 ROTATION | 180 ROTATION | 270 ROTATION |')
EgtOutLog( '----------------------------------------------------------------------------------------------------------')
local nProcessingsNumber
local nFirstAvailableRotation
-- ricerco prima rotazione effettivamente calcolata. In genere è sempre la prima
for i = nStartIndex, nEndIndex do
if PartInfo.CombinationList.Rotations[i-nOffsetIndex] == 1 then
nProcessingsNumber = #ProcessingsOnPart.Rotation[i]
nFirstAvailableRotation = i
break
end
end
-- per ogni feature
for ProcLog = 1, nProcessingsNumber do
-- ricavo il massimo numero di strategie per feature
local nMaxStrategiesPerFeature = 0
for nRotLog = nStartIndex, nEndIndex do
if PartInfo.CombinationList.Rotations[nRotLog-nOffsetIndex] == 1 and ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies then
nMaxStrategiesPerFeature = max( nMaxStrategiesPerFeature, #ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies)
end
end
-- ciclo su tutte le strategie
for nCountStrategies = 1, nMaxStrategiesPerFeature do
local sLogLine = ''
-- al primo ciclo scrivo ID feature
if nCountStrategies == 1 then
sLogLine = ' ' .. tostring( ProcessingsOnPart.Rotation[nFirstAvailableRotation][ProcLog].id)
while string.len( sLogLine) <= 20 do
sLogLine = sLogLine .. ' '
end
sLogLine = sLogLine .. '|'
else
sLogLine = ' |'
end
for nRotLog = nStartIndex, nEndIndex do
-- se rotazione abilitata
if PartInfo.CombinationList.Rotations[nRotLog-nOffsetIndex] == 1 then
-- se ci sono strategie
if ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies and ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies] then
-- se la strategia è stat processata e ha un risultato
if ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies].Result then
-- leggo lo stato della strategia per aggiungere un suffisso
local sStatusStrategy = ' '
local sIndexes, sRating = '', ''
if not ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies].Result.sStatus or
ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies].Result.sStatus == 'Not-Applicable' then
sStatusStrategy = 'N'
sRating = '----'
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'
elseif ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies].Result.sStatus == 'Not-Completed' then
sStatusStrategy = 'P'
end
sRating = EgtNumToString( ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies].Result.dCompositeRating, -1)
sIndexes = ' (C:'.. EgtNumToString( ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies].Result.dCompletionIndex, -1)..
'|Q:'.. EgtNumToString( ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies].Result.dQuality, -1)..
'|T:'.. EgtNumToString( ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies].Result.dTimeIndex, -1)..')'
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 .. ' (' ..
tostring( ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies].sStrategyId) .. ')' ..
sStatusStrategy .. ' |'
while string.len( sLogLineProc) <= 38 do
sLogLineProc = ' ' .. sLogLineProc
end
sLogLine = sLogLine .. sLogLineProc
else
sLogLine = sLogLine .. ' 0 (STR----)- |'
end
else
sLogLine = sLogLine .. ' |'
end
-- rotazione non presa in considerazione
else
if nCountStrategies == 1 then
sLogLine = sLogLine .. ' ---------- |'
else
sLogLine = sLogLine .. ' |'
end
end
end
EgtOutLog( sLogLine)
end
end
EgtOutLog( '----------------------------------------------------------------------------------------------------------')
nOffsetIndex = 4
end
end
-------------------------------------------------------------------------------------------------------------
function Logs.WriteCombinationLog( CombinationsList, BestCombination)
EgtOutLog( ' === === === === === === === === === === COMBINATIONS === === === === === === ')
EgtOutLog( ' COMBI (UNL) POS | RATING | COMPLETE | NO COMPL | NO EXEC | ROTATE |')
EgtOutLog( '------------------------------------------------------------------------------')
for CombiLog = 1, #CombinationsList do
local sPartPosition = EgtIf( CombinationsList[CombiLog].bPartInCombiIsInverted, 'INV', 'ORI')
local sLogLine = ' ' .. CombinationsList[CombiLog].sBitIndexCombination .. ' (' .. CombinationsList[CombiLog].nUnloadPos .. ') ' .. sPartPosition .. ' |'
-- rating
local sOtherField = EgtNumToString( CombinationsList[CombiLog].dTotalRating, - 3) .. ' |'
while string.len( sOtherField) <= 15 do
sOtherField = ' ' .. sOtherField
end
sLogLine = sLogLine .. sOtherField
-- completed
sOtherField = tostring( CombinationsList[CombiLog].nComplete) .. ' |'
while string.len( sOtherField) <= 11 do
sOtherField = ' ' .. sOtherField
end
sLogLine = sLogLine .. sOtherField
-- not completed
sOtherField = tostring( CombinationsList[CombiLog].nNotComplete) .. ' |'
while string.len( sOtherField) <= 11 do
sOtherField = ' ' .. sOtherField
end
sLogLine = sLogLine .. sOtherField
-- not executed
sOtherField = tostring( CombinationsList[CombiLog].nNotExecute) .. ' |'
while string.len( sOtherField) <= 11 do
sOtherField = ' ' .. sOtherField
end
sLogLine = sLogLine .. sOtherField
-- rotations
sOtherField = tostring( CombinationsList[CombiLog].nRotations) .. ' |'
while string.len( sOtherField) <= 11 do
sOtherField = ' ' .. sOtherField
end
sLogLine = sLogLine .. sOtherField
EgtOutLog( sLogLine)
end
local sPartPosition = EgtIf( BestCombination.bPartInCombiIsInverted, 'INV', 'ORI')
EgtOutLog( '------------------------------------------------------------------------------')
EgtOutLog( ' BEST ROTATION : ' .. BestCombination.sBitIndexCombination .. ' (' .. BestCombination.nUnloadPos .. ') ' .. sPartPosition)
EgtOutLog( '---------------------------')
end
-------------------------------------------------------------------------------------------------------------
function Logs.WriteMainFacesLog( Proc, MainFaces)
-- reset eventuali visualizzazioni facce a due colori
EgtSurfTmResetTwoColors( Proc.id)
if MainFaces.BottomFaces then
for i = 1, #MainFaces.BottomFaces do
EgtOutLog( 'Bottom Face : ' .. MainFaces.BottomFaces[i].id)
end
-- colore differente per la faccia di fondo principale
--EgtSurfTmSetFaceColor( Proc.id, MainFaces.BottomFaces[1].id, 1)
end
if MainFaces.LongFaces then
for i = 1, #MainFaces.LongFaces do
EgtOutLog( 'Long Face : ' .. MainFaces.LongFaces[i].id)
end
end
if MainFaces.SideFaces then
for i = 1, #MainFaces.SideFaces do
EgtOutLog( 'Side Face : ' .. MainFaces.SideFaces[i].id)
end
end
if MainFaces.TunnelAddedFaces then
EgtOutLog( 'Middle Face (Trimesh): ' .. MainFaces.TunnelAddedFaces.MiddleFaceTm.id)
end
end
---------------------------------------------------------------------
return Logs
+1532 -150
View File
File diff suppressed because it is too large Load Diff
+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
+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')
+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')
+95 -42
View File
@@ -13,7 +13,7 @@ EgtEnableDebug( false)
EgtAddToPackagePath( BEAM.BASEDIR .. '\\LuaLibs\\?.lua')
-- Imposto direttorio strategie. N.B. Le strategie dovranno essere caricate con il nome del direttorio padre
EgtAddToPackagePath( BEAM.BASEDIR .. '\\Strategies\\Standard\\?.lua')
EgtAddToPackagePath( BEAM.BASEDIR .. '\\Strategies\\Core\\?.lua')
EgtAddToPackagePath( BEAM.BASEDIR .. '\\StrategyLibs\\?.lua')
-- Verifico che la macchina corrente sia abilitata per la lavorazione delle Travi
local sMachDir = EgtGetCurrMachineDir()
@@ -21,7 +21,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')
return
end
@@ -34,31 +34,37 @@ EgtAddToPackagePath( sMachDir .. '\\Beam\\?.lua')
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.BeamData = nil
_G.package.loaded.Identity = nil
_G.package.loaded.BasicCustomerStrategies = nil
_G.package.loaded.FeatureData = 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( tostring( i/10000, 4), '0.', '')
local sLibraryToReload = "STR" .. IdSTRTemp .. "\\STR" .. IdSTRTemp
local sLibraryConfigToReload = sLibraryToReload .. "Config"
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
if _G.package.loaded[sLibraryConfigToReload] then
_G.package.loaded[sLibraryConfigToReload] = nil
end
end
local vtCoreStrategiesNames = EgtFindAllFiles( BEAM.BASEDIR .. '\\Strategies\\Core\\*.lua')
local vtCoreStrategiesNames = EgtFindAllFiles( BEAM.BASEDIR .. '\\StrategyLibs\\*.lua')
for i = 1, #vtCoreStrategiesNames do
local sCurrentName = EgtSplitString( vtCoreStrategiesNames[i], '.')[1]
if _G.package.loaded[sCurrentName] then
@@ -66,13 +72,15 @@ for i = 1, #vtCoreStrategiesNames do
end
end
local BeamExec = require( 'BeamExec')
-- Variabili globali
PARTS = {}
PARTS = {} -- tabella contenente tutte le informazioni di ogni pezzo
-- Carico i dati globali
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
-- carico librerie
local BeamExec = require( 'BeamExec')
local BeamLib = require( 'BeamLib')
-- Variabili di modulo
local dRawW
@@ -121,15 +129,15 @@ local function MyProcessInputData()
EgtOutBox( 'Box non definito per la trave ' .. PARTS[i].sName, 'Lavora Travi', 'ERROR')
return false
else
PARTS[i].b3Box = b3Solid
PARTS[i].b3PartOriginal = b3Solid
end
end
dRawW = PARTS[1].b3Box:getDimY()
dRawH = PARTS[1].b3Box:getDimZ()
dRawW = PARTS[1].b3PartOriginal:getDimY()
dRawH = PARTS[1].b3PartOriginal:getDimZ()
local vBeamErr = {}
for i = 2, #PARTS do
local dDimW = PARTS[i].b3Box:getDimY()
local dDimH = PARTS[i].b3Box:getDimZ()
local dDimW = PARTS[i].b3PartOriginal:getDimY()
local dDimH = PARTS[i].b3PartOriginal:getDimZ()
if ( abs( dDimW - dRawW) > 10 * GEO.EPS_SMALL or abs( dDimH - dRawH) > 10 * GEO.EPS_SMALL) and
( abs( dDimH - dRawW) > 10 * GEO.EPS_SMALL or abs( dDimW - dRawH) > 10 * GEO.EPS_SMALL) then
table.insert( vBeamErr, i)
@@ -157,11 +165,6 @@ end
local function GetDataConfig()
-- recupero utensili dal magazzino
BeamExec.GetToolsFromDB()
-- se si utilizza interfaccia B&W, si carica il file JSON
local bIsBeamWall = true -- TODO serve parametro per capire se stiamo utilizzando B&W
if bIsBeamWall then
BeamExec.GetStrategiesFromJSONinBD()
end
-- TODO da gestire eventuali errori bloccanti
return true
end
@@ -176,9 +179,9 @@ local function MyProcessBeams()
-- Lunghezza totale delle travi
local dTotLen = 0
for i = 1, #PARTS - 1 do
dTotLen = dTotLen + PARTS[i].b3Box:getDimX()
dTotLen = dTotLen + PARTS[i].b3PartOriginal:getDimX()
end
dTotLen = dTotLen + max( PARTS[#PARTS].b3Box:getDimX(), BeamData.dMinRaw)
dTotLen = dTotLen + max( PARTS[#PARTS].b3PartOriginal:getDimX(), BeamData.dMinRaw)
local dAddLen = BeamData.OVM_HEAD + ( #PARTS - 1) * BeamData.OVM_MID
EgtOutLog( 'Ltot : '..EgtNumToString( dTotLen, 1) .. ' Lagg : '..EgtNumToString( dAddLen, 1)..' MinUnloadRaw : '.. EgtNumToString( BeamData.dMinRaw + BeamData.OVM_MID, 1), 1)
@@ -267,10 +270,10 @@ local function MyProcessBeams()
local bOrd = ( vsVal[5] == 'true')
if bOrd then
table.sort( PARTS, function( B1, B2)
if abs( B1.b3Box:getDimX() - B2.b3Box:getDimX()) < 1 then
if abs( B1.b3PartOriginal:getDimX() - B2.b3PartOriginal:getDimX()) < 1 then
return B1.nInd < B2.nInd
else
return B1.b3Box:getDimX() < B2.b3Box:getDimX()
return B1.b3PartOriginal:getDimX() < B2.b3PartOriginal:getDimX()
end
end)
end
@@ -284,7 +287,7 @@ local function MyProcessBeams()
end
-- Sistemo le travi nel grezzo
local bOk, sErr = BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS)
local bOk, sErr = BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS, nil, false)
if not bOk then
EgtOutLog( sErr)
EgtOutBox( sErr, 'Lavora Travi', 'ERROR')
@@ -298,24 +301,55 @@ end
-- *** Inserimento delle lavorazioni nelle travi ***
-------------------------------------------------------------------------------------------------------------
local function MyProcessFeatures()
local bOk, Stats = BeamExec.ProcessFeatures( PARTS)
BeamExec.GetProcessings( PARTS, false)
BeamExec.GetCombinationMatrix( PARTS, false)
BeamExec.ProcessMachinings( PARTS, false)
local nErrCnt = 0
local nWarnCnt = 0
local sOutput = ''
for i = 1, #Stats do
if Stats[i].nErr > 0 then
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
sOutput = sOutput .. string.format( '[%d,%d] %s\n', Stats[i].idCut, Stats[i].idTask, Stats[i].sMsg)
elseif Stats[i].nErr < 0 then
-- se segnalazione scarico pezzo standard, incompleto o a caduta
if Stats[i].nErr == -100 or Stats[i].nErr == -101 or Stats[i].nErr == -102 then
-- non faccio niente
else
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
sOutput = sOutput .. string.format( '[%d,%d] %s\n', Stats[i].idCut, Stats[i].idTask, Stats[i].sMsg)
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
-- 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')
@@ -331,8 +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
@@ -340,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
+893
View File
@@ -0,0 +1,893 @@
[
{
"sName":"Cut",
"nPrc": 10,
"nGrp": 1,
"TopologyList" : [
{ "sName": "Cut-1-Through",
"sImage": "ConfigStrategy\\Cut-1-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" } ]
},
{ "sName": "Bevel-1-Through",
"sImage": "ConfigStrategy\\Bevel-1-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" } ]
},
{ "sName": "HeadCut",
"sImage": "ConfigStrategy\\HeadCut.png",
"StrategyList" : [ { "sStrategyId": "HEADCUT" } ]
},
{ "sName": "TailCut",
"sImage": "ConfigStrategy\\TailCut.png",
"StrategyList" : [ { "sStrategyId": "TAILCUT" } ]
}
]
},
{
"sName":"Longitudinal Cut",
"nPrc": 10,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "ConfigStrategy\\Bevel-1-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" }, { "sStrategyId": "STR0010" } ]
}
]
},
{
"sName":"Double Cut",
"nPrc": 11,
"nGrp": 1,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "ConfigStrategy\\DoubleCut.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" }, { "sStrategyId": "STR0010" } ]
}
]
},
{
"sName":"Ridge or Valley Cut",
"nPrc": 12,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "ConfigStrategy\\RidgeValleyCut.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" }, { "sStrategyId": "STR0010" } ]
}
]
},
{
"sName":"Saw Cut",
"nPrc": 13,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Cut-1-Through",
"sImage": "ConfigStrategy\\Cut-1-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" }, { "sStrategyId": "STR0010" } ]
},
{ "sName": "Bevel-1-Through",
"sImage": "ConfigStrategy\\Bevel-1-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" }, { "sStrategyId": "STR0010" } ]
}
]
},
{
"sName":"Slot",
"nPrc": 16,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Pocket-5-Blind",
"sImage": "ConfigStrategy\\Pocket-5-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Groove-4-Blind",
"sImage": "ConfigStrategy\\Groove-4-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Groove-3-Through",
"sImage": "ConfigStrategy\\Groove-3-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Tunnel-4-Through",
"sImage": "ConfigStrategy\\Tunnel-4-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Groove-3-Blind",
"sImage": "ConfigStrategy\\Groove-3-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" } ]
},
{ "sName": "Bevel-3-Blind",
"sImage": "ConfigStrategy\\Bevel-3-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" } ]
},
{ "sName": "Bevel-2-Blind",
"sImage": "ConfigStrategy\\Bevel-2-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" }, { "sStrategyId": "STR0010" } ]
},
{ "sName": "Rabbet-2-Through",
"sImage": "ConfigStrategy\\Rabbet-2-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" }, { "sStrategyId": "STR0010"} ]
},
{ "sName": "Cut-1-Through",
"sImage": "ConfigStrategy\\Cut-1-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" } ]
}
]
},
{
"sName":"Front Slot",
"nPrc": 17,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Pocket-5-Blind",
"sImage": "ConfigStrategy\\Pocket-5-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Groove-4-Blind",
"sImage": "ConfigStrategy\\Groove-4-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Groove-3-Through",
"sImage": "ConfigStrategy\\Groove-3-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Tunnel-4-Through",
"sImage": "ConfigStrategy\\Tunnel-4-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Groove-3-Blind",
"sImage": "ConfigStrategy\\Groove-3-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" } ]
},
{ "sName": "Bevel-3-Blind",
"sImage": "ConfigStrategy\\Bevel-3-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" } ]
},
{ "sName": "Bevel-2-Blind",
"sImage": "ConfigStrategy\\Bevel-2-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" }, { "sStrategyId": "STR0010" } ]
},
{ "sName": "Rabbet-2-Through",
"sImage": "ConfigStrategy\\Rabbet-2-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" }, { "sStrategyId": "STR0010"} ]
},
{ "sName": "Cut-1-Through",
"sImage": "ConfigStrategy\\Cut-1-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" } ]
}
]
},
{
"sName":"Birds Mouth",
"nPrc": 20,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" }, { "sStrategyId": "STR0010"} ]
}
]
},
{
"sName":"Hip or Valley Rafter Notch",
"nPrc": 25,
"nGrp": 0,
"TopologyList" : [
{ "sName": "RafterNotch-5-Through",
"sImage": "",
"StrategyList" : [ { "sStrategyId": "STR0002" } ]
},
{ "sName": "Groove-3-Through",
"sImage": "ConfigStrategy\\Groove-3-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Groove-3-Blind",
"sImage": "ConfigStrategy\\Groove-3-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" } ]
},
{ "sName": "Bevel-3-Blind",
"sImage": "ConfigStrategy\\Bevel-3-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" } ]
},
{ "sName": "Bevel-2-Blind",
"sImage": "ConfigStrategy\\Bevel-2-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" }, { "sStrategyId": "STR0010" } ]
},
{ "sName": "Rabbet-2-Through",
"sImage": "ConfigStrategy\\Rabbet-2-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" }, { "sStrategyId": "STR0010"} ]
}
]
},
{
"sName":"Ridge Lap",
"nPrc": 30,
"nGrp": 1,
"TopologyList" : [
{ "sName": "RidgeLap-3-Through",
"sImage": "",
"StrategyList" : [ { "sStrategyId": "STR0012"} ]
},
{ "sName": "Groove-3-Blind",
"sImage": "ConfigStrategy\\Groove-3-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" } ]
},
{ "sName": "Bevel-3-Blind",
"sImage": "ConfigStrategy\\Bevel-3-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" } ]
},
{ "sName": "Bevel-2-Blind",
"sImage": "ConfigStrategy\\Bevel-2-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" }, { "sStrategyId": "STR0010" } ]
},
{ "sName": "Rabbet-2-Through",
"sImage": "ConfigStrategy\\Rabbet-2-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" }, { "sStrategyId": "STR0010"} ]
},
{ "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"} ]
}
]
},
{
"sName":"Lap Joint",
"nPrc": 30,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Pocket-5-Blind",
"sImage": "ConfigStrategy\\Pocket-5-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Groove-4-Blind",
"sImage": "ConfigStrategy\\Groove-4-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Groove-3-Through",
"sImage": "ConfigStrategy\\Groove-3-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Tunnel-4-Through",
"sImage": "ConfigStrategy\\Tunnel-4-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Groove-3-Blind",
"sImage": "ConfigStrategy\\Groove-3-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" } ]
},
{ "sName": "Bevel-3-Blind",
"sImage": "ConfigStrategy\\Bevel-3-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" } ]
},
{ "sName": "Bevel-2-Blind",
"sImage": "ConfigStrategy\\Bevel-2-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" }, { "sStrategyId": "STR0010" } ]
},
{ "sName": "Rabbet-2-Through",
"sImage": "ConfigStrategy\\Rabbet-2-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" }, { "sStrategyId": "STR0010"} ]
},
{ "sName": "Cut-1-Through",
"sImage": "ConfigStrategy\\Cut-1-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" } ]
}
]
},
{
"sName":"Notch/Rabbet",
"nPrc": 32,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Pocket-5-Blind",
"sImage": "ConfigStrategy\\Pocket-5-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Groove-4-Blind",
"sImage": "ConfigStrategy\\Groove-4-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Groove-3-Through",
"sImage": "ConfigStrategy\\Groove-3-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Tunnel-4-Through",
"sImage": "ConfigStrategy\\Tunnel-4-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Groove-3-Blind",
"sImage": "ConfigStrategy\\Groove-3-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" } ]
},
{ "sName": "Bevel-3-Blind",
"sImage": "ConfigStrategy\\Bevel-3-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" } ]
},
{ "sName": "Bevel-2-Blind",
"sImage": "ConfigStrategy\\Bevel-2-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" }, { "sStrategyId": "STR0010" } ]
},
{ "sName": "Rabbet-2-Through",
"sImage": "ConfigStrategy\\Rabbet-2-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" }, { "sStrategyId": "STR0010"} ]
},
{ "sName": "Cut-1-Through",
"sImage": "ConfigStrategy\\Cut-1-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" } ]
}
]
},
{
"sName":"Block Haus",
"nPrc": 33,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "BlockHouse.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
}
]
},
{
"sName":"Notch",
"nPrc": 34,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Pocket-5-Blind",
"sImage": "ConfigStrategy\\Pocket-5-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Groove-4-Blind",
"sImage": "ConfigStrategy\\Groove-4-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Groove-3-Through",
"sImage": "ConfigStrategy\\Groove-3-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Tunnel-4-Through",
"sImage": "ConfigStrategy\\Tunnel-4-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Groove-3-Blind",
"sImage": "ConfigStrategy\\Groove-3-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" } ]
},
{ "sName": "Bevel-3-Blind",
"sImage": "ConfigStrategy\\Bevel-3-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" } ]
},
{ "sName": "Bevel-2-Blind",
"sImage": "ConfigStrategy\\Bevel-2-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" }, { "sStrategyId": "STR0010" } ]
},
{ "sName": "Rabbet-2-Through",
"sImage": "ConfigStrategy\\Rabbet-2-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" }, { "sStrategyId": "STR0010"} ]
},
{ "sName": "Cut-1-Through",
"sImage": "ConfigStrategy\\Cut-1-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" } ]
}
]
},
{
"sName":"French Ridge Lap",
"nPrc": 35,
"nGrp": 1,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "ConfigStrategy\\FrenchRidgeLap.png",
"StrategyList" : [ ]
}
]
},
{
"sName":"Chamfer",
"nPrc": 36,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "ConfigStrategy\\Chamfer.png",
"StrategyList" : [ ]
}
]
},
{
"sName":"Block Haus Half Lap",
"nPrc": 37,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "ConfigStrategy\\BlockHouseHalfLap.png",
"StrategyList" : [ ]
}
]
},
{
"sName":"Block Haus Front",
"nPrc": 38,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "ConfigStrategy\\BlockHouseFront.png",
"StrategyList" : [ ]
}
]
},
{
"sName":"Pocket",
"nPrc": 39,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Pocket-5-Blind",
"sImage": "ConfigStrategy\\Pocket-5-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Groove-4-Blind",
"sImage": "ConfigStrategy\\Groove-4-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Groove-3-Through",
"sImage": "ConfigStrategy\\Groove-3-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Tunnel-4-Through",
"sImage": "ConfigStrategy\\Tunnel-4-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Groove-3-Blind",
"sImage": "ConfigStrategy\\Groove-3-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" } ]
},
{ "sName": "Bevel-3-Blind",
"sImage": "ConfigStrategy\\Bevel-3-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" } ]
},
{ "sName": "Bevel-2-Blind",
"sImage": "ConfigStrategy\\Bevel-2-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" }, { "sStrategyId": "STR0010" } ]
},
{ "sName": "Rabbet-2-Through",
"sImage": "ConfigStrategy\\Rabbet-2-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" }, { "sStrategyId": "STR0010"} ]
},
{ "sName": "Cut-1-Through",
"sImage": "ConfigStrategy\\Cut-1-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" } ]
}
]
},
{
"sName":"Drilling",
"nPrc": 40,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "ConfigStrategy\\Drilling.png",
"StrategyList" : [ { "sStrategyId": "STR0011" }, { "sStrategyId": "STR0013" } ]
}
]
},
{
"sName":"Tenon",
"nPrc": 50,
"nGrp": 1,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "ConfigStrategy\\Tenon.png",
"StrategyList" : [ { "sStrategyId": "STR0006" } ]
}
]
},
{
"sName":"Mortise",
"nPrc": 50,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Pocket-5-Blind",
"sImage": "ConfigStrategy\\Pocket-5-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Groove-4-Blind",
"sImage": "ConfigStrategy\\Groove-4-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Groove-3-Through",
"sImage": "ConfigStrategy\\Groove-3-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Tunnel-4-Through",
"sImage": "ConfigStrategy\\Tunnel-4-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Groove-3-Blind",
"sImage": "ConfigStrategy\\Groove-3-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" } ]
},
{ "sName": "Bevel-3-Blind",
"sImage": "ConfigStrategy\\Bevel-3-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" } ]
},
{ "sName": "Bevel-2-Blind",
"sImage": "ConfigStrategy\\Bevel-2-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" }, { "sStrategyId": "STR0010" } ]
},
{ "sName": "Rabbet-2-Through",
"sImage": "ConfigStrategy\\Rabbet-2-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" }, { "sStrategyId": "STR0010"} ]
},
{ "sName": "Cut-1-Through",
"sImage": "ConfigStrategy\\Cut-1-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" } ]
},
{ "sName": "Pocket-Round",
"sImage": "ConfigStrategy\\Pocket-Round.png",
"StrategyList" : [ { "sStrategyId": "STR0008" } ]
},
{ "sName": "Pocket-Round-Front",
"sImage": "ConfigStrategy\\MortiseFront.png",
"StrategyList" : [ { "sStrategyId": "STR0008" } ]
},
{ "sName": "Pocket-Round-Through",
"sImage": "",
"StrategyList" : [ { "sStrategyId": "STR0008" } ]
}
]
},
{
"sName":"Front Mortise",
"nPrc": 51,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Pocket-5-Blind",
"sImage": "ConfigStrategy\\Pocket-5-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Groove-4-Blind",
"sImage": "ConfigStrategy\\Groove-4-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Groove-3-Through",
"sImage": "ConfigStrategy\\Groove-3-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Tunnel-4-Through",
"sImage": "ConfigStrategy\\Tunnel-4-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0003" }, { "sStrategyId": "STR0004" } ]
},
{ "sName": "Groove-3-Blind",
"sImage": "ConfigStrategy\\Groove-3-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" } ]
},
{ "sName": "Bevel-3-Blind",
"sImage": "ConfigStrategy\\Bevel-3-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" } ]
},
{ "sName": "Bevel-2-Blind",
"sImage": "ConfigStrategy\\Bevel-2-Blind.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" }, { "sStrategyId": "STR0010" } ]
},
{ "sName": "Rabbet-2-Through",
"sImage": "ConfigStrategy\\Rabbet-2-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" }, { "sStrategyId": "STR0010"} ]
},
{ "sName": "Cut-1-Through",
"sImage": "ConfigStrategy\\Cut-1-Through.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0005" } ]
},
{ "sName": "Pocket-Round",
"sImage": "ConfigStrategy\\Pocket-Round.png",
"StrategyList" : [ { "sStrategyId": "STR0008" } ]
},
{ "sName": "Pocket-Round-Front",
"sImage": "ConfigStrategy\\MortiseFront.png",
"StrategyList" : [ { "sStrategyId": "STR0008" } ]
},
{ "sName": "Pocket-Round-Through",
"sImage": "",
"StrategyList" : [ { "sStrategyId": "STR0008" } ]
}
]
},
{
"sName":"House",
"nPrc": 52,
"nGrp": 1,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "",
"StrategyList" : [ ]
}
]
},
{
"sName":"House Mortise",
"nPrc": 53,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "",
"StrategyList" : [ ]
}
]
},
{
"sName":"Dovetail Tenon",
"nPrc": 55,
"nGrp": 1,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "ConfigStrategy\\DovetailTenon.png",
"StrategyList" : [ { "sStrategyId": "STR0001" } ]
}
]
},
{
"sName":"Dovetail Mortise",
"nPrc": 55,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "ConfigStrategy\\DovetailMortise.png",
"StrategyList" : [ { "sStrategyId": "STR0007" } ]
}
]
},
{
"sName":"Dovetail Mortise Front",
"nPrc": 56,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "ConfigStrategy\\DovetailMortiseFront.png",
"StrategyList" : [ { "sStrategyId": "STR0007" } ]
}
]
},
{
"sName":"Marking",
"nPrc": 60,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "ConfigStrategy\\Text.png",
"StrategyList" : [ { "sStrategyId": "STR0014" }]
}
]
},
{
"sName":"Text",
"nPrc": 61,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "ConfigStrategy\\Text.png",
"StrategyList" : [ { "sStrategyId": "STR0014" }]
}
]
},
{
"sName":"Scarf Simple",
"nPrc": 70,
"nGrp": 1,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "ConfigStrategy\\ScarfSimple.png",
"StrategyList" : [ ]
}
]
},
{
"sName":"Scarf Joint",
"nPrc": 71,
"nGrp": 1,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "ConfigStrategy\\ScarfJoint.png",
"StrategyList" : [ { "sStrategyId": "STR0009" }]
}
]
},
{
"sName":"Step Joint",
"nPrc": 80,
"nGrp": 1,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "ConfigStrategy\\StepJoint.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0010"} ]
}
]
},
{
"sName":"Step Joint Notch",
"nPrc": 80,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "ConfigStrategy\\StepJointNotch.png",
"StrategyList" : [ { "sStrategyId": "STR0002" }, { "sStrategyId": "STR0010"} ]
}
]
},
{
"sName":"Planing",
"nPrc": 90,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "ConfigStrategy\\Planing.png",
"StrategyList" : [ ]
}
]
},
{
"sName":"Front Profile",
"nPrc": 100,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "ConfigStrategy\\ProfileFront.png",
"StrategyList" : [ { "sStrategyId": "STR0015" } ]
}
]
},
{
"sName":"Head Concave Profile",
"nPrc": 101,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "ConfigStrategy\\ProfileHeadConcave.png",
"StrategyList" : [ { "sStrategyId": "STR0015" } ]
}
]
},
{
"sName":"Head Convex Profile",
"nPrc": 102,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "ConfigStrategy\\ProfileHeadConvex.png",
"StrategyList" : [ { "sStrategyId": "STR0015" } ]
}
]
},
{
"sName":"Head Cambered Profile",
"nPrc": 103,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "ConfigStrategy\\ProfileHeadCambered.png",
"StrategyList" : [ { "sStrategyId": "STR0015" } ]
}
]
},
{
"sName":"Round Arch",
"nPrc": 104,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "ConfigStrategy\\RoundArch.png",
"StrategyList" : [ { "sStrategyId": "STR0015" } ]
}
]
},
{
"sName":"Head Profile",
"nPrc": 106,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "ConfigStrategy\\ProfileHead.png",
"StrategyList" : [ { "sStrategyId": "STR0015" } ]
}
]
},
{
"sName":"Sphere",
"nPrc": 107,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "",
"StrategyList" : [ ]
}
]
},
{
"sName":"Triangle Cut",
"nPrc": 120,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "ConfigStrategy\\TriangleCut.png",
"StrategyList" : [ ]
}
]
},
{
"sName":"TyroleanDovetail",
"nPrc": 136,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "ConfigStrategy\\TyroleanDovetail.png",
"StrategyList" : [ ]
}
]
},
{
"sName":"Dovetail",
"nPrc": 138,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "ConfigStrategy\\Dovetail.png",
"StrategyList" : [ ]
}
]
},
{
"sName":"Free Contour",
"nPrc": 250,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "ConfigStrategy\\ProfileHead.png",
"StrategyList" : [ { "sStrategyId": "STR0015" } ]
}
]
},
{
"sName":"Outline",
"nPrc": 251,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "",
"StrategyList" : [ ]
}
]
},
{
"sName":"Aperture",
"nPrc": 252,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "",
"StrategyList" : [ ]
}
]
},
{
"sName":"Variant",
"nPrc": 900,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "",
"StrategyList" : [ ]
}
]
},
{
"sName":"Decor",
"nPrc": 959,
"nGrp": 0,
"TopologyList" : [
{ "sName": "Feature",
"sImage": "",
"StrategyList" : [ ]
}
]
}
]
-257
View File
@@ -1,257 +0,0 @@
-- Strategia: SLOTBYBLADE
-- Descrizione
-- Strategia di base per la lavorazione delle slot o tasche con lama
-- Feature: tipo lapjoint
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local MachiningLib = require( 'MachiningLib')
-- Tabella per definizione modulo
local SLOTBYBLADE = {}
-------------------------------------------------------------------------------------------------------------
local function CalculateLeadInOut( Machining, EdgeToMachine)
-- TODO implementare le funzioni di Tool Collision Avoidance (vedi wiki e FacesBysaw -> CalcLeadInOutPerpGeom)
-- si determina l'eventuale riduzione da applicare in caso di inizio o fine chiusi
local dAddLengthToReduce = 0
dAddLengthToReduce = sqrt( Machining.dDepthToMachine * TOOLS[Machining.nToolIndex].dDiameter - Machining.dDepthToMachine * Machining.dDepthToMachine)
if Machining.bInvert then
Machining.bIsStartClosed, Machining.bIsEndClosed = Machining.bIsEndClosed, Machining.bIsStartClosed
end
local LeadIn = {}
local LeadOut = {}
LeadIn.dStartAddLength = 0
LeadOut.dEndAddLength = 0
LeadIn.nType = MCH_MILL_LI.LINEAR
LeadOut.nType = MCH_MILL_LI.LINEAR
LeadIn.dTangentDistance = 0
LeadOut.dTangentDistance = 0
if EdgeToMachine.dElevation > -10 * GEO.EPS_SMALL then
LeadIn.dPerpDistance = EdgeToMachine.dElevation + BeamData.CUT_SIC
LeadOut.dPerpDistance = EdgeToMachine.dElevation + BeamData.CUT_SIC
else
LeadIn.dPerpDistance = BeamData.CUT_SIC
LeadOut.dPerpDistance = BeamData.CUT_SIC
end
LeadIn.dElevation = 0
LeadOut.dElevation = 0
LeadIn.dCompLength = 0
LeadOut.dCompLength = 0
if Machining.bIsStartClosed and Machining.bIsEndClosed then
LeadIn.dStartAddLength = -dAddLengthToReduce
LeadOut.dEndAddLength = -dAddLengthToReduce
elseif Machining.bIsStartClosed then
LeadIn.dStartAddLength = -dAddLengthToReduce
-- 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 = -dAddLengthToReduce
-- 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 = BeamData.CUT_EXTRA
LeadOut.dEndAddLength = BeamData.CUT_EXTRA
end
return LeadIn, LeadOut
end
local function GetSCC( vtMachiningDirection)
-- TODO implementare SCC come per FacesBySaw
local nSCC = MCH_SCC.NONE
if AreSameVectorApprox( vtMachiningDirection, Z_AX()) then
nSCC = MCH_SCC.ADIR_ZP
elseif AreOppositeVectorApprox( vtMachiningDirection, Z_AX()) then
nSCC = MCH_SCC.ADIR_ZM
elseif AreSameVectorApprox( vtMachiningDirection, Y_AX()) then
nSCC = MCH_SCC.ADIR_YP
elseif AreOppositeVectorApprox( vtMachiningDirection, Y_AX()) then
nSCC = MCH_SCC.ADIR_YM
elseif AreSameVectorApprox( vtMachiningDirection, X_AX()) then
nSCC = MCH_SCC.ADIR_XP
elseif AreOppositeVectorApprox( vtMachiningDirection, X_AX()) then
nSCC = MCH_SCC.ADIR_XM
end
return nSCC
end
-- TODO calcolo area lavorata per completamento
function SLOTBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalParameters)
local Cutting = {}
Cutting.bIsApplicable = true
Cutting.dDepthToMachine = 0
Cutting.sMessage = ''
Cutting.idProc = Proc.id
Cutting.dResidualDepth = abs( EdgeToMachine.dElevation)
Cutting.dBladeMarkLength = 0
Cutting.sEdgeType = EdgeToMachine.sType
-- parametri opzionali
local bForceLongcutBlade = OptionalParameters.bForceLongcutBlade or false
local dPocketHeight = 0
if Proc.Topology.sFamily == 'Tunnel' then
dPocketHeight = Proc.MainFaces.SideFaces[1].MainEdges.OppositeEdges[1].dLength
else
if FaceToMachine.sType == 'Long' then
dPocketHeight = Proc.MainFaces.BottomFaces[1].MainEdges.SideEdges[1].dLength
elseif FaceToMachine.sType == 'Side' then
dPocketHeight = Proc.MainFaces.BottomFaces[1].MainEdges.LongEdges[1].dLength
end
end
-- ricerca utensile
local ToolSearchParameters = {}
ToolSearchParameters.dElevation = abs( EdgeToMachine.dElevation)
ToolSearchParameters.vtToolDirection = EdgeToMachine.vtToolDirection
ToolSearchParameters.bAllowTopHead = true
ToolSearchParameters.bAllowBottomHead = false
ToolSearchParameters.bForceLongcutBlade = bForceLongcutBlade
local ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters)
Cutting.nToolIndex = ToolInfo.nToolIndex
Cutting.nType = MCH_OY.MILLING
if not TOOLS[Cutting.nToolIndex].sName then
Cutting.sMessage = 'Blade not found'
Cutting.bIsApplicable = false
EgtOutLog( Cutting.sMessage)
return Cutting, EdgeToMachine.dElevation
end
-- verifica dimensioni tasca compatibili
-- se tasca meno spessa della lama la strategia non è applicabile
if TOOLS[Cutting.nToolIndex].dThickness > dPocketHeight + 10 * GEO.EPS_SMALL then
Cutting.sMessage = 'Pocket too narrow for blade thickness'
Cutting.bIsApplicable = false
EgtOutLog( Cutting.sMessage)
return Cutting, EdgeToMachine.dElevation
end
if #( Proc.MainFaces.SideFaces) > 1 then
-- se tasca più stretta della lama la strategia non è applicabile
if TOOLS[Cutting.nToolIndex].dDiameter > EdgeToMachine.dLength + 10 * GEO.EPS_SMALL then
Cutting.sMessage = 'Pocket too narrow for blade diameter'
Cutting.bIsApplicable = false
EgtOutLog( Cutting.sMessage)
return Cutting, EdgeToMachine.dElevation
end
end
-- parametri della lavorazione
-- profondità (parametro DEPTH) non usata
Cutting.sDepth = 0
-- inizio e fine aperti o chiusi
Cutting.bIsStartClosed = not EdgeToMachine.bIsStartOpen
Cutting.bIsEndClosed = not EdgeToMachine.bIsEndOpen
-- lato di lavoro e inversioni
if TOOLS[Cutting.nToolIndex].bIsCCW then
Cutting.nWorkside = MCH_MILL_WS.RIGHT
Cutting.bInvert = true
else
Cutting.nWorkside = MCH_MILL_WS.LEFT
Cutting.bInvert = false
end
if EdgeToMachine.dElevation < -10 * GEO.EPS_SMALL then
Cutting.bInvert = not Cutting.bInvert
end
-- TODO gestire lama da sotto e lama downUp
if FaceToMachine.vtN:getZ() < - 10 * GEO.EPS_SMALL then
Cutting.bToolInvert = true
Cutting.bInvert = not Cutting.bInvert
else
Cutting.bToolInvert = false
end
-- profondità da lavorare e offset radiale
if TOOLS[Cutting.nToolIndex].dMaxDepth > abs( EdgeToMachine.dElevation) - 10 * GEO.EPS_SMALL then
-- TODO la depth dovrebbe essere quella del machining
Cutting.dDepthToMachine = abs( EdgeToMachine.dElevation)
Cutting.dResidualDepth = 0
if EdgeToMachine.dElevation > -10 * GEO.EPS_SMALL then
Cutting.dRadialOffset = 0
else
Cutting.dRadialOffset = EdgeToMachine.dElevation
end
else
Cutting.dDepthToMachine = TOOLS[Cutting.nToolIndex].dMaxDepth - 1
Cutting.dResidualDepth = abs( EdgeToMachine.dElevation) - Cutting.dDepthToMachine
if EdgeToMachine.dElevation > -10 * GEO.EPS_SMALL then
Cutting.dRadialOffset = EdgeToMachine.dElevation - Cutting.dDepthToMachine
else
Cutting.dRadialOffset = -Cutting.dDepthToMachine
end
end
-- completamento
Cutting.dCompletionPercentage = 100 - Cutting.dResidualDepth / Cutting.dDepthToMachine
-- step verticale e offset longitudinale
Cutting.Steps = MachiningLib.GetMachiningSteps( 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 and Cutting.Steps.nCount > 1 then
Cutting.dLongitudinalOffset = - dPocketHeight
else
Cutting.dLongitudinalOffset = 0
end
-- distanza di sicurezza
Cutting.dStartSafetyLength = 10
-- overlap
Cutting.dOverlap = 0
-- faceuse
if EdgeToMachine.dElevation > - 10 * GEO.EPS_SMALL then
Cutting.nFaceuse = BeamLib.GetNearestOrthoOpposite( EdgeToMachine.vtToolDirection)
else
Cutting.nFaceuse = BeamLib.GetNearestOrthoOpposite( -EdgeToMachine.vtToolDirection)
end
-- SCC
Cutting.nSCC = GetSCC( EdgeToMachine.vtToolDirection)
-- asse bloccato
Cutting.sBlockedAxis = BeamLib.GetBlockedAxis( Cutting.nToolIndex, 'perpendicular', Part.b3Raw, FaceToMachine.vtN, EgtIf( FaceToMachine.vtN:getX() > 0, X_AX(), -X_AX()))
-- approccio e retrazione
Cutting.LeadIn, Cutting.LeadOut = CalculateLeadInOut( Cutting, EdgeToMachine)
-- eventuale step orizzontale
Cutting.HorizontalSteps = {}
if TOOLS[Cutting.nToolIndex].dSideStep then
Cutting.HorizontalSteps = MachiningLib.GetMachiningSteps( Cutting.dDepthToMachine, TOOLS[Cutting.nToolIndex].dSideStep)
else
Cutting.HorizontalSteps.nCount = 1
Cutting.HorizontalSteps.dStep = 0
end
-- lunghezza impronta lama
if Cutting.bIsStartClosed and Cutting.bIsEndClosed then
Cutting.dBladeMarkLength = abs( min( Cutting.LeadIn.dStartAddLength, Cutting.LeadOut.dEndAddLength))
elseif Cutting.bIsStartClosed then
Cutting.dBladeMarkLength = abs( Cutting.LeadIn.dStartAddLength)
elseif Cutting.bIsEndClosed then
Cutting.dBladeMarkLength = abs( Cutting.LeadOut.dEndAddLength)
end
-- geometria
Cutting.Geometry = {{Proc.id, FaceToMachine.id}}
-- nome operazione
Cutting.sOperationName = 'Cut_' .. ( EgtGetName( Cutting.idProc) or tostring( Cutting.idProc)) .. '_' .. tostring( FaceToMachine.id + 1)
-- eventuale avviso di danneggiamento pezzo successivo
-- TODO da sostituire con check se si riesce a separare e il grezzo dietro è lungo a sufficienza
-- local dOffsideLength = max( Cutting.LeadIn.dStartAddLength, Cutting.LeadOut.dEndAddLength) + TOOLS[Cutting.nToolIndex].dDiameter / 2 + 10 * GEO.EPS_SMALL
-- if ( not Proc.bTail or Proc.bAdvTail) and Proc.AffectedFaces.bLeft and ( Proc.dDistanceToNextPart < dOffsideLength) then
-- local sDamageNextPieceMessage = 'Feature '.. Proc.idFeature .. ' : sawblade can damage next piece.'
-- if #Cutting.sMessage > 0 then
-- Cutting.sMessage = Cutting.sMessage .. '\n' .. sDamageNextPieceMessage
-- else
-- Cutting.sMessage = sDamageNextPieceMessage
-- end
-- EgtOutLog( sDamageNextPieceMessage)
-- end
return Cutting
end
-------------------------------------------------------------------------------------------------------------
return SLOTBYBLADE
-232
View File
@@ -1,232 +0,0 @@
-- Strategia: SLOTBYCHAINSAW
-- Descrizione
-- Strategia di base per la lavorazione delle slot o tasche con sega a catena
-- Feature: tipo lapjoint
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local MachiningLib = require( 'MachiningLib')
-- Tabella per definizione modulo
local SLOTBYCHAINSAW = {}
-------------------------------------------------------------------------------------------------------------
local function CalculateLeadInOut( Machining, EdgeToMachine, sSideToMachine, dLengthToMachine)
-- TODO implementare le funzioni di Tool Collision Avoidance (vedi wiki e FacesBysaw -> CalcLeadInOutPerpGeom)
-- si determina l'eventuale riduzione da applicare in caso di inizio o fine chiusi
local dAddLengthToReduce = 0
dAddLengthToReduce = TOOLS[Machining.nToolIndex].dDiameter / 2
if Machining.bInvert then
Machining.bIsStartClosed, Machining.bIsEndClosed = Machining.bIsEndClosed, Machining.bIsStartClosed
end
local LeadIn = {}
local LeadOut = {}
LeadIn.dStartAddLength = 0
LeadOut.dEndAddLength = 0
if sSideToMachine == 'End' then
LeadIn.dStartAddLength = dAddLengthToReduce + dLengthToMachine + BeamData.CUT_EXTRA - EdgeToMachine.dLength
elseif Machining.bIsStartClosed then
LeadIn.dStartAddLength = -dAddLengthToReduce
else
LeadIn.dStartAddLength = BeamData.CUT_EXTRA
end
if sSideToMachine == 'Start' then
LeadOut.dEndAddLength = dAddLengthToReduce + dLengthToMachine + BeamData.CUT_EXTRA - EdgeToMachine.dLength
elseif Machining.bIsEndClosed then
LeadOut.dEndAddLength = -dAddLengthToReduce
else
LeadOut.dEndAddLength = BeamData.CUT_EXTRA
end
return LeadIn, LeadOut
end
-- TODO calcolo area lavorata per completamento
function SLOTBYCHAINSAW.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalParameters)
local Mortising = {}
Mortising.bIsApplicable = true
Mortising.dDepthToMachine = 0
Mortising.dResidualDepth = abs( EdgeToMachine.dElevation)
Mortising.sMessage = ''
Mortising.idProc = Proc.id
Mortising.sEdgeType = EdgeToMachine.sType
-- parametri opzionali
local bUseZigZagMortising = OptionalParameters.bUseZigZagMortising or false
local sSideToMachine = OptionalParameters.sSideToMachine or ''
local dLengthToMachine = OptionalParameters.dLengthToMachine or EdgeToMachine.dLength
local dCustomMaxElev = OptionalParameters.dMaxElev or abs( EdgeToMachine.dElevation)
local bStopAtHalfElevation = OptionalParameters.bStopAtHalfElevation or false
-- altezza tasca, in base alla topologia
local dPocketHeight = 0
if Proc.Topology.sFamily == 'Tunnel' then
dPocketHeight = Proc.MainFaces.SideFaces[1].MainEdges.OppositeEdges[1].dLength
else
if FaceToMachine.sType == 'Long' then
dPocketHeight = Proc.MainFaces.BottomFaces[1].MainEdges.SideEdges[1].dLength
elseif FaceToMachine.sType == 'Side' then
dPocketHeight = Proc.MainFaces.BottomFaces[1].MainEdges.LongEdges[1].dLength
end
end
-- ricerca utensile
local bExtendWithCornerRadius = false
if not bStopAtHalfElevation then
if ( EdgeToMachine.sType == 'Side' and Proc.Topology.sName == 'Groove-3-Through') or
( EdgeToMachine.sType == 'Opposite' and Proc.Topology.sFamily == 'Tunnel') then
bExtendWithCornerRadius = true
Mortising.dDepthToMachine = abs( EdgeToMachine.dElevation) + BeamData.CUT_EXTRA
else
Mortising.dDepthToMachine = abs( EdgeToMachine.dElevation)
end
else
bExtendWithCornerRadius = true
Mortising.dDepthToMachine = abs( EdgeToMachine.dElevation) / 2 + BeamData.CUT_EXTRA_MIN
end
local ToolSearchParameters = {}
local ToolInfo = {}
ToolSearchParameters.vtToolDirection = EdgeToMachine.vtToolDirection
ToolSearchParameters.bAllowTopHead = true
ToolSearchParameters.bAllowBottomHead = true
ToolSearchParameters.dElevation = Mortising.dDepthToMachine
ToolSearchParameters.bExtendWithCornerRadius = bExtendWithCornerRadius
ToolInfo = MachiningLib.FindChainSaw( Proc, ToolSearchParameters)
Mortising.nToolIndex = ToolInfo.nToolIndex
Mortising.nType = MCH_OY.MORTISING
if not TOOLS[Mortising.nToolIndex] or not TOOLS[Mortising.nToolIndex].sName then
Mortising.sMessage = 'Chainsaw not found'
Mortising.bIsApplicable = false
EgtOutLog( Mortising.sMessage)
return Mortising
end
-- verifica dimensioni tasca compatibili
-- se tasca meno spessa della sega a catena la strategia non è applicabile
if TOOLS[Mortising.nToolIndex].dThickness > dPocketHeight + 10 * GEO.EPS_SMALL then
Mortising.sMessage = 'Pocket too narrow for chainsaw thickness'
Mortising.bIsApplicable = false
EgtOutLog( Mortising.sMessage)
return Mortising
end
if #( Proc.MainFaces.SideFaces) > 1 then
-- se tasca più stretta della sega a catena la strategia non è applicabile
if TOOLS[Mortising.nToolIndex].dWidth > EdgeToMachine.dLength + 10 * GEO.EPS_SMALL then
Mortising.sMessage = 'Pocket too narrow for chainsaw width'
Mortising.bIsApplicable = false
EgtOutLog( Mortising.sMessage)
return Mortising
end
end
-- parametri della lavorazione
-- TODO gestire ToolInvert per rispettare direzione migliore di lavorazione
-- profondità (parametro DEPTH) non usata
Mortising.sDepth = 'TH'
-- inizio e fine aperti o chiusi
Mortising.bIsStartClosed = not EdgeToMachine.bIsStartOpen
Mortising.bIsEndClosed = not EdgeToMachine.bIsEndOpen
-- lato di lavoro e inversioni
Mortising.bInvert = false
if EdgeToMachine.dElevation > -10 * GEO.EPS_SMALL then
Mortising.nWorkside = MCH_MILL_WS.RIGHT
Mortising.bToolInvert = false
else
Mortising.nWorkside = MCH_MILL_WS.LEFT
Mortising.bToolInvert = true
end
-- profondità e offset longitudinale
if bExtendWithCornerRadius then
Mortising.dDepthToMachine = Mortising.dDepthToMachine + TOOLS[Mortising.nToolIndex].dCornerRadius
end
if TOOLS[Mortising.nToolIndex].dMaxMaterial > Mortising.dDepthToMachine - 10 * GEO.EPS_SMALL then
Mortising.dResidualDepth = 0
if EdgeToMachine.dElevation > -10 * GEO.EPS_SMALL then
Mortising.dLongitudinalOffset = 0
else
Mortising.dLongitudinalOffset = abs( EdgeToMachine.dElevation) - Mortising.dDepthToMachine
end
else
Mortising.dDepthToMachine = TOOLS[Mortising.nToolIndex].dMaxMaterial - 1
Mortising.dResidualDepth = abs( EdgeToMachine.dElevation) - Mortising.dDepthToMachine
if EdgeToMachine.dElevation > -10 * GEO.EPS_SMALL then
Mortising.dLongitudinalOffset = EdgeToMachine.dElevation - Mortising.dDepthToMachine
else
Mortising.dLongitudinalOffset = 0
end
Mortising.sMessage = 'Feature '.. Proc.idFeature .. ' : chainsaw elevation (' .. EgtNumToString( EdgeToMachine.dElevation, 1) .. ') bigger than max tool depth (' .. EgtNumToString( Mortising.dDepthToMachine, 1) .. ')'
EgtOutLog( Mortising.sMessage)
end
-- completamento
Mortising.dCompletionPercentage = 100 - Mortising.dResidualDepth / Mortising.dDepthToMachine
-- massima elevazione
if dCustomMaxElev < Mortising.dDepthToMachine - 10 * GEO.EPS_SMALL then
Mortising.dMaxElev = dCustomMaxElev
end
-- offset radiale
Mortising.dRadialOffset = 0
-- distanza di sicurezza
Mortising.dStartSafetyLength = max( EdgeToMachine.dElevation, 10)
-- overlap
Mortising.dOverlap = 0
-- step
Mortising.Steps = {}
if bUseZigZagMortising then
Mortising.Steps.nStepType = MCH_MILL_ST.ZIGZAG
else
Mortising.Steps.nStepType = MCH_MILL_ST.ONEWAY
end
Mortising.Steps.dStep = TOOLS[Mortising.nToolIndex].dStep
-- faceuse
if EdgeToMachine.dElevation > - 10 * GEO.EPS_SMALL then
Mortising.nFaceuse = BeamLib.GetNearestParalOpposite( EdgeToMachine.vtToolDirection)
else
Mortising.nFaceuse = BeamLib.GetNearestParalOpposite( -EdgeToMachine.vtToolDirection)
end
-- SCC
Mortising.SCC = MCH_SCC.NONE
-- asse bloccato e angoli suggeriti
local vtRes = FaceToMachine.vtN ^ EdgeToMachine.vtToolDirection
if abs( vtRes:getZ()) < 10 * GEO.EPS_SMALL then
Mortising.sBlockedAxis = BeamLib.GetBlockedAxis( Mortising.nToolIndex, 'perpendicular', Part.b3Raw, FaceToMachine.vtN)
Mortising.sSuggestedAngles = BeamLib.GetChainSawInitAngs( FaceToMachine.vtN, EdgeToMachine.vtToolDirection, 1)
elseif EdgeToMachine.vtToolDirection:getZ() < 10 * GEO.EPS_SMALL then
Mortising.sBlockedAxis = BeamLib.GetBlockedAxis( Mortising.nToolIndex, 'parallel', Part.b3Raw, FaceToMachine.vtN)
Mortising.sSuggestedAngles = BeamLib.GetChainSawInitAngs( FaceToMachine.vtN, EdgeToMachine.vtToolDirection, 2)
end
-- approccio e retrazione
Mortising.LeadIn, Mortising.LeadOut = CalculateLeadInOut( Mortising, EdgeToMachine, sSideToMachine, dLengthToMachine)
-- eventuale step verticale
Mortising.VerticalSteps = MachiningLib.GetMachiningSteps( dPocketHeight, TOOLS[Mortising.nToolIndex].dThickness)
-- geometria
Mortising.Geometry = {{Proc.id, FaceToMachine.id}}
-- nome operazione
Mortising.sOperationName = 'Chainsaw_' .. ( EgtGetName( Mortising.idProc) or tostring( Mortising.idProc)) .. '_' .. tostring( FaceToMachine.id + 1)
-- eventuale avviso di danneggiamento pezzo successivo
-- TODO da sostituire con check se si riesce a separare e il grezzo dietro è lungo a sufficienza
-- local dOffsideLength = max( Mortising.LeadIn.dStartAddLength, Mortising.LeadOut.dEndAddLength) + TOOLS[Mortising.nToolIndex].dWidth / 2 + 10 * GEO.EPS_SMALL
-- if ( not Proc.bTail or Proc.bAdvTail) and Proc.AffectedFaces.bLeft and ( Proc.dDistanceToNextPart < dOffsideLength) then
-- local sDamageNextPieceMessage = 'Feature '.. Proc.idFeature .. ' : chainsaw can damage next piece.'
-- if #Mortising.sMessage > 0 then
-- Mortising.sMessage = Mortising.sMessage .. '\n' .. sDamageNextPieceMessage
-- else
-- Mortising.sMessage = sDamageNextPieceMessage
-- end
-- EgtOutLog( sDamageNextPieceMessage)
-- end
return Mortising
end
-------------------------------------------------------------------------------------------------------------
return SLOTBYCHAINSAW
+170
View File
@@ -0,0 +1,170 @@
[
{
"nGroup": "PIECE LOADING",
"sName": "GEN_sPiecesLoadingPosition",
"sNameNge": "GEN_PIECES_LOADING",
"sValue": "BTL_POSITION",
"sDescriptionShort": "Part loading position",
"sDescriptionLong": "",
"sType": "combo",
"sMinUserLevel": "1",
"Choices": [
{
"sValue": "BTL_POSITION",
"sDescriptionShort": "Loading position from BTL, no pre-rotation",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "STD_PRE_ROTATION",
"sDescriptionShort": "Get Best loading position from 0° and 180°",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"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",
"sNameNge": "GEN_PIECE_ROTATION",
"sValue": "IF_NECESSARY",
"sDescriptionShort": "Part rotating acceptability",
"sDescriptionLong": "Acceptability of rotating the part between machining steps",
"sType": "combo",
"sMinUserLevel": "1",
"Choices": [
{
"sValue": "NOT_ALLOWED",
"sDescriptionShort": "Rotation not allowed",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "IF_NECESSARY",
"sDescriptionShort": "Rotation allowed only if strictly necessary",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "NO_CONSTRAINT",
"sDescriptionShort": "Rotation easily acceptable / no constraint",
"sDescriptionLong": "",
"sMessageId": ""
}
]
},
{
"nGroup": "MACHINE",
"sName": "GEN_sMachiningStrategy",
"sNameNge": "GEN_MACHINING_STRATEGY",
"sValue": "AUTO",
"sDescriptionShort": "Machining Strategy",
"sDescriptionLong": "",
"sType": "combo",
"sMinUserLevel": "1",
"Choices": [
{
"sValue": "AUTO",
"sDescriptionShort": "Quality and time equally prioritized",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "FASTEST",
"sDescriptionShort": "Fastest",
"sDescriptionLong": "Prefer fastest strategies",
"sMessageId": ""
},
{
"sValue": "HIGH_QUALITY",
"sDescriptionShort": "High quality",
"sDescriptionLong": "Prefer high-quality strategies",
"sMessageId": ""
}
]
},
{
"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",
"sNameNge": "REDUCE_BLADE_PATH",
"sValue": "true",
"sDescriptionShort": "Use entire blade diameter to shorten path",
"sDescriptionLong": "",
"sType": "b",
"sMessageId": " ",
"sMinUserLevel": "5"
},
{
"nGroup": "MACHINING STRATEGY",
"sName": "GEN_dMaxWasteLength",
"sNameNge": "GEN_MAX_WASTE_LENGTH",
"sValue": "300",
"sDescriptionShort": "Maximum length for dropped waste",
"sDescriptionLong": "",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "5"
},
{
"nGroup": "MACHINING STRATEGY",
"sName": "GEN_dMaxWasteVolume",
"sNameNge": "GEN_MAX_WASTE_VOLUME",
"sValue": "6000000",
"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": " ",
"sMinUserLevel": "5"
}
]
+62
View File
@@ -0,0 +1,62 @@
{
"sStrategyId": "HEADCUT",
"sStrategyName": "HEADCUT",
"ParameterList" : [
{
"sName": "dDepthChamfer",
"sNameNge": "DEPTH_CHAMFER",
"sValue": "0",
"sDescriptionShort": "Depth Chamfer",
"sDescriptionLong": "Depth of the V-Mill to execute chamfers on cut-edges",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "bForceChainSaw",
"sNameNge": "FORCE_CHAIN",
"sValue": "false",
"sDescriptionShort": "Force to use chain saw",
"sDescriptionLong": "Force to use chain saw",
"sType": "b",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "bExecutePreCut",
"sNameNge": "EXEC_PRECUT",
"sValue": "false",
"sDescriptionShort": "Force to add PreCuts",
"sDescriptionLong": "Autocam will apply a machining on the theoretical zero, to avoid collision if the theoretical piece length doesn't correspond to the real length",
"sType": "b",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "bFinishWithMill",
"sNameNge": "MILL_FINISH",
"sValue": "true",
"sDescriptionShort": "Finish with mill",
"sDescriptionLong": "Use a mill to finish the surface if split with chain saw",
"sType": "b",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "dMaxWasteLength",
"sSource": "GEN_dMaxWasteLength",
"sMinUserLevel": "5"
},
{
"sName": "dMaxWasteVolume",
"sSource": "GEN_dMaxWasteVolume",
"sMinUserLevel": "5"
},
{
"sName": "bReduceBladePath",
"sSource": "GEN_bReduceBladePath",
"sMinUserLevel": "5"
}
]
}
+149
View File
@@ -0,0 +1,149 @@
-- Strategia: HEADCUT
-- Descrizione
-- HeadCut
-- Feature: HeadCut
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamDataNew')
local FeatureLib = require( 'FeatureLib')
local MachiningLib = require( 'MachiningLib')
local SPLITCUT = require( 'SPLITCUT')
-- strategie di base
local BladeToWaste = require('BLADETOWASTE')
-- Tabella per definizione modulo
local HEADCUT = {}
local Strategy = {}
-------------------------------------------------------------------------------------------------------------
local function MakeChamfer()
-- TODO funzionalità da aggiungere
end
-------------------------------------------------------------------------------------------------------------
function HEADCUT.Make( bAddMachining, Proc, Part, CustomParameters)
local StrategyLib = {}
StrategyLib.Config = STRATEGIES_CONFIG[CustomParameters.sStrategyId]
Strategy.sName = StrategyLib.Config.sStrategyId
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( Proc, Part, CustomParameters, StrategyLib.Config)
Strategy.SplitStrategy = {}
Strategy.Result = {}
Strategy.Machining = {}
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 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'
-- end
if Strategy.Result.sStatus ~= 'Completed' then
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( 'Precut Head not possible')
return false, Strategy.Result
end
end
Strategy.Result.sStatus = 'Completed'
Strategy.Result.dCompletionIndex = 5
Strategy.Result.dMRR = 1
-- 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
-- inserimento smussi su spigoli del taglio
if Strategy.Parameters.bMakeChamfer then
MakeChamfer()
end
local MachiningsToAdd = {}
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 = {}
TempList = Strategy.SplitStrategy[i]
if bExecutePrecutOnly then
TempList.dLongitudinalOffset = 0
else
TempList.bIsPreCut = true
TempList.dLongitudinalOffset = Part.dHeadOverMaterial
end
table.insert( MachiningsToAdd, TempList)
end
end
end
if not bExecutePrecutOnly then
-- 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())
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
-- aggiungo lavorazioni trovate alla lista generale
for i = 1, #MachiningsToAdd do
MachiningsToAdd[i].sStage = 'Head'
MachiningLib.AddMachinings( Proc, MachiningsToAdd[i], MachiningsToAdd[i].AuxiliaryData)
end
return bAreAllMachiningsAdded, Strategy.Result
else
return nil, Strategy.Result
end
end
-------------------------------------------------------------------------------------------------------------
return HEADCUT
+118
View File
@@ -0,0 +1,118 @@
{
"sStrategyId": "STR0001",
"sStrategyName": "DoveTail Tenon",
"ParameterList" : [
{
"sName": "dOverMatOnLength",
"sNameNge": "OVM_LENGTH",
"sValue": "0",
"sDescriptionShort": "Overmaterial on tenon length",
"sDescriptionLong": "",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "dOverMatOnRadius",
"sNameNge": "OVM_RADIUS",
"sValue": "0",
"sDescriptionShort": "Overmaterial on tenon width",
"sDescriptionLong": "",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "nMaxMillingPaths",
"sNameNge": "MAX_PATHS",
"sValue": "3",
"sDescriptionShort": "Maximum number of milling passes",
"sDescriptionLong": "Maximum number of milling passes. If more passes are required, pocketing is performed",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "bUseDTToolOnPocketing",
"sNameNge": "ALLOW_DT_POCKET",
"sValue": "true",
"sDescriptionShort": "Use DoveTail tool to pocket",
"sDescriptionLong": "",
"sType": "b",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "sCuttingStrategy",
"sNameNge": "EXEC_TENON_SURF",
"sValue": "AUTO",
"sDescriptionShort": "Cutting Strategy",
"sDescriptionLong": "",
"sType": "combo",
"sMinUserLevel": "1",
"Choices": [
{
"sValue": "AUTO",
"sDescriptionShort": "Automatic",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "BLADE_FORCED",
"sDescriptionShort": "Blade only",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "MILL_FORCED",
"sDescriptionShort": "Mill only",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "CHAINSAW_FORCED",
"sDescriptionShort": "ChainSaw only",
"sDescriptionLong": "",
"sMessageId": ""
}
]
},
{
"sName": "sPocketingList",
"sNameNge": "POCK_DTTENON_SURF_LIST",
"sValue": "",
"sDescriptionShort": "Available mill to machine the tenon cut surface",
"sDescriptionLong": "",
"sType": "tool",
"sSubType": "MCH_TF.MILL",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "sMillingList",
"sNameNge": "DOVETAIL_TOOL_LIST",
"sValue": "",
"sDescriptionShort": "Available mill to machine the dovetail tenon",
"sDescriptionLong": "",
"sType": "tool",
"sSubType": "MCH_TF.MILL",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "dMaxWasteLength",
"sSource": "GEN_dMaxWasteLength",
"sMinUserLevel": "5"
},
{
"sName": "dMaxWasteVolume",
"sSource": "GEN_dMaxWasteVolume",
"sMinUserLevel": "5"
},
{
"sName": "bReduceBladePath",
"sSource": "GEN_bReduceBladePath",
"sMinUserLevel": "5"
}
]
}
+436 -6
View File
@@ -5,18 +5,448 @@
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
local PreSimulationLib = require( 'PreSimulationLib')
-- strategie di base
local BladeToWaste = require('BLADETOWASTE')
-- Tabella per definizione modulo
local STR0001 = {}
local Strategy = {}
-------------------------------------------------------------------------------------------------------------
function STR0001.Make( AddMachining, Proc, Part, CustomParameters)
-- carico parametri de default e li aggiorno con quelli passati dal chiamante (potrebbero non essere congruenti)
local StrategyLib = {}
StrategyLib.Config = require( 'STR0001\\STR0001Config')
CustomParameters = BeamLib.GetUpdateCustomParameters( CustomParameters, StrategyLib.Config.Parameters)
StrategyParameters = BeamLib.LoadCustomParametersInStrategy( CustomParameters)
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
-------------------------------------------------------------------------------------------------------------
local function GetTenonStrategy( Proc, Part)
local Machining = {}
Machining.Milling = MachiningLib.InitMachiningParameters( MCH_MY.MILLING)
Machining.Cutting = MachiningLib.InitMachiningParameters( MCH_MY.MILLING)
Machining.Pocketing = MachiningLib.InitMachiningParameters( MCH_MY.POCKETING)
local Result = {}
Result.Milling = {}
Result.Cutting = {}
Result.Pocketing = {}
local ToolSearchParameters = {}
-- scelta automatica lavorazione. Non viene mai scelta la motosega
if Strategy.Parameters.sCuttingStrategy == 'AUTO' then
-- creo piano di taglio sulla testa del tenone
local OptionalParameters = { dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume,
dMaxWasteLength = Strategy.Parameters.dMaxWasteLength,
bReduceBladePath = Strategy.Parameters.bReduceBladePath
}
Machining.Cutting, Result.Cutting = BladeToWaste.Make( Strategy.idTenonCutPlane, Part, OptionalParameters)
-- se presente almeno una lavorazione e completo, il taglio è applicabile
if #Machining.Cutting > 0 and Result.Cutting and Result.Cutting.sStatus == 'Completed' then
Machining.Cutting.bIsApplicable = true
end
-- se non possibile di lama si prova con fresa
if not Machining.Cutting or Result.Cutting.sStatus ~= 'Completed' then
Machining.bCuttingWithMill = true
end
-- lavorazione forzata con utensile lama
elseif Strategy.Parameters.sCuttingStrategy == 'BLADE_FORCED' then
local OptionalParameters = { dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume,
dMaxWasteLength = Strategy.Parameters.dMaxWasteLength,
bReduceBladePath = Strategy.Parameters.bReduceBladePath
}
Machining.Cutting, Result.Cutting = BladeToWaste.Make( Strategy.idTenonCutPlane, Part, OptionalParameters)
-- se presente almeno una lavorazione e completo, il taglio è applicabile
if #Machining.Cutting > 0 and Result.Cutting.sStatus == 'Completed' then
Machining.Cutting.bIsApplicable = true
else
Machining.Cutting.bIsApplicable = false
end
-- lavorazione forzata con utensile fresa
elseif Strategy.Parameters.sCuttingStrategy == 'MILL_FORCED' then
Machining.bCuttingWithMill = true
-- lavorazione forzata con utensile motosega
elseif Strategy.Parameters.sCuttingStrategy == 'CHAINSAW_FORCED' then
-- DA FARE!!
end
-- === ricerca utensile per svuotare taglio iniziale, se taglio non possibile ===
if Machining.bCuttingWithMill and ( not( Proc.AffectedFaces.bLeft) or Strategy.bCanMoveAfterSplit) then
ToolSearchParameters = {}
-- TODO SISTEMARE!!! qui la svuotatura non deve limitare l'elevazione se aperta da tutti i lati. In futuro si deve passare 0 come elevazione
ToolSearchParameters.dElevation = EgtSurfTmFacetElevationInBBox( Strategy.idTenonCutPlane, 0, Part.b3Part, true, GDB_ID.ROOT)
ToolSearchParameters.vtToolDirection = Proc.FeatureInfo.vtTenonN
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sPocketingList, 'Pocketing')
Machining.Cutting.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
-- TODO anche il test sul ResidualDepth va tolto
if Machining.Cutting.ToolInfo.nToolIndex and ( Machining.Cutting.ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL) then
Machining.Cutting.bIsApplicable = true
local ParametersMRR = {}
ParametersMRR.nToolIndex = Machining.Cutting.ToolInfo.nToolIndex
Result.Cutting.dMRR = MachiningLib.GetToolMRR( ParametersMRR)
Machining.Cutting.sStatus = 'Completed'
Machining.Cutting.Steps = {}
Machining.Cutting.LeadIn = {}
Machining.Cutting.nType = MCH_MY.POCKETING
Machining.Cutting.nSubType = MCH_POCK_SUB.SPIRALIN
Machining.Cutting.LeadIn.nType = MCH_POCK_LI.ZIGZAG
Machining.Cutting.Steps.dStep = TOOLS[Machining.Cutting.ToolInfo.nToolIndex].dStep
Machining.Cutting.Steps.dSideStep = TOOLS[Machining.Cutting.ToolInfo.nToolIndex].dSideStep
Machining.Cutting.nToolIndex = Machining.Cutting.ToolInfo.nToolIndex
Machining.Cutting.LeadIn.dTangentDistance = TOOLS[Machining.Cutting.ToolInfo.nToolIndex].dDiameter/2
Machining.Cutting.LeadIn.dElevation = TOOLS[Machining.Cutting.ToolInfo.nToolIndex].dDiameter/2
Machining.Cutting.sDepth = 0
Machining.Cutting.Geometry = {{ Strategy.idTenonCutPlane, 0}}
Machining.Cutting.vtToolDirection = Proc.FeatureInfo.vtTenonN
if Proc.AffectedFaces.bLeft and Strategy.bCanMoveAfterSplit then
Machining.Cutting.sStage = 'AfterTail'
end
-- tempo di svuotatura
Result.Cutting.dTimeToMachine = MachiningLib.GetTimeToMachineAllStepsWithLeadInOut( Machining.Cutting, Part)
end
end
-- === ricerca utensile per lavorare tenone coda di rondine ===
Machining.Milling.bIsApplicable = false
-- se tenone in testa oppure se di coda ma è possibile lavorare dopo separazione
if not( Proc.AffectedFaces.bLeft) or Strategy.bCanMoveAfterSplit then
ToolSearchParameters.dElevation = Proc.FeatureInfo.dTenonLength
ToolSearchParameters.vtToolDirection = Proc.FeatureInfo.vtTenonN
ToolSearchParameters.sMillShape = 'DOVETAIL'
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sMillingList, 'Milling')
Machining.Milling.ToolInfo = {}
Machining.Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
if Machining.Milling.ToolInfo.nToolIndex then
Machining.Milling.bIsApplicable = true
local ParametersMRR = {}
ParametersMRR.nToolIndex = Machining.Milling.ToolInfo.nToolIndex
Result.Milling.dMRR = MachiningLib.GetToolMRR( ParametersMRR)
-- l'utensile a coda di rondine deve per forza riuscire a lavorare tutto, altrimenti errore
if Machining.Milling.ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then
Result.Milling.sStatus = 'Completed'
-- aggiungo geometria e imposto tutti i dati
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.vtTenonN
Machining.Milling.sDepth = min( -Machining.Milling.ToolInfo.dResidualDepth, 0)
-- LeadIn / LeadOut
Machining.Milling.LeadIn = {}
Machining.Milling.LeadOut = {}
Machining.Milling.LeadIn.nType = MCH_MILL_LI.TANGENT
Machining.Milling.LeadOut.nType = MCH_MILL_LI.TANGENT
Machining.Milling.LeadIn.dTangentDistance = TOOLS[Machining.Milling.ToolInfo.nToolIndex].dDiameter / 2 + BeamData.COLL_SIC
Machining.Milling.LeadIn.dPerpDistance = TOOLS[Machining.Milling.ToolInfo.nToolIndex].dSideStep
Machining.Milling.LeadOut.dTangentDistance = TOOLS[Machining.Milling.ToolInfo.nToolIndex].dDiameter / 2 + BeamData.COLL_SIC
Machining.Milling.LeadOut.dPerpDistance = TOOLS[Machining.Milling.ToolInfo.nToolIndex].dSideStep
Machining.Milling.dLengthToMachine = Proc.FeatureInfo.dTenonPathLength
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.RIGHT, MCH_MILL_WS.LEFT)
Machining.Milling.sUserNotes = EgtSetVal( 'MaxElev', EgtNumToString( Proc.FeatureInfo.dTenonLength, 1)) .. ';'
Machining.Milling.nSCC = GetSCC( Machining.Milling)
-- passate con sovramateriale
Machining.nMillingPathsNeeded = ceil( Proc.FeatureInfo.dTenonMaxDist / TOOLS[Machining.Milling.ToolInfo.nToolIndex].dSideStep)
Machining.Milling.AuxiliaryData = {}
Machining.Milling.AuxiliaryData.Clones = {}
for i = Machining.nMillingPathsNeeded, 1, -1 do
-- il primo è il passaggio più esterno
local nIndexClones = Machining.nMillingPathsNeeded - i + 1
-- suddivido step in base al numero passate da fare
local dRealSideStep = floor( Proc.FeatureInfo.dTenonMaxDist / Machining.nMillingPathsNeeded)
-- 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
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
Machining.Milling.bIsApplicable = false
end
end
end
-- === ricerca utensile di svuotatura (se richiesto e se è andata a buon fine la coda di rondine) ===
if Machining.Milling.bIsApplicable then
if Machining.nMillingPathsNeeded <= Strategy.Parameters.nMaxMillingPaths then
Machining.Pocketing.bNotNeeded = true
Machining.Pocketing.dMRR = Machining.Milling.dMRR
-- serve svuotatura
else
-- se ammessa svuotatura con utensile DoveTail, copio i dati
if Strategy.Parameters.bUseDTToolOnPocketing then
Machining.Pocketing.bIsApplicable = true
Machining.Pocketing.ToolInfo = Machining.Milling.ToolInfo
Machining.Pocketing.dMRR = Machining.Milling.dMRR
-- altrimenti serve cercarne un altro
else
ToolSearchParameters = {}
ToolSearchParameters.dElevation = Proc.FeatureInfo.dTenonLength
ToolSearchParameters.vtToolDirection = Proc.vtTenonN
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sMillingList, 'Milling')
Machining.Pocketing.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
if Machining.Pocketing.ToolInfo.nToolIndex then
Machining.Pocketing.bIsApplicable = true
local ParametersMRR = {}
ParametersMRR.nToolIndex = Machining.Pocketing.ToolInfo.nToolIndex
Result.Pocketing.dMRR = MachiningLib.GetToolMRR( ParametersMRR)
if Machining.Pocketing.ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then
Result.Pocketing.sStatus = 'Completed'
Result.Pocketing.dCompletionPercentage = 100
else
Result.Pocketing.sStatus = 'Not-Completed'
Result.Pocketing.sInfo = 'Tenon not complete, left ' .. ceil( Machining.Pocketing.ToolInfo.dResidualDepth) .. 'mm'
Result.Pocketing.dCompletionPercentage = ( 1 - Machining.Pocketing.ToolInfo.dResidualDepth / Proc.dDTLength) * 100
end
end
end
end
end
return Machining, Result
end
-------------------------------------------------------------------------------------------------------------
local function GetFeatureRotationIndex( Proc)
local nVoteIndex
-- se fatto con testa sopra
if TOOLS[Strategy.Machining.Milling.ToolInfo.nToolIndex].SetupInfo.HeadType.bTop then
if Proc.FeatureInfo.vtTenonN:getZ() < 0 then
nVoteIndex = 2
elseif Proc.FeatureInfo.vtTenonN:getZ() > abs( Proc.FeatureInfo.vtTenonN:getY()) then
nVoteIndex = 4
else
nVoteIndex = 3
end
-- se fatto con testa sotto
elseif TOOLS[Strategy.Machining.Milling.ToolInfo.nToolIndex].SetupInfo.HeadType.bBottom then
if Proc.FeatureInfo.vtTenonN:getZ() > 0 then
nVoteIndex = 2
elseif Proc.FeatureInfo.vtTenonN:getZ() < - abs( Proc.FeatureInfo.vtTenonN:getY()) then
nVoteIndex = 4
else
nVoteIndex = 3
end
end
return nVoteIndex
end
-------------------------------------------------------------------------------------------------------------
-- TODO vedere se leggere direttamente la quality dell'utensile e mediarle nel caso di utensile doppio
local function GetTenonMachiningResult( Proc, Result)
local TotalResult = {}
-- setto il risultato in base agli utensili trovati
-- lavorazione completa
if Strategy.Machining.Milling.bIsApplicable and Strategy.Machining.Cutting.bIsApplicable then
TotalResult.sStatus = Result.Milling.sStatus
TotalResult.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
TotalResult.dMRR = ( Result.Milling.dMRR + Result.Cutting.dMRR) / 2
if Strategy.Machining.nMillingPathsNeeded > Strategy.Parameters.nMaxMillingPaths then
TotalResult.dQuality = FeatureLib.GetStrategyQuality( 'STD')
else
TotalResult.dQuality = FeatureLib.GetStrategyQuality( 'FINE')
end
TotalResult.nFeatureRotationIndex = GetFeatureRotationIndex( Proc)
TotalResult.dTimeToMachine = Result.Milling.dTimeToMachine + Result.Cutting.dTimeToMachine
TotalResult.sInfo = ''
-- lavorazione incompleta
elseif Strategy.Machining.Cutting.bIsApplicable then
TotalResult.sStatus = 'Not-Completed'
TotalResult.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 50)
TotalResult.dMRR = Result.Cutting.dMRR
TotalResult.dQuality = FeatureLib.GetStrategyQuality( 'FINE')
TotalResult.sInfo = 'Tenon not completed'
TotalResult.dTimeToMachine = Result.Cutting.dTimeToMachine
-- strategia non applicabile, manca il taglio di lama sulla lunghezza del tenone
else
TotalResult = FeatureLib.GetStrategyResultNotApplicable( 'Error on Tenon cutting')
end
return TotalResult
end
-------------------------------------------------------------------------------------------------------------
function STR0001.Make( bAddMachining, Proc, Part, CustomParameters)
-- carico parametri de default e li aggiorno con quelli passati dal chiamante (potrebbero non essere congruenti)
local StrategyLib = {}
StrategyLib.Config = STRATEGIES_CONFIG[CustomParameters.sStrategyId]
Strategy.sName = StrategyLib.Config.sStrategyId
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( Proc, Part, CustomParameters, StrategyLib.Config)
Strategy.Machining = {}
Strategy.Result = {}
Strategy.Result.dTimeToMachine = 0
local bAreAllMachiningsAdded = true
local Results = {}
-- controllo conformità offset tenone
Strategy.Parameters.dOverMatOnRadius = EgtClamp( Strategy.Parameters.dOverMatOnRadius, -5, 5)
Strategy.Parameters.dOverMatOnLength = EgtClamp( Strategy.Parameters.dOverMatOnRadius, -5, 5)
-- calcolo se la lavorazione del tenone può essere spostata dopo taglio di coda
local dLengthOnX = Proc.b3Box:getDimX()
Strategy.bCanMoveAfterSplit = MachiningLib.CanMoveAfterSplitcut( dLengthOnX, Part)
-- aggiunta superficie di taglio sulla lunghezza del tenone
local nAddGrpId = BeamLib.GetAddGroup( Part.id)
local ptCenterAddSurf = Proc.FeatureInfo.ptTenonCenter + ( Proc.FeatureInfo.vtTenonN * Strategy.Parameters.dOverMatOnLength)
Strategy.idTenonCutPlane = EgtSurfTmPlaneInBBox( nAddGrpId, ptCenterAddSurf, Proc.FeatureInfo.vtTenonN, Part.b3Part, GDB_RT.GLOB)
Strategy.Machining, Results = GetTenonStrategy( Proc, Part)
Strategy.Result = GetTenonMachiningResult( Proc, Results)
-- applicazione delle lavorazioni
if bAddMachining and Strategy.Result.sStatus ~= 'Not-Applicable' then
-- taglio in lunghezza sul tenone
if Strategy.Machining.Cutting.bIsApplicable then
-- se cutting da fare come svuotatura
if Strategy.Machining.bCuttingWithMill then
bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, Strategy.Machining.Cutting)
-- taglio di lama
else
for i = 1, #Strategy.Machining.Cutting do
if Strategy.Machining.Cutting.bIsApplicable then
if Proc.AffectedFaces.bLeft and Strategy.bCanMoveAfterSplit then
Strategy.Machining.Cutting[i].sStage = 'AfterTail'
end
local bIsMachiningAdded = MachiningLib.AddMachinings( Proc, Strategy.Machining.Cutting[i])
if not bIsMachiningAdded then
bAreAllMachiningsAdded = false
end
end
end
end
end
-- passaggio sul profilo
if Strategy.Machining.Milling.bIsApplicable then
-- 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
-- aggiunge lavorazione
bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, Strategy.Machining.Milling, Strategy.Machining.Milling.AuxiliaryData)
end
-- si controllano le ultime 5 facce della feature
local nIndFace = -1
for i = 1, 5 do
if abs( Proc.FeatureInfo.vtTenonN * EgtSurfTmFacetNormVersor( Proc.id, Proc.nFct-i, GDB_ID.ROOT)) < GEO.EPS_ANG_SMALL then
nIndFace = Proc.nFct-i
end
end
-- controllo se serve passaggio di finitura in caso il tenone non cominci dal bordo della trave (P14 > 0)
if nIndFace > 0 then
-- verifico che entrambi i punti iniziale e finale della curva no giacciano in uno dei piani limite del pezzo, quindi se è un lato aperto
local ptIni = EgtSP( Proc.FeatureInfo.idAddAuxGeom, GDB_RT.GLOB)
local ptFin = EgtEP( Proc.FeatureInfo.idAddAuxGeom, GDB_RT.GLOB)
-- se entrambi i punti non sono sul limite pezzo
if not( BeamLib.IsPointOnBoxLimit( ptIni, Part.b3Part) or BeamLib.IsPointOnBoxLimit( ptFin, Part.b3Part)) then
-- cerco utensile
local ToolSearchParameters = {}
local FinishMach = {}
ToolSearchParameters.dElevation = Proc.FeatureInfo.dTenonLength
ToolSearchParameters.vtToolDirection = Proc.FeatureInfo.vtTenonN
ToolSearchParameters.sMillShape = 'STANDARD'
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sMillingList, 'MillingFinish')
FinishMach.ToolInfo = {}
FinishMach.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
if FinishMach.ToolInfo.nToolIndex then
-- aggiungo geometria e imposto tutti i dati
FinishMach.Geometry = {{ Proc.id, Proc.nFct-1}}
FinishMach.nToolIndex = FinishMach.ToolInfo.nToolIndex
FinishMach.nType = MCH_MY.MILLING
FinishMach.vtToolDirection = Proc.FeatureInfo.vtTenonN
FinishMach.sDepth = 'TH'
-- LeadIn / LeadOut
FinishMach.LeadIn = {}
FinishMach.LeadOut = {}
FinishMach.LeadIn.nType = MCH_MILL_LI.TANGENT
FinishMach.LeadOut.nType = MCH_MILL_LI.TANGENT
FinishMach.LeadIn.dTangentDistance = TOOLS[FinishMach.ToolInfo.nToolIndex].dDiameter / 2 + BeamData.COLL_SIC
FinishMach.LeadIn.dPerpDistance = TOOLS[FinishMach.ToolInfo.nToolIndex].dSideStep
FinishMach.LeadOut.dTangentDistance = TOOLS[FinishMach.ToolInfo.nToolIndex].dDiameter / 2 + BeamData.COLL_SIC
FinishMach.LeadOut.dPerpDistance = TOOLS[FinishMach.ToolInfo.nToolIndex].dSideStep
if Proc.AffectedFaces.bLeft and Strategy.bCanMoveAfterSplit then
FinishMach.sStage = 'AfterTail'
end
-- sistemo il lato e la direzione di lavoro
FinishMach.bInvert = EgtIf( TOOLS[FinishMach.ToolInfo.nToolIndex].bIsCCW, false, true)
FinishMach.nWorkside = EgtIf( TOOLS[FinishMach.ToolInfo.nToolIndex].bIsCCW, MCH_MILL_WS.RIGHT, MCH_MILL_WS.LEFT)
FinishMach.sUserNotes = EgtSetVal( 'MaxElev', EgtNumToString( Proc.FeatureInfo.dTenonLength, 1)) .. ';'
FinishMach.nSCC = GetSCC( FinishMach)
-- imposto utilizzo faccia (--TODO verificare se serve riconoscere il lato specifico)
local nFaceUse
if Proc.FeatureInfo.vtTenonN:getX() > -GEO.EPS_SMALL then
nFaceUse = MCH_MILL_FU.PARAL_LEFT
else
nFaceUse = MCH_MILL_FU.PARAL_RIGHT
end
FinishMach.nFaceuse = nFaceUse
-- aggiunge lavorazione
bAreAllMachiningsAdded = bAreAllMachiningsAdded and MachiningLib.AddMachinings( Proc, FinishMach)
end
end
end
end
end
return bAreAllMachiningsAdded, Strategy.Result
end
-------------------------------------------------------------------------------------------------------------
@@ -1,13 +0,0 @@
-- Parametri configurabili da cliente per strategia: STR0001
local STR0001Data = {
sStrategyId = 'STR0001',
Parameters = {
{ sName = 'dOverMatOnLenght', sValue = '0', sDescription = 'Sovramateriale lunghezza tenone', sType = 'd'},
{ sName = 'dOverMatOnRadius', sValue = '0', sDescription = 'Sovramateriale larghezza tenone', sType = 'd'},
{ sName = 'nMaxMillingPaths', sValue = '3', sDescription = 'Numero massimo di passaggi di fresatura. Se richiesti più passaggi, si fa svuotatura', sType = 'd'},
{ sName = 'bUseDTToolOnPocketing', sValue = 'true', sDescription = 'Utilizza utensile a coda di rondimne per fare svuotatura', sType = 'b'}
}
}
return STR0001Data
+57
View File
@@ -0,0 +1,57 @@
{
"sStrategyId": "STR0002",
"sStrategyName": "Pocketing",
"ParameterList" : [
{
"sName": "dMaxCornerRadius",
"sNameNge": "MAX_CORNER_RADIUS",
"sValue": "15",
"sDescriptionShort": "Max radius left on corners",
"sDescriptionLong": "Radius-limit left by the tool at each corner of the feature",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "bAntiSplint",
"sNameNge": "ANTISPLINT",
"sValue": "false",
"sDescriptionShort": "Use Anti-Splint strategy",
"sDescriptionLong": "The strategy will apply blade cuts on corner to avoid wood splint",
"sType": "b",
"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": "10",
"sDescriptionShort": "Minimum approach distance on open sides",
"sDescriptionLong": "Minimum approach distance on open sides",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "sPocketingList",
"sNameNge": "POCK_LAPJOINT",
"sValue": "",
"sDescriptionShort": "Available mill to pocket the feature",
"sDescriptionLong": "",
"sType": "tool",
"sSubType": "MCH_TF.MILL",
"sMessageId": " ",
"sMinUserLevel": "1"
}
]
}
+369 -215
View File
@@ -1,25 +1,25 @@
-- Strategia: STR0002
-- Descrizione
-- Svuotatura tasca
-- Feature tipo LapJpint
-- Feature tipo LapJoint
-------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------
-- TODO
-- 1 - Controllare lavorazioni in caso di feature lunga spezzata
-- 2 - Inserire antischeggia (fresa o lama)
-- 3 - Modalità svuotatura con fresa grande e spigoli con fresa piccola
-- 4 - Smusso a V
-- 5 - Finitura con motosega (se la fresa non completa)
-- 1 - Inserire antischeggia (fresa o lama)
-- 2 - Modalità svuotatura con fresa grande e spigoli con fresa piccola
-- 3 - Smusso a V
-- 4 - Finitura con motosega (se la fresa non completa)
-------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FeatureData = require( 'FeatureData')
local FeatureLib = require( 'FeatureLib')
local AntiSplintOnFace = require( 'ANTISPLINTONFACE')
-- Tabella per definizione modulo
local STR0002 = {}
@@ -28,11 +28,18 @@ local Strategy = {}
-------------------------------------------------------------------------------------------------------------
local function IsTopologyOk( Proc)
if Proc.Topology.sName == 'Pocket-5-Blind' or
Proc.Topology.sName == 'RafterNotch-5-Through' or
Proc.Topology.sName == 'Tunnel-4-Through' or
Proc.Topology.sName == 'Groove-4-Blind' or
Proc.Topology.sName == 'Groove-3-Through' or
Proc.Topology.sName == 'Groove-3-Blind' or
Proc.Topology.sName == 'Rabbet-2-Through' then
Proc.Topology.sName == 'Bevel-3-Blind' or
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' or
Proc.Topology.sName == 'Cut-1-Through' or
Proc.Topology.sName == 'Bevel-1-Through' then
return true
else
@@ -40,6 +47,19 @@ local function IsTopologyOk( Proc)
end
end
-------------------------------------------------------------------------------------------------------------
local function GetSCC( Proc, Pocketing)
local nSCC
if Pocketing.vtToolDirection:getY() > 0 then
nSCC = MCH_SCC.ADIR_YP
else
nSCC = MCH_SCC.ADIR_YM
end
return nSCC
end
-------------------------------------------------------------------------------------------------------------
local function CalcMachinedPercentage( Proc, Machining)
-- se non ci sono lavorazioni esco subito
@@ -81,40 +101,66 @@ local function CalcMachinedPercentage( Proc, Machining)
end
-------------------------------------------------------------------------------------------------------------
local function GetBestPocketingStrategy( Proc)
-- imposto paraemtri di ricerca utensile in base a topologia
-- TODO va gestita meglio la decisione delle facce da lavorare
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
Strategy.Result.nQuality = FeatureData.GetFeatureQuality( 'Mill')
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
if Proc.Topology.sName == 'Tunnel-4-Through' then
local dFaceHeight = Proc.MainFaces.SideFaces[1].MainEdges.OppositeEdges[1].dLength
local dFaceWidth = Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1].dLength
local dFaceLength = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dLMinRectangle
local dFaceWidth = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dWMinRectangle
ToolSearchParameters.sType = 'MILL_STD'
ToolSearchParameters.dMaxToolDiameter = min( Strategy.Parameters.dMaxCornerRadius * 2, dFaceHeight, dFaceWidth)
ToolSearchParameters.dMaxToolDiameter = min( Strategy.Parameters.dMaxCornerRadius * 2, dFaceLength, dFaceWidth)
elseif Proc.Topology.sName == 'RafterNotch-5-Through' then
ToolSearchParameters.sType = 'MILL_STD'
ToolSearchParameters.dMaxToolDiameter = min( Strategy.Parameters.dMaxCornerRadius * 2, Proc.FeatureInfo.dFaceLength / 2)
-- imposto dati per cercare la fresa migliore
elseif Proc.Topology.sName == 'Pocket-5-Blind' then
local dFaceWidth = Proc.MainFaces.BottomFaces[1].MainEdges.LongEdges[1].dLength
local dFaceHeight = Proc.MainFaces.BottomFaces[1].MainEdges.SideEdges[1].dLength
local dFaceWidth, dFaceLength
if Proc.MainFaces.BottomFaces[1].MainEdges then
dFaceWidth = Proc.MainFaces.BottomFaces[1].MainEdges.LongEdges[1].dLength
dFaceLength = Proc.MainFaces.BottomFaces[1].MainEdges.SideEdges[1].dLength
else
dFaceWidth = Proc.MainFaces.BottomFaces[1].dWMinRectangle
dFaceLength = Proc.MainFaces.BottomFaces[1].dLMinRectangle
end
ToolSearchParameters.sType = 'MILL_STD'
ToolSearchParameters.dMaxToolDiameter = min( Strategy.Parameters.dMaxCornerRadius * 2, dFaceHeight, dFaceWidth)
ToolSearchParameters.dMaxToolDiameter = min( Strategy.Parameters.dMaxCornerRadius * 2, dFaceLength, dFaceWidth)
-- cerco fresa che può anche non lavorare di testa
elseif Proc.Topology.sName == 'Groove-4-Blind' then
local dFaceWidth = Proc.MainFaces.BottomFaces[2].MainEdges.BottomEdge.dLength
local dFaceLength
if Proc.MainFaces.BottomFaces[2].MainEdges then
dFaceLength = Proc.MainFaces.BottomFaces[2].MainEdges.BottomEdge.dLength
else
dFaceLength = Proc.MainFaces.BottomFaces[2].dLMinRectangle
end
ToolSearchParameters.sType = 'MILL_NOTIP'
ToolSearchParameters.dMaxToolDiameter = min( Strategy.Parameters.dMaxCornerRadius * 2, dFaceWidth)
elseif Proc.Topology.sName == 'Groove-3-Through' then
local dFaceWidth = Proc.MainFaces.BottomFaces[1].MainEdges.SideEdges[1].dLength
ToolSearchParameters.dMaxToolDiameter = min( Strategy.Parameters.dMaxCornerRadius * 2, dFaceLength)
elseif Proc.Topology.sName == 'Groove-3-Through' or Proc.Topology.sName == 'Bevel-3-Blind' then
local dFaceLength
if Proc.MainFaces.BottomFaces[1].MainEdges then
dFaceLength = Proc.MainFaces.BottomFaces[1].MainEdges.SideEdges[1].dLength
else
dFaceLength = Proc.MainFaces.BottomFaces[1].dLMinRectangle
end
ToolSearchParameters.sType = 'MILL_NOTIP'
ToolSearchParameters.dMaxToolDiameter = dFaceWidth
ToolSearchParameters.dMaxToolDiameter = dFaceLength
elseif Proc.Topology.sName == 'Groove-3-Blind' then
ToolSearchParameters.sType = 'MILL_NOTIP'
ToolSearchParameters.dMaxToolDiameter = Strategy.Parameters.dMaxCornerRadius * 2
elseif Proc.Topology.sName == 'Rabbet-2-Through' then
elseif 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'
or Proc.Topology.sName == 'Cut-1-Through'
or Proc.Topology.sName == 'Bevel-1-Through' then
ToolSearchParameters.sType = 'MILL_NOTIP'
ToolSearchParameters.dMaxToolDiameter = 9999
else
@@ -125,15 +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
@@ -145,13 +209,16 @@ local function GetBestPocketingStrategy( Proc)
-- caso speciale 'Rabbet-2-Through' seconda faccia principale
Milling = {}
Milling.bIsApplicable = false
if Proc.Topology.sName == 'Rabbet-2-Through' 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
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.LongFaces[1].dElevation
Milling.dElevation = Proc.MainFaces.BottomFaces[2].dElevation
Milling.ToolInfo = {}
Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
if Milling.ToolInfo.nToolIndex then
@@ -166,7 +233,9 @@ local function GetBestPocketingStrategy( Proc)
-- cerco utensile per lavorare di fianco 1
Milling = {}
Milling.bIsApplicable = false
if Proc.Topology.sName ~= 'Pocket-5-Blind' then
if Proc.Topology.sName ~= 'DoubleBevel-2-Through'
and Proc.Topology.sName ~= 'Pocket-5-Blind' and Proc.Topology.sName ~= 'RafterNotch-5-Through' then
if Proc.Topology.sName == 'Groove-4-Blind' then
ToolSearchParameters.dElevation = Proc.MainFaces.BottomFaces[2].dElevation
ToolSearchParameters.vtToolDirection = Proc.MainFaces.BottomFaces[2].vtN
@@ -174,14 +243,23 @@ local function GetBestPocketingStrategy( Proc)
Milling.idFaceToMachine = Proc.MainFaces.BottomFaces[2].id
Milling.idProc = Proc.id
Milling.dElevation = Proc.MainFaces.BottomFaces[2].dElevation
elseif Proc.Topology.sName == 'Groove-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
else -- 'Tunnel-4-Through', 'Groove-3-Through', 'Rabbet-2-Through'
elseif Proc.Topology.sName == 'Groove-3-Blind' or Proc.Topology.sName == 'Bevel-3-Blind' then
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)
ToolSearchParameters.dElevation = ( Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation * 2) + BeamData.MILL_OVERLAP
@@ -191,7 +269,10 @@ 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 = {}
Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
if Milling.ToolInfo.nToolIndex then
@@ -199,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)
@@ -206,8 +300,13 @@ local function GetBestPocketingStrategy( Proc)
-- cerco utensile per lavorare di fianco 2
Milling = {}
Milling.bIsApplicable = false
if Proc.Topology.sName ~= 'Pocket-5-Blind' and Proc.Topology.sName ~= 'Groove-4-Blind' then
if Proc.MainFaces.TunnelAddedFaces then -- Tunnel-4-Through, Groove-3-Through, Rabbet-2-Through
if Proc.Topology.sName ~= 'DoubleBevel-2-Through'
and Proc.Topology.sName ~= 'Pocket-5-Blind'
and Proc.Topology.sName ~= 'RafterNotch-5-Through'
and Proc.Topology.sName ~= 'Groove-4-Blind'
and Proc.Topology.sName ~= 'Bevel-3-Blind' then
if 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)
ToolSearchParameters.dElevation = ( Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation * 2) + BeamData.MILL_OVERLAP
@@ -218,14 +317,17 @@ local function GetBestPocketingStrategy( Proc)
Milling.dElevation = ( Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation * 2) + BeamData.MILL_OVERLAP
Milling.bToolInvert = true
Milling.bMachAppliedToTunnelFace = true
else -- 'Groove-3-Blind'
elseif #Proc.MainFaces.SideFaces > 0 then -- 'Groove-3-Blind'
ToolSearchParameters.dElevation = Proc.MainFaces.SideFaces[1].dElevation
ToolSearchParameters.vtToolDirection = Proc.MainFaces.SideFaces[1].vtN
Milling.vtFaceNormal = Proc.MainFaces.SideFaces[1].vtN
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 = {}
Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
if Milling.ToolInfo.nToolIndex then
@@ -233,27 +335,86 @@ 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.nCompletionIndex = FeatureData.GetFeatureCompletionIndex( 100)
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
Strategy.Result.dMRR = Machining[1].dMRR
Machining[1].ToolInfo.dResidualDepth = 0
Machining[2].bIsApplicable = false
Machining[3].bIsApplicable = false
Machining[4].bIsApplicable = false
-- caso speciale in cui si devono lavorare due facce
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 = 'Bottom-Bottom2'
Strategy.Result.sStatus = 'Completed'
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
Strategy.Result.dMRR = Machining[1].dMRR + Machining[2].dMRR / 2
Machining[2].ToolInfo.dResidualDepth = 0
else
Machining[2].bIsApplicable = false
end
return Machining
-- caso speciale 'Rabbet-2-Through' che ha la sweconda faccia come se fosse una seconda bottom
elseif Proc.Topology.sName == 'Rabbet-2-Through' and Machining[2].bIsApplicable and Machining[2].ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then
-- caso speciale 'Rabbet-2-Through' che ha la seconda faccia come se fosse una seconda bottom
elseif ( Proc.Topology.sName == 'Rabbet-2-Through' or Proc.Topology.sName == 'Bevel-2-Blind' or Proc.Topology.sName == 'VGroove-2-Through' )
and Machining[2].bIsApplicable and Machining[2].ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then
Machining.sTypeMachining = 'Bottom2'
Strategy.Result.sStatus = 'Completed'
Strategy.Result.nCompletionIndex = FeatureData.GetFeatureCompletionIndex( 100)
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
Strategy.Result.dMRR = Machining[2].dMRR
Machining[2].ToolInfo.dResidualDepth = 0
Machining[1].bIsApplicable = false
@@ -264,7 +425,11 @@ local function GetBestPocketingStrategy( Proc)
elseif Machining[3].bIsApplicable and Machining[3].ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then
Machining.sTypeMachining = 'Side1'
Strategy.Result.sStatus = 'Completed'
Strategy.Result.nCompletionIndex = FeatureData.GetFeatureCompletionIndex( 100)
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
-- si cambia qualità perchè è rimasto il raggio sullo spigolo. E' giusto considerare non completo?
if Proc.Topology.sName == 'Groove-3-Through' or Proc.Topology.sName == 'Rabbet-2-Through' or Proc.Topology.sName == 'Bevel-2-Blind' or Proc.Topology.sName == 'VGroove-2-Through' then
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'SEMI')
end
Strategy.Result.dMRR = Machining[3].dMRR
if Proc.MainFaces.TunnelAddedFaces then
Machining[3].ToolInfo.dResidualDepth = -( Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation + BeamData.MILL_OVERLAP)
@@ -279,7 +444,11 @@ local function GetBestPocketingStrategy( Proc)
elseif Machining[4].bIsApplicable and Machining[4].ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then
Machining.sTypeMachining = 'Side2'
Strategy.Result.sStatus = 'Completed'
Strategy.Result.nCompletionIndex = FeatureData.GetFeatureCompletionIndex( 100)
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
-- si cambia qualità perchè è rimasto il raggio sullo spigolo. E' giusto considerare non completo?
if Proc.Topology.sName == 'Groove-3-Through' or Proc.Topology.sName == 'Rabbet-2-Through' or Proc.Topology.sName == 'Bevel-2-Blind' or Proc.Topology.sName == 'VGroove-2-Through' then
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'SEMI')
end
Strategy.Result.dMRR = Machining[4].dMRR
if Proc.MainFaces.TunnelAddedFaces then
Machining[4].ToolInfo.dResidualDepth = -( Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation + BeamData.MILL_OVERLAP)
@@ -290,14 +459,20 @@ local function GetBestPocketingStrategy( Proc)
Machining[2].bIsApplicable = false
Machining[3].bIsApplicable = false
return Machining
-- se tunnel 2+3 completa tutto
-- se tunnel 3+4 completa tutto
elseif Proc.MainFaces.TunnelAddedFaces and Machining[3].bIsApplicable and Machining[4].bIsApplicable and
Machining[3].ToolInfo.dResidualDepth + Machining[4].ToolInfo.dResidualDepth < (Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation * 2) + BeamData.MILL_OVERLAP then
Machining.sTypeMachining = 'Side1-Side2'
Strategy.Result.sStatus = 'Completed'
Machining[3].ToolInfo.dResidualDepth = Machining[3].ToolInfo.dResidualDepth - Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation
Machining[4].ToolInfo.dResidualDepth = -Machining[3].ToolInfo.dResidualDepth - BeamData.MILL_OVERLAP
Strategy.Result.nCompletionIndex = FeatureData.GetFeatureCompletionIndex( 100)
-- si suddivide l'extra lavorabile sulle due frese
local dExtraMachDepth = ( Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation * 2 - Machining[3].ToolInfo.dResidualDepth - Machining[4].ToolInfo.dResidualDepth - BeamData.MILL_OVERLAP) / 2
Machining[3].ToolInfo.dResidualDepth = Machining[3].ToolInfo.dResidualDepth - Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation + dExtraMachDepth
Machining[4].ToolInfo.dResidualDepth = Machining[4].ToolInfo.dResidualDepth - Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation + dExtraMachDepth
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
-- si cambia qualità perchè è rimasto il raggio sullo spigolo. E' giusto considerare non completo?
if Proc.Topology.sName == 'Groove-3-Through' or Proc.Topology.sName == 'Rabbet-2-Through' or Proc.Topology.sName == 'Bevel-2-Blind' or Proc.Topology.sName == 'VGroove-2-Through' then
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'SEMI')
end
Strategy.Result.dMRR = ( Machining[3].dMRR + Machining[4].dMRR) / 2
Machining[1].bIsApplicable = false
Machining[2].bIsApplicable = false
@@ -330,227 +505,204 @@ local function GetBestPocketingStrategy( Proc)
end
local dMachinedPrercentage = CalcMachinedPercentage( Proc, Machining)
Strategy.Result.nCompletionIndex = FeatureData.GetFeatureCompletionIndex( dMachinedPrercentage)
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( dMachinedPrercentage)
Strategy.Result.sInfo = 'Machining not complete, left ' .. tostring( 100 - ceil( dMachinedPrercentage)) .. '%'
-- se non ho trovato neanche una lavorazione
if Machining.sTypeMachining == 'None' then
Strategy.Result.sStatus = 'Not-Applicable'
Strategy.Result.nCompletionIndex = 0
Strategy.Result.dMRR = 0
Strategy.Result.nQuality = 0
Strategy.Result.sInfo = 'Mill not found'
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( 'Mill not found')
end
return Machining
end
-------------------------------------------------------------------------------------------------------------
local function VerifySplitMachiningNeeded( Proc, Part)
local function GetSplitSurfaces( Proc, Part, bAddMachining)
local vAddId = {}
local vAddIdTunnel = {}
local bSplit
-- la lunghezza richiede spezzatura
if Proc.b3Box:getDimX() > BeamData.LONGCUT_MAXLEN or Proc.b3Box:getDimX() > 0.7 * Part.b3Solid:getDimX() then
bSplit = true
local idAddGroup
if bAddMachining then
idAddGroup = BeamLib.GetAddGroup( Part.id)
else
bSplit = false
idAddGroup = Part.idTempGroup
end
local nOriginalTmIdTunnel = GDB_ID.NULL
if Proc.MainFaces.TunnelAddedFaces then
nOriginalTmIdTunnel = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.id
end
-- la lunghezza richiede spezzatura
if ( bSplit) then
-- recupero gruppo per geometria aggiuntiva
local nAddGrpId = BeamLib.GetAddGroup( Part.id)
local bStartLeft, bStartRight
local nIdTunnel = nil
if Proc.MainFaces.TunnelAddedFaces then
nIdTunnel = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.id
end
-- recupero punti di spezzatura - da destra a sinistra
local FeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
-- se feature inizia al di sotto del limite sinistro (coda)
if Proc.b3Box:getMin():getX() < Part.b3Solid:getMin():getX() + BeamData.LONGCUT_ENDLEN then
bStartLeft = true
end
-- se feature inizia al di sotto del limite destro (testa)
if Proc.b3Box:getMax():getX() > Part.b3Solid:getMax():getX() - BeamData.LONGCUT_ENDLEN then
bStartRight = true
end
-- recupero utensile con massimo diametro
local dMaxDiam = 30
for t = 1, #Strategy.Machining do
if Strategy.Machining[t].bIsApplicable then
dMaxDiam = min( dMaxDiam, TOOLS[Strategy.Machining[t].ToolInfo.nToolIndex].dDiameter)
end
end
-- salvo valori
local dNewMinX = Proc.b3Box:getMin():getX()
local dNewMaxX = Proc.b3Box:getMax():getX()
local dNewRest = Proc.b3Box:getDimX()
-- creo primo spezzone sulla sinistra
if bStartLeft then
local AddId = EgtCopyGlob( Proc.id, nAddGrpId) or GDB_ID.NULL
-- copio faccia tunnel
local AddIdTunnel = EgtCopyGlob( nIdTunnel, nAddGrpId) or GDB_ID.NULL
-- decido punto spezzatura verso la coda
if Proc.b3Box:getDimX() > BeamData.LONGCUT_ENDLEN * 2 then
dNewMinX = max( Part.b3Solid:getMin():getX() + BeamData.LONGCUT_ENDLEN, Proc.b3Box:getMin():getX() + dMaxDiam * 3)
else
-- se pezzo abbastanza piccolo, spezzo in mezzo al 'pezzo + grezzo restante'
if Part.dRestLength + Part.b3Solid:getDimX() < BeamData.dMinRaw * 1.5 then
dNewMinX = Part.b3Solid:getMax():getX() - ( ( Part.dRestLength + Part.b3Solid:getDimX()) / 2)
else
dNewMinX = max( Proc.b3Box:getMin():getX() + ( BeamData.dMinRaw)/2 + 150, Part.b3Solid:getMax():getX() - BeamData.LONGCUT_ENDLEN)
end
end
local ptOn = Point3d( dNewMinX, 0, 0)
dNewRest = abs( dNewMaxX - dNewMinX)
-- taglio della superficie lato sinistro
EgtCutSurfTmPlane( AddId, ptOn, X_AX(), true, GDB_RT.GLOB)
EgtCutSurfTmPlane( AddIdTunnel, ptOn, X_AX(), true, GDB_RT.GLOB)
-- eseguo inserimento
table.insert( vAddId, AddId)
table.insert( vAddIdTunnel, AddIdTunnel)
end
-- creo spezzone sulla destra
if bStartRight then
local AddId = EgtCopyGlob( Proc.id, nAddGrpId) or GDB_ID.NULL
-- copio faccia tunnel
local AddIdTunnel = EgtCopyGlob( nIdTunnel, nAddGrpId) or GDB_ID.NULL
dNewMaxX = min( ( Proc.b3Box:getMax():getX() - dMaxDiam * 3), Part.b3Solid:getMax():getX() - BeamData.LONGCUT_ENDLEN)
if dNewMaxX - dNewMinX < 500 * GEO.EPS_SMALL then
dNewMaxX = dNewMinX - BeamData.MILL_OVERLAP
dNewRest = 0
else
dNewRest = dNewMaxX - dNewMinX
end
local ptOn = Point3d( dNewMaxX, 0, 0)
-- taglio della superficie lato destro
EgtCutSurfTmPlane( AddId, ptOn, -X_AX(), true, GDB_RT.GLOB)
EgtCutSurfTmPlane( AddIdTunnel, ptOn, -X_AX(), true, GDB_RT.GLOB)
-- eseguo inserimento
table.insert( vAddId, 1, AddId)
table.insert( vAddIdTunnel, AddIdTunnel)
end
-- lavoro il restante
if dNewRest > 0 then
local nSplitParts = max( ceil( dNewRest / BeamData.LONGCUT_MAXLEN + 10 * GEO.EPS_SMALL), 1)
local dSplitPartsLen = dNewRest / nSplitParts
for i = 1, nSplitParts do
local AddId = EgtCopyGlob( Proc.id, nAddGrpId) or GDB_ID.NULL
-- copio faccia tunnel
local AddIdTunnel = EgtCopyGlob( nIdTunnel, nAddGrpId) or GDB_ID.NULL
local ptOn
-- se un solo spezzone, prendo punto massimo e minimo
if nSplitParts == 1 then
ptOn = Point3d( dNewMinX, 0, 0)
-- taglio della superficie lato sinistro
EgtCutSurfTmPlane( AddId, ptOn, -X_AX(), true, GDB_RT.GLOB)
EgtCutSurfTmPlane( AddIdTunnel, ptOn, -X_AX(), true, GDB_RT.GLOB)
ptOn = Point3d( dNewMaxX, 0, 0)
-- taglio della superficie lato destro
EgtCutSurfTmPlane( AddId, ptOn, X_AX(), true, GDB_RT.GLOB)
EgtCutSurfTmPlane( AddIdTunnel, ptOn, X_AX(), true, GDB_RT.GLOB)
else
-- eseguo trim sinistro
if i ~= 1 or bStartLeft then
ptOn = Point3d( dNewMinX, 0, 0)
-- taglio della superficie lato sinistro
EgtCutSurfTmPlane( AddId, ptOn, -X_AX(), true, GDB_RT.GLOB)
EgtCutSurfTmPlane( AddIdTunnel, ptOn, -X_AX(), true, GDB_RT.GLOB)
end
-- eseguo trim destro
dNewMaxX = dNewMinX + dSplitPartsLen
if i ~= nSplitParts or bStartRight then
ptOn = Point3d( dNewMaxX, 0, 0)
-- taglio della superficie lato destro
EgtCutSurfTmPlane( AddId, ptOn, X_AX(), true, GDB_RT.GLOB)
EgtCutSurfTmPlane( AddIdTunnel, ptOn, X_AX(), true, GDB_RT.GLOB)
end
-- il nuovo minimo è il punto massimo del precedente
dNewMinX = dNewMaxX
end
-- eseguo inserimento in modo da ordinare da X- a X+
table.insert( vAddId, EgtIf( #vAddId == 0 or not bStartRight, 1, 2), AddId)
table.insert( vAddIdTunnel, EgtIf( #vAddIdTunnel == 0 or not bStartRight, 1, 2), AddIdTunnel)
end
end
if #FeatureSplittingPoints == 0 then
local nAddId = EgtCopyGlob( Proc.id, idAddGroup) or GDB_ID.NULL
local nAddIdTunnel = EgtCopyGlob( nOriginalTmIdTunnel, idAddGroup) or GDB_ID.NULL
table.insert( vAddId, nAddId)
table.insert( vAddIdTunnel, nAddIdTunnel)
else
-- TODO se è sulla coda, messaggio che posso rovinare
table.insert( vAddId, Proc.id)
for i = 1, #FeatureSplittingPoints do
local nAddId = EgtCopyGlob( Proc.id, 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)
EgtCutSurfTmPlane( nAddId, ptSplit, -X_AX(), true, GDB_RT.GLOB)
EgtCutSurfTmPlane( nAddIdTunnel, ptSplit, -X_AX(), true, GDB_RT.GLOB)
else
-- taglio della superficie corrente - lato sinistro
local ptSplit = FeatureSplittingPoints[i] + Vector3d( -BeamData.MILL_OVERLAP / 2, 0, 0)
EgtCutSurfTmPlane( nAddId, ptSplit, -X_AX(), true, GDB_RT.GLOB)
EgtCutSurfTmPlane( nAddIdTunnel, ptSplit, -X_AX(), true, GDB_RT.GLOB)
-- taglio della superficie corrente - lato destro
ptSplit = FeatureSplittingPoints[i - 1] + Vector3d( BeamData.MILL_OVERLAP / 2, 0, 0)
EgtCutSurfTmPlane( nAddId, ptSplit, X_AX(), true, GDB_RT.GLOB)
EgtCutSurfTmPlane( nAddIdTunnel, ptSplit, X_AX(), true, GDB_RT.GLOB)
end
table.insert( vAddId, nAddId)
table.insert( vAddIdTunnel, nAddIdTunnel)
end
-- taglio ultima superficie, va tagliata solo a destra
local nAddId = EgtCopyGlob( Proc.id, 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)
table.insert( vAddId, nAddId)
table.insert( vAddIdTunnel, nAddIdTunnel)
end
return vAddId, vAddIdTunnel
end
-------------------------------------------------------------------------------------------------------------
-- TODO rimuovere il calcolo MRR dove non serve, è fatto tutto alla fine.
function STR0002.Make( bAddMachining, Proc, Part, CustomParameters)
-- carico parametri de default e li aggiorno con quelli passati dal chiamante (potrebbero non essere congruenti)
local StrategyLib = {}
StrategyLib.Config = require( 'STR0002\\STR0002Config')
StrategyLib.Config = STRATEGIES_CONFIG[CustomParameters.sStrategyId]
Strategy.sName = StrategyLib.Config.sStrategyId
CustomParameters = BeamLib.GetUpdateCustomParameters( CustomParameters, StrategyLib.Config.Parameters)
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( CustomParameters)
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( Proc, Part, CustomParameters, StrategyLib.Config)
Strategy.Machining = {}
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.sStatus = 'Not-Applicable'
Strategy.Result.nCompletionIndex = 0
Strategy.Result.dMRR = 0
Strategy.Result.nQuality = 0
Strategy.Result.sInfo = 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 bAreAllApplyOk = true
local bAreAllMachiningsAdded = true
local dFeatureVolume = Proc.dVolume
local ToolInfo = {}
local Pocketing = {}
Strategy.Machining = GetBestPocketingStrategy( Proc)
Strategy.Machining = GetBestPocketingStrategy( Proc, Part)
if bAddMachining and Strategy.Result.sStatus ~= 'Not-Applicable' then
local vAddId, vAddIdTunnel = VerifySplitMachiningNeeded( Proc, Part)
if Strategy.Result.sStatus ~= 'Not-Applicable' then
local vAddId = {}
local vAddIdTunnel = {}
-- recupero superficie, se necessario trimmata sugli spezzoni
vAddId, vAddIdTunnel = GetSplitSurfaces( Proc, Part, bAddMachining)
-- si applicano le lavorazioni
for i = 1, #vAddId do
for j = 1, #Strategy.Machining do
if Strategy.Machining[j].bIsApplicable then
Pocketing = {}
Pocketing = MachiningLib.InitMachiningParameters( MCH_MY.POCKETING)
Pocketing.Steps = {}
Pocketing.LeadIn = {}
Pocketing.nType = MCH_OY.POCKETING
Pocketing.nSubType = EgtIf( Proc.Topology.sName == 'Pocket-5-Blind', MCH_POCK_SUB.SPIRALOUT, MCH_POCK_SUB.SPIRALIN)
Pocketing.nType = MCH_MY.POCKETING
Pocketing.nSubType = EgtIf( Proc.Topology.sName == 'Pocket-5-Blind' or Proc.Topology.sName == 'Tunnel-4-Through', MCH_POCK_SUB.SPIRALOUT, MCH_POCK_SUB.SPIRALIN)
Pocketing.LeadIn.nType = MCH_POCK_LI.ZIGZAG
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
Pocketing.dOpenMinSafe = Strategy.Parameters.dOpenMinSafe
-- il quarto ciclo è la lavorazione opposta sulla faccia Tunnel
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}}
bAreAllApplyOk = MachiningLib.AddNewMachining( Proc, Pocketing)
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
Pocketing.sStage = 'AfterTail'
end
Pocketing.nSCC = GetSCC( Proc, Pocketing)
Pocketing.dTimeToMachine = MachiningLib.GetTimeToMachineAllStepsWithLeadInOut( Pocketing, Part)
Strategy.Result.dTimeToMachine = Strategy.Result.dTimeToMachine + Pocketing.dTimeToMachine
if bAddMachining then
bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, Pocketing)
end
else
-- TODO settare parametro per indicare qual è lo spezzone che deve essere fatto dopo il taglio di separazione
-- TODO controllare parametro danneggiamento ammesso per decidere se spostare dopo taglio seprazione
-- se è aperta sulla coda, dico che deve essere fatta dopo la separazione
if Proc.AffectedFaces.bLeft and i == #vAddId then
Pocketing.sStage = 'AfterTail'
end
for k = 1, Proc.nFct do
local vtNSplitFace
local dIdTm = EgtIf( Strategy.Machining[j].bMachAppliedToTunnelFace, vAddIdTunnel[i], vAddId[i])
_, vtNSplitFace = EgtSurfTmFacetCenter( dIdTm, k - 1, GDB_ID.ROOT)
local nIdTm = EgtIf( Strategy.Machining[j].bMachAppliedToTunnelFace, vAddIdTunnel[i], vAddId[i])
Pocketing.ptCenter, vtNSplitFace = EgtSurfTmFacetCenter( nIdTm, k - 1, GDB_ID.ROOT)
Pocketing.vtToolDirection = vtNSplitFace or Strategy.Machining[j].vtFaceNormal
if Pocketing.bToolInvert then
Pocketing.vtToolDirection = -Pocketing.vtToolDirection
end
if vtNSplitFace and AreSameVectorApprox( vtNSplitFace * EgtIf( Pocketing.bToolInvert, -1, 1), Strategy.Machining[j].vtFaceNormal) then
Pocketing.Geometry = {{ dIdTm, k - 1}}
bAreAllApplyOk = bAreAllApplyOk and MachiningLib.AddNewMachining( Proc, Pocketing)
Pocketing.Geometry = {{ nIdTm, k - 1}}
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
break
end
end
@@ -558,11 +710,13 @@ function STR0002.Make( bAddMachining, Proc, Part, CustomParameters)
end
end
end
-- TODO se incompleta il volume non è corretto, ma conta? L'MRR ha senso nelle incomplete??
Strategy.Result.dMRR = ( dFeatureVolume / Strategy.Result.dTimeToMachine) / pow( 10, 6)
else
bAreAllApplyOk = false
bAreAllMachiningsAdded = false
end
return bAreAllApplyOk, Strategy.Result
return bAreAllMachiningsAdded, Strategy.Result
end
-------------------------------------------------------------------------------------------------------------
@@ -1,11 +0,0 @@
-- Parametri configurabili da cliente per strategia: STR0002
local STR0002Data = {
sStrategyId = 'STR0002',
Parameters = {
{ sName = 'dMaxCornerRadius', sValue = '15', sDescriptionShort = 'Max radius left on corners', sDescriptionLong = 'Radius-limit left by the tool at each corner of the feature', sType = 'd', sMinUserLevel = '1', sMessageId = ''},
{ sName = 'bAntiSplint', sValue = 'false', sDescriptionShort = 'Use Anti-Splint strategy', sDescriptionLong = 'The strategy will apply blade cuts on corner to avoid wood splint', sType = 'b', sMinUserLevel = '1', sMessageId = ''}
}
}
return STR0002Data
+95
View File
@@ -0,0 +1,95 @@
{
"sStrategyId": "STR0003",
"sStrategyName": "Blade plus ChainSaw",
"ParameterList" : [
{
"sName": "bFinishWithChainSaw",
"sNameNge": "ALLOW_FINISH_CHAINSAW",
"sValue": "true",
"sDescriptionShort": "Finish with chainsaw if needed",
"sDescriptionLong": "Finish with chainsaw if needed",
"sType": "b",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "dExtendAfterTail",
"sNameNge": "EXTEND_AFTER_TAIL",
"sValue": "",
"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": "bForceLongcutBlade",
"sNameNge": "USE_LONGCUT_BLADE",
"sValue": "false",
"sDescriptionShort": "Force ripping blade",
"sDescriptionLong": "Force the use of ripping blade, designed for cuts parallel to the grain",
"sType": "b",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "bNotCompleteWithBladeRadius",
"sNameNge": "NOT_COMPLETE_WITH_BLADE_RADIUS",
"sValue": "true",
"sDescriptionShort": "Not complete with Blade radius imprint left",
"sDescriptionLong": "If the parameter is active, the automatism considers the feature as - not complete - if the blade radius imprint is left",
"sType": "b",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "bUseZigZagMortising",
"sNameNge": "USE_ZIGZAG_CHAINSAW",
"sValue": "false",
"sDescriptionShort": "Use Zig-Zag ChainSaw",
"sDescriptionLong": "Enable the parameter to set the Zig-Zag movement on the ChainSaw machining. Deactivate it to use One-Way movement.",
"sType": "b",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "bSortBySegment",
"sNameNge": "SORT_BY_SEGMENT",
"sValue": "true",
"sDescriptionShort": "Sort by segment",
"sDescriptionLong": "Sort the machinings according to the piece-segment where the machining has inserted",
"sType": "b",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "sCanDamageNextPiece",
"sNameNge": "DAMAGE_NEXT_PIECE",
"sValue": "NEVER",
"sDescriptionShort": "Damage next piece",
"sDescriptionLong": "This option allows you to decide how to consider the next piece in the bar. The software calculates specifics LeadIn/out to respect the parameter. This parameter may change the machining time",
"sType": "combo",
"sMinUserLevel": "1",
"Choices": [
{
"sValue": "NEVER",
"sDescriptionShort": "Never damage",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "ONLY_IF_RAWPART",
"sDescriptionShort": "Damage only if raw",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "ALWAYS",
"sDescriptionShort": "Can damage",
"sDescriptionLong": "",
"sMessageId": ""
}
]
}
]
}
+486 -267
View File
@@ -3,14 +3,24 @@
-- Lama + motosega per slot
-- Feature: tipo lapjoint
-------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------
-- TODO
-- 1 - Gestire lavorazioni da sotto
-- 2 - Inserire antischeggia (fresa o lama)
-- 3 - Smusso a V
-- 4 - Implementare lavorazione di geometrie inclinate
-------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamData')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FeatureData = require( 'FeatureData')
local FeatureLib = require( 'FeatureLib')
-- strategie di base
local SlotByBlade = require( 'SLOTBYBLADE')
local SlotByChainSaw = require( 'SLOTBYCHAINSAW')
local FaceByBlade = require( 'FACEBYBLADE')
local FaceByChainsaw = require( 'FACEBYCHAINSAW')
-- Tabella per definizione modulo
local STR0003 = {}
@@ -25,38 +35,87 @@ 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
local function GetCompletionPercentage( Proc, Result)
local dNotMachinedArea = 0
local dCompletionPercentage = 0
if Proc.Topology.sFamily == 'Tunnel' then
dNotMachinedArea = Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1].dLength * ( Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength - Result[1].dDepthMachined)
if #Result == 2 then
dNotMachinedArea = dNotMachinedArea - Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1].dLength * ( Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength - Result[2].dDepthMachined)
end
-- TODO si può unificare con eguale funzione in STR0004
local function SortMachiningsBySegment( MachiningA, MachiningB)
if MachiningA.nFeatureSegment > MachiningB.nFeatureSegment then
return false
elseif MachiningB.nFeatureSegment > MachiningA.nFeatureSegment then
return true
else
if #Result == 1 then
dNotMachinedArea = Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.dLength * ( Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength - Result[1].dDepthMachined)
elseif #Result == 2 then
dNotMachinedArea = ( Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.dLength - Result[2].dDepthMachined) * ( Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength - Result[1].dDepthMachined)
elseif #Result == 3 then
dNotMachinedArea = ( Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.dLength - Result[2].dDepthMachined - Result[3].dDepthMachined) * ( Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength - Result[1].dDepthMachined)
if TOOLS[ MachiningA.nToolIndex].sFamily == 'SAWBLADE' and TOOLS[ MachiningB.nToolIndex].sFamily == 'MORTISE' then
return true
elseif TOOLS[ MachiningA.nToolIndex].sFamily == 'MORTISE' and TOOLS[ MachiningB.nToolIndex].sFamily == 'SAWBLADE' then
return false
else
if MachiningA.sEdgeType == 'Side' and MachiningB.sEdgeType ~= 'Side' then
return true
elseif MachiningB.sEdgeType == 'Side' and MachiningA.sEdgeType ~= 'Side' then
return false
end
end
end
dCompletionPercentage = 100 - dNotMachinedArea / Proc.MainFaces.LongFaces[1].dArea * 100
end
return dCompletionPercentage
local function SortMachiningsByTool( MachiningA, MachiningB)
if TOOLS[ MachiningA.nToolIndex].sFamily == 'SAWBLADE' and TOOLS[ MachiningB.nToolIndex].sFamily == 'MORTISE' then
return true
elseif TOOLS[ MachiningA.nToolIndex].sFamily == 'MORTISE' and TOOLS[ MachiningB.nToolIndex].sFamily == 'SAWBLADE' then
return false
else
if MachiningA.nFeatureSegment > MachiningB.nFeatureSegment then
return false
elseif MachiningB.nFeatureSegment > MachiningA.nFeatureSegment then
return true
else
if MachiningA.sEdgeType == 'Side' and MachiningB.sEdgeType ~= 'Side' then
return true
elseif MachiningB.sEdgeType == 'Side' and MachiningA.sEdgeType ~= 'Side' then
return false
end
end
end
end
local function MergeResults( Result)
local SortedResult = {}
for i = 1, #Result.Side do
if Result.Side[i].bIsApplicable then
table.insert( SortedResult, Result.Side[i])
end
end
for i = 1, #Result.Bottom do
if Result.Bottom[i].bIsApplicable then
table.insert( SortedResult, Result.Bottom[i])
end
end
for i = 1, #Result.Opposite do
if Result.Opposite[i].bIsApplicable then
table.insert( SortedResult, Result.Opposite[i])
end
end
return SortedResult
end
@@ -85,33 +144,26 @@ local function AddResult( Machining, Result)
end
function Blade.AddResult( Cutting)
AddResult( Cutting, Blade.Result)
local function AddMachinings( Proc, Machinings)
local bAreAllMachiningsAdded = true
for i = 1, #Machinings do
if Machinings[i].bIsApplicable then
local bIsMachiningAdded
bIsMachiningAdded = MachiningLib.AddMachinings( Proc, Machinings[i])
if not bIsMachiningAdded then
bAreAllMachiningsAdded = false
end
Strategy.Result.sInfo = Strategy.Result.sInfo .. '\n' .. Machinings[i].sMessage
end
end
return bAreAllMachiningsAdded
end
function Blade.AddMachiningAllSteps( Proc, Cutting, AuxiliaryData)
local bMachiningAdded = false
if not AuxiliaryData then
AuxiliaryData = {}
end
AuxiliaryData.Clones = {}
local dOriginalRadialOffset = Cutting.dRadialOffset
local dOriginalLeadInPerpDistance = Cutting.LeadIn.dPerpDistance
local dOriginalLeadOutPerpDistance = Cutting.LeadOut.dPerpDistance
for i = Cutting.HorizontalSteps.nCount, 1, -1 do
AuxiliaryData.Clones[i] = {}
AuxiliaryData.Clones[i].LeadIn = {}
AuxiliaryData.Clones[i].LeadOut = {}
AuxiliaryData.Clones[i].dRadialOffset = dOriginalRadialOffset + Cutting.HorizontalSteps.dStep * ( i - 1)
-- update distanza perpendicolare attacco per contemplare l'offset applicato
AuxiliaryData.Clones[i].LeadIn.dPerpDistance = dOriginalLeadInPerpDistance - Cutting.dRadialOffset
AuxiliaryData.Clones[i].LeadOut.dPerpDistance = dOriginalLeadOutPerpDistance - Cutting.dRadialOffset
end
bMachiningAdded = MachiningLib.AddNewMachining( Proc, Cutting, AuxiliaryData)
return bMachiningAdded
function Blade.AddResult( Cutting)
AddResult( Cutting, Blade.Result)
end
@@ -120,82 +172,145 @@ function Chainsaw.AddResult( Mortising)
end
function Chainsaw.AddMachiningAllSteps( Proc, Mortising, AuxiliaryData)
local bMachiningAdded = false
if not AuxiliaryData then
AuxiliaryData = {}
end
AuxiliaryData.Clones = {}
local function GetTotalAreaToMachine( Machinings)
local dTotalAreaToMachine = 0
local dOriginalRadialOffsetMortising = Mortising.dRadialOffset
for i = Mortising.VerticalSteps.nCount, 1, -1 do
AuxiliaryData.Clones[i] = {}
AuxiliaryData.Clones[i].dRadialOffset = dOriginalRadialOffsetMortising + Mortising.VerticalSteps.dStep * ( i - 1)
for i = 1, #Machinings do
local Machining = Machinings[i]
dTotalAreaToMachine = dTotalAreaToMachine + Machining.dAreaToMachine
end
bMachiningAdded = MachiningLib.AddNewMachining( Proc, Mortising, AuxiliaryData)
return bMachiningAdded
return dTotalAreaToMachine
end
function STR0003.Make( bAddMachining, Proc, Part, CustomParameters)
-- TODO da implementare gestione feature lunghe e spezzatura
-- carico parametri da default e li aggiorno con quelli passati dal chiamante (potrebbero non essere congruenti)
local StrategyLib = {}
StrategyLib.Config = require( 'STR0003\\STR0003Config')
StrategyLib.Config = STRATEGIES_CONFIG[CustomParameters.sStrategyId]
Strategy.sName = StrategyLib.Config.sStrategyId
CustomParameters = BeamLib.GetUpdateCustomParameters( CustomParameters, StrategyLib.Config.Parameters)
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( CustomParameters)
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( Proc, Part, CustomParameters, StrategyLib.Config)
Strategy.Result = {}
Strategy.Result.sInfo = ''
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)
Strategy.Result.sStatus = 'Not-Applicable'
Strategy.Result.sInfo = 'Topology'
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)
-- 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.sStatus = 'Not-Applicable'
Strategy.Result.sInfo = '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
-- lama
-- lavorazione di lama - fondo della tasca o fino a massimo materiale se tunnel
local Cutting = {}
local OptionalParameters = { bForceLongcutBlade = Strategy.Parameters.bForceLongcutBlade}
local dExtendAfterTail = Strategy.Parameters.dExtendAfterTail or max( Part.dDistanceToNextPiece - BeamData.CUT_EXTRA, 0)
if MachiningLib.CanExtendAfterTail( Strategy.Parameters.sCanDamageNextPiece, Part) then
dExtendAfterTail = 10000
end
-- volume della feature
local dFeatureVolume = Proc.dVolume
-- eventuali punti di spezzatura
local FeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
local bIsSplitFeature = false
if #FeatureSplittingPoints > 0 then
bIsSplitFeature = true
end
-- altezza tasca
local dPocketHeight = 0
if Proc.Topology.sFamily == 'Tunnel' then
Cutting = SlotByBlade.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1], OptionalParameters)
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
Cutting = SlotByBlade.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge, OptionalParameters)
dPocketHeight = Proc.MainFaces.BottomFaces[1].MainEdges.SideEdges[1].dLength
end
-- riferimenti locali per leggibilità e performance
local LongFace = Proc.MainFaces.LongFaces[1]
local OppositeEdge1 = LongFace.MainEdges.OppositeEdges[1]
local OppositeEdge2 = LongFace.MainEdges.OppositeEdges[2]
local SideEdge1 = LongFace.MainEdges.SideEdges[1]
local SideEdge2 = LongFace.MainEdges.SideEdges[2]
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
local OptionalParameters = {
bForceLongcutBlade = Strategy.Parameters.bForceLongcutBlade,
dExtendAfterTail = dExtendAfterTail,
dPocketHeight = dPocketHeight,
bIsSplitFeature = bIsSplitFeature
}
-- primo lato del tunnel o lato di fondo
if Proc.Topology.sFamily == 'Tunnel' then
OptionalParameters.OppositeToolDirectionMode = 'Enabled'
Cutting = FaceByBlade.Make( Proc, Part, LongFace, OppositeEdge1, OptionalParameters)
else
Cutting = FaceByBlade.Make( Proc, Part, LongFace, BottomEdge, OptionalParameters)
end
Blade.AddResult( Cutting)
-- lato opposto del tunnel
if Proc.Topology.sFamily == 'Tunnel' then
Cutting = SlotByBlade.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[2], OptionalParameters)
OptionalParameters.OppositeToolDirectionMode = 'Enabled'
Cutting = FaceByBlade.Make( Proc, Part, LongFace, OppositeEdge2, OptionalParameters)
Blade.AddResult( Cutting)
-- per tutte le altre topologie lavorazione lati aggiuntivi
else
-- se la lama non è arrivata sul fondo e c'è almeno un lato aperto va lavorato
if Blade.Result.Bottom[1].dResidualDepth > 10 * GEO.EPS_SMALL then
-- eventuale lavorazione di lama - lato della tasca da cui inizia la lavorazione
if Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.bIsStartOpen then
Cutting = SlotByBlade.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1], OptionalParameters)
if BottomEdge.bIsStartOpen then
OptionalParameters.OppositeToolDirectionMode = 'Enabled'
Cutting = FaceByBlade.Make( Proc, Part, LongFace, SideEdge1, OptionalParameters)
Cutting.dAreaToMachine = Cutting.dDepthToMachine * ( Cutting.dEdgeLength - Blade.Result.Bottom[1].dDepthToMachine)
Blade.AddResult( Cutting)
end
-- eventuale lavorazione di lama - lato della tasca in cui finisce la lavorazione
if Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.bIsEndOpen then
Cutting = SlotByBlade.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[2], OptionalParameters)
if BottomEdge.bIsEndOpen then
OptionalParameters.OppositeToolDirectionMode = 'Enabled'
Cutting = FaceByBlade.Make( Proc, Part, LongFace, SideEdge2, OptionalParameters)
Cutting.dAreaToMachine = Cutting.dDepthToMachine * ( Cutting.dEdgeLength - Blade.Result.Bottom[1].dDepthToMachine)
Blade.AddResult( Cutting)
end
-- la lama è arrivata sul fondo e tasca passante, non servono ulteriori lavorazioni
elseif #( Proc.MainFaces.SideFaces) == 0 then
Strategy.Parameters.bFinishWithChainSaw = false
@@ -203,169 +318,244 @@ function STR0003.Make( bAddMachining, Proc, Part, CustomParameters)
end
end
local nIsApplicableCount = 0
local dFinalCompletionPercentage = 100
local bAreAllMachiningsAdded = true
for i = 1, #Blade.Result.Bottom do
if Blade.Result.Bottom[i].bIsApplicable then
nIsApplicableCount = nIsApplicableCount + 1
if bAddMachining then
local bIsMachiningAdded = Blade.AddMachiningAllSteps( Proc, Blade.Result.Bottom[i])
if not bIsMachiningAdded then
bAreAllMachiningsAdded = false
end
end
Strategy.Result.sInfo = Strategy.Result.sInfo .. '\n' .. Blade.Result.Bottom[i].sMessage
end
end
for i = 1, #Blade.Result.Side do
if Blade.Result.Side[i].bIsApplicable then
nIsApplicableCount = nIsApplicableCount + 1
if bAddMachining then
local bIsMachiningAdded = Blade.AddMachiningAllSteps( Proc, Blade.Result.Side[i])
if not bIsMachiningAdded then
bAreAllMachiningsAdded = false
end
end
Strategy.Result.sInfo = Strategy.Result.sInfo .. '\n' .. Blade.Result.Side[i].sMessage
end
end
for i = 1, #Blade.Result.Opposite do
if Blade.Result.Opposite[i].bIsApplicable then
nIsApplicableCount = nIsApplicableCount + 1
if bAddMachining then
local bIsMachiningAdded = Blade.AddMachiningAllSteps( Proc, Blade.Result.Opposite[i])
if not bIsMachiningAdded then
bAreAllMachiningsAdded = false
end
end
Strategy.Result.sInfo = Strategy.Result.sInfo .. '\n' .. Blade.Result.Opposite[i].sMessage
end
end
if nIsApplicableCount > 0 then
-- TODO sistemare il calcolo completamento - implementare calcolo area lavorata
if not Strategy.Parameters.bNotCompleteWithBladeRadius and Cutting.dCompletionPercentage > 100 - 10 * GEO.EPS_SMALL then
Strategy.Result.sStatus = 'Completed'
else
Strategy.Result.sStatus = 'Not-Completed'
-- TODO al momento si assume che la percentuale di completamento dell'ultima lavorazione sia quella rilevante
dFinalCompletionPercentage = Cutting.dCompletionPercentage
end
else
Strategy.Result.sStatus = 'Not-Applicable'
Strategy.Parameters.bFinishWithChainSaw = false
-- lama - lavorazioni raggruppate in unica lista, escluse le lavorazioni non applicabili
Blade.Result.Sorted = MergeResults( Blade.Result)
-- lama - calcolo area lavorata
local dAreaToMachineBlade = GetTotalAreaToMachine( Blade.Result.Sorted)
-- lama - aggiunta eventuali lavorazioni splittate
if bIsSplitFeature then
Blade.Result.Sorted = MachiningLib.GetSplitMachinings( Blade.Result.Sorted, FeatureSplittingPoints, Part)
end
-- lama - nessuna lavorazione successiva - aggiunta lavorazioni e calcolo risultati
if not Strategy.Parameters.bFinishWithChainSaw then
Strategy.Result.nCompletionIndex = FeatureData.GetFeatureCompletionIndex( dFinalCompletionPercentage)
Strategy.Result.nQuality = FeatureData.GetFeatureQuality( 'Blade')
local MRRParametersBlade = {
dStep = TOOLS[Cutting.nToolIndex].dThickness,
dSideStep = min( TOOLS[Cutting.nToolIndex].dSideStep, Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength),
dFeed = TOOLS[Cutting.nToolIndex].Feeds.dFeed}
local dMRRBlade = MachiningLib.GetToolMRR( MRRParametersBlade)
Strategy.Result.dMRR = dMRRBlade
-- ordinamento
if Strategy.Parameters.bSortBySegment then
table.sort( Blade.Result.Sorted, SortMachiningsBySegment)
else
table.sort( Blade.Result.Sorted, SortMachiningsByTool)
end
-- aggiunta lavorazioni
local bAreAllMachiningsAdded = true
if bAddMachining then
bAreAllMachiningsAdded = AddMachinings( Proc, Blade.Result.Sorted)
end
-- calcolo risultati
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( Blade.Result.Sorted)
Strategy.Result.dCompletionPercentage = dAreaToMachineBlade / LongFace.dArea * 100
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( Strategy.Result.dCompletionPercentage)
Strategy.Result.dTimeToMachine = FeatureLib.GetStrategyTimeToMachine( Blade.Result.Sorted)
Strategy.Result.dMRR = ( dFeatureVolume / Strategy.Result.dTimeToMachine) / pow( 10, 6)
if #Blade.Result.Sorted > 0 then
if not Strategy.Parameters.bNotCompleteWithBladeRadius and Cutting.dCompletionPercentage > 100 - 10 * GEO.EPS_SMALL then
Strategy.Result.sStatus = 'Completed'
else
Strategy.Result.sStatus = 'Not-Completed'
end
-- non ha senso che STR0003 lama+catena sia applicabile se la lama non può lavorare, in quel caso deve essere scelta la STR0004 solo catena
else
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable()
Strategy.Parameters.bFinishWithChainSaw = false
end
return bAreAllMachiningsAdded, Strategy.Result
end
-- sega a catena
-- TODO funzione separata
-- sega a catena - calcolo lavorazioni
local Mortising = {}
OptionalParameters = {}
-- parametri comuni a tutte le lavorazioni mortising
OptionalParameters = {
dExtendAfterTail = dExtendAfterTail,
dPocketHeight = dPocketHeight,
bIsSplitFeature = bIsSplitFeature
}
if Proc.Topology.sName == 'Groove-4-Blind' or Proc.Topology.sName == 'Pocket-5-Blind' then
-- si lavora solamente l'impronta lama sui lati chiusi
if ( Blade.Result.Bottom[1].dResidualDepth < 10 * GEO.EPS_SMALL) and
( Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.dLength > 3 * Blade.Result.Bottom[1].dBladeMarkLength - 10 * GEO.EPS_SMALL) then
( BottomEdge.dLength > 3 * Blade.Result.Bottom[1].dToolMarkLength - 10 * GEO.EPS_SMALL) then
if not Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.bIsStartOpen then
local OptionalParameters = { sSideToMachine = 'Start', dLengthToMachine = Blade.Result.Bottom[1].dBladeMarkLength, dMaxElev = 0}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge, OptionalParameters)
if not BottomEdge.bIsStartOpen then
OptionalParameters.sSideToMachine = 'Start'
OptionalParameters.dLengthToMachine = Blade.Result.Bottom[1].dToolMarkLength
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, BottomEdge, OptionalParameters)
Mortising.dAreaToMachine = Mortising.dDepthToMachine * Mortising.dEdgeLength
Chainsaw.AddResult( Mortising)
end
if not Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.bIsEndOpen then
local OptionalParameters = { sSideToMachine = 'End', dLengthToMachine = Blade.Result.Bottom[1].dBladeMarkLength, dMaxElev = 0}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge, OptionalParameters)
if not BottomEdge.bIsEndOpen then
OptionalParameters.sSideToMachine = 'End'
OptionalParameters.dLengthToMachine = Blade.Result.Bottom[1].dToolMarkLength
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, BottomEdge, OptionalParameters)
Mortising.dAreaToMachine = Mortising.dDepthToMachine * Mortising.dEdgeLength
Chainsaw.AddResult( Mortising)
end
-- reset parametri opzionali
OptionalParameters.sSideToMachine = nil
OptionalParameters.dLengthToMachine = nil
-- si lavora tutto il fondo
else
local OptionalParameters = { dMaxElev = Blade.Result.Bottom[1].dResidualDepth + BeamData.CUT_EXTRA}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge, OptionalParameters)
OptionalParameters.dMaxElev = Blade.Result.Bottom[1].dResidualDepth + BeamData.CUT_EXTRA
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, BottomEdge, OptionalParameters)
Chainsaw.AddResult( Mortising)
OptionalParameters.dMaxElev = nil
end
-- ancora materiale residuo - se possibile si lavora dal lato
if Chainsaw.Result.Bottom[#Chainsaw.Result.Bottom].dResidualDepth > 10 * GEO.EPS_SMALL and #Proc.MainFaces.SideFaces == 1 then
if Chainsaw.Result.Bottom[#Chainsaw.Result.Bottom].dResidualDepth > 10 * GEO.EPS_SMALL
and #Proc.MainFaces.SideFaces == 1 then
-- si lavora solamente l'impronta lama sul fondo
if ( #Blade.Result.Side > 0) and Blade.Result.Side[1].dResidualDepth < 10 * GEO.EPS_SMALL then
if ( Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.bIsStartOpen and Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength > 3 * Blade.Result.Side[1].dBladeMarkLength - 10 * GEO.EPS_SMALL) then
local OptionalParameters = { sSideToMachine = 'End', dLengthToMachine = Blade.Result.Side[1].dBladeMarkLength, dMaxElev = 0}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1], OptionalParameters)
elseif ( Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.bIsEndOpen and Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[2].dLength > 3 * Blade.Result.Side[1].dBladeMarkLength - 10 * GEO.EPS_SMALL) then
local OptionalParameters = { sSideToMachine = 'Start', dLengthToMachine = Blade.Result.Side[1].dBladeMarkLength, dMaxElev = 0}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[2], OptionalParameters)
if ( BottomEdge.bIsStartOpen and SideEdge1.dLength > 3 * Blade.Result.Side[1].dToolMarkLength - 10 * GEO.EPS_SMALL) then
OptionalParameters.sSideToMachine = 'End'
OptionalParameters.dLengthToMachine = Blade.Result.Side[1].dToolMarkLength
OptionalParameters.OppositeToolDirectionMode = 'Enabled'
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, SideEdge1, OptionalParameters)
Mortising.dAreaToMachine = Mortising.dDepthToMachine * ( Mortising.dEdgeLength - Chainsaw.Result.Bottom[1].dDepthToMachine)
elseif ( BottomEdge.bIsEndOpen and SideEdge2.dLength > 3 * Blade.Result.Side[1].dToolMarkLength - 10 * GEO.EPS_SMALL) then
OptionalParameters.sSideToMachine = 'Start'
OptionalParameters.dLengthToMachine = Blade.Result.Side[2].dToolMarkLength
OptionalParameters.OppositeToolDirectionMode = 'Enabled'
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, SideEdge2, OptionalParameters)
Mortising.dAreaToMachine = Mortising.dDepthToMachine * ( Mortising.dEdgeLength - Chainsaw.Result.Bottom[1].dDepthToMachine)
end
-- si lavora tutto il lato
else
local dBladeResidualDepth
if #Blade.Result.Side > 0 then
dBladeResidualDepth = Blade.Result.Side[1].dResidualDepth
else
dBladeResidualDepth = Blade.Result.Bottom[1].dResidualDepth
end
if Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.bIsStartOpen then
local OptionalParameters = { dMaxElev = dBladeResidualDepth + BeamData.CUT_EXTRA}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1], OptionalParameters)
elseif Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.bIsEndOpen then
local OptionalParameters = { dMaxElev = dBladeResidualDepth + BeamData.CUT_EXTRA}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[2], OptionalParameters)
if BottomEdge.bIsStartOpen then
OptionalParameters.dMaxElev = dBladeResidualDepth + BeamData.CUT_EXTRA
OptionalParameters.OppositeToolDirectionMode = 'Enabled'
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, SideEdge1, OptionalParameters)
Mortising.dAreaToMachine = Mortising.dDepthToMachine * ( Mortising.dEdgeLength - Chainsaw.Result.Bottom[1].dDepthToMachine)
elseif BottomEdge.bIsEndOpen then
OptionalParameters.dMaxElev = dBladeResidualDepth + BeamData.CUT_EXTRA
OptionalParameters.OppositeToolDirectionMode = 'Enabled'
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, SideEdge2, OptionalParameters)
Mortising.dAreaToMachine = Mortising.dDepthToMachine * ( Mortising.dEdgeLength - Chainsaw.Result.Bottom[1].dDepthToMachine)
end
end
Chainsaw.AddResult( Mortising)
end
elseif Proc.Topology.sName == 'Groove-3-Through' then
if Blade.Result.Bottom[1].dResidualDepth > 10 * GEO.EPS_SMALL then
-- si lavora tutto il fondo
local OptionalParameters = { dMaxElev = Blade.Result.Bottom[1].dResidualDepth + BeamData.CUT_EXTRA}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge, OptionalParameters)
OptionalParameters.dMaxElev = Blade.Result.Bottom[1].dResidualDepth + BeamData.CUT_EXTRA
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, BottomEdge, OptionalParameters)
Chainsaw.AddResult( Mortising)
OptionalParameters.dMaxElev = nil
-- ancora materiale residuo - si lavorano i lati
if Chainsaw.Result.Bottom[1].dResidualDepth > 10 * GEO.EPS_SMALL then
OptionalParameters.bExtendWithCornerRadius = true
-- si lavora solamente l'impronta lama sul fondo
if ( Blade.Result.Side[1].dResidualDepth < 10 * GEO.EPS_SMALL and Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength > 3 * Blade.Result.Side[1].dBladeMarkLength - 10 * GEO.EPS_SMALL) and
( Blade.Result.Side[2].dResidualDepth < 10 * GEO.EPS_SMALL and Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[2].dLength > 3 * Blade.Result.Side[2].dBladeMarkLength - 10 * GEO.EPS_SMALL) then
if ( Blade.Result.Side[1].dResidualDepth < 10 * GEO.EPS_SMALL and SideEdge1.dLength > 3 * Blade.Result.Side[1].dToolMarkLength - 10 * GEO.EPS_SMALL) and
( Blade.Result.Side[2].dResidualDepth < 10 * GEO.EPS_SMALL and SideEdge2.dLength > 3 * Blade.Result.Side[2].dToolMarkLength - 10 * GEO.EPS_SMALL) then
local OptionalParameters = { sSideToMachine = 'End', dLengthToMachine = Blade.Result.Side[1].dBladeMarkLength, dMaxElev = 0}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1], OptionalParameters)
OptionalParameters.dDepthToMachine = SideEdge1.dElevation + BeamData.CUT_EXTRA
OptionalParameters.sSideToMachine = 'End'
OptionalParameters.dLengthToMachine = Blade.Result.Side[1].dToolMarkLength
OptionalParameters.OppositeToolDirectionMode = 'Enabled'
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, SideEdge1, OptionalParameters)
Mortising.dAreaToMachine = Mortising.dDepthToMachine * ( Mortising.dEdgeLength - Chainsaw.Result.Bottom[1].dDepthToMachine)
Chainsaw.AddResult( Mortising)
-- ancora materiale residuo - si lavora da entrambi i lati
if Chainsaw.Result.Side[1].dResidualDepth > 10 * GEO.EPS_SMALL then
local OptionalParameters = { bStopAtHalfElevation = true, sSideToMachine = 'End', dLengthToMachine = Blade.Result.Side[1].dBladeMarkLength, dMaxElev = 0}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1], OptionalParameters)
Chainsaw.Result.Side[1].bIsApplicable = false
OptionalParameters.dDepthToMachine = SideEdge1.dElevation / 2 + BeamData.CUT_EXTRA_MIN
OptionalParameters.sSideToMachine = 'End'
OptionalParameters.dLengthToMachine = Blade.Result.Side[1].dToolMarkLength
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, SideEdge1, OptionalParameters)
Mortising.dAreaToMachine = Mortising.dDepthToMachine * ( Mortising.dEdgeLength - Chainsaw.Result.Bottom[1].dDepthToMachine)
Chainsaw.AddResult( Mortising)
OptionalParameters = {}
OptionalParameters = { bStopAtHalfElevation = true, sSideToMachine = 'Start', dLengthToMachine = Blade.Result.Side[2].dBladeMarkLength, dMaxElev = 0}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[2], OptionalParameters)
OptionalParameters.dDepthToMachine = SideEdge2.dElevation / 2 + BeamData.CUT_EXTRA_MIN
OptionalParameters.sSideToMachine = 'Start'
OptionalParameters.dLengthToMachine = Blade.Result.Side[2].dToolMarkLength
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, SideEdge2, OptionalParameters)
Mortising.dAreaToMachine = 0
Chainsaw.AddResult( Mortising)
-- lavorando dai due lati non c'è materiale residuo - si può eliminare la lavorazione del fondo
if Chainsaw.Result.Side[2].dResidualDepth < 10 * GEO.EPS_SMALL then
Chainsaw.Result.Bottom[1].bIsApplicable = false
end
end
-- si lavora tutto il lato
else
local OptionalParameters = { dMaxElev = Blade.Result.Side[1].dResidualDepth + BeamData.CUT_EXTRA}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1], OptionalParameters)
OptionalParameters.dDepthToMachine = SideEdge1.dElevation + BeamData.CUT_EXTRA
OptionalParameters.dMaxElev = Blade.Result.Side[1].dResidualDepth + BeamData.CUT_EXTRA
OptionalParameters.OppositeToolDirectionMode = 'Enabled'
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, SideEdge1, OptionalParameters)
Mortising.dAreaToMachine = Mortising.dDepthToMachine * ( Mortising.dEdgeLength - Chainsaw.Result.Bottom[1].dDepthToMachine)
Chainsaw.AddResult( Mortising)
-- ancora materiale residuo - si lavora da entrambi i lati
if Chainsaw.Result.Side[1].dResidualDepth > 10 * GEO.EPS_SMALL then
Chainsaw.Result.Side[1].bIsApplicable = false
local OptionalParameters = { bStopAtHalfElevation = true, dMaxElev = Blade.Result.Side[1].dResidualDepth + BeamData.CUT_EXTRA}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1], OptionalParameters)
OptionalParameters.dDepthToMachine = SideEdge1.dElevation / 2 + BeamData.CUT_EXTRA_MIN
OptionalParameters.dMaxElev = Blade.Result.Side[1].dResidualDepth + BeamData.CUT_EXTRA
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, SideEdge1, OptionalParameters)
Mortising.dAreaToMachine = Mortising.dDepthToMachine * ( Mortising.dEdgeLength - Chainsaw.Result.Bottom[1].dDepthToMachine)
Chainsaw.AddResult( Mortising)
OptionalParameters = {}
OptionalParameters = { bStopAtHalfElevation = true, dMaxElev = Blade.Result.Side[2].dResidualDepth + BeamData.CUT_EXTRA}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[2], OptionalParameters)
OptionalParameters.dDepthToMachine = SideEdge2.dElevation / 2 + BeamData.CUT_EXTRA_MIN
OptionalParameters.dMaxElev = Blade.Result.Side[2].dResidualDepth + BeamData.CUT_EXTRA
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, SideEdge2, OptionalParameters)
Mortising.dAreaToMachine = 0
Chainsaw.AddResult( Mortising)
-- lavorando dai due lati non c'è materiale residuo - si può disabilitare la lavorazione del fondo
if Chainsaw.Result.Side[2].dResidualDepth < 10 * GEO.EPS_SMALL then
Chainsaw.Result.Bottom[1].bIsApplicable = false
@@ -374,117 +564,146 @@ function STR0003.Make( bAddMachining, Proc, Part, CustomParameters)
end
end
end
elseif Proc.Topology.sName == 'Tunnel-4-Through' then
OptionalParameters.OppositeToolDirectionMode = 'Enabled'
OptionalParameters.bExtendWithCornerRadius = true
-- si lavora solamente l'impronta lama sul lato opposto
if ( Blade.Result.Opposite[1].dResidualDepth < 10 * GEO.EPS_SMALL and Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1].dLength > 3 * Blade.Result.Opposite[1].dBladeMarkLength - 10 * GEO.EPS_SMALL) and
( Blade.Result.Opposite[2].dResidualDepth < 10 * GEO.EPS_SMALL and Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[2].dLength > 3 * Blade.Result.Opposite[2].dBladeMarkLength - 10 * GEO.EPS_SMALL) then
local OptionalParameters = { sSideToMachine = 'Start', dLengthToMachine = Blade.Result.Opposite[1].dBladeMarkLength, dMaxElev = 0}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1], OptionalParameters)
if ( Blade.Result.Opposite[1].dResidualDepth < 10 * GEO.EPS_SMALL and OppositeEdge1.dLength > 3 * Blade.Result.Opposite[1].dToolMarkLength - 10 * GEO.EPS_SMALL) and
( Blade.Result.Opposite[2].dResidualDepth < 10 * GEO.EPS_SMALL and OppositeEdge2.dLength > 3 * Blade.Result.Opposite[2].dToolMarkLength - 10 * GEO.EPS_SMALL) then
OptionalParameters.dLengthToMachine = max(
Blade.Result.Opposite[1].dToolMarkLength,
Blade.Result.Opposite[2].dToolMarkLength
)
OptionalParameters.dDepthToMachine = OppositeEdge1.dElevation + BeamData.CUT_EXTRA
OptionalParameters.sSideToMachine = 'Start'
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, OppositeEdge1, OptionalParameters)
Mortising.dAreaToMachine = Mortising.dDepthToMachine * Mortising.dEdgeLength
Chainsaw.AddResult( Mortising)
OptionalParameters = {}
OptionalParameters = { sSideToMachine = 'End', dLengthToMachine = Blade.Result.Opposite[2].dBladeMarkLength, dMaxElev = 0}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1], OptionalParameters)
OptionalParameters.sSideToMachine = 'End'
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, OppositeEdge1, OptionalParameters)
Mortising.dAreaToMachine = 0
Chainsaw.AddResult( Mortising)
if Chainsaw.Result.Opposite[1].dResidualDepth > GEO.EPS_SMALL or Chainsaw.Result.Opposite[2].dResidualDepth > GEO.EPS_SMALL then
-- se lavorando solo da un lato rimane materiale residuo, si lavora da entrambi
if Chainsaw.Result.Opposite[1].dResidualDepth > 10 * GEO.EPS_SMALL
or Chainsaw.Result.Opposite[2].dResidualDepth > 10 * GEO.EPS_SMALL then
Chainsaw.Result.Opposite[1].bIsApplicable = false
Chainsaw.Result.Opposite[2].bIsApplicable = false
local OptionalParameters = { bStopAtHalfElevation = true, sSideToMachine = 'Start', dLengthToMachine = Blade.Result.Opposite[1].dBladeMarkLength, dMaxElev = 0}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1], OptionalParameters)
OptionalParameters.dDepthToMachine = OppositeEdge1.dElevation / 2 + BeamData.CUT_EXTRA_MIN
OptionalParameters.sSideToMachine = 'Start'
OptionalParameters.dLengthToMachine = Blade.Result.Opposite[1].dToolMarkLength
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, OppositeEdge1, OptionalParameters)
Mortising.dAreaToMachine = Mortising.dDepthToMachine * Mortising.dEdgeLength
Chainsaw.AddResult( Mortising)
OptionalParameters = {}
OptionalParameters = { bStopAtHalfElevation = true, sSideToMachine = 'End', dLengthToMachine = Blade.Result.Opposite[1].dBladeMarkLength, dMaxElev = 0}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1], OptionalParameters)
OptionalParameters.sSideToMachine = 'End'
OptionalParameters.dLengthToMachine = Blade.Result.Opposite[1].dToolMarkLength
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, OppositeEdge1, OptionalParameters)
Mortising.dAreaToMachine = 0
Chainsaw.AddResult( Mortising)
OptionalParameters = {}
OptionalParameters = { bStopAtHalfElevation = true, sSideToMachine = 'Start', dLengthToMachine = Blade.Result.Opposite[2].dBladeMarkLength, dMaxElev = 0}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[2], OptionalParameters)
OptionalParameters.dDepthToMachine = OppositeEdge2.dElevation / 2 + BeamData.CUT_EXTRA_MIN
OptionalParameters.sSideToMachine = 'Start'
OptionalParameters.dLengthToMachine = Blade.Result.Opposite[2].dToolMarkLength
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, OppositeEdge2, OptionalParameters)
Mortising.dAreaToMachine = Mortising.dDepthToMachine * Mortising.dEdgeLength
Chainsaw.AddResult( Mortising)
OptionalParameters = {}
OptionalParameters = { bStopAtHalfElevation = true, sSideToMachine = 'End', dLengthToMachine = Blade.Result.Opposite[2].dBladeMarkLength, dMaxElev = 0}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[2], OptionalParameters)
OptionalParameters.sSideToMachine = 'End'
OptionalParameters.dLengthToMachine = Blade.Result.Opposite[2].dToolMarkLength
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, OppositeEdge2, OptionalParameters)
Mortising.dAreaToMachine = 0
Chainsaw.AddResult( Mortising)
end
-- si lavora tutto il lato
else
local OptionalParameters = { dMaxElev = Blade.Result.Opposite[1].dResidualDepth + BeamData.CUT_EXTRA}
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1], OptionalParameters)
OptionalParameters.dDepthToMachine = OppositeEdge1.dElevation + BeamData.CUT_EXTRA
OptionalParameters.dMaxElev = Blade.Result.Opposite[1].dResidualDepth + BeamData.CUT_EXTRA
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, OppositeEdge1, OptionalParameters)
Chainsaw.AddResult( Mortising)
if Chainsaw.Result.Opposite[1].dResidualDepth > GEO.EPS_SMALL then
if Chainsaw.Result.Opposite[1].dResidualDepth > 10 * GEO.EPS_SMALL then
Chainsaw.Result.Opposite[1].bIsApplicable = false
local OptionalParameters = { bStopAtHalfElevation = true, dMaxElev = Blade.Result.Opposite[1].dResidualDepth + BeamData.CUT_EXTRA}
SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1], OptionalParameters)
OptionalParameters.dDepthToMachine = OppositeEdge1.dElevation / 2 + BeamData.CUT_EXTRA_MIN
OptionalParameters.dMaxElev = Blade.Result.Opposite[1].dResidualDepth + BeamData.CUT_EXTRA
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, OppositeEdge1, OptionalParameters)
Chainsaw.AddResult( Mortising)
OptionalParameters = {}
OptionalParameters = { bStopAtHalfElevation = true, dMaxElev = Blade.Result.Opposite[2].dResidualDepth + BeamData.CUT_EXTRA}
SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[2], OptionalParameters)
OptionalParameters.dDepthToMachine = OppositeEdge2.dElevation / 2 + BeamData.CUT_EXTRA_MIN
OptionalParameters.dMaxElev = Blade.Result.Opposite[2].dResidualDepth + BeamData.CUT_EXTRA
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, OppositeEdge2, OptionalParameters)
Chainsaw.AddResult( Mortising)
end
end
end
local nIsApplicableCount = 0
local dFinalCompletionPercentage = 100
-- sega a catena - lavorazioni raggruppate in unica lista
Chainsaw.Result.Sorted = MergeResults( Chainsaw.Result)
-- sega a catena - calcolo area lavorata
local dAreaToMachineChainsaw = GetTotalAreaToMachine( Chainsaw.Result.Sorted)
-- sega a catena - aggiunta eventuali lavorazioni splittate
if bIsSplitFeature then
Chainsaw.Result.Sorted = MachiningLib.GetSplitMachinings( Chainsaw.Result.Sorted, FeatureSplittingPoints, Part)
end
-- tutte le lavorazioni di tutti gli utensili in unica lista
local Result = {}
for i = 1, #Blade.Result.Sorted do
table.insert( Result, Blade.Result.Sorted[i])
end
for i = 1, #Chainsaw.Result.Sorted do
table.insert( Result, Chainsaw.Result.Sorted[i])
end
-- ordinamento
if Strategy.Parameters.bSortBySegment then
table.sort( Result, SortMachiningsBySegment)
else
table.sort( Result, SortMachiningsByTool)
end
-- aggiunta lavorazioni per tutti gli utensili
local bAreAllMachiningsAdded = true
for i = 1, #Chainsaw.Result.Bottom do
if Chainsaw.Result.Bottom[i].bIsApplicable then
nIsApplicableCount = nIsApplicableCount + 1
if bAddMachining then
local bIsMachiningAdded = Chainsaw.AddMachiningAllSteps( Proc, Chainsaw.Result.Bottom[i])
if not bIsMachiningAdded then
bAreAllMachiningsAdded = false
end
end
Strategy.Result.sInfo = Strategy.Result.sInfo .. '\n' .. Chainsaw.Result.Bottom[i].sMessage
end
if bAddMachining then
bAreAllMachiningsAdded = AddMachinings( Proc, Result)
end
for i = 1, #Chainsaw.Result.Side do
if Chainsaw.Result.Side[i].bIsApplicable then
nIsApplicableCount = nIsApplicableCount + 1
if bAddMachining then
local bIsMachiningAdded = Chainsaw.AddMachiningAllSteps( Proc, Chainsaw.Result.Side[i])
if not bIsMachiningAdded then
bAreAllMachiningsAdded = false
end
end
Strategy.Result.sInfo = Strategy.Result.sInfo .. '\n' .. Chainsaw.Result.Side[i].sMessage
end
end
for i = 1, #Chainsaw.Result.Opposite do
if Chainsaw.Result.Opposite[i].bIsApplicable then
nIsApplicableCount = nIsApplicableCount + 1
if bAddMachining then
local bIsMachiningAdded = Chainsaw.AddMachiningAllSteps( Proc, Chainsaw.Result.Opposite[i])
if not bIsMachiningAdded then
bAreAllMachiningsAdded = false
end
end
Strategy.Result.sInfo = Strategy.Result.sInfo .. '\n' .. Chainsaw.Result.Opposite[i].sMessage
end
end
if nIsApplicableCount > 0 then
if Mortising.dCompletionPercentage > 100 - 10 * GEO.EPS_SMALL then
-- calcolo risultati
Strategy.Result.dCompletionPercentage = max( dAreaToMachineBlade, dAreaToMachineChainsaw) / LongFace.dArea * 100
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( Strategy.Result.dCompletionPercentage)
if #Result > 0 then
if Strategy.Result.dCompletionPercentage > 100 - 10 * GEO.EPS_SMALL then
Strategy.Result.sStatus = 'Completed'
else
Strategy.Result.sStatus = 'Not-Completed'
-- TODO al momento si assume che la percentuale di completamento dell'ultima lavorazione sia quella rilevante
dFinalCompletionPercentage = Mortising.dCompletionPercentage
end
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( Result)
Strategy.Result.dTimeToMachine = FeatureLib.GetStrategyTimeToMachine( Result)
Strategy.Result.dMRR = ( dFeatureVolume / Strategy.Result.dTimeToMachine) / pow( 10, 6)
else
Strategy.Result.sStatus = 'Not-Applicable'
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable()
end
Strategy.Result.nCompletionIndex = FeatureData.GetFeatureCompletionIndex( dFinalCompletionPercentage)
Strategy.Result.nQuality = FeatureData.GetFeatureQuality( 'Chainsaw')
local MRRParametersBlade = {
dStep = TOOLS[Cutting.nToolIndex].dThickness,
dSideStep = min( TOOLS[Cutting.nToolIndex].dSideStep, Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength),
dFeed = TOOLS[Cutting.nToolIndex].Feeds.dFeed}
local MRRParametersChainsaw = {
dStep = min( TOOLS[Mortising.nToolIndex].dStep, Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength),
dSideStep = TOOLS[Mortising.nToolIndex].dThickness,
dFeed = TOOLS[Mortising.nToolIndex].Feeds.dFeed}
local dMRRBlade = MachiningLib.GetToolMRR( MRRParametersBlade)
local dMRRChainsaw = MachiningLib.GetToolMRR( MRRParametersChainsaw)
Strategy.Result.dMRR = ( dMRRBlade + dMRRChainsaw) / 2
return bAreAllMachiningsAdded, Strategy.Result
end
@@ -1,13 +0,0 @@
-- Parametri configurabili da cliente per strategia: STR0001
local STR0003Data = {
sStrategyId = 'STR0003',
Parameters = {
{ sName = 'bFinishWithChainSaw', sValue = 'true', sDescriptionShort = 'Finish with chainsaw if needed', sDescriptionLong = 'Finish with chainsaw if needed', sType = 'b', sMessageId = '', sMinUserLevel = '1'},
{ sName = 'bForceLongcutBlade', sValue = 'false', sDescriptionShort = 'Force ripping blade', sDescriptionLong = 'Force the use of ripping blade, designed for cuts parallel to the grain', sType = 'b', sMessageId = '', sMinUserLevel = '1'},
{ sName = 'bNotCompleteWithBladeRadius', sValue = 'true', sDescriptionShort = '', sDescriptionLong = '', sType = 'b', sMessageId = '', sMinUserLevel = '1'},
{ sName = 'bUseZigZagMortising', sValue = 'false', sDescriptionShort = '', sDescriptionLong = '', sType = 'b', sMessageId = '', sMinUserLevel = '1'}
}
}
return STR0003Data
+55
View File
@@ -0,0 +1,55 @@
{
"sStrategyId": "STR0004",
"sStrategyName": "ChainSaw",
"ParameterList" : [
{
"sName": "bUseZigZagMortising",
"sNameNge": "USE_ZIGZAG_CHAINSAW",
"sValue": "false",
"sDescriptionShort": "Use Zig-Zag ChainSaw",
"sDescriptionLong": "Enable the parameter to set the Zig-Zag movement on the ChainSaw machining. Deactivate it to use One-Way movement.",
"sType": "b",
"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": "sCanDamageNextPiece",
"sNameNge": "DAMAGE_NEXT_PIECE",
"sValue": "NEVER",
"sDescriptionShort": "Damage next piece",
"sDescriptionLong": "This option allows you to decide how to consider the next piece in the bar. The software calculates specifics LeadIn/out to respect the parameter. This parameter may change the machining time",
"sType": "combo",
"sMinUserLevel": "1",
"Choices": [
{
"sValue": "NEVER",
"sDescriptionShort": "Never damage",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "ONLY_IF_RAWPART",
"sDescriptionShort": "Damage only if raw",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "ALWAYS",
"sDescriptionShort": "Can damage",
"sDescriptionLong": "",
"sMessageId": ""
}
]
}
]
}
+348
View File
@@ -0,0 +1,348 @@
-- Strategia: STR0004
-- Descrizione
-- motosega per slot
-- Feature: tipo lapjoint
-------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------
-- TODO
-- 1 - Inserire antischeggia (fresa o lama)
-- 2 - Smusso a V
-- 3 - Implementare lavorazione di geometrie inclinate
-- 4 - Gestire lavorazioni da sotto (ove possibile, in generale la motosega non lavora da sotto)
-------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
-- strategie di base
local FaceByChainsaw = require( 'FACEBYCHAINSAW')
-- Tabella per definizione modulo
local STR0004 = {}
local Strategy = {}
local Chainsaw = {}
Chainsaw.Result = {}
-------------------------------------------------------------------------------------------------------------
local function IsTopologyOk( Proc)
if Proc.Topology.bAllRightAngles and
( Proc.Topology.sName == 'Pocket-5-Blind' or
Proc.Topology.sName == 'Groove-3-Through' or
Proc.Topology.sName == 'Groove-4-Blind' or
Proc.Topology.sName == 'Tunnel-4-Through') then
return true
else
return false
end
end
-- TODO si può unificare con Sorting generale
local function SortMachiningsBySegment( MachiningA, MachiningB)
if MachiningA.nFeatureSegment > MachiningB.nFeatureSegment then
return false
elseif MachiningB.nFeatureSegment > MachiningA.nFeatureSegment then
return true
else
if MachiningA.sEdgeType == 'Side' and MachiningB.sEdgeType ~= 'Side' then
return true
elseif MachiningB.sEdgeType == 'Side' and MachiningA.sEdgeType ~= 'Side' then
return false
end
end
end
local function AddResult( Machining, Result)
table.insert( Result, {})
if not Result.Bottom then
Result.Bottom = {}
end
if not Result.Side then
Result.Side = {}
end
if not Result.Opposite then
Result.Opposite = {}
end
if Machining.sEdgeType == 'Bottom' then
table.insert( Result.Bottom, Machining)
elseif Machining.sEdgeType == 'Side' then
table.insert( Result.Side, Machining)
elseif Machining.sEdgeType == 'Opposite' then
table.insert( Result.Opposite, Machining)
else
error('AddResult : unknown edge type')
end
return Result
end
function Chainsaw.AddResult( Mortising)
AddResult( Mortising, Chainsaw.Result)
end
local function GetTotalAreaToMachine( Machinings)
local dTotalAreaToMachine = 0
for i = 1, #Machinings do
local Machining = Machinings[i]
dTotalAreaToMachine = dTotalAreaToMachine + Machining.dAreaToMachine
end
return dTotalAreaToMachine
end
function STR0004.Make( bAddMachining, Proc, Part, CustomParameters)
-- carico parametri da default e li aggiorno con quelli passati dal chiamante (potrebbero non essere congruenti)
local StrategyLib = {}
StrategyLib.Config = STRATEGIES_CONFIG[CustomParameters.sStrategyId]
Strategy.sName = StrategyLib.Config.sStrategyId
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( Proc, Part, CustomParameters, StrategyLib.Config)
Strategy.Result = {}
Strategy.Result.sInfo = ''
Chainsaw.Result = {}
if not IsTopologyOk( Proc) then
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( 'Topology')
return false, Strategy.Result
end
-- calcolo estensione oltre la coda
local dExtendAfterTail = Strategy.Parameters.dExtendAfterTail or max( Part.dDistanceToNextPiece - BeamData.CUT_EXTRA, 0)
if MachiningLib.CanExtendAfterTail( Strategy.Parameters.sCanDamageNextPiece, Part) then
dExtendAfterTail = 10000
end
-- volume della feature
local dFeatureVolume = Proc.dVolume
-- eventuali punti di spezzatura
local FeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
local bIsSplitFeature = false
if #FeatureSplittingPoints > 0 then
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
-- riferimenti locali per leggibilità e performance
local LongFace = Proc.MainFaces.LongFaces[1]
local OppositeEdge1 = LongFace.MainEdges.OppositeEdges[1]
local OppositeEdge2 = LongFace.MainEdges.OppositeEdges[2]
local SideEdge1 = LongFace.MainEdges.SideEdges[1]
local SideEdge2 = LongFace.MainEdges.SideEdges[2]
local BottomEdge = LongFace.MainEdges.BottomEdge
-- calcolo lavorazioni
local Mortising = {}
-- parametri comuni a tutte le lavorazioni
OptionalParameters = {
dExtendAfterTail = dExtendAfterTail,
dPocketHeight = dPocketHeight,
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
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, BottomEdge, OptionalParameters)
Chainsaw.AddResult( Mortising)
-- materiale residuo - se possibile si lavora dal lato
if ( Chainsaw.Result.Bottom[#Chainsaw.Result.Bottom].dResidualDepth > 10 * GEO.EPS_SMALL
or not Chainsaw.Result.Bottom[#Chainsaw.Result.Bottom].bIsApplicable)
and #Proc.MainFaces.SideFaces == 1 then
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 - dLengthAlreadyMachined)
elseif BottomEdge.bIsEndOpen then
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, SideEdge2, OptionalParameters)
Mortising.dAreaToMachine = Mortising.dDepthToMachine * ( Mortising.dEdgeLength - dLengthAlreadyMachined)
end
Chainsaw.AddResult( Mortising)
end
elseif Proc.Topology.sName == 'Groove-3-Through' then
-- si lavora tutto il fondo
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, BottomEdge, OptionalParameters)
Chainsaw.AddResult( Mortising)
-- materiale residuo - si lavorano i lati
if ( Chainsaw.Result.Bottom[1].dResidualDepth > 10 * GEO.EPS_SMALL or
not Chainsaw.Result.Bottom[#Chainsaw.Result.Bottom].bIsApplicable) then
OptionalParameters.dDepthToMachine = SideEdge1.dElevation + BeamData.CUT_EXTRA
OptionalParameters.OppositeToolDirectionMode = 'Enabled'
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, SideEdge1, OptionalParameters)
Mortising.dAreaToMachine = Mortising.dDepthToMachine * ( Mortising.dEdgeLength - Chainsaw.Result.Bottom[1].dDepthToMachine)
Chainsaw.AddResult( Mortising)
-- ancora materiale residuo - si lavora da entrambi i lati
if Chainsaw.Result.Side[1].dResidualDepth > 10 * GEO.EPS_SMALL then
Chainsaw.Result.Side[1].bIsApplicable = false
OptionalParameters.bExtendWithCornerRadius = true
OptionalParameters.dDepthToMachine = SideEdge1.dElevation / 2 + BeamData.CUT_EXTRA_MIN
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, SideEdge1, OptionalParameters)
Mortising.dAreaToMachine = Mortising.dDepthToMachine * ( Mortising.dEdgeLength - Chainsaw.Result.Bottom[1].dDepthToMachine)
Chainsaw.AddResult( Mortising)
OptionalParameters.dDepthToMachine = SideEdge2.dElevation / 2 + BeamData.CUT_EXTRA_MIN
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, SideEdge2, OptionalParameters)
Mortising.dAreaToMachine = Mortising.dDepthToMachine * ( Mortising.dEdgeLength - Chainsaw.Result.Bottom[1].dDepthToMachine)
Chainsaw.AddResult( Mortising)
-- lavorando dai due lati non c'è materiale residuo - si può disabilitare la lavorazione del fondo
if Chainsaw.Result.Side[2].dResidualDepth < 10 * GEO.EPS_SMALL then
Chainsaw.Result.Bottom[1].bIsApplicable = false
end
end
end
elseif Proc.Topology.sName == 'Tunnel-4-Through' then
OptionalParameters.dDepthToMachine = OppositeEdge1.dElevation + BeamData.CUT_EXTRA
OptionalParameters.OppositeToolDirectionMode = 'Enabled'
OptionalParameters.bExtendWithCornerRadius = true
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
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
FaceByChainsaw.Make( Proc, Part, LongFace, OppositeEdge1, OptionalParameters)
Chainsaw.AddResult( Mortising)
OptionalParameters.dDepthToMachine = OppositeEdge2.dElevation / 2 + BeamData.CUT_EXTRA_MIN
FaceByChainsaw.Make( Proc, Part, LongFace, OppositeEdge2, OptionalParameters)
Chainsaw.AddResult( Mortising)
end
end
-- lavorazioni raggruppate in unica lista
Chainsaw.Result.Sorted = {}
for i = 1, #Chainsaw.Result.Side do
if Chainsaw.Result.Side[i].bIsApplicable then
table.insert( Chainsaw.Result.Sorted, Chainsaw.Result.Side[i])
end
end
for i = 1, #Chainsaw.Result.Bottom do
if Chainsaw.Result.Bottom[i].bIsApplicable then
table.insert( Chainsaw.Result.Sorted, Chainsaw.Result.Bottom[i])
end
end
for i = 1, #Chainsaw.Result.Opposite do
if Chainsaw.Result.Opposite[i].bIsApplicable then
table.insert( Chainsaw.Result.Sorted, Chainsaw.Result.Opposite[i])
end
end
-- aggiunta eventuali lavorazioni splittate
if bIsSplitFeature then
Chainsaw.Result.Sorted = MachiningLib.GetSplitMachinings( Chainsaw.Result.Sorted, FeatureSplittingPoints, Part)
end
-- ordinamento
-- TODO aggiungere ordinamento per utensile
table.sort( Chainsaw.Result.Sorted, SortMachiningsBySegment)
-- calcolo area lavorata
local dTotalAreaToMachine = GetTotalAreaToMachine( Chainsaw.Result.Sorted)
-- aggiunta lavorazioni
local bAreAllMachiningsAdded = true
for i = 1, #Chainsaw.Result.Sorted do
if Chainsaw.Result.Sorted[i].bIsApplicable then
if bAddMachining then
local bIsMachiningAdded = MachiningLib.AddMachinings( Proc, Chainsaw.Result.Sorted[i])
if not bIsMachiningAdded then
bAreAllMachiningsAdded = false
end
end
Strategy.Result.sInfo = Strategy.Result.sInfo .. '\n' .. Chainsaw.Result.Sorted[i].sMessage
end
end
-- calcolo risultati
Strategy.Result.dCompletionPercentage = dTotalAreaToMachine / LongFace.dArea * 100
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( Strategy.Result.dCompletionPercentage)
if #Chainsaw.Result.Sorted > 0 then
if Mortising.dCompletionPercentage > 100 - 10 * GEO.EPS_SMALL then
Strategy.Result.sStatus = 'Completed'
else
Strategy.Result.sStatus = 'Not-Completed'
end
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( Chainsaw.Result.Sorted)
Strategy.Result.dTimeToMachine = FeatureLib.GetStrategyTimeToMachine( Chainsaw.Result.Sorted)
Strategy.Result.dMRR = ( dFeatureVolume / Strategy.Result.dTimeToMachine) / pow( 10, 6)
else
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable()
end
return bAreAllMachiningsAdded, Strategy.Result
end
-------------------------------------------------------------------------------------------------------------
return STR0004
+154
View File
@@ -0,0 +1,154 @@
{
"sStrategyId": "STR0005",
"sStrategyName": "Blade",
"ParameterList" : [
{
"sName": "bForceLongcutBlade",
"sNameNge": "USE_LONGCUT_BLADE",
"sValue": "false",
"sDescriptionShort": "Force ripping blade",
"sDescriptionLong": "Force the use of ripping blade, designed for cuts parallel to the grain",
"sType": "b",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "dExtendAfterTail",
"sNameNge": "EXTEND_AFTER_TAIL",
"sValue": "",
"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": "sCanDamageNextPiece",
"sNameNge": "DAMAGE_NEXT_PIECE",
"sValue": "NEVER",
"sDescriptionShort": "Damage next piece",
"sDescriptionLong": "This option allows you to decide how to consider the next piece in the bar. The software calculates specifics LeadIn/out to respect the parameter. This parameter may change the machining time",
"sType": "combo",
"sMinUserLevel": "1",
"Choices": [
{
"sValue": "NEVER",
"sDescriptionShort": "Never damage",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "ONLY_IF_RAWPART",
"sDescriptionShort": "Damage only if raw",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "ALWAYS",
"sDescriptionShort": "Can damage",
"sDescriptionLong": "",
"sMessageId": ""
}
]
},
{
"sName": "sCuttingStrategy",
"sNameNge": "CUTTING_STRATEGY",
"sValue": "AUTO",
"sDescriptionShort": "Cutting strategy",
"sDescriptionLong": "",
"sType": "combo",
"sMinUserLevel": "1",
"Choices": [
{
"sValue": "AUTO",
"sDescriptionShort": "Automatic",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "DROP_WASTE",
"sDescriptionShort": "Drop waste",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "KEEP_WASTE_ATTACHED",
"sDescriptionShort": "Keep waste attached",
"sDescriptionLong": "",
"sMessageId": ""
}
]
},
{
"sName": "bDisableDicing",
"sNameNge": "DISABLE_DICING",
"sValue": "false",
"sDescriptionShort": "Disable dicing",
"sDescriptionLong": "",
"sType": "b",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "bAllowFastCuts",
"sNameNge": "ALLOW_FAST_CUTS",
"sValue": "false",
"sDescriptionShort": "Prioritize machining speed over quality",
"sDescriptionLong": "",
"sType": "b",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "dStripWidth",
"sNameNge": "STRIP_WIDTH",
"sValue": "5",
"sDescriptionShort": "Strip width",
"sDescriptionLong": "In case the waste is still kept attached, this is the wigth dimension of the strip",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "bFinishWithMill",
"sNameNge": "ALLOW_FINISH_MILL",
"sValue": "true",
"sDescriptionShort": "Clean blade radius with mill",
"sDescriptionLong": "Clean blade 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"
},
{
"sName": "dMaxWasteLength",
"sSource": "GEN_dMaxWasteLength",
"sMinUserLevel": "5"
},
{
"sName": "dMaxWasteVolume",
"sSource": "GEN_dMaxWasteVolume",
"sMinUserLevel": "5"
},
{
"sName": "dMaxDimDice",
"sSource": "GEN_dMaxDimDice",
"sMinUserLevel": "5"
},
{
"sName": "bReduceBladePath",
"sSource": "GEN_bReduceBladePath",
"sMinUserLevel": "5"
}
]
}
+222
View File
@@ -0,0 +1,222 @@
-- Strategia: STR0005
-- Descrizione
-- lama per taglio facce lasciando codolo o con cubetti
-- Feature: cut, longcut, ridgelap, ...
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
-- strategie di base
local BladeToWaste = require( 'BLADETOWASTE')
local BladeKeepWaste = require( 'BLADEKEEPWASTE')
-- Tabella per definizione modulo
local STR0005 = {}
local Strategy = {}
local Blade = {}
Blade.Result = {}
-------------------------------------------------------------------------------------------------------------
local function IsTwoFacesCommonEdgeTooLong( Proc, Part)
local bIsTwoFacesCommonEdgeTooLong = false
-- controlli preventivi
if Proc.nFct ~= 2 then
error('IsTwoFacesCommonEdgeTooLong : feature must have two faces ')
end
-- ricerca lato in comune
local nCommonEdge
for i = 1, #Proc.Faces[1].Edges do
if Proc.Faces[1].Edges[i].idAdjacentFace > -1 then
nCommonEdge = i
end
end
-- se due facce, cubetti troppo lunghi in X non si possono fare
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
bIsTwoFacesCommonEdgeTooLong = true
end
return bIsTwoFacesCommonEdgeTooLong
end
-------------------------------------------------------------------------------------------------------------
function STR0005.Make( bAddMachining, Proc, Part, CustomParameters)
-- carico parametri da default e li aggiorno con quelli passati dal chiamante (potrebbero non essere congruenti)
local StrategyLib = {}
StrategyLib.Config = STRATEGIES_CONFIG[CustomParameters.sStrategyId]
Strategy.sName = StrategyLib.Config.sStrategyId
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( Proc, Part, CustomParameters, StrategyLib.Config)
Strategy.Result = {}
Strategy.Result.sInfo = ''
Blade.Result = {}
local AuxiliaryData = { bIgnoreNotClampableLength = false}
local dTimeToMachine = 0
local dMRRBlade = 0
local dCompletionPercentage = 0
local dQuality = 0
local dMRRBladeAddedFace = 0
local dCompletionPercentageAddedFace = 0
local dQualityAddedFace = 0
-- più di 3 facce non supportate
if Proc.nFct > 3 and ( not Proc.Topology.sFamily == 'DoubleBevel') then
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( 'More than 3 faces not supported')
end
-- estensione oltre la coda
local dExtendAfterTail = Strategy.Parameters.dExtendAfterTail or max( Part.dDistanceToNextPiece, 0)
if MachiningLib.CanExtendAfterTail( Strategy.Parameters.sCanDamageNextPiece, Part) then
dExtendAfterTail = 10000
end
-- disambiguazione caso 3 facce tipo RidgeLap
local idAddedTmFace
local nAddedFace
if Proc.nFct == 3 and not Proc.Topology.sName == 'Groove-3-Through' then
if Proc.AdjacencyMatrix[2][3] < 0 then
nAddedFace = 1 - 1
elseif Proc.AdjacencyMatrix[1][3] < 0 then
nAddedFace = 2 - 1
else
nAddedFace = 3 - 1
end
-- recupero gruppo per geometria addizionale
local nAddGrpId = BeamLib.GetAddGroup( Part.id)
-- faccia aggiuntiva da lavorare
idAddedTmFace = EgtCopySurfTmFacet( Proc.id, nAddedFace, nAddGrpId)
-- rimozione della terza faccia dalla Proc
local idNewProc = EgtCopyGlob( Proc.id, nAddGrpId)
EgtSurfTmRemoveFacet( idNewProc, nAddedFace)
Proc = FeatureLib.GetProcFromTrimesh( idNewProc, Part, Proc)
end
-- 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 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))
-- lavorazione con codolo
if ( Proc.nFct > 2 and bIsFeatureLong)
or ( bFeatureHindersClamping and not bDropWaste)
or bKeepWasteAttached then
local BladeKeepWasteResult
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
if #Blade.Result == 0
and Proc.nFct < 3
and not bKeepWasteAttached
and not bIsTwoFacesCommonEdgeTooLong then
AuxiliaryData.bIgnoreNotClampableLength = false
local BladeToWasteResult
local OptionalParameters = { dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume,
dMaxWasteLength = Strategy.Parameters.dMaxWasteLength,
bSaveAddedGeometries = bAddMachining,
dExtendAfterTail = dExtendAfterTail,
bAllowFastCuts = Strategy.Parameters.bAllowFastCuts,
bReduceBladePath = Strategy.Parameters.bReduceBladePath,
bDisableDicing = Strategy.Parameters.bDisableDicing
}
Blade.Result, BladeToWasteResult = BladeToWaste.Make( Proc, Part, OptionalParameters)
dTimeToMachine = BladeToWasteResult.dTimeToMachine
dMRRBlade = BladeToWasteResult.dMRR
dCompletionPercentage = BladeToWasteResult.dCompletionPercentage
dQuality = BladeToWasteResult.dQuality
end
-- se arrivati qui non è stata ancora applicata alcuna lavorazione, si prova la lavorazione con codolo
if #Blade.Result == 0 and not bDropWaste then
local BladeKeepWasteResult
local OptionalParameters = { dExtendAfterTail = dExtendAfterTail, dStripWidth = Strategy.Parameters.dStripWidth,
dMillingOffsetFromSide = Strategy.Parameters.dMillingOffsetFromSide
}
AuxiliaryData.bIgnoreNotClampableLength = true
Blade.Result, BladeKeepWasteResult = BladeKeepWaste.Make( Proc, Part, OptionalParameters)
dTimeToMachine = BladeKeepWasteResult.dTimeToMachine
dMRRBlade = BladeKeepWasteResult.dMRR
dCompletionPercentage = BladeKeepWasteResult.dCompletionPercentage
dQuality = BladeKeepWasteResult.dQuality
end
-- lavorazione eventuale terza faccia tipo RidgeLap
-- TODO da completare
-- TODO va messa per prima????????
if idAddedTmFace then
local BladeToWasteResult
local OptionalParameters = { dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume,
dMaxWasteLength = Strategy.Parameters.dMaxWasteLength,
bSaveAddedGeometries = bAddMachining,
dExtendAfterTail = dExtendAfterTail
}
Blade.Result, BladeToWasteResult = BladeToWaste.Make( idAddedTmFace, Part, OptionalParameters)
-- TODO calcolo risultati da aggiornare con funzioni nuove
dMRRBladeAddedFace = BladeToWasteResult.dMRR
dCompletionPercentageAddedFace = BladeToWasteResult.dCompletionPercentage
dQualityAddedFace = BladeToWasteResult.dQuality
dTimeToMachine = dTimeToMachine + BladeToWasteResult.dTimeToMachine
-- la faccia aggiuntiva conta per 1/3
dMRRBlade = 2/3 * dMRRBlade + 1/3 * dMRRBladeAddedFace
dCompletionPercentage = 2/3 * dCompletionPercentage + 1/3 * dCompletionPercentageAddedFace
dQuality = 2/3 * dQuality + 1/3 * dQualityAddedFace
end
-- aggiunta lavorazioni
local nIsApplicableCount = 0
local bAreAllMachiningsAdded = true
for i = 1, #Blade.Result do
if Blade.Result[i].bIsApplicable then
nIsApplicableCount = nIsApplicableCount + 1
if bAddMachining then
local bIsMachiningAdded = MachiningLib.AddMachinings( Proc, Blade.Result[i], AuxiliaryData)
if not bIsMachiningAdded then
bAreAllMachiningsAdded = false
end
end
Strategy.Result.sInfo = Strategy.Result.sInfo .. '\n' .. Blade.Result[i].sMessage
end
end
-- TODO migliorare calcolo area lavorata; se ho il codolo ha senso l'incompleta? se incompleta con codolo faccio i cubetti??
-- TODO settare che il codolo restituisce incompleta tranne quando è forzato
if nIsApplicableCount > 0 then
if dCompletionPercentage > 100 - 10 * GEO.EPS_SMALL then
Strategy.Result.sStatus = 'Completed'
else
Strategy.Result.sStatus = 'Not-Completed'
end
else
Strategy.Result.sStatus = 'Not-Applicable'
end
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( dCompletionPercentage)
Strategy.Result.dQuality = dQuality
Strategy.Result.dTimeToMachine = dTimeToMachine
Strategy.Result.dMRR = dMRRBlade
return bAreAllMachiningsAdded, Strategy.Result
end
-------------------------------------------------------------------------------------------------------------
return STR0005
+97
View File
@@ -0,0 +1,97 @@
{
"sStrategyId": "STR0006",
"sStrategyName": "Tenon",
"ParameterList" : [
{
"sName": "dOverMatOnLength",
"sNameNge": "OVM_LENGTH",
"sValue": "0",
"sDescriptionShort": "Overmaterial on tenon length",
"sDescriptionLong": "",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "dOverMatOnRadius",
"sNameNge": "OVM_RADIUS",
"sValue": "0",
"sDescriptionShort": "Overmaterial on tenon width",
"sDescriptionLong": "",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "nMaxMillingPaths",
"sNameNge": "MAX_PATHS",
"sValue": "3",
"sDescriptionShort": "Maximum number of milling passes",
"sDescriptionLong": "Maximum number of milling passes. If more passes are required, pocketing is performed",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "sCuttingStrategy",
"sNameNge": "EXEC_TENON_SURF",
"sValue": "AUTO",
"sDescriptionShort": "Cutting Strategy",
"sDescriptionLong": "",
"sType": "combo",
"sMinUserLevel": "1",
"Choices": [
{
"sValue": "AUTO",
"sDescriptionShort": "Automatic",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "BLADE_FORCED",
"sDescriptionShort": "Blade only",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "MILL_FORCED",
"sDescriptionShort": "Mill only",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "CHAINSAW_FORCED",
"sDescriptionShort": "ChainSaw only",
"sDescriptionLong": "",
"sMessageId": ""
}
]
},
{
"sName": "sMillingList",
"sNameNge": "TENON_TOOL_LIST",
"sValue": "",
"sDescriptionShort": "Available mill to machine the tenon",
"sDescriptionLong": "",
"sType": "tool",
"sSubType": "MCH_TF.MILL",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "dMaxWasteLength",
"sSource": "GEN_dMaxWasteLength",
"sMinUserLevel": "5"
},
{
"sName": "dMaxWasteVolume",
"sSource": "GEN_dMaxWasteVolume",
"sMinUserLevel": "5"
},
{
"sName": "bReduceBladePath",
"sSource": "GEN_bReduceBladePath",
"sMinUserLevel": "5"
}
]
}
+362
View File
@@ -0,0 +1,362 @@
-- Strategia: STR0006
-- Descrizione
-- Lama + fresa tenone
-- Feature: 50,1
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
local PreSimulationLib = require( 'PreSimulationLib')
-- strategie di base
local BladeToWaste = require( 'BLADETOWASTE')
-- Tabella per definizione modulo
local STR0006 = {}
local Strategy = {}
-------------------------------------------------------------------------------------------------------------
local function GetTenonStrategy( Proc, Part)
local Machining = {}
Machining.Milling = MachiningLib.InitMachiningParameters( MCH_MY.MILLING)
Machining.Cutting = MachiningLib.InitMachiningParameters( MCH_MY.MILLING)
local Result = {}
Result.Milling = {}
Result.Cutting = {}
local ToolSearchParameters = {}
-- scelta automatica lavorazione. Non viene mai scelta la motosega
if Strategy.Parameters.sCuttingStrategy == 'AUTO' then
-- creo piano di taglio sulla testa del tenone
local OptionalParameters = { dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume,
dMaxWasteLength = Strategy.Parameters.dMaxWasteLength,
bReduceBladePath = Strategy.Parameters.bReduceBladePath
}
Machining.Cutting, Result.Cutting = BladeToWaste.Make( Strategy.idTenonCutPlane, Part, OptionalParameters)
-- se presente almeno una lavorazione e completo, il taglio è applicabile
if #Machining.Cutting > 0 and Result.Cutting and Result.Cutting.sStatus == 'Completed' then
Machining.Cutting.bIsApplicable = true
end
-- se non possibile di lama si prova con fresa
if not Machining.Cutting or Result.Cutting.sStatus ~= 'Completed' then
Machining.bCuttingWithMill = true
end
-- lavorazione forzata con utensile lama
elseif Strategy.Parameters.sCuttingStrategy == 'BLADE_FORCED' then
local OptionalParameters = { dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume,
dMaxWasteLength = Strategy.Parameters.dMaxWasteLength,
bReduceBladePath = Strategy.Parameters.bReduceBladePath
}
Machining.Cutting, Result.Cutting = BladeToWaste.Make( Strategy.idTenonCutPlane, Part, OptionalParameters)
-- se presente almeno una lavorazione e completo, il taglio è applicabile
if #Machining.Cutting > 0 and Result.Cutting.sStatus == 'Completed' then
Machining.Cutting.bIsApplicable = true
end
-- lavorazione forzata con utensile fresa
elseif Strategy.Parameters.sCuttingStrategy == 'MILL_FORCED' then
Machining.bCuttingWithMill = true
-- lavorazione forzata con utensile motosega
elseif Strategy.Parameters.sCuttingStrategy == 'CHAINSAW_FORCED' then
-- DA FARE!!
end
-- === ricerca utensile per lavorare tenone ===
Machining.Milling.bIsApplicable = false
-- se tenone in testa oppure se di coda ma è possibile lavorare dopo separazione
if not( Proc.AffectedFaces.bLeft) or Strategy.bCanMoveAfterSplit then
ToolSearchParameters.dElevation = Proc.FeatureInfo.dTenonLength
ToolSearchParameters.vtToolDirection = Proc.FeatureInfo.vtTenonN
ToolSearchParameters.sMillShape = 'STANDARD'
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sMillingList, 'Milling')
Machining.Milling.ToolInfo = {}
Machining.Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
if Machining.Milling.ToolInfo.nToolIndex then
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
bMachIsOk = false
end
end
if bMachIsOk then
Machining.Milling.bIsApplicable = true
-- calcolo passate necessarie
if Proc.FeatureInfo.dTenonMaxDist > TOOLS[Machining.Milling.ToolInfo.nToolIndex].dDiameter * 0.8 then
Machining.nMillingPathsNeeded = ceil( Proc.FeatureInfo.dTenonMaxDist / TOOLS[Machining.Milling.ToolInfo.nToolIndex].dSideStep)
else
Machining.nMillingPathsNeeded = 1
end
local ParametersMRR = {}
ParametersMRR.nToolIndex = Machining.Milling.ToolInfo.nToolIndex
Result.Milling.dMRR = MachiningLib.GetToolMRR( ParametersMRR)
if Machining.Milling.ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then
Result.Milling.sStatus = 'Completed'
else
Result.Milling.sStatus = 'Not-Completed'
Result.Milling.sInfo = 'Tenon not complete, left ' .. ceil( Machining.Milling.ToolInfo.dResidualDepth) .. 'mm'
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.vtTenonN
Machining.Milling.sDepth = min( -Machining.Milling.ToolInfo.dResidualDepth, 0)
Machining.Milling.dStartSafetyLength = BeamData.COLL_SIC
Machining.Milling.Steps = {}
-- se servono passate con sovramateriale e lunghezza tenone entro il massimo materiale, si annulla lo step
if Machining.nMillingPathsNeeded > 1 and Proc.FeatureInfo.dTenonLength < TOOLS[Machining.Milling.ToolInfo.nToolIndex].dMaxMaterial - BeamData.COLL_SIC then
Machining.Milling.Steps.dStep = 0
else
Machining.Milling.Steps.dStep = TOOLS[Machining.Milling.ToolInfo.nToolIndex].dStep
end
Machining.Milling.Steps.nStepType = MCH_MILL_ST.ONEWAY
-- LeadIn / LeadOut
Machining.Milling.LeadIn = {}
Machining.Milling.LeadOut = {}
Machining.Milling.LeadIn.nType = MCH_MILL_LI.TANGENT
Machining.Milling.LeadOut.nType = MCH_MILL_LI.TANGENT
Machining.Milling.LeadIn.dTangentDistance = TOOLS[Machining.Milling.ToolInfo.nToolIndex].dDiameter / 2 + BeamData.COLL_SIC
Machining.Milling.LeadIn.dPerpDistance = TOOLS[Machining.Milling.ToolInfo.nToolIndex].dSideStep
Machining.Milling.LeadOut.dTangentDistance = TOOLS[Machining.Milling.ToolInfo.nToolIndex].dDiameter / 2 + BeamData.COLL_SIC
Machining.Milling.LeadOut.dPerpDistance = TOOLS[Machining.Milling.ToolInfo.nToolIndex].dSideStep
Machining.Milling.dLengthToMachine = Proc.FeatureInfo.dTenonPathLength
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.RIGHT, MCH_MILL_WS.LEFT)
Machining.Milling.sUserNotes = EgtSetVal( 'MaxElev', EgtNumToString( Proc.FeatureInfo.dTenonLength, 1)) .. ';'
-- SCC : si tiene il motore sempre più verso l'esterno
if Proc.AffectedFaces.bLeft then
Machining.Milling.nSCC = MCH_SCC.ADIR_XM
else
Machining.Milling.nSCC = MCH_SCC.ADIR_XP
end
-- passate con sovramateriale
Machining.Milling.AuxiliaryData = {}
Machining.Milling.AuxiliaryData.Clones = {}
for i = Machining.nMillingPathsNeeded, 1, -1 do
-- il primo è il passaggio più esterno
local nIndexClones = Machining.nMillingPathsNeeded - i + 1
-- suddivido step in base al numero passate da fare
local dRealSideStep = floor( Proc.FeatureInfo.dTenonMaxDist / Machining.nMillingPathsNeeded)
-- 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
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
end
-- se cutting da fare come svuotatura, copio i dati dell'utensile scelto per lavorare il tenone
if Machining.bCuttingWithMill and Machining.Milling.bIsApplicable then
Machining.Cutting.bIsApplicable = true
Machining.Cutting.ToolInfo = Machining.Milling.ToolInfo
Result.Cutting.dMRR = Result.Milling.dMRR
Machining.Cutting.Steps = {}
Machining.Cutting.LeadIn = {}
Machining.Cutting.nType = MCH_MY.POCKETING
Machining.Cutting.nSubType = MCH_POCK_SUB.SPIRALIN
Machining.Cutting.LeadIn.nType = MCH_POCK_LI.ZIGZAG
Machining.Cutting.Steps.dStep = TOOLS[Machining.Cutting.ToolInfo.nToolIndex].dStep
Machining.Cutting.Steps.dSideStep = TOOLS[Machining.Cutting.ToolInfo.nToolIndex].dSideStep
Machining.Cutting.nToolIndex = Machining.Cutting.ToolInfo.nToolIndex
Machining.Cutting.LeadIn.dTangentDistance = TOOLS[Machining.Cutting.ToolInfo.nToolIndex].dDiameter/2
Machining.Cutting.LeadIn.dElevation = TOOLS[Machining.Cutting.ToolInfo.nToolIndex].dDiameter/2
Machining.Cutting.sDepth = 0
Machining.Cutting.Geometry = {{ Strategy.idTenonCutPlane, 0}}
Machining.Cutting.vtToolDirection = Proc.FeatureInfo.vtTenonN
if Proc.AffectedFaces.bLeft and Strategy.bCanMoveAfterSplit then
Machining.Cutting.sStage = 'AfterTail'
end
-- tempo di svuotatura
Result.Cutting.dTimeToMachine = MachiningLib.GetTimeToMachineAllStepsWithLeadInOut( Machining.Cutting, Part)
end
end
return Machining, Result
end
-------------------------------------------------------------------------------------------------------------
local function GetFeatureRotationIndex( Proc)
local nVoteIndex
-- se fatto con testa sopra
if TOOLS[Strategy.Machining.Milling.ToolInfo.nToolIndex].SetupInfo.HeadType.bTop then
if Proc.FeatureInfo.vtTenonN:getZ() < 0 then
nVoteIndex = 2
elseif Proc.FeatureInfo.vtTenonN:getZ() > abs( Proc.FeatureInfo.vtTenonN:getY()) then
nVoteIndex = 4
else
nVoteIndex = 3
end
-- se fatto con testa sotto
elseif TOOLS[Strategy.Machining.Milling.ToolInfo.nToolIndex].SetupInfo.HeadType.bBottom then
if Proc.FeatureInfo.vtTenonN:getZ() > 0 then
nVoteIndex = 2
elseif Proc.FeatureInfo.vtTenonN:getZ() < - abs( Proc.FeatureInfo.vtTenonN:getY()) then
nVoteIndex = 4
else
nVoteIndex = 3
end
end
return nVoteIndex
end
-------------------------------------------------------------------------------------------------------------
-- TODO vedere se leggere direttamente la quality dell'utensile e mediarle nel caso di utensile doppio
local function GetTenonMachiningResult( Proc, Result)
local TotalResult = {}
-- setto il risultato in base agli utensili trovati
-- lavorazione completa
if Strategy.Machining.Milling.bIsApplicable and Strategy.Machining.Cutting.bIsApplicable then
TotalResult.sStatus = Result.Milling.sStatus
TotalResult.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
TotalResult.dMRR = ( Result.Milling.dMRR + Result.Cutting.dMRR) / 2
TotalResult.dQuality = FeatureLib.GetStrategyQuality( EgtIf( Strategy.Machining.bCuttingWithMill, 'STD', 'FINE'))
TotalResult.nFeatureRotationIndex = GetFeatureRotationIndex( Proc)
TotalResult.dTimeToMachine = Result.Milling.dTimeToMachine + Result.Cutting.dTimeToMachine
TotalResult.sInfo = ''
-- lavorazione incompleta
elseif Strategy.Machining.Cutting.bIsApplicable then
TotalResult.sStatus = 'Not-Completed'
TotalResult.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 50)
TotalResult.dMRR = Result.Cutting.dMRR
TotalResult.dQuality = FeatureLib.GetStrategyQuality( EgtIf( Strategy.Machining.bCuttingWithMill, 'MILL', 'SAWBLADE'))
TotalResult.sInfo = 'Tenon not completed'
TotalResult.dTimeToMachine = Result.Cutting.dTimeToMachine
-- strategia non applicabile, manca il taglio di lama sulla lunghezza del tenone
else
TotalResult = FeatureLib.GetStrategyResultNotApplicable( 'Error on Tenon cutting')
end
return TotalResult
end
-------------------------------------------------------------------------------------------------------------
function STR0006.Make( bAddMachining, Proc, Part, CustomParameters)
-- carico parametri de default e li aggiorno con quelli passati dal chiamante (potrebbero non essere congruenti)
local StrategyLib = {}
StrategyLib.Config = STRATEGIES_CONFIG[CustomParameters.sStrategyId]
Strategy.sName = StrategyLib.Config.sStrategyId
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( Proc, Part, CustomParameters, StrategyLib.Config)
Strategy.Machining = {}
Strategy.Result = {}
local Results = {}
local bAreAllMachiningsAdded = true
-- controllo conformità offset tenone
Strategy.Parameters.dOverMatOnRadius = EgtClamp( Strategy.Parameters.dOverMatOnRadius, -5, 5)
Strategy.Parameters.dOverMatOnLength = EgtClamp( Strategy.Parameters.dOverMatOnLength, -5, 5)
-- calcolo se la lavorazione del tenone può essere spostata dopo taglio di coda
local dLengthOnX = Proc.b3Box:getDimX()
Strategy.bCanMoveAfterSplit = MachiningLib.CanMoveAfterSplitcut( dLengthOnX, Part)
-- aggiunta superficie di taglio sulla lunghezza del tenone
local nAddGrpId = BeamLib.GetAddGroup( Part.id)
local ptCenterAddSurf = Proc.FeatureInfo.ptTenonCenter + ( Proc.FeatureInfo.vtTenonN * Strategy.Parameters.dOverMatOnLength)
Strategy.idTenonCutPlane = EgtSurfTmPlaneInBBox( nAddGrpId, ptCenterAddSurf, Proc.FeatureInfo.vtTenonN, Part.b3Part, GDB_RT.GLOB)
Strategy.Machining, Results = GetTenonStrategy( Proc, Part)
Strategy.Result = GetTenonMachiningResult( Proc, Results)
-- applicazione delle lavorazioni
if bAddMachining and Strategy.Result.sStatus ~= 'Not-Applicable' then
-- taglio in lunghezza sul tenone
if Strategy.Machining.Cutting.bIsApplicable then
OptionalParameters = {}
-- se cutting da fare come svuotatura
if Strategy.Machining.bCuttingWithMill then
bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, Strategy.Machining.Cutting)
-- taglio di lama
else
for i = 1, #Strategy.Machining.Cutting do
if Strategy.Machining.Cutting.bIsApplicable then
if Proc.AffectedFaces.bLeft and Strategy.bCanMoveAfterSplit then
Strategy.Machining.Cutting[i].sStage = 'AfterTail'
end
local bIsMachiningAdded = MachiningLib.AddMachinings( Proc, Strategy.Machining.Cutting[i])
if not bIsMachiningAdded then
bAreAllMachiningsAdded = false
end
end
end
end
end
-- passaggio sul profilo
if Strategy.Machining.Milling.bIsApplicable then
-- 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
local nNearSide -- +3 = Z+, -3 = Z-
local bShortPart = ( Part.b3Part:getDimX() < BeamData.LEN_SHORT_PART)
if TOOLS[Strategy.Machining.Milling.nToolIndex].SetupInfo.HeadType.bTop then
if bShortPart and Proc.FeatureInfo.vtTenonN:getX() < 0 and Proc.FeatureInfo.vtTenonN:getZ() > 0 then
nNearSide = -3
else
nNearSide = 3
end
else
if bShortPart and Proc.FeatureInfo.vtTenonN:getX() < 0 and Proc.FeatureInfo.vtTenonN:getZ() < 0 then
nNearSide = 3
else
nNearSide = -3
end
end
BeamLib.PutStartNearestToEdge( Proc.FeatureInfo.idAddAuxGeom, Part.b3Raw, Proc.FeatureInfo.dTenonMaxDist, nNearSide)
-- aggiunge lavorazione
bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, Strategy.Machining.Milling, Strategy.Machining.Milling.AuxiliaryData)
end
end
end
return bAreAllMachiningsAdded, Strategy.Result
end
-------------------------------------------------------------------------------------------------------------
return STR0006
+128
View File
@@ -0,0 +1,128 @@
{
"sStrategyId": "STR0007",
"sStrategyName": "DoveTail Mortise",
"ParameterList" : [
{
"sName": "dOverMatOnLength",
"sNameNge": "OVM_LENGTH",
"sValue": "0",
"sDescriptionShort": "Overmaterial on Mortise length",
"sDescriptionLong": "",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "dOverMatOnRadius",
"sNameNge": "OVM_RADIUS",
"sValue": "0",
"sDescriptionShort": "Overmaterial on Mortise width",
"sDescriptionLong": "",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "nMaxMillingPaths",
"sNameNge": "MAX_PATHS",
"sValue": "3",
"sDescriptionShort": "Maximum number of milling passes",
"sDescriptionLong": "Maximum number of milling passes. If more passes are required, pocketing is performed",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "bUseDTToolOnPocketing",
"sNameNge": "ALLOW_DT_POCKET",
"sValue": "true",
"sDescriptionShort": "Use DoveTail tool in case of pocketing",
"sDescriptionLong": "",
"sType": "b",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "bAntiSplint",
"sNameNge": "ANTI_SPLINT",
"sValue": "true",
"sDescriptionShort": "Add Anti-Splint",
"sDescriptionLong": "",
"sType": "b",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "sCuttingStrategy",
"sNameNge": "EXEC_MORTISE_SURF",
"sValue": "AUTO",
"sDescriptionShort": "Cutting Strategy",
"sDescriptionLong": "",
"sType": "combo",
"sMinUserLevel": "1",
"Choices": [
{
"sValue": "AUTO",
"sDescriptionShort": "Automatic",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "BLADE_FORCED",
"sDescriptionShort": "Blade only",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "MILL_FORCED",
"sDescriptionShort": "Mill only",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "CHAINSAW_FORCED",
"sDescriptionShort": "ChainSaw only",
"sDescriptionLong": "",
"sMessageId": ""
}
]
},
{
"sName": "sPocketingList",
"sNameNge": "POCK_MORTISE_SURF_LIST",
"sValue": "",
"sDescriptionShort": "Available mill to machine the mortise cut surface",
"sDescriptionLong": "",
"sType": "tool",
"sSubType": "MCH_TF.MILL",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "sMillingList",
"sNameNge": "DOVETAIL_TOOL_LIST",
"sValue": "",
"sDescriptionShort": "Available mill to machine the dovetail mortise",
"sDescriptionLong": "",
"sType": "tool",
"sSubType": "MCH_TF.MILL",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "dMaxWasteLength",
"sSource": "GEN_dMaxWasteLength",
"sMinUserLevel": "5"
},
{
"sName": "dMaxWasteVolume",
"sSource": "GEN_dMaxWasteVolume",
"sMinUserLevel": "5"
},
{
"sName": "bReduceBladePath",
"sSource": "GEN_bReduceBladePath",
"sMinUserLevel": "5"
}
]
}
+518
View File
@@ -0,0 +1,518 @@
-- Strategia: STR0007
-- Descrizione
-- Mortasa a coda di rondine e mortasa frontale a coda di rondine
-- Feature: 55/56,0
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
local PreSimulationLib = require( 'PreSimulationLib')
-- strategie di base
local BladeToWaste = require('BLADETOWASTE')
-- Tabella per definizione modulo
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 = {}
Machining.Milling = {}
Machining.Cutting = {}
Machining.Pocketing = {}
local Result = {}
Result.Milling = {}
Result.Cutting = {}
Result.Pocketing = {}
local ToolSearchParameters = {}
-- in caso sia una mortasa frontale, bisogna lavorare il taglio
if Proc.FeatureInfo.bIsFrontMortise then
-- scelta automatica lavorazione. Non viene mai scelta la motosega
if Strategy.Parameters.sCuttingStrategy == 'AUTO' then
-- creo piano di taglio sulla testa del tenone
local OptionalParameters = { dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume,
dMaxWasteLength = Strategy.Parameters.dMaxWasteLength,
bReduceBladePath = Strategy.Parameters.bReduceBladePath
}
Machining.Cutting, Result.Cutting = BladeToWaste.Make( Strategy.idMortiseCutPlane, Part, OptionalParameters)
-- se presente almeno una lavorazione e completo, il taglio è applicabile
if #Machining.Cutting > 0 and Result.Cutting and Result.Cutting.sStatus == 'Completed' then
Machining.Cutting.bIsApplicable = true
end
-- se non possibile di lama si prova con fresa
if not Machining.Cutting or Result.Cutting.sStatus ~= 'Completed' then
Machining.bCuttingWithMill = true
end
-- lavorazione forzata con utensile lama
elseif Strategy.Parameters.sCuttingStrategy == 'BLADE_FORCED' then
local OptionalParameters = { dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume,
dMaxWasteLength = Strategy.Parameters.dMaxWasteLength,
bReduceBladePath = Strategy.Parameters.bReduceBladePath
}
Machining.Cutting, Result.Cutting = BladeToWaste.Make( Strategy.idMortiseCutPlane, Part, OptionalParameters)
-- se presente almeno una lavorazione e completo, il taglio è applicabile
if #Machining.Cutting > 0 and Result.Cutting.sStatus == 'Completed' then
Machining.Cutting.bIsApplicable = true
else
Machining.Cutting.bIsApplicable = false
end
-- lavorazione forzata con utensile fresa
elseif Strategy.Parameters.sCuttingStrategy == 'MILL_FORCED' then
Machining.bCuttingWithMill = true
-- lavorazione forzata con utensile motosega
elseif Strategy.Parameters.sCuttingStrategy == 'CHAINSAW_FORCED' then
-- DA FARE!!
end
-- === ricerca utensile per svuotare taglio iniziale, se taglio non possibile ===
if Machining.bCuttingWithMill and ( not( Proc.AffectedFaces.bLeft) or Strategy.bCanMoveAfterSplit) then
ToolSearchParameters = {}
ToolSearchParameters.dElevation = 0
ToolSearchParameters.vtToolDirection = Proc.FeatureInfo.vtMortiseN
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sPocketingList, 'Pocketing')
Machining.Cutting.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
if Machining.Cutting.ToolInfo.nToolIndex then
Machining.Cutting.bIsApplicable = true
local ParametersMRR = {}
ParametersMRR.nToolIndex = Machining.Cutting.ToolInfo.nToolIndex
Result.Cutting.dMRR = MachiningLib.GetToolMRR( ParametersMRR)
Result.Cutting.sStatus = 'Completed'
end
end
end
-- === ricerca utensile per lavorare mortasa coda di rondine ===
Machining.Milling.bIsApplicable = false
-- se mortasa in testa oppure se di coda ma è possibile lavorare dopo separazione
if not( Proc.AffectedFaces.bLeft) or Strategy.bCanMoveAfterSplit then
ToolSearchParameters.dElevation = Proc.FeatureInfo.dMortiseDepth
ToolSearchParameters.vtToolDirection = Proc.FeatureInfo.vtMortiseN
ToolSearchParameters.sMillShape = 'DOVETAIL'
Machining.Milling.ToolInfo = {}
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sMillingList, 'Milling')
Machining.Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
if Machining.Milling.ToolInfo.nToolIndex then
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 > 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
Machining.Milling.dRealSideStep = ( ( Proc.FeatureInfo.dMortiseMaxDist / 2) - dToolDiam) / (Machining.nMillingPathsNeeded - 1)
else
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)
-- l'utensile a coda di rondine deve per forza riuscire a lavorare tutto, altrimenti errore
if Machining.Milling.ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then
Result.Milling.sStatus = 'Completed'
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
return Machining, Result
end
-------------------------------------------------------------------------------------------------------------
local function GetFeatureRotationIndex( Proc)
local nVoteIndex
-- se fatto con testa sopra
if TOOLS[Strategy.Machining.Milling.ToolInfo.nToolIndex].SetupInfo.HeadType.bTop then
if Proc.FeatureInfo.vtMortiseN:getZ() < 0 then
nVoteIndex = 2
elseif Proc.FeatureInfo.vtMortiseN:getZ() > abs( Proc.FeatureInfo.vtMortiseN:getY()) then
nVoteIndex = 4
else
nVoteIndex = 3
end
-- se fatto con testa sotto
elseif TOOLS[Strategy.Machining.Milling.ToolInfo.nToolIndex].SetupInfo.HeadType.bBottom then
if Proc.FeatureInfo.vtMortiseN:getZ() > 0 then
nVoteIndex = 2
elseif Proc.FeatureInfo.vtMortiseN:getZ() < - abs( Proc.FeatureInfo.vtMortiseN:getY()) then
nVoteIndex = 4
else
nVoteIndex = 3
end
end
return nVoteIndex
end
-------------------------------------------------------------------------------------------------------------
-- TODO vedere se leggere direttamente la quality dell'utensile e mediarle nel caso di utensile doppio
function GetMortiseMachiningResult( Proc, Result)
local TotalResult = {}
-- setto il risultato in base agli utensili trovati
-- lavorazione mortasa frontale completa
if Strategy.Machining.Milling.bIsApplicable and Strategy.Machining.Cutting.bIsApplicable and Proc.FeatureInfo.bIsFrontMortise then
TotalResult.sStatus = Result.Milling.sStatus
TotalResult.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
TotalResult.dMRR = ( Result.Milling.dMRR + Result.Cutting.dMRR) / 2
local sQuality
if not Strategy.Machining.bCuttingWithMill and Strategy.Machining.AntiSplint.bIsApplicable then
sQuality = 'BEST'
elseif Strategy.Machining.AntiSplint.bIsApplicable then
sQuality = 'FINE'
else
sQuality = 'STD'
end
TotalResult.dQuality = FeatureLib.GetStrategyQuality( sQuality)
TotalResult.nFeatureRotationIndex = GetFeatureRotationIndex( Proc)
TotalResult.sInfo = ''
-- lavorazione mortasa completa
elseif Strategy.Machining.Milling.bIsApplicable and not( Proc.FeatureInfo.bIsFrontMortise) then
TotalResult.sStatus = Result.Milling.sStatus
TotalResult.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
TotalResult.dMRR = Result.Milling.dMRR
local sQuality = EgtIf( Strategy.Machining.AntiSplint.bIsApplicable, 'BEST', 'STD')
TotalResult.dQuality = FeatureLib.GetStrategyQuality( sQuality)
TotalResult.nFeatureRotationIndex = GetFeatureRotationIndex( Proc)
TotalResult.sInfo = ''
-- lavorazione incompleta
elseif Strategy.Machining.Cutting.bIsApplicable then
TotalResult.sStatus = 'Not-Completed'
TotalResult.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 50)
TotalResult.dMRR = Result.Cutting.dMRR
TotalResult.dQuality = FeatureLib.GetStrategyQuality( EgtIf( Strategy.Machining.bCuttingWithMill, 'MILL', 'SAWBLADE'))
TotalResult.sInfo = 'Mortise not completed'
-- strategia non applicabile, manca il taglio di lama sulla lunghezza del Mortise
else
TotalResult = FeatureLib.GetStrategyResultNotApplicable( 'Error on Mortise cutting')
end
return TotalResult
end
---------------------------------------------------------------------
local function CalcTopPath( nProcId, AuxId, nAddGrpId, dAltMort, dSideAng, b3Solid)
-- copio la curva di base
local NewAuxId = EgtCopyGlob( AuxId, nAddGrpId)
if not NewAuxId then return end
-- ne allungo gli estremi
EgtAddCurveCompoLineTg( NewAuxId, 100, false)
EgtAddCurveCompoLineTg( NewAuxId, 100, true)
EgtMergeCurvesInCurveCompo( NewAuxId)
local dOffset = dAltMort * tan( dSideAng)
if not EgtOffsetCurveAdv( NewAuxId, dOffset) then return end
-- la limito entro la trave
local refBox = Frame3d( b3Solid:getMin())
local vtBoxDiag = b3Solid:getMax() - b3Solid:getMin()
local nCount
NewAuxId, nCount = EgtTrimFlatCurveWithBox( NewAuxId, refBox, vtBoxDiag, true, true, GDB_RT.GLOB)
-- eseguo traslazione e offset per portarla sul top
local vtMove = EgtCurveExtrusion( AuxId, GDB_RT.GLOB) * ( dAltMort - 10 * GEO.EPS_SMALL)
EgtMove( NewAuxId, vtMove, GDB_RT.GLOB)
-- se divisa in più parti, le unisco congiungendole con segmenti
if nCount > 1 then
if EgtGetType( NewAuxId) ~= GDB_TY.CRV_COMPO then
NewAuxId = EgtCurveCompo( nAddGrpId, NewAuxId)
end
for i = 2, nCount do
local CrvId = NewAuxId + i - 1
local ptStart = EgtSP( CrvId)
EgtAddCurveCompoLine( NewAuxId, ptStart)
EgtAddCurveCompoCurve( NewAuxId, CrvId)
end
end
return NewAuxId
end
-------------------------------------------------------------------------------------------------------------
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[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
if nAuxId1 then
-- creo percorso sulla parte alta della mortasa
local dToolRadDelta = Proc.FeatureInfo.dMortiseDepth * tan( dSideAng)
local dTopDiam = dToolDiam + 2 * dToolRadDelta
-- recupero punto iniziale e finale del percorso
local ptStart = EgtSP( nAuxId1, GDB_RT.GLOB)
local ptEnd = EgtEP( nAuxId1, GDB_RT.GLOB)
if ptStart and ptEnd then
local nId1
-- direzione del segmento
local vtDir = ptEnd - ptStart ;
local dLen = vtDir:len()
vtDir:normalize()
-- direzioni tangenti iniziale e finale
local vtStart = EgtSV( nAuxId1, GDB_RT.GLOB)
local vtEnd = EgtEV( nAuxId1, GDB_RT.GLOB)
-- angoli
local dAngStart = acos( vtStart * vtDir)
local dAngEnd = acos( vtEnd * vtDir)
local dMaxAng = min( 30, dAngStart, dAngEnd)
if dLen < dTopDiam then
dMaxAng = min( dMaxAng, asin( dLen / dTopDiam))
end
local vtTg = vtDir ; vtTg:rotate( vtExtr, -dMaxAng)
-- creo l'arco
nId1 = EgtArc2PV( nAddGrpId, ptStart, ptEnd, vtTg, GDB_RT.GLOB)
if not nId1 then
local sErr = 'Wrong geometry : Error on DtMortise '
EgtOutLog( sErr)
return AntiSplint
end
EgtModifyCurveExtrusion( nId1, vtExtr, GDB_RT.GLOB)
AntiSplint.nToolIndex = ToolInfo.nToolIndex
AntiSplint.nType = MCH_MY.MILLING
AntiSplint.vtToolDirection = Proc.FeatureInfo.vtMortiseN
-- LeadIn / LeadOut
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
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
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
else
local sErr = 'Wrong geometry : Error on DtMortise ' .. tostring( Proc.id)
EgtOutLog( sErr)
end
else
local sErr = 'Wrong geometry : Error on DtMortise ' .. tostring( Proc.id)
EgtOutLog( sErr)
end
end
return AntiSplint
end
-------------------------------------------------------------------------------------------------------------
function STR0007.Make( bAddMachining, Proc, Part, CustomParameters)
-- carico parametri de default e li aggiorno con quelli passati dal chiamante (potrebbero non essere congruenti)
local StrategyLib = {}
StrategyLib.Config = STRATEGIES_CONFIG[CustomParameters.sStrategyId]
Strategy.sName = StrategyLib.Config.sStrategyId
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( Proc, Part, CustomParameters, StrategyLib.Config)
Strategy.Machining = {}
Strategy.Result = {}
local bAreAllMachiningsAdded = true
local Results = {}
-- controllo conformità offset mortasa
Strategy.Parameters.dOverMatOnRadius = EgtClamp( Strategy.Parameters.dOverMatOnRadius, -5, 5)
Strategy.Parameters.dOverMatOnLength = EgtClamp( Strategy.Parameters.dOverMatOnLength, -2, 2)
-- calcolo se la lavorazione della mortasa può essere spostata dopo taglio di coda
local dLengthOnX = Proc.b3Box:getDimX()
Strategy.bCanMoveAfterSplit = MachiningLib.CanMoveAfterSplitcut( dLengthOnX, Part)
-- se mortasa frontale, verifico che esista faccia di taglio
if Proc.FeatureInfo.bIsFrontMortise then
-- verifico esista la faccia di taglio
local ptCutC, vtCutN = EgtSurfTmFacetCenter( Proc.id, 1, GDB_ID.ROOT)
if ptCutC and vtCutN and AreSameVectorApprox( Proc.FeatureInfo.vtMortiseN, vtCutN) then
-- recupero gruppo per geometria addizionale
local nAddGrpId = BeamLib.GetAddGroup( Part.id)
Strategy.idMortiseCutPlane = EgtSurfTmPlaneInBBox( nAddGrpId, ptCutC, vtCutN, Part.b3Part, GDB_RT.GLOB)
end
end
Strategy.Machining, Results = GetMortiseStrategy( Proc, Part)
Strategy.Result = GetMortiseMachiningResult( Proc, Results)
-- applicazione delle lavorazioni
if bAddMachining and Strategy.Result.sStatus ~= 'Not-Applicable' then
-- taglio in lunghezza sul tenone
if Strategy.Machining.Cutting.bIsApplicable then
OptionalParameters = {}
-- se cutting da fare come svuotatura
if Strategy.Machining.bCuttingWithMill then
Strategy.Machining.Cutting.Steps = {}
Strategy.Machining.Cutting.LeadIn = {}
Strategy.Machining.Cutting.nType = MCH_MY.POCKETING
Strategy.Machining.Cutting.nSubType = MCH_POCK_SUB.SPIRALIN
Strategy.Machining.Cutting.LeadIn.nType = MCH_POCK_LI.ZIGZAG
Strategy.Machining.Cutting.Steps.dStep = TOOLS[Strategy.Machining.Cutting.ToolInfo.nToolIndex].dStep
Strategy.Machining.Cutting.Steps.dSideStep = TOOLS[Strategy.Machining.Cutting.ToolInfo.nToolIndex].dSideStep
Strategy.Machining.Cutting.nToolIndex = Strategy.Machining.Cutting.ToolInfo.nToolIndex
Strategy.Machining.Cutting.LeadIn.dTangentDistance = TOOLS[Strategy.Machining.Cutting.ToolInfo.nToolIndex].dDiameter/2
Strategy.Machining.Cutting.LeadIn.dElevation = TOOLS[Strategy.Machining.Cutting.ToolInfo.nToolIndex].dDiameter/2
Strategy.Machining.Cutting.sDepth = 0
Strategy.Machining.Cutting.Geometry = {{ Strategy.idMortiseCutPlane, 0}}
Strategy.Machining.Cutting.vtToolDirection = Proc.FeatureInfo.vtMortiseN
if Proc.AffectedFaces.bLeft and Strategy.bCanMoveAfterSplit then
Strategy.Machining.Cutting.sStage = 'AfterTail'
end
bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, Strategy.Machining.Cutting)
-- taglio di lama
else
for i = 1, #Strategy.Machining.Cutting do
if Strategy.Machining.Cutting.bIsApplicable then
if Proc.AffectedFaces.bLeft and Strategy.bCanMoveAfterSplit then
Strategy.Machining.Cutting[i].sStage = 'AfterTail'
end
local bIsMachiningAdded = MachiningLib.AddMachinings( Proc, Strategy.Machining.Cutting[i])
if not bIsMachiningAdded then
bAreAllMachiningsAdded = false
end
end
end
end
end
-- se richiesta passata antischeggia
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
-- 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
-- aggiunge lavorazione
bAreAllMachiningsAdded = bAreAllMachiningsAdded and MachiningLib.AddMachinings( Proc, Strategy.Machining.Milling, Strategy.Machining.Milling.AuxiliaryData)
end
end
end
return bAreAllMachiningsAdded, Strategy.Result
end
-------------------------------------------------------------------------------------------------------------
return STR0007
+98
View File
@@ -0,0 +1,98 @@
{
"sStrategyId": "STR0008",
"sStrategyName": "Mortise",
"ParameterList" : [
{
"sName": "dOverMatOnLength",
"sNameNge": "OVM_LENGTH",
"sValue": "0",
"sDescriptionShort": "Overmaterial on mortise length",
"sDescriptionLong": "",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "dOverMatOnRadius",
"sNameNge": "OVM_RADIUS",
"sValue": "0",
"sDescriptionShort": "Overmaterial on mortise width",
"sDescriptionLong": "",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "sCuttingStrategy",
"sNameNge": "EXEC_TENON_SURF",
"sValue": "AUTO",
"sDescriptionShort": "Cutting Strategy",
"sDescriptionLong": "",
"sType": "combo",
"sMinUserLevel": "1",
"Choices": [
{
"sValue": "AUTO",
"sDescriptionShort": "Automatic",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "BLADE_FORCED",
"sDescriptionShort": "Blade only",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "MILL_FORCED",
"sDescriptionShort": "Mill only",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "CHAINSAW_FORCED",
"sDescriptionShort": "ChainSaw only",
"sDescriptionLong": "",
"sMessageId": ""
}
]
},
{
"sName": "sPocketingList",
"sNameNge": "POCK_MORTISE_SURF_LIST",
"sValue": "",
"sDescriptionShort": "Available mill to machine the mortise cut surface",
"sDescriptionLong": "",
"sType": "tool",
"sSubType": "MCH_TF.MILL",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "sMillingList",
"sNameNge": "MORTISE_TOOL_LIST",
"sValue": "",
"sDescriptionShort": "Available mill to machine the mortise",
"sDescriptionLong": "",
"sType": "tool",
"sSubType": "MCH_TF.MILL",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "dMaxWasteLength",
"sSource": "GEN_dMaxWasteLength",
"sMinUserLevel": "5"
},
{
"sName": "dMaxWasteVolume",
"sSource": "GEN_dMaxWasteVolume",
"sMinUserLevel": "5"
},
{
"sName": "bReduceBladePath",
"sSource": "GEN_bReduceBladePath",
"sMinUserLevel": "5"
}
]
}
+353
View File
@@ -0,0 +1,353 @@
-- Strategia: STR0008
-- Descrizione
-- Svuotatura tasca
-- Feature tipo Mortise (con raggio)
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
-- strategie di base
local BladeToWaste = require('BLADETOWASTE')
-- Tabella per definizione modulo
local STR0008 = {}
local Strategy = {}
-------------------------------------------------------------------------------------------------------------
local function IsTopologyOk( Proc)
if Proc.Topology.sName == 'Pocket-Round' or
Proc.Topology.sName == 'Pocket-Round-Through' or
Proc.Topology.sName == 'Pocket-Round-Front' then
return true
else
return false
end
end
-------------------------------------------------------------------------------------------------------------
-- TODO vedere se leggere direttamente la quality dell'utensile e mediarle nel caso di utensile doppio
local function GetBestPocketingStrategy( Proc, Part)
local Machining = { Cutting = {}, Pocketing = {}}
local Result = { Cutting = {}, Pocketing = {}}
local ToolSearchParameters = {}
Machining.sTypeMachining = 'None' -- Bottom\ Side1\ Side2\ Side1-Side2\ None
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'MILL')
-- in caso sia una mortasa frontale, bisogna lavorare il taglio
if Proc.FeatureInfo.bIsFrontMortise then
-- scelta automatica lavorazione. Non viene mai scelta la motosega
if Strategy.Parameters.sCuttingStrategy == 'AUTO' then
-- creo piano di taglio sulla testa del tenone
local OptionalParameters = { dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume,
dMaxWasteLength = Strategy.Parameters.dMaxWasteLength,
bReduceBladePath = Strategy.Parameters.bReduceBladePath
}
Machining.Cutting, Result.Cutting = BladeToWaste.Make( Strategy.idMortiseCutPlane, Part, OptionalParameters)
-- se presente almeno una lavorazione e completo, il taglio è applicabile
if #Machining.Cutting > 0 and Result.Cutting and Result.Cutting.sStatus == 'Completed' then
Machining.Cutting.bIsApplicable = true
end
-- se non possibile di lama si prova con fresa
if not Machining.Cutting or #Machining.Cutting == 0 then
Machining.bCuttingWithMill = true
end
-- lavorazione forzata con utensile lama
elseif Strategy.Parameters.sCuttingStrategy == 'BLADE_FORCED' then
local OptionalParameters = { dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume,
dMaxWasteLength = Strategy.Parameters.dMaxWasteLength,
bReduceBladePath = Strategy.Parameters.bReduceBladePath
}
Machining.Cutting, Result.Cutting = BladeToWaste.Make( Strategy.idMortiseCutPlane, Part, OptionalParameters)
-- se presente almeno una lavorazione e completo, il taglio è applicabile
if #Machining.Cutting > 0 and Result.Cutting.sStatus == 'Completed' then
Machining.Cutting.bIsApplicable = true
else
Machining.Cutting.bIsApplicable = false
end
-- lavorazione forzata con utensile fresa
elseif Strategy.Parameters.sCuttingStrategy == 'MILL_FORCED' then
Machining.bCuttingWithMill = true
-- lavorazione forzata con utensile motosega
elseif Strategy.Parameters.sCuttingStrategy == 'CHAINSAW_FORCED' then
-- DA FARE!!
end
-- === ricerca utensile per svuotare taglio iniziale, se taglio non possibile ===
if Machining.bCuttingWithMill then
-- se può essere fatto di fresa
if not( Proc.AffectedFaces.bLeft) or Strategy.bCanMoveAfterSplit then
ToolSearchParameters = {}
ToolSearchParameters.dElevation = 0
ToolSearchParameters.vtToolDirection = Proc.FeatureInfo.vtMortiseN
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sPocketingList, 'Pocketing')
ToolSearchParameters.sMillShape = 'STANDARD'
Machining.Cutting.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
if Machining.Cutting.ToolInfo.nToolIndex then
Machining.Cutting.bIsApplicable = true
local ParametersMRR = {}
ParametersMRR.nToolIndex = Machining.Cutting.ToolInfo.nToolIndex
Strategy.Result.dMRR = MachiningLib.GetToolMRR( ParametersMRR)
Strategy.Result.sStatus = 'Completed'
end
-- alterimenti esco subito
else
Strategy.Result.sStatus = 'Not-Applicable'
Strategy.Result.dCompletionIndex = 0
Strategy.Result.dMRR = 0
Strategy.Result.dQuality = 0
Strategy.Result.sInfo = 'Mill not found'
return Machining
end
end
end
-- ===== RICERCA UTENSILE =====
-- cerco utensile per lavorare faccia Bottom
local Milling = {}
Milling.bIsApplicable = false
ToolSearchParameters = {}
ToolSearchParameters.sMillShape = 'STANDARD'
ToolSearchParameters.dMaxToolDiameter = Proc.FeatureInfo.dMortiseMinRadius * 2
ToolSearchParameters.dElevation = Proc.FeatureInfo.dMortiseDepth + EgtIf( Proc.Topology.sName == 'Pocket-Round-Through', BeamData.CUT_EXTRA, 0)
ToolSearchParameters.vtToolDirection = Proc.FeatureInfo.vtMortiseN
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sMillingList, 'Pocketing')
Milling.ToolInfo = {}
-- si cerca prima utensile per lavorare in accordo con normale mortasa
Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
Milling.idFaceToMachine = 0 -- ATTENZIONE: Per convenzione, la faccia di fondo della mortasa ha sempre indice 0
Milling.idProc = Proc.id
Milling.vtFaceNormal = Proc.FeatureInfo.vtMortiseN
Milling.dElevation = Proc.FeatureInfo.dMortiseDepth
if Milling.ToolInfo.nToolIndex then
Milling.bIsApplicable = true
end
table.insert( Machining.Pocketing, Milling)
-- si cerca utensile che lavora dal lato opposto
Milling = {}
Milling.bIsApplicable = false
if Proc.Topology.sName == 'Pocket-Round-Through' then
ToolSearchParameters = {}
ToolSearchParameters.sMillShape = 'STANDARD'
ToolSearchParameters.dMaxToolDiameter = Proc.FeatureInfo.dMortiseMinRadius * 2
ToolSearchParameters.dElevation = Proc.FeatureInfo.dMortiseDepth + BeamData.CUT_EXTRA
ToolSearchParameters.vtToolDirection = -Proc.FeatureInfo.vtMortiseN
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sMillingList, 'Pocketing')
Milling.ToolInfo = {}
-- si cerca prima utensile per lavorare in accordo con normale mortasa
Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
Milling.idFaceToMachine = 0 -- ATTENZIONE: Per convenzione, la faccia di fondo della mortasa ha sempre indice 0
Milling.idProc = Proc.id
Milling.vtFaceNormal = -Proc.FeatureInfo.vtMortiseN
Milling.bToolInvert = true
Milling.dElevation = Proc.FeatureInfo.dMortiseDepth
if Milling.ToolInfo.nToolIndex then
Milling.bIsApplicable = true
end
end
table.insert( Machining.Pocketing, Milling)
-- tipo di lavorazione
-- solo svuotatura diretta come normale mortasa, completa
if Machining.Pocketing[1].bIsApplicable and Machining.Pocketing[1].ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then
if Proc.Topology.sName == 'Pocket-Round-Through' then
Machining.sTypeMachining = 'Side1'
Machining.Pocketing[1].sDepth = BeamData.CUT_EXTRA
else
Machining.sTypeMachining = 'Bottom'
Machining.Pocketing[1].sDepth = -Strategy.Parameters.dOverMatOnLength
end
Strategy.Result.dMRR = MachiningLib.GetToolMRR( Machining.Pocketing[1].ToolInfo)
Machining.dResidual = 0
Machining.Pocketing[2].bIsApplicable = false
-- solo svuotatura diretta opposta alla normale mortasa, completa
elseif Machining.Pocketing[2].bIsApplicable and Machining.Pocketing[2].ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then
Machining.sTypeMachining = 'Side2'
Machining.dResidual = 0
Machining.Pocketing[2].sDepth = Proc.FeatureInfo.dMortiseDepth + BeamData.CUT_EXTRA
Strategy.Result.dMRR = MachiningLib.GetToolMRR( Machining.Pocketing[2].ToolInfo)
Machining.Pocketing[1].bIsApplicable = false
-- solo svuotatura diretta come normale mortasa, incompleta
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 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
Strategy.Result.dMRR = MachiningLib.GetToolMRR( Machining.Pocketing[2].ToolInfo)
-- lavorazione da entrambi i lati
elseif Machining.Pocketing[1].bIsApplicable and Machining.Pocketing[2].bIsApplicable then
Machining.sTypeMachining = 'Side1-Side2'
local dResidualMach = Machining.Pocketing[1].ToolInfo.dResidualDepth + Machining.Pocketing[2].ToolInfo.dResidualDepth - Proc.FeatureInfo.dMortiseDepth
Machining.dResidual = max( 0, dResidualMach)
-- se lavorazione non copmpleta, si entra il massimio possibile
if dResidualMach > 0 then
Machining.Pocketing[1].sDepth = -Machining.Pocketing[1].ToolInfo.dResidualDepth
Machining.Pocketing[2].sDepth = Proc.FeatureInfo.dMortiseDepth - Machining.Pocketing[2].ToolInfo.dResidualDepth
else
Machining.Pocketing[1].sDepth = -Machining.Pocketing[1].ToolInfo.dResidualDepth + dResidualMach/2 + BeamData.CUT_EXTRA_MIN
Machining.Pocketing[2].sDepth = Proc.FeatureInfo.dMortiseDepth - ( Machining.Pocketing[2].ToolInfo.dResidualDepth - dResidualMach/2 - BeamData.CUT_EXTRA_MIN)
end
Strategy.Result.dMRR = min( MachiningLib.GetToolMRR( Machining.Pocketing[1].ToolInfo), MachiningLib.GetToolMRR( Machining.Pocketing[2].ToolInfo))
-- altrimenti non applicabile
else
-- TODO per feature frontale, ha senso voler applicare solo il taglio e non la lavorazione della mortasatura? Adesso non fa nulla
Strategy.Result.sStatus = 'Not-Applicable'
Strategy.Result.dCompletionIndex = 0
Strategy.Result.dMRR = 0
Strategy.Result.dQuality = 0
Strategy.Result.sInfo = 'Mill not found'
return Machining
end
-- se completo
if Machining.dResidual < 10 * GEO.EPS_SMALL then
Strategy.Result.sStatus = 'Completed'
Strategy.Result.dCompletionPercentage = 100
else
Strategy.Result.sStatus = 'Not-Completed'
Strategy.Result.sInfo = 'Mortise not complete, left ' .. ceil( Machining.dResidual) .. 'mm'
Strategy.Result.dCompletionPercentage = ( 1 - Machining.dResidual / Proc.FeatureInfo.dMortiseDepth) * 100
end
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( Strategy.Result.dCompletionPercentage)
return Machining
end
-------------------------------------------------------------------------------------------------------------
function STR0008.Make( bAddMachining, Proc, Part, CustomParameters)
-- carico parametri de default e li aggiorno con quelli passati dal chiamante (potrebbero non essere congruenti)
local StrategyLib = {}
StrategyLib.Config = STRATEGIES_CONFIG[CustomParameters.sStrategyId]
Strategy.sName = StrategyLib.Config.sStrategyId
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( Proc, Part, CustomParameters, StrategyLib.Config)
Strategy.Machining = {}
Strategy.Result = {}
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
local bAreAllMachiningsAdded = true
local Pocketing = {}
-- controllo conformità offset mortasa
Strategy.Parameters.dOverMatOnRadius = EgtClamp( Strategy.Parameters.dOverMatOnRadius, -5, 5)
Strategy.Parameters.dOverMatOnLength = EgtClamp( Strategy.Parameters.dOverMatOnLength, -2, 2)
-- calcolo se la lavorazione della mortasa può essere spostata dopo taglio di coda
local dLengthOnX = Proc.b3Box:getDimX()
Strategy.bCanMoveAfterSplit = MachiningLib.CanMoveAfterSplitcut( dLengthOnX, Part)
-- se mortasa frontale, verifico che esista faccia di taglio
if Proc.FeatureInfo.bIsFrontMortise then
-- verifico esista la faccia di taglio
local ptCutC, vtCutN = EgtSurfTmFacetCenter( Proc.id, 1, GDB_ID.ROOT)
if ptCutC and vtCutN and AreSameVectorApprox( Proc.FeatureInfo.vtMortiseN, vtCutN) then
-- recupero gruppo per geometria addizionale
local nAddGrpId = BeamLib.GetAddGroup( Part.id)
Strategy.idMortiseCutPlane = EgtSurfTmPlaneInBBox( nAddGrpId, ptCutC, vtCutN, Part.b3Part, GDB_RT.GLOB)
end
end
Strategy.Machining = GetBestPocketingStrategy( Proc, Part)
if bAddMachining and Strategy.Result.sStatus ~= 'Not-Applicable' then
-- se mortasa frontale si fa taglio di lama
if Proc.FeatureInfo.bIsFrontMortise then
-- taglio in lunghezza sulla faccia frontale
if Strategy.Machining.Cutting.bIsApplicable then
OptionalParameters = {}
-- se cutting da fare come svuotatura
if Strategy.Machining.bCuttingWithMill then
Strategy.Machining.Cutting.Steps = {}
Strategy.Machining.Cutting.LeadIn = {}
Strategy.Machining.Cutting.nType = MCH_MY.POCKETING
Strategy.Machining.Cutting.nSubType = MCH_POCK_SUB.SPIRALIN
Strategy.Machining.Cutting.LeadIn.nType = MCH_POCK_LI.ZIGZAG
Strategy.Machining.Cutting.Steps.dStep = TOOLS[Strategy.Machining.Cutting.ToolInfo.nToolIndex].dStep
Strategy.Machining.Cutting.Steps.dSideStep = TOOLS[Strategy.Machining.Cutting.ToolInfo.nToolIndex].dSideStep
Strategy.Machining.Cutting.nToolIndex = Strategy.Machining.Cutting.ToolInfo.nToolIndex
Strategy.Machining.Cutting.LeadIn.dTangentDistance = TOOLS[Strategy.Machining.Cutting.ToolInfo.nToolIndex].dDiameter/2
Strategy.Machining.Cutting.LeadIn.dElevation = TOOLS[Strategy.Machining.Cutting.ToolInfo.nToolIndex].dDiameter/2
Strategy.Machining.Cutting.sDepth = 0
Strategy.Machining.Cutting.Geometry = {{ Strategy.idMortiseCutPlane, 0}}
Strategy.Machining.Cutting.vtToolDirection = Proc.FeatureInfo.vtMortiseN
if Proc.AffectedFaces.bLeft and Strategy.bCanMoveAfterSplit then
Strategy.Machining.Cutting.sStage = 'AfterTail'
end
bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, Strategy.Machining.Cutting)
-- taglio di lama
else
for i = 1, #Strategy.Machining.Cutting do
if Strategy.Machining.Cutting.bIsApplicable then
if Proc.AffectedFaces.bLeft and Strategy.bCanMoveAfterSplit then
Strategy.Machining.Cutting[i].sStage = 'AfterTail'
end
local bIsMachiningAdded = MachiningLib.AddMachinings( Proc, Strategy.Machining.Cutting[i])
if not bIsMachiningAdded then
bAreAllMachiningsAdded = false
end
end
end
end
end
end
-- si applicano le lavorazioni di svuotatura
for i = 1, #Strategy.Machining.Pocketing do
if Strategy.Machining.Pocketing[i].bIsApplicable then
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
Pocketing.Steps.dSideStep = TOOLS[Strategy.Machining.Pocketing[i].ToolInfo.nToolIndex].dSideStep
Pocketing.nToolIndex = Strategy.Machining.Pocketing[i].ToolInfo.nToolIndex
Pocketing.LeadIn.dTangentDistance = TOOLS[Strategy.Machining.Pocketing[i].ToolInfo.nToolIndex].dDiameter/2
Pocketing.LeadIn.dElevation = TOOLS[Strategy.Machining.Pocketing[i].ToolInfo.nToolIndex].dDiameter/2
Pocketing.sDepth = Strategy.Machining.Pocketing[i].sDepth
Pocketing.dRadialOffset = Strategy.Parameters.dOverMatOnRadius
Pocketing.bToolInvert = Strategy.Machining.Pocketing[i].bToolInvert
if Proc.FeatureInfo.bIsFrontMortise then
Pocketing.dMaxElev = Proc.FeatureInfo.dMortiseDepth
end
-- se feature passante, si applica la lavorazione alla curva
if Proc.Topology.sName == 'Pocket-Round-Through' then
Pocketing.Geometry = {{ Proc.FeatureInfo.idAddAuxGeom, -1}}
else
Pocketing.Geometry = {{ Strategy.Machining.Pocketing[i].idProc, Strategy.Machining.Pocketing[i].idFaceToMachine}}
end
Pocketing.vtToolDirection = Strategy.Machining.Pocketing[i].vtFaceNormal
-- se è aperta sulla coda, dico che deve essere fatta dopo la separazione
if Proc.AffectedFaces.bLeft then
Pocketing.sStage = 'AfterTail'
end
bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, Pocketing)
end
end
else
bAreAllMachiningsAdded = false
end
return bAreAllMachiningsAdded, Strategy.Result
end
-------------------------------------------------------------------------------------------------------------
return STR0008
+37
View File
@@ -0,0 +1,37 @@
{
"sStrategyId": "STR0009",
"sStrategyName": "ScarfJoint",
"ParameterList" : [
{
"sName": "dDepthChamfer",
"sNameNge": "DEPTH_CHAMFER",
"sValue": "0",
"sDescriptionShort": "Depth Chamfer",
"sDescriptionLong": "Depth of the V-Mill to execute chamfers on cut-edges",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "bAntiSplint",
"sNameNge": "ANTISPLINT",
"sValue": "false",
"sDescriptionShort": "Use Anti-Splint strategy",
"sDescriptionLong": "The strategy will apply blade cuts on corner to avoid wood splint",
"sType": "b",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "sMillingList",
"sNameNge": "PROFILE_TOOL_LIST",
"sValue": "",
"sDescriptionShort": "Available mill to machine the profile",
"sDescriptionLong": "",
"sType": "tool",
"sSubType": "MCH_TF.MILL",
"sMessageId": " ",
"sMinUserLevel": "1"
}
]
}
+233
View File
@@ -0,0 +1,233 @@
-- Strategia: STR0009
-- Descrizione
-- Feature tipo ScarfJoint
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
-- strategie di base
local BladeToWaste = require( 'BLADETOWASTE')
local FaceByMill = require( 'FACEBYMILL')
local FaceByBlade = require( 'FACEBYBLADE')
local AntiSplintOnFace = require( 'ANTISPLINTONFACE')
-- Tabella per definizione modulo
local STR0009 = {}
local Strategy = {}
-------------------------------------------------------------------------------------------------------------
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
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)
Result = FeatureLib.GetStrategyResultNotApplicable( sErr)
else
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
Result.dQuality = FeatureLib.GetStrategyQuality( 'STD')
end
-- altrimenti non completa
else
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
-- creo una tabella unica contenente tutte le lavorazioni
local Machinings = {}
EgtJoinTables( Machinings, Cutting.Machinings)
EgtJoinTables( Machinings, AntiSplints)
EgtJoinTables( Machinings, Pocketing)
return Machinings, Result
end
-------------------------------------------------------------------------------------------------------------
function STR0009.Make( bAddMachining, Proc, Part, CustomParameters)
-- carico parametri de default e li aggiorno con quelli passati dal chiamante (potrebbero non essere congruenti)
local StrategyLib = {}
StrategyLib.Config = STRATEGIES_CONFIG[CustomParameters.sStrategyId]
Strategy.sName = StrategyLib.Config.sStrategyId
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( Proc, Part, CustomParameters, StrategyLib.Config)
Strategy.Machinings = {}
Strategy.Result = {}
local bAreAllMachiningsAdded = true
-- 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
Strategy.Machinings, Strategy.Result = GetScarfJointStrategy( Proc, Part)
-- aggiunta lavorazioni
if #Strategy.Machinings > 0 then
if bAddMachining and Strategy.Result.sStatus ~= 'Not-Applicable' then
-- aggiunge lavorazione
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
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable()
end
return bAreAllMachiningsAdded, Strategy.Result
end
-------------------------------------------------------------------------------------------------------------
return STR0009
+75
View File
@@ -0,0 +1,75 @@
{
"sStrategyId": "STR0010",
"sStrategyName": "Milling",
"ParameterList" : [
{
"sName": "bAntiSplintWithBlade",
"sNameNge": "ANTISPLINT_BLADE",
"sValue": "false",
"sDescriptionShort": "Antisplint with blade",
"sDescriptionLong": "Use the blade as antisplint in case the geometry is not through",
"sType": "b",
"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": "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"
},
{
"sName": "sCanDamageNextPiece",
"sNameNge": "DAMAGE_NEXT_PIECE",
"sValue": "NEVER",
"sDescriptionShort": "Damage next piece",
"sDescriptionLong": "This option allows you to decide how to consider the next piece in the bar. The software calculates specifics LeadIn/out to respect the parameter. This parameter may change the machining time",
"sType": "combo",
"sMinUserLevel": "1",
"Choices": [
{
"sValue": "NEVER",
"sDescriptionShort": "Never damage",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "ONLY_IF_RAWPART",
"sDescriptionShort": "Damage only if raw",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "ALWAYS",
"sDescriptionShort": "Can damage",
"sDescriptionLong": "",
"sMessageId": ""
}
]
}
]
}
+431
View File
@@ -0,0 +1,431 @@
-- Strategia: STR0010
-- Descrizione
-- fresatura perpendicolare
-- Feature: cut, longcut, ...
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
-- strategie di base
local FaceByMill = require( 'FACEBYMILL')
local FaceByBlade = require( 'FACEBYBLADE')
local AntiSplintOnFace = require( 'ANTISPLINTONFACE')
-- Tabella per definizione modulo
local STR0010 = {}
local Strategy = {}
-------------------------------------------------------------------------------------------------------------
local function GetStrategyCompletionPercentage( Machinings)
local dCompletionPercentage = 0
local dCompletionPercentageNumerator = 0
local dCompletionPercentageDenominator = 0
local nWeightsCount = 0
for i = 1, #Machinings do
local Machining = Machinings[i]
local dWeight = Machining.dResultWeight
if not dWeight or ( dWeight < 10 * GEO.EPS_SMALL) then
dWeight = 1
else
nWeightsCount = nWeightsCount + 1
end
-- il peso deve essere settato in tutte le lavorazioni o in nessuna
if nWeightsCount ~= 0 and nWeightsCount ~= i then
error( 'GetWeightedCompletionPercentage : inconsistent weights')
end
local dWeightedCompletionPercentage = ( Machining.dCompletionPercentage or 0) / 100 * dWeight
if Machining.bIsApplicable then
dCompletionPercentageNumerator = dCompletionPercentageNumerator + dWeightedCompletionPercentage
end
dCompletionPercentageDenominator = dCompletionPercentageDenominator + dWeight
end
dCompletionPercentage = min( 100 * dCompletionPercentageNumerator / dCompletionPercentageDenominator, 100)
return dCompletionPercentage
end
-------------------------------------------------------------------------------------------------------------
local function CompareEdgesLongestTop( 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 basso
else
if EdgeA.vtN:getZ() > EdgeB.vtN:getZ() + 10 * GEO.EPS_SMALL then
return true
elseif EdgeA.vtN:getZ() < EdgeB.vtN:getZ() - 10 * GEO.EPS_SMALL then
return false
-- se stessa Z si preferiscono i lati verso il fronte della trave
else
if EdgeA.vtN:getY() > EdgeB.vtN:getY() + 10 * GEO.EPS_SMALL then
return true
elseif EdgeA.vtN:getY() < EdgeB.vtN:getY() - 10 * GEO.EPS_SMALL then
return false
else
return false
end
end
end
end
-------------------------------------------------------------------------------------------------------------
local function 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
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' or
Proc.Topology.sName == 'Cut-1-Through' then
return true
else
return false
end
end
-------------------------------------------------------------------------------------------------------------
-- TODO modificare funzione e verificare pinzaggio con regioni e area outline
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
if ( bIsFeatureLong and Proc.b3Box:getDimZ() > Part.dHeight / 2) or ( not bIsFeatureLong and Proc.b3Box:getDimZ() > Part.dHeight / 2) then
return false
end
end
if Proc.AffectedFaces.bBottom then
if ( bIsFeatureLong and Proc.b3Box:getDimY() > Part.dHeight / 2) or ( not bIsFeatureLong and Proc.b3Box:getDimY() > Part.dHeight / 2) then
return false
end
end
-- altrimenti fattibile
return true
end
-------------------------------------------------------------------------------------------------------------
local function GetLongEdgeToMachine( Face, bHeadType)
local Edge = {}
local EdgesSorted = {}
for i = 1, #Face.Edges do
table.insert( EdgesSorted, Face.Edges[i])
end
if bHeadType.bBottom then
table.sort( EdgesSorted, CompareEdgesLongestBottom)
else
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
end
-------------------------------------------------------------------------------------------------------------
local function SortMachiningsBySegment( MachiningA, MachiningB)
if MachiningA.nFeatureSegment > MachiningB.nFeatureSegment then
return false
elseif MachiningB.nFeatureSegment > MachiningA.nFeatureSegment then
return true
-- se segmento uguale, si guarda la priorità
else
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
local bIsOddSegment = ( MachiningA.nFeatureSegment % 2 ~= 0)
if MachiningA.vtToolDirection:getY() < MachiningB.vtToolDirection:getY() - 10 * GEO.EPS_SMALL then
if bIsOddSegment then
return true
else
return false
end
elseif MachiningA.vtToolDirection:getY() > MachiningB.vtToolDirection:getY() + 10 * GEO.EPS_SMALL then
if bIsOddSegment then
return false
else
return true
end
else
return false
end
end
end
end
-------------------------------------------------------------------------------------------------------------
function STR0010.Make( bAddMachining, Proc, Part, CustomParameters)
-- carico parametri da default e li aggiorno con quelli passati dal chiamante (potrebbero non essere congruenti)
local StrategyLib = {}
StrategyLib.Config = STRATEGIES_CONFIG[CustomParameters.sStrategyId]
Strategy.sName = StrategyLib.Config.sStrategyId
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( Proc, Part, CustomParameters, StrategyLib.Config)
Strategy.Machinings = {}
Strategy.Result = {}
local CalculatedMachinings = {}
-- controllo su topologia
if not IsTopologyOk( Proc) then
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( 'Strategy ' .. StrategyLib.Config.sStrategyId .. ' not implemented')
return false, Strategy.Result
end
-- 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 = Proc.dVolume
-- eventuali punti di spezzatura
local FeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
local bIsSplitFeature = false
if #FeatureSplittingPoints > 0 then
bIsSplitFeature = true
end
local dExtendAfterTail = Strategy.Parameters.dExtendAfterTail or max( Part.dDistanceToNextPiece - BeamData.CUT_EXTRA, 0)
if MachiningLib.CanExtendAfterTail( Strategy.Parameters.sCanDamageNextPiece, Part) then
dExtendAfterTail = 10000
end
local bAreAllMachiningsAdded = true
-- 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
-- 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
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
-- 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)
-- 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
Strategy.Result.sStatus = 'Completed'
else
Strategy.Result.sStatus = 'Not-Completed'
end
-- aggiunta lavorazioni
if #Strategy.Machinings > 0 then
if bAddMachining and Strategy.Result.sStatus ~= 'Not-Applicable' then
-- aggiunge lavorazione
for j = 1, #Strategy.Machinings do
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
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable()
end
return bAreAllMachiningsAdded, Strategy.Result
end
-------------------------------------------------------------------------------------------------------------
return STR0010
+66
View File
@@ -0,0 +1,66 @@
{
"sStrategyId": "STR0011",
"sStrategyName": "Hole with Drillbit",
"ParameterList" : [
{
"sName": "dDiameterTolerance",
"sNameNge": "TOLERANCE",
"sValue": "0",
"sDescriptionShort": "Tolerance on Diameter",
"sDescriptionLong": "Tolerance on Diameter",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "dDepthPreHole",
"sNameNge": "DEPTHPREHOLE",
"sValue": "0",
"sDescriptionShort": "Depth PreHole",
"sDescriptionLong": "",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "sDrillingMode",
"sNameNge": "DRILLING_MODE",
"sValue": "AUTO",
"sDescriptionShort": "Drilling Mode",
"sDescriptionLong": "",
"sType": "combo",
"sMinUserLevel": "1",
"Choices": [
{
"sValue": "AUTO",
"sDescriptionShort": "Automatic",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "PREFER_ONE",
"sDescriptionShort": "Preferred machining from one side only",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "FORCE_TWO",
"sDescriptionShort": "Force machining from two sides",
"sDescriptionLong": "",
"sMessageId": ""
}
]
},
{
"sName": "sDrillBitList",
"sNameNge": "DRILL_TOOL_LIST",
"sValue": "",
"sDescriptionShort": "Available Drillbit list",
"sDescriptionLong": "",
"sType": "tool",
"sSubType": "MCH_TF.DRILLBIT",
"sMessageId": " ",
"sMinUserLevel": "1"
}
]
}
+207
View File
@@ -0,0 +1,207 @@
-- Strategia: STR0011
-- Descrizione
-- foratura
-- Feature: foro
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
-- strategie di base
-- Tabella per definizione modulo
local STR0011 = {}
local Strategy = {}
-- TODO Da fare completamente gestione foratura doppia con 2 teste
-------------------------------------------------------------------------------------------------------------
local function GetDrillingStrategy( Proc, Part)
local ToolSearchParameters = {}
local Machining = {}
-- 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.dDiameterTolerance = Strategy.Parameters.dDiameterTolerance
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sDrillBitList, 'Drilling')
ToolSearchParameters.ptCheckOutStroke = { Proc.FeatureInfo.ptDrillCenter + ( ( Proc.FeatureInfo.dDrillLen + EgtMdbGetGeneralParam( MCH_GP.SAFEZ)) * ToolSearchParameters.vtToolDirection)}
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.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
-------------------------------------------------------------------------------------------------------------
function STR0011.Make( bAddMachining, Proc, Part, CustomParameters)
-- carico parametri da default e li aggiorno con quelli passati dal chiamante (potrebbero non essere congruenti)
local StrategyLib = {}
StrategyLib.Config = STRATEGIES_CONFIG[CustomParameters.sStrategyId]
Strategy.sName = StrategyLib.Config.sStrategyId
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( Proc, Part, CustomParameters, StrategyLib.Config)
Strategy.Machinings = {}
Strategy.Result = {}
local bAreAllMachiningsAdded
Strategy.Machinings, Strategy.Result = GetDrillingStrategy( Proc, Part)
if bAddMachining and Strategy.Result.sStatus ~= 'Not-Applicable' then
-- aggiunge lavorazione
for j = 1, #Strategy.Machinings do
Strategy.Machinings[j].nType = MCH_MY.DRILLING
Strategy.Machinings[j].Steps.dStep = TOOLS[Strategy.Machinings[j].ToolInfo.nToolIndex].dStep
bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, Strategy.Machinings[j])
end
end
return bAreAllMachiningsAdded, Strategy.Result
end
-------------------------------------------------------------------------------------------------------------
return STR0011
+89
View File
@@ -0,0 +1,89 @@
{
"sStrategyId": "STR0012",
"sStrategyName": "RidgeLap with Blade",
"ParameterList" : [
{
"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": "sCanDamageNextPiece",
"sNameNge": "DAMAGE_NEXT_PIECE",
"sValue": "NEVER",
"sDescriptionShort": "Damage next piece",
"sDescriptionLong": "This option allows you to decide how to consider the next piece in the bar. The software calculates specifics LeadIn/out to respect the parameter. This parameter may change the machining time",
"sType": "combo",
"sMinUserLevel": "1",
"Choices": [
{
"sValue": "NEVER",
"sDescriptionShort": "Never damage",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "ONLY_IF_RAWPART",
"sDescriptionShort": "Damage only if raw",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "ALWAYS",
"sDescriptionShort": "Can damage",
"sDescriptionLong": "",
"sMessageId": ""
}
]
},
{
"sName": "sRidgelapStrategy",
"sNameNge": "RIDGELAP_STRATEGY",
"sValue": "AUTO",
"sDescriptionShort": "Ridge Lap strategy",
"sDescriptionLong": "",
"sType": "combo",
"sMinUserLevel": "1",
"Choices": [
{
"sValue": "AUTO",
"sDescriptionShort": "Automatic",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "BLADE",
"sDescriptionShort": "Use blade",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "MILL",
"sDescriptionShort": "Use mill",
"sDescriptionLong": "",
"sMessageId": ""
}
]
},
{
"sName": "dMaxWasteLength",
"sSource": "GEN_dMaxWasteLength",
"sMinUserLevel": "5"
},
{
"sName": "dMaxWasteVolume",
"sSource": "GEN_dMaxWasteVolume",
"sMinUserLevel": "5"
},
{
"sName": "bReduceBladePath",
"sSource": "GEN_bReduceBladePath",
"sMinUserLevel": "5"
}
]
}
+200
View File
@@ -0,0 +1,200 @@
-- Strategia: STR0012
-- Descrizione
-- RidgeLap
-- Feature: RidgeLap
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
-- strategie di base
local BladeToWaste = require( 'BLADETOWASTE')
local BladeKeepWaste =require ( 'BLADEKEEPWASTE')
-- Tabella per definizione modulo
local STR0012 = {}
local Strategy = {}
local RidgeLap = {}
RidgeLap.Result = {}
-------------------------------------------------------------------------------------------------------------
-- TODO risolvere problemi calcolo volume nullo se facce rimosse
-- TODO gestire lavorazione con svuotatura
-- TODO risolvere problema ultimo cubetto troppo profondo!!
-- TODO gestire strategia con fresa
function STR0012.Make( bAddMachining, Proc, Part, CustomParameters)
-- carico parametri da default e li aggiorno con quelli passati dal chiamante (potrebbero non essere congruenti)
local StrategyLib = {}
StrategyLib.Config = STRATEGIES_CONFIG[CustomParameters.sStrategyId]
Strategy.sName = StrategyLib.Config.sStrategyId
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( Proc, Part, CustomParameters, StrategyLib.Config)
Strategy.Result = {}
Strategy.Result.sInfo = ''
RidgeLap.Result = {}
local TwoFaces = {}
local AddedFace = {}
TwoFaces.Result = {}
AddedFace.Result = {}
local dTimeToMachine = 0
local dMRRBlade = 0
local dCompletionPercentage = 0
local dQuality = 0
local dMRRBladeAddedFace = 0
local dCompletionPercentageAddedFace = 0
local dQualityAddedFace = 0
local AuxiliaryData = { bIgnoreNotClampableLength = false}
-- gestito solo RidgeLap 3 facce
if Proc.nFct ~= 3 then
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( 'Only RidgeLap 3 faces is applicable')
end
-- estensione oltre la coda
local dExtendAfterTail = Strategy.Parameters.dExtendAfterTail or max( Part.dDistanceToNextPiece - BeamData.CUT_EXTRA, 0)
if MachiningLib.CanExtendAfterTail( Strategy.Parameters.sCanDamageNextPiece, Part) then
dExtendAfterTail = 10000
end
-- separazione della terza faccia
local idAddedTmFace
local nAddedFace
if Proc.AdjacencyMatrix[2][3] < 0 then
nAddedFace = 1 - 1
elseif Proc.AdjacencyMatrix[1][3] < 0 then
nAddedFace = 2 - 1
else
nAddedFace = 3 - 1
end
local OriginalProc = Proc
-- recupero gruppo per geometria addizionale
local nAddGrpId = BeamLib.GetAddGroup( Part.id)
-- se la faccia aggiuntiva non corrisponde al taglio di testa o di coda, si deve lavorare come faccia singola
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: 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
local idNewProc = EgtCopyGlob( Proc.id, nAddGrpId)
EgtSurfTmRemoveFacet( idNewProc, nAddedFace)
local NewProc = FeatureLib.GetProcFromTrimesh( idNewProc, Part, Proc)
NewProc.Topology = FeatureLib.ClassifyTopology( NewProc, Part)
NewProc.NotClampableLength = FeatureLib.CalculateFeatureNotClampableLengths( NewProc, Part)
NewProc.bHindersLaserMeasure = FeatureLib.CalculateFeatureHindersLaserMeasure( NewProc, Part)
-- 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 bFeatureHindersClamping = MachiningLib.IsFeatureHinderingClamping( Proc, Part)
-- lavorazione con codolo
if ( bFeatureHindersClamping and not bDropWaste)
or bKeepWasteAttached then
local BladeKeepWasteResult
local OptionalParameters = { dExtendAfterTail = dExtendAfterTail, dStripWidth = 5, bFinishWithMill = false}
AuxiliaryData.bIgnoreNotClampableLength = true
TwoFaces.Result, BladeKeepWasteResult = BladeKeepWaste.Make( NewProc, Part, OptionalParameters)
dTimeToMachine = BladeKeepWasteResult.dTimeToMachine
dMRRBlade = BladeKeepWasteResult.dMRR
dCompletionPercentage = BladeKeepWasteResult.dCompletionPercentage
dQuality = BladeKeepWasteResult.dQuality
-- lavorazione a cubetti facce concave
else
local BladeToWasteResult
local OptionalParameters = { dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume,
dMaxWasteLength = Strategy.Parameters.dMaxWasteLength,
bSaveAddedGeometries = bAddMachining,
dExtendAfterTail = dExtendAfterTail,
bReduceBladePath = Strategy.Parameters.bReduceBladePath
}
AuxiliaryData.bIgnoreNotClampableLength = false
TwoFaces.Result, BladeToWasteResult = BladeToWaste.Make( NewProc, Part, OptionalParameters)
dTimeToMachine = BladeToWasteResult.dTimeToMachine
dMRRBlade = BladeToWasteResult.dMRR
dCompletionPercentage = BladeToWasteResult.dCompletionPercentage
dQuality = BladeToWasteResult.dQuality
end
-- lavorazione terza faccia
-- TODO da completare
-- TODO va messa per prima????????
if idAddedTmFace then
local BladeToWasteResult
local OptionalParameters = { dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume,
dMaxWasteLength = Strategy.Parameters.dMaxWasteLength,
bSaveAddedGeometries = bAddMachining,
dExtendAfterTail = dExtendAfterTail,
bReduceBladePath = Strategy.Parameters.bReduceBladePath
}
AddedFace.Result, BladeToWasteResult = BladeToWaste.Make( idAddedTmFace, Part, OptionalParameters)
-- TODO calcolo risultati da aggiornare con funzioni nuove
dMRRBladeAddedFace = BladeToWasteResult.dMRR
dCompletionPercentageAddedFace = BladeToWasteResult.dCompletionPercentage
dQualityAddedFace = BladeToWasteResult.dQuality
dTimeToMachine = dTimeToMachine + BladeToWasteResult.dTimeToMachine
-- la faccia aggiuntiva conta per 1/3
dMRRBlade = 2/3 * dMRRBlade + 1/3 * dMRRBladeAddedFace
dCompletionPercentage = 2/3 * dCompletionPercentage + 1/3 * dCompletionPercentageAddedFace
dQuality = 2/3 * dQuality + 1/3 * dQualityAddedFace
end
-- lavorazioni in lista unica
for i = 1, #AddedFace.Result do
table.insert( RidgeLap.Result, AddedFace.Result[i])
end
for i = 1, #TwoFaces.Result do
table.insert( RidgeLap.Result, TwoFaces.Result[i])
end
-- aggiunta lavorazioni
local nIsApplicableCount = 0
local bAreAllMachiningsAdded = true
for i = 1, #RidgeLap.Result do
if RidgeLap.Result[i].bIsApplicable then
nIsApplicableCount = nIsApplicableCount + 1
if bAddMachining then
local bIsMachiningAdded = MachiningLib.AddMachinings( OriginalProc, RidgeLap.Result[i], AuxiliaryData)
if not bIsMachiningAdded then
bAreAllMachiningsAdded = false
end
end
Strategy.Result.sInfo = Strategy.Result.sInfo .. '\n' .. RidgeLap.Result[i].sMessage
end
end
-- TODO migliorare calcolo area lavorata; se ho il codolo ha senso l'incompleta? se incompleta con codolo faccio i cubetti??
-- TODO settare che il codolo restituisce incompleta tranne quando è forzato
if nIsApplicableCount > 0 then
if dCompletionPercentage > 100 - 10 * GEO.EPS_SMALL then
Strategy.Result.sStatus = 'Completed'
else
Strategy.Result.sStatus = 'Not-Completed'
end
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( dCompletionPercentage)
Strategy.Result.dQuality = dQuality
Strategy.Result.dTimeToMachine = dTimeToMachine
Strategy.Result.dMRR = dMRRBlade
else
Strategy.Result.sStatus = 'Not-Applicable'
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable()
end
return bAreAllMachiningsAdded, Strategy.Result
end
-------------------------------------------------------------------------------------------------------------
return STR0012
+76
View File
@@ -0,0 +1,76 @@
{
"sStrategyId": "STR0013",
"sStrategyName": "Hole with Mill",
"ParameterList" : [
{
"sName": "dDiameterTolerance",
"sNameNge": "TOLERANCE",
"sValue": "0",
"sDescriptionShort": "Tolerance on Diameter",
"sDescriptionLong": "Tolerance on Diameter",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "bUseMillAsDrill",
"sNameNge": "DRILLMILL",
"sValue": "0",
"sDescriptionShort": "Use mill as a drillbit",
"sDescriptionLong": "Admit to use the mill as a drillbit",
"sType": "b",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "bOnlyContouring",
"sNameNge": "ONLYCONT",
"sValue": "0",
"sDescriptionShort": "Execute contour only",
"sDescriptionLong": "Execute the contour anyway, even the hole is bigger than the tool diameter",
"sType": "b",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "sDrillingMode",
"sNameNge": "DRILLING_MODE",
"sValue": "AUTO",
"sDescriptionShort": "Drilling mode",
"sDescriptionLong": "",
"sType": "combo",
"sMinUserLevel": "1",
"Choices": [
{
"sValue": "AUTO",
"sDescriptionShort": "Automatic",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "PREFER_ONE",
"sDescriptionShort": "Preferred machining from one side only",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "FORCE_TWO",
"sDescriptionShort": "Force machining from two sides",
"sDescriptionLong": "",
"sMessageId": ""
}
]
},
{
"sName": "sMillList",
"sNameNge": "DRILLPOCK_TOOL_LIST",
"sValue": "",
"sDescriptionShort": "Available mill to machine drills",
"sDescriptionLong": "",
"sType": "tool",
"sSubType": "MCH_TF.MILL",
"sMessageId": " ",
"sMinUserLevel": "1"
}
]
}
+214
View File
@@ -0,0 +1,214 @@
-- Strategia: STR0013
-- Descrizione
-- foratura
-- Feature: foro con fresa
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
-- strategie di base
-- Tabella per definizione modulo
local STR0013 = {}
local Strategy = {}
-------------------------------------------------------------------------------------------------------------
local function GetDrillingWithMillStrategy( Proc, Part)
local ToolSearchParameters = {}
local Machining = {}
local Milling = { ToolInfo = {}}
local Milling2 = { ToolInfo = {}}
-- si cerca fresa con direzione standard
ToolSearchParameters = {}
ToolSearchParameters.dElevation = Proc.FeatureInfo.dDrillLen + BeamData.MILL_OVERLAP
ToolSearchParameters.vtToolDirection = Proc.FeatureInfo.vtDrillExtrusion
ToolSearchParameters.dMaxToolDiameter = Proc.FeatureInfo.dDrillDiam + Strategy.Parameters.dDiameterTolerance
ToolSearchParameters.sType = 'MILL_STD'
ToolSearchParameters.sMillShape = 'STANDARD'
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sMillList, 'Milling')
Milling.vtToolDirection = -Proc.FeatureInfo.vtDrillExtrusion
Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
-- se foro aperto, si cerca anche fresa con direzione invertita
if Proc.FeatureInfo.bIsDrillOpen then
ToolSearchParameters = {}
ToolSearchParameters.dElevation = Proc.FeatureInfo.dDrillLen + BeamData.MILL_OVERLAP
ToolSearchParameters.vtToolDirection = -Proc.FeatureInfo.vtDrillExtrusion
ToolSearchParameters.dMaxToolDiameter = Proc.FeatureInfo.dDrillDiam + Strategy.Parameters.dDiameterTolerance
ToolSearchParameters.sType = 'MILL_STD'
ToolSearchParameters.sMillShape = 'STANDARD'
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sMillList, 'Milling')
Milling2.vtToolDirection = -Proc.FeatureInfo.vtDrillExtrusion
Milling2.bInvert = true
Milling2.bToolInvert = true
Milling2.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
end
local bDouble = false
-- se ho trovato entrambi gli utensili e non è forzato da eseguire solo da un lato e una punta lo fa completo, si fa foratura in doppio
if Milling.ToolInfo.nToolIndex and Milling2.ToolInfo.nToolIndex and
not ( Strategy.Parameters.sDrillingMode == 'PREFER_ONE' and ( Milling.ToolInfo.dResidualDepth < 0 or Milling2.ToolInfo.dResidualDepth < 0)) then
bDouble = true
-- se entrambe le punte lavorano più della metà del foro, si cerca un altro utensile che possa lavorare fino alla metà del foro
-- è possibile che si possa trovare fresa più corta che lavora a sufficienza
if Milling.ToolInfo.dResidualDepth < ( Proc.FeatureInfo.dDrillLen - BeamData.MILL_OVERLAP) / 2 and
Milling2.ToolInfo.dResidualDepth < ( Proc.FeatureInfo.dDrillLen - BeamData.MILL_OVERLAP) / 2 then
ToolSearchParameters = {}
ToolSearchParameters.dElevation = ( Proc.FeatureInfo.dDrillLen + BeamData.MILL_OVERLAP) / 2
ToolSearchParameters.vtToolDirection = Proc.FeatureInfo.vtDrillExtrusion
ToolSearchParameters.dMaxToolDiameter = Proc.FeatureInfo.dDrillDiam + Strategy.Parameters.dDiameterTolerance
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sMillList, 'Milling')
local HalfMilling = {}
HalfMilling.ToolInfo = {}
HalfMilling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
ToolSearchParameters.vtToolDirection = -Proc.FeatureInfo.vtDrillExtrusion
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sMillList, 'Milling')
local HalfMilling2 = {}
HalfMilling2.ToolInfo = {}
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 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
if Milling2.ToolInfo.nToolIndex ~= HalfMilling2.ToolInfo.nToolIndex then
Milling2.ToolInfo.nToolIndex, Milling2.ToolInfo.dResidualDepth = HalfMilling2.ToolInfo.nToolIndex, HalfMilling2.ToolInfo.dResidualDepth
end
end
end
end
local dResidual = Proc.FeatureInfo.dDrillLen
-- aggiunta lavorazioni a lista
-- se foro doppio
if bDouble then
dResidual = Milling.ToolInfo.dResidualDepth + Milling2.ToolInfo.dResidualDepth - Proc.FeatureInfo.dDrillLen
Strategy.Result.dMRR = ( MachiningLib.GetToolMRR( Milling.ToolInfo) + MachiningLib.GetToolMRR( Milling2.ToolInfo)) / 2
local dExtraDrill = ( Proc.FeatureInfo.dDrillLen - BeamData.MILL_OVERLAP - ( Milling.ToolInfo.dResidualDepth + Milling2.ToolInfo.dResidualDepth)) / 2
Milling.sDepth = Proc.FeatureInfo.dDrillLen - Milling.ToolInfo.dResidualDepth - dExtraDrill
table.insert( Machining, Milling)
Milling2.sDepth = Proc.FeatureInfo.dDrillLen - Milling2.ToolInfo.dResidualDepth - dExtraDrill
table.insert( Machining, Milling2)
-- altrimenti singolo
else
local BestMilling
if not Milling.ToolInfo.nToolIndex then
BestMilling = Milling2
elseif not Milling2.ToolInfo.nToolIndex then
BestMilling = Milling
else
if Milling.ToolInfo.dResidualDepth < 0 then
BestMilling = Milling
elseif Milling2.ToolInfo.dResidualDepth < 0 then
BestMilling = Milling2
else
BestMilling = EgtIf( Milling.ToolInfo.dResidualDepth < Milling2.ToolInfo.dResidualDepth, Milling, Milling2)
end
end
if BestMilling.ToolInfo.nToolIndex then
dResidual = BestMilling.ToolInfo.dResidualDepth
if dResidual < 0 then
BestMilling.sDepth = Proc.FeatureInfo.dDrillLen + EgtIf( Proc.FeatureInfo.bIsDrillOpen, BeamData.MILL_OVERLAP, 0)
else
BestMilling.sDepth = Proc.FeatureInfo.dDrillLen - BestMilling.ToolInfo.dResidualDepth
end
Strategy.Result.dMRR = MachiningLib.GetToolMRR( BestMilling.ToolInfo)
table.insert( Machining, BestMilling)
end
end
-- se c'è almeno una lavorazione, si calcola voto
if #Machining > 0 then
if dResidual < 0 then
Strategy.Result.sStatus = 'Completed'
Strategy.Result.dCompletionIndex = 5
Strategy.Result.sInfo = ''
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'MILL')
else
Strategy.Result.sStatus = 'Not-Completed'
local dResidualPrercentage = 100 * ( dResidual / Proc.FeatureInfo.dDrillLen)
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100 - dResidualPrercentage)
Strategy.Result.sInfo = 'Machining not complete, left ' .. tostring( ceil( dResidualPrercentage)) .. '%'
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'MILL')
end
-- se son state trovate frese compatibili
else
local sMessage = 'Mill not found'
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( sMessage)
end
return Machining, Strategy.Result
end
-------------------------------------------------------------------------------------------------------------
function STR0013.Make( bAddMachining, Proc, Part, CustomParameters)
-- carico parametri da default e li aggiorno con quelli passati dal chiamante (potrebbero non essere congruenti)
local StrategyLib = {}
StrategyLib.Config = STRATEGIES_CONFIG[CustomParameters.sStrategyId]
Strategy.sName = StrategyLib.Config.sStrategyId
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( Proc, Part, CustomParameters, StrategyLib.Config)
Strategy.Machinings = {}
Strategy.Result = {}
local bAreAllMachiningsAdded
Strategy.Machinings, Strategy.Result = GetDrillingWithMillStrategy( Proc, Part)
if bAddMachining and Strategy.Result.sStatus ~= 'Not-Applicable' then
-- aggiunge lavorazione
for j = 1, #Strategy.Machinings do
local MachiningToAdd
local nIndexTool = Strategy.Machinings[j].ToolInfo.nToolIndex
-- se diametro fresa differisce al massimo della tolleranza si fa foratura con fresa (se ammesso)
if abs( TOOLS[nIndexTool].dDiameter - Proc.FeatureInfo.dDrillDiam) < Strategy.Parameters.dDiameterTolerance and Strategy.Parameters.bUseMillAsDrill then
MachiningToAdd = MachiningLib.InitMachiningParameters( MCH_MY.DRILLING)
MachiningToAdd = BeamLib.MergeTables( MachiningToAdd, Strategy.Machinings[j])
MachiningToAdd.Steps.dStep = TOOLS[nIndexTool].dStep / 3
-- se diametro foro più grande della fresa, ma non oltre il doppio del diametro, si fa contornatura a spirale
elseif Proc.FeatureInfo.dDrillDiam < ( TOOLS[nIndexTool].dDiameter * 0.75) * 2 or Strategy.Parameters.bOnlyContouring then
MachiningToAdd = MachiningLib.InitMachiningParameters( MCH_MY.MILLING)
MachiningToAdd = BeamLib.MergeTables( MachiningToAdd, Strategy.Machinings[j])
-- il diametro deve essere almeno 1mm più grande del foro, altrimenti la macchina non riesce ad interpolare
MachiningToAdd.dRadialOffset = min( 0, Proc.FeatureInfo.dDrillDiam - ( TOOLS[nIndexTool].dDiameter + 1))
MachiningToAdd.Steps.nStepType = MCH_MILL_ST.SPIRAL
MachiningToAdd.Steps.dStep = TOOLS[nIndexTool].dStep / 3
MachiningToAdd.LeadOut.nType = MCH_MILL_LI.TANGENT
MachiningToAdd.LeadOut.dTangentDistance = 0.5
MachiningToAdd.LeadOut.dPerpDistance = 0.5
MachiningToAdd.LeadOut.dElevation = Proc.FeatureInfo.dDrillLen
-- se diametro foro più grande del doppio del diametro fresa, si fa svuotatura
else
MachiningToAdd = MachiningLib.InitMachiningParameters( MCH_MY.POCKETING)
MachiningToAdd = BeamLib.MergeTables( MachiningToAdd, Strategy.Machinings[j])
MachiningToAdd.Steps.dStep = TOOLS[nIndexTool].dStep
MachiningToAdd.Steps.dSideStep = TOOLS[nIndexTool].dSideStep
MachiningToAdd.nSubType = MCH_POCK_SUB.SPIRALOUT
MachiningToAdd.LeadIn.nType = MCH_POCK_LI.HELIX
MachiningToAdd.LeadIn.dTangentDistance = TOOLS[nIndexTool].dDiameter / 2
MachiningToAdd.LeadIn.dElevation = MachiningToAdd.Steps.dStep / 2
end
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
return bAreAllMachiningsAdded, Strategy.Result
end
-------------------------------------------------------------------------------------------------------------
return STR0013
+56
View File
@@ -0,0 +1,56 @@
{
"sStrategyId": "STR0014",
"sStrategyName": "Marking",
"ParameterList" : [
{
"sName": "dMachiningDepth",
"sNameNge": "DEPTH",
"sValue": "1",
"sDescriptionShort": "Machining Depth",
"sDescriptionLong": "",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "sMillingList",
"sNameNge": "MARK_TOOL_LIST",
"sValue": "",
"sDescriptionShort": "Available mill to machine mark and text",
"sDescriptionLong": "",
"sType": "tool",
"sSubType": "MCH_TF.MILL",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "sMarkStrategy",
"sNameNge": "EXEC_MARK",
"sValue": "AUTO",
"sDescriptionShort": "Marking Strategy",
"sDescriptionLong": "",
"sType": "combo",
"sMinUserLevel": "1",
"Choices": [
{
"sValue": "AUTO",
"sDescriptionShort": "Automatic",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "PEN_FORCED",
"sDescriptionShort": "Pen only",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "VMILL_FORCED",
"sDescriptionShort": "V-Mill only",
"sDescriptionLong": "",
"sMessageId": ""
}
]
}
]
}
+126
View File
@@ -0,0 +1,126 @@
-- Strategia: STR0014
-- Descrizione
-- Incisione con fresa
-- Feature tipo Mark
-------------------------------------------------------------------------------------------------------------
-------------------------------------------------------------------------------------------------------------
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
local ID = require( 'Identity')
-- Tabella per definizione modulo
local STR0014 = {}
local Strategy = {}
-------------------------------------------------------------------------------------------------------------
local function GetSCC( Machining)
local nSCC
if TOOLS[Machining.nToolIndex].SetupInfo.bToolOnAggregate then
nSCC = MCH_SCC.ADIR_NEAR
elseif Machining.vtToolDirection:getY() <= 0 then
nSCC = MCH_SCC.ADIR_YM
else
nSCC = MCH_SCC.ADIR_YP
end
return nSCC
end
-------------------------------------------------------------------------------------------------------------
-- TODO rimuovere il calcolo MRR dove non serve, è fatto tutto alla fine.
function STR0014.Make( bAddMachining, Proc, Part, CustomParameters)
-- carico parametri de default e li aggiorno con quelli passati dal chiamante (potrebbero non essere congruenti)
local StrategyLib = {}
StrategyLib.Config = STRATEGIES_CONFIG[CustomParameters.sStrategyId]
Strategy.sName = StrategyLib.Config.sStrategyId
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( Proc, Part, CustomParameters, StrategyLib.Config)
Strategy.Machining = MachiningLib.InitMachiningParameters( MCH_MY.MILLING)
Strategy.Result = {}
Strategy.Result.dTimeToMachine = 0
local bAreAllMachiningsAdded = true
local ToolSearchParameters = {}
ToolSearchParameters.dElevation = 0
ToolSearchParameters.vtToolDirection = Proc.FeatureInfo.vtExtr
if Strategy.Parameters.sMarkStrategy == 'AUTO' then
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sMillingList, 'Milling')
ToolSearchParameters.sMillShape = EgtIf( ID.IsMarking( Proc), 'VMILL', 'PEN')
Strategy.Machining.ToolInfo = {}
Strategy.Machining.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
-- se utensile non trovato, si cerca altro tipo di utensile compatibile per questi tipi di lavorazione
if not Strategy.Machining.ToolInfo.nToolIndex then
ToolSearchParameters.sMillShape = EgtIf( ID.IsMarking( Proc), 'PEN', 'VMILL')
Strategy.Machining.ToolInfo = {}
Strategy.Machining.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
end
else
if Strategy.Parameters.sMarkStrategy == 'PEN_FORCED' then
ToolSearchParameters.sMillShape = 'PEN'
elseif Strategy.Parameters.sMarkStrategy == 'VMILL_FORCED' then
ToolSearchParameters.sMillShape = 'VMILL'
end
Strategy.Machining.ToolInfo = {}
Strategy.Machining.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
end
if Strategy.Machining.ToolInfo.nToolIndex then
Strategy.Result.sStatus = 'Completed'
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
local Parameters = { nToolIndex = Strategy.Machining.ToolInfo.nToolIndex}
Strategy.Result.dMRR = MachiningLib.GetToolMRR( Parameters)
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'MILL')
else
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable()
end
if Strategy.Result.sStatus ~= 'Not-Applicable' then
if bAddMachining then
-- potrebbero esserci altre geometrie, si prepara già struttura con cloni
Strategy.AuxiliaryData = {}
Strategy.AuxiliaryData.Clones = {}
Strategy.AuxiliaryData.Clones[1] = {}
Strategy.AuxiliaryData.Clones[1].Geometry = {{ Proc.id, -1}}
Strategy.Machining.Geometry = {{ Proc.id, -1}}
Strategy.Machining.nToolIndex = Strategy.Machining.ToolInfo.nToolIndex
Strategy.Machining.vtToolDirection = Proc.FeatureInfo.vtExtr
Strategy.Machining.nSCC = GetSCC( Strategy.Machining)
Strategy.Machining.nType = MCH_MY.MILLING
Strategy.Machining.sDepth = EgtClamp( Strategy.Parameters.dMachiningDepth, -1, 5)
Strategy.Machining.nWorkside = MCH_MILL_WS.CENTER
-- LeadIn / LeadOut
Strategy.Machining.LeadIn = {}
Strategy.Machining.LeadOut = {}
Strategy.Machining.LeadIn.nType = MCH_MILL_LI.NONE
Strategy.Machining.LeadOut.nType = MCH_MILL_LI.NONE
-- stessi parametri cambia solo al geometria
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 = {{ AuxId, -1}}
end
bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, Strategy.Machining, Strategy.AuxiliaryData)
end
else
bAreAllMachiningsAdded = false
end
return bAreAllMachiningsAdded, Strategy.Result
end
-------------------------------------------------------------------------------------------------------------
return STR0014
+136
View File
@@ -0,0 +1,136 @@
{
"sStrategyId": "STR0015",
"sStrategyName": "Mill Heading",
"ParameterList" : [
{
"sName": "dDepthChamfer",
"sNameNge": "DEPTH_CHAMFER",
"sValue": "0",
"sDescriptionShort": "Depth Chamfer",
"sDescriptionLong": "Depth of the V-Mill to execute chamfers on cut-edges",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "bOnlyChamfer",
"sNameNge": "ONLY_CHAMFER",
"sValue": "false",
"sDescriptionShort": "Only Chamfer",
"sDescriptionLong": "Execute the chamfer only, no other machining",
"sType": "b",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "dOverMaterial",
"sNameNge": "OVERMAT",
"sValue": "0",
"sDescriptionShort": "Overmaterial",
"sDescriptionLong": "",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "dMaxCornerRadius",
"sNameNge": "MAX_CORNER_RADIUS",
"sValue": "15",
"sDescriptionShort": "Max radius left on corners",
"sDescriptionLong": "Radius-limit left by the tool at each corner of the feature",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "bExecRough",
"sNameNge": "EXEC_ROUGH",
"sValue": "true",
"sDescriptionShort": "Execute cut to remove material",
"sDescriptionLong": "",
"sType": "b",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "bForceStrip",
"sNameNge": "FORCE_STRIP",
"sValue": "false",
"sDescriptionShort": "Force strip",
"sDescriptionLong": "Enable the parameter to force the software to leave a strip to sustain the piece",
"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": "sConcaveFaceStrategy",
"sNameNge": "CONCAVE_FACE",
"sValue": "AUTO",
"sDescriptionShort": "Cutting Strategy",
"sDescriptionLong": "",
"sType": "combo",
"sMinUserLevel": "1",
"Choices": [
{
"sValue": "AUTO",
"sDescriptionShort": "Automatic",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "NONE",
"sDescriptionShort": "No machining",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "BLADE_FORCED",
"sDescriptionShort": "Blade forced",
"sDescriptionLong": "",
"sMessageId": ""
},
{
"sValue": "MILL_FORCED",
"sDescriptionShort": "Mill forced",
"sDescriptionLong": "",
"sMessageId": ""
}
]
},
{
"sName": "sMillingList",
"sNameNge": "PROFILE_TOOL_LIST",
"sValue": "",
"sDescriptionShort": "Available mill to machine the profile",
"sDescriptionLong": "",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "dMaxWasteLength",
"sSource": "GEN_dMaxWasteLength",
"sMinUserLevel": "5"
},
{
"sName": "dMaxWasteVolume",
"sSource": "GEN_dMaxWasteVolume",
"sMinUserLevel": "5"
},
{
"sName": "bReduceBladePath",
"sSource": "GEN_bReduceBladePath",
"sMinUserLevel": "5"
}
]
}
+881
View File
@@ -0,0 +1,881 @@
-- Strategia: STR0015
-- Descrizione
-- Fresatura di contorno
-- Feature tipo Profilo arcuato, Convesso, Concavo, Arco
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamDataNew')
local MachiningLib = require( 'MachiningLib')
local FeatureLib = require( 'FeatureLib')
local FaceData = require( 'FaceData')
local ID = require( 'Identity')
-- strategie di base
local BladeToWaste = require('BLADETOWASTE')
local FaceByBlade = require('FACEBYBLADE')
local FaceByMill = require('FACEBYMILL')
-- Tabella per definizione modulo
local STR0015 = {}
local Strategy = {}
-------------------------------------------------------------------------------------------------------------
local function GetEdgeToMachine( Proc, idFace, vtEdge)
local Edge
local dBestEdgeAngle = 999
for i = 1, #Proc.Faces[idFace].Edges do
local dAngle = abs( GetAngle( Proc.Faces[idFace].Edges[i].vtN, vtEdge) or 999)
if dAngle < dBestEdgeAngle then
dBestEdgeAngle = dAngle
Edge = Proc.Faces[idFace].Edges[i]
end
end
return Edge
end
-- TODO funzione recuperata da beam vecchio, verificare se possibile migliorare
---------------------------------------------------------------------
local function GetSawCutData( Proc, AuxId, vtNF, vtN)
local ptStart, vtNP
if ID.IsHeadConcaveProfile( Proc) or ID.IsHeadConvexProfile( Proc) or ID.IsHeadProfile( Proc) or ID.IsFrontProfile( Proc) then
vtNP = Vector3d( vtN)
-- comincio con la normale a 45deg
for i = 1, 3 do
if vtNP[i] > GEO.EPS_SMALL then
vtNP[i] = 1
elseif vtNP[i] < -GEO.EPS_SMALL then
vtNP[i] = -1
end
end
vtNP:normalize()
-- assegno un punto di passaggio
ptStart = EgtMP( AuxId, GDB_ID.ROOT)
local frOCS = Frame3d( ptStart, vtNP) ;
local b3Box = EgtGetBBoxRef( AuxId, GDB_BB.STANDARD, frOCS)
ptStart = ptStart + vtNP * ( b3Box:getMax():getZ() + 10.0)
elseif ID.IsHeadCamberedProfile( Proc) then
vtNP = Vector3d( vtNF)
-- comincio con la normale a 45deg
for i = 1, 3 do
if vtNP[i] > GEO.EPS_SMALL then
vtNP[i] = 1
elseif vtNP[i] < -GEO.EPS_SMALL then
vtNP[i] = -1
end
end
vtNP:normalize()
-- assegno un punto di passaggio
ptStart = EgtSP( AuxId, GDB_ID.ROOT) + vtNP * 5.0
-- determino asse di rotazione
local vtRot = - Y_AX()
if vtNF:getX() < 0 then vtRot = - vtRot end
if vtNF:getZ() < -0.1 then
vtRot = - vtRot
elseif vtNF:getY() < -0.1 then
vtRot:rotate( X_AX(), 90)
elseif vtNF:getY() > 0.1 then
vtRot:rotate( X_AX(), -90)
end
-- miglioro l'inclinazione (ripartendo da faccia perpendicolare asse trave)
vtNP[2] = 0 vtNP[3] = 0
local dRot = 45
for i = 1, 4 do
local vtNP2 = Vector3d( vtNP)
vtNP2:rotate( vtRot, dRot)
local frRef = Frame3d( ptStart, vtNP2)
local b3Box = EgtGetBBoxRef( AuxId, GDB_BB.STANDARD, frRef)
if b3Box:getMax():getZ() < -3 then
vtNP = Vector3d( vtNP2)
end
dRot = dRot / 2
end
end
-- restituisco i dati del piano
return ptStart, vtNP
end
-------------------------------------------------------------------------------------------------------------
local function GetRoughStrategy( Proc, Part, bSaveAddedGeometries)
local Machining = {}
local Result = {}
-- ====== Taglio di sgrossatura generale su tutto il profilo ======
local vtNF = EgtSurfTmFacetNormVersor( Proc.id, Proc.nFct-1, GDB_ID.ROOT)
local nMidFacet = Proc.nFct // 2 -- faccia a metà circa
local vtN = EgtSurfTmFacetNormVersor( Proc.id, nMidFacet, GDB_ID.ROOT)
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( idAddGroup, ptStart, vtNP, Part.b3Part, GDB_RT.GLOB)
-- se la faccia è stata creata
if AddId then
-- creo piano di taglio sulla testa del tenone
local OptionalParameters = { dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume,
dMaxWasteLength = Strategy.Parameters.dMaxWasteLength,
bReduceBladePath = Strategy.Parameters.bReduceBladePath
}
Machining, Result = BladeToWaste.Make( AddId, Part, OptionalParameters)
-- se non ci sono lavorazioni, provo con fresa
if not Machining or #Machining == 0 then
Machining.bCuttingWithMill = true
-- === ricerca utensile per svuotare taglio iniziale, se taglio non possibile ===
if not( Proc.AffectedFaces.bLeft) or Strategy.bCanMoveAfterSplit then
ToolSearchParameters = {}
-- TODO SISTEMARE!!! qui la svuotatura non deve limitare l'elevazione se aperta da tutti i lati. In futuro si deve passare 0 come elevazione
ToolSearchParameters.dElevation = EgtSurfTmFacetElevationInBBox( AddId, 0, Part.b3Part, true, GDB_ID.ROOT)
ToolSearchParameters.vtToolDirection = vtNP
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sPocketingList, 'Pocketing')
Machining.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
-- TODO anche il test sul ResidualDepth va tolto
if Machining.ToolInfo.nToolIndex and ( Machining.ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL) then
Machining.bIsApplicable = true
local ParametersMRR = {}
ParametersMRR.nToolIndex = Machining.ToolInfo.nToolIndex
Result.dMRR = MachiningLib.GetToolMRR( ParametersMRR)
Result.sStatus = 'Completed'
Machining.Steps = {}
Machining.LeadIn = {}
Machining.nType = MCH_MY.POCKETING
Machining.nSubType = MCH_POCK_SUB.SPIRALIN
Machining.LeadIn.nType = MCH_POCK_LI.ZIGZAG
Machining.Steps.dStep = TOOLS[Machining.ToolInfo.nToolIndex].dStep
Machining.Steps.dSideStep = TOOLS[Machining.ToolInfo.nToolIndex].dSideStep
Machining.nToolIndex = Machining.ToolInfo.nToolIndex
Machining.LeadIn.dTangentDistance = TOOLS[Machining.ToolInfo.nToolIndex].dDiameter/2
Machining.LeadIn.dElevation = TOOLS[Machining.ToolInfo.nToolIndex].dDiameter/2
Machining.sDepth = 0
Machining.Geometry = {{ AddId, 0}}
Machining.vtToolDirection = vtNF
if Proc.AffectedFaces.bLeft and Strategy.bCanMoveAfterSplit then
Machining.sStage = 'AfterTail'
end
-- tempo di svuotatura
Result.dTimeToMachine = MachiningLib.GetTimeToMachineAllStepsWithLeadInOut( Machining, Part)
end
end
end
end
return Machining, Result
end
-------------------------------------------------------------------------------------------------------------
local function GetEdgeWithCornerStrategy( Proc, Part)
local Machining = {}
local Result = { dCompletionPercentage = 100}
local nFirstFacet = 0 -- faccia iniziale
local nLastFacet = Proc.nFct - 1 -- faccia finale
-- verifico se necessari ripassi agli estremi negli angoli
local _, _, _, dFirstAng = EgtSurfTmFacetsContact( Proc.id, nFirstFacet, nFirstFacet + 1, GDB_ID.ROOT)
local bFirstTrim = ( dFirstAng and dFirstAng < -30)
local _, _, _, dLastAng = EgtSurfTmFacetsContact( Proc.id, nLastFacet, nLastFacet - 1, GDB_ID.ROOT)
local bLastTrim = ( dLastAng and dLastAng < -30)
local nMidFacet = ( nLastFacet + 1) // 2 -- faccia a metà circa
local vtN = EgtSurfTmFacetNormVersor( Proc.id, nMidFacet, GDB_ID.ROOT)
-- se non ci sono angoli da pulire si esce subito
if Strategy.Parameters.sConcaveFaceStrategy == 'NONE' or ( not bFirstTrim and not bLastTrim) then
return nil, nil
end
local FacesToGet = {}
if bFirstTrim then
table.insert( FacesToGet, nFirstFacet)
table.insert( FacesToGet, nFirstFacet+1)
end
if bLastTrim then
table.insert( FacesToGet, nLastFacet - 1)
table.insert( FacesToGet, nLastFacet)
end
-- ricavo info facce da lavorare
Proc.Faces = FaceData.GetFacesInfo( Proc, Part, FacesToGet)
-- direzioni di lavorazione
local vtCutDir1
-- se è diretta verso alto o basso
if abs( vtN:getZ()) > abs( vtN:getY()) then
if vtN:getZ() > 0 then
vtCutDir1 = Z_AX()
else
vtCutDir1 = -Z_AX()
end
-- altrimenti è di fianco
else
if vtN:getY() > 0 then
vtCutDir1 = Y_AX()
else
vtCutDir1 = -Y_AX()
end
end
local vtCutDir2
if vtN:getX() > 0 then
vtCutDir2 = X_AX()
else
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.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.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.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.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 ( 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.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.bIsApplicable then
table.insert( Machining, Milling)
end
end
end
if nMachiningsToAdd and ( #Machining < nMachiningsToAdd) then
Result = { dCompletionPercentage = ( #Machining / nMachiningsToAdd)}
end
return Machining, Result
end
-------------------------------------------------------------------------------------------------------------
local function GetChamferStrategy( Proc, Part)
local Machining = {}
local Result = {}
local ToolSearchParameters = {}
local dExtraDepth = 2
local vtExtr = EgtCurveExtrusion( Proc.idAddAuxGeom, GDB_RT.GLOB)
local bIsHorizontal = abs( vtExtr:getZ()) < 10 * GEO.EPS_SMALL
local bToolInvert = ( vtExtr:getZ() < -0.1)
if Strategy.Parameters.dDepthChamfer > 100 * GEO.EPS_SMALL then
-- controllo conformità affondamento smussi
Strategy.Parameters.dDepthChamfer = EgtClamp( Strategy.Parameters.dDepthChamfer, 0.1, 5)
-- si prapara tabella con parametri di base comuni a tutte le lavorazioni
local BasicMach = MachiningLib.InitMachiningParameters( MCH_MY.MILLING)
BasicMach.Geometry = {{ Proc.idAddAuxGeom, -1}}
BasicMach.nType = MCH_MY.MILLING
BasicMach.sDepth = Strategy.Parameters.dDepthChamfer + dExtraDepth
-- LeadIn / LeadOut
BasicMach.LeadIn.nType = MCH_MILL_LI.NONE
BasicMach.LeadOut.nType = MCH_MILL_LI.NONE
BasicMach.LeadIn.dStartAddLength = 5
BasicMach.LeadOut.dEndAddLength = 5
if Proc.AffectedFaces.bLeft and Strategy.bCanMoveAfterSplit then
BasicMach.sStage = 'AfterTail'
end
BasicMach.ptEdge1 = EgtSP( Proc.idAddAuxGeom, GDB_ID.ROOT)
BasicMach.ptEdge2 = EgtEP( Proc.idAddAuxGeom, GDB_ID.ROOT)
BasicMach.dEdgeLength = EgtCurveLength( Proc.idAddAuxGeom)
BasicMach.vtEdgeDirection = EgtSV( Proc.idAddAuxGeom, GDB_ID.ROOT) + EgtMV( Proc.idAddAuxGeom, GDB_ID.ROOT) + EgtEV( Proc.idAddAuxGeom, GDB_ID.ROOT)
BasicMach.dLengthOnX = Proc.b3Box:getDimX()
-- parametri di ricerca utensile comuni a tutte le lavorazioni
ToolSearchParameters.sMillShape = 'VMILL'
ToolSearchParameters.dElevation = Strategy.Parameters.dDepthChamfer
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sMillingList, 'MillingSmooth')
-- se lavorazione orizzontale
if bIsHorizontal then
local Milling = {}
ToolSearchParameters.vtToolDirection = EgtIf( bToolInvert, -vtExtr, vtExtr)
Milling.ToolInfo = {}
Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
-- se trovato utensile adatto
if Milling.ToolInfo.nToolIndex then
Milling.vtToolDirection = ToolSearchParameters.vtToolDirection
Milling.nToolIndex = Milling.ToolInfo.nToolIndex
Milling.dRadialOffset = dExtraDepth * cos( TOOLS[Milling.nToolIndex].dSideAngle)
Milling.bInvert = EgtIf( TOOLS[Milling.nToolIndex].bIsCCW, false, true)
Milling.nWorkside = EgtIf( TOOLS[Milling.nToolIndex].bIsCCW, MCH_MILL_WS.RIGHT, MCH_MILL_WS.LEFT)
Milling = BeamLib.MergeTables( BasicMach, Milling)
table.insert( Machining, Milling)
local Milling2 = BeamLib.TableCopyDeep( Milling)
Milling2.bToolInvert = true
Milling2.bInvert = EgtIf( TOOLS[Milling2.nToolIndex].bIsCCW, true, false)
Milling2.nWorkside = EgtIf( TOOLS[Milling2.nToolIndex].bIsCCW, MCH_MILL_WS.RIGHT, MCH_MILL_WS.LEFT)
table.insert( Machining, Milling2)
end
-- se lavorazione verticale
else
-- si cerca utensile 1
local Milling = {}
ToolSearchParameters.vtToolDirection = EgtIf( bToolInvert, -vtExtr, vtExtr)
Milling.ToolInfo = {}
Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
Milling.vtToolDirection = ToolSearchParameters.vtToolDirection
-- si cerca utensile 2
local Milling2 = {}
ToolSearchParameters.vtToolDirection = EgtIf( bToolInvert, vtExtr, -vtExtr)
Milling2.ToolInfo = {}
Milling2.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
Milling2.vtToolDirection = ToolSearchParameters.vtToolDirection
Milling2.bToolInvert = true
-- se trovato utensile 1 adatto
if Milling.ToolInfo.nToolIndex then
Milling.nToolIndex = Milling.ToolInfo.nToolIndex
Milling.dRadialOffset = dExtraDepth * cos( TOOLS[Milling.nToolIndex].dSideAngle)
Milling.bInvert = EgtIf( TOOLS[Milling.nToolIndex].bIsCCW, false, true)
Milling.nWorkside = EgtIf( TOOLS[Milling.nToolIndex].bIsCCW, MCH_MILL_WS.RIGHT, MCH_MILL_WS.LEFT)
Milling = BeamLib.MergeTables( BasicMach, Milling)
table.insert( Machining, Milling)
end
-- se trovato utensile 2 adatto
if Milling2.ToolInfo.nToolIndex then
Milling2.nToolIndex = Milling2.ToolInfo.nToolIndex
Milling2.dRadialOffset = dExtraDepth * cos( TOOLS[Milling2.nToolIndex].dSideAngle)
Milling2.bToolInvert = true
Milling2.bInvert = EgtIf( TOOLS[Milling2.nToolIndex].bIsCCW, true, false)
Milling2.nWorkside = EgtIf( TOOLS[Milling2.nToolIndex].bIsCCW, MCH_MILL_WS.RIGHT, MCH_MILL_WS.LEFT)
Milling2 = BeamLib.MergeTables( BasicMach, Milling2)
table.insert( Machining, Milling2)
end
end
end
return Machining, Result
end
-------------------------------------------------------------------------------------------------------------
local function GetArcStrategy( Proc, Part)
local Machining = {}
local Result = { dCompletionPercentage = 100}
local ToolSearchParameters = {}
-- recupero i dati della curva e del profilo
local dDepth = abs( EgtCurveThickness( Proc.idAddAuxGeom))
local vtExtr = EgtCurveExtrusion( Proc.idAddAuxGeom, 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 sMaxDepth = dDepth * 2
local bExecStrip = false
-- se la lavorazione si trova nella parte inferiore o in battuta dietro, il codolo va sempre lasciato
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
dDimStrip = dDimStrip or max( BeamData.DIM_STRIP_SMALL or 5, 1)
end
bExecStrip = true
end
if not bExecStrip then
dDimStrip = 0
end
-- la passata di finitura c'è sempre
local nPassages = 1
-- si verifica se fare passaggio di sgrossatura con fresa
if not bExecStrip and Strategy.Parameters.dOverMaterial > 100 * GEO.EPS_SMALL then
nPassages = 2
end
-- ciclo su numero passate (2 in caso di sgrossatura + finitura)
for nCycle = nPassages, 1, -1 do
local nMaxDiamMill = EgtIf( nCycle == 1, Strategy.Parameters.dMaxCornerRadius * 2, nil)
local sTypeTool = EgtIf( nCycle == 1 and nPassages == 2, 'MillingFinish', 'Milling')
-- se lavorazione orizzontale
if bIsHorizontal then
local bDouble
local Milling = MachiningLib.InitMachiningParameters( MCH_MY.MILLING)
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, sTypeTool)
ToolSearchParameters.dMaxToolDiameter = nMaxDiamMill
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.nToolIndex then
if Milling.ToolInfo.dResidualDepth > 10 * GEO.EPS_SMALL and not bExecStrip then
bDouble = true
ToolSearchParameters.dElevation = ( dDepth + BeamData.MILL_OVERLAP) / 2
Milling.ToolInfo = {}
Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
end
Milling.vtToolDirection = ToolSearchParameters.vtToolDirection
if nCycle == 2 then
Milling.dRadialOffset = Strategy.Parameters.dOverMaterial
end
-- se non completo
if Milling.ToolInfo.dResidualDepth > 10 * GEO.EPS_SMALL then
sMaxDepth = ToolSearchParameters.dElevation - Milling.ToolInfo.dResidualDepth
-- si salva percentuala lavorata
Result.dCompletionPercentage = 100 - ceil( ( Milling.ToolInfo.dResidualDepth / ToolSearchParameters.dElevation) * 100)
end
if bDouble or bExecStrip then
if bDouble then
Milling.sDepth = min( sMaxDepth, ( dDepth + BeamData.MILL_OVERLAP) / 2)
else
Milling.sDepth = min( sMaxDepth, ( dDepth - dDimStrip) / 2)
end
table.insert( Machining, Milling)
local Milling2 = BeamLib.TableCopyDeep( Milling)
Milling2.bOtherDirection = true
table.insert( Machining, Milling2)
else
Milling.sDepth = min( sMaxDepth, dDepth + BeamData.MILL_OVERLAP)
table.insert( Machining, Milling)
end
end
-- se lavorazione verticale
else
ToolSearchParameters = {}
ToolSearchParameters.sMillShape = 'STANDARD'
ToolSearchParameters.dElevation = dDepth + BeamData.MILL_OVERLAP
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sMillingList, sTypeTool)
ToolSearchParameters.dMaxToolDiameter = nMaxDiamMill
-- si cerca utensile 1
local Milling = MachiningLib.InitMachiningParameters( MCH_MY.MILLING)
ToolSearchParameters.vtToolDirection = EgtIf( bToolInvert, -vtExtr, vtExtr)
Milling.ToolInfo = {}
Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
if nCycle == 2 then
Milling.dRadialOffset = Strategy.Parameters.dOverMaterial
end
Milling.vtToolDirection = ToolSearchParameters.vtToolDirection
Milling.bOtherDirection = bToolInvert
-- si cerca utensile 2
local Milling2 = MachiningLib.InitMachiningParameters( MCH_MY.MILLING)
ToolSearchParameters.vtToolDirection = EgtIf( bToolInvert, vtExtr, -vtExtr)
Milling2.ToolInfo = {}
Milling2.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
if nCycle == 2 then
Milling2.dRadialOffset = Strategy.Parameters.dOverMaterial
end
Milling2.vtToolDirection = ToolSearchParameters.vtToolDirection
Milling2.bOtherDirection = bToolInvert
-- se serve codolo
if bExecStrip then
local sDepthMachined = 0
-- se a disposizione entrambi gli utensili
if Milling.ToolInfo.nToolIndex and Milling2.ToolInfo.nToolIndex then
local dExtraDepth = ( dDepth - dDimStrip - ( Milling.ToolInfo.dResidualDepth + Milling2.ToolInfo.dResidualDepth)) / 2
Milling.sDepth = dDepth - Milling.ToolInfo.dResidualDepth - dExtraDepth
Milling2.sDepth = dDepth - Milling2.ToolInfo.dResidualDepth - dExtraDepth
sDepthMachined = Milling.sDepth + Milling2.sDepth
table.insert( Machining, Milling)
table.insert( Machining, Milling2)
-- se disponibile solo primo utensile
elseif Milling.ToolInfo.nToolIndex then
sMaxDepth = ToolSearchParameters.dElevation - Milling.ToolInfo.dResidualDepth
Milling.sDepth = min( sMaxDepth, dDepth - dDimStrip)
table.insert( Machining, Milling)
sDepthMachined = Milling.sDepth
-- se disponibile solo secondo utensile
elseif Milling2.ToolInfo.nToolIndex then
sMaxDepth = ToolSearchParameters.dElevation - Milling2.ToolInfo.dResidualDepth
Milling2.sDepth = min( sMaxDepth, dDepth - dDimStrip)
table.insert( Machining, Milling2)
sDepthMachined = Milling2.sDepth
-- nessun utensile disponibile
else
-- non si fa nulla
end
Result.dCompletionPercentage = min( ( sDepthMachined * 100) / ( dDepth - dDimStrip), 100)
-- altrimenti senza codolo
else
local sDepthMachined = 0
local dExtraDepth = ( dDepth - BeamData.MILL_OVERLAP - ( Milling.ToolInfo.dResidualDepth + Milling2.ToolInfo.dResidualDepth)) / 2
-- se utensile 1 esegue completamente (con almeno 1mm extra)
if Milling.ToolInfo.nToolIndex and Milling.ToolInfo.dResidualDepth < 1000 * GEO.EPS_SMALL then
sMaxDepth = ToolSearchParameters.dElevation - Milling.ToolInfo.dResidualDepth
Milling.sDepth = min( sMaxDepth, dDepth + BeamData.MILL_OVERLAP)
table.insert( Machining, Milling)
sDepthMachined = Milling.sDepth
-- se utensile 2 esegue completamente (con almeno 1mm extra)
elseif Milling2.ToolInfo.nToolIndex and Milling2.ToolInfo.dResidualDepth < 1000 * GEO.EPS_SMALL then
sMaxDepth = ToolSearchParameters.dElevation - Milling2.ToolInfo.dResidualDepth
Milling2.sDepth = min( sMaxDepth, dDepth + BeamData.MILL_OVERLAP)
table.insert( Machining, Milling2)
sDepthMachined = Milling2.sDepth
-- se possono lavorare entrambi
elseif Milling.ToolInfo.nToolIndex and Milling2.ToolInfo.nToolIndex then
Milling.sDepth = dDepth - Milling.ToolInfo.dResidualDepth - dExtraDepth
Milling2.sDepth = dDepth - Milling2.ToolInfo.dResidualDepth - dExtraDepth
table.insert( Machining, Milling)
table.insert( Machining, Milling2)
sDepthMachined = Milling.sDepth + Milling2.sDepth
-- se utensile 1 non completo
elseif Milling.ToolInfo.nToolIndex then
Milling.sDepth = ToolSearchParameters.dElevation - Milling.ToolInfo.dResidualDepth
table.insert( Machining, Milling)
sDepthMachined = Milling.sDepth
-- se utensile 2 non completo
elseif Milling2.ToolInfo.nToolIndex then
Milling2.sDepth = ToolSearchParameters.dElevation - Milling2.ToolInfo.dResidualDepth
table.insert( Machining, Milling2)
sDepthMachined = Milling2.sDepth
end
Result.dCompletionPercentage = min( ( sDepthMachined * 100) / ( dDepth - dDimStrip), 100)
end
end
end
Machining.bIsApplicable = #Machining > 0
return Machining, Result
end
-------------------------------------------------------------------------------------------------------------
local function GetFeatureResult( Proc)
local Result = { sStatus = 'Completed', dCompletionPercentage = 100, sInfo = ''}
local dPercentageChamfer = 10
local dPercentageEdgeCorner = 10
local dPercentageProfile = 80
-- se non ci sono lavorazioni di smusso
if not Strategy.Chamfer.Machinings or #Strategy.Chamfer.Machinings < 2 then
-- se esclusivo, non applicabile
if Strategy.Parameters.bOnlyChamfer then
Result = FeatureLib.GetStrategyResultNotApplicable( 'Not possible to machine chamfer only, tool not found!')
Result.dCompletionPercentage = 0
-- se non esclusivo, non completo
elseif Strategy.Parameters.dDepthChamfer > 100 * GEO.EPS_SMALL then
Result.dCompletionPercentage = Result.dCompletionPercentage - dPercentageChamfer -- gli smussi incidono per il 10%
dPercentageChamfer = 0
Result.sInfo = '- Chamfer not executed, tool not found!\n'
end
end
-- se richieste anche le altre lavorazioni
if not Strategy.Parameters.bOnlyChamfer then
-- per tutti tranne che per feature RoundArc
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
Result.dCompletionPercentage = Result.dCompletionPercentage -- non incide sulla percentuale lavorata, solo messaggio che manca
Result.sInfo = Result.sInfo .. '- Roughing not executed\n'
end
end
-- se lavorazioni corner
if Strategy.EdgeWithCorner.Machinings and #Strategy.EdgeWithCorner.Machinings == 0 then
Result.dCompletionPercentage = Result.dCompletionPercentage - dPercentageEdgeCorner -- la pulizia dei corner incide per il 10%
dPercentageEdgeCorner = 0
Result.sInfo = Result.sInfo .. '- Corner not executed, material left\n'
end
end
-- lavorazione del profilo
if not Strategy.Profile.Machinings or #Strategy.Profile.Machinings == 0 then
Result.sInfo = Result.sInfo .. '- Profile not executed, tool not found!\n'
else
local dTotalPercentage = dPercentageProfile + dPercentageEdgeCorner + dPercentageChamfer
Result.dCompletionPercentage = Result.dCompletionPercentage - ( ( ( 100 - Strategy.Profile.Result.dCompletionPercentage) * dTotalPercentage) / 100)
end
end
-- si setta lo stato in base alla percentuale di completamento
if Result.dCompletionPercentage == 100 then
Result.sStatus = "Completed"
elseif Result.dCompletionPercentage == 0 then
Result.sStatus = "Not-Applicable"
else
Result.sStatus = "Not-Completed"
local dPercentageLeft = ceil( 100 - Result.dCompletionPercentage)
Result.sInfo = Result.sInfo .. '- Not Complete : left ' .. tostring( dPercentageLeft) .. '%\n'
end
Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( Result.dCompletionPercentage)
Result.dMRR = 1
-- se tutte le lavorazioni sono state eseguite, è la massima qualità che si possa ottenere, altrimenti qualità più bassa
if Result.sInfo == '' then
Result.dQuality = FeatureLib.GetStrategyQuality( 'BEST')
else
Result.dQuality = FeatureLib.GetStrategyQuality( 'MILL')
end
return Result
end
-------------------------------------------------------------------------------------------------------------
function STR0015.Make( bAddMachining, Proc, Part, CustomParameters)
-- carico parametri de default e li aggiorno con quelli passati dal chiamante (potrebbero non essere congruenti)
local StrategyLib = {}
StrategyLib.Config = STRATEGIES_CONFIG[CustomParameters.sStrategyId]
Strategy.sName = StrategyLib.Config.sStrategyId
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( Proc, Part, CustomParameters, StrategyLib.Config)
Strategy.Chamfer = {}
Strategy.Chamfer.Machinings = {}
Strategy.Chamfer.Result = {}
Strategy.Result = {}
local bAreAllMachiningsAdded = true
-- verifico se la lavorazione può essere spostata dopo taglio di coda
local dLengthOnX = Proc.b3Box:getDimX()
Strategy.bCanMoveAfterSplit = MachiningLib.CanMoveAfterSplitcut( dLengthOnX, Part)
-- 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'
EgtOutLog( sErr)
return false, sErr
end
Proc.idAddAuxGeom = idAux
-- lavorazione smussi
Strategy.Chamfer.Machinings, Strategy.Chamfer.Result = GetChamferStrategy( Proc, Part)
-- 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) and not ID.IsFreeContour( Proc) then
-- lavorazione taglio per sgrossare
if Strategy.Parameters.bExecRough then
Strategy.RoughCut = {}
Strategy.RoughCut.Machinings = {}
Strategy.RoughCut.Result = {}
Strategy.RoughCut.Machinings, Strategy.RoughCut.Result = GetRoughStrategy( Proc, Part, bAddMachining)
end
-- lavorazione degli estremi con angoli interni
Strategy.EdgeWithCorner = {}
Strategy.EdgeWithCorner.Machinings = {}
Strategy.EdgeWithCorner.Result = {}
Strategy.EdgeWithCorner.Machinings, Strategy.EdgeWithCorner.Result = GetEdgeWithCornerStrategy( Proc, Part)
end
-- lavorazione profilo (a meno che non si facciano solo smussi)
Strategy.Profile = {}
Strategy.Profile.Machinings = {}
Strategy.Profile.Result = {}
Strategy.Profile.Machinings, Strategy.Profile.Result = GetArcStrategy( Proc, Part)
end
Strategy.Result = GetFeatureResult( Proc)
if bAddMachining and Strategy.Result.sStatus ~= 'Not-Applicable' then
-- eventuali punti di spezzatura
local FeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
-- lavorazione degli smussi
if Strategy.Chamfer.Machinings then
for i = 1, #Strategy.Chamfer.Machinings do
local MachiningToSplit = {}
table.insert( MachiningToSplit, Strategy.Chamfer.Machinings[i])
local MachiningResult = MachiningLib.GetSplitMachinings( MachiningToSplit, FeatureSplittingPoints, Part)
-- aggiunge lavorazione
for j = 1, #MachiningResult do
bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, MachiningResult[j])
end
end
end
-- per tutti tranne che per feature RoundArc
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
if Strategy.RoughCut.Machinings.bCuttingWithMill then
bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, Strategy.RoughCut.Machinings)
-- taglio di lama
else
for i = 1, #Strategy.RoughCut.Machinings do
if Proc.AffectedFaces.bLeft and Strategy.bCanMoveAfterSplit then
Strategy.RoughCut.Machinings[i].sStage = 'AfterTail'
end
local bIsMachiningAdded = MachiningLib.AddMachinings( Proc, Strategy.RoughCut.Machinings[i])
if not bIsMachiningAdded then
bAreAllMachiningsAdded = false
end
end
end
end
-- lavorazione degli angoli interni
if Strategy.EdgeWithCorner.Machinings then
for i = 1, #Strategy.EdgeWithCorner.Machinings do
local bIsMachiningAdded = MachiningLib.AddMachinings( Proc, Strategy.EdgeWithCorner.Machinings[i])
if not bIsMachiningAdded then
bAreAllMachiningsAdded = false
end
end
end
end
-- lavorazione del profilo
if Strategy.Profile.Machinings then
for i = 1, #Strategy.Profile.Machinings do
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 = 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
Strategy.Profile.Machinings[i].LeadIn.nType = MCH_MILL_LI.TANGENT
Strategy.Profile.Machinings[i].LeadOut.nType = MCH_MILL_LI.TANGENT
Strategy.Profile.Machinings[i].LeadIn.dTangentDistance = TOOLS[Strategy.Profile.Machinings[i].ToolInfo.nToolIndex].dDiameter / 2 + BeamData.COLL_SIC
Strategy.Profile.Machinings[i].LeadIn.dPerpDistance = 0
Strategy.Profile.Machinings[i].LeadIn.dStartAddLength = 0
Strategy.Profile.Machinings[i].LeadOut.dTangentDistance = TOOLS[Strategy.Profile.Machinings[i].ToolInfo.nToolIndex].dDiameter / 2 + BeamData.COLL_SIC
Strategy.Profile.Machinings[i].LeadOut.dPerpDistance = 0
Strategy.Profile.Machinings[i].LeadOut.dEndAddLength = 0
if Proc.AffectedFaces.bLeft and Strategy.bCanMoveAfterSplit then
Strategy.Profile.Machinings[i].sStage = 'AfterTail'
end
-- preparo attacco/uscita in caso di spezzatura arco
Strategy.Profile.Machinings[i].LeadInForSplit = BeamLib.TableCopyDeep( Strategy.Profile.Machinings[i].LeadIn)
Strategy.Profile.Machinings[i].LeadOutForSplit = BeamLib.TableCopyDeep( Strategy.Profile.Machinings[i].LeadOut)
Strategy.Profile.Machinings[i].LeadInForSplit.nType = MCH_MILL_LI.LINEAR
Strategy.Profile.Machinings[i].LeadOutForSplit.nType = MCH_MILL_LI.LINEAR
Strategy.Profile.Machinings[i].LeadInForSplit.dTangentDistance = 0
Strategy.Profile.Machinings[i].LeadInForSplit.dPerpDistance = TOOLS[Strategy.Profile.Machinings[i].ToolInfo.nToolIndex].dDiameter / 2 + BeamData.COLL_SIC
Strategy.Profile.Machinings[i].LeadOutForSplit.dTangentDistance = 0
Strategy.Profile.Machinings[i].LeadOutForSplit.dPerpDistance = TOOLS[Strategy.Profile.Machinings[i].ToolInfo.nToolIndex].dDiameter / 2 + BeamData.COLL_SIC
-- sistemo il lato e la direzione di lavoro
if Strategy.Profile.Machinings[i].bOtherDirection then
Strategy.Profile.Machinings[i].bToolInvert = true
Strategy.Profile.Machinings[i].bInvert = EgtIf( TOOLS[Strategy.Profile.Machinings[i].ToolInfo.nToolIndex].bIsCCW, true, false)
Strategy.Profile.Machinings[i].nWorkside = EgtIf( TOOLS[Strategy.Profile.Machinings[i].ToolInfo.nToolIndex].bIsCCW, MCH_MILL_WS.RIGHT, MCH_MILL_WS.LEFT)
else
Strategy.Profile.Machinings[i].bInvert = EgtIf( TOOLS[Strategy.Profile.Machinings[i].ToolInfo.nToolIndex].bIsCCW, false, true)
Strategy.Profile.Machinings[i].nWorkside = EgtIf( TOOLS[Strategy.Profile.Machinings[i].ToolInfo.nToolIndex].bIsCCW, MCH_MILL_WS.RIGHT, MCH_MILL_WS.LEFT)
end
Strategy.Profile.Machinings[i].ptEdge1 = EgtSP( Proc.idAddAuxGeom, GDB_ID.ROOT)
Strategy.Profile.Machinings[i].ptEdge2 = EgtEP( Proc.idAddAuxGeom, GDB_ID.ROOT)
Strategy.Profile.Machinings[i].dEdgeLength = EgtCurveLength( Proc.idAddAuxGeom)
Strategy.Profile.Machinings[i].vtEdgeDirection = EgtSV( Proc.idAddAuxGeom, GDB_ID.ROOT) + EgtMV( Proc.idAddAuxGeom, GDB_ID.ROOT) + EgtEV( Proc.idAddAuxGeom, GDB_ID.ROOT)
Strategy.Profile.Machinings[i].dLengthOnX = Proc.b3Box:getDimX()
local MachiningToSplit = {}
table.insert( MachiningToSplit, Strategy.Profile.Machinings[i])
local MachiningResult = MachiningLib.GetSplitMachinings( MachiningToSplit, FeatureSplittingPoints, Part)
-- aggiunge lavorazione
for j = 1, #MachiningResult do
bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, MachiningResult[j])
end
end
end
else
bAreAllMachiningsAdded = false
end
return bAreAllMachiningsAdded, Strategy.Result
end
-------------------------------------------------------------------------------------------------------------
return STR0015
+61
View File
@@ -0,0 +1,61 @@
{
"sStrategyId": "TAILCUT",
"sStrategyName": "TAILCUT",
"ParameterList" : [
{
"sName": "dDepthChamfer",
"sNameNge": "DEPTH_CHAMFER",
"sValue": "0",
"sDescriptionShort": "Depth Chamfer",
"sDescriptionLong": "Depth of the V-Mill to execute chamfers on cut-edges",
"sType": "d",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "bForceChainSaw",
"sNameNge": "FORCE_CHAIN",
"sValue": "false",
"sDescriptionShort": "Force to use chain saw",
"sDescriptionLong": "Force to use chain saw",
"sType": "b",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "bExecutePreCut",
"sNameNge": "EXEC_PRECUT",
"sValue": "true",
"sDescriptionShort": "Force to add PreCuts",
"sDescriptionLong": "Autocam will apply a machining on the theoretical zero, to avoid collision if the theoretical piece length doesn't correspond to the real length",
"sType": "b",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "bFinishWithMill",
"sNameNge": "MILL_FINISH",
"sValue": "true",
"sDescriptionShort": "Finish with mill",
"sDescriptionLong": "Use a mill to finish the surface if split with chain saw",
"sType": "b",
"sMessageId": " ",
"sMinUserLevel": "1"
},
{
"sName": "dMaxWasteLength",
"sSource": "GEN_dMaxWasteLength",
"sMinUserLevel": "5"
},
{
"sName": "dMaxWasteVolume",
"sSource": "GEN_dMaxWasteVolume",
"sMinUserLevel": "5"
},
{
"sName": "bReduceBladePath",
"sSource": "GEN_bReduceBladePath",
"sMinUserLevel": "5"
}
]
}
+195
View File
@@ -0,0 +1,195 @@
-- Strategia: TAILCUT
-- Descrizione
-- Taglio di separazione
-- Feature: TailCut
-- carico librerie
local BeamLib = require( 'BeamLib')
local BeamData = require( 'BeamDataNew')
local FeatureLib = require( 'FeatureLib')
local MachiningLib = require( 'MachiningLib')
local SPLITCUT = require( 'SPLITCUT')
-- strategie di base
local BladeToWaste = require('BLADETOWASTE')
-- Tabella per definizione modulo
local TAILCUT = {}
local Strategy = {}
-------------------------------------------------------------------------------------------------------------
local function MakeChamfer()
-- TODO funzionalità da aggiungere
end
-------------------------------------------------------------------------------------------------------------
function TAILCUT.Make( bAddMachining, Proc, Part, CustomParameters)
local StrategyLib = {}
StrategyLib.Config = STRATEGIES_CONFIG[CustomParameters.sStrategyId]
Strategy.sName = StrategyLib.Config.sStrategyId
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( Proc, Part, CustomParameters, StrategyLib.Config)
Strategy.SplitStrategy = {}
Strategy.Result = {}
Strategy.Machining = {}
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
-- se devo fare split perchè c'è un grezzo da scaricare o un altro pezzo
if Strategy.bSplit then
OptionalParameters.dOffset = 0
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)
if Strategy.Parameters.bExecutePreCut then
if Part.dRestLength < 20 then
bExecutePrecutOnly = true
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'
Strategy.Result.dCompletionIndex = 5
Strategy.Result.dMRR = 1
-- si imposta qualità lama perchè verrà fatta BladeToWaste, probabilmente a cubetti
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'SAWBLADE')
end
end
-- se devo applicare le lavorazioni
if bAddMachining then
-- inserimento smussi su spigoli del taglio
if Strategy.Parameters.bMakeChamfer then
MakeChamfer()
end
local MachiningsToAdd = {}
-- se devo fare split perchè c'è un grezzo da scaricare o un altro pezzo
if Strategy.bSplit then
if Strategy.SplitStrategy and #Strategy.SplitStrategy > 0 then
for i = 1, #Strategy.SplitStrategy do
local TempList = {}
TempList.Splitting = Strategy.SplitStrategy[i]
if i == #Strategy.SplitStrategy then
TempList.Splitting.sUserNotes = 'Split;'
TempList.AuxiliaryData = { bIsSplitOrCut = true}
else
TempList.Splitting.sUserNotes = 'Presplit;'
end
table.insert( MachiningsToAdd, TempList)
end
end
-- se devo rimuovere tutto il restante
else
-- se abilitato, faccio tagli di PRECUT a zero (come SPLIT)
if Strategy.Parameters.bExecutePreCut then
if Strategy.SplitStrategy and #Strategy.SplitStrategy > 0 then
for i = 1, #Strategy.SplitStrategy do
local TempList = {}
TempList.Splitting = Strategy.SplitStrategy[i]
TempList.Splitting.dLongitudinalOffset = OptionalParameters.dOffset
if bExecutePrecutOnly then
if i == #Strategy.SplitStrategy then
TempList.Splitting.sUserNotes = 'Cut;'
TempList.AuxiliaryData = { bIsSplitOrCut = true}
else
TempList.Splitting.sUserNotes = 'Precut;'
end
end
table.insert( MachiningsToAdd, TempList)
end
end
end
if not bExecutePrecutOnly then
-- 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
if Strategy.Machining and #Strategy.Machining > 0 then
for i = 1, #Strategy.Machining do
local TempList = {}
TempList.Splitting = Strategy.Machining[i]
if i == #Strategy.Machining then
TempList.Splitting.sUserNotes = 'Cut;'
TempList.AuxiliaryData = { bIsSplitOrCut = true}
else
TempList.Splitting.sUserNotes = 'Precut;'
end
table.insert( MachiningsToAdd, TempList)
end
else
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( 'Tail machining not possible')
return false, Strategy.Result
end
end
end
-- aggiungo lavorazioni trovate alla lista generale
for i = 1, #MachiningsToAdd do
MachiningsToAdd[i].Splitting.sStage = 'Tail'
MachiningLib.AddMachinings( Proc, MachiningsToAdd[i].Splitting, MachiningsToAdd[i].AuxiliaryData)
end
return bAreAllMachiningsAdded, Strategy.Result
else
return nil, Strategy.Result
end
end
-------------------------------------------------------------------------------------------------------------
return TAILCUT
+42 -30
View File
@@ -3,13 +3,25 @@
STR0001 = Tenone a coda di rondine. Lama + fresa a coda di rondine
STR0002 = Topologia tipo LapJoint. Svuotatura con fresa
STR0003 = Topologia tipo LapJoint. Lama + motosega
STR0004 = Topologia tipo LapJoint. Motosega
STR0005 = 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 mortasa (raggiata)
STR0009 = ScarfJoint
STR0010 = Fresatura perpendicolare (tipo cut, longcut)
STR0011 = Foratura
STR0012 = RidgeLap
STR0013 = Foratura con fresa (svuotatura)
STR0014 = Incisione con fresa/penna (Mark/text)
STR0015 = Profilo arcuato (Head Cambered Profile)
[Strategies]
; Processing , Gruppo , Topologia , Strategie
;Feature : Cut
10,1,Feature,
10,1,Feature,STR0005
;Feature : Longitudinal Cut
10,0,Feature,
10,0,Feature,STR0005
;Feature : Double Cut
11,1,Feature,
; Feature : Ridge or Valley Cut
@@ -17,53 +29,53 @@ STR0003 = Topologia tipo LapJoint. Lama + motosega
; Feature : Saw Cut
13,0,Feature,
; Feature : Slot
16,0,Pocket-5-Blind,STR0002,STR0003
16,0,Groove-4-Blind,STR0002,STR0003
16,0,Groove-3-Through,STR0002,STR0003
16,0,Pocket-5-Blind,STR0002,STR0003,STR0004
16,0,Groove-4-Blind,STR0002,STR0003,STR0004
16,0,Groove-3-Through,STR0002,STR0003,STR0004
16,0,Groove-3-Blind,STR0002
16,0,Rabbet-2-Through,STR0002
16,0,Tunnel-4-Through,STR0003
16,0,Tunnel-4-Through,STR0003,STR0004
; Feature : Front Slot
17,0,Pocket-5-Blind,STR0002,STR0003
17,0,Groove-4-Blind,STR0002,STR0003
17,0,Pocket-5-Blind,STR0002,STR0003,STR0004
17,0,Groove-4-Blind,STR0002,STR0003,STR0004
17,0,Groove-3-Blind,STR0002
17,0,Groove-3-Through,STR0002,STR0003
17,0,Groove-3-Through,STR0002,STR0003,STR0004
17,0,Rabbet-2-Through,STR0002
17,0,Tunnel-4-Through,STR0003
17,0,Tunnel-4-Through,STR0003,STR0004
; Feature : Birds Mouth
20,0,Feature,
; Feature : Hip or Valley Rafter Notch
25,0,Feature,
; Feature : Ridge Lap
30,1,Pocket-5-Blind,STR0002,STR0003
30,1,Groove-4-Blind,STR0002,STR0003
30,1,Pocket-5-Blind,STR0002,STR0003,STR0004
30,1,Groove-4-Blind,STR0002,STR0003,STR0004
30,1,Groove-3-Blind,STR0002
30,1,Groove-3-Through,STR0002,STR0003
30,1,Groove-3-Through,STR0002,STR0003,STR0004
30,1,Rabbet-2-Through,STR0002
30,1,Tunnel-4-Through,STR0003
30,1,Tunnel-4-Through,STR0003,STR0004
; Feature : Lap Joint
30,0,Pocket-5-Blind,STR0002,STR0003
30,0,Groove-4-Blind,STR0002,STR0003
30,0,Pocket-5-Blind,STR0002,STR0003,STR0004
30,0,Groove-4-Blind,STR0002,STR0003,STR0004
30,0,Groove-3-Blind,STR0002
30,0,Groove-3-Through,STR0002,STR0003
30,0,Groove-3-Through,STR0002,STR0003,STR0004
30,0,Rabbet-2-Through,STR0002
30,0,Tunnel-4-Through,STR0003
30,0,Tunnel-4-Through,STR0003,STR0004
; Feature : Notch/Rabbet
32,0,Pocket-5-Blind,STR0002,STR0003
32,0,Groove-4-Blind,STR0002,STR0003
32,0,Pocket-5-Blind,STR0002,STR0003,STR0004
32,0,Groove-4-Blind,STR0002,STR0003,STR0004
32,0,Groove-3-Blind,STR0002
32,0,Groove-3-Through,STR0002,STR0003
32,0,Groove-3-Through,STR0002,STR0003,STR0004
32,0,Rabbet-2-Through,STR0002
32,0,Tunnel-4-Through,STR0003
32,0,Tunnel-4-Through,STR0003,STR0004
; Feature : Block Haus
33,0,Feature,
; Feature : Notch
34,0,Pocket-5-Blind,STR0002,STR0003
34,0,Groove-4-Blind,STR0002,STR0003
34,0,Pocket-5-Blind,STR0002,STR0003,STR0004
34,0,Groove-4-Blind,STR0002,STR0003,STR0004
34,0,Groove-3-Blind,STR0002
34,0,Groove-3-Through,STR0002,STR0003
34,0,Groove-3-Through,STR0002,STR0003,STR0004
34,0,Rabbet-2-Through,STR0002
34,0,Tunnel-4-Through,STR0003
34,0,Tunnel-4-Through,STR0003,STR0004
; Feature : French Ridge Lap
35,1,Feature,
; Feature : Chamfer
@@ -73,12 +85,12 @@ STR0003 = Topologia tipo LapJoint. Lama + motosega
; Feature : Block Haus Front
38,0,Feature,
; Feature : Pocket
39,0,Pocket-5-Blind,STR0002,STR0003
39,0,Groove-4-Blind,STR0002,STR0003
39,0,Pocket-5-Blind,STR0002,STR0003,STR0004
39,0,Groove-4-Blind,STR0002,STR0003,STR0004
39,0,Groove-3-Blind,STR0002
39,0,Groove-3-Through,STR0002,STR0003
39,0,Groove-3-Through,STR0002,STR0003,STR0004
39,0,Rabbet-2-Through,STR0002
39,0,Tunnel-4-Through,STR0003
39,0,Tunnel-4-Through,STR0003,STR0004
; Feature : Drilling
40,0,Feature,
; Feature : Tenon
+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

Some files were not shown because too many files have changed in this diff Show More