Compare commits
472 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 6ce4af9884 | |||
| fa36c51de0 | |||
| dd0b39df71 | |||
| ee54c32918 | |||
| 746eb9efe9 | |||
| fac9fd8877 | |||
| 28696ff4e5 | |||
| befc942be8 | |||
| 334680d3d6 | |||
| a3a29dc5bf | |||
| 50336bfad6 | |||
| 9c4fab2d3c | |||
| 00eeb482dd | |||
| 83ab68b075 | |||
| 66b273354e | |||
| 5c41793b70 | |||
| bc40db6a6e | |||
| c0cab77689 | |||
| d7fac47297 | |||
| c8431a4584 | |||
| 232a112036 | |||
| 58a98231ad | |||
| b3bf317780 | |||
| f9b62f4026 | |||
| f304df4d5b | |||
| 2d2b492fd0 | |||
| 01d4ac1c27 | |||
| 69f9669a5c | |||
| 1ac003c57c | |||
| 3b59b8f37a | |||
| 415e539e71 | |||
| ac774c2e2f | |||
| 716ebf7046 | |||
| 677e11d1e2 | |||
| 911113e853 | |||
| f7462a47f4 | |||
| 810bf4f7ab | |||
| 20b9da785e | |||
| 738b2af502 | |||
| 0f4f245827 | |||
| ddbbc894fd | |||
| a508b4bb94 | |||
| 1a14d156cf | |||
| cbb6e11515 | |||
| 4cc0b6e2b3 | |||
| 6fc055de57 | |||
| 29c2c461ac | |||
| e6d9060b80 | |||
| 45bfcdbcfc | |||
| 5f663d3362 | |||
| b65a5b758b | |||
| 9ed6cf8c30 | |||
| ed1de946c1 | |||
| aa543fdf2d | |||
| a8f000fe75 | |||
| edeb99bdb9 | |||
| c9dd712e70 | |||
| b43eca9f27 | |||
| 4215b3f5b0 | |||
| e1bce72db5 | |||
| 0290547a93 | |||
| d7c3bd83de | |||
| cb81dc1d15 | |||
| 8f2e10fc22 | |||
| 9e2bef3192 | |||
| d48d392c58 | |||
| dcf61e0442 | |||
| 3634af8f29 | |||
| f84f0a6569 | |||
| 3836764c51 | |||
| 51dec026ec | |||
| 3a4b29070e | |||
| 1eb839fce4 | |||
| d642a5ebae | |||
| f459cf94b2 | |||
| 0e4aeb49b8 | |||
| dbe0a04434 | |||
| 7eff64d3bb | |||
| 8e960954ef | |||
| 70b4927fd2 | |||
| 5a02c08965 | |||
| c6353aadc1 | |||
| 8e49d0afcc | |||
| a0e595e58d | |||
| 43aa2f1b3b | |||
| fca9eff9a7 | |||
| af1a7b768d | |||
| 0be9defb0f | |||
| 814a0feefa | |||
| 8f7969d93f | |||
| acf53145b4 | |||
| caf8e5f144 | |||
| 967df73f43 | |||
| bba5d13084 | |||
| a15b5621c7 | |||
| 6b0714ca36 | |||
| f7a07e0cc1 | |||
| ae3a0ef148 | |||
| af971f70fc | |||
| ed0098efef | |||
| a0d44ed1e4 | |||
| 3c1925ed29 | |||
| fd4e761c36 | |||
| 232751fd5d | |||
| 69259e3f80 | |||
| d72517df6b | |||
| 719d3b61af | |||
| 5bbde3e60f | |||
| dc3d534cb4 | |||
| a4c20cee6c | |||
| fd070db4d0 | |||
| b27bb97e50 | |||
| c5c45a8dd0 | |||
| b298bd24e7 | |||
| b0ca47880f | |||
| 6d9e987bc7 | |||
| 698e7d1639 | |||
| 8585797cc0 | |||
| 4c5f620117 | |||
| 87d39d747e | |||
| eb551742d1 | |||
| 188ddce206 | |||
| 0825cc7a62 | |||
| 6b2c267dfe | |||
| d51f2bc7d5 | |||
| 3d25ba23cc | |||
| 48e449d85a | |||
| 2b634dbb96 | |||
| 91dc770f92 | |||
| 825d8596dd | |||
| e4b0955846 | |||
| 0d5d97a58a | |||
| 8211fbc4b0 | |||
| f0e56275b9 | |||
| 5af77cff10 | |||
| 1e4388c091 | |||
| 702d4617a0 | |||
| 6adb856b7a | |||
| e155fee802 | |||
| 792cb4feb4 | |||
| 0d981a3d4f | |||
| fdb4bd405e | |||
| 4edd45a355 | |||
| 4a9db5d986 | |||
| 5f06b160b9 | |||
| c7b3668418 | |||
| 05cc611dae | |||
| 56ad7bb04c | |||
| a772113107 | |||
| 97dfd6f2e1 | |||
| d580a0fe08 | |||
| bbd5c67f65 | |||
| cff6dbcd7b | |||
| ee39724618 | |||
| 85f14504aa | |||
| 564a17fb35 | |||
| 27e900c944 | |||
| 7a27212cb8 | |||
| 5b10e28f07 | |||
| eb05b74a44 | |||
| ff8a753d65 | |||
| af761c95bf | |||
| 970fb60d66 | |||
| 3aecde91b9 | |||
| 05dfa1da6c | |||
| e2532b29f6 | |||
| 9d961977b2 | |||
| 8c95d5d27e | |||
| b4a1df8110 | |||
| da7d3cc08f | |||
| 1739634c58 | |||
| fd4de3742f | |||
| cdfebf83fb | |||
| d3a4ff1cd3 | |||
| 861384b5bb | |||
| e1b4089bfc | |||
| 3198287dfe | |||
| f947f761f1 | |||
| 9eeccf67a0 | |||
| 0a1c658b20 | |||
| a1f8339724 | |||
| 13f73a5363 | |||
| dd40555bbe | |||
| d9e2bdb44a | |||
| 19ce519fa6 | |||
| edf030367e | |||
| 691fbc516e | |||
| cc066f9b4f | |||
| 7ee7b63224 | |||
| 927550f438 | |||
| 41e70ccbd4 | |||
| e0d1a2905d | |||
| cfc2260997 | |||
| e12fd6824e | |||
| 48aa1477f1 | |||
| 060b919f5b | |||
| dd7c98229c | |||
| 8d8f66fd77 | |||
| 8a127f39ee | |||
| d9665b4ca9 | |||
| d46b466f71 | |||
| 10aa2352ae | |||
| fb59349345 | |||
| 03e37702e6 | |||
| 957269abf1 | |||
| 4aae1dbb54 | |||
| 607a3e61af | |||
| 717dca1089 | |||
| 4b49ebad7f | |||
| ca95265ee9 | |||
| 53fb0bdf0d | |||
| 340345725f | |||
| 0c0f6cf73b | |||
| 24245e8bd6 | |||
| a1528576b9 | |||
| e584c90c71 | |||
| 3b785a0907 | |||
| 4cd1bf526a | |||
| 86bb2e6651 | |||
| 9dbee99eca | |||
| db231be6ed | |||
| f5638e522f | |||
| 1cce5ca69a | |||
| 037e07921c | |||
| 95fdb3a250 | |||
| 1ef1c22337 | |||
| bd3a5fd318 | |||
| fe51d2746c | |||
| b9310cdeb0 | |||
| edebdb26d3 | |||
| 335604b8f2 | |||
| 53bcb4c74d | |||
| f2f1317fdf | |||
| 40259ba8d7 | |||
| 444ba1cc6c | |||
| e1bc32c22f | |||
| 85734fb7a3 | |||
| 8be4a152b7 | |||
| 60ffe9da73 | |||
| d3f88c44a9 | |||
| 46bfae300f | |||
| 81d7794b6d | |||
| c234978cab | |||
| 390c2cd14e | |||
| 81ab09a122 | |||
| 6dbf203d4d | |||
| 3e2541bd87 | |||
| 8d4212c926 | |||
| 603043b9d2 | |||
| dca28cbe1b | |||
| d77cdd6c7d | |||
| 837969e0a7 | |||
| 3bc9ef4688 | |||
| 64c800ab3e | |||
| 1dae899c6e | |||
| 27a8e785fd | |||
| 4a5e7a2af8 | |||
| a25f1b18b9 | |||
| 88ee8759a3 | |||
| 0d3cc467a9 | |||
| c0eeb01321 | |||
| 16c74add6f | |||
| 011830fb59 | |||
| c9fd830dff | |||
| 74611f99c5 | |||
| e028c9cd01 | |||
| ef6981f1b5 | |||
| 3837354ab8 | |||
| 28c9df081a | |||
| ab19bbdb6a | |||
| b2917f8b37 | |||
| 8c2d9653d7 | |||
| 2e12b09eb2 | |||
| ad652e1cd8 | |||
| a532bbf481 | |||
| a0d79c4d0f | |||
| 652141fd1d | |||
| 824f89b43f | |||
| 9a436bfdcf | |||
| d9a081f95e | |||
| ce661864a7 | |||
| 165230374e | |||
| 9888bc7f4e | |||
| fed75861be | |||
| 0c0d52afcb | |||
| 05f1130e02 | |||
| 4b1c598141 | |||
| ad1f28d670 | |||
| 9b5bd46972 | |||
| bec6ef3ea3 | |||
| 36f1ae5513 | |||
| d17673e65d | |||
| ada7d5d870 | |||
| 0023706024 | |||
| 05326f30bb | |||
| e37b3d3c3e | |||
| fb68dd28a0 | |||
| 5443173068 | |||
| 6f7ed8961f | |||
| 1c1d0f7b96 | |||
| 68a6c7d897 | |||
| 63006b913a | |||
| ed9dde9bec | |||
| 943f4f7501 | |||
| 09200303b3 | |||
| edd00a7b8f | |||
| 3b9aee2ba3 | |||
| f23085c483 | |||
| 1dac802cc0 | |||
| f36ab53755 | |||
| e141a0f4a9 | |||
| 13c227ee0b | |||
| 7a2d6696b8 | |||
| 8ed49c5cd1 | |||
| e947fb9384 | |||
| f0f0187de5 | |||
| 0a419e9b3e | |||
| ae802c8afb | |||
| 2be6204725 | |||
| b82e40d8ff | |||
| 80e309721e | |||
| 62c384a171 | |||
| 589e32cf92 | |||
| e03359b4d1 | |||
| 603edc9417 | |||
| 5032edc79a | |||
| 4e9ab24192 | |||
| 848e8ecd2c | |||
| 5a0fb8ca86 | |||
| 02d12d7106 | |||
| 67ceda8599 | |||
| a89f09b572 | |||
| eff84f5f4d | |||
| c512def05d | |||
| c29d2beec6 | |||
| 81270c324f | |||
| e47d9ac6df | |||
| 76e00c211e | |||
| 6f215f9849 | |||
| c06c2378ce | |||
| e7a08b330b | |||
| a0140dae55 | |||
| 26dff39619 | |||
| 6e45be2538 | |||
| 9cc0121229 | |||
| 0d9381b6ae | |||
| d674eec6ff | |||
| 5977a4c6db | |||
| 5233d89a5b | |||
| 0c70d6f812 | |||
| 2b929974dc | |||
| 07236b51cf | |||
| a4ed9b5b5b | |||
| 5f930e2e21 | |||
| 1a455e66de | |||
| 89d92bdcb4 | |||
| 99cbeca5c9 | |||
| 62efd89018 | |||
| 38eaed18cf | |||
| dcefd35cc9 | |||
| a7759e3b37 | |||
| 45712e604b | |||
| 44628dfa13 | |||
| fe9aaf0439 | |||
| 703fefa973 | |||
| 35e8e921f3 | |||
| 4a948aa61a | |||
| 5894e98047 | |||
| 18a4529ed4 | |||
| 99c2950ab9 | |||
| 1cd85c85b6 | |||
| 1dc1aa5a7c | |||
| c34f3dccd8 | |||
| d47343aba9 | |||
| 8807760db7 | |||
| 0ccfb2bfe6 | |||
| 562a219ffd | |||
| 67d7ce2dd9 | |||
| ab2a381808 | |||
| 2c1b0c7c79 | |||
| 2c410008fd | |||
| d548cc1b43 | |||
| ac4b2ff262 | |||
| 0b6bb3fe71 | |||
| adab6ab342 | |||
| e37d29fae3 | |||
| eafc1bec3f | |||
| c2b30d8ed9 | |||
| 6b7d15e503 | |||
| 46cdaa494b | |||
| bbf28a2ed7 | |||
| 8f1f99a628 | |||
| 6251c070ee | |||
| 3e1c7e3698 | |||
| e14e196a35 | |||
| 8800369b1e | |||
| 8dd3485048 | |||
| b7fdf8531a | |||
| 117dfa097f | |||
| fa9625b65c | |||
| feda17bd17 | |||
| 7b37da048a | |||
| 42b7decc48 | |||
| 15eab9b508 | |||
| 2256c15015 | |||
| f7201c32ed | |||
| fbfef76c64 | |||
| 7ccf3f888f | |||
| 64145e62cf | |||
| cf037fb574 | |||
| 20c10f495d | |||
| cf4b504733 | |||
| b229b21e64 | |||
| 81c0acbde1 | |||
| 7eb83ccf79 | |||
| 2f1b56ddc6 | |||
| 1271205f2c | |||
| b8a694db60 | |||
| a7664d5743 | |||
| 665113929a | |||
| f1baaa9842 | |||
| 084b6758a3 | |||
| a8c2e2fe98 | |||
| e37486db1d | |||
| f9168e8380 | |||
| 9edd39305f | |||
| 0c5373700e | |||
| 098244b109 | |||
| e553197d61 | |||
| c64aaade13 | |||
| ffe2d07918 | |||
| 89c315cdd8 | |||
| e3ab0b8f35 | |||
| 40e76a23c9 | |||
| fc6b50b345 | |||
| 8d2a9955ba | |||
| 87aa2a7ce6 | |||
| 2be4a3fe0b | |||
| d76ecbc9f6 | |||
| cc8410b0c5 | |||
| 3835f6f6e0 | |||
| cf96eb7bc3 | |||
| 3287420f41 | |||
| d013e836a0 | |||
| 3a5cba1c15 | |||
| 0c8d5516e1 | |||
| e443bd5813 | |||
| 37f85bccec | |||
| 512b907aae | |||
| e9d71ab75e | |||
| ad112ca6c3 | |||
| ce7d87a5ac | |||
| 8238767f69 | |||
| ca4141515d | |||
| 6ca555efc8 | |||
| b882f23d3e | |||
| 8c39c6a94f | |||
| e126e3f389 | |||
| 3bce7b5fd6 | |||
| 99e0bd27d9 | |||
| 456d8e903a | |||
| 14f81da3df | |||
| eb4a5e521f | |||
| 233a928dcd | |||
| db88c7bb8d | |||
| 992a115f93 | |||
| 50753dda52 | |||
| cff250ca37 | |||
| 7309ebb6a3 | |||
| c649870518 | |||
| 3d8ec03c47 | |||
| 42329d7688 |
@@ -1 +1,3 @@
|
||||
.vscode/settings.json
|
||||
Compile.bat.old
|
||||
/bin
|
||||
|
||||
@@ -0,0 +1,851 @@
|
||||
-- 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\\BeamData.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
|
||||
-- strategie di base sempre presenti
|
||||
_G.package.loaded['HEADCUT\\HEADCUT'] = nil
|
||||
_G.package.loaded['TAILCUT\\TAILCUT'] = nil
|
||||
-- libreria macchina
|
||||
_G.package.loaded.BeamData = 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( 'BeamData')
|
||||
-- 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
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
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 .. ', ' .. sFlag
|
||||
EgtOutLog( sLog)
|
||||
|
||||
-- TODO forzatura calcolo con prerotazioni. Cancellare dopo che è stata aggiunta la gestione corretta
|
||||
local bCalcBestPieceUnloadPosition = true or BEAM.FLAG == 10
|
||||
|
||||
-- Dati dei file
|
||||
-- TODO spostare a quando flag ~= 6 e 9
|
||||
local sDir, sTitle = EgtSplitPath( BEAM.FILE)
|
||||
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.b3Part = EgtGetBBoxGlob( EgtGetFirstNameInGroup( Part.id, 'Box') or GDB_ID.NULL, GDB_BB.STANDARD)
|
||||
|
||||
local Proc = FeatureLib.GetProcFromTrimesh( BEAM.FEATUREID, Part)
|
||||
Proc.nGrp = EgtGetInfo( Proc.id, 'GRP', 'i')
|
||||
Proc.nPrc = EgtGetInfo( Proc.id, 'PRC', 'i')
|
||||
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
return
|
||||
else
|
||||
PARTS[i].b3PartOriginal = b3Solid
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- recupero parametri generali da progetto
|
||||
BeamExec.GetGeneralParameters()
|
||||
|
||||
-- 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
|
||||
|
||||
-- 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)
|
||||
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)
|
||||
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)
|
||||
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, bCalcBestPieceUnloadPosition)
|
||||
if not bPbOk then
|
||||
BEAM.ERR = 18
|
||||
BEAM.MSG = sPbErr
|
||||
WriteErrToLogFile( BEAM.ERR, BEAM.MSG)
|
||||
PostErrView( BEAM.ERR, BEAM.MSG)
|
||||
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].b3Part = EgtGetBBoxGlob( EgtGetFirstNameInGroup( PARTS[i].id, 'Box') or GDB_ID.NULL, 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].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
|
||||
BeamExec.GetStrategiesFromJSONinBD( PARTS[i].sAISetupConfig)
|
||||
PARTS[i].GeneralParameters = BeamLib.GetPieceGeneralParameters( PARTS[i], GENERAL_PARAMETERS_JSON)
|
||||
PARTS[i].CombinationList = BeamExec.GetAvailableCombinations( PARTS[i], bCalcBestPieceUnloadPosition)
|
||||
|
||||
-- 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)
|
||||
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
|
||||
if not GetDataConfig() then return end
|
||||
|
||||
-- creo un gruppo temporaneo dove finiranno tutte le entità che non bisogna salvare, alla fine lo si cancella
|
||||
BeamLib.CreateTempGroup()
|
||||
|
||||
BeamExec.GetProcessings( PARTS, bCalcBestPieceUnloadPosition)
|
||||
BeamExec.GetCombinationMatrix( PARTS, bCalcBestPieceUnloadPosition)
|
||||
BeamExec.ProcessMachinings( PARTS)
|
||||
|
||||
-- si cancella gruppo temporaneo contenente entità da cancellare
|
||||
local idTempGroup = BeamLib.GetTempGroup()
|
||||
EgtErase( idTempGroup)
|
||||
|
||||
local sOutput = ''
|
||||
|
||||
-- Scrittura json risultati
|
||||
WriteResultToJson( RESULT)
|
||||
-- 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
|
||||
BEAM.ERR = 0
|
||||
BEAM.MSG = '---'
|
||||
BEAM.ROT = -( RESULT[i].nRotation 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 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)
|
||||
-- feature incompleta e altro
|
||||
elseif RESULT[i].sType == 'Feature' and RESULT[i].ChosenStrategy.sStatus == 'Not-Completed' then
|
||||
nWarnCnt = nWarnCnt + 1
|
||||
sOutput = sOutput .. string.format( '[%d,%d] %s\n', RESULT[i].idCut, RESULT[i].idTask, sMsg)
|
||||
BEAM.ERR = -19
|
||||
BEAM.MSG = 'Incomplete : Completion index ' .. RESULT[i].ChosenStrategy.dCompletionIndex .. '/5\n' .. sMsg
|
||||
BEAM.ROT = -( RESULT[i].nRotation or 1) + 1
|
||||
BEAM.CUTID = RESULT[i].idCut
|
||||
BEAM.TASKID = RESULT[i].idTask
|
||||
WriteErrToLogFile( BEAM.ERR, BEAM.MSG, BEAM.ROT, BEAM.CUTID, BEAM.TASKID)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- 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
|
||||
|
||||
-- *** 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
|
||||
WriteErrToLogFile( 19, 'Error in setup: tool/s ' .. sToolsList .. ' not found', 0, 0, 0)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
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)
|
||||
|
||||
EgtOutLog( ' +++ BatchProcess completed')
|
||||
@@ -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
|
||||
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 9.0 KiB |
|
After Width: | Height: | Size: 7.7 KiB |
|
After Width: | Height: | Size: 8.4 KiB |
|
After Width: | Height: | Size: 8.4 KiB |
|
After Width: | Height: | Size: 7.3 KiB |
|
After Width: | Height: | Size: 8.9 KiB |
|
After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 9.8 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 8.1 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 9.7 KiB |
|
After Width: | Height: | Size: 7.6 KiB |
|
After Width: | Height: | Size: 8.1 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 9.8 KiB |
|
After Width: | Height: | Size: 8.5 KiB |
|
After Width: | Height: | Size: 9.4 KiB |
|
After Width: | Height: | Size: 16 KiB |
|
After Width: | Height: | Size: 15 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 8.5 KiB |
|
After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 8.6 KiB |
|
After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 8.2 KiB |
|
After Width: | Height: | Size: 7.9 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 8.4 KiB |
|
After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 8.3 KiB |
|
After Width: | Height: | Size: 9.8 KiB |
@@ -10,6 +10,7 @@ local BeamLib = {}
|
||||
require( 'EgtBase')
|
||||
local BeamData = require( 'BeamData')
|
||||
|
||||
|
||||
EgtOutLog( ' BeamLib started', 1)
|
||||
|
||||
--TODO refactoring di queste funzioni
|
||||
@@ -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,48 +58,177 @@ 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( nRawId, OriXR, PosXR, dDeltaSucc)
|
||||
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)
|
||||
EgtAddPhase()
|
||||
-- si aprono i limiti tavola per permettere rotazioni di pezzi più larghi della tavola
|
||||
EgtSetTableAreaOffset( 2000, 2000, 2000, 2000)
|
||||
local dRawMove = 0
|
||||
while nRawId do
|
||||
EgtKeepRawPart( nRawId)
|
||||
EgtMoveToCornerRawPart( nRawId, OriXR, PosXR)
|
||||
EgtMoveRawPart( nRawId, Vector3d( - dRawMove, 0, 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( nRawId):getDimX()
|
||||
nRawId = EgtGetNextRawPart( nRawId)
|
||||
dRawMove = dRawMove + EgtGetRawPartBBox( idRaw):getDimX()
|
||||
idRaw = EgtGetNextRawPart( idRaw)
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
--- funzione che ruota il pezzo, da lanciare per creare la disposizione corretta
|
||||
function BeamLib.RotatePart( Part, nPosition)
|
||||
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 nPosition == 1 then
|
||||
if nNumberOfRotations == 0 then
|
||||
; -- il pezzo è già in posizione
|
||||
-- rotazione 90°
|
||||
elseif nPosition == 2 then
|
||||
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
|
||||
@@ -119,12 +236,13 @@ function BeamLib.RotatePart( Part, nPosition)
|
||||
local nRId = Part.idRaw
|
||||
while nRId do
|
||||
if bPreMove then EgtMoveRawPart( nRId, vtMove) end
|
||||
EgtRotateRawPart( nRId, X_AX(), EgtIf( BeamData.RIGHT_LOAD, -90, 90))
|
||||
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 nPosition == 3 then
|
||||
elseif nNumberOfRotations == 2 then
|
||||
-- ribalto le travi della fase corrente
|
||||
local nRId = Part.idRaw
|
||||
while nRId do
|
||||
@@ -132,7 +250,7 @@ function BeamLib.RotatePart( Part, nPosition)
|
||||
nRId = EgtGetNextRawPart( nRId)
|
||||
end
|
||||
-- rotazione 270°
|
||||
elseif nPosition == 4 then
|
||||
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
|
||||
@@ -140,7 +258,8 @@ function BeamLib.RotatePart( Part, nPosition)
|
||||
local nRId = Part.idRaw
|
||||
while nRId do
|
||||
if bPreMove then EgtMoveRawPart( nRId, vtMove) end
|
||||
EgtRotateRawPart( nRId, X_AX(), EgtIf( BeamData.RIGHT_LOAD, 90, -90))
|
||||
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
|
||||
@@ -168,11 +287,29 @@ function BeamLib.CreateOrEmptyAddGroup( PartId)
|
||||
-- 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))
|
||||
EgtSetColor( AddGrpId, Color3d( 80, 160, 160, 25))
|
||||
|
||||
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#")
|
||||
EgtSetLevel( idTempGroup, GDB_LV.TEMP)
|
||||
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
|
||||
@@ -190,25 +327,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
|
||||
@@ -216,7 +355,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)
|
||||
@@ -251,7 +390,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)
|
||||
@@ -285,7 +424,7 @@ function BeamLib.GetNearestParalOpposite( vtRef, vtNorm)
|
||||
return nil
|
||||
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)
|
||||
@@ -309,7 +448,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
|
||||
@@ -320,41 +459,186 @@ 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] 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].sType == 'd' then
|
||||
Parameters[CustomParameters[i].sName] = tonumber( CustomParameters[i].sValue)
|
||||
else --CustomParameters[i].sType == 's' or CustomParameters[i].sType == 'combo'
|
||||
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
|
||||
-- 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
|
||||
|
||||
-- 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')
|
||||
-- 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
|
||||
|
||||
return UpdatedParameters
|
||||
end
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function BeamLib.GetChainSawInitAngs( vtN, vtO, nInd)
|
||||
if BeamData.GetChainSawInitAngs then
|
||||
return BeamData.GetChainSawInitAngs( vtN, vtO, nInd)
|
||||
@@ -371,7 +655,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
|
||||
@@ -393,7 +677,7 @@ function BeamLib.GetBlockedAxis( nToolIndex, sBlockedAxis, b3Raw, vtTool, vtOut)
|
||||
return ''
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function BeamLib.BinaryToDecimal( dNumber)
|
||||
local sNumberToConvert = tostring( dNumber)
|
||||
local dResult = 0
|
||||
@@ -408,7 +692,7 @@ function BeamLib.BinaryToDecimal( dNumber)
|
||||
return dResult
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function BeamLib.DecimalToBinary( dNumber)
|
||||
local sNumberToConvert = tostring( dNumber)
|
||||
local n = sNumberToConvert
|
||||
@@ -433,7 +717,7 @@ function BeamLib.DecimalToBinary( dNumber)
|
||||
return tonumber( sResult)
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function BeamLib.CalculateStringBinaryFormat( dNumber, CharNumber)
|
||||
local NumberString = tostring( dNumber)
|
||||
while #NumberString < CharNumber do
|
||||
@@ -443,10 +727,14 @@ function BeamLib.CalculateStringBinaryFormat( dNumber, CharNumber)
|
||||
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
|
||||
@@ -473,5 +761,185 @@ function BeamLib.TableCopyDeep( OriginalTable)
|
||||
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
|
||||
if #StrategyList.FEATURE[i].TopologyList == 1 and StrategyList.FEATURE[i].TopologyList[1].sName == 'Feature' then
|
||||
return BeamLib.TableCopyDeep( StrategyList.FEATURE[i].TopologyList[1].StrategyList)
|
||||
else
|
||||
-- cerco tra le topologie
|
||||
for j = 1, #StrategyList.FEATURE[i].TopologyList do
|
||||
-- se trovo la topologia
|
||||
if Proc.Topology.sName == StrategyList.FEATURE[i].TopologyList[j].sName then
|
||||
-- ritorno le strategie disponibili per la feature che sto analizzando
|
||||
return BeamLib.TableCopyDeep( StrategyList.FEATURE[i].TopologyList[j].StrategyList)
|
||||
end
|
||||
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
|
||||
|
||||
@@ -0,0 +1,680 @@
|
||||
-- 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( 'BeamData')
|
||||
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- creo i piani paralleli
|
||||
-- GetParallelPlanes: restituisce un vettore con gli indici delle superfici
|
||||
-- nAddGrpId: 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( nAddGrpId, 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( nAddGrpId, 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:
|
||||
-- nAddGrpId: il layer
|
||||
-- TabParallelPlanes: tabella delle superfici dei piani paralleli
|
||||
-- TabOrtoPlanes: tabella delle superfici dei piani ortogonali
|
||||
-- stampo l'ordine dei piani di taglio (prima tagli ortogonali piu' esterni poi taglio parallelo collettivo)
|
||||
local function GetOrderedCutTable( nAddGrpId, TabParallelPlanes, TabOrtoPlanes)
|
||||
local StepParallel = #TabParallelPlanes
|
||||
local StepOrto = #TabOrtoPlanes
|
||||
local TabellaOrderParallelCut1 = {}
|
||||
|
||||
for IndexTmP=1, StepParallel do
|
||||
TabellaOrderParallelCut1[IndexTmP] = {}
|
||||
for IndexOrto=1, StepOrto do
|
||||
local ptOrtoN, vtNOrtoN = EgtSurfTmFacetCenter( TabOrtoPlanes[IndexOrto ], 0, GDB_ID.ROOT)
|
||||
local Copy1Id = EgtCopySurfTmFacet( TabParallelPlanes[IndexTmP], 0, nAddGrpId)
|
||||
local Copy2Id = EgtCopySurfTmFacet( TabParallelPlanes[IndexTmP], 0, nAddGrpId)
|
||||
if Copy1Id and ptOrtoN then
|
||||
EgtCutSurfTmPlane( Copy1Id, ptOrtoN, -vtNOrtoN, false, GDB_RT.GLOB)
|
||||
EgtCutSurfTmPlane( Copy2Id, ptOrtoN, vtNOrtoN, false, GDB_RT.GLOB)
|
||||
local nFacet1 = EgtSurfTmFacetCount( Copy1Id)
|
||||
local nFacet2 = EgtSurfTmFacetCount( Copy2Id)
|
||||
if nFacet1 < 1 then
|
||||
EgtErase( Copy1Id)
|
||||
EgtErase( Copy2Id)
|
||||
EgtCutSurfTmPlane( TabParallelPlanes[IndexTmP], ptOrtoN, vtNOrtoN, false, GDB_RT.GLOB)
|
||||
elseif nFacet2 < 1 then
|
||||
EgtErase( Copy1Id)
|
||||
EgtErase( Copy2Id)
|
||||
break
|
||||
else
|
||||
table.insert( TabellaOrderParallelCut1[IndexTmP], Copy1Id)
|
||||
EgtErase( Copy2Id)
|
||||
EgtCutSurfTmPlane( TabParallelPlanes[IndexTmP], ptOrtoN, vtNOrtoN, false, GDB_RT.GLOB)
|
||||
end
|
||||
end
|
||||
end
|
||||
table.insert(TabellaOrderParallelCut1[IndexTmP], TabParallelPlanes[IndexTmP])
|
||||
end
|
||||
return TabellaOrderParallelCut1
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- GetOrtoCutCenter:
|
||||
-- idFacet: l'id della faccia
|
||||
-- ptC: il punto centrale della faccia
|
||||
-- vtN: il versore normale della faccia
|
||||
-- vtO: il versore dei piani ortogonali
|
||||
-- dOffsetEff: offset della distanza dal punto centrale
|
||||
-- Verifica se l'asse X del box costruito sopra la superficie è più grande di un certo offset
|
||||
local function GetOrtoCutCenter( FacetId, ptC, vtN, vtO, dOffsetEff, dMinNzDownUp)
|
||||
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) and vtN:getZ() > dMinNzDownUp 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, dMinNzDownUp)
|
||||
|
||||
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 and vtN1:getZ() > dMinNzDownUp then
|
||||
local nAddGrpId = EgtGetParent( Cut1Id)
|
||||
local SurfId = EgtSurfTmBySewing( nAddGrpId, { Cut1Id, Cut2Id})
|
||||
--EgtSetColor( SurfId, Color3d( FUCHSIA(), 60))
|
||||
EgtErase( CutOId)
|
||||
table.remove( CutTable[1], 1)
|
||||
table.remove( CutTable[2], 1)
|
||||
table.remove( CutTable[2], 1)
|
||||
table.insert( CutTable[2], 1, SurfId)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------------------------------------------------------------------------
|
||||
-- ricavo i vertici del box
|
||||
local function CalcolaPuntiEstremiBox( 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( nAddGrpId, 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( nAddGrpId)
|
||||
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 nAddGrpId = BeamLib.GetAddGroup( Part.id)
|
||||
|
||||
-- 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
|
||||
-- distanza ridotta tra piani ortogonali - usato in tagli orizzontali con affondamento verticale
|
||||
local dOffsetOrthogonalReduced = OptionalParameters.dOffsetOrthogonalReduced or BeamData.MAX_DIM_HTCUT
|
||||
-- numero massimo piani paralleli
|
||||
local nStepParallel = OptionalParameters.nStepParallel or 100
|
||||
-- numero massimo piani perpendicolari
|
||||
local nStepOrthogonal = OptionalParameters.nStepOrthogonal or 100
|
||||
-- distanza tra piani paralleli e piani di taglio (era sempre 0, serve???)
|
||||
local dTolerance = OptionalParameters.dTolerance or 0
|
||||
-- inclinazione limite per taglio da sotto
|
||||
local dMinNzDownUp = OptionalParameters.dMinNzDownUp or -2
|
||||
|
||||
--Ricavo le altezze dei BoundingBox contenente feature e estremi del grezzo
|
||||
local TBoxPoint = CalcolaPuntiEstremiBox( b3BoxDicing)
|
||||
TBoxPoint = VerificaEstremiGrezzo( ptCMainFace, vtNMainFace, TBoxPoint)
|
||||
if ptCSubordinateFace and vtNSubordinateFace then
|
||||
TBoxPoint = VerificaEstremiGrezzo( ptCSubordinateFace, vtNSubordinateFace, TBoxPoint)
|
||||
end
|
||||
local dElevP = DistanzaMassima( nAddGrpId, ptCMainFace, vtNMainFace, ptCSubordinateFace, vtNSubordinateFace, b3BoxDicing, TBoxPoint)
|
||||
local dElevO
|
||||
if ptCSubordinateFace and vtNSubordinateFace and not AreOppositeVectorApprox( vtNSubordinateFace, vtNMainFace) then
|
||||
dElevO = DistanzaMassima( nAddGrpId, ptCSubordinateFace, vtNSubordinateFace, ptCMainFace, vtNMainFace, b3BoxDicing, TBoxPoint)
|
||||
end
|
||||
|
||||
-- TODO parte sotto da aggiungere???? se sì va passata anche la dimensione cubetto ridotta dOffsetOrthogonalReduced
|
||||
-- se non c'è testa da sotto e normali senza componenti in Y con faccia quasi verticale e trave non alta, uso per offset i limiti dei tagli di testa e coda
|
||||
-- if not BD.TURN and not BD.DOWN_HEAD and abs( vtNPlanes:getY()) < 0.1 and vtNPlanes:getZ() < 0.7071 and ( not vtNBond or abs( vtNBond:getY()) < 0.1) and BBoxRawPart:getDimZ() < BD.MIN_DIM_HBEAM then
|
||||
-- dOffsetOrthogonal = dOffsetOrthogonalReduced
|
||||
-- end
|
||||
|
||||
-- aggiungo piccolo extra agli offset
|
||||
dOffsetParallel = dOffsetParallel + 10 * GEO.EPS_SMALL
|
||||
dOffsetOrthogonal = dOffsetOrthogonal + 10 * GEO.EPS_SMALL
|
||||
|
||||
-- se piani non ortogonali, diminuisco la distanza di offset opportunamente
|
||||
local dOffsetParallelOriginal = dOffsetParallel
|
||||
if not bGetOrtoPlanes then
|
||||
local dCoeff = ( vtNMainFace ^ vtNSubordinateFace):len()
|
||||
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( nAddGrpId, 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( nAddGrpId, b3BoxDicing, ptCSubordinateFace, vtNSubordinateFace, 0, dOffsetOrthogonal, nStepOrthogonal, Color3d( GREEN(), 60), dTolerance, false, ptCMainFace, vtNMainFace)
|
||||
for i = #TabFromIn, 1, -1 do
|
||||
table.insert( TabellaTmSurfOrto, TabFromIn[i])
|
||||
end
|
||||
local TabellaOrderParallelCut = GetOrderedCutTable( nAddGrpId, TabellaTmSurfP, TabellaTmSurfOrto) -- Ottiene la tabella dei tagli paralleli ordinati
|
||||
local TabellaOrderOrtoCut = GetOrderedCutTable( nAddGrpId, TabellaTmSurfOrto, TabellaTmSurfP) -- Ottiene la tabella dei tagli ortogonali da riordinare per strato
|
||||
|
||||
TabGREEN = SortOrtoCutsByNormalMethod( TabellaOrderParallelCut, TabellaOrderOrtoCut) -- I tagli ortogonali vengono ordinati per strato
|
||||
TabFUCHSIA = TabellaOrderParallelCut -- I tagli paralleli sono già ordinati
|
||||
|
||||
-- orientamento da definire
|
||||
else
|
||||
for PlnInd = 1, #TabellaTmSurfP do
|
||||
-- piano interno
|
||||
local ptCInner, vtNInner = EgtSurfTmFacetCenter( TabellaTmSurfP[PlnInd], 0, GDB_ID.ROOT)
|
||||
-- eventuale piano esterno
|
||||
local ptCOuter, vtNOuter = nil, nil
|
||||
if PlnInd > 1 then
|
||||
ptCOuter, vtNOuter = EgtSurfTmFacetCenter( TabellaTmSurfP[PlnInd-1], 0, GDB_ID.ROOT)
|
||||
vtNOuter = -vtNOuter
|
||||
end
|
||||
-- calcolo la direzione dei piani ortogonali
|
||||
local vtO = VectorFromUprightOrtho( vtNInner)
|
||||
if vtNInner:getZ() > -0.0175 or vtNInner:getZ() < dMinNzDownUp or abs( vtNInner:getY()) > 0.8 then
|
||||
vtO:rotate( vtNInner, 90)
|
||||
-- se diretto troppo ortogonalmente all'asse trave e taglio non da sotto, lo ruoto ulteriormente
|
||||
if ( abs( vtO:getY()) > 4 * abs( vtO:getX()) or b3BoxDicing:getDimZ() > 620) and vtNInner:getZ() > dMinNzDownUp then
|
||||
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, dMinNzDownUp)
|
||||
|
||||
if OffsetRel and CopyPlane and dCenOffs then
|
||||
ptCInner = ptCInner + dCenOffs * vtO
|
||||
local TabRight = GetParallelPlanes( nAddGrpId, b3BoxDicing, ptCStart, vtO, CopyPlane, -OffsetRel, nStepOrthogonal, Color3d( GREEN(), 60),
|
||||
dTolerance, false, ptCInner, vtNInner, ptCOuter, vtNOuter)
|
||||
if CopyPlane == 0 then
|
||||
CopyPlane = 1
|
||||
end
|
||||
local TabLeft = GetParallelPlanes( nAddGrpId, b3BoxDicing, ptCStart, vtO, CopyPlane, OffsetRel, nStepOrthogonal, Color3d( GREEN(), 60),
|
||||
dTolerance, false, ptCInner, vtNInner, ptCOuter, vtNOuter)
|
||||
-- carico la tabella con gli indici riordinati
|
||||
local TempOrtoTab = {}
|
||||
for i = #TabLeft, 1, -1 do
|
||||
table.insert( TempOrtoTab, TabLeft[i])
|
||||
end
|
||||
for i = 1, #TabRight do
|
||||
table.insert( TempOrtoTab, TabRight[i])
|
||||
end
|
||||
-- creo una tabella per ogni piano per generare i tagli sulla Inner
|
||||
local TempParTab = GetOrderedCutTable( nAddGrpId, {TabellaTmSurfP[PlnInd]}, TempOrtoTab)
|
||||
for i = 1, #TempParTab do
|
||||
table.insert( TabFUCHSIA, TempParTab[i])
|
||||
end
|
||||
table.insert( TabGREEN, TempOrtoTab)
|
||||
else
|
||||
table.insert( TabFUCHSIA, {TabellaTmSurfP[PlnInd]})
|
||||
table.insert( TabGREEN, {})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Se sono state costruite non più di una faccia parallela e una faccia perpendicolare, allora non servono e tengo le originali
|
||||
if #TabGREEN == 1 and #TabGREEN[1] <= 1 and #TabFUCHSIA == 1 and #TabFUCHSIA[1] <= 1 then
|
||||
if #TabGREEN[1] == 1 then
|
||||
EgtErase( TabGREEN[1][1])
|
||||
end
|
||||
TabGREEN = {}
|
||||
if #TabFUCHSIA[1] == 1 then
|
||||
EgtErase( TabFUCHSIA[1][1])
|
||||
end
|
||||
TabFUCHSIA = {}
|
||||
end
|
||||
|
||||
-- Si uniscono le tabelle dei tagli ortogonali e paralleli in una sola tabella
|
||||
local UltimateTable = TableMesh( TabGREEN, TabFUCHSIA)
|
||||
|
||||
-- Se esiste la superficie limitante (nFacet == 2) verifica se il taglio più esterno è superfluo e quindi viene eliminato
|
||||
if not bGetOrtoPlanes then
|
||||
VerifyFirstOrthoCut( UltimateTable, dOffsetParallelOriginal, b3BoxDicing, dMinNzDownUp)
|
||||
-- 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
|
||||
@@ -98,10 +98,69 @@ function FaceData.GetFacesByAdjacencyNumber( Proc)
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function FaceData.GetFacesInfo( Proc, Part)
|
||||
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.sType = 'Standard'
|
||||
CurrentEdge.id = i - 1
|
||||
|
||||
table.insert( Edges, CurrentEdge)
|
||||
end
|
||||
|
||||
return nFaceType, Edges
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function FaceData.GetFacesInfo( Proc, Part, FacesToGet)
|
||||
EgtOutLog( '---Faces START---')
|
||||
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
|
||||
@@ -109,25 +168,28 @@ 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].ptCenter, Faces[i].vtN = EgtSurfTmFacetCenter( Proc.id, i - 1, GDB_ID.ROOT)
|
||||
if Proc.nFct < 6 then
|
||||
if Proc.nFct < 6 or FaceIsToGet( i) then
|
||||
-- frame OCS faccia
|
||||
Faces[i].vtFrameHV = Frame3d( Faces[i].ptCenter, Faces[i].vtN)
|
||||
-- elevazione calcolata rispetto al box della parte
|
||||
Faces[i].dElevation = EgtSurfTmFacetElevationInBBox( Proc.id, i - 1, Part.b3Solid, true, GDB_ID.ROOT)
|
||||
Faces[i].dElevation = EgtSurfTmFacetElevationInBBox( Proc.id, i - 1, Part.b3Part, true, GDB_ID.ROOT)
|
||||
-- TODO qui sarebbe meglio l'area vera e non quella del rettangolo minimo
|
||||
local _, dLongEdgeDimension, dShortEdgeDimension = EgtSurfTmFacetMinAreaRectangle( Proc.id, i - 1, GDB_ID.ROOT)
|
||||
Faces[i].dArea = dShortEdgeDimension * dLongEdgeDimension
|
||||
local _, dLongDimension, dShortDimension = EgtSurfTmFacetMinAreaRectangle( Proc.id, i - 1, GDB_ID.ROOT)
|
||||
Faces[i].dArea = dShortDimension * dLongDimension
|
||||
Faces[i].dLMinRectangle = dLongDimension
|
||||
Faces[i].dWMinRectangle = dShortDimension
|
||||
|
||||
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
|
||||
Faces[i].Edges = Edges
|
||||
|
||||
-- TODO valutare se fare un output unico alla fine o gestire log in altro modo
|
||||
EgtOutLog( 'Facet ' .. Faces[i].id .. ' of ' .. Proc.nFct - 1)
|
||||
@@ -152,18 +214,96 @@ function FaceData.GetFacesInfo( Proc, Part)
|
||||
return Faces
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function FaceData.IsFaceRectangular( Proc, idFace)
|
||||
local nAddGrpId = BeamLib.GetAddGroup( Proc.idPart)
|
||||
local nContourId, nContourCnt = EgtExtractSurfTmFacetLoops( Proc.id, idFace, nAddGrpId)
|
||||
if nContourCnt > 1 then
|
||||
error( 'IsFaceRectangular : too many loops')
|
||||
end
|
||||
|
||||
local bIsRectangular = EgtCurveIsARectangle( nContourId)
|
||||
|
||||
-- elimino curve create
|
||||
for i = 1, nContourCnt do
|
||||
EgtErase( nContourId + i - 1)
|
||||
end
|
||||
|
||||
return bIsRectangular
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function FaceData.IsFaceRhomboid( Proc, idFace)
|
||||
local nAddGrpId = BeamLib.GetAddGroup( Proc.idPart)
|
||||
local nContourId, nContourCnt = EgtExtractSurfTmFacetLoops( Proc.id, idFace, nAddGrpId)
|
||||
if nContourCnt > 1 then
|
||||
error( 'IsFaceRectangular : too many loops')
|
||||
end
|
||||
|
||||
local bIsTrapezoid = EgtCurveIsATrapezoid( nContourId)
|
||||
local bIsRhomboid = false
|
||||
-- un parallelogramma è un trapezoide con i lati paralleli a due a due
|
||||
if bIsTrapezoid
|
||||
and AreOppositeVectorApprox( Proc.Faces[idFace + 1].Edges[1].vtN, Proc.Faces[idFace + 1].Edges[3].vtN)
|
||||
and AreOppositeVectorApprox( Proc.Faces[idFace + 1].Edges[2].vtN, Proc.Faces[idFace + 1].Edges[4].vtN) then
|
||||
|
||||
bIsRhomboid = true
|
||||
end
|
||||
|
||||
-- elimino curve create
|
||||
for i = 1, nContourCnt do
|
||||
EgtErase( nContourId + i - 1)
|
||||
end
|
||||
|
||||
return bIsRhomboid
|
||||
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)
|
||||
@@ -180,7 +320,7 @@ local function GetTunnelFaces( Proc, Part)
|
||||
end
|
||||
|
||||
-- faccia centrale
|
||||
local nMiddleTmId = EgtSurfTmPlaneInBBox( nAddGrpId, ptTunnelCenter, vtTunnelDirection, Part.b3Solid, GDB_ID.ROOT)
|
||||
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( nMiddleTmId, Proc.Faces[i].ptCenter, -Proc.Faces[i].vtN, false, GDB_ID.ROOT)
|
||||
@@ -197,7 +337,7 @@ local function GetTunnelFaces( Proc, Part)
|
||||
|
||||
-- TODO c'è un modo più elegante per raccogliere le informazioni delle facce aggiunte
|
||||
TunnelAddedFaces.MiddleFaceTm.sType = 'Tunnel'
|
||||
TunnelAddedFaces.MiddleFaceTm.nFct = Proc.nFct + 1
|
||||
TunnelAddedFaces.MiddleFaceTm.nFct = EgtSurfTmFacetCount( TunnelAddedFaces.MiddleFaceTm.id)
|
||||
TunnelAddedFaces.MiddleFaceTm.Faces = FaceData.GetFacesInfo( TunnelAddedFaces.MiddleFaceTm, Part)
|
||||
|
||||
return TunnelAddedFaces
|
||||
@@ -209,10 +349,22 @@ 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
|
||||
|
||||
if Proc.nFct == 1 then
|
||||
return { Proc.Faces[1]}
|
||||
end
|
||||
|
||||
-- la faccia di fondo ha sempre Fct - 1 adiacenze
|
||||
local FacesByAdjacencyNumber = FaceData.GetFacesByAdjacencyNumber( Proc)
|
||||
if FacesByAdjacencyNumber then
|
||||
@@ -236,20 +388,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
|
||||
@@ -262,27 +422,28 @@ 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.dLengthOnX = CurrentEdge.dLength * CurrentEdge.vtToolDirection:getY()
|
||||
CurrentEdge.dElevation = BottomFaces[1].Edges[i].Elev
|
||||
CurrentEdge.bIsOpen = BottomFaces[1].Edges[i].Open
|
||||
CurrentEdge.bIsStartOpen = BottomFaces[1].Edges[nPreviousEdgeIndex].Open
|
||||
CurrentEdge.bIsEndOpen = BottomFaces[1].Edges[nNextEdgeIndex].Open
|
||||
CurrentEdge.idAdjacentFace = BottomFaces[1].Edges[i].idAdjacentFace
|
||||
CurrentEdge.vtN = BottomFaces[1].Edges[i].vtN
|
||||
CurrentEdge.dLength = BottomFaces[1].Edges[i].dLength
|
||||
CurrentEdge.bIsOpen = BottomFaces[1].Edges[i].bIsOpen
|
||||
CurrentEdge.dElevation = BottomFaces[1].Edges[i].dElevation
|
||||
CurrentEdge.bIsStartOpen = BottomFaces[1].Edges[i].bIsStartOpen
|
||||
CurrentEdge.bIsEndOpen = BottomFaces[1].Edges[i].bIsEndOpen
|
||||
|
||||
if i == nFirstLongEdgeIndex then
|
||||
BottomFaces[1].MainEdges.LongEdges[1] = CurrentEdge
|
||||
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
|
||||
|
||||
@@ -295,6 +456,8 @@ local function GetLongFaces( Proc, MainFaces)
|
||||
|
||||
if Proc.nFct > 5 then
|
||||
error( 'GetLongFaces : Topology not implemented')
|
||||
elseif Proc.nFct == 1 then
|
||||
return {}
|
||||
end
|
||||
|
||||
local BottomFace
|
||||
@@ -316,11 +479,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
|
||||
@@ -333,6 +496,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 = {}
|
||||
@@ -348,14 +517,13 @@ local function GetLongFaces( Proc, MainFaces)
|
||||
end
|
||||
|
||||
local CurrentEdge = {}
|
||||
CurrentEdge.idAdjacentFace = LongFaces[i].Edges[j].Adj
|
||||
CurrentEdge.vtToolDirection = Vector3d( LongFaces[i].Edges[j].Norm)
|
||||
CurrentEdge.dLength = LongFaces[i].Edges[j].Len
|
||||
CurrentEdge.dLengthOnX = CurrentEdge.dLength * CurrentEdge.vtToolDirection:getY()
|
||||
CurrentEdge.dElevation = LongFaces[i].Edges[j].Elev
|
||||
CurrentEdge.bIsOpen = LongFaces[i].Edges[j].Open
|
||||
CurrentEdge.bIsStartOpen = LongFaces[i].Edges[nPreviousEdgeIndex].Open
|
||||
CurrentEdge.bIsEndOpen = LongFaces[i].Edges[nNextEdgeIndex].Open
|
||||
CurrentEdge.idAdjacentFace = LongFaces[i].Edges[j].idAdjacentFace
|
||||
CurrentEdge.vtN = LongFaces[i].Edges[j].vtN
|
||||
CurrentEdge.dLength = LongFaces[i].Edges[j].dLength
|
||||
CurrentEdge.bIsOpen = LongFaces[i].Edges[j].bIsOpen
|
||||
CurrentEdge.dElevation = LongFaces[i].Edges[j].dElevation
|
||||
CurrentEdge.bIsStartOpen = LongFaces[i].Edges[j].bIsStartOpen
|
||||
CurrentEdge.bIsEndOpen = LongFaces[i].Edges[j].bIsEndOpen
|
||||
|
||||
if Proc.Topology.sFamily == 'Tunnel' then
|
||||
if CurrentEdge.idAdjacentFace > -1 then
|
||||
@@ -369,10 +537,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
|
||||
@@ -392,6 +560,8 @@ local function GetSideFaces( Proc, MainFaces)
|
||||
|
||||
if Proc.nFct > 5 then
|
||||
error( 'GetSideFaces : Topology not implemented')
|
||||
elseif Proc.nFct == 1 then
|
||||
return {}
|
||||
end
|
||||
|
||||
local BottomFace
|
||||
@@ -403,11 +573,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])
|
||||
@@ -420,6 +592,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 = {}
|
||||
@@ -435,14 +613,13 @@ local function GetSideFaces( Proc, MainFaces)
|
||||
end
|
||||
|
||||
local CurrentEdge = {}
|
||||
CurrentEdge.idAdjacentFace = SideFaces[i].Edges[j].Adj
|
||||
CurrentEdge.vtToolDirection = Vector3d( SideFaces[i].Edges[j].Norm)
|
||||
CurrentEdge.dLength = SideFaces[i].Edges[j].Len
|
||||
CurrentEdge.dLengthOnX = CurrentEdge.dLength * CurrentEdge.vtToolDirection:getY()
|
||||
CurrentEdge.dElevation = SideFaces[i].Edges[j].Elev
|
||||
CurrentEdge.bIsOpen = SideFaces[i].Edges[j].Open
|
||||
CurrentEdge.bIsStartOpen = SideFaces[i].Edges[nPreviousEdgeIndex].Open
|
||||
CurrentEdge.bIsEndOpen = SideFaces[i].Edges[nNextEdgeIndex].Open
|
||||
CurrentEdge.idAdjacentFace = SideFaces[i].Edges[j].idAdjacentFace
|
||||
CurrentEdge.vtN = SideFaces[i].Edges[j].vtN
|
||||
CurrentEdge.dLength = SideFaces[i].Edges[j].dLength
|
||||
CurrentEdge.bIsOpen = SideFaces[i].Edges[j].bIsOpen
|
||||
CurrentEdge.dElevation = SideFaces[i].Edges[j].dElevation
|
||||
CurrentEdge.bIsStartOpen = SideFaces[i].Edges[j].bIsStartOpen
|
||||
CurrentEdge.bIsEndOpen = SideFaces[i].Edges[j].bIsEndOpen
|
||||
|
||||
if Proc.Topology.sFamily == 'Tunnel' then
|
||||
if CurrentEdge.idAdjacentFace > -1 then
|
||||
@@ -454,10 +631,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
|
||||
@@ -473,15 +650,20 @@ 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.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
|
||||
|
||||
@@ -494,6 +676,7 @@ function FaceData.GetMainFaces( Proc, Part)
|
||||
Logs.WriteMainFacesLog( Proc, MainFaces)
|
||||
end
|
||||
else
|
||||
MainFaces = nil
|
||||
EgtOutLog( '---MainFaces NOT NEEDED---')
|
||||
end
|
||||
|
||||
|
||||
@@ -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
|
||||
---------------------------------------------------------------------
|
||||
|
||||
@@ -6,150 +6,131 @@ local Logs = {}
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function Logs.WriteFeaturesLog( ProcessingsOnPart, PartInfo)
|
||||
EgtOutLog( ' === === === === === === === === === === FEATURES STRATEGIES === === === === === === === === === === === ===')
|
||||
EgtOutLog( ' Feature ID | BTL POSITION | 90 ROTATION | 180 ROTATION | 270 ROTATION |')
|
||||
EgtOutLog( '----------------------------------------------------------------------------------------------------------')
|
||||
|
||||
local nProcessingsNumber
|
||||
local nFirstAvailableRotation
|
||||
-- ricerco prima rotazione effettivamente calcolata. In genere è sempre la prima
|
||||
for i = 1, 4 do
|
||||
if PartInfo.CombinationList.Rotations[i] == 1 then
|
||||
nProcessingsNumber = #ProcessingsOnPart.Rotation[i]
|
||||
nFirstAvailableRotation = i
|
||||
break
|
||||
end
|
||||
local nCycles = 1
|
||||
local nOffsetIndex = 0
|
||||
if #ProcessingsOnPart.Rotation > 4 then
|
||||
nCycles = 2
|
||||
end
|
||||
|
||||
-- per ogni feature
|
||||
for ProcLog = 1, nProcessingsNumber do
|
||||
-- ricavo il massimo numero di strategie per feature
|
||||
local nMaxStrategiesPerFeature = 0
|
||||
for nRotLog = 1, 4 do
|
||||
if PartInfo.CombinationList.Rotations[nRotLog] == 1 and ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies then
|
||||
nMaxStrategiesPerFeature = max( nMaxStrategiesPerFeature, #ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies)
|
||||
for nCycle = 1, nCycles do
|
||||
local nStartIndex = 1 + nOffsetIndex
|
||||
local nEndIndex = 4 + nOffsetIndex
|
||||
if nCycle == 1 then
|
||||
EgtOutLog( ' === === === === === === === === === === FEATURES STRATEGIES === === === === === === === === === === === ===')
|
||||
else
|
||||
EgtOutLog( ' === === === === === === === === === === === === === === === === === === === === === === === === === === ===')
|
||||
EgtOutLog( ' === === === === === === === === FEATURES STRATEGIES PIECE INVERTED === === === === === === === === === ===')
|
||||
end
|
||||
EgtOutLog( ' 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
|
||||
|
||||
-- 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 .. ' '
|
||||
-- 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
|
||||
sLogLine = sLogLine .. '|'
|
||||
else
|
||||
sLogLine = ' |'
|
||||
end
|
||||
|
||||
for nRotLog = 1, 4 do
|
||||
-- se rotazione abilitata
|
||||
if PartInfo.CombinationList.Rotations[nRotLog] == 1 then
|
||||
-- se ci sono strategie
|
||||
if ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies and ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies] then
|
||||
-- se la strategia è stat processata e ha un risultato
|
||||
if ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies].Result then
|
||||
-- leggo lo stato della strategia per aggiungere un suffisso
|
||||
local sStatusStrategy = ' '
|
||||
if not ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies].Result.sStatus or
|
||||
ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies].Result.sStatus == 'Not-Applicable' then
|
||||
sStatusStrategy = 'N'
|
||||
elseif ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies].Result.sStatus == 'Completed' then
|
||||
sStatusStrategy = 'C'
|
||||
elseif ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies].Result.sStatus == 'Not-Completed' then
|
||||
sStatusStrategy = 'P'
|
||||
-- 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 = '----'
|
||||
sIndexes = ' (C:---|Q:---|T:---)'
|
||||
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
|
||||
-- se c'è una chosen strategy, si aggiunge prefisso '*' per indicare nel log qual è la strategia che è stata scelta
|
||||
local nIndexBestStrategy = ProcessingsOnPart.Rotation[nRotLog][ProcLog].nIndexBestStrategy or 0
|
||||
local sLogLineProc = EgtIf( nIndexBestStrategy == nCountStrategies, '*', '') ..
|
||||
tostring( ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies].Result.dCompositeRating) ..' (' ..
|
||||
tostring( ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies].sStrategyId) .. ')' ..
|
||||
sStatusStrategy .. ' |'
|
||||
while string.len( sLogLineProc) <= 20 do
|
||||
sLogLineProc = ' ' .. sLogLineProc
|
||||
end
|
||||
sLogLine = sLogLine .. sLogLineProc
|
||||
else
|
||||
sLogLine = sLogLine .. ' 0 (STR----)- |'
|
||||
sLogLine = sLogLine .. ' |'
|
||||
end
|
||||
-- rotazione non presa in considerazione
|
||||
else
|
||||
sLogLine = sLogLine .. ' |'
|
||||
end
|
||||
-- rotazione non presa in considerazione
|
||||
else
|
||||
if nCountStrategies == 1 then
|
||||
sLogLine = sLogLine .. ' ---------- |'
|
||||
else
|
||||
sLogLine = sLogLine .. ' |'
|
||||
if nCountStrategies == 1 then
|
||||
sLogLine = sLogLine .. ' ---------- |'
|
||||
else
|
||||
sLogLine = sLogLine .. ' |'
|
||||
end
|
||||
end
|
||||
end
|
||||
EgtOutLog( sLogLine)
|
||||
end
|
||||
EgtOutLog( sLogLine)
|
||||
end
|
||||
|
||||
end
|
||||
EgtOutLog( '----------------------------------------------------------------------------------------------------------')
|
||||
nOffsetIndex = 4
|
||||
end
|
||||
EgtOutLog( '----------------------------------------------------------------------------------------------------------')
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function Logs.WriteMatrixLog( ProcessingsOnPart, PartInfo)
|
||||
EgtOutLog( ' === === === === === === === === === === ROTATION MATRIX === === === === === === === === === === === === ===')
|
||||
EgtOutLog( ' Feature ID | BTL POSITION | 90 ROTATION | 180 ROTATION | 270 ROTATION |')
|
||||
EgtOutLog( '----------------------------------------------------------------------------------------------------------')
|
||||
|
||||
local nProcessingsNumber
|
||||
local nFirstAvailableRotation
|
||||
-- ricerco prima rotazione effettivamente calcolata. In genere è sempre la prima
|
||||
for i = 1, 4 do
|
||||
if PartInfo.CombinationList.Rotations[i] == 1 then
|
||||
nProcessingsNumber = #ProcessingsOnPart.Rotation[i]
|
||||
nFirstAvailableRotation = i
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
for ProcLog = 1, nProcessingsNumber do
|
||||
local sLogLine = ' ' .. tostring( ProcessingsOnPart.Rotation[nFirstAvailableRotation][ProcLog].id)
|
||||
while string.len( sLogLine) <= 20 do
|
||||
sLogLine = sLogLine .. ' '
|
||||
end
|
||||
sLogLine = sLogLine .. '|'
|
||||
for nRotLog = 1, 4 do
|
||||
if PartInfo.CombinationList.Rotations[nRotLog] == 1 then
|
||||
if ProcessingsOnPart.Rotation[nRotLog][ProcLog].ChosenStrategy then
|
||||
local sStatusStrategy = EgtIf( ProcessingsOnPart.Rotation[nRotLog][ProcLog].ChosenStrategy.Result.sStatus == 'Completed', 'C', 'P')
|
||||
local sLogLineProc = tostring( ProcessingsOnPart.Rotation[nRotLog][ProcLog].ChosenStrategy.Result.dCompositeRating) ..
|
||||
' (' .. tostring( ProcessingsOnPart.Rotation[nRotLog][ProcLog].ChosenStrategy.sStrategyId) .. ')' .. sStatusStrategy .. ' |'
|
||||
while string.len( sLogLineProc) <= 20 do
|
||||
sLogLineProc = ' ' .. sLogLineProc
|
||||
end
|
||||
sLogLine = sLogLine .. sLogLineProc
|
||||
else
|
||||
sLogLine = sLogLine .. ' 0 (STR----)- |'
|
||||
end
|
||||
else
|
||||
sLogLine = sLogLine .. ' ---------- |'
|
||||
end
|
||||
end
|
||||
EgtOutLog( sLogLine)
|
||||
end
|
||||
EgtOutLog( '----------------------------------------------------------------------------------------------------------')
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function Logs.WriteCombinationLog( CombinationsList, BestCombination)
|
||||
EgtOutLog( ' === === === === === === === === === === COMBINATIONS === === === === === === ')
|
||||
EgtOutLog( ' COMBI (UNL) | RATING | COMPLETE | NO COMPL | NO EXEC | ROTATE |')
|
||||
EgtOutLog( '---------------------------------------------------------------------------')
|
||||
EgtOutLog( ' COMBI (UNL) POS | RATING | COMPLETE | NO COMPL | NO EXEC | ROTATE |')
|
||||
EgtOutLog( '------------------------------------------------------------------------------')
|
||||
|
||||
for CombiLog = 1, #CombinationsList do
|
||||
local sLogLine = ' ' .. CombinationsList[CombiLog].sBitIndexCombination .. ' (' .. CombinationsList[CombiLog].nUnloadPos .. ') |'
|
||||
local sPartPosition = EgtIf( CombinationsList[CombiLog].bPartInCombiIsInverted, 'INV', 'ORI')
|
||||
local sLogLine = ' ' .. CombinationsList[CombiLog].sBitIndexCombination .. ' (' .. CombinationsList[CombiLog].nUnloadPos .. ') ' .. sPartPosition .. ' |'
|
||||
-- rating
|
||||
local sOtherField = tostring( CombinationsList[CombiLog].dTotalRating) .. ' |'
|
||||
while string.len( sOtherField) <= 11 do
|
||||
local sOtherField = EgtNumToString( CombinationsList[CombiLog].dTotalRating, - 3) .. ' |'
|
||||
while string.len( sOtherField) <= 15 do
|
||||
sOtherField = ' ' .. sOtherField
|
||||
end
|
||||
sLogLine = sLogLine .. sOtherField
|
||||
@@ -180,19 +161,23 @@ function Logs.WriteCombinationLog( CombinationsList, BestCombination)
|
||||
|
||||
EgtOutLog( sLogLine)
|
||||
end
|
||||
EgtOutLog( '---------------------------------------------------------------------------')
|
||||
EgtOutLog( ' BEST ROTATION : ' .. BestCombination.sBitIndexCombination .. ' (' .. BestCombination.nUnloadPos .. ')')
|
||||
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)
|
||||
--EgtSurfTmSetFaceColor( Proc.id, MainFaces.BottomFaces[1].id, 1)
|
||||
end
|
||||
if MainFaces.LongFaces then
|
||||
for i = 1, #MainFaces.LongFaces do
|
||||
|
||||
@@ -0,0 +1,479 @@
|
||||
-- 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
|
||||
--EgtStartCounter()
|
||||
EgtMaxFillerCompute( Raw.LenToFill, Raw.StartGap, Raw.MidGap, Raw.EndGap, Raw.SortType)
|
||||
--local dTime = EgtStopCounter()
|
||||
-- Recupero i risultati
|
||||
local nFilledParts, nDiffParts, dTotFillRatio = EgtMaxFillerGetResults()
|
||||
local OneRes = {}
|
||||
for i = 0, nDiffParts - 1 do
|
||||
local nPartId, nCount = EgtMaxFillerGetOneResult( i)
|
||||
table.insert( OneRes, { Id=nPartId, Count=nCount})
|
||||
end
|
||||
--return { FilledParts=nFilledParts, DiffParts=nDiffParts, FillRatio=dTotFillRatio, Time=dTime, Data=OneRes}
|
||||
return { FilledParts=nFilledParts, DiffParts=nDiffParts, FillRatio=dTotFillRatio, Data=OneRes}
|
||||
end
|
||||
|
||||
-- Funzione per trovare nome MachGroup
|
||||
local function NewMachGroupName()
|
||||
local nMachGroupId = EgtGetFirstMachGroup()
|
||||
if not nMachGroupId then return 1 end
|
||||
local nMaxMachGroup = 0
|
||||
while nMachGroupId do
|
||||
sMachGroupName = EgtGetMachGroupName(nMachGroupId)
|
||||
local nMachGroupName = tonumber(sMachGroupName)
|
||||
if nMachGroupName > nMaxMachGroup then
|
||||
nMaxMachGroup = nMachGroupName
|
||||
end
|
||||
nMachGroupId = EgtGetNextMachGroup(nMachGroupId)
|
||||
end
|
||||
return nMaxMachGroup + 1
|
||||
end
|
||||
|
||||
local function TotRawCount(Raws)
|
||||
local nTotRaws = 0
|
||||
for RawIndex = 1, #Raws do
|
||||
nTotRaws = nTotRaws + Raws[RawIndex].Count
|
||||
end
|
||||
return nTotRaws
|
||||
end
|
||||
|
||||
local function TotPartLen(Parts)
|
||||
local nTotPartLen = 0
|
||||
for PartIndex = 1, #Parts do
|
||||
nTotPartLen = nTotPartLen + ( Parts[PartIndex].Len * Parts[PartIndex].Cnt)
|
||||
end
|
||||
return nTotPartLen
|
||||
end
|
||||
|
||||
-- Imposto direttorio libreria specializzata per Travi
|
||||
EgtAddToPackagePath( NEST.BASEDIR .. '\\LuaLibs\\?.lua')
|
||||
|
||||
-- Imposto la macchina corrente e verifico sia abilitata per la lavorazione delle Travi
|
||||
EgtSetCurrMachine( NEST.MACHINE)
|
||||
local sMachDir = EgtGetCurrMachineDir()
|
||||
if not EgtExistsFile( sMachDir .. '\\Beam\\BeamData.lua') then
|
||||
NEST.ERR = 12
|
||||
NEST.MSG = 'Error not configured for beam machine : ' .. sMachine
|
||||
WriteErrToLogFile( NEST.ERR, NEST.MSG)
|
||||
PostErrView( NEST.ERR, NEST.MSG)
|
||||
return
|
||||
end
|
||||
|
||||
-- Elimino direttori altre macchine e imposto direttorio macchina corrente per ricerca librerie
|
||||
EgtRemoveBaseMachineDirFromPackagePath()
|
||||
EgtAddToPackagePath( sMachDir .. '\\Beam\\?.lua')
|
||||
|
||||
-- Inizializzo contatori errori e avvisi
|
||||
local nErrCnt = 0
|
||||
local nWarnCnt = 0
|
||||
|
||||
-- Grezzi
|
||||
local Raws = {}
|
||||
-- creo tabella dei grezzi
|
||||
for nIndex, nLen in pairs( LEN) do
|
||||
Raws[tonumber(nIndex)] = {LenToFill = nLen, StartGap = NEST.STARTOFFSET, MidGap = NEST.OFFSET, EndGap = 0, SortType = -1}
|
||||
end
|
||||
for nIndex, nQty in pairs( QTY) do
|
||||
Raws[tonumber(nIndex)].Count = nQty
|
||||
end
|
||||
-- cerco il grezzo con la lunghezza maggiore, epurata dello start gap
|
||||
local maxRawLenToFillNoStartGap = 0
|
||||
for RawIndex = 1, #Raws do
|
||||
if Raws[RawIndex].Count > 0 then
|
||||
maxRawLenToFillNoStartGap = max( maxRawLenToFillNoStartGap, Raws[RawIndex].LenToFill - Raws[RawIndex].StartGap)
|
||||
end
|
||||
end
|
||||
|
||||
-- Pezzi
|
||||
local Parts = {}
|
||||
-- ciclo su pezzi per aggiungerli al nesting
|
||||
local dTotLen = 0
|
||||
for nPartId, nCount in pairs( PART) do
|
||||
-- recupero lunghezza pezzo
|
||||
local Len = EgtGetInfo( nPartId, "L", 'd')
|
||||
local DispLen = EgtIf( Len <= 1000, 2000, 0) --EgtIf( Len <= 2000, max( 2000, 6000 - Len), 0)
|
||||
-- aggiungo il pezzo solo se ci sta nel grezzo più lungo a disposizione
|
||||
if Len < maxRawLenToFillNoStartGap then
|
||||
for nCntIndex = 1 , nCount do
|
||||
table.insert( Parts, {Id = nPartId, Len = Len, DispLen = DispLen, Cnt = 1})
|
||||
dTotLen = dTotLen + Len
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- lunghezza totale pezzi
|
||||
local dTotPartLen = TotPartLen( Parts)
|
||||
-- calcolo media delle barre necessarie
|
||||
local NeededRawsForType = {}
|
||||
for RawIndex = 1, #Raws do
|
||||
NeededRawsForType[RawIndex] = min( ceil( dTotPartLen / Raws[RawIndex].LenToFill), Raws[RawIndex].Count)
|
||||
end
|
||||
local RawQtySum = 0
|
||||
for NeededRawIndex = 1, #NeededRawsForType do
|
||||
RawQtySum = RawQtySum + NeededRawsForType[NeededRawIndex]
|
||||
end
|
||||
local MediumRawQty = ceil( RawQtySum / #NeededRawsForType)
|
||||
if MediumRawQty > 1 then
|
||||
MediumRawQty = MediumRawQty - 1
|
||||
end
|
||||
|
||||
-- lista dei risultati
|
||||
local ResultList = {}
|
||||
local BestResult = nil
|
||||
local BestResultIndex = nil
|
||||
-- riordino lista pezzi per lunghezza
|
||||
table.sort( Parts, function( B1, B2) return B1.Len < B2.Len end)
|
||||
|
||||
local function NestSolutionByIndex( Index)
|
||||
|
||||
-- creo copia lista raw
|
||||
local TempRaws = {}
|
||||
for TempRawIndex = 1, #Raws do
|
||||
table.insert(TempRaws, {LenToFill = Raws[TempRawIndex].LenToFill, StartGap = Raws[TempRawIndex].StartGap, MidGap = Raws[TempRawIndex].MidGap, EndGap = Raws[TempRawIndex].EndGap, SortType = Raws[TempRawIndex].SortType, Count = Raws[TempRawIndex].Count})
|
||||
end
|
||||
|
||||
-- recupero pezzi corti
|
||||
local ShortList = {}
|
||||
local LongList = {}
|
||||
|
||||
for PartIndex = 1, #Parts do
|
||||
if PartIndex <= Index then
|
||||
table.insert( ShortList, Parts[PartIndex])
|
||||
else
|
||||
table.insert( LongList, Parts[PartIndex])
|
||||
end
|
||||
Parts[PartIndex].Cnt = 1
|
||||
end
|
||||
-- numero di pezzi piccoli per barra
|
||||
local ShortCount = Index
|
||||
local ShortForRaw = floor( ShortCount / MediumRawQty)
|
||||
local ExtraShortForRaw = 0
|
||||
if MediumRawQty > 0 then
|
||||
ExtraShortForRaw = fmod( ShortCount, MediumRawQty)
|
||||
end
|
||||
-- creo lista pezzi corti singoli
|
||||
local SingleShortList = {}
|
||||
for ShortIndex = 1, #ShortList do
|
||||
for ShortCount = 1, ShortList[ShortIndex].Cnt do
|
||||
table.insert( SingleShortList, {Id = ShortList[ShortIndex].Id, Len = ShortList[ShortIndex].Len, DispLen = ShortList[ShortIndex].DispLen, Cnt = 1})
|
||||
end
|
||||
end
|
||||
-- li divido per le barre previste
|
||||
local RawsShortList = {}
|
||||
local RawIndex = 0
|
||||
local ShortRawIndex = 0
|
||||
for ShortIndex = 1, #SingleShortList do
|
||||
if ShortRawIndex > 0 then
|
||||
table.insert( RawsShortList[RawIndex], SingleShortList[ShortIndex])
|
||||
ShortRawIndex = ShortRawIndex - 1
|
||||
else
|
||||
table.insert( RawsShortList, {SingleShortList[ShortIndex]})
|
||||
RawIndex = RawIndex + 1
|
||||
ShortRawIndex = ShortForRaw + EgtIf( RawIndex <= ExtraShortForRaw, 1, 0) - 1
|
||||
end
|
||||
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')
|
||||
@@ -13,7 +13,10 @@ EgtEnableDebug( true)
|
||||
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')
|
||||
|
||||
-- TODO forzatura calcolo con prerotazioni. Cancellare dopo che è stata aggiunta la gestione corretta
|
||||
local bCalcBestPieceUnloadPosition = true
|
||||
|
||||
-- Verifico che la macchina corrente sia abilitata per la lavorazione delle Travi
|
||||
local sMachDir = EgtGetCurrMachineDir()
|
||||
@@ -34,37 +37,33 @@ 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.FeatureLib = nil
|
||||
_G.package.loaded.DiceCut = nil
|
||||
_G.package.loaded.FaceData = nil
|
||||
_G.package.loaded.MachiningLib = nil
|
||||
_G.package.loaded.FeatureLib = nil
|
||||
_G.package.loaded.Identity = nil
|
||||
_G.package.loaded.Logs = nil
|
||||
_G.package.loaded.MachiningLib = nil
|
||||
-- strategie di base sempre presenti
|
||||
_G.package.loaded['SPLITCUT\\SPLITCUT'] = nil
|
||||
_G.package.loaded['SPLITCUT\\SPLITCUTConfig'] = nil
|
||||
_G.package.loaded['HEADCUT\\HEADCUT'] = nil
|
||||
_G.package.loaded['HEADCUT\\HEADCUTConfig'] = nil
|
||||
_G.package.loaded['TAILCUT\\TAILCUT'] = nil
|
||||
-- libreria macchina
|
||||
_G.package.loaded.BeamData = 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
|
||||
@@ -73,14 +72,14 @@ for i = 1, #vtCoreStrategiesNames do
|
||||
end
|
||||
|
||||
|
||||
local BeamExec = require( 'BeamExec')
|
||||
|
||||
-- Variabili globali
|
||||
PARTS = {} -- tabella contenente tutte le informazioni di ogni pezzo
|
||||
PROCESSINGS = {} -- tabella contenente tutte le informazioni di ogni feature, processate per ogni rotazione
|
||||
|
||||
-- Carico i dati globali
|
||||
local BeamData = require( 'BeamData')
|
||||
-- carico librerie
|
||||
local BeamExec = require( 'BeamExec')
|
||||
local BeamLib = require( 'BeamLib')
|
||||
|
||||
-- Variabili di modulo
|
||||
local dRawW
|
||||
@@ -129,15 +128,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)
|
||||
@@ -165,11 +164,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
|
||||
@@ -184,9 +178,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)
|
||||
|
||||
@@ -275,10 +269,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
|
||||
@@ -292,7 +286,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, bCalcBestPieceUnloadPosition)
|
||||
if not bOk then
|
||||
EgtOutLog( sErr)
|
||||
EgtOutBox( sErr, 'Lavora Travi', 'ERROR')
|
||||
@@ -306,25 +300,56 @@ end
|
||||
-- *** Inserimento delle lavorazioni nelle travi ***
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function MyProcessFeatures()
|
||||
local PROCESSINGS = BeamExec.GetProcessings( PROCESSINGS, PARTS)
|
||||
local bOk, Stats = BeamExec.ProcessMachinings( PROCESSINGS, PARTS)
|
||||
-- creo un gruppo temporaneo dove finiranno tutte le entità che non bisogna salvare, alla fine lo si cancella
|
||||
local idTempGroup = BeamLib.CreateTempGroup()
|
||||
|
||||
BeamExec.GetProcessings( PARTS, bCalcBestPieceUnloadPosition)
|
||||
BeamExec.GetCombinationMatrix( PARTS, bCalcBestPieceUnloadPosition)
|
||||
BeamExec.ProcessMachinings( PARTS)
|
||||
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
|
||||
-- nulla da segnalare
|
||||
|
||||
-- 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
|
||||
EgtErase( idTempGroup)
|
||||
|
||||
if #sOutput > 0 then EgtOutLog( sOutput) end
|
||||
if nErrCnt > 0 then
|
||||
EgtOutBox( sOutput, 'Lavora Travi', 'ERRORS')
|
||||
@@ -342,6 +367,9 @@ end
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
if not MyProcessInputData() then return end
|
||||
|
||||
-- recupero parametri generali da progetto
|
||||
BeamExec.GetGeneralParameters()
|
||||
|
||||
if not MyProcessBeams() then return end
|
||||
|
||||
if not GetDataConfig() then return end
|
||||
|
||||
@@ -0,0 +1,889 @@
|
||||
|
||||
[
|
||||
{
|
||||
"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\\Cut-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":"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" : [ ]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"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": "",
|
||||
"StrategyList" : [ ]
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"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" : [ ]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -1,118 +0,0 @@
|
||||
-- Strategia: FACEBYBLADE
|
||||
-- Descrizione
|
||||
-- Strategia di base per la lavorazione di una faccia con lama
|
||||
-- Feature: tutte
|
||||
|
||||
-- carico librerie
|
||||
local BeamLib = require( 'BeamLib')
|
||||
local BeamData = require( 'BeamData')
|
||||
local MachiningLib = require( 'MachiningLib')
|
||||
|
||||
-- Tabella per definizione modulo
|
||||
local FACEBYBLADE = {}
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function CalculateLeadInOut( EdgeToMachine)
|
||||
local LeadIn = {}
|
||||
local LeadOut = {}
|
||||
LeadIn.dStartAddLength = 0
|
||||
LeadOut.dEndAddLength = 0
|
||||
LeadIn.nType = MCH_MILL_LI.LINEAR
|
||||
LeadOut.nType = MCH_MILL_LI.LINEAR
|
||||
LeadIn.dTangentDistance = 0
|
||||
LeadOut.dTangentDistance = 0
|
||||
-- elevazione sempre in negativo
|
||||
if EdgeToMachine.Elev < 10 * GEO.EPS_SMALL then
|
||||
LeadIn.dPerpDistance = BeamData.CUT_SIC - EdgeToMachine.Elev
|
||||
LeadOut.dPerpDistance = BeamData.CUT_SIC - EdgeToMachine.Elev
|
||||
else
|
||||
LeadIn.dPerpDistance = BeamData.CUT_SIC
|
||||
LeadOut.dPerpDistance = BeamData.CUT_SIC
|
||||
end
|
||||
LeadIn.dElevation = 0
|
||||
LeadOut.dElevation = 0
|
||||
LeadIn.dCompLength = 0
|
||||
LeadOut.dCompLength = 0
|
||||
LeadIn.dStartAddLength = BeamData.CUT_EXTRA
|
||||
LeadOut.dEndAddLength = BeamData.CUT_EXTRA
|
||||
|
||||
return LeadIn, LeadOut
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-- TODO da sistemare
|
||||
local function GetSCC( vtMachiningDirection)
|
||||
local nSCC = MCH_SCC.NONE
|
||||
|
||||
if vtMachiningDirection:getZ() < -0.9 then
|
||||
nSCC = MCH_SCC.ADIR_ZM
|
||||
elseif vtMachiningDirection:getZ() > 0.9 then
|
||||
nSCC = MCH_SCC.ADIR_ZP
|
||||
elseif vtMachiningDirection:getY() < -0.707 then
|
||||
nSCC = MCH_SCC.ADIR_YM
|
||||
elseif vtMachiningDirection:getY() > 0.707 then
|
||||
nSCC = MCH_SCC.ADIR_YP
|
||||
elseif vtMachiningDirection:getX() < -0.707 then
|
||||
nSCC = MCH_SCC.ADIR_XM
|
||||
elseif vtMachiningDirection:getX() > 0.707 then
|
||||
nSCC = MCH_SCC.ADIR_XP
|
||||
end
|
||||
|
||||
return nSCC
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-- TODO da sistemare
|
||||
function FACEBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalParameters)
|
||||
local Cutting = {}
|
||||
|
||||
local vtMachiningDirection = EdgeToMachine.Norm
|
||||
local vtN = Proc.Faces[FaceToMachine+1].vtN
|
||||
Cutting.sDepth = OptionalParameters.sDepth or 0
|
||||
Cutting.dRadialOffset = OptionalParameters.dRadialOffset or 0
|
||||
|
||||
Cutting.nType = MCH_MY.MILLING
|
||||
Cutting.nToolIndex = OptionalParameters.nToolIndex
|
||||
Cutting.Geometry = {{ Proc.id, FaceToMachine}}
|
||||
Cutting.id = Proc.id
|
||||
|
||||
|
||||
-- ===== calcolo LeadIn/out =====
|
||||
if OptionalParameters.LeadIn and OptionalParameters.LeadOut then
|
||||
Cutting.LeadIn, Cutting.LeadOut = OptionalParameters.LeadIn, OptionalParameters.LeadOut
|
||||
else
|
||||
Cutting.LeadIn, Cutting.LeadOut = CalculateLeadInOut( EdgeToMachine)
|
||||
end
|
||||
|
||||
-- ===== scelta soluzione braccio C del motore =====
|
||||
Cutting.nSCC = GetSCC( vtMachiningDirection)
|
||||
|
||||
-- ===== parametri da settare in UserNotes =====
|
||||
Cutting.nFaceuse = OptionalParameters.nFaceuse
|
||||
Cutting.sUserNotes = EgtSetValInNotes( Cutting.sUserNotes, 'VtFaceUse', vtMachiningDirection)
|
||||
if OptionalParameters.sUserNotes then
|
||||
Cutting.sUserNotes = Cutting.sUserNotes .. OptionalParameters.sUserNotes
|
||||
end
|
||||
|
||||
-- ===== scelta senso di lavorazione =====
|
||||
local bIsSawCCW = TOOLS[Cutting.nToolIndex].bIsCCW
|
||||
local bInvert
|
||||
-- se la lama ruota in senso antiorario inverto la direzione di lavorazione, per avere rotazione lama opposta a avanzamento
|
||||
if bInvert == nil then
|
||||
bInvert = ( not bIsSawCCW)
|
||||
if bIsSawCCW then
|
||||
bInvert = (( Cutting.nFaceuse == MCH_MILL_FU.ORTHO_FRONT and vtN:getX() < 0) or ( Cutting.nFaceuse == MCH_MILL_FU.ORTHO_BACK and vtN:getX() > 0))
|
||||
else
|
||||
bInvert = (( Cutting.nFaceuse == MCH_MILL_FU.ORTHO_FRONT and vtN:getX() > 0) or ( Cutting.nFaceuse == MCH_MILL_FU.ORTHO_BACK and vtN:getX() < 0))
|
||||
end
|
||||
end
|
||||
Cutting.bInvert = bInvert
|
||||
Cutting.nWorkside = EgtIf( bInvert, MCH_MILL_WS.RIGHT, MCH_MILL_WS.LEFT)
|
||||
|
||||
return Cutting
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return FACEBYBLADE
|
||||
@@ -1,283 +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 = 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
|
||||
Cutting. nSegment = 1
|
||||
|
||||
-- parametri opzionali
|
||||
if not OptionalParameters then
|
||||
OptionalParameters = {}
|
||||
end
|
||||
local bForceLongcutBlade = OptionalParameters.bForceLongcutBlade or false
|
||||
local dExtendAfterTail = OptionalParameters.dExtendAfterTail or 10000
|
||||
|
||||
-- lunghezze e punti caratteristici della lavorazione e del lato lavorato
|
||||
Cutting.dLengthToMachine = EdgeToMachine.dLength
|
||||
Cutting.dLengthOnX = abs( EdgeToMachine.dLength * EdgeToMachine.vtToolDirection:getY())
|
||||
Cutting.dEdgeLength = EdgeToMachine.dLength
|
||||
Cutting.ptEdge1, _, Cutting.ptEdge2 = EgtSurfTmFacetOppositeSide( Proc.id, FaceToMachine.id, -EdgeToMachine.vtToolDirection, GDB_ID.ROOT)
|
||||
Cutting.vtEdgeDirection = EdgeToMachine.vtToolDirection ^ FaceToMachine.vtN
|
||||
|
||||
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)
|
||||
|
||||
-- se lavorazione aperta sulla coda, eventuali aggiustamenti
|
||||
-- TODO valutare se fare funzione a parte
|
||||
if Proc.AffectedFaces.bLeft then
|
||||
local bStartLeft = MachiningLib.StartsLeftSide( Cutting)
|
||||
local dAddLengthLeftSide = Cutting.LeadOut.dEndAddLength
|
||||
local dAddLengthToReduce = sqrt( Cutting.dDepthToMachine * TOOLS[Cutting.nToolIndex].dDiameter - Cutting.dDepthToMachine * Cutting.dDepthToMachine)
|
||||
if bStartLeft then
|
||||
dAddLengthLeftSide = Cutting.LeadIn.dStartAddLength
|
||||
end
|
||||
if not AreSameOrOppositeVectorApprox( EdgeToMachine.vtToolDirection, Y_AX()) then
|
||||
if MachiningLib.CanMoveAfterSplitcut( Cutting.dLengthOnX, Part) then
|
||||
Cutting.bMoveAfterSplitcut = true
|
||||
else
|
||||
Cutting.bIsApplicable = false
|
||||
end
|
||||
elseif dAddLengthLeftSide + dAddLengthToReduce > dExtendAfterTail then
|
||||
if MachiningLib.CanMoveAfterSplitcut( Cutting.dLengthOnX, Part) then
|
||||
Cutting.bMoveAfterSplitcut = true
|
||||
else
|
||||
if bStartLeft then
|
||||
Cutting.LeadIn.dStartAddLength = - dAddLengthToReduce + dExtendAfterTail
|
||||
else
|
||||
Cutting.LeadOut.dEndAddLength = - dAddLengthToReduce + dExtendAfterTail
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return Cutting
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return SLOTBYBLADE
|
||||
@@ -0,0 +1,126 @@
|
||||
|
||||
[
|
||||
{
|
||||
"nGroup": "MACHINE",
|
||||
"sName": "GEN_sPiecesLoadingPosition",
|
||||
"sNameNge": "GEN_PIECES_LOADING",
|
||||
"sValue": "BEST_POSITION",
|
||||
"sDescriptionShort": "Part loading position",
|
||||
"sDescriptionLong": "",
|
||||
"sType": "combo",
|
||||
"sMinUserLevel": "1",
|
||||
"Choices": [
|
||||
{
|
||||
"sValue": "BTL_POSITION",
|
||||
"sDescriptionShort": "Last piece position as BTL",
|
||||
"sDescriptionLong": "",
|
||||
"sMessageId": ""
|
||||
},
|
||||
{
|
||||
"sValue": "BEST_ROTATION",
|
||||
"sDescriptionShort": "Allow piece rotations",
|
||||
"sDescriptionLong": "",
|
||||
"sMessageId": ""
|
||||
},
|
||||
{
|
||||
"sValue": "BEST_POSITION",
|
||||
"sDescriptionShort": "Allow piece rotation and inversion",
|
||||
"sDescriptionLong": "",
|
||||
"sMessageId": ""
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"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_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 Waste Length for Dice-cut",
|
||||
"sDescriptionLong": "",
|
||||
"sType": "d",
|
||||
"sMessageId": " ",
|
||||
"sMinUserLevel": "5"
|
||||
},
|
||||
{
|
||||
"nGroup": "MACHINING STRATEGY",
|
||||
"sName": "GEN_dMaxWasteVolume",
|
||||
"sNameNge": "GEN_MAX_WASTE_VOLUME",
|
||||
"sValue": "6000000",
|
||||
"sDescriptionShort": "Maximum Waste Volume for Dice-cut",
|
||||
"sDescriptionLong": "",
|
||||
"sType": "d",
|
||||
"sMessageId": " ",
|
||||
"sMinUserLevel": "5"
|
||||
}
|
||||
]
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -3,381 +3,116 @@
|
||||
-- HeadCut
|
||||
-- Feature: HeadCut
|
||||
|
||||
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
-- TODO: HEADCUT copiata da SPLITCUT. Da sistemare e capire se fare solo una strategia oppure due divise.
|
||||
---------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
-- carico librerie
|
||||
local BeamLib = require( 'BeamLib')
|
||||
local BeamData = require( 'BeamData')
|
||||
local MachiningLib = require( 'MachiningLib')
|
||||
local FeatureLib = require( 'FeatureLib')
|
||||
local MachiningLib = require( 'MachiningLib')
|
||||
local SPLITCUT = require( 'SPLITCUT')
|
||||
-- strategie di base
|
||||
local FaceByBlade = require('FACEBYBLADE')
|
||||
local BladeToWaste = require('BLADETOWASTE')
|
||||
|
||||
-- Tabella per definizione modulo
|
||||
local HEADCUT = {}
|
||||
local Strategy = {}
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function LoadStrategyParameters( CustomParameters)
|
||||
local StrategyLib = {}
|
||||
StrategyLib.Config = require( 'HEADCUT\\HEADCUTConfig')
|
||||
Strategy.sName = StrategyLib.Config.sStrategyId
|
||||
CustomParameters = BeamLib.GetUpdateCustomParameters( CustomParameters, StrategyLib.Config.Parameters)
|
||||
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( CustomParameters)
|
||||
Strategy.Result = {}
|
||||
Strategy.Machining = {}
|
||||
Strategy.Result.sInfo = ''
|
||||
return Strategy
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function CalculateLeadInOut( Machining, EdgeToMachine)
|
||||
|
||||
local LeadIn = {}
|
||||
local LeadOut = {}
|
||||
LeadIn.dStartAddLength = 0
|
||||
LeadOut.dEndAddLength = 0
|
||||
LeadIn.nType = MCH_MILL_LI.LINEAR
|
||||
LeadOut.nType = MCH_MILL_LI.LINEAR
|
||||
LeadIn.dTangentDistance = 0
|
||||
LeadOut.dTangentDistance = 0
|
||||
-- elevazione sempre in negativo
|
||||
if EdgeToMachine.Elev < 10 * GEO.EPS_SMALL then
|
||||
LeadIn.dPerpDistance = BeamData.CUT_SIC - EdgeToMachine.Elev
|
||||
LeadOut.dPerpDistance = BeamData.CUT_SIC - EdgeToMachine.Elev
|
||||
else
|
||||
LeadIn.dPerpDistance = BeamData.CUT_SIC
|
||||
LeadOut.dPerpDistance = BeamData.CUT_SIC
|
||||
end
|
||||
LeadIn.dElevation = 0
|
||||
LeadOut.dElevation = 0
|
||||
LeadIn.dCompLength = 0
|
||||
LeadOut.dCompLength = 0
|
||||
LeadIn.dStartAddLength = BeamData.CUT_EXTRA
|
||||
LeadOut.dEndAddLength = BeamData.CUT_EXTRA
|
||||
|
||||
return LeadIn, LeadOut
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function MakeChamfer()
|
||||
-- TODO funzionalit� da aggiungere
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function GetEdgeToMachine( Proc, vtEdge)
|
||||
local Edge
|
||||
for i = 1, #Proc.Faces[1].Edges do
|
||||
if AreSameVectorApprox( Proc.Faces[1].Edges[i].Norm, vtEdge) then
|
||||
Edge = Proc.Faces[1].Edges[i]
|
||||
end
|
||||
end
|
||||
return Edge
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function GetSplitStrategy( Proc, Part)
|
||||
-- se non sono stati caricati i parametri, si ricaricano
|
||||
if not Strategy.Parameters then
|
||||
Strategy = LoadStrategyParameters()
|
||||
end
|
||||
|
||||
-- separazione solo se esiste grezzo successivo con pezzi o scaricabile
|
||||
local nNextRawId = EgtGetNextRawPart( Part.idRaw)
|
||||
Strategy.bSplit = ( nNextRawId and ( EgtGetPartInRawPartCount( nNextRawId) > 0 or EgtGetRawPartBBox( nNextRawId):getDimX() >= BeamData.dMinRaw))
|
||||
|
||||
-- imposto paraemtri di ricerca utensile in base a topologia
|
||||
local Machining = {}
|
||||
-- sTypeMachining = BladeSideSingle\ BladeSideDouble\ BladeHorizontalSingle\ BladeHorizontalDouble\ ChainSawHorizontal\ ChainSawSideSingle\ ChainSawSideDouble\ ChainSawPlusBlade\ Mill\ None
|
||||
Machining.sTypeMachining = 'None'
|
||||
local Splitting = {}
|
||||
local ToolSearchParameters = {}
|
||||
ToolSearchParameters.vtToolDirection = Proc.Faces[1].vtN
|
||||
|
||||
|
||||
-- ===== RICERCA UTENSILE =====
|
||||
-- cerco lama sopra
|
||||
Splitting.bIsApplicable = false
|
||||
ToolSearchParameters.bAllowTopHead = true
|
||||
ToolSearchParameters.bAllowBottomHead = false
|
||||
Splitting.ToolInfo = {}
|
||||
Splitting.ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters)
|
||||
if Splitting.ToolInfo.nToolIndex then
|
||||
Splitting.bIsApplicable = true
|
||||
local ParametersMRR = {}
|
||||
ParametersMRR.nToolIndex = Splitting.ToolInfo.nToolIndex
|
||||
Splitting.dMRR = MachiningLib.GetToolMRR( ParametersMRR)
|
||||
end
|
||||
table.insert( Machining, Splitting)
|
||||
|
||||
-- cerco lama sotto
|
||||
Splitting = {}
|
||||
Splitting.bIsApplicable = false
|
||||
ToolSearchParameters.bAllowTopHead = false
|
||||
ToolSearchParameters.bAllowBottomHead = true
|
||||
Splitting.ToolInfo = {}
|
||||
Splitting.ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters)
|
||||
if Splitting.ToolInfo.nToolIndex then
|
||||
Splitting.bIsApplicable = true
|
||||
local ParametersMRR = {}
|
||||
ParametersMRR.nToolIndex = Splitting.ToolInfo.nToolIndex
|
||||
Splitting.dMRR = MachiningLib.GetToolMRR( ParametersMRR)
|
||||
end
|
||||
table.insert( Machining, Splitting)
|
||||
|
||||
-- cerco motosega
|
||||
Splitting = {}
|
||||
Splitting.bIsApplicable = false
|
||||
table.insert( Machining, Splitting)
|
||||
|
||||
-- cerco fresa
|
||||
Splitting = {}
|
||||
Splitting.bIsApplicable = false
|
||||
table.insert( Machining, Splitting)
|
||||
|
||||
-- ===== SCELTA LAVORAZIONI =====
|
||||
-- forzature da parametri
|
||||
if Strategy.Parameters.bForceChainSaw then
|
||||
Machining[1].bIsApplicable = false
|
||||
Machining[2].bIsApplicable = false
|
||||
end
|
||||
|
||||
-- setto valori di default. Impossibile che taglio di separazione sia incompleto
|
||||
Strategy.Result.sStatus = 'Completed'
|
||||
Strategy.Result.nCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
|
||||
Strategy.Result.dMRR = 1
|
||||
|
||||
-- correzioni sul massimo materiale lama, considerando ingombri vari
|
||||
local dMaxMatBladeSideSingle
|
||||
local dMaxMatBladeSideDouble
|
||||
local dMaxMatBladeHorizontalSingle
|
||||
local dMaxMatBladeHorizontalDouble
|
||||
if Machining[1].bIsApplicable then
|
||||
local dMaxMat = TOOLS[Machining[1].ToolInfo.nToolIndex].dMaxMaterial
|
||||
local dRadius = TOOLS[Machining[1].ToolInfo.nToolIndex].dDiameter / 2
|
||||
local sHead = TOOLS[Machining[1].ToolInfo.nToolIndex].sHead
|
||||
-- se taglio di fianco disponibile, si controlla il massimo materiale reale. Per pezzi alti, bisogna controllare anche l'ingombro asse Z nelle 4 direzioni.
|
||||
if Part.dHeight < BeamData.MIN_DIM_HBEAM then
|
||||
dMaxMat = min( dMaxMat, BeamData.MAX_DIM_HTCUT)
|
||||
dMaxMatBladeSideSingle = dMaxMat
|
||||
dMaxMatBladeSideDouble = dMaxMat * 2
|
||||
else
|
||||
if BeamData.GetMaxMatReductionBladeCut then
|
||||
dMaxMatBladeSideSingle = min( max( dRadius - BeamData.GetMaxMatReductionBladeCut( sHead, Y_AX()), dRadius - BeamData.GetMaxMatReductionBladeCut( sHead, -Y_AX())),
|
||||
TOOLS[Machining[1].ToolInfo.nToolIndex].dMaxMaterial)
|
||||
dMaxMatBladeSideDouble = dRadius - BeamData.GetMaxMatReductionBladeCut( sHead, Y_AX()) + dRadius - BeamData.GetMaxMatReductionBladeCut( sHead, -Y_AX())
|
||||
else
|
||||
dMaxMatBladeSideSingle = abs( BeamData.MAX_DIM_HTCUT_HBEAM)
|
||||
dMaxMatBladeSideDouble = abs( BeamData.MAX_DIM_HTCUT_HBEAM) * 2
|
||||
end
|
||||
end
|
||||
-- se taglio orizzontale
|
||||
if BeamData.GetMaxMatReductionBladeCut then
|
||||
dMaxMatBladeHorizontalSingle = min( TOOLS[Machining[1].ToolInfo.nToolIndex].dMaxMaterial, dRadius - BeamData.GetMaxMatReductionBladeCut( TOOLS[Machining[1].ToolInfo.nToolIndex].sHead, -Z_AX()))
|
||||
else
|
||||
dMaxMatBladeHorizontalSingle = TOOLS[Machining[1].ToolInfo.nToolIndex].dMaxMaterial
|
||||
end
|
||||
end
|
||||
if Machining[2].bIsApplicable then
|
||||
if BeamData.GetMaxMatReductionBladeCut then
|
||||
local dRadius = TOOLS[Machining[2].ToolInfo.nToolIndex].dDiameter / 2
|
||||
dMaxMatBladeHorizontalDouble = min( TOOLS[Machining[2].ToolInfo.nToolIndex].dMaxMaterial, dRadius - BeamData.GetMaxMatReductionBladeCut( TOOLS[Machining[2].ToolInfo.nToolIndex].sHead, Z_AX()))
|
||||
else
|
||||
dMaxMatBladeHorizontalDouble = TOOLS[Machining[2].ToolInfo.nToolIndex].dMaxMaterial
|
||||
end
|
||||
end
|
||||
|
||||
-- TODO considerare di tagliare con il massimo materiale possibile per non salire troppo in Z (macchine tipo PF), oppure non scendere troppo (tipo Kairos)
|
||||
-- BladeSideSingle (taglio di lama singolo di fianco)
|
||||
if Machining[1].bIsApplicable and ( dMaxMatBladeSideSingle - BeamData.CUT_EXTRA) > Part.dWidth + 10 * GEO.EPS_SMALL then
|
||||
Strategy.Result.nQuality = FeatureLib.GetFeatureQuality( 'Blade')
|
||||
Machining.sTypeMachining = 'BladeSideSingle'
|
||||
Machining[2].bIsApplicable = false
|
||||
Machining[3].bIsApplicable = false
|
||||
Machining[4].bIsApplicable = false
|
||||
return Machining
|
||||
-- TODO considerare di tagliare con il massimo materiale possibile per non salire troppo in Z (macchine tipo PF), oppure non scendere troppo (tipo Kairos)
|
||||
-- BladeSideDouble (taglio di lama doppio di fianco)
|
||||
elseif Machining[1].bIsApplicable and ( dMaxMatBladeSideDouble - BeamData.CUT_EXTRA) > Part.dWidth + 10 * GEO.EPS_SMALL then
|
||||
Strategy.Result.nQuality = FeatureLib.GetFeatureQuality( 'Blade')
|
||||
Strategy.Result.dMRR = Strategy.Result.dMRR/2
|
||||
Machining.sTypeMachining = 'BladeSideDouble'
|
||||
Machining[2].bIsApplicable = false
|
||||
Machining[3].bIsApplicable = false
|
||||
Machining[4].bIsApplicable = false
|
||||
return Machining
|
||||
-- BladeHorizontalSingle (taglio di lama singolo orizzontale)
|
||||
elseif Machining[1].bIsApplicable and ( dMaxMatBladeHorizontalSingle - BeamData.CUT_EXTRA) > Part.dHeight + 10 * GEO.EPS_SMALL then
|
||||
Strategy.Result.nQuality = FeatureLib.GetFeatureQuality( 'Blade')
|
||||
Machining.sTypeMachining = 'BladeHorizontalSingle'
|
||||
Machining[2].bIsApplicable = false
|
||||
Machining[3].bIsApplicable = false
|
||||
Machining[4].bIsApplicable = false
|
||||
return Machining
|
||||
-- BladeHorizontalDouble (taglio di lama doppio orizzontale)
|
||||
elseif Machining[1].bIsApplicable and Machining[2].bIsApplicable and
|
||||
( dMaxMatBladeHorizontalSingle + dMaxMatBladeHorizontalDouble - BeamData.CUT_EXTRA) > Part.dHeight + 10 * GEO.EPS_SMALL then
|
||||
Strategy.Result.nQuality = FeatureLib.GetFeatureQuality( 'Blade')
|
||||
Strategy.Result.dMRR = Strategy.Result.dMRR/2
|
||||
Machining.sTypeMachining = 'BladeHorizontalDouble'
|
||||
Machining[1].ToolInfo.dMaxMatBladeFromTop = dMaxMatBladeHorizontalSingle
|
||||
Machining[2].ToolInfo.dMaxMatBladeFromDown = dMaxMatBladeHorizontalDouble
|
||||
Machining[3].bIsApplicable = false
|
||||
Machining[4].bIsApplicable = false
|
||||
return Machining
|
||||
|
||||
-- TODO : casi con motosega da completare
|
||||
-- ChainSawHorizontal (motosega)
|
||||
-- ChainSawSideSingle (motosega)
|
||||
-- ChainSawSideDouble (motosega)
|
||||
-- ChainSawPlusBlade (motosega pi� lama orizzontale)
|
||||
-- Mill (svuotatura)
|
||||
end
|
||||
|
||||
-- se non ho trovato neanche una lavorazione completa, non posso separare
|
||||
if Machining.sTypeMachining == 'None' then
|
||||
Strategy.Result.sStatus = 'Not-Applicable'
|
||||
Strategy.Result.nCompletionIndex = 0
|
||||
Strategy.Result.dMRR = 0
|
||||
Strategy.Result.nQuality = 0
|
||||
Strategy.Result.sInfo = 'Split not possible'
|
||||
end
|
||||
|
||||
return Machining
|
||||
-- TODO funzionalità da aggiungere
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function HEADCUT.Make( bAddMachining, Proc, Part, CustomParameters)
|
||||
Strategy = LoadStrategyParameters( 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 }
|
||||
local bAreAllMachiningsAdded = true
|
||||
local Splitting = {}
|
||||
local AuxiliaryData = {}
|
||||
|
||||
Strategy.sSplitStrategy = GetSplitStrategy( Proc, Part)
|
||||
-- si setta che è taglio di coda
|
||||
Strategy.bIsHeadCut = true
|
||||
|
||||
-- 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
|
||||
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 devo applicare le lavorazioni
|
||||
if bAddMachining then
|
||||
-- si forza il nome della feature
|
||||
EgtSetName( Proc.id, 'StartCut')
|
||||
|
||||
-- inserimento smussi su spigoli del taglio
|
||||
if Strategy.Parameters.bMakeChamfer then
|
||||
MakeChamfer()
|
||||
end
|
||||
|
||||
local OptionalParameters = {}
|
||||
-- applico le lavorazioni
|
||||
----------------------------------------------------------------------------------
|
||||
if Strategy.sSplitStrategy.sTypeMachining == 'BladeSideSingle' then
|
||||
OptionalParameters = {}
|
||||
OptionalParameters.nToolIndex = Strategy.sSplitStrategy[1].ToolInfo.nToolIndex
|
||||
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_BACK
|
||||
OptionalParameters.sDepth = 0
|
||||
local MachiningsToAdd = {}
|
||||
local bExecutePrecutOnly = Part.dHeadOverMaterial < 20
|
||||
-- se abilitato, faccio tagli di PRECUT a zero (come SPLIT)
|
||||
if Strategy.Parameters.bExecutePreCut then
|
||||
|
||||
-- TODO gestire lavorazione a cubetti
|
||||
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
|
||||
|
||||
local EdgeToMachine = GetEdgeToMachine( Proc, -Y_AX())
|
||||
-- approccio e retrazione
|
||||
OptionalParameters.LeadIn, OptionalParameters.LeadOut = CalculateLeadInOut( Splitting, EdgeToMachine)
|
||||
Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1].id, EdgeToMachine, OptionalParameters)
|
||||
MachiningLib.AddNewMachining( Proc, Splitting, AuxiliaryData)
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.sSplitStrategy.sTypeMachining == 'BladeSideDouble' then
|
||||
OptionalParameters = {}
|
||||
OptionalParameters.nToolIndex = Strategy.sSplitStrategy[1].ToolInfo.nToolIndex
|
||||
-- Taglio lato frontale
|
||||
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_BACK
|
||||
OptionalParameters.sDepth = 0
|
||||
OptionalParameters.dRadialOffset = ( Part.dWidth - BeamData.CUT_EXTRA) / 2
|
||||
table.insert( MachiningsToAdd, TempList)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- TODO gestire lavorazione a cubetti
|
||||
if not bExecutePrecutOnly then
|
||||
local OptionalParameters = {}
|
||||
-- si parte dal box della feature e si aggiunge il punto estremo del grezzo
|
||||
-- ATTENZIONE : Proc.b3Box viene modificata dato che il tipo Box è come se fosse una tabella, ma da qui passa solo 1 volta per pezzo quindi non dovrebbero esserci problemi
|
||||
local b3BoxDicing = Proc.b3Box
|
||||
b3BoxDicing:Add( Part.b3Raw:getMax())
|
||||
b3BoxDicing:expand( 1000 * GEO.EPS_SMALL)
|
||||
OptionalParameters.b3BoxDicing = b3BoxDicing
|
||||
|
||||
local EdgeToMachine = GetEdgeToMachine( Proc, -Y_AX())
|
||||
-- approccio e retrazione
|
||||
OptionalParameters.LeadIn, OptionalParameters.LeadOut = CalculateLeadInOut( Splitting, EdgeToMachine)
|
||||
Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1].id, EdgeToMachine, OptionalParameters)
|
||||
MachiningLib.AddNewMachining( Proc, Splitting, AuxiliaryData)
|
||||
|
||||
-- Taglio lato dietro
|
||||
OptionalParameters = {}
|
||||
Splitting = {}
|
||||
AuxiliaryData = {}
|
||||
OptionalParameters.nToolIndex = Strategy.sSplitStrategy[1].ToolInfo.nToolIndex
|
||||
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_FRONT
|
||||
OptionalParameters.sDepth = 0
|
||||
OptionalParameters.dRadialOffset = ( Part.dWidth - BeamData.CUT_EXTRA) / 2
|
||||
OptionalParameters.dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume
|
||||
OptionalParameters.dMaxWasteLength = Strategy.Parameters.dMaxWasteLength
|
||||
OptionalParameters.bReduceBladePath = Strategy.Parameters.bReduceBladePath
|
||||
|
||||
-- TODO gestire lavorazione a cubetti
|
||||
Strategy.Machining, _ = BladeToWaste.Make( Proc, Part, OptionalParameters)
|
||||
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
|
||||
end
|
||||
end
|
||||
|
||||
EdgeToMachine = GetEdgeToMachine( Proc, Y_AX())
|
||||
-- approccio e retrazione
|
||||
OptionalParameters.LeadIn, OptionalParameters.LeadOut = CalculateLeadInOut( Splitting, EdgeToMachine)
|
||||
Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1].id, EdgeToMachine, OptionalParameters)
|
||||
MachiningLib.AddNewMachining( Proc, Splitting, AuxiliaryData)
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.sSplitStrategy.sTypeMachining == 'BladeHorizontalSingle' then
|
||||
OptionalParameters = {}
|
||||
OptionalParameters.nToolIndex = Strategy.sSplitStrategy[1].ToolInfo.nToolIndex
|
||||
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_DOWN
|
||||
OptionalParameters.sDepth = 0
|
||||
OptionalParameters.dRadialOffset = -BeamData.CUT_EXTRA
|
||||
|
||||
-- TODO gestire lavorazione a cubetti
|
||||
|
||||
local EdgeToMachine = GetEdgeToMachine( Proc, Z_AX())
|
||||
-- approccio e retrazione
|
||||
OptionalParameters.LeadIn, OptionalParameters.LeadOut = CalculateLeadInOut( Splitting, EdgeToMachine)
|
||||
Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1].id, EdgeToMachine, OptionalParameters)
|
||||
MachiningLib.AddNewMachining( Proc, Splitting, AuxiliaryData)
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.sSplitStrategy.sTypeMachining == 'BladeHorizontalDouble' then
|
||||
OptionalParameters = {}
|
||||
OptionalParameters.nToolIndex = Strategy.sSplitStrategy[1].ToolInfo.nToolIndex
|
||||
-- Taglio lato frontale
|
||||
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_DOWN
|
||||
OptionalParameters.sDepth = 0
|
||||
local dExtraMaxMat = ( Strategy.sSplitStrategy[1].ToolInfo.dMaxMatBladeFromTop + Strategy.sSplitStrategy[2].ToolInfo.dMaxMatBladeFromDown - Part.dHeight - BeamData.CUT_EXTRA) / 2
|
||||
OptionalParameters.dRadialOffset = Part.dHeight - Strategy.sSplitStrategy[1].ToolInfo.dMaxMatBladeFromTop + dExtraMaxMat
|
||||
|
||||
-- TODO gestire lavorazione a cubetti
|
||||
|
||||
local EdgeToMachine = GetEdgeToMachine( Proc, Z_AX())
|
||||
-- approccio e retrazione
|
||||
OptionalParameters.LeadIn, OptionalParameters.LeadOut = CalculateLeadInOut( Splitting, EdgeToMachine)
|
||||
Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1].id, EdgeToMachine, OptionalParameters)
|
||||
MachiningLib.AddNewMachining( Proc, Splitting, AuxiliaryData)
|
||||
|
||||
-- Taglio lato dietro
|
||||
OptionalParameters = {}
|
||||
Splitting = {}
|
||||
AuxiliaryData = {}
|
||||
OptionalParameters.nToolIndex = Strategy.sSplitStrategy[2].ToolInfo.nToolIndex
|
||||
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_TOP
|
||||
OptionalParameters.sDepth = 0
|
||||
OptionalParameters.dRadialOffset = Part.dHeight - Strategy.sSplitStrategy[2].ToolInfo.dMaxMatBladeFromDown + dExtraMaxMat
|
||||
|
||||
-- TODO gestire lavorazione a cubetti
|
||||
|
||||
EdgeToMachine = GetEdgeToMachine( Proc, -Z_AX())
|
||||
-- approccio e retrazione
|
||||
OptionalParameters.LeadIn, OptionalParameters.LeadOut = CalculateLeadInOut( Splitting, EdgeToMachine)
|
||||
Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1].id, EdgeToMachine, OptionalParameters)
|
||||
MachiningLib.AddNewMachining( Proc, Splitting, AuxiliaryData)
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.sSplitStrategy.sTypeMachining == 'ChainSawHorizontal' then
|
||||
; -- TODO
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.sSplitStrategy.sTypeMachining == 'ChainSawSideSingle' then
|
||||
; -- TODO
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.sSplitStrategy.sTypeMachining == 'ChainSawSideDouble' then
|
||||
; -- TODO
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.sSplitStrategy.sTypeMachining == 'ChainSawPlusBlade' then
|
||||
; -- TODO
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.sSplitStrategy.sTypeMachining == 'Mill' then
|
||||
; -- TODO
|
||||
----------------------------------------------------------------------------------
|
||||
-- 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
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
-- Parametri configurabili da cliente per strategia: HEADCUT
|
||||
|
||||
local HEADCUTData = {
|
||||
sStrategyId = 'HEADCUT',
|
||||
Parameters = {
|
||||
{ sName = 'bMakeChamfer', sValue = 'false', sDescriptionShort = 'Execute Chamfer', sDescriptionLong = 'Use the V-Mill to execute chamfers on cut-edges', sType = 'b', sMessageId = '', sMinUserLevel = '1'},
|
||||
{ sName = 'bForceChainSaw', sValue = 'false', sDescriptionShort = 'Force to use chain saw', sDescriptionLong = 'Force to use chain saw', sType = 'b', sMessageId = '', sMinUserLevel = '1'},
|
||||
{ sName = 'bFinishWithMill', sValue = 'true', sDescriptionShort = 'Finish with mill', sDescriptionLong = 'Use a mill to finish the surface if split with chain saw', sType = 'b', sMessageId = '', sMinUserLevel = '1'}
|
||||
}
|
||||
}
|
||||
|
||||
return HEADCUTData
|
||||
@@ -1,425 +0,0 @@
|
||||
-- Strategia: SPLITCUT
|
||||
-- Descrizione
|
||||
-- Taglio di separazione
|
||||
-- Feature: SplitCut
|
||||
|
||||
-- carico librerie
|
||||
local BeamLib = require( 'BeamLib')
|
||||
local BeamData = require( 'BeamData')
|
||||
local MachiningLib = require( 'MachiningLib')
|
||||
local FeatureLib = require( 'FeatureLib')
|
||||
-- strategie di base
|
||||
local FaceByBlade = require('FACEBYBLADE')
|
||||
|
||||
-- Tabella per definizione modulo
|
||||
local SPLITCUT = {}
|
||||
local Strategy = {}
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function LoadStrategyParameters( CustomParameters)
|
||||
local StrategyLib = {}
|
||||
StrategyLib.Config = require( 'SPLITCUT\\SPLITCUTConfig')
|
||||
Strategy.sName = StrategyLib.Config.sStrategyId
|
||||
CustomParameters = BeamLib.GetUpdateCustomParameters( CustomParameters, StrategyLib.Config.Parameters)
|
||||
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( CustomParameters)
|
||||
Strategy.Result = {}
|
||||
Strategy.Machining = {}
|
||||
Strategy.Result.sInfo = ''
|
||||
return Strategy
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function CalculateLeadInOut( Machining, EdgeToMachine)
|
||||
|
||||
local LeadIn = {}
|
||||
local LeadOut = {}
|
||||
LeadIn.dStartAddLength = 0
|
||||
LeadOut.dEndAddLength = 0
|
||||
LeadIn.nType = MCH_MILL_LI.LINEAR
|
||||
LeadOut.nType = MCH_MILL_LI.LINEAR
|
||||
LeadIn.dTangentDistance = 0
|
||||
LeadOut.dTangentDistance = 0
|
||||
-- elevazione sempre in negativo
|
||||
if EdgeToMachine.Elev < 10 * GEO.EPS_SMALL then
|
||||
LeadIn.dPerpDistance = BeamData.CUT_SIC - EdgeToMachine.Elev
|
||||
LeadOut.dPerpDistance = BeamData.CUT_SIC - EdgeToMachine.Elev
|
||||
else
|
||||
LeadIn.dPerpDistance = BeamData.CUT_SIC
|
||||
LeadOut.dPerpDistance = BeamData.CUT_SIC
|
||||
end
|
||||
LeadIn.dElevation = 0
|
||||
LeadOut.dElevation = 0
|
||||
LeadIn.dCompLength = 0
|
||||
LeadOut.dCompLength = 0
|
||||
LeadIn.dStartAddLength = BeamData.CUT_EXTRA
|
||||
LeadOut.dEndAddLength = BeamData.CUT_EXTRA
|
||||
|
||||
return LeadIn, LeadOut
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function MakeChamfer()
|
||||
-- TODO funzionalità da aggiungere
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function GetEdgeToMachine( Proc, vtEdge)
|
||||
local Edge
|
||||
for i = 1, #Proc.Faces[1].Edges do
|
||||
if AreSameVectorApprox( Proc.Faces[1].Edges[i].Norm, vtEdge) then
|
||||
Edge = Proc.Faces[1].Edges[i]
|
||||
end
|
||||
end
|
||||
return Edge
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function GetSplitStrategy( Proc, Part)
|
||||
-- se non sono stati caricati i parametri, si ricaricano
|
||||
if not Strategy.Parameters then
|
||||
Strategy = LoadStrategyParameters()
|
||||
end
|
||||
|
||||
-- separazione solo se esiste grezzo successivo con pezzi o scaricabile
|
||||
local nNextRawId = EgtGetNextRawPart( Part.idRaw)
|
||||
Strategy.bSplit = ( nNextRawId and ( EgtGetPartInRawPartCount( nNextRawId) > 0 or EgtGetRawPartBBox( nNextRawId):getDimX() >= BeamData.dMinRaw))
|
||||
|
||||
-- imposto paraemtri di ricerca utensile in base a topologia
|
||||
local Machining = {}
|
||||
-- sTypeMachining = BladeSideSingle\ BladeSideDouble\ BladeHorizontalSingle\ BladeHorizontalDouble\ ChainSawHorizontal\ ChainSawSideSingle\ ChainSawSideDouble\ ChainSawPlusBlade\ Mill\ None
|
||||
Machining.sTypeMachining = 'None'
|
||||
local Splitting = {}
|
||||
local ToolSearchParameters = {}
|
||||
ToolSearchParameters.vtToolDirection = Proc.Faces[1].vtN
|
||||
|
||||
|
||||
-- ===== RICERCA UTENSILE =====
|
||||
-- cerco lama sopra
|
||||
Splitting.bIsApplicable = false
|
||||
ToolSearchParameters.bAllowTopHead = true
|
||||
ToolSearchParameters.bAllowBottomHead = false
|
||||
Splitting.ToolInfo = {}
|
||||
Splitting.ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters)
|
||||
if Splitting.ToolInfo.nToolIndex then
|
||||
Splitting.bIsApplicable = true
|
||||
local ParametersMRR = {}
|
||||
ParametersMRR.nToolIndex = Splitting.ToolInfo.nToolIndex
|
||||
Splitting.dMRR = MachiningLib.GetToolMRR( ParametersMRR)
|
||||
end
|
||||
table.insert( Machining, Splitting)
|
||||
|
||||
-- cerco lama sotto
|
||||
Splitting = {}
|
||||
Splitting.bIsApplicable = false
|
||||
ToolSearchParameters.bAllowTopHead = false
|
||||
ToolSearchParameters.bAllowBottomHead = true
|
||||
Splitting.ToolInfo = {}
|
||||
Splitting.ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters)
|
||||
if Splitting.ToolInfo.nToolIndex then
|
||||
Splitting.bIsApplicable = true
|
||||
local ParametersMRR = {}
|
||||
ParametersMRR.nToolIndex = Splitting.ToolInfo.nToolIndex
|
||||
Splitting.dMRR = MachiningLib.GetToolMRR( ParametersMRR)
|
||||
end
|
||||
table.insert( Machining, Splitting)
|
||||
|
||||
-- cerco motosega
|
||||
Splitting = {}
|
||||
Splitting.bIsApplicable = false
|
||||
table.insert( Machining, Splitting)
|
||||
|
||||
-- cerco fresa
|
||||
Splitting = {}
|
||||
Splitting.bIsApplicable = false
|
||||
table.insert( Machining, Splitting)
|
||||
|
||||
-- ===== SCELTA LAVORAZIONI =====
|
||||
-- forzature da parametri
|
||||
if Strategy.Parameters.bForceChainSaw then
|
||||
Machining[1].bIsApplicable = false
|
||||
Machining[2].bIsApplicable = false
|
||||
end
|
||||
|
||||
-- setto valori di default. Impossibile che taglio di separazione sia incompleto
|
||||
Strategy.Result.sStatus = 'Completed'
|
||||
Strategy.Result.nCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
|
||||
Strategy.Result.dMRR = 1
|
||||
|
||||
-- correzioni sul massimo materiale lama, considerando ingombri vari
|
||||
local dMaxMatBladeSideSingle
|
||||
local dMaxMatBladeSideDouble
|
||||
local dMaxMatBladeHorizontalSingle
|
||||
local dMaxMatBladeHorizontalDouble
|
||||
if Machining[1].bIsApplicable then
|
||||
local dMaxMat = TOOLS[Machining[1].ToolInfo.nToolIndex].dMaxMaterial
|
||||
local dRadius = TOOLS[Machining[1].ToolInfo.nToolIndex].dDiameter / 2
|
||||
local sHead = TOOLS[Machining[1].ToolInfo.nToolIndex].sHead
|
||||
-- se taglio di fianco disponibile, si controlla il massimo materiale reale. Per pezzi alti, bisogna controllare anche l'ingombro asse Z nelle 4 direzioni.
|
||||
if Part.dHeight < BeamData.MIN_DIM_HBEAM then
|
||||
dMaxMat = min( dMaxMat, BeamData.MAX_DIM_HTCUT)
|
||||
dMaxMatBladeSideSingle = dMaxMat
|
||||
dMaxMatBladeSideDouble = dMaxMat * 2
|
||||
else
|
||||
if BeamData.GetMaxMatReductionBladeCut then
|
||||
dMaxMatBladeSideSingle = min( max( dRadius - BeamData.GetMaxMatReductionBladeCut( sHead, Y_AX()), dRadius - BeamData.GetMaxMatReductionBladeCut( sHead, -Y_AX())),
|
||||
TOOLS[Machining[1].ToolInfo.nToolIndex].dMaxMaterial)
|
||||
dMaxMatBladeSideDouble = dRadius - BeamData.GetMaxMatReductionBladeCut( sHead, Y_AX()) + dRadius - BeamData.GetMaxMatReductionBladeCut( sHead, -Y_AX())
|
||||
else
|
||||
dMaxMatBladeSideSingle = abs( BeamData.MAX_DIM_HTCUT_HBEAM)
|
||||
dMaxMatBladeSideDouble = abs( BeamData.MAX_DIM_HTCUT_HBEAM) * 2
|
||||
end
|
||||
end
|
||||
-- se taglio orizzontale
|
||||
if BeamData.GetMaxMatReductionBladeCut then
|
||||
dMaxMatBladeHorizontalSingle = min( TOOLS[Machining[1].ToolInfo.nToolIndex].dMaxMaterial, dRadius - BeamData.GetMaxMatReductionBladeCut( TOOLS[Machining[1].ToolInfo.nToolIndex].sHead, -Z_AX()))
|
||||
else
|
||||
dMaxMatBladeHorizontalSingle = TOOLS[Machining[1].ToolInfo.nToolIndex].dMaxMaterial
|
||||
end
|
||||
end
|
||||
if Machining[2].bIsApplicable then
|
||||
if BeamData.GetMaxMatReductionBladeCut then
|
||||
local dRadius = TOOLS[Machining[2].ToolInfo.nToolIndex].dDiameter / 2
|
||||
dMaxMatBladeHorizontalDouble = min( TOOLS[Machining[2].ToolInfo.nToolIndex].dMaxMaterial, dRadius - BeamData.GetMaxMatReductionBladeCut( TOOLS[Machining[2].ToolInfo.nToolIndex].sHead, Z_AX()))
|
||||
else
|
||||
dMaxMatBladeHorizontalDouble = TOOLS[Machining[2].ToolInfo.nToolIndex].dMaxMaterial
|
||||
end
|
||||
end
|
||||
|
||||
-- TODO considerare di tagliare con il massimo materiale possibile per non salire troppo in Z (macchine tipo PF), oppure non scendere troppo (tipo Kairos)
|
||||
-- BladeSideSingle (taglio di lama singolo di fianco)
|
||||
if Machining[1].bIsApplicable and ( dMaxMatBladeSideSingle - BeamData.CUT_EXTRA) > Part.dWidth + 10 * GEO.EPS_SMALL then
|
||||
Strategy.Result.nQuality = FeatureLib.GetFeatureQuality( 'Blade')
|
||||
Machining.sTypeMachining = 'BladeSideSingle'
|
||||
Machining[2].bIsApplicable = false
|
||||
Machining[3].bIsApplicable = false
|
||||
Machining[4].bIsApplicable = false
|
||||
return Machining
|
||||
-- TODO considerare di tagliare con il massimo materiale possibile per non salire troppo in Z (macchine tipo PF), oppure non scendere troppo (tipo Kairos)
|
||||
-- BladeSideDouble (taglio di lama doppio di fianco)
|
||||
elseif Machining[1].bIsApplicable and ( dMaxMatBladeSideDouble - BeamData.CUT_EXTRA) > Part.dWidth + 10 * GEO.EPS_SMALL then
|
||||
Strategy.Result.nQuality = FeatureLib.GetFeatureQuality( 'Blade')
|
||||
Strategy.Result.dMRR = Strategy.Result.dMRR/2
|
||||
Machining.sTypeMachining = 'BladeSideDouble'
|
||||
Machining[2].bIsApplicable = false
|
||||
Machining[3].bIsApplicable = false
|
||||
Machining[4].bIsApplicable = false
|
||||
return Machining
|
||||
-- BladeHorizontalSingle (taglio di lama singolo orizzontale)
|
||||
elseif Machining[1].bIsApplicable and ( dMaxMatBladeHorizontalSingle - BeamData.CUT_EXTRA) > Part.dHeight + 10 * GEO.EPS_SMALL then
|
||||
Strategy.Result.nQuality = FeatureLib.GetFeatureQuality( 'Blade')
|
||||
Machining.sTypeMachining = 'BladeHorizontalSingle'
|
||||
Machining[2].bIsApplicable = false
|
||||
Machining[3].bIsApplicable = false
|
||||
Machining[4].bIsApplicable = false
|
||||
return Machining
|
||||
-- BladeHorizontalDouble (taglio di lama doppio orizzontale)
|
||||
elseif Machining[1].bIsApplicable and Machining[2].bIsApplicable and
|
||||
( dMaxMatBladeHorizontalSingle + dMaxMatBladeHorizontalDouble - BeamData.CUT_EXTRA) > Part.dHeight + 10 * GEO.EPS_SMALL then
|
||||
Strategy.Result.nQuality = FeatureLib.GetFeatureQuality( 'Blade')
|
||||
Strategy.Result.dMRR = Strategy.Result.dMRR/2
|
||||
Machining.sTypeMachining = 'BladeHorizontalDouble'
|
||||
Machining[1].ToolInfo.dMaxMatBladeFromTop = dMaxMatBladeHorizontalSingle
|
||||
Machining[2].ToolInfo.dMaxMatBladeFromDown = dMaxMatBladeHorizontalDouble
|
||||
Machining[3].bIsApplicable = false
|
||||
Machining[4].bIsApplicable = false
|
||||
return Machining
|
||||
|
||||
-- TODO : casi con motosega da completare
|
||||
-- ChainSawHorizontal (motosega)
|
||||
-- ChainSawSideSingle (motosega)
|
||||
-- ChainSawSideDouble (motosega)
|
||||
-- ChainSawPlusBlade (motosega più lama orizzontale)
|
||||
-- Mill (svuotatura)
|
||||
end
|
||||
|
||||
-- se non ho trovato neanche una lavorazione completa, non posso separare
|
||||
if Machining.sTypeMachining == 'None' then
|
||||
Strategy.Result.sStatus = 'Not-Applicable'
|
||||
Strategy.Result.nCompletionIndex = 0
|
||||
Strategy.Result.dMRR = 0
|
||||
Strategy.Result.nQuality = 0
|
||||
Strategy.Result.sInfo = 'Split not possible'
|
||||
end
|
||||
|
||||
return Machining
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function SPLITCUT.Make( bAddMachining, Proc, Part, CustomParameters)
|
||||
Strategy = LoadStrategyParameters( CustomParameters)
|
||||
local bAreAllMachiningsAdded = true
|
||||
local Splitting = {}
|
||||
local AuxiliaryData = {}
|
||||
|
||||
Strategy.sSplitStrategy = GetSplitStrategy( Proc, Part)
|
||||
if bAddMachining then
|
||||
-- inserimento smussi su spigoli del taglio
|
||||
if Strategy.Parameters.bMakeChamfer then
|
||||
MakeChamfer()
|
||||
end
|
||||
|
||||
local OptionalParameters = {}
|
||||
-- applico le lavorazioni
|
||||
----------------------------------------------------------------------------------
|
||||
if Strategy.sSplitStrategy.sTypeMachining == 'BladeSideSingle' then
|
||||
OptionalParameters = {}
|
||||
OptionalParameters.nToolIndex = Strategy.sSplitStrategy[1].ToolInfo.nToolIndex
|
||||
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_BACK
|
||||
OptionalParameters.sDepth = 0
|
||||
|
||||
-- TODO gestire lavorazione a cubetti
|
||||
|
||||
if Strategy.bSplit then
|
||||
OptionalParameters.sUserNotes = 'Split;'
|
||||
else
|
||||
OptionalParameters.sUserNotes = 'Cut;'
|
||||
end
|
||||
AuxiliaryData.bAddNewPhase = true
|
||||
|
||||
local EdgeToMachine = GetEdgeToMachine( Proc, -Y_AX())
|
||||
-- approccio e retrazione
|
||||
OptionalParameters.LeadIn, OptionalParameters.LeadOut = CalculateLeadInOut( Splitting, EdgeToMachine)
|
||||
Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1].id, EdgeToMachine, OptionalParameters)
|
||||
MachiningLib.AddNewMachining( Proc, Splitting, AuxiliaryData)
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.sSplitStrategy.sTypeMachining == 'BladeSideDouble' then
|
||||
OptionalParameters = {}
|
||||
OptionalParameters.nToolIndex = Strategy.sSplitStrategy[1].ToolInfo.nToolIndex
|
||||
-- Taglio lato frontale
|
||||
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_BACK
|
||||
OptionalParameters.sDepth = 0
|
||||
OptionalParameters.dRadialOffset = ( Part.dWidth - BeamData.CUT_EXTRA) / 2
|
||||
|
||||
-- TODO gestire lavorazione a cubetti
|
||||
|
||||
if Strategy.bSplit then
|
||||
OptionalParameters.sUserNotes = 'PreSplit;'
|
||||
else
|
||||
OptionalParameters.sUserNotes = 'PreCut;'
|
||||
end
|
||||
|
||||
local EdgeToMachine = GetEdgeToMachine( Proc, -Y_AX())
|
||||
-- approccio e retrazione
|
||||
OptionalParameters.LeadIn, OptionalParameters.LeadOut = CalculateLeadInOut( Splitting, EdgeToMachine)
|
||||
Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1].id, EdgeToMachine, OptionalParameters)
|
||||
MachiningLib.AddNewMachining( Proc, Splitting, AuxiliaryData)
|
||||
|
||||
-- Taglio lato dietro
|
||||
OptionalParameters = {}
|
||||
Splitting = {}
|
||||
AuxiliaryData = {}
|
||||
OptionalParameters.nToolIndex = Strategy.sSplitStrategy[1].ToolInfo.nToolIndex
|
||||
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_FRONT
|
||||
OptionalParameters.sDepth = 0
|
||||
OptionalParameters.dRadialOffset = ( Part.dWidth - BeamData.CUT_EXTRA) / 2
|
||||
|
||||
-- TODO gestire lavorazione a cubetti
|
||||
|
||||
if Strategy.bSplit then
|
||||
OptionalParameters.sUserNotes = 'Split;'
|
||||
else
|
||||
OptionalParameters.sUserNotes = 'Cut;'
|
||||
end
|
||||
AuxiliaryData.bAddNewPhase = true
|
||||
|
||||
EdgeToMachine = GetEdgeToMachine( Proc, Y_AX())
|
||||
-- approccio e retrazione
|
||||
OptionalParameters.LeadIn, OptionalParameters.LeadOut = CalculateLeadInOut( Splitting, EdgeToMachine)
|
||||
Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1].id, EdgeToMachine, OptionalParameters)
|
||||
MachiningLib.AddNewMachining( Proc, Splitting, AuxiliaryData)
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.sSplitStrategy.sTypeMachining == 'BladeHorizontalSingle' then
|
||||
OptionalParameters = {}
|
||||
OptionalParameters.nToolIndex = Strategy.sSplitStrategy[1].ToolInfo.nToolIndex
|
||||
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_DOWN
|
||||
OptionalParameters.sDepth = 0
|
||||
OptionalParameters.dRadialOffset = -BeamData.CUT_EXTRA
|
||||
|
||||
-- TODO gestire lavorazione a cubetti
|
||||
|
||||
if Strategy.bSplit then
|
||||
OptionalParameters.sUserNotes = 'Split;'
|
||||
else
|
||||
OptionalParameters.sUserNotes = 'Cut;'
|
||||
end
|
||||
AuxiliaryData.bAddNewPhase = true
|
||||
|
||||
local EdgeToMachine = GetEdgeToMachine( Proc, Z_AX())
|
||||
-- approccio e retrazione
|
||||
OptionalParameters.LeadIn, OptionalParameters.LeadOut = CalculateLeadInOut( Splitting, EdgeToMachine)
|
||||
Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1].id, EdgeToMachine, OptionalParameters)
|
||||
MachiningLib.AddNewMachining( Proc, Splitting, AuxiliaryData)
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.sSplitStrategy.sTypeMachining == 'BladeHorizontalDouble' then
|
||||
OptionalParameters = {}
|
||||
OptionalParameters.nToolIndex = Strategy.sSplitStrategy[1].ToolInfo.nToolIndex
|
||||
-- Taglio lato frontale
|
||||
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_DOWN
|
||||
OptionalParameters.sDepth = 0
|
||||
local dExtraMaxMat = ( Strategy.sSplitStrategy[1].ToolInfo.dMaxMatBladeFromTop + Strategy.sSplitStrategy[2].ToolInfo.dMaxMatBladeFromDown - Part.dHeight - BeamData.CUT_EXTRA) / 2
|
||||
OptionalParameters.dRadialOffset = Part.dHeight - Strategy.sSplitStrategy[1].ToolInfo.dMaxMatBladeFromTop + dExtraMaxMat
|
||||
|
||||
-- TODO gestire lavorazione a cubetti
|
||||
|
||||
if Strategy.bSplit then
|
||||
OptionalParameters.sUserNotes = 'PreSplit;'
|
||||
else
|
||||
OptionalParameters.sUserNotes = 'PreCut;'
|
||||
end
|
||||
|
||||
local EdgeToMachine = GetEdgeToMachine( Proc, Z_AX())
|
||||
-- approccio e retrazione
|
||||
OptionalParameters.LeadIn, OptionalParameters.LeadOut = CalculateLeadInOut( Splitting, EdgeToMachine)
|
||||
Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1].id, EdgeToMachine, OptionalParameters)
|
||||
MachiningLib.AddNewMachining( Proc, Splitting, AuxiliaryData)
|
||||
|
||||
-- Taglio lato dietro
|
||||
OptionalParameters = {}
|
||||
Splitting = {}
|
||||
AuxiliaryData = {}
|
||||
OptionalParameters.nToolIndex = Strategy.sSplitStrategy[2].ToolInfo.nToolIndex
|
||||
OptionalParameters.nFaceuse = MCH_MILL_FU.ORTHO_TOP
|
||||
OptionalParameters.sDepth = 0
|
||||
OptionalParameters.dRadialOffset = Part.dHeight - Strategy.sSplitStrategy[2].ToolInfo.dMaxMatBladeFromDown + dExtraMaxMat
|
||||
|
||||
-- TODO gestire lavorazione a cubetti
|
||||
|
||||
if Strategy.bSplit then
|
||||
OptionalParameters.sUserNotes = 'Split;'
|
||||
else
|
||||
OptionalParameters.sUserNotes = 'Cut;'
|
||||
end
|
||||
AuxiliaryData.bAddNewPhase = true
|
||||
|
||||
EdgeToMachine = GetEdgeToMachine( Proc, -Z_AX())
|
||||
-- approccio e retrazione
|
||||
OptionalParameters.LeadIn, OptionalParameters.LeadOut = CalculateLeadInOut( Splitting, EdgeToMachine)
|
||||
Splitting = FaceByBlade.Make( Proc, Part, Proc.Faces[1].id, EdgeToMachine, OptionalParameters)
|
||||
MachiningLib.AddNewMachining( Proc, Splitting, AuxiliaryData)
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.sSplitStrategy.sTypeMachining == 'ChainSawHorizontal' then
|
||||
; -- TODO
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.sSplitStrategy.sTypeMachining == 'ChainSawSideSingle' then
|
||||
; -- TODO
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.sSplitStrategy.sTypeMachining == 'ChainSawSideDouble' then
|
||||
; -- TODO
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.sSplitStrategy.sTypeMachining == 'ChainSawPlusBlade' then
|
||||
; -- TODO
|
||||
----------------------------------------------------------------------------------
|
||||
elseif Strategy.sSplitStrategy.sTypeMachining == 'Mill' then
|
||||
; -- TODO
|
||||
----------------------------------------------------------------------------------
|
||||
end
|
||||
|
||||
return bAreAllMachiningsAdded, Strategy.Result
|
||||
else
|
||||
return nil, Strategy.Result
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return SPLITCUT
|
||||
@@ -1,12 +0,0 @@
|
||||
-- Parametri configurabili da cliente per strategia: SPLITCUT
|
||||
|
||||
local SPLITCUTData = {
|
||||
sStrategyId = 'SPLITCUT',
|
||||
Parameters = {
|
||||
{ sName = 'bMakeChamfer', sValue = 'false', sDescriptionShort = 'Execute Chamfer', sDescriptionLong = 'Use the V-Mill to execute chamfers on cut-edges', sType = 'b', sMessageId = '', sMinUserLevel = '1'},
|
||||
{ sName = 'bForceChainSaw', sValue = 'false', sDescriptionShort = 'Force to use chain saw', sDescriptionLong = 'Force to use chain saw', sType = 'b', sMessageId = '', sMinUserLevel = '1'},
|
||||
{ sName = 'bFinishWithMill', sValue = 'true', sDescriptionShort = 'Finish with mill', sDescriptionLong = 'Use a mill to finish the surface if split with chain saw', sType = 'b', sMessageId = '', sMinUserLevel = '1'}
|
||||
}
|
||||
}
|
||||
|
||||
return SPLITCUTData
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -5,18 +5,430 @@
|
||||
|
||||
-- carico librerie
|
||||
local BeamLib = require( 'BeamLib')
|
||||
local BeamData = require( 'BeamData')
|
||||
local MachiningLib = require( 'MachiningLib')
|
||||
local FeatureLib = require( 'FeatureLib')
|
||||
-- strategie di base
|
||||
local BladeToWaste = require('BLADETOWASTE')
|
||||
|
||||
-- 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
|
||||
-- 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', sNameNge = 'OVM_LENGTH', sValue = '0', sDescription = 'Sovramateriale lunghezza tenone', sType = 'd'},
|
||||
{ sName = 'dOverMatOnRadius', sNameNge = 'OVM_RADIUS', sValue = '0', sDescription = 'Sovramateriale larghezza tenone', sType = 'd'},
|
||||
{ sName = 'nMaxMillingPaths', sNameNge = 'MAX_PATHS', sValue = '3', sDescription = 'Numero massimo di passaggi di fresatura. Se richiesti più passaggi, si fa svuotatura', sType = 'd'},
|
||||
{ sName = 'bUseDTToolOnPocketing', sNameNge = 'ALLOW_DT_POCKET', sValue = 'true', sDescription = 'Utilizza utensile a coda di rondine per fare svuotatura', sType = 'b'}
|
||||
}
|
||||
}
|
||||
|
||||
return STR0001Data
|
||||
@@ -0,0 +1,47 @@
|
||||
{
|
||||
"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": "dOpenMinSafe",
|
||||
"sNameNge": "OPENMINSAFE",
|
||||
"sValue": "40",
|
||||
"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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -1,16 +1,15 @@
|
||||
-- Strategia: STR0002
|
||||
-- Descrizione
|
||||
-- Svuotatura tasca
|
||||
-- Feature tipo LapJpint
|
||||
-- Feature tipo LapJoint
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-- TODO
|
||||
-- 1 - Controllare lavorazioni in caso di feature lunga spezzata
|
||||
-- 2 - Inserire antischeggia (fresa o lama)
|
||||
-- 3 - Modalità svuotatura con fresa grande e spigoli con fresa piccola
|
||||
-- 4 - Smusso a V
|
||||
-- 5 - Finitura con motosega (se la fresa non completa)
|
||||
-- 1 - Inserire antischeggia (fresa o lama)
|
||||
-- 2 - Modalità svuotatura con fresa grande e spigoli con fresa piccola
|
||||
-- 3 - Smusso a V
|
||||
-- 4 - Finitura con motosega (se la fresa non completa)
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -28,11 +27,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 +46,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,6 +100,7 @@ local function CalcMachinedPercentage( Proc, Machining)
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-- TODO va gestita meglio la decisione delle facce da lavorare
|
||||
local function GetBestPocketingStrategy( Proc)
|
||||
-- imposto parametri di ricerca utensile in base a topologia
|
||||
local Machining = {}
|
||||
@@ -88,33 +108,58 @@ local function GetBestPocketingStrategy( Proc)
|
||||
local ToolSearchParameters = {}
|
||||
ToolSearchParameters.sMillShape = 'STANDARD'
|
||||
Machining.sTypeMachining = 'None' -- Bottom-Side1-Side2\ Bottom-Side1\ Bottom-Side2\ Side1-Side2\ Bottom\ Side1 \ Side2 \ None
|
||||
Strategy.Result.nQuality = FeatureLib.GetFeatureQuality( 'Mill')
|
||||
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
|
||||
@@ -127,6 +172,7 @@ local function GetBestPocketingStrategy( Proc)
|
||||
if Proc.Topology.sName ~= 'Tunnel-4-Through' then
|
||||
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.idProc = Proc.id
|
||||
Milling.vtFaceNormal = Proc.MainFaces.BottomFaces[1].vtN
|
||||
@@ -134,10 +180,6 @@ local function GetBestPocketingStrategy( Proc)
|
||||
Milling.ToolInfo = {}
|
||||
Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
|
||||
if Milling.ToolInfo.nToolIndex then
|
||||
-- se utensile scelto è su aggregato, ricalcolo la qualità
|
||||
if TOOLS[Milling.ToolInfo.nToolIndex].SetupInfo.bToolOnAggregate then
|
||||
Strategy.Result.nQuality = FeatureLib.GetFeatureQuality( 'MillOnAggregate')
|
||||
end
|
||||
Milling.bIsApplicable = true
|
||||
local ParametersMRR = {}
|
||||
ParametersMRR.nToolIndex = Milling.ToolInfo.nToolIndex
|
||||
@@ -149,13 +191,15 @@ 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.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
|
||||
@@ -170,7 +214,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
|
||||
@@ -178,14 +224,14 @@ 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
|
||||
elseif Proc.Topology.sName == 'Groove-3-Blind' or Proc.Topology.sName == 'Bevel-3-Blind' then
|
||||
ToolSearchParameters.dElevation = Proc.MainFaces.LongFaces[1].dElevation
|
||||
ToolSearchParameters.vtToolDirection = Proc.MainFaces.LongFaces[1].vtN
|
||||
Milling.vtFaceNormal = Proc.MainFaces.LongFaces[1].vtN
|
||||
Milling.idFaceToMachine = Proc.MainFaces.LongFaces[1].id
|
||||
Milling.idProc = Proc.id
|
||||
Milling.dElevation = Proc.MainFaces.LongFaces[1].dElevation
|
||||
else -- 'Tunnel-4-Through', 'Groove-3-Through', 'Rabbet-2-Through'
|
||||
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
|
||||
@@ -196,6 +242,7 @@ local function GetBestPocketingStrategy( Proc)
|
||||
Milling.dElevation = ( Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation * 2) + BeamData.MILL_OVERLAP
|
||||
Milling.bMachAppliedToTunnelFace = true
|
||||
end
|
||||
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sPocketingList, 'Pocketing')
|
||||
Milling.ToolInfo = {}
|
||||
Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
|
||||
if Milling.ToolInfo.nToolIndex then
|
||||
@@ -210,8 +257,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
|
||||
@@ -222,7 +274,7 @@ 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
|
||||
@@ -230,6 +282,7 @@ local function GetBestPocketingStrategy( Proc)
|
||||
Milling.idProc = Proc.id
|
||||
Milling.dElevation = Proc.MainFaces.SideFaces[1].dElevation
|
||||
end
|
||||
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sPocketingList, 'Pocketing')
|
||||
Milling.ToolInfo = {}
|
||||
Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
|
||||
if Milling.ToolInfo.nToolIndex then
|
||||
@@ -246,18 +299,30 @@ local function GetBestPocketingStrategy( Proc)
|
||||
if Machining[1].bIsApplicable and Machining[1].ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then
|
||||
Machining.sTypeMachining = 'Bottom'
|
||||
Strategy.Result.sStatus = 'Completed'
|
||||
Strategy.Result.nCompletionIndex = FeatureLib.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 = 'Bottom2'
|
||||
Strategy.Result.sStatus = 'Completed'
|
||||
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
|
||||
Strategy.Result.dMRR = Machining[2].dMRR
|
||||
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 = FeatureLib.GetFeatureCompletionIndex( 100)
|
||||
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
|
||||
Strategy.Result.dMRR = Machining[2].dMRR
|
||||
Machining[2].ToolInfo.dResidualDepth = 0
|
||||
Machining[1].bIsApplicable = false
|
||||
@@ -268,7 +333,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 = FeatureLib.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)
|
||||
@@ -283,7 +352,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 = FeatureLib.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)
|
||||
@@ -294,14 +367,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 = FeatureLib.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
|
||||
@@ -334,23 +413,19 @@ local function GetBestPocketingStrategy( Proc)
|
||||
end
|
||||
|
||||
local dMachinedPrercentage = CalcMachinedPercentage( Proc, Machining)
|
||||
Strategy.Result.nCompletionIndex = FeatureLib.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 GetSplitSurfaces( Proc, Part)
|
||||
local function GetSplitSurfaces( Proc, Part, bAddMachining)
|
||||
local vAddId = {}
|
||||
local vAddIdTunnel = {}
|
||||
local nAddGrpId = BeamLib.GetAddGroup( Part.id)
|
||||
@@ -360,41 +435,53 @@ local function GetSplitSurfaces( Proc, Part)
|
||||
end
|
||||
|
||||
-- recupero punti di spezzatura - da destra a sinistra
|
||||
local vFeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
|
||||
local FeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
|
||||
|
||||
if #vFeatureSplittingPoints == 0 then
|
||||
if #FeatureSplittingPoints == 0 then
|
||||
local nAddId = EgtCopyGlob( Proc.id, nAddGrpId) or GDB_ID.NULL
|
||||
local nAddIdTunnel = EgtCopyGlob( nOriginalTmIdTunnel, nAddGrpId) or GDB_ID.NULL
|
||||
if not bAddMachining then
|
||||
EgtSetLevel( nAddId, GDB_LV.TEMP)
|
||||
EgtSetLevel( nAddIdTunnel, GDB_LV.TEMP)
|
||||
end
|
||||
table.insert( vAddId, nAddId)
|
||||
table.insert( vAddIdTunnel, nAddIdTunnel)
|
||||
else
|
||||
for i = 1, #vFeatureSplittingPoints do
|
||||
for i = 1, #FeatureSplittingPoints do
|
||||
local nAddId = EgtCopyGlob( Proc.id, nAddGrpId) or GDB_ID.NULL
|
||||
local nAddIdTunnel = EgtCopyGlob( nOriginalTmIdTunnel, nAddGrpId) or GDB_ID.NULL
|
||||
if i == 1 then
|
||||
-- prima superficie, va tagliata solo a sinistra
|
||||
local ptSplit = vFeatureSplittingPoints[i] + Vector3d( -BeamData.MILL_OVERLAP / 2, 0, 0)
|
||||
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 = vFeatureSplittingPoints[i] + Vector3d( -BeamData.MILL_OVERLAP / 2, 0, 0)
|
||||
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 = vFeatureSplittingPoints[i - 1] + Vector3d( BeamData.MILL_OVERLAP / 2, 0, 0)
|
||||
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
|
||||
if not bAddMachining then
|
||||
EgtSetLevel( nAddId, GDB_LV.TEMP)
|
||||
EgtSetLevel( nAddIdTunnel, GDB_LV.TEMP)
|
||||
end
|
||||
table.insert( vAddId, nAddId)
|
||||
table.insert( vAddIdTunnel, nAddIdTunnel)
|
||||
end
|
||||
-- taglio ultima superficie, va tagliata solo a destra
|
||||
local nAddId = EgtCopyGlob( Proc.id, nAddGrpId) or GDB_ID.NULL
|
||||
local nAddIdTunnel = EgtCopyGlob( nOriginalTmIdTunnel, nAddGrpId) or GDB_ID.NULL
|
||||
local ptSplit = vFeatureSplittingPoints[#vFeatureSplittingPoints] + Vector3d( BeamData.MILL_OVERLAP / 2, 0, 0)
|
||||
local ptSplit = FeatureSplittingPoints[#FeatureSplittingPoints] + Vector3d( BeamData.MILL_OVERLAP / 2, 0, 0)
|
||||
EgtCutSurfTmPlane( nAddId, ptSplit, X_AX(), true, GDB_RT.GLOB)
|
||||
EgtCutSurfTmPlane( nAddIdTunnel, ptSplit, X_AX(), true, GDB_RT.GLOB)
|
||||
if not bAddMachining then
|
||||
EgtSetLevel( nAddId, GDB_LV.TEMP)
|
||||
EgtSetLevel( nAddIdTunnel, GDB_LV.TEMP)
|
||||
end
|
||||
table.insert( vAddId, nAddId)
|
||||
table.insert( vAddIdTunnel, nAddIdTunnel)
|
||||
end
|
||||
@@ -403,49 +490,47 @@ local function GetSplitSurfaces( Proc, Part)
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
local bAreAllMachiningsAdded = true
|
||||
local dFeatureVolume = FeatureLib.GetFeatureVolume( Proc, Part)
|
||||
local ToolInfo = {}
|
||||
local Pocketing = {}
|
||||
|
||||
Strategy.Machining = GetBestPocketingStrategy( Proc)
|
||||
|
||||
if bAddMachining and Strategy.Result.sStatus ~= 'Not-Applicable' then
|
||||
if Strategy.Result.sStatus ~= 'Not-Applicable' then
|
||||
local vAddId = {}
|
||||
local vAddIdTunnel = {}
|
||||
|
||||
|
||||
-- recupero superficie, se necessario trimmata sugli spezzoni
|
||||
vAddId, vAddIdTunnel = GetSplitSurfaces( Proc, Part)
|
||||
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
|
||||
@@ -453,6 +538,9 @@ function STR0002.Make( bAddMachining, Proc, Part, CustomParameters)
|
||||
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
|
||||
@@ -460,16 +548,44 @@ function STR0002.Make( bAddMachining, Proc, Part, CustomParameters)
|
||||
-- se ho una sola trimesh, sto lavorando la Proc direttamente e non ho spezzato. Applico direttamente alla geometria calcolata prima
|
||||
if #vAddId == 1 then
|
||||
Pocketing.Geometry = {{ Strategy.Machining[j].idProc, Strategy.Machining[j].idFaceToMachine}}
|
||||
bAreAllMachiningsAdded = 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 nIdTm = EgtIf( Strategy.Machining[j].bMachAppliedToTunnelFace, vAddIdTunnel[i], vAddId[i])
|
||||
vtNSplitFace = EgtSurfTmFacetNormVersor( nIdTm, k - 1, GDB_ID.ROOT)
|
||||
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 = {{ nIdTm, k - 1}}
|
||||
bAreAllMachiningsAdded = bAreAllMachiningsAdded and MachiningLib.AddNewMachining( Proc, Pocketing)
|
||||
|
||||
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
|
||||
@@ -477,6 +593,8 @@ 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
|
||||
bAreAllMachiningsAdded = false
|
||||
end
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
-- Parametri configurabili da cliente per strategia: STR0002
|
||||
|
||||
local STR0002Data = {
|
||||
sStrategyId = 'STR0002',
|
||||
Parameters = {
|
||||
{ sName = 'dMaxCornerRadius', sNameNge = 'MAX_CORNER_RADIUS', sValue = '15', sDescriptionShort = 'Max radius left on corners', sDescriptionLong = 'Radius-limit left by the tool at each corner of the feature', sType = 'd', sMinUserLevel = '1', sMessageId = ''},
|
||||
{ sName = 'bAntiSplint', sNameNge = 'ANTISPLINT', sValue = 'false', sDescriptionShort = 'Use Anti-Splint strategy', sDescriptionLong = 'The strategy will apply blade cuts on corner to avoid wood splint', sType = 'b', sMinUserLevel = '1', sMessageId = ''}
|
||||
}
|
||||
}
|
||||
|
||||
return STR0002Data
|
||||
@@ -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 lenght 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": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -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 MachiningLib = require( 'MachiningLib')
|
||||
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 = {}
|
||||
@@ -36,35 +46,11 @@ local function IsTopologyOk( Proc)
|
||||
end
|
||||
|
||||
|
||||
local function GetCompletionPercentage( Proc, Result)
|
||||
local dNotMachinedArea = 0
|
||||
local dCompletionPercentage = 0
|
||||
|
||||
if Proc.Topology.sFamily == 'Tunnel' then
|
||||
dNotMachinedArea = Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1].dLength * ( Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength - Result[1].dDepthMachined)
|
||||
if #Result == 2 then
|
||||
dNotMachinedArea = dNotMachinedArea - Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1].dLength * ( Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength - Result[2].dDepthMachined)
|
||||
end
|
||||
else
|
||||
if #Result == 1 then
|
||||
dNotMachinedArea = Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.dLength * ( Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength - Result[1].dDepthMachined)
|
||||
elseif #Result == 2 then
|
||||
dNotMachinedArea = ( Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.dLength - Result[2].dDepthMachined) * ( Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength - Result[1].dDepthMachined)
|
||||
elseif #Result == 3 then
|
||||
dNotMachinedArea = ( Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.dLength - Result[2].dDepthMachined - Result[3].dDepthMachined) * ( Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength - Result[1].dDepthMachined)
|
||||
end
|
||||
end
|
||||
dCompletionPercentage = 100 - dNotMachinedArea / Proc.MainFaces.LongFaces[1].dArea * 100
|
||||
|
||||
return dCompletionPercentage
|
||||
end
|
||||
|
||||
|
||||
-- TODO si può unificare con eguale funzione in STR0004
|
||||
local function SortMachiningsBySegment( MachiningA, MachiningB)
|
||||
if MachiningA.nSegment > MachiningB.nSegment then
|
||||
if MachiningA.nFeatureSegment > MachiningB.nFeatureSegment then
|
||||
return false
|
||||
elseif MachiningB.nSegment > MachiningA.nSegment then
|
||||
elseif MachiningB.nFeatureSegment > MachiningA.nFeatureSegment then
|
||||
return true
|
||||
else
|
||||
if TOOLS[ MachiningA.nToolIndex].sFamily == 'SAWBLADE' and TOOLS[ MachiningB.nToolIndex].sFamily == 'MORTISE' then
|
||||
@@ -88,9 +74,9 @@ local function SortMachiningsByTool( MachiningA, MachiningB)
|
||||
elseif TOOLS[ MachiningA.nToolIndex].sFamily == 'MORTISE' and TOOLS[ MachiningB.nToolIndex].sFamily == 'SAWBLADE' then
|
||||
return false
|
||||
else
|
||||
if MachiningA.nSegment > MachiningB.nSegment then
|
||||
if MachiningA.nFeatureSegment > MachiningB.nFeatureSegment then
|
||||
return false
|
||||
elseif MachiningB.nSegment > MachiningA.nSegment then
|
||||
elseif MachiningB.nFeatureSegment > MachiningA.nFeatureSegment then
|
||||
return true
|
||||
else
|
||||
if MachiningA.sEdgeType == 'Side' and MachiningB.sEdgeType ~= 'Side' then
|
||||
@@ -151,31 +137,21 @@ local function AddResult( Machining, Result)
|
||||
end
|
||||
|
||||
|
||||
local function AddMachinings( Proc, Machinings, bAddMachining)
|
||||
local nIsApplicableCount = 0
|
||||
local function AddMachinings( Proc, Machinings)
|
||||
local bAreAllMachiningsAdded = true
|
||||
|
||||
for i = 1, #Machinings do
|
||||
if Machinings[i].bIsApplicable then
|
||||
nIsApplicableCount = nIsApplicableCount + 1
|
||||
if bAddMachining then
|
||||
local bIsMachiningAdded
|
||||
if TOOLS[ Machinings[i].nToolIndex].sFamily == 'SAWBLADE' then
|
||||
Blade.AddMachiningAllSteps( Proc, Machinings[i])
|
||||
elseif TOOLS[ Machinings[i].nToolIndex].sFamily == 'MORTISE' then
|
||||
Chainsaw.AddMachiningAllSteps( Proc, Machinings[i])
|
||||
else
|
||||
error( 'AddMachinings : tool type not supported')
|
||||
end
|
||||
if not bIsMachiningAdded then
|
||||
bAreAllMachiningsAdded = false
|
||||
end
|
||||
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, nIsApplicableCount
|
||||
return bAreAllMachiningsAdded
|
||||
end
|
||||
|
||||
|
||||
@@ -184,62 +160,29 @@ function Blade.AddResult( Cutting)
|
||||
end
|
||||
|
||||
|
||||
function Blade.AddMachiningAllSteps( Proc, Cutting, AuxiliaryData)
|
||||
local bMachiningAdded = false
|
||||
if not AuxiliaryData then
|
||||
AuxiliaryData = {}
|
||||
end
|
||||
AuxiliaryData.Clones = {}
|
||||
|
||||
local dOriginalRadialOffset = Cutting.dRadialOffset
|
||||
local dOriginalLeadInPerpDistance = Cutting.LeadIn.dPerpDistance
|
||||
local dOriginalLeadOutPerpDistance = Cutting.LeadOut.dPerpDistance
|
||||
for i = 1, Cutting.HorizontalSteps.nCount do
|
||||
AuxiliaryData.Clones[i] = {}
|
||||
AuxiliaryData.Clones[i].LeadIn = {}
|
||||
AuxiliaryData.Clones[i].LeadOut = {}
|
||||
AuxiliaryData.Clones[i].dRadialOffset = dOriginalRadialOffset + Cutting.HorizontalSteps.dStep * ( Cutting.HorizontalSteps.nCount - i)
|
||||
-- update distanza perpendicolare attacco per contemplare l'offset applicato
|
||||
AuxiliaryData.Clones[i].LeadIn.dPerpDistance = dOriginalLeadInPerpDistance - Cutting.dRadialOffset
|
||||
AuxiliaryData.Clones[i].LeadOut.dPerpDistance = dOriginalLeadOutPerpDistance - Cutting.dRadialOffset
|
||||
end
|
||||
bMachiningAdded = MachiningLib.AddNewMachining( Proc, Cutting, AuxiliaryData)
|
||||
|
||||
return bMachiningAdded
|
||||
end
|
||||
|
||||
|
||||
function Chainsaw.AddResult( Mortising)
|
||||
AddResult( Mortising, Chainsaw.Result)
|
||||
end
|
||||
|
||||
|
||||
function Chainsaw.AddMachiningAllSteps( Proc, Mortising, AuxiliaryData)
|
||||
local bMachiningAdded = false
|
||||
if not AuxiliaryData then
|
||||
AuxiliaryData = {}
|
||||
end
|
||||
AuxiliaryData.Clones = {}
|
||||
local 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 = {}
|
||||
@@ -248,8 +191,7 @@ function STR0003.Make( bAddMachining, Proc, Part, CustomParameters)
|
||||
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
|
||||
|
||||
@@ -258,8 +200,7 @@ function STR0003.Make( bAddMachining, Proc, Part, CustomParameters)
|
||||
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'
|
||||
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( 'Direction')
|
||||
return false, Strategy.Result
|
||||
end
|
||||
|
||||
@@ -268,180 +209,328 @@ function STR0003.Make( bAddMachining, Proc, Part, CustomParameters)
|
||||
dExtendAfterTail = 10000
|
||||
end
|
||||
|
||||
-- volume della feature
|
||||
local dFeatureVolume = FeatureLib.GetFeatureVolume( Proc, Part)
|
||||
|
||||
-- eventuali punti di spezzatura
|
||||
local FeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
|
||||
local bIsSplitFeature = false
|
||||
if #FeatureSplittingPoints > 0 then
|
||||
bIsSplitFeature = true
|
||||
end
|
||||
|
||||
-- altezza tasca
|
||||
local dPocketHeight = 0
|
||||
if Proc.Topology.sFamily == 'Tunnel' then
|
||||
dPocketHeight = Proc.MainFaces.SideFaces[1].MainEdges.OppositeEdges[1].dLength
|
||||
else
|
||||
dPocketHeight = Proc.MainFaces.BottomFaces[1].MainEdges.SideEdges[1].dLength
|
||||
end
|
||||
|
||||
-- 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
|
||||
-- lama - calcolo lavorazioni
|
||||
local Cutting = {}
|
||||
local OptionalParameters = { bForceLongcutBlade = Strategy.Parameters.bForceLongcutBlade, dExtendAfterTail = dExtendAfterTail}
|
||||
-- parametri comuni a tutte le lavorazioni cutting
|
||||
local OptionalParameters = {
|
||||
bForceLongcutBlade = Strategy.Parameters.bForceLongcutBlade,
|
||||
dExtendAfterTail = dExtendAfterTail,
|
||||
dPocketHeight = dPocketHeight,
|
||||
bIsSplitFeature = bIsSplitFeature,
|
||||
dMinNzDownUp = 0
|
||||
}
|
||||
|
||||
-- primo lato del tunnel o lato di fondo
|
||||
if Proc.Topology.sFamily == 'Tunnel' then
|
||||
Cutting = SlotByBlade.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1], OptionalParameters)
|
||||
OptionalParameters.OppositeToolDirectionMode = 'Enabled'
|
||||
Cutting = FaceByBlade.Make( Proc, Part, LongFace, OppositeEdge1, OptionalParameters)
|
||||
else
|
||||
Cutting = SlotByBlade.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge, OptionalParameters)
|
||||
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
|
||||
Strategy.Parameters.bNotCompleteWithBladeRadius = false
|
||||
end
|
||||
end
|
||||
-- lama - lavorazioni raggruppate in unica lista
|
||||
|
||||
-- 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
|
||||
local vFeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
|
||||
if #vFeatureSplittingPoints > 0 then
|
||||
Blade.Result.Sorted = MachiningLib.GetSplitMachinings( Blade.Result.Sorted, vFeatureSplittingPoints, Part)
|
||||
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
|
||||
|
||||
-- ordinamento
|
||||
if Strategy.Parameters.bSortBySegment then
|
||||
table.sort( Blade.Result.Sorted, SortMachiningsBySegment)
|
||||
else
|
||||
table.sort( Blade.Result.Sorted, SortMachiningsByTool)
|
||||
end
|
||||
|
||||
-- aggiunta lavorazioni
|
||||
local nIsApplicableCount = 0
|
||||
local bAreAllMachiningsAdded = true
|
||||
local dFinalCompletionPercentage = 100
|
||||
bAreAllMachiningsAdded, nIsApplicableCount = AddMachinings( Proc, Blade.Result.Sorted, bAddMachining)
|
||||
if nIsApplicableCount > 0 then
|
||||
-- TODO sistemare il calcolo completamento - implementare calcolo area lavorata
|
||||
if 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'
|
||||
-- TODO al momento si assume che la percentuale di completamento dell'ultima lavorazione sia quella rilevante
|
||||
dFinalCompletionPercentage = Cutting.dCompletionPercentage
|
||||
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.sStatus = 'Not-Applicable'
|
||||
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable()
|
||||
Strategy.Parameters.bFinishWithChainSaw = false
|
||||
end
|
||||
Strategy.Result.nCompletionIndex = FeatureLib.GetFeatureCompletionIndex( dFinalCompletionPercentage)
|
||||
Strategy.Result.nQuality = FeatureLib.GetFeatureQuality( 'Blade')
|
||||
local MRRParametersBlade = {
|
||||
dStep = TOOLS[Cutting.nToolIndex].dThickness,
|
||||
dSideStep = min( TOOLS[Cutting.nToolIndex].dSideStep, Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength),
|
||||
dFeed = TOOLS[Cutting.nToolIndex].Feeds.dFeed}
|
||||
local dMRRBlade = MachiningLib.GetToolMRR( MRRParametersBlade)
|
||||
Strategy.Result.dMRR = dMRRBlade
|
||||
|
||||
return bAreAllMachiningsAdded, Strategy.Result
|
||||
end
|
||||
|
||||
-- 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, dExtendAfterTail = dExtendAfterTail}
|
||||
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, dExtendAfterTail = dExtendAfterTail}
|
||||
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, dExtendAfterTail = dExtendAfterTail}
|
||||
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, dExtendAfterTail = dExtendAfterTail}
|
||||
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, dExtendAfterTail = dExtendAfterTail}
|
||||
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, dExtendAfterTail = dExtendAfterTail}
|
||||
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, dExtendAfterTail = dExtendAfterTail}
|
||||
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, dExtendAfterTail = dExtendAfterTail}
|
||||
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, dExtendAfterTail = dExtendAfterTail}
|
||||
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, dExtendAfterTail = dExtendAfterTail}
|
||||
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, dExtendAfterTail = dExtendAfterTail}
|
||||
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, dExtendAfterTail = dExtendAfterTail}
|
||||
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, dExtendAfterTail = dExtendAfterTail}
|
||||
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, dExtendAfterTail = dExtendAfterTail}
|
||||
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
|
||||
@@ -450,58 +539,107 @@ 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, dExtendAfterTail = dExtendAfterTail}
|
||||
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, dExtendAfterTail = dExtendAfterTail}
|
||||
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 > 10 * GEO.EPS_SMALL or Chainsaw.Result.Opposite[2].dResidualDepth > 10 * 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, dExtendAfterTail = dExtendAfterTail}
|
||||
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, dExtendAfterTail = dExtendAfterTail}
|
||||
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, dExtendAfterTail = dExtendAfterTail}
|
||||
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, dExtendAfterTail = dExtendAfterTail}
|
||||
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, dExtendAfterTail = dExtendAfterTail}
|
||||
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 > 10 * GEO.EPS_SMALL then
|
||||
|
||||
Chainsaw.Result.Opposite[1].bIsApplicable = false
|
||||
local OptionalParameters = { bStopAtHalfElevation = true, dMaxElev = Blade.Result.Opposite[1].dResidualDepth + BeamData.CUT_EXTRA, dExtendAfterTail = dExtendAfterTail}
|
||||
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, dExtendAfterTail = dExtendAfterTail}
|
||||
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
|
||||
|
||||
-- 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 #vFeatureSplittingPoints > 0 then
|
||||
Chainsaw.Result.Sorted = MachiningLib.GetSplitMachinings( Chainsaw.Result.Sorted, vFeatureSplittingPoints, Part)
|
||||
if bIsSplitFeature then
|
||||
Chainsaw.Result.Sorted = MachiningLib.GetSplitMachinings( Chainsaw.Result.Sorted, FeatureSplittingPoints, Part)
|
||||
end
|
||||
|
||||
-- tutte le lavorazioni di tutti gli utensili in unica lista
|
||||
@@ -512,42 +650,35 @@ function STR0003.Make( bAddMachining, Proc, Part, CustomParameters)
|
||||
for i = 1, #Chainsaw.Result.Sorted do
|
||||
table.insert( Result, Chainsaw.Result.Sorted[i])
|
||||
end
|
||||
|
||||
-- ordinamento
|
||||
if Strategy.Parameters.bSortBySegment then
|
||||
table.sort( Result, SortMachiningsBySegment)
|
||||
else
|
||||
table.sort( Result, SortMachiningsByTool)
|
||||
end
|
||||
|
||||
-- aggiunta lavorazioni per tutti gli utensili
|
||||
local nIsApplicableCount = 0
|
||||
local bAreAllMachiningsAdded = true
|
||||
local dFinalCompletionPercentage = 100
|
||||
bAreAllMachiningsAdded, nIsApplicableCount = AddMachinings( Proc, Result, bAddMachining)
|
||||
if nIsApplicableCount > 0 then
|
||||
if Mortising.dCompletionPercentage > 100 - 10 * GEO.EPS_SMALL then
|
||||
if bAddMachining then
|
||||
bAreAllMachiningsAdded = AddMachinings( Proc, Result)
|
||||
end
|
||||
|
||||
-- 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
|
||||
-- calcolo risultati
|
||||
Strategy.Result.nCompletionIndex = FeatureLib.GetFeatureCompletionIndex( dFinalCompletionPercentage)
|
||||
Strategy.Result.nQuality = FeatureLib.GetFeatureQuality( 'Chainsaw')
|
||||
local MRRParametersBlade = {
|
||||
dStep = TOOLS[Cutting.nToolIndex].dThickness,
|
||||
dSideStep = min( TOOLS[Cutting.nToolIndex].dSideStep, Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength),
|
||||
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,19 +0,0 @@
|
||||
-- Parametri configurabili da cliente per strategia: STR0003
|
||||
|
||||
local STR0003Data = {
|
||||
sStrategyId = 'STR0003',
|
||||
Parameters = {
|
||||
{ sName = 'bFinishWithChainSaw', sNameNge = 'ALLOW_FINISH_CHAINSAW', sValue = 'true', sDescriptionShort = 'Finish with chainsaw if needed', sDescriptionLong = 'Finish with chainsaw if needed', sType = 'b', sMessageId = '', sMinUserLevel = '1'},
|
||||
{ sName = 'dExtendAfterTail', sNameNge = 'EXTEND_AFTER_TAIL', sValue = 'false', sDescriptionShort = '', sDescriptionLong = '', sType = 'd', sMessageId = '', sMinUserLevel = '1'},
|
||||
{ sName = 'bForceLongcutBlade', sNameNge = 'USE_LONGCUT_BLADE', sValue = 'false', sDescriptionShort = 'Force ripping blade', sDescriptionLong = 'Force the use of ripping blade, designed for cuts parallel to the grain', sType = 'b', sMessageId = '', sMinUserLevel = '1'},
|
||||
{ sName = 'bNotCompleteWithBladeRadius', sNameNge = 'NOT_COMPLETE_WITH_BLADE_RADIUS', sValue = 'true', sDescriptionShort = '', sDescriptionLong = '', sType = 'b', sMessageId = '', sMinUserLevel = '1'},
|
||||
{ sName = 'bUseZigZagMortising', sNameNge = 'USE_ZIGZAG_CHAINSAW', sValue = 'false', sDescriptionShort = '', sDescriptionLong = '', sType = 'b', sMessageId = '', sMinUserLevel = '1'},
|
||||
{ sName = 'bSortBySegment', sNameNge = 'SORT_BY_SEGMENT', sValue = 'true', sDescriptionShort = '', sDescriptionLong = '', sType = 'b', sMessageId = '', sMinUserLevel = '1'},
|
||||
{ sName = 'sCanDamageNextPiece', sNameNge = 'DAMAGE_NEXT_PIECE', sValue = 'NEVER', sType = 'combo', sMinUserLevel = '1',
|
||||
Choices = { sValue = 'NEVER', sDescriptionShort = '', sDescriptionLong = '', sMessageId = ''},
|
||||
{ sValue = 'ONLY_IF_RAWPART', sDescriptionShort = '', sDescriptionLong = '', sMessageId = ''},
|
||||
{ sValue = 'ALWAYS', sDescriptionShort = '', sDescriptionLong = '', sMessageId = ''}}
|
||||
}
|
||||
}
|
||||
|
||||
return STR0003Data
|
||||
@@ -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 lenght 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": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -3,13 +3,23 @@
|
||||
-- motosega per slot
|
||||
-- Feature: tipo lapjoint
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-- TODO
|
||||
-- 1 - Inserire antischeggia (fresa o lama)
|
||||
-- 2 - Smusso a V
|
||||
-- 3 - Implementare lavorazione di geometrie inclinate
|
||||
-- 4 - Gestire lavorazioni da sotto (ove possibile, in generale la motosega non lavora da sotto)
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- carico librerie
|
||||
local BeamLib = require( 'BeamLib')
|
||||
local BeamData = require( 'BeamData')
|
||||
local MachiningLib = require( 'MachiningLib')
|
||||
local FeatureLib = require( 'FeatureLib')
|
||||
-- strategie di base
|
||||
local SlotByChainSaw = require( 'SLOTBYCHAINSAW')
|
||||
local FaceByChainsaw = require( 'FACEBYCHAINSAW')
|
||||
|
||||
-- Tabella per definizione modulo
|
||||
local STR0004 = {}
|
||||
@@ -33,34 +43,11 @@ local function IsTopologyOk( Proc)
|
||||
end
|
||||
|
||||
|
||||
local function GetCompletionPercentage( Proc, Result)
|
||||
local dNotMachinedArea = 0
|
||||
local dCompletionPercentage = 0
|
||||
|
||||
if Proc.Topology.sFamily == 'Tunnel' then
|
||||
dNotMachinedArea = Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1].dLength * ( Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength - Result[1].dDepthMachined)
|
||||
if #Result == 2 then
|
||||
dNotMachinedArea = dNotMachinedArea - Proc.MainFaces.LongFaces[1].MainEdges.OppositeEdges[1].dLength * ( Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength - Result[2].dDepthMachined)
|
||||
end
|
||||
else
|
||||
if #Result == 1 then
|
||||
dNotMachinedArea = Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.dLength * ( Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength - Result[1].dDepthMachined)
|
||||
elseif #Result == 2 then
|
||||
dNotMachinedArea = ( Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.dLength - Result[2].dDepthMachined) * ( Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength - Result[1].dDepthMachined)
|
||||
elseif #Result == 3 then
|
||||
dNotMachinedArea = ( Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.dLength - Result[2].dDepthMachined - Result[3].dDepthMachined) * ( Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength - Result[1].dDepthMachined)
|
||||
end
|
||||
end
|
||||
dCompletionPercentage = 100 - dNotMachinedArea / Proc.MainFaces.LongFaces[1].dArea * 100
|
||||
|
||||
return dCompletionPercentage
|
||||
end
|
||||
|
||||
|
||||
-- TODO si può unificare con Sorting generale
|
||||
local function SortMachiningsBySegment( MachiningA, MachiningB)
|
||||
if MachiningA.nSegment > MachiningB.nSegment then
|
||||
if MachiningA.nFeatureSegment > MachiningB.nFeatureSegment then
|
||||
return false
|
||||
elseif MachiningB.nSegment > MachiningA.nSegment then
|
||||
elseif MachiningB.nFeatureSegment > MachiningA.nFeatureSegment then
|
||||
return true
|
||||
else
|
||||
if MachiningA.sEdgeType == 'Side' and MachiningB.sEdgeType ~= 'Side' then
|
||||
@@ -102,32 +89,24 @@ 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 STR0004.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( 'STR0004\\STR0004Config')
|
||||
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 = ''
|
||||
Chainsaw.Result = {}
|
||||
@@ -135,8 +114,7 @@ function STR0004.Make( bAddMachining, Proc, Part, CustomParameters)
|
||||
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
|
||||
|
||||
@@ -144,73 +122,139 @@ function STR0004.Make( bAddMachining, Proc, Part, CustomParameters)
|
||||
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'
|
||||
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( 'Direction')
|
||||
return false, Strategy.Result
|
||||
end
|
||||
|
||||
-- calcolo estensione oltre la coda
|
||||
local dExtendAfterTail = Strategy.Parameters.dExtendAfterTail or max( Part.dDistanceToNextPiece - BeamData.CUT_EXTRA, 0)
|
||||
if MachiningLib.CanExtendAfterTail( Strategy.Parameters.sCanDamageNextPiece, Part) then
|
||||
dExtendAfterTail = 10000
|
||||
end
|
||||
|
||||
-- volume della feature
|
||||
local dFeatureVolume = FeatureLib.GetFeatureVolume( Proc, Part)
|
||||
|
||||
-- eventuali punti di spezzatura
|
||||
local FeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
|
||||
local bIsSplitFeature = false
|
||||
if #FeatureSplittingPoints > 0 then
|
||||
bIsSplitFeature = true
|
||||
end
|
||||
|
||||
-- altezza tasca
|
||||
local dPocketHeight = 0
|
||||
if Proc.Topology.sFamily == 'Tunnel' then
|
||||
dPocketHeight = Proc.MainFaces.SideFaces[1].MainEdges.OppositeEdges[1].dLength
|
||||
else
|
||||
dPocketHeight = Proc.MainFaces.BottomFaces[1].MainEdges.SideEdges[1].dLength
|
||||
end
|
||||
|
||||
-- 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 = {}
|
||||
OptionalParameters = { dExtendAfterTail = dExtendAfterTail}
|
||||
-- parametri comuni a tutte le lavorazioni
|
||||
OptionalParameters = {
|
||||
dExtendAfterTail = dExtendAfterTail,
|
||||
dPocketHeight = dPocketHeight,
|
||||
bIsSplitFeature = bIsSplitFeature
|
||||
}
|
||||
|
||||
if Proc.Topology.sName == 'Groove-4-Blind' or Proc.Topology.sName == 'Pocket-5-Blind' then
|
||||
|
||||
-- si lavora tutto il fondo
|
||||
local OptionalParameters = { dExtendAfterTail = dExtendAfterTail}
|
||||
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge, OptionalParameters)
|
||||
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
|
||||
if Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge.bIsStartOpen then
|
||||
local OptionalParameters = { dExtendAfterTail = dExtendAfterTail}
|
||||
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 = { dExtendAfterTail = dExtendAfterTail}
|
||||
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[2], OptionalParameters)
|
||||
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'
|
||||
|
||||
if BottomEdge.bIsStartOpen then
|
||||
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, SideEdge1, OptionalParameters)
|
||||
Mortising.dAreaToMachine = Mortising.dDepthToMachine * ( Mortising.dEdgeLength - Chainsaw.Result.Bottom[1].dDepthToMachine)
|
||||
elseif BottomEdge.bIsEndOpen then
|
||||
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, SideEdge2, OptionalParameters)
|
||||
Mortising.dAreaToMachine = Mortising.dDepthToMachine * ( Mortising.dEdgeLength - Chainsaw.Result.Bottom[1].dDepthToMachine)
|
||||
end
|
||||
|
||||
Chainsaw.AddResult( Mortising)
|
||||
end
|
||||
|
||||
elseif Proc.Topology.sName == 'Groove-3-Through' then
|
||||
|
||||
-- si lavora tutto il fondo
|
||||
local OptionalParameters = { dExtendAfterTail = dExtendAfterTail}
|
||||
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.BottomEdge, OptionalParameters)
|
||||
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
|
||||
local OptionalParameters = { dExtendAfterTail = dExtendAfterTail}
|
||||
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1], OptionalParameters)
|
||||
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
|
||||
local OptionalParameters = { bStopAtHalfElevation = true, dExtendAfterTail = dExtendAfterTail}
|
||||
Mortising = SlotByChainSaw.Make( Proc, Part, Proc.MainFaces.LongFaces[1], Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1], OptionalParameters)
|
||||
|
||||
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 = {}
|
||||
OptionalParameters = { bStopAtHalfElevation = true, dExtendAfterTail = dExtendAfterTail}
|
||||
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
|
||||
|
||||
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
|
||||
local OptionalParameters = { dExtendAfterTail = dExtendAfterTail}
|
||||
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.OppositeToolDirectionMode = 'Enabled'
|
||||
OptionalParameters.bExtendWithCornerRadius = true
|
||||
|
||||
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, OppositeEdge1, OptionalParameters)
|
||||
Chainsaw.AddResult( Mortising)
|
||||
|
||||
-- se lavorando solo da un lato rimane materiale residuo, si lavora da entrambi
|
||||
if Chainsaw.Result.Opposite[1].dResidualDepth > 10 * GEO.EPS_SMALL then
|
||||
|
||||
Chainsaw.Result.Opposite[1].bIsApplicable = false
|
||||
local OptionalParameters = { bStopAtHalfElevation = true, dExtendAfterTail = dExtendAfterTail}
|
||||
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
|
||||
|
||||
FaceByChainsaw.Make( Proc, Part, LongFace, OppositeEdge1, OptionalParameters)
|
||||
Chainsaw.AddResult( Mortising)
|
||||
OptionalParameters = {}
|
||||
OptionalParameters = { bStopAtHalfElevation = true, dExtendAfterTail = dExtendAfterTail}
|
||||
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
|
||||
|
||||
FaceByChainsaw.Make( Proc, Part, LongFace, OppositeEdge2, OptionalParameters)
|
||||
Chainsaw.AddResult( Mortising)
|
||||
end
|
||||
end
|
||||
@@ -234,24 +278,23 @@ function STR0004.Make( bAddMachining, Proc, Part, CustomParameters)
|
||||
end
|
||||
|
||||
-- aggiunta eventuali lavorazioni splittate
|
||||
local vFeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
|
||||
if #vFeatureSplittingPoints > 0 then
|
||||
Chainsaw.Result.Sorted = MachiningLib.GetSplitMachinings( Chainsaw.Result.Sorted, vFeatureSplittingPoints, Part)
|
||||
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 nIsApplicableCount = 0
|
||||
local dFinalCompletionPercentage = 100
|
||||
local bAreAllMachiningsAdded = true
|
||||
for i = 1, #Chainsaw.Result.Sorted do
|
||||
if Chainsaw.Result.Sorted[i].bIsApplicable then
|
||||
nIsApplicableCount = nIsApplicableCount + 1
|
||||
if bAddMachining then
|
||||
local bIsMachiningAdded = Chainsaw.AddMachiningAllSteps( Proc, Chainsaw.Result.Sorted[i])
|
||||
local bIsMachiningAdded = MachiningLib.AddMachinings( Proc, Chainsaw.Result.Sorted[i])
|
||||
if not bIsMachiningAdded then
|
||||
bAreAllMachiningsAdded = false
|
||||
end
|
||||
@@ -259,25 +302,22 @@ function STR0004.Make( bAddMachining, Proc, Part, CustomParameters)
|
||||
Strategy.Result.sInfo = Strategy.Result.sInfo .. '\n' .. Chainsaw.Result.Sorted[i].sMessage
|
||||
end
|
||||
end
|
||||
if nIsApplicableCount > 0 then
|
||||
|
||||
-- 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'
|
||||
-- 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( Chainsaw.Result.Sorted)
|
||||
Strategy.Result.dTimeToMachine = FeatureLib.GetStrategyTimeToMachine( Chainsaw.Result.Sorted)
|
||||
Strategy.Result.dMRR = ( dFeatureVolume / Strategy.Result.dTimeToMachine) / pow( 10, 6)
|
||||
else
|
||||
Strategy.Result.sStatus = 'Not-Applicable'
|
||||
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable()
|
||||
end
|
||||
Strategy.Result.nCompletionIndex = FeatureLib.GetFeatureCompletionIndex( dFinalCompletionPercentage)
|
||||
Strategy.Result.nQuality = FeatureLib.GetFeatureQuality( 'Chainsaw')
|
||||
local MRRParametersChainsaw = {
|
||||
dStep = min( TOOLS[Mortising.nToolIndex].dStep, Proc.MainFaces.LongFaces[1].MainEdges.SideEdges[1].dLength),
|
||||
dSideStep = TOOLS[Mortising.nToolIndex].dThickness,
|
||||
dFeed = TOOLS[Mortising.nToolIndex].Feeds.dFeed}
|
||||
local dMRRChainsaw = MachiningLib.GetToolMRR( MRRParametersChainsaw)
|
||||
Strategy.Result.dMRR = dMRRChainsaw
|
||||
|
||||
return bAreAllMachiningsAdded, Strategy.Result
|
||||
end
|
||||
|
||||
@@ -1,15 +0,0 @@
|
||||
-- Parametri configurabili da cliente per strategia: STR0004
|
||||
|
||||
local STR0004Data = {
|
||||
sStrategyId = 'STR0004',
|
||||
Parameters = {
|
||||
{ sName = 'bUseZigZagMortising', sNameNge = 'USE_ZIGZAG_CHAINSAW', sValue = 'false', sDescriptionShort = '', sDescriptionLong = '', sType = 'b', sMessageId = '', sMinUserLevel = '1'},
|
||||
{ sName = 'dExtendAfterTail', sNameNge = 'EXTEND_AFTER_TAIL', sValue = 'false', sDescriptionShort = '', sDescriptionLong = '', sType = 'd', sMessageId = '', sMinUserLevel = '1'},
|
||||
{ sName = 'sCanDamageNextPiece', sNameNge = 'DAMAGE_NEXT_PIECE', sValue = 'NEVER', sType = 'combo', sMinUserLevel = '1',
|
||||
Choices = { sValue = 'NEVER', sDescriptionShort = '', sDescriptionLong = '', sMessageId = ''},
|
||||
{ sValue = 'ONLY_IF_RAWPART', sDescriptionShort = '', sDescriptionLong = '', sMessageId = ''},
|
||||
{ sValue = 'ALWAYS', sDescriptionShort = '', sDescriptionLong = '', sMessageId = ''}}
|
||||
}
|
||||
}
|
||||
|
||||
return STR0004Data
|
||||
@@ -0,0 +1,169 @@
|
||||
{
|
||||
"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 lenght 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": "dMinZAngleTopBlade",
|
||||
"sNameNge": "MIN_Z_ANGLE_TOP_BLADE",
|
||||
"sValue": "",
|
||||
"sDescriptionShort": "Min Z angle top blade",
|
||||
"sDescriptionLong": "",
|
||||
"sType": "d",
|
||||
"sMessageId": " ",
|
||||
"sMinUserLevel": "1"
|
||||
},
|
||||
{
|
||||
"sName": "dMaxYAngleTopBlade",
|
||||
"sNameNge": "MAX_Y_ANGLE_TOP_BLADE",
|
||||
"sValue": "",
|
||||
"sDescriptionShort": "Max Y angle top blade",
|
||||
"sDescriptionLong": "",
|
||||
"sType": "d",
|
||||
"sMessageId": " ",
|
||||
"sMinUserLevel": "1"
|
||||
},
|
||||
{
|
||||
"sName": "bFinishWithMill",
|
||||
"sNameNge": "ALLOW_FINISH_MILL",
|
||||
"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": "bReduceBladePath",
|
||||
"sSource": "GEN_bReduceBladePath",
|
||||
"sMinUserLevel": "5"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
-- 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( 'BeamData')
|
||||
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 = EgtSurfTmFacetOppositeSide( Proc.id, Proc.Faces[1].id, -Proc.Faces[1].Edges[nCommonEdge].vtN, GDB_ID.ROOT)
|
||||
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 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[1][2] > 10 * GEO.EPS_ANG_SMALL and Proc.AdjacencyMatrix[2][3] < 10 * GEO.EPS_ANG_SMALL then
|
||||
nAddedFace = 1 - 1
|
||||
elseif Proc.AdjacencyMatrix[2][3] > 10 * GEO.EPS_ANG_SMALL and Proc.AdjacencyMatrix[3][1] < 10 * GEO.EPS_ANG_SMALL then
|
||||
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 dFeatureMaxNotClampableLengthHead, dFeatureMaxNotClampableLengthTail = FeatureLib.GetFeatureMaxNotClampableLengths( Proc, Part)
|
||||
local bFeatureHindersClamping = FeatureLib.IsMachiningLong( max( dFeatureMaxNotClampableLengthHead, dFeatureMaxNotClampableLengthTail), Part, { dMaxSegmentLength = BeamData.LONGCUT_ENDLEN})
|
||||
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}
|
||||
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 a cubetti / taglio singolo
|
||||
if #Blade.Result == 0
|
||||
and Proc.nFct < 3
|
||||
and not bKeepWasteAttached
|
||||
and not bIsTwoFacesCommonEdgeTooLong then
|
||||
|
||||
AuxiliaryData.bIgnoreNotClampableLength = false
|
||||
local dMinZTopBlade
|
||||
local dMaxNyTopBlade
|
||||
local BladeToWasteResult
|
||||
if Strategy.Parameters.dMinZAngleTopBlade then
|
||||
dMinZTopBlade = sin( Strategy.Parameters.dMinZAngleTopBlade)
|
||||
end
|
||||
if Strategy.Parameters.dMaxYAngleTopBlade then
|
||||
dMaxNyTopBlade = sin( Strategy.Parameters.dMaxYAngleTopBlade)
|
||||
end
|
||||
-- TODO rimuovere dMinNzTopBlade e dMaxNyTopBlade opzionali? non sono gestiti ovunque e probabilmente hanno utilizzo limitato
|
||||
local OptionalParameters = { dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume,
|
||||
dMaxWasteLength = Strategy.Parameters.dMaxWasteLength,
|
||||
dMinNzTopBlade = dMinZTopBlade,
|
||||
dMaxNyTopBlade = dMaxNyTopBlade,
|
||||
bSaveAddedGeometries = bAddMachining,
|
||||
dExtendAfterTail = dExtendAfterTail,
|
||||
bAllowFastCuts = Strategy.Parameters.bAllowFastCuts,
|
||||
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 dMinZTopBlade
|
||||
local dMaxNyTopBlade
|
||||
local BladeToWasteResult
|
||||
if Strategy.Parameters.dMinZAngleTopBlade then
|
||||
dMinZTopBlade = sin( Strategy.Parameters.dMinZAngleTopBlade)
|
||||
end
|
||||
if Strategy.Parameters.dMaxYAngleTopBlade then
|
||||
dMaxNyTopBlade = sin( Strategy.Parameters.dMaxYAngleTopBlade)
|
||||
end
|
||||
local OptionalParameters = { dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume,
|
||||
dMaxWasteLength = Strategy.Parameters.dMaxWasteLength,
|
||||
dMinNzTopBlade = dMinZTopBlade,
|
||||
dMaxNyTopBlade = dMaxNyTopBlade,
|
||||
bSaveAddedGeometries = bAddMachining,
|
||||
dExtendAfterTail = dExtendAfterTail
|
||||
}
|
||||
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
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,343 @@
|
||||
-- Strategia: STR0006
|
||||
-- Descrizione
|
||||
-- Lama + fresa tenone
|
||||
-- Feature: 50,1
|
||||
|
||||
-- carico librerie
|
||||
local BeamLib = require( 'BeamLib')
|
||||
local BeamData = require( 'BeamData')
|
||||
local MachiningLib = require( 'MachiningLib')
|
||||
local FeatureLib = require( 'FeatureLib')
|
||||
-- strategie di base
|
||||
local BladeToWaste = require( 'BLADETOWASTE')
|
||||
|
||||
-- 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
|
||||
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
|
||||
-- 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
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,470 @@
|
||||
-- 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( 'BeamData')
|
||||
local MachiningLib = require( 'MachiningLib')
|
||||
local FeatureLib = require( 'FeatureLib')
|
||||
-- strategie di base
|
||||
local BladeToWaste = require('BLADETOWASTE')
|
||||
|
||||
-- Tabella per definizione modulo
|
||||
local STR0007 = {}
|
||||
local Strategy = {}
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
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
|
||||
Machining.Milling.bIsApplicable = true
|
||||
|
||||
-- calcolo numero passate necessarie
|
||||
if Proc.FeatureInfo.dMortiseMaxDist > TOOLS[Machining.Milling.ToolInfo.nToolIndex].dDiameter * 1.9 then
|
||||
local dToolDiam = TOOLS[Machining.Milling.ToolInfo.nToolIndex].dDiameter
|
||||
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
|
||||
|
||||
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
|
||||
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.bAntiSplint then
|
||||
sQuality = 'BEST'
|
||||
elseif Strategy.Machining.bAntiSplint 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.Parameters.bAntiSplint, '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 ApplyMortiseAntiSplint( Proc, Part)
|
||||
-- se il percorso non è chiuso, aggiungo percorso e lavorazione antischeggia
|
||||
if not EgtCurveIsClosed( Proc.FeatureInfo.idAddAuxGeom) then
|
||||
-- recupero gruppo per geometria addizionale
|
||||
local nAddGrpId = BeamLib.GetAddGroup( Part.id)
|
||||
-- calcolo il percorso top mortise
|
||||
local dSideAng = TOOLS[Strategy.Machining.Milling.ToolInfo.nToolIndex].dSideAngle
|
||||
local dToolDiam = TOOLS[Strategy.Machining.Milling.ToolInfo.nToolIndex].dDiameter
|
||||
local 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 false, sErr
|
||||
end
|
||||
EgtModifyCurveExtrusion( nId1, vtExtr, GDB_RT.GLOB)
|
||||
|
||||
local Machining = {}
|
||||
Machining.nToolIndex = Strategy.Machining.Milling.ToolInfo.nToolIndex
|
||||
Machining.nType = MCH_MY.MILLING
|
||||
Machining.vtToolDirection = Proc.FeatureInfo.vtMortiseN
|
||||
|
||||
-- LeadIn / LeadOut
|
||||
Machining.LeadIn = {}
|
||||
Machining.LeadOut = {}
|
||||
Machining.LeadIn.nType = MCH_MILL_LI.TANGENT
|
||||
Machining.LeadOut.nType = MCH_MILL_LI.TANGENT
|
||||
Machining.LeadIn.dTangentDistance = TOOLS[Strategy.Machining.Milling.ToolInfo.nToolIndex].dDiameter / 2 + BeamData.COLL_SIC
|
||||
Machining.LeadIn.dPerpDistance = 0
|
||||
Machining.LeadOut.dTangentDistance = TOOLS[Strategy.Machining.Milling.ToolInfo.nToolIndex].dDiameter / 2 + BeamData.COLL_SIC
|
||||
Machining.LeadOut.dPerpDistance = 0
|
||||
|
||||
Machining.dRadialOffset = dToolRadDelta - 1
|
||||
Machining.sDepth = Proc.FeatureInfo.dMortiseDepth - Strategy.Parameters.dOverMatOnLength
|
||||
Machining.Geometry = {{ nId1, -1}}
|
||||
Machining.bInvert = EgtIf( TOOLS[Strategy.Machining.Milling.ToolInfo.nToolIndex].bIsCCW, false, true)
|
||||
Machining.nWorkside = EgtIf( TOOLS[Strategy.Machining.Milling.ToolInfo.nToolIndex].bIsCCW, MCH_MILL_WS.LEFT, MCH_MILL_WS.RIGHT)
|
||||
Machining.dMaxElev = Proc.FeatureInfo.dMortiseDepth
|
||||
|
||||
if Proc.AffectedFaces.bLeft and Strategy.bCanMoveAfterSplit then
|
||||
Machining.sStage = 'AfterTail'
|
||||
end
|
||||
MachiningLib.AddMachinings( Proc, Machining)
|
||||
|
||||
else
|
||||
local sErr = 'Wrong geometry : Error on DtMortise ' .. tostring( Proc.id)
|
||||
EgtOutLog( sErr)
|
||||
return false, sErr
|
||||
end
|
||||
else
|
||||
local sErr = 'Wrong geometry : Error on DtMortise ' .. tostring( Proc.id)
|
||||
EgtOutLog( sErr)
|
||||
return false, sErr
|
||||
end
|
||||
end
|
||||
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.Parameters.bAntiSplint then
|
||||
ApplyMortiseAntiSplint( Proc, Part)
|
||||
end
|
||||
|
||||
-- passaggio sul profilo
|
||||
if Strategy.Machining.Milling.bIsApplicable then
|
||||
local AuxiliaryData = {}
|
||||
-- se molti passaggi richiesti, si fa svuotatura
|
||||
-- TODO in attesa delle svuotature, si fanno passaggi senza limiti sul numero massimo. Poi togliere il FALSE nella condizione.
|
||||
if false and Strategy.Machining.nMillingPathsNeeded > Strategy.Parameters.nMaxMillingPaths then
|
||||
-- TODO. SERVONO NUOVE SVUOTATURE!!!!
|
||||
else
|
||||
-- aggiungo geometria
|
||||
Strategy.Machining.Milling.Geometry = {{ Proc.FeatureInfo.idAddAuxGeom, -1}}
|
||||
Strategy.Machining.Milling.nToolIndex = Strategy.Machining.Milling.ToolInfo.nToolIndex
|
||||
Strategy.Machining.Milling.nType = MCH_MY.MILLING
|
||||
Strategy.Machining.Milling.vtToolDirection = Proc.FeatureInfo.vtMortiseN
|
||||
Strategy.Machining.Milling.sDepth = Strategy.Parameters.dOverMatOnLength
|
||||
|
||||
-- LeadIn / LeadOut
|
||||
Strategy.Machining.Milling.LeadIn = {}
|
||||
Strategy.Machining.Milling.LeadOut = {}
|
||||
Strategy.Machining.Milling.LeadIn.nType = MCH_MILL_LI.TANGENT
|
||||
Strategy.Machining.Milling.LeadOut.nType = MCH_MILL_LI.TANGENT
|
||||
Strategy.Machining.Milling.LeadIn.dTangentDistance = TOOLS[Strategy.Machining.Milling.ToolInfo.nToolIndex].dDiameter / 2 + BeamData.COLL_SIC
|
||||
Strategy.Machining.Milling.LeadIn.dPerpDistance = 0
|
||||
Strategy.Machining.Milling.LeadOut.dTangentDistance = TOOLS[Strategy.Machining.Milling.ToolInfo.nToolIndex].dDiameter / 2 + BeamData.COLL_SIC
|
||||
Strategy.Machining.Milling.LeadOut.dPerpDistance = 0
|
||||
|
||||
if Proc.AffectedFaces.bLeft and Strategy.bCanMoveAfterSplit then
|
||||
Strategy.Machining.Milling.sStage = 'AfterTail'
|
||||
end
|
||||
|
||||
-- sistemo il lato e la direzione di lavoro
|
||||
Strategy.Machining.Milling.bInvert = EgtIf( TOOLS[Strategy.Machining.Milling.ToolInfo.nToolIndex].bIsCCW, false, true)
|
||||
Strategy.Machining.Milling.nWorkside = EgtIf( TOOLS[Strategy.Machining.Milling.ToolInfo.nToolIndex].bIsCCW, MCH_MILL_WS.LEFT, MCH_MILL_WS.RIGHT)
|
||||
|
||||
Strategy.Machining.Milling.dMaxElev = Proc.FeatureInfo.dMortiseDepth
|
||||
|
||||
-- TODO calcolare SCC
|
||||
|
||||
-- passate con sovramateriale
|
||||
AuxiliaryData.Clones = {}
|
||||
for i = Strategy.Machining.nMillingPathsNeeded, 1, -1 do
|
||||
-- il primo è il passaggio più esterno
|
||||
local nIndexClones = Strategy.Machining.nMillingPathsNeeded - i + 1
|
||||
-- cambia solo sovrmateriale radiale
|
||||
AuxiliaryData.Clones[nIndexClones] = {}
|
||||
-- ultima passata con sovramateriale impostato
|
||||
if i == 1 then
|
||||
AuxiliaryData.Clones[nIndexClones].dRadialOffset = Strategy.Parameters.dOverMatOnRadius
|
||||
else
|
||||
-- suddivido step in base al numero passate da fare
|
||||
AuxiliaryData.Clones[nIndexClones].dRadialOffset = ( i - 1) * Strategy.Machining.Milling.dRealSideStep
|
||||
end
|
||||
end
|
||||
|
||||
-- aggiunge lavorazione
|
||||
bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, Strategy.Machining.Milling, AuxiliaryData)
|
||||
end
|
||||
end
|
||||
end
|
||||
return bAreAllMachiningsAdded, Strategy.Result
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return STR0007
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,356 @@
|
||||
-- Strategia: STR0008
|
||||
-- Descrizione
|
||||
-- Svuotatura tasca
|
||||
-- Feature tipo Mortise (con raggio)
|
||||
|
||||
|
||||
-- carico librerie
|
||||
local BeamLib = require( 'BeamLib')
|
||||
local BeamData = require( 'BeamData')
|
||||
local MachiningLib = require( 'MachiningLib')
|
||||
local FeatureLib = require( 'FeatureLib')
|
||||
-- strategie di base
|
||||
local BladeToWaste = require('BLADETOWASTE')
|
||||
|
||||
-- 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 not Machining.Pocketing[2].bIsApplicable then
|
||||
Machining.sTypeMachining = 'Side1'
|
||||
Machining.dResidual = Machining.Pocketing[1].ToolInfo.dResidualDepth
|
||||
Machining.Pocketing[1].sDepth = -Machining.dResidual
|
||||
Strategy.Result.dMRR = MachiningLib.GetToolMRR( Machining.Pocketing[1].ToolInfo)
|
||||
-- solo svuotatura diretta come normale mortasa, incompleta
|
||||
elseif not Machining.Pocketing[1].bIsApplicable then
|
||||
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 = {}
|
||||
Pocketing.Steps = {}
|
||||
Pocketing.LeadIn = {}
|
||||
Pocketing.nType = 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
|
||||
@@ -0,0 +1,57 @@
|
||||
{
|
||||
"sStrategyId": "STR0009",
|
||||
"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": "dOverMaterial",
|
||||
"sNameNge": "OVERMAT",
|
||||
"sValue": "0",
|
||||
"sDescriptionShort": "Overmaterial",
|
||||
"sDescriptionLong": "",
|
||||
"sType": "d",
|
||||
"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": "sMillingList",
|
||||
"sNameNge": "PROFILE_TOOL_LIST",
|
||||
"sValue": "",
|
||||
"sDescriptionShort": "Available mill to machine the profile",
|
||||
"sDescriptionLong": "",
|
||||
"sType": "tool",
|
||||
"sSubType": "MCH_TF.MILL",
|
||||
"sMessageId": " ",
|
||||
"sMinUserLevel": "1"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,255 @@
|
||||
-- Strategia: STR0009
|
||||
-- Descrizione
|
||||
-- Fresatura di contorno
|
||||
-- Feature tipo Arco
|
||||
|
||||
|
||||
-- carico librerie
|
||||
local BeamLib = require( 'BeamLib')
|
||||
local BeamData = require( 'BeamData')
|
||||
local MachiningLib = require( 'MachiningLib')
|
||||
local FeatureLib = require( 'FeatureLib')
|
||||
-- strategie di base
|
||||
local BladeToWaste = require('BLADETOWASTE')
|
||||
|
||||
-- Tabella per definizione modulo
|
||||
local STR0009 = {}
|
||||
local Strategy = {}
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-- TODO gestire il caso in cui non si trova l'utensile
|
||||
local function GetArcStrategy( Proc, Part)
|
||||
local Machining = {}
|
||||
local ToolSearchParameters = {}
|
||||
|
||||
-- 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
|
||||
|
||||
-- recupero i dati della curva e del profilo
|
||||
local dDepth = abs( EgtCurveThickness( idAux))
|
||||
local vtExtr = EgtCurveExtrusion( idAux, GDB_RT.GLOB)
|
||||
local bToolInvert = ( vtExtr:getZ() < -0.1)
|
||||
local bIsHorizontal = abs( vtExtr:getZ()) < 10 * GEO.EPS_SMALL
|
||||
local bIsFeatureDown = Proc.AffectedFaces.bBottom and not Proc.AffectedFaces.bTop
|
||||
local bIsFeatureBack = Proc.AffectedFaces.bBack and not Proc.AffectedFaces.bFront
|
||||
local bForceStrip = Strategy.Parameters.bForceStrip
|
||||
local dDimStrip = EgtIf( Strategy.Parameters.dStripWidth < 100 * GEO.EPS_SMALL, nil, Strategy.Parameters.dStripWidth)
|
||||
|
||||
local bExecStrip = false
|
||||
-- se la lavorazione si trova nella parte inferiore o in battuta dietro, il codolo va sempre lasciato
|
||||
if bIsFeatureDown or bIsFeatureBack or bForceStrip then
|
||||
if bIsFeatureDown or bIsFeatureBack then
|
||||
dDimStrip = dDimStrip or max( BeamData.DIM_STRIP or 5, 5)
|
||||
else
|
||||
dDimStrip = dDimStrip or max( BeamData.DIM_STRIP_SMALL or 5, 1)
|
||||
end
|
||||
bExecStrip = true
|
||||
end
|
||||
if not bExecStrip then
|
||||
dDimStrip = 0
|
||||
end
|
||||
|
||||
-- se lavorazione orizzontale
|
||||
if bIsHorizontal then
|
||||
local bDouble
|
||||
local Milling = MachiningLib.InitMachiningParameters( MCH_MY.MILLING)
|
||||
Milling.bIsApplicable = false
|
||||
ToolSearchParameters = {}
|
||||
ToolSearchParameters.sMillShape = 'STANDARD'
|
||||
ToolSearchParameters.dElevation = EgtIf( bExecStrip, ( dDepth - dDimStrip) / 2, dDepth + BeamData.MILL_OVERLAP)
|
||||
ToolSearchParameters.vtToolDirection = EgtIf( bToolInvert, -vtExtr, vtExtr)
|
||||
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sMillingList, 'Milling')
|
||||
Milling.ToolInfo = {}
|
||||
Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
|
||||
-- se posso lavorare in una passata, ma utensile trovato non completa la lavorazione,
|
||||
-- allora provo a cercare utensile con massimo materiale sufficiente per fare le due passate, magari trova un utensile più prestante
|
||||
if Milling.ToolInfo.dResidualDepth > 10 * GEO.EPS_SMALL and not bExecStrip then
|
||||
bDouble = true
|
||||
ToolSearchParameters.dElevation = ( dDepth + BeamData.MILL_OVERLAP) / 2
|
||||
ToolSearchParameters.vtToolDirection = EgtIf( bToolInvert, -vtExtr, vtExtr)
|
||||
end
|
||||
Milling.bToolInvert = bToolInvert
|
||||
Milling.vtToolDirection = vtExtr
|
||||
|
||||
if bDouble or bExecStrip then
|
||||
if bDouble then
|
||||
Milling.sDepth = ( dDepth + BeamData.MILL_OVERLAP) / 2
|
||||
else
|
||||
Milling.sDepth = ( dDepth - dDimStrip) / 2
|
||||
end
|
||||
table.insert( Machining, Milling)
|
||||
local Milling2 = BeamLib.TableCopyDeep( Milling)
|
||||
table.insert( Machining, Milling2)
|
||||
else
|
||||
Milling.sDepth = dDepth + BeamData.MILL_OVERLAP
|
||||
table.insert( Machining, Milling)
|
||||
end
|
||||
-- se lavorazione verticale
|
||||
else
|
||||
-- si cerca utensile 1
|
||||
local Milling = {}
|
||||
Milling.bIsApplicable = false
|
||||
ToolSearchParameters = {}
|
||||
ToolSearchParameters.sMillShape = 'STANDARD'
|
||||
ToolSearchParameters.dElevation = dDepth + BeamData.MILL_OVERLAP
|
||||
ToolSearchParameters.vtToolDirection = EgtIf( bToolInvert, -vtExtr, vtExtr)
|
||||
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sMillingList, 'Milling')
|
||||
Milling.ToolInfo = {}
|
||||
Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
|
||||
-- si cerca utensile 2
|
||||
local Milling2 = {}
|
||||
Milling2.bIsApplicable = false
|
||||
ToolSearchParameters = {}
|
||||
ToolSearchParameters.sMillShape = 'STANDARD'
|
||||
ToolSearchParameters.dElevation = dDepth + BeamData.MILL_OVERLAP
|
||||
ToolSearchParameters.vtToolDirection = EgtIf( bToolInvert, vtExtr, -vtExtr)
|
||||
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sMillingList, 'Milling')
|
||||
Milling2.ToolInfo = {}
|
||||
Milling2.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
|
||||
|
||||
-- se serve codolo
|
||||
if bExecStrip then
|
||||
-- se a disposizione entrambi gli utensili
|
||||
if Milling.ToolInfo.nToolIndex and Milling2.ToolInfo.nToolIndex then
|
||||
table.insert( Machining, Milling)
|
||||
table.insert( Machining, Milling2)
|
||||
-- se disponibile solo primo utensile
|
||||
elseif Milling.ToolInfo.nToolIndex then
|
||||
table.insert( Machining, Milling)
|
||||
-- se disponibile solo secondo utensile
|
||||
elseif Milling2.ToolInfo.nToolIndex then
|
||||
table.insert( Machining, Milling2)
|
||||
-- nessun utensile disponibile
|
||||
else
|
||||
-- non si fa nulla
|
||||
end
|
||||
-- altrimenti senza codolo
|
||||
else
|
||||
-- se utensile 1 esegue completamente
|
||||
if Milling.ToolInfo.nToolIndex and Milling.ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then
|
||||
table.insert( Machining, Milling)
|
||||
-- se utensile 2 esegue completamente
|
||||
elseif Milling2.ToolInfo.nToolIndex and Milling2.ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then
|
||||
table.insert( Machining, Milling2)
|
||||
-- se possono lavorare entrambi
|
||||
elseif Milling.ToolInfo.nToolIndex and Milling2.ToolInfo.nToolIndex then
|
||||
table.insert( Machining, Milling)
|
||||
table.insert( Machining, Milling2)
|
||||
-- se utensile 1 non completo
|
||||
elseif Milling.ToolInfo.nToolIndex then
|
||||
table.insert( Machining, Milling)
|
||||
-- se utensile 2 non completo
|
||||
elseif Milling2.ToolInfo.nToolIndex then
|
||||
table.insert( Machining, Milling2)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- TODO VOTO DA FARE!!!!
|
||||
Strategy.Result.sStatus = 'Completed'
|
||||
Strategy.Result.dCompletionIndex = 5
|
||||
Strategy.Result.dMRR = MachiningLib.GetToolMRR( Machining[1].ToolInfo or Machining[2].ToolInfo)
|
||||
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'MILL')
|
||||
Strategy.Result.sInfo = ''
|
||||
|
||||
return Machining
|
||||
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
|
||||
local Milling = {}
|
||||
|
||||
Strategy.Machinings = GetArcStrategy( Proc, Part)
|
||||
|
||||
if bAddMachining and Strategy.Result.sStatus ~= 'Not-Applicable' then
|
||||
-- eventuali punti di spezzatura
|
||||
local FeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
|
||||
|
||||
for i = 1, #Strategy.Machinings do
|
||||
|
||||
Strategy.Machinings[i].Geometry = {{ Proc.idAddAuxGeom, -1}}
|
||||
Strategy.Machinings[i].nToolIndex = Strategy.Machinings[i].ToolInfo.nToolIndex
|
||||
Strategy.Machinings[i].nType = MCH_MY.MILLING
|
||||
Strategy.Machinings[i].dStartSafetyLength = 0
|
||||
Strategy.Machinings[i].Steps = {}
|
||||
Strategy.Machinings[i].Steps.dStep = TOOLS[Strategy.Machinings[i].ToolInfo.nToolIndex].dStep
|
||||
Strategy.Machinings[i].Steps = MachiningLib.GetMachiningSteps( tonumber( Strategy.Machinings[i].sDepth), TOOLS[Strategy.Machinings[i].nToolIndex].dStep)
|
||||
|
||||
-- LeadIn / LeadOut
|
||||
Strategy.Machinings[i].LeadIn = {}
|
||||
Strategy.Machinings[i].LeadOut = {}
|
||||
Strategy.Machinings[i].LeadIn.nType = MCH_MILL_LI.TANGENT
|
||||
Strategy.Machinings[i].LeadOut.nType = MCH_MILL_LI.TANGENT
|
||||
Strategy.Machinings[i].LeadIn.dTangentDistance = TOOLS[Strategy.Machinings[i].ToolInfo.nToolIndex].dDiameter / 2 + BeamData.COLL_SIC
|
||||
Strategy.Machinings[i].LeadIn.dPerpDistance = 0
|
||||
Strategy.Machinings[i].LeadIn.dStartAddLength = 0
|
||||
Strategy.Machinings[i].LeadOut.dTangentDistance = TOOLS[Strategy.Machinings[i].ToolInfo.nToolIndex].dDiameter / 2 + BeamData.COLL_SIC
|
||||
Strategy.Machinings[i].LeadOut.dPerpDistance = 0
|
||||
Strategy.Machinings[i].LeadOut.dEndAddLength = 0
|
||||
|
||||
local dLengthOnX = Proc.b3Box:getDimX()
|
||||
Strategy.bCanMoveAfterSplit = MachiningLib.CanMoveAfterSplitcut( dLengthOnX, Part)
|
||||
if Proc.AffectedFaces.bLeft and Strategy.bCanMoveAfterSplit then
|
||||
Strategy.Machinings[i].sStage = 'AfterTail'
|
||||
end
|
||||
|
||||
-- preparo attacco/uscita in caso di spezzatura arco
|
||||
Strategy.Machinings[i].LeadInForSplit = BeamLib.TableCopyDeep( Strategy.Machinings[i].LeadIn)
|
||||
Strategy.Machinings[i].LeadOutForSplit = BeamLib.TableCopyDeep( Strategy.Machinings[i].LeadOut)
|
||||
Strategy.Machinings[i].LeadInForSplit.nType = MCH_MILL_LI.LINEAR
|
||||
Strategy.Machinings[i].LeadOutForSplit.nType = MCH_MILL_LI.LINEAR
|
||||
Strategy.Machinings[i].LeadInForSplit.dTangentDistance = 0
|
||||
Strategy.Machinings[i].LeadInForSplit.dPerpDistance = TOOLS[Strategy.Machinings[i].ToolInfo.nToolIndex].dDiameter / 2 + BeamData.COLL_SIC
|
||||
Strategy.Machinings[i].LeadOutForSplit.dTangentDistance = 0
|
||||
Strategy.Machinings[i].LeadOutForSplit.dPerpDistance = TOOLS[Strategy.Machinings[i].ToolInfo.nToolIndex].dDiameter / 2 + BeamData.COLL_SIC
|
||||
|
||||
-- sistemo il lato e la direzione di lavoro
|
||||
if i == 1 then
|
||||
Strategy.Machinings[i].bInvert = EgtIf( TOOLS[Strategy.Machinings[i].ToolInfo.nToolIndex].bIsCCW, false, true)
|
||||
Strategy.Machinings[i].nWorkside = EgtIf( TOOLS[Strategy.Machinings[i].ToolInfo.nToolIndex].bIsCCW, MCH_MILL_WS.RIGHT, MCH_MILL_WS.LEFT)
|
||||
else
|
||||
Strategy.Machinings[i].bToolInvert = true
|
||||
Strategy.Machinings[i].bInvert = EgtIf( TOOLS[Strategy.Machinings[i].ToolInfo.nToolIndex].bIsCCW, true, false)
|
||||
Strategy.Machinings[i].nWorkside = EgtIf( TOOLS[Strategy.Machinings[i].ToolInfo.nToolIndex].bIsCCW, MCH_MILL_WS.RIGHT, MCH_MILL_WS.LEFT)
|
||||
end
|
||||
Strategy.Machinings[i].ptEdge1 = EgtSP( Proc.idAddAuxGeom, GDB_ID.ROOT)
|
||||
Strategy.Machinings[i].ptEdge2 = EgtEP( Proc.idAddAuxGeom, GDB_ID.ROOT)
|
||||
Strategy.Machinings[i].dEdgeLength = EgtCurveLength( Proc.idAddAuxGeom)
|
||||
Strategy.Machinings[i].vtEdgeDirection = EgtSV( Proc.idAddAuxGeom, GDB_ID.ROOT) + EgtMV( Proc.idAddAuxGeom, GDB_ID.ROOT) + EgtEV( Proc.idAddAuxGeom, GDB_ID.ROOT)
|
||||
Strategy.Machinings[i].dLengthOnX = Proc.b3Box:getDimX()
|
||||
|
||||
local MachiningToSplit = {}
|
||||
table.insert( MachiningToSplit, Strategy.Machinings[i])
|
||||
local MachiningResult = MachiningLib.GetSplitMachinings( MachiningToSplit, FeatureSplittingPoints, Part)
|
||||
-- aggiunge lavorazione
|
||||
for j = 1, #MachiningResult do
|
||||
bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, MachiningResult[j])
|
||||
end
|
||||
end
|
||||
|
||||
else
|
||||
bAreAllMachiningsAdded = false
|
||||
end
|
||||
|
||||
return bAreAllMachiningsAdded, Strategy.Result
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return STR0009
|
||||
@@ -0,0 +1,55 @@
|
||||
{
|
||||
"sStrategyId": "STR0010",
|
||||
"sStrategyName": "Milling",
|
||||
"ParameterList" : [
|
||||
{
|
||||
"sName": "dAntiSplintWithBlade",
|
||||
"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 lenght 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": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,268 @@
|
||||
-- Strategia: STR0010
|
||||
-- Descrizione
|
||||
-- fresatura perpendicolare
|
||||
-- Feature: cut, longcut, ...
|
||||
|
||||
-- carico librerie
|
||||
local BeamLib = require( 'BeamLib')
|
||||
local BeamData = require( 'BeamData')
|
||||
local MachiningLib = require( 'MachiningLib')
|
||||
local FeatureLib = require( 'FeatureLib')
|
||||
-- strategie di base
|
||||
local FaceByMill = require('FACEBYMILL')
|
||||
|
||||
-- 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 / 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 CompareEdges( EdgeA, EdgeB)
|
||||
-- prima i lati orientati lungo X
|
||||
if abs( EdgeA.vtN:getX()) < abs( EdgeB.vtN:getX()) - 10 * GEO.EPS_SMALL then
|
||||
return true
|
||||
elseif abs( EdgeA.vtN:getX()) > abs( EdgeB.vtN:getX()) + 10 * GEO.EPS_SMALL then
|
||||
return false
|
||||
-- se stessa X si preferiscono i lati più lunghi (nel caso di 5 lati è quello non spezzato)
|
||||
else
|
||||
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
|
||||
-- TODO qui dipenderà dalla lama scelta
|
||||
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
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function IsTopologyOk( Proc)
|
||||
if Proc.Topology.sFamily == 'Bevel' or Proc.Topology.sFamily == 'DoubleBevel' or
|
||||
Proc.Topology.sName == 'VGroove-2-Through' or Proc.Topology.sName == 'Rabbet-2-Through' then
|
||||
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
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-- TODO da sistemare
|
||||
local function GetBottomFaceEdge( Proc, nIndexFace)
|
||||
local Edge = {}
|
||||
|
||||
-- si lavora la bottom longitudinalmente
|
||||
if Proc.nFct == 1 or Proc.Topology.sFamily == 'DoubleBevel' then
|
||||
local BottomEdgesSorted = {}
|
||||
for i = 1, #Proc.MainFaces.BottomFaces[nIndexFace].Edges do
|
||||
table.insert( BottomEdgesSorted, Proc.MainFaces.BottomFaces[nIndexFace].Edges[i])
|
||||
end
|
||||
table.sort( BottomEdgesSorted, CompareEdges)
|
||||
Edge = BottomEdgesSorted[1]
|
||||
-- edge in comune tra le due facce
|
||||
elseif Proc.nFct == 2 then
|
||||
if nIndexFace == 1 then
|
||||
Edge = Proc.MainFaces.BottomFaces[nIndexFace].MainEdges.LongEdges[1]
|
||||
elseif nIndexFace == 2 then
|
||||
Edge = Proc.MainFaces.BottomFaces[nIndexFace].MainEdges.BottomEdge
|
||||
end
|
||||
else
|
||||
if nIndexFace == 1 then
|
||||
Edge = Proc.MainFaces.BottomFaces[nIndexFace].MainEdges.LongEdges[1]
|
||||
elseif nIndexFace == 2 then
|
||||
Edge = Proc.MainFaces.BottomFaces[nIndexFace].MainEdges.BottomEdge
|
||||
end
|
||||
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
|
||||
else
|
||||
if TOOLS[ MachiningA.nToolIndex].sFamily == 'SAWBLADE' and TOOLS[ MachiningB.nToolIndex].sFamily == 'MORTISE' then
|
||||
return true
|
||||
elseif TOOLS[ MachiningA.nToolIndex].sFamily == 'MORTISE' and TOOLS[ MachiningB.nToolIndex].sFamily == 'SAWBLADE' then
|
||||
return false
|
||||
else
|
||||
if MachiningA.sEdgeType == 'Side' and MachiningB.sEdgeType ~= 'Side' then
|
||||
return true
|
||||
elseif MachiningB.sEdgeType == 'Side' and MachiningA.sEdgeType ~= 'Side' then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
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 = {}
|
||||
|
||||
-- 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
|
||||
if not IsPositionOK( Proc, Part) then
|
||||
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( 'Feature not machinable in this position')
|
||||
return false, Strategy.Result
|
||||
end
|
||||
|
||||
-- volume della feature
|
||||
local dFeatureVolume = FeatureLib.GetFeatureVolume( Proc, Part)
|
||||
|
||||
-- TODO taglio su eventuali facce di chiusura
|
||||
|
||||
-- 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
|
||||
|
||||
-- lavorazione della BottomFace
|
||||
local bAreAllMachiningsAdded = true
|
||||
local Milling = {}
|
||||
local OptionalParametersFaceByMill = { nStepType = MCH_MILL_ST.ONEWAY, bIsSplitFeature = bIsSplitFeature, dExtendAfterTail = dExtendAfterTail}
|
||||
local EdgeToMachine = GetBottomFaceEdge( Proc, 1)
|
||||
if EdgeToMachine.bIsOpen then
|
||||
OptionalParametersFaceByMill.dDepthToMachine = EdgeToMachine.dElevation + BeamData.CUT_EXTRA
|
||||
end
|
||||
Milling = FaceByMill.Make( Proc, Part, Proc.MainFaces.BottomFaces[1], EdgeToMachine, OptionalParametersFaceByMill)
|
||||
if Milling.bIsApplicable then
|
||||
table.insert( Strategy.Machinings, Milling)
|
||||
end
|
||||
|
||||
-- si lavora seconda BottomFace
|
||||
if Proc.Topology.sFamily == 'DoubleBevel' or Proc.Topology.sName == 'Rabbet-2-Through' or Proc.Topology.sName == 'Bevel-2-Blind' then
|
||||
local dAngleBetweenFaces = Proc.AdjacencyMatrix[1][2]
|
||||
-- se convesso o concavo maggiore di angolo retto
|
||||
if dAngleBetweenFaces >= -91 then
|
||||
Milling = {}
|
||||
OptionalParametersFaceByMill = { nStepType = MCH_MILL_ST.ONEWAY, bIsSplitFeature = bIsSplitFeature, dExtendAfterTail = dExtendAfterTail}
|
||||
EdgeToMachine = GetBottomFaceEdge( Proc, 2)
|
||||
if EdgeToMachine.bIsOpen then
|
||||
OptionalParametersFaceByMill.dDepthToMachine = EdgeToMachine.dElevation + BeamData.CUT_EXTRA
|
||||
end
|
||||
Milling = FaceByMill.Make( Proc, Part, Proc.MainFaces.BottomFaces[2], EdgeToMachine, OptionalParametersFaceByMill)
|
||||
if Milling.bIsApplicable then
|
||||
table.insert( Strategy.Machinings, Milling)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- calcolo completamento, serve la lista di lavorazioni che comprende le non applicabili
|
||||
Strategy.Result.dCompletionPercentage = GetStrategyCompletionPercentage( Strategy.Machinings)
|
||||
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( Strategy.Result.dCompletionPercentage)
|
||||
|
||||
Strategy.Machinings = MachiningLib.GetSplitMachinings( Strategy.Machinings, FeatureSplittingPoints, Part)
|
||||
table.sort( Strategy.Machinings, SortMachiningsBySegment)
|
||||
|
||||
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( Strategy.Machinings)
|
||||
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
|
||||
bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, Strategy.Machinings[j])
|
||||
end
|
||||
end
|
||||
else
|
||||
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable()
|
||||
end
|
||||
|
||||
return bAreAllMachiningsAdded, Strategy.Result
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return STR0010
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,272 @@
|
||||
-- Strategia: STR0011
|
||||
-- Descrizione
|
||||
-- foratura
|
||||
-- Feature: foro
|
||||
|
||||
-- carico librerie
|
||||
local BeamLib = require( 'BeamLib')
|
||||
local BeamData = require( 'BeamData')
|
||||
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 = {}
|
||||
local sQuality
|
||||
|
||||
-- se lavorazione orizzontale
|
||||
if Proc.FeatureInfo.bIsDrillHorizontal then
|
||||
local bDouble = false
|
||||
local Drilling = MachiningLib.InitMachiningParameters( MCH_MY.DRILLING)
|
||||
Drilling.bIsApplicable = false
|
||||
ToolSearchParameters = {}
|
||||
ToolSearchParameters.dElevation = Proc.FeatureInfo.dDrillLen + BeamData.MILL_OVERLAP
|
||||
ToolSearchParameters.vtToolDirection = Proc.FeatureInfo.vtDrillExtrusion
|
||||
ToolSearchParameters.dToolDiameter = Proc.FeatureInfo.dDrillDiam
|
||||
ToolSearchParameters.dDiameterTolerance = Strategy.Parameters.dDiameterTolerance
|
||||
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sDrillBitList, 'Drilling')
|
||||
Drilling.ToolInfo = {}
|
||||
Drilling.ToolInfo = MachiningLib.FindDrill( Proc, ToolSearchParameters)
|
||||
if Drilling.ToolInfo.nToolIndex then
|
||||
Drilling.nToolIndex = Drilling.ToolInfo.nToolIndex
|
||||
Drilling.Geometry = {{ Proc.FeatureInfo.idAddAuxGeom, -1}}
|
||||
Drilling.dStep = TOOLS[Drilling.ToolInfo.nToolIndex].dStep
|
||||
-- se lavorazione non completa o se si deve forare dai due lati
|
||||
if Proc.FeatureInfo.bIsDrillOpen and
|
||||
( Drilling.ToolInfo.dResidualDepth > 10 * GEO.EPS_SMALL or Strategy.Parameters.sDrillingMode == 'FORCE_TWO' or Strategy.Parameters.sDrillingMode == 'AUTO') then
|
||||
bDouble = true
|
||||
local dHalfDrill = ( Proc.FeatureInfo.dDrillLen + BeamData.MILL_OVERLAP) / 2
|
||||
Drilling.sDepth = min( dHalfDrill, Proc.FeatureInfo.dDrillLen - Drilling.ToolInfo.dResidualDepth)
|
||||
Drilling.vtFaceNormal = Proc.FeatureInfo.vtDrillExtrusion
|
||||
Drilling.bInvert = false
|
||||
Drilling.vtToolDirection = Proc.FeatureInfo.vtDrillExtrusion
|
||||
table.insert( Machining, Drilling)
|
||||
local Drilling2 = BeamLib.TableCopyDeep( Drilling)
|
||||
Drilling2.bInvert = true
|
||||
Drilling2.vtToolDirection = -Proc.FeatureInfo.vtDrillExtrusion
|
||||
table.insert( Machining, Drilling2)
|
||||
else
|
||||
Drilling.sDepth = 'TH'
|
||||
Drilling.vtFaceNormal = Proc.FeatureInfo.vtDrillExtrusion
|
||||
Drilling.bInvert = false
|
||||
Drilling.vtToolDirection = Proc.FeatureInfo.vtDrillExtrusion
|
||||
table.insert( Machining, Drilling)
|
||||
end
|
||||
|
||||
-- voto
|
||||
if Drilling.ToolInfo.dResidualDepth < 0 or ( Proc.FeatureInfo.dDrillLen + BeamData.MILL_OVERLAP) / 2 > Drilling.ToolInfo.dResidualDepth then
|
||||
Strategy.Result.sStatus = 'Completed'
|
||||
Strategy.Result.dCompletionIndex = 5
|
||||
Strategy.Result.dMRR = MachiningLib.GetToolMRR( Machining[1].ToolInfo or Machining[2].ToolInfo)
|
||||
if bDouble or not Proc.FeatureInfo.bIsDrillOpen then
|
||||
sQuality = 'FINE'
|
||||
else
|
||||
sQuality = 'ROUGH'
|
||||
end
|
||||
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( sQuality)
|
||||
Strategy.Result.sInfo = ''
|
||||
else
|
||||
Strategy.Result.sStatus = 'Not-Completed'
|
||||
local dMachinedLen = EgtIf( bDouble, Machining[1].sDepth * 2, Proc.FeatureInfo.dDrillLen)
|
||||
local dMachinedPrercentage = 100 * ( dMachinedLen / Proc.FeatureInfo.dDrillLen)
|
||||
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( dMachinedPrercentage)
|
||||
Strategy.Result.sInfo = 'Drill not complete, left ' .. tostring( 100 - ceil( dMachinedPrercentage)) .. '%'
|
||||
Strategy.Result.dMRR = MachiningLib.GetToolMRR( Machining[1].ToolInfo or Machining[2].ToolInfo)
|
||||
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'FINE') -- se non completo, anche se fosse foro singolo, comunque non esce dall'altra parte, quindi non scheggia
|
||||
end
|
||||
else
|
||||
local sMessage = 'Drillbit not found'
|
||||
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( sMessage)
|
||||
end
|
||||
-- se lavorazione verticale
|
||||
else
|
||||
-- si cerca utensile 1
|
||||
local Drilling = MachiningLib.InitMachiningParameters( MCH_MY.DRILLING)
|
||||
ToolSearchParameters = {}
|
||||
ToolSearchParameters.dElevation = Proc.FeatureInfo.dDrillLen + BeamData.MILL_OVERLAP
|
||||
ToolSearchParameters.vtToolDirection = Proc.FeatureInfo.vtDrillExtrusion
|
||||
ToolSearchParameters.dToolDiameter = Proc.FeatureInfo.dDrillDiam
|
||||
ToolSearchParameters.dDiameterTolerance = Strategy.Parameters.dDiameterTolerance
|
||||
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sDrillBitList, 'Drilling')
|
||||
Drilling.ToolInfo = {}
|
||||
Drilling.ToolInfo = MachiningLib.FindDrill( Proc, ToolSearchParameters)
|
||||
-- si cerca utensile 2
|
||||
local Drilling2 = MachiningLib.InitMachiningParameters( MCH_MY.DRILLING)
|
||||
Drilling2.ToolInfo = {}
|
||||
if Proc.FeatureInfo.bIsDrillOpen then
|
||||
ToolSearchParameters = {}
|
||||
ToolSearchParameters.dElevation = Proc.FeatureInfo.dDrillLen + BeamData.MILL_OVERLAP
|
||||
ToolSearchParameters.vtToolDirection = -Proc.FeatureInfo.vtDrillExtrusion
|
||||
ToolSearchParameters.dDiameterTolerance = Strategy.Parameters.dDiameterTolerance
|
||||
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sDrillBitList, 'Drilling')
|
||||
Drilling2.ToolInfo = MachiningLib.FindDrill( Proc, ToolSearchParameters)
|
||||
end
|
||||
|
||||
-- se possono lavorare entrambi e si deve fare lavorazione doppia e si riesce a completare
|
||||
if Drilling.ToolInfo.nToolIndex and Drilling2.ToolInfo.nToolIndex and
|
||||
( Strategy.Parameters.sDrillingMode == 'FORCE_TWO' or Strategy.Parameters.sDrillingMode == 'AUTO') and
|
||||
Drilling.ToolInfo.dResidualDepth + Drilling2.ToolInfo.dResidualDepth < Proc.FeatureInfo.dDrillLen then
|
||||
|
||||
local dExtraDrill = ( Proc.FeatureInfo.dDrillLen - BeamData.MILL_OVERLAP - ( Drilling.ToolInfo.dResidualDepth + Drilling2.ToolInfo.dResidualDepth)) / 2
|
||||
Drilling.nToolIndex = Drilling.ToolInfo.nToolIndex
|
||||
Drilling.Geometry = {{ Proc.FeatureInfo.idAddAuxGeom, -1}}
|
||||
Drilling.vtToolDirection = Proc.FeatureInfo.vtDrillExtrusion
|
||||
Drilling.sDepth = Proc.FeatureInfo.dDrillLen - Drilling.ToolInfo.dResidualDepth - dExtraDrill
|
||||
table.insert( Machining, Drilling)
|
||||
|
||||
Drilling2.nToolIndex = Drilling2.ToolInfo.nToolIndex
|
||||
Drilling2.Geometry = {{ Proc.FeatureInfo.idAddAuxGeom, -1}}
|
||||
Drilling2.bInvert = true
|
||||
Drilling2.vtToolDirection = -Proc.FeatureInfo.vtDrillExtrusion
|
||||
Drilling2.sDepth = Proc.FeatureInfo.dDrillLen - Drilling2.ToolInfo.dResidualDepth - dExtraDrill
|
||||
table.insert( Machining, Drilling2)
|
||||
|
||||
-- voto
|
||||
Strategy.Result.sStatus = 'Completed'
|
||||
Strategy.Result.dCompletionIndex = 5
|
||||
Strategy.Result.sInfo = ''
|
||||
Strategy.Result.dMRR = MachiningLib.GetToolMRR( Machining[1].ToolInfo)
|
||||
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'FINE')
|
||||
|
||||
-- se utensile 1 esegue completamente
|
||||
elseif Drilling.ToolInfo.nToolIndex and Drilling.ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL and
|
||||
( Strategy.Parameters.sDrillingMode == 'PREFER_ONE' or ( not Drilling2.ToolInfo.nToolIndex and Strategy.Parameters.sDrillingMode == 'AUTO') or not Proc.FeatureInfo.bIsDrillOpen) then
|
||||
Drilling.sDepth = 'TH'
|
||||
Drilling.nToolIndex = Drilling.ToolInfo.nToolIndex
|
||||
Drilling.Geometry = {{ Proc.FeatureInfo.idAddAuxGeom, -1}}
|
||||
Drilling.vtToolDirection = Proc.FeatureInfo.vtDrillExtrusion
|
||||
table.insert( Machining, Drilling)
|
||||
-- voto
|
||||
Strategy.Result.sStatus = 'Completed'
|
||||
Strategy.Result.dCompletionIndex = 5
|
||||
Strategy.Result.dMRR = MachiningLib.GetToolMRR( Machining[1].ToolInfo)
|
||||
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( EgtIf( Proc.FeatureInfo.bIsDrillOpen, 'ROUGH', 'FINE'))
|
||||
Strategy.Result.sInfo = ''
|
||||
-- se utensile 2 esegue completamente
|
||||
elseif Drilling2.ToolInfo.nToolIndex and Drilling2.ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL and
|
||||
( Strategy.Parameters.sDrillingMode == 'PREFER_ONE' or ( not Drilling.ToolInfo.nToolIndex and Strategy.Parameters.sDrillingMode == 'AUTO')) then
|
||||
Drilling2.sDepth = 'TH'
|
||||
Drilling2.nToolIndex = Drilling2.ToolInfo.nToolIndex
|
||||
Drilling2.Geometry = {{ Proc.FeatureInfo.idAddAuxGeom, -1}}
|
||||
Drilling2.bInvert = true
|
||||
Drilling2.vtToolDirection = -Proc.FeatureInfo.vtDrillExtrusion
|
||||
table.insert( Machining, Drilling2)
|
||||
-- voto
|
||||
Strategy.Result.sStatus = 'Completed'
|
||||
Strategy.Result.dCompletionIndex = 5
|
||||
Strategy.Result.dMRR = MachiningLib.GetToolMRR( Machining[1].ToolInfo)
|
||||
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( EgtIf( Proc.FeatureInfo.bIsDrillOpen, 'ROUGH', 'FINE'))
|
||||
Strategy.Result.sInfo = ''
|
||||
-- se possono lavorare entrambi
|
||||
elseif Drilling.ToolInfo.nToolIndex and Drilling2.ToolInfo.nToolIndex then
|
||||
Drilling.nToolIndex = Drilling.ToolInfo.nToolIndex
|
||||
Drilling.Geometry = {{ Proc.FeatureInfo.idAddAuxGeom, -1}}
|
||||
Drilling.vtToolDirection = Proc.FeatureInfo.vtDrillExtrusion
|
||||
Drilling.sDepth = Proc.FeatureInfo.dDrillLen - Drilling.ToolInfo.dResidualDepth
|
||||
table.insert( Machining, Drilling)
|
||||
|
||||
Drilling2.nToolIndex = Drilling2.ToolInfo.nToolIndex
|
||||
Drilling2.Geometry = {{ Proc.FeatureInfo.idAddAuxGeom, -1}}
|
||||
Drilling2.bInvert = true
|
||||
Drilling2.vtToolDirection = -Proc.FeatureInfo.vtDrillExtrusion
|
||||
Drilling2.sDepth = Proc.FeatureInfo.dDrillLen - Drilling2.ToolInfo.dResidualDepth
|
||||
table.insert( Machining, Drilling2)
|
||||
if Drilling.ToolInfo.dResidualDepth + Drilling2.ToolInfo.dResidualDepth < Proc.FeatureInfo.dDrillLen then
|
||||
Strategy.Result.sStatus = 'Not-Completed'
|
||||
local dMachinedLen = Machining[1].sDepth + Machining[2].sDepth
|
||||
local dMachinedPrercentage = 100 * ( dMachinedLen / Proc.FeatureInfo.dDrillLen)
|
||||
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( dMachinedPrercentage)
|
||||
Strategy.Result.sInfo = 'Drill not complete, left ' .. tostring( 100 - ceil( dMachinedPrercentage)) .. '%'
|
||||
else
|
||||
Strategy.Result.sStatus = 'Completed'
|
||||
Strategy.Result.dCompletionIndex = 5
|
||||
Strategy.Result.sInfo = ''
|
||||
end
|
||||
-- voto
|
||||
Strategy.Result.dMRR = MachiningLib.GetToolMRR( Machining[1].ToolInfo)
|
||||
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'FINE')
|
||||
-- se utensile 1 non completo
|
||||
elseif Drilling.ToolInfo.nToolIndex and ( Strategy.Parameters.sDrillingMode ~= 'FORCE_TWO' or Proc.FeatureInfo.bIsDrillOpen) then
|
||||
Drilling.sDepth = Proc.FeatureInfo.dDrillLen - Drilling.ToolInfo.dResidualDepth
|
||||
Drilling.nToolIndex = Drilling.ToolInfo.nToolIndex
|
||||
Drilling.Geometry = {{ Proc.FeatureInfo.idAddAuxGeom, -1}}
|
||||
Drilling.vtToolDirection = Proc.FeatureInfo.vtDrillExtrusion
|
||||
Drilling.sDepth = Proc.FeatureInfo.dDrillLen - Drilling.ToolInfo.dResidualDepth
|
||||
table.insert( Machining, Drilling)
|
||||
-- voto
|
||||
Strategy.Result.sStatus = 'Not-Completed'
|
||||
local dMachinedLen = Machining[1].sDepth
|
||||
local dMachinedPrercentage = 100 * ( dMachinedLen / Proc.FeatureInfo.dDrillLen)
|
||||
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( dMachinedPrercentage)
|
||||
Strategy.Result.sInfo = 'Drill not complete, left ' .. tostring( 100 - ceil( dMachinedPrercentage)) .. '%'
|
||||
Strategy.Result.dMRR = MachiningLib.GetToolMRR( Machining[1].ToolInfo)
|
||||
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'FINE')
|
||||
-- se utensile 2 non completo
|
||||
elseif Drilling2.ToolInfo.nToolIndex and Strategy.Parameters.sDrillingMode ~= 'FORCE_TWO' then
|
||||
Drilling2.sDepth = Proc.FeatureInfo.dDrillLen - Drilling2.ToolInfo.dResidualDepth
|
||||
Drilling2.nToolIndex = Drilling2.ToolInfo.nToolIndex
|
||||
Drilling2.Geometry = {{ Proc.FeatureInfo.idAddAuxGeom, -1}}
|
||||
Drilling2.bInvert = true
|
||||
Drilling2.vtToolDirection = -Proc.FeatureInfo.vtDrillExtrusion
|
||||
Drilling2.sDepth = Proc.FeatureInfo.dDrillLen - Drilling2.ToolInfo.dResidualDepth
|
||||
table.insert( Machining, Drilling2)
|
||||
-- voto
|
||||
Strategy.Result.sStatus = 'Not-Completed'
|
||||
local dMachinedLen = Machining[1].sDepth
|
||||
local dMachinedPrercentage = 100 * ( dMachinedLen / Proc.FeatureInfo.dDrillLen)
|
||||
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( dMachinedPrercentage)
|
||||
Strategy.Result.sInfo = 'Drill not complete, left ' .. tostring( 100 - ceil( dMachinedPrercentage)) .. '%'
|
||||
Strategy.Result.dMRR = MachiningLib.GetToolMRR( Machining[1].ToolInfo)
|
||||
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'FINE')
|
||||
else
|
||||
local sMessage
|
||||
-- se non sono state trovate punte
|
||||
if not Drilling.ToolInfo.nToolIndex and not Drilling2.ToolInfo.nToolIndex then
|
||||
sMessage = 'Drillbit not found'
|
||||
-- se son state trovate delle punte, ma non è stato possibile forare da entrambe le parti
|
||||
elseif Strategy.Parameters.sDrillingMode == 'FORCE_TWO' then
|
||||
sMessage = "Not possible to force machining from both sides. Please change drilling mode to AUTO"
|
||||
end
|
||||
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( sMessage)
|
||||
end
|
||||
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
|
||||
@@ -0,0 +1,109 @@
|
||||
{
|
||||
"sStrategyId": "STR0012",
|
||||
"sStrategyName": "RidgeLap with Blade",
|
||||
"ParameterList" : [
|
||||
{
|
||||
"sName": "dExtendAfterTail",
|
||||
"sNameNge": "EXTEND_AFTER_TAIL",
|
||||
"sValue": "",
|
||||
"sDescriptionShort": "Extend after tail",
|
||||
"sDescriptionLong": "The automatism considers this lenght as machinable. This means you accept to damage the next piece in the bar",
|
||||
"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": "dMinZAngleTopBlade",
|
||||
"sNameNge": "MIN_Z_ANGLE_TOP_BLADE",
|
||||
"sValue": "",
|
||||
"sDescriptionShort": "Min Z angle top blade",
|
||||
"sDescriptionLong": "",
|
||||
"sType": "d",
|
||||
"sMessageId": " ",
|
||||
"sMinUserLevel": "1"
|
||||
},
|
||||
{
|
||||
"sName": "dMaxYAngleTopBlade",
|
||||
"sNameNge": "MAX_Y_ANGLE_TOP_BLADE",
|
||||
"sValue": "",
|
||||
"sDescriptionShort": "Max Y angle top blade",
|
||||
"sDescriptionLong": "",
|
||||
"sType": "d",
|
||||
"sMessageId": " ",
|
||||
"sMinUserLevel": "1"
|
||||
},
|
||||
{
|
||||
"sName": "dMaxWasteLength",
|
||||
"sSource": "GEN_dMaxWasteLength",
|
||||
"sMinUserLevel": "5"
|
||||
},
|
||||
{
|
||||
"sName": "dMaxWasteVolume",
|
||||
"sSource": "GEN_dMaxWasteVolume",
|
||||
"sMinUserLevel": "5"
|
||||
},
|
||||
{
|
||||
"sName": "bReduceBladePath",
|
||||
"sSource": "GEN_bReduceBladePath",
|
||||
"sMinUserLevel": "5"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
-- Strategia: STR0012
|
||||
-- Descrizione
|
||||
-- RidgeLap
|
||||
-- Feature: RidgeLap
|
||||
|
||||
-- carico librerie
|
||||
local BeamLib = require( 'BeamLib')
|
||||
local BeamData = require( 'BeamData')
|
||||
local MachiningLib = require( 'MachiningLib')
|
||||
local FeatureLib = require( 'FeatureLib')
|
||||
-- strategie di base
|
||||
local BladeToWaste = require( 'BLADETOWASTE')
|
||||
local 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[1][2] > 10 * GEO.EPS_ANG_SMALL and Proc.AdjacencyMatrix[2][3] < 10 * GEO.EPS_ANG_SMALL then
|
||||
nAddedFace = 1 - 1
|
||||
elseif Proc.AdjacencyMatrix[2][3] > 10 * GEO.EPS_ANG_SMALL and Proc.AdjacencyMatrix[3][1] < 10 * GEO.EPS_ANG_SMALL then
|
||||
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
|
||||
idAddedTmFace = EgtCopySurfTmFacet( Proc.id, nAddedFace, nAddGrpId)
|
||||
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)
|
||||
|
||||
-- TODO rimuovere??? codolo da implementare o no??
|
||||
-- considerazioni necessarie a determinare se lavorare con codolo oppure no
|
||||
local bKeepWasteAttached = ( Strategy.Parameters.sCuttingStrategy == 'KEEP_WASTE_ATTACHED')
|
||||
local bDropWaste = ( Strategy.Parameters.sCuttingStrategy == 'DROP_WASTE')
|
||||
local dFeatureMaxNotClampableLengthHead, dFeatureMaxNotClampableLengthTail = FeatureLib.GetFeatureMaxNotClampableLengths( NewProc, Part)
|
||||
local bFeatureHindersClamping = FeatureLib.IsMachiningLong( max( dFeatureMaxNotClampableLengthHead, dFeatureMaxNotClampableLengthTail), Part, { dMaxSegmentLength = BeamData.LONGCUT_ENDLEN})
|
||||
local bIsFeatureLong = FeatureLib.IsMachiningLong( NewProc.b3Box:getDimX(), Part, { dMaxSegmentLength = BeamData.LONGCUT_ENDLEN})
|
||||
|
||||
-- lavorazione con codolo
|
||||
if ( bIsFeatureLong)
|
||||
or ( 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 dMinZTopBlade
|
||||
local dMaxNyTopBlade
|
||||
local BladeToWasteResult
|
||||
if Strategy.Parameters.dMinZAngleTopBlade then
|
||||
dMinZTopBlade = sin( Strategy.Parameters.dMinZAngleTopBlade)
|
||||
end
|
||||
if Strategy.Parameters.dMaxYAngleTopBlade then
|
||||
dMaxNyTopBlade = sin( Strategy.Parameters.dMaxYAngleTopBlade)
|
||||
end
|
||||
local OptionalParameters = { dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume,
|
||||
dMaxWasteLength = Strategy.Parameters.dMaxWasteLength,
|
||||
dMinNzTopBlade = dMinZTopBlade,
|
||||
dMaxNyTopBlade = dMaxNyTopBlade,
|
||||
bSaveAddedGeometries = bAddMachining,
|
||||
dExtendAfterTail = dExtendAfterTail,
|
||||
bReduceBladePath = Strategy.Parameters.bReduceBladePath
|
||||
}
|
||||
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 dMinZTopBlade
|
||||
local dMaxNyTopBlade
|
||||
local BladeToWasteResult
|
||||
if Strategy.Parameters.dMinZAngleTopBlade then
|
||||
dMinZTopBlade = sin( Strategy.Parameters.dMinZAngleTopBlade)
|
||||
end
|
||||
if Strategy.Parameters.dMaxYAngleTopBlade then
|
||||
dMaxNyTopBlade = sin( Strategy.Parameters.dMaxYAngleTopBlade)
|
||||
end
|
||||
local OptionalParameters = { dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume,
|
||||
dMaxWasteLength = Strategy.Parameters.dMaxWasteLength,
|
||||
dMinNzTopBlade = dMinZTopBlade,
|
||||
dMaxNyTopBlade = dMaxNyTopBlade,
|
||||
bSaveAddedGeometries = bAddMachining,
|
||||
dExtendAfterTail = dExtendAfterTail,
|
||||
bReduceBladePath = Strategy.Parameters.bReduceBladePath
|
||||
}
|
||||
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
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
-- Strategia: STR0013
|
||||
-- Descrizione
|
||||
-- foratura
|
||||
-- Feature: foro con fresa
|
||||
|
||||
-- carico librerie
|
||||
local BeamLib = require( 'BeamLib')
|
||||
local BeamData = require( 'BeamData')
|
||||
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 < 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}}
|
||||
bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, MachiningToAdd)
|
||||
end
|
||||
end
|
||||
|
||||
return bAreAllMachiningsAdded, Strategy.Result
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return STR0013
|
||||
@@ -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": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,126 @@
|
||||
-- Strategia: STR0014
|
||||
-- Descrizione
|
||||
-- Incisione con fresa
|
||||
-- Feature tipo Mark
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
-- carico librerie
|
||||
local BeamLib = require( 'BeamLib')
|
||||
local BeamData = require( 'BeamData')
|
||||
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 = EgtSetMachiningGeometry( {{ AuxId, -1}})
|
||||
end
|
||||
|
||||
bAreAllMachiningsAdded = MachiningLib.AddMachinings( Proc, Strategy.Machining, Strategy.AuxiliaryData)
|
||||
end
|
||||
else
|
||||
bAreAllMachiningsAdded = false
|
||||
end
|
||||
|
||||
return bAreAllMachiningsAdded, Strategy.Result
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return STR0014
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,864 @@
|
||||
-- Strategia: STR0015
|
||||
-- Descrizione
|
||||
-- Fresatura di contorno
|
||||
-- Feature tipo Profilo arcuato, Convesso, Concavo, Arco
|
||||
|
||||
|
||||
-- carico librerie
|
||||
local BeamLib = require( 'BeamLib')
|
||||
local BeamData = require( 'BeamData')
|
||||
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 nAddGroupId = BeamLib.GetAddGroup( Part.id)
|
||||
-- aggiungo piano di sgrossatura e lo lavoro
|
||||
local ptStart, vtNP = GetSawCutData( Proc, Proc.idAddAuxGeom, vtNF, vtN)
|
||||
local AddId = EgtSurfTmPlaneInBBox( nAddGroupId, ptStart, vtNP, Part.b3Part, GDB_RT.GLOB)
|
||||
-- se la faccia è stata creata
|
||||
if AddId then
|
||||
if not bSaveAddedGeometries then
|
||||
EgtSetLevel( AddId, GDB_LV.TEMP)
|
||||
end
|
||||
|
||||
-- creo piano di taglio sulla testa del tenone
|
||||
local OptionalParameters = { dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume,
|
||||
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 vtN:getZ() > 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
|
||||
|
||||
-- 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
|
||||
-- TODO c'è una funzione che ritorni l'edge di connessione tra una faccia e un'altra?
|
||||
-- lavorazione faccia 1 spigolo finale
|
||||
if bLastTrim then
|
||||
local EdgeToMachine = GetEdgeToMachine( Proc, nLastFacet+1, vtCutDir1)
|
||||
local Cutting = FaceByBlade.Make( Proc, Part, Proc.Faces[nLastFacet+1], EdgeToMachine)
|
||||
if Proc.AffectedFaces.bLeft and Strategy.bCanMoveAfterSplit then
|
||||
Cutting.sStage = 'AfterTail'
|
||||
end
|
||||
if Cutting then
|
||||
table.insert( Machining, Cutting)
|
||||
end
|
||||
end
|
||||
|
||||
-- lavorazione faccia 1 spigolo iniziale
|
||||
if bFirstTrim then
|
||||
local EdgeToMachine = GetEdgeToMachine( Proc, nFirstFacet+2, vtCutDir1)
|
||||
local Cutting = FaceByBlade.Make( Proc, Part, Proc.Faces[nFirstFacet+2], EdgeToMachine)
|
||||
if Proc.AffectedFaces.bLeft and Strategy.bCanMoveAfterSplit then
|
||||
Cutting.sStage = 'AfterTail'
|
||||
end
|
||||
if Cutting then
|
||||
table.insert( Machining, Cutting)
|
||||
end
|
||||
end
|
||||
|
||||
-- lavorazione faccia 2 spigolo finale
|
||||
if bLastTrim then
|
||||
EdgeToMachine = GetEdgeToMachine( Proc, nLastFacet, vtCutDir2)
|
||||
Cutting = FaceByBlade.Make( Proc, Part, Proc.Faces[nLastFacet], EdgeToMachine)
|
||||
if Cutting then
|
||||
table.insert( Machining, Cutting)
|
||||
end
|
||||
end
|
||||
|
||||
-- lavorazione faccia 2 spigolo iniziale
|
||||
if bFirstTrim then
|
||||
local EdgeToMachine = GetEdgeToMachine( Proc, nFirstFacet+1, vtCutDir2)
|
||||
local Cutting = FaceByBlade.Make( Proc, Part, Proc.Faces[nFirstFacet+1], EdgeToMachine)
|
||||
if Cutting then
|
||||
table.insert( Machining, Cutting)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- se non ci sono lavorazioni provo a pulire spigoli con fresa, a patto che non sia stato forzato con lama
|
||||
if #Machining == 0 and Strategy.Parameters.sConcaveFaceStrategy ~= 'BLADE_FORCED' then
|
||||
-- TODO c'è una funzione che ritorni l'edge di connessione tra una faccia e un'altra?
|
||||
-- lavorazione faccia 1 spigolo iniziale
|
||||
if bFirstTrim then
|
||||
local EdgeToMachine = GetEdgeToMachine( Proc, nFirstFacet+2, vtCutDir1)
|
||||
local Milling = FaceByMill.Make( Proc, Part, Proc.Faces[nFirstFacet+2], EdgeToMachine)
|
||||
if Proc.AffectedFaces.bLeft and Strategy.bCanMoveAfterSplit then
|
||||
Milling.sStage = 'AfterTail'
|
||||
end
|
||||
if Milling then
|
||||
table.insert( Machining, Milling)
|
||||
end
|
||||
end
|
||||
|
||||
-- lavorazione faccia 2 spigolo finale
|
||||
if bLastTrim then
|
||||
EdgeToMachine = GetEdgeToMachine( Proc, nLastFacet, vtCutDir2)
|
||||
local Milling = FaceByMill.Make( Proc, Part, Proc.Faces[nLastFacet], EdgeToMachine)
|
||||
if Proc.AffectedFaces.bLeft and Strategy.bCanMoveAfterSplit then
|
||||
Milling.sStage = 'AfterTail'
|
||||
end
|
||||
if Milling then
|
||||
table.insert( Machining, Milling)
|
||||
end
|
||||
end
|
||||
|
||||
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 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) 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
|
||||
|
||||
-- calcolo se la lavorazione del tenone 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) 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) 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 = {}
|
||||
|
||||
Strategy.Profile.Machinings[i].Steps.dStep = TOOLS[Strategy.Profile.Machinings[i].ToolInfo.nToolIndex].dStep
|
||||
Strategy.Profile.Machinings[i].Steps = MachiningLib.GetMachiningSteps( tonumber( Strategy.Profile.Machinings[i].sDepth), TOOLS[Strategy.Profile.Machinings[i].nToolIndex].dStep)
|
||||
Strategy.Profile.Machinings[i].Steps.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
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,170 @@
|
||||
-- Strategia: TAILCUT
|
||||
-- Descrizione
|
||||
-- Taglio di separazione
|
||||
-- Feature: TailCut
|
||||
|
||||
-- carico librerie
|
||||
local BeamLib = require( 'BeamLib')
|
||||
local BeamData = require( 'BeamData')
|
||||
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 }
|
||||
local bAreAllMachiningsAdded = true
|
||||
local bExecutePrecutOnly = false
|
||||
|
||||
-- si setta che è taglio di coda
|
||||
Strategy.bIsTailCut = true
|
||||
|
||||
-- separazione solo se esiste grezzo successivo con pezzi o scaricabile
|
||||
Strategy.bSplit = not( Part.bIsLastPart) or Part.dRestLength >= BeamData.dMinRaw
|
||||
|
||||
-- se devo fare split perchè c'è un grezzo da scaricare o un altro pezzo
|
||||
if Strategy.bSplit then
|
||||
OptionalParameters.dOffset = 0
|
||||
OptionalParameters.bDisableDicing = true
|
||||
Strategy.SplitStrategy, Strategy.Result = SPLITCUT.GetMachining( Proc, Part, OptionalParameters)
|
||||
|
||||
-- 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
|
||||
OptionalParameters.dOffset = Part.dRestLength
|
||||
end
|
||||
OptionalParameters.bDisableDicing = true
|
||||
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
|
||||
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
|
||||
-- si forza il nome della feature
|
||||
EgtSetName( Proc.id, 'EndCut')
|
||||
|
||||
-- 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
|
||||
OptionalParameters = {}
|
||||
|
||||
-- eventuale grezzo custom per dicing (grezzo attuale + grezzo di coda)
|
||||
local nNextRawId = EgtGetNextRawPart( Part.idRaw)
|
||||
if nNextRawId then
|
||||
local b3BoxDicing = EgtGetRawPartBBox( nNextRawId)
|
||||
b3BoxDicing:Add( Part.b3Raw)
|
||||
OptionalParameters.b3BoxDicing = b3BoxDicing
|
||||
end
|
||||
|
||||
OptionalParameters.dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume
|
||||
OptionalParameters.dMaxWasteLength = Strategy.Parameters.dMaxWasteLength
|
||||
OptionalParameters.bReduceBladePath = Strategy.Parameters.bReduceBladePath
|
||||
|
||||
Strategy.Machining, _ = BladeToWaste.Make( Proc, Part, OptionalParameters)
|
||||
if Strategy.Machining and #Strategy.Machining > 0 then
|
||||
for i = 1, #Strategy.Machining do
|
||||
local TempList = {}
|
||||
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
|
||||
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
|
||||
@@ -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 tasca
|
||||
STR0009 = !!DEPRECATA!! Sostituita da STR0015. RIUTILIZZABILE!
|
||||
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
|
||||
@@ -137,10 +149,6 @@ STR0003 = Topologia tipo LapJoint. Lama + motosega
|
||||
251,0,Feature,
|
||||
; Feature : Aperture
|
||||
252,0,Feature,
|
||||
; Feature : HEADCUT
|
||||
340,0,Feature,HEADCUT
|
||||
; Feature : SPLITCUT
|
||||
350,0,Feature,SPLITCUT
|
||||
; Feature : Variant
|
||||
900,0,Feature,
|
||||
; Feature Decor
|
||||
|
||||
@@ -0,0 +1,287 @@
|
||||
-- BLADEKEEPWASTE.lua by Egalware s.r.l. 2025/03/17
|
||||
-- Libreria di supporto a strategie con funzioni comune a strategie diverse.
|
||||
|
||||
-- Tabella per definizione modulo
|
||||
local BLADEKEEPWASTE = {}
|
||||
|
||||
-- Include
|
||||
require( 'EgtBase')
|
||||
|
||||
-- Carico i dati globali
|
||||
local FeatureLib = require( 'FeatureLib')
|
||||
local FaceData = require( 'FaceData')
|
||||
local MachiningLib = require( 'MachiningLib')
|
||||
-- strategie di base
|
||||
local FaceByBlade = require('FACEBYBLADE')
|
||||
local FaceByMill = require('FACEBYMILL')
|
||||
|
||||
-- tabelle per definizione modulo
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function CompareEdges( EdgeA, EdgeB)
|
||||
-- prima i lati orientati lungo X
|
||||
if abs( EdgeA.vtN:getX()) < abs( EdgeB.vtN:getX()) - 10 * GEO.EPS_SMALL then
|
||||
return true
|
||||
elseif abs( EdgeA.vtN:getX()) > abs( EdgeB.vtN:getX()) + 10 * GEO.EPS_SMALL then
|
||||
return false
|
||||
-- se stessa X si preferiscono i lati più lunghi (nel caso di 5 lati è quello non spezzato)
|
||||
else
|
||||
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
|
||||
-- TODO qui dipenderà dalla lama scelta
|
||||
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
|
||||
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
|
||||
|
||||
|
||||
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 / 100 * dWeight
|
||||
if Machining.bIsApplicable then
|
||||
dCompletionPercentageNumerator = dCompletionPercentageNumerator + dWeightedCompletionPercentage
|
||||
end
|
||||
dCompletionPercentageDenominator = dCompletionPercentageDenominator + dWeight
|
||||
end
|
||||
|
||||
dCompletionPercentage = min( 100 * dCompletionPercentageNumerator / dCompletionPercentageDenominator, 100)
|
||||
|
||||
return dCompletionPercentage
|
||||
end
|
||||
|
||||
|
||||
function BLADEKEEPWASTE.Make( Proc, Part, OptionalParameters)
|
||||
-- TODO verificare funzionamento con lama da sotto
|
||||
-- attenzione perchè se l'inclinazione della faccia la fa finire oltre lo spigolo questo riduce il massimo (come calcolare????)
|
||||
-- il FindBlade dovrà restituire di utilizzare sempre la lama sopra se l'angolo lo permette, ma avendo un'altezza massima (da macchina) oltre cui il DownUp non sarà fattibile (evita collisioni tra asse e pezzo)
|
||||
|
||||
local Result = {}
|
||||
local Machinings = {}
|
||||
local CalculatedMachinings = {}
|
||||
local Cutting1 = {}
|
||||
local Cutting2 = {}
|
||||
|
||||
-- controlli preventivi
|
||||
if Proc.nFct > 3 then
|
||||
error( 'BladeKeepWaste : max 3 faces supported')
|
||||
elseif Proc.nFct == 2 then
|
||||
-- per angolo tra le facce >= 90deg (feature convessa) non applicabile
|
||||
if Proc.AdjacencyMatrix[1][2] > 10 * GEO.EPS_SMALL or Proc.AdjacencyMatrix[1][2] < -91 then
|
||||
Result = FeatureLib.GetStrategyResultNotApplicable( 'BladeKeepWaste : angle between faces must be concave and >= 90deg')
|
||||
return Machinings, Result
|
||||
end
|
||||
-- Rabbet lungo X non gestito
|
||||
if Proc.Topology.sName == 'Rabbet-2-Through' and Proc.AffectedFaces.bLeft and Proc.AffectedFaces.bRight then
|
||||
Result = FeatureLib.GetStrategyResultNotApplicable( 'BladeKeepWaste : Rabbet along X not managed')
|
||||
return Machinings, Result
|
||||
end
|
||||
elseif Proc.nFct == 3 then
|
||||
-- caso speciale RidgeLap - per angolo tra le facce >= 90deg (feature convessa) non applicabile
|
||||
if Proc.AdjacencyMatrix[1][2] > 10 * GEO.EPS_SMALL or Proc.AdjacencyMatrix[1][2] < -91 then
|
||||
Result = FeatureLib.GetStrategyResultNotApplicable( 'BladeKeepWaste : angle between faces must be concave and >= 90deg')
|
||||
return Machinings, Result
|
||||
end
|
||||
if Proc.AdjacencyMatrix[1][3] > 10 * GEO.EPS_SMALL or Proc.AdjacencyMatrix[1][3] < -91 then
|
||||
Result = FeatureLib.GetStrategyResultNotApplicable( 'BladeKeepWaste : angle between faces must be concave and >= 90deg')
|
||||
return Machinings, Result
|
||||
end
|
||||
if Proc.AdjacencyMatrix[2][3] > 10 * GEO.EPS_SMALL or Proc.AdjacencyMatrix[2][3] < -91 then
|
||||
Result = FeatureLib.GetStrategyResultNotApplicable( 'BladeKeepWaste : angle between faces must be concave and >= 90deg')
|
||||
return Machinings, Result
|
||||
end
|
||||
end
|
||||
|
||||
-- parametri opzionali e default
|
||||
if not OptionalParameters then
|
||||
OptionalParameters = {}
|
||||
end
|
||||
local nToolIndex = OptionalParameters.nToolIndex
|
||||
local dExtendAfterTail = OptionalParameters.dExtendAfterTail or 10000
|
||||
local bFinishWithMill
|
||||
if OptionalParameters.bFinishWithMill == nil then
|
||||
bFinishWithMill = true
|
||||
else
|
||||
bFinishWithMill = OptionalParameters.bFinishWithMill
|
||||
end
|
||||
local dMillingOffsetFromSide = OptionalParameters.dMillingOffsetFromSide or 1
|
||||
|
||||
-- volume della feature
|
||||
local dFeatureVolume = FeatureLib.GetFeatureVolume( Proc, Part)
|
||||
|
||||
-- si trovano le facce da lavorare
|
||||
local BottomFace = {}
|
||||
local LongFaces = {}
|
||||
if Proc.nFct == 1 then
|
||||
BottomFace = Proc.Faces[1]
|
||||
else
|
||||
if not Proc.MainFaces then
|
||||
Proc.MainFaces = FaceData.GetMainFaces( Proc, Part)
|
||||
end
|
||||
BottomFace = Proc.MainFaces.BottomFaces[1]
|
||||
LongFaces = Proc.MainFaces.LongFaces
|
||||
end
|
||||
|
||||
|
||||
-- si trova il lato della faccia di fondo da lavorare
|
||||
local BottomEdgeToMachine = {}
|
||||
local BottomEdgesSorted = {}
|
||||
for i = 1, #BottomFace.Edges do
|
||||
table.insert( BottomEdgesSorted, BottomFace.Edges[i])
|
||||
end
|
||||
table.sort( BottomEdgesSorted, CompareEdges)
|
||||
BottomEdgeToMachine = BottomEdgesSorted[1]
|
||||
|
||||
-- eventuali punti di spezzatura
|
||||
local FeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
|
||||
local bIsSplitFeature = false
|
||||
if #FeatureSplittingPoints > 0 then
|
||||
bIsSplitFeature = true
|
||||
end
|
||||
|
||||
-- calcolo lavorazioni
|
||||
-- taglio eventuali facce di chiusura
|
||||
for i = 1, #LongFaces do
|
||||
local Cutting = {}
|
||||
local OptionalParametersFaceByBlade = { bIsSplitFeature = bIsSplitFeature, dExtendAfterTail = 9999, nToolIndex = nToolIndex}
|
||||
Cutting = FaceByBlade.Make( Proc, Part, LongFaces[i], LongFaces[i].MainEdges.BottomEdge, OptionalParametersFaceByBlade)
|
||||
Cutting.nInternalSortingPriority = 1
|
||||
Cutting.dResultWeight = 0.15
|
||||
table.insert( CalculatedMachinings, Cutting)
|
||||
end
|
||||
|
||||
-- taglio con codolo faccia di fondo
|
||||
local dDepthToMachine = BottomEdgeToMachine.dElevation - OptionalParameters.dStripWidth
|
||||
local OptionalParametersFaceByBlade = { dDepthToMachine = dDepthToMachine, bIsSplitFeature = bIsSplitFeature, dExtendAfterTail = dExtendAfterTail, nToolIndex = nToolIndex}
|
||||
-- primo lato
|
||||
Cutting1 = FaceByBlade.Make( Proc, Part, BottomFace, BottomEdgeToMachine, OptionalParametersFaceByBlade)
|
||||
Cutting1.nInternalSortingPriority = 3
|
||||
Cutting1.dResultWeight = 0.3
|
||||
table.insert( CalculatedMachinings, Cutting1)
|
||||
-- secondo lato
|
||||
OptionalParametersFaceByBlade.OppositeToolDirectionMode = 'Enabled'
|
||||
Cutting2 = FaceByBlade.Make( Proc, Part, BottomFace, BottomEdgeToMachine, OptionalParametersFaceByBlade)
|
||||
Cutting2.nInternalSortingPriority = 3
|
||||
Cutting2.dResultWeight = 0.3
|
||||
--table.insert( CalculatedMachinings, Cutting2)
|
||||
|
||||
-- fresatura eventuali facce di chiusura
|
||||
if bFinishWithMill then
|
||||
for i = 1, #LongFaces do
|
||||
local dDepthToMachineMill = BottomFace.MainEdges.LongEdges[i].dElevation - dMillingOffsetFromSide
|
||||
local dToolMarkLength = max( Cutting1.dToolMarkLength, Cutting2.dToolMarkLength)
|
||||
local OptionalParametersFaceByMill = { bIsSplitFeature = bIsSplitFeature, dExtendAfterTail = dExtendAfterTail,
|
||||
dRadialStepSpan = dToolMarkLength, dDepthToMachine = dDepthToMachineMill
|
||||
}
|
||||
local Milling = FaceByMill.Make( Proc, Part, BottomFace, BottomFace.MainEdges.LongEdges[i], OptionalParametersFaceByMill)
|
||||
Milling.nInternalSortingPriority = 2
|
||||
Milling.dResultWeight = 0.05
|
||||
table.insert( CalculatedMachinings, Milling)
|
||||
end
|
||||
end
|
||||
|
||||
-- lavorazioni da applicare spostate in lista finale
|
||||
for i = 1, #CalculatedMachinings do
|
||||
if CalculatedMachinings[i].bIsApplicable then
|
||||
table.insert( Machinings, CalculatedMachinings[i])
|
||||
end
|
||||
end
|
||||
|
||||
-- calcolo completamento, serve la lista di lavorazioni che comprende le non applicabili
|
||||
Result.dCompletionPercentage = GetStrategyCompletionPercentage( CalculatedMachinings)
|
||||
Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( Result.dCompletionPercentage)
|
||||
|
||||
-- aggiunta eventuali lavorazioni splittate
|
||||
if bIsSplitFeature then
|
||||
Machinings = MachiningLib.GetSplitMachinings( Machinings, FeatureSplittingPoints, Part)
|
||||
end
|
||||
|
||||
-- ordinamento
|
||||
table.sort( Machinings, SortMachiningsBySegment)
|
||||
|
||||
-- calcolo risultati
|
||||
if Cutting1.bIsApplicable or Cutting2.bIsApplicable then
|
||||
Result.dQuality = FeatureLib.GetStrategyQuality( Machinings)
|
||||
Result.dTimeToMachine = FeatureLib.GetStrategyTimeToMachine( Machinings)
|
||||
Result.dMRR = ( dFeatureVolume / Result.dTimeToMachine) / pow( 10, 6)
|
||||
if Result.dCompletionPercentage > 100 - 10 * GEO.EPS_SMALL then
|
||||
Result.sStatus = 'Completed'
|
||||
else
|
||||
Result.sStatus = 'Not-Completed'
|
||||
end
|
||||
else
|
||||
Result = FeatureLib.GetStrategyResultNotApplicable()
|
||||
end
|
||||
|
||||
return Machinings, Result
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return BLADEKEEPWASTE
|
||||
@@ -0,0 +1,542 @@
|
||||
-- Strategia: FACEBYBLADE
|
||||
-- Descrizione
|
||||
-- Strategia di base per la lavorazione delle facce con lama
|
||||
|
||||
-- carico librerie
|
||||
local BeamLib = require( 'BeamLib')
|
||||
local BeamData = require( 'BeamData')
|
||||
local MachiningLib = require( 'MachiningLib')
|
||||
local FaceData = require( 'FaceData')
|
||||
|
||||
-- Tabella per definizione modulo
|
||||
local FACEBYBLADE = {}
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function GetLeadInOutType( Machining)
|
||||
local sLeadInOutType = ''
|
||||
|
||||
if Machining.bIsStartClosed or Machining.bIsEndClosed
|
||||
or Machining.sCutType == 'Guillotine'
|
||||
or Machining.sCutType == 'Reduced' then
|
||||
|
||||
sLeadInOutType = 'Perpendicular'
|
||||
else
|
||||
-- testa sopra
|
||||
if TOOLS[Machining.nToolIndex].SetupInfo.HeadType.bTop then
|
||||
if abs( Machining.vtToolDirection:getX()) < 0.7 then
|
||||
if Machining.vtToolDirection:getZ() > -0.087
|
||||
or ( abs( Machining.vtToolDirection:getX()) < 0.34202 and abs( Machining.vtToolDirection:getZ()) < 0.7) then
|
||||
sLeadInOutType = 'Perpendicular'
|
||||
else
|
||||
sLeadInOutType = 'Tangent'
|
||||
end
|
||||
elseif abs( Machining.vtEdgeDirection:getZ()) > 0.7 then
|
||||
sLeadInOutType = 'Perpendicular'
|
||||
else
|
||||
-- TODO qui attacco tangenziale speciale tutto da un lato
|
||||
sLeadInOutType = 'Tangent'
|
||||
end
|
||||
-- testa sotto
|
||||
elseif TOOLS[Machining.nToolIndex].SetupInfo.HeadType.bBottom then
|
||||
if abs( Machining.vtToolDirection:getX()) < 0.7 then
|
||||
if Machining.vtToolDirection:getZ() < -GEO.EPS_SMALL
|
||||
or ( abs( Machining.vtToolDirection:getX()) < 0.34202 and abs( Machining.vtToolDirection:getZ()) < 0.7) then
|
||||
sLeadInOutType = 'Perpendicular'
|
||||
else
|
||||
sLeadInOutType = 'Tangent'
|
||||
end
|
||||
elseif abs( Machining.vtEdgeDirection:getZ()) > 0.7 then
|
||||
sLeadInOutType = 'Perpendicular'
|
||||
else
|
||||
-- TODO qui attacco tangenziale speciale tutto da un lato
|
||||
sLeadInOutType = 'Tangent'
|
||||
end
|
||||
-- se testa senza preferenza Top e Bottom si fa sempre attacco tangenziale
|
||||
else
|
||||
sLeadInOutType = 'Tangent'
|
||||
end
|
||||
end
|
||||
|
||||
return sLeadInOutType
|
||||
end
|
||||
|
||||
|
||||
local function CalculateLeadInOut( Machining, EdgeToMachine, bIsSplitFeature)
|
||||
-- TODO implementare le funzioni di Tool Collision Avoidance (vedi wiki e FacesBysaw -> CalcLeadInOutPerpGeom)
|
||||
|
||||
-- accorciamento per lati chiusi (è sempre l'impronta utensile)
|
||||
local dToolMarkLength = sqrt( Machining.dDepthToMachine * TOOLS[Machining.nToolIndex].dDiameter - Machining.dDepthToMachine * Machining.dDepthToMachine)
|
||||
-- allungamento per faccia singola (aperta in tutte le direzioni)
|
||||
local dAddedLengthOpenFace = BeamData.CUT_EXTRA
|
||||
if Machining.sCutType == 'Guillotine' then
|
||||
local dGuillotineLengthToMachine = 1
|
||||
dAddedLengthOpenFace = ( - EdgeToMachine.dLength + dGuillotineLengthToMachine) / 2
|
||||
elseif Machining.sCutType == 'Reduced' then
|
||||
dAddedLengthOpenFace = - FACEBYBLADE.GetPathReductionLength( Machining.nToolIndex, Machining.dMaxRadialOffset)
|
||||
end
|
||||
|
||||
if Machining.bInvert then
|
||||
Machining.bIsStartClosed, Machining.bIsEndClosed = Machining.bIsEndClosed, Machining.bIsStartClosed
|
||||
end
|
||||
|
||||
local LeadIn = {}
|
||||
local LeadOut = {}
|
||||
Machining.sLeadInOutType = ''
|
||||
LeadIn.dStartAddLength = 0
|
||||
LeadOut.dEndAddLength = 0
|
||||
LeadIn.nType = MCH_MILL_LI.LINEAR
|
||||
LeadOut.nType = MCH_MILL_LI.LINEAR
|
||||
LeadIn.dPerpDistance = 0
|
||||
LeadOut.dPerpDistance = 0
|
||||
LeadIn.dTangentDistance = 0
|
||||
LeadOut.dTangentDistance = 0
|
||||
if Machining.bIsStartClosed
|
||||
or Machining.bIsEndClosed
|
||||
or Machining.CloneStepsRadial.nCount > 1
|
||||
or Machining.Steps.nCount > 1
|
||||
or bIsSplitFeature then
|
||||
|
||||
Machining.sLeadInOutType = 'Perpendicular'
|
||||
if AreSameVectorApprox( Machining.vtToolDirection, EdgeToMachine.vtN) then
|
||||
LeadIn.dPerpDistance = EdgeToMachine.dElevation + BeamData.CUT_SIC - Machining.dRadialOffset
|
||||
LeadOut.dPerpDistance = EdgeToMachine.dElevation + BeamData.CUT_SIC - Machining.dRadialOffset
|
||||
else
|
||||
LeadIn.dPerpDistance = BeamData.CUT_SIC - Machining.dRadialOffset
|
||||
LeadOut.dPerpDistance = BeamData.CUT_SIC - Machining.dRadialOffset
|
||||
end
|
||||
else
|
||||
Machining.sLeadInOutType = GetLeadInOutType( Machining)
|
||||
if Machining.sLeadInOutType == 'Perpendicular' then
|
||||
LeadIn.dPerpDistance = 1
|
||||
LeadOut.dPerpDistance = 1
|
||||
else
|
||||
-- TODO da rimuovere, già inserito in GetLeadInOutType
|
||||
if abs( Machining.vtEdgeDirection:getZ()) > 0.707 then
|
||||
LeadIn.dPerpDistance = 1
|
||||
LeadOut.dPerpDistance = 1
|
||||
else
|
||||
LeadIn.dTangentDistance = TOOLS[Machining.nToolIndex].dDiameter / 2 + BeamData.CUT_SIC
|
||||
LeadOut.dTangentDistance = TOOLS[Machining.nToolIndex].dDiameter / 2 + BeamData.CUT_SIC
|
||||
end
|
||||
end
|
||||
end
|
||||
LeadIn.dElevation = 0
|
||||
LeadOut.dElevation = 0
|
||||
LeadIn.dCompLength = 0
|
||||
LeadOut.dCompLength = 0
|
||||
if Machining.bIsStartClosed and Machining.bIsEndClosed then
|
||||
LeadIn.dStartAddLength = -dToolMarkLength
|
||||
LeadOut.dEndAddLength = -dToolMarkLength
|
||||
elseif Machining.bIsStartClosed then
|
||||
LeadIn.dStartAddLength = -dToolMarkLength
|
||||
-- eventuale correzione per accorciamento maggiore di larghezza tasca
|
||||
LeadOut.dEndAddLength = max( -LeadIn.dStartAddLength - EdgeToMachine.dLength + 10 * BeamData.CUT_EXTRA, BeamData.CUT_EXTRA)
|
||||
elseif Machining.bIsEndClosed then
|
||||
LeadOut.dEndAddLength = -dToolMarkLength
|
||||
-- eventuale correzione per accorciamento maggiore di larghezza tasca
|
||||
LeadIn.dStartAddLength = max( -LeadOut.dEndAddLength - EdgeToMachine.dLength + 10 * BeamData.CUT_EXTRA, BeamData.CUT_EXTRA)
|
||||
else
|
||||
LeadIn.dStartAddLength = dAddedLengthOpenFace
|
||||
LeadOut.dEndAddLength = dAddedLengthOpenFace
|
||||
end
|
||||
-- stima lunghezza reale attacchi per calcolo lunghezza lavorata
|
||||
local dEstimatedLeadInPerpDistance = 0
|
||||
local dEstimatedLeadInTangentDistance = 0
|
||||
local dEstimatedLeadOutPerpDistance = 0
|
||||
local dEstimatedLeadOutTangentDistance = 0
|
||||
if LeadIn.dPerpDistance > 0 then
|
||||
dEstimatedLeadInPerpDistance = ( Machining.dDepthToMachine + min( TOOLS[Machining.nToolIndex].dSideStep, Machining.dDepthToMachine)) / 2
|
||||
end
|
||||
if LeadIn.dTangentDistance > 0 then
|
||||
dEstimatedLeadInTangentDistance = TOOLS[Machining.nToolIndex].dDiameter / 2 + BeamData.CUT_SIC
|
||||
end
|
||||
if LeadOut.dPerpDistance > 0 then
|
||||
dEstimatedLeadOutPerpDistance = ( Machining.dDepthToMachine + min( TOOLS[Machining.nToolIndex].dSideStep, Machining.dDepthToMachine)) / 2
|
||||
end
|
||||
if LeadOut.dTangentDistance > 0 then
|
||||
dEstimatedLeadOutTangentDistance = TOOLS[Machining.nToolIndex].dDiameter / 2 + BeamData.CUT_SIC
|
||||
end
|
||||
LeadIn.dTotalEstimatedDistance = sqrt( dEstimatedLeadInPerpDistance ^ 2 + dEstimatedLeadInTangentDistance ^ 2) + Machining.dStartSafetyLength
|
||||
LeadOut.dTotalEstimatedDistance = sqrt( dEstimatedLeadOutPerpDistance ^ 2 + dEstimatedLeadOutTangentDistance ^ 2) + Machining.dStartSafetyLength
|
||||
|
||||
return LeadIn, LeadOut
|
||||
end
|
||||
|
||||
|
||||
-- TODO implementare SCC in funzione macchina
|
||||
local function GetSCC( vtMachiningDirection, vtEdgeDirection, vtNFace)
|
||||
local nSCC = MCH_SCC.NONE
|
||||
|
||||
if abs( vtMachiningDirection:getX()) > abs( vtMachiningDirection:getY()) - GEO.EPS_SMALL then
|
||||
-- se il taglio è orizzontale, si gira aggregato lama per facilitare caduta del legno
|
||||
if abs( vtEdgeDirection:getZ()) < 10 * GEO.EPS_SMALL and not AreSameOrOppositeVectorApprox( vtNFace, Z_AX()) then
|
||||
nSCC = EgtIf( ( vtMachiningDirection:getX() > -GEO.EPS_SMALL), MCH_SCC.ADIR_XM, MCH_SCC.ADIR_XP)
|
||||
else
|
||||
nSCC = EgtIf( ( vtMachiningDirection:getX() > -GEO.EPS_SMALL), MCH_SCC.ADIR_XP, MCH_SCC.ADIR_XM)
|
||||
end
|
||||
else
|
||||
-- se il taglio è orizzontale, si gira aggregato lama per facilitare caduta del legno
|
||||
if abs( vtEdgeDirection:getZ()) < 10 * GEO.EPS_SMALL and not AreSameOrOppositeVectorApprox( vtNFace, Z_AX()) then
|
||||
nSCC = EgtIf( ( vtMachiningDirection:getY() > -GEO.EPS_SMALL), MCH_SCC.ADIR_YM, MCH_SCC.ADIR_YP)
|
||||
else
|
||||
nSCC = EgtIf( ( vtMachiningDirection:getY() > -GEO.EPS_SMALL), MCH_SCC.ADIR_YP, MCH_SCC.ADIR_YM)
|
||||
end
|
||||
end
|
||||
|
||||
return nSCC
|
||||
end
|
||||
|
||||
|
||||
-- dato un certo offset radiale (uscente) e la distanza da mantenere dallo spigolo, calcola di quanto la lama deve arretrare lateralmente rispetto al centro per lavorare il lato
|
||||
function FACEBYBLADE.GetPathReductionLength( nToolIndex, dRadialOffset, OptionalParameters)
|
||||
local Tool = TOOLS[nToolIndex]
|
||||
local dToolRadius = Tool.dDiameter / 2
|
||||
|
||||
-- parametri opzionali
|
||||
if not OptionalParameters then
|
||||
OptionalParameters = {}
|
||||
end
|
||||
local dExtra = OptionalParameters.dExtra or BeamData.CUT_EXTRA
|
||||
|
||||
-- calcolo
|
||||
local dReductionLength = -dExtra
|
||||
if dRadialOffset > dExtra + 10 * GEO.EPS_SMALL then
|
||||
dReductionLength = sqrt( ( dToolRadius - dExtra)^2 - ( dToolRadius - dRadialOffset)^2)
|
||||
end
|
||||
|
||||
return dReductionLength
|
||||
end
|
||||
|
||||
|
||||
-- data la lunghezza del lato da lavorare e la distanza da mantenere dallo spigolo, calcola di quanto la lama deve andare oltre per lavorare il lato
|
||||
function FACEBYBLADE.GetRadialOffsetForGuillotine( nToolIndex, dEdgeLength, OptionalParameters)
|
||||
local Tool = TOOLS[nToolIndex]
|
||||
local dToolRadius = Tool.dDiameter / 2
|
||||
|
||||
-- parametri opzionali
|
||||
if not OptionalParameters then
|
||||
OptionalParameters = {}
|
||||
end
|
||||
local dExtra = OptionalParameters.dExtra or BeamData.CUT_EXTRA
|
||||
|
||||
-- calcolo
|
||||
local dRadialOffset = dToolRadius - sqrt( ( dToolRadius - dExtra)^2 - ( dEdgeLength / 2)^2)
|
||||
if dRadialOffset < dExtra + 10 * GEO.EPS_SMALL then
|
||||
dRadialOffset = GEO.INFINITO
|
||||
end
|
||||
|
||||
return dRadialOffset
|
||||
end
|
||||
|
||||
|
||||
function FACEBYBLADE.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalParameters)
|
||||
local Cutting = MachiningLib.InitMachiningParameters( MCH_MY.MILLING)
|
||||
Cutting.bIsApplicable = true
|
||||
Cutting.dDepthToMachine = 0
|
||||
Cutting.sMessage = ''
|
||||
Cutting.idProc = Proc.id
|
||||
Cutting.dResidualDepth = EdgeToMachine.dElevation
|
||||
Cutting.dCompletionPercentage = 0
|
||||
Cutting.dToolMarkLength = 0
|
||||
Cutting.sEdgeType = EdgeToMachine.sType
|
||||
Cutting.nFeatureSegment = 1
|
||||
|
||||
-- parametri opzionali
|
||||
if not OptionalParameters then
|
||||
OptionalParameters = {}
|
||||
end
|
||||
local bForceLongcutBlade = OptionalParameters.bForceLongcutBlade or false
|
||||
local dExtendAfterTail = OptionalParameters.dExtendAfterTail or 10000
|
||||
local dPocketHeight = OptionalParameters.dPocketHeight or 0
|
||||
local dDepthToMachine = OptionalParameters.dDepthToMachine or EdgeToMachine.dElevation
|
||||
local bIsSplitFeature = OptionalParameters.bIsSplitFeature or false
|
||||
local OppositeToolDirectionMode = OptionalParameters.OppositeToolDirectionMode or 'Disabled'
|
||||
local bReduceBladePath = OptionalParameters.bReduceBladePath or false
|
||||
local sDepth = OptionalParameters.sDepth or 0
|
||||
local nToolIndex = OptionalParameters.nToolIndex
|
||||
local dLongitudinalOffset = OptionalParameters.dLongitudinalOffset or 0
|
||||
if OptionalParameters.dPocketHeight then
|
||||
dLongitudinalOffset = 0
|
||||
end
|
||||
local dRadialStepSpan = OptionalParameters.dRadialStepSpan
|
||||
local dMinNzDownUp = OptionalParameters.dMinNzDownUp
|
||||
local sUserNotes = OptionalParameters.sUserNotes or ''
|
||||
|
||||
-- lunghezze, direzioni e punti caratteristici della lavorazione e del lato lavorato
|
||||
Cutting.dEdgeLength = EdgeToMachine.dLength
|
||||
if OppositeToolDirectionMode == 'Enabled' then
|
||||
Cutting.vtToolDirection = -EdgeToMachine.vtN
|
||||
else
|
||||
Cutting.vtToolDirection = EdgeToMachine.vtN
|
||||
end
|
||||
Cutting.vtEdgeDirection = EdgeToMachine.vtN ^ FaceToMachine.vtN
|
||||
-- TODO conviene spostare questi calcoli nel FaceData?
|
||||
Cutting.ptEdge1, _, Cutting.ptEdge2 = EgtSurfTmFacetOppositeSide( Proc.id, FaceToMachine.id, -Cutting.vtToolDirection, GDB_ID.ROOT)
|
||||
-- TODO gestire lama da sotto
|
||||
-- se si conosce il limite downUp (utensile forzato o downUp forzato) si decide se invertire (ToolInvert)
|
||||
-- TODO esiste un limite downUp massimo per la lama da sopra??
|
||||
if nToolIndex and not dMinNzDownUp then
|
||||
dMinNzDownUp = TOOLS[nToolIndex].SetupInfo.GetMinNzDownUp( Part.b3Raw, FaceToMachine.vtN, Cutting.vtToolDirection, TOOLS[nToolIndex])
|
||||
end
|
||||
if dMinNzDownUp and FaceToMachine.vtN:getZ() < dMinNzDownUp then
|
||||
Cutting.bToolInvert = true
|
||||
else
|
||||
Cutting.bToolInvert = false
|
||||
end
|
||||
|
||||
-- ricerca utensile
|
||||
if nToolIndex then
|
||||
Cutting.nToolIndex = nToolIndex
|
||||
else
|
||||
local ToolSearchParameters = {}
|
||||
ToolSearchParameters.dElevation = dDepthToMachine
|
||||
if Cutting.bToolInvert then
|
||||
ToolSearchParameters.vtN = -FaceToMachine.vtN
|
||||
else
|
||||
ToolSearchParameters.vtN = FaceToMachine.vtN
|
||||
end
|
||||
ToolSearchParameters.bAllowTopHead = true
|
||||
-- TODO bisognerà implementare anche la lama da sotto
|
||||
ToolSearchParameters.bAllowBottomHead = false
|
||||
ToolSearchParameters.bForceLongcutBlade = bForceLongcutBlade
|
||||
local ToolInfo = MachiningLib.FindBlade( Proc, ToolSearchParameters)
|
||||
-- ora che l'utensile è scelto, se non era definito l'angolo di DownUp lo verifico per decidere se invertire
|
||||
if ToolInfo.nToolIndex and not dMinNzDownUp then
|
||||
dMinNzDownUp = TOOLS[ToolInfo.nToolIndex].SetupInfo.GetMinNzDownUp( Part.b3Raw, FaceToMachine.vtN, Cutting.vtToolDirection, TOOLS[ToolInfo.nToolIndex])
|
||||
if FaceToMachine.vtN:getZ() < dMinNzDownUp then
|
||||
Cutting.bToolInvert = true
|
||||
end
|
||||
end
|
||||
Cutting.nToolIndex = ToolInfo.nToolIndex
|
||||
end
|
||||
if not TOOLS[Cutting.nToolIndex] or 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 lavorazione non è applicabile
|
||||
if OptionalParameters.dPocketHeight and ( TOOLS[Cutting.nToolIndex].dThickness > dPocketHeight + 10 * GEO.EPS_SMALL) then
|
||||
Cutting.sMessage = 'Pocket too narrow for blade thickness'
|
||||
Cutting.bIsApplicable = false
|
||||
EgtOutLog( Cutting.sMessage)
|
||||
return Cutting, EdgeToMachine.dElevation
|
||||
end
|
||||
-- se tasca chiusa da entrambi i lati e più stretta della lama la lavorazione non è applicabile
|
||||
if not ( EdgeToMachine.bIsStartOpen or EdgeToMachine.bIsEndOpen) then
|
||||
if TOOLS[Cutting.nToolIndex].dDiameter > EdgeToMachine.dLength + 10 * GEO.EPS_SMALL then
|
||||
Cutting.sMessage = 'Pocket too narrow for blade diameter'
|
||||
Cutting.bIsApplicable = false
|
||||
EgtOutLog( Cutting.sMessage)
|
||||
return Cutting, EdgeToMachine.dElevation
|
||||
end
|
||||
end
|
||||
|
||||
-- parametri della lavorazione
|
||||
-- profondità (parametro DEPTH)
|
||||
Cutting.sDepth = sDepth
|
||||
-- inizio e fine aperti o chiusi
|
||||
Cutting.bIsStartClosed = not EdgeToMachine.bIsStartOpen
|
||||
Cutting.bIsEndClosed = not EdgeToMachine.bIsEndOpen
|
||||
-- lato di lavoro e inversione per avere taglio concorde
|
||||
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
|
||||
-- se OppositeToolDirectionMode è Optimized, se possibile e necessario, si attiva per garantire taglio concorde e verso l'alto (massima qualità)
|
||||
if ( OppositeToolDirectionMode == 'Optimized') and ( Proc.nFct == 1) and ( FaceData.IsFaceRhomboid( Proc, FaceToMachine.id)) then
|
||||
OppositeToolDirectionMode = 'Disabled'
|
||||
-- la direzione di percorrenza del lato deve essere verso l'alto; bInvert va considerata perchè inverte la direzione di percorrenza.
|
||||
if ( Cutting.bInvert and Cutting.vtEdgeDirection:getZ() > 100 * GEO.EPS_SMALL)
|
||||
or ( ( not Cutting.bInvert) and Cutting.vtEdgeDirection:getZ() < -100 * GEO.EPS_SMALL) then
|
||||
|
||||
-- si attiva OppositeToolDirection solo se non cambiano le condizioni di taglio downUp
|
||||
local dNewMinNzDownUp = TOOLS[nToolIndex].SetupInfo.GetMinNzDownUp( Part.b3Raw, FaceToMachine.vtN, -Cutting.vtToolDirection, TOOLS[nToolIndex])
|
||||
if ( FaceToMachine.vtN:getZ() < dMinNzDownUp) == ( FaceToMachine.vtN:getZ() < dNewMinNzDownUp) then
|
||||
OppositeToolDirectionMode = 'Enabled'
|
||||
Cutting.vtToolDirection = -EdgeToMachine.vtN
|
||||
Cutting.ptEdge1, _, Cutting.ptEdge2 = EgtSurfTmFacetOppositeSide( Proc.id, FaceToMachine.id, -Cutting.vtToolDirection, GDB_ID.ROOT)
|
||||
Cutting.bInvert = not Cutting.bInvert
|
||||
-- se le condizioni downUp cambiano, si setta per tagliare verso l'alto
|
||||
else
|
||||
if Cutting.nWorkside == MCH_MILL_WS.RIGHT then
|
||||
Cutting.nWorkside = MCH_MILL_WS.LEFT
|
||||
Cutting.bInvert = false
|
||||
else
|
||||
Cutting.nWorkside = MCH_MILL_WS.RIGHT
|
||||
Cutting.bInvert = true
|
||||
end
|
||||
end
|
||||
end
|
||||
elseif OppositeToolDirectionMode == 'Enabled' then
|
||||
Cutting.bInvert = not Cutting.bInvert
|
||||
end
|
||||
if Cutting.bToolInvert then
|
||||
Cutting.bInvert = not Cutting.bInvert
|
||||
end
|
||||
-- profondità da lavorare e offset radiale
|
||||
if OptionalParameters.dPocketHeight then
|
||||
if TOOLS[Cutting.nToolIndex].dMaxDepth > dDepthToMachine - 10 * GEO.EPS_SMALL then
|
||||
-- TODO la depth dovrebbe essere quella del machining
|
||||
Cutting.dDepthToMachine = dDepthToMachine
|
||||
Cutting.dResidualDepth = 0
|
||||
if OppositeToolDirectionMode == 'Enabled' then
|
||||
Cutting.dRadialOffset = -dDepthToMachine
|
||||
else
|
||||
Cutting.dRadialOffset = EdgeToMachine.dElevation - dDepthToMachine
|
||||
end
|
||||
else
|
||||
Cutting.dDepthToMachine = TOOLS[Cutting.nToolIndex].dMaxDepth - 1
|
||||
Cutting.dResidualDepth = dDepthToMachine - Cutting.dDepthToMachine
|
||||
if OppositeToolDirectionMode == 'Enabled' then
|
||||
Cutting.dRadialOffset = -Cutting.dDepthToMachine
|
||||
else
|
||||
Cutting.dRadialOffset = EdgeToMachine.dElevation - Cutting.dDepthToMachine
|
||||
end
|
||||
end
|
||||
else
|
||||
Cutting.dDepthToMachine = dDepthToMachine
|
||||
Cutting.dResidualDepth = 0
|
||||
Cutting.sCutType = 'Standard'
|
||||
if bReduceBladePath
|
||||
and ( Proc.nFct == 1)
|
||||
and FaceData.IsFaceRectangular( Proc, FaceToMachine.id) then
|
||||
|
||||
local bIsTopBlade = TOOLS[nToolIndex].SetupInfo.HeadType.bTop
|
||||
Cutting.dMaxRadialOffset = TOOLS[nToolIndex].dMaxMaterial - Cutting.dDepthToMachine - BeamData.CUT_SIC
|
||||
Cutting.dRadialOffsetGuillotine = FACEBYBLADE.GetRadialOffsetForGuillotine( nToolIndex, EdgeToMachine.dLength)
|
||||
if Cutting.dMaxRadialOffset > 10 * GEO.EPS_SMALL then
|
||||
-- taglio a ghigliottina
|
||||
if bIsTopBlade and ( Cutting.dRadialOffsetGuillotine < Cutting.dMaxRadialOffset - 10 * GEO.EPS_SMALL) then
|
||||
dDepthToMachine = Cutting.dDepthToMachine + Cutting.dRadialOffsetGuillotine
|
||||
Cutting.sCutType = 'Guillotine'
|
||||
-- taglio ridotto
|
||||
else
|
||||
dDepthToMachine = Cutting.dDepthToMachine + Cutting.dMaxRadialOffset
|
||||
Cutting.sCutType = 'Reduced'
|
||||
end
|
||||
end
|
||||
end
|
||||
if OppositeToolDirectionMode == 'Enabled' then
|
||||
Cutting.dRadialOffset = -dDepthToMachine
|
||||
else
|
||||
Cutting.dRadialOffset = EdgeToMachine.dElevation - dDepthToMachine
|
||||
end
|
||||
end
|
||||
-- completamento
|
||||
Cutting.dCompletionPercentage = ( 1 - Cutting.dResidualDepth / Cutting.dDepthToMachine) * 100
|
||||
-- step verticale e offset longitudinale
|
||||
Cutting.Steps = MachiningLib.GetMachiningSteps( dPocketHeight, TOOLS[Cutting.nToolIndex].dThickness)
|
||||
Cutting.Steps.nStepType = MCH_MILL_ST.ONEWAY
|
||||
Cutting.dMaxElev = Cutting.Steps.dStep * Cutting.Steps.nCount - 10 * GEO.EPS_SMALL
|
||||
if Cutting.bToolInvert then
|
||||
if Cutting.Steps.nCount > 1 then
|
||||
Cutting.dLongitudinalOffset = - dPocketHeight
|
||||
else
|
||||
Cutting.dLongitudinalOffset = - TOOLS[Cutting.nToolIndex].dThickness - dLongitudinalOffset
|
||||
end
|
||||
else
|
||||
Cutting.dLongitudinalOffset = dLongitudinalOffset
|
||||
end
|
||||
-- distanza di sicurezza
|
||||
Cutting.dStartSafetyLength = BeamData.CUT_SIC
|
||||
-- overlap
|
||||
Cutting.dOverlap = 0
|
||||
-- EdgeUse e frame lavorazione
|
||||
if OppositeToolDirectionMode == 'Enabled' then
|
||||
Cutting.nFaceuse = BeamLib.GetNearestOrthoOpposite( -Cutting.vtToolDirection)
|
||||
--Cutting.vtFaceUse = -Cutting.vtToolDirection
|
||||
Cutting.nEdgesFaceUse = EdgeToMachine.id
|
||||
else
|
||||
Cutting.nFaceuse = BeamLib.GetNearestOrthoOpposite( Cutting.vtToolDirection)
|
||||
--Cutting.vtFaceUse = Cutting.vtToolDirection
|
||||
Cutting.nEdgesFaceUse = EdgeToMachine.id
|
||||
end
|
||||
-- SCC
|
||||
Cutting.nSCC = GetSCC( Cutting.vtToolDirection, Cutting.vtEdgeDirection, FaceToMachine.vtN)
|
||||
-- asse bloccato
|
||||
Cutting.sBlockedAxis = BeamLib.GetBlockedAxis( Cutting.nToolIndex, 'perpendicular', Part.b3Raw, FaceToMachine.vtN, EgtIf( FaceToMachine.vtN:getX() > 0, X_AX(), -X_AX()))
|
||||
-- eventuale step orizzontale
|
||||
Cutting.CloneStepsRadial = {}
|
||||
if not dRadialStepSpan then
|
||||
dRadialStepSpan = Cutting.dDepthToMachine
|
||||
end
|
||||
if dRadialStepSpan > 10 * GEO.EPS_SMALL and TOOLS[Cutting.nToolIndex].dSideStep then
|
||||
Cutting.CloneStepsRadial = MachiningLib.GetMachiningSteps( dRadialStepSpan, TOOLS[Cutting.nToolIndex].dSideStep)
|
||||
else
|
||||
Cutting.CloneStepsRadial.nCount = 1
|
||||
Cutting.CloneStepsRadial.dStep = Cutting.dDepthToMachine
|
||||
end
|
||||
-- approccio e retrazione
|
||||
Cutting.LeadIn, Cutting.LeadOut = CalculateLeadInOut( Cutting, EdgeToMachine, bIsSplitFeature)
|
||||
-- lunghezza lavorata
|
||||
-- TODO per il calcolo del dLengthOnX si deve correggere con allungamento / accorciamento percorso
|
||||
Cutting.dLengthToMachine = EdgeToMachine.dLength + Cutting.LeadIn.dStartAddLength + Cutting.LeadOut.dEndAddLength
|
||||
local b3BoxEdge = BBox3d( Cutting.ptEdge1, Cutting.ptEdge2)
|
||||
Cutting.dLengthOnX = b3BoxEdge:getDimX()
|
||||
Cutting.dTimeToMachine, Cutting.dLengthToMachineAllStepsWithLeadInOut = MachiningLib.GetTimeToMachineAllStepsWithLeadInOut( Cutting, Part)
|
||||
-- lunghezza impronta lama
|
||||
if Cutting.bIsStartClosed and Cutting.bIsEndClosed then
|
||||
Cutting.dToolMarkLength = abs( min( Cutting.LeadIn.dStartAddLength, Cutting.LeadOut.dEndAddLength))
|
||||
elseif Cutting.bIsStartClosed then
|
||||
Cutting.dToolMarkLength = abs( Cutting.LeadIn.dStartAddLength)
|
||||
elseif Cutting.bIsEndClosed then
|
||||
Cutting.dToolMarkLength = abs( Cutting.LeadOut.dEndAddLength)
|
||||
end
|
||||
-- area lavorata
|
||||
Cutting.dAreaToMachine = min( EdgeToMachine.dElevation, Cutting.dDepthToMachine) * ( min( Cutting.dEdgeLength, Cutting.dLengthToMachine + 2 * Cutting.dToolMarkLength))
|
||||
-- geometria
|
||||
Cutting.Geometry = {{Cutting.idProc, FaceToMachine.id}}
|
||||
-- note utente
|
||||
Cutting.sUserNotes = sUserNotes
|
||||
-- nome operazione
|
||||
Cutting.sOperationName = 'Cut_' .. ( EgtGetName( Cutting.idProc) or tostring( Cutting.idProc)) .. '_' .. tostring( FaceToMachine.id + 1)
|
||||
|
||||
-- se lavorazione aperta sulla coda, eventuali aggiustamenti
|
||||
-- TODO valutare se fare funzione a parte
|
||||
local bIsTruncatingCutOnTail = Proc.Topology and ( Proc.Topology.sName == 'Cut-1-Through' or Proc.Topology.sName == 'TailCut') and Proc.AffectedFaces.bLeft
|
||||
if bIsTruncatingCutOnTail then
|
||||
Cutting.sStage = 'AfterTail'
|
||||
elseif Proc.AffectedFaces.bLeft and ( EdgeToMachine.sType == 'Bottom' or ( Cutting.vtToolDirection:getX() < 0.707)) then
|
||||
local dLengthOnX = Cutting.dLengthOnX
|
||||
-- se feature splittata non si considera la lunghezza della feature per il check spostamento dopo separazione
|
||||
if bIsSplitFeature then
|
||||
dLengthOnX = 0
|
||||
end
|
||||
local bStartLeft = MachiningLib.StartsLeftSide( Cutting)
|
||||
local dAddLengthLeftSide = Cutting.LeadOut.dEndAddLength
|
||||
local dAddLengthToReduce = sqrt( Cutting.dDepthToMachine * TOOLS[Cutting.nToolIndex].dDiameter - Cutting.dDepthToMachine * Cutting.dDepthToMachine)
|
||||
if bStartLeft then
|
||||
dAddLengthLeftSide = Cutting.LeadIn.dStartAddLength
|
||||
end
|
||||
if not AreSameOrOppositeVectorApprox( EdgeToMachine.vtN, Y_AX()) then
|
||||
if MachiningLib.CanMoveAfterSplitcut( dLengthOnX, Part) then
|
||||
Cutting.sStage = 'AfterTail'
|
||||
else
|
||||
Cutting.bIsApplicable = false
|
||||
end
|
||||
elseif dAddLengthLeftSide + dAddLengthToReduce > dExtendAfterTail then
|
||||
if MachiningLib.CanMoveAfterSplitcut( dLengthOnX, Part) then
|
||||
Cutting.sStage = 'AfterTail'
|
||||
else
|
||||
if bStartLeft then
|
||||
Cutting.LeadIn.dStartAddLength = - dAddLengthToReduce + dExtendAfterTail
|
||||
else
|
||||
Cutting.LeadOut.dEndAddLength = - dAddLengthToReduce + dExtendAfterTail
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return Cutting
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return FACEBYBLADE
|
||||
@@ -1,7 +1,6 @@
|
||||
-- Strategia: SLOTBYCHAINSAW
|
||||
-- Strategia: FACEBYCHAINSAW
|
||||
-- Descrizione
|
||||
-- Strategia di base per la lavorazione delle slot o tasche con sega a catena
|
||||
-- Feature: tipo lapjoint
|
||||
-- Strategia di base per la lavorazione delle facce con sega a catena
|
||||
|
||||
-- carico librerie
|
||||
local BeamLib = require( 'BeamLib')
|
||||
@@ -9,7 +8,7 @@ local BeamData = require( 'BeamData')
|
||||
local MachiningLib = require( 'MachiningLib')
|
||||
|
||||
-- Tabella per definizione modulo
|
||||
local SLOTBYCHAINSAW = {}
|
||||
local FACEBYCHAINSAW = {}
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
@@ -48,15 +47,16 @@ end
|
||||
|
||||
|
||||
-- TODO calcolo area lavorata per completamento
|
||||
function SLOTBYCHAINSAW.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalParameters)
|
||||
local Mortising = {}
|
||||
function FACEBYCHAINSAW.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalParameters)
|
||||
local Mortising = MachiningLib.InitMachiningParameters( MCH_MY.MORTISING)
|
||||
Mortising.bIsApplicable = true
|
||||
Mortising.dDepthToMachine = 0
|
||||
Mortising.dResidualDepth = abs( EdgeToMachine.dElevation)
|
||||
Mortising.dResidualDepth = EdgeToMachine.dElevation
|
||||
Mortising.dCompletionPercentage = 0
|
||||
Mortising.sMessage = ''
|
||||
Mortising.idProc = Proc.id
|
||||
Mortising.sEdgeType = EdgeToMachine.sType
|
||||
Mortising.nSegment = 1
|
||||
Mortising.nFeatureSegment = 1
|
||||
|
||||
-- parametri opzionali
|
||||
if not OptionalParameters then
|
||||
@@ -65,54 +65,36 @@ function SLOTBYCHAINSAW.Make( Proc, Part, FaceToMachine, EdgeToMachine, Optional
|
||||
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
|
||||
local dCustomMaxElev = OptionalParameters.dMaxElev or EdgeToMachine.dElevation
|
||||
local dDepthToMachine = OptionalParameters.dDepthToMachine or EdgeToMachine.dElevation
|
||||
local bExtendWithCornerRadius = OptionalParameters.bExtendWithCornerRadius or false
|
||||
local dExtendAfterTail = OptionalParameters.dExtendAfterTail or 10000
|
||||
local dPocketHeight = OptionalParameters.dPocketHeight or 0
|
||||
local bIsSplitFeature = OptionalParameters.bIsSplitFeature or false
|
||||
local OppositeToolDirectionMode = OptionalParameters.OppositeToolDirectionMode or 'Disabled'
|
||||
local sDepth = OptionalParameters.sDepth or 'TH'
|
||||
local dLongitudinalStepSpan = OptionalParameters.dLongitudinalStepSpan
|
||||
|
||||
-- lunghezze e punti caratteristici della lavorazione e del lato lavorato
|
||||
Mortising.dLengthToMachine = dLengthToMachine
|
||||
Mortising.dLengthOnX = abs( dLengthToMachine * EdgeToMachine.vtToolDirection:getY())
|
||||
Mortising.dEdgeLength = EdgeToMachine.dLength
|
||||
Mortising.ptEdge1, _, Mortising.ptEdge2 = EgtSurfTmFacetOppositeSide( Proc.id, FaceToMachine.id, -EdgeToMachine.vtToolDirection, GDB_ID.ROOT)
|
||||
Mortising.vtEdgeDirection = EdgeToMachine.vtToolDirection ^ FaceToMachine.vtN
|
||||
|
||||
-- altezza tasca, in base alla topologia
|
||||
local dPocketHeight = 0
|
||||
if Proc.Topology.sFamily == 'Tunnel' then
|
||||
dPocketHeight = Proc.MainFaces.SideFaces[1].MainEdges.OppositeEdges[1].dLength
|
||||
if OppositeToolDirectionMode == 'Enabled' then
|
||||
Mortising.vtToolDirection = -EdgeToMachine.vtN
|
||||
else
|
||||
if FaceToMachine.sType == 'Long' then
|
||||
dPocketHeight = Proc.MainFaces.BottomFaces[1].MainEdges.SideEdges[1].dLength
|
||||
elseif FaceToMachine.sType == 'Side' then
|
||||
dPocketHeight = Proc.MainFaces.BottomFaces[1].MainEdges.LongEdges[1].dLength
|
||||
end
|
||||
Mortising.vtToolDirection = EdgeToMachine.vtN
|
||||
end
|
||||
Mortising.vtEdgeDirection = EdgeToMachine.vtN ^ FaceToMachine.vtN
|
||||
Mortising.ptEdge1, _, Mortising.ptEdge2 = EgtSurfTmFacetOppositeSide( Proc.id, FaceToMachine.id, -Mortising.vtToolDirection, GDB_ID.ROOT)
|
||||
|
||||
-- ricerca utensile
|
||||
local bExtendWithCornerRadius = false
|
||||
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.vtToolDirection = Mortising.vtToolDirection
|
||||
ToolSearchParameters.bAllowTopHead = true
|
||||
ToolSearchParameters.bAllowBottomHead = true
|
||||
ToolSearchParameters.dElevation = Mortising.dDepthToMachine
|
||||
ToolSearchParameters.dElevation = 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
|
||||
@@ -121,15 +103,15 @@ function SLOTBYCHAINSAW.Make( Proc, Part, FaceToMachine, EdgeToMachine, Optional
|
||||
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
|
||||
-- se tasca meno spessa della sega a catena la lavorazione non è applicabile
|
||||
if OptionalParameters.dPocketHeight and ( TOOLS[Mortising.nToolIndex].dThickness > dPocketHeight + 10 * GEO.EPS_SMALL) then
|
||||
Mortising.sMessage = 'Pocket too narrow for chainsaw thickness'
|
||||
Mortising.bIsApplicable = false
|
||||
EgtOutLog( Mortising.sMessage)
|
||||
return Mortising
|
||||
end
|
||||
if #( Proc.MainFaces.SideFaces) > 1 then
|
||||
-- se tasca più stretta della sega a catena la strategia non è applicabile
|
||||
-- se tasca chiusa da entrambi i lati e più stretta della sega a catena la lavorazione non è applicabile
|
||||
if not ( EdgeToMachine.bIsStartOpen or EdgeToMachine.bIsEndOpen) then
|
||||
if TOOLS[Mortising.nToolIndex].dWidth > EdgeToMachine.dLength + 10 * GEO.EPS_SMALL then
|
||||
Mortising.sMessage = 'Pocket too narrow for chainsaw width'
|
||||
Mortising.bIsApplicable = false
|
||||
@@ -141,43 +123,44 @@ function SLOTBYCHAINSAW.Make( Proc, Part, FaceToMachine, EdgeToMachine, Optional
|
||||
-- parametri della lavorazione
|
||||
-- TODO gestire ToolInvert per rispettare direzione migliore di lavorazione
|
||||
-- profondità (parametro DEPTH) non usata
|
||||
Mortising.sDepth = 'TH'
|
||||
Mortising.sDepth = sDepth
|
||||
-- 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
|
||||
if OppositeToolDirectionMode == 'Enabled' then
|
||||
Mortising.nWorkside = MCH_MILL_WS.LEFT
|
||||
Mortising.bToolInvert = true
|
||||
else
|
||||
Mortising.nWorkside = MCH_MILL_WS.RIGHT
|
||||
Mortising.bToolInvert = false
|
||||
end
|
||||
-- profondità e offset longitudinale
|
||||
if bExtendWithCornerRadius then
|
||||
Mortising.dDepthToMachine = Mortising.dDepthToMachine + TOOLS[Mortising.nToolIndex].dCornerRadius
|
||||
dDepthToMachine = dDepthToMachine + TOOLS[Mortising.nToolIndex].dCornerRadius
|
||||
end
|
||||
if TOOLS[Mortising.nToolIndex].dMaxMaterial > Mortising.dDepthToMachine - 10 * GEO.EPS_SMALL then
|
||||
if TOOLS[Mortising.nToolIndex].dMaxMaterial > dDepthToMachine - 10 * GEO.EPS_SMALL then
|
||||
Mortising.dDepthToMachine = dDepthToMachine
|
||||
Mortising.dResidualDepth = 0
|
||||
if EdgeToMachine.dElevation > -10 * GEO.EPS_SMALL then
|
||||
Mortising.dLongitudinalOffset = 0
|
||||
if OppositeToolDirectionMode == 'Enabled' then
|
||||
Mortising.dLongitudinalOffset = EdgeToMachine.dElevation - dDepthToMachine
|
||||
else
|
||||
Mortising.dLongitudinalOffset = abs( EdgeToMachine.dElevation) - Mortising.dDepthToMachine
|
||||
Mortising.dLongitudinalOffset = 0
|
||||
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.dResidualDepth = dDepthToMachine - Mortising.dDepthToMachine
|
||||
if OppositeToolDirectionMode == 'Enabled' then
|
||||
Mortising.dLongitudinalOffset = 0
|
||||
else
|
||||
Mortising.dLongitudinalOffset = EdgeToMachine.dElevation - Mortising.dDepthToMachine
|
||||
end
|
||||
Mortising.sMessage = 'Feature '.. Proc.idFeature .. ' : chainsaw elevation (' .. EgtNumToString( EdgeToMachine.dElevation, 1) .. ') bigger than max tool depth (' .. EgtNumToString( Mortising.dDepthToMachine, 1) .. ')'
|
||||
EgtOutLog( Mortising.sMessage)
|
||||
end
|
||||
-- completamento
|
||||
Mortising.dCompletionPercentage = 100 - Mortising.dResidualDepth / Mortising.dDepthToMachine
|
||||
Mortising.dCompletionPercentage = ( 1 - Mortising.dResidualDepth / Mortising.dDepthToMachine) * 100
|
||||
-- massima elevazione
|
||||
if dCustomMaxElev < Mortising.dDepthToMachine - 10 * GEO.EPS_SMALL then
|
||||
Mortising.dMaxElev = max( dCustomMaxElev, dCustomMaxElev - Mortising.dLongitudinalOffset)
|
||||
@@ -185,7 +168,7 @@ function SLOTBYCHAINSAW.Make( Proc, Part, FaceToMachine, EdgeToMachine, Optional
|
||||
-- offset radiale
|
||||
Mortising.dRadialOffset = 0
|
||||
-- distanza di sicurezza
|
||||
Mortising.dStartSafetyLength = max( EdgeToMachine.dElevation, 10)
|
||||
Mortising.dStartSafetyLength = max( EdgeToMachine.dElevation, ( TOOLS[Mortising.nToolIndex].SetupInfo.dZSafeDelta or 60) + EgtMdbGetGeneralParam( MCH_GP.SAFEZ))
|
||||
-- overlap
|
||||
Mortising.dOverlap = 0
|
||||
-- step
|
||||
@@ -196,27 +179,45 @@ function SLOTBYCHAINSAW.Make( Proc, Part, FaceToMachine, EdgeToMachine, Optional
|
||||
Mortising.Steps.nStepType = MCH_MILL_ST.ONEWAY
|
||||
end
|
||||
Mortising.Steps.dStep = TOOLS[Mortising.nToolIndex].dStep
|
||||
Mortising.Steps.nCount = max( 1, ceil( ( min( Mortising.dDepthToMachine, ( Mortising.dMaxElev or Mortising.dDepthToMachine)) + 10 * GEO.EPS_SMALL) / Mortising.Steps.dStep))
|
||||
-- faceuse
|
||||
if EdgeToMachine.dElevation > - 10 * GEO.EPS_SMALL then
|
||||
Mortising.nFaceuse = BeamLib.GetNearestParalOpposite( EdgeToMachine.vtToolDirection)
|
||||
if OppositeToolDirectionMode == 'Enabled' then
|
||||
Mortising.nFaceuse = BeamLib.GetNearestParalOpposite( -Mortising.vtToolDirection)
|
||||
else
|
||||
Mortising.nFaceuse = BeamLib.GetNearestParalOpposite( -EdgeToMachine.vtToolDirection)
|
||||
Mortising.nFaceuse = BeamLib.GetNearestParalOpposite( Mortising.vtToolDirection)
|
||||
end
|
||||
-- SCC
|
||||
Mortising.SCC = MCH_SCC.NONE
|
||||
-- asse bloccato e angoli suggeriti
|
||||
local vtRes = FaceToMachine.vtN ^ EdgeToMachine.vtToolDirection
|
||||
local vtRes = FaceToMachine.vtN ^ EdgeToMachine.vtN
|
||||
if abs( vtRes:getZ()) < 10 * GEO.EPS_SMALL then
|
||||
Mortising.sBlockedAxis = BeamLib.GetBlockedAxis( Mortising.nToolIndex, 'perpendicular', Part.b3Raw, FaceToMachine.vtN)
|
||||
Mortising.sSuggestedAngles = BeamLib.GetChainSawInitAngs( FaceToMachine.vtN, EdgeToMachine.vtToolDirection, 1)
|
||||
elseif EdgeToMachine.vtToolDirection:getZ() < 10 * GEO.EPS_SMALL then
|
||||
Mortising.sSuggestedAngles = BeamLib.GetChainSawInitAngs( FaceToMachine.vtN, EdgeToMachine.vtN, 1)
|
||||
elseif EdgeToMachine.vtN:getZ() < 10 * GEO.EPS_SMALL then
|
||||
Mortising.sBlockedAxis = BeamLib.GetBlockedAxis( Mortising.nToolIndex, 'parallel', Part.b3Raw, FaceToMachine.vtN)
|
||||
Mortising.sSuggestedAngles = BeamLib.GetChainSawInitAngs( FaceToMachine.vtN, EdgeToMachine.vtToolDirection, 2)
|
||||
Mortising.sSuggestedAngles = BeamLib.GetChainSawInitAngs( FaceToMachine.vtN, EdgeToMachine.vtN, 2)
|
||||
end
|
||||
-- approccio e retrazione
|
||||
Mortising.LeadIn, Mortising.LeadOut = CalculateLeadInOut( Mortising, EdgeToMachine, sSideToMachine, dLengthToMachine)
|
||||
-- eventuale step verticale
|
||||
Mortising.VerticalSteps = MachiningLib.GetMachiningSteps( dPocketHeight, TOOLS[Mortising.nToolIndex].dThickness)
|
||||
Mortising.CloneStepsLongitudinal = {}
|
||||
if not dLongitudinalStepSpan then
|
||||
dLongitudinalStepSpan = dPocketHeight
|
||||
end
|
||||
if dLongitudinalStepSpan > 10 * GEO.EPS_SMALL then
|
||||
Mortising.CloneStepsLongitudinal = MachiningLib.GetMachiningSteps( dLongitudinalStepSpan, TOOLS[Mortising.nToolIndex].dThickness)
|
||||
else
|
||||
Mortising.CloneStepsLongitudinal.nCount = 1
|
||||
Mortising.CloneStepsLongitudinal.dStep = dPocketHeight
|
||||
end
|
||||
-- lunghezza lavorata
|
||||
-- TODO per il calcolo della dLenghtOnX ripetere il calcolo del FACEBYBLADE con proiezione del lato; serve prolungare con la Add Length secondo la vtEdgeDirection
|
||||
-- TODO fare funzione EstimatePathLength o simile
|
||||
Mortising.dLengthToMachine = Mortising.dEdgeLength + Mortising.LeadIn.dStartAddLength + Mortising.LeadOut.dEndAddLength
|
||||
Mortising.dLengthOnX = abs( dLengthToMachine * EdgeToMachine.vtN:getY())
|
||||
Mortising.dTimeToMachine, Mortising.dLengthToMachineAllStepsWithLeadInOut = MachiningLib.GetTimeToMachineAllStepsWithLeadInOut( Mortising, Part)
|
||||
-- area lavorata
|
||||
Mortising.dAreaToMachine = min( EdgeToMachine.dElevation, Mortising.dDepthToMachine) * ( min( Mortising.dEdgeLength, Mortising.dLengthToMachine + TOOLS[Mortising.nToolIndex].dDiameter))
|
||||
-- geometria
|
||||
Mortising.Geometry = {{Proc.id, FaceToMachine.id}}
|
||||
-- nome operazione
|
||||
@@ -224,21 +225,26 @@ function SLOTBYCHAINSAW.Make( Proc, Part, FaceToMachine, EdgeToMachine, Optional
|
||||
|
||||
-- se lavorazione aperta sulla coda, eventuali aggiustamenti
|
||||
-- TODO valutare se fare funzione a parte
|
||||
if Proc.AffectedFaces.bLeft then
|
||||
if Proc.AffectedFaces.bLeft and ( EdgeToMachine.sType == 'Bottom' or ( Mortising.vtToolDirection:getX() < 0.707)) then
|
||||
local dLengthOnX = Mortising.dLengthOnX
|
||||
-- se feature splittata non si considera la lunghezza della feature per il check spostamento dopo separazione
|
||||
if bIsSplitFeature then
|
||||
dLengthOnX = 0
|
||||
end
|
||||
local bStartLeft = MachiningLib.StartsLeftSide( Mortising)
|
||||
local dAddLengthLeftSide = Mortising.LeadOut.dEndAddLength
|
||||
if bStartLeft then
|
||||
dAddLengthLeftSide = Mortising.LeadIn.dStartAddLength
|
||||
end
|
||||
if not AreSameOrOppositeVectorApprox( EdgeToMachine.vtToolDirection, Y_AX()) then
|
||||
if MachiningLib.CanMoveAfterSplitcut( Mortising.dLengthOnX, Part) then
|
||||
Mortising.bMoveAfterSplitcut = true
|
||||
if not AreSameOrOppositeVectorApprox( EdgeToMachine.vtN, Y_AX()) then
|
||||
if MachiningLib.CanMoveAfterSplitcut( dLengthOnX, Part) then
|
||||
Mortising.sStage = 'AfterTail'
|
||||
else
|
||||
Mortising.bIsApplicable = false
|
||||
end
|
||||
elseif dAddLengthLeftSide + TOOLS[Mortising.nToolIndex].dDiameter / 2 > dExtendAfterTail then
|
||||
if MachiningLib.CanMoveAfterSplitcut( Mortising.dLengthOnX, Part) then
|
||||
Mortising.bMoveAfterSplitcut = true
|
||||
if MachiningLib.CanMoveAfterSplitcut( dLengthOnX, Part) then
|
||||
Mortising.sStage = 'AfterTail'
|
||||
else
|
||||
if bStartLeft then
|
||||
Mortising.LeadIn.dStartAddLength = - TOOLS[Mortising.nToolIndex].dDiameter / 2 + dExtendAfterTail
|
||||
@@ -254,4 +260,4 @@ end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return SLOTBYCHAINSAW
|
||||
return FACEBYCHAINSAW
|
||||