Compare commits
641 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 | |||
| 9fcd805ed5 | |||
| eccfb96c22 | |||
| cff250ca37 | |||
| 7309ebb6a3 | |||
| c649870518 | |||
| 3d8ec03c47 | |||
| 42329d7688 | |||
| a6ddaa8bbd | |||
| bb82dcb724 | |||
| d58be78868 | |||
| 1cb9104404 | |||
| 19a47115ea | |||
| 6da682dfed | |||
| 08d3f7ff6d | |||
| 229e98cf9d | |||
| d7096a8a68 | |||
| b0f26bdea2 | |||
| 2586407ec9 | |||
| a34a62d635 | |||
| 44215b3b4e | |||
| a2b49fdf3e | |||
| 21b73e0031 | |||
| 54c86774b7 | |||
| 80c5a5a393 | |||
| 13ae86b6a7 | |||
| 8119643221 | |||
| 941954825d | |||
| 8d1286dd71 | |||
| 4abc2c01af | |||
| 7e6d8f4172 | |||
| 5aa2b5ac4d | |||
| ae4c3f9156 | |||
| a4f6e10dc3 | |||
| fc047c2350 | |||
| 28946a0291 | |||
| 9375cd0868 | |||
| 8bd772c96d | |||
| 2fff4438c0 | |||
| a17c62c15f | |||
| 20c8518f1d | |||
| 730d37c917 | |||
| 184a78d34c | |||
| a33e794b1e | |||
| f212c0cede | |||
| 38fdaca7bf | |||
| 7b580b24bb | |||
| 23bbd938fc | |||
| 21dd75b4a6 | |||
| a8ec76f451 | |||
| 9b5bb25c76 | |||
| b9c492fe5a | |||
| fdcb428002 | |||
| 91c883b87c | |||
| 8e151758b1 | |||
| 1132369f1e | |||
| b9bb1aefdd | |||
| 2b9113347a | |||
| 7c80c4d3d8 | |||
| 69fc865452 | |||
| 88bc848966 | |||
| 81a274563f | |||
| 32fa372012 | |||
| 21da5f633d | |||
| c24fef22a7 | |||
| 35e8ef2482 | |||
| 23d5f82403 | |||
| ec734ca99d | |||
| 34c5ecc5ec | |||
| 362f3fd2b0 | |||
| 9acd52ea10 | |||
| 74279896e9 | |||
| b270e150c0 | |||
| d9a36c0c5f | |||
| e189c0d518 | |||
| 380eb9450b | |||
| 5bbebcbbde | |||
| 3319d8b271 | |||
| 86fd80ee61 | |||
| 67bb860185 | |||
| 0b172e2be2 | |||
| d66bb615c9 | |||
| e3d73e9805 | |||
| f5f362c318 | |||
| 81c9a40618 | |||
| e5e9e7b876 | |||
| f5cbd7bfee | |||
| 546a60d8a3 | |||
| 62ca7479c7 | |||
| 4127bb5eef | |||
| 9a6036dc4c | |||
| 13c6eb3e06 | |||
| 4facba3389 | |||
| cd1f892a6c | |||
| 67899a5835 | |||
| 5dec2dc821 | |||
| c21de95a47 | |||
| db5ec90fbf | |||
| 285f3bc78d | |||
| cb37a14305 | |||
| d80a780886 | |||
| 9a8c0386d9 | |||
| 435075014d | |||
| 2b3630ee3a | |||
| 6d2037e0c5 | |||
| 2df3069711 | |||
| 5fc2b80cc1 | |||
| 2edfd52628 | |||
| 342082bb82 | |||
| 7e0bee34cc | |||
| 21ec48bc2d | |||
| f67f9530f5 | |||
| 0e634c7f0d | |||
| b6049893de | |||
| 0cdee9cfcb | |||
| d8b8a79a78 | |||
| 26c6cc68c9 | |||
| 58c9630563 | |||
| 04f40edd16 | |||
| 52fb5100ff | |||
| c49e81bcc4 | |||
| 4160190886 | |||
| b20ab1013a | |||
| a5382e0847 | |||
| 60bac29b1e | |||
| cc597ce890 | |||
| e0b4a8b852 | |||
| a312f715c7 | |||
| d191825118 | |||
| 8eeb7fa6d8 | |||
| b2a8279eb5 | |||
| c7687419a6 | |||
| 8cff8827a0 | |||
| 404938a6be | |||
| 69f97362b9 | |||
| 01bf95c56c | |||
| 32a16f97f3 | |||
| 297dcba66b | |||
| c1c6e2a220 | |||
| 230b5f871d | |||
| d53fdca890 | |||
| 7165db47f6 | |||
| 7b09634461 | |||
| 5dcc75587d | |||
| c3069a962a | |||
| 1a82df39ad | |||
| 6a89e6e29d | |||
| 5f30714a56 | |||
| 30fa7c8cbd | |||
| 59bbf159e4 | |||
| d45fc8e89b | |||
| ecf89edf59 | |||
| 3c1814ebdc | |||
| 5ea5c78605 | |||
| fedfc92ef0 | |||
| 03e4b4457d | |||
| 80dcdb0003 | |||
| 385143fb00 | |||
| 7bcce7463b | |||
| 8cda36a838 | |||
| 10399347f0 | |||
| 38540c5685 | |||
| 69f172863b | |||
| 76ec20260e | |||
| 10c1cd55f3 | |||
| ea588844c5 | |||
| fb47b28173 | |||
| 4f90b0704d | |||
| ce156606e6 | |||
| e58cf7e398 | |||
| bdc7c45204 | |||
| 7193f2595d | |||
| 65fec1e05d | |||
| a8a0ac5875 | |||
| 904b15a4c9 |
@@ -0,0 +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,7 @@
|
||||
[Beam]
|
||||
BtlEnable=1
|
||||
BaseDir=C:\EgtData\Beam
|
||||
BtlExec=BatchProcess.lua
|
||||
Button1=Process.lua,Images\Process.png,Lavora Travi
|
||||
Button2=Swap.lua,Images\Swap.png,Scambia estremi trave
|
||||
Button3=Rotate.lua,Images\Rotate.png,Ruota trave
|
||||
@@ -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 |
|
After Width: | Height: | Size: 1.0 KiB |
|
After Width: | Height: | Size: 528 B |
|
After Width: | Height: | Size: 479 B |
@@ -0,0 +1,762 @@
|
||||
--BasicCustomerStrategies.lua by Egalware s.r.l. 2024/04/02
|
||||
-- Libreria strategie di base disponibili per i clienti
|
||||
-- 2024/04/02 PRIMA VERSIONE CALCOLO LAVORAZIONI CON STRATEGIE
|
||||
|
||||
-- Tabella per definizione modulo
|
||||
local BasicCustomerStrategies = {}
|
||||
|
||||
-- Include
|
||||
require( 'EgtBase')
|
||||
|
||||
-- Carico i dati globali
|
||||
local BeamData = require( 'BeamData')
|
||||
local BeamLib = require( 'BeamLib')
|
||||
local ID = require( 'Identity')
|
||||
|
||||
|
||||
|
||||
-- TODO tabella da compleatare man mano che si inseriscono le varie strategie
|
||||
-- ESEMPIO SCRITTURA TABELLA CON STRATEGIE DISPONIBILI
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Cut
|
||||
-- if ID.TipoFeature( Proc) then
|
||||
-- if Proc.Topology.sName == 'QQQQQQQQQ' then
|
||||
-- Strategies = {
|
||||
-- { sStrategyId = 'STR9999',
|
||||
-- Parameters = {
|
||||
-- { sName = 'Val_1', sValue = '15', sType = 'd'},
|
||||
-- { sName = 'Val_2', sValue = 'false', sType = 'b'}
|
||||
-- }
|
||||
-- }
|
||||
-- { sStrategyId = 'STR9998'}
|
||||
-- }
|
||||
-- end
|
||||
-- end
|
||||
|
||||
----------------------------------------------------------------------------------
|
||||
-- *** STRATEGIE ***
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
----------------------------------------------------------------------------------
|
||||
-- *** EGALWARE ***
|
||||
----------------------------------------------------------------------------------
|
||||
local function GetStrategies_Egalware( Proc)
|
||||
local Strategies = {}
|
||||
|
||||
local sFile = BEAM.BASEDIR .. '\\Strategies\\AvailableStrategyList.json'
|
||||
-- se non esiste file JSON, annullo la lista contenente le strategie
|
||||
if not EgtExistsFile( sFile) then
|
||||
return nil
|
||||
end
|
||||
|
||||
local CompleteList = {}
|
||||
CompleteList.FEATURE = BeamLib.ImportFileJSON( sFile)
|
||||
|
||||
Strategies = BeamLib.GetStrategiesFromList( Proc, CompleteList)
|
||||
|
||||
-- si salva che la strategia è stata presa dallo standard
|
||||
if Strategies and #Strategies > 0 then
|
||||
Strategies.bIsBasicStrategy = true
|
||||
end
|
||||
|
||||
return Strategies
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------
|
||||
-- *** ESSETRE ***
|
||||
----------------------------------------------------------------------------------
|
||||
local function GetStrategies_Essetre( Proc)
|
||||
local Strategies = {}
|
||||
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Cut (1-10)
|
||||
if ID.IsHeadCut( Proc) then
|
||||
Strategies = { { sStrategyId = 'HEADCUT'}}
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Cut (2-10)
|
||||
elseif ID.IsTailCut( Proc) then
|
||||
Strategies = { { sStrategyId = 'TAILCUT'}}
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Cut (1-10)
|
||||
elseif ID.IsCut( Proc) then
|
||||
if Proc.Topology.sName == 'Cut-1-Through' or Proc.Topology.sName == 'Bevel-1-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0005'}}
|
||||
elseif Proc.Topology.sName == 'HeadCut' then
|
||||
Strategies = { { sStrategyId = 'HEADCUT'}}
|
||||
elseif Proc.Topology.sName == 'TailCut' then
|
||||
Strategies = { { sStrategyId = 'TAILCUT'}}
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Longitudinal Cut (0-10)
|
||||
elseif ID.IsLongitudinalCut( Proc) then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0005'}, { sStrategyId = 'STR0010'}}
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Double Cut (1-11)
|
||||
elseif ID.IsDoubleCut( Proc) then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0005'}}
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Ridge or Valley Cut (0-12)
|
||||
elseif ID.IsDoubleLongitudinalCut( Proc) then
|
||||
Strategies = { { sStrategyId = 'STR0005'}, { sStrategyId = 'STR0010'}}
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Saw Cut (0-13)
|
||||
elseif ID.IsSawCut( Proc) then
|
||||
if Proc.Topology.sName == 'Cut-1-Through' or Proc.Topology.sName == 'Bevel-1-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0005'}, { sStrategyId = 'STR0010'}}
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Slot (0-16)
|
||||
elseif ID.IsSlot( Proc) then
|
||||
if Proc.Topology.sName == 'Pocket-5-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Groove-4-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Groove-3-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Tunnel-4-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Groove-3-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}}
|
||||
elseif Proc.Topology.sName == 'Bevel-3-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}}
|
||||
elseif Proc.Topology.sName == 'Bevel-2-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0005'}, { sStrategyId = 'STR0010'}}
|
||||
elseif Proc.Topology.sName == 'Rabbet-2-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0005'}, { sStrategyId = 'STR0010'}}
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Front Slot (0-17)
|
||||
elseif ID.IsFrontSlot( Proc) then
|
||||
if Proc.Topology.sName == 'Pocket-5-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Groove-4-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Groove-3-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Tunnel-4-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Groove-3-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}}
|
||||
elseif Proc.Topology.sName == 'Bevel-3-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}}
|
||||
elseif Proc.Topology.sName == 'Bevel-2-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0005'}, { sStrategyId = 'STR0010'}}
|
||||
elseif Proc.Topology.sName == 'Rabbet-2-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0005'}, { sStrategyId = 'STR0010'}}
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Birds Mouth (0-20)
|
||||
elseif ID.IsBirdsMouth( Proc) then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0005'}, { sStrategyId = 'STR0010'}}
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Hip or Valley Rafter Notch (0-25)
|
||||
elseif ID.IsHipValleyRafterNotch( Proc) then
|
||||
if Proc.Topology.sName == 'RafterNotch-5-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}}
|
||||
elseif Proc.Topology.sName == 'Groove-3-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Groove-3-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}}
|
||||
elseif Proc.Topology.sName == 'Bevel-3-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}}
|
||||
elseif Proc.Topology.sName == 'Bevel-2-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0005'}, { sStrategyId = 'STR0010'}}
|
||||
elseif Proc.Topology.sName == 'Rabbet-2-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0005'}, { sStrategyId = 'STR0010'}}
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Ridge Lap (1-30)
|
||||
elseif ID.IsRidgeLap( Proc) then
|
||||
if Proc.Topology.sName == 'RidgeLap-3-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0012'}}
|
||||
elseif Proc.Topology.sName == 'Groove-3-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}}
|
||||
elseif Proc.Topology.sName == 'Bevel-3-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}}
|
||||
elseif Proc.Topology.sName == 'Bevel-2-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0005'}, { sStrategyId = 'STR0010'}}
|
||||
elseif Proc.Topology.sName == 'Rabbet-2-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0010'}}
|
||||
elseif Proc.Topology.sName == 'Cut-1-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0005'}, { sStrategyId = 'STR0005'}}
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Lap Joint (0-30)
|
||||
elseif ID.IsLapJoint( Proc) then
|
||||
if Proc.Topology.sName == 'Pocket-5-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Groove-4-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Groove-3-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Tunnel-4-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Groove-3-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}}
|
||||
elseif Proc.Topology.sName == 'Bevel-3-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}}
|
||||
elseif Proc.Topology.sName == 'Bevel-2-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0005'}, { sStrategyId = 'STR0010'}}
|
||||
elseif Proc.Topology.sName == 'Rabbet-2-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0005'}, { sStrategyId = 'STR0010'}}
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Notch/Rabbet (0-32)
|
||||
elseif ID.IsNotchRabbet( Proc) then
|
||||
if Proc.Topology.sName == 'Pocket-5-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Groove-4-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Groove-3-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Tunnel-4-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Groove-3-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}}
|
||||
elseif Proc.Topology.sName == 'Bevel-3-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}}
|
||||
elseif Proc.Topology.sName == 'Bevel-2-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0005'}, { sStrategyId = 'STR0010'}}
|
||||
elseif Proc.Topology.sName == 'Rabbet-2-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0005'}, { sStrategyId = 'STR0010'}}
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Block Haus (0-33)
|
||||
elseif ID.IsBlockHaus( Proc) then
|
||||
if Proc.Topology.sName == 'Groove-3-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Notch (0-32)
|
||||
elseif ID.IsNotch( Proc) then
|
||||
if Proc.Topology.sName == 'Pocket-5-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Groove-4-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Groove-3-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Tunnel-4-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Groove-3-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}}
|
||||
elseif Proc.Topology.sName == 'Bevel-3-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}}
|
||||
elseif Proc.Topology.sName == 'Bevel-2-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0005'}, { sStrategyId = 'STR0010'}}
|
||||
elseif Proc.Topology.sName == 'Rabbet-2-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0005'}, { sStrategyId = 'STR0010'}}
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : French Ridge Lap (1-35)
|
||||
elseif ID.IsFrenchRidgeLap( Proc) then
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Chamfer (0-36)
|
||||
elseif ID.IsChamfer( Proc) then
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Block Haus Half Lap (0-37)
|
||||
elseif ID.IsHalfBlockHaus( Proc) then
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Block Haus Front (0-38)
|
||||
elseif ID.IsFrontBlockHaus( Proc) then
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Pocket (0-39)
|
||||
elseif ID.IsPocket( Proc) then
|
||||
if Proc.Topology.sName == 'Pocket-5-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Groove-4-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Groove-3-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Tunnel-4-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Groove-3-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}}
|
||||
elseif Proc.Topology.sName == 'Bevel-3-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}}
|
||||
elseif Proc.Topology.sName == 'Bevel-2-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0005'}, { sStrategyId = 'STR0010'}}
|
||||
elseif Proc.Topology.sName == 'Rabbet-2-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0005'}, { sStrategyId = 'STR0010'}}
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Drilling (0-40)
|
||||
elseif ID.IsDrill( Proc) then
|
||||
Strategies = { { sStrategyId = 'STR0011'}, { sStrategyId = 'STR0013'}}
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Tenon (1-50)
|
||||
elseif ID.IsTenon( Proc) then
|
||||
Strategies = { { sStrategyId = 'STR0006'}}
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Mortise (0-50)
|
||||
elseif ID.IsMortise( Proc) then
|
||||
if Proc.Topology.sName == 'Pocket-5-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Groove-4-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Groove-3-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Tunnel-4-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Groove-3-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}}
|
||||
elseif Proc.Topology.sName == 'Bevel-3-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}}
|
||||
elseif Proc.Topology.sName == 'Bevel-2-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0005'}, { sStrategyId = 'STR0010'}}
|
||||
elseif Proc.Topology.sName == 'Rabbet-2-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0005'}, { sStrategyId = 'STR0010'}}
|
||||
elseif Proc.Topology.sName == 'Pocket-Round' or Proc.Topology.sName == 'Pocket-Round-Front' or Proc.Topology.sName == 'Pocket-Round-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0008'}}
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Front Mortise (0-51)
|
||||
elseif ID.IsFrontMortise( Proc) then
|
||||
if Proc.Topology.sName == 'Pocket-5-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Groove-4-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Groove-3-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Tunnel-4-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0003'}, { sStrategyId = 'STR0004'}}
|
||||
elseif Proc.Topology.sName == 'Groove-3-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}}
|
||||
elseif Proc.Topology.sName == 'Bevel-3-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}}
|
||||
elseif Proc.Topology.sName == 'Bevel-2-Blind' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0005'}, { sStrategyId = 'STR0010'}}
|
||||
elseif Proc.Topology.sName == 'Rabbet-2-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0005'}, { sStrategyId = 'STR0010'}}
|
||||
elseif Proc.Topology.sName == 'Pocket-Round' or Proc.Topology.sName == 'Pocket-Round-Front' or Proc.Topology.sName == 'Pocket-Round-Through' then
|
||||
Strategies = { { sStrategyId = 'STR0008'}}
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : House (1-52)
|
||||
elseif ID.IsHouse( Proc) then
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : House Mortise (0-53)
|
||||
elseif ID.IsHouseMortise( Proc) then
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Dovetail Tenon (1-55)
|
||||
elseif ID.IsDovetailTenon( Proc) then
|
||||
Strategies = { { sStrategyId = 'STR0001'}}
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Dovetail Mortise (0-55)
|
||||
elseif ID.IsDovetailMortise( Proc) then
|
||||
Strategies = { { sStrategyId = 'STR0007'}}
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Dovetail Mortise Front (0-56)
|
||||
elseif ID.IsFrontDovetailMortise( Proc) then
|
||||
Strategies = { { sStrategyId = 'STR0007'}}
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Marking (0-60)
|
||||
elseif ID.IsMarking( Proc) then
|
||||
Strategies = { { sStrategyId = 'STR0014'}}
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Text (0-61)
|
||||
elseif ID.IsText( Proc) then
|
||||
Strategies = { { sStrategyId = 'STR0014'}}
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Scarf Simple (1-70)
|
||||
elseif ID.IsScarfSimple( Proc) then
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Scarf Joint (1-71)
|
||||
elseif ID.IsScarfJoint( Proc) then
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Step Joint (1-80)
|
||||
elseif ID.IsStepJoint( Proc) then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0010'}}
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Step Joint Notch (0-80)
|
||||
elseif ID.IsStepJointNotch( Proc) then
|
||||
Strategies = { { sStrategyId = 'STR0002'}, { sStrategyId = 'STR0010'}}
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Planing (0-90)
|
||||
elseif ID.IsPlaning( Proc) then
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Front Profile (0-100)
|
||||
elseif ID.IsFrontProfile( Proc) then
|
||||
Strategies = { { sStrategyId = 'STR0015'}}
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Head Concave Profile (0-101)
|
||||
elseif ID.IsHeadConcaveProfile( Proc) then
|
||||
Strategies = { { sStrategyId = 'STR0015'}}
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Head Convex Profile (0-102)
|
||||
elseif ID.IsHeadConvexProfile( Proc) then
|
||||
Strategies = { { sStrategyId = 'STR0015'}}
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Head Cambered Profile (0-103)
|
||||
elseif ID.IsHeadCamberedProfile( Proc) then
|
||||
Strategies = { { sStrategyId = 'STR0015'}}
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Round Arch (0-104)
|
||||
elseif ID.IsRoundArch( Proc) then
|
||||
Strategies = { { sStrategyId = 'STR0015'}}
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Head Profile (0-106)
|
||||
elseif ID.IsHeadProfile( Proc) then
|
||||
Strategies = { { sStrategyId = 'STR0015'}}
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Sphere (0-107)
|
||||
elseif ID.IsSphere( Proc) then
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Triangle Cut (0-120)
|
||||
elseif ID.IsTriangleCut( Proc) then
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : TyroleanDovetail (0-136)
|
||||
elseif ID.IsTyroleanDovetail( Proc) then
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Dovetail (0-138)
|
||||
elseif ID.IsDovetail( Proc) then
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Free Contour (0-250)
|
||||
elseif ID.IsFreeContour( Proc) then
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Outline (0-251)
|
||||
elseif ID.IsOutline( Proc) then
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Aperture (0-252)
|
||||
elseif ID.IsAperture( Proc) then
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Variant (0-900)
|
||||
elseif ID.IsVariant( Proc) then
|
||||
---------------------------------------------------------------------
|
||||
end
|
||||
|
||||
-- si salva che la strategia è stata presa dallo script
|
||||
if #Strategies > 0 then
|
||||
Strategies.bIsBasicStrategy = true
|
||||
end
|
||||
|
||||
return Strategies
|
||||
end
|
||||
|
||||
|
||||
----------------------------------------------------------------------------------
|
||||
-- *** PARAMETRI ***
|
||||
----------------------------------------------------------------------------------
|
||||
----------------------------------------------------------------------------------
|
||||
-- *** ESSETRE ***
|
||||
----------------------------------------------------------------------------------
|
||||
-- funzione che recupera i parametri custom della strategia. Per cliente Essetre, vengono salvati dei valori 'Q' sul processing del file NGE per modificare il comportamento delle macro
|
||||
local function GetParameters_Essetre( Proc, sStrategyIdToGet)
|
||||
local Parameters = {}
|
||||
--###---###---###---###---###---###---###---###---###---###---###---###---###--
|
||||
-- Feature : HeadCut
|
||||
if ID.IsHeadCut( Proc) then
|
||||
-- Per Essetre non esiste il taglio di testa, quindi si leggono le variabili Q sul processing che coincide con il taglio di testa
|
||||
if sStrategyIdToGet == 'HEADCUT' then
|
||||
local dDepthChamfer = EgtGetInfo( Proc.id or GDB_ID.NULL, 'Q06', 'd') or 0
|
||||
table.insert( Parameters, { sName = 'dDepthChamfer', sValue = dDepthChamfer, sType = 'd'})
|
||||
local dCuttingStrategy = EgtGetInfo( Proc.id or GDB_ID.NULL, 'Q05', 'd') or 0
|
||||
local bForceChainSaw = dCuttingStrategy > 0
|
||||
table.insert( Parameters, { sName = 'bForceChainSaw', sValue = bForceChainSaw, sType = 'b'})
|
||||
local bFinishWithMill = dCuttingStrategy == 2
|
||||
table.insert( Parameters, { sName = 'bFinishWithMill', sValue = bFinishWithMill, sType = 'b'})
|
||||
end
|
||||
--###---###---###---###---###---###---###---###---###---###---###---###---###--
|
||||
-- Feature : Cut (1-10)
|
||||
elseif ID.IsCut( Proc) then
|
||||
local dDepthChamfer = EgtGetInfo( Proc.id or GDB_ID.NULL, 'Q06', 'd') or 0
|
||||
table.insert( Parameters, { sName = 'dDepthChamfer', sValue = dDepthChamfer, sType = 'd'})
|
||||
local bForcePocketing = EgtGetInfo( Proc.id or GDB_ID.NULL, 'Q07', 'd') == 1
|
||||
-- tutte le strategie che non siano svuotatura, devono essere rimosse
|
||||
if bForcePocketing and sStrategyIdToGet ~= 'STR0002' then
|
||||
Parameters.bToRemove = true
|
||||
else
|
||||
if sStrategyIdToGet == 'STR0002' then
|
||||
-- non ci sono Q per questa strategia
|
||||
elseif sStrategyIdToGet == 'STR0005' then
|
||||
local dCuttingStrategy = EgtGetInfo( Proc.id or GDB_ID.NULL, 'Q04', 'd') or 0
|
||||
local sCuttingStrategy = EgtIf( dCuttingStrategy == 1, 'KEEP_WASTE_ATTACHED', 'AUTO')
|
||||
table.insert( Parameters, { sName = 'sCuttingStrategy', sValue = sCuttingStrategy, sType = 's'})
|
||||
end
|
||||
end
|
||||
--###---###---###---###---###---###---###---###---###---###---###---###---###--
|
||||
-- Feature : Drill (1-40)
|
||||
elseif ID.IsDrill( Proc) then
|
||||
if sStrategyIdToGet == 'STR0011' then
|
||||
local dDepthPreHole = ( EgtGetInfo( Proc.id or GDB_ID.NULL, 'Q03', 'd') or 0) == 1
|
||||
table.insert( Parameters, { sName = 'dDepthPreHole', sValue = dDepthPreHole, sType = 'd'})
|
||||
elseif sStrategyIdToGet == 'STR0013' then
|
||||
local bOnlyContouring = ( EgtGetInfo( Proc.id or GDB_ID.NULL, 'Q01', 'd') or 0) == 1
|
||||
table.insert( Parameters, { sName = 'bOnlyContouring', sValue = bOnlyContouring, sType = 'b'})
|
||||
end
|
||||
local bDrillFromOneSide = ( EgtGetInfo( Proc.id or GDB_ID.NULL, 'Q02', 'd') or 0) == 1
|
||||
local sDrillingMode = EgtIf( bDrillFromOneSide, 'PREFER_ONE', 'AUTO')
|
||||
table.insert( Parameters, { sName = 'sDrillingMode', sValue = sDrillingMode, sType = 's'})
|
||||
--###---###---###---###---###---###---###---###---###---###---###---###---###--
|
||||
-- Feature : Front Profile (0-100)
|
||||
elseif ID.IsFrontProfile( Proc) then
|
||||
local dDepthChamfer = EgtGetInfo( Proc.id or GDB_ID.NULL, 'Q01', 'd') or 0
|
||||
local dOverMaterial = EgtGetInfo( Proc.id or GDB_ID.NULL, 'Q02', 'd') or 0
|
||||
local bOnlyChamfer = ( EgtGetInfo( Proc.id or GDB_ID.NULL, 'Q03', 'd') or 0) == 1
|
||||
table.insert( Parameters, { sName = 'dDepthChamfer' , sValue = dDepthChamfer, sType = 'd'})
|
||||
table.insert( Parameters, { sName = 'bOnlyChamfer' , sValue = bOnlyChamfer, sType = 'b'})
|
||||
table.insert( Parameters, { sName = 'dOverMaterial' , sValue = dOverMaterial, sType = 'd'})
|
||||
--###---###---###---###---###---###---###---###---###---###---###---###---###--
|
||||
-- Feature : Head Concave Profile (0-101)
|
||||
elseif ID.IsHeadConcaveProfile( Proc) then
|
||||
local dDepthChamfer = EgtGetInfo( Proc.id or GDB_ID.NULL, 'Q01', 'd') or 0
|
||||
local dOverMaterial = EgtGetInfo( Proc.id or GDB_ID.NULL, 'Q02', 'd') or 0
|
||||
local bOnlyChamfer = ( EgtGetInfo( Proc.id or GDB_ID.NULL, 'Q04', 'd') or 0) == 1
|
||||
table.insert( Parameters, { sName = 'dDepthChamfer' , sValue = dDepthChamfer, sType = 'd'})
|
||||
table.insert( Parameters, { sName = 'bOnlyChamfer' , sValue = bOnlyChamfer, sType = 'b'})
|
||||
table.insert( Parameters, { sName = 'dOverMaterial' , sValue = dOverMaterial, sType = 'd'})
|
||||
--###---###---###---###---###---###---###---###---###---###---###---###---###--
|
||||
-- Feature : Head Convex Profile (0-102)
|
||||
elseif ID.IsHeadConvexProfile( Proc) then
|
||||
local dDepthChamfer = EgtGetInfo( Proc.id or GDB_ID.NULL, 'Q02', 'd') or 0
|
||||
local dOverMaterial = EgtGetInfo( Proc.id or GDB_ID.NULL, 'Q04', 'd') or 0
|
||||
local bOnlyChamfer = ( EgtGetInfo( Proc.id or GDB_ID.NULL, 'Q01', 'd') or 0) == 1
|
||||
table.insert( Parameters, { sName = 'dDepthChamfer' , sValue = dDepthChamfer, sType = 'd'})
|
||||
table.insert( Parameters, { sName = 'bOnlyChamfer' , sValue = bOnlyChamfer, sType = 'b'})
|
||||
table.insert( Parameters, { sName = 'dOverMaterial' , sValue = dOverMaterial, sType = 'd'})
|
||||
--###---###---###---###---###---###---###---###---###---###---###---###---###--
|
||||
-- Feature : Head Cambered Profile (0-103)
|
||||
elseif ID.IsHeadCamberedProfile( Proc) then
|
||||
local sUpperFaceStrategy = EgtGetInfo( Proc.id or GDB_ID.NULL, 'Q01', 's') or '' -- Q01 = forza fresa
|
||||
sUpperFaceStrategy = EgtGetInfo( Proc.id or GDB_ID.NULL, 'Q02', 's') or sUpperFaceStrategy or 'AUTO' -- Q02 = forza lama (se entrambi attivi comanda la lama)
|
||||
table.insert( Parameters, { sName = 'sUpperFaceStrategy' , sValue = sUpperFaceStrategy, sType = 's'})
|
||||
local dDepthChamfer = EgtGetInfo( Proc.id or GDB_ID.NULL, 'Q03', 'd') or 0
|
||||
local dOverMaterial = EgtGetInfo( Proc.id or GDB_ID.NULL, 'Q04', 'd') or 0
|
||||
local bOnlyChamfer = ( EgtGetInfo( Proc.id or GDB_ID.NULL, 'Q05', 'd') or 0) == 1
|
||||
table.insert( Parameters, { sName = 'dDepthChamfer' , sValue = dDepthChamfer, sType = 'd'})
|
||||
table.insert( Parameters, { sName = 'bOnlyChamfer' , sValue = bOnlyChamfer, sType = 'b'})
|
||||
table.insert( Parameters, { sName = 'dOverMaterial' , sValue = dOverMaterial, sType = 'd'})
|
||||
--###---###---###---###---###---###---###---###---###---###---###---###---###--
|
||||
-- Feature : Round Arch (0-104)
|
||||
elseif ID.IsRoundArch( Proc) then
|
||||
local dDepthChamfer = EgtGetInfo( Proc.id or GDB_ID.NULL, 'Q03', 'd') or 0
|
||||
local dOverMaterial = EgtGetInfo( Proc.id or GDB_ID.NULL, 'Q01', 'd') or 0
|
||||
local dStripWidth = ( EgtGetInfo( Proc.id or GDB_ID.NULL, 'Q02', 'd') or 0)
|
||||
table.insert( Parameters, { sName = 'dDepthChamfer' , sValue = dDepthChamfer, sType = 'd'})
|
||||
table.insert( Parameters, { sName = 'dStripWidth' , sValue = dStripWidth, sType = 'b'})
|
||||
table.insert( Parameters, { sName = 'dOverMaterial' , sValue = dOverMaterial, sType = 'd'})
|
||||
--###---###---###---###---###---###---###---###---###---###---###---###---###--
|
||||
-- Feature : Head Profile (0-106)
|
||||
elseif ID.IsHeadProfile( Proc) then
|
||||
local dDepthChamfer = EgtGetInfo( Proc.id or GDB_ID.NULL, 'Q01', 'd') or 0
|
||||
local dOverMaterial = EgtGetInfo( Proc.id or GDB_ID.NULL, 'Q02', 'd') or 0
|
||||
local bOnlyChamfer = ( EgtGetInfo( Proc.id or GDB_ID.NULL, 'Q03', 'd') or 0) == 1
|
||||
table.insert( Parameters, { sName = 'dDepthChamfer' , sValue = dDepthChamfer, sType = 'd'})
|
||||
table.insert( Parameters, { sName = 'bOnlyChamfer' , sValue = bOnlyChamfer, sType = 'b'})
|
||||
table.insert( Parameters, { sName = 'dOverMaterial' , sValue = dOverMaterial, sType = 'd'})
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
return Parameters
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-- funzione che verifica se un item è contenuto in lista
|
||||
local function Contains( List, Item)
|
||||
for _, value in ipairs( List) do
|
||||
if EgtStartsWith( Item, value) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-- funzione che ritorna lista utensili presenti in lista compatibili con i tag passati
|
||||
local function GetToolsFromMachDataFile( MachiningDataList, TagListToGet)
|
||||
local ToolList = {}
|
||||
|
||||
if MachiningDataList and #MachiningDataList > 0 and #TagListToGet > 0 then
|
||||
for nIndex = 1, #MachiningDataList do
|
||||
-- se utensile attivo e compatibile con TAG
|
||||
if MachiningDataList[nIndex].On and Contains( TagListToGet, MachiningDataList[nIndex].Type) then
|
||||
-- se è nuova versione, prendo il tool
|
||||
if MachiningDataList[nIndex].Tool then
|
||||
table.insert( ToolList, { sName = MachiningDataList[nIndex].Tool})
|
||||
-- altrimenti dalla lavorazione si ricava il tool
|
||||
elseif MachiningDataList[nIndex].Name then
|
||||
if EgtMdbSetCurrMachining( MachiningDataList[nIndex].Name) then
|
||||
table.insert( ToolList, { sName = EgtMdbGetCurrMachiningParam( MCH_MP.TOOL)})
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
return ToolList
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-- TODO da completare
|
||||
-- funzione che recupera gli utensili disponibili per un certo tipo di lavorazione
|
||||
local function GetTools_Essetre( Proc, sMachiningCategory)
|
||||
local sMachDir = EgtGetCurrMachineDir()
|
||||
local TagList = {}
|
||||
local ToolList = {}
|
||||
|
||||
-- CATEGORIE PREVISTE :
|
||||
-- Cutting
|
||||
-- Drill
|
||||
-- Milling, MillingFinish, MillingAntiSplint, MillingChamfer
|
||||
-- Pocketing
|
||||
-- ChainSawing
|
||||
|
||||
if sMachiningCategory == 'Cutting' then
|
||||
if EgtExistsFile( sMachDir .. '\\Beam\\CutData.lua') then
|
||||
local CutData = dofile( sMachDir .. '\\Beam\\CutData.lua')
|
||||
if ID.IsDoubleLongitudinalCut( Proc) or ID.IsLongitudinalCut( Proc) then
|
||||
TagList = { 'LongCut'}
|
||||
else
|
||||
TagList = { 'HeadSide', 'TailSide'}
|
||||
end
|
||||
ToolList = GetToolsFromMachDataFile( CutData, TagList)
|
||||
end
|
||||
elseif sMachiningCategory == 'Drilling' or ID.IsDrill( Proc) then
|
||||
if EgtExistsFile( sMachDir .. '\\Beam\\DrillData.lua') then
|
||||
local DrillData = dofile( sMachDir .. '\\Beam\\DrillData.lua')
|
||||
if sMachiningCategory == 'Pocketing' or sMachiningCategory == 'Milling' then
|
||||
TagList = { 'Pocket'}
|
||||
else
|
||||
TagList = { 'Drill', 'Predrill', 'AngleDrill', 'MultiDrill'}
|
||||
end
|
||||
ToolList = GetToolsFromMachDataFile( DrillData, TagList)
|
||||
end
|
||||
elseif sMachiningCategory == 'Milling' or sMachiningCategory == 'MillingFinish' or sMachiningCategory == 'MillingAntiSplint' or sMachiningCategory == 'MillingChamfer' or
|
||||
sMachiningCategory == 'MillingSmooth' then
|
||||
if EgtExistsFile( sMachDir .. '\\Beam\\MillingData.lua') then
|
||||
local MillingData = dofile( sMachDir .. '\\Beam\\MillingData.lua')
|
||||
-- si cercano TAG esclusivi
|
||||
if sMachiningCategory == 'MillingSmooth' then
|
||||
TagList = { 'Mark', 'Text', 'Decor01', 'CleanCorner'}
|
||||
elseif sMachiningCategory == 'MillingAntiSplint' then
|
||||
TagList = { 'AntiSplintMillCut'}
|
||||
elseif ID.IsTenon( Proc) then
|
||||
TagList = { 'Tenon'}
|
||||
elseif ID.IsDovetailTenon( Proc) then
|
||||
-- gestione passaggio di taglio tenone superiore in caso di P14>0. Si prendono le frese per tenone standard dato che serve fresa cilindrica
|
||||
if sMachiningCategory == 'MillingFinish' then
|
||||
TagList = { 'Tenon'}
|
||||
else
|
||||
TagList = { 'DtTenon'}
|
||||
end
|
||||
elseif ID.IsDovetailMortise( Proc) then
|
||||
TagList = { 'DtMortise'}
|
||||
elseif ID.IsFrontProfile( Proc) or ID.IsHeadConcaveProfile( Proc) or ID.IsHeadConvexProfile( Proc) or
|
||||
ID.IsHeadCamberedProfile( Proc) or ID.IsRoundArch( Proc) or ID.IsHeadProfile( Proc) then
|
||||
if sMachiningCategory == 'MillingFinish' then
|
||||
TagList = { 'Prof_end'}
|
||||
end
|
||||
if not TagList or #TagList == 0 then
|
||||
TagList = { 'Prof', 'Prof_end'}
|
||||
end
|
||||
elseif ID.IsFreeContour( Proc) then
|
||||
TagList = { 'FreeContour', 'Prof', 'Prof_end'}
|
||||
elseif ID.IsMarking( Proc) then
|
||||
TagList = { 'Mark'}
|
||||
elseif sMachiningCategory == 'MillingChamfer' then
|
||||
TagList = { 'Chamfer'}
|
||||
elseif ID.IsText( Proc) then
|
||||
TagList = { 'Text'}
|
||||
elseif ID.IsTyroleanDovetail( Proc) or ID.IsDovetail( Proc) then
|
||||
TagList = { 'ProfTCone', 'Long2Cut'}
|
||||
elseif ID.IsBirdsMouth( Proc) then
|
||||
TagList = { 'BirdsMouth'}
|
||||
elseif sMachiningCategory == 'MillingFinish' then
|
||||
TagList = { 'CleanCorner', 'SmallToolContour'}
|
||||
elseif ID.IsSlot( Proc) or ID.IsFrontSlot( Proc) or ID.IsLapJoint( Proc) or ID.IsNotchRabbet( Proc) or ID.IsNotch( Proc) or
|
||||
ID.IsPocket( Proc) or ID.IsMortise( Proc) or ID.IsFrontMortise( Proc) then
|
||||
TagList = { 'SideMillAsBlade', 'BHSideMill', 'Long2Cut', 'Long2CutDown', 'LongSmallCut', 'Long2CutSide'}
|
||||
elseif ID.IsDoubleLongitudinalCut( Proc) or ID.IsDoubleLongitudinalCut( Proc) then
|
||||
TagList = { 'Long2Cut', 'Long2CutDown', 'LongSmallCut', 'Long2CutSide'}
|
||||
end
|
||||
|
||||
ToolList = GetToolsFromMachDataFile( MillingData, TagList)
|
||||
end
|
||||
elseif sMachiningCategory == 'Pocketing' then
|
||||
if EgtExistsFile( sMachDir .. '\\Beam\\PocketingData.lua') then
|
||||
local PocketingData = dofile( sMachDir .. '\\Beam\\PocketingData.lua')
|
||||
-- si cercano TAG esclusivi
|
||||
if ID.IsMortise( Proc) then
|
||||
TagList = { 'Mortise'}
|
||||
else
|
||||
TagList = { 'Pocket', 'OpenPocket'}
|
||||
end
|
||||
ToolList = GetToolsFromMachDataFile( PocketingData, TagList)
|
||||
end
|
||||
elseif sMachiningCategory == 'ChainSawing' then
|
||||
if EgtExistsFile( sMachDir .. '\\Beam\\SawingData.lua') then
|
||||
local SawingData = dofile( sMachDir .. '\\Beam\\SawingData.lua')
|
||||
TagList = { 'Sawing', 'Mortising'}
|
||||
ToolList = GetToolsFromMachDataFile( SawingData, TagList)
|
||||
end
|
||||
end
|
||||
|
||||
return ToolList
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------
|
||||
-- *** Esecuzione ***
|
||||
----------------------------------------------------------------------------------
|
||||
|
||||
-- script delle strategie di base standard definito con cliente (statico e non modificabile)
|
||||
-- se non esiste JSON configurazione, o se non ha trovato nessuna strategia, prova a cercare in questi script
|
||||
function BasicCustomerStrategies.GetStrategiesFromBasicCustomerStrategies( Proc)
|
||||
local StrategiesFromScript = {}
|
||||
|
||||
-- CLIENTE : ESSETRE
|
||||
if EgtStartsWith( EgtGetCurrMachineName(), 'Essetre') then
|
||||
StrategiesFromScript = GetStrategies_Essetre( Proc)
|
||||
-- per tutti gli altri clienti, si carica standard di default EGALWARE
|
||||
else
|
||||
StrategiesFromScript = GetStrategies_Egalware( Proc)
|
||||
end
|
||||
|
||||
return StrategiesFromScript
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------
|
||||
-- lettura parametri che personalizzano le strategie. I parametri di default sono decisi con cliente
|
||||
function BasicCustomerStrategies.GetParametersFromBasicCustomerStrategies( Proc, sStrategyIdToGet)
|
||||
local ParametersFromScript = {}
|
||||
|
||||
-- CLIENTE : ESSETRE
|
||||
if EgtStartsWith( EgtGetCurrMachineName(), 'Essetre') then
|
||||
ParametersFromScript = GetParameters_Essetre( Proc, sStrategyIdToGet)
|
||||
else
|
||||
ParametersFromScript = nil
|
||||
end
|
||||
|
||||
return ParametersFromScript
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------
|
||||
-- funzione che riprocessa le strategie dopo che sono stati letti tutti i parmetri
|
||||
function BasicCustomerStrategies.UpdateStrategies( AvailableStrategies)
|
||||
-- se la strategia è settata come da rimuovere, la si toglie dalla lista
|
||||
for nIndexStrategy = #AvailableStrategies, 1, -1 do
|
||||
if AvailableStrategies[nIndexStrategy].bToRemove then
|
||||
table.remove( AvailableStrategies, nIndexStrategy)
|
||||
end
|
||||
end
|
||||
return AvailableStrategies
|
||||
end
|
||||
|
||||
----------------------------------------------------------------------------------
|
||||
-- lettura utensili disponibili settati in lista machining data
|
||||
function BasicCustomerStrategies.GetToolsFromMachiningDataFile( Proc, sToolType)
|
||||
local ToolList = {}
|
||||
|
||||
-- CLIENTE : ESSETRE
|
||||
if EgtStartsWith( EgtGetCurrMachineName(), 'Essetre') then
|
||||
ToolList = GetTools_Essetre( Proc, sToolType)
|
||||
-- l'ordine di come le lavorazioni sono state in lista deve essere rispettato
|
||||
ToolList.bRespectListOrder = true
|
||||
-- per tutti gli altri si considerano tutti gli utensili a disposizione
|
||||
else
|
||||
ToolList = nil
|
||||
end
|
||||
|
||||
return ToolList
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return BasicCustomerStrategies
|
||||
@@ -0,0 +1,945 @@
|
||||
-- BeamLib.lua by Egalware s.r.l. 2024/04/02
|
||||
-- Libreria globale per Travi
|
||||
-- 2024/04/02 PRIMA VERSIONE CALCOLO LAVORAZIONI CON STRATEGIE
|
||||
|
||||
|
||||
-- Tabella per definizione modulo
|
||||
local BeamLib = {}
|
||||
|
||||
-- Include
|
||||
require( 'EgtBase')
|
||||
local BeamData = require( 'BeamData')
|
||||
|
||||
|
||||
EgtOutLog( ' BeamLib started', 1)
|
||||
|
||||
--TODO refactoring di queste funzioni
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function BeamLib.AddPartStartFace( PartId, b3Solid)
|
||||
-- recupero gruppo per geometria aggiuntiva
|
||||
local AddGrpId = BeamLib.GetAddGroup( PartId)
|
||||
if not AddGrpId then
|
||||
local sErr = 'Error on process StartFace impossible to find AddGroup'
|
||||
EgtOutLog( sErr)
|
||||
return false, sErr
|
||||
end
|
||||
|
||||
-- aggiungo nuovo taglio iniziale
|
||||
local nStmId = EgtSurfTmPlaneInBBox( AddGrpId, b3Solid:getMax(), X_AX(), b3Solid, GDB_RT.GLOB)
|
||||
if not nStmId then
|
||||
local sErr = 'Error on process StartFace impossible to create Face'
|
||||
EgtOutLog( sErr)
|
||||
return false, sErr
|
||||
end
|
||||
-- applico gli opportuni attributi di feature
|
||||
EgtSetInfo( nStmId, 'HEAD_ADD_CUT', 1)
|
||||
EgtSetInfo( nStmId, 'GRP', 1)
|
||||
EgtSetInfo( nStmId, 'PRC', 10) -- ex 340
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function BeamLib.AddPartEndFace( PartId, b3Solid)
|
||||
-- recupero gruppo per geometria aggiuntiva
|
||||
local AddGrpId = BeamLib.GetAddGroup( PartId)
|
||||
if not AddGrpId then
|
||||
local sErr = 'Error on process EndFace impossible to find AddGroup'
|
||||
EgtOutLog( sErr)
|
||||
return false, sErr
|
||||
end
|
||||
|
||||
-- aggiungo nuovo taglio finale
|
||||
local nStmId = EgtSurfTmPlaneInBBox( AddGrpId, b3Solid:getMin(), -X_AX(), b3Solid, GDB_RT.GLOB)
|
||||
if not nStmId then
|
||||
local sErr = 'Error on process EndFace impossible to create Face'
|
||||
EgtOutLog( sErr)
|
||||
return false, sErr
|
||||
end
|
||||
-- applico gli opportuni attributi di feature
|
||||
EgtSetInfo( nStmId, 'HEAD_ADD_CUT', 1)
|
||||
EgtSetInfo( nStmId, 'GRP', 2)
|
||||
EgtSetInfo( nStmId, 'PRC', 10) -- ex 350
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function BeamLib.GetPartSplittingPoints( Part)
|
||||
local PartSplittingPoints = {}
|
||||
local dPartLength = Part.b3Part:getDimX()
|
||||
local dMaxSegmentLength = BeamData.LONGCUT_MAXLEN
|
||||
local dMaxSegmentLengthOnEdges = BeamData.LONGCUT_ENDLEN
|
||||
|
||||
if dPartLength < dMaxSegmentLength + 10 * GEO.EPS_SMALL then
|
||||
return {}
|
||||
elseif dPartLength >= dMaxSegmentLength + 10 * GEO.EPS_SMALL
|
||||
and dPartLength < 3 * dMaxSegmentLengthOnEdges + 10 * GEO.EPS_SMALL then
|
||||
local dXPartCentralPoint = ( Part.b3Part:getMax():getX() - Part.b3Part:getMin():getX()) / 2
|
||||
table.insert( PartSplittingPoints, Point3d( dXPartCentralPoint, 0, 0))
|
||||
else
|
||||
-- punto estremo destro
|
||||
local dSplitXRight = Part.b3Part:getMax():getX() - dMaxSegmentLengthOnEdges
|
||||
table.insert( PartSplittingPoints, Point3d( dSplitXRight, 0, 0))
|
||||
|
||||
-- punti centrali
|
||||
local dPartCentralLength = dPartLength - 2 * dMaxSegmentLengthOnEdges
|
||||
local nSplitParts = max( ceil( dPartCentralLength / dMaxSegmentLength + 10 * GEO.EPS_SMALL), 1)
|
||||
local dSplitPartsLen = dPartCentralLength / nSplitParts
|
||||
for i = 1, ( nSplitParts - 1) do
|
||||
local ptOn
|
||||
local dCurrentPointX = dSplitXRight - i * dSplitPartsLen
|
||||
ptOn = Point3d( dCurrentPointX, 0, 0)
|
||||
table.insert( PartSplittingPoints, ptOn)
|
||||
end
|
||||
|
||||
-- punto estremo sinistro
|
||||
local dSplitXLeft = Part.b3Part:getMin():getX() + dMaxSegmentLengthOnEdges
|
||||
table.insert( PartSplittingPoints, Point3d( dSplitXLeft, 0, 0))
|
||||
end
|
||||
|
||||
return PartSplittingPoints
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function BeamLib.AddPhaseWithRawParts( idRaw, OriXR, PosXR, dDeltaSucc)
|
||||
EgtAddPhase()
|
||||
-- si aprono i limiti tavola per permettere rotazioni di pezzi più larghi della tavola
|
||||
EgtSetTableAreaOffset( 2000, 2000, 2000, 2000)
|
||||
local dRawMove = 0
|
||||
while idRaw do
|
||||
EgtKeepRawPart( idRaw)
|
||||
EgtMoveToCornerRawPart( idRaw, OriXR, PosXR)
|
||||
EgtMoveRawPart( idRaw, Vector3d( - dRawMove, 0, 0))
|
||||
if dRawMove == 0 then dRawMove = dRawMove + dDeltaSucc end
|
||||
dRawMove = dRawMove + EgtGetRawPartBBox( idRaw):getDimX()
|
||||
idRaw = EgtGetNextRawPart( idRaw)
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function BeamLib.IsPointOnBoxLimit( ptPointToCheck, b3Solid)
|
||||
local bOnBoxLimit = false
|
||||
if abs( ptPointToCheck:getX() - b3Solid:getMax():getX()) < 100 * GEO.EPS_SMALL or
|
||||
abs( ptPointToCheck:getX() - b3Solid:getMin():getX()) < 100 * GEO.EPS_SMALL or
|
||||
abs( ptPointToCheck:getY() - b3Solid:getMax():getY()) < 100 * GEO.EPS_SMALL or
|
||||
abs( ptPointToCheck:getY() - b3Solid:getMin():getY()) < 100 * GEO.EPS_SMALL or
|
||||
abs( ptPointToCheck:getZ() - b3Solid:getMax():getZ()) < 100 * GEO.EPS_SMALL or
|
||||
abs( ptPointToCheck:getZ() - b3Solid:getMin():getZ()) < 100 * GEO.EPS_SMALL then
|
||||
bOnBoxLimit = true
|
||||
end
|
||||
return bOnBoxLimit
|
||||
end
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function BeamLib.SetOpenSide( nPathInt, b3Solid)
|
||||
-- fondo tra loro le curve compatibili
|
||||
EgtMergeCurvesInCurveCompo( nPathInt)
|
||||
-- vettore indici lati aperti
|
||||
local vOpen = {}
|
||||
-- ciclo sulle curve elementari della composita
|
||||
local _, nNumEnt = EgtCurveDomain( nPathInt)
|
||||
for i = 0, nNumEnt - 1 do
|
||||
-- se segmento di retta
|
||||
if EgtCurveCompoRadius( nPathInt, i) == -1 then
|
||||
-- verifico se giace in uno dei piani limite del pezzo quindi se è un lato aperto
|
||||
local ptIni = EgtUP( nPathInt, i, GDB_RT.GLOB)
|
||||
local ptFin = EgtUP( nPathInt, i + 1, GDB_RT.GLOB)
|
||||
if BeamLib.IsPointOnBoxLimit( ptIni, b3Solid) and BeamLib.IsPointOnBoxLimit( ptFin, b3Solid) then
|
||||
-- aggiorno il vettore dei lati aperti
|
||||
table.insert( vOpen, i)
|
||||
end
|
||||
end
|
||||
end
|
||||
-- assegno gli indici dei lati aperti
|
||||
EgtSetInfo( nPathInt, 'OPEN', vOpen)
|
||||
return true
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function BeamLib.ConvertToClosedCurve( Proc, AuxId)
|
||||
local bCurveModified = false
|
||||
if not EgtCurveIsClosed( AuxId) then
|
||||
local NewId, nCount = EgtExtractSurfTmFacetLoops( Proc.id, 0, EgtGetParent( Proc.id))
|
||||
if NewId then
|
||||
-- elimino eventuali loop interni (non dovrebbero comunque esserci)
|
||||
for i = 1, nCount - 1 do
|
||||
EgtErase( NewId + i)
|
||||
end
|
||||
local vtExtr = EgtCurveExtrusion( AuxId, GDB_ID.ROOT)
|
||||
-- sostituisco il loop esterno alla curva originale
|
||||
EgtModifyCurveExtrusion( NewId, vtExtr, GDB_ID.ROOT)
|
||||
EgtRelocate( NewId, AuxId, GDB_IN.AFTER)
|
||||
EgtErase( AuxId)
|
||||
EgtChangeId( NewId, AuxId)
|
||||
bCurveModified = true
|
||||
-- sistemo i lati aperti
|
||||
local vFacAdj = EgtSurfTmFacetAdjacencies( Proc.id, 0)[1]
|
||||
if vFacAdj then
|
||||
local vOpen = {}
|
||||
for i = 1, #vFacAdj do
|
||||
if vFacAdj[i] < 0 then
|
||||
table.insert( vOpen, i - 1)
|
||||
end
|
||||
end
|
||||
EgtSetInfo( AuxId, 'OPEN', vOpen)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return true, bCurveModified
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
--- funzione che inverte il grezzo testa-coda
|
||||
function BeamLib.InvertRawPart( Part, nNumberOfRotations)
|
||||
-- se non si deve ruotare, si esce subito
|
||||
if nNumberOfRotations == 0 then
|
||||
return
|
||||
end
|
||||
-- box del solido
|
||||
local b3BoxPart = EgtGetBBoxGlob( EgtGetFirstNameInGroup( Part.id or GDB_ID.NULL, 'Box') or GDB_ID.NULL, GDB_BB.EXACT)
|
||||
-- box esatto del pezzo
|
||||
local b3BoxExact = EgtGetBBoxGlob( Part.id or GDB_ID.NULL, GDB_BB.EXACT)
|
||||
-- rotazione
|
||||
local dAngRot = nNumberOfRotations * 90
|
||||
EgtRotatePartInRawPart( Part.id, Z_AX(), dAngRot)
|
||||
-- correggo per eccentricità solido rispetto a geometria complessiva del pezzo
|
||||
local vtEccOri = b3BoxPart:getCenter() - b3BoxExact:getCenter()
|
||||
local vtEccRot = Vector3d( vtEccOri)
|
||||
vtEccRot:rotate( Z_AX(), dAngRot)
|
||||
EgtMovePartInRawPart( Part.id, ( vtEccOri - vtEccRot))
|
||||
-- si salva posizione corrente
|
||||
if Part.bIsInverted then
|
||||
Part.bIsInverted = false
|
||||
else
|
||||
Part.bIsInverted = true
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
--- funzione che ruota il grezzo
|
||||
function BeamLib.RotateRawPart( Part, nNumberOfRotations)
|
||||
-- sistemo numero rotazioni in caso sia negativa
|
||||
if nNumberOfRotations < 0 then
|
||||
nNumberOfRotations = nNumberOfRotations + 4
|
||||
end
|
||||
-- primo posizionamento
|
||||
if nNumberOfRotations == 0 then
|
||||
; -- il pezzo è già in posizione
|
||||
-- rotazione 90°
|
||||
elseif nNumberOfRotations == 1 then
|
||||
local dDeltaYZ = EgtGetRawPartBBox( Part.idRaw):getDimY() - EgtGetRawPartBBox( Part.idRaw):getDimZ()
|
||||
local vtMove = Vector3d( 0, dDeltaYZ / 2 * EgtIf( BeamData.RIGHT_LOAD, -1, 1), dDeltaYZ / 2)
|
||||
local bPreMove = dDeltaYZ < 0
|
||||
-- ruoto le travi della fase corrente
|
||||
local nRId = Part.idRaw
|
||||
while nRId do
|
||||
if bPreMove then EgtMoveRawPart( nRId, vtMove) end
|
||||
local bIsRotationOK = EgtRotateRawPart( nRId, X_AX(), EgtIf( BeamData.RIGHT_LOAD, -90, 90))
|
||||
if not bIsRotationOK then error( 'UNEXPECTED ERROR: rotation of the raw not executed') end
|
||||
if not bPreMove then EgtMoveRawPart( nRId, vtMove) end
|
||||
nRId = EgtGetNextRawPart( nRId)
|
||||
end
|
||||
-- rotazione 180°
|
||||
elseif nNumberOfRotations == 2 then
|
||||
-- ribalto le travi della fase corrente
|
||||
local nRId = Part.idRaw
|
||||
while nRId do
|
||||
EgtRotateRawPart( nRId, X_AX(), 180)
|
||||
nRId = EgtGetNextRawPart( nRId)
|
||||
end
|
||||
-- rotazione 270°
|
||||
elseif nNumberOfRotations == 3 then
|
||||
local dDeltaYZ = EgtGetRawPartBBox( Part.idRaw):getDimY() - EgtGetRawPartBBox( Part.idRaw):getDimZ()
|
||||
local vtMove = Vector3d( 0, dDeltaYZ / 2 * EgtIf( BeamData.RIGHT_LOAD, -1, 1), dDeltaYZ / 2)
|
||||
local bPreMove = dDeltaYZ < 0
|
||||
-- ruoto le travi della fase corrente
|
||||
local nRId = Part.idRaw
|
||||
while nRId do
|
||||
if bPreMove then EgtMoveRawPart( nRId, vtMove) end
|
||||
local bIsRotationOK = EgtRotateRawPart( nRId, X_AX(), EgtIf( BeamData.RIGHT_LOAD, 90, -90))
|
||||
if not bIsRotationOK then error( 'UNEXPECTED ERROR: rotation of the raw not executed') end
|
||||
if not bPreMove then EgtMoveRawPart( nRId, vtMove) end
|
||||
nRId = EgtGetNextRawPart( nRId)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function BeamLib.CreateOrEmptyAddGroup( PartId)
|
||||
-- recupero i dati del gruppo aggiuntivo
|
||||
local AddGrpId, sMchGrp = BeamLib.GetAddGroup( PartId)
|
||||
if not sMchGrp then
|
||||
return false
|
||||
end
|
||||
|
||||
-- se esiste, aggiorno riferimento al gruppo di lavoro e lo svuoto
|
||||
if AddGrpId then
|
||||
EgtSetInfo( AddGrpId, GDB_SI.MGRPONLY, EgtGetCurrMachGroup())
|
||||
return EgtEmptyGroup( AddGrpId)
|
||||
end
|
||||
-- altrimenti lo creo
|
||||
AddGrpId = EgtGroup( PartId or GDB_ID.NULL)
|
||||
if not AddGrpId then
|
||||
return false
|
||||
end
|
||||
-- assegno nome, flag di layer per gruppo di lavoro e colore
|
||||
EgtSetName( AddGrpId, sMchGrp)
|
||||
EgtSetInfo( AddGrpId, GDB_SI.MGRPONLY, EgtGetCurrMachGroup())
|
||||
EgtSetColor( AddGrpId, Color3d( 80, 160, 160, 25))
|
||||
|
||||
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
|
||||
local sMchGrp = EgtGetMachGroupName( EgtGetCurrMachGroup() or GDB_ID.NULL)
|
||||
if not sMchGrp then
|
||||
return nil, nil
|
||||
end
|
||||
|
||||
-- cerco il gruppo aggiuntivo omonimo nel pezzo e se esiste lo restituisco
|
||||
local AddGrpId = EgtGetFirstNameInGroup( PartId or GDB_ID.NULL, sMchGrp)
|
||||
|
||||
-- restituisco Id e Nome
|
||||
return AddGrpId, sMchGrp
|
||||
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.b3Part:getMax():getZ() - 500 * GEO.EPS_SMALL then
|
||||
vtFacesAffected.bTop = true
|
||||
end
|
||||
if Proc.b3Box:getMin():getZ() < Part.b3Part:getMin():getZ() + 500 * GEO.EPS_SMALL then
|
||||
vtFacesAffected.bBottom = true
|
||||
end
|
||||
if Proc.b3Box:getMin():getY() < Part.b3Part:getMin():getY() + 500 * GEO.EPS_SMALL then
|
||||
vtFacesAffected.bFront = true
|
||||
end
|
||||
if Proc.b3Box:getMax():getY() > Part.b3Part:getMax():getY() - 500 * GEO.EPS_SMALL then
|
||||
vtFacesAffected.bBack = true
|
||||
end
|
||||
if Proc.b3Box:getMin():getX() < Part.b3Part:getMin():getX() + 500 * GEO.EPS_SMALL then
|
||||
vtFacesAffected.bLeft = true
|
||||
end
|
||||
if Proc.b3Box:getMax():getX() > Part.b3Part:getMax():getX() - 500 * GEO.EPS_SMALL then
|
||||
vtFacesAffected.bRight = true
|
||||
end
|
||||
end
|
||||
|
||||
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)
|
||||
if vtNorm then
|
||||
vtMyRef = vtMyRef - ( vtMyRef * vtNorm) * vtNorm
|
||||
vtMyRef:normalize()
|
||||
end
|
||||
-- se prevalente una componente orizzontale (con piccolissimo vantaggio)
|
||||
if abs( vtMyRef:getX()) > 0.91 * abs( vtMyRef:getZ()) or abs( vtMyRef:getY()) > 0.91 * abs( vtMyRef:getZ()) then
|
||||
-- se prevale la componente destra/sinistra
|
||||
if abs( vtMyRef:getX()) > 0.95 * abs( vtMyRef:getY()) then
|
||||
if vtMyRef:getX() > -GEO.EPS_SMALL then
|
||||
return MCH_MILL_FU.ORTHO_LEFT
|
||||
else
|
||||
return MCH_MILL_FU.ORTHO_RIGHT
|
||||
end
|
||||
else
|
||||
if vtMyRef:getY() > -GEO.EPS_SMALL then
|
||||
return MCH_MILL_FU.ORTHO_FRONT
|
||||
else
|
||||
return MCH_MILL_FU.ORTHO_BACK
|
||||
end
|
||||
end
|
||||
-- altrimenti prevale la verticale
|
||||
else
|
||||
if vtMyRef:getZ() > -GEO.EPS_SMALL then
|
||||
return MCH_MILL_FU.ORTHO_DOWN
|
||||
else
|
||||
return MCH_MILL_FU.ORTHO_TOP
|
||||
end
|
||||
end
|
||||
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)
|
||||
if vtNorm then
|
||||
vtMyRef = vtMyRef - ( vtMyRef * vtNorm) * vtNorm
|
||||
vtMyRef:normalize()
|
||||
end
|
||||
-- se prevalente una componente orizzontale (con piccolissimo vantaggio)
|
||||
if abs( vtMyRef:getX()) > 0.95 * abs( vtMyRef:getZ()) or abs( vtMyRef:getY()) > 0.95 * abs( vtMyRef:getZ()) then
|
||||
if abs( vtMyRef:getX()) > 0.95 * abs( vtMyRef:getY()) then
|
||||
if vtMyRef:getX() > -GEO.EPS_SMALL then
|
||||
return MCH_MILL_FU.PARAL_LEFT
|
||||
else
|
||||
return MCH_MILL_FU.PARAL_RIGHT
|
||||
end
|
||||
else
|
||||
if vtMyRef:getY() > -GEO.EPS_SMALL then
|
||||
return MCH_MILL_FU.PARAL_FRONT
|
||||
else
|
||||
return MCH_MILL_FU.PARAL_BACK
|
||||
end
|
||||
end
|
||||
-- altrimenti prevale la verticale
|
||||
else
|
||||
if vtMyRef:getZ() > -GEO.EPS_SMALL then
|
||||
return MCH_MILL_FU.PARAL_DOWN
|
||||
else
|
||||
return MCH_MILL_FU.PARAL_TOP
|
||||
end
|
||||
end
|
||||
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)
|
||||
if not nAddGrpId then
|
||||
local nEdges = #(EgtSurfTmFacetAdjacencies( Proc.id, idFace)[1])
|
||||
return ( nEdges == 3)
|
||||
end
|
||||
local bResult = false
|
||||
|
||||
local nContourId, nContourCnt = EgtExtractSurfTmFacetLoops( Proc.id, idFace, nAddGrpId)
|
||||
if not nContourId then
|
||||
return false
|
||||
end
|
||||
EgtMergeCurvesInCurveCompo( nContourId)
|
||||
-- recupero il numero effettivo di lati
|
||||
local _, nEntityCount = EgtCurveDomain( nContourId)
|
||||
local nEdges = nEntityCount
|
||||
if nEntityCount and nEntityCount == 3 then
|
||||
bResult = true
|
||||
-- rimuovo i lati molto corti dal conteggio totale
|
||||
elseif nEntityCount then
|
||||
for i = 1, nEntityCount do
|
||||
local dLength = EgtCurveCompoLength( nContourId, i - 1)
|
||||
if dLength < 5 then nEdges = nEdges - 1 end
|
||||
end
|
||||
end
|
||||
if nEdges == 3 then bResult = true end
|
||||
-- cancello tutti i contorni appena creati
|
||||
EgtErase( EgtTableFill( nContourId, nContourCnt))
|
||||
|
||||
return bResult
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-- 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 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( 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 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)
|
||||
else
|
||||
if BeamData.C_SIMM then
|
||||
return EgtIf( vtN:getY() > 0, 'C=180', 'C=-180')
|
||||
else
|
||||
if nInd == 1 then
|
||||
return ''
|
||||
else
|
||||
return EgtIf( vtN:getY() > 0, 'C=180', 'C=-180')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function BeamLib.GetBlockedAxis( nToolIndex, sBlockedAxis, b3Raw, vtTool, vtOut)
|
||||
-- se presente funzione specifica nella macchina, la richiamo
|
||||
if BeamData.GetBlockedAxis then
|
||||
return BeamData.GetBlockedAxis( TOOLS[nToolIndex].sHead, TOOLS[nToolIndex].nTypeId, sBlockedAxis, b3Raw, vtTool, vtOut) or ''
|
||||
-- sezione mantenuta per retrocompatibilità con GetChainSawBlockedAxis
|
||||
elseif TOOLS[nToolIndex].nTypeId == MCH_TY.MORTISE_STD then
|
||||
local nInd = EgtIf( sBlockedAxis == 'parallel', 0, 1)
|
||||
if BeamData.GetChainSawBlockedAxis then
|
||||
return BeamData.GetChainSawBlockedAxis( nInd)
|
||||
else
|
||||
if nInd == 1 then
|
||||
return EgtIf( BeamData.C_SIMM, 'A=90', 'A=90')
|
||||
else
|
||||
return EgtIf( BeamData.C_SIMM, 'A=0', 'A=0')
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return ''
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function BeamLib.BinaryToDecimal( dNumber)
|
||||
local sNumberToConvert = tostring( dNumber)
|
||||
local dResult = 0
|
||||
local k = 0
|
||||
|
||||
for i = #sNumberToConvert, 1, -1 do
|
||||
k = k + 1
|
||||
local n = string.sub(sNumberToConvert, k, k)
|
||||
dResult = dResult + n*(2^(i-1))
|
||||
end
|
||||
|
||||
return dResult
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function BeamLib.DecimalToBinary( dNumber)
|
||||
local sNumberToConvert = tostring( dNumber)
|
||||
local n = sNumberToConvert
|
||||
local tmp = {}
|
||||
local sResult = ""
|
||||
|
||||
for i = sNumberToConvert, 0, -1 do
|
||||
local q = math.modf(n)
|
||||
n = n/2
|
||||
local b = q%2
|
||||
table.insert(tmp, b)
|
||||
|
||||
if (q == 1) then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
for i = #tmp, 1, -1 do
|
||||
sResult = sResult..tmp[i]
|
||||
end
|
||||
|
||||
return tonumber( sResult)
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function BeamLib.CalculateStringBinaryFormat( dNumber, CharNumber)
|
||||
local NumberString = tostring( dNumber)
|
||||
while #NumberString < CharNumber do
|
||||
NumberString = '0' .. NumberString
|
||||
end
|
||||
|
||||
return NumberString
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
--- copia una tabella lua in modo ricorsivo, ossia mantiene indipendenti anche tutte le sottotabelle
|
||||
--- ATTENZIONE: in caso di modifiche vanno gestiti anche i tipi custom; sarebbe meglio metterla nel LuaLibs
|
||||
function BeamLib.TableCopyDeep( OriginalTable)
|
||||
-- controllo se oggetto passato è valido, altrimenti errore. Non deve mai succedere
|
||||
if not OriginalTable then
|
||||
error( "TableCopyDeep : can't copy nil object")
|
||||
end
|
||||
local CopiedTable = {}
|
||||
for key, value in pairs( OriginalTable) do
|
||||
if type( value) == "table" then
|
||||
if isBBox3d( value) then
|
||||
CopiedTable[ key] = BBox3d( value)
|
||||
elseif isColor3d( value) then
|
||||
CopiedTable[ key] = Color3d( value)
|
||||
elseif isFrame3d( value) then
|
||||
CopiedTable[ key] = Frame3d( value)
|
||||
elseif isPoint3d( value) then
|
||||
CopiedTable[ key] = Point3d( value)
|
||||
elseif isQuaternion( value) then
|
||||
CopiedTable[ key] = Quaternion( value)
|
||||
elseif isVector3d( value) then
|
||||
CopiedTable[ key] = Vector3d( value)
|
||||
else
|
||||
CopiedTable[ key] = BeamLib.TableCopyDeep( value)
|
||||
end
|
||||
else
|
||||
CopiedTable[ key] = value
|
||||
end
|
||||
end
|
||||
|
||||
return CopiedTable
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function BeamLib.MergeTables( OriginalTable, InputTable)
|
||||
local result = {}
|
||||
for k, v in pairs( OriginalTable) do result[k] = v end
|
||||
for k, v in pairs( InputTable) do result[k] = v end
|
||||
return result
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function BeamLib.FindEdgeBestOrientedAsDirection( Edges, vtDirection)
|
||||
local BestEdge = {}
|
||||
|
||||
local dMaxDotProduct = GEO.INFINITO
|
||||
for i = 1, #Edges do
|
||||
local dCurrentDotProduct = ( Edges[i].vtN * vtDirection)
|
||||
if ( i == 1) or ( dCurrentDotProduct > dMaxDotProduct + 10 * GEO.EPS_SMALL) then
|
||||
dMaxDotProduct = dCurrentDotProduct
|
||||
BestEdge = Edges[i]
|
||||
end
|
||||
end
|
||||
|
||||
return BestEdge
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-- nNearSide : 3=Z+, -3=Z-
|
||||
function BeamLib.PutStartNearestToEdge( nCrvId, b3Raw, dMaxDist, nNearSide)
|
||||
-- verifico che la curva sia chiusa
|
||||
if not EgtCurveIsClosed( nCrvId) then return false end
|
||||
-- recupero il versore normale al piano di lavoro o estrusione
|
||||
local vtN = EgtCurveExtrusion( nCrvId, GDB_ID.ROOT)
|
||||
-- coefficienti per riportare la distanza nel piano di lavoro
|
||||
local dCoeffY = 0
|
||||
if abs( vtN:getY()) < 0.999 then dCoeffY= 1 / ( sqrt( 1 - vtN:getY() * vtN:getY())) end
|
||||
local dCoeffZ = 0
|
||||
if abs( vtN:getZ()) < 0.999 then dCoeffZ = 1 / ( sqrt( 1 - vtN:getZ() * vtN:getZ())) end
|
||||
-- cerco l'estremo più vicino al box e lo imposto come inizio (se da sotto escludo Zmax e viceversa)
|
||||
local dUopt = 0
|
||||
local dDopt = GEO.INFINITO
|
||||
local dSopt = GEO.INFINITO
|
||||
local dUi, dUf = EgtCurveDomain( nCrvId)
|
||||
for dU = dUi, dUf, 0.5 do
|
||||
local ptP = EgtUP( nCrvId, dU, GDB_ID.ROOT)
|
||||
local vtDp = EgtUV( nCrvId, dU, -1, GDB_ID.ROOT)
|
||||
local vtDs = EgtUV( nCrvId, dU, 1, GDB_ID.ROOT)
|
||||
local bTg = ( vtDp and vtDs and vtDp * vtDs > 0.96)
|
||||
if ptP and bTg then
|
||||
local vtMin = ptP - b3Raw:getMin()
|
||||
local vtMax = ptP - b3Raw:getMax()
|
||||
local dD = abs( vtMin:getY()) * dCoeffY
|
||||
dD = min( abs( vtMax:getY()) * dCoeffY, dD)
|
||||
dD = min( abs( vtMin:getZ()) * dCoeffZ, dD)
|
||||
dD = min( abs( vtMax:getZ()) * dCoeffZ, dD)
|
||||
local dS
|
||||
if nNearSide == -3 then
|
||||
dS = abs( vtMin:getZ() * dCoeffZ)
|
||||
else --nNearSide == 3
|
||||
dS = abs( vtMax:getZ() * dCoeffZ)
|
||||
end
|
||||
if dD < dMaxDist and dS < dSopt + GEO.EPS_SMALL then
|
||||
dUopt = dU
|
||||
dDopt = dD
|
||||
dSopt = dS
|
||||
end
|
||||
end
|
||||
end
|
||||
if abs( dUopt - dUi) > GEO.EPS_ZERO and abs( dUopt - dUf) > GEO.EPS_ZERO then
|
||||
-- TODO. Non utilizzare la funzione EgtChangeClosedCurveStart perchè cambia proprietà della geometria.
|
||||
-- dopo aver trovato l'entità di partenza, calcolare l'offset da aggiungere alla lavorazione per poter cominciare da questa entità (senza modifica della geometria)
|
||||
EgtChangeClosedCurveStart( nCrvId, dUopt)
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function BeamLib.ImportFileJSON( sFileToImport)
|
||||
local JSON = require( 'JSON')
|
||||
|
||||
local function readAll( sFileToImport)
|
||||
local f = io.open( sFileToImport, "rb")
|
||||
local content = f:read( "*all")
|
||||
f:close()
|
||||
return content
|
||||
end
|
||||
|
||||
local content = readAll( sFileToImport)
|
||||
return JSON:decode( content)
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function BeamLib.GetStrategiesFromList( Proc, StrategyList)
|
||||
-- cerco tra le feature
|
||||
for i = 1, #StrategyList.FEATURE do
|
||||
-- se trovo la feature
|
||||
if Proc.nPrc == StrategyList.FEATURE[i].nPrc then
|
||||
local bGroupIsCompatible = false
|
||||
-- nel JSON il gruppo è sempre 0/1, mente da BTL possono arrivare altri valori.
|
||||
if StrategyList.FEATURE[i].nGrp == 0 then
|
||||
if Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4 then
|
||||
bGroupIsCompatible = true
|
||||
end
|
||||
elseif StrategyList.FEATURE[i].nGrp == 1 then
|
||||
if Proc.nGrp == 1 or Proc.nGrp == 2 then
|
||||
bGroupIsCompatible = true
|
||||
end
|
||||
end
|
||||
|
||||
-- si controlla gruppo
|
||||
if bGroupIsCompatible then
|
||||
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
|
||||
@@ -0,0 +1,689 @@
|
||||
-- FaceData.lua by Egalware s.r.l. 2024/04/18
|
||||
-- Libreria lettura o calcolo dati e proprietà delle facce di una trimesh
|
||||
-- 2024/04/02 PRIMA VERSIONE CALCOLO LAVORAZIONI CON STRATEGIE
|
||||
|
||||
-- Tabella per definizione modulo
|
||||
local FaceData = {}
|
||||
|
||||
-- carico librerie
|
||||
local BeamLib = require( 'BeamLib')
|
||||
local Logs = require( 'Logs')
|
||||
|
||||
|
||||
---------------------------------------------------------------------
|
||||
-- restituisce la matrice delle adiacenze di Proc dove i e j sono le facce e a(ij) è l'angolo tra di esse; 0 se nessuna adiacenza
|
||||
function FaceData.GetAdjacencyMatrix( Proc)
|
||||
local vAdj = {}
|
||||
|
||||
-- essendo la matrice simmetrica a diagonale nulla, ne calcolo solo la metà superiore
|
||||
for i = 1, Proc.nFct do
|
||||
vAdj[i] = {}
|
||||
for j = i + 1, Proc.nFct do
|
||||
_, _, _, vAdj[i][j] = EgtSurfTmFacetsContact( Proc.id, i - 1, j - 1, GDB_ID.ROOT)
|
||||
if not vAdj[i][j] then
|
||||
vAdj[i][j] = 0
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- riempio di conseguenza il resto della matrice
|
||||
for i = 1, Proc.nFct do
|
||||
vAdj[i][i] = 0
|
||||
for j = i + 1, Proc.nFct do
|
||||
vAdj[j][i] = vAdj[i][j]
|
||||
end
|
||||
|
||||
end
|
||||
return vAdj
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------
|
||||
-- restituisce un vettore con gli indici (0 based) delle facce triangolari (o quasi) di Proc
|
||||
function FaceData.GetTriangularFaces( Proc)
|
||||
-- se la feature ha una sola faccia, esco subito
|
||||
if Proc.nFct <= 1 then
|
||||
return
|
||||
end
|
||||
|
||||
local vTriangularFaces = {}
|
||||
|
||||
for i = 1, Proc.nFct do
|
||||
if BeamLib.Is3EdgesApprox( Proc, i - 1) then
|
||||
table.insert( vTriangularFaces, i - 1)
|
||||
end
|
||||
|
||||
end
|
||||
return vTriangularFaces
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function GetNotAdjacentFaces( Proc, idFace)
|
||||
local NotAdjacentFaces = {}
|
||||
|
||||
for i = 1, Proc.nFct do
|
||||
if Proc.Faces[i].id ~= idFace then
|
||||
local bIsAdjacent = false
|
||||
for j = 1, #Proc.Faces[idFace + 1].Adjacencies do
|
||||
if Proc.Faces[i].id == Proc.Faces[idFace + 1].Adjacencies[j] then
|
||||
bIsAdjacent = true
|
||||
end
|
||||
end
|
||||
if not bIsAdjacent then
|
||||
table.insert( NotAdjacentFaces, Proc.Faces[i])
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return NotAdjacentFaces
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------
|
||||
-- restituisce una tabella che correla numero di adiacenze e id delle facce con quello stesso numero di adiacenze
|
||||
function FaceData.GetFacesByAdjacencyNumber( Proc)
|
||||
-- se la feature ha una sola faccia, esco subito
|
||||
if Proc.nFct <= 1 then
|
||||
return {}
|
||||
end
|
||||
|
||||
local FacesByAdjacencyNumber = {}
|
||||
|
||||
for i = 1, 10 do
|
||||
FacesByAdjacencyNumber[i] = {}
|
||||
end
|
||||
for i = 1, Proc.nFct do
|
||||
table.insert( FacesByAdjacencyNumber[#Proc.Faces[i].Adjacencies], Proc.Faces[i])
|
||||
end
|
||||
|
||||
return FacesByAdjacencyNumber
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
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
|
||||
else
|
||||
vAdj = FaceData.GetAdjacencyMatrix( Proc)
|
||||
end
|
||||
|
||||
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 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.b3Part, true, GDB_ID.ROOT)
|
||||
-- TODO qui sarebbe meglio l'area vera e non quella del rettangolo minimo
|
||||
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, Edges = FaceData.GetEdgesInfo( Proc, i - 1)
|
||||
Faces[i].bIsOkForMachining = nFaceType < 1
|
||||
Faces[i].Edges = Edges
|
||||
|
||||
-- TODO valutare se fare un output unico alla fine o gestire log in altro modo
|
||||
EgtOutLog( 'Facet ' .. Faces[i].id .. ' of ' .. Proc.nFct - 1)
|
||||
EgtOutLog( ' vtN: ' .. tostring( Faces[i].vtN))
|
||||
|
||||
-- adiacenze della faccia
|
||||
-- TODO chiamarle in modo che si capisca che sono solo gli id e non l'intero oggetto faccia
|
||||
Faces[i].Adjacencies = {}
|
||||
for j = 1, Proc.nFct do
|
||||
if vAdj[i][j] and vAdj[i][j] ~= 0 and ( i ~= j) then
|
||||
table.insert( Faces[i].Adjacencies, j - 1)
|
||||
if EgtGetDebugLevel() >= 3 then
|
||||
EgtOutLog( ' Adjacent to facet: ' .. j - 1)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
EgtOutLog( '---Faces END---')
|
||||
return Faces
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function FaceData.IsFaceRectangular( Proc, idFace)
|
||||
local nAddGrpId = BeamLib.GetAddGroup( Proc.idPart)
|
||||
local nContourId, nContourCnt = EgtExtractSurfTmFacetLoops( Proc.id, idFace, nAddGrpId)
|
||||
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)
|
||||
or ( Proc.nFct == 1 ) or Proc.Topology.sName == 'Bevel-2-Blind') then
|
||||
|
||||
error( 'GetTunnelFaces : Topology not implemented')
|
||||
end
|
||||
|
||||
-- direzione del tunnel
|
||||
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)
|
||||
local b3Tunnel = EgtGetBBoxRef( Proc.id, GDB_BB.STANDARD, frTunnel)
|
||||
local ptTunnelCenter = b3Tunnel:getCenter()
|
||||
ptTunnelCenter:toGlob( frTunnel)
|
||||
|
||||
-- recupero gruppo per geometria addizionale
|
||||
local nAddGrpId = BeamLib.GetAddGroup( Proc.idPart)
|
||||
if not nAddGrpId then
|
||||
-- TODO gestire meglio questo errore. Non conviene creare e verificare all'inizio se il gruppo esiste?
|
||||
EgtOutLog( 'Error : missing AddGroup')
|
||||
return TunnelAddedFaces
|
||||
end
|
||||
|
||||
-- faccia centrale
|
||||
local nMiddleTmId = EgtSurfTmPlaneInBBox( nAddGrpId, ptTunnelCenter, vtTunnelDirection, Part.b3Part, GDB_ID.ROOT)
|
||||
-- TODO se non si riesce a costruire la faccia bisogna dare errore o semplicemente non ritornarla??
|
||||
for i = 1, Proc.nFct do
|
||||
EgtCutSurfTmPlane( nMiddleTmId, Proc.Faces[i].ptCenter, -Proc.Faces[i].vtN, false, GDB_ID.ROOT)
|
||||
end
|
||||
|
||||
-- facce laterali
|
||||
local nLateralTmId = EgtCopyGlob( Proc.id, nAddGrpId) or GDB_ID.NULL
|
||||
EgtCutSurfTmPlane( nLateralTmId, ptTunnelCenter, -vtTunnelDirection, false, GDB_ID.ROOT)
|
||||
|
||||
-- unione facce
|
||||
-- TODO cambiare nome alla trimesh?? non contiene più solamente la faccia di mezzo
|
||||
TunnelAddedFaces.MiddleFaceTm = {}
|
||||
TunnelAddedFaces.MiddleFaceTm.id = EgtSurfTmBySewing( nAddGrpId, { nMiddleTmId, nLateralTmId}, true)
|
||||
|
||||
-- TODO c'è un modo più elegante per raccogliere le informazioni delle facce aggiunte
|
||||
TunnelAddedFaces.MiddleFaceTm.sType = 'Tunnel'
|
||||
TunnelAddedFaces.MiddleFaceTm.nFct = EgtSurfTmFacetCount( TunnelAddedFaces.MiddleFaceTm.id)
|
||||
TunnelAddedFaces.MiddleFaceTm.Faces = FaceData.GetFacesInfo( TunnelAddedFaces.MiddleFaceTm, Part)
|
||||
|
||||
return TunnelAddedFaces
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function GetBottomFaces( Proc)
|
||||
local BottomFaces = {}
|
||||
|
||||
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'
|
||||
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
|
||||
BottomFaces = FacesByAdjacencyNumber[ Proc.nFct - 1]
|
||||
-- si rimuovono le facce non adatte ad essere lavorate
|
||||
local nBottomFaces = #BottomFaces
|
||||
local nCurrentFace = 1
|
||||
while nCurrentFace <= nBottomFaces do
|
||||
if not BottomFaces[nCurrentFace].bIsOkForMachining then
|
||||
table.remove( BottomFaces, nCurrentFace)
|
||||
nBottomFaces = nBottomFaces - 1
|
||||
end
|
||||
nCurrentFace = nCurrentFace + 1
|
||||
end
|
||||
-- la BottomFace 1 è sempre quella con minor elevazione
|
||||
table.sort( BottomFaces, function (a, b) return a.dElevation < b.dElevation end)
|
||||
end
|
||||
|
||||
if #BottomFaces == 0 then
|
||||
return nil
|
||||
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 EdgesSorted = {}
|
||||
for i = 1, #BottomFaces[1].Edges do
|
||||
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
|
||||
|
||||
for i = 1, #BottomFaces[1].Edges do
|
||||
local nPreviousEdgeIndex = i - 1
|
||||
if i == 1 then
|
||||
nPreviousEdgeIndex = #BottomFaces[1].Edges
|
||||
end
|
||||
local nNextEdgeIndex = i + 1
|
||||
if i == #BottomFaces[1].Edges then
|
||||
nNextEdgeIndex = 1
|
||||
end
|
||||
|
||||
local CurrentEdge = {}
|
||||
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 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
|
||||
|
||||
return BottomFaces
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function GetLongFaces( Proc, MainFaces)
|
||||
local LongFaces = {}
|
||||
|
||||
if Proc.nFct > 5 then
|
||||
error( 'GetLongFaces : Topology not implemented')
|
||||
elseif Proc.nFct == 1 then
|
||||
return {}
|
||||
end
|
||||
|
||||
local BottomFace
|
||||
local BottomFaces = MainFaces.BottomFaces or GetBottomFaces( Proc)
|
||||
if BottomFaces and #BottomFaces > 0 then
|
||||
BottomFace = BottomFaces[1]
|
||||
end
|
||||
|
||||
local idFirstLongFace = GDB_ID.NULL
|
||||
local idSecondLongFace = GDB_ID.NULL
|
||||
if not BottomFace then
|
||||
local FacesSortedByGreatestArea = {}
|
||||
for i = 1, Proc.nFct do
|
||||
FacesSortedByGreatestArea[i] = {}
|
||||
FacesSortedByGreatestArea[i].id = Proc.Faces[i].id
|
||||
FacesSortedByGreatestArea[i].dArea = Proc.Faces[i].dArea
|
||||
end
|
||||
table.sort( FacesSortedByGreatestArea, function (a, b) return a.dArea > b.dArea end)
|
||||
idFirstLongFace = FacesSortedByGreatestArea[1].id
|
||||
local FacesNotAdjacent = GetNotAdjacentFaces( Proc, idFirstLongFace)
|
||||
idSecondLongFace = FacesNotAdjacent[1].id
|
||||
elseif BottomFace.MainEdges then
|
||||
if BottomFace.MainEdges.LongEdges[1].idAdjacentFace > -1 then
|
||||
idFirstLongFace = BottomFace.MainEdges.LongEdges[1].idAdjacentFace
|
||||
end
|
||||
if BottomFace.MainEdges.LongEdges[2].idAdjacentFace > -1 then
|
||||
idSecondLongFace = BottomFace.MainEdges.LongEdges[2].idAdjacentFace
|
||||
end
|
||||
end
|
||||
if idFirstLongFace > -1 and Proc.Faces[idFirstLongFace + 1].bIsOkForMachining then
|
||||
table.insert( LongFaces, Proc.Faces[idFirstLongFace + 1])
|
||||
end
|
||||
if idSecondLongFace > -1 and Proc.Faces[idSecondLongFace + 1].bIsOkForMachining then
|
||||
table.insert( LongFaces, Proc.Faces[idSecondLongFace + 1])
|
||||
end
|
||||
|
||||
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 = {}
|
||||
|
||||
for j = 1, #LongFaces[i].Edges do
|
||||
local nPreviousEdgeIndex = j - 1
|
||||
if j == 1 then
|
||||
nPreviousEdgeIndex = #LongFaces[1].Edges
|
||||
end
|
||||
local nNextEdgeIndex = j + 1
|
||||
if j == #LongFaces[i].Edges then
|
||||
nNextEdgeIndex = 1
|
||||
end
|
||||
|
||||
local CurrentEdge = {}
|
||||
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
|
||||
table.insert( LongFaces[i].MainEdges.SideEdges, CurrentEdge)
|
||||
LongFaces[i].MainEdges.SideEdges[#LongFaces[i].MainEdges.SideEdges].sType = 'Side'
|
||||
else
|
||||
table.insert( LongFaces[i].MainEdges.OppositeEdges, CurrentEdge)
|
||||
LongFaces[i].MainEdges.OppositeEdges[#LongFaces[i].MainEdges.OppositeEdges].sType = 'Opposite'
|
||||
end
|
||||
else
|
||||
if CurrentEdge.idAdjacentFace == BottomFace.id then
|
||||
LongFaces[i].MainEdges.BottomEdge = CurrentEdge
|
||||
LongFaces[i].MainEdges.BottomEdge.sType = 'Bottom'
|
||||
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].idAdjacentFace == BottomFace.id then
|
||||
LongFaces[i].MainEdges.SideEdges[2] = CurrentEdge
|
||||
LongFaces[i].MainEdges.SideEdges[2].sType = 'Side'
|
||||
else
|
||||
table.insert( LongFaces[i].MainEdges.OppositeEdges, CurrentEdge)
|
||||
LongFaces[i].MainEdges.OppositeEdges[#LongFaces[i].MainEdges.OppositeEdges].sType = 'Opposite'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return LongFaces
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function GetSideFaces( Proc, MainFaces)
|
||||
local SideFaces = {}
|
||||
|
||||
if Proc.nFct > 5 then
|
||||
error( 'GetSideFaces : Topology not implemented')
|
||||
elseif Proc.nFct == 1 then
|
||||
return {}
|
||||
end
|
||||
|
||||
local BottomFace
|
||||
local BottomFaces = MainFaces.BottomFaces or GetBottomFaces( Proc)
|
||||
if BottomFaces and #BottomFaces > 0 then
|
||||
BottomFace = BottomFaces[1]
|
||||
end
|
||||
local LongFaces = MainFaces.LongFaces or GetLongFaces( Proc, MainFaces)
|
||||
|
||||
local idFirstSideFace = GDB_ID.NULL
|
||||
local idSecondSideFace = GDB_ID.NULL
|
||||
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])
|
||||
SideFaces[#SideFaces].sType = 'Side'
|
||||
end
|
||||
if idSecondSideFace > -1 and Proc.Faces[idSecondSideFace + 1].bIsOkForMachining then
|
||||
table.insert( SideFaces, Proc.Faces[idSecondSideFace + 1])
|
||||
SideFaces[#SideFaces].sType = 'Side'
|
||||
end
|
||||
|
||||
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 = {}
|
||||
|
||||
for j = 1, #SideFaces[i].Edges do
|
||||
local nPreviousEdgeIndex = j - 1
|
||||
if j == 1 then
|
||||
nPreviousEdgeIndex = #SideFaces[1].Edges
|
||||
end
|
||||
local nNextEdgeIndex = j + 1
|
||||
if j == #SideFaces[i].Edges then
|
||||
nNextEdgeIndex = 1
|
||||
end
|
||||
|
||||
local CurrentEdge = {}
|
||||
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
|
||||
table.insert( SideFaces[i].MainEdges.LongEdges, CurrentEdge)
|
||||
else
|
||||
table.insert( SideFaces[i].MainEdges.OppositeEdges, CurrentEdge)
|
||||
end
|
||||
else
|
||||
if CurrentEdge.idAdjacentFace == BottomFace.id then
|
||||
SideFaces[i].MainEdges.BottomEdge = CurrentEdge
|
||||
SideFaces[i].MainEdges.BottomEdge.sType = 'Bottom'
|
||||
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].idAdjacentFace == BottomFace.id then
|
||||
SideFaces[i].MainEdges.LongEdges[2] = CurrentEdge
|
||||
SideFaces[i].MainEdges.LongEdges[2].sType = 'Long'
|
||||
else
|
||||
table.insert( SideFaces[i].MainEdges.OppositeEdges, CurrentEdge)
|
||||
SideFaces[i].MainEdges.OppositeEdges[#SideFaces[i].MainEdges.OppositeEdges].sType = 'Opposite'
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return SideFaces
|
||||
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' or Proc.Topology.sFamily == 'Bevel' or
|
||||
Proc.Topology.sFamily == 'DoubleBevel' or Proc.Topology.sFamily == 'Cut' or Proc.Topology.sFamily == 'HeadCut' or Proc.Topology.sFamily == 'TailCut' then
|
||||
|
||||
if ( Proc.Topology.bIsThrough and Proc.Topology.bAllRightAngles and Proc.nFct < 5)
|
||||
or ( Proc.nFct == 1) or Proc.Topology.sName == 'Bevel-2-Blind' then
|
||||
|
||||
MainFaces.TunnelAddedFaces = GetTunnelFaces( Proc, Part)
|
||||
end
|
||||
|
||||
MainFaces.BottomFaces = GetBottomFaces( Proc)
|
||||
MainFaces.LongFaces = GetLongFaces( Proc, MainFaces)
|
||||
MainFaces.SideFaces = GetSideFaces( Proc, MainFaces)
|
||||
|
||||
-- scrivo informazioni delle facce nel log
|
||||
if EgtGetDebugLevel() >= 3 then
|
||||
Logs.WriteMainFacesLog( Proc, MainFaces)
|
||||
end
|
||||
else
|
||||
MainFaces = nil
|
||||
EgtOutLog( '---MainFaces NOT NEEDED---')
|
||||
end
|
||||
|
||||
EgtOutLog( '---MainFaces END---')
|
||||
return MainFaces
|
||||
end
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
return FaceData
|
||||
@@ -0,0 +1,275 @@
|
||||
-- Identity.lua by Egalware s.r.l. 2024/04/02
|
||||
-- Libreria Riconoscimento della feature
|
||||
-- 2024/04/02 PRIMA VERSIONE CALCOLO LAVORAZIONI CON STRATEGIE
|
||||
|
||||
-- Tabella per definizione modulo
|
||||
local Identity = {}
|
||||
|
||||
---------------------------------------------------------------------
|
||||
------------------------ SPECIAL TOPOLOGY -------------------------
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Head Cut
|
||||
function Identity.IsHeadCut( Proc)
|
||||
return Identity.IsCut( Proc) and Proc.Topology.sName == 'HeadCut'
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Tail Cut
|
||||
function Identity.IsTailCut( Proc)
|
||||
return Identity.IsCut( Proc) and Proc.Topology.sName == 'TailCut'
|
||||
end
|
||||
|
||||
---------------------------------------------------------------------
|
||||
------------------------ STANDARD FEATURES ------------------------
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Cut
|
||||
function Identity.IsCut( Proc)
|
||||
return ( ( Proc.nGrp == 1 or Proc.nGrp == 2) and Proc.nPrc == 10)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Longitudinal Cut
|
||||
function Identity.IsLongitudinalCut( Proc)
|
||||
return (( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 10)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Double Cut
|
||||
function Identity.IsDoubleCut( Proc)
|
||||
return ( ( Proc.nGrp == 1 or Proc.nGrp == 2) and Proc.nPrc == 11)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Ridge or Valley Cut
|
||||
function Identity.IsDoubleLongitudinalCut( Proc)
|
||||
return ( Proc.nGrp == 0 and Proc.nPrc == 12)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Saw Cut
|
||||
function Identity.IsSawCut( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 13)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Slot
|
||||
function Identity.IsSlot( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 16)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Front Slot
|
||||
function Identity.IsFrontSlot( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 17)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Birds Mouth
|
||||
function Identity.IsBirdsMouth( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 20)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Hip or Valley Rafter Notch
|
||||
function Identity.IsHipValleyRafterNotch( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 25)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Ridge Lap
|
||||
function Identity.IsRidgeLap( Proc)
|
||||
return ( ( Proc.nGrp == 1 or Proc.nGrp == 2) and Proc.nPrc == 30)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Lap Joint
|
||||
function Identity.IsLapJoint( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 30)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Notch/Rabbet
|
||||
function Identity.IsNotchRabbet( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 32)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Block Haus
|
||||
function Identity.IsBlockHaus( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 33)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Notch
|
||||
function Identity.IsNotch( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 34)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : French Ridge Lap
|
||||
function Identity.IsFrenchRidgeLap( Proc)
|
||||
return ( ( Proc.nGrp == 1 or Proc.nGrp == 2) and Proc.nPrc == 35)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Chamfer
|
||||
function Identity.IsChamfer( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 36)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Block Haus Half Lap
|
||||
function Identity.IsHalfBlockHaus( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 37)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Block Haus Front
|
||||
function Identity.IsFrontBlockHaus( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 38)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Pocket
|
||||
function Identity.IsPocket( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 39)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Drilling
|
||||
function Identity.IsDrill( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 40)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Tenon
|
||||
function Identity.IsTenon( Proc)
|
||||
return ( ( Proc.nGrp == 1 or Proc.nGrp == 2) and Proc.nPrc == 50)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Mortise
|
||||
function Identity.IsMortise( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 50)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Front Mortise
|
||||
function Identity.IsFrontMortise( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 51)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : House
|
||||
function Identity.IsHouse( Proc)
|
||||
return ( ( Proc.nGrp == 1 or Proc.nGrp == 2) and Proc.nPrc == 52)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : House Mortise
|
||||
function Identity.IsHouseMortise( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 53)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Dovetail Tenon
|
||||
function Identity.IsDovetailTenon( Proc)
|
||||
return ( ( Proc.nGrp == 1 or Proc.nGrp == 2) and Proc.nPrc == 55)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Dovetail Mortise
|
||||
function Identity.IsDovetailMortise( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 55)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Dovetail Mortise Front
|
||||
function Identity.IsFrontDovetailMortise( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 56)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Marking
|
||||
function Identity.IsMarking( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 60)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Text
|
||||
function Identity.IsText( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 61)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Scarf Simple
|
||||
function Identity.IsScarfSimple( Proc)
|
||||
return ( ( Proc.nGrp == 1 or Proc.nGrp == 2) and Proc.nPrc == 70)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Scarf Joint
|
||||
function Identity.IsScarfJoint( Proc)
|
||||
return ( ( Proc.nGrp == 1 or Proc.nGrp == 2) and Proc.nPrc == 71)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Step Joint
|
||||
function Identity.IsStepJoint( Proc)
|
||||
return ( ( Proc.nGrp == 1 or Proc.nGrp == 2) and Proc.nPrc == 80)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Step Joint Notch
|
||||
function Identity.IsStepJointNotch( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 80)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Planing
|
||||
function Identity.IsPlaning( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 90)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Front Profile
|
||||
function Identity.IsFrontProfile( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 100)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Head Concave Profile
|
||||
function Identity.IsHeadConcaveProfile( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 101)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Head Convex Profile
|
||||
function Identity.IsHeadConvexProfile( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 102)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Head Cambered Profile
|
||||
function Identity.IsHeadCamberedProfile( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 103)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Round Arch
|
||||
function Identity.IsRoundArch( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 104)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Head Profile
|
||||
function Identity.IsHeadProfile( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 106)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Sphere
|
||||
function Identity.IsSphere( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 107)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Triangle Cut
|
||||
function Identity.IsTriangleCut( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 120)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : TyroleanDovetail
|
||||
function Identity.IsTyroleanDovetail( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 1 or Proc.nGrp == 2 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 136)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Dovetail
|
||||
function Identity.IsDovetail( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 1 or Proc.nGrp == 2 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 138)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Free Contour
|
||||
function Identity.IsFreeContour( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 250)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Outline
|
||||
function Identity.IsOutline( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 251)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Aperture
|
||||
function Identity.IsAperture( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 252)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature : Variant
|
||||
function Identity.IsVariant( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 1 or Proc.nGrp == 2 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 900)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
-- Feature Decor
|
||||
function Identity.IsDecor( Proc)
|
||||
return ( ( Proc.nGrp == 0 or Proc.nGrp == 3 or Proc.nGrp == 4) and Proc.nPrc == 959)
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
|
||||
return Identity
|
||||
@@ -0,0 +1,198 @@
|
||||
-- Logs.lua by Egalware s.r.l. 2024/11/20
|
||||
-- Libreria per logs vari
|
||||
|
||||
-- Tabella per definizione modulo
|
||||
local Logs = {}
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function Logs.WriteFeaturesLog( ProcessingsOnPart, PartInfo)
|
||||
|
||||
local nCycles = 1
|
||||
local nOffsetIndex = 0
|
||||
if #ProcessingsOnPart.Rotation > 4 then
|
||||
nCycles = 2
|
||||
end
|
||||
|
||||
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
|
||||
|
||||
-- per ogni feature
|
||||
for ProcLog = 1, nProcessingsNumber do
|
||||
-- ricavo il massimo numero di strategie per feature
|
||||
local nMaxStrategiesPerFeature = 0
|
||||
for nRotLog = nStartIndex, nEndIndex do
|
||||
if PartInfo.CombinationList.Rotations[nRotLog-nOffsetIndex] == 1 and ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies then
|
||||
nMaxStrategiesPerFeature = max( nMaxStrategiesPerFeature, #ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies)
|
||||
end
|
||||
end
|
||||
|
||||
-- ciclo su tutte le strategie
|
||||
for nCountStrategies = 1, nMaxStrategiesPerFeature do
|
||||
local sLogLine = ''
|
||||
-- al primo ciclo scrivo ID feature
|
||||
if nCountStrategies == 1 then
|
||||
sLogLine = ' ' .. tostring( ProcessingsOnPart.Rotation[nFirstAvailableRotation][ProcLog].id)
|
||||
while string.len( sLogLine) <= 20 do
|
||||
sLogLine = sLogLine .. ' '
|
||||
end
|
||||
sLogLine = sLogLine .. '|'
|
||||
else
|
||||
sLogLine = ' |'
|
||||
end
|
||||
|
||||
for nRotLog = nStartIndex, nEndIndex do
|
||||
-- se rotazione abilitata
|
||||
if PartInfo.CombinationList.Rotations[nRotLog-nOffsetIndex] == 1 then
|
||||
-- se ci sono strategie
|
||||
if ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies and ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies] then
|
||||
-- se la strategia è stat processata e ha un risultato
|
||||
if ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies].Result then
|
||||
-- leggo lo stato della strategia per aggiungere un suffisso
|
||||
local sStatusStrategy = ' '
|
||||
local sIndexes, sRating = '', ''
|
||||
if not ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies].Result.sStatus or
|
||||
ProcessingsOnPart.Rotation[nRotLog][ProcLog].AvailableStrategies[nCountStrategies].Result.sStatus == 'Not-Applicable' then
|
||||
sStatusStrategy = 'N'
|
||||
sRating = '----'
|
||||
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
|
||||
else
|
||||
sLogLine = sLogLine .. ' |'
|
||||
end
|
||||
-- rotazione non presa in considerazione
|
||||
else
|
||||
if nCountStrategies == 1 then
|
||||
sLogLine = sLogLine .. ' ---------- |'
|
||||
else
|
||||
sLogLine = sLogLine .. ' |'
|
||||
end
|
||||
end
|
||||
end
|
||||
EgtOutLog( sLogLine)
|
||||
end
|
||||
|
||||
end
|
||||
EgtOutLog( '----------------------------------------------------------------------------------------------------------')
|
||||
nOffsetIndex = 4
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function Logs.WriteCombinationLog( CombinationsList, BestCombination)
|
||||
EgtOutLog( ' === === === === === === === === === === COMBINATIONS === === === === === === ')
|
||||
EgtOutLog( ' COMBI (UNL) POS | RATING | COMPLETE | NO COMPL | NO EXEC | ROTATE |')
|
||||
EgtOutLog( '------------------------------------------------------------------------------')
|
||||
|
||||
for CombiLog = 1, #CombinationsList do
|
||||
local sPartPosition = EgtIf( CombinationsList[CombiLog].bPartInCombiIsInverted, 'INV', 'ORI')
|
||||
local sLogLine = ' ' .. CombinationsList[CombiLog].sBitIndexCombination .. ' (' .. CombinationsList[CombiLog].nUnloadPos .. ') ' .. sPartPosition .. ' |'
|
||||
-- rating
|
||||
local sOtherField = EgtNumToString( CombinationsList[CombiLog].dTotalRating, - 3) .. ' |'
|
||||
while string.len( sOtherField) <= 15 do
|
||||
sOtherField = ' ' .. sOtherField
|
||||
end
|
||||
sLogLine = sLogLine .. sOtherField
|
||||
-- completed
|
||||
sOtherField = tostring( CombinationsList[CombiLog].nComplete) .. ' |'
|
||||
while string.len( sOtherField) <= 11 do
|
||||
sOtherField = ' ' .. sOtherField
|
||||
end
|
||||
sLogLine = sLogLine .. sOtherField
|
||||
-- not completed
|
||||
sOtherField = tostring( CombinationsList[CombiLog].nNotComplete) .. ' |'
|
||||
while string.len( sOtherField) <= 11 do
|
||||
sOtherField = ' ' .. sOtherField
|
||||
end
|
||||
sLogLine = sLogLine .. sOtherField
|
||||
-- not executed
|
||||
sOtherField = tostring( CombinationsList[CombiLog].nNotExecute) .. ' |'
|
||||
while string.len( sOtherField) <= 11 do
|
||||
sOtherField = ' ' .. sOtherField
|
||||
end
|
||||
sLogLine = sLogLine .. sOtherField
|
||||
-- rotations
|
||||
sOtherField = tostring( CombinationsList[CombiLog].nRotations) .. ' |'
|
||||
while string.len( sOtherField) <= 11 do
|
||||
sOtherField = ' ' .. sOtherField
|
||||
end
|
||||
sLogLine = sLogLine .. sOtherField
|
||||
|
||||
EgtOutLog( sLogLine)
|
||||
end
|
||||
local sPartPosition = EgtIf( BestCombination.bPartInCombiIsInverted, 'INV', 'ORI')
|
||||
EgtOutLog( '------------------------------------------------------------------------------')
|
||||
EgtOutLog( ' BEST ROTATION : ' .. BestCombination.sBitIndexCombination .. ' (' .. BestCombination.nUnloadPos .. ') ' .. sPartPosition)
|
||||
EgtOutLog( '---------------------------')
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function Logs.WriteMainFacesLog( Proc, MainFaces)
|
||||
-- reset eventuali visualizzazioni facce a due colori
|
||||
EgtSurfTmResetTwoColors( Proc.id)
|
||||
|
||||
if MainFaces.BottomFaces then
|
||||
for i = 1, #MainFaces.BottomFaces do
|
||||
EgtOutLog( 'Bottom Face : ' .. MainFaces.BottomFaces[i].id)
|
||||
end
|
||||
-- colore differente per la faccia di fondo principale
|
||||
--EgtSurfTmSetFaceColor( Proc.id, MainFaces.BottomFaces[1].id, 1)
|
||||
end
|
||||
if MainFaces.LongFaces then
|
||||
for i = 1, #MainFaces.LongFaces do
|
||||
EgtOutLog( 'Long Face : ' .. MainFaces.LongFaces[i].id)
|
||||
end
|
||||
end
|
||||
if MainFaces.SideFaces then
|
||||
for i = 1, #MainFaces.SideFaces do
|
||||
EgtOutLog( 'Side Face : ' .. MainFaces.SideFaces[i].id)
|
||||
end
|
||||
end
|
||||
if MainFaces.TunnelAddedFaces then
|
||||
EgtOutLog( 'Middle Face (Trimesh): ' .. MainFaces.TunnelAddedFaces.MiddleFaceTm.id)
|
||||
end
|
||||
end
|
||||
---------------------------------------------------------------------
|
||||
|
||||
return Logs
|
||||
@@ -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')
|
||||
@@ -0,0 +1,380 @@
|
||||
-- Process.lua by Egalware s.r.l. 2024/04/02
|
||||
-- Gestione calcolo disposizione e lavorazioni per Travi
|
||||
-- Si opera sulla macchina corrente
|
||||
-- 2024/04/02 PRIMA VERSIONE
|
||||
|
||||
|
||||
-- Intestazioni
|
||||
require( 'EgtBase')
|
||||
_ENV = EgtProtectGlobal()
|
||||
EgtEnableDebug( true)
|
||||
|
||||
-- Imposto direttorio libreria specializzata per Travi
|
||||
EgtAddToPackagePath( BEAM.BASEDIR .. '\\LuaLibs\\?.lua')
|
||||
-- Imposto direttorio strategie. N.B. Le strategie dovranno essere caricate con il nome del direttorio padre
|
||||
EgtAddToPackagePath( BEAM.BASEDIR .. '\\Strategies\\Standard\\?.lua')
|
||||
EgtAddToPackagePath( BEAM.BASEDIR .. '\\StrategyLibs\\?.lua')
|
||||
|
||||
-- TODO forzatura calcolo con prerotazioni. Cancellare dopo che è stata aggiunta la gestione corretta
|
||||
local bCalcBestPieceUnloadPosition = true
|
||||
|
||||
-- Verifico che la macchina corrente sia abilitata per la lavorazione delle Travi
|
||||
local sMachDir = EgtGetCurrMachineDir()
|
||||
if not sMachDir then
|
||||
EgtOutBox( 'Errore nel caricamento della macchina corrente', 'Lavora Travi', 'ERROR')
|
||||
return
|
||||
end
|
||||
if not EgtExistsFile( sMachDir .. '\\Beam\\BeamData.lua') then
|
||||
EgtOutBox( 'La macchina corrente non è configurata per lavorare travi', 'Lavora Travi', 'ERROR')
|
||||
return
|
||||
end
|
||||
|
||||
-- Elimino direttori altre macchine e imposto direttorio macchina corrente per ricerca librerie
|
||||
EgtRemoveBaseMachineDirFromPackagePath()
|
||||
EgtAddToPackagePath( sMachDir .. '\\Beam\\?.lua')
|
||||
|
||||
-- Segnalazione avvio
|
||||
EgtOutLog( '*** Beam Process Start ***', 1)
|
||||
|
||||
-- Carico le librerie
|
||||
_G.package.loaded.BasicCustomerStrategies = nil
|
||||
_G.package.loaded.BeamExec = nil
|
||||
_G.package.loaded.BeamLib = nil
|
||||
_G.package.loaded.DiceCut = nil
|
||||
_G.package.loaded.FaceData = nil
|
||||
_G.package.loaded.FeatureLib = nil
|
||||
_G.package.loaded.Identity = nil
|
||||
_G.package.loaded.Logs = nil
|
||||
_G.package.loaded.MachiningLib = nil
|
||||
-- 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')
|
||||
|
||||
-- Variabili di modulo
|
||||
local dRawW
|
||||
local dRawH
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-- *** Recupero le travi selezionate ***
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function MyProcessInputData()
|
||||
|
||||
-- Recupero le travi selezionate
|
||||
local nId = EgtGetFirstSelectedObj()
|
||||
while nId do
|
||||
local nPartId = EgtGetParent( EgtGetParent( nId or GDB_ID.NULL) or GDB_ID.NULL)
|
||||
if nPartId then
|
||||
local bFound = false
|
||||
for i = 1, #PARTS do
|
||||
if PARTS[i].id == nPartId then
|
||||
bFound = true
|
||||
break
|
||||
end
|
||||
end
|
||||
if not bFound then
|
||||
table.insert( PARTS, { nInd = #PARTS + 1, id = nPartId, sName = ( EgtGetName( nPartId) or ( 'Id=' .. tonumber( nPartId)))})
|
||||
end
|
||||
end
|
||||
nId = EgtGetNextSelectedObj()
|
||||
end
|
||||
if #PARTS == 0 then
|
||||
EgtOutBox( 'Non sono state selezionate travi', 'Lavora Travi', 'ERROR')
|
||||
return false
|
||||
else
|
||||
local sOut = ''
|
||||
for i = 1, #PARTS do
|
||||
sOut = sOut .. PARTS[i].sName .. ', '
|
||||
end
|
||||
sOut = sOut:sub( 1, -3)
|
||||
EgtOutLog( 'Travi selezionate : ' .. sOut, 1)
|
||||
end
|
||||
|
||||
-- Ne recupero e verifico 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
|
||||
EgtOutBox( 'Box non definito per la trave ' .. PARTS[i].sName, 'Lavora Travi', 'ERROR')
|
||||
return false
|
||||
else
|
||||
PARTS[i].b3PartOriginal = b3Solid
|
||||
end
|
||||
end
|
||||
dRawW = PARTS[1].b3PartOriginal:getDimY()
|
||||
dRawH = PARTS[1].b3PartOriginal:getDimZ()
|
||||
local vBeamErr = {}
|
||||
for i = 2, #PARTS do
|
||||
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)
|
||||
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'
|
||||
EgtDeselectPartObjs( PARTS[vBeamErr[i]].id)
|
||||
table.remove( PARTS, vBeamErr[i])
|
||||
end
|
||||
EgtOutLog( sOut, 1)
|
||||
EgtOutBox( sOut, 'Lavora Travi', 'INFO')
|
||||
EgtDraw()
|
||||
return false
|
||||
end
|
||||
EgtDeselectAll()
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function GetDataConfig()
|
||||
-- recupero utensili dal magazzino
|
||||
BeamExec.GetToolsFromDB()
|
||||
-- TODO da gestire eventuali errori bloccanti
|
||||
return true
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-- *** Inserimento delle travi nel grezzo ***
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function MyProcessBeams()
|
||||
-- Determinazione minimo grezzo scaricabile
|
||||
BeamExec.CalcMinUnloadableRaw( dRawW, dRawH)
|
||||
|
||||
-- Lunghezza totale delle travi
|
||||
local dTotLen = 0
|
||||
for i = 1, #PARTS - 1 do
|
||||
dTotLen = dTotLen + PARTS[i].b3PartOriginal:getDimX()
|
||||
end
|
||||
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)
|
||||
|
||||
-- Richiedo lunghezza del grezzo, sovramateriale di testa, forzatura verticale e ordinamento automatico secondo la lunghezza
|
||||
local vsVal = EgtDialogBox( 'Lavora Travi' .. ' (Ltot='..EgtNumToString( dTotLen + dAddLen + 0.5, 0)..
|
||||
', Lmax='..EgtNumToString( BeamData.MAX_RAW, 0)..',MinUlr='..EgtNumToString( BeamData.dMinRaw + BeamData.OVM_MID, 0)..')',
|
||||
--{'Lunghezza grezzo', EgtNumToString( BeamData.STD_RAW, 0)}, -- TODO RIPRISTINARE
|
||||
{'Lunghezza grezzo', EgtNumToString( 0)},
|
||||
{'Sovramateriale di testa', EgtNumToString( BeamData.OVM_HEAD, 0)},
|
||||
{'Offset intermedio', EgtNumToString( BeamData.OVM_MID, 0)},
|
||||
{'Forza sezione verticale', ' CB:true,*false'},
|
||||
{'Ordina per lunghezza', ' CB:true,*false'},
|
||||
{'Calcolo Lavorazioni', ' CB:*Da progetto,Ricalcolo standard,Ricalcolo IA'})
|
||||
if not vsVal then
|
||||
EgtDraw()
|
||||
return
|
||||
end
|
||||
local dRawL = EgtEvalNumExpr( vsVal[1])
|
||||
if not dRawL then
|
||||
local sOut = 'Lunghezza grezzo errata : ' .. vsVal[1]
|
||||
EgtOutLog( sOut)
|
||||
EgtOutBox( sOut, 'Lavora Travi', 'WARNING')
|
||||
EgtDraw()
|
||||
return false
|
||||
end
|
||||
if dRawL < GEO.EPS_SMALL then dRawL = dTotLen + dAddLen + 0.5 end
|
||||
dRawL = min( dRawL, BeamData.MAX_RAW)
|
||||
local dOvmHead = EgtEvalNumExpr( vsVal[2])
|
||||
if not dOvmHead then
|
||||
local sOut = 'Sovramateriale di testa errato : ' .. vsVal[2]
|
||||
EgtOutLog( sOut)
|
||||
EgtOutBox( sOut, 'Lavora Travi', 'WARNING')
|
||||
EgtDraw()
|
||||
return false
|
||||
end
|
||||
local dOvmMid = EgtEvalNumExpr( vsVal[3])
|
||||
if not dOvmMid then
|
||||
local sOut = 'Offset intermedio : ' .. vsVal[3]
|
||||
EgtOutLog( sOut)
|
||||
EgtOutBox( sOut, 'Lavora Travi', 'WARNING')
|
||||
EgtDraw()
|
||||
return false
|
||||
end
|
||||
|
||||
-- Sistemo sezione barra con travi
|
||||
local bVert = ( vsVal[4] == 'true')
|
||||
if bVert then
|
||||
if dRawW > dRawH then dRawW, dRawH = dRawH, dRawW end
|
||||
end
|
||||
EgtOutLog( 'Lraw : ' .. EgtNumToString( dRawL, 1) .. ' Lovm : '.. EgtNumToString( dOvmHead, 1), 1)
|
||||
|
||||
-- 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
|
||||
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) .. ') '
|
||||
EgtOutLog( sOut)
|
||||
EgtOutBox( sOut, 'Lavora Travi', 'WARNING')
|
||||
EgtDraw()
|
||||
return false
|
||||
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
|
||||
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) .. ')'
|
||||
EgtOutLog( sOut)
|
||||
EgtOutBox( sOut, 'Lavora Travi', 'WARNING')
|
||||
EgtDraw()
|
||||
return false
|
||||
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
|
||||
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) .. ')'
|
||||
EgtOutLog( sOut)
|
||||
EgtOutBox( sOut, 'Lavora Travi', 'WARNING')
|
||||
EgtDraw()
|
||||
return false
|
||||
end
|
||||
|
||||
-- Se richiesto, ordino le travi in senso di lunghezza crescente
|
||||
local bOrd = ( vsVal[5] == 'true')
|
||||
if bOrd then
|
||||
table.sort( PARTS, function( B1, B2)
|
||||
if abs( B1.b3PartOriginal:getDimX() - B2.b3PartOriginal:getDimX()) < 1 then
|
||||
return B1.nInd < B2.nInd
|
||||
else
|
||||
return B1.b3PartOriginal:getDimX() < B2.b3PartOriginal:getDimX()
|
||||
end
|
||||
end)
|
||||
end
|
||||
do
|
||||
local sOut = ''
|
||||
for i = 1, #PARTS do
|
||||
sOut = sOut .. PARTS[i].sName .. ', '
|
||||
end
|
||||
sOut = sOut:sub( 1, -3)
|
||||
EgtOutLog( 'Travi ordinate : ' .. sOut, 1)
|
||||
end
|
||||
|
||||
-- Sistemo le travi nel grezzo
|
||||
local bOk, sErr = BeamExec.ProcessBeams( dRawW, dRawH, dRawL, dOvmHead, dOvmMid, PARTS, nil, bCalcBestPieceUnloadPosition)
|
||||
if not bOk then
|
||||
EgtOutLog( sErr)
|
||||
EgtOutBox( sErr, 'Lavora Travi', 'ERROR')
|
||||
return false
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-- *** Inserimento delle lavorazioni nelle travi ***
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function MyProcessFeatures()
|
||||
-- creo un gruppo temporaneo dove finiranno tutte le entità che non bisogna salvare, alla fine lo si cancella
|
||||
local idTempGroup = BeamLib.CreateTempGroup()
|
||||
|
||||
BeamExec.GetProcessings( PARTS, bCalcBestPieceUnloadPosition)
|
||||
BeamExec.GetCombinationMatrix( PARTS, bCalcBestPieceUnloadPosition)
|
||||
BeamExec.ProcessMachinings( PARTS)
|
||||
local nErrCnt = 0
|
||||
local nWarnCnt = 0
|
||||
local sOutput = ''
|
||||
for i = 1, #RESULT do
|
||||
local sMsg = ''
|
||||
if RESULT[i].sType == 'Feature' then
|
||||
sMsg = RESULT[i].ChosenStrategy.sInfo
|
||||
elseif RESULT[i].sType == 'Part' then
|
||||
sMsg = RESULT[i].sMsg
|
||||
end
|
||||
sMsg = string.gsub( sMsg or '', '\n', ' ', 10)
|
||||
sMsg = string.gsub( sMsg or '', '\r', ' ', 10)
|
||||
-- trovata almeno una strategia e feature lavorata completamente
|
||||
if RESULT[i].sType == 'Feature' and RESULT[i].ChosenStrategy.sStatus == 'Completed' then
|
||||
-- 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
|
||||
if #sMsg == 0 then
|
||||
sMsg = 'No applicable strategy found'
|
||||
end
|
||||
sOutput = sOutput .. string.format( '[%d,%d] %s\n', RESULT[i].idCut, RESULT[i].idTask, sMsg)
|
||||
else
|
||||
-- segnalazione scarico pezzo standard, incompleto o a caduta
|
||||
if RESULT[i].sType == 'Part' and ( RESULT[i].nErr == -100 or RESULT[i].nErr == -101 or RESULT[i].nErr == -102) then
|
||||
-- nulla da segnalare
|
||||
|
||||
-- feature incompleta e altro
|
||||
elseif RESULT[i].sType == 'Feature' and RESULT[i].ChosenStrategy.sStatus == 'Not-Completed' then
|
||||
nWarnCnt = nWarnCnt + 1
|
||||
sMsg = 'Incomplete : Completion index ' .. RESULT[i].ChosenStrategy.dCompletionIndex .. '/5\n' .. sMsg
|
||||
sOutput = sOutput .. string.format( '[%d,%d] %s\n', RESULT[i].idCut, RESULT[i].idTask, sMsg)
|
||||
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- cancello gruppo temporaneo
|
||||
EgtErase( idTempGroup)
|
||||
|
||||
if #sOutput > 0 then EgtOutLog( sOutput) end
|
||||
if nErrCnt > 0 then
|
||||
EgtOutBox( sOutput, 'Lavora Travi', 'ERRORS')
|
||||
return false
|
||||
elseif nWarnCnt > 0 then
|
||||
EgtOutBox( sOutput, 'Lavora Travi', 'WARNINGS')
|
||||
return true
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-- *** Esecuzione ***
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
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
|
||||
|
||||
-- Abilito Vmill
|
||||
EgtSetInfo( EgtGetCurrMachGroup(), 'Vm', '1')
|
||||
|
||||
if not MyProcessFeatures() then return end
|
||||
@@ -1,93 +0,0 @@
|
||||
# DataBeamNEW
|
||||
|
||||
|
||||
|
||||
## Getting started
|
||||
|
||||
To make it easy for you to get started with GitLab, here's a list of recommended next steps.
|
||||
|
||||
Already a pro? Just edit this README.md and make it your own. Want to make it easy? [Use the template at the bottom](#editing-this-readme)!
|
||||
|
||||
## Add your files
|
||||
|
||||
- [ ] [Create](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#create-a-file) or [upload](https://docs.gitlab.com/ee/user/project/repository/web_editor.html#upload-a-file) files
|
||||
- [ ] [Add files using the command line](https://docs.gitlab.com/ee/gitlab-basics/add-file.html#add-a-file-using-the-command-line) or push an existing Git repository with the following command:
|
||||
|
||||
```
|
||||
cd existing_repo
|
||||
git remote add origin https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew.git
|
||||
git branch -M main
|
||||
git push -uf origin main
|
||||
```
|
||||
|
||||
## Integrate with your tools
|
||||
|
||||
- [ ] [Set up project integrations](https://gitlab.steamware.net/egalware-cadcam/lua/databeamnew/-/settings/integrations)
|
||||
|
||||
## Collaborate with your team
|
||||
|
||||
- [ ] [Invite team members and collaborators](https://docs.gitlab.com/ee/user/project/members/)
|
||||
- [ ] [Create a new merge request](https://docs.gitlab.com/ee/user/project/merge_requests/creating_merge_requests.html)
|
||||
- [ ] [Automatically close issues from merge requests](https://docs.gitlab.com/ee/user/project/issues/managing_issues.html#closing-issues-automatically)
|
||||
- [ ] [Enable merge request approvals](https://docs.gitlab.com/ee/user/project/merge_requests/approvals/)
|
||||
- [ ] [Set auto-merge](https://docs.gitlab.com/ee/user/project/merge_requests/merge_when_pipeline_succeeds.html)
|
||||
|
||||
## Test and Deploy
|
||||
|
||||
Use the built-in continuous integration in GitLab.
|
||||
|
||||
- [ ] [Get started with GitLab CI/CD](https://docs.gitlab.com/ee/ci/quick_start/index.html)
|
||||
- [ ] [Analyze your code for known vulnerabilities with Static Application Security Testing (SAST)](https://docs.gitlab.com/ee/user/application_security/sast/)
|
||||
- [ ] [Deploy to Kubernetes, Amazon EC2, or Amazon ECS using Auto Deploy](https://docs.gitlab.com/ee/topics/autodevops/requirements.html)
|
||||
- [ ] [Use pull-based deployments for improved Kubernetes management](https://docs.gitlab.com/ee/user/clusters/agent/)
|
||||
- [ ] [Set up protected environments](https://docs.gitlab.com/ee/ci/environments/protected_environments.html)
|
||||
|
||||
***
|
||||
|
||||
# Editing this README
|
||||
|
||||
When you're ready to make this README your own, just edit this file and use the handy template below (or feel free to structure it however you want - this is just a starting point!). Thanks to [makeareadme.com](https://www.makeareadme.com/) for this template.
|
||||
|
||||
## Suggestions for a good README
|
||||
|
||||
Every project is different, so consider which of these sections apply to yours. The sections used in the template are suggestions for most open source projects. Also keep in mind that while a README can be too long and detailed, too long is better than too short. If you think your README is too long, consider utilizing another form of documentation rather than cutting out information.
|
||||
|
||||
## Name
|
||||
Choose a self-explaining name for your project.
|
||||
|
||||
## Description
|
||||
Let people know what your project can do specifically. Provide context and add a link to any reference visitors might be unfamiliar with. A list of Features or a Background subsection can also be added here. If there are alternatives to your project, this is a good place to list differentiating factors.
|
||||
|
||||
## Badges
|
||||
On some READMEs, you may see small images that convey metadata, such as whether or not all the tests are passing for the project. You can use Shields to add some to your README. Many services also have instructions for adding a badge.
|
||||
|
||||
## Visuals
|
||||
Depending on what you are making, it can be a good idea to include screenshots or even a video (you'll frequently see GIFs rather than actual videos). Tools like ttygif can help, but check out Asciinema for a more sophisticated method.
|
||||
|
||||
## Installation
|
||||
Within a particular ecosystem, there may be a common way of installing things, such as using Yarn, NuGet, or Homebrew. However, consider the possibility that whoever is reading your README is a novice and would like more guidance. Listing specific steps helps remove ambiguity and gets people to using your project as quickly as possible. If it only runs in a specific context like a particular programming language version or operating system or has dependencies that have to be installed manually, also add a Requirements subsection.
|
||||
|
||||
## Usage
|
||||
Use examples liberally, and show the expected output if you can. It's helpful to have inline the smallest example of usage that you can demonstrate, while providing links to more sophisticated examples if they are too long to reasonably include in the README.
|
||||
|
||||
## Support
|
||||
Tell people where they can go to for help. It can be any combination of an issue tracker, a chat room, an email address, etc.
|
||||
|
||||
## Roadmap
|
||||
If you have ideas for releases in the future, it is a good idea to list them in the README.
|
||||
|
||||
## Contributing
|
||||
State if you are open to contributions and what your requirements are for accepting them.
|
||||
|
||||
For people who want to make changes to your project, it's helpful to have some documentation on how to get started. Perhaps there is a script that they should run or some environment variables that they need to set. Make these steps explicit. These instructions could also be useful to your future self.
|
||||
|
||||
You can also document commands to lint the code or run tests. These steps help to ensure high code quality and reduce the likelihood that the changes inadvertently break something. Having instructions for running tests is especially helpful if it requires external setup, such as starting a Selenium server for testing in a browser.
|
||||
|
||||
## Authors and acknowledgment
|
||||
Show your appreciation to those who have contributed to the project.
|
||||
|
||||
## License
|
||||
For open source projects, say how it is licensed.
|
||||
|
||||
## Project status
|
||||
If you have run out of energy or time for your project, put a note at the top of the README saying that development has slowed down or stopped completely. Someone may choose to fork your project or volunteer to step in as a maintainer or owner, allowing your project to keep going. You can also make an explicit request for maintainers.
|
||||
@@ -0,0 +1,32 @@
|
||||
-- Rotate.lua by Egaltech s.r.l. 2017/11/04
|
||||
-- Gestione rotazione di una Trave
|
||||
|
||||
-- Intestazioni
|
||||
require( 'EgtBase')
|
||||
_ENV = EgtProtectGlobal()
|
||||
EgtEnableDebug( false)
|
||||
|
||||
|
||||
-- recupero il pezzo del primo oggetto selezionato
|
||||
local nId = EgtGetFirstSelectedObj()
|
||||
local nPartId = EgtGetParent( EgtGetParent( nId or GDB_ID.NULL) or GDB_ID.NULL)
|
||||
if not nPartId or not EgtIsPart( nPartId) then
|
||||
EgtOutBox( 'Nessuna trave selezionata', 'Rotate Trave', 'ERROR')
|
||||
return
|
||||
end
|
||||
|
||||
-- recupero il box del pezzo
|
||||
local Ls = EgtGetFirstNameInGroup( nPartId, 'Box')
|
||||
local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD)
|
||||
if not b3Solid then
|
||||
local sName = EgtGetName( nPartId) or ( 'Id=' .. tonumber( nPartId))
|
||||
EgtOutBox( 'Box non definito per la trave ' .. sName, 'Rotate Trave', 'ERROR')
|
||||
return
|
||||
end
|
||||
|
||||
-- eseguo rotazione di 90 gradi attorno asse X
|
||||
local ptRot = b3Solid:getMin() + Vector3d( 0, b3Solid:getDimZ() / 2, b3Solid:getDimZ() / 2)
|
||||
EgtRotate( nPartId, ptRot, X_AX(), 90, GDB_RT.GLOB)
|
||||
EgtDraw()
|
||||
|
||||
-- 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" : [ ]
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -0,0 +1,126 @@
|
||||
-- Strategia: HEADCUT
|
||||
-- Descrizione
|
||||
-- HeadCut
|
||||
-- Feature: HeadCut
|
||||
|
||||
-- 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 HEADCUT = {}
|
||||
local Strategy = {}
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function MakeChamfer()
|
||||
-- TODO funzionalità da aggiungere
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
function HEADCUT.Make( bAddMachining, Proc, Part, CustomParameters)
|
||||
local StrategyLib = {}
|
||||
StrategyLib.Config = STRATEGIES_CONFIG[CustomParameters.sStrategyId]
|
||||
Strategy.sName = StrategyLib.Config.sStrategyId
|
||||
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( Proc, Part, CustomParameters, StrategyLib.Config)
|
||||
Strategy.SplitStrategy = {}
|
||||
Strategy.Result = {}
|
||||
Strategy.Machining = {}
|
||||
Strategy.Result.sInfo = ''
|
||||
local OptionalParameters = { bForceChainSaw = Strategy.Parameters.bForceChainSaw, bReduceBladePath = Strategy.Parameters.bReduceBladePath,
|
||||
dMaxWasteLength = Strategy.Parameters.dMaxWasteLength, dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume }
|
||||
local bAreAllMachiningsAdded = true
|
||||
|
||||
-- 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 MachiningsToAdd = {}
|
||||
local bExecutePrecutOnly = Part.dHeadOverMaterial < 20
|
||||
-- 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 = Strategy.SplitStrategy[i]
|
||||
if bExecutePrecutOnly then
|
||||
TempList.dLongitudinalOffset = 0
|
||||
else
|
||||
TempList.bIsPreCut = true
|
||||
TempList.dLongitudinalOffset = Part.dHeadOverMaterial
|
||||
end
|
||||
|
||||
table.insert( MachiningsToAdd, TempList)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
if not bExecutePrecutOnly then
|
||||
local OptionalParameters = {}
|
||||
-- si parte dal box della feature e si aggiunge il punto estremo del grezzo
|
||||
-- ATTENZIONE : Proc.b3Box viene modificata dato che il tipo Box è come se fosse una tabella, ma da qui passa solo 1 volta per pezzo quindi non dovrebbero esserci problemi
|
||||
local b3BoxDicing = Proc.b3Box
|
||||
b3BoxDicing:Add( Part.b3Raw:getMax())
|
||||
b3BoxDicing:expand( 1000 * GEO.EPS_SMALL)
|
||||
OptionalParameters.b3BoxDicing = b3BoxDicing
|
||||
|
||||
OptionalParameters.dMaxWasteVolume = Strategy.Parameters.dMaxWasteVolume
|
||||
OptionalParameters.dMaxWasteLength = Strategy.Parameters.dMaxWasteLength
|
||||
OptionalParameters.bReduceBladePath = Strategy.Parameters.bReduceBladePath
|
||||
|
||||
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
|
||||
|
||||
-- aggiungo lavorazioni trovate alla lista generale
|
||||
for i = 1, #MachiningsToAdd do
|
||||
MachiningsToAdd[i].sStage = 'Head'
|
||||
MachiningLib.AddMachinings( Proc, MachiningsToAdd[i], MachiningsToAdd[i].AuxiliaryData)
|
||||
end
|
||||
|
||||
return bAreAllMachiningsAdded, Strategy.Result
|
||||
else
|
||||
return nil, Strategy.Result
|
||||
end
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return HEADCUT
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,436 @@
|
||||
-- Strategia: STR0001
|
||||
-- Descrizione
|
||||
-- Lama + fresa CodaDiRondine per tenone
|
||||
-- Feature: 55,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 STR0001 = {}
|
||||
local Strategy = {}
|
||||
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function GetSCC( Machining)
|
||||
local nSCC
|
||||
|
||||
if Machining.vtToolDirection:getX() > 0 then
|
||||
nSCC = MCH_SCC.ADIR_XP
|
||||
else
|
||||
nSCC = MCH_SCC.ADIR_XM
|
||||
end
|
||||
|
||||
return nSCC
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
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
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return STR0001
|
||||
@@ -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"
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,607 @@
|
||||
-- Strategia: STR0002
|
||||
-- Descrizione
|
||||
-- Svuotatura tasca
|
||||
-- Feature tipo LapJoint
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-- TODO
|
||||
-- 1 - Inserire antischeggia (fresa o lama)
|
||||
-- 2 - Modalità svuotatura con fresa grande e spigoli con fresa piccola
|
||||
-- 3 - Smusso a V
|
||||
-- 4 - Finitura con motosega (se la fresa non completa)
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
|
||||
-- carico librerie
|
||||
local BeamLib = require( 'BeamLib')
|
||||
local BeamData = require( 'BeamData')
|
||||
local MachiningLib = require( 'MachiningLib')
|
||||
local FeatureLib = require( 'FeatureLib')
|
||||
|
||||
-- Tabella per definizione modulo
|
||||
local STR0002 = {}
|
||||
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 == '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
|
||||
return false
|
||||
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
|
||||
if Machining.sTypeMachining == 'None' then
|
||||
return 0
|
||||
end
|
||||
|
||||
local dTotalPercentage = 0
|
||||
local dPercentageBottom = 0
|
||||
|
||||
if Machining[1].bIsApplicable then
|
||||
dTotalPercentage = ( Machining[1].dElevation - Machining[1].ToolInfo.dResidualDepth) / Machining[1].dElevation
|
||||
dPercentageBottom = dTotalPercentage
|
||||
end
|
||||
if Machining[2].bIsApplicable then
|
||||
local dAbsPercentage = ( Machining[2].dElevation - Machining[2].ToolInfo.dResidualDepth) / Machining[2].dElevation
|
||||
dTotalPercentage = dTotalPercentage + ( 1 - dTotalPercentage) * dAbsPercentage
|
||||
end
|
||||
if Machining[3].bIsApplicable then
|
||||
local dAbsPercentage
|
||||
if Machining[3].bMachAppliedToTunnelFace then
|
||||
dAbsPercentage = ( Machining[3].dElevation - Machining[3].ToolInfo.dResidualDepth - Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation) / Machining[3].dElevation
|
||||
else
|
||||
dAbsPercentage = ( Machining[3].dElevation - Machining[3].ToolInfo.dResidualDepth) / Machining[3].dElevation
|
||||
end
|
||||
dTotalPercentage = dTotalPercentage + ( 1 - dPercentageBottom) * dAbsPercentage
|
||||
end
|
||||
if Machining[4].bIsApplicable then
|
||||
local dAbsPercentage
|
||||
if Machining[3].bMachAppliedToTunnelFace then
|
||||
dAbsPercentage = ( Machining[4].dElevation - Machining[4].ToolInfo.dResidualDepth - Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation) / Machining[4].dElevation
|
||||
else
|
||||
dAbsPercentage = ( Machining[4].dElevation - Machining[4].ToolInfo.dResidualDepth) / Machining[4].dElevation
|
||||
end
|
||||
dTotalPercentage = dTotalPercentage + ( 1 - dPercentageBottom) * dAbsPercentage
|
||||
end
|
||||
|
||||
return dTotalPercentage * 100
|
||||
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 = {}
|
||||
local Milling = {}
|
||||
local ToolSearchParameters = {}
|
||||
ToolSearchParameters.sMillShape = 'STANDARD'
|
||||
Machining.sTypeMachining = 'None' -- Bottom-Side1-Side2\ Bottom-Side1\ Bottom-Side2\ Side1-Side2\ Bottom\ Side1 \ Side2 \ None
|
||||
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( 'STD')
|
||||
|
||||
-- caso speciale Tunnel che non ha faccia bottom
|
||||
if Proc.Topology.sName == 'Tunnel-4-Through' then
|
||||
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, 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, 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, dFaceLength, dFaceWidth)
|
||||
-- cerco fresa che può anche non lavorare di testa
|
||||
elseif Proc.Topology.sName == 'Groove-4-Blind' then
|
||||
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, 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 = 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'
|
||||
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
|
||||
return nil
|
||||
end
|
||||
|
||||
-- ===== RICERCA UTENSILE =====
|
||||
-- cerco utensile per lavorare faccia Bottom
|
||||
Milling.bIsApplicable = false
|
||||
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
|
||||
Milling.dElevation = Proc.MainFaces.BottomFaces[1].dElevation
|
||||
Milling.ToolInfo = {}
|
||||
Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
|
||||
if Milling.ToolInfo.nToolIndex then
|
||||
Milling.bIsApplicable = true
|
||||
local ParametersMRR = {}
|
||||
ParametersMRR.nToolIndex = Milling.ToolInfo.nToolIndex
|
||||
Milling.dMRR = MachiningLib.GetToolMRR( ParametersMRR)
|
||||
end
|
||||
end
|
||||
table.insert( Machining, Milling)
|
||||
|
||||
-- caso speciale 'Rabbet-2-Through' seconda faccia principale
|
||||
Milling = {}
|
||||
Milling.bIsApplicable = false
|
||||
if Proc.Topology.sName == 'Rabbet-2-Through' or Proc.Topology.sName == 'Bevel-2-Blind' or
|
||||
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.BottomFaces[2].dElevation
|
||||
Milling.ToolInfo = {}
|
||||
Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
|
||||
if Milling.ToolInfo.nToolIndex then
|
||||
Milling.bIsApplicable = true
|
||||
local ParametersMRR = {}
|
||||
ParametersMRR.nToolIndex = Milling.ToolInfo.nToolIndex
|
||||
Milling.dMRR = MachiningLib.GetToolMRR( ParametersMRR)
|
||||
end
|
||||
end
|
||||
table.insert( Machining, Milling)
|
||||
|
||||
-- cerco utensile per lavorare di fianco 1
|
||||
Milling = {}
|
||||
Milling.bIsApplicable = false
|
||||
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
|
||||
Milling.vtFaceNormal = Proc.MainFaces.BottomFaces[2].vtN
|
||||
Milling.idFaceToMachine = Proc.MainFaces.BottomFaces[2].id
|
||||
Milling.idProc = Proc.id
|
||||
Milling.dElevation = Proc.MainFaces.BottomFaces[2].dElevation
|
||||
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
|
||||
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
|
||||
ToolSearchParameters.vtToolDirection = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].vtN
|
||||
Milling.vtFaceNormal = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].vtN
|
||||
Milling.idFaceToMachine = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].id
|
||||
Milling.idProc = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.id
|
||||
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
|
||||
Milling.bIsApplicable = true
|
||||
local ParametersMRR = {}
|
||||
ParametersMRR.nToolIndex = Milling.ToolInfo.nToolIndex
|
||||
Milling.dMRR = MachiningLib.GetToolMRR( ParametersMRR)
|
||||
end
|
||||
end
|
||||
table.insert( Machining, Milling)
|
||||
|
||||
-- cerco utensile per lavorare di fianco 2
|
||||
Milling = {}
|
||||
Milling.bIsApplicable = false
|
||||
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
|
||||
ToolSearchParameters.vtToolDirection = -Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].vtN
|
||||
Milling.vtFaceNormal = -Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].vtN
|
||||
Milling.idFaceToMachine = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].id
|
||||
Milling.idProc = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.id
|
||||
Milling.dElevation = ( Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation * 2) + BeamData.MILL_OVERLAP
|
||||
Milling.bToolInvert = true
|
||||
Milling.bMachAppliedToTunnelFace = true
|
||||
elseif #Proc.MainFaces.SideFaces > 0 then -- 'Groove-3-Blind'
|
||||
ToolSearchParameters.dElevation = Proc.MainFaces.SideFaces[1].dElevation
|
||||
ToolSearchParameters.vtToolDirection = Proc.MainFaces.SideFaces[1].vtN
|
||||
Milling.vtFaceNormal = Proc.MainFaces.SideFaces[1].vtN
|
||||
Milling.idFaceToMachine = Proc.MainFaces.SideFaces[1].id
|
||||
Milling.idProc = Proc.id
|
||||
Milling.dElevation = Proc.MainFaces.SideFaces[1].dElevation
|
||||
end
|
||||
ToolSearchParameters.AvailableToolList = MachiningLib.GetAvailableToolList( Proc, Strategy.Parameters.sPocketingList, 'Pocketing')
|
||||
Milling.ToolInfo = {}
|
||||
Milling.ToolInfo = MachiningLib.FindMill( Proc, ToolSearchParameters)
|
||||
if Milling.ToolInfo.nToolIndex then
|
||||
Milling.bIsApplicable = true
|
||||
local ParametersMRR = {}
|
||||
ParametersMRR.nToolIndex = Milling.ToolInfo.nToolIndex
|
||||
Milling.dMRR = MachiningLib.GetToolMRR( ParametersMRR)
|
||||
end
|
||||
end
|
||||
table.insert( Machining, Milling)
|
||||
|
||||
-- ===== SCELTA LAVORAZIONI =====
|
||||
-- se bottom completa tutto
|
||||
if Machining[1].bIsApplicable and Machining[1].ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then
|
||||
Machining.sTypeMachining = 'Bottom'
|
||||
Strategy.Result.sStatus = 'Completed'
|
||||
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
|
||||
Strategy.Result.dMRR = Machining[1].dMRR
|
||||
Machining[1].ToolInfo.dResidualDepth = 0
|
||||
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 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.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( 100)
|
||||
Strategy.Result.dMRR = Machining[2].dMRR
|
||||
Machining[2].ToolInfo.dResidualDepth = 0
|
||||
Machining[1].bIsApplicable = false
|
||||
Machining[3].bIsApplicable = false
|
||||
Machining[4].bIsApplicable = false
|
||||
return Machining
|
||||
-- se la 3 completa tutto
|
||||
elseif Machining[3].bIsApplicable and Machining[3].ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then
|
||||
Machining.sTypeMachining = 'Side1'
|
||||
Strategy.Result.sStatus = 'Completed'
|
||||
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)
|
||||
else
|
||||
Machining[3].ToolInfo.dResidualDepth = 0
|
||||
end
|
||||
Machining[1].bIsApplicable = false
|
||||
Machining[2].bIsApplicable = false
|
||||
Machining[4].bIsApplicable = false
|
||||
return Machining
|
||||
-- se la 4 completa tutto
|
||||
elseif Machining[4].bIsApplicable and Machining[4].ToolInfo.dResidualDepth < 10 * GEO.EPS_SMALL then
|
||||
Machining.sTypeMachining = 'Side2'
|
||||
Strategy.Result.sStatus = 'Completed'
|
||||
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)
|
||||
else
|
||||
Machining[4].ToolInfo.dResidualDepth = 0
|
||||
end
|
||||
Machining[1].bIsApplicable = false
|
||||
Machining[2].bIsApplicable = false
|
||||
Machining[3].bIsApplicable = false
|
||||
return Machining
|
||||
-- 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'
|
||||
-- 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
|
||||
return Machining
|
||||
end
|
||||
|
||||
Strategy.Result.sStatus = 'Not-Completed'
|
||||
Strategy.Result.dMRR = 0
|
||||
if Machining[1].bIsApplicable then
|
||||
Machining.sTypeMachining = 'Bottom'
|
||||
Strategy.Result.dMRR = Machining[1].dMRR
|
||||
end
|
||||
if Machining[2].bIsApplicable then
|
||||
Machining.sTypeMachining = EgtIf( Machining.sTypeMachining == 'None', 'Bottom2', Machining.sTypeMachining .. '-Bottom2')
|
||||
Strategy.Result.dMRR = ( Strategy.Result.dMRR + Machining[2].dMRR) / EgtIf( Strategy.Result.dMRR == 0, 1, 2)
|
||||
end
|
||||
if Machining[3].bIsApplicable then
|
||||
if Proc.MainFaces.TunnelAddedFaces then
|
||||
Machining[3].ToolInfo.dResidualDepth = Machining[3].ToolInfo.dResidualDepth - Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation + BeamData.MILL_OVERLAP
|
||||
end
|
||||
Machining.sTypeMachining = EgtIf( Machining.sTypeMachining == 'None', 'Side1', Machining.sTypeMachining .. '-Side1')
|
||||
Strategy.Result.dMRR = ( Strategy.Result.dMRR + Machining[3].dMRR) / EgtIf( Strategy.Result.dMRR == 0, 1, 2)
|
||||
end
|
||||
if Machining[4].bIsApplicable then
|
||||
if Proc.MainFaces.TunnelAddedFaces then
|
||||
Machining[4].ToolInfo.dResidualDepth = Machining[4].ToolInfo.dResidualDepth - Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.Faces[1].dElevation + BeamData.MILL_OVERLAP
|
||||
end
|
||||
Machining.sTypeMachining = EgtIf( Machining.sTypeMachining == 'None', 'Side2', Machining.sTypeMachining .. '-Side2')
|
||||
Strategy.Result.dMRR = ( Strategy.Result.dMRR + Machining[4].dMRR) / EgtIf( Strategy.Result.dMRR == 0, 1, 2)
|
||||
end
|
||||
|
||||
local dMachinedPrercentage = CalcMachinedPercentage( Proc, Machining)
|
||||
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 = FeatureLib.GetStrategyResultNotApplicable( 'Mill not found')
|
||||
end
|
||||
|
||||
return Machining
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function GetSplitSurfaces( Proc, Part, bAddMachining)
|
||||
local vAddId = {}
|
||||
local vAddIdTunnel = {}
|
||||
local nAddGrpId = BeamLib.GetAddGroup( Part.id)
|
||||
local nOriginalTmIdTunnel = GDB_ID.NULL
|
||||
if Proc.MainFaces.TunnelAddedFaces then
|
||||
nOriginalTmIdTunnel = Proc.MainFaces.TunnelAddedFaces.MiddleFaceTm.id
|
||||
end
|
||||
|
||||
-- recupero punti di spezzatura - da destra a sinistra
|
||||
local FeatureSplittingPoints = FeatureLib.GetFeatureSplittingPoints( Proc, Part)
|
||||
|
||||
if #FeatureSplittingPoints == 0 then
|
||||
local nAddId = EgtCopyGlob( Proc.id, nAddGrpId) or GDB_ID.NULL
|
||||
local nAddIdTunnel = EgtCopyGlob( nOriginalTmIdTunnel, nAddGrpId) or GDB_ID.NULL
|
||||
if not bAddMachining then
|
||||
EgtSetLevel( nAddId, GDB_LV.TEMP)
|
||||
EgtSetLevel( nAddIdTunnel, GDB_LV.TEMP)
|
||||
end
|
||||
table.insert( vAddId, nAddId)
|
||||
table.insert( vAddIdTunnel, nAddIdTunnel)
|
||||
else
|
||||
for i = 1, #FeatureSplittingPoints do
|
||||
local nAddId = EgtCopyGlob( Proc.id, nAddGrpId) or GDB_ID.NULL
|
||||
local nAddIdTunnel = EgtCopyGlob( nOriginalTmIdTunnel, nAddGrpId) or GDB_ID.NULL
|
||||
if i == 1 then
|
||||
-- prima superficie, va tagliata solo a sinistra
|
||||
local ptSplit = FeatureSplittingPoints[i] + Vector3d( -BeamData.MILL_OVERLAP / 2, 0, 0)
|
||||
EgtCutSurfTmPlane( nAddId, ptSplit, -X_AX(), true, GDB_RT.GLOB)
|
||||
EgtCutSurfTmPlane( nAddIdTunnel, ptSplit, -X_AX(), true, GDB_RT.GLOB)
|
||||
else
|
||||
-- taglio della superficie corrente - lato sinistro
|
||||
local ptSplit = FeatureSplittingPoints[i] + Vector3d( -BeamData.MILL_OVERLAP / 2, 0, 0)
|
||||
EgtCutSurfTmPlane( nAddId, ptSplit, -X_AX(), true, GDB_RT.GLOB)
|
||||
EgtCutSurfTmPlane( nAddIdTunnel, ptSplit, -X_AX(), true, GDB_RT.GLOB)
|
||||
-- taglio della superficie corrente - lato destro
|
||||
ptSplit = FeatureSplittingPoints[i - 1] + Vector3d( BeamData.MILL_OVERLAP / 2, 0, 0)
|
||||
EgtCutSurfTmPlane( nAddId, ptSplit, X_AX(), true, GDB_RT.GLOB)
|
||||
EgtCutSurfTmPlane( nAddIdTunnel, ptSplit, X_AX(), true, GDB_RT.GLOB)
|
||||
end
|
||||
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 = 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
|
||||
|
||||
return vAddId, vAddIdTunnel
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-- TODO rimuovere il calcolo MRR dove non serve, è fatto tutto alla fine.
|
||||
function STR0002.Make( bAddMachining, Proc, Part, CustomParameters)
|
||||
-- carico parametri de default e li aggiorno con quelli passati dal chiamante (potrebbero non essere congruenti)
|
||||
local StrategyLib = {}
|
||||
StrategyLib.Config = 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
|
||||
|
||||
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 dFeatureVolume = FeatureLib.GetFeatureVolume( Proc, Part)
|
||||
local ToolInfo = {}
|
||||
local Pocketing = {}
|
||||
|
||||
Strategy.Machining = GetBestPocketingStrategy( Proc)
|
||||
|
||||
if Strategy.Result.sStatus ~= 'Not-Applicable' then
|
||||
local vAddId = {}
|
||||
local vAddIdTunnel = {}
|
||||
|
||||
-- recupero superficie, se necessario trimmata sugli spezzoni
|
||||
vAddId, vAddIdTunnel = GetSplitSurfaces( Proc, Part, bAddMachining)
|
||||
|
||||
-- si applicano le lavorazioni
|
||||
for i = 1, #vAddId do
|
||||
for j = 1, #Strategy.Machining do
|
||||
if Strategy.Machining[j].bIsApplicable then
|
||||
Pocketing = MachiningLib.InitMachiningParameters( MCH_MY.POCKETING)
|
||||
Pocketing.Steps = {}
|
||||
Pocketing.LeadIn = {}
|
||||
Pocketing.nType = MCH_MY.POCKETING
|
||||
Pocketing.nSubType = EgtIf( Proc.Topology.sName == 'Pocket-5-Blind' or Proc.Topology.sName == 'Tunnel-4-Through', MCH_POCK_SUB.SPIRALOUT, MCH_POCK_SUB.SPIRALIN)
|
||||
Pocketing.LeadIn.nType = MCH_POCK_LI.ZIGZAG
|
||||
Pocketing.Steps.dStep = TOOLS[Strategy.Machining[j].ToolInfo.nToolIndex].dStep
|
||||
Pocketing.Steps.dSideStep = TOOLS[Strategy.Machining[j].ToolInfo.nToolIndex].dSideStep
|
||||
Pocketing.nToolIndex = Strategy.Machining[j].ToolInfo.nToolIndex
|
||||
Pocketing.LeadIn.dTangentDistance = TOOLS[Strategy.Machining[j].ToolInfo.nToolIndex].dDiameter/2
|
||||
Pocketing.LeadIn.dElevation = TOOLS[Strategy.Machining[j].ToolInfo.nToolIndex].dDiameter/2
|
||||
Pocketing.sDepth = -Strategy.Machining[j].ToolInfo.dResidualDepth
|
||||
Pocketing.dResidualDepth = Strategy.Machining[j].ToolInfo.dResidualDepth
|
||||
-- TODO vedere se questo parametro con svuotature nuove si può rimuovere
|
||||
Pocketing.dOpenMinSafe = Strategy.Parameters.dOpenMinSafe
|
||||
-- il quarto ciclo è la lavorazione opposta sulla faccia Tunnel
|
||||
if Strategy.Machining[j].bToolInvert then
|
||||
Pocketing.bToolInvert = true
|
||||
end
|
||||
-- se ho una sola trimesh, sto lavorando la Proc direttamente e non ho spezzato. Applico direttamente alla geometria calcolata prima
|
||||
if #vAddId == 1 then
|
||||
Pocketing.Geometry = {{ Strategy.Machining[j].idProc, Strategy.Machining[j].idFaceToMachine}}
|
||||
Pocketing.vtToolDirection = Strategy.Machining[j].vtFaceNormal
|
||||
|
||||
-- TODO controllare parametro danneggiamento ammesso per decidere se spostare dopo taglio seprazione
|
||||
-- se è aperta sulla coda, dico che deve essere fatta dopo la separazione
|
||||
if Proc.AffectedFaces.bLeft then
|
||||
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 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])
|
||||
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}}
|
||||
|
||||
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
|
||||
end
|
||||
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
|
||||
|
||||
return bAreAllMachiningsAdded, Strategy.Result
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return STR0002
|
||||
@@ -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": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,688 @@
|
||||
-- Strategia: STR0003
|
||||
-- Descrizione
|
||||
-- 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 FaceByBlade = require( 'FACEBYBLADE')
|
||||
local FaceByChainsaw = require( 'FACEBYCHAINSAW')
|
||||
|
||||
-- Tabella per definizione modulo
|
||||
local STR0003 = {}
|
||||
local Strategy = {}
|
||||
local Blade = {}
|
||||
local Chainsaw = {}
|
||||
Blade.Result = {}
|
||||
Chainsaw.Result = {}
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
local function IsTopologyOk( Proc)
|
||||
if Proc.Topology.bAllRightAngles and
|
||||
( Proc.Topology.sName == 'Pocket-5-Blind' or
|
||||
Proc.Topology.sName == 'Groove-3-Through' or
|
||||
Proc.Topology.sName == 'Groove-4-Blind' or
|
||||
Proc.Topology.sName == 'Tunnel-4-Through') then
|
||||
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- TODO si può unificare con eguale funzione in STR0004
|
||||
local function SortMachiningsBySegment( MachiningA, MachiningB)
|
||||
if MachiningA.nFeatureSegment > MachiningB.nFeatureSegment then
|
||||
return false
|
||||
elseif MachiningB.nFeatureSegment > MachiningA.nFeatureSegment then
|
||||
return true
|
||||
else
|
||||
if TOOLS[ MachiningA.nToolIndex].sFamily == 'SAWBLADE' and TOOLS[ MachiningB.nToolIndex].sFamily == 'MORTISE' then
|
||||
return true
|
||||
elseif TOOLS[ MachiningA.nToolIndex].sFamily == 'MORTISE' and TOOLS[ MachiningB.nToolIndex].sFamily == 'SAWBLADE' then
|
||||
return false
|
||||
else
|
||||
if MachiningA.sEdgeType == 'Side' and MachiningB.sEdgeType ~= 'Side' then
|
||||
return true
|
||||
elseif MachiningB.sEdgeType == 'Side' and MachiningA.sEdgeType ~= 'Side' then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function SortMachiningsByTool( MachiningA, MachiningB)
|
||||
if TOOLS[ MachiningA.nToolIndex].sFamily == 'SAWBLADE' and TOOLS[ MachiningB.nToolIndex].sFamily == 'MORTISE' then
|
||||
return true
|
||||
elseif TOOLS[ MachiningA.nToolIndex].sFamily == 'MORTISE' and TOOLS[ MachiningB.nToolIndex].sFamily == 'SAWBLADE' then
|
||||
return false
|
||||
else
|
||||
if MachiningA.nFeatureSegment > MachiningB.nFeatureSegment then
|
||||
return false
|
||||
elseif MachiningB.nFeatureSegment > MachiningA.nFeatureSegment then
|
||||
return true
|
||||
else
|
||||
if MachiningA.sEdgeType == 'Side' and MachiningB.sEdgeType ~= 'Side' then
|
||||
return true
|
||||
elseif MachiningB.sEdgeType == 'Side' and MachiningA.sEdgeType ~= 'Side' then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function MergeResults( Result)
|
||||
local SortedResult = {}
|
||||
|
||||
for i = 1, #Result.Side do
|
||||
if Result.Side[i].bIsApplicable then
|
||||
table.insert( SortedResult, Result.Side[i])
|
||||
end
|
||||
end
|
||||
for i = 1, #Result.Bottom do
|
||||
if Result.Bottom[i].bIsApplicable then
|
||||
table.insert( SortedResult, Result.Bottom[i])
|
||||
end
|
||||
end
|
||||
for i = 1, #Result.Opposite do
|
||||
if Result.Opposite[i].bIsApplicable then
|
||||
table.insert( SortedResult, Result.Opposite[i])
|
||||
end
|
||||
end
|
||||
|
||||
return SortedResult
|
||||
end
|
||||
|
||||
|
||||
local function AddResult( Machining, Result)
|
||||
table.insert( Result, {})
|
||||
if not Result.Bottom then
|
||||
Result.Bottom = {}
|
||||
end
|
||||
if not Result.Side then
|
||||
Result.Side = {}
|
||||
end
|
||||
if not Result.Opposite then
|
||||
Result.Opposite = {}
|
||||
end
|
||||
if Machining.sEdgeType == 'Bottom' then
|
||||
table.insert( Result.Bottom, Machining)
|
||||
elseif Machining.sEdgeType == 'Side' then
|
||||
table.insert( Result.Side, Machining)
|
||||
elseif Machining.sEdgeType == 'Opposite' then
|
||||
table.insert( Result.Opposite, Machining)
|
||||
else
|
||||
error('AddResult : unknown edge type')
|
||||
end
|
||||
|
||||
return Result
|
||||
end
|
||||
|
||||
|
||||
local function AddMachinings( Proc, Machinings)
|
||||
local bAreAllMachiningsAdded = true
|
||||
|
||||
for i = 1, #Machinings do
|
||||
if Machinings[i].bIsApplicable then
|
||||
local bIsMachiningAdded
|
||||
bIsMachiningAdded = MachiningLib.AddMachinings( Proc, Machinings[i])
|
||||
if not bIsMachiningAdded then
|
||||
bAreAllMachiningsAdded = false
|
||||
end
|
||||
Strategy.Result.sInfo = Strategy.Result.sInfo .. '\n' .. Machinings[i].sMessage
|
||||
end
|
||||
end
|
||||
|
||||
return bAreAllMachiningsAdded
|
||||
end
|
||||
|
||||
|
||||
function Blade.AddResult( Cutting)
|
||||
AddResult( Cutting, Blade.Result)
|
||||
end
|
||||
|
||||
|
||||
function Chainsaw.AddResult( Mortising)
|
||||
AddResult( Mortising, Chainsaw.Result)
|
||||
end
|
||||
|
||||
|
||||
local function GetTotalAreaToMachine( Machinings)
|
||||
local dTotalAreaToMachine = 0
|
||||
|
||||
for i = 1, #Machinings do
|
||||
local Machining = Machinings[i]
|
||||
dTotalAreaToMachine = dTotalAreaToMachine + Machining.dAreaToMachine
|
||||
end
|
||||
|
||||
return dTotalAreaToMachine
|
||||
end
|
||||
|
||||
|
||||
function STR0003.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 = {}
|
||||
Chainsaw.Result = {}
|
||||
|
||||
if not IsTopologyOk( Proc) then
|
||||
local sErr = 'Feature '.. Proc.idFeature .. ' : strategy ' .. Strategy.sName .. ' not implemented'
|
||||
EgtOutLog( sErr)
|
||||
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( 'Topology')
|
||||
return false, Strategy.Result
|
||||
end
|
||||
|
||||
-- se tasca su faccia sotto la strategia non è applicabile (la sega a catena in generale non può lavorare da sotto)
|
||||
-- TODO se OnlySaw questo test è da rimuovere ma bisogna considerare anche la lama da sotto
|
||||
if Proc.AffectedFaces.bBottom and ( Proc.nFct > 3 or not Proc.AffectedFaces.bTop) then
|
||||
local sErr = 'Feature '.. Proc.idFeature .. ' : strategy ' .. Strategy.sName .. ' not applicable - pocket on bottom face'
|
||||
EgtOutLog( sErr)
|
||||
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( 'Direction')
|
||||
return false, Strategy.Result
|
||||
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
|
||||
|
||||
-- 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 = {}
|
||||
-- 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
|
||||
OptionalParameters.OppositeToolDirectionMode = 'Enabled'
|
||||
Cutting = FaceByBlade.Make( Proc, Part, LongFace, OppositeEdge1, OptionalParameters)
|
||||
else
|
||||
Cutting = FaceByBlade.Make( Proc, Part, LongFace, BottomEdge, OptionalParameters)
|
||||
end
|
||||
Blade.AddResult( Cutting)
|
||||
|
||||
-- lato opposto del tunnel
|
||||
if Proc.Topology.sFamily == 'Tunnel' then
|
||||
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 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 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, escluse le lavorazioni non applicabili
|
||||
Blade.Result.Sorted = MergeResults( Blade.Result)
|
||||
|
||||
-- lama - calcolo area lavorata
|
||||
local dAreaToMachineBlade = GetTotalAreaToMachine( Blade.Result.Sorted)
|
||||
|
||||
-- lama - aggiunta eventuali lavorazioni splittate
|
||||
if bIsSplitFeature then
|
||||
Blade.Result.Sorted = MachiningLib.GetSplitMachinings( Blade.Result.Sorted, FeatureSplittingPoints, Part)
|
||||
end
|
||||
|
||||
-- lama - nessuna lavorazione successiva - aggiunta lavorazioni e calcolo risultati
|
||||
if not Strategy.Parameters.bFinishWithChainSaw then
|
||||
|
||||
-- ordinamento
|
||||
if Strategy.Parameters.bSortBySegment then
|
||||
table.sort( Blade.Result.Sorted, SortMachiningsBySegment)
|
||||
else
|
||||
table.sort( Blade.Result.Sorted, SortMachiningsByTool)
|
||||
end
|
||||
|
||||
-- aggiunta lavorazioni
|
||||
local bAreAllMachiningsAdded = true
|
||||
if bAddMachining then
|
||||
bAreAllMachiningsAdded = AddMachinings( Proc, Blade.Result.Sorted)
|
||||
end
|
||||
|
||||
-- calcolo risultati
|
||||
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( Blade.Result.Sorted)
|
||||
Strategy.Result.dCompletionPercentage = dAreaToMachineBlade / LongFace.dArea * 100
|
||||
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( Strategy.Result.dCompletionPercentage)
|
||||
Strategy.Result.dTimeToMachine = FeatureLib.GetStrategyTimeToMachine( Blade.Result.Sorted)
|
||||
Strategy.Result.dMRR = ( dFeatureVolume / Strategy.Result.dTimeToMachine) / pow( 10, 6)
|
||||
if #Blade.Result.Sorted > 0 then
|
||||
if not Strategy.Parameters.bNotCompleteWithBladeRadius and Cutting.dCompletionPercentage > 100 - 10 * GEO.EPS_SMALL then
|
||||
Strategy.Result.sStatus = 'Completed'
|
||||
else
|
||||
Strategy.Result.sStatus = 'Not-Completed'
|
||||
end
|
||||
-- non ha senso che STR0003 lama+catena sia applicabile se la lama non può lavorare, in quel caso deve essere scelta la STR0004 solo catena
|
||||
else
|
||||
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable()
|
||||
Strategy.Parameters.bFinishWithChainSaw = false
|
||||
end
|
||||
|
||||
return bAreAllMachiningsAdded, Strategy.Result
|
||||
end
|
||||
|
||||
-- TODO funzione separata
|
||||
-- sega a catena - calcolo lavorazioni
|
||||
local Mortising = {}
|
||||
-- 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
|
||||
( BottomEdge.dLength > 3 * Blade.Result.Bottom[1].dToolMarkLength - 10 * GEO.EPS_SMALL) then
|
||||
|
||||
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 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
|
||||
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
|
||||
|
||||
-- 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 ( 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 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
|
||||
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 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
|
||||
|
||||
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
|
||||
|
||||
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.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
|
||||
|
||||
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
|
||||
|
||||
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.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
|
||||
end
|
||||
end
|
||||
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 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.sSideToMachine = 'End'
|
||||
|
||||
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, OppositeEdge1, OptionalParameters)
|
||||
Mortising.dAreaToMachine = 0
|
||||
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
|
||||
or Chainsaw.Result.Opposite[2].dResidualDepth > 10 * GEO.EPS_SMALL then
|
||||
|
||||
Chainsaw.Result.Opposite[1].bIsApplicable = false
|
||||
Chainsaw.Result.Opposite[2].bIsApplicable = false
|
||||
|
||||
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.sSideToMachine = 'End'
|
||||
OptionalParameters.dLengthToMachine = Blade.Result.Opposite[1].dToolMarkLength
|
||||
|
||||
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, OppositeEdge1, OptionalParameters)
|
||||
Mortising.dAreaToMachine = 0
|
||||
Chainsaw.AddResult( Mortising)
|
||||
|
||||
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.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
|
||||
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
|
||||
|
||||
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.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 bIsSplitFeature then
|
||||
Chainsaw.Result.Sorted = MachiningLib.GetSplitMachinings( Chainsaw.Result.Sorted, FeatureSplittingPoints, Part)
|
||||
end
|
||||
|
||||
-- tutte le lavorazioni di tutti gli utensili in unica lista
|
||||
local Result = {}
|
||||
for i = 1, #Blade.Result.Sorted do
|
||||
table.insert( Result, Blade.Result.Sorted[i])
|
||||
end
|
||||
for i = 1, #Chainsaw.Result.Sorted do
|
||||
table.insert( Result, Chainsaw.Result.Sorted[i])
|
||||
end
|
||||
|
||||
-- ordinamento
|
||||
if Strategy.Parameters.bSortBySegment then
|
||||
table.sort( Result, SortMachiningsBySegment)
|
||||
else
|
||||
table.sort( Result, SortMachiningsByTool)
|
||||
end
|
||||
|
||||
-- aggiunta lavorazioni per tutti gli utensili
|
||||
local bAreAllMachiningsAdded = true
|
||||
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'
|
||||
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 = FeatureLib.GetStrategyResultNotApplicable()
|
||||
end
|
||||
|
||||
return bAreAllMachiningsAdded, Strategy.Result
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return STR0003
|
||||
@@ -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": ""
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,327 @@
|
||||
-- Strategia: STR0004
|
||||
-- Descrizione
|
||||
-- motosega per slot
|
||||
-- Feature: tipo lapjoint
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-- TODO
|
||||
-- 1 - Inserire antischeggia (fresa o lama)
|
||||
-- 2 - Smusso a V
|
||||
-- 3 - Implementare lavorazione di geometrie inclinate
|
||||
-- 4 - Gestire lavorazioni da sotto (ove possibile, in generale la motosega non lavora da sotto)
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
-- carico librerie
|
||||
local BeamLib = require( 'BeamLib')
|
||||
local BeamData = require( 'BeamData')
|
||||
local MachiningLib = require( 'MachiningLib')
|
||||
local FeatureLib = require( 'FeatureLib')
|
||||
-- strategie di base
|
||||
local FaceByChainsaw = require( 'FACEBYCHAINSAW')
|
||||
|
||||
-- Tabella per definizione modulo
|
||||
local STR0004 = {}
|
||||
local Strategy = {}
|
||||
local Chainsaw = {}
|
||||
Chainsaw.Result = {}
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
local function IsTopologyOk( Proc)
|
||||
if Proc.Topology.bAllRightAngles and
|
||||
( Proc.Topology.sName == 'Pocket-5-Blind' or
|
||||
Proc.Topology.sName == 'Groove-3-Through' or
|
||||
Proc.Topology.sName == 'Groove-4-Blind' or
|
||||
Proc.Topology.sName == 'Tunnel-4-Through') then
|
||||
|
||||
return true
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- TODO si può unificare con Sorting generale
|
||||
local function SortMachiningsBySegment( MachiningA, MachiningB)
|
||||
if MachiningA.nFeatureSegment > MachiningB.nFeatureSegment then
|
||||
return false
|
||||
elseif MachiningB.nFeatureSegment > MachiningA.nFeatureSegment then
|
||||
return true
|
||||
else
|
||||
if MachiningA.sEdgeType == 'Side' and MachiningB.sEdgeType ~= 'Side' then
|
||||
return true
|
||||
elseif MachiningB.sEdgeType == 'Side' and MachiningA.sEdgeType ~= 'Side' then
|
||||
return false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
local function AddResult( Machining, Result)
|
||||
table.insert( Result, {})
|
||||
if not Result.Bottom then
|
||||
Result.Bottom = {}
|
||||
end
|
||||
if not Result.Side then
|
||||
Result.Side = {}
|
||||
end
|
||||
if not Result.Opposite then
|
||||
Result.Opposite = {}
|
||||
end
|
||||
if Machining.sEdgeType == 'Bottom' then
|
||||
table.insert( Result.Bottom, Machining)
|
||||
elseif Machining.sEdgeType == 'Side' then
|
||||
table.insert( Result.Side, Machining)
|
||||
elseif Machining.sEdgeType == 'Opposite' then
|
||||
table.insert( Result.Opposite, Machining)
|
||||
else
|
||||
error('AddResult : unknown edge type')
|
||||
end
|
||||
|
||||
return Result
|
||||
end
|
||||
|
||||
|
||||
function Chainsaw.AddResult( Mortising)
|
||||
AddResult( Mortising, Chainsaw.Result)
|
||||
end
|
||||
|
||||
|
||||
local function GetTotalAreaToMachine( Machinings)
|
||||
local dTotalAreaToMachine = 0
|
||||
|
||||
for i = 1, #Machinings do
|
||||
local Machining = Machinings[i]
|
||||
dTotalAreaToMachine = dTotalAreaToMachine + Machining.dAreaToMachine
|
||||
end
|
||||
|
||||
return dTotalAreaToMachine
|
||||
end
|
||||
|
||||
|
||||
function STR0004.Make( bAddMachining, Proc, Part, CustomParameters)
|
||||
-- carico parametri da default e li aggiorno con quelli passati dal chiamante (potrebbero non essere congruenti)
|
||||
local StrategyLib = {}
|
||||
StrategyLib.Config = STRATEGIES_CONFIG[CustomParameters.sStrategyId]
|
||||
Strategy.sName = StrategyLib.Config.sStrategyId
|
||||
Strategy.Parameters = BeamLib.LoadCustomParametersInStrategy( Proc, Part, CustomParameters, StrategyLib.Config)
|
||||
Strategy.Result = {}
|
||||
Strategy.Result.sInfo = ''
|
||||
Chainsaw.Result = {}
|
||||
|
||||
if not IsTopologyOk( Proc) then
|
||||
local sErr = 'Feature '.. Proc.idFeature .. ' : strategy ' .. Strategy.sName .. ' not implemented'
|
||||
EgtOutLog( sErr)
|
||||
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( 'Topology')
|
||||
return false, Strategy.Result
|
||||
end
|
||||
|
||||
-- se tasca su faccia sotto la strategia non è applicabile (la sega a catena in generale non può lavorare da sotto)
|
||||
if Proc.AffectedFaces.bBottom and ( Proc.nFct > 3 or not Proc.AffectedFaces.bTop) then
|
||||
local sErr = 'Feature '.. Proc.idFeature .. ' : strategy ' .. Strategy.sName .. ' not applicable - pocket on bottom face'
|
||||
EgtOutLog( sErr)
|
||||
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable( 'Direction')
|
||||
return false, Strategy.Result
|
||||
end
|
||||
|
||||
-- calcolo estensione oltre la coda
|
||||
local dExtendAfterTail = Strategy.Parameters.dExtendAfterTail or max( Part.dDistanceToNextPiece - BeamData.CUT_EXTRA, 0)
|
||||
if MachiningLib.CanExtendAfterTail( Strategy.Parameters.sCanDamageNextPiece, Part) then
|
||||
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 = {}
|
||||
-- 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
|
||||
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, BottomEdge, OptionalParameters)
|
||||
Chainsaw.AddResult( Mortising)
|
||||
|
||||
-- materiale residuo - se possibile si lavora dal lato
|
||||
if ( Chainsaw.Result.Bottom[#Chainsaw.Result.Bottom].dResidualDepth > 10 * GEO.EPS_SMALL
|
||||
or not Chainsaw.Result.Bottom[#Chainsaw.Result.Bottom].bIsApplicable)
|
||||
and #Proc.MainFaces.SideFaces == 1 then
|
||||
|
||||
OptionalParameters.OppositeToolDirectionMode = 'Enabled'
|
||||
|
||||
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
|
||||
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, BottomEdge, OptionalParameters)
|
||||
Chainsaw.AddResult( Mortising)
|
||||
|
||||
-- materiale residuo - si lavorano i lati
|
||||
if ( Chainsaw.Result.Bottom[1].dResidualDepth > 10 * GEO.EPS_SMALL or
|
||||
not Chainsaw.Result.Bottom[#Chainsaw.Result.Bottom].bIsApplicable) then
|
||||
|
||||
OptionalParameters.dDepthToMachine = SideEdge1.dElevation + BeamData.CUT_EXTRA
|
||||
OptionalParameters.OppositeToolDirectionMode = 'Enabled'
|
||||
|
||||
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, SideEdge1, OptionalParameters)
|
||||
Mortising.dAreaToMachine = Mortising.dDepthToMachine * ( Mortising.dEdgeLength - Chainsaw.Result.Bottom[1].dDepthToMachine)
|
||||
Chainsaw.AddResult( Mortising)
|
||||
|
||||
-- ancora materiale residuo - si lavora da entrambi i lati
|
||||
if Chainsaw.Result.Side[1].dResidualDepth > 10 * GEO.EPS_SMALL then
|
||||
|
||||
Chainsaw.Result.Side[1].bIsApplicable = false
|
||||
|
||||
OptionalParameters.bExtendWithCornerRadius = true
|
||||
OptionalParameters.dDepthToMachine = SideEdge1.dElevation / 2 + BeamData.CUT_EXTRA_MIN
|
||||
|
||||
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, SideEdge1, OptionalParameters)
|
||||
Mortising.dAreaToMachine = Mortising.dDepthToMachine * ( Mortising.dEdgeLength - Chainsaw.Result.Bottom[1].dDepthToMachine)
|
||||
Chainsaw.AddResult( Mortising)
|
||||
|
||||
OptionalParameters.dDepthToMachine = SideEdge2.dElevation / 2 + BeamData.CUT_EXTRA_MIN
|
||||
|
||||
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, SideEdge2, OptionalParameters)
|
||||
Mortising.dAreaToMachine = Mortising.dDepthToMachine * ( Mortising.dEdgeLength - Chainsaw.Result.Bottom[1].dDepthToMachine)
|
||||
Chainsaw.AddResult( Mortising)
|
||||
|
||||
-- lavorando dai due lati non c'è materiale residuo - si può disabilitare la lavorazione del fondo
|
||||
if Chainsaw.Result.Side[2].dResidualDepth < 10 * GEO.EPS_SMALL then
|
||||
Chainsaw.Result.Bottom[1].bIsApplicable = false
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
elseif Proc.Topology.sName == 'Tunnel-4-Through' then
|
||||
|
||||
OptionalParameters.dDepthToMachine = OppositeEdge1.dElevation + BeamData.CUT_EXTRA
|
||||
OptionalParameters.OppositeToolDirectionMode = 'Enabled'
|
||||
OptionalParameters.bExtendWithCornerRadius = true
|
||||
|
||||
Mortising = FaceByChainsaw.Make( Proc, Part, LongFace, OppositeEdge1, OptionalParameters)
|
||||
Chainsaw.AddResult( Mortising)
|
||||
|
||||
-- se 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
|
||||
|
||||
OptionalParameters.dDepthToMachine = OppositeEdge1.dElevation / 2 + BeamData.CUT_EXTRA_MIN
|
||||
|
||||
FaceByChainsaw.Make( Proc, Part, LongFace, OppositeEdge1, OptionalParameters)
|
||||
Chainsaw.AddResult( Mortising)
|
||||
|
||||
OptionalParameters.dDepthToMachine = OppositeEdge2.dElevation / 2 + BeamData.CUT_EXTRA_MIN
|
||||
|
||||
FaceByChainsaw.Make( Proc, Part, LongFace, OppositeEdge2, OptionalParameters)
|
||||
Chainsaw.AddResult( Mortising)
|
||||
end
|
||||
end
|
||||
|
||||
-- lavorazioni raggruppate in unica lista
|
||||
Chainsaw.Result.Sorted = {}
|
||||
for i = 1, #Chainsaw.Result.Side do
|
||||
if Chainsaw.Result.Side[i].bIsApplicable then
|
||||
table.insert( Chainsaw.Result.Sorted, Chainsaw.Result.Side[i])
|
||||
end
|
||||
end
|
||||
for i = 1, #Chainsaw.Result.Bottom do
|
||||
if Chainsaw.Result.Bottom[i].bIsApplicable then
|
||||
table.insert( Chainsaw.Result.Sorted, Chainsaw.Result.Bottom[i])
|
||||
end
|
||||
end
|
||||
for i = 1, #Chainsaw.Result.Opposite do
|
||||
if Chainsaw.Result.Opposite[i].bIsApplicable then
|
||||
table.insert( Chainsaw.Result.Sorted, Chainsaw.Result.Opposite[i])
|
||||
end
|
||||
end
|
||||
|
||||
-- aggiunta eventuali lavorazioni splittate
|
||||
if bIsSplitFeature then
|
||||
Chainsaw.Result.Sorted = MachiningLib.GetSplitMachinings( Chainsaw.Result.Sorted, FeatureSplittingPoints, Part)
|
||||
end
|
||||
|
||||
-- ordinamento
|
||||
-- TODO aggiungere ordinamento per utensile
|
||||
table.sort( Chainsaw.Result.Sorted, SortMachiningsBySegment)
|
||||
|
||||
-- calcolo area lavorata
|
||||
local dTotalAreaToMachine = GetTotalAreaToMachine( Chainsaw.Result.Sorted)
|
||||
|
||||
-- aggiunta lavorazioni
|
||||
local bAreAllMachiningsAdded = true
|
||||
for i = 1, #Chainsaw.Result.Sorted do
|
||||
if Chainsaw.Result.Sorted[i].bIsApplicable then
|
||||
if bAddMachining then
|
||||
local bIsMachiningAdded = MachiningLib.AddMachinings( Proc, Chainsaw.Result.Sorted[i])
|
||||
if not bIsMachiningAdded then
|
||||
bAreAllMachiningsAdded = false
|
||||
end
|
||||
end
|
||||
Strategy.Result.sInfo = Strategy.Result.sInfo .. '\n' .. Chainsaw.Result.Sorted[i].sMessage
|
||||
end
|
||||
end
|
||||
|
||||
-- calcolo risultati
|
||||
Strategy.Result.dCompletionPercentage = dTotalAreaToMachine / LongFace.dArea * 100
|
||||
Strategy.Result.dCompletionIndex = FeatureLib.GetFeatureCompletionIndex( Strategy.Result.dCompletionPercentage)
|
||||
if #Chainsaw.Result.Sorted > 0 then
|
||||
if Mortising.dCompletionPercentage > 100 - 10 * GEO.EPS_SMALL then
|
||||
Strategy.Result.sStatus = 'Completed'
|
||||
else
|
||||
Strategy.Result.sStatus = 'Not-Completed'
|
||||
end
|
||||
Strategy.Result.dQuality = FeatureLib.GetStrategyQuality( Chainsaw.Result.Sorted)
|
||||
Strategy.Result.dTimeToMachine = FeatureLib.GetStrategyTimeToMachine( Chainsaw.Result.Sorted)
|
||||
Strategy.Result.dMRR = ( dFeatureVolume / Strategy.Result.dTimeToMachine) / pow( 10, 6)
|
||||
else
|
||||
Strategy.Result = FeatureLib.GetStrategyResultNotApplicable()
|
||||
end
|
||||
|
||||
return bAreAllMachiningsAdded, Strategy.Result
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return STR0004
|
||||
@@ -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
|
||||
@@ -0,0 +1,155 @@
|
||||
; Commento per evitare BOM con UTF-8
|
||||
[Comments]
|
||||
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,STR0005
|
||||
;Feature : Longitudinal Cut
|
||||
10,0,Feature,STR0005
|
||||
;Feature : Double Cut
|
||||
11,1,Feature,
|
||||
; Feature : Ridge or Valley Cut
|
||||
12,0,Feature,
|
||||
; Feature : Saw Cut
|
||||
13,0,Feature,
|
||||
; Feature : Slot
|
||||
16,0,Pocket-5-Blind,STR0002,STR0003,STR0004
|
||||
16,0,Groove-4-Blind,STR0002,STR0003,STR0004
|
||||
16,0,Groove-3-Through,STR0002,STR0003,STR0004
|
||||
16,0,Groove-3-Blind,STR0002
|
||||
16,0,Rabbet-2-Through,STR0002
|
||||
16,0,Tunnel-4-Through,STR0003,STR0004
|
||||
; Feature : Front Slot
|
||||
17,0,Pocket-5-Blind,STR0002,STR0003,STR0004
|
||||
17,0,Groove-4-Blind,STR0002,STR0003,STR0004
|
||||
17,0,Groove-3-Blind,STR0002
|
||||
17,0,Groove-3-Through,STR0002,STR0003,STR0004
|
||||
17,0,Rabbet-2-Through,STR0002
|
||||
17,0,Tunnel-4-Through,STR0003,STR0004
|
||||
; Feature : Birds Mouth
|
||||
20,0,Feature,
|
||||
; Feature : Hip or Valley Rafter Notch
|
||||
25,0,Feature,
|
||||
; Feature : Ridge Lap
|
||||
30,1,Pocket-5-Blind,STR0002,STR0003,STR0004
|
||||
30,1,Groove-4-Blind,STR0002,STR0003,STR0004
|
||||
30,1,Groove-3-Blind,STR0002
|
||||
30,1,Groove-3-Through,STR0002,STR0003,STR0004
|
||||
30,1,Rabbet-2-Through,STR0002
|
||||
30,1,Tunnel-4-Through,STR0003,STR0004
|
||||
; Feature : Lap Joint
|
||||
30,0,Pocket-5-Blind,STR0002,STR0003,STR0004
|
||||
30,0,Groove-4-Blind,STR0002,STR0003,STR0004
|
||||
30,0,Groove-3-Blind,STR0002
|
||||
30,0,Groove-3-Through,STR0002,STR0003,STR0004
|
||||
30,0,Rabbet-2-Through,STR0002
|
||||
30,0,Tunnel-4-Through,STR0003,STR0004
|
||||
; Feature : Notch/Rabbet
|
||||
32,0,Pocket-5-Blind,STR0002,STR0003,STR0004
|
||||
32,0,Groove-4-Blind,STR0002,STR0003,STR0004
|
||||
32,0,Groove-3-Blind,STR0002
|
||||
32,0,Groove-3-Through,STR0002,STR0003,STR0004
|
||||
32,0,Rabbet-2-Through,STR0002
|
||||
32,0,Tunnel-4-Through,STR0003,STR0004
|
||||
; Feature : Block Haus
|
||||
33,0,Feature,
|
||||
; Feature : Notch
|
||||
34,0,Pocket-5-Blind,STR0002,STR0003,STR0004
|
||||
34,0,Groove-4-Blind,STR0002,STR0003,STR0004
|
||||
34,0,Groove-3-Blind,STR0002
|
||||
34,0,Groove-3-Through,STR0002,STR0003,STR0004
|
||||
34,0,Rabbet-2-Through,STR0002
|
||||
34,0,Tunnel-4-Through,STR0003,STR0004
|
||||
; Feature : French Ridge Lap
|
||||
35,1,Feature,
|
||||
; Feature : Chamfer
|
||||
36,0,Feature,
|
||||
; Feature : Block Haus Half Lap
|
||||
37,0,Feature,
|
||||
; Feature : Block Haus Front
|
||||
38,0,Feature,
|
||||
; Feature : Pocket
|
||||
39,0,Pocket-5-Blind,STR0002,STR0003,STR0004
|
||||
39,0,Groove-4-Blind,STR0002,STR0003,STR0004
|
||||
39,0,Groove-3-Blind,STR0002
|
||||
39,0,Groove-3-Through,STR0002,STR0003,STR0004
|
||||
39,0,Rabbet-2-Through,STR0002
|
||||
39,0,Tunnel-4-Through,STR0003,STR0004
|
||||
; Feature : Drilling
|
||||
40,0,Feature,
|
||||
; Feature : Tenon
|
||||
50,1,Feature,
|
||||
; Feature : Mortise
|
||||
50,0,Feature,
|
||||
; Feature : Front Mortise
|
||||
51,0,Feature,
|
||||
; Feature : House
|
||||
52,1,Feature,
|
||||
; Feature : House Mortise
|
||||
53,0,Feature,
|
||||
; Feature : Dovetail Tenon
|
||||
55,1,Feature,STR0001
|
||||
; Feature : Dovetail Mortise
|
||||
55,0,Feature,
|
||||
; Feature : Dovetail Mortise Front
|
||||
56,0,Feature,
|
||||
; Feature : Marking
|
||||
60,0,Feature,
|
||||
; Feature : Text
|
||||
61,0,Feature,
|
||||
; Feature : Scarf Simple
|
||||
70,1,Feature,
|
||||
; Feature : Scarf Joint
|
||||
71,1,Feature,
|
||||
; Feature : Step Joint
|
||||
80,1,Feature,
|
||||
; Feature : Step Joint Notch
|
||||
80,0,Feature,
|
||||
; Feature : Planing
|
||||
90,0,Feature,
|
||||
; Feature : Front Profile
|
||||
100,0,Feature,
|
||||
; Feature : Head Concave Profile
|
||||
101,0,Feature,
|
||||
; Feature : Head Convex Profile
|
||||
102,0,Feature,
|
||||
; Feature : Head Cambered Profile
|
||||
103,0,Feature,
|
||||
; Feature : Round Arch
|
||||
104,0,Feature,
|
||||
; Feature : Head Profile
|
||||
106,0,Feature,
|
||||
; Feature : Sphere
|
||||
107,0,Feature,
|
||||
; Feature : Triangle Cut
|
||||
120,0,Feature,
|
||||
; Feature : TyroleanDovetail
|
||||
136,0,Feature,
|
||||
; Feature : Dovetail
|
||||
138,0,Feature,
|
||||
; Feature : Free Contour
|
||||
250,0,Feature,
|
||||
; Feature : Outline
|
||||
251,0,Feature,
|
||||
; Feature : Aperture
|
||||
252,0,Feature,
|
||||
; Feature : Variant
|
||||
900,0,Feature,
|
||||
; Feature Decor
|
||||
959,0,Feature,
|
||||
@@ -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
|
||||
@@ -0,0 +1,263 @@
|
||||
-- Strategia: FACEBYCHAINSAW
|
||||
-- Descrizione
|
||||
-- Strategia di base per la lavorazione delle facce con sega a catena
|
||||
|
||||
-- carico librerie
|
||||
local BeamLib = require( 'BeamLib')
|
||||
local BeamData = require( 'BeamData')
|
||||
local MachiningLib = require( 'MachiningLib')
|
||||
|
||||
-- Tabella per definizione modulo
|
||||
local FACEBYCHAINSAW = {}
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
local function CalculateLeadInOut( Machining, EdgeToMachine, sSideToMachine, dLengthToMachine)
|
||||
-- TODO implementare le funzioni di Tool Collision Avoidance (vedi wiki e FacesBysaw -> CalcLeadInOutPerpGeom)
|
||||
|
||||
-- si determina l'eventuale riduzione da applicare in caso di inizio o fine chiusi
|
||||
local dAddLengthToReduce = 0
|
||||
dAddLengthToReduce = TOOLS[Machining.nToolIndex].dDiameter / 2
|
||||
|
||||
if Machining.bInvert then
|
||||
Machining.bIsStartClosed, Machining.bIsEndClosed = Machining.bIsEndClosed, Machining.bIsStartClosed
|
||||
end
|
||||
|
||||
local LeadIn = {}
|
||||
local LeadOut = {}
|
||||
LeadIn.dStartAddLength = 0
|
||||
LeadOut.dEndAddLength = 0
|
||||
if sSideToMachine == 'End' then
|
||||
LeadIn.dStartAddLength = dAddLengthToReduce + dLengthToMachine + BeamData.CUT_EXTRA - EdgeToMachine.dLength
|
||||
elseif Machining.bIsStartClosed then
|
||||
LeadIn.dStartAddLength = -dAddLengthToReduce
|
||||
else
|
||||
LeadIn.dStartAddLength = BeamData.CUT_EXTRA
|
||||
end
|
||||
if sSideToMachine == 'Start' then
|
||||
LeadOut.dEndAddLength = dAddLengthToReduce + dLengthToMachine + BeamData.CUT_EXTRA - EdgeToMachine.dLength
|
||||
elseif Machining.bIsEndClosed then
|
||||
LeadOut.dEndAddLength = -dAddLengthToReduce
|
||||
else
|
||||
LeadOut.dEndAddLength = BeamData.CUT_EXTRA
|
||||
end
|
||||
|
||||
return LeadIn, LeadOut
|
||||
end
|
||||
|
||||
|
||||
-- TODO calcolo area lavorata per completamento
|
||||
function FACEBYCHAINSAW.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalParameters)
|
||||
local Mortising = MachiningLib.InitMachiningParameters( MCH_MY.MORTISING)
|
||||
Mortising.bIsApplicable = true
|
||||
Mortising.dDepthToMachine = 0
|
||||
Mortising.dResidualDepth = EdgeToMachine.dElevation
|
||||
Mortising.dCompletionPercentage = 0
|
||||
Mortising.sMessage = ''
|
||||
Mortising.idProc = Proc.id
|
||||
Mortising.sEdgeType = EdgeToMachine.sType
|
||||
Mortising.nFeatureSegment = 1
|
||||
|
||||
-- parametri opzionali
|
||||
if not OptionalParameters then
|
||||
OptionalParameters = {}
|
||||
end
|
||||
local bUseZigZagMortising = OptionalParameters.bUseZigZagMortising or false
|
||||
local sSideToMachine = OptionalParameters.sSideToMachine or ''
|
||||
local dLengthToMachine = OptionalParameters.dLengthToMachine or EdgeToMachine.dLength
|
||||
local dCustomMaxElev = OptionalParameters.dMaxElev or 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.dEdgeLength = EdgeToMachine.dLength
|
||||
if OppositeToolDirectionMode == 'Enabled' then
|
||||
Mortising.vtToolDirection = -EdgeToMachine.vtN
|
||||
else
|
||||
Mortising.vtToolDirection = EdgeToMachine.vtN
|
||||
end
|
||||
Mortising.vtEdgeDirection = EdgeToMachine.vtN ^ FaceToMachine.vtN
|
||||
Mortising.ptEdge1, _, Mortising.ptEdge2 = EgtSurfTmFacetOppositeSide( Proc.id, FaceToMachine.id, -Mortising.vtToolDirection, GDB_ID.ROOT)
|
||||
|
||||
-- ricerca utensile
|
||||
local ToolSearchParameters = {}
|
||||
local ToolInfo = {}
|
||||
ToolSearchParameters.vtToolDirection = Mortising.vtToolDirection
|
||||
ToolSearchParameters.bAllowTopHead = true
|
||||
ToolSearchParameters.bAllowBottomHead = true
|
||||
ToolSearchParameters.dElevation = dDepthToMachine
|
||||
ToolSearchParameters.bExtendWithCornerRadius = bExtendWithCornerRadius
|
||||
ToolInfo = MachiningLib.FindChainSaw( Proc, ToolSearchParameters)
|
||||
Mortising.nToolIndex = ToolInfo.nToolIndex
|
||||
if not TOOLS[Mortising.nToolIndex] or not TOOLS[Mortising.nToolIndex].sName then
|
||||
Mortising.sMessage = 'Chainsaw not found'
|
||||
Mortising.bIsApplicable = false
|
||||
EgtOutLog( Mortising.sMessage)
|
||||
return Mortising
|
||||
end
|
||||
|
||||
-- verifica dimensioni tasca compatibili
|
||||
-- se tasca meno spessa della sega a catena la 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
|
||||
-- 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
|
||||
EgtOutLog( Mortising.sMessage)
|
||||
return Mortising
|
||||
end
|
||||
end
|
||||
|
||||
-- parametri della lavorazione
|
||||
-- TODO gestire ToolInvert per rispettare direzione migliore di lavorazione
|
||||
-- profondità (parametro DEPTH) non usata
|
||||
Mortising.sDepth = 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 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
|
||||
dDepthToMachine = dDepthToMachine + TOOLS[Mortising.nToolIndex].dCornerRadius
|
||||
end
|
||||
if TOOLS[Mortising.nToolIndex].dMaxMaterial > dDepthToMachine - 10 * GEO.EPS_SMALL then
|
||||
Mortising.dDepthToMachine = dDepthToMachine
|
||||
Mortising.dResidualDepth = 0
|
||||
if OppositeToolDirectionMode == 'Enabled' then
|
||||
Mortising.dLongitudinalOffset = EdgeToMachine.dElevation - dDepthToMachine
|
||||
else
|
||||
Mortising.dLongitudinalOffset = 0
|
||||
end
|
||||
else
|
||||
Mortising.dDepthToMachine = TOOLS[Mortising.nToolIndex].dMaxMaterial - 1
|
||||
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 = ( 1 - Mortising.dResidualDepth / Mortising.dDepthToMachine) * 100
|
||||
-- massima elevazione
|
||||
if dCustomMaxElev < Mortising.dDepthToMachine - 10 * GEO.EPS_SMALL then
|
||||
Mortising.dMaxElev = max( dCustomMaxElev, dCustomMaxElev - Mortising.dLongitudinalOffset)
|
||||
end
|
||||
-- offset radiale
|
||||
Mortising.dRadialOffset = 0
|
||||
-- distanza di sicurezza
|
||||
Mortising.dStartSafetyLength = max( EdgeToMachine.dElevation, ( TOOLS[Mortising.nToolIndex].SetupInfo.dZSafeDelta or 60) + EgtMdbGetGeneralParam( MCH_GP.SAFEZ))
|
||||
-- overlap
|
||||
Mortising.dOverlap = 0
|
||||
-- step
|
||||
Mortising.Steps = {}
|
||||
if bUseZigZagMortising then
|
||||
Mortising.Steps.nStepType = MCH_MILL_ST.ZIGZAG
|
||||
else
|
||||
Mortising.Steps.nStepType = MCH_MILL_ST.ONEWAY
|
||||
end
|
||||
Mortising.Steps.dStep = TOOLS[Mortising.nToolIndex].dStep
|
||||
Mortising.Steps.nCount = max( 1, ceil( ( min( Mortising.dDepthToMachine, ( Mortising.dMaxElev or Mortising.dDepthToMachine)) + 10 * GEO.EPS_SMALL) / Mortising.Steps.dStep))
|
||||
-- faceuse
|
||||
if OppositeToolDirectionMode == 'Enabled' then
|
||||
Mortising.nFaceuse = BeamLib.GetNearestParalOpposite( -Mortising.vtToolDirection)
|
||||
else
|
||||
Mortising.nFaceuse = BeamLib.GetNearestParalOpposite( Mortising.vtToolDirection)
|
||||
end
|
||||
-- SCC
|
||||
Mortising.SCC = MCH_SCC.NONE
|
||||
-- asse bloccato e angoli suggeriti
|
||||
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.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.vtN, 2)
|
||||
end
|
||||
-- approccio e retrazione
|
||||
Mortising.LeadIn, Mortising.LeadOut = CalculateLeadInOut( Mortising, EdgeToMachine, sSideToMachine, dLengthToMachine)
|
||||
-- eventuale step verticale
|
||||
Mortising.CloneStepsLongitudinal = {}
|
||||
if not dLongitudinalStepSpan then
|
||||
dLongitudinalStepSpan = dPocketHeight
|
||||
end
|
||||
if dLongitudinalStepSpan > 10 * GEO.EPS_SMALL then
|
||||
Mortising.CloneStepsLongitudinal = MachiningLib.GetMachiningSteps( dLongitudinalStepSpan, TOOLS[Mortising.nToolIndex].dThickness)
|
||||
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
|
||||
Mortising.sOperationName = 'Chainsaw_' .. ( EgtGetName( Mortising.idProc) or tostring( Mortising.idProc)) .. '_' .. tostring( FaceToMachine.id + 1)
|
||||
|
||||
-- se lavorazione aperta sulla coda, eventuali aggiustamenti
|
||||
-- TODO valutare se fare funzione a parte
|
||||
if Proc.AffectedFaces.bLeft and ( EdgeToMachine.sType == 'Bottom' or ( Mortising.vtToolDirection:getX() < 0.707)) then
|
||||
local dLengthOnX = Mortising.dLengthOnX
|
||||
-- se feature splittata non si considera la lunghezza della feature per il check spostamento dopo separazione
|
||||
if bIsSplitFeature then
|
||||
dLengthOnX = 0
|
||||
end
|
||||
local bStartLeft = MachiningLib.StartsLeftSide( Mortising)
|
||||
local dAddLengthLeftSide = Mortising.LeadOut.dEndAddLength
|
||||
if bStartLeft then
|
||||
dAddLengthLeftSide = Mortising.LeadIn.dStartAddLength
|
||||
end
|
||||
if not AreSameOrOppositeVectorApprox( EdgeToMachine.vtN, Y_AX()) then
|
||||
if MachiningLib.CanMoveAfterSplitcut( dLengthOnX, Part) then
|
||||
Mortising.sStage = 'AfterTail'
|
||||
else
|
||||
Mortising.bIsApplicable = false
|
||||
end
|
||||
elseif dAddLengthLeftSide + TOOLS[Mortising.nToolIndex].dDiameter / 2 > dExtendAfterTail then
|
||||
if MachiningLib.CanMoveAfterSplitcut( dLengthOnX, Part) then
|
||||
Mortising.sStage = 'AfterTail'
|
||||
else
|
||||
if bStartLeft then
|
||||
Mortising.LeadIn.dStartAddLength = - TOOLS[Mortising.nToolIndex].dDiameter / 2 + dExtendAfterTail
|
||||
else
|
||||
Mortising.LeadOut.dEndAddLength = - TOOLS[Mortising.nToolIndex].dDiameter / 2 + dExtendAfterTail
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return Mortising
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return FACEBYCHAINSAW
|
||||
@@ -0,0 +1,440 @@
|
||||
-- Strategia: FACEBYMILL
|
||||
-- Descrizione
|
||||
-- Strategia di base per la lavorazione delle facce con fresa
|
||||
|
||||
-- carico librerie
|
||||
local BeamLib = require( 'BeamLib')
|
||||
local BeamData = require( 'BeamData')
|
||||
local MachiningLib = require( 'MachiningLib')
|
||||
|
||||
-- Tabella per definizione modulo
|
||||
local FACEBYMILL = {}
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
local function GetLeadInOutType( Machining)
|
||||
local sLeadInOutType = ''
|
||||
|
||||
if Machining.bIsStartClosed or Machining.bIsEndClosed 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 then
|
||||
sLeadInOutType = 'Perpendicular'
|
||||
else
|
||||
sLeadInOutType = 'Tangent'
|
||||
end
|
||||
elseif abs( Machining.vtEdgeDirection:getZ()) < 0.7 then
|
||||
sLeadInOutType = 'Tangent'
|
||||
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 then
|
||||
sLeadInOutType = 'Perpendicular'
|
||||
else
|
||||
sLeadInOutType = 'Tangent'
|
||||
end
|
||||
elseif abs( Machining.vtEdgeDirection:getZ()) > 0.7 then
|
||||
sLeadInOutType = 'Tangent'
|
||||
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)
|
||||
|
||||
-- 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 = {}
|
||||
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 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
|
||||
LeadIn.dTangentDistance = TOOLS[Machining.nToolIndex].dDiameter / 2
|
||||
LeadOut.dTangentDistance = TOOLS[Machining.nToolIndex].dDiameter / 2
|
||||
end
|
||||
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
|
||||
-- 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
|
||||
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
|
||||
end
|
||||
LeadIn.dTotalEstimatedDistance = sqrt( dEstimatedLeadInPerpDistance ^ 2 + dEstimatedLeadInTangentDistance ^ 2) + Machining.dStartSafetyLength
|
||||
LeadOut.dTotalEstimatedDistance = sqrt( dEstimatedLeadOutPerpDistance ^ 2 + dEstimatedLeadOutTangentDistance ^ 2) + Machining.dStartSafetyLength
|
||||
|
||||
return LeadIn, LeadOut
|
||||
end
|
||||
|
||||
|
||||
local function GetSCC( vtMachiningDirection)
|
||||
-- TODO implementare SCC come per FacesBySaw
|
||||
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 calcolo area lavorata per completamento
|
||||
function FACEBYMILL.Make( Proc, Part, FaceToMachine, EdgeToMachine, OptionalParameters)
|
||||
local Milling = MachiningLib.InitMachiningParameters( MCH_MY.MILLING)
|
||||
Milling.bIsApplicable = true
|
||||
Milling.dDepthToMachine = 0
|
||||
Milling.sMessage = ''
|
||||
Milling.idProc = Proc.id
|
||||
Milling.dResidualDepth = EdgeToMachine.dElevation
|
||||
Milling.dCompletionPercentage = 0
|
||||
Milling.dToolMarkLength = 0
|
||||
Milling.sEdgeType = EdgeToMachine.sType
|
||||
Milling.nFeatureSegment = 1
|
||||
|
||||
-- parametri opzionali
|
||||
if not OptionalParameters then
|
||||
OptionalParameters = {}
|
||||
end
|
||||
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 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
|
||||
Milling.dEdgeLength = EdgeToMachine.dLength
|
||||
if OppositeToolDirectionMode == 'Enabled' then
|
||||
Milling.vtToolDirection = -EdgeToMachine.vtN
|
||||
else
|
||||
Milling.vtToolDirection = EdgeToMachine.vtN
|
||||
end
|
||||
Milling.vtEdgeDirection = EdgeToMachine.vtN ^ FaceToMachine.vtN
|
||||
-- TODO conviene spostare questi calcoli nel FaceData?
|
||||
Milling.ptEdge1, _, Milling.ptEdge2 = EgtSurfTmFacetOppositeSide( Proc.id, FaceToMachine.id, -Milling.vtToolDirection, GDB_ID.ROOT)
|
||||
|
||||
-- se si conosce il limite downUp (utensile forzato o downUp forzato) si decide se invertire (ToolInvert)
|
||||
if nToolIndex and not dMinNzDownUp then
|
||||
dMinNzDownUp = TOOLS[nToolIndex].SetupInfo.GetMinNzDownUp( Part.b3Raw, FaceToMachine.vtN, Milling.vtToolDirection, TOOLS[nToolIndex])
|
||||
end
|
||||
if dMinNzDownUp and FaceToMachine.vtN:getZ() < dMinNzDownUp then
|
||||
Milling.bToolInvert = true
|
||||
else
|
||||
Milling.bToolInvert = false
|
||||
end
|
||||
|
||||
-- ricerca utensile
|
||||
if nToolIndex then
|
||||
Milling.nToolIndex = nToolIndex
|
||||
else
|
||||
local ToolSearchParameters = {}
|
||||
if OptionalParameters.dPocketHeight then
|
||||
ToolSearchParameters.sMillShape = 'TSHAPEMILL'
|
||||
else
|
||||
ToolSearchParameters.sMillShape = 'STANDARD'
|
||||
end
|
||||
ToolSearchParameters.dElevation = FaceToMachine.dElevation
|
||||
-- TODO qui ToolSearchParameters.vtToolDirection andrà sosituito con vtN!!
|
||||
if Milling.bToolInvert then
|
||||
ToolSearchParameters.vtToolDirection = -FaceToMachine.vtN
|
||||
else
|
||||
ToolSearchParameters.vtToolDirection = FaceToMachine.vtN
|
||||
end
|
||||
ToolSearchParameters.bAllowTopHead = true
|
||||
-- TODO bisognerà implementare anche la lama da sotto
|
||||
ToolSearchParameters.bAllowBottomHead = false
|
||||
local ToolInfo = MachiningLib.FindMill( 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, Milling.vtToolDirection, TOOLS[ToolInfo.nToolIndex])
|
||||
if FaceToMachine.vtN:getZ() < dMinNzDownUp then
|
||||
Milling.bToolInvert = true
|
||||
end
|
||||
end
|
||||
Milling.nToolIndex = ToolInfo.nToolIndex
|
||||
end
|
||||
if not TOOLS[Milling.nToolIndex] or not TOOLS[Milling.nToolIndex].sName then
|
||||
Milling.sMessage = 'Mill not found'
|
||||
Milling.bIsApplicable = false
|
||||
EgtOutLog( Milling.sMessage)
|
||||
return Milling, EdgeToMachine.dElevation
|
||||
end
|
||||
|
||||
-- verifica dimensioni tasca compatibili
|
||||
-- se tasca meno spessa della fresa la lavorazione non è applicabile
|
||||
if OptionalParameters.dPocketHeight and TOOLS[Milling.nToolIndex].dMaxMaterial > dPocketHeight + 10 * GEO.EPS_SMALL then
|
||||
Milling.sMessage = 'Pocket too narrow for blade thickness'
|
||||
Milling.bIsApplicable = false
|
||||
EgtOutLog( Milling.sMessage)
|
||||
return Milling, EdgeToMachine.dElevation
|
||||
end
|
||||
-- se tasca chiusa da entrambi i lati e più stretta della fresa la lavorazione non è applicabile
|
||||
if not ( EdgeToMachine.bIsStartOpen or EdgeToMachine.bIsEndOpen) then
|
||||
if TOOLS[Milling.nToolIndex].dDiameter > EdgeToMachine.dLength + 10 * GEO.EPS_SMALL then
|
||||
Milling.sMessage = 'Pocket too narrow for blade diameter'
|
||||
Milling.bIsApplicable = false
|
||||
EgtOutLog( Milling.sMessage)
|
||||
return Milling, EdgeToMachine.dElevation
|
||||
end
|
||||
end
|
||||
|
||||
-- parametri della lavorazione
|
||||
-- profondità (parametro DEPTH)
|
||||
Milling.sDepth = sDepth
|
||||
-- inizio e fine aperti o chiusi
|
||||
Milling.bIsStartClosed = not EdgeToMachine.bIsStartOpen
|
||||
Milling.bIsEndClosed = not EdgeToMachine.bIsEndOpen
|
||||
-- lato di lavoro e inversione
|
||||
if TOOLS[Milling.nToolIndex].bIsCCW then
|
||||
Milling.nWorkside = MCH_MILL_WS.RIGHT
|
||||
Milling.bInvert = true
|
||||
else
|
||||
Milling.nWorkside = MCH_MILL_WS.LEFT
|
||||
Milling.bInvert = false
|
||||
end
|
||||
if OppositeToolDirectionMode == 'Enabled' then
|
||||
Milling.bInvert = not Milling.bInvert
|
||||
end
|
||||
if Milling.bToolInvert then
|
||||
Milling.bInvert = not Milling.bInvert
|
||||
end
|
||||
-- profondità da lavorare e offset radiale
|
||||
if OptionalParameters.dPocketHeight then
|
||||
if TOOLS[Milling.nToolIndex].dSideDepth > dDepthToMachine - 10 * GEO.EPS_SMALL then
|
||||
-- TODO la depth dovrebbe essere quella del machining
|
||||
Milling.dDepthToMachine = dDepthToMachine
|
||||
Milling.dResidualDepth = 0
|
||||
if OppositeToolDirectionMode == 'Enabled' then
|
||||
Milling.dRadialOffset = -dDepthToMachine
|
||||
else
|
||||
Milling.dRadialOffset = EdgeToMachine.dElevation - dDepthToMachine
|
||||
end
|
||||
else
|
||||
Milling.dDepthToMachine = TOOLS[Milling.nToolIndex].dSideDepth - 1
|
||||
Milling.dResidualDepth = dDepthToMachine - Milling.dDepthToMachine
|
||||
if OppositeToolDirectionMode == 'Enabled' then
|
||||
Milling.dRadialOffset = -Milling.dDepthToMachine
|
||||
else
|
||||
Milling.dRadialOffset = EdgeToMachine.dElevation - Milling.dDepthToMachine
|
||||
end
|
||||
end
|
||||
else
|
||||
Milling.dDepthToMachine = dDepthToMachine
|
||||
Milling.dResidualDepth = 0
|
||||
if OppositeToolDirectionMode == 'Enabled' then
|
||||
Milling.dRadialOffset = -dDepthToMachine
|
||||
else
|
||||
Milling.dRadialOffset = EdgeToMachine.dElevation - dDepthToMachine
|
||||
end
|
||||
end
|
||||
-- completamento
|
||||
Milling.dCompletionPercentage = ( 1 - Milling.dResidualDepth / Milling.dDepthToMachine) * 100
|
||||
-- step verticale e offset longitudinale
|
||||
if OptionalParameters.dPocketHeight then
|
||||
Milling.Steps = MachiningLib.GetMachiningSteps( dPocketHeight, TOOLS[Milling.nToolIndex].dMaxMaterial)
|
||||
Milling.Steps.nStepType = OptionalParameters.nStepType or MCH_MILL_ST.ONEWAY
|
||||
Milling.dMaxElev = Milling.Steps.dStep * Milling.Steps.nCount - 10 * GEO.EPS_SMALL
|
||||
else
|
||||
Milling.Steps = {}
|
||||
Milling.Steps.dStep = TOOLS[Milling.nToolIndex].dStep
|
||||
Milling.Steps.nCount = ceil( ( FaceToMachine.dElevation - 50 * GEO.EPS_SMALL) / Milling.Steps.dStep)
|
||||
Milling.Steps.nStepType = OptionalParameters.nStepType or MCH_MILL_ST.ZIGZAG
|
||||
Milling.dMaxElev = FaceToMachine.dElevation
|
||||
end
|
||||
if Milling.bToolInvert then
|
||||
if Milling.Steps.nCount > 1 then
|
||||
Milling.dLongitudinalOffset = - dPocketHeight
|
||||
else
|
||||
Milling.dLongitudinalOffset = - TOOLS[Milling.nToolIndex].dMaxMaterial - dLongitudinalOffset
|
||||
end
|
||||
else
|
||||
Milling.dLongitudinalOffset = dLongitudinalOffset
|
||||
end
|
||||
-- distanza di sicurezza
|
||||
Milling.dStartSafetyLength = BeamData.CUT_SIC
|
||||
-- overlap
|
||||
Milling.dOverlap = 0
|
||||
-- faceuse e frame lavorazione
|
||||
if OppositeToolDirectionMode == 'Enabled' then
|
||||
Milling.nFaceuse = BeamLib.GetNearestOrthoOpposite( -Milling.vtToolDirection)
|
||||
--Milling.vtFaceUse = -Milling.vtToolDirection
|
||||
Milling.nEdgesFaceUse = EdgeToMachine.id
|
||||
else
|
||||
Milling.nFaceuse = BeamLib.GetNearestOrthoOpposite( Milling.vtToolDirection)
|
||||
--Milling.vtFaceUse = Milling.vtToolDirection
|
||||
Milling.nEdgesFaceUse = EdgeToMachine.id
|
||||
end
|
||||
-- SCC
|
||||
Milling.nSCC = GetSCC( Milling.vtToolDirection)
|
||||
-- asse bloccato
|
||||
Milling.sBlockedAxis = ''
|
||||
-- eventuale step orizzontale
|
||||
Milling.CloneStepsRadial = {}
|
||||
if not dRadialStepSpan then
|
||||
dRadialStepSpan = Milling.dDepthToMachine
|
||||
end
|
||||
if dRadialStepSpan > 10 * GEO.EPS_SMALL and TOOLS[Milling.nToolIndex].dSideStep then
|
||||
Milling.CloneStepsRadial = MachiningLib.GetMachiningSteps( dRadialStepSpan, TOOLS[Milling.nToolIndex].dSideStep)
|
||||
else
|
||||
Milling.CloneStepsRadial.nCount = 1
|
||||
Milling.CloneStepsRadial.dStep = 0
|
||||
end
|
||||
-- approccio e retrazione
|
||||
Milling.LeadIn, Milling.LeadOut = CalculateLeadInOut( Milling, EdgeToMachine, bIsSplitFeature)
|
||||
-- lunghezza lavorata
|
||||
-- TODO per il calcolo del dLengthOnX si deve correggere con allungamento / accorciamento percorso
|
||||
Milling.dLengthToMachine = EdgeToMachine.dLength + Milling.LeadIn.dStartAddLength + Milling.LeadOut.dEndAddLength
|
||||
local b3BoxEdge = BBox3d( Milling.ptEdge1, Milling.ptEdge2)
|
||||
Milling.dLengthOnX = b3BoxEdge:getDimX()
|
||||
Milling.dTimeToMachine, Milling.dLengthToMachineAllStepsWithLeadInOut = MachiningLib.GetTimeToMachineAllStepsWithLeadInOut( Milling, Part)
|
||||
-- lunghezza impronta lama
|
||||
if Milling.bIsStartClosed and Milling.bIsEndClosed then
|
||||
Milling.dToolMarkLength = abs( min( Milling.LeadIn.dStartAddLength, Milling.LeadOut.dEndAddLength))
|
||||
elseif Milling.bIsStartClosed then
|
||||
Milling.dToolMarkLength = abs( Milling.LeadIn.dStartAddLength)
|
||||
elseif Milling.bIsEndClosed then
|
||||
Milling.dToolMarkLength = abs( Milling.LeadOut.dEndAddLength)
|
||||
end
|
||||
-- area lavorata
|
||||
Milling.dAreaToMachine = min( EdgeToMachine.dElevation, Milling.dDepthToMachine) * ( min( Milling.dEdgeLength, Milling.dLengthToMachine + 2 * Milling.dToolMarkLength))
|
||||
-- geometria
|
||||
Milling.Geometry = {{Milling.idProc, FaceToMachine.id}}
|
||||
-- note utente
|
||||
Milling.sUserNotes = sUserNotes
|
||||
-- nome operazione
|
||||
Milling.sOperationName = 'Milling_' .. ( EgtGetName( Milling.idProc) or tostring( Milling.idProc)) .. '_' .. tostring( FaceToMachine.id + 1)
|
||||
|
||||
-- se lavorazione aperta sulla coda, eventuali aggiustamenti
|
||||
-- TODO valutare se fare funzione a parte
|
||||
if Proc.AffectedFaces.bLeft and ( EdgeToMachine.sType == 'Bottom' or ( Milling.vtToolDirection:getX() < 0.707)) then
|
||||
local dLengthOnX = Milling.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( Milling)
|
||||
local dAddLengthLeftSide = Milling.LeadOut.dEndAddLength
|
||||
local dAddLengthToReduce = sqrt( Milling.dDepthToMachine * TOOLS[Milling.nToolIndex].dDiameter - Milling.dDepthToMachine * Milling.dDepthToMachine)
|
||||
if bStartLeft then
|
||||
dAddLengthLeftSide = Milling.LeadIn.dStartAddLength
|
||||
end
|
||||
if not AreSameOrOppositeVectorApprox( EdgeToMachine.vtN, Y_AX()) then
|
||||
if MachiningLib.CanMoveAfterSplitcut( dLengthOnX, Part) then
|
||||
Milling.sStage = 'AfterTail'
|
||||
else
|
||||
Milling.bIsApplicable = false
|
||||
end
|
||||
elseif dAddLengthLeftSide + dAddLengthToReduce > dExtendAfterTail then
|
||||
if MachiningLib.CanMoveAfterSplitcut( dLengthOnX, Part) then
|
||||
Milling.sStage = 'AfterTail'
|
||||
else
|
||||
if bStartLeft then
|
||||
Milling.LeadIn.dStartAddLength = - dAddLengthToReduce + dExtendAfterTail
|
||||
else
|
||||
Milling.LeadOut.dEndAddLength = - dAddLengthToReduce + dExtendAfterTail
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return Milling
|
||||
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
|
||||
return FACEBYMILL
|
||||
@@ -0,0 +1,51 @@
|
||||
-- SPLITCUT.lua by Egalware s.r.l. 2024/04/02
|
||||
-- Libreria di supporto a strategie con funzioni comune a strategie diverse.
|
||||
|
||||
-- Tabella per definizione modulo
|
||||
local SPLITCUT = {}
|
||||
|
||||
-- Include
|
||||
require( 'EgtBase')
|
||||
|
||||
-- Carico i dati globali
|
||||
local FeatureLib = require( 'FeatureLib')
|
||||
-- strategie di base
|
||||
local BladeToWaste = require('BLADETOWASTE')
|
||||
|
||||
EgtOutLog( ' SPLITCUT started', 1)
|
||||
|
||||
-----------------------------------------------------------------------------------
|
||||
---------------------- FUNZIONI DI SPLIT ------------------------------------------
|
||||
-----------------------------------------------------------------------------------
|
||||
|
||||
function SPLITCUT.GetMachining( Proc, Part, ParametersFromStrategy)
|
||||
local Machining = { sTypeMachining = 'None'}
|
||||
local Result = {}
|
||||
-- sTypeMachining = Blade\ ChainSawHorizontal\ ChainSawSideSingle\ ChainSawSideDouble\ ChainSawPlusBlade\ Mill\ None
|
||||
|
||||
-- se forza utilizzo motosega
|
||||
if ParametersFromStrategy.bForceChainSaw then
|
||||
-- ChainSawHorizontal (motosega)
|
||||
-- ChainSawSideSingle (motosega)
|
||||
-- ChainSawSideDouble (motosega)
|
||||
else
|
||||
-- Blade
|
||||
Machining, Result = BladeToWaste.Make( Proc, Part, ParametersFromStrategy)
|
||||
if Machining and #Machining > 0 then
|
||||
Machining.sTypeMachining = 'Blade'
|
||||
end
|
||||
-- TODO : casi con motosega da completare
|
||||
-- ChainSawPlusBlade (motosega più lama orizzontale)
|
||||
-- Mill (svuotatura)
|
||||
end
|
||||
|
||||
-- se non ho trovato neanche una lavorazione completa, non posso separare
|
||||
if Machining.sTypeMachining == 'None' then
|
||||
Result = FeatureLib.GetStrategyResultNotApplicable( 'Split not possible')
|
||||
end
|
||||
|
||||
return Machining, Result
|
||||
end
|
||||
|
||||
-------------------------------------------------------------------------------------------------------------
|
||||
return SPLITCUT
|
||||
@@ -0,0 +1,31 @@
|
||||
-- Swap.lua by Egaltech s.r.l. 2017/11/02
|
||||
-- Gestione scambio testa coda di una Trave
|
||||
|
||||
-- Intestazioni
|
||||
require( 'EgtBase')
|
||||
_ENV = EgtProtectGlobal()
|
||||
EgtEnableDebug( false)
|
||||
|
||||
|
||||
-- recupero il pezzo del primo oggetto selezionato
|
||||
local nId = EgtGetFirstSelectedObj()
|
||||
local nPartId = EgtGetParent( EgtGetParent( nId or GDB_ID.NULL) or GDB_ID.NULL)
|
||||
if not nPartId or not EgtIsPart( nPartId) then
|
||||
EgtOutBox( 'Nessuna trave selezionata', 'Swap Trave', 'ERROR')
|
||||
return
|
||||
end
|
||||
|
||||
-- recupero il box del pezzo
|
||||
local Ls = EgtGetFirstNameInGroup( nPartId, 'Box')
|
||||
local b3Solid = EgtGetBBoxGlob( Ls or GDB_ID.NULL, GDB_BB.STANDARD)
|
||||
if not b3Solid then
|
||||
local sName = EgtGetName( nPartId) or ( 'Id=' .. tonumber( nPartId))
|
||||
EgtOutBox( 'Box non definito per la trave ' .. sName, 'Swap Trave', 'ERROR')
|
||||
return
|
||||
end
|
||||
|
||||
-- eseguo rotazione di 180 gradi attorno asse Z
|
||||
EgtRotate( nPartId, b3Solid:getCenter(), Z_AX(), 180, GDB_RT.GLOB)
|
||||
EgtDraw()
|
||||
|
||||
-- end
|
||||