mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-09 09:21:46 +00:00
Compare commits
863 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 73817acdff | |||
| 3d7e8d7c6c | |||
| a701840826 | |||
| 5de2ac9042 | |||
| 573e2626ad | |||
| 9de59afd49 | |||
| 74a9671075 | |||
| 799658ff41 | |||
| bd64f42a54 | |||
| 8eab7f155e | |||
| 5351966430 | |||
| 2663c079f4 | |||
| 6747bd9c8f | |||
| 6ece295be4 | |||
| 64a9f85f25 | |||
| d8fa853308 | |||
| ce37c49624 | |||
| 0da3270c7f | |||
| fda6fc6c48 | |||
| 3865f01df9 | |||
| 6bf61d7163 | |||
| b8ad73668f | |||
| b7a3dd4164 | |||
| 566fd443db | |||
| 51b5a507cf | |||
| a44357dad5 | |||
| 8e792ebb50 | |||
| 352321364c | |||
| 2ab32e41b2 | |||
| 3fbd9d7cdf | |||
| 7a7fde0a2a | |||
| 7992bd9902 | |||
| 3182fe9c15 | |||
| e8858aeeb3 | |||
| ec79d61095 | |||
| 266236ee49 | |||
| 192e4e43a4 | |||
| b22c92e951 | |||
| 7634e71434 | |||
| dda803df2e | |||
| c3ded31a6a | |||
| f2d19ab2c3 | |||
| ab80400e16 | |||
| c88496c6a6 | |||
| 0ee07fb8cc | |||
| 36cf458498 | |||
| e7c25bf99f | |||
| 50a3c8c2f3 | |||
| f18298d1fd | |||
| d4770bdee3 | |||
| 1fb107c361 | |||
| 0fa1e2d585 | |||
| dc13f4c5cc | |||
| d197c3f49a | |||
| c05200a5c6 | |||
| 235bb198da | |||
| 40f332d674 | |||
| e8a272dc97 | |||
| 0b308770a6 | |||
| 96c8323a06 | |||
| 25573cd0e0 | |||
| ff3c7786f6 | |||
| 5f4dfcf215 | |||
| 9a89555a53 | |||
| fc69a2acbe | |||
| 85a2a5ad12 | |||
| 49c3d28a0b | |||
| a8f20b2c6b | |||
| 66fa1cedd9 | |||
| eb971d3d73 | |||
| a30a796c07 | |||
| 9e46bacc12 | |||
| b33378e135 | |||
| d42e19f491 | |||
| 2597827ab3 | |||
| 3f71efea6d | |||
| 2d279b7a7f | |||
| e5fe039fd0 | |||
| 9e14829cc1 | |||
| e867602d9d | |||
| aecc3d56b8 | |||
| e3f5d3d2b7 | |||
| 65f8b1a532 | |||
| 96b4df10ba | |||
| 98b56aea42 | |||
| ba6ba29da8 | |||
| 1112b102f7 | |||
| 04b8172ea9 | |||
| f5f3edbc79 | |||
| 30029e3dc7 | |||
| ed836f5b4a | |||
| a88b708442 | |||
| 764c3bbb85 | |||
| 382d3f1f9f | |||
| c92f607a15 | |||
| b57b7080fd | |||
| 860ff4e513 | |||
| 3546f13593 | |||
| 663966e08d | |||
| f077ebdc81 | |||
| eb888fd116 | |||
| 40b6b3bf17 | |||
| 2ef2f923d0 | |||
| 75fab58831 | |||
| ce26c6e19b | |||
| 8728fa38b9 | |||
| 3037795199 | |||
| 39ee9cd8b1 | |||
| b375bbf558 | |||
| f2cae79dea | |||
| aadc77f6b6 | |||
| 35223d968c | |||
| e106dc4502 | |||
| 2995b73c2d | |||
| 770bc6ea61 | |||
| f5736a7144 | |||
| b4120b1cab | |||
| f44ca67ab9 | |||
| 77eae1c8e8 | |||
| 02d79f0687 | |||
| 83d364574a | |||
| 688d2b7bd1 | |||
| bf35239979 | |||
| ca8e014647 | |||
| b5f63ec4f3 | |||
| aec2141128 | |||
| 778344c804 | |||
| 3ede9b254f | |||
| 8df40dc4a6 | |||
| 75dd4f3132 | |||
| be11df3dc1 | |||
| 09ac212aa9 | |||
| e159151b44 | |||
| 27f6ac0575 | |||
| f840da3ffd | |||
| 034df852b2 | |||
| f242071ebb | |||
| b6663e9189 | |||
| 39d143668c | |||
| 6ea1e378c5 | |||
| a33f30e8ce | |||
| e79fb2ff0b | |||
| 054b4d0ee2 | |||
| 43bebf4eee | |||
| 532869a48a | |||
| 6569d0031f | |||
| bfaa61e592 | |||
| 1a09ce40e9 | |||
| 6f1b40fc86 | |||
| 734eec7715 | |||
| bfabc0db0f | |||
| e71aac84dc | |||
| c156100be2 | |||
| 48c2b43a58 | |||
| 2f8cfb5a95 | |||
| 1c4cc34c1b | |||
| b81e03d9c2 | |||
| eb96858460 | |||
| 5c7e70e987 | |||
| 9093c9d419 | |||
| 02a5b8d997 | |||
| f1b5f7d558 | |||
| 742a9ecd81 | |||
| 77a497cdf7 | |||
| 00576ef574 | |||
| c26caaa58d | |||
| b260bd3877 | |||
| cd6246c382 | |||
| a96d6dacc7 | |||
| 64c711a02a | |||
| 68a2480a66 | |||
| d5e2fd5d3c | |||
| bb445663f8 | |||
| 1f7db75572 | |||
| f478ec8d6b | |||
| cf3ba334b7 | |||
| c36af110c4 | |||
| 91eac7085b | |||
| 239d1d6fd2 | |||
| 831709d514 | |||
| 5925476ed9 | |||
| 3edb3c8df3 | |||
| 72badd8427 | |||
| ff251b7a6a | |||
| dbce57ffc5 | |||
| 8ff9bcef32 | |||
| 82b2006686 | |||
| ca4181c714 | |||
| 3928dd7c9c | |||
| 925964ee2a | |||
| 7201df8d22 | |||
| 7b65108a76 | |||
| 0fbe4d80c7 | |||
| 54c689d615 | |||
| ab828b1a8b | |||
| 8ddd349f8b | |||
| 3221219f4a | |||
| 36387f348e | |||
| c39c6d81e3 | |||
| e8042de1ed | |||
| 78fd999c53 | |||
| 91d1cb79c2 | |||
| 832618b84a | |||
| e4ce53d548 | |||
| 7b92b5c7e2 | |||
| c8c08439b2 | |||
| 3476ee8fd5 | |||
| d2f331c813 | |||
| 9e9b294f44 | |||
| f824ee8ca4 | |||
| 919f673108 | |||
| b034b40b09 | |||
| 34f038530f | |||
| 1c70990b06 | |||
| 07eecad433 | |||
| ef87f0fe74 | |||
| 23c2d73e8e | |||
| 0b47fb5987 | |||
| 8a1dee532b | |||
| f0c6c4ca59 | |||
| 92cf0d9265 | |||
| 7c438b6b9b | |||
| 46454c5c94 | |||
| 73aeafb063 | |||
| e06297940f | |||
| 1652629332 | |||
| 3d8de40407 | |||
| 308457300e | |||
| 6ef96841ac | |||
| 289b2d1e9d | |||
| 96db699ad2 | |||
| 6b7eec0db6 | |||
| 80f35d0bda | |||
| df390a655d | |||
| 593fca7c3d | |||
| 9335c8a0c8 | |||
| eccc21277d | |||
| 2ce7e16537 | |||
| 49835ee303 | |||
| f5500da0af | |||
| c9552fac29 | |||
| b11b3b7fa8 | |||
| 8aecee5836 | |||
| 2f3b3011ec | |||
| 491c9203b0 | |||
| 7f2b996d23 | |||
| d2ea6f6656 | |||
| 25128e8aa8 | |||
| 30fa917e69 | |||
| 40e494996d | |||
| cfdc54064e | |||
| 6daead6b61 | |||
| 241d52f0ad | |||
| 68dd93da1d | |||
| 82703670f0 | |||
| cb8462a0d0 | |||
| 000245c26c | |||
| d97ee8eed4 | |||
| f8af28f12a | |||
| f6fab30d0a | |||
| f1a4ed702b | |||
| c4080626df | |||
| a8078e38d2 | |||
| c52fe8abf9 | |||
| b310b5aaba | |||
| 7246e75085 | |||
| 48c0378bff | |||
| 91c90e7b86 | |||
| 72abdb0569 | |||
| 7947ba4aaf | |||
| 2520a93055 | |||
| fa480d99a2 | |||
| 72c057e7a0 | |||
| 61cfb361fa | |||
| 3786cfa666 | |||
| cabc06821f | |||
| f9fef4f5f6 | |||
| 7c89d072e2 | |||
| dbb9e8c907 | |||
| 2df5b4c70e | |||
| a5aa608240 | |||
| f7454366cc | |||
| f773480917 | |||
| 89f9cd0403 | |||
| b21159c6b3 | |||
| 227f556669 | |||
| 42bd69929c | |||
| a3532b24b3 | |||
| 5486c4c8e9 | |||
| 0259d4c0cd | |||
| 66c4c61dc2 | |||
| 0f32ffe232 | |||
| 72630de77a | |||
| 9395bed72b | |||
| 507a5cab83 | |||
| a46a60996d | |||
| 3106168889 | |||
| 7e0c0c5c83 | |||
| 19205c8774 | |||
| 62b5f1d728 | |||
| 299df62758 | |||
| e58bfde500 | |||
| b60306cdbd | |||
| 61e0549e65 | |||
| 52ae759218 | |||
| 9b41614eff | |||
| 58e01751c1 | |||
| 624134d033 | |||
| 22f83b68e4 | |||
| 1b35ea122e | |||
| f1deefbcb3 | |||
| d6c020b5ee | |||
| ff4eddf38a | |||
| 2b34dc4ce7 | |||
| 530260ebe7 | |||
| 594268c860 | |||
| e5fa8a01b4 | |||
| ad934cd9a6 | |||
| 92fe325816 | |||
| 818bb9c823 | |||
| d71fad988d | |||
| ff0d6c810f | |||
| 8b72929d22 | |||
| 6452872e83 | |||
| 88d2c61453 | |||
| f777be6403 | |||
| 9aad249586 | |||
| 7168f8eeff | |||
| da306c6141 | |||
| e53c0b74b1 | |||
| cb2f58ba0f | |||
| c0c7727f36 | |||
| 60526e62b4 | |||
| 496e58418a | |||
| b976ad3880 | |||
| 31a763fe12 | |||
| 93ef2d0349 | |||
| 7828508179 | |||
| 7aa6be8e8a | |||
| 0679956add | |||
| b86f924543 | |||
| 962b8fac67 | |||
| fdcb705551 | |||
| b80ca3c167 | |||
| e8bd272189 | |||
| 25bd94e84a | |||
| 5face7170f | |||
| 434a11a502 | |||
| eb91f5179b | |||
| c6643da4ba | |||
| 18c93a13ec | |||
| 7cb582de5d | |||
| a5bb458d3d | |||
| c7f6a5e621 | |||
| 141e0240d4 | |||
| 15cd2b6075 | |||
| fab8b5b702 | |||
| 844f4c4944 | |||
| 03809b3d5e | |||
| 3e268be5c7 | |||
| 6e932ec2fb | |||
| 58414777be | |||
| 14f1acadb7 | |||
| f215670381 | |||
| 11df5065e4 | |||
| ed47b6b227 | |||
| 6216ee9a98 | |||
| 848d6b294e | |||
| 795a372ac9 | |||
| 03a6ee9121 | |||
| 5299a9d8a2 | |||
| a5d5d72064 | |||
| b6f2a76385 | |||
| ea6c8fe2f8 | |||
| c7268b6f42 | |||
| 5937ed4b63 | |||
| 8f650c56e5 | |||
| 1d972a6a6f | |||
| 70a1d7d345 | |||
| 519d59effe | |||
| 7f5f67b131 | |||
| 8c64d9ddcc | |||
| 397f333db0 | |||
| b01bd8afb3 | |||
| 1dd8624825 | |||
| bc0c2e641b | |||
| f5f68ea150 | |||
| 76ce117b46 | |||
| 52cad9d11c | |||
| 58af81e256 | |||
| fc2da4ee8f | |||
| c04fa12051 | |||
| 623d2b5be1 | |||
| 46319634fb | |||
| 91d2e5ccd1 | |||
| d23e32c64a | |||
| 764efa1fed | |||
| b051adcc6c | |||
| b815719477 | |||
| 0612d2b615 | |||
| 0da210b732 | |||
| 9429e478fe | |||
| 2f6c50d9c2 | |||
| 640341715c | |||
| 42878e325e | |||
| ac5cf95f9e | |||
| c9189055c7 | |||
| 6a08993f5e | |||
| df2a50b335 | |||
| c7543ff48d | |||
| 1f75fa09ae | |||
| 94ce8e2c9c | |||
| 85e94d2cfc | |||
| c2b332da48 | |||
| 6ee4edd0a0 | |||
| 0d757027e3 | |||
| 9ffe56e64d | |||
| 37a9a1b5d9 | |||
| c30c9d50c9 | |||
| 8e64b55290 | |||
| b45001a95a | |||
| fd65009f5a | |||
| 52036e9bd4 | |||
| 5399767898 | |||
| f96d477d2b | |||
| d5f3991d06 | |||
| 2f2e81f585 | |||
| 0b7442b288 | |||
| 229c7285c2 | |||
| 4fb99d2eed | |||
| 123557939f | |||
| 3c396d3180 | |||
| 5d39603308 | |||
| b792673f88 | |||
| cf65612a96 | |||
| 50bbe849ff | |||
| dc438b2560 | |||
| 6750dd927c | |||
| 9fb1986cad | |||
| 60f8d30fc1 | |||
| 67be2e8ce8 | |||
| 2557580500 | |||
| c0d2ac6ff9 | |||
| 52c168051e | |||
| e072da8d65 | |||
| 8a63275db0 | |||
| 69be3a005c | |||
| ad9ad3f060 | |||
| f0e5304b8e | |||
| c6454803ee | |||
| e8aa8c44e5 | |||
| 48b237ab54 | |||
| 608b3e5401 | |||
| c5d38227fc | |||
| e98ff136c2 | |||
| 02ebc80525 | |||
| 66431158b5 | |||
| dd044c8516 | |||
| 55763ea7df | |||
| 8fe92e810f | |||
| c26988b292 | |||
| 46e70c92c5 | |||
| 325c3665d9 | |||
| 9a80dc14e9 | |||
| 6bda066e1b | |||
| 912b01587b | |||
| 5d4d953320 | |||
| 11ed8cc787 | |||
| d1a7b99eda | |||
| 85bdeaeef4 | |||
| a5f0de4d19 | |||
| cb3392ec70 | |||
| 1dbe42061d | |||
| a024d5c07f | |||
| ea5e3c30b6 | |||
| ebfc8ef619 | |||
| c0d8467154 | |||
| d0adbab9c2 | |||
| 8e80f456cb | |||
| 61bd98e7db | |||
| 4bf0d9ccff | |||
| 1e36ac8740 | |||
| af864e8556 | |||
| 8cd9fb9015 | |||
| d9fdc0908a | |||
| a218ce5160 | |||
| b3a6b8e07f | |||
| 52700452d9 | |||
| aab011f7bf | |||
| 5f129e2357 | |||
| 4e76f36af1 | |||
| 6f3ff51d91 | |||
| 0de0422c2e | |||
| 98de86e0ba | |||
| 142e41b3ad | |||
| 1e0dc7749d | |||
| 0f29de0391 | |||
| 9933cc1b20 | |||
| fa6192e9bc | |||
| bfd4559da8 | |||
| 01f52e069e | |||
| 2fbc9e4424 | |||
| ba97da20eb | |||
| 44f5be142f | |||
| 2f951d352b | |||
| 8b23c615c3 | |||
| 7c694e5b3e | |||
| 8eeb212003 | |||
| 7bf8d58cde | |||
| b6e24559e5 | |||
| 0d87d5927e | |||
| dfd5cc4728 | |||
| 20b7ee009d | |||
| 19a3f56941 | |||
| 3b298d44c1 | |||
| 038d3bc41c | |||
| 235e89ae14 | |||
| e2de9efc33 | |||
| 8126085037 | |||
| bbe14834e4 | |||
| 45f2d301b3 | |||
| 2ecd11d71f | |||
| b42f072bd5 | |||
| 3b3668eedf | |||
| 7f7f353131 | |||
| 53594de1ff | |||
| 4fbbfb5191 | |||
| 4e1daea838 | |||
| d8ff83da73 | |||
| a7712a923f | |||
| 01b5f8f237 | |||
| b9ad15c50f | |||
| db06cff997 | |||
| f0028c0094 | |||
| 1c954801b0 | |||
| 973e4f0064 | |||
| be5d291bd9 | |||
| cbec56c2f0 | |||
| 880d0ba753 | |||
| db85689364 | |||
| 48a0d8c508 | |||
| df4cd493ee | |||
| 74132dcd49 | |||
| ef72cd3250 | |||
| 5cf1dd4249 | |||
| 29bd30d3bf | |||
| 3f8a0a91b3 | |||
| 416a572664 | |||
| 388c72360d | |||
| b841afc2e4 | |||
| f10d340254 | |||
| 0d0b91ee9b | |||
| 4f1e59a613 | |||
| 5960e4153c | |||
| 8032333a17 | |||
| 712ec6def3 | |||
| 0d43ef0736 | |||
| b318509cba | |||
| f3b541f00a | |||
| 4f64dcdbd4 | |||
| 68acf84e26 | |||
| aaceb923ad | |||
| 074de2741a | |||
| 0e4bc320cb | |||
| 9e9412bec0 | |||
| 7e92471ac9 | |||
| 078a7eb290 | |||
| df3876b438 | |||
| d414de450b | |||
| 9e89bb5044 | |||
| aa0c42e1ec | |||
| a4daa0e3d9 | |||
| 162ac39570 | |||
| 8c73fa69a1 | |||
| 159eeeb3a4 | |||
| 66f735fde9 | |||
| 1a3aa7f031 | |||
| ac41a9e63a | |||
| eb0873996f | |||
| c85826ef2e | |||
| 627cf63a4c | |||
| 744c08e13e | |||
| dd7a6a80eb | |||
| ab807e3b9b | |||
| c35be50c83 | |||
| 37ab9c80e3 | |||
| 7ff98d2918 | |||
| 35d66f5d8c | |||
| 3f018a4195 | |||
| 578e15adb2 | |||
| c4474455e9 | |||
| 8f43854cbf | |||
| 787149da13 | |||
| 3b31f6932a | |||
| 6c9e130ca8 | |||
| 86a234d17e | |||
| f68baee5c3 | |||
| 0028fd3e9c | |||
| f5f9862b78 | |||
| f38952dc51 | |||
| 24eb149221 | |||
| ce8598a0b4 | |||
| fb9cf75412 | |||
| 68f5df73b9 | |||
| e068c523ec | |||
| aa182bf047 | |||
| 6e9639446d | |||
| c48c1c3b32 | |||
| 14224ac538 | |||
| 58be92d3fc | |||
| 7107a91f6f | |||
| 438ed22f8f | |||
| a9dfc9a9fd | |||
| f8b09b3525 | |||
| f1ab02b311 | |||
| 4e833e26ca | |||
| 25df2f6414 | |||
| 42719d3fe3 | |||
| 1f6d23c19c | |||
| 94db9ec522 | |||
| a47c57c22c | |||
| 8f4bc0ea00 | |||
| dd70b09fb1 | |||
| c930050da6 | |||
| 55a7a72e61 | |||
| ca2ae36d41 | |||
| 81b4e42ca2 | |||
| 55e61b55d8 | |||
| a99529cb1e | |||
| bf43efe509 | |||
| da7f5b015b | |||
| 3de9915389 | |||
| 418444a196 | |||
| 171251b27d | |||
| 9fef920a6f | |||
| 5bff837a61 | |||
| 05f6f4efab | |||
| e4f5b0e3d8 | |||
| 49b733f660 | |||
| 36ed618adf | |||
| 48042011e2 | |||
| 0e1939a871 | |||
| bea1e61739 | |||
| 72cd82f450 | |||
| befa059591 | |||
| 7229f7271c | |||
| 9c5970e757 | |||
| 2fe3f0a9df | |||
| 3929f02e94 | |||
| 1abf80c310 | |||
| 2c18c89807 | |||
| 1b81fa5aa1 | |||
| baa08b3221 | |||
| b9a9abd30d | |||
| 33536957d8 | |||
| d092fd45ba | |||
| 78c748df5d | |||
| 3d76de3041 | |||
| ed3e9f3347 | |||
| eb836436b9 | |||
| c34a9c52d0 | |||
| 88d96f7d57 | |||
| 69e447be1c | |||
| df09acfa31 | |||
| 6343f77c0d | |||
| 285fc2269e | |||
| 68a1da9190 | |||
| ceae7d4fdb | |||
| 371daa6c80 | |||
| 948993e066 | |||
| ec4f0e5ad6 | |||
| ef56c6ce7e | |||
| 3c02da416e | |||
| 6660bf7618 | |||
| 000e5ec29a | |||
| ef8f4df4ab | |||
| dff70f2608 | |||
| 0d7967ff62 | |||
| 4fe459dab6 | |||
| 0e5e1f7873 | |||
| 82d4829c83 | |||
| a24fab6d92 | |||
| 748055dcf1 | |||
| 3904162360 | |||
| 7ca24ede4c | |||
| 1e59b10479 | |||
| cda61bff5b | |||
| 09a9753ca7 | |||
| 1621449143 | |||
| d0ef7f69b1 | |||
| 3df95b8970 | |||
| ddd4b0e262 | |||
| 6b05b6e7fb | |||
| 9dd728ce7e | |||
| 90b40ff0dc | |||
| 3c27c52c9f | |||
| 05d4dc5666 | |||
| edaabf5bd2 | |||
| ad79c63a37 | |||
| 9461bf2129 | |||
| f2097c0c5f | |||
| d838e1808d | |||
| 5ed54d9e7c | |||
| 78aba1c7e4 | |||
| 3faaee80ec | |||
| a847b8f4e4 | |||
| 24170a8a16 | |||
| 5438331fe1 | |||
| 3c957e0cbe | |||
| 10672f3e1a | |||
| fa90e420eb | |||
| 347bb2df4b | |||
| 986ffe66f8 | |||
| c1bedec354 | |||
| 182b6c7b07 | |||
| 22edbddd84 | |||
| 50f6f44d26 | |||
| e93a697179 | |||
| f1a5805b1c | |||
| 126f530af1 | |||
| 5dfbbb8d96 | |||
| 6962e505f9 | |||
| 5c2523e752 | |||
| 635dff73b4 | |||
| c85e4e7ceb | |||
| 7ed4301c6c | |||
| 1193e7025a | |||
| cc1ee19115 | |||
| e975eac4a7 | |||
| 779fc35228 | |||
| 8e59282fe0 | |||
| 11c8d47909 | |||
| 2661999f3e | |||
| e4bfb05875 | |||
| fe14988d50 | |||
| d45bef5e70 | |||
| 82d03b98c6 | |||
| 9c1ecf3f2c | |||
| 8f6be60c6e | |||
| 81a1bd9206 | |||
| 9f7dffb29d | |||
| eee799bfc4 | |||
| 9665adb61d | |||
| e40019f3cb | |||
| b2f95bfa60 | |||
| be2c7a62fd | |||
| 38f5468f19 | |||
| 31dcbc0159 | |||
| bd81320c08 | |||
| 0707f37247 | |||
| 0993736cea | |||
| cc3e2204e2 | |||
| 8ac5f0318b | |||
| 270a61e73a | |||
| 1c057b1ce1 | |||
| e74e824417 | |||
| 73d1de5dcf | |||
| 4549be0d05 | |||
| e3f2f2175d | |||
| a604cf2b2a | |||
| d6b4c1f454 | |||
| d3258693b2 | |||
| 9eba3b6eaa | |||
| 7b75364feb | |||
| 4a4a0f09ef | |||
| 6d14c2d448 | |||
| 57edd47ed7 | |||
| aefcedf754 | |||
| 2c685c846f | |||
| 6536f7b56b | |||
| 9d3881b00e | |||
| baffbd6a32 | |||
| 9e4702c102 | |||
| b63f3f335c | |||
| 29b0bcb6b9 | |||
| 62fa0bb218 | |||
| 9e67565c71 | |||
| dee4cf591e | |||
| bc5d6ee113 | |||
| 5af3b537da | |||
| 4b159d400c | |||
| f3c012660a | |||
| b5b8b5df26 | |||
| 6d38d9b538 | |||
| ef11ae6540 | |||
| a3802c25c0 | |||
| 377bcfe6da | |||
| 63a5c0986f | |||
| 8320623210 | |||
| 90c4a2fd41 | |||
| 4ee66caaf9 | |||
| 23251de6f1 | |||
| 37287bac7e | |||
| 43a7340f5d | |||
| 2363b5e167 | |||
| 62bf8c2287 | |||
| a5a958d6e2 | |||
| 812d8508f4 | |||
| c40cc3f740 | |||
| 56040951f1 | |||
| 39b1a65dc5 | |||
| 438f35fe88 | |||
| 9240518066 | |||
| 27b71a9d07 | |||
| 0f1d675bef | |||
| 19345ff538 | |||
| 7b28bc9c68 | |||
| d67eae55df | |||
| 8e375dcf73 | |||
| a34d0cabfc | |||
| a668743d10 | |||
| b13cbbb244 | |||
| b6ae5fd344 | |||
| 1c85034e19 | |||
| b0d1823968 | |||
| f0e03c79df | |||
| 6109cdf41b | |||
| ec0873d527 | |||
| 63223172b4 | |||
| 9778253d21 | |||
| 0140b4ded1 | |||
| dca60b83a9 | |||
| 42e683375c | |||
| 66e07c2f69 | |||
| 2b067b9dec | |||
| c22d7d2f41 | |||
| ea3d489c24 | |||
| 97683a14ef | |||
| d79b912e0e | |||
| 7ec8f8b03e | |||
| 58199ef7c9 | |||
| d5c46514d3 | |||
| f400973557 | |||
| 148d6e7b1b | |||
| 74dec650a7 | |||
| 5f6e003e4e | |||
| d3df22b44b | |||
| 257208d55b | |||
| d8b9b09d14 | |||
| 6f9e14ceb0 | |||
| d854984dda | |||
| 2951721886 | |||
| 02801b32a6 | |||
| b243e04fd2 | |||
| 02902d9a41 | |||
| 5c33034455 | |||
| 7541293a3c | |||
| da7d4dac7a | |||
| 507ab8ec11 | |||
| e93ff7a6b1 | |||
| 098ae2b69f | |||
| a58a10e93d | |||
| 9be7d951c3 | |||
| 6cf482dc63 | |||
| aaa4683462 | |||
| 0b5535b6d4 | |||
| cc8f103465 | |||
| 339ab9eeab | |||
| 6c29c53a72 | |||
| 59e11aa804 | |||
| 155a8b79da | |||
| b46ccc9b78 | |||
| 4f1e21dfb0 |
@@ -39,7 +39,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
pyver: [py39, py310]
|
||||
pyver: [py39, py310, py311]
|
||||
config:
|
||||
- {
|
||||
name: "Windows Build",
|
||||
@@ -62,7 +62,7 @@ jobs:
|
||||
- uses: actions/setup-python@v2 # https://github.com/actions/setup-python
|
||||
with:
|
||||
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
|
||||
python-version: '3.10'
|
||||
python-version: '3.11'
|
||||
- run: echo ${{ env.DATE }}
|
||||
- name: Get current date
|
||||
id: date
|
||||
|
||||
@@ -1,10 +1,7 @@
|
||||
name: ci-ifcopenshell-conda-daily
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- .github/workflows/ci-ifcopenshell-conda-daily.yml
|
||||
- conda/**
|
||||
workflow_dispatch:
|
||||
schedule:
|
||||
# ┌───────────── minute (0 - 59)
|
||||
# │ ┌───────────── hour (0 - 23)
|
||||
@@ -15,17 +12,8 @@ on:
|
||||
- cron: "49 23 * * *" # 11min before utc midnight every day
|
||||
|
||||
jobs:
|
||||
activate:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.repository == 'IfcOpenShell/IfcOpenShell'
|
||||
steps:
|
||||
- name: Set env
|
||||
run: echo ok go
|
||||
|
||||
test:
|
||||
name: ${{ matrix.platform.distver }}-${{ matrix.pyver.name }}
|
||||
needs: activate
|
||||
name: ${{ matrix.platform.distver }}-${{ matrix.pyver.name }}-${{ matrix.variant }}
|
||||
runs-on: ${{ matrix.platform.distver }}
|
||||
defaults:
|
||||
run:
|
||||
@@ -34,18 +22,23 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
pyver: [
|
||||
{ name: py310, distver: '3.10'},
|
||||
{ name: py311, distver: '3.11'}
|
||||
{ name: py311, distver: '3.11'},
|
||||
{ name: py312, distver: '3.12'}
|
||||
]
|
||||
platform: [
|
||||
{ name: Windows, distver: windows-2022, upload: 'true' },
|
||||
{ name: Linux, distver: ubuntu-22.04, upload: 'true' },
|
||||
{ name: macOS, distver: macos-12, upload: 'true' }
|
||||
]
|
||||
variant: [
|
||||
'novtk',
|
||||
# 'all'
|
||||
]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Download MacOSX SDK
|
||||
if: ${{ matrix.platform.name == 'macOS' }}
|
||||
run: |
|
||||
@@ -53,21 +46,22 @@ jobs:
|
||||
tar xf MacOSX10.13.sdk.tar.xz && \
|
||||
sudo mv -v MacOSX10.13.sdk /opt/ && \
|
||||
ls /opt/
|
||||
- uses: seanmiddleditch/gha-setup-ninja@master
|
||||
- uses: mamba-org/provision-with-micromamba@main # https://github.com/mamba-org/provision-with-micromamba
|
||||
|
||||
- uses: mamba-org/setup-micromamba@v1 # https://github.com/mamba-org/setup-micromamba
|
||||
with:
|
||||
channels: conda-forge
|
||||
channel-priority: strict
|
||||
environment-file: conda/environment.yml
|
||||
extra-specs: |
|
||||
python=${{ matrix.pyver.distver }}
|
||||
environment-name: build-env
|
||||
cache-environment: true
|
||||
condarc: |
|
||||
channels:
|
||||
- conda-forge
|
||||
channel_priority: strict
|
||||
create-args: >-
|
||||
python=3.11
|
||||
anaconda-client
|
||||
boa
|
||||
|
||||
- name: build, test and upload ifcopenshell
|
||||
if: ${{ matrix.platform.upload == 'true' }}
|
||||
run: |
|
||||
conda-build . --python ${{ matrix.pyver.distver }} -c conda-forge --token ${{ secrets.ANACONDA_TOKEN }} --user ifcopenshell
|
||||
working-directory: ./conda
|
||||
- name: build & test ifcopenshell
|
||||
if: ${{ matrix.platform.upload == 'false' }}
|
||||
run: |
|
||||
conda-build . --python ${{ matrix.pyver.distver }} -c conda-forge
|
||||
conda mambabuild . --python ${{ matrix.pyver.distver }} -c conda-forge --variants "{variant: ${{ matrix.variant }}}" --token ${{ secrets.ANACONDA_TOKEN }} --user ifcopenshell
|
||||
working-directory: ./conda
|
||||
|
||||
@@ -1,99 +0,0 @@
|
||||
name: ci_py_only
|
||||
|
||||
on:
|
||||
push:
|
||||
paths:
|
||||
- 'src/**'
|
||||
- 'test/**'
|
||||
- 'conda/**'
|
||||
- 'cmake/**'
|
||||
- '.github/workflows/ci-py-only.yml'
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
activate:
|
||||
runs-on: ubuntu-latest
|
||||
if: |
|
||||
github.repository == 'IfcOpenShell/IfcOpenShell' &&
|
||||
!contains(github.event.head_commit.message, 'skip ci')
|
||||
steps:
|
||||
- run: echo ok go
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-20.04
|
||||
needs: activate
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
submodules: recursive
|
||||
- name: Install C++ dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt-get install --no-install-recommends \
|
||||
git cmake gcc g++ \
|
||||
libboost-date-time-dev \
|
||||
libboost-filesystem-dev \
|
||||
libboost-iostreams-dev \
|
||||
libboost-program-options-dev \
|
||||
libboost-regex-dev \
|
||||
libboost-system-dev \
|
||||
libboost-thread-dev \
|
||||
python3-all-dev python3-pip \
|
||||
swig libpcre3-dev libxml2-dev \
|
||||
libtbb-dev nlohmann-json3-dev \
|
||||
libocct-foundation-dev libocct-modeling-algorithms-dev libocct-modeling-data-dev libocct-ocaf-dev libocct-visualization-dev libocct-data-exchange-dev \
|
||||
libhdf5-dev libcgal-dev
|
||||
|
||||
- name: ccache
|
||||
uses: hendrikmuhs/ccache-action@v1
|
||||
with:
|
||||
key: ${GITHUB_WORKFLOW}
|
||||
|
||||
- name: Build ifcopenshell
|
||||
run: |
|
||||
sudo /usr/sbin/update-ccache-symlinks
|
||||
mkdir build && cd build
|
||||
PATH="/usr/lib/ccache:$PATH" cmake \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DCMAKE_PREFIX_PATH=/usr \
|
||||
-DCMAKE_SYSTEM_PREFIX_PATH=/usr \
|
||||
-DOCC_INCLUDE_DIR=/usr/include/opencascade \
|
||||
-DOCC_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
|
||||
-DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/python3 \
|
||||
-DPYTHON_INCLUDE_DIR:PATH=/usr/include/python3.8 \
|
||||
-DPYTHON_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libpython3.8.so \
|
||||
-DCOLLADA_SUPPORT=Off \
|
||||
"-DSCHEMA_VERSIONS=2x3;4;4x3_add1" \
|
||||
-DBUILD_CONVERT=Off \
|
||||
-DGLTF_SUPPORT=On \
|
||||
-DJSON_INCLUDE_DIR=/usr/include \
|
||||
-DCGAL_INCLUDE_DIR=/usr/include \
|
||||
-DGMP_INCLUDE_DIR=/usr/include \
|
||||
-DMPFR_INCLUDE_DIR=/usr/include \
|
||||
-DGMP_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
|
||||
-DMPFR_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
|
||||
-DHDF5_INCLUDE_DIR=/usr/include/hdf5/serial \
|
||||
../cmake
|
||||
sudo make -j $(nproc)
|
||||
sudo make install
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
sudo /usr/bin/python -m pip install -U pip
|
||||
sudo /usr/bin/python -m pip install xmlschema xsdata numpy lxml
|
||||
sudo /usr/bin/python -m pip install src/bcf --no-deps
|
||||
sudo /usr/bin/python -m pip install pytest
|
||||
sudo /usr/bin/python -m pip install isodate
|
||||
sudo /usr/bin/python -m pip install lark
|
||||
sudo /usr/bin/python -m pip install networkx
|
||||
sudo /usr/bin/python -m pip install tabulate
|
||||
sudo /usr/bin/python -m pip install python-dateutil
|
||||
sudo /usr/bin/python -m pip install mathutils
|
||||
|
||||
- name: Test
|
||||
run: |
|
||||
cd test
|
||||
sudo /usr/bin/python tests.py
|
||||
cd ../src/ifcopenshell-python
|
||||
mv ifcopenshell ifcopenshell-local # Force testing on installed module
|
||||
make test
|
||||
+24
-22
@@ -31,12 +31,25 @@ jobs:
|
||||
- run: echo ok go
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-20.04
|
||||
runs-on: ubuntu-latest
|
||||
needs: activate
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v5
|
||||
with:
|
||||
python-version: 3.11
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install xmlschema xsdata numpy lxml pytest isodate lark networkx tabulate python-dateutil
|
||||
pip install src/bcf --no-deps
|
||||
pip install https://github.com/Andrej730/aud/archive/refs/heads/master-reduced-size.zip
|
||||
|
||||
- name: Install C++ dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
@@ -49,7 +62,6 @@ jobs:
|
||||
libboost-regex-dev \
|
||||
libboost-system-dev \
|
||||
libboost-thread-dev \
|
||||
python3-all-dev python3-pip \
|
||||
swig libpcre3-dev libxml2-dev \
|
||||
libtbb-dev nlohmann-json3-dev \
|
||||
libocct-foundation-dev libocct-modeling-algorithms-dev libocct-modeling-data-dev libocct-ocaf-dev libocct-visualization-dev libocct-data-exchange-dev \
|
||||
@@ -62,6 +74,9 @@ jobs:
|
||||
|
||||
- name: Build ifcopenshell
|
||||
run: |
|
||||
echo $Python3_ROOT_DIR
|
||||
echo ${{ env.pythonLocation }}
|
||||
|
||||
mkdir build && cd build
|
||||
cmake \
|
||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||
@@ -71,9 +86,9 @@ jobs:
|
||||
-DCMAKE_SYSTEM_PREFIX_PATH=/usr \
|
||||
-DOCC_INCLUDE_DIR=/usr/include/opencascade \
|
||||
-DOCC_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
|
||||
-DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/python3 \
|
||||
-DPYTHON_INCLUDE_DIR:PATH=/usr/include/python3.8 \
|
||||
-DPYTHON_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libpython3.8.so \
|
||||
-DPYTHON_EXECUTABLE:FILEPATH=${{ env.pythonLocation }}/bin/python \
|
||||
-DPYTHON_INCLUDE_DIR:PATH=${{ env.pythonLocation }}/include/python3.11 \
|
||||
-DPYTHON_LIBRARY:FILEPATH=${{ env.pythonLocation }}/lib/libpython3.11.so \
|
||||
-DCOLLADA_SUPPORT=Off \
|
||||
"-DSCHEMA_VERSIONS=2x3;4;4x3_add1" \
|
||||
-DGLTF_SUPPORT=On \
|
||||
@@ -102,24 +117,11 @@ jobs:
|
||||
grep 0$ statuses
|
||||
grep 0$ statuses | wc -l
|
||||
|
||||
- name: Install Python dependencies
|
||||
run: |
|
||||
sudo /usr/bin/python -m pip install -U pip
|
||||
sudo /usr/bin/python -m pip install xmlschema xsdata numpy lxml
|
||||
sudo /usr/bin/python -m pip install src/bcf --no-deps
|
||||
sudo /usr/bin/python -m pip install pytest
|
||||
sudo /usr/bin/python -m pip install isodate
|
||||
sudo /usr/bin/python -m pip install lark
|
||||
sudo /usr/bin/python -m pip install networkx
|
||||
sudo /usr/bin/python -m pip install https://github.com/Andrej730/aud/archive/refs/heads/master-reduced-size.zip
|
||||
sudo /usr/bin/python -m pip install tabulate
|
||||
sudo /usr/bin/python -m pip install python-dateutil
|
||||
sudo /usr/bin/python -m pip install mathutils
|
||||
|
||||
- name: Test
|
||||
- name: Test ifcopenshell-python
|
||||
run: |
|
||||
cd test
|
||||
sudo /usr/bin/python tests.py
|
||||
python tests.py
|
||||
cd ../src/ifcopenshell-python
|
||||
mv ifcopenshell ifcopenshell-local # Force testing on installed module
|
||||
make test
|
||||
make test-safe
|
||||
|
||||
+6
-12
@@ -7,34 +7,26 @@
|
||||
|
||||
# output directories
|
||||
/cmake/out/
|
||||
/docs/out/
|
||||
/src/examples/out/
|
||||
/src/ifcmax/out/
|
||||
/src/ifcwrap/out/
|
||||
/src/qtviewer/out/
|
||||
|
||||
|
||||
/win/BuildDepsCache*.txt
|
||||
# IfcExpressParser residue
|
||||
/src/ifcexpressparser/express_parser.py
|
||||
|
||||
# General Python residue
|
||||
__pycache__
|
||||
*.py.bak
|
||||
|
||||
# Visual Studio Code files
|
||||
.vscode
|
||||
.vs
|
||||
|
||||
# PyCharm files
|
||||
.idea
|
||||
|
||||
#Virtual Env Files
|
||||
Pipfile
|
||||
Pipfile.lock
|
||||
|
||||
# Docs
|
||||
/docs/output
|
||||
/docs/rst_files
|
||||
/docs/doxygen
|
||||
/src/ifcblenderexport/docs/_build
|
||||
/docs/cpp-api/output
|
||||
|
||||
# gettext binary translation files
|
||||
*.mo
|
||||
@@ -96,6 +88,8 @@ src/ifcopenshell-python/ifcopenshell/ifcopenshell_wrapper.py
|
||||
# apple
|
||||
.DS_Store
|
||||
|
||||
# clangd config
|
||||
.clangd
|
||||
# clangd cache
|
||||
.cache
|
||||
|
||||
|
||||
+4
-1
@@ -10,4 +10,7 @@
|
||||
url = https://github.com/IfcOpenShell/svgfill
|
||||
[submodule "src/ifcopenshell-python/test/Sample-BIM-Files"]
|
||||
path = src/ifcopenshell-python/test/Sample-BIM-Files
|
||||
url = https://github.com/IfcOpenShell/ids-test-files
|
||||
url = https://github.com/IfcOpenShell/ids-test-files
|
||||
[submodule "docs/cpp-api/assets/doxygen-awesome-css"]
|
||||
path = docs/cpp-api/assets/doxygen-awesome-css
|
||||
url = https://github.com/jothepro/doxygen-awesome-css.git
|
||||
|
||||
@@ -7,13 +7,13 @@ IfcOpenShell
|
||||
</p>
|
||||
|
||||
IfcOpenShell is an open source ([LGPL]) software library for working with Industry Foundation Classes ([IFC]). Complete
|
||||
parsing support is provided for [IFC2x3 TC1], [IFC4 Add2 TC1], IFC4x1, IFC4x2, and IFC4x3. Extensive geometric support
|
||||
parsing support is provided for [IFC2x3 TC1], [IFC4 Add2 TC1], IFC4x1, IFC4x2, and [IFC4x3 Add2]. Extensive geometric support
|
||||
is implemented for the IFC releases [IFC2x3 TC1] and [IFC4 Add2 TC1]. Extending with support for arbitrary IFC schemas
|
||||
is possible at compile-time when using C++ and at run-time when using Python.
|
||||
|
||||
In addition to a C++ and Python API, IfcOpenShell comes with an ecosystem of tools, notably including IfcConvert (an application to convert IFC models to
|
||||
other formats), the BlenderBIM Add-on (an add-on to Blender providing a graphical IFC authoring platform), and many
|
||||
other libraries, CLI apps, and more. Support is also provided for auxiliary standards such as BCF and IDS.
|
||||
In addition to a C++ and Python API, IfcOpenShell comes with an ecosystem of tools, notably including IfcConvert (an application
|
||||
to convert IFC models to other formats), the BlenderBIM Add-on (an add-on to Blender providing a graphical IFC authoring platform),
|
||||
and many other libraries, CLI apps, and more. Support is also provided for auxiliary standards such as BCF and IDS.
|
||||
|
||||
For more information, see:
|
||||
|
||||
@@ -32,8 +32,8 @@ For more information, see:
|
||||
| Anaconda Daily Build | [](https://anaconda.org/ifcopenshell/ifcopenshell) |
|
||||
| Anaconda v0.7.0 Stable | [](https://anaconda.org/conda-forge/ifcopenshell) |
|
||||
| PyPi Daily Build | [](https://pypi.org/project/ifcopenshell/) |
|
||||
| ArchLinux AUR Package Stable | [](https://aur.archlinux.org/packages/ifcopenshell) |
|
||||
| ArchLinux AUR Package git | [](https://aur.archlinux.org/packages/ifcopenshell-git) |
|
||||
| ArchLinux AUR Package Stable | [](https://aur.archlinux.org/packages/ifcopenshell) |
|
||||
| ArchLinux AUR Package git | [](https://aur.archlinux.org/packages/ifcopenshell-git) |
|
||||
| BlenderBIM Add-on Chocolatey (under moderation) | [](https://community.chocolatey.org/packages/blenderbim-nightly/) |
|
||||
| Sponsor development on OpenCollective | [](https://opencollective.com/opensourcebim/) |
|
||||
| Docker hub | [](https://hub.docker.com/r/aecgeeks/ifcopenshell) |
|
||||
@@ -44,7 +44,7 @@ Contents
|
||||
Those marked with an asterisk are part of IfcOpenShell.
|
||||
|
||||
| Name | Description | License |
|
||||
| ------------------------- | ----------------------------------------------------------------------| ------------------- |
|
||||
| ------------------------- | --------------------------------------------------------------------- | ------------------- |
|
||||
| bcf | Library to read and write BCF-XML and query OpenCDE BCF-API modules | LGPL-3.0-or-later |
|
||||
| blenderbim | Add-on to Blender providing a graphical native IFC authoring platform | GPL-3.0-or-later |
|
||||
| bsdd | Library to query the bSDD API | LGPL-3.0-or-later |
|
||||
@@ -55,7 +55,6 @@ Those marked with an asterisk are part of IfcOpenShell.
|
||||
| ifcblender | Historic Blender IFC import add-on | LGPL-3.0-or-later\* |
|
||||
| ifccityjson | Convert CityJSON to IFC | LGPL-3.0-or-later |
|
||||
| ifcclash | Clash detection library and CLI app | LGPL-3.0-or-later |
|
||||
| ifccobie | Extract IFC data for COBie handover requirements | LGPL-3.0-or-later |
|
||||
| ifcconvert | CLI app to convert IFC to many other formats | LGPL-3.0-or-later\* |
|
||||
| ifccsv | Library and CLI app to export and import schedules from IFC | LGPL-3.0-or-later |
|
||||
| ifcdiff | Compare changes between IFC models | LGPL-3.0-or-later |
|
||||
@@ -78,6 +77,7 @@ Those marked with an asterisk are part of IfcOpenShell.
|
||||
[IFC]: https://technical.buildingsmart.org/standards/ifc/ "IFC"
|
||||
[IFC2x3 TC1]: https://standards.buildingsmart.org/IFC/RELEASE/IFC2x3/TC1/HTML/ "IFC2x3 TC1"
|
||||
[IFC4 Add2 TC1]: https://standards.buildingsmart.org/IFC/RELEASE/IFC4/ADD2_TC1/HTML/ "IFC4 Add2 TC1"
|
||||
[IFC4x3 Add2]: https://standards.buildingsmart.org/IFC/RELEASE/IFC4_3/ "IFC4x3 Add2"
|
||||
[Visual Studio]: https://www.visualstudio.com/ "Visual Studio"
|
||||
[Visual C++ Build Tools]: http://landinghub.visualstudio.com/visual-cpp-build-tools "Visual C++ Build Tools"
|
||||
[MSYS2]: https://msys2.github.io/ "MSYS2"
|
||||
|
||||
@@ -29,7 +29,7 @@ URL_CHOCO_PACKAGE = "https://community.chocolatey.org/packages/blender"
|
||||
URL_BLENDER_CMAKE = "https://raw.githubusercontent.com/blender/blender/{}/build_files/cmake/Modules/FindPythonLibsUnix.cmake"
|
||||
RE_BLENDER_VERSION_MIN_MAJ = r"Latest Version.+<span>Blender (\d+\.\d+)\..+</span>"
|
||||
RE_BLENDER_VERSION_MIN_MAJ_PAT = r"Latest Version.+<span>Blender (\d+\.\d+\.\d+)</span>"
|
||||
RE_BLENDER_PYTHON_VERSION_MAJ_MIN = r"SET\(_PYTHON_VERSION_SUPPORTED (\d+\.\d+)\)"
|
||||
RE_BLENDER_PYTHON_VERSION_MAJ_MIN = r"(?:set|SET)\(_PYTHON_VERSION_SUPPORTED (\d+\.\d+)\)"
|
||||
|
||||
|
||||
if sys.argv[1] == "--do_choco_release?":
|
||||
|
||||
+40
-18
@@ -58,6 +58,7 @@ option(BUILD_PACKAGE "" OFF)
|
||||
option(COLLADA_SUPPORT "Build IfcConvert with COLLADA support (requires OpenCOLLADA)." ON)
|
||||
option(GLTF_SUPPORT "Build IfcConvert with glTF support (requires json.hpp)." OFF)
|
||||
option(HDF5_SUPPORT "Enable HDF5 support (requires HDF5, zlib)" ON)
|
||||
option(WITH_PROJ "Enable output of Earth-Centered Earth-Fixed glTF output using the PROJ library" OFF)
|
||||
option(IFCXML_SUPPORT "Build IfcParse with ifcXML support (requires libxml2)." ON)
|
||||
option(USD_SUPPORT "Build IfcConvert with USD support (requires pixar's USD library)." OFF)
|
||||
|
||||
@@ -438,9 +439,13 @@ if(BUILD_IFCGEOM)
|
||||
if(WASM_BUILD)
|
||||
set(OPENCASCADE_LIBRARIES ${OPENCASCADE_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
|
||||
else()
|
||||
# OPENCASCADE_LIBRARIES repeated N times below in order to fix cyclic dependencies - use --start-group ... --end-group instead?
|
||||
# OPENCASCADE_LIBRARIES repeated N times below in order to fix cyclic dependencies
|
||||
# tfk: --start-group ... --end-group didn't work on the apple linker when last tested
|
||||
set(OPENCASCADE_LIBRARIES ${OPENCASCADE_LIBRARIES} ${OPENCASCADE_LIBRARIES} ${OPENCASCADE_LIBRARIES} ${OPENCASCADE_LIBRARIES} ${OPENCASCADE_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
|
||||
if(APPLE)
|
||||
set(OPENCASCADE_LIBRARIES ${OPENCASCADE_LIBRARIES} ${OPENCASCADE_LIBRARIES} ${OPENCASCADE_LIBRARIES} ${OPENCASCADE_LIBRARIES} ${OPENCASCADE_LIBRARIES} ${CMAKE_THREAD_LIBS_INIT})
|
||||
else()
|
||||
set(OPENCASCADE_LIBRARIES -Wl,--start-group ${OPENCASCADE_LIBRARIES} -Wl,--end-group ${CMAKE_THREAD_LIBS_INIT})
|
||||
endif()
|
||||
endif()
|
||||
|
||||
if (NOT APPLE AND NOT WIN32)
|
||||
@@ -580,23 +585,31 @@ if(HDF5_SUPPORT)
|
||||
|
||||
if(WIN32)
|
||||
# Windows
|
||||
set(zlib_post zlib)
|
||||
set(lib_ext lib)
|
||||
elseif(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
# macOS
|
||||
set(zlib_post libz)
|
||||
set(lib_ext dylib)
|
||||
set(HDF5_LIBRARIES)
|
||||
find_package(HDF5 COMPONENTS CXX)
|
||||
if (HDF5_FOUND)
|
||||
set(HDF5_LIBRARIES ${HDF5_CXX_LIBRARIES})
|
||||
endif()
|
||||
list(APPEND HDF5_LIBRARIES
|
||||
"${HDF5_LIBRARY_DIR}/zlib.lib"
|
||||
)
|
||||
else()
|
||||
# linux
|
||||
set(zlib_post libz)
|
||||
set(lib_ext so)
|
||||
endif()
|
||||
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
|
||||
# macOS
|
||||
set(zlib_post libz)
|
||||
set(lib_ext dylib)
|
||||
else()
|
||||
# linux
|
||||
set(zlib_post libz)
|
||||
set(lib_ext so)
|
||||
endif()
|
||||
|
||||
set(HDF5_LIBRARIES
|
||||
"${HDF5_LIBRARY_DIR}/libhdf5_cpp.${lib_ext}"
|
||||
"${HDF5_LIBRARY_DIR}/libhdf5.${lib_ext}"
|
||||
"${HDF5_LIBRARY_DIR}/${zlib_post}.${lib_ext}"
|
||||
)
|
||||
set(HDF5_LIBRARIES
|
||||
"${HDF5_LIBRARY_DIR}/libhdf5_cpp.${lib_ext}"
|
||||
"${HDF5_LIBRARY_DIR}/libhdf5.${lib_ext}"
|
||||
"${HDF5_LIBRARY_DIR}/${zlib_post}.${lib_ext}"
|
||||
)
|
||||
endif()
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -738,7 +751,7 @@ if(NOT SCHEMA_VERSIONS)
|
||||
# super arbitrarily try to keep size down at least a little bit
|
||||
set(SCHEMA_VERSIONS "2x3" "4")
|
||||
else()
|
||||
set(SCHEMA_VERSIONS "2x3" "4" "4x1" "4x2" "4x3_rc1" "4x3_rc2" "4x3_rc3" "4x3_rc4" "4x3" "4x3_tc1" "4x3_add1")
|
||||
set(SCHEMA_VERSIONS "2x3" "4" "4x1" "4x2" "4x3_rc1" "4x3_rc2" "4x3_rc3" "4x3_rc4" "4x3" "4x3_tc1" "4x3_add1" "4x3_add2")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -934,6 +947,15 @@ if(BUILD_CONVERT OR BUILD_IFCPYTHON)
|
||||
add_library(Serializers ${SERIALIZERS_FILES})
|
||||
set_target_properties(Serializers PROPERTIES COMPILE_FLAGS "-DIFC_GEOM_EXPORTS" VERSION "${PROJECT_VERSION}" SOVERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}")
|
||||
|
||||
if (WITH_PROJ)
|
||||
target_compile_definitions(Serializers PRIVATE "WITH_PROJ")
|
||||
if (PROJ_STATIC)
|
||||
target_compile_definitions(Serializers PRIVATE "PROJ_DLL=")
|
||||
endif()
|
||||
target_include_directories(Serializers PRIVATE ${PROJ_INCLUDE_DIR} ${SQLITE_INCLUDE_DIR})
|
||||
target_link_libraries(Serializers ${PROJ_LIBRARIES})
|
||||
endif()
|
||||
|
||||
target_link_libraries(Serializers ${SERIALIZER_SCHEMA_LIBRARIES} ${OPENCOLLADA_LIBRARIES} ${USD_LIBRARIES})
|
||||
|
||||
endif(BUILD_CONVERT OR BUILD_IFCPYTHON)
|
||||
|
||||
@@ -1,8 +0,0 @@
|
||||
compile:
|
||||
conda activate conda-build && conda-build -c conda-forge . --keep-old-work --python 3.10.5
|
||||
|
||||
debug:
|
||||
conda activate conda-build && conda-debug -c conda-forge . --python 3.10.4
|
||||
|
||||
env:
|
||||
conda env update --f environment.yml --prune
|
||||
@@ -1,2 +1,6 @@
|
||||
CONDA_BUILD_SYSROOT:
|
||||
- /opt/MacOSX10.13.sdk # [osx]
|
||||
- /opt/MacOSX10.13.sdk # [osx]
|
||||
|
||||
variant:
|
||||
- novtk
|
||||
- all
|
||||
@@ -1,13 +0,0 @@
|
||||
name: conda-build
|
||||
channels:
|
||||
- conda-forge
|
||||
dependencies:
|
||||
- conda-build
|
||||
- conda-verify
|
||||
- anaconda-client
|
||||
- ninja
|
||||
- doxygen
|
||||
- ripgrep
|
||||
- pip
|
||||
- pip:
|
||||
- lief==0.13
|
||||
+12
-7
@@ -1,6 +1,10 @@
|
||||
{% set name = "ifcopenshell" %}
|
||||
{% set version = "0.7.0" %}
|
||||
{% set build = 1 %}
|
||||
|
||||
# Higher number -> Always prioritize "novtk" variant over "all" variant
|
||||
{% set build = build + 200 %} # [variant == "novtk"]
|
||||
{% set build = build + 100 %} # [variant == "all"]
|
||||
|
||||
package:
|
||||
name: {{ name }}
|
||||
@@ -10,8 +14,9 @@ source:
|
||||
path: ..
|
||||
|
||||
build:
|
||||
string: py{{ CONDA_PY }}_{{ variant }}_h{{ PKG_HASH }}_{{ build }}
|
||||
binary_relocation: false [osx]
|
||||
number: 1
|
||||
number: {{ build }}
|
||||
|
||||
requirements:
|
||||
build:
|
||||
@@ -19,12 +24,12 @@ requirements:
|
||||
- {{ compiler('cxx') }}
|
||||
- ninja >=1.10.2
|
||||
- cmake
|
||||
- swig >=4.0.2
|
||||
- swig 4.1.1
|
||||
|
||||
host:
|
||||
- python
|
||||
- boost-cpp
|
||||
- occt ==7.7.0
|
||||
- occt 7.7.2 *{{ variant }}*
|
||||
- libxml2
|
||||
- cgal-cpp
|
||||
- hdf5
|
||||
@@ -36,11 +41,11 @@ requirements:
|
||||
|
||||
run:
|
||||
- python
|
||||
- {{ pin_compatible('occt', max_pin='x.x.x') }}
|
||||
- occt 7.7.2 *{{ variant }}*
|
||||
- {{ pin_compatible('cgal-cpp', max_pin='x.x.x') }}
|
||||
- {{ pin_compatible('boost-cpp', max_pin='x.x.x') }}
|
||||
- {{ pin_compatible('hdf5', max_pin='x.x.x') }}
|
||||
- libxml2
|
||||
- hdf5
|
||||
- mpfr
|
||||
- gmp # [unix]
|
||||
- mpir # [win]
|
||||
@@ -52,12 +57,12 @@ test:
|
||||
- ifcopenshell
|
||||
|
||||
about:
|
||||
home: http://ifcopenshell.org
|
||||
home: https://ifcopenshell.org
|
||||
license: LGPL-3.0-or-later
|
||||
license_file: COPYING
|
||||
summary: 'IfcOpenShell is a library to support the IFC file format'
|
||||
description: |
|
||||
IfcOpenShell is an open source (LGPL) software library for
|
||||
working with the Industry Foundation Classes (IFC) file format.
|
||||
doc_url: http://ifcopenshell.org/
|
||||
doc_url: https://ifcopenshell.org/
|
||||
dev_url: https://github.com/IfcOpenShell/IfcOpenShell
|
||||
|
||||
@@ -1,11 +0,0 @@
|
||||
#Look for an executable called sphinx-build
|
||||
find_program(SPHINX_EXECUTABLE
|
||||
NAMES sphinx-build
|
||||
DOC "Path to sphinx-build executable")
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
#Handle standard arguments to find_package like REQUIRED and QUIET
|
||||
find_package_handle_standard_args(Sphinx
|
||||
"Failed to find sphinx-build executable"
|
||||
SPHINX_EXECUTABLE)
|
||||
@@ -1,11 +0,0 @@
|
||||
#Look for an executable called sphinx-build
|
||||
find_program(SPHINX_EXECUTABLE
|
||||
NAMES sphinx-build
|
||||
DOC "Path to sphinx-build executable")
|
||||
|
||||
include(FindPackageHandleStandardArgs)
|
||||
|
||||
#Handle standard arguments to find_package like REQUIRED and QUIET
|
||||
find_package_handle_standard_args(Sphinx
|
||||
"Failed to find sphinx-build executable"
|
||||
SPHINX_EXECUTABLE)
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,33 @@
|
||||
# IfcOpenShell C++ API documentation
|
||||
|
||||
This folder contains the setup to build the IfcOpenShell C++ API documentation from the source code.
|
||||
|
||||
## Generating the documentation
|
||||
|
||||
> Prerequisites:
|
||||
>
|
||||
> Make sure to have [Doxygen](https://www.doxygen.nl) and [Graphviz](https://graphviz.org) installed into your `$PATH` variable.
|
||||
>
|
||||
> The documentation also use the [doxygen-awesome](https://jothepro.github.io/doxygen-awesome-css) theme as a git submodule.
|
||||
|
||||
Build with the command (from within the `/docs/cpp-api` folder):
|
||||
|
||||
```shell
|
||||
$ doxygen
|
||||
```
|
||||
|
||||
To include the current git commit hash into the build documentation, use the following command:
|
||||
|
||||
```shell
|
||||
$ PROJECT_NUMBER=$(git rev-parse --short HEAD) doxygen
|
||||
```
|
||||
|
||||
This will extract the current commit hash in short version and sets the propper ENV variable used by doxygen.
|
||||
|
||||
The generation of the documentation might take a while depending on your systems hardware, as it is configured to generate the Class graphs using .
|
||||
|
||||
The resulting documentation is located unter `/cpp-api/output/html` and can be directly accessed with your browser:
|
||||
|
||||
```shell
|
||||
$ open ./output/html/index.html
|
||||
```
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 16 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 20 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 14 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 21 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 120 KiB |
@@ -1,240 +0,0 @@
|
||||
APPLY_DEFAULT_MATERIALS
|
||||
-----------------------
|
||||
|
||||
Given the command invocation:
|
||||
|
||||
Duplex_A_20110907_optimized.ifc d.dae -yv --include attribute GlobalId 3bXiCStxP6Fgxdej$yc50U
|
||||
|
||||
You will find log messages along the lines of
|
||||
|
||||
[Warning] {3bXiCStxP6Fgxdej$yc50U} No material and surface styles for:
|
||||
#333=IfcCovering('3bXiCStxP6Fgxdej$yc50U',#1,'Compound Ceiling:Gypsum Board:187483',$,'Compound Ceiling:Gypsum Board',#17840,#17052,'187483',.CEILING.)
|
||||
|
||||
This means that there is no IfcStyledItem associated to the representation items and that the element does not have an IfcMaterial association with IfcMaterialRepresentation from which we can derive a style (colour) for the element.
|
||||
|
||||
The interactive session below shows how with this setting enabled you will get a default generated material from the IFC element entity type and material indices of 0 pointing to that. With this setting disabled the material index would be -1 to indicate a missing style. Note that there is one material index for every triangle in the list of `shp.geometry.faces`.
|
||||
|
||||
>>> import ifcopenshell, ifcopenshell.geom
|
||||
>>> f = ifcopenshell.open("Duplex_A_20110907_optimized.ifc")
|
||||
>>> s = ifcopenshell.geom.settings()
|
||||
>>> c = f["3bXiCStxP6Fgxdej$yc50U"]
|
||||
>>>
|
||||
>>> shp = ifcopenshell.geom.create_shape(s, c)
|
||||
>>> shp.geometry.material_ids
|
||||
(-1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1)
|
||||
>>> [(m.name, m.diffuse) for m in shp.geometry.materials]
|
||||
[]
|
||||
>>>
|
||||
>>> s.set(s.APPLY_DEFAULT_MATERIALS, True)
|
||||
>>> shp = ifcopenshell.geom.create_shape(s, c)
|
||||
>>> shp.geometry.material_ids
|
||||
(0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
|
||||
>>> [(m.name, m.diffuse) for m in shp.geometry.materials]
|
||||
[('IfcCovering', (0.7, 0.7, 0.7))]
|
||||
|
||||
This is enabled by default for the IfcConvert serializers as they will not gracefully handle -1 material indices and allows users to quickly assign colours based on entity types in their modelling applications.
|
||||
|
||||
APPLY_LAYERSETS
|
||||
---------------
|
||||
|
||||
This setting is available in IfcConvert as `--enable-layerset-slicing`.
|
||||
|
||||
For IfcWall and IfcSlab elements, takes the associated IfcMaterialLayerSet and builds a set of surfaces to segment the building element geometry.
|
||||
|
||||
Note that enabling this settings is computationally intensive as it involves 3D Boolean operations.
|
||||
|
||||
Duplex_A_20110907_optimized.ifc d1.dae -yv --include attribute GlobalId 2O2Fr$t4X7Zf8NOew3FNr2
|
||||
|
||||

|
||||
|
||||
Duplex_A_20110907_optimized.ifc d2.dae --enable-layerset-slicing -yv --include attribute GlobalId 2O2Fr$t4X7Zf8NOew3FNr2
|
||||
|
||||

|
||||
|
||||
BUILDING_LOCAL_PLACEMENT
|
||||
------------------------
|
||||
|
||||
This setting is available in IfcConvert using `--building-local-placement`.
|
||||
|
||||
In the typical IfcSite > IfcBuilding > IfcBuildingStorey > ... hierarchy of elements, don't incorporate the ObjectPlacement of the IfcBuilding and above in the placement of elements in the output. This is useful when there is a large offset in this placement that reduces precision in further processing.
|
||||
|
||||
CONVERT_BACK_UNITS
|
||||
------------------
|
||||
|
||||
This setting is available in IfcConvert using `--convert-back-units`.
|
||||
|
||||
Internally IfcOpenShell uses meters as the global length unit to do calculations. This setting restores the coordinate positions after conversion by multiplying the factor of the IfcUnit with UnitType=LENGTHUNIT into the output geometry coordinate values.
|
||||
|
||||
DISABLE_OPENING_SUBTRACTIONS
|
||||
----------------------------
|
||||
|
||||
This setting is available in IfcConvert using `--disable-opening-subtraction`.
|
||||
|
||||
As in most viewer applications, IfcOpeningElement geometry is subtracted from their host elements. This setting disables this behavior.
|
||||
|
||||
Duplex_A_20110907_optimized.ifc d1.dae -yv --include attribute GlobalId 2O2Fr$t4X7Zf8NOew3FNr2
|
||||
|
||||

|
||||
|
||||
Duplex_A_20110907_optimized.ifc d3.dae --disable-opening-subtraction -yv --include attribute GlobalId 2O2Fr$t4X7Zf8NOew3FNr2
|
||||
|
||||

|
||||
|
||||
Note that disabling this settings will reduce processing time and improve robustness as it involves 3D Boolean operations.
|
||||
|
||||
DISABLE_TRIANGULATION
|
||||
---------------------
|
||||
|
||||
To be used in conjunction with `USE_BREP_DATA`. Do not apply the triangulation and - when `USE_BREP_DATA` is set - return a OpenCASCADE serialized TopoDS_Shape from `create_shape()` and `iterator`.
|
||||
|
||||
>>> import ifcopenshell, ifcopenshell.geom
|
||||
>>> s = ifcopenshell.geom.settings()
|
||||
>>> s.set(s.DISABLE_TRIANGULATION, True)
|
||||
>>> s.set(s.USE_BREP_DATA, True)
|
||||
>>> f = ifcopenshell.open("Duplex_A_20110907_optimized.ifc")
|
||||
>>> c = f["3bXiCStxP6Fgxdej$yc50U"]
|
||||
>>> shp = ifcopenshell.geom.create_shape(s, c)
|
||||
>>> print(shp.geometry.brep_data)
|
||||
|
||||
CASCADE Topology V1, (c) Matra-Datavision
|
||||
Locations 0
|
||||
Curve2ds 0
|
||||
Curves 12
|
||||
1 4.6750000000000034 -8.0749999999999904 2.657 -2.0455514041918775e-15 -1 0
|
||||
1 4.6750000000000034 -8.0749999999999904 2.657 1 -3.435893306383461e-15 0
|
||||
1 6.2260000000000044 -8.0749999999999957 2.657 -2.0455514041918724e-15 -1 0
|
||||
1 6.226 -10.246000000000031 2.657 -1 6.8717866127669219e-15 0
|
||||
...
|
||||
|
||||
EDGE_ARROWS
|
||||
-----------
|
||||
|
||||
When `INCLUDE_CURVES` is true and geometric elements include curves (such as the wall axis), add arrow heads to the edges to indicate direction of the curve.
|
||||
|
||||
Duplex_A_20110907_optimized.ifc d4.dae --model --plan --edge-arrows -yv --include attribute GlobalId 2O2Fr$t4X7Zf8NOew3FNr2
|
||||
|
||||

|
||||
|
||||
EXCLUDE_SOLIDS_AND_SURFACES
|
||||
---------------------------
|
||||
|
||||
Exclude faces, shells and solids from geometrical output. Implied when using `--plan` without `--model` in IfcConvert.
|
||||
|
||||
FASTER_BOOLEANS
|
||||
---------------
|
||||
|
||||
NOTE: Only applicable when using OCCT 6.9 and earlier.
|
||||
|
||||
This setting is available in IfcConvert using `--merge-boolean-operands`.
|
||||
|
||||
Fuse the collection of all boolean operands into a single union before applying the boolean subtraction, as opposed to doing individual subtractions. This likely improves performance. From OCCT 7.0 onwards the boolean operations with multiple arguments is used.
|
||||
|
||||
GENERATE_UVS
|
||||
------------
|
||||
|
||||
This setting is available in IfcConvert using `--generate-uvs`.
|
||||
|
||||
Applies a box projection on the generated geometry for the element to obtain UV coordinates. This is purely generated, it does not involve texture coordinates stored in the IFC model.
|
||||
|
||||
Duplex_A_20110907_optimized.ifc d5.dae --generate-uvs -yv --include attribute GlobalId 2O2Fr$t4X7Zf8NOew3FNr2
|
||||
|
||||

|
||||
|
||||
INCLUDE_CURVES
|
||||
--------------
|
||||
|
||||
This setting is available in IfcConvert using `--plan`.
|
||||
|
||||
Include edge and wire geometries in the geometric output.
|
||||
|
||||
LAYERSET_FIRST
|
||||
--------------
|
||||
|
||||
This setting is available in IfcConvert using `--layerset-first`.
|
||||
|
||||
When not using APPLY_LAYERSETS, take the first material layer from the set to use as the material for the overall element.
|
||||
|
||||
NO_NORMALS
|
||||
----------
|
||||
|
||||
This setting is available in IfcConvert using `--no-normals`.
|
||||
|
||||
Do not emit normals on geometric output
|
||||
|
||||
SEARCH_FLOOR
|
||||
------------
|
||||
|
||||
Note: Only applicable to Collada .DAE output when used from IfcConvert.
|
||||
|
||||
This setting is available in IfcConvert using `--use-element-hierarchy`.
|
||||
|
||||
Include the spatial hierarchy in the elements.
|
||||
|
||||
SEW_SHELLS
|
||||
----------
|
||||
|
||||
This setting is available in IfcConvert using `--orient-shells`.
|
||||
|
||||
Re-orient or sew connected face sets to have a consistent outwards orientation.
|
||||
|
||||
SITE_LOCAL_PLACEMENT
|
||||
--------------------
|
||||
|
||||
This setting is available in IfcConvert using `--site-local-placement`.
|
||||
|
||||
See `BUILDING_LOCAL_PLACEMENT`, but exclude also the ObjectPlacement of the IfcSite.
|
||||
|
||||
USE_BREP_DATA
|
||||
-------------
|
||||
|
||||
See `DISABLE_TRIANGULATION`.
|
||||
|
||||
USE_PYTHON_OPENCASCADE
|
||||
----------------------
|
||||
|
||||
Note: Only available when an import of `OCC.Core.BRepTools` or `OCC.BRepTools` succeeds.
|
||||
|
||||
This implies `USE_WORLD_COORDS` `USE_BREP_DATA` and `DISABLE_TRIANGULATION`. The serialized TopoDS_Shape of `USE_BREP_DATA` is deserialized by Python OpenCASCADE.
|
||||
|
||||
USE_WORLD_COORDS
|
||||
----------------
|
||||
|
||||
Apply the ObjectPlacement of the building elements to the geometric output. This is implied when using the Wavefront .OBJ output in IfcConvert. Note that this also eliminates the possibility for geometric elements to point to the same interpreted geometry result.
|
||||
|
||||
VALIDATE_QUANTITIES
|
||||
-------------------
|
||||
|
||||
This setting is available in IfcConvert using `--validate`.
|
||||
|
||||
Running IfcConvert with `--validate` will set a non-zero exit code when ever a log message with severity equal or greater than ERROR has been emitted.
|
||||
|
||||
Currently for internal use only. For every building element geometry converted, looks for an associated quantity set where the OwnerHistory's organization name is IfcOpenShell. And looks for the quantities "Total Surface Area", "Volume", "Shape Validation Properties.Surface Genus" and validates these according to the interpreted geometry definition. Emit Logger::Error when calculated values are outside of the tolerance range for the value stored in the model.
|
||||
|
||||
WELD_VERTICES
|
||||
-------------
|
||||
|
||||
Note: In Python, this setting is *on* by default.
|
||||
|
||||
Note: This setting only affects triangulated output.
|
||||
|
||||
This setting is available in IfcConvert using `--weld-vertices`.
|
||||
|
||||
Discards normals and joins vertices solely based on position. This is useful when output is to be modified in a modeling application.
|
||||
|
||||
>>> import ifcopenshell, ifcopenshell.geom
|
||||
>>> s = ifcopenshell.geom.settings()
|
||||
>>> s.set(s.WELD_VERTICES, False)
|
||||
>>> f = ifcopenshell.open("Duplex_A_20110907_optimized.ifc")
|
||||
>>> c = f["3bXiCStxP6Fgxdej$yc50U"]
|
||||
>>> shp = ifcopenshell.geom.create_shape(s, c)
|
||||
>>> shp.geometry.verts
|
||||
(4.675000000000003, -8.07499999999999, 2.657, 4.674999999999999, -10.24600000000002, 2.657, 6.226000000000004, -8.074999999999996, 2.657, 6.226, -10.24600000000003, 2.657, 4.675000000000003, -8.07499999999999, 2.6, 4.674999999999999, -10.24600000000002, 2.6, 6.226000000000004, -8.074999999999996, 2.6, 6.226, -10.24600000000003, 2.6, 4.674999999999999, -10.24600000000002, 2.657, 4.674999999999999, -10.24600000000002, 2.6, 4.675000000000003, -8.07499999999999, 2.657, 4.675000000000003, -8.07499999999999, 2.6, 6.226, -10.24600000000003, 2.657, 4.674999999999999, -10.24600000000002, 2.657, 6.226, -10.24600000000003, 2.6, 4.674999999999999, -10.24600000000002, 2.6, 6.226000000000004, -8.074999999999996, 2.657, 6.226, -10.24600000000003, 2.657, 6.226000000000004, -8.074999999999996, 2.6, 6.226, -10.24600000000003, 2.6, 4.675000000000003, -8.07499999999999, 2.657, 4.675000000000003, -8.07499999999999, 2.6, 6.226000000000004, -8.074999999999996, 2.657, 6.226000000000004, -8.074999999999996, 2.6)
|
||||
>>> shp.geometry.normals
|
||||
(3.059754518198021e-17, 0.0, -1.0, 3.059754518198021e-17, 0.0, -1.0, 3.059754518198021e-17, 0.0, -1.0, 3.059754518198021e-17, 0.0, -1.0, 2.110175529791737e-16, 0.0, -1.0, 2.110175529791737e-16, 0.0, -1.0, 2.110175529791737e-16, 0.0, -1.0, 2.110175529791737e-16, 0.0, -1.0, -1.0, 1.79434333701042e-15, 0.0, -1.0, 1.79434333701042e-15, 0.0, -1.0, 1.79434333701042e-15, 0.0, -1.0, 1.79434333701042e-15, 0.0, 6.8717866127669046e-15, 1.0, 0.0, 6.8717866127669046e-15, 1.0, 0.0, 6.8717866127669046e-15, 1.0, 0.0, 6.8717866127669046e-15, 1.0, 0.0, -1.0, 1.79434333701042e-15, 0.0, -1.0, 1.79434333701042e-15, 0.0, -1.0, 1.79434333701042e-15, 0.0, -1.0, 1.79434333701042e-15, 0.0, 3.4358933063834523e-15, 1.0, 0.0, 3.4358933063834523e-15, 1.0, 0.0, 3.4358933063834523e-15, 1.0, 0.0, 3.4358933063834523e-15, 1.0, 0.0)
|
||||
>>>
|
||||
>>> s.set(s.WELD_VERTICES, True)
|
||||
>>> shp = ifcopenshell.geom.create_shape(s, c)
|
||||
>>> shp.geometry.verts
|
||||
(4.675000000000003, -8.07499999999999, 2.657, 4.674999999999999, -10.24600000000002, 2.657, 6.226000000000004, -8.074999999999996, 2.657, 6.226, -10.24600000000003, 2.657, 4.675000000000003, -8.07499999999999, 2.6, 4.674999999999999, -10.24600000000002, 2.6, 6.226000000000004, -8.074999999999996, 2.6, 6.226, -10.24600000000003, 2.6)
|
||||
>>> shp.geometry.normals
|
||||
()
|
||||
+4
-3
@@ -76,7 +76,7 @@ PROJECT_NAME = "IfcOpenShell"
|
||||
USE_CURRENT_PYTHON_VERSION = os.getenv("USE_CURRENT_PYTHON_VERSION")
|
||||
ADD_COMMIT_SHA = os.getenv("ADD_COMMIT_SHA")
|
||||
|
||||
PYTHON_VERSIONS = ["3.6.14", "3.7.13", "3.8.13", "3.9.11", "3.10.3", "3.11.0"]
|
||||
PYTHON_VERSIONS = ["3.6.14", "3.7.13", "3.8.13", "3.9.11", "3.10.3", "3.11.7", "3.12.1"]
|
||||
JSON_VERSION = "v3.6.1"
|
||||
OCE_VERSION = "0.18.3"
|
||||
OCCT_VERSION = "7.5.3"
|
||||
@@ -892,8 +892,9 @@ if "IfcOpenShell-Python" in targets:
|
||||
module_dir = os.path.dirname(run([python_executable, "-c", "import inspect, ifcopenshell; print(inspect.getfile(ifcopenshell))"]))
|
||||
|
||||
if platform.system() != "Darwin":
|
||||
# TODO: This symbol name depends on the Python version?
|
||||
run([strip, "-s", "-K", "PyInit__ifcopenshell_wrapper", "_ifcopenshell_wrapper.so"], cwd=module_dir)
|
||||
if BUILD_CFG == "Release":
|
||||
# TODO: This symbol name depends on the Python version?
|
||||
run([strip, "-s", "-K", "PyInit__ifcopenshell_wrapper", "_ifcopenshell_wrapper.so"], cwd=module_dir)
|
||||
|
||||
return module_dir
|
||||
|
||||
|
||||
+3
-82
@@ -1,84 +1,5 @@
|
||||
# bcf
|
||||
|
||||
A simple Python implementation of BCF.
|
||||
Manipulation of BCF-XML is available via `bcfxml.py` and manipulation of BCF-API
|
||||
is available via `bcfapi.py`.
|
||||
|
||||
It tries to support BCF-XML version 2.1 and 3.0, and BCF-API 3.0.
|
||||
|
||||
## bcfxml
|
||||
|
||||
The `bcfxml.load` function lets you read a BCF-XML file.
|
||||
It takes care of using the right version based on the "bcf.version" file contained in the BCF package.
|
||||
|
||||
The BCF files are extracted and parsed on-demand, and edits are stored in memory until you call the `save` method.
|
||||
|
||||
```python
|
||||
from bcf.bcfxml import load
|
||||
|
||||
# Load a project
|
||||
with load("/path/to/file.bcf") as bcfxml:
|
||||
project = bcfxml.project
|
||||
print(project.name)
|
||||
|
||||
# To edit a project, just modify the object directly
|
||||
bcfxml.project.name = "New name"
|
||||
|
||||
# Get a dictionary of topics
|
||||
topics = bcfxml.topics
|
||||
|
||||
for topic_guid, topic_handler in bcfxml.topics.items():
|
||||
topic = topic_handler.topic
|
||||
print("Topic guid is", topic.guid)
|
||||
print("Topic title is", topic.title)
|
||||
|
||||
# Fetch extra data about a topic
|
||||
header = topic_handler.header
|
||||
comments = topic_handler.comments
|
||||
viewpoints = topic_handler.viewpoints
|
||||
|
||||
for comment in comments:
|
||||
print(comment.guid)
|
||||
print(comment.comment)
|
||||
print(comment.author)
|
||||
|
||||
# Get a particular topic
|
||||
topic = bcfxml.get_topic(guid)
|
||||
|
||||
# Modify a topic
|
||||
topic.title = "New title"
|
||||
|
||||
bcfxml.save()
|
||||
```
|
||||
|
||||
## bcfapi
|
||||
|
||||
The `bcfapi` module lets you interact with the BCF-API standard.
|
||||
|
||||
```python
|
||||
from bcf.v3.bcfapi import FoundationClient, BcfClient
|
||||
|
||||
foundation_client = FoundationClient("YOUR_CLIENT_ID", "YOUR_CLIENT_SECRET", "OPENCDE_BASEURL")
|
||||
auth_methods = foundation_client.get_auth_methods()
|
||||
|
||||
# Our library currently only implements the authorization_code flow
|
||||
if "authorization_code" in auth_methods:
|
||||
foundation_client.login()
|
||||
|
||||
bcf_client = BcfClient(foundation_client)
|
||||
|
||||
versions = foundation_client.get_versions()
|
||||
for version in versions:
|
||||
if "3.0" in versions:
|
||||
if version["api_id"] == "bcf" and version["version_id"] == "3.0":
|
||||
bcf_client.set_version(version)
|
||||
|
||||
data = bcf_client.get_projects()
|
||||
print(data)
|
||||
project_id = data[0]["project_id"]
|
||||
print(project_id)
|
||||
data = bcf_client.get_project(project_id)
|
||||
print(data)
|
||||
data = bcf_client.get_extensions(project_id)
|
||||
print(data)
|
||||
```
|
||||
A simple Python implementation of the BCF standard. Manipulation of BCF-XML is
|
||||
available via `bcfxml.py` and manipulation of BCF-API is available via
|
||||
`bcfapi.py`.
|
||||
|
||||
+92
-58
@@ -50,24 +50,31 @@ PYLIBDIR:=python3.10
|
||||
PYNUMBER:=310
|
||||
PYPI_VERSION:=3.10
|
||||
endif
|
||||
ifeq ($(PYVERSION), py311)
|
||||
PYLIBDIR:=python3.11
|
||||
PYNUMBER:=311
|
||||
PYPI_VERSION:=3.11
|
||||
endif
|
||||
|
||||
ifeq ($(PLATFORM), linux)
|
||||
PYPI_PLATFORM:=--platform manylinux_2_17_x86_64
|
||||
LXML_ARCH:=manylinux_2_28_x86_64
|
||||
SHAPELY_ARCH:=manylinux_2_17_x86_64.manylinux2014_x86_64
|
||||
PILLOW_ARCH:=manylinux_2_28_x86_64
|
||||
ifeq ($(PYVERSION), py39)
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/2.3.4/download/linux-64/hpp-fcl-2.3.4-py39h40a70d0_0.conda
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/3.1.0/download/linux-64/eigenpy-3.1.0-py39hdfdd6bb_0.conda
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/2.4.0/download/linux-64/hpp-fcl-2.4.0-py39h359ec1e_0.conda
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/3.2.0/download/linux-64/eigenpy-3.2.0-py39hb1babde_0.conda
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.78.0/download/linux-64/boost-1.78.0-py39h7c9e3ff_4.tar.bz2
|
||||
LXML_URL:=https://files.pythonhosted.org/packages/19/d9/a69c6aff5673554df48120565a14a50eaa41d29ae03b02faa0b023666318/lxml-4.6.3-cp39-cp39-manylinux2014_x86_64.whl
|
||||
SHAPELY_URL:=https://files.pythonhosted.org/packages/2d/f2/8ec281d357e8bb7d08dc8d727f0e4c8ef3dae7d3fa75c69c8e452bb82d50/shapely-2.0.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
|
||||
PILLOW_URL:=https://files.pythonhosted.org/packages/01/61/3ff85fb4bb596ce3d223c8fcf93c8df5c12bc8899dfb4fb3cb1c5b20dd5f/Pillow-9.2.0-cp39-cp39-manylinux_2_28_x86_64.whl
|
||||
endif
|
||||
ifeq ($(PYVERSION), py310)
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/2.3.4/download/linux-64/hpp-fcl-2.3.4-py310h995690b_0.conda
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/3.1.0/download/linux-64/eigenpy-3.1.0-py310hf02b7e0_0.conda
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/2.4.0/download/linux-64/hpp-fcl-2.4.0-py310hd002f03_0.conda
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/3.2.0/download/linux-64/eigenpy-3.2.0-py310hcfe0b05_0.conda
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.78.0/download/linux-64/boost-1.78.0-py310hc4a4660_4.tar.bz2
|
||||
LXML_URL:=https://files.pythonhosted.org/packages/25/1e/19b46d8e8881fe0df2e20945d51919eeb1817836d62a90efa8506530e45c/lxml-4.8.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.manylinux_2_24_x86_64.whl
|
||||
SHAPELY_URL:=https://files.pythonhosted.org/packages/a8/a5/403728b5614b28083f6424dfdefec5fcf58068495fb03bb08532671c642f/shapely-2.0.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl
|
||||
PILLOW_URL:=https://files.pythonhosted.org/packages/f6/51/320986ebd6d46a0e95c2240468ced73153b691ce07617078bcdf30c609ec/Pillow-9.2.0-cp310-cp310-manylinux_2_28_x86_64.whl
|
||||
endif
|
||||
ifeq ($(PYVERSION), py311)
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/2.4.0/download/linux-64/hpp-fcl-2.4.0-py311h04f086a_0.conda
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/3.2.0/download/linux-64/eigenpy-3.2.0-py311h995a085_0.conda
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.78.0/download/linux-64/boost-1.78.0-py311h59ea3da_3.tar.bz2
|
||||
endif
|
||||
ASSIMP_URL:=https://anaconda.org/conda-forge/assimp/5.0.1/download/linux-64/assimp-5.0.1-hedfc422_6.tar.bz2
|
||||
QHULL_URL:=https://anaconda.org/conda-forge/qhull/2020.2/download/linux-64/qhull-2020.2-h4bd325d_2.tar.bz2
|
||||
@@ -78,21 +85,25 @@ endif
|
||||
|
||||
ifeq ($(PLATFORM), macos)
|
||||
PYPI_PLATFORM:=--platform macosx_10_9_x86_64
|
||||
SHAPELY_ARCH:=macosx_10_9_x86_64
|
||||
PILLOW_ARCH:=macosx_10_10_x86_64
|
||||
ifeq ($(PYVERSION), py39)
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/2.3.4/download/osx-64/hpp-fcl-2.3.4-py39hd85b194_0.conda
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/3.1.0/download/osx-64/eigenpy-3.1.0-py39hc4d6e28_0.conda
|
||||
LXML_ARCH:=macosx_11_0_x86_64
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/2.4.0/download/osx-64/hpp-fcl-2.4.0-py39h26350b9_0.conda
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/3.2.0/download/osx-64/eigenpy-3.2.0-py39h3323527_0.conda
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.78.0/download/osx-64/boost-1.78.0-py39h953a6b8_4.tar.bz2
|
||||
LXML_URL:=https://files.pythonhosted.org/packages/b8/74/a71f7ad72e8db54ce899efab84507b801660750cbbfa6a39e6717557d36a/lxml-4.6.3-cp39-cp39-macosx_10_9_x86_64.whl
|
||||
SHAPELY_URL:=https://files.pythonhosted.org/packages/36/a4/7e542a209f862f967d7cb8e939eff155f4294a27d17e16441fb8bdd51a2c/shapely-2.0.1-cp39-cp39-macosx_10_9_x86_64.whl
|
||||
PILLOW_URL:=https://files.pythonhosted.org/packages/88/7a/ddfe28b485b623361457d4783007c1f9ba83a87f93e7fec32f64793efb6c/Pillow-9.2.0-cp39-cp39-macosx_10_10_x86_64.whl
|
||||
endif
|
||||
ifeq ($(PYVERSION), py310)
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/2.3.4/download/osx-64/hpp-fcl-2.3.4-py310h1db6f5f_0.conda
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/3.1.0/download/osx-64/eigenpy-3.1.0-py310h43da829_0.conda
|
||||
LXML_ARCH:=macosx_11_0_x86_64
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/2.4.0/download/osx-64/hpp-fcl-2.4.0-py310ha216469_0.conda
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/3.2.0/download/osx-64/eigenpy-3.2.0-py310h33a8c9b_0.conda
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.78.0/download/osx-64/boost-1.78.0-py310h3e792ce_4.tar.bz2
|
||||
LXML_URL:=https://files.pythonhosted.org/packages/a1/44/17b7dac7a18807d30e2fe10c3328c152808f5464565e230bfd0e77f178c6/lxml-4.8.0-cp310-cp310-macosx_10_15_x86_64.whl
|
||||
SHAPELY_URL:=https://files.pythonhosted.org/packages/1f/2a/dc3353c2431cf53e8d04bb8fba27e584410ca3435c9c85f76d71bf0c0e80/shapely-2.0.1-cp310-cp310-macosx_10_9_x86_64.whl
|
||||
PILLOW_URL:=https://files.pythonhosted.org/packages/d8/60/b13c00d403f34110e96c1b5c0afa73ce461efe3fe960c3a7e3e7fe190d82/Pillow-9.2.0-cp310-cp310-macosx_10_10_x86_64.whl
|
||||
endif
|
||||
ifeq ($(PYVERSION), py311)
|
||||
LXML_ARCH:=macosx_11_0_universal2
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/2.4.0/download/osx-64/hpp-fcl-2.4.0-py311hebdd1a2_0.conda
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/3.2.0/download/osx-64/eigenpy-3.2.0-py311h62e90b6_0.conda
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.78.0/download/osx-64/boost-1.78.0-py311h349b758_4.tar.bz2
|
||||
endif
|
||||
ASSIMP_URL:=https://anaconda.org/conda-forge/assimp/5.0.1/download/osx-64/assimp-5.0.1-h1224e73_6.tar.bz2
|
||||
QHULL_URL:=https://anaconda.org/conda-forge/qhull/2020.2/download/osx-64/qhull-2020.2-h940c156_2.tar.bz2
|
||||
@@ -103,21 +114,23 @@ endif
|
||||
|
||||
ifeq ($(PLATFORM), macosm1)
|
||||
PYPI_PLATFORM:=--platform macosx_11_0_arm64
|
||||
LXML_ARCH:=macosx_11_0_universal2
|
||||
SHAPELY_ARCH:=macosx_11_0_arm64
|
||||
PILLOW_ARCH:=macosx_11_0_arm64
|
||||
ifeq ($(PYVERSION), py39)
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/2.3.4/download/osx-arm64/hpp-fcl-2.3.4-py39hc34188a_0.conda
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/3.1.0/download/osx-arm64/eigenpy-3.1.0-py39h13cfc01_0.conda
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/2.4.0/download/osx-arm64/hpp-fcl-2.4.0-py39h82b2ff2_0.conda
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/3.2.0/download/osx-arm64/eigenpy-3.2.0-py39h3a9e884_0.conda
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.78.0/download/osx-arm64/boost-1.78.0-py39h99de9ae_4.tar.bz2
|
||||
LXML_URL:=https://anaconda.org/conda-forge/lxml/4.9.1/download/osx-arm64/lxml-4.9.1-py39h9eb174b_0.tar.bz2
|
||||
SHAPELY_URL:=https://files.pythonhosted.org/packages/ea/aa/45fbd031edf3149cb767d8b9f9db45d5faf0324d743c6b8fb0298cc022d0/shapely-2.0.1-cp39-cp39-macosx_11_0_arm64.whl
|
||||
PILLOW_URL:=https://files.pythonhosted.org/packages/aa/bc/21097cd891dd2fa02f2b3d767e02e883e026482e59d29975d1bc30024aa3/Pillow-9.2.0-cp39-cp39-macosx_11_0_arm64.whl
|
||||
endif
|
||||
ifeq ($(PYVERSION), py310)
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/2.3.4/download/osx-arm64/hpp-fcl-2.3.4-py310h46fc4cd_0.conda
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/3.1.0/download/osx-arm64/eigenpy-3.1.0-py310ha2643af_0.conda
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/2.4.0/download/osx-arm64/hpp-fcl-2.4.0-py310hdb6c3eb_0.conda
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/3.2.0/download/osx-arm64/eigenpy-3.2.0-py310h96e9823_0.conda
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.78.0/download/osx-arm64/boost-1.78.0-py310h629746b_4.tar.bz2
|
||||
LXML_URL:=https://anaconda.org/conda-forge/lxml/4.9.1/download/osx-arm64/lxml-4.9.1-py310h02f21da_0.tar.bz2
|
||||
SHAPELY_URL:=https://files.pythonhosted.org/packages/ec/41/d59208743e737184e1b403e95a937aebb022b8459e99efbcd5208fc8be46/shapely-2.0.1-cp310-cp310-macosx_11_0_arm64.whl
|
||||
PILLOW_URL:=https://files.pythonhosted.org/packages/0c/5f/117b653cad585f3aedfe0de996c292e67d4b020ed77f652e5a6c8c24f908/Pillow-9.2.0-cp310-cp310-macosx_11_0_arm64.whl
|
||||
endif
|
||||
ifeq ($(PYVERSION), py311)
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/2.4.0/download/osx-arm64/hpp-fcl-2.4.0-py311hc0c29b9_0.conda
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/3.2.0/download/osx-arm64/eigenpy-3.2.0-py311h24fa84d_0.conda
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.78.0/download/osx-arm64/boost-1.78.0-py311h5c64717_4.tar.bz2
|
||||
endif
|
||||
ASSIMP_URL:=https://anaconda.org/conda-forge/assimp/5.0.1/download/osx-arm64/assimp-5.0.1-h0f81e16_7.tar.bz2
|
||||
QHULL_URL:=https://anaconda.org/conda-forge/qhull/2020.2/download/osx-arm64/qhull-2020.2-hc021e02_2.tar.bz2
|
||||
@@ -128,21 +141,23 @@ endif
|
||||
|
||||
ifeq ($(PLATFORM), win)
|
||||
PYPI_PLATFORM:=--platform win_amd64
|
||||
LXML_ARCH:=win_amd64
|
||||
SHAPELY_ARCH:=win_amd64
|
||||
PILLOW_ARCH:=win_amd64
|
||||
ifeq ($(PYVERSION), py39)
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/2.3.4/download/win-64/hpp-fcl-2.3.4-py39h39b25cb_0.conda
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/3.1.0/download/win-64/eigenpy-3.1.0-py39hb6c915b_0.conda
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/2.4.0/download/win-64/hpp-fcl-2.4.0-py39hf3ebc58_0.conda
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/3.2.0/download/win-64/eigenpy-3.2.0-py39ha1f6a47_0.conda
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.78.0/download/win-64/boost-1.78.0-py39hea4d8d1_4.tar.bz2
|
||||
LXML_URL:=https://files.pythonhosted.org/packages/72/d4/426ecb8849c47c3e370c87aa0ac05d85768df917ffea27fcd6686a5e6495/lxml-4.6.3-cp39-cp39-win_amd64.whl
|
||||
SHAPELY_URL:=https://files.pythonhosted.org/packages/a7/ae/eab645c4075093584b7a65ab71cb8ff4563a015bd935c9b55dba14b2c1eb/shapely-2.0.1-cp39-cp39-win_amd64.whl
|
||||
PILLOW_URL:=https://files.pythonhosted.org/packages/19/3f/b4d4bcf05dbcbe07f2e9613a8f4180c297395e73a91d8ad22c32c6624f8c/Pillow-9.2.0-cp39-cp39-win_amd64.whl
|
||||
endif
|
||||
ifeq ($(PYVERSION), py310)
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/2.3.4/download/win-64/hpp-fcl-2.3.4-py310heb59267_0.conda
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/3.1.0/download/win-64/eigenpy-3.1.0-py310hd146abe_0.conda
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/2.4.0/download/win-64/hpp-fcl-2.4.0-py310h1bf3f0a_0.conda
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/3.2.0/download/win-64/eigenpy-3.2.0-py310h7fb871d_0.conda
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.78.0/download/win-64/boost-1.78.0-py310h220cb41_4.tar.bz2
|
||||
LXML_URL:=https://files.pythonhosted.org/packages/f6/71/65c80a4caa1617a4c6e8fe1500cebb179db96232e2f623bfe6a1f4294e39/lxml-4.8.0-cp310-cp310-win_amd64.whl
|
||||
SHAPELY_URL:=https://files.pythonhosted.org/packages/81/8a/7ac076a86b2632f1872284c5e60ed5f2fc26094875a85b35d9fa17b52504/shapely-2.0.1-cp310-cp310-win_amd64.whl
|
||||
PILLOW_URL:=https://files.pythonhosted.org/packages/02/55/67a3c17b9e7d972ed8c246f104da99ca4f3ea42fba566697e479011b84b6/Pillow-9.2.0-cp310-cp310-win_amd64.whl
|
||||
endif
|
||||
ifeq ($(PYVERSION), py311)
|
||||
HPPFCL_URL:=https://anaconda.org/conda-forge/hpp-fcl/2.4.0/download/win-64/hpp-fcl-2.4.0-py311hd263b2c_0.conda
|
||||
EIGENPY_URL:=https://anaconda.org/conda-forge/eigenpy/3.2.0/download/win-64/eigenpy-3.2.0-py311hd354db1_0.conda
|
||||
BOOST_URL:=https://anaconda.org/conda-forge/boost/1.78.0/download/win-64/boost-1.78.0-py311h12feb9d_3.tar.bz2
|
||||
endif
|
||||
ASSIMP_URL:=https://anaconda.org/conda-forge/assimp/5.2.5/download/win-64/assimp-5.2.5-h4dcb625_0.tar.bz2
|
||||
QHULL_URL:=https://anaconda.org/conda-forge/qhull/2020.2/download/win-64/qhull-2020.2-h70d2c02_2.tar.bz2
|
||||
@@ -151,6 +166,33 @@ BOOSTCPP_URL:=https://anaconda.org/conda-forge/boost-cpp/1.78.0/download/win-64/
|
||||
ZLIB_URL:=https://anaconda.org/conda-forge/zlib/1.2.11/download/win-64/zlib-1.2.11-h62dcd97_1010.tar.bz2
|
||||
endif
|
||||
|
||||
LXML_NAME:=lxml
|
||||
LXML_VER:=4.9.4
|
||||
SHAPELY_NAME:=shapely
|
||||
SHAPELY_VER:=2.0.2
|
||||
PILLOW_NAME:=pillow
|
||||
PILLOW_PKG_NAME:=Pillow
|
||||
PILLOW_VER:=9.5.0
|
||||
SHAPELY_URL:=https://files.pythonhosted.org/packages/cp$(PYNUMBER)/s/$(SHAPELY_NAME)/$(SHAPELY_NAME)-$(SHAPELY_VER)-cp$(PYNUMBER)-cp$(PYNUMBER)-$(SHAPELY_ARCH).whl
|
||||
PILLOW_URL:=https://files.pythonhosted.org/packages/cp$(PYNUMBER)/p/$(PILLOW_NAME)/$(PILLOW_PKG_NAME)-$(PILLOW_VER)-cp$(PYNUMBER)-cp$(PYNUMBER)-$(PILLOW_ARCH).whl
|
||||
|
||||
ifeq ($(PLATFORM), macosm1)
|
||||
ifeq ($(PYVERSION), py39)
|
||||
LXML_URL:=https://anaconda.org/conda-forge/lxml/4.9.1/download/osx-arm64/lxml-4.9.1-py39h0520ce3_1.tar.bz2
|
||||
endif
|
||||
ifeq ($(PYVERSION), py310)
|
||||
LXML_URL:=https://anaconda.org/conda-forge/lxml/4.9.1/download/osx-arm64/lxml-4.9.1-py310h02f21da_0.tar.bz2
|
||||
endif
|
||||
ifeq ($(PYVERSION), py311)
|
||||
LXML_URL:=https://anaconda.org/conda-forge/lxml/4.9.1/download/osx-arm64/lxml-4.9.1-py311h246f609_1.tar.bz2
|
||||
endif
|
||||
else
|
||||
LXML_URL:=https://files.pythonhosted.org/packages/cp$(PYNUMBER)/l/$(LXML_NAME)/$(LXML_NAME)-$(LXML_VER)-cp$(PYNUMBER)-cp$(PYNUMBER)-$(LXML_ARCH).whl
|
||||
endif
|
||||
$(info $$LXML_URL is [${LXML_URL}])
|
||||
$(info $$SHAPELY_URL is [${SHAPELY_URL}])
|
||||
$(info $$PILLOW_URL is [${PILLOW_URL}])
|
||||
|
||||
.PHONY: bump
|
||||
bump:
|
||||
cd . && $(SED) "s/$(OLD)/$(NEW)/" Makefile
|
||||
@@ -169,7 +211,7 @@ endif
|
||||
cp -r blenderbim/* dist/blenderbim/
|
||||
|
||||
# Provides IfcOpenShell Python functionality
|
||||
cd dist/working && wget https://s3.amazonaws.com/ifcopenshell-builds/ifcopenshell-python-$(PYNUMBER)-v0.7.0-9cc1f5f-$(PLATFORM)64.zip
|
||||
cd dist/working && wget https://s3.amazonaws.com/ifcopenshell-builds/ifcopenshell-python-$(PYNUMBER)-v0.7.0-6c9e130-$(PLATFORM)64.zip
|
||||
cd dist/working && unzip ifcopenshell-python*
|
||||
cp -r dist/working/ifcopenshell dist/blenderbim/libs/site/packages/
|
||||
|
||||
@@ -199,8 +241,10 @@ endif
|
||||
cp -r dist/working/IfcOpenShell-0.7.0/src/ifcbimtester/bimtester dist/blenderbim/libs/site/packages/
|
||||
# Provides IFCTester functionality
|
||||
cp -r dist/working/IfcOpenShell-0.7.0/src/ifctester/ifctester dist/blenderbim/libs/site/packages/
|
||||
# Provides IFCCOBie functionality
|
||||
cp -r dist/working/IfcOpenShell-0.7.0/src/ifccobie/* dist/blenderbim/libs/site/packages/
|
||||
# Provides IFCFM functionality
|
||||
cp -r dist/working/IfcOpenShell-0.7.0/src/ifcfm/ifcfm dist/blenderbim/libs/site/packages/
|
||||
# Provides bSDD functionality
|
||||
cp -r dist/working/IfcOpenShell-0.7.0/src/bsdd/* dist/blenderbim/libs/site/packages/
|
||||
# Provides IFCDiff functionality
|
||||
cp -r dist/working/IfcOpenShell-0.7.0/src/ifcdiff/* dist/blenderbim/libs/site/packages/
|
||||
# Provides IFCCSV functionality
|
||||
@@ -592,14 +636,6 @@ endif
|
||||
cd dist/working/parse_type-0.5.2/ && cp -r parse_type ../../blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Required by IFCCOBie for XLSX support
|
||||
# TODO: see if we can replace this with openpyxl which does both read/write
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://files.pythonhosted.org/packages/0c/bc/82d6783f83f65f56d8b77d052773c4a2f952fa86385f0cd54e1e006658d7/XlsxWriter-1.2.9.tar.gz
|
||||
cd dist/working && tar -xzvf XlsxWriter*
|
||||
cd dist/working/XlsxWriter-1.2.9/ && cp -r xlsxwriter ../../blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Required by augin
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://files.pythonhosted.org/packages/76/b4/b7baffbda025efd5dc8fcd8d2e953e3aa939c236a484084fa8f4c3588ee9/boto3-1.17.17.tar.gz
|
||||
@@ -635,13 +671,6 @@ endif
|
||||
cp -r dist/working/IFC2JSON_python-master/file_converters/ifcjson dist/blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Provides OpenLCA functionality
|
||||
mkdir dist/working
|
||||
cd dist/working && wget https://files.pythonhosted.org/packages/85/33/f91b96e9e8608ff65a003b692e8a9cdd60f2178f60617e5b1d21334c009c/olca-ipc-0.0.10.tar.gz
|
||||
cd dist/working && tar -xzvf olca-ipc*
|
||||
cd dist/working/olca-ipc-0.0.10/ && cp -r olca ../../blenderbim/libs/site/packages/
|
||||
rm -rf dist/working
|
||||
|
||||
# Provides Brickschema functionality
|
||||
mkdir dist/working
|
||||
# For now lets bundle the latest nightly schema
|
||||
@@ -667,6 +696,11 @@ endif
|
||||
# Required for Desktop icon and file association
|
||||
cp -r blenderbim/libs/desktop dist/blenderbim/libs/
|
||||
|
||||
# generate translations module for BBIM build
|
||||
git clone https://github.com/IfcOpenShell/blenderbim-translations.git dist/working
|
||||
python scripts/bbim_translations.py -i "dist/working" -o "dist/blenderbim"
|
||||
rm -rf dist/working
|
||||
|
||||
# Remove dependencies also bundled with Blender
|
||||
rm -rf dist/blenderbim/libs/site/packages/numpy
|
||||
rm -rf dist/blenderbim/libs/site/packages/numpy.libs
|
||||
|
||||
@@ -24,12 +24,17 @@ import blenderbim
|
||||
import importlib
|
||||
from . import handler, ui, prop, operator, helper
|
||||
|
||||
try:
|
||||
from blenderbim.translations import translations_dict
|
||||
except ImportError:
|
||||
translations_dict = {}
|
||||
cwd = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
modules = {
|
||||
"project": None,
|
||||
"search": None,
|
||||
"bcf": None,
|
||||
"bsdd": None,
|
||||
"root": None,
|
||||
"unit": None,
|
||||
"model": None,
|
||||
@@ -43,8 +48,9 @@ modules = {
|
||||
"spatial": None,
|
||||
"void": None,
|
||||
"aggregate": None,
|
||||
"nest": None,
|
||||
"geometry": None,
|
||||
"cobie": None,
|
||||
"fm": None,
|
||||
"resource": None,
|
||||
"cost": None,
|
||||
"sequence": None,
|
||||
@@ -66,7 +72,6 @@ modules = {
|
||||
"document": None,
|
||||
"pset_template": None,
|
||||
"clash": None,
|
||||
"lca": None,
|
||||
"csv": None,
|
||||
"tester": None,
|
||||
"bimtester": None,
|
||||
@@ -77,6 +82,7 @@ modules = {
|
||||
"augin": None,
|
||||
"debug": None,
|
||||
"ifcgit": None,
|
||||
"covering": None,
|
||||
# Uncomment this line to enable loading of the demo module. Happy hacking!
|
||||
# The name "demo" must correlate to a folder name in `bim/module/`.
|
||||
# "demo": None,
|
||||
@@ -90,28 +96,28 @@ for name in modules.keys():
|
||||
classes = [
|
||||
operator.AddIfcFile,
|
||||
operator.BIM_OT_add_section_plane,
|
||||
operator.BIM_OT_open_webbrowser,
|
||||
operator.BIM_OT_remove_section_plane,
|
||||
operator.BIM_OT_show_description,
|
||||
operator.EditBlenderCollection,
|
||||
operator.FileAssociate,
|
||||
operator.FileUnassociate,
|
||||
operator.OpenUpstream,
|
||||
operator.OpenUri,
|
||||
operator.SwitchTab,
|
||||
operator.SetTab,
|
||||
operator.ReloadIfcFile,
|
||||
operator.RemoveIfcFile,
|
||||
operator.SelectDataDir,
|
||||
operator.SelectIfcFile,
|
||||
operator.ReloadSelectedIfcFile,
|
||||
operator.SelectSchemaDir,
|
||||
operator.FileAssociate,
|
||||
operator.FileUnassociate,
|
||||
operator.SelectURIAttribute,
|
||||
operator.EditBlenderCollection,
|
||||
operator.BIM_OT_open_webbrowser,
|
||||
operator.BIM_OT_show_description,
|
||||
operator.SetTab,
|
||||
operator.SwitchTab,
|
||||
prop.StrProperty,
|
||||
operator.BIM_OT_enum_property_search, # /!\ Register AFTER prop.StrProperty
|
||||
prop.ObjProperty,
|
||||
prop.Attribute,
|
||||
prop.BIMAreaProperties,
|
||||
prop.BIMTabProperties,
|
||||
prop.BIMProperties,
|
||||
prop.IfcParameter,
|
||||
prop.PsetQto,
|
||||
@@ -120,29 +126,38 @@ classes = [
|
||||
prop.BIMCollectionProperties,
|
||||
prop.BIMMaterialProperties,
|
||||
prop.BIMMeshProperties,
|
||||
prop.BIMFacet,
|
||||
prop.BIMFilterGroup,
|
||||
ui.BIM_UL_generic,
|
||||
ui.BIM_UL_topics,
|
||||
ui.BIM_ADDON_preferences,
|
||||
# Project overview
|
||||
ui.BIM_PT_project_info,
|
||||
ui.BIM_PT_project_setup,
|
||||
ui.BIM_PT_geometry,
|
||||
ui.BIM_PT_tab_grouping_and_filtering,
|
||||
# Tabs panel
|
||||
ui.BIM_PT_tabs,
|
||||
# Project overview
|
||||
ui.BIM_PT_tab_project_info,
|
||||
ui.BIM_PT_tab_project_setup,
|
||||
ui.BIM_PT_tab_geometry,
|
||||
ui.BIM_PT_tab_stakeholders,
|
||||
ui.BIM_PT_tab_grouping_and_filtering,
|
||||
# Object information
|
||||
ui.BIM_PT_tab_object_metadata,
|
||||
ui.BIM_PT_tab_misc,
|
||||
# Geometry and materials
|
||||
ui.BIM_PT_tab_placement,
|
||||
ui.BIM_PT_tab_representations,
|
||||
ui.BIM_PT_tab_geometric_relationships,
|
||||
ui.BIM_PT_tab_parametric_geometry,
|
||||
ui.BIM_PT_tab_profiles,
|
||||
ui.BIM_PT_tab_materials,
|
||||
ui.BIM_PT_tab_styles,
|
||||
# Drawings and documents
|
||||
ui.BIM_PT_tab_sheets,
|
||||
ui.BIM_PT_tab_drawings,
|
||||
ui.BIM_PT_tab_schedules,
|
||||
ui.BIM_PT_tab_references,
|
||||
# Services and systems
|
||||
ui.BIM_PT_tab_services,
|
||||
ui.BIM_PT_tab_services_object,
|
||||
ui.BIM_PT_tab_zones,
|
||||
# Structural analysis
|
||||
ui.BIM_PT_tab_structural,
|
||||
# Construction scheduling
|
||||
@@ -169,6 +184,7 @@ addon_keymaps = []
|
||||
icons = None
|
||||
is_registering = False
|
||||
last_commit_hash = "8888888"
|
||||
overridden_scene_panels = dict()
|
||||
|
||||
|
||||
def on_register(scene):
|
||||
@@ -193,6 +209,7 @@ def register():
|
||||
bpy.app.handlers.load_post.append(handler.loadIfcStore)
|
||||
bpy.types.Scene.BIMProperties = bpy.props.PointerProperty(type=prop.BIMProperties)
|
||||
bpy.types.Screen.BIMAreaProperties = bpy.props.CollectionProperty(type=prop.BIMAreaProperties)
|
||||
bpy.types.Screen.BIMTabProperties = bpy.props.PointerProperty(type=prop.BIMTabProperties)
|
||||
bpy.types.Collection.BIMCollectionProperties = bpy.props.PointerProperty(type=prop.BIMCollectionProperties)
|
||||
bpy.types.Object.BIMObjectProperties = bpy.props.PointerProperty(type=prop.BIMObjectProperties)
|
||||
bpy.types.Material.BIMObjectProperties = bpy.props.PointerProperty(type=prop.BIMObjectProperties)
|
||||
@@ -210,8 +227,8 @@ def register():
|
||||
|
||||
wm = bpy.context.window_manager
|
||||
if wm.keyconfigs.addon:
|
||||
km = wm.keyconfigs.addon.keymaps.new(name='Window', space_type='EMPTY')
|
||||
kmi = km.keymap_items.new('bim.switch_tab', 'TAB', 'PRESS', ctrl=True)
|
||||
km = wm.keyconfigs.addon.keymaps.new(name="Window", space_type="EMPTY")
|
||||
kmi = km.keymap_items.new("bim.switch_tab", "TAB", "PRESS", ctrl=True)
|
||||
addon_keymaps.append((km, kmi))
|
||||
|
||||
global icons
|
||||
@@ -229,12 +246,16 @@ def register():
|
||||
global last_commit_hash
|
||||
try:
|
||||
import git
|
||||
|
||||
path = Path(__file__).resolve().parent
|
||||
repo = git.Repo(str(path), search_parent_directories=True)
|
||||
last_commit_hash = repo.head.object.hexsha
|
||||
except:
|
||||
pass
|
||||
|
||||
bpy.app.translations.register("blenderbim", translations_dict)
|
||||
|
||||
|
||||
def unregister():
|
||||
global icons
|
||||
|
||||
@@ -271,16 +292,10 @@ def unregister():
|
||||
km.keymap_items.remove(kmi)
|
||||
addon_keymaps.clear()
|
||||
|
||||
for panel in [
|
||||
"SCENE_PT_scene",
|
||||
"SCENE_PT_unit",
|
||||
"SCENE_PT_physics",
|
||||
"SCENE_PT_rigid_body_world",
|
||||
"SCENE_PT_audio",
|
||||
"SCENE_PT_keying_sets",
|
||||
"SCENE_PT_custom_props",
|
||||
]:
|
||||
try:
|
||||
bpy.utils.unregister_class(getattr(handler, f"Override_{panel}"))
|
||||
except:
|
||||
pass
|
||||
for panel in tuple(overridden_scene_panels.keys()):
|
||||
original_panel, override_panel = overridden_scene_panels[panel]
|
||||
bpy.utils.unregister_class(override_panel)
|
||||
bpy.utils.register_class(original_panel)
|
||||
del overridden_scene_panels[panel]
|
||||
|
||||
bpy.app.translations.unregister("blenderbim")
|
||||
|
||||
@@ -0,0 +1,993 @@
|
||||
ISO-10303-21;
|
||||
HEADER;
|
||||
FILE_DESCRIPTION(('ViewDefinition[DesignTransferView]'),'2;1');
|
||||
FILE_NAME('/dev/null','2024-01-24T15:32:17+05:00',(),(),'IfcOpenShell v0.7.0-6c9e130ca','IfcOpenShell v0.7.0-6c9e130ca','Nobody');
|
||||
FILE_SCHEMA(('IFC4'));
|
||||
ENDSEC;
|
||||
DATA;
|
||||
#1=IFCPROJECT('3GRx5GJtv7EvI86hmjeQD6',$,'Landscape Assets Library',$,$,$,$,(#10,#14),#5);
|
||||
#2=IFCPROJECTLIBRARY('1Go1D2HIr9AR4M6PdJb8DW',$,'Landscape Assets Library',$,$,$,$,$,$);
|
||||
#3=IFCRELDECLARES('2Nc$sSRrvCzOJbe4Q6ZcVa',$,$,$,#1,(#2));
|
||||
#4=IFCSIUNIT(*,.LENGTHUNIT.,.MILLI.,.METRE.);
|
||||
#5=IFCUNITASSIGNMENT((#4));
|
||||
#6=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#7=IFCDIRECTION((0.,0.,1.));
|
||||
#8=IFCDIRECTION((1.,0.,0.));
|
||||
#9=IFCAXIS2PLACEMENT3D(#6,#7,#8);
|
||||
#10=IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,1.E-05,#9,$);
|
||||
#11=IFCCARTESIANPOINT((0.,0.));
|
||||
#12=IFCDIRECTION((1.,0.));
|
||||
#13=IFCAXIS2PLACEMENT2D(#11,#12);
|
||||
#14=IFCGEOMETRICREPRESENTATIONCONTEXT($,'Plan',2,1.E-05,#13,$);
|
||||
#15=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Body','Model',*,*,*,*,#10,$,.MODEL_VIEW.,$);
|
||||
#16=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Body','Plan',*,*,*,*,#14,$,.PLAN_VIEW.,$);
|
||||
#17=IFCCARTESIANPOINTLIST2D(((-331.408782958984,488.559936523438),(-428.486114501953,371.370391845703),(-408.744873046875,331.425659179688),(-492.345001220703,263.470184326172),(-519.991760253906,89.2266616821289),(-366.53076171875,65.1004943847656),(-523.9287109375,51.0255508422852),(-542.778625488281,-161.150390625),(-455.430816650391,-198.061676025391),(-467.317413330078,-264.261047363281),(-389.842987060547,-378.319213867188),(-351.178894042969,-382.372741699219),(-243.823715209961,-498.601684570312),(-171.287063598633,-509.852447509766),(-182.036499023438,-454.125518798828),(-123.127815246582,-538.493591308594),(208.583557128906,-495.693969726562),(174.199142456055,-387.101898193359),(269.968353271484,-457.362365722656),(517.720397949219,-208.39501953125),(467.592559814453,-165.981643676758),(535.54443359375,-138.483825683594),(546.240173339844,47.7887229919434),(425.388610839844,29.4520435333252),(514.287658691406,107.907821655273),(467.776489257812,312.002685546875),(374.896423339844,365.066589355469),(325.083190917969,461.613433837891),(224.657806396484,496.0244140625),(105.845329284668,424.517761230469),(191.164672851562,514.677307128906),(-7.41858577728271,553.592407226562),(-105.371849060059,531.902709960938),(-180.417175292969,499.200317382812)));
|
||||
#18=IFCINDEXEDPOLYCURVE(#17,(IFCLINEINDEX((1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,1))),$);
|
||||
#19=IFCCARTESIANPOINTLIST3D(((80.,0.,0.),(40.,69.2820323027551,0.),(-40.,69.2820323027551,0.),(-80.,9.79717439317883E-15,0.),(-40.,-69.2820323027551,0.),(40.,-69.2820323027551,0.),(80.,0.,280.),(40.,69.2820323027551,280.),(-40.,69.2820323027551,280.),(-80.,9.79717439317883E-15,280.),(-40.,-69.2820323027551,280.),(40.,-69.2820323027551,280.),(570.140986817674,-5.11998806339175,502.765430824539),(261.339072714044,511.863483235935,520.441255965265),(-271.449977559115,464.840881207563,498.631051036932),(-577.400357563209,-18.0002392785791,529.745674601363),(-246.747896537159,-522.096293601777,523.07445182747),(289.929723989709,-497.828722152031,481.563368832141),(502.264135660384,-3.10815712380199,727.667741239885),(256.486268377103,397.638199139059,733.570036889682),(-210.099579404528,457.859720268934,722.445245365077),(-522.479901100414,-35.7080296205946,687.931736233252),(-213.081169792834,-438.257812253687,704.648197605265),(273.503462940155,-437.429578762916,717.812431534607),(409.72756228227,-31.3204193188668,937.51589967911),(231.939555298324,334.085354425246,911.578097173966),(-213.440011711198,325.481782873574,931.184023328963),(-391.4385670944,11.3681475906559,933.839400395571),(-181.597613330968,-384.045646583411,936.269525762716),(198.107253544529,-351.52926490917,903.558501964971),(358.836914477244,-29.0443800107266,1124.54961826854),(191.636382145782,325.816574427016,1143.76409675514),(-175.686180114122,275.257306965059,1132.35007279295),(-330.55780048986,-23.1508504281077,1121.17416888324),(-172.687090174965,-317.707089809191,1159.279616419),(192.616008554028,-273.601791847896,1147.14103266758),(252.691797114565,-4.70084047240072,1330.07490310776),(147.138603790187,216.221351494253,1352.71275883304),(-162.078730999078,224.60205813657,1371.67941135993),(-271.544406853979,26.607279268613,1378.19571732018),(-150.451939922955,-226.516554345382,1395.27272058484),(133.281231324475,-220.990480915293,1334.23398662872),(187.5691337229,-2.77622907865673,1575.7384942221),(88.4380124532162,169.216774598146,1585.64117034361),(-94.8941720337192,139.038794764388,1578.6341137138),(-154.588503036945,-6.10749408831602,1549.40002660187),(-129.962875945536,-160.551322551302,1550.49839466833),(64.8441918513045,-191.270989336927,1579.55078264226),(0.05,0.,1800.),(0.025,0.0433012701892219,1800.),(-0.025,0.0433012701892219,1800.),(-0.05,6.12323399573677E-18,1800.),(-0.025,-0.0433012701892219,1800.),(0.025,-0.0433012701892219,1800.)));
|
||||
#20=IFCINDEXEDPOLYGONALFACE((1,2,3,4,5,6));
|
||||
#21=IFCINDEXEDPOLYGONALFACE((6,1,7,12));
|
||||
#22=IFCINDEXEDPOLYGONALFACE((1,2,8,7));
|
||||
#23=IFCINDEXEDPOLYGONALFACE((2,3,9,8));
|
||||
#24=IFCINDEXEDPOLYGONALFACE((3,4,10,9));
|
||||
#25=IFCINDEXEDPOLYGONALFACE((4,5,11,10));
|
||||
#26=IFCINDEXEDPOLYGONALFACE((5,6,12,11));
|
||||
#27=IFCINDEXEDPOLYGONALFACE((12,7,13,18));
|
||||
#28=IFCINDEXEDPOLYGONALFACE((7,8,14,13));
|
||||
#29=IFCINDEXEDPOLYGONALFACE((8,9,15,14));
|
||||
#30=IFCINDEXEDPOLYGONALFACE((9,10,16,15));
|
||||
#31=IFCINDEXEDPOLYGONALFACE((10,11,17,16));
|
||||
#32=IFCINDEXEDPOLYGONALFACE((11,12,18,17));
|
||||
#33=IFCINDEXEDPOLYGONALFACE((18,13,19,24));
|
||||
#34=IFCINDEXEDPOLYGONALFACE((13,14,20,19));
|
||||
#35=IFCINDEXEDPOLYGONALFACE((14,15,21,20));
|
||||
#36=IFCINDEXEDPOLYGONALFACE((15,16,22,21));
|
||||
#37=IFCINDEXEDPOLYGONALFACE((16,17,23,22));
|
||||
#38=IFCINDEXEDPOLYGONALFACE((17,18,24,23));
|
||||
#39=IFCINDEXEDPOLYGONALFACE((24,19,25,30));
|
||||
#40=IFCINDEXEDPOLYGONALFACE((19,20,26,25));
|
||||
#41=IFCINDEXEDPOLYGONALFACE((20,21,27,26));
|
||||
#42=IFCINDEXEDPOLYGONALFACE((21,22,28,27));
|
||||
#43=IFCINDEXEDPOLYGONALFACE((22,23,29,28));
|
||||
#44=IFCINDEXEDPOLYGONALFACE((23,24,30,29));
|
||||
#45=IFCINDEXEDPOLYGONALFACE((30,25,31,36));
|
||||
#46=IFCINDEXEDPOLYGONALFACE((25,26,32,31));
|
||||
#47=IFCINDEXEDPOLYGONALFACE((26,27,33,32));
|
||||
#48=IFCINDEXEDPOLYGONALFACE((27,28,34,33));
|
||||
#49=IFCINDEXEDPOLYGONALFACE((28,29,35,34));
|
||||
#50=IFCINDEXEDPOLYGONALFACE((29,30,36,35));
|
||||
#51=IFCINDEXEDPOLYGONALFACE((36,31,37,42));
|
||||
#52=IFCINDEXEDPOLYGONALFACE((31,32,38,37));
|
||||
#53=IFCINDEXEDPOLYGONALFACE((32,33,39,38));
|
||||
#54=IFCINDEXEDPOLYGONALFACE((33,34,40,39));
|
||||
#55=IFCINDEXEDPOLYGONALFACE((34,35,41,40));
|
||||
#56=IFCINDEXEDPOLYGONALFACE((35,36,42,41));
|
||||
#57=IFCINDEXEDPOLYGONALFACE((42,37,43,48));
|
||||
#58=IFCINDEXEDPOLYGONALFACE((37,38,44,43));
|
||||
#59=IFCINDEXEDPOLYGONALFACE((38,39,45,44));
|
||||
#60=IFCINDEXEDPOLYGONALFACE((39,40,46,45));
|
||||
#61=IFCINDEXEDPOLYGONALFACE((40,41,47,46));
|
||||
#62=IFCINDEXEDPOLYGONALFACE((41,42,48,47));
|
||||
#63=IFCINDEXEDPOLYGONALFACE((48,43,49,54));
|
||||
#64=IFCINDEXEDPOLYGONALFACE((43,44,50,49));
|
||||
#65=IFCINDEXEDPOLYGONALFACE((44,45,51,50));
|
||||
#66=IFCINDEXEDPOLYGONALFACE((45,46,52,51));
|
||||
#67=IFCINDEXEDPOLYGONALFACE((46,47,53,52));
|
||||
#68=IFCINDEXEDPOLYGONALFACE((47,48,54,53));
|
||||
#69=IFCINDEXEDPOLYGONALFACE((49,50,51,52,53,54));
|
||||
#70=IFCPOLYGONALFACESET(#19,$,(#20,#21,#22,#23,#24,#25,#26,#27,#28,#29,#30,#31,#32,#33,#34,#35,#36,#37,#38,#39,#40,#41,#42,#43,#44,#45,#46,#47,#48,#49,#50,#51,#52,#53,#54,#55,#56,#57,#58,#59,#60,#61,#62,#63,#64,#65,#66,#67,#68,#69),$);
|
||||
#71=IFCSHAPEREPRESENTATION(#16,'Body','Curve2D',(#18));
|
||||
#72=IFCSHAPEREPRESENTATION(#15,'Body','Tessellation',(#70));
|
||||
#73=IFCGEOGRAPHICELEMENTTYPE('34zHVx8cX0dRoaynJ1QKTg',$,'Cone Tree (1.8m)',$,$,$,(#78,#83),$,$,.NOTDEFINED.);
|
||||
#74=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#75=IFCDIRECTION((1.,0.,0.));
|
||||
#76=IFCDIRECTION((0.,0.,1.));
|
||||
#77=IFCAXIS2PLACEMENT3D(#74,#76,#75);
|
||||
#78=IFCREPRESENTATIONMAP(#77,#72);
|
||||
#79=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#80=IFCDIRECTION((1.,0.,0.));
|
||||
#81=IFCDIRECTION((0.,0.,1.));
|
||||
#82=IFCAXIS2PLACEMENT3D(#79,#81,#80);
|
||||
#83=IFCREPRESENTATIONMAP(#82,#71);
|
||||
#84=IFCRELDECLARES('2hc5gFJQT6VP_pTBscCuS_',$,$,$,#2,(#840,#409,#680,#208,#613,#73,#342,#773,#275,#479,#742,#907,#711,#141,#546,#974,#444));
|
||||
#85=IFCCARTESIANPOINTLIST2D(((-1281.64282226562,1889.38659667969),(-1657.06579589844,1436.1845703125),(-1580.72131347656,1281.70812988281),(-1904.02453613281,1018.90686035156),(-2010.94165039062,345.062408447266),(-1417.46850585938,251.760314941406),(-2026.16674804688,197.328903198242),(-2099.06420898438,-623.209899902344),(-1761.26782226562,-765.955322265625),(-1807.236328125,-1021.96527099609),(-1507.62292480469,-1463.05749511719),(-1358.09887695312,-1478.73352050781),(-942.928833007812,-1928.220703125),(-662.411010742188,-1971.73022460938),(-703.981872558594,-1756.21984863281),(-476.166870117188,-2082.49291992188),(806.646179199219,-1916.97583007812),(673.672790527344,-1497.02233886719),(1044.03686523438,-1768.73767089844),(2002.15771484375,-805.917053222656),(1808.30041503906,-641.893615722656),(2071.087890625,-535.552490234375),(2112.45092773438,184.811248779297),(1645.0869140625,113.898612976074),(1988.88244628906,417.307220458984),(1809.01171875,1206.59436035156),(1449.82067871094,1411.80627441406),(1257.18005371094,1785.17761230469),(868.809387207031,1918.25366210938),(409.3310546875,1641.71911621094),(739.282836914062,1990.38916015625),(-28.6895751953125,2140.8837890625),(-407.5,2057.00415039062),(-697.719543457031,1930.53576660156)));
|
||||
#86=IFCINDEXEDPOLYCURVE(#85,(IFCLINEINDEX((1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,1))),$);
|
||||
#87=IFCCARTESIANPOINTLIST3D(((220.,0.,0.),(110.,190.525588832576,0.),(-110.,190.525588832577,0.),(-220.,2.69422295812418E-14,0.),(-110.,-190.525588832576,0.),(110.,-190.525588832576,0.),(220.,0.,740.),(110.,190.525588832576,740.),(-110.,190.525588832577,740.),(-220.,2.69422295812418E-14,740.),(-110.,-190.525588832576,740.),(110.,-190.525588832576,740.),(2227.84155681395,-42.6665671949312,2823.99763782354),(916.158939283701,2080.25825808339,2971.29618066292),(-1000.41647965929,1688.40324118029,2789.54447292681),(-2288.33631302674,-150.00199398816,3048.8330026304),(-794.565804476328,-2165.53167779874,2993.23947951463),(1154.41436658091,-1963.30191571753,2647.31378788689),(1998.64557494764,-25.9013093650166,4925.80260557047),(1043.94112536474,1419.75032646046,4974.98840265211),(-657.385383926618,1921.59633587608,4882.28180661374),(-2167.11028694789,-297.566913504955,4594.66923051519),(-682.231970495834,-1758.24710241569,4733.97307528197),(1185.75108005685,-1751.34515665926,4843.67502469316),(1563.95190790781,-261.00349432389,6902.15630684973),(1007.60740526381,1181.51272302971,6686.0079526402),(-853.444542037762,1109.81629343244,6849.3906705985),(-1411.54361467555,94.7345632554656,6871.51881282023),(-588.091222202507,-1597.84849101442,6891.76985754645),(725.67155731552,-1326.87864372908,6619.17799256523),(1476.3076206437,-242.036500089388,8688.38967604738),(839.969851214854,1403.97565889549,8848.51033010232),(-707.051500951019,982.648430045852,8753.39346375077),(-1240.6483374155,-192.923753567565,8660.26093116989),(-682.059084791378,-1336.39662041362,8977.80632730116),(848.133404616898,-968.852470736159,8876.65146270604),(928.209420399157,-39.1736706033394,10628.7194306599),(637.377253807116,782.05157030683,10817.3682283706),(-761.878313881205,851.890792326142,10975.4236660946),(-1085.31450156094,221.727327238442,11029.7262157634),(-664.988388246851,-867.844927399578,11172.0345763022),(521.899149926181,-821.794315482163,10663.3784600012),(721.965003246392,-23.1352423221394,12903.5350708985),(316.42788155458,681.716198690303,12986.057371911),(-370.229211392105,430.233033408991,12927.6652333293),(-447.126414196768,-50.8957840693003,12684.0478407298),(-662.468410657245,-609.504098299938,12693.2009079504),(119.812709871982,-865.501321513485,12935.3041410664),(0.05,0.,15000.),(0.025,0.0433012701892219,15000.),(-0.025,0.0433012701892219,15000.),(-0.05,6.12323399573677E-18,15000.),(-0.025,-0.0433012701892219,15000.),(0.025,-0.0433012701892219,15000.)));
|
||||
#88=IFCINDEXEDPOLYGONALFACE((1,2,3,4,5,6));
|
||||
#89=IFCINDEXEDPOLYGONALFACE((6,1,7,12));
|
||||
#90=IFCINDEXEDPOLYGONALFACE((1,2,8,7));
|
||||
#91=IFCINDEXEDPOLYGONALFACE((2,3,9,8));
|
||||
#92=IFCINDEXEDPOLYGONALFACE((3,4,10,9));
|
||||
#93=IFCINDEXEDPOLYGONALFACE((4,5,11,10));
|
||||
#94=IFCINDEXEDPOLYGONALFACE((5,6,12,11));
|
||||
#95=IFCINDEXEDPOLYGONALFACE((12,7,13,18));
|
||||
#96=IFCINDEXEDPOLYGONALFACE((7,8,14,13));
|
||||
#97=IFCINDEXEDPOLYGONALFACE((8,9,15,14));
|
||||
#98=IFCINDEXEDPOLYGONALFACE((9,10,16,15));
|
||||
#99=IFCINDEXEDPOLYGONALFACE((10,11,17,16));
|
||||
#100=IFCINDEXEDPOLYGONALFACE((11,12,18,17));
|
||||
#101=IFCINDEXEDPOLYGONALFACE((18,13,19,24));
|
||||
#102=IFCINDEXEDPOLYGONALFACE((13,14,20,19));
|
||||
#103=IFCINDEXEDPOLYGONALFACE((14,15,21,20));
|
||||
#104=IFCINDEXEDPOLYGONALFACE((15,16,22,21));
|
||||
#105=IFCINDEXEDPOLYGONALFACE((16,17,23,22));
|
||||
#106=IFCINDEXEDPOLYGONALFACE((17,18,24,23));
|
||||
#107=IFCINDEXEDPOLYGONALFACE((24,19,25,30));
|
||||
#108=IFCINDEXEDPOLYGONALFACE((19,20,26,25));
|
||||
#109=IFCINDEXEDPOLYGONALFACE((20,21,27,26));
|
||||
#110=IFCINDEXEDPOLYGONALFACE((21,22,28,27));
|
||||
#111=IFCINDEXEDPOLYGONALFACE((22,23,29,28));
|
||||
#112=IFCINDEXEDPOLYGONALFACE((23,24,30,29));
|
||||
#113=IFCINDEXEDPOLYGONALFACE((30,25,31,36));
|
||||
#114=IFCINDEXEDPOLYGONALFACE((25,26,32,31));
|
||||
#115=IFCINDEXEDPOLYGONALFACE((26,27,33,32));
|
||||
#116=IFCINDEXEDPOLYGONALFACE((27,28,34,33));
|
||||
#117=IFCINDEXEDPOLYGONALFACE((28,29,35,34));
|
||||
#118=IFCINDEXEDPOLYGONALFACE((29,30,36,35));
|
||||
#119=IFCINDEXEDPOLYGONALFACE((36,31,37,42));
|
||||
#120=IFCINDEXEDPOLYGONALFACE((31,32,38,37));
|
||||
#121=IFCINDEXEDPOLYGONALFACE((32,33,39,38));
|
||||
#122=IFCINDEXEDPOLYGONALFACE((33,34,40,39));
|
||||
#123=IFCINDEXEDPOLYGONALFACE((34,35,41,40));
|
||||
#124=IFCINDEXEDPOLYGONALFACE((35,36,42,41));
|
||||
#125=IFCINDEXEDPOLYGONALFACE((42,37,43,48));
|
||||
#126=IFCINDEXEDPOLYGONALFACE((37,38,44,43));
|
||||
#127=IFCINDEXEDPOLYGONALFACE((38,39,45,44));
|
||||
#128=IFCINDEXEDPOLYGONALFACE((39,40,46,45));
|
||||
#129=IFCINDEXEDPOLYGONALFACE((40,41,47,46));
|
||||
#130=IFCINDEXEDPOLYGONALFACE((41,42,48,47));
|
||||
#131=IFCINDEXEDPOLYGONALFACE((48,43,49,54));
|
||||
#132=IFCINDEXEDPOLYGONALFACE((43,44,50,49));
|
||||
#133=IFCINDEXEDPOLYGONALFACE((44,45,51,50));
|
||||
#134=IFCINDEXEDPOLYGONALFACE((45,46,52,51));
|
||||
#135=IFCINDEXEDPOLYGONALFACE((46,47,53,52));
|
||||
#136=IFCINDEXEDPOLYGONALFACE((47,48,54,53));
|
||||
#137=IFCINDEXEDPOLYGONALFACE((49,50,51,52,53,54));
|
||||
#138=IFCPOLYGONALFACESET(#87,$,(#88,#89,#90,#91,#92,#93,#94,#95,#96,#97,#98,#99,#100,#101,#102,#103,#104,#105,#106,#107,#108,#109,#110,#111,#112,#113,#114,#115,#116,#117,#118,#119,#120,#121,#122,#123,#124,#125,#126,#127,#128,#129,#130,#131,#132,#133,#134,#135,#136,#137),$);
|
||||
#139=IFCSHAPEREPRESENTATION(#16,'Body','Curve2D',(#86));
|
||||
#140=IFCSHAPEREPRESENTATION(#15,'Body','Tessellation',(#138));
|
||||
#141=IFCGEOGRAPHICELEMENTTYPE('1up5YjiS1CSvOopNo9qhzA',$,'Cone Tree (15m)',$,$,$,(#146,#151),$,$,.NOTDEFINED.);
|
||||
#142=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#143=IFCDIRECTION((1.,0.,0.));
|
||||
#144=IFCDIRECTION((0.,0.,1.));
|
||||
#145=IFCAXIS2PLACEMENT3D(#142,#144,#143);
|
||||
#146=IFCREPRESENTATIONMAP(#145,#140);
|
||||
#147=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#148=IFCDIRECTION((1.,0.,0.));
|
||||
#149=IFCDIRECTION((0.,0.,1.));
|
||||
#150=IFCAXIS2PLACEMENT3D(#147,#149,#148);
|
||||
#151=IFCREPRESENTATIONMAP(#150,#139);
|
||||
#152=IFCCARTESIANPOINTLIST2D(((-498.579620361328,735.001647949219),(-644.625122070312,558.698791503906),(-614.925903320312,498.60498046875),(-740.696044921875,396.37109375),(-782.288513183594,134.234802246094),(-551.41796875,97.9387969970703),(-788.211303710938,76.7640991210938),(-816.569641113281,-242.43864440918),(-685.161376953125,-297.968902587891),(-703.043884277344,-397.560852050781),(-586.489440917969,-569.15283203125),(-528.322204589844,-575.251037597656),(-366.814422607422,-750.108703613281),(-257.688507080078,-767.03466796875),(-273.860229492188,-683.197692871094),(-185.236541748047,-810.123107910156),(313.798278808594,-745.734313964844),(262.069519042969,-582.365661621094),(406.147064208984,-688.067260742188),(778.871398925781,-313.5146484375),(703.457824707031,-249.706893920898),(805.686340332031,-208.338500976562),(821.777282714844,71.8945388793945),(639.965148925781,44.3083839416504),(773.707153320312,162.339202880859),(703.734558105469,469.384552001953),(564.003479003906,549.215209960938),(489.063201904297,694.462707519531),(337.980773925781,746.2314453125),(159.236328125,638.655029296875),(287.592864990234,774.293273925781),(-11.1607036590576,832.838073730469),(-158.524017333984,800.207580566406),(-271.424072265625,751.009338378906)));
|
||||
#153=IFCINDEXEDPOLYCURVE(#152,(IFCLINEINDEX((1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,1))),$);
|
||||
#154=IFCCARTESIANPOINTLIST3D(((110.,0.,0.),(55.,95.2627944162882,0.),(-55.,95.2627944162883,0.),(-110.,1.34711147906209E-14,0.),(-55.,-95.2627944162882,0.),(55.,-95.2627944162882,0.),(110.,0.,320.),(55.,95.2627944162882,320.),(-55.,95.2627944162883,320.),(-110.,1.34711147906209E-14,320.),(-55.,-95.2627944162882,320.),(55.,-95.2627944162882,320.),(864.280518937983,-14.2221890649771,1004.18968879832),(366.2196464279,798.785843488237,1053.28920307812),(-394.305493219765,668.167504520537,992.705300499414),(-884.445437675581,-50.0006646627198,1079.13481040061),(-325.688601492109,-827.210316726686,1060.60363602869),(445.638122193637,-759.800396032949,945.295072152772),(771.659636093658,-8.63376978833887,1694.31515423778),(400.702597343804,564.567676396979,1710.71041993166),(-271.850683531095,731.84967953552,1679.8082212522),(-827.814540093743,-99.1889711683184,1583.93736255268),(-280.132879054167,-677.399935048722,1630.37197747494),(447.972582241171,-675.099286463246,1666.93929394534),(610.539524858158,-87.0011647746299,2342.62353085467),(380.480246199047,471.106285369781,2270.57407945149),(-329.092625123698,447.207475504026,2325.0349854376),(-559.736760447407,31.5781877518219,2332.41103284484),(-240.641518511947,-609.88487469802,2339.16138108691),(286.501630216284,-519.561592269572,2248.29742609317),(565.102540214566,-80.6788333631295,2927.55846344436),(316.489950404951,531.211740774762,2980.93201479601),(-272.18383365034,390.769331158215,2949.22639267883),(-486.549445805167,-64.3079178558549,2918.18221515187),(-263.853028263793,-508.685394614137,3024.03068052896),(319.211134872299,-386.170678054984,2990.31239233058),(366.18091791083,-13.0578902011131,3563.85885783901),(240.847973491261,309.854854694926,3626.74179040925),(-282.348326849291,333.134595368031,3679.42693631726),(-418.54927829809,73.9091090794806,3697.52778620685),(-250.051684971173,-338.452640392509,3744.96390638646),(202.355272197616,-323.102436420037,3575.41186761945),(281.210556637686,-7.71174744071313,4311.65454744235),(125.753738295971,262.36087427247,4339.1619811132),(-143.687514908479,178.533152512032,4319.69793491929),(-189.597693621145,-16.9652613564334,4238.49213738614),(-241.100581330193,-238.290174142348,4241.54315979299),(60.215347735105,-323.622581880197,4322.24423749834),(0.05,0.,5000.),(0.025,0.0433012701892219,5000.),(-0.025,0.0433012701892219,5000.),(-0.05,6.12323399573677E-18,5000.),(-0.025,-0.0433012701892219,5000.),(0.025,-0.0433012701892219,5000.)));
|
||||
#155=IFCINDEXEDPOLYGONALFACE((1,2,3,4,5,6));
|
||||
#156=IFCINDEXEDPOLYGONALFACE((6,1,7,12));
|
||||
#157=IFCINDEXEDPOLYGONALFACE((1,2,8,7));
|
||||
#158=IFCINDEXEDPOLYGONALFACE((2,3,9,8));
|
||||
#159=IFCINDEXEDPOLYGONALFACE((3,4,10,9));
|
||||
#160=IFCINDEXEDPOLYGONALFACE((4,5,11,10));
|
||||
#161=IFCINDEXEDPOLYGONALFACE((5,6,12,11));
|
||||
#162=IFCINDEXEDPOLYGONALFACE((12,7,13,18));
|
||||
#163=IFCINDEXEDPOLYGONALFACE((7,8,14,13));
|
||||
#164=IFCINDEXEDPOLYGONALFACE((8,9,15,14));
|
||||
#165=IFCINDEXEDPOLYGONALFACE((9,10,16,15));
|
||||
#166=IFCINDEXEDPOLYGONALFACE((10,11,17,16));
|
||||
#167=IFCINDEXEDPOLYGONALFACE((11,12,18,17));
|
||||
#168=IFCINDEXEDPOLYGONALFACE((18,13,19,24));
|
||||
#169=IFCINDEXEDPOLYGONALFACE((13,14,20,19));
|
||||
#170=IFCINDEXEDPOLYGONALFACE((14,15,21,20));
|
||||
#171=IFCINDEXEDPOLYGONALFACE((15,16,22,21));
|
||||
#172=IFCINDEXEDPOLYGONALFACE((16,17,23,22));
|
||||
#173=IFCINDEXEDPOLYGONALFACE((17,18,24,23));
|
||||
#174=IFCINDEXEDPOLYGONALFACE((24,19,25,30));
|
||||
#175=IFCINDEXEDPOLYGONALFACE((19,20,26,25));
|
||||
#176=IFCINDEXEDPOLYGONALFACE((20,21,27,26));
|
||||
#177=IFCINDEXEDPOLYGONALFACE((21,22,28,27));
|
||||
#178=IFCINDEXEDPOLYGONALFACE((22,23,29,28));
|
||||
#179=IFCINDEXEDPOLYGONALFACE((23,24,30,29));
|
||||
#180=IFCINDEXEDPOLYGONALFACE((30,25,31,36));
|
||||
#181=IFCINDEXEDPOLYGONALFACE((25,26,32,31));
|
||||
#182=IFCINDEXEDPOLYGONALFACE((26,27,33,32));
|
||||
#183=IFCINDEXEDPOLYGONALFACE((27,28,34,33));
|
||||
#184=IFCINDEXEDPOLYGONALFACE((28,29,35,34));
|
||||
#185=IFCINDEXEDPOLYGONALFACE((29,30,36,35));
|
||||
#186=IFCINDEXEDPOLYGONALFACE((36,31,37,42));
|
||||
#187=IFCINDEXEDPOLYGONALFACE((31,32,38,37));
|
||||
#188=IFCINDEXEDPOLYGONALFACE((32,33,39,38));
|
||||
#189=IFCINDEXEDPOLYGONALFACE((33,34,40,39));
|
||||
#190=IFCINDEXEDPOLYGONALFACE((34,35,41,40));
|
||||
#191=IFCINDEXEDPOLYGONALFACE((35,36,42,41));
|
||||
#192=IFCINDEXEDPOLYGONALFACE((42,37,43,48));
|
||||
#193=IFCINDEXEDPOLYGONALFACE((37,38,44,43));
|
||||
#194=IFCINDEXEDPOLYGONALFACE((38,39,45,44));
|
||||
#195=IFCINDEXEDPOLYGONALFACE((39,40,46,45));
|
||||
#196=IFCINDEXEDPOLYGONALFACE((40,41,47,46));
|
||||
#197=IFCINDEXEDPOLYGONALFACE((41,42,48,47));
|
||||
#198=IFCINDEXEDPOLYGONALFACE((48,43,49,54));
|
||||
#199=IFCINDEXEDPOLYGONALFACE((43,44,50,49));
|
||||
#200=IFCINDEXEDPOLYGONALFACE((44,45,51,50));
|
||||
#201=IFCINDEXEDPOLYGONALFACE((45,46,52,51));
|
||||
#202=IFCINDEXEDPOLYGONALFACE((46,47,53,52));
|
||||
#203=IFCINDEXEDPOLYGONALFACE((47,48,54,53));
|
||||
#204=IFCINDEXEDPOLYGONALFACE((49,50,51,52,53,54));
|
||||
#205=IFCPOLYGONALFACESET(#154,$,(#155,#156,#157,#158,#159,#160,#161,#162,#163,#164,#165,#166,#167,#168,#169,#170,#171,#172,#173,#174,#175,#176,#177,#178,#179,#180,#181,#182,#183,#184,#185,#186,#187,#188,#189,#190,#191,#192,#193,#194,#195,#196,#197,#198,#199,#200,#201,#202,#203,#204),$);
|
||||
#206=IFCSHAPEREPRESENTATION(#16,'Body','Curve2D',(#153));
|
||||
#207=IFCSHAPEREPRESENTATION(#15,'Body','Tessellation',(#205));
|
||||
#208=IFCGEOGRAPHICELEMENTTYPE('1cYi681Jz1UQcLu0VCPumj',$,'Cone Tree (5m)',$,$,$,(#213,#218),$,$,.NOTDEFINED.);
|
||||
#209=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#210=IFCDIRECTION((1.,0.,0.));
|
||||
#211=IFCDIRECTION((0.,0.,1.));
|
||||
#212=IFCAXIS2PLACEMENT3D(#209,#211,#210);
|
||||
#213=IFCREPRESENTATIONMAP(#212,#207);
|
||||
#214=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#215=IFCDIRECTION((1.,0.,0.));
|
||||
#216=IFCDIRECTION((0.,0.,1.));
|
||||
#217=IFCAXIS2PLACEMENT3D(#214,#216,#215);
|
||||
#218=IFCREPRESENTATIONMAP(#217,#206);
|
||||
#219=IFCCARTESIANPOINTLIST2D(((-117.312850952148,172.941558837891),(-151.676498413086,131.458541870117),(-144.688446044922,117.318817138672),(-174.28141784668,93.263786315918),(-184.067886352539,31.584659576416),(-129.745407104492,23.0444221496582),(-185.461486816406,18.062141418457),(-192.134033203125,-57.0443878173828),(-161.214447021484,-70.1103286743164),(-165.422088623047,-93.5437316894531),(-137.997512817383,-133.918304443359),(-124.311111450195,-135.353179931641),(-86.3092803955078,-176.496170043945),(-60.6325874328613,-180.478744506836),(-64.4376983642578,-160.752395629883),(-43.5850677490234,-190.617202758789),(73.8348922729492,-175.466888427734),(61.6634140014648,-137.027221679688),(95.5640106201172,-161.898178100586),(183.263854980469,-73.7681503295898),(165.519485473633,-58.7545623779297),(189.573257446289,-49.020824432373),(193.359359741211,16.9163608551025),(150.580032348633,10.4255018234253),(182.048736572266,38.1974563598633),(165.584594726562,110.443428039551),(132.706695556641,129.227111816406),(115.073692321777,163.402984619141),(79.5248870849609,175.583862304688),(37.4673728942871,150.271774291992),(67.6689071655273,182.186645507812),(-2.62604808807373,195.961898803711),(-37.2997703552246,188.284133911133),(-63.8644866943359,176.708084106445)));
|
||||
#220=IFCINDEXEDPOLYCURVE(#219,(IFCLINEINDEX((1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,1))),$);
|
||||
#221=IFCCARTESIANPOINTLIST3D(((0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(189.142441515039,-1.13777512519817,58.3923179610087),(89.297571714232,167.825915933192,62.3202791033923),(-91.5444394575811,157.376448815776,57.4735668970959),(-190.755635014047,-4.00005317301757,64.3879276891917),(-86.0550881193688,-170.099873792268,62.9054337394378),(95.651049775491,-164.707080136769,53.6807486293646),(196.799437554159,-0.69070158306711,117.259498053308),(99.5895411208377,162.136578649577,118.571119308818),(-89.2813880158209,175.51913890066,116.098943414462),(-201.291829874166,-7.93511769346546,108.4292747185),(-89.9439636576667,-171.163159341716,112.144043912281),(103.371139912627,-170.979107454878,115.069429229913),(198.976495321986,-6.96009318197039,172.781311039802),(105.50508636259,167.707783451086,167.017354927548),(-101.394076676563,165.795878661826,171.374227406436),(-194.912274169126,2.52625502014577,171.964311199016),(-94.3179881476225,-178.810070597345,172.504339058381),(97.9867970839694,-171.58420800307,165.235222658882),(198.408203217165,-6.45430666905036,223.233248504121),(101.919196032396,175.172031121757,227.503132612252),(-98.3747066920271,163.936638352433,224.966682842878),(-192.123955664413,-5.14463342846837,222.483148640721),(-97.7082422611035,-173.369923428907,230.951025870888),(102.136890789784,-163.568746104175,228.253562815018),(185.561140099533,-1.04463121608905,277.794422912835),(97.4011712126342,160.119291473642,282.825057518454),(-100.721199481277,161.981670727491,287.039869191095),(-189.750608930514,5.91272872635847,288.487937182262),(-98.1374681310272,-162.407114329449,292.282826796631),(94.3217551091426,-161.179098011651,278.71866369527),(181.830177864348,-0.61693979525705,341.275220938245),(89.7269657303444,158.975584278118,343.475815631913),(-91.161667859345,152.269366537283,341.9186919364),(-174.501148823025,-1.35722090851465,335.422228133748),(-98.9547131730822,-157.049928267708,335.666309926296),(84.4838944854751,-163.876520886736,342.122396142724),(0.05,0.,400.),(0.025,0.0433012701892219,400.),(-0.025,0.0433012701892219,400.),(-0.05,6.12323399573677E-18,400.),(-0.025,-0.0433012701892219,400.),(0.025,-0.0433012701892219,400.)));
|
||||
#222=IFCINDEXEDPOLYGONALFACE((1,2,3,4,5,6));
|
||||
#223=IFCINDEXEDPOLYGONALFACE((6,1,7,12));
|
||||
#224=IFCINDEXEDPOLYGONALFACE((1,2,8,7));
|
||||
#225=IFCINDEXEDPOLYGONALFACE((2,3,9,8));
|
||||
#226=IFCINDEXEDPOLYGONALFACE((3,4,10,9));
|
||||
#227=IFCINDEXEDPOLYGONALFACE((4,5,11,10));
|
||||
#228=IFCINDEXEDPOLYGONALFACE((5,6,12,11));
|
||||
#229=IFCINDEXEDPOLYGONALFACE((12,7,13,18));
|
||||
#230=IFCINDEXEDPOLYGONALFACE((7,8,14,13));
|
||||
#231=IFCINDEXEDPOLYGONALFACE((8,9,15,14));
|
||||
#232=IFCINDEXEDPOLYGONALFACE((9,10,16,15));
|
||||
#233=IFCINDEXEDPOLYGONALFACE((10,11,17,16));
|
||||
#234=IFCINDEXEDPOLYGONALFACE((11,12,18,17));
|
||||
#235=IFCINDEXEDPOLYGONALFACE((18,13,19,24));
|
||||
#236=IFCINDEXEDPOLYGONALFACE((13,14,20,19));
|
||||
#237=IFCINDEXEDPOLYGONALFACE((14,15,21,20));
|
||||
#238=IFCINDEXEDPOLYGONALFACE((15,16,22,21));
|
||||
#239=IFCINDEXEDPOLYGONALFACE((16,17,23,22));
|
||||
#240=IFCINDEXEDPOLYGONALFACE((17,18,24,23));
|
||||
#241=IFCINDEXEDPOLYGONALFACE((24,19,25,30));
|
||||
#242=IFCINDEXEDPOLYGONALFACE((19,20,26,25));
|
||||
#243=IFCINDEXEDPOLYGONALFACE((20,21,27,26));
|
||||
#244=IFCINDEXEDPOLYGONALFACE((21,22,28,27));
|
||||
#245=IFCINDEXEDPOLYGONALFACE((22,23,29,28));
|
||||
#246=IFCINDEXEDPOLYGONALFACE((23,24,30,29));
|
||||
#247=IFCINDEXEDPOLYGONALFACE((30,25,31,36));
|
||||
#248=IFCINDEXEDPOLYGONALFACE((25,26,32,31));
|
||||
#249=IFCINDEXEDPOLYGONALFACE((26,27,33,32));
|
||||
#250=IFCINDEXEDPOLYGONALFACE((27,28,34,33));
|
||||
#251=IFCINDEXEDPOLYGONALFACE((28,29,35,34));
|
||||
#252=IFCINDEXEDPOLYGONALFACE((29,30,36,35));
|
||||
#253=IFCINDEXEDPOLYGONALFACE((36,31,37,42));
|
||||
#254=IFCINDEXEDPOLYGONALFACE((31,32,38,37));
|
||||
#255=IFCINDEXEDPOLYGONALFACE((32,33,39,38));
|
||||
#256=IFCINDEXEDPOLYGONALFACE((33,34,40,39));
|
||||
#257=IFCINDEXEDPOLYGONALFACE((34,35,41,40));
|
||||
#258=IFCINDEXEDPOLYGONALFACE((35,36,42,41));
|
||||
#259=IFCINDEXEDPOLYGONALFACE((42,37,43,48));
|
||||
#260=IFCINDEXEDPOLYGONALFACE((37,38,44,43));
|
||||
#261=IFCINDEXEDPOLYGONALFACE((38,39,45,44));
|
||||
#262=IFCINDEXEDPOLYGONALFACE((39,40,46,45));
|
||||
#263=IFCINDEXEDPOLYGONALFACE((40,41,47,46));
|
||||
#264=IFCINDEXEDPOLYGONALFACE((41,42,48,47));
|
||||
#265=IFCINDEXEDPOLYGONALFACE((48,43,49,54));
|
||||
#266=IFCINDEXEDPOLYGONALFACE((43,44,50,49));
|
||||
#267=IFCINDEXEDPOLYGONALFACE((44,45,51,50));
|
||||
#268=IFCINDEXEDPOLYGONALFACE((45,46,52,51));
|
||||
#269=IFCINDEXEDPOLYGONALFACE((46,47,53,52));
|
||||
#270=IFCINDEXEDPOLYGONALFACE((47,48,54,53));
|
||||
#271=IFCINDEXEDPOLYGONALFACE((49,50,51,52,53,54));
|
||||
#272=IFCPOLYGONALFACESET(#221,$,(#222,#223,#224,#225,#226,#227,#228,#229,#230,#231,#232,#233,#234,#235,#236,#237,#238,#239,#240,#241,#242,#243,#244,#245,#246,#247,#248,#249,#250,#251,#252,#253,#254,#255,#256,#257,#258,#259,#260,#261,#262,#263,#264,#265,#266,#267,#268,#269,#270,#271),$);
|
||||
#273=IFCSHAPEREPRESENTATION(#16,'Body','Curve2D',(#220));
|
||||
#274=IFCSHAPEREPRESENTATION(#15,'Body','Tessellation',(#272));
|
||||
#275=IFCGEOGRAPHICELEMENTTYPE('1mO0fZa2b4sflxAiM3QTIb',$,'Hedge Small (0.4m)',$,$,$,(#280,#285),$,$,.NOTDEFINED.);
|
||||
#276=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#277=IFCDIRECTION((1.,0.,0.));
|
||||
#278=IFCDIRECTION((0.,0.,1.));
|
||||
#279=IFCAXIS2PLACEMENT3D(#276,#278,#277);
|
||||
#280=IFCREPRESENTATIONMAP(#279,#274);
|
||||
#281=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#282=IFCDIRECTION((1.,0.,0.));
|
||||
#283=IFCDIRECTION((0.,0.,1.));
|
||||
#284=IFCAXIS2PLACEMENT3D(#281,#283,#282);
|
||||
#285=IFCREPRESENTATIONMAP(#284,#273);
|
||||
#286=IFCCARTESIANPOINTLIST2D(((-234.625701904297,345.883117675781),(-303.352996826172,262.917083740234),(-289.376892089844,234.637634277344),(-348.562835693359,186.527572631836),(-368.135772705078,63.169319152832),(-259.490814208984,46.0888442993164),(-370.922973632812,36.1242828369141),(-384.26806640625,-114.088775634766),(-322.428894042969,-140.220657348633),(-330.844177246094,-187.087463378906),(-275.995025634766,-267.836608886719),(-248.622222900391,-270.706359863281),(-172.618560791016,-352.992340087891),(-121.265174865723,-360.957489013672),(-128.875396728516,-321.504791259766),(-87.1701354980469,-381.234405517578),(147.669784545898,-350.933776855469),(123.32682800293,-274.054443359375),(191.128021240234,-323.796356201172),(366.527709960938,-147.53630065918),(331.038970947266,-117.509124755859),(379.146514892578,-98.0416488647461),(386.718719482422,33.8327217102051),(301.160064697266,20.8510036468506),(364.097473144531,76.3949127197266),(331.169189453125,220.886856079102),(265.413391113281,258.454223632812),(230.147384643555,326.805969238281),(159.049774169922,351.167724609375),(74.9347457885742,300.543548583984),(135.337814331055,364.373291015625),(-5.25209617614746,391.923797607422),(-74.5995407104492,376.568267822266),(-127.728973388672,353.416168212891)));
|
||||
#287=IFCINDEXEDPOLYCURVE(#286,(IFCLINEINDEX((1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,1))),$);
|
||||
#288=IFCCARTESIANPOINTLIST3D(((0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(378.284883030077,-2.27555025039633,116.784635922017),(178.595143428464,335.651831866383,124.640558206785),(-183.088878915162,314.752897631551,114.947133794192),(-381.511270028093,-8.00010634603514,128.775855378383),(-172.110176238738,-340.199747584535,125.810867478876),(191.302099550982,-329.414160273537,107.361497258729),(393.598875108319,-1.38140316613422,234.518996106616),(199.179082241675,324.273157299153,237.142238617636),(-178.562776031642,351.03827780132,232.197886828923),(-402.583659748332,-15.8702353869309,216.858549437001),(-179.887927315333,-342.326318683432,224.288087824562),(206.742279825254,-341.958214909756,230.138858459826),(397.952990643972,-13.9201863639408,345.562622079605),(211.010172725181,335.415566902172,334.034709855096),(-202.788153353125,331.591757323652,342.748454812872),(-389.824548338252,5.05251004029154,343.928622398032),(-188.635976295245,-357.620141194691,345.008678116763),(195.973594167939,-343.168416006139,330.470445317765),(396.81640643433,-12.9086133381007,446.466497008241),(203.838392064792,350.344062243514,455.006265224505),(-196.749413384054,327.873276704866,449.933365685756),(-384.247911328827,-10.2892668569367,444.966297281442),(-195.416484522207,-346.739846857814,461.902051741776),(204.273781579568,-327.137492208349,456.507125630036),(371.122280199066,-2.0892624321781,555.588845825671),(194.802342425268,320.238582947285,565.650115036909),(-201.442398962553,323.963341454982,574.07973838219),(-379.501217861028,11.8254574527169,576.975874364524),(-196.274936262054,-324.814228658898,584.565653593263),(188.643510218285,-322.358196023303,557.43732739054),(363.660355728696,-1.2338795905141,682.550441876491),(179.453931460689,317.951168556236,686.951631263826),(-182.32333571869,304.538733074566,683.837383872801),(-349.00229764605,-2.71444181702931,670.844456267496),(-197.909426346164,-314.099856535417,671.332619852593),(168.96778897095,-327.753041773473,684.244792285448),(0.05,0.,800.),(0.025,0.0433012701892219,800.),(-0.025,0.0433012701892219,800.),(-0.05,6.12323399573677E-18,800.),(-0.025,-0.0433012701892219,800.),(0.025,-0.0433012701892219,800.)));
|
||||
#289=IFCINDEXEDPOLYGONALFACE((1,2,3,4,5,6));
|
||||
#290=IFCINDEXEDPOLYGONALFACE((6,1,7,12));
|
||||
#291=IFCINDEXEDPOLYGONALFACE((1,2,8,7));
|
||||
#292=IFCINDEXEDPOLYGONALFACE((2,3,9,8));
|
||||
#293=IFCINDEXEDPOLYGONALFACE((3,4,10,9));
|
||||
#294=IFCINDEXEDPOLYGONALFACE((4,5,11,10));
|
||||
#295=IFCINDEXEDPOLYGONALFACE((5,6,12,11));
|
||||
#296=IFCINDEXEDPOLYGONALFACE((12,7,13,18));
|
||||
#297=IFCINDEXEDPOLYGONALFACE((7,8,14,13));
|
||||
#298=IFCINDEXEDPOLYGONALFACE((8,9,15,14));
|
||||
#299=IFCINDEXEDPOLYGONALFACE((9,10,16,15));
|
||||
#300=IFCINDEXEDPOLYGONALFACE((10,11,17,16));
|
||||
#301=IFCINDEXEDPOLYGONALFACE((11,12,18,17));
|
||||
#302=IFCINDEXEDPOLYGONALFACE((18,13,19,24));
|
||||
#303=IFCINDEXEDPOLYGONALFACE((13,14,20,19));
|
||||
#304=IFCINDEXEDPOLYGONALFACE((14,15,21,20));
|
||||
#305=IFCINDEXEDPOLYGONALFACE((15,16,22,21));
|
||||
#306=IFCINDEXEDPOLYGONALFACE((16,17,23,22));
|
||||
#307=IFCINDEXEDPOLYGONALFACE((17,18,24,23));
|
||||
#308=IFCINDEXEDPOLYGONALFACE((24,19,25,30));
|
||||
#309=IFCINDEXEDPOLYGONALFACE((19,20,26,25));
|
||||
#310=IFCINDEXEDPOLYGONALFACE((20,21,27,26));
|
||||
#311=IFCINDEXEDPOLYGONALFACE((21,22,28,27));
|
||||
#312=IFCINDEXEDPOLYGONALFACE((22,23,29,28));
|
||||
#313=IFCINDEXEDPOLYGONALFACE((23,24,30,29));
|
||||
#314=IFCINDEXEDPOLYGONALFACE((30,25,31,36));
|
||||
#315=IFCINDEXEDPOLYGONALFACE((25,26,32,31));
|
||||
#316=IFCINDEXEDPOLYGONALFACE((26,27,33,32));
|
||||
#317=IFCINDEXEDPOLYGONALFACE((27,28,34,33));
|
||||
#318=IFCINDEXEDPOLYGONALFACE((28,29,35,34));
|
||||
#319=IFCINDEXEDPOLYGONALFACE((29,30,36,35));
|
||||
#320=IFCINDEXEDPOLYGONALFACE((36,31,37,42));
|
||||
#321=IFCINDEXEDPOLYGONALFACE((31,32,38,37));
|
||||
#322=IFCINDEXEDPOLYGONALFACE((32,33,39,38));
|
||||
#323=IFCINDEXEDPOLYGONALFACE((33,34,40,39));
|
||||
#324=IFCINDEXEDPOLYGONALFACE((34,35,41,40));
|
||||
#325=IFCINDEXEDPOLYGONALFACE((35,36,42,41));
|
||||
#326=IFCINDEXEDPOLYGONALFACE((42,37,43,48));
|
||||
#327=IFCINDEXEDPOLYGONALFACE((37,38,44,43));
|
||||
#328=IFCINDEXEDPOLYGONALFACE((38,39,45,44));
|
||||
#329=IFCINDEXEDPOLYGONALFACE((39,40,46,45));
|
||||
#330=IFCINDEXEDPOLYGONALFACE((40,41,47,46));
|
||||
#331=IFCINDEXEDPOLYGONALFACE((41,42,48,47));
|
||||
#332=IFCINDEXEDPOLYGONALFACE((48,43,49,54));
|
||||
#333=IFCINDEXEDPOLYGONALFACE((43,44,50,49));
|
||||
#334=IFCINDEXEDPOLYGONALFACE((44,45,51,50));
|
||||
#335=IFCINDEXEDPOLYGONALFACE((45,46,52,51));
|
||||
#336=IFCINDEXEDPOLYGONALFACE((46,47,53,52));
|
||||
#337=IFCINDEXEDPOLYGONALFACE((47,48,54,53));
|
||||
#338=IFCINDEXEDPOLYGONALFACE((49,50,51,52,53,54));
|
||||
#339=IFCPOLYGONALFACESET(#288,$,(#289,#290,#291,#292,#293,#294,#295,#296,#297,#298,#299,#300,#301,#302,#303,#304,#305,#306,#307,#308,#309,#310,#311,#312,#313,#314,#315,#316,#317,#318,#319,#320,#321,#322,#323,#324,#325,#326,#327,#328,#329,#330,#331,#332,#333,#334,#335,#336,#337,#338),$);
|
||||
#340=IFCSHAPEREPRESENTATION(#16,'Body','Curve2D',(#287));
|
||||
#341=IFCSHAPEREPRESENTATION(#15,'Body','Tessellation',(#339));
|
||||
#342=IFCGEOGRAPHICELEMENTTYPE('1esPZTKFXE3Af39$mWJyUW',$,'Hedge Medium (0.8m)',$,$,$,(#347,#352),$,$,.NOTDEFINED.);
|
||||
#343=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#344=IFCDIRECTION((1.,0.,0.));
|
||||
#345=IFCDIRECTION((0.,0.,1.));
|
||||
#346=IFCAXIS2PLACEMENT3D(#343,#345,#344);
|
||||
#347=IFCREPRESENTATIONMAP(#346,#341);
|
||||
#348=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#349=IFCDIRECTION((1.,0.,0.));
|
||||
#350=IFCDIRECTION((0.,0.,1.));
|
||||
#351=IFCAXIS2PLACEMENT3D(#348,#350,#349);
|
||||
#352=IFCREPRESENTATIONMAP(#351,#340);
|
||||
#353=IFCCARTESIANPOINTLIST2D(((-527.907836914062,778.237060546875),(-682.544250488281,591.5634765625),(-651.098022460938,527.934692382812),(-784.266357421875,419.687042236328),(-828.305480957031,142.130966186523),(-583.854309082031,103.699897766113),(-834.57666015625,81.2796401977539),(-864.603149414062,-256.699737548828),(-725.465026855469,-315.496459960938),(-744.3994140625,-420.946807861328),(-620.988830566406,-602.632385253906),(-559.400024414062,-609.08935546875),(-388.391754150391,-794.232788085938),(-272.846649169922,-812.154357910156),(-289.969635009766,-723.3857421875),(-196.1328125,-857.777404785156),(332.257019042969,-789.601013183594),(277.4853515625,-616.622497558594),(430.038055419922,-728.541809082031),(824.687377929688,-331.956665039062),(744.837707519531,-264.395538330078),(853.079650878906,-220.593704223633),(870.117126464844,76.1236267089844),(677.610168457031,46.9147605895996),(819.219299316406,171.888565063477),(745.130676269531,496.995422363281),(597.18017578125,581.522033691406),(517.831604003906,735.313415527344),(357.861999511719,790.127380371094),(168.603179931641,676.222961425781),(304.510101318359,819.839904785156),(-11.8172159194946,881.828552246094),(-167.848968505859,847.278625488281),(-287.390197753906,795.186340332031)));
|
||||
#354=IFCINDEXEDPOLYCURVE(#353,(IFCLINEINDEX((1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,1))),$);
|
||||
#355=IFCCARTESIANPOINTLIST3D(((0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(851.140986817674,-5.11998806339175,262.765430824539),(401.839072714044,755.216621699362,280.441255965265),(-411.949977559115,708.19401967099,258.631051036932),(-858.400357563209,-18.0002392785791,289.745674601363),(-387.24789653716,-765.449432065204,283.07445182747),(430.429723989709,-741.181860615459,241.563368832141),(885.597468993717,-3.10815712380199,527.667741239885),(448.152935043769,729.614603923094,533.570036889682),(-401.766246071194,789.836125052969,522.445245365077),(-905.813234433747,-35.7080296205946,487.931736233252),(-404.7478364595,-770.234217037722,504.648197605265),(465.170129606822,-769.40598354695,517.812431534608),(895.394228948937,-31.3204193188668,777.515899679111),(474.772888631657,754.685025529888,751.578097173967),(-456.273345044531,746.081453978216,771.184023328963),(-877.105233761067,11.368147590656,773.839400395571),(-424.430946664301,-804.645317688054,776.269525762717),(440.940586877863,-772.128936013813,743.558501964971),(892.836914477244,-29.0443800107266,1004.54961826854),(458.636382145783,788.274140047906,1023.76409675514),(-442.686180114122,737.714872585949,1012.35007279295),(-864.55780048986,-23.1508504281077,1001.17416888324),(-439.687090174966,-780.164655430081,1039.279616419),(459.616008554028,-736.059357468786,1027.14103266758),(835.025130447899,-4.70084047240072,1250.07490310776),(438.305270456854,720.536811631391,1272.71275883304),(-453.245397665745,728.917518273708,1291.67941135993),(-853.877740187312,26.6072792686131,1298.19571732018),(-441.618606589622,-730.832014482521,1315.27272058484),(424.447897991142,-725.305941052431,1254.23398662872),(818.235800389567,-2.77622907865673,1535.7384942221),(403.77134578655,715.390129251532,1545.64117034361),(-410.227505367052,685.212149417774,1538.6341137138),(-785.255169703612,-6.10749408831594,1509.40002660187),(-445.29620927887,-706.724677204688,1510.49839466833),(380.177525184638,-737.444343990313,1539.55078264226),(0.05,0.,1800.),(0.025,0.0433012701892219,1800.),(-0.025,0.0433012701892219,1800.),(-0.05,6.12323399573677E-18,1800.),(-0.025,-0.0433012701892219,1800.),(0.025,-0.0433012701892219,1800.)));
|
||||
#356=IFCINDEXEDPOLYGONALFACE((1,2,3,4,5,6));
|
||||
#357=IFCINDEXEDPOLYGONALFACE((6,1,7,12));
|
||||
#358=IFCINDEXEDPOLYGONALFACE((1,2,8,7));
|
||||
#359=IFCINDEXEDPOLYGONALFACE((2,3,9,8));
|
||||
#360=IFCINDEXEDPOLYGONALFACE((3,4,10,9));
|
||||
#361=IFCINDEXEDPOLYGONALFACE((4,5,11,10));
|
||||
#362=IFCINDEXEDPOLYGONALFACE((5,6,12,11));
|
||||
#363=IFCINDEXEDPOLYGONALFACE((12,7,13,18));
|
||||
#364=IFCINDEXEDPOLYGONALFACE((7,8,14,13));
|
||||
#365=IFCINDEXEDPOLYGONALFACE((8,9,15,14));
|
||||
#366=IFCINDEXEDPOLYGONALFACE((9,10,16,15));
|
||||
#367=IFCINDEXEDPOLYGONALFACE((10,11,17,16));
|
||||
#368=IFCINDEXEDPOLYGONALFACE((11,12,18,17));
|
||||
#369=IFCINDEXEDPOLYGONALFACE((18,13,19,24));
|
||||
#370=IFCINDEXEDPOLYGONALFACE((13,14,20,19));
|
||||
#371=IFCINDEXEDPOLYGONALFACE((14,15,21,20));
|
||||
#372=IFCINDEXEDPOLYGONALFACE((15,16,22,21));
|
||||
#373=IFCINDEXEDPOLYGONALFACE((16,17,23,22));
|
||||
#374=IFCINDEXEDPOLYGONALFACE((17,18,24,23));
|
||||
#375=IFCINDEXEDPOLYGONALFACE((24,19,25,30));
|
||||
#376=IFCINDEXEDPOLYGONALFACE((19,20,26,25));
|
||||
#377=IFCINDEXEDPOLYGONALFACE((20,21,27,26));
|
||||
#378=IFCINDEXEDPOLYGONALFACE((21,22,28,27));
|
||||
#379=IFCINDEXEDPOLYGONALFACE((22,23,29,28));
|
||||
#380=IFCINDEXEDPOLYGONALFACE((23,24,30,29));
|
||||
#381=IFCINDEXEDPOLYGONALFACE((30,25,31,36));
|
||||
#382=IFCINDEXEDPOLYGONALFACE((25,26,32,31));
|
||||
#383=IFCINDEXEDPOLYGONALFACE((26,27,33,32));
|
||||
#384=IFCINDEXEDPOLYGONALFACE((27,28,34,33));
|
||||
#385=IFCINDEXEDPOLYGONALFACE((28,29,35,34));
|
||||
#386=IFCINDEXEDPOLYGONALFACE((29,30,36,35));
|
||||
#387=IFCINDEXEDPOLYGONALFACE((36,31,37,42));
|
||||
#388=IFCINDEXEDPOLYGONALFACE((31,32,38,37));
|
||||
#389=IFCINDEXEDPOLYGONALFACE((32,33,39,38));
|
||||
#390=IFCINDEXEDPOLYGONALFACE((33,34,40,39));
|
||||
#391=IFCINDEXEDPOLYGONALFACE((34,35,41,40));
|
||||
#392=IFCINDEXEDPOLYGONALFACE((35,36,42,41));
|
||||
#393=IFCINDEXEDPOLYGONALFACE((42,37,43,48));
|
||||
#394=IFCINDEXEDPOLYGONALFACE((37,38,44,43));
|
||||
#395=IFCINDEXEDPOLYGONALFACE((38,39,45,44));
|
||||
#396=IFCINDEXEDPOLYGONALFACE((39,40,46,45));
|
||||
#397=IFCINDEXEDPOLYGONALFACE((40,41,47,46));
|
||||
#398=IFCINDEXEDPOLYGONALFACE((41,42,48,47));
|
||||
#399=IFCINDEXEDPOLYGONALFACE((48,43,49,54));
|
||||
#400=IFCINDEXEDPOLYGONALFACE((43,44,50,49));
|
||||
#401=IFCINDEXEDPOLYGONALFACE((44,45,51,50));
|
||||
#402=IFCINDEXEDPOLYGONALFACE((45,46,52,51));
|
||||
#403=IFCINDEXEDPOLYGONALFACE((46,47,53,52));
|
||||
#404=IFCINDEXEDPOLYGONALFACE((47,48,54,53));
|
||||
#405=IFCINDEXEDPOLYGONALFACE((49,50,51,52,53,54));
|
||||
#406=IFCPOLYGONALFACESET(#355,$,(#356,#357,#358,#359,#360,#361,#362,#363,#364,#365,#366,#367,#368,#369,#370,#371,#372,#373,#374,#375,#376,#377,#378,#379,#380,#381,#382,#383,#384,#385,#386,#387,#388,#389,#390,#391,#392,#393,#394,#395,#396,#397,#398,#399,#400,#401,#402,#403,#404,#405),$);
|
||||
#407=IFCSHAPEREPRESENTATION(#16,'Body','Curve2D',(#354));
|
||||
#408=IFCSHAPEREPRESENTATION(#15,'Body','Tessellation',(#406));
|
||||
#409=IFCGEOGRAPHICELEMENTTYPE('2ITyucrb9DnxtmPeA_FCBG',$,'Hedge Big (1.8m)',$,$,$,(#414,#419),$,$,.NOTDEFINED.);
|
||||
#410=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#411=IFCDIRECTION((1.,0.,0.));
|
||||
#412=IFCDIRECTION((0.,0.,1.));
|
||||
#413=IFCAXIS2PLACEMENT3D(#410,#412,#411);
|
||||
#414=IFCREPRESENTATIONMAP(#413,#408);
|
||||
#415=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#416=IFCDIRECTION((1.,0.,0.));
|
||||
#417=IFCDIRECTION((0.,0.,1.));
|
||||
#418=IFCAXIS2PLACEMENT3D(#415,#417,#416);
|
||||
#419=IFCREPRESENTATIONMAP(#418,#407);
|
||||
#420=IFCCARTESIANPOINTLIST3D(((-2517.70166015625,-2646.30053710938,3901.58129882812),(-255.675521850586,-1248.60815429688,5000.),(-1133.70935058594,-349.566070556641,4688.61865234375),(0.,0.,4658.5205078125),(3472.91040039062,-1142.93579101562,3901.58129882812),(1250.74682617188,317.302124023438,5000.),(806.568603515625,-858.251220703125,4688.61865234375),(1171.36364746094,3483.57202148438,3901.58129882812),(-298.783111572266,1267.951171875,5000.),(874.774963378906,818.52783203125,4688.61865234375),(-3164.8310546875,1859.35131835938,3901.58129882812),(-1289.18603515625,-25.3927478790283,5000.),(-613.466796875,1034.14660644531,4688.61865234375)));
|
||||
#421=IFCINDEXEDPOLYGONALFACE((3,2,1));
|
||||
#422=IFCINDEXEDPOLYGONALFACE((3,4,2));
|
||||
#423=IFCINDEXEDPOLYGONALFACE((7,6,5));
|
||||
#424=IFCINDEXEDPOLYGONALFACE((7,4,6));
|
||||
#425=IFCINDEXEDPOLYGONALFACE((10,9,8));
|
||||
#426=IFCINDEXEDPOLYGONALFACE((10,4,9));
|
||||
#427=IFCINDEXEDPOLYGONALFACE((13,12,11));
|
||||
#428=IFCINDEXEDPOLYGONALFACE((13,4,12));
|
||||
#429=IFCPOLYGONALFACESET(#420,$,(#421,#422,#423,#424,#425,#426,#427,#428),$);
|
||||
#430=IFCCARTESIANPOINT((0.,0.));
|
||||
#431=IFCAXIS2PLACEMENT2D(#430,$);
|
||||
#432=IFCCIRCLE(#431,100.);
|
||||
#433=IFCARBITRARYCLOSEDPROFILEDEF(.AREA.,$,#432);
|
||||
#434=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#435=IFCDIRECTION((0.,0.,1.));
|
||||
#436=IFCDIRECTION((1.,0.,0.));
|
||||
#437=IFCAXIS2PLACEMENT3D(#434,#435,#436);
|
||||
#438=IFCDIRECTION((0.,0.,1.));
|
||||
#439=IFCEXTRUDEDAREASOLID(#433,#437,#438,4658.5204646405);
|
||||
#440=IFCCARTESIANPOINTLIST2D(((-2517.70166015625,-2646.30053710938,0.),(-255.675521850586,-1248.60815429688,0.),(-1133.70935058594,-349.566070556641,0.),(0.,0.,0.),(3472.91040039062,-1142.93579101562,0.),(1250.74682617188,317.302124023438,0.),(806.568603515625,-858.251220703125,0.),(1171.36364746094,3483.57202148438,0.),(-298.783111572266,1267.951171875,0.),(874.774963378906,818.52783203125,0.),(-3164.8310546875,1859.35131835938,0.),(-1289.18603515625,-25.3927478790283,0.),(-613.466796875,1034.14660644531,0.)));
|
||||
#441=IFCINDEXEDPOLYCURVE(#440,(IFCLINEINDEX((4,12,11,13,4)),IFCLINEINDEX((4,2,1,3,4)),IFCLINEINDEX((4,6,5,7,4)),IFCLINEINDEX((4,9,8,10,4))),$);
|
||||
#442=IFCSHAPEREPRESENTATION(#16,'Body','Curve2D',(#441));
|
||||
#443=IFCSHAPEREPRESENTATION(#15,'Body','SweptSolid',(#429,#439));
|
||||
#444=IFCGEOGRAPHICELEMENTTYPE('0If5oJIRTAxw5EHjhL6zX$',$,'Palm Tree (5m)',$,$,$,(#449,#454),$,$,.NOTDEFINED.);
|
||||
#445=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#446=IFCDIRECTION((1.,0.,0.));
|
||||
#447=IFCDIRECTION((0.,0.,1.));
|
||||
#448=IFCAXIS2PLACEMENT3D(#445,#447,#446);
|
||||
#449=IFCREPRESENTATIONMAP(#448,#443);
|
||||
#450=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#451=IFCDIRECTION((1.,0.,0.));
|
||||
#452=IFCDIRECTION((0.,0.,1.));
|
||||
#453=IFCAXIS2PLACEMENT3D(#450,#452,#451);
|
||||
#454=IFCREPRESENTATIONMAP(#453,#442);
|
||||
#455=IFCCARTESIANPOINTLIST3D(((-5223.76025390625,-5490.57861328125,12720.986328125),(-530.478881835938,-2590.62841796875,15000.),(-2352.23486328125,-725.284240722656,14353.9423828125),(0.,0.,14291.4931640625),(7205.64013671875,-2371.37817382812,12720.986328125),(2595.06591796875,658.342590332031,15000.),(1673.47912597656,-1780.7109375,14353.9423828125),(2430.36059570312,7227.76025390625,12720.986328125),(-619.919128417969,2630.76171875,15000.),(1814.99462890625,1698.29223632812,14353.9423828125),(-6566.43310546875,3857.80639648438,12720.986328125),(-2674.81982421875,-52.6852073669434,15000.),(-1272.82897949219,2145.66088867188,14353.9423828125)));
|
||||
#456=IFCINDEXEDPOLYGONALFACE((3,2,1));
|
||||
#457=IFCINDEXEDPOLYGONALFACE((3,4,2));
|
||||
#458=IFCINDEXEDPOLYGONALFACE((7,6,5));
|
||||
#459=IFCINDEXEDPOLYGONALFACE((7,4,6));
|
||||
#460=IFCINDEXEDPOLYGONALFACE((10,9,8));
|
||||
#461=IFCINDEXEDPOLYGONALFACE((10,4,9));
|
||||
#462=IFCINDEXEDPOLYGONALFACE((13,12,11));
|
||||
#463=IFCINDEXEDPOLYGONALFACE((13,4,12));
|
||||
#464=IFCPOLYGONALFACESET(#455,$,(#456,#457,#458,#459,#460,#461,#462,#463),$);
|
||||
#465=IFCCARTESIANPOINT((0.,0.));
|
||||
#466=IFCAXIS2PLACEMENT2D(#465,$);
|
||||
#467=IFCCIRCLE(#466,200.);
|
||||
#468=IFCARBITRARYCLOSEDPROFILEDEF(.AREA.,$,#467);
|
||||
#469=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#470=IFCDIRECTION((0.,0.,1.));
|
||||
#471=IFCDIRECTION((1.,0.,0.));
|
||||
#472=IFCAXIS2PLACEMENT3D(#469,#470,#471);
|
||||
#473=IFCDIRECTION((0.,0.,1.));
|
||||
#474=IFCEXTRUDEDAREASOLID(#468,#472,#473,14291.4938033876);
|
||||
#475=IFCCARTESIANPOINTLIST2D(((-5223.76025390625,-5490.57861328125,0.),(-530.478881835938,-2590.62841796875,0.),(-2352.23486328125,-725.284240722656,0.),(0.,0.,0.),(7205.64013671875,-2371.37817382812,0.),(2595.06591796875,658.342590332031,0.),(1673.47912597656,-1780.7109375,0.),(2430.36059570312,7227.76025390625,0.),(-619.919128417969,2630.76171875,0.),(1814.99462890625,1698.29223632812,0.),(-6566.43310546875,3857.80639648438,0.),(-2674.81982421875,-52.6852073669434,0.),(-1272.82897949219,2145.66088867188,0.)));
|
||||
#476=IFCINDEXEDPOLYCURVE(#475,(IFCLINEINDEX((4,12,11,13,4)),IFCLINEINDEX((4,2,1,3,4)),IFCLINEINDEX((4,6,5,7,4)),IFCLINEINDEX((4,9,8,10,4))),$);
|
||||
#477=IFCSHAPEREPRESENTATION(#16,'Body','Curve2D',(#476));
|
||||
#478=IFCSHAPEREPRESENTATION(#15,'Body','SweptSolid',(#464,#474));
|
||||
#479=IFCGEOGRAPHICELEMENTTYPE('11RlAtH99EAwxYuNeuU3sf',$,'Palm Tree (15m)',$,$,$,(#484,#489),$,$,.NOTDEFINED.);
|
||||
#480=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#481=IFCDIRECTION((1.,0.,0.));
|
||||
#482=IFCDIRECTION((0.,0.,1.));
|
||||
#483=IFCAXIS2PLACEMENT3D(#480,#482,#481);
|
||||
#484=IFCREPRESENTATIONMAP(#483,#478);
|
||||
#485=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#486=IFCDIRECTION((1.,0.,0.));
|
||||
#487=IFCDIRECTION((0.,0.,1.));
|
||||
#488=IFCAXIS2PLACEMENT3D(#485,#487,#486);
|
||||
#489=IFCREPRESENTATIONMAP(#488,#477);
|
||||
#490=IFCCARTESIANPOINTLIST2D(((-117.312850952148,172.941558837891),(-151.676498413086,131.458541870117),(-144.688446044922,117.318817138672),(-174.28141784668,93.263786315918),(-184.067886352539,31.584659576416),(-129.745407104492,23.0444221496582),(-185.461486816406,18.062141418457),(-192.134033203125,-57.0443878173828),(-161.214447021484,-70.1103286743164),(-165.422088623047,-93.5437316894531),(-137.997512817383,-133.918304443359),(-124.311111450195,-135.353179931641),(-86.3092803955078,-176.496170043945),(-60.6325874328613,-180.478744506836),(-64.4376983642578,-160.752395629883),(-43.5850677490234,-190.617202758789),(73.8348922729492,-175.466888427734),(61.6634140014648,-137.027221679688),(95.5640106201172,-161.898178100586),(183.263854980469,-73.7681503295898),(165.519485473633,-58.7545623779297),(189.573257446289,-49.020824432373),(193.359359741211,16.9163608551025),(150.580032348633,10.4255018234253),(182.048736572266,38.1974563598633),(165.584594726562,110.443428039551),(132.706695556641,129.227111816406),(115.073692321777,163.402984619141),(79.5248870849609,175.583862304688),(37.4673728942871,150.271774291992),(67.6689071655273,182.186645507812),(-2.62604808807373,195.961898803711),(-37.2997703552246,188.284133911133),(-63.8644866943359,176.708084106445)));
|
||||
#491=IFCINDEXEDPOLYCURVE(#490,(IFCLINEINDEX((1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,1))),$);
|
||||
#492=IFCCARTESIANPOINTLIST3D(((0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(117.302441515039,-1.13777512519817,58.3923179610087),(53.377571714232,105.610650925318,62.3202791033923),(-55.6244394575812,95.1611838079015,57.4735668970959),(-118.915635014047,-4.00005317301758,64.3879276891917),(-50.1350881193688,-107.884608784393,62.9054337394378),(59.731049775491,-102.491815128895,53.6807486293646),(146.906104220826,-0.69070158306711,117.259498053308),(74.642874454171,118.927684503425,118.571119308818),(-64.3347213491543,132.310244754508,116.098943414462),(-151.398496540833,-7.93511769346546,108.4292747185),(-64.9972969910001,-127.954265195564,112.144043912281),(78.4244732459604,-127.770213308726,115.069429229913),(171.029828655319,-6.96009318197039,172.781311039802),(91.5317530292571,143.505260166657,167.017354927548),(-87.4207433432292,141.593355377397,171.374227406436),(-166.965607502459,2.52625502014577,171.964311199016),(-80.3446548142891,-154.607547312916,172.504339058381),(84.0134637506361,-147.38168471864,165.235222658882),(204.408203217165,-6.45430666905036,223.233248504121),(104.919196032396,180.368183544464,227.503132612252),(-101.374706692027,169.13279077514,224.966682842878),(-198.123955664413,-5.14463342846837,222.483148640721),(-100.708242261103,-178.566075851614,230.951025870888),(105.136890789784,-168.764898526881,228.253562815018),(169.614473432866,-1.04463121608905,277.794422912835),(89.4278378793009,146.309073034627,282.825057518454),(-92.7478661479432,148.171452288475,287.039869191095),(-173.803942263847,5.91272872635847,288.487937182262),(-90.1641347976938,-148.596895890433,292.282826796631),(86.3484217758093,-147.368879572635,278.71866369527),(143.936844531015,-0.61693979525705,341.275220938245),(70.7802990636777,126.15899497738,343.475815631913),(-72.2150011926783,119.452777236545,341.9186919364),(-136.607815489692,-1.35722090851466,335.422228133748),(-80.0080465064155,-124.23333896697,335.666309926296),(65.5372278188084,-131.059931585998,342.122396142724),(0.05,0.,400.),(0.025,0.0433012701892219,400.),(-0.025,0.0433012701892219,400.),(-0.05,6.12323399573677E-18,400.),(-0.025,-0.0433012701892219,400.),(0.025,-0.0433012701892219,400.)));
|
||||
#493=IFCINDEXEDPOLYGONALFACE((1,2,3,4,5,6));
|
||||
#494=IFCINDEXEDPOLYGONALFACE((6,1,7,12));
|
||||
#495=IFCINDEXEDPOLYGONALFACE((1,2,8,7));
|
||||
#496=IFCINDEXEDPOLYGONALFACE((2,3,9,8));
|
||||
#497=IFCINDEXEDPOLYGONALFACE((3,4,10,9));
|
||||
#498=IFCINDEXEDPOLYGONALFACE((4,5,11,10));
|
||||
#499=IFCINDEXEDPOLYGONALFACE((5,6,12,11));
|
||||
#500=IFCINDEXEDPOLYGONALFACE((12,7,13,18));
|
||||
#501=IFCINDEXEDPOLYGONALFACE((7,8,14,13));
|
||||
#502=IFCINDEXEDPOLYGONALFACE((8,9,15,14));
|
||||
#503=IFCINDEXEDPOLYGONALFACE((9,10,16,15));
|
||||
#504=IFCINDEXEDPOLYGONALFACE((10,11,17,16));
|
||||
#505=IFCINDEXEDPOLYGONALFACE((11,12,18,17));
|
||||
#506=IFCINDEXEDPOLYGONALFACE((18,13,19,24));
|
||||
#507=IFCINDEXEDPOLYGONALFACE((13,14,20,19));
|
||||
#508=IFCINDEXEDPOLYGONALFACE((14,15,21,20));
|
||||
#509=IFCINDEXEDPOLYGONALFACE((15,16,22,21));
|
||||
#510=IFCINDEXEDPOLYGONALFACE((16,17,23,22));
|
||||
#511=IFCINDEXEDPOLYGONALFACE((17,18,24,23));
|
||||
#512=IFCINDEXEDPOLYGONALFACE((24,19,25,30));
|
||||
#513=IFCINDEXEDPOLYGONALFACE((19,20,26,25));
|
||||
#514=IFCINDEXEDPOLYGONALFACE((20,21,27,26));
|
||||
#515=IFCINDEXEDPOLYGONALFACE((21,22,28,27));
|
||||
#516=IFCINDEXEDPOLYGONALFACE((22,23,29,28));
|
||||
#517=IFCINDEXEDPOLYGONALFACE((23,24,30,29));
|
||||
#518=IFCINDEXEDPOLYGONALFACE((30,25,31,36));
|
||||
#519=IFCINDEXEDPOLYGONALFACE((25,26,32,31));
|
||||
#520=IFCINDEXEDPOLYGONALFACE((26,27,33,32));
|
||||
#521=IFCINDEXEDPOLYGONALFACE((27,28,34,33));
|
||||
#522=IFCINDEXEDPOLYGONALFACE((28,29,35,34));
|
||||
#523=IFCINDEXEDPOLYGONALFACE((29,30,36,35));
|
||||
#524=IFCINDEXEDPOLYGONALFACE((36,31,37,42));
|
||||
#525=IFCINDEXEDPOLYGONALFACE((31,32,38,37));
|
||||
#526=IFCINDEXEDPOLYGONALFACE((32,33,39,38));
|
||||
#527=IFCINDEXEDPOLYGONALFACE((33,34,40,39));
|
||||
#528=IFCINDEXEDPOLYGONALFACE((34,35,41,40));
|
||||
#529=IFCINDEXEDPOLYGONALFACE((35,36,42,41));
|
||||
#530=IFCINDEXEDPOLYGONALFACE((42,37,43,48));
|
||||
#531=IFCINDEXEDPOLYGONALFACE((37,38,44,43));
|
||||
#532=IFCINDEXEDPOLYGONALFACE((38,39,45,44));
|
||||
#533=IFCINDEXEDPOLYGONALFACE((39,40,46,45));
|
||||
#534=IFCINDEXEDPOLYGONALFACE((40,41,47,46));
|
||||
#535=IFCINDEXEDPOLYGONALFACE((41,42,48,47));
|
||||
#536=IFCINDEXEDPOLYGONALFACE((48,43,49,54));
|
||||
#537=IFCINDEXEDPOLYGONALFACE((43,44,50,49));
|
||||
#538=IFCINDEXEDPOLYGONALFACE((44,45,51,50));
|
||||
#539=IFCINDEXEDPOLYGONALFACE((45,46,52,51));
|
||||
#540=IFCINDEXEDPOLYGONALFACE((46,47,53,52));
|
||||
#541=IFCINDEXEDPOLYGONALFACE((47,48,54,53));
|
||||
#542=IFCINDEXEDPOLYGONALFACE((49,50,51,52,53,54));
|
||||
#543=IFCPOLYGONALFACESET(#492,$,(#493,#494,#495,#496,#497,#498,#499,#500,#501,#502,#503,#504,#505,#506,#507,#508,#509,#510,#511,#512,#513,#514,#515,#516,#517,#518,#519,#520,#521,#522,#523,#524,#525,#526,#527,#528,#529,#530,#531,#532,#533,#534,#535,#536,#537,#538,#539,#540,#541,#542),$);
|
||||
#544=IFCSHAPEREPRESENTATION(#16,'Body','Curve2D',(#491));
|
||||
#545=IFCSHAPEREPRESENTATION(#15,'Body','Tessellation',(#543));
|
||||
#546=IFCGEOGRAPHICELEMENTTYPE('224k6o88949Ak$WjDPqiY0',$,'Shrub Small (0.4m)',$,$,$,(#551,#556),$,$,.NOTDEFINED.);
|
||||
#547=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#548=IFCDIRECTION((1.,0.,0.));
|
||||
#549=IFCDIRECTION((0.,0.,1.));
|
||||
#550=IFCAXIS2PLACEMENT3D(#547,#549,#548);
|
||||
#551=IFCREPRESENTATIONMAP(#550,#545);
|
||||
#552=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#553=IFCDIRECTION((1.,0.,0.));
|
||||
#554=IFCDIRECTION((0.,0.,1.));
|
||||
#555=IFCAXIS2PLACEMENT3D(#552,#554,#553);
|
||||
#556=IFCREPRESENTATIONMAP(#555,#544);
|
||||
#557=IFCCARTESIANPOINTLIST2D(((-234.625701904297,345.883117675781),(-303.352996826172,262.917083740234),(-289.376892089844,234.637634277344),(-348.562835693359,186.527572631836),(-368.135772705078,63.169319152832),(-259.490814208984,46.0888442993164),(-370.922973632812,36.1242828369141),(-384.26806640625,-114.088775634766),(-322.428894042969,-140.220657348633),(-330.844177246094,-187.087463378906),(-275.995025634766,-267.836608886719),(-248.622222900391,-270.706359863281),(-172.618560791016,-352.992340087891),(-121.265174865723,-360.957489013672),(-128.875396728516,-321.504791259766),(-87.1701354980469,-381.234405517578),(147.669784545898,-350.933776855469),(123.32682800293,-274.054443359375),(191.128021240234,-323.796356201172),(366.527709960938,-147.53630065918),(331.038970947266,-117.509124755859),(379.146514892578,-98.0416488647461),(386.718719482422,33.8327217102051),(301.160064697266,20.8510036468506),(364.097473144531,76.3949127197266),(331.169189453125,220.886856079102),(265.413391113281,258.454223632812),(230.147384643555,326.805969238281),(159.049774169922,351.167724609375),(74.9347457885742,300.543548583984),(135.337814331055,364.373291015625),(-5.25209617614746,391.923797607422),(-74.5995407104492,376.568267822266),(-127.728973388672,353.416168212891)));
|
||||
#558=IFCINDEXEDPOLYCURVE(#557,(IFCLINEINDEX((1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,1))),$);
|
||||
#559=IFCCARTESIANPOINTLIST3D(((0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(234.604883030077,-2.27555025039633,116.784635922017),(106.755143428464,211.221301850635,124.640558206785),(-111.248878915162,190.322367615803,114.947133794192),(-237.831270028093,-8.00010634603516,128.775855378383),(-100.270176238738,-215.769217568787,125.810867478876),(119.462099550982,-204.983630257789,107.361497258729),(293.812208441652,-1.38140316613422,234.518996106616),(149.285748908342,237.85536900685,237.142238617636),(-128.669442698309,264.620489509016,232.197886828923),(-302.796993081665,-15.8702353869309,216.858549437001),(-129.994593982,-255.908530391129,224.288087824562),(156.848946491921,-255.540426617453,230.138858459826),(342.059657310639,-13.9201863639408,345.562622079605),(183.063506058514,287.010520333314,334.034709855096),(-174.841486686458,283.186710754793,342.748454812872),(-333.931215004918,5.05251004029153,343.928622398032),(-160.689309628578,-309.215094625832,345.008678116763),(168.026927501272,-294.763369437281,330.470445317765),(408.81640643433,-12.9086133381007,446.466497008241),(209.838392064792,360.736367088927,455.006265224505),(-202.749413384054,338.26558155028,449.933365685756),(-396.247911328827,-10.2892668569367,444.966297281442),(-201.416484522207,-357.132151703227,461.902051741776),(210.273781579568,-337.529797053763,456.507125630036),(339.228946865733,-2.0892624321781,555.588845825671),(178.855675758602,292.618146069253,565.650115036909),(-185.495732295886,296.34290457695,574.07973838219),(-347.607884527694,11.8254574527169,576.975874364524),(-180.328269595388,-297.193791780866,584.565653593263),(172.696843551619,-294.737759145271,557.43732739054),(287.87368906203,-1.2338795905141,682.550441876491),(141.560598127355,252.31798995476,686.951631263826),(-144.430002385357,238.90555447309,683.837383872801),(-273.215630979383,-2.71444181702932,670.844456267496),(-160.016093012831,-248.46667793394,671.332619852593),(131.074455637617,-262.119863171996,684.244792285448),(0.05,0.,800.),(0.025,0.0433012701892219,800.),(-0.025,0.0433012701892219,800.),(-0.05,6.12323399573677E-18,800.),(-0.025,-0.0433012701892219,800.),(0.025,-0.0433012701892219,800.)));
|
||||
#560=IFCINDEXEDPOLYGONALFACE((1,2,3,4,5,6));
|
||||
#561=IFCINDEXEDPOLYGONALFACE((6,1,7,12));
|
||||
#562=IFCINDEXEDPOLYGONALFACE((1,2,8,7));
|
||||
#563=IFCINDEXEDPOLYGONALFACE((2,3,9,8));
|
||||
#564=IFCINDEXEDPOLYGONALFACE((3,4,10,9));
|
||||
#565=IFCINDEXEDPOLYGONALFACE((4,5,11,10));
|
||||
#566=IFCINDEXEDPOLYGONALFACE((5,6,12,11));
|
||||
#567=IFCINDEXEDPOLYGONALFACE((12,7,13,18));
|
||||
#568=IFCINDEXEDPOLYGONALFACE((7,8,14,13));
|
||||
#569=IFCINDEXEDPOLYGONALFACE((8,9,15,14));
|
||||
#570=IFCINDEXEDPOLYGONALFACE((9,10,16,15));
|
||||
#571=IFCINDEXEDPOLYGONALFACE((10,11,17,16));
|
||||
#572=IFCINDEXEDPOLYGONALFACE((11,12,18,17));
|
||||
#573=IFCINDEXEDPOLYGONALFACE((18,13,19,24));
|
||||
#574=IFCINDEXEDPOLYGONALFACE((13,14,20,19));
|
||||
#575=IFCINDEXEDPOLYGONALFACE((14,15,21,20));
|
||||
#576=IFCINDEXEDPOLYGONALFACE((15,16,22,21));
|
||||
#577=IFCINDEXEDPOLYGONALFACE((16,17,23,22));
|
||||
#578=IFCINDEXEDPOLYGONALFACE((17,18,24,23));
|
||||
#579=IFCINDEXEDPOLYGONALFACE((24,19,25,30));
|
||||
#580=IFCINDEXEDPOLYGONALFACE((19,20,26,25));
|
||||
#581=IFCINDEXEDPOLYGONALFACE((20,21,27,26));
|
||||
#582=IFCINDEXEDPOLYGONALFACE((21,22,28,27));
|
||||
#583=IFCINDEXEDPOLYGONALFACE((22,23,29,28));
|
||||
#584=IFCINDEXEDPOLYGONALFACE((23,24,30,29));
|
||||
#585=IFCINDEXEDPOLYGONALFACE((30,25,31,36));
|
||||
#586=IFCINDEXEDPOLYGONALFACE((25,26,32,31));
|
||||
#587=IFCINDEXEDPOLYGONALFACE((26,27,33,32));
|
||||
#588=IFCINDEXEDPOLYGONALFACE((27,28,34,33));
|
||||
#589=IFCINDEXEDPOLYGONALFACE((28,29,35,34));
|
||||
#590=IFCINDEXEDPOLYGONALFACE((29,30,36,35));
|
||||
#591=IFCINDEXEDPOLYGONALFACE((36,31,37,42));
|
||||
#592=IFCINDEXEDPOLYGONALFACE((31,32,38,37));
|
||||
#593=IFCINDEXEDPOLYGONALFACE((32,33,39,38));
|
||||
#594=IFCINDEXEDPOLYGONALFACE((33,34,40,39));
|
||||
#595=IFCINDEXEDPOLYGONALFACE((34,35,41,40));
|
||||
#596=IFCINDEXEDPOLYGONALFACE((35,36,42,41));
|
||||
#597=IFCINDEXEDPOLYGONALFACE((42,37,43,48));
|
||||
#598=IFCINDEXEDPOLYGONALFACE((37,38,44,43));
|
||||
#599=IFCINDEXEDPOLYGONALFACE((38,39,45,44));
|
||||
#600=IFCINDEXEDPOLYGONALFACE((39,40,46,45));
|
||||
#601=IFCINDEXEDPOLYGONALFACE((40,41,47,46));
|
||||
#602=IFCINDEXEDPOLYGONALFACE((41,42,48,47));
|
||||
#603=IFCINDEXEDPOLYGONALFACE((48,43,49,54));
|
||||
#604=IFCINDEXEDPOLYGONALFACE((43,44,50,49));
|
||||
#605=IFCINDEXEDPOLYGONALFACE((44,45,51,50));
|
||||
#606=IFCINDEXEDPOLYGONALFACE((45,46,52,51));
|
||||
#607=IFCINDEXEDPOLYGONALFACE((46,47,53,52));
|
||||
#608=IFCINDEXEDPOLYGONALFACE((47,48,54,53));
|
||||
#609=IFCINDEXEDPOLYGONALFACE((49,50,51,52,53,54));
|
||||
#610=IFCPOLYGONALFACESET(#559,$,(#560,#561,#562,#563,#564,#565,#566,#567,#568,#569,#570,#571,#572,#573,#574,#575,#576,#577,#578,#579,#580,#581,#582,#583,#584,#585,#586,#587,#588,#589,#590,#591,#592,#593,#594,#595,#596,#597,#598,#599,#600,#601,#602,#603,#604,#605,#606,#607,#608,#609),$);
|
||||
#611=IFCSHAPEREPRESENTATION(#16,'Body','Curve2D',(#558));
|
||||
#612=IFCSHAPEREPRESENTATION(#15,'Body','Tessellation',(#610));
|
||||
#613=IFCGEOGRAPHICELEMENTTYPE('0sCZ5iWS904ODo2Mqo8nHu',$,'Shrum Medium (0.8m)',$,$,$,(#618,#623),$,$,.NOTDEFINED.);
|
||||
#614=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#615=IFCDIRECTION((1.,0.,0.));
|
||||
#616=IFCDIRECTION((0.,0.,1.));
|
||||
#617=IFCAXIS2PLACEMENT3D(#614,#616,#615);
|
||||
#618=IFCREPRESENTATIONMAP(#617,#612);
|
||||
#619=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#620=IFCDIRECTION((1.,0.,0.));
|
||||
#621=IFCDIRECTION((0.,0.,1.));
|
||||
#622=IFCAXIS2PLACEMENT3D(#619,#621,#620);
|
||||
#623=IFCREPRESENTATIONMAP(#622,#611);
|
||||
#624=IFCCARTESIANPOINTLIST2D(((-527.907836914062,778.237060546875),(-682.544250488281,591.5634765625),(-651.098022460938,527.934692382812),(-784.266357421875,419.687042236328),(-828.305480957031,142.130966186523),(-583.854309082031,103.699897766113),(-834.57666015625,81.2796401977539),(-864.603149414062,-256.699737548828),(-725.465026855469,-315.496459960938),(-744.3994140625,-420.946807861328),(-620.988830566406,-602.632385253906),(-559.400024414062,-609.08935546875),(-388.391754150391,-794.232788085938),(-272.846649169922,-812.154357910156),(-289.969635009766,-723.3857421875),(-196.1328125,-857.777404785156),(332.257019042969,-789.601013183594),(277.4853515625,-616.622497558594),(430.038055419922,-728.541809082031),(824.687377929688,-331.956665039062),(744.837707519531,-264.395538330078),(853.079650878906,-220.593704223633),(870.117126464844,76.1236267089844),(677.610168457031,46.9147605895996),(819.219299316406,171.888565063477),(745.130676269531,496.995422363281),(597.18017578125,581.522033691406),(517.831604003906,735.313415527344),(357.861999511719,790.127380371094),(168.603179931641,676.222961425781),(304.510101318359,819.839904785156),(-11.8172159194946,881.828552246094),(-167.848968505859,847.278625488281),(-287.390197753906,795.186340332031)));
|
||||
#625=IFCINDEXEDPOLYCURVE(#624,(IFCLINEINDEX((1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,1))),$);
|
||||
#626=IFCCARTESIANPOINTLIST3D(((0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(0.,0.,0.),(527.860986817674,-5.11998806339175,262.765430824539),(240.199072714044,475.247929163929,280.441255965265),(-250.309977559115,428.225327135557,258.631051036932),(-535.120357563209,-18.0002392785791,289.745674601363),(-225.607896537159,-485.480739529771,283.07445182747),(268.789723989709,-461.213168080025,241.563368832141),(661.077468993717,-3.10815712380199,527.667741239885),(335.892935043769,535.174580265412,533.570036889682),(-289.506246071194,595.396101395287,522.445245365077),(-681.293234433747,-35.7080296205946,487.931736233252),(-292.4878364595,-575.794193380039,504.648197605265),(352.910129606822,-574.965959889268,517.812431534608),(769.634228948937,-31.3204193188668,777.515899679111),(411.892888631657,645.773670749957,751.578097173967),(-393.393345044531,637.170099198285,771.184023328963),(-751.345233761067,11.3681475906559,773.839400395571),(-361.550946664301,-695.733962908123,776.269525762717),(378.060586877863,-663.217581233882,743.558501964971),(919.836914477244,-29.0443800107266,1004.54961826854),(472.136382145783,811.656825950086,1023.76409675514),(-456.186180114122,761.097558488129,1012.35007279295),(-891.55780048986,-23.1508504281077,1001.17416888324),(-453.187090174966,-803.547341332261,1039.279616419),(473.116008554028,-759.442043370966,1027.14103266758),(763.265130447899,-4.70084047240072,1250.07490310776),(402.425270456854,658.39082865582,1272.71275883304),(-417.365397665745,666.771535298137,1291.67941135993),(-782.117740187312,26.6072792686131,1298.19571732018),(-405.738606589622,-668.686031506949,1315.27272058484),(388.567897991142,-663.159958076859,1254.23398662872),(647.715800389567,-2.77622907865673,1535.7384942221),(318.51134578655,567.715477398209,1545.64117034361),(-324.967505367052,537.537497564452,1538.6341137138),(-614.735169703612,-6.10749408831597,1509.40002660187),(-360.03620927887,-559.050025351365,1510.49839466833),(294.917525184638,-589.769692136991,1539.55078264226),(0.05,0.,1800.),(0.025,0.0433012701892219,1800.),(-0.025,0.0433012701892219,1800.),(-0.05,6.12323399573677E-18,1800.),(-0.025,-0.0433012701892219,1800.),(0.025,-0.0433012701892219,1800.)));
|
||||
#627=IFCINDEXEDPOLYGONALFACE((1,2,3,4,5,6));
|
||||
#628=IFCINDEXEDPOLYGONALFACE((6,1,7,12));
|
||||
#629=IFCINDEXEDPOLYGONALFACE((1,2,8,7));
|
||||
#630=IFCINDEXEDPOLYGONALFACE((2,3,9,8));
|
||||
#631=IFCINDEXEDPOLYGONALFACE((3,4,10,9));
|
||||
#632=IFCINDEXEDPOLYGONALFACE((4,5,11,10));
|
||||
#633=IFCINDEXEDPOLYGONALFACE((5,6,12,11));
|
||||
#634=IFCINDEXEDPOLYGONALFACE((12,7,13,18));
|
||||
#635=IFCINDEXEDPOLYGONALFACE((7,8,14,13));
|
||||
#636=IFCINDEXEDPOLYGONALFACE((8,9,15,14));
|
||||
#637=IFCINDEXEDPOLYGONALFACE((9,10,16,15));
|
||||
#638=IFCINDEXEDPOLYGONALFACE((10,11,17,16));
|
||||
#639=IFCINDEXEDPOLYGONALFACE((11,12,18,17));
|
||||
#640=IFCINDEXEDPOLYGONALFACE((18,13,19,24));
|
||||
#641=IFCINDEXEDPOLYGONALFACE((13,14,20,19));
|
||||
#642=IFCINDEXEDPOLYGONALFACE((14,15,21,20));
|
||||
#643=IFCINDEXEDPOLYGONALFACE((15,16,22,21));
|
||||
#644=IFCINDEXEDPOLYGONALFACE((16,17,23,22));
|
||||
#645=IFCINDEXEDPOLYGONALFACE((17,18,24,23));
|
||||
#646=IFCINDEXEDPOLYGONALFACE((24,19,25,30));
|
||||
#647=IFCINDEXEDPOLYGONALFACE((19,20,26,25));
|
||||
#648=IFCINDEXEDPOLYGONALFACE((20,21,27,26));
|
||||
#649=IFCINDEXEDPOLYGONALFACE((21,22,28,27));
|
||||
#650=IFCINDEXEDPOLYGONALFACE((22,23,29,28));
|
||||
#651=IFCINDEXEDPOLYGONALFACE((23,24,30,29));
|
||||
#652=IFCINDEXEDPOLYGONALFACE((30,25,31,36));
|
||||
#653=IFCINDEXEDPOLYGONALFACE((25,26,32,31));
|
||||
#654=IFCINDEXEDPOLYGONALFACE((26,27,33,32));
|
||||
#655=IFCINDEXEDPOLYGONALFACE((27,28,34,33));
|
||||
#656=IFCINDEXEDPOLYGONALFACE((28,29,35,34));
|
||||
#657=IFCINDEXEDPOLYGONALFACE((29,30,36,35));
|
||||
#658=IFCINDEXEDPOLYGONALFACE((36,31,37,42));
|
||||
#659=IFCINDEXEDPOLYGONALFACE((31,32,38,37));
|
||||
#660=IFCINDEXEDPOLYGONALFACE((32,33,39,38));
|
||||
#661=IFCINDEXEDPOLYGONALFACE((33,34,40,39));
|
||||
#662=IFCINDEXEDPOLYGONALFACE((34,35,41,40));
|
||||
#663=IFCINDEXEDPOLYGONALFACE((35,36,42,41));
|
||||
#664=IFCINDEXEDPOLYGONALFACE((42,37,43,48));
|
||||
#665=IFCINDEXEDPOLYGONALFACE((37,38,44,43));
|
||||
#666=IFCINDEXEDPOLYGONALFACE((38,39,45,44));
|
||||
#667=IFCINDEXEDPOLYGONALFACE((39,40,46,45));
|
||||
#668=IFCINDEXEDPOLYGONALFACE((40,41,47,46));
|
||||
#669=IFCINDEXEDPOLYGONALFACE((41,42,48,47));
|
||||
#670=IFCINDEXEDPOLYGONALFACE((48,43,49,54));
|
||||
#671=IFCINDEXEDPOLYGONALFACE((43,44,50,49));
|
||||
#672=IFCINDEXEDPOLYGONALFACE((44,45,51,50));
|
||||
#673=IFCINDEXEDPOLYGONALFACE((45,46,52,51));
|
||||
#674=IFCINDEXEDPOLYGONALFACE((46,47,53,52));
|
||||
#675=IFCINDEXEDPOLYGONALFACE((47,48,54,53));
|
||||
#676=IFCINDEXEDPOLYGONALFACE((49,50,51,52,53,54));
|
||||
#677=IFCPOLYGONALFACESET(#626,$,(#627,#628,#629,#630,#631,#632,#633,#634,#635,#636,#637,#638,#639,#640,#641,#642,#643,#644,#645,#646,#647,#648,#649,#650,#651,#652,#653,#654,#655,#656,#657,#658,#659,#660,#661,#662,#663,#664,#665,#666,#667,#668,#669,#670,#671,#672,#673,#674,#675,#676),$);
|
||||
#678=IFCSHAPEREPRESENTATION(#16,'Body','Curve2D',(#625));
|
||||
#679=IFCSHAPEREPRESENTATION(#15,'Body','Tessellation',(#677));
|
||||
#680=IFCGEOGRAPHICELEMENTTYPE('3mKZtHjt12Rh_uInKdrcGZ',$,'Shrub Big (1.8m)',$,$,$,(#685,#690),$,$,.NOTDEFINED.);
|
||||
#681=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#682=IFCDIRECTION((1.,0.,0.));
|
||||
#683=IFCDIRECTION((0.,0.,1.));
|
||||
#684=IFCAXIS2PLACEMENT3D(#681,#683,#682);
|
||||
#685=IFCREPRESENTATIONMAP(#684,#679);
|
||||
#686=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#687=IFCDIRECTION((1.,0.,0.));
|
||||
#688=IFCDIRECTION((0.,0.,1.));
|
||||
#689=IFCAXIS2PLACEMENT3D(#686,#688,#687);
|
||||
#690=IFCREPRESENTATIONMAP(#689,#678);
|
||||
#691=IFCCARTESIANPOINT((0.,0.));
|
||||
#692=IFCAXIS2PLACEMENT2D(#691,$);
|
||||
#693=IFCCIRCLE(#692,100.);
|
||||
#694=IFCARBITRARYCLOSEDPROFILEDEF(.AREA.,$,#693);
|
||||
#695=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#696=IFCDIRECTION((0.,0.,1.));
|
||||
#697=IFCDIRECTION((1.,0.,0.));
|
||||
#698=IFCAXIS2PLACEMENT3D(#695,#696,#697);
|
||||
#699=IFCDIRECTION((0.,0.,1.));
|
||||
#700=IFCEXTRUDEDAREASOLID(#694,#698,#699,460.);
|
||||
#701=IFCCARTESIANPOINT((0.,0.,1130.));
|
||||
#702=IFCDIRECTION((0.,0.,1.));
|
||||
#703=IFCDIRECTION((1.,0.,0.));
|
||||
#704=IFCAXIS2PLACEMENT3D(#701,#702,#703);
|
||||
#705=IFCSPHERE(#704,670.);
|
||||
#706=IFCCARTESIANPOINT((0.,0.));
|
||||
#707=IFCAXIS2PLACEMENT2D(#706,$);
|
||||
#708=IFCCIRCLE(#707,670.);
|
||||
#709=IFCSHAPEREPRESENTATION(#16,'Body','Curve2D',(#708));
|
||||
#710=IFCSHAPEREPRESENTATION(#15,'Body','SweptSolid',(#700,#705));
|
||||
#711=IFCGEOGRAPHICELEMENTTYPE('24b7xpbZb38f1BXogqUXhD',$,'Simple Tree (1.8m)',$,$,$,(#716,#721),$,$,.NOTDEFINED.);
|
||||
#712=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#713=IFCDIRECTION((1.,0.,0.));
|
||||
#714=IFCDIRECTION((0.,0.,1.));
|
||||
#715=IFCAXIS2PLACEMENT3D(#712,#714,#713);
|
||||
#716=IFCREPRESENTATIONMAP(#715,#710);
|
||||
#717=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#718=IFCDIRECTION((1.,0.,0.));
|
||||
#719=IFCDIRECTION((0.,0.,1.));
|
||||
#720=IFCAXIS2PLACEMENT3D(#717,#719,#718);
|
||||
#721=IFCREPRESENTATIONMAP(#720,#709);
|
||||
#722=IFCCARTESIANPOINT((0.,0.));
|
||||
#723=IFCAXIS2PLACEMENT2D(#722,$);
|
||||
#724=IFCCIRCLE(#723,100.);
|
||||
#725=IFCARBITRARYCLOSEDPROFILEDEF(.AREA.,$,#724);
|
||||
#726=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#727=IFCDIRECTION((0.,0.,1.));
|
||||
#728=IFCDIRECTION((1.,0.,0.));
|
||||
#729=IFCAXIS2PLACEMENT3D(#726,#727,#728);
|
||||
#730=IFCDIRECTION((0.,0.,1.));
|
||||
#731=IFCEXTRUDEDAREASOLID(#725,#729,#730,1710.);
|
||||
#732=IFCCARTESIANPOINT((0.,0.,3355.));
|
||||
#733=IFCDIRECTION((0.,0.,1.));
|
||||
#734=IFCDIRECTION((1.,0.,0.));
|
||||
#735=IFCAXIS2PLACEMENT3D(#732,#733,#734);
|
||||
#736=IFCSPHERE(#735,1645.);
|
||||
#737=IFCCARTESIANPOINT((0.,0.));
|
||||
#738=IFCAXIS2PLACEMENT2D(#737,$);
|
||||
#739=IFCCIRCLE(#738,1645.);
|
||||
#740=IFCSHAPEREPRESENTATION(#16,'Body','Curve2D',(#739));
|
||||
#741=IFCSHAPEREPRESENTATION(#15,'Body','SweptSolid',(#731,#736));
|
||||
#742=IFCGEOGRAPHICELEMENTTYPE('3VL8Zl9Xb2AwPSDD7jujfl',$,'Simple Tree (5m)',$,$,$,(#747,#752),$,$,.NOTDEFINED.);
|
||||
#743=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#744=IFCDIRECTION((1.,0.,0.));
|
||||
#745=IFCDIRECTION((0.,0.,1.));
|
||||
#746=IFCAXIS2PLACEMENT3D(#743,#745,#744);
|
||||
#747=IFCREPRESENTATIONMAP(#746,#741);
|
||||
#748=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#749=IFCDIRECTION((1.,0.,0.));
|
||||
#750=IFCDIRECTION((0.,0.,1.));
|
||||
#751=IFCAXIS2PLACEMENT3D(#748,#750,#749);
|
||||
#752=IFCREPRESENTATIONMAP(#751,#740);
|
||||
#753=IFCCARTESIANPOINT((0.,0.));
|
||||
#754=IFCAXIS2PLACEMENT2D(#753,$);
|
||||
#755=IFCCIRCLE(#754,220.);
|
||||
#756=IFCARBITRARYCLOSEDPROFILEDEF(.AREA.,$,#755);
|
||||
#757=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#758=IFCDIRECTION((0.,0.,1.));
|
||||
#759=IFCDIRECTION((1.,0.,0.));
|
||||
#760=IFCAXIS2PLACEMENT3D(#757,#758,#759);
|
||||
#761=IFCDIRECTION((0.,0.,1.));
|
||||
#762=IFCEXTRUDEDAREASOLID(#756,#760,#761,5790.);
|
||||
#763=IFCCARTESIANPOINT((0.,0.,10395.));
|
||||
#764=IFCDIRECTION((0.,0.,1.));
|
||||
#765=IFCDIRECTION((1.,0.,0.));
|
||||
#766=IFCAXIS2PLACEMENT3D(#763,#764,#765);
|
||||
#767=IFCSPHERE(#766,4605.);
|
||||
#768=IFCCARTESIANPOINT((0.,0.));
|
||||
#769=IFCAXIS2PLACEMENT2D(#768,$);
|
||||
#770=IFCCIRCLE(#769,4605.);
|
||||
#771=IFCSHAPEREPRESENTATION(#16,'Body','Curve2D',(#770));
|
||||
#772=IFCSHAPEREPRESENTATION(#15,'Body','SweptSolid',(#762,#767));
|
||||
#773=IFCGEOGRAPHICELEMENTTYPE('3jGYIuJcL0phM2h4r9r95Q',$,'Simple Tree (15m)',$,$,$,(#778,#783),$,$,.NOTDEFINED.);
|
||||
#774=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#775=IFCDIRECTION((1.,0.,0.));
|
||||
#776=IFCDIRECTION((0.,0.,1.));
|
||||
#777=IFCAXIS2PLACEMENT3D(#774,#776,#775);
|
||||
#778=IFCREPRESENTATIONMAP(#777,#772);
|
||||
#779=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#780=IFCDIRECTION((1.,0.,0.));
|
||||
#781=IFCDIRECTION((0.,0.,1.));
|
||||
#782=IFCAXIS2PLACEMENT3D(#779,#781,#780);
|
||||
#783=IFCREPRESENTATIONMAP(#782,#771);
|
||||
#784=IFCCARTESIANPOINTLIST2D(((-498.579620361328,735.001647949219),(-644.625122070312,558.698791503906),(-614.925903320312,498.60498046875),(-740.696044921875,396.37109375),(-782.288513183594,134.234802246094),(-551.41796875,97.9387969970703),(-788.211303710938,76.7640991210938),(-816.569641113281,-242.43864440918),(-685.161376953125,-297.968902587891),(-703.043884277344,-397.560852050781),(-586.489440917969,-569.15283203125),(-528.322204589844,-575.251037597656),(-366.814422607422,-750.108703613281),(-257.688507080078,-767.03466796875),(-273.860229492188,-683.197692871094),(-185.236541748047,-810.123107910156),(313.798278808594,-745.734313964844),(262.069519042969,-582.365661621094),(406.147064208984,-688.067260742188),(778.871398925781,-313.5146484375),(703.457824707031,-249.706893920898),(805.686340332031,-208.338500976562),(821.777282714844,71.8945388793945),(639.965148925781,44.3083839416504),(773.707153320312,162.339202880859),(703.734558105469,469.384552001953),(564.003479003906,549.215209960938),(489.063201904297,694.462707519531),(337.980773925781,746.2314453125),(159.236328125,638.655029296875),(287.592864990234,774.293273925781),(-11.1607036590576,832.838073730469),(-158.524017333984,800.207580566406),(-271.424072265625,751.009338378906)));
|
||||
#785=IFCINDEXEDPOLYCURVE(#784,(IFCLINEINDEX((1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,1))),$);
|
||||
#786=IFCCARTESIANPOINTLIST3D(((80.,0.,0.),(40.,69.2820323027551,0.),(-40.,69.2820323027551,0.),(-80.,9.79717439317883E-15,0.),(-40.,-69.2820323027551,0.),(40.,-69.2820323027551,0.),(80.,0.,280.),(40.,69.2820323027551,280.),(-40.,69.2820323027551,280.),(-80.,9.79717439317883E-15,280.),(-40.,-69.2820323027551,280.),(40.,-69.2820323027551,280.),(610.340986817674,-5.11998806339175,502.765430824539),(281.439072714044,546.677704468069,520.441255965265),(-291.549977559115,499.655102439697,498.631051036932),(-617.600357563209,-18.0002392785791,529.745674601363),(-266.847896537159,-556.910514833911,523.07445182747),(310.029723989709,-532.642943384166,481.563368832141),(699.397468993717,-3.10815712380199,727.667741239885),(355.052935043769,568.360673738432,733.570036889682),(-308.666246071194,628.582194868307,722.445245365077),(-719.613234433747,-35.7080296205946,687.931736233252),(-311.6478364595,-608.980286853059,704.648197605265),(372.070129606822,-608.152053362288,717.812431534607),(763.794228948937,-31.3204193188668,937.51589967911),(408.972888631657,640.716082391856,911.578097173966),(-390.473345044531,632.112510840184,931.184023328963),(-745.505233761067,11.3681475906559,933.839400395571),(-358.630946664301,-690.676374550022,936.269525762716),(375.140586877863,-658.159992875781,903.558501964971),(869.836914477244,-29.0443800107266,1124.54961826854),(447.136382145783,768.355555760864,1143.76409675514),(-431.186180114122,717.796288298907,1132.35007279295),(-841.55780048986,-23.1508504281077,1121.17416888324),(-428.187090174966,-760.246071143039,1159.279616419),(448.116008554028,-716.140773181744,1147.14103266758),(757.425130447899,-4.70084047240072,1330.07490310776),(399.505270456854,653.333240297718,1352.71275883304),(-414.445397665745,661.713946940036,1371.67941135993),(-776.277740187312,26.6072792686131,1378.19571732018),(-402.818606589622,-663.628443148848,1395.27272058484),(385.647897991142,-658.102369718758,1334.23398662872),(686.035800389567,-2.77622907865673,1575.7384942221),(337.67134578655,600.901570871229,1585.64117034361),(-344.127505367052,570.723591037471,1578.6341137138),(-653.055169703612,-6.10749408831596,1549.40002660187),(-379.19620927887,-592.236118824385,1550.49839466833),(314.077525184638,-622.955785610011,1579.55078264226),(0.05,0.,1800.),(0.025,0.0433012701892219,1800.),(-0.025,0.0433012701892219,1800.),(-0.05,6.12323399573677E-18,1800.),(-0.025,-0.0433012701892219,1800.),(0.025,-0.0433012701892219,1800.)));
|
||||
#787=IFCINDEXEDPOLYGONALFACE((1,2,3,4,5,6));
|
||||
#788=IFCINDEXEDPOLYGONALFACE((6,1,7,12));
|
||||
#789=IFCINDEXEDPOLYGONALFACE((1,2,8,7));
|
||||
#790=IFCINDEXEDPOLYGONALFACE((2,3,9,8));
|
||||
#791=IFCINDEXEDPOLYGONALFACE((3,4,10,9));
|
||||
#792=IFCINDEXEDPOLYGONALFACE((4,5,11,10));
|
||||
#793=IFCINDEXEDPOLYGONALFACE((5,6,12,11));
|
||||
#794=IFCINDEXEDPOLYGONALFACE((12,7,13,18));
|
||||
#795=IFCINDEXEDPOLYGONALFACE((7,8,14,13));
|
||||
#796=IFCINDEXEDPOLYGONALFACE((8,9,15,14));
|
||||
#797=IFCINDEXEDPOLYGONALFACE((9,10,16,15));
|
||||
#798=IFCINDEXEDPOLYGONALFACE((10,11,17,16));
|
||||
#799=IFCINDEXEDPOLYGONALFACE((11,12,18,17));
|
||||
#800=IFCINDEXEDPOLYGONALFACE((18,13,19,24));
|
||||
#801=IFCINDEXEDPOLYGONALFACE((13,14,20,19));
|
||||
#802=IFCINDEXEDPOLYGONALFACE((14,15,21,20));
|
||||
#803=IFCINDEXEDPOLYGONALFACE((15,16,22,21));
|
||||
#804=IFCINDEXEDPOLYGONALFACE((16,17,23,22));
|
||||
#805=IFCINDEXEDPOLYGONALFACE((17,18,24,23));
|
||||
#806=IFCINDEXEDPOLYGONALFACE((24,19,25,30));
|
||||
#807=IFCINDEXEDPOLYGONALFACE((19,20,26,25));
|
||||
#808=IFCINDEXEDPOLYGONALFACE((20,21,27,26));
|
||||
#809=IFCINDEXEDPOLYGONALFACE((21,22,28,27));
|
||||
#810=IFCINDEXEDPOLYGONALFACE((22,23,29,28));
|
||||
#811=IFCINDEXEDPOLYGONALFACE((23,24,30,29));
|
||||
#812=IFCINDEXEDPOLYGONALFACE((30,25,31,36));
|
||||
#813=IFCINDEXEDPOLYGONALFACE((25,26,32,31));
|
||||
#814=IFCINDEXEDPOLYGONALFACE((26,27,33,32));
|
||||
#815=IFCINDEXEDPOLYGONALFACE((27,28,34,33));
|
||||
#816=IFCINDEXEDPOLYGONALFACE((28,29,35,34));
|
||||
#817=IFCINDEXEDPOLYGONALFACE((29,30,36,35));
|
||||
#818=IFCINDEXEDPOLYGONALFACE((36,31,37,42));
|
||||
#819=IFCINDEXEDPOLYGONALFACE((31,32,38,37));
|
||||
#820=IFCINDEXEDPOLYGONALFACE((32,33,39,38));
|
||||
#821=IFCINDEXEDPOLYGONALFACE((33,34,40,39));
|
||||
#822=IFCINDEXEDPOLYGONALFACE((34,35,41,40));
|
||||
#823=IFCINDEXEDPOLYGONALFACE((35,36,42,41));
|
||||
#824=IFCINDEXEDPOLYGONALFACE((42,37,43,48));
|
||||
#825=IFCINDEXEDPOLYGONALFACE((37,38,44,43));
|
||||
#826=IFCINDEXEDPOLYGONALFACE((38,39,45,44));
|
||||
#827=IFCINDEXEDPOLYGONALFACE((39,40,46,45));
|
||||
#828=IFCINDEXEDPOLYGONALFACE((40,41,47,46));
|
||||
#829=IFCINDEXEDPOLYGONALFACE((41,42,48,47));
|
||||
#830=IFCINDEXEDPOLYGONALFACE((48,43,49,54));
|
||||
#831=IFCINDEXEDPOLYGONALFACE((43,44,50,49));
|
||||
#832=IFCINDEXEDPOLYGONALFACE((44,45,51,50));
|
||||
#833=IFCINDEXEDPOLYGONALFACE((45,46,52,51));
|
||||
#834=IFCINDEXEDPOLYGONALFACE((46,47,53,52));
|
||||
#835=IFCINDEXEDPOLYGONALFACE((47,48,54,53));
|
||||
#836=IFCINDEXEDPOLYGONALFACE((49,50,51,52,53,54));
|
||||
#837=IFCPOLYGONALFACESET(#786,$,(#787,#788,#789,#790,#791,#792,#793,#794,#795,#796,#797,#798,#799,#800,#801,#802,#803,#804,#805,#806,#807,#808,#809,#810,#811,#812,#813,#814,#815,#816,#817,#818,#819,#820,#821,#822,#823,#824,#825,#826,#827,#828,#829,#830,#831,#832,#833,#834,#835,#836),$);
|
||||
#838=IFCSHAPEREPRESENTATION(#16,'Body','Curve2D',(#785));
|
||||
#839=IFCSHAPEREPRESENTATION(#15,'Body','Tessellation',(#837));
|
||||
#840=IFCGEOGRAPHICELEMENTTYPE('1CLHhCfcnFaBY1EM4kLSOR',$,'Tree Small (1.8m)',$,$,$,(#845,#850),$,$,.NOTDEFINED.);
|
||||
#841=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#842=IFCDIRECTION((1.,0.,0.));
|
||||
#843=IFCDIRECTION((0.,0.,1.));
|
||||
#844=IFCAXIS2PLACEMENT3D(#841,#843,#842);
|
||||
#845=IFCREPRESENTATIONMAP(#844,#839);
|
||||
#846=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#847=IFCDIRECTION((1.,0.,0.));
|
||||
#848=IFCDIRECTION((0.,0.,1.));
|
||||
#849=IFCAXIS2PLACEMENT3D(#846,#848,#847);
|
||||
#850=IFCREPRESENTATIONMAP(#849,#838);
|
||||
#851=IFCCARTESIANPOINTLIST2D(((-2932.8212890625,4323.5390625),(-3791.91259765625,3286.46362304688),(-3617.21118164062,2932.97045898438),(-4357.03564453125,2331.5947265625),(-4601.697265625,789.616455078125),(-3243.63500976562,576.110534667969),(-4636.537109375,451.553527832031),(-4803.35107421875,-1426.10961914062),(-4030.36108398438,-1752.75817871094),(-4135.55224609375,-2338.59326171875),(-3449.93798828125,-3347.95776367188),(-3107.77783203125,-3383.82958984375),(-2157.73193359375,-4412.404296875),(-1515.81469726562,-4511.96826171875),(-1610.94250488281,-4018.80981445312),(-1089.62670898438,-4765.43017578125),(1845.87219238281,-4386.67236328125),(1541.58532714844,-3425.68041992188),(2389.10034179688,-4047.45458984375),(4581.5966796875,-1844.20373535156),(4137.9873046875,-1468.86413574219),(4739.33154296875,-1225.52062988281),(4833.98388671875,422.909027099609),(3764.5009765625,260.637542724609),(4551.21826171875,954.936462402344),(4139.615234375,2761.08569335938),(3317.66748046875,3230.677734375),(2876.84228515625,4085.07470703125),(1988.12219238281,4389.5966796875),(936.684326171875,3756.79443359375),(1691.72277832031,4554.66650390625),(-65.6511993408203,4899.0478515625),(-932.494262695312,4707.103515625),(-1596.61218261719,4417.7021484375)));
|
||||
#852=IFCINDEXEDPOLYCURVE(#851,(IFCLINEINDEX((1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,1))),$);
|
||||
#853=IFCCARTESIANPOINTLIST3D(((220.,0.,0.),(110.,190.525588832576,0.),(-110.,190.525588832577,0.),(-220.,2.69422295812418E-14,0.),(-110.,-190.525588832576,0.),(110.,-190.525588832576,0.),(220.,0.,1830.),(110.,190.525588832576,1830.),(-110.,190.525588832577,1830.),(-220.,2.69422295812418E-14,1830.),(-110.,-190.525588832576,1830.),(110.,-190.525588832576,1830.),(3602.84155681395,-42.6665671949312,3758.28335210925),(1603.6589392837,3271.04318828699,3905.58189494864),(-1687.91647965929,2879.18817138389,3723.83018721253),(-3663.33631302674,-150.001993988159,3983.11871691612),(-1482.06580447633,-3356.31660800234,3927.52519380035),(1841.91436658091,-3154.08684592113,3581.5995021726),(4144.97890828097,-25.9013093650166,5704.3740341419),(2117.10779203141,3278.52951811646,5753.55983122354),(-1730.55205059328,3780.37552753208,5660.85323518517),(-4313.44362028123,-297.566913504955,5373.24065908662),(-1755.3986371625,-3617.02629407169,5512.5445038534),(2258.91774672351,-3610.12434831526,5622.24645326459),(4481.61857457447,-261.00349432389,7525.01344970687),(2466.44073859714,3708.28617613811,7308.86509549734),(-2312.27787537109,3636.58974654084,7472.24781345564),(-4329.21028134222,94.734563255466,7494.37595567738),(-2046.92455553584,-4124.62194412282,7514.62700040359),(2184.50489064885,-3853.65209683748,7242.03513542238),(5165.3076206437,-242.036500089388,9155.53253319023),(2684.46985121485,4598.74337345629,9315.65318724518),(-2551.55150095102,4177.41614460665,9220.53632089363),(-4929.6483374155,-192.923753567564,9127.40378831275),(-2526.55908479138,-4531.16433497441,9444.94918444402),(2692.6334046169,-4163.62018529695,9343.7943198489),(4428.54275373249,-39.1736706033394,10940.1480020885),(2387.54392047378,3813.42915868696,11128.7967997992),(-2512.04498054787,3883.26838070627,11286.8522375232),(-4585.64783489427,221.727327238442,11341.154787192),(-2415.15505491352,-3899.22251577971,11483.4631477308),(2272.06581659285,-3853.17190386229,10974.8070314298),(4033.63166991306,-23.1352423221394,13059.2493566128),(1972.26121488791,3549.70366088977,13141.7716576253),(-2026.06254472544,3298.22049560846,13083.3795190436),(-3758.79308086343,-50.8957840692999,12839.7621264441),(-2318.30174399058,-3477.4915604994,12848.9151936647),(1775.64604320532,-3733.48878371295,13091.0184267807),(0.05,0.,15000.),(0.025,0.0433012701892219,15000.),(-0.025,0.0433012701892219,15000.),(-0.05,6.12323399573677E-18,15000.),(-0.025,-0.0433012701892219,15000.),(0.025,-0.0433012701892219,15000.)));
|
||||
#854=IFCINDEXEDPOLYGONALFACE((1,2,3,4,5,6));
|
||||
#855=IFCINDEXEDPOLYGONALFACE((6,1,7,12));
|
||||
#856=IFCINDEXEDPOLYGONALFACE((1,2,8,7));
|
||||
#857=IFCINDEXEDPOLYGONALFACE((2,3,9,8));
|
||||
#858=IFCINDEXEDPOLYGONALFACE((3,4,10,9));
|
||||
#859=IFCINDEXEDPOLYGONALFACE((4,5,11,10));
|
||||
#860=IFCINDEXEDPOLYGONALFACE((5,6,12,11));
|
||||
#861=IFCINDEXEDPOLYGONALFACE((12,7,13,18));
|
||||
#862=IFCINDEXEDPOLYGONALFACE((7,8,14,13));
|
||||
#863=IFCINDEXEDPOLYGONALFACE((8,9,15,14));
|
||||
#864=IFCINDEXEDPOLYGONALFACE((9,10,16,15));
|
||||
#865=IFCINDEXEDPOLYGONALFACE((10,11,17,16));
|
||||
#866=IFCINDEXEDPOLYGONALFACE((11,12,18,17));
|
||||
#867=IFCINDEXEDPOLYGONALFACE((18,13,19,24));
|
||||
#868=IFCINDEXEDPOLYGONALFACE((13,14,20,19));
|
||||
#869=IFCINDEXEDPOLYGONALFACE((14,15,21,20));
|
||||
#870=IFCINDEXEDPOLYGONALFACE((15,16,22,21));
|
||||
#871=IFCINDEXEDPOLYGONALFACE((16,17,23,22));
|
||||
#872=IFCINDEXEDPOLYGONALFACE((17,18,24,23));
|
||||
#873=IFCINDEXEDPOLYGONALFACE((24,19,25,30));
|
||||
#874=IFCINDEXEDPOLYGONALFACE((19,20,26,25));
|
||||
#875=IFCINDEXEDPOLYGONALFACE((20,21,27,26));
|
||||
#876=IFCINDEXEDPOLYGONALFACE((21,22,28,27));
|
||||
#877=IFCINDEXEDPOLYGONALFACE((22,23,29,28));
|
||||
#878=IFCINDEXEDPOLYGONALFACE((23,24,30,29));
|
||||
#879=IFCINDEXEDPOLYGONALFACE((30,25,31,36));
|
||||
#880=IFCINDEXEDPOLYGONALFACE((25,26,32,31));
|
||||
#881=IFCINDEXEDPOLYGONALFACE((26,27,33,32));
|
||||
#882=IFCINDEXEDPOLYGONALFACE((27,28,34,33));
|
||||
#883=IFCINDEXEDPOLYGONALFACE((28,29,35,34));
|
||||
#884=IFCINDEXEDPOLYGONALFACE((29,30,36,35));
|
||||
#885=IFCINDEXEDPOLYGONALFACE((36,31,37,42));
|
||||
#886=IFCINDEXEDPOLYGONALFACE((31,32,38,37));
|
||||
#887=IFCINDEXEDPOLYGONALFACE((32,33,39,38));
|
||||
#888=IFCINDEXEDPOLYGONALFACE((33,34,40,39));
|
||||
#889=IFCINDEXEDPOLYGONALFACE((34,35,41,40));
|
||||
#890=IFCINDEXEDPOLYGONALFACE((35,36,42,41));
|
||||
#891=IFCINDEXEDPOLYGONALFACE((42,37,43,48));
|
||||
#892=IFCINDEXEDPOLYGONALFACE((37,38,44,43));
|
||||
#893=IFCINDEXEDPOLYGONALFACE((38,39,45,44));
|
||||
#894=IFCINDEXEDPOLYGONALFACE((39,40,46,45));
|
||||
#895=IFCINDEXEDPOLYGONALFACE((40,41,47,46));
|
||||
#896=IFCINDEXEDPOLYGONALFACE((41,42,48,47));
|
||||
#897=IFCINDEXEDPOLYGONALFACE((48,43,49,54));
|
||||
#898=IFCINDEXEDPOLYGONALFACE((43,44,50,49));
|
||||
#899=IFCINDEXEDPOLYGONALFACE((44,45,51,50));
|
||||
#900=IFCINDEXEDPOLYGONALFACE((45,46,52,51));
|
||||
#901=IFCINDEXEDPOLYGONALFACE((46,47,53,52));
|
||||
#902=IFCINDEXEDPOLYGONALFACE((47,48,54,53));
|
||||
#903=IFCINDEXEDPOLYGONALFACE((49,50,51,52,53,54));
|
||||
#904=IFCPOLYGONALFACESET(#853,$,(#854,#855,#856,#857,#858,#859,#860,#861,#862,#863,#864,#865,#866,#867,#868,#869,#870,#871,#872,#873,#874,#875,#876,#877,#878,#879,#880,#881,#882,#883,#884,#885,#886,#887,#888,#889,#890,#891,#892,#893,#894,#895,#896,#897,#898,#899,#900,#901,#902,#903),$);
|
||||
#905=IFCSHAPEREPRESENTATION(#16,'Body','Curve2D',(#852));
|
||||
#906=IFCSHAPEREPRESENTATION(#15,'Body','Tessellation',(#904));
|
||||
#907=IFCGEOGRAPHICELEMENTTYPE('1$Hd6qXnz8ff4y_T2Agko8',$,'Tree Big (15m)',$,$,$,(#912,#917),$,$,.NOTDEFINED.);
|
||||
#908=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#909=IFCDIRECTION((1.,0.,0.));
|
||||
#910=IFCDIRECTION((0.,0.,1.));
|
||||
#911=IFCAXIS2PLACEMENT3D(#908,#910,#909);
|
||||
#912=IFCREPRESENTATIONMAP(#911,#906);
|
||||
#913=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#914=IFCDIRECTION((1.,0.,0.));
|
||||
#915=IFCDIRECTION((0.,0.,1.));
|
||||
#916=IFCAXIS2PLACEMENT3D(#913,#915,#914);
|
||||
#917=IFCREPRESENTATIONMAP(#916,#905);
|
||||
#918=IFCCARTESIANPOINTLIST2D(((-1466.41064453125,2161.76953125),(-1895.95629882812,1643.23181152344),(-1808.60559082031,1466.48522949219),(-2178.51782226562,1165.79736328125),(-2300.8486328125,394.808227539062),(-1621.81750488281,288.055267333984),(-2318.2685546875,225.776763916016),(-2401.67553710938,-713.054809570312),(-2015.18054199219,-876.379089355469),(-2067.77612304688,-1169.29663085938),(-1724.96899414062,-1673.97888183594),(-1553.88891601562,-1691.91479492188),(-1078.86596679688,-2206.2021484375),(-757.907348632812,-2255.98413085938),(-805.471252441406,-2009.40490722656),(-544.813354492188,-2382.71508789062),(922.936096191406,-2193.33618164062),(770.792663574219,-1712.84020996094),(1194.55017089844,-2023.72729492188),(2290.79833984375,-922.101867675781),(2068.99365234375,-734.432067871094),(2369.66577148438,-612.760314941406),(2416.99194335938,211.454513549805),(1882.25048828125,130.318771362305),(2275.60913085938,477.468231201172),(2069.8076171875,1380.54284667969),(1658.83374023438,1615.3388671875),(1438.42114257812,2042.53735351562),(994.061096191406,2194.79833984375),(468.342163085938,1878.39721679688),(845.861389160156,2277.33325195312),(-32.8255996704102,2449.52392578125),(-466.247131347656,2353.5517578125),(-798.306091308594,2208.85107421875)));
|
||||
#919=IFCINDEXEDPOLYCURVE(#918,(IFCLINEINDEX((1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,1))),$);
|
||||
#920=IFCCARTESIANPOINTLIST3D(((110.,0.,0.),(55.,95.2627944162882,0.),(-55.,95.2627944162883,0.),(-110.,1.34711147906209E-14,0.),(-55.,-95.2627944162882,0.),(55.,-95.2627944162882,0.),(110.,0.,840.),(55.,95.2627944162882,840.),(-55.,95.2627944162883,840.),(-110.,1.34711147906209E-14,840.),(-55.,-95.2627944162882,840.),(55.,-95.2627944162882,840.),(1794.28051893798,-14.2221890649771,1449.90397451261),(831.219646427901,1604.18946900776,1499.0034887924),(-859.305493219764,1473.57113004006,1438.4195862137),(-1814.44543767558,-50.0006646627197,1524.8490961149),(-790.68860149211,-1632.61394224621,1506.31792174297),(910.638122193637,-1565.20402155248,1391.00935786706),(2054.99296942699,-8.63376978833887,2065.74372566635),(1042.36926401047,1675.96694458701,2082.13899136023),(-913.517350197761,1843.24894772555,2051.23679268077),(-2111.14787342708,-99.1889711683183,1955.36593398126),(-921.799545720834,-1788.79920323875,2001.80054890351),(1089.63924890784,-1786.49855465328,2038.36786537391),(2247.20619152482,-87.0011647746299,2639.76638799753),(1198.81357953238,1888.50119623031,2567.71693659435),(-1147.42595845703,1864.60238636456,2622.17784258045),(-2196.40342711407,31.5781877518221,2629.5538899877),(-1058.97485184528,-2027.27978555855,2636.30423822977),(1104.83496354962,-1936.9565031301,2545.44028323603),(2555.10254021457,-80.6788333631295,3150.41560630151),(1311.48995040495,2254.60229430579,3203.78915765315),(-1267.18383365034,2114.15988468925,3172.08353553597),(-2476.54944580517,-64.3079178558546,3141.03935800901),(-1258.85302826379,-2232.07594814517,3246.8878233861),(1314.2111348723,-2109.56123158602,3213.16953518773),(2229.51425124416,-13.0578902011131,3712.43028641044),(1172.51464015793,1923.54885707993,3775.31321898068),(-1214.01499351596,1946.82859775303,3827.99836488869),(-2281.88261163142,73.9091090794808,3846.09921477827),(-1181.71835163784,-1952.14664277751,3893.53533495789),(1134.02193886428,-1936.79643880504,3723.98329619088),(2017.87722330435,-7.71174744071313,4385.94026172807),(994.087071629305,1766.35832551144,4413.44769539892),(-1012.02084824181,1682.53060375101,4393.983649205),(-1926.26436028781,-16.9652613564332,4312.77785167185),(-1109.43391466353,-1742.28762538132,4315.82887407871),(928.548681068438,-1827.62003311917,4396.52995178405),(0.05,0.,5000.),(0.025,0.0433012701892219,5000.),(-0.025,0.0433012701892219,5000.),(-0.05,6.12323399573677E-18,5000.),(-0.025,-0.0433012701892219,5000.),(0.025,-0.0433012701892219,5000.)));
|
||||
#921=IFCINDEXEDPOLYGONALFACE((1,2,3,4,5,6));
|
||||
#922=IFCINDEXEDPOLYGONALFACE((6,1,7,12));
|
||||
#923=IFCINDEXEDPOLYGONALFACE((1,2,8,7));
|
||||
#924=IFCINDEXEDPOLYGONALFACE((2,3,9,8));
|
||||
#925=IFCINDEXEDPOLYGONALFACE((3,4,10,9));
|
||||
#926=IFCINDEXEDPOLYGONALFACE((4,5,11,10));
|
||||
#927=IFCINDEXEDPOLYGONALFACE((5,6,12,11));
|
||||
#928=IFCINDEXEDPOLYGONALFACE((12,7,13,18));
|
||||
#929=IFCINDEXEDPOLYGONALFACE((7,8,14,13));
|
||||
#930=IFCINDEXEDPOLYGONALFACE((8,9,15,14));
|
||||
#931=IFCINDEXEDPOLYGONALFACE((9,10,16,15));
|
||||
#932=IFCINDEXEDPOLYGONALFACE((10,11,17,16));
|
||||
#933=IFCINDEXEDPOLYGONALFACE((11,12,18,17));
|
||||
#934=IFCINDEXEDPOLYGONALFACE((18,13,19,24));
|
||||
#935=IFCINDEXEDPOLYGONALFACE((13,14,20,19));
|
||||
#936=IFCINDEXEDPOLYGONALFACE((14,15,21,20));
|
||||
#937=IFCINDEXEDPOLYGONALFACE((15,16,22,21));
|
||||
#938=IFCINDEXEDPOLYGONALFACE((16,17,23,22));
|
||||
#939=IFCINDEXEDPOLYGONALFACE((17,18,24,23));
|
||||
#940=IFCINDEXEDPOLYGONALFACE((24,19,25,30));
|
||||
#941=IFCINDEXEDPOLYGONALFACE((19,20,26,25));
|
||||
#942=IFCINDEXEDPOLYGONALFACE((20,21,27,26));
|
||||
#943=IFCINDEXEDPOLYGONALFACE((21,22,28,27));
|
||||
#944=IFCINDEXEDPOLYGONALFACE((22,23,29,28));
|
||||
#945=IFCINDEXEDPOLYGONALFACE((23,24,30,29));
|
||||
#946=IFCINDEXEDPOLYGONALFACE((30,25,31,36));
|
||||
#947=IFCINDEXEDPOLYGONALFACE((25,26,32,31));
|
||||
#948=IFCINDEXEDPOLYGONALFACE((26,27,33,32));
|
||||
#949=IFCINDEXEDPOLYGONALFACE((27,28,34,33));
|
||||
#950=IFCINDEXEDPOLYGONALFACE((28,29,35,34));
|
||||
#951=IFCINDEXEDPOLYGONALFACE((29,30,36,35));
|
||||
#952=IFCINDEXEDPOLYGONALFACE((36,31,37,42));
|
||||
#953=IFCINDEXEDPOLYGONALFACE((31,32,38,37));
|
||||
#954=IFCINDEXEDPOLYGONALFACE((32,33,39,38));
|
||||
#955=IFCINDEXEDPOLYGONALFACE((33,34,40,39));
|
||||
#956=IFCINDEXEDPOLYGONALFACE((34,35,41,40));
|
||||
#957=IFCINDEXEDPOLYGONALFACE((35,36,42,41));
|
||||
#958=IFCINDEXEDPOLYGONALFACE((42,37,43,48));
|
||||
#959=IFCINDEXEDPOLYGONALFACE((37,38,44,43));
|
||||
#960=IFCINDEXEDPOLYGONALFACE((38,39,45,44));
|
||||
#961=IFCINDEXEDPOLYGONALFACE((39,40,46,45));
|
||||
#962=IFCINDEXEDPOLYGONALFACE((40,41,47,46));
|
||||
#963=IFCINDEXEDPOLYGONALFACE((41,42,48,47));
|
||||
#964=IFCINDEXEDPOLYGONALFACE((48,43,49,54));
|
||||
#965=IFCINDEXEDPOLYGONALFACE((43,44,50,49));
|
||||
#966=IFCINDEXEDPOLYGONALFACE((44,45,51,50));
|
||||
#967=IFCINDEXEDPOLYGONALFACE((45,46,52,51));
|
||||
#968=IFCINDEXEDPOLYGONALFACE((46,47,53,52));
|
||||
#969=IFCINDEXEDPOLYGONALFACE((47,48,54,53));
|
||||
#970=IFCINDEXEDPOLYGONALFACE((49,50,51,52,53,54));
|
||||
#971=IFCPOLYGONALFACESET(#920,$,(#921,#922,#923,#924,#925,#926,#927,#928,#929,#930,#931,#932,#933,#934,#935,#936,#937,#938,#939,#940,#941,#942,#943,#944,#945,#946,#947,#948,#949,#950,#951,#952,#953,#954,#955,#956,#957,#958,#959,#960,#961,#962,#963,#964,#965,#966,#967,#968,#969,#970),$);
|
||||
#972=IFCSHAPEREPRESENTATION(#16,'Body','Curve2D',(#919));
|
||||
#973=IFCSHAPEREPRESENTATION(#15,'Body','Tessellation',(#971));
|
||||
#974=IFCGEOGRAPHICELEMENTTYPE('1t393Epk10ahdDnhnFR8sr',$,'Tree Medium (5m)',$,$,$,(#979,#984),$,$,.NOTDEFINED.);
|
||||
#975=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#976=IFCDIRECTION((1.,0.,0.));
|
||||
#977=IFCDIRECTION((0.,0.,1.));
|
||||
#978=IFCAXIS2PLACEMENT3D(#975,#977,#976);
|
||||
#979=IFCREPRESENTATIONMAP(#978,#973);
|
||||
#980=IFCCARTESIANPOINT((0.,0.,0.));
|
||||
#981=IFCDIRECTION((1.,0.,0.));
|
||||
#982=IFCDIRECTION((0.,0.,1.));
|
||||
#983=IFCAXIS2PLACEMENT3D(#980,#982,#981);
|
||||
#984=IFCREPRESENTATIONMAP(#983,#972);
|
||||
ENDSEC;
|
||||
END-ISO-10303-21;
|
||||
@@ -0,0 +1,23 @@
|
||||
ISO-10303-21;
|
||||
HEADER;
|
||||
FILE_DESCRIPTION(('ViewDefinition [CoordinationView]'),'2;1');
|
||||
FILE_NAME('','2023-09-28T23:00:50',(),(),'IfcOpenShell v0.7.0-fbd8ea1ed','IfcOpenShell v0.7.0-fbd8ea1ed','');
|
||||
FILE_SCHEMA(('IFC4'));
|
||||
ENDSEC;
|
||||
DATA;
|
||||
#1=IFCPROPERTYSETTEMPLATE('1TLQmgUKf0I8Zi07bm9Jqn',$,'ePSet_ProjectedCRS','',.PSET_OCCURRENCEDRIVEN.,'IfcProject',(#2,#3,#4,#5,#6,#7));
|
||||
#2=IFCSIMPLEPROPERTYTEMPLATE('2cH53PtVT3v88uf_uGFblG',$,'Name','',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.);
|
||||
#3=IFCSIMPLEPROPERTYTEMPLATE('3JsReA6vXDqR7aNC$haRYW',$,'Description','',.P_SINGLEVALUE.,'IfcText',$,$,$,$,$,.READWRITE.);
|
||||
#4=IFCSIMPLEPROPERTYTEMPLATE('0u0uEsT5HFtuX5GvozO9ba',$,'GeodeticDatum','',.P_SINGLEVALUE.,'IfcIdentifier',$,$,$,$,$,.READWRITE.);
|
||||
#5=IFCSIMPLEPROPERTYTEMPLATE('1JgEX9Fsf0$ggxYltdkqiY',$,'VerticalDatum','',.P_SINGLEVALUE.,'IfcIdentifier',$,$,$,$,$,.READWRITE.);
|
||||
#6=IFCSIMPLEPROPERTYTEMPLATE('3ahTZjYrD0MAOo5IH6QuGH',$,'MapProjection','',.P_SINGLEVALUE.,'IfcIdentifier',$,$,$,$,$,.READWRITE.);
|
||||
#7=IFCSIMPLEPROPERTYTEMPLATE('3hqJR2ghD0GAti7q4sXKj7',$,'MapZone','',.P_SINGLEVALUE.,'IfcIdentifier',$,$,$,$,$,.READWRITE.);
|
||||
#8=IFCPROPERTYSETTEMPLATE('1jGHTycOj0vA8xHfRl4TNs',$,'ePSet_MapConversion','',.PSET_OCCURRENCEDRIVEN.,'IfcProject',(#9,#10,#11,#12,#13,#15));
|
||||
#9=IFCSIMPLEPROPERTYTEMPLATE('0nxsULXo17JRrAvNteYtNR',$,'Eastings','',.P_SINGLEVALUE.,'IfcLengthMeasure',$,$,$,$,$,.READWRITE.);
|
||||
#10=IFCSIMPLEPROPERTYTEMPLATE('26RfaGJs5CqemN0Xin12XL',$,'Northings','',.P_SINGLEVALUE.,'IfcLengthMeasure',$,$,$,$,$,.READWRITE.);
|
||||
#11=IFCSIMPLEPROPERTYTEMPLATE('0ziCn3nZv3m850VEUwWH42',$,'OrthogonalHeight','',.P_SINGLEVALUE.,'IfcLengthMeasure',$,$,$,$,$,.READWRITE.);
|
||||
#12=IFCSIMPLEPROPERTYTEMPLATE('3d4BOt4In8WR119ms1SaAe',$,'XAxisAbscissa','',.P_SINGLEVALUE.,'IfcReal',$,$,$,$,$,.READWRITE.);
|
||||
#13=IFCSIMPLEPROPERTYTEMPLATE('1Q4Voqj2j84RQRI8l67m28',$,'XAxisOrdinate','',.P_SINGLEVALUE.,'IfcReal',$,$,$,$,$,.READWRITE.);
|
||||
#15=IFCSIMPLEPROPERTYTEMPLATE('0O1Hc0$XnDNOG_jPBmbW5r',$,'Scale','',.P_SINGLEVALUE.,'IfcReal',$,$,$,$,$,.READWRITE.);
|
||||
ENDSEC;
|
||||
END-ISO-10303-21;
|
||||
@@ -21,6 +21,7 @@ import bpy
|
||||
import json
|
||||
import addon_utils
|
||||
import ifcopenshell.api.owner.settings
|
||||
import blenderbim.bim
|
||||
import blenderbim.tool as tool
|
||||
import blenderbim.core.owner as core_owner
|
||||
from bpy.app.handlers import persistent
|
||||
@@ -59,6 +60,10 @@ def name_callback(obj, data):
|
||||
if not obj.BIMObjectProperties.ifc_definition_id:
|
||||
return
|
||||
|
||||
if obj.BIMObjectProperties.is_renaming:
|
||||
obj.BIMObjectProperties.is_renaming = False
|
||||
return
|
||||
|
||||
element = IfcStore.get_file().by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||
if "/" in obj.name:
|
||||
object_name = obj.name
|
||||
@@ -177,30 +182,20 @@ def refresh_ui_data():
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
if isinstance(tool.Ifc.get(), ifcopenshell.sqlite):
|
||||
tool.Ifc.get().clear_cache()
|
||||
|
||||
|
||||
def purge_module_data():
|
||||
from blenderbim.bim import modules
|
||||
|
||||
refresh_ui_data()
|
||||
for name, value in modules.items():
|
||||
try:
|
||||
getattr(getattr(getattr(ifcopenshell.api, name), "data"), "Data").purge()
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
# TODO: deprecate prop purge functions and refactor into data classes.
|
||||
try:
|
||||
getattr(value, "prop").purge()
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
if isinstance(tool.Ifc.get(), ifcopenshell.sqlite):
|
||||
tool.Ifc.get().clear_cache()
|
||||
|
||||
|
||||
@persistent
|
||||
def loadIfcStore(scene):
|
||||
IfcStore.purge()
|
||||
purge_module_data()
|
||||
refresh_ui_data()
|
||||
if not IfcStore.get_file():
|
||||
return
|
||||
IfcStore.get_schema()
|
||||
@@ -212,7 +207,7 @@ def undo_post(scene):
|
||||
if IfcStore.last_transaction != bpy.context.scene.BIMProperties.last_transaction:
|
||||
IfcStore.last_transaction = bpy.context.scene.BIMProperties.last_transaction
|
||||
IfcStore.undo(until_key=bpy.context.scene.BIMProperties.last_transaction)
|
||||
purge_module_data()
|
||||
refresh_ui_data()
|
||||
tool.Ifc.rebuild_element_maps()
|
||||
|
||||
|
||||
@@ -221,7 +216,7 @@ def redo_post(scene):
|
||||
if IfcStore.last_transaction != bpy.context.scene.BIMProperties.last_transaction:
|
||||
IfcStore.last_transaction = bpy.context.scene.BIMProperties.last_transaction
|
||||
IfcStore.redo(until_key=bpy.context.scene.BIMProperties.last_transaction)
|
||||
purge_module_data()
|
||||
refresh_ui_data()
|
||||
tool.Ifc.rebuild_element_maps()
|
||||
|
||||
|
||||
@@ -259,74 +254,58 @@ def viewport_shading_changed_callback(area):
|
||||
bpy.context.scene.BIMStylesProperties.active_style_type = "External"
|
||||
|
||||
|
||||
if getattr(bpy.types, "SCENE_PT_scene"):
|
||||
@classmethod
|
||||
def poll_check_blender_tab(cls, context):
|
||||
return tool.Blender.is_tab(context, "BLENDER")
|
||||
|
||||
class Override_SCENE_PT_scene(bpy.types.SCENE_PT_scene):
|
||||
bl_idname = "SCENE_PT_scene_override"
|
||||
|
||||
def get_override_scene_panel(panel_name):
|
||||
original_panel = getattr(bpy.types, panel_name)
|
||||
|
||||
override_panel = type(f"Override_{panel_name}", (original_panel,), {})
|
||||
override_panel.bl_idname = f"{panel_name}_override"
|
||||
|
||||
# some blender panel depend on other and register_class will throw an error
|
||||
# if we won't override their `bl_parent_id`
|
||||
bl_parent_id = getattr(override_panel, "bl_parent_id", None)
|
||||
if bl_parent_id is not None:
|
||||
override_panel.bl_parent_id = f"{bl_parent_id}_override"
|
||||
|
||||
# override poll method
|
||||
poll = getattr(override_panel, "poll", None)
|
||||
if poll is None:
|
||||
override_panel.poll = poll_check_blender_tab
|
||||
else:
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return tool.Blender.is_tab(context, "BLENDER")
|
||||
def wrapped_poll(cls, context):
|
||||
return super(override_panel, cls).poll(context) and poll_check_blender_tab.__func__(cls, context)
|
||||
|
||||
override_panel.poll = wrapped_poll
|
||||
|
||||
return override_panel
|
||||
|
||||
|
||||
if getattr(bpy.types, "SCENE_PT_unit"):
|
||||
|
||||
class Override_SCENE_PT_unit(bpy.types.SCENE_PT_unit):
|
||||
bl_idname = "SCENE_PT_unit_override"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return tool.Blender.is_tab(context, "BLENDER")
|
||||
|
||||
|
||||
if getattr(bpy.types, "SCENE_PT_physics"):
|
||||
|
||||
class Override_SCENE_PT_physics(bpy.types.SCENE_PT_physics):
|
||||
bl_idname = "SCENE_PT_physics_override"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return tool.Blender.is_tab(context, "BLENDER")
|
||||
|
||||
|
||||
if getattr(bpy.types, "SCENE_PT_rigid_body_world"):
|
||||
|
||||
class Override_SCENE_PT_rigid_body_world(bpy.types.SCENE_PT_rigid_body_world):
|
||||
bl_idname = "SCENE_PT_rigid_body_world_override"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return tool.Blender.is_tab(context, "BLENDER")
|
||||
|
||||
|
||||
if getattr(bpy.types, "SCENE_PT_audio"):
|
||||
|
||||
class Override_SCENE_PT_audio(bpy.types.SCENE_PT_audio):
|
||||
bl_idname = "SCENE_PT_audio_override"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return tool.Blender.is_tab(context, "BLENDER")
|
||||
|
||||
|
||||
if getattr(bpy.types, "SCENE_PT_keying_sets"):
|
||||
|
||||
class Override_SCENE_PT_keying_sets(bpy.types.SCENE_PT_keying_sets):
|
||||
bl_idname = "SCENE_PT_keying_sets_override"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return tool.Blender.is_tab(context, "BLENDER")
|
||||
|
||||
|
||||
if getattr(bpy.types, "SCENE_PT_custom_props"):
|
||||
|
||||
class Override_SCENE_PT_custom_props(bpy.types.SCENE_PT_custom_props):
|
||||
bl_idname = "SCENE_PT_custom_props_override"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return tool.Blender.is_tab(context, "BLENDER")
|
||||
# TODO: possibly override scene panels from other addons too?
|
||||
# list can be updated from
|
||||
# https://projects.blender.org/blender/blender/src/branch/main/scripts/startup/bl_ui/properties_scene.py#L421
|
||||
OVERRIDE_SCENE_PANELS = (
|
||||
"SCENE_PT_scene",
|
||||
"SCENE_PT_unit",
|
||||
"SCENE_PT_physics",
|
||||
"SCENE_PT_rigid_body_world",
|
||||
"SCENE_PT_rigid_body_world_settings",
|
||||
"SCENE_PT_rigid_body_cache",
|
||||
"SCENE_PT_rigid_body_field_weights",
|
||||
"SCENE_PT_audio",
|
||||
"SCENE_PT_keying_sets",
|
||||
"SCENE_PT_custom_props",
|
||||
# after SCENE_PT_keying_sets
|
||||
"SCENE_PT_keying_set_paths",
|
||||
"SCENE_PT_keyframing_settings",
|
||||
)
|
||||
if bpy.app.version >= (4, 0):
|
||||
OVERRIDE_SCENE_PANELS += ("SCENE_PT_simulation",)
|
||||
|
||||
|
||||
@persistent
|
||||
@@ -355,6 +334,9 @@ def load_post(scene):
|
||||
ifcopenshell.api.owner.settings.get_application = get_application
|
||||
AuthoringData.type_thumbnails = {}
|
||||
|
||||
if not bpy.context.preferences.addons["blenderbim"].preferences.should_setup_toolbar:
|
||||
tool.Blender.unregister_toolbar()
|
||||
|
||||
if bpy.context.preferences.addons["blenderbim"].preferences.should_setup_workspace:
|
||||
if "BIM" in bpy.data.workspaces:
|
||||
bpy.context.window.workspace = bpy.data.workspaces["BIM"]
|
||||
@@ -364,26 +346,12 @@ def load_post(scene):
|
||||
# To improve usability for new users, we hijack the scene properties
|
||||
# tab. We override default scene properties panels with our own poll
|
||||
# to hide them unless the user has chosen to view Blender properties.
|
||||
for panel in [
|
||||
"SCENE_PT_scene",
|
||||
"SCENE_PT_unit",
|
||||
"SCENE_PT_physics",
|
||||
"SCENE_PT_rigid_body_world",
|
||||
"SCENE_PT_audio",
|
||||
"SCENE_PT_keying_sets",
|
||||
"SCENE_PT_custom_props",
|
||||
]:
|
||||
if getattr(bpy.types, panel, None):
|
||||
try:
|
||||
bpy.utils.register_class(globals()[f"Override_{panel}"])
|
||||
bpy.utils.unregister_class(getattr(bpy.types, panel))
|
||||
except:
|
||||
pass
|
||||
|
||||
# https://blender.stackexchange.com/questions/140644/how-can-make-the-state-of-a-boolean-property-relative-to-the-3d-view-area
|
||||
for screen in bpy.data.screens:
|
||||
if len(screen.BIMAreaProperties) == 20:
|
||||
continue
|
||||
screen.BIMAreaProperties.clear()
|
||||
for i in range(20): # 20 is an arbitrary value of split areas
|
||||
screen.BIMAreaProperties.add()
|
||||
for panel in OVERRIDE_SCENE_PANELS:
|
||||
if panel in blenderbim.bim.overridden_scene_panels:
|
||||
continue
|
||||
override_panel = get_override_scene_panel(panel)
|
||||
original_panel = getattr(bpy.types, panel)
|
||||
bpy.utils.register_class(override_panel)
|
||||
bpy.utils.unregister_class(original_panel)
|
||||
blenderbim.bim.overridden_scene_panels[panel] = (original_panel, override_panel)
|
||||
tool.Blender.setup_tabs()
|
||||
|
||||
@@ -87,8 +87,15 @@ def import_attributes(ifc_class, props, data, callback=None):
|
||||
|
||||
# A more elegant attribute importer signature, intended to supersede import_attributes
|
||||
def import_attributes2(element, props, callback=None):
|
||||
for attribute in element.wrapped_data.declaration().as_entity().all_attributes():
|
||||
import_attribute(attribute, props, element.get_info(), callback=callback)
|
||||
if isinstance(element, str):
|
||||
attributes = tool.Ifc.schema().declaration_by_name(element).as_entity().all_attributes()
|
||||
info = {a.name(): None for a in attributes}
|
||||
info["type"] = element
|
||||
else:
|
||||
attributes = element.wrapped_data.declaration().as_entity().all_attributes()
|
||||
info = element.get_info()
|
||||
for attribute in attributes:
|
||||
import_attribute(attribute, props, info, callback=callback)
|
||||
|
||||
|
||||
def import_attribute(attribute, props, data, callback=None):
|
||||
@@ -238,7 +245,9 @@ def get_obj_ifc_definition_id(context, obj, obj_type):
|
||||
].ifc_definition_id
|
||||
elif obj_type == "WorkSchedule":
|
||||
return context.scene.BIMWorkScheduleProperties.active_work_schedule_id
|
||||
|
||||
elif obj_type == "Group":
|
||||
prop = context.scene.BIMGroupProperties
|
||||
return prop.groups[prop.active_group_index].ifc_definition_id
|
||||
|
||||
# hack to close popup
|
||||
# https://blender.stackexchange.com/a/202576/130742
|
||||
@@ -260,12 +269,7 @@ def convert_property_group_from_si(property_group, skip_props=()):
|
||||
for prop_name in property_group.bl_rna.properties.keys():
|
||||
if prop_name in skip_props:
|
||||
continue
|
||||
prop_bl_rna = property_group.bl_rna.properties[prop_name]
|
||||
if prop_bl_rna.array_length > 0:
|
||||
prop_value = prop_bl_rna.default_array
|
||||
else:
|
||||
prop_value = prop_bl_rna.default
|
||||
|
||||
prop_value = tool.Blender.get_blender_prop_default_value(property_group, prop_name)
|
||||
if type(prop_value) is float:
|
||||
prop_value = prop_value * conversion_k
|
||||
elif type(prop_value) is bpy.types.bpy_prop_array:
|
||||
@@ -273,7 +277,7 @@ def convert_property_group_from_si(property_group, skip_props=()):
|
||||
setattr(property_group, prop_name, prop_value)
|
||||
|
||||
|
||||
def draw_filter(layout, props, data, module):
|
||||
def draw_filter(layout, filter_groups, data, module):
|
||||
if not data.is_loaded:
|
||||
data.load()
|
||||
|
||||
@@ -291,7 +295,7 @@ def draw_filter(layout, props, data, module):
|
||||
row.operator("bim.add_filter_group", text="Add Search Group", icon="ADD").module = module
|
||||
row.operator("bim.edit_filter_query", text="", icon="FILTER").module = module
|
||||
|
||||
for i, filter_group in enumerate(props.filter_groups):
|
||||
for i, filter_group in enumerate(filter_groups):
|
||||
box = layout.box()
|
||||
|
||||
row = box.row(align=True)
|
||||
@@ -319,13 +323,17 @@ def draw_filter(layout, props, data, module):
|
||||
row = box.row(align=True)
|
||||
row.prop(ifc_filter, "pset", text="", icon="PROPERTIES")
|
||||
row.prop(ifc_filter, "name", text="")
|
||||
row.prop(ifc_filter, "comparison", text="")
|
||||
row.prop(ifc_filter, "value", text="")
|
||||
elif ifc_filter.type == "classification":
|
||||
row = box.row(align=True)
|
||||
row.prop(ifc_filter, "value", text="", icon="OUTLINER")
|
||||
elif ifc_filter.type == "location":
|
||||
row = box.row(align=True)
|
||||
row.prop(ifc_filter, "name", text="", icon="PACKAGE")
|
||||
row.prop(ifc_filter, "value", text="", icon="PACKAGE")
|
||||
elif ifc_filter.type == "group":
|
||||
row = box.row(align=True)
|
||||
row.prop(ifc_filter, "value", text="", icon="OUTLINER_COLLECTION")
|
||||
elif ifc_filter.type == "query":
|
||||
row = box.row(align=True)
|
||||
row.prop(ifc_filter, "name", text="", icon="POINTCLOUD_DATA")
|
||||
|
||||
@@ -80,8 +80,8 @@ class IfcStore:
|
||||
if IfcStore.path:
|
||||
try:
|
||||
IfcStore.load_file(IfcStore.path)
|
||||
except:
|
||||
pass
|
||||
except Exception as e:
|
||||
print(f"Failed to load file {IfcStore.path}. Error details: {e}")
|
||||
return IfcStore.file
|
||||
|
||||
@staticmethod
|
||||
@@ -163,8 +163,12 @@ class IfcStore:
|
||||
if not IfcStore.get_file():
|
||||
return
|
||||
for obj in bpy.data.objects:
|
||||
if obj.library:
|
||||
continue
|
||||
IfcStore.relink_object(obj)
|
||||
for obj in bpy.data.materials:
|
||||
if obj.library:
|
||||
continue
|
||||
IfcStore.relink_object(obj)
|
||||
|
||||
@staticmethod
|
||||
@@ -317,6 +321,7 @@ class IfcStore:
|
||||
|
||||
@staticmethod
|
||||
def execute_ifc_operator(operator, context, is_invoke=False):
|
||||
bpy.context.scene.BIMProperties.is_dirty = True
|
||||
is_top_level_operator = not bool(IfcStore.current_transaction)
|
||||
|
||||
if is_top_level_operator:
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -20,14 +20,14 @@ import bpy
|
||||
from . import ui, prop, operator
|
||||
|
||||
classes = (
|
||||
operator.BIM_OT_assign_object,
|
||||
operator.BIM_OT_unassign_object,
|
||||
operator.BIM_OT_enable_editing_aggregate,
|
||||
operator.BIM_OT_disable_editing_aggregate,
|
||||
operator.BIM_OT_add_aggregate,
|
||||
operator.BIM_OT_select_parts,
|
||||
operator.BIM_OT_select_aggregate,
|
||||
operator.BIM_OT_add_part_to_object,
|
||||
operator.BIM_OT_aggregate_assign_object,
|
||||
operator.BIM_OT_disable_editing_aggregate,
|
||||
operator.BIM_OT_enable_editing_aggregate,
|
||||
operator.BIM_OT_select_aggregate,
|
||||
operator.BIM_OT_select_parts,
|
||||
operator.BIM_OT_aggregate_unassign_object,
|
||||
prop.BIMObjectAggregateProperties,
|
||||
ui.BIM_PT_aggregate,
|
||||
)
|
||||
|
||||
@@ -35,7 +35,7 @@ class AggregateData:
|
||||
"has_relating_object": cls.has_relating_object(),
|
||||
"relating_object_label": cls.get_relating_object_label(),
|
||||
"has_related_objects": cls.has_related_objects(),
|
||||
"related_objects_amount": cls.get_related_objects_amount(),
|
||||
"total_parts": cls.total_parts(),
|
||||
"ifc_class": cls.ifc_class(),
|
||||
}
|
||||
cls.is_loaded = True
|
||||
@@ -59,7 +59,7 @@ class AggregateData:
|
||||
return ifcopenshell.util.element.get_parts(tool.Ifc.get_entity(bpy.context.active_object))
|
||||
|
||||
@classmethod
|
||||
def get_related_objects_amount(cls):
|
||||
def total_parts(cls):
|
||||
parts = cls.get_related_objects()
|
||||
return len(parts) if parts else 0
|
||||
|
||||
|
||||
@@ -33,11 +33,11 @@ class Operator:
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class BIM_OT_assign_object(bpy.types.Operator, Operator):
|
||||
class BIM_OT_aggregate_assign_object(bpy.types.Operator, Operator):
|
||||
"""Create aggregation relationship between two ifc elements"""
|
||||
|
||||
bl_idname = "bim.assign_object"
|
||||
bl_label = "Assign Object"
|
||||
bl_idname = "bim.aggregate_assign_object"
|
||||
bl_label = "Assign Object To Aggregation"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
relating_object: bpy.props.IntProperty()
|
||||
|
||||
@@ -67,11 +67,11 @@ class BIM_OT_assign_object(bpy.types.Operator, Operator):
|
||||
self.report({"ERROR"}, f" Cannot aggregate {obj.name} to {relating_obj.name}")
|
||||
|
||||
|
||||
class BIM_OT_unassign_object(bpy.types.Operator, Operator):
|
||||
class BIM_OT_aggregate_unassign_object(bpy.types.Operator, Operator):
|
||||
"""Remove aggregation relationship between two ifc elements"""
|
||||
|
||||
bl_idname = "bim.unassign_object"
|
||||
bl_label = "Unassign Object"
|
||||
bl_idname = "bim.aggregate_unassign_object"
|
||||
bl_label = "Unassign Object From Aggregation"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
@@ -164,6 +164,7 @@ class BIM_OT_add_aggregate(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
def create_aggregate(self, context, ifc_class):
|
||||
aggregate = bpy.data.objects.new("Assembly", None)
|
||||
aggregate.location = context.scene.cursor.location
|
||||
bpy.ops.bim.assign_class(obj=aggregate.name, ifc_class=ifc_class)
|
||||
return aggregate
|
||||
|
||||
@@ -202,6 +203,7 @@ class BIM_OT_select_aggregate(bpy.types.Operator):
|
||||
aggregate_obj = tool.Ifc.get_object(aggregate)
|
||||
if aggregate_obj in context.selectable_objects:
|
||||
aggregate_obj.select_set(True)
|
||||
bpy.context.view_layer.objects.active = aggregate_obj
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ class BIM_PT_aggregate(Panel):
|
||||
row = layout.row(align=True)
|
||||
row.prop(props, "relating_object", text="")
|
||||
if props.relating_object:
|
||||
op = row.operator("bim.assign_object", icon="CHECKMARK", text="")
|
||||
op = row.operator("bim.aggregate_assign_object", icon="CHECKMARK", text="")
|
||||
op.relating_object = props.relating_object.BIMObjectProperties.ifc_definition_id
|
||||
row.operator("bim.disable_editing_aggregate", icon="CANCEL", text="")
|
||||
else:
|
||||
@@ -65,15 +65,21 @@ class BIM_PT_aggregate(Panel):
|
||||
op.obj = context.active_object.name
|
||||
row.operator("bim.enable_editing_aggregate", icon="GREASEPENCIL", text="")
|
||||
row.operator("bim.add_aggregate", icon="ADD", text="")
|
||||
op = row.operator("bim.unassign_object", icon="X", text="")
|
||||
op = row.operator("bim.aggregate_unassign_object", icon="X", text="")
|
||||
else:
|
||||
row.label(text="No Aggregate", icon="TRIA_UP")
|
||||
row.operator("bim.enable_editing_aggregate", icon="GREASEPENCIL", text="")
|
||||
row.operator("bim.add_aggregate", icon="ADD", text="")
|
||||
|
||||
row = layout.row(align=True)
|
||||
parts = AggregateData.data["related_objects_amount"]
|
||||
row.label(text=f"{parts or 'No'} Part{'s' if parts > 1 else ''}", icon="TRIA_DOWN")
|
||||
total_parts = AggregateData.data["total_parts"]
|
||||
if total_parts == 0:
|
||||
row.label(text="No Parts", icon="TRIA_DOWN")
|
||||
elif total_parts == 1:
|
||||
row.label(text="1 Part", icon="TRIA_DOWN")
|
||||
else:
|
||||
row.label(text=f"{total_parts} Parts", icon="TRIA_DOWN")
|
||||
|
||||
if AggregateData.data["has_related_objects"]:
|
||||
op = row.operator("bim.select_parts", icon="RESTRICT_SELECT_OFF", text="")
|
||||
op.obj = context.active_object.name
|
||||
|
||||
@@ -16,6 +16,8 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import bpy
|
||||
import bcf
|
||||
import bcf.v2.bcfxml
|
||||
|
||||
@@ -23,12 +25,31 @@ import bcf.v2.bcfxml
|
||||
class BcfStore:
|
||||
bcfxml = None
|
||||
|
||||
@staticmethod
|
||||
def get_bcfxml():
|
||||
if not BcfStore.bcfxml:
|
||||
BcfStore.bcfxml = bcf.v2.bcfxml.BcfXml()
|
||||
return BcfStore.bcfxml
|
||||
@classmethod
|
||||
def get_bcfxml(cls):
|
||||
if not cls.bcfxml:
|
||||
bcf_filepath = bpy.context.scene.BCFProperties.bcf_file
|
||||
if not os.path.isabs(bcf_filepath):
|
||||
bcf_filepath = os.path.abspath(os.path.join(bpy.path.abspath("//"), bcf_filepath))
|
||||
if bcf_filepath:
|
||||
try:
|
||||
cls.bcfxml = bcf.bcfxml.load(bcf_filepath)
|
||||
except:
|
||||
# there will be a plenty of "Permission denied" errors
|
||||
# as many poll() methods will try to access the bcfxml simultaneously
|
||||
# the first time it's loaded
|
||||
pass
|
||||
return cls.bcfxml
|
||||
|
||||
@classmethod
|
||||
def set(cls, bcfxml):
|
||||
def set(cls, bcfxml, filepath):
|
||||
cls.bcfxml = bcfxml
|
||||
bpy.context.scene.BCFProperties.bcf_file = filepath
|
||||
|
||||
@classmethod
|
||||
def set_by_filepath(cls, filepath):
|
||||
cls.set(None, filepath)
|
||||
|
||||
@classmethod
|
||||
def unload_bcfxml(cls):
|
||||
cls.set(None, "")
|
||||
|
||||
@@ -42,11 +42,9 @@ class NewBcfProject(bpy.types.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
context.scene.BCFProperties.is_loaded = False
|
||||
bcfxml = bcf.v2.bcfxml.BcfXml.create_new("New Project")
|
||||
bcfstore.BcfStore.set(bcfxml)
|
||||
bcfstore.BcfStore.set(bcfxml, "")
|
||||
bpy.ops.bim.load_bcf_project()
|
||||
context.scene.BCFProperties.is_loaded = True
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -59,11 +57,10 @@ class LoadBcfProject(bpy.types.Operator):
|
||||
|
||||
def execute(self, context):
|
||||
if self.filepath:
|
||||
bcfstore.BcfStore.bcfxml = bcf.bcfxml.load(self.filepath)
|
||||
bcfstore.BcfStore.set_by_filepath(self.filepath)
|
||||
bcfxml = bcfstore.BcfStore.get_bcfxml()
|
||||
context.scene.BCFProperties.name = bcfxml.project.name
|
||||
bpy.ops.bim.load_bcf_topics()
|
||||
context.scene.BCFProperties.is_loaded = True
|
||||
return {"FINISHED"}
|
||||
|
||||
def invoke(self, context, event):
|
||||
@@ -77,8 +74,7 @@ class UnloadBcfProject(bpy.types.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
bcfstore.BcfStore.set(None)
|
||||
context.scene.BCFProperties.is_loaded = False
|
||||
bcfstore.BcfStore.unload_bcfxml()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -267,6 +263,7 @@ class SaveBcfProject(bpy.types.Operator):
|
||||
def execute(self, context):
|
||||
bcfxml = bcfstore.BcfStore.get_bcfxml()
|
||||
bcfxml.save(self.filepath)
|
||||
bcfstore.BcfStore.set(bcfxml, self.filepath)
|
||||
return {"FINISHED"}
|
||||
|
||||
def invoke(self, context, event):
|
||||
@@ -964,7 +961,8 @@ class ActivateBcfViewpoint(bpy.types.Operator):
|
||||
context_override = {}
|
||||
context_override["object"] = context_override["active_object"] = objs[0]
|
||||
context_override["selected_objects"] = context_override["selected_editable_objects"] = objs
|
||||
bpy.ops.object.hide_view_set(context_override, unselected=True)
|
||||
with context.temp_override(**context_override):
|
||||
bpy.ops.object.hide_view_set(unselected=True)
|
||||
context.area.type = old
|
||||
|
||||
if viewpoint.visualization_info.components.view_setup_hints:
|
||||
@@ -978,14 +976,16 @@ class ActivateBcfViewpoint(bpy.types.Operator):
|
||||
self.hide_spaces(context)
|
||||
self.set_openings_visibility(False, context)
|
||||
|
||||
# set selection at the end not to conflict with .hide_spaces
|
||||
self.set_selection(viewpoint)
|
||||
self.set_colours(viewpoint)
|
||||
|
||||
def hide_spaces(self, context):
|
||||
old = context.area.type
|
||||
context.area.type = "VIEW_3D"
|
||||
bpy.ops.object.select_all(action="DESELECT")
|
||||
bpy.ops.object.select_pattern(pattern="IfcSpace/*")
|
||||
bpy.ops.object.hide_view_set({})
|
||||
bpy.ops.object.hide_view_set()
|
||||
context.area.type = old
|
||||
|
||||
def set_openings_visibility(self, is_visible, context):
|
||||
|
||||
@@ -41,37 +41,37 @@ def purge():
|
||||
|
||||
|
||||
def updateBcfReferenceLink(self, context):
|
||||
if context.scene.BCFProperties.is_loaded:
|
||||
if bcfstore.BcfStore.get_bcfxml():
|
||||
bpy.ops.bim.edit_bcf_reference_links()
|
||||
|
||||
|
||||
def updateBcfLabel(self, context):
|
||||
if context.scene.BCFProperties.is_loaded:
|
||||
if bcfstore.BcfStore.get_bcfxml():
|
||||
bpy.ops.bim.edit_bcf_labels()
|
||||
|
||||
|
||||
def updateBcfProjectName(self, context):
|
||||
if self.is_loaded:
|
||||
if bcfstore.BcfStore.get_bcfxml():
|
||||
bpy.ops.bim.edit_bcf_project_name()
|
||||
|
||||
|
||||
def updateBcfAuthor(self, context):
|
||||
if self.is_loaded:
|
||||
if bcfstore.BcfStore.get_bcfxml():
|
||||
bpy.ops.bim.edit_bcf_author()
|
||||
|
||||
|
||||
def updateBcfTopicName(self, context):
|
||||
if context.scene.BCFProperties.is_loaded:
|
||||
if bcfstore.BcfStore.get_bcfxml():
|
||||
bpy.ops.bim.edit_bcf_topic_name()
|
||||
|
||||
|
||||
def updateBcfTopicIsEditable(self, context):
|
||||
if context.scene.BCFProperties.is_loaded and not self.is_editable:
|
||||
if bcfstore.BcfStore.get_bcfxml() and not self.is_editable:
|
||||
bpy.ops.bim.edit_bcf_topic()
|
||||
|
||||
|
||||
def updateBcfCommentIsEditable(self, context):
|
||||
if context.scene.BCFProperties.is_loaded and not self.is_editable:
|
||||
if bcfstore.BcfStore.get_bcfxml() and not self.is_editable:
|
||||
bpy.ops.bim.edit_bcf_comment(comment_guid=self.name)
|
||||
|
||||
|
||||
@@ -151,7 +151,7 @@ class BcfTopic(PropertyGroup):
|
||||
|
||||
|
||||
class BCFProperties(PropertyGroup):
|
||||
is_loaded: BoolProperty(name="Is Loaded", default=False)
|
||||
bcf_file: StringProperty(name="BCF File")
|
||||
comment_text_width: IntProperty(name="Comment Text Width", default=40)
|
||||
name: StringProperty(default="", name="Project Name", update=updateBcfProjectName)
|
||||
author: StringProperty(default="john@doe.com", name="Author Email", update=updateBcfAuthor)
|
||||
|
||||
@@ -39,8 +39,7 @@ class BIM_PT_bcf(Panel):
|
||||
scene = context.scene
|
||||
props = scene.BCFProperties
|
||||
|
||||
|
||||
if not props.is_loaded:
|
||||
if not bcfstore.BcfStore.get_bcfxml():
|
||||
row = layout.row(align=True)
|
||||
row.operator("bim.new_bcf_project", text="New Project")
|
||||
row.operator("bim.load_bcf_project", text="Load Project")
|
||||
|
||||
@@ -62,14 +62,14 @@ class BoundaryDecorator:
|
||||
gpu.state.point_size_set(6)
|
||||
gpu.state.blend_set("ALPHA")
|
||||
|
||||
self.line_shader = gpu.shader.from_builtin("3D_POLYLINE_UNIFORM_COLOR")
|
||||
self.line_shader = gpu.shader.from_builtin("POLYLINE_UNIFORM_COLOR")
|
||||
self.line_shader.bind() # required to be able to change uniforms of the shader
|
||||
# POLYLINE_UNIFORM_COLOR specific uniforms
|
||||
self.line_shader.uniform_float("viewportSize", (context.region.width, context.region.height))
|
||||
self.line_shader.uniform_float("lineWidth", 2.0)
|
||||
|
||||
# general shader
|
||||
self.shader = gpu.shader.from_builtin("3D_UNIFORM_COLOR")
|
||||
self.shader = gpu.shader.from_builtin("UNIFORM_COLOR")
|
||||
|
||||
selected_vertices = []
|
||||
selected_edges = []
|
||||
|
||||
@@ -22,6 +22,7 @@ import logging
|
||||
import shapely
|
||||
import mathutils
|
||||
import numpy as np
|
||||
import multiprocessing
|
||||
import ifcopenshell.api
|
||||
import ifcopenshell.util.unit
|
||||
import ifcopenshell.util.shape
|
||||
@@ -30,7 +31,7 @@ import ifcopenshell.util.placement
|
||||
import ifcopenshell.util.representation
|
||||
import blenderbim.tool as tool
|
||||
import blenderbim.bim.import_ifc as import_ifc
|
||||
from math import pi, inf
|
||||
from math import pi, inf, degrees, acos, radians
|
||||
from mathutils import Vector, Matrix
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from blenderbim.bim.module.model.decorator import ProfileDecorator
|
||||
@@ -63,7 +64,8 @@ def disable_editing_boundary_geometry(context):
|
||||
|
||||
|
||||
class Loader:
|
||||
def __init__(self):
|
||||
def __init__(self, operator=None):
|
||||
self.operator = operator
|
||||
self.ifc_file = None
|
||||
self.logger = None
|
||||
self.ifc_importer = None
|
||||
@@ -85,14 +87,33 @@ class Loader:
|
||||
tool.Loader.link_mesh(shape, mesh)
|
||||
except RuntimeError:
|
||||
# Fallback solution for invalid geometry provided by Revit. (InnerBoundaries cuting OuterBoundary)
|
||||
print(f"Failed to create mesh from IfcRelSpaceBoundary with ID {boundary.id()}. Geometry might be invalid")
|
||||
shape = ifcopenshell.geom.create_shape(self.fallback_settings, surface.OuterBoundary)
|
||||
self.operator.report(
|
||||
{"WARNING"},
|
||||
(
|
||||
f"IfcRelSpaceBoundary {boundary.id()} mesh creation failed. Geometry might be invalid. Using fallback solution"
|
||||
),
|
||||
)
|
||||
try:
|
||||
shape = ifcopenshell.geom.create_shape(self.fallback_settings, surface.OuterBoundary)
|
||||
except RuntimeError:
|
||||
self.operator.report(
|
||||
{"WARNING"},
|
||||
f"Skipping IfcRelSpaceBoundary {boundary.id()}. Fallback solution failed. Geometry might be invalid",
|
||||
)
|
||||
return None
|
||||
mesh = bpy.data.meshes.new(str(surface.id()))
|
||||
bm = bmesh.new()
|
||||
verts = [bm.verts.new(shape.verts[i : i + 3]) for i in range(0, len(shape.verts), 3)]
|
||||
bm.faces.new(verts)
|
||||
for inner_boundary in surface.InnerBoundaries:
|
||||
shape = ifcopenshell.geom.create_shape(self.fallback_settings, inner_boundary)
|
||||
try:
|
||||
shape = ifcopenshell.geom.create_shape(self.fallback_settings, inner_boundary)
|
||||
except RuntimeError:
|
||||
self.operator.report(
|
||||
{"WARNING"},
|
||||
f"Skipping an inner boundary for IfcRelSpaceBoundary with ID {boundary.id()}. Geometry might be invalid",
|
||||
)
|
||||
return None
|
||||
verts = [bm.verts.new(shape.verts[i : i + 3]) for i in range(0, len(shape.verts), 3)]
|
||||
for i in range(len(verts) - 1):
|
||||
bm.edges.new(verts[i : i + 2])
|
||||
@@ -103,7 +124,7 @@ class Loader:
|
||||
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
matrix = mathutils.Matrix(
|
||||
ifcopenshell.util.placement.get_axis2placement(surface.BasisSurface.Position).tolist()
|
||||
)
|
||||
)
|
||||
matrix.translation *= unit_scale
|
||||
mesh.transform(matrix)
|
||||
return mesh
|
||||
@@ -126,7 +147,15 @@ class Loader:
|
||||
self.ifc_importer = import_ifc.IfcImporter(ifc_import_settings)
|
||||
self.ifc_importer.file = self.ifc_file
|
||||
|
||||
def load_boundary(self, boundary, blender_space):
|
||||
def load_boundary(self, boundary, blender_space=None):
|
||||
if not blender_space:
|
||||
if not boundary.RelatingSpace:
|
||||
self.operator.report(
|
||||
{"WARNING"},
|
||||
f"Skipping IfcRelSpaceBoundary {boundary.id()} which have no relating space. Invalid boundary.",
|
||||
)
|
||||
return
|
||||
blender_space = tool.Ifc.get_object(boundary.RelatingSpace)
|
||||
obj = tool.Ifc.get_object(boundary)
|
||||
if obj:
|
||||
return obj
|
||||
@@ -145,9 +174,9 @@ class LoadProjectSpaceBoundaries(bpy.types.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
loader = Loader()
|
||||
loader = Loader(self)
|
||||
for rel in tool.Ifc.get().by_type("IfcRelSpaceBoundary"):
|
||||
loader.load_boundary(rel, tool.Ifc.get_object(rel.RelatingSpace))
|
||||
loader.load_boundary(rel)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -158,7 +187,7 @@ class LoadBoundary(bpy.types.Operator):
|
||||
boundary_id: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
loader = Loader()
|
||||
loader = Loader(self)
|
||||
for obj in context.visible_objects:
|
||||
obj.select_set(False)
|
||||
obj = loader.load_boundary(tool.Ifc.get().by_id(self.boundary_id), context.active_object)
|
||||
@@ -173,7 +202,7 @@ class LoadSpaceBoundaries(bpy.types.Operator):
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
loader = Loader()
|
||||
loader = Loader(self)
|
||||
element = tool.Ifc.get_entity(context.active_object)
|
||||
for rel in element.BoundedBy or []:
|
||||
loader.load_boundary(rel, context.active_object)
|
||||
@@ -421,7 +450,7 @@ class EnableEditingBoundaryGeometry(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bpy.ops.object.mode_set(mode="EDIT")
|
||||
ProfileDecorator.install(context, exit_edit_mode_callback=lambda: disable_editing_boundary_geometry(context))
|
||||
if not bpy.app.background:
|
||||
bpy.ops.wm.tool_set_by_id(tool.Blender.get_viewport_context(), name="bim.cad_tool")
|
||||
tool.Blender.set_viewport_tool("bim.cad_tool")
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -459,7 +488,7 @@ class EditBoundaryGeometry(bpy.types.Operator, tool.Ifc.Operator):
|
||||
ifcopenshell.util.element.remove_deep2(tool.Ifc.get(), old_surface)
|
||||
|
||||
old_mesh = obj.data
|
||||
loader = Loader()
|
||||
loader = Loader(self)
|
||||
obj.data = loader.create_mesh(element)
|
||||
tool.Geometry.delete_data(old_mesh)
|
||||
|
||||
@@ -484,7 +513,7 @@ class ShowBoundaries(bpy.types.Operator, tool.Ifc.Operator):
|
||||
|
||||
def _execute(self, context):
|
||||
props = bpy.context.scene.BIMBoundaryProperties
|
||||
loader = Loader()
|
||||
loader = Loader(self)
|
||||
for obj in context.selected_objects:
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
if not element or not getattr(element, "BoundedBy", None):
|
||||
@@ -538,6 +567,7 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
|
||||
related_building_element = None
|
||||
relating_space_obj = None
|
||||
related_building_element_obj = None
|
||||
parent_boundaries = []
|
||||
|
||||
objs = context.selected_objects
|
||||
if len(objs) == 2:
|
||||
@@ -552,8 +582,19 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
|
||||
else:
|
||||
related_building_element = element
|
||||
related_building_element_obj = obj
|
||||
parent_boundary = self.create_element_boundary(
|
||||
context, relating_space, relating_space_obj, related_building_element, related_building_element_obj
|
||||
)
|
||||
if parent_boundary:
|
||||
parent_boundaries.append(parent_boundary)
|
||||
elif len(objs) == 1:
|
||||
# New prototype, old code not yet removed. Still testing.
|
||||
space = tool.Ifc.get_entity(objs[0])
|
||||
if space.is_a("IfcSpace"):
|
||||
self.auto_generate_boundaries(space, objs[0])
|
||||
elif len(objs) == 1:
|
||||
# Optionally the user may select just the space, and the building element shall be auto-detected
|
||||
# TODO : refactor to be able to generate all boundaries for selected space automatically or with an option
|
||||
|
||||
def msg(self, context):
|
||||
self.layout.label(text="NO ACTIVE STOREY")
|
||||
@@ -563,8 +604,6 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
|
||||
relating_space = element
|
||||
relating_space_obj = objs[0]
|
||||
|
||||
target = bpy.context.scene.cursor.location
|
||||
|
||||
collection = context.view_layer.active_layer_collection.collection
|
||||
collection_obj = bpy.data.objects.get(collection.name)
|
||||
if not collection_obj:
|
||||
@@ -576,19 +615,258 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
|
||||
return
|
||||
|
||||
for subelement in ifcopenshell.util.element.get_decomposition(spatial_element):
|
||||
if not (subelement.is_a("IfcWall") or subelement.is_a("IfcSlab")):
|
||||
if not (
|
||||
subelement.is_a("IfcWall") or subelement.is_a("IfcSlab") or subelement.is_a("IfcVirtualElement")
|
||||
):
|
||||
continue
|
||||
obj = tool.Ifc.get_object(subelement)
|
||||
if obj:
|
||||
raycast = obj.closest_point_on_mesh(obj.matrix_world.inverted() @ target, distance=0.1)
|
||||
if raycast[0]:
|
||||
related_building_element = subelement
|
||||
related_building_element_obj = obj
|
||||
break
|
||||
related_building_element = subelement
|
||||
related_building_element_obj = obj
|
||||
parent_boundary = self.create_element_boundary(
|
||||
context,
|
||||
relating_space,
|
||||
relating_space_obj,
|
||||
related_building_element,
|
||||
related_building_element_obj,
|
||||
)
|
||||
if parent_boundary:
|
||||
parent_boundaries.append(parent_boundary)
|
||||
|
||||
bpy.ops.bim.show_boundaries()
|
||||
for parent_boundary in parent_boundaries:
|
||||
obj = tool.Ifc.get_object(parent_boundary)
|
||||
obj.select_set(True)
|
||||
|
||||
def auto_generate_boundaries(self, space, space_obj):
|
||||
# Identify all potential building elements
|
||||
# TODO: don't select everything, use AABB culling in Blender
|
||||
building_elements = (
|
||||
tool.Ifc.get().by_type("IfcWall")
|
||||
+ tool.Ifc.get().by_type("IfcSlab")
|
||||
+ tool.Ifc.get().by_type("IfcVirtualElement")
|
||||
)
|
||||
|
||||
# Don't generate boundaries of building elements that we've already got bounaries for.
|
||||
for boundary in space.BoundedBy:
|
||||
if boundary.RelatedBuildingElement in building_elements:
|
||||
building_elements.remove(boundary.RelatedBuildingElement)
|
||||
|
||||
# Create tree of gross shapes of all potential related building elements
|
||||
include = building_elements + [space]
|
||||
tree = ifcopenshell.geom.tree()
|
||||
shapes = {}
|
||||
settings = ifcopenshell.geom.settings()
|
||||
settings.set(settings.STRICT_TOLERANCE, True)
|
||||
settings.set(settings.DISABLE_OPENING_SUBTRACTIONS, True)
|
||||
iterator = ifcopenshell.geom.iterator(settings, tool.Ifc.get(), multiprocessing.cpu_count(), include=include)
|
||||
if iterator.initialize():
|
||||
while True:
|
||||
tree.add_element(iterator.get_native())
|
||||
shape = iterator.get()
|
||||
shapes[shape.id] = shape
|
||||
if not iterator.next():
|
||||
break
|
||||
|
||||
# Spatially query all potential boundary elements via a 100mm extension of the space
|
||||
building_elements = [e for e in tree.select(space, extend=0.1) if e != space]
|
||||
|
||||
if not building_elements:
|
||||
return
|
||||
|
||||
# Create a dissolved bmesh for the space
|
||||
space_bm = bmesh.new()
|
||||
space_bm.from_mesh(space_obj.data)
|
||||
bmesh.ops.dissolve_limit(space_bm, angle_limit=pi * 2 / 360, verts=space_bm.verts, edges=space_bm.edges)
|
||||
|
||||
# Create dissolved bmeshes for all boundary elements
|
||||
building_element_bms = {}
|
||||
for building_element in building_elements:
|
||||
bm = bmesh.new()
|
||||
shape = shapes[building_element.id()]
|
||||
|
||||
verts = ifcopenshell.util.shape.get_vertices(shape.geometry)
|
||||
for vert in verts:
|
||||
bm.verts.new(Vector(vert))
|
||||
bm.verts.ensure_lookup_table()
|
||||
|
||||
faces = ifcopenshell.util.shape.get_faces(shape.geometry)
|
||||
for face in faces:
|
||||
bm.faces.new([bm.verts[i] for i in face])
|
||||
bm.verts.ensure_lookup_table()
|
||||
bm.faces.ensure_lookup_table()
|
||||
bm.normal_update() # Needed so that dissolve_limit will work.
|
||||
bmesh.ops.dissolve_limit(bm, angle_limit=radians(1), verts=bm.verts[:], edges=bm.edges[:])
|
||||
bm.verts.ensure_lookup_table()
|
||||
bm.faces.ensure_lookup_table()
|
||||
building_element_bms[building_element.id()] = bm
|
||||
|
||||
# Compare space faces and building element faces to see if they relate to one another
|
||||
for space_face in space_bm.faces:
|
||||
space_face_normal = space_obj.matrix_world.to_3x3() @ space_face.normal
|
||||
space_face_vert = space_obj.matrix_world @ space_face.verts[0].co
|
||||
for building_element in building_elements:
|
||||
for face in building_element_bms[building_element.id()].faces:
|
||||
building_obj = tool.Ifc.get_object(building_element)
|
||||
face_normal = building_obj.matrix_world.to_3x3() @ face.normal
|
||||
angle = degrees(acos(max(min(space_face_normal.dot(face_normal), 1), -1)))
|
||||
if tool.Cad.is_x(angle, 180, tolerance=2):
|
||||
pass # Faces need to be parallel and have opposite normals to be related.
|
||||
elif building_element.is_a("IfcVirtualElement") and tool.Cad.is_x(angle, 0, tolerance=2):
|
||||
pass # Virtual elements only need to be parallel to be related, since they are planes.
|
||||
else:
|
||||
continue
|
||||
|
||||
# Both faces should be close to one another. Say within 50mm.
|
||||
space_vert = building_obj.matrix_world.inverted() @ space_face_vert
|
||||
dist = mathutils.geometry.distance_point_to_plane(space_vert, face.verts[0].co, face.normal)
|
||||
if abs(dist) > 0.05:
|
||||
continue
|
||||
|
||||
# Project the building element face onto the space face
|
||||
space_face_verts = [v.co.copy() for v in space_face.verts]
|
||||
space_face_matrix = self.get_face_matrix(*[v.copy() for v in space_face_verts[0:3]])
|
||||
space_face_matrix_i = space_face_matrix.inverted()
|
||||
|
||||
space_face_polygon = shapely.Polygon(
|
||||
[tuple((space_face_matrix_i @ v).xy) for v in space_face_verts]
|
||||
)
|
||||
|
||||
space_matrix_world_i = space_obj.matrix_world.inverted()
|
||||
face_verts = [space_matrix_world_i @ building_obj.matrix_world @ v.co.copy() for v in face.verts]
|
||||
face_polygon = shapely.Polygon([tuple((space_face_matrix_i @ v).xy) for v in face_verts])
|
||||
|
||||
gross_boundary_polygon = space_face_polygon.intersection(face_polygon)
|
||||
|
||||
if type(gross_boundary_polygon) == shapely.GeometryCollection:
|
||||
for geom in gross_boundary_polygon.geoms:
|
||||
if type(geom) == shapely.Polygon:
|
||||
gross_boundary_polygon = geom
|
||||
break
|
||||
|
||||
if (
|
||||
not (isinstance(gross_boundary_polygon, shapely.Polygon) and gross_boundary_polygon.is_valid)
|
||||
or gross_boundary_polygon.is_empty
|
||||
):
|
||||
continue
|
||||
|
||||
# The gross boundary polygon may not be a true gross boundary since it
|
||||
# may have openings already removed, such as in IFC4 Reference View. So
|
||||
# we cheat by using the exterior boundary to mean "gross".
|
||||
exterior_boundary_polygon = shapely.Polygon(gross_boundary_polygon.exterior.coords)
|
||||
|
||||
parent_boundary = tool.Ifc.run(
|
||||
"root.create_entity", ifc_class=bpy.context.scene.BIMModelProperties.boundary_class
|
||||
)
|
||||
if building_element.is_a("IfcVirtualElement"):
|
||||
parent_boundary.PhysicalOrVirtualBoundary = "VIRTUAL"
|
||||
else:
|
||||
parent_boundary.PhysicalOrVirtualBoundary = "PHYSICAL"
|
||||
parent_boundary.InternalOrExternalBoundary = "NOTDEFINED"
|
||||
if building_element.is_a("IfcWall"):
|
||||
is_external = ifcopenshell.util.element.get_pset(
|
||||
building_element, "Pset_WallCommon", "IsExternal"
|
||||
)
|
||||
if is_external is True:
|
||||
parent_boundary.InternalOrExternalBoundary = "EXTERNAL"
|
||||
elif is_external is False:
|
||||
parent_boundary.InternalOrExternalBoundary = "INTERNAL"
|
||||
elif building_element.is_a("IfcSlab"):
|
||||
predefined_type = ifcopenshell.util.element.get_predefined_type(building_element)
|
||||
if predefined_type == "BASESLAB":
|
||||
parent_boundary.InternalOrExternalBoundary = "EXTERNAL_EARTH"
|
||||
else:
|
||||
is_external = ifcopenshell.util.element.get_pset(
|
||||
building_element, "Pset_SlabCommon", "IsExternal"
|
||||
)
|
||||
if is_external is True:
|
||||
parent_boundary.InternalOrExternalBoundary = "EXTERNAL"
|
||||
elif is_external is False:
|
||||
parent_boundary.InternalOrExternalBoundary = "INTERNAL"
|
||||
parent_boundary.RelatingSpace = space
|
||||
parent_boundary.RelatedBuildingElement = building_element
|
||||
parent_boundary.ConnectionGeometry = self.create_connection_geometry_from_polygon(
|
||||
exterior_boundary_polygon, space_face_matrix
|
||||
)
|
||||
self.set_boundary_name(parent_boundary)
|
||||
|
||||
for rel in getattr(building_element, "HasOpenings", []):
|
||||
opening = rel.RelatedOpeningElement
|
||||
filling = opening.HasFillings[0].RelatedBuildingElement if opening.HasFillings else None
|
||||
|
||||
# Create shape of opening as a dissolved BMesh
|
||||
settings = ifcopenshell.geom.settings()
|
||||
settings.set(settings.STRICT_TOLERANCE, True)
|
||||
shape = ifcopenshell.geom.create_shape(settings, opening)
|
||||
m = shape.transformation.matrix.data
|
||||
mat = Matrix(
|
||||
(
|
||||
[m[0], m[3], m[6], m[9]],
|
||||
[m[1], m[4], m[7], m[10]],
|
||||
[m[2], m[5], m[8], m[11]],
|
||||
[0, 0, 0, 1],
|
||||
)
|
||||
)
|
||||
opening_bm = bmesh.new()
|
||||
verts = ifcopenshell.util.shape.get_vertices(shape.geometry)
|
||||
for vert in verts:
|
||||
opening_bm.verts.new(Vector(vert))
|
||||
opening_bm.verts.ensure_lookup_table()
|
||||
faces = ifcopenshell.util.shape.get_faces(shape.geometry)
|
||||
for face in faces:
|
||||
opening_bm.faces.new([opening_bm.verts[i] for i in face])
|
||||
opening_bm.verts.ensure_lookup_table()
|
||||
opening_bm.faces.ensure_lookup_table()
|
||||
opening_bm.normal_update() # Needed so that dissolve_limit will work.
|
||||
bmesh.ops.dissolve_limit(
|
||||
opening_bm, angle_limit=radians(1), verts=opening_bm.verts[:], edges=opening_bm.edges[:]
|
||||
)
|
||||
opening_bm.verts.ensure_lookup_table()
|
||||
opening_bm.faces.ensure_lookup_table()
|
||||
|
||||
# Get relevant faces of BMesh that can turn into boundaries
|
||||
opening_polygons = []
|
||||
for opening_face in opening_bm.faces:
|
||||
opening_face_normal = mat.to_3x3() @ opening_face.normal
|
||||
angle = degrees(acos(max(min(opening_face_normal.dot(face_normal), 1), -1)))
|
||||
if not tool.Cad.is_x(angle, 180, tolerance=2):
|
||||
continue # Any non-parallel faces are not relevant
|
||||
opening_face_verts = [space_matrix_world_i @ mat @ v.co.copy() for v in opening_face.verts]
|
||||
polygon = shapely.Polygon([tuple((space_face_matrix_i @ v).xy) for v in opening_face_verts])
|
||||
opening_polygons.append(polygon)
|
||||
|
||||
# Merge them all into a single opening polygon for our boundary
|
||||
opening_polygon = shapely.ops.unary_union(opening_polygons)
|
||||
|
||||
# Only openings that are projected onto our exterior boundary are relevant.
|
||||
if opening_polygon.intersection(exterior_boundary_polygon).area == 0:
|
||||
continue
|
||||
|
||||
boundary = tool.Ifc.run(
|
||||
"root.create_entity", ifc_class=bpy.context.scene.BIMModelProperties.boundary_class
|
||||
)
|
||||
boundary.RelatingSpace = space
|
||||
boundary.RelatedBuildingElement = filling or opening
|
||||
boundary.ConnectionGeometry = self.create_connection_geometry_from_polygon(
|
||||
opening_polygon, space_face_matrix
|
||||
)
|
||||
if filling:
|
||||
boundary.PhysicalOrVirtualBoundary = "PHYSICAL"
|
||||
else:
|
||||
boundary.PhysicalOrVirtualBoundary = "VIRTUAL"
|
||||
boundary.InternalOrExternalBoundary = parent_boundary.InternalOrExternalBoundary
|
||||
if boundary.is_a() != "IfcRelSpaceBoundary":
|
||||
boundary.ParentBoundary = parent_boundary
|
||||
self.set_boundary_name(boundary)
|
||||
|
||||
def create_element_boundary(
|
||||
self, context, relating_space, relating_space_obj, related_building_element, related_building_element_obj
|
||||
):
|
||||
if not relating_space or not related_building_element:
|
||||
return
|
||||
|
||||
# Find which face on space should be bounded to related building element
|
||||
# TODO: Handle round wall where multiple faces need to be bound to the same related building element
|
||||
bm = bmesh.new()
|
||||
bm.from_mesh(relating_space_obj.data)
|
||||
bmesh.ops.dissolve_limit(bm, angle_limit=pi * 2 / 360, verts=bm.verts, edges=bm.edges)
|
||||
@@ -609,8 +887,6 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
|
||||
if not target_face:
|
||||
return
|
||||
|
||||
parent_boundary = tool.Ifc.run("root.create_entity", ifc_class=context.scene.BIMModelProperties.boundary_class)
|
||||
|
||||
# Is this right? Or should I use loop?
|
||||
target_face_verts = [v.co.copy() for v in target_face.verts]
|
||||
target_face_matrix = self.get_face_matrix(*[v.copy() for v in target_face_verts[0:3]])
|
||||
@@ -630,6 +906,18 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
|
||||
gross_boundary_polygon = geom
|
||||
break
|
||||
|
||||
if (
|
||||
not (isinstance(gross_boundary_polygon, shapely.Polygon) and gross_boundary_polygon.is_valid)
|
||||
or gross_boundary_polygon.is_empty
|
||||
):
|
||||
return
|
||||
|
||||
parent_boundary = tool.Ifc.run("root.create_entity", ifc_class=context.scene.BIMModelProperties.boundary_class)
|
||||
parent_boundary.PhysicalOrVirtualBoundary = "PHYSICAL"
|
||||
# Set to EXTERNAL by default and turn later to internal if there is a corresponding boundary relating to an
|
||||
# internal space
|
||||
parent_boundary.InternalOrExternalBoundary = "EXTERNAL"
|
||||
|
||||
# The gross boundary polygon may not be a true gross boundary since it
|
||||
# may have openings already removed, such as in IFC4 Reference View. So
|
||||
# we cheat by using the exterior boundary to mean "gross". Later, we
|
||||
@@ -637,19 +925,25 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
|
||||
# space.
|
||||
exterior_boundary_polygon = shapely.Polygon(gross_boundary_polygon.exterior.coords)
|
||||
|
||||
net_boundary_polygon = shapely.Polygon(gross_boundary_polygon)
|
||||
|
||||
inner_boundaries = []
|
||||
|
||||
for rel in getattr(related_building_element, "HasOpenings", []):
|
||||
opening = rel.RelatedOpeningElement
|
||||
filling = None
|
||||
if opening.HasFillings:
|
||||
filling = opening.HasFillings[0].RelatedBuildingElement
|
||||
if not opening.HasFillings:
|
||||
continue
|
||||
# TODO: HasFilling is a zero to many relationship. How to handle many ?
|
||||
filling = opening.HasFillings[0].RelatedBuildingElement
|
||||
|
||||
opening_polygon = self.get_flattened_polygon(opening, relating_space_obj, target_face_matrix_i)
|
||||
|
||||
net_boundary_polygon = net_boundary_polygon.difference(opening_polygon)
|
||||
# An inner boundary is supposed to overlap its parent boundary according to IFC4 documentation
|
||||
# so we extend our exterior boundary with all opening which has a filling
|
||||
# Also see Implementation aggreement SB 1.1 for IFC 2x3 TC1 Space Boundary Addon View
|
||||
# https://standards.buildingsmart.org/MVD/RELEASE/IFC2x3/TC1/SB1_1/IFC%20Space%20Boundary%20Implementation%20Agreement%20Addendum%202010-03-22.pdf
|
||||
unionised_object = exterior_boundary_polygon.union(opening_polygon)
|
||||
if isinstance(unionised_object, shapely.Polygon):
|
||||
exterior_boundary_polygon = unionised_object
|
||||
|
||||
# Only openings that are projected onto our exterior boundary are relevant.
|
||||
if opening_polygon.intersection(exterior_boundary_polygon).area == 0:
|
||||
continue
|
||||
@@ -657,24 +951,25 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
|
||||
connection_geometry = self.create_connection_geometry_from_polygon(opening_polygon, target_face_matrix)
|
||||
boundary = tool.Ifc.run("root.create_entity", ifc_class=context.scene.BIMModelProperties.boundary_class)
|
||||
boundary.RelatingSpace = relating_space
|
||||
boundary.RelatedBuildingElement = filling or related_building_element
|
||||
boundary.RelatedBuildingElement = filling
|
||||
boundary.ConnectionGeometry = connection_geometry
|
||||
boundary.PhysicalOrVirtualBoundary = "PHYSICAL" if filling else "VIRTUAL"
|
||||
boundary.InternalOrExternalBoundary = "INTERNAL"
|
||||
|
||||
if related_building_element.is_a("IfcVirtualElement"):
|
||||
boundary.PhysicalOrVirtualBoundary = "VIRTUAL"
|
||||
else:
|
||||
boundary.PhysicalOrVirtualBoundary = "PHYSICAL"
|
||||
boundary.InternalOrExternalBoundary = parent_boundary.InternalOrExternalBoundary
|
||||
self.set_boundary_name(boundary)
|
||||
if boundary.is_a("IfcRelSpaceBoundary2ndLevel"):
|
||||
boundary.ParentBoundary = parent_boundary
|
||||
|
||||
connection_geometry = self.create_connection_geometry_from_polygon(net_boundary_polygon, target_face_matrix)
|
||||
connection_geometry = self.create_connection_geometry_from_polygon(
|
||||
exterior_boundary_polygon, target_face_matrix
|
||||
)
|
||||
parent_boundary.RelatingSpace = relating_space
|
||||
parent_boundary.RelatedBuildingElement = related_building_element
|
||||
parent_boundary.ConnectionGeometry = connection_geometry
|
||||
parent_boundary.PhysicalOrVirtualBoundary = "PHYSICAL"
|
||||
parent_boundary.InternalOrExternalBoundary = "INTERNAL"
|
||||
|
||||
bpy.ops.bim.show_boundaries()
|
||||
obj = tool.Ifc.get_object(parent_boundary)
|
||||
obj.select_set(True)
|
||||
self.set_boundary_name(parent_boundary)
|
||||
return parent_boundary
|
||||
|
||||
def get_face_matrix(self, p1, p2, p3):
|
||||
edge1 = p2 - p1
|
||||
@@ -729,11 +1024,13 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
|
||||
tool.Model.unit_scale = self.unit_scale
|
||||
|
||||
surface = tool.Ifc.get().createIfcCurveBoundedPlane()
|
||||
surface.BasisSurface = tool.Ifc.get().createIfcPlane(tool.Ifc.get().createIfcAxis2Placement3D(
|
||||
tool.Ifc.get().createIfcCartesianPoint([o / self.unit_scale for o in p1]),
|
||||
tool.Ifc.get().createIfcDirection([float(o) for o in z_axis]),
|
||||
tool.Ifc.get().createIfcDirection([float(o) for o in x_axis]),
|
||||
))
|
||||
surface.BasisSurface = tool.Ifc.get().createIfcPlane(
|
||||
tool.Ifc.get().createIfcAxis2Placement3D(
|
||||
tool.Ifc.get().createIfcCartesianPoint([o / self.unit_scale for o in p1]),
|
||||
tool.Ifc.get().createIfcDirection([float(o) for o in z_axis]),
|
||||
tool.Ifc.get().createIfcDirection([float(o) for o in x_axis]),
|
||||
)
|
||||
)
|
||||
|
||||
if tool.Ifc.get().schema != "IFC2X3":
|
||||
points = [tool.Model.convert_si_to_unit(list(co)) for co in polygon.exterior.coords]
|
||||
@@ -746,9 +1043,24 @@ class AddBoundary(bpy.types.Operator, tool.Ifc.Operator):
|
||||
point_list = tool.Ifc.get().createIfcCartesianPointList2D(points)
|
||||
inner_boundaries.append(tool.Ifc.get().createIfcIndexedPolyCurve(point_list, None, False))
|
||||
else:
|
||||
pass # TODO
|
||||
pass # TODO
|
||||
|
||||
surface.OuterBoundary = outer_boundary
|
||||
surface.InnerBoundaries = inner_boundaries
|
||||
|
||||
return surface
|
||||
|
||||
def set_boundary_name(self, boundary):
|
||||
"""
|
||||
By convention 1stLevel and 2ndLevel boundary have specific name and description
|
||||
See https://ifc43-docs.standards.buildingsmart.org/IFC/RELEASE/IFC4x3/HTML/lexical/IfcRelSpaceBoundary.htm
|
||||
Warning: IfcRelSpaceBoundary2ndLevel is a subclass of IfcRelSpaceBoundary1stLevel test order matter
|
||||
"""
|
||||
if boundary.is_a("IfcRelSpaceBoundary2ndLevel"):
|
||||
boundary.Name = "2ndLevel"
|
||||
if boundary.CorrespondingBoundary:
|
||||
boundary.Description = "2a"
|
||||
else:
|
||||
boundary.Description = "2b"
|
||||
elif boundary.is_a("IfcRelSpaceBoundary1stLevel"):
|
||||
boundary.Name = "1stLevel"
|
||||
|
||||
@@ -31,7 +31,7 @@ class BIM_PT_SceneBoundaries(Panel):
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_geometry"
|
||||
bl_parent_id = "BIM_PT_tab_geometry"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
||||
# Copyright (C) 2023 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of BlenderBIM Add-on.
|
||||
#
|
||||
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# BlenderBIM Add-on is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
from . import ui, prop, operator
|
||||
|
||||
classes = (
|
||||
operator.GetBSDDClassificationProperties,
|
||||
operator.LoadBSDDDomains,
|
||||
operator.SearchBSDDClass,
|
||||
operator.SetActiveBSDDDictionary,
|
||||
prop.BSDDDomain,
|
||||
prop.BSDDClassification,
|
||||
prop.BSDDPset,
|
||||
prop.BIMBSDDProperties,
|
||||
ui.BIM_UL_bsdd_domains,
|
||||
ui.BIM_UL_bsdd_classifications,
|
||||
ui.BIM_PT_bsdd,
|
||||
)
|
||||
|
||||
|
||||
def register():
|
||||
bpy.types.Scene.BIMBSDDProperties = bpy.props.PointerProperty(type=prop.BIMBSDDProperties)
|
||||
|
||||
|
||||
def unregister():
|
||||
del bpy.types.Scene.BIMBSDDProperties
|
||||
@@ -0,0 +1,65 @@
|
||||
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
||||
# Copyright (C) 2023 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of BlenderBIM Add-on.
|
||||
#
|
||||
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# BlenderBIM Add-on is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
import bsdd
|
||||
import blenderbim.tool as tool
|
||||
from blenderbim.core import bsdd as core
|
||||
|
||||
|
||||
class LoadBSDDDomains(bpy.types.Operator):
|
||||
bl_idname = "bim.load_bsdd_domains"
|
||||
bl_label = "Load bSDD Dictionaries"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
core.load_bsdd(bsdd.Client(), tool.Bsdd)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class SetActiveBSDDDictionary(bpy.types.Operator):
|
||||
bl_idname = "bim.set_active_bsdd_domain"
|
||||
bl_label = "Load bSDD Dictionary"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
name: bpy.props.StringProperty()
|
||||
uri: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
core.set_active_bsdd_dictionary(self.name, self.uri, tool.Bsdd)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class SearchBSDDClass(bpy.types.Operator):
|
||||
bl_idname = "bim.search_bsdd_classifications"
|
||||
bl_label = "Search bSDD Class"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
keyword = context.scene.BIMBSDDProperties.keyword
|
||||
core.search_class(keyword, bsdd.Client(), tool.Bsdd)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class GetBSDDClassificationProperties(bpy.types.Operator):
|
||||
bl_idname = "bim.get_bsdd_classification_properties"
|
||||
bl_label = "Search bSDD Classifications"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
core.get_class_properties(bsdd.Client(), tool.Bsdd)
|
||||
return {"FINISHED"}
|
||||
@@ -0,0 +1,67 @@
|
||||
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
||||
# Copyright (C) 2023 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of BlenderBIM Add-on.
|
||||
#
|
||||
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# BlenderBIM Add-on is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
from bpy.types import PropertyGroup
|
||||
from blenderbim.bim.prop import Attribute, StrProperty
|
||||
from bpy.props import (
|
||||
PointerProperty,
|
||||
StringProperty,
|
||||
EnumProperty,
|
||||
BoolProperty,
|
||||
IntProperty,
|
||||
FloatProperty,
|
||||
FloatVectorProperty,
|
||||
CollectionProperty,
|
||||
)
|
||||
|
||||
|
||||
class BSDDDomain(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
uri: StringProperty(name="URI")
|
||||
default_language_code: StringProperty(name="Language")
|
||||
organization_name_owner: StringProperty(name="Organization")
|
||||
status: StringProperty(name="Status")
|
||||
version: StringProperty(name="Version")
|
||||
|
||||
|
||||
class BSDDClassification(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
reference_code: StringProperty(name="Reference Code")
|
||||
description: StringProperty(name="Description")
|
||||
uri: StringProperty(name="Namespace URI")
|
||||
domain_name: StringProperty(name="Domain Name")
|
||||
domain_namespace_uri: StringProperty(name="Domain Namespace URI")
|
||||
|
||||
|
||||
class BSDDPset(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
properties: CollectionProperty(name="Properties", type=Attribute)
|
||||
|
||||
|
||||
class BIMBSDDProperties(PropertyGroup):
|
||||
active_domain: StringProperty(name="Active Domain")
|
||||
active_uri: StringProperty(name="Active URI")
|
||||
domains: CollectionProperty(name="Domains", type=BSDDDomain)
|
||||
active_domain_index: IntProperty(name="Active Domain Index")
|
||||
classifications: CollectionProperty(name="Classifications", type=BSDDClassification)
|
||||
active_classification_index: IntProperty(name="Active Classification Index")
|
||||
keyword: StringProperty(name="Keyword")
|
||||
should_filter_ifc_class: BoolProperty(name="Filter Active IFC Class", default=True)
|
||||
load_preview_domains: BoolProperty(name="Load Preview Domains", default=False)
|
||||
classification_psets: CollectionProperty(name="Classification Psets", type=BSDDPset)
|
||||
@@ -0,0 +1,79 @@
|
||||
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
||||
# Copyright (C) 2023 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of BlenderBIM Add-on.
|
||||
#
|
||||
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# BlenderBIM Add-on is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import blenderbim.tool as tool
|
||||
from bpy.types import Panel, UIList
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
|
||||
|
||||
class BIM_PT_bsdd(Panel):
|
||||
bl_label = "buildingSMART Data Dictionary"
|
||||
bl_idname = "BIM_PT_bsdd"
|
||||
bl_options = {"DEFAULT_CLOSED"}
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_tab_project_setup"
|
||||
|
||||
def draw(self, context):
|
||||
props = context.scene.BIMBSDDProperties
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(props, "load_preview_domains")
|
||||
if len(props.domains):
|
||||
row.operator("bim.load_bsdd_domains", text="", icon="FILE_REFRESH")
|
||||
|
||||
if props.active_domain:
|
||||
row = self.layout.row()
|
||||
row.label(text="Active: " + props.active_domain, icon="URL")
|
||||
else:
|
||||
row = self.layout.row()
|
||||
row.label(text="No Active bSDD Domain", icon="ERROR")
|
||||
|
||||
if len(props.domains):
|
||||
self.layout.template_list(
|
||||
"BIM_UL_bsdd_domains",
|
||||
"",
|
||||
props,
|
||||
"domains",
|
||||
props,
|
||||
"active_domain_index",
|
||||
)
|
||||
else:
|
||||
row = self.layout.row()
|
||||
row.operator("bim.load_bsdd_domains")
|
||||
|
||||
|
||||
class BIM_UL_bsdd_domains(UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
if item:
|
||||
row = layout.row(align=True)
|
||||
if item.status != "Active":
|
||||
row.label(text=f"{item.name} ({item.organization_name_owner}) - {item.status}", icon="ERROR")
|
||||
else:
|
||||
row.label(text=f"{item.name} ({item.organization_name_owner})")
|
||||
op = row.operator("bim.set_active_bsdd_domain", text="", icon="RESTRICT_SELECT_OFF")
|
||||
op.name = item.name
|
||||
op.uri = item.uri
|
||||
|
||||
|
||||
class BIM_UL_bsdd_classifications(UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
if item:
|
||||
row = layout.row(align=True)
|
||||
row.label(text=item.reference_code)
|
||||
row.label(text=item.name)
|
||||
@@ -24,6 +24,8 @@ import bpy_extras
|
||||
import blenderbim.tool as tool
|
||||
from mathutils import Vector, Matrix
|
||||
from math import pi, radians, sin, cos, sqrt
|
||||
import ifcopenshell.util.unit
|
||||
|
||||
|
||||
messages = {
|
||||
"SHARED_VERTEX": "Shared Vertex, no intersection possible",
|
||||
@@ -140,6 +142,9 @@ class CadFillet(bpy.types.Operator):
|
||||
layout.prop(self, prop)
|
||||
|
||||
def execute(self, context):
|
||||
si_conversion = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
self.radius = self.radius * si_conversion
|
||||
|
||||
bpy.ops.object.mode_set(mode="OBJECT")
|
||||
bpy.ops.object.mode_set(mode="EDIT")
|
||||
|
||||
@@ -361,6 +366,10 @@ class CadOffset(bpy.types.Operator):
|
||||
# dialog that Mesh Tools has. Sverchok is 2D based, but has a weird side
|
||||
# effect of converting an unclosed loop into a closed loop which is also
|
||||
# not what users expect.
|
||||
|
||||
si_conversion = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
self.distance = self.distance * si_conversion
|
||||
|
||||
bpy.ops.object.mode_set(mode="OBJECT")
|
||||
bpy.ops.object.mode_set(mode="EDIT")
|
||||
|
||||
@@ -498,6 +507,8 @@ class CadOffset(bpy.types.Operator):
|
||||
local_direction = (rotation_i @ direction).normalized()
|
||||
normals.append(local_direction)
|
||||
|
||||
|
||||
|
||||
if len(normals) == 2:
|
||||
# https://stackoverflow.com/a/54042831/9627415
|
||||
new_normal = (normals[0].lerp(normals[1], 0.5)).normalized()
|
||||
@@ -531,7 +542,7 @@ class CadOffset(bpy.types.Operator):
|
||||
class AddIfcCircle(bpy.types.Operator):
|
||||
bl_idname = "bim.add_ifccircle"
|
||||
bl_label = "Add IfcCircle"
|
||||
radius: bpy.props.FloatProperty(name="Radius", default=0.1)
|
||||
radius: bpy.props.FloatProperty(name="Radius", default=0.5)
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
@@ -539,6 +550,9 @@ class AddIfcCircle(bpy.types.Operator):
|
||||
return bool(obj) and obj.type == "MESH"
|
||||
|
||||
def execute(self, context):
|
||||
si_conversion = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
self.radius = self.radius * si_conversion
|
||||
|
||||
if self.has_selected_existing_circle(context):
|
||||
self.change_radius(context)
|
||||
else:
|
||||
@@ -622,6 +636,9 @@ class AddIfcArcIndexFillet(bpy.types.Operator):
|
||||
layout.prop(self, prop)
|
||||
|
||||
def execute(self, context):
|
||||
si_conversion = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
self.radius = self.radius * si_conversion
|
||||
|
||||
if self.has_selected_existing_arc(context):
|
||||
self.change_radius(context)
|
||||
else:
|
||||
@@ -786,8 +803,8 @@ class AlignViewToProfile(bpy.types.Operator):
|
||||
class AddRectangle(bpy.types.Operator):
|
||||
bl_idname = "bim.add_rectangle"
|
||||
bl_label = "Add Rectangle"
|
||||
x: bpy.props.FloatProperty(name="X", default=0.1)
|
||||
y: bpy.props.FloatProperty(name="Y", default=0.1)
|
||||
x: bpy.props.FloatProperty(name="X", default=1)
|
||||
y: bpy.props.FloatProperty(name="Y", default=1)
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
@@ -795,6 +812,10 @@ class AddRectangle(bpy.types.Operator):
|
||||
return bool(obj) and obj.type == "MESH"
|
||||
|
||||
def execute(self, context):
|
||||
si_conversion = ifcopenshell.util.unit.calculate_unit_scale(tool.Ifc.get())
|
||||
self.x = self.x * si_conversion
|
||||
self.y = self.y * si_conversion
|
||||
|
||||
obj = context.active_object
|
||||
bm = bmesh.from_edit_mesh(obj.data)
|
||||
cursor = obj.matrix_world.inverted() @ context.scene.cursor.location
|
||||
|
||||
@@ -20,26 +20,33 @@ import bpy
|
||||
from . import ui, prop, operator
|
||||
|
||||
classes = (
|
||||
operator.AddClashSet,
|
||||
operator.AddClashSource,
|
||||
operator.ExecuteIfcClash,
|
||||
operator.ExportClashSets,
|
||||
operator.ImportClashSets,
|
||||
operator.AddClashSet,
|
||||
operator.LoadIfcClashes,
|
||||
operator.SaveIfcClashes,
|
||||
operator.LoadSmartGroupsForActiveClashSet,
|
||||
operator.RemoveClashSet,
|
||||
operator.AddClashSource,
|
||||
operator.RemoveClashSource,
|
||||
operator.SelectClashSource,
|
||||
operator.ExecuteIfcClash,
|
||||
operator.SelectIfcClashResults,
|
||||
operator.SelectClash,
|
||||
operator.SelectClashResults,
|
||||
operator.SelectClashSource,
|
||||
operator.SelectIfcClashResults,
|
||||
operator.SelectSmartGroup,
|
||||
operator.SelectSmartGroupedClashesPath,
|
||||
operator.SmartClashGroup,
|
||||
operator.SelectSmartGroup,
|
||||
operator.LoadSmartGroupsForActiveClashSet,
|
||||
prop.Clash,
|
||||
prop.ClashSource,
|
||||
prop.ClashSet,
|
||||
prop.SmartClashGroup,
|
||||
prop.BIMClashProperties,
|
||||
ui.BIM_PT_ifcclash,
|
||||
ui.BIM_PT_clash_manager,
|
||||
ui.BIM_PT_dumb_clash_manager,
|
||||
ui.BIM_PT_smart_clash_manager,
|
||||
ui.BIM_UL_clashes,
|
||||
ui.BIM_UL_clash_sets,
|
||||
ui.BIM_UL_smart_groups,
|
||||
)
|
||||
|
||||
@@ -26,6 +26,7 @@ import ifcopenshell
|
||||
from mathutils import Matrix, Vector
|
||||
from math import radians
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
import blenderbim.tool as tool
|
||||
|
||||
|
||||
class ExportClashSets(bpy.types.Operator):
|
||||
@@ -245,12 +246,14 @@ class ExecuteIfcClash(bpy.types.Operator):
|
||||
y = Vector([y.x, y.y, y.z])
|
||||
x = y.cross(z)
|
||||
|
||||
mat = Matrix([
|
||||
[x[0], y[0], z[0], p.x],
|
||||
[x[1], y[1], z[1], p.y],
|
||||
[x[2], y[2], z[2], p.z],
|
||||
[0, 0, 0, 0],
|
||||
])
|
||||
mat = Matrix(
|
||||
[
|
||||
[x[0], y[0], z[0], p.x],
|
||||
[x[1], y[1], z[1], p.y],
|
||||
[x[2], y[2], z[2], p.z],
|
||||
[0, 0, 0, 0],
|
||||
]
|
||||
)
|
||||
|
||||
camera.matrix_world = mat
|
||||
context.scene.camera = camera
|
||||
@@ -336,12 +339,132 @@ class SelectIfcClashResults(bpy.types.Operator):
|
||||
else:
|
||||
element_file = self.file
|
||||
|
||||
element = element_file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||
if element.GlobalId in global_ids:
|
||||
try:
|
||||
element = element_file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||
except:
|
||||
continue
|
||||
|
||||
global_id = getattr(element, "GlobalId", None)
|
||||
if not global_id:
|
||||
continue
|
||||
if global_id in global_ids:
|
||||
obj.select_set(True)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class LoadIfcClashes(bpy.types.Operator):
|
||||
bl_idname = "bim.load_ifc_clashes"
|
||||
bl_label = "Load IFC Clashes"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
bl_description = "Load the clashing IFC geometry stored in a file"
|
||||
filename_ext = ".json"
|
||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||
|
||||
def invoke(self, context, event):
|
||||
self.filepath = bpy.path.ensure_ext(bpy.data.filepath, ".json")
|
||||
WindowManager = context.window_manager
|
||||
WindowManager.fileselect_add(self)
|
||||
return {"RUNNING_MODAL"}
|
||||
|
||||
def execute(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
self.filepath = bpy.path.ensure_ext(self.filepath, ".json")
|
||||
with open(self.filepath) as f:
|
||||
clash_sets_json = json.load(f)
|
||||
active_clash_set = context.scene.BIMClashProperties.active_clash_set
|
||||
|
||||
for clash_set in clash_sets_json:
|
||||
if not "clashes" in clash_set.keys():
|
||||
self.report({"WARNING"}, "No clashes found for the selected Clash Set.")
|
||||
return {"CANCELLED"}
|
||||
active_clash_set.clashes.clear()
|
||||
for clash in clash_set["clashes"].values():
|
||||
blender_clash = active_clash_set.clashes.add()
|
||||
blender_clash.a_global_id = clash["a_global_id"]
|
||||
blender_clash.b_global_id = clash["b_global_id"]
|
||||
blender_clash.a_name = "{}/{}".format(clash["a_ifc_class"], clash["a_name"])
|
||||
blender_clash.b_name = "{}/{}".format(clash["b_ifc_class"], clash["b_name"])
|
||||
blender_clash.status = False if not "status" in clash.keys() else clash["status"]
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class SaveIfcClashes(bpy.types.Operator):
|
||||
bl_idname = "bim.save_ifc_clashes"
|
||||
bl_label = "Save IFC Clashes"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
bl_description = "Save the clashing IFC geometry stored in a file"
|
||||
filename_ext = ".json"
|
||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||
|
||||
def invoke(self, context, event):
|
||||
self.filepath = bpy.path.ensure_ext(bpy.data.filepath, ".json")
|
||||
WindowManager = context.window_manager
|
||||
WindowManager.fileselect_add(self)
|
||||
return {"RUNNING_MODAL"}
|
||||
|
||||
def execute(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
self.filepath = bpy.path.ensure_ext(self.filepath, ".json")
|
||||
clash_sets_json = self.load_json()
|
||||
active_clash_set = context.scene.BIMClashProperties.active_clash_set
|
||||
self.update_clash_sets(clash_sets_json, active_clash_set)
|
||||
self.save_json(clash_sets_json)
|
||||
return {"FINISHED"}
|
||||
|
||||
def load_json(self):
|
||||
with open(self.filepath) as f:
|
||||
return json.load(f)
|
||||
|
||||
def update_clash_sets(self, clash_sets_json, active_clash_set):
|
||||
for clash_set in clash_sets_json:
|
||||
if clash_set["name"] != active_clash_set.name or "clashes" not in clash_set.keys():
|
||||
continue
|
||||
for clash in active_clash_set.clashes:
|
||||
clash_key = clash.a_global_id + "-" + clash.b_global_id
|
||||
if clash_set.get("clashes", {}).get(clash_key, None) is not None:
|
||||
clash_set["clashes"][clash_key]["status"] = clash.status
|
||||
|
||||
def save_json(self, clash_sets_json):
|
||||
with open(self.filepath, "w") as destination:
|
||||
json.dump(clash_sets_json, destination, indent=4)
|
||||
|
||||
|
||||
class SelectClash(bpy.types.Operator):
|
||||
bl_idname = "bim.select_clash"
|
||||
bl_label = "Select Clash"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
bl_description = "Select the clashing IFC geometry stored in a file"
|
||||
index: bpy.props.IntProperty()
|
||||
|
||||
def execute(self, context):
|
||||
clash = context.scene.BIMClashProperties.active_clash
|
||||
|
||||
products = []
|
||||
linked_objects = []
|
||||
try:
|
||||
products.append(tool.Ifc.get().by_guid(clash.a_global_id))
|
||||
except:
|
||||
linked_objects.append(clash.a_name)
|
||||
try:
|
||||
products.append(tool.Ifc.get().by_guid(clash.b_global_id))
|
||||
except:
|
||||
linked_objects.append(clash.b_name)
|
||||
|
||||
tool.Spatial.select_products(products, unhide=True)
|
||||
print(linked_objects)
|
||||
for obj_name in linked_objects:
|
||||
obj = bpy.data.objects.get(obj_name)
|
||||
if obj:
|
||||
obj.select_set(True)
|
||||
else:
|
||||
print("Object not found:", obj_name)
|
||||
if context.scene.BIMClashProperties.sould_focus_on_clash:
|
||||
context_override = tool.Blender.get_viewport_context()
|
||||
with bpy.context.temp_override(**context_override):
|
||||
bpy.ops.view3d.view_selected()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class SmartClashGroup(bpy.types.Operator):
|
||||
bl_idname = "bim.smart_clash_group"
|
||||
bl_label = "Smart Group Clashes"
|
||||
@@ -426,9 +549,9 @@ class LoadSmartGroupsForActiveClashSet(bpy.types.Operator):
|
||||
new_group = context.scene.BIMClashProperties.smart_clash_groups.add()
|
||||
new_group.number = f"{smart_group}"
|
||||
for pair in global_id_pairs:
|
||||
for id in pair:
|
||||
for guid in pair:
|
||||
new_global_id = new_group.global_ids.add()
|
||||
new_global_id.name = id
|
||||
new_global_id.guid = guid
|
||||
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -443,20 +566,16 @@ class SelectSmartGroup(bpy.types.Operator):
|
||||
return IfcStore.get_file() and context.visible_objects and context.scene.BIMClashProperties.active_smart_group
|
||||
|
||||
def execute(self, context):
|
||||
self.file = IfcStore.get_file()
|
||||
# Select smart group in view
|
||||
selected_smart_group = context.scene.BIMClashProperties.active_smart_group
|
||||
# print(selected_smart_group.number)
|
||||
|
||||
for obj in context.visible_objects:
|
||||
if not obj.BIMObjectProperties.ifc_definition_id:
|
||||
products = []
|
||||
for global_id in selected_smart_group.global_ids:
|
||||
try:
|
||||
products.append(tool.Ifc.get().by_guid(global_id.guid))
|
||||
except:
|
||||
continue
|
||||
element = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||
for id in selected_smart_group.global_ids:
|
||||
# print("Id: ", id)
|
||||
# print("Global id: ", element.GlobalId)
|
||||
if element.GlobalId in id.name:
|
||||
# print("object match: ", global_id)
|
||||
obj.select_set(True)
|
||||
|
||||
tool.Spatial.select_products(products, unhide=True)
|
||||
context_override = tool.Blender.get_viewport_context()
|
||||
with bpy.context.temp_override(**context_override):
|
||||
bpy.ops.view3d.view_selected()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -43,11 +43,20 @@ class ClashSource(PropertyGroup):
|
||||
)
|
||||
|
||||
|
||||
class Clash(PropertyGroup):
|
||||
a_global_id: StringProperty(name="A")
|
||||
b_global_id: StringProperty(name="B")
|
||||
a_name: StringProperty(name="A Name")
|
||||
b_name: StringProperty(name="B Name")
|
||||
status: BoolProperty(name="Status", default=False)
|
||||
|
||||
|
||||
class ClashSet(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
tolerance: FloatProperty(name="Tolerance")
|
||||
a: CollectionProperty(name="Group A", type=ClashSource)
|
||||
b: CollectionProperty(name="Group B", type=ClashSource)
|
||||
clashes: CollectionProperty(name="Clashes", type=Clash)
|
||||
|
||||
|
||||
class SmartClashGroup(PropertyGroup):
|
||||
@@ -63,11 +72,13 @@ class BIMClashProperties(PropertyGroup):
|
||||
clash_results_path: StringProperty(name="Clash Results Path")
|
||||
smart_grouped_clashes_path: StringProperty(name="Smart Grouped Clashes Path")
|
||||
active_clash_set_index: IntProperty(name="Active Clash Set Index")
|
||||
active_clash_index: IntProperty(name="Active Clash Index")
|
||||
smart_clash_groups: CollectionProperty(name="Smart Clash Groups", type=SmartClashGroup)
|
||||
active_smart_group_index: IntProperty(name="Active Smart Group Index")
|
||||
smart_clash_grouping_max_distance: IntProperty(
|
||||
name="Smart Clash Grouping Max Distance", default=3, soft_min=1, soft_max=10
|
||||
)
|
||||
sould_focus_on_clash: BoolProperty(name="Show Focus Clash", default=False)
|
||||
|
||||
@property
|
||||
def active_clash_set(self):
|
||||
@@ -80,3 +91,9 @@ class BIMClashProperties(PropertyGroup):
|
||||
if not self.smart_clash_groups:
|
||||
return None
|
||||
return self.smart_clash_groups[self.active_smart_group_index]
|
||||
|
||||
@property
|
||||
def active_clash(self):
|
||||
if not self.active_clash_set:
|
||||
return None
|
||||
return self.active_clash_set.clashes[self.active_clash_index]
|
||||
|
||||
@@ -107,6 +107,42 @@ class BIM_PT_clash_manager(Panel):
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_tab_clash_detection"
|
||||
|
||||
def draw(self, context):
|
||||
pass
|
||||
|
||||
|
||||
class BIM_PT_dumb_clash_manager(Panel):
|
||||
bl_idname = "BIM_PT_dumb_clash_manager"
|
||||
bl_label = "Dumb Manager"
|
||||
bl_options = {"DEFAULT_CLOSED"}
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_clash_manager"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
props = context.scene.BIMClashProperties
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.operator("bim.load_ifc_clashes", text="LOAD IFC CLASHES", icon="IMPORT")
|
||||
row.operator("bim.save_ifc_clashes", text="SAVE CLASH RESULTS", icon="EXPORT")
|
||||
layout.template_list("BIM_UL_clashes", "", props.active_clash_set, "clashes", props, "active_clash_index")
|
||||
# bim.select_clash
|
||||
row = layout.row(align=True)
|
||||
row.operator("bim.select_clash", text="SELECT CLASH", icon="IMPORT")
|
||||
row.prop(props, "sould_focus_on_clash", icon="RESTRICT_VIEW_OFF")
|
||||
|
||||
|
||||
class BIM_PT_smart_clash_manager(Panel):
|
||||
bl_idname = "BIM_PT_smart_clash_manager"
|
||||
bl_label = "Smart Clash Manager"
|
||||
bl_options = {"DEFAULT_CLOSED"}
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_clash_manager"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
props = context.scene.BIMClashProperties
|
||||
@@ -156,3 +192,14 @@ class BIM_UL_smart_groups(bpy.types.UIList):
|
||||
layout.label(text=str(item.number), translate=False, icon="NONE", icon_value=0)
|
||||
else:
|
||||
layout.label(text="", translate=False)
|
||||
|
||||
|
||||
class BIM_UL_clashes(bpy.types.UIList):
|
||||
def draw_item(self, context, layout, data, item, icon, active_data, active_propname):
|
||||
if item:
|
||||
row = layout.row(align=True)
|
||||
row.label(text=str(item.a_name), translate=False, icon="NONE", icon_value=0)
|
||||
row.label(text=str(item.b_name), translate=False, icon="NONE", icon_value=0)
|
||||
row.prop(item, "status", text="")
|
||||
else:
|
||||
layout.label(text="", translate=False)
|
||||
|
||||
@@ -21,13 +21,21 @@ from . import ui, prop, operator
|
||||
|
||||
classes = (
|
||||
operator.AddClassification,
|
||||
operator.AddClassificationFromBSDD,
|
||||
operator.AddClassificationReference,
|
||||
operator.AddClassificationReferenceFromBSDD,
|
||||
operator.AddManualClassification,
|
||||
operator.AddManualClassificationReference,
|
||||
operator.ChangeClassificationLevel,
|
||||
operator.DisableAddingManualClassification,
|
||||
operator.DisableAddingManualClassificationReference,
|
||||
operator.DisableEditingClassification,
|
||||
operator.DisableEditingClassificationReference,
|
||||
operator.DisableEditingClassificationReferences,
|
||||
operator.EditClassification,
|
||||
operator.EditClassificationReference,
|
||||
operator.EnableAddingManualClassification,
|
||||
operator.EnableAddingManualClassificationReference,
|
||||
operator.EnableEditingClassification,
|
||||
operator.EnableEditingClassificationReference,
|
||||
operator.LoadClassificationLibrary,
|
||||
|
||||
@@ -73,6 +73,10 @@ class ReferencesData:
|
||||
if name in [e.Name for e in tool.Ifc.get().by_type("IfcClassification")]:
|
||||
return name
|
||||
|
||||
@classmethod
|
||||
def classifications(cls):
|
||||
return [(str(e.id()), e.Name, "") for e in tool.Ifc.get().by_type("IfcClassification")]
|
||||
|
||||
|
||||
class ClassificationReferencesData(ReferencesData):
|
||||
data = {}
|
||||
@@ -83,6 +87,8 @@ class ClassificationReferencesData(ReferencesData):
|
||||
cls.is_loaded = True
|
||||
cls.data["references"] = cls.references()
|
||||
cls.data["active_classification_library"] = cls.active_classification_library()
|
||||
cls.data["classifications"] = cls.classifications()
|
||||
cls.data["object_type"] = "OBJECT"
|
||||
|
||||
@classmethod
|
||||
def references(cls):
|
||||
@@ -105,6 +111,8 @@ class MaterialClassificationsData(ReferencesData):
|
||||
cls.is_loaded = True
|
||||
cls.data["references"] = cls.references()
|
||||
cls.data["active_classification_library"] = cls.active_classification_library()
|
||||
cls.data["classifications"] = cls.classifications()
|
||||
cls.data["object_type"] = "MATERIAL"
|
||||
|
||||
@classmethod
|
||||
def references(cls):
|
||||
@@ -127,6 +135,8 @@ class CostClassificationsData(ReferencesData):
|
||||
cls.is_loaded = True
|
||||
cls.data["references"] = cls.references()
|
||||
cls.data["active_classification_library"] = cls.active_classification_library()
|
||||
cls.data["classifications"] = cls.classifications()
|
||||
cls.data["object_type"] = "COST"
|
||||
|
||||
@classmethod
|
||||
def references(cls):
|
||||
|
||||
@@ -54,6 +54,120 @@ class AddClassification(bpy.types.Operator, tool.Ifc.Operator):
|
||||
)
|
||||
|
||||
|
||||
class AddManualClassification(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.add_manual_classification"
|
||||
bl_label = "Add Manual Classification"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
props = context.scene.BIMClassificationProperties
|
||||
attributes = blenderbim.bim.helper.export_attributes(props.classification_attributes)
|
||||
classification = ifcopenshell.api.run(
|
||||
"classification.add_classification", tool.Ifc.get(), classification="Unnamed"
|
||||
)
|
||||
ifcopenshell.api.run(
|
||||
"classification.edit_classification", tool.Ifc.get(), classification=classification, attributes=attributes
|
||||
)
|
||||
props.is_adding = False
|
||||
|
||||
|
||||
class AddManualClassificationReference(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.add_manual_classification_reference"
|
||||
bl_label = "Add Manual Classification Reference"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
obj_type: bpy.props.StringProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
obj = context.active_object
|
||||
props = obj.BIMClassificationReferenceProperties
|
||||
attributes = blenderbim.bim.helper.export_attributes(props.reference_attributes)
|
||||
product = tool.Ifc.get_entity(obj)
|
||||
# TODO: refactor and support material and cost item classifications
|
||||
classification = tool.Ifc.get().by_id(int(props.classifications))
|
||||
reference = ifcopenshell.api.run(
|
||||
"classification.add_reference",
|
||||
tool.Ifc.get(),
|
||||
product=product,
|
||||
classification=classification,
|
||||
identification="X",
|
||||
name="Unnamed",
|
||||
)
|
||||
ifcopenshell.api.run(
|
||||
"classification.edit_reference", tool.Ifc.get(), reference=reference, attributes=attributes
|
||||
)
|
||||
props.is_adding = False
|
||||
|
||||
|
||||
class AddClassificationFromBSDD(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.add_classification_from_bsdd"
|
||||
bl_label = "Add Classification From bSDD"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def _execute(self, context):
|
||||
props = context.scene.BIMBSDDProperties
|
||||
domain = [d for d in props.domains if d.name == props.active_domain][0]
|
||||
for element in tool.Ifc.get().by_type("IfcClassification"):
|
||||
if element.Name == props.active_domain or element.Location == domain.uri:
|
||||
return
|
||||
classification = ifcopenshell.api.run(
|
||||
"classification.add_classification", tool.Ifc.get(), classification=props.active_domain
|
||||
)
|
||||
classification.Source = domain.organization_name_owner
|
||||
classification.Location = domain.uri
|
||||
classification.Edition = domain.version
|
||||
|
||||
|
||||
class EnableAddingManualClassification(bpy.types.Operator):
|
||||
bl_idname = "bim.enable_adding_manual_classification"
|
||||
bl_label = "Enable Adding Manual Classification"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMClassificationProperties
|
||||
props.is_adding = True
|
||||
props.active_classification_id = 0
|
||||
props.classification_attributes.clear()
|
||||
blenderbim.bim.helper.import_attributes2("IfcClassification", props.classification_attributes)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class DisableAddingManualClassification(bpy.types.Operator):
|
||||
bl_idname = "bim.disable_adding_manual_classification"
|
||||
bl_label = "Disable Adding Manual Classification"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMClassificationProperties
|
||||
props.is_adding = False
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class EnableAddingManualClassificationReference(bpy.types.Operator):
|
||||
bl_idname = "bim.enable_adding_manual_classification_reference"
|
||||
bl_label = "Enable Adding Manual Classification Reference"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
obj = context.active_object
|
||||
props = obj.BIMClassificationReferenceProperties
|
||||
props.is_adding = True
|
||||
props.reference_attributes.clear()
|
||||
blenderbim.bim.helper.import_attributes2("IfcClassificationReference", props.reference_attributes)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class DisableAddingManualClassificationReference(bpy.types.Operator):
|
||||
bl_idname = "bim.disable_adding_manual_classification_reference"
|
||||
bl_label = "Disable Adding Manual Classification Reference"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
def execute(self, context):
|
||||
obj = context.active_object
|
||||
props = obj.BIMClassificationReferenceProperties
|
||||
props.is_adding = False
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class EnableEditingClassification(bpy.types.Operator):
|
||||
bl_idname = "bim.enable_editing_classification"
|
||||
bl_label = "Enable Editing Classification"
|
||||
@@ -175,21 +289,23 @@ class RemoveClassificationReference(bpy.types.Operator, tool.Ifc.Operator):
|
||||
else:
|
||||
objects = [self.obj]
|
||||
|
||||
identification = tool.Ifc.get().by_id(self.reference)[0]
|
||||
active_reference = tool.Ifc.get().by_id(self.reference)
|
||||
identification = active_reference[1]
|
||||
|
||||
for obj in objects:
|
||||
ifc_definition_id = blenderbim.bim.helper.get_obj_ifc_definition_id(context, obj, self.obj_type)
|
||||
element = tool.Ifc.get().by_id(ifc_definition_id)
|
||||
references = ifcopenshell.util.classification.get_references(element, should_inherit=False)
|
||||
for reference in references:
|
||||
if reference[0] == identification:
|
||||
if (identification and reference[1] == identification) or (
|
||||
not identification and reference == active_reference
|
||||
):
|
||||
ifcopenshell.api.run(
|
||||
"classification.remove_reference",
|
||||
tool.Ifc.get(),
|
||||
reference=reference,
|
||||
product=element,
|
||||
)
|
||||
break
|
||||
|
||||
|
||||
class EditClassificationReference(bpy.types.Operator, tool.Ifc.Operator):
|
||||
@@ -254,6 +370,85 @@ class AddClassificationReference(bpy.types.Operator, tool.Ifc.Operator):
|
||||
)
|
||||
|
||||
|
||||
class AddClassificationReferenceFromBSDD(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.add_classification_reference_from_bsdd"
|
||||
bl_label = "Add Classification Reference From bSDD"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
obj: bpy.props.StringProperty()
|
||||
obj_type: bpy.props.StringProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
if self.obj_type == "Object":
|
||||
if context.selected_objects:
|
||||
objects = [o.name for o in context.selected_objects]
|
||||
else:
|
||||
objects = [context.active_object.name]
|
||||
else:
|
||||
objects = [self.obj]
|
||||
props = context.scene.BIMClassificationProperties
|
||||
bprops = context.scene.BIMBSDDProperties
|
||||
|
||||
bsdd_classification = bprops.classifications[bprops.active_classification_index]
|
||||
|
||||
classification = None
|
||||
for element in tool.Ifc.get().by_type("IfcClassification"):
|
||||
if (
|
||||
element.Name == bsdd_classification.domain_name
|
||||
or element.Location == bsdd_classification.domain_namespace_uri
|
||||
):
|
||||
classification = element
|
||||
break
|
||||
|
||||
if not classification:
|
||||
classification = ifcopenshell.api.run(
|
||||
"classification.add_classification", tool.Ifc.get(), classification=bsdd_classification.domain_name
|
||||
)
|
||||
classification.Location = bsdd_classification.domain_namespace_uri
|
||||
|
||||
for obj in objects:
|
||||
ifc_definition_id = blenderbim.bim.helper.get_obj_ifc_definition_id(context, obj, self.obj_type)
|
||||
if not ifc_definition_id:
|
||||
continue
|
||||
element = tool.Ifc.get().by_id(ifc_definition_id)
|
||||
reference = ifcopenshell.api.run(
|
||||
"classification.add_reference",
|
||||
tool.Ifc.get(),
|
||||
product=element,
|
||||
classification=classification,
|
||||
identification=bsdd_classification.reference_code,
|
||||
name=bsdd_classification.name,
|
||||
)
|
||||
reference.Location = bsdd_classification.uri
|
||||
|
||||
for classification_pset in bprops.classification_psets:
|
||||
is_pset = not classification_pset.name.startswith("Qto_")
|
||||
|
||||
if is_pset:
|
||||
pset = ifcopenshell.util.element.get_pset(element, classification_pset.name, psets_only=True)
|
||||
else:
|
||||
pset = ifcopenshell.util.element.get_pset(element, classification_pset.name, qtos_only=True)
|
||||
|
||||
if pset:
|
||||
pset = tool.Ifc.get().by_id(pset["id"])
|
||||
elif is_pset:
|
||||
pset = ifcopenshell.api.run(
|
||||
"pset.add_pset", tool.Ifc.get(), product=element, name=classification_pset.name
|
||||
)
|
||||
else:
|
||||
pset = ifcopenshell.api.run(
|
||||
"pset.add_qto", tool.Ifc.get(), product=element, name=classification_pset.name
|
||||
)
|
||||
|
||||
properties = {}
|
||||
for prop in classification_pset.properties:
|
||||
properties[prop.name] = prop.get_value()
|
||||
|
||||
if is_pset:
|
||||
ifcopenshell.api.run("pset.edit_pset", tool.Ifc.get(), pset=pset, properties=properties)
|
||||
else:
|
||||
ifcopenshell.api.run("pset.edit_qto", tool.Ifc.get(), qto=pset, properties=properties)
|
||||
|
||||
|
||||
class ChangeClassificationLevel(bpy.types.Operator):
|
||||
bl_idname = "bim.change_classification_level"
|
||||
bl_label = "Change Classification Level"
|
||||
|
||||
@@ -17,9 +17,10 @@
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
import blenderbim.bim.helper
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from blenderbim.bim.prop import StrProperty, Attribute
|
||||
from blenderbim.bim.module.classification.data import ClassificationsData
|
||||
from blenderbim.bim.module.classification.data import ClassificationsData, ClassificationReferencesData
|
||||
from bpy.types import PropertyGroup
|
||||
from bpy.props import (
|
||||
PointerProperty,
|
||||
@@ -39,6 +40,12 @@ def get_available_classifications(self, context):
|
||||
return ClassificationsData.data["available_classifications"]
|
||||
|
||||
|
||||
def get_classifications(self, context):
|
||||
if not ClassificationReferencesData.is_loaded:
|
||||
ClassificationReferencesData.load()
|
||||
return ClassificationReferencesData.data["classifications"]
|
||||
|
||||
|
||||
class ClassificationReference(PropertyGroup):
|
||||
name: StringProperty(name="Name")
|
||||
identification: StringProperty(name="Identification")
|
||||
@@ -48,6 +55,16 @@ class ClassificationReference(PropertyGroup):
|
||||
|
||||
|
||||
class BIMClassificationProperties(PropertyGroup):
|
||||
is_adding: BoolProperty(name="Is Adding", default=False)
|
||||
classification_source: EnumProperty(
|
||||
items=[
|
||||
("FILE", "IFC File", ""),
|
||||
("BSDD", "buildingSMART Data Dictionary", ""),
|
||||
("MANUAL", "Manual Entry", ""),
|
||||
],
|
||||
name="Classification Source",
|
||||
default="FILE",
|
||||
)
|
||||
available_classifications: EnumProperty(items=get_available_classifications, name="Available Classifications")
|
||||
classification_attributes: CollectionProperty(name="Classification Attributes", type=Attribute)
|
||||
active_classification_id: IntProperty(name="Active Classification Id")
|
||||
@@ -57,5 +74,7 @@ class BIMClassificationProperties(PropertyGroup):
|
||||
|
||||
|
||||
class BIMClassificationReferenceProperties(PropertyGroup):
|
||||
is_adding: BoolProperty(name="Is Adding", default=False)
|
||||
classifications: EnumProperty(items=get_classifications, name="Classifications")
|
||||
reference_attributes: CollectionProperty(name="Reference Attributes", type=Attribute)
|
||||
active_reference_id: IntProperty(name="Active Reference Id")
|
||||
|
||||
@@ -36,7 +36,7 @@ class BIM_PT_classifications(Panel):
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_project_setup"
|
||||
bl_parent_id = "BIM_PT_tab_project_setup"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
@@ -48,6 +48,48 @@ class BIM_PT_classifications(Panel):
|
||||
|
||||
self.props = context.scene.BIMClassificationProperties
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text="Source", icon="OUTLINER")
|
||||
row.prop(self.props, "classification_source", text="")
|
||||
|
||||
if self.props.classification_source == "FILE":
|
||||
self.draw_add_file_ui(context)
|
||||
elif self.props.classification_source == "BSDD":
|
||||
self.draw_add_bsdd_ui(context)
|
||||
elif self.props.classification_source == "MANUAL":
|
||||
self.draw_add_manual_ui(context)
|
||||
|
||||
for classification in ClassificationsData.data["classifications"]:
|
||||
if self.props.active_classification_id == classification["id"]:
|
||||
self.draw_editable_ui()
|
||||
else:
|
||||
self.draw_ui(classification)
|
||||
|
||||
def draw_add_manual_ui(self, context):
|
||||
if self.props.is_adding:
|
||||
blenderbim.bim.helper.draw_attributes(self.props.classification_attributes, self.layout)
|
||||
row = self.layout.row(align=True)
|
||||
row.operator("bim.add_manual_classification", text="Save", icon="CHECKMARK")
|
||||
row.operator("bim.disable_adding_manual_classification", text="", icon="CANCEL")
|
||||
else:
|
||||
row = self.layout.row()
|
||||
row.operator("bim.enable_adding_manual_classification", text="Add Classification", icon="ADD")
|
||||
|
||||
def draw_add_bsdd_ui(self, context):
|
||||
self.bprops = context.scene.BIMBSDDProperties
|
||||
|
||||
if not self.bprops.active_domain:
|
||||
row = self.layout.row()
|
||||
row.label(text="No Active bSDD Domain", icon="ERROR")
|
||||
return
|
||||
|
||||
row = self.layout.row()
|
||||
row.label(text="Active: " + self.bprops.active_domain, icon="URL")
|
||||
|
||||
row = self.layout.row()
|
||||
row.operator("bim.add_classification_from_bsdd", icon="ADD")
|
||||
|
||||
def draw_add_file_ui(self, context):
|
||||
if ClassificationsData.data["has_classification_file"]:
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(self.props, "available_classifications", text="")
|
||||
@@ -58,12 +100,6 @@ class BIM_PT_classifications(Panel):
|
||||
row.label(text="No Active Classification Library")
|
||||
row.operator("bim.load_classification_library", text="", icon="IMPORT")
|
||||
|
||||
for classification in ClassificationsData.data["classifications"]:
|
||||
if self.props.active_classification_id == classification["id"]:
|
||||
self.draw_editable_ui()
|
||||
else:
|
||||
self.draw_ui(classification)
|
||||
|
||||
def draw_editable_ui(self):
|
||||
row = self.layout.row(align=True)
|
||||
row.operator("bim.edit_classification", text="Save changes", icon="CHECKMARK")
|
||||
@@ -84,6 +120,7 @@ class ReferenceUI:
|
||||
obj = context.active_object
|
||||
self.oprops = obj.BIMObjectProperties
|
||||
self.sprops = context.scene.BIMClassificationProperties
|
||||
self.bprops = context.scene.BIMBSDDProperties
|
||||
self.props = obj.BIMClassificationReferenceProperties
|
||||
self.file = IfcStore.get_file()
|
||||
|
||||
@@ -100,14 +137,85 @@ class ReferenceUI:
|
||||
self.draw_reference_ui(reference)
|
||||
|
||||
def draw_add_ui(self, context):
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text="Source", icon="OUTLINER")
|
||||
row.prop(self.sprops, "classification_source", text="")
|
||||
|
||||
if self.sprops.classification_source == "FILE":
|
||||
self.draw_add_file_ui(context)
|
||||
elif self.sprops.classification_source == "BSDD":
|
||||
self.draw_add_bsdd_ui(context)
|
||||
elif self.sprops.classification_source == "MANUAL":
|
||||
self.draw_add_manual_ui(context)
|
||||
|
||||
def draw_add_manual_ui(self, context):
|
||||
row = self.layout.row()
|
||||
row.prop(self.props, "classifications", text="")
|
||||
if self.props.is_adding:
|
||||
blenderbim.bim.helper.draw_attributes(self.props.reference_attributes, self.layout)
|
||||
row = self.layout.row(align=True)
|
||||
op = row.operator("bim.add_manual_classification_reference", text="Save", icon="CHECKMARK")
|
||||
op.type = self.data.data["object_type"]
|
||||
row.operator("bim.disable_adding_manual_classification_reference", text="", icon="CANCEL")
|
||||
else:
|
||||
row = self.layout.row()
|
||||
row.operator("bim.enable_adding_manual_classification_reference", text="Add Reference", icon="ADD")
|
||||
|
||||
def draw_add_bsdd_ui(self, context):
|
||||
if not self.bprops.active_domain:
|
||||
row = self.layout.row()
|
||||
row.label(text="No Active bSDD Domain", icon="ERROR")
|
||||
return
|
||||
|
||||
row = self.layout.row()
|
||||
row.label(text="Active: " + self.bprops.active_domain, icon="URL")
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(self.bprops, "keyword", text="")
|
||||
row.operator("bim.search_bsdd_classifications", text="", icon="VIEWZOOM")
|
||||
|
||||
row = self.layout.row()
|
||||
row.prop(self.bprops, "should_filter_ifc_class")
|
||||
|
||||
if len(self.bprops.classifications):
|
||||
self.layout.template_list(
|
||||
"BIM_UL_bsdd_classifications",
|
||||
"",
|
||||
self.bprops,
|
||||
"classifications",
|
||||
self.bprops,
|
||||
"active_classification_index",
|
||||
)
|
||||
else:
|
||||
row = self.layout.row()
|
||||
row.label(text="No Search Results")
|
||||
|
||||
if self.bprops.active_classification_index < len(self.bprops.classifications):
|
||||
row = self.layout.row(align=True)
|
||||
op = row.operator(
|
||||
"bim.add_classification_reference_from_bsdd", text="Add Classification Reference", icon="ADD"
|
||||
)
|
||||
op.obj = self.obj
|
||||
op.obj_type = self.obj_type
|
||||
row.operator("bim.get_bsdd_classification_properties", text="", icon="COPY_ID")
|
||||
|
||||
if len(self.bprops.classification_psets):
|
||||
for pset in self.bprops.classification_psets:
|
||||
box = self.layout.box()
|
||||
row = box.row()
|
||||
row.label(text=pset.name, icon="COPY_ID")
|
||||
blenderbim.bim.helper.draw_attributes(pset.properties, box)
|
||||
|
||||
def draw_add_file_ui(self, context):
|
||||
if not self.data.data["active_classification_library"]:
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text="No Active Classification Library")
|
||||
row.label(text="No Active Classification Library", icon="ERROR")
|
||||
row.operator("bim.load_classification_library", text="", icon="IMPORT")
|
||||
return
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text=f"Active Classification Library: {self.data.data['active_classification_library']}")
|
||||
#row.prop(self.sprops, "available_classifications", text="")
|
||||
# row.prop(self.sprops, "available_classifications", text="")
|
||||
if not self.sprops.available_library_references:
|
||||
op = row.operator("bim.change_classification_level", text="", icon="GREASEPENCIL")
|
||||
op.parent_id = int(self.sprops.available_classifications)
|
||||
@@ -146,6 +254,8 @@ class ReferenceUI:
|
||||
name = reference["Identification"] or "No Identification"
|
||||
row.label(text=name, icon="ASSET_MANAGER")
|
||||
row.label(text=reference["Name"] or "")
|
||||
if reference["Location"]:
|
||||
row.operator("bim.open_uri", icon="URL", text="").uri = reference["Location"]
|
||||
if not self.props.active_reference_id:
|
||||
op = row.operator("bim.enable_editing_classification_reference", text="", icon="GREASEPENCIL")
|
||||
op.reference = reference["id"]
|
||||
|
||||
@@ -1,124 +0,0 @@
|
||||
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
||||
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of BlenderBIM Add-on.
|
||||
#
|
||||
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# BlenderBIM Add-on is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
import os
|
||||
import logging
|
||||
import ifcopenshell
|
||||
import json
|
||||
import webbrowser
|
||||
import tempfile
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
|
||||
|
||||
class SelectCobieIfcFile(bpy.types.Operator):
|
||||
bl_idname = "bim.select_cobie_ifc_file"
|
||||
bl_label = "Select COBie IFC File"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||
|
||||
def execute(self, context):
|
||||
context.scene.COBieProperties.cobie_ifc_file = self.filepath
|
||||
return {"FINISHED"}
|
||||
|
||||
def invoke(self, context, event):
|
||||
context.window_manager.fileselect_add(self)
|
||||
return {"RUNNING_MODAL"}
|
||||
|
||||
|
||||
class SelectCobieJsonFile(bpy.types.Operator):
|
||||
bl_idname = "bim.select_cobie_json_file"
|
||||
bl_label = "Select COBie JSON File"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||
|
||||
def execute(self, context):
|
||||
context.scene.COBieProperties.cobie_json_file = self.filepath
|
||||
return {"FINISHED"}
|
||||
|
||||
def invoke(self, context, event):
|
||||
context.window_manager.fileselect_add(self)
|
||||
return {"RUNNING_MODAL"}
|
||||
|
||||
|
||||
class ExecuteIfcCobie(bpy.types.Operator):
|
||||
bl_idname = "bim.execute_ifc_cobie"
|
||||
bl_label = "Execute IFCCOBie"
|
||||
file_format: bpy.props.StringProperty()
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
props = context.scene.COBieProperties
|
||||
return props.should_load_from_memory or props.cobie_ifc_file
|
||||
|
||||
def execute(self, context):
|
||||
from cobie import IfcCobieParser
|
||||
|
||||
props = context.scene.COBieProperties
|
||||
|
||||
if props.should_load_from_memory:
|
||||
output_dir = tempfile.gettempdir()
|
||||
else:
|
||||
output_dir = os.path.dirname(props.cobie_ifc_file)
|
||||
|
||||
output = os.path.join(output_dir, "output")
|
||||
logger = logging.getLogger("IFCtoCOBie")
|
||||
fh = logging.FileHandler(os.path.join(output_dir, "cobie.log"))
|
||||
fh.setLevel(logging.DEBUG)
|
||||
fh.setFormatter(logging.Formatter("%(asctime)s : %(levelname)s : %(message)s"))
|
||||
logger = logging.getLogger("IFCtoCOBie")
|
||||
logger.addHandler(fh)
|
||||
selector = ifcopenshell.util.selector.Selector()
|
||||
if props.cobie_json_file:
|
||||
with open(props.cobie_json_file, "r") as f:
|
||||
custom_data = json.load(f)
|
||||
else:
|
||||
custom_data = {}
|
||||
parser = IfcCobieParser(logger, selector)
|
||||
|
||||
ifc_file = IfcStore.get_file()
|
||||
|
||||
if not (ifc_file and props.should_load_from_memory):
|
||||
ifc_file = props.cobie_ifc_file
|
||||
|
||||
parser.parse(
|
||||
ifc_file,
|
||||
props.cobie_types,
|
||||
props.cobie_components,
|
||||
custom_data,
|
||||
)
|
||||
if self.file_format == "xlsx":
|
||||
from cobie import CobieXlsWriter
|
||||
|
||||
writer = CobieXlsWriter(parser, output)
|
||||
writer.write()
|
||||
webbrowser.open("file://" + output + "." + self.file_format)
|
||||
elif self.file_format == "ods":
|
||||
from cobie import CobieOdsWriter
|
||||
|
||||
writer = CobieOdsWriter(parser, output)
|
||||
writer.write()
|
||||
webbrowser.open("file://" + output + "." + self.file_format)
|
||||
else:
|
||||
from cobie import CobieCsvWriter
|
||||
|
||||
writer = CobieCsvWriter(parser, output_dir)
|
||||
writer.write()
|
||||
webbrowser.open("file://" + output_dir)
|
||||
webbrowser.open("file://" + output_dir + "/cobie.log")
|
||||
return {"FINISHED"}
|
||||
@@ -29,7 +29,7 @@ class BIM_PT_constraints(Panel):
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_project_setup"
|
||||
bl_parent_id = "BIM_PT_tab_project_setup"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
|
||||
@@ -29,7 +29,7 @@ class BIM_PT_context(bpy.types.Panel):
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_geometry"
|
||||
bl_parent_id = "BIM_PT_tab_geometry"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
|
||||
@@ -136,13 +136,11 @@ class CostSchedulesData:
|
||||
data["UnitBasisUnitSymbol"] = "U"
|
||||
if cost_value.Category == "*":
|
||||
is_sum = True
|
||||
cost_quantity = data["TotalCostQuantity"] or 1
|
||||
if has_unit_basis:
|
||||
data["TotalCost"] = data["TotalAppliedValue"] / data["UnitBasisValueComponent"]
|
||||
data["TotalCost"] = data["TotalAppliedValue"] * cost_quantity / data["UnitBasisValueComponent"]
|
||||
else:
|
||||
if data["TotalCostQuantity"] is not None:
|
||||
data["TotalCost"] = data["TotalAppliedValue"] * data["TotalCostQuantity"]
|
||||
else:
|
||||
data["TotalCost"] = data["TotalAppliedValue"]
|
||||
data["TotalCost"] = data["TotalAppliedValue"] * cost_quantity
|
||||
if is_sum:
|
||||
data["TotalAppliedValue"] = None
|
||||
|
||||
@@ -160,8 +158,10 @@ class CostSchedulesData:
|
||||
unit = ifcopenshell.util.unit.get_property_unit(quantity, tool.Ifc.get())
|
||||
if unit:
|
||||
data["UnitSymbol"] = ifcopenshell.util.unit.get_unit_symbol(unit)
|
||||
else:
|
||||
data["UnitSymbol"] = "U"
|
||||
if quantity.is_a("IfcPhysicalSimpleQuantity"):
|
||||
measure_class = quantity.wrapped_data.declaration().as_entity().attribute_by_index(3).type_of_attribute().declared_type().name()
|
||||
if "Count" in measure_class:
|
||||
data["UnitSymbol"] = "U"
|
||||
|
||||
# same_unit_nested_cost_item = set()
|
||||
# data["DerivedTotalCostQuantity"] = None
|
||||
@@ -256,7 +256,7 @@ class CostSchedulesData:
|
||||
for cost_value in cost_item.CostValues or []:
|
||||
label = "{0:.2f}".format(ifcopenshell.util.cost.calculate_applied_value(cost_item, cost_value))
|
||||
label += " = {}".format(ifcopenshell.util.cost.serialise_cost_value(cost_value))
|
||||
results.append({"id": cost_value.id(), "label": label})
|
||||
results.append({"id": cost_value.id(), "label": label, "name": cost_value.Name})
|
||||
return results
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -37,12 +37,10 @@ class AddCostSchedule(bpy.types.Operator, tool.Ifc.Operator):
|
||||
object_type: bpy.props.StringProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
core.add_cost_schedule(
|
||||
tool.Ifc,
|
||||
name=self.name,
|
||||
predefined_type=context.scene.BIMCostProperties.cost_schedule_predefined_types,
|
||||
object_type=self.object_type,
|
||||
)
|
||||
predefined_type = context.scene.BIMCostProperties.cost_schedule_predefined_types
|
||||
if predefined_type == "USERDEFINED":
|
||||
predefined_type = self.object_type
|
||||
core.add_cost_schedule(tool.Ifc, name=self.name, predefined_type=predefined_type)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
@@ -42,19 +42,21 @@ class BIM_PT_cost_schedules(Panel):
|
||||
CostSchedulesData.load()
|
||||
|
||||
self.props = context.scene.BIMCostProperties
|
||||
row = self.layout.row(align=True)
|
||||
if not self.props.active_cost_schedule_id:
|
||||
row = self.layout.row(align=True)
|
||||
if CostSchedulesData.data["total_cost_schedules"]:
|
||||
row.alignment = "RIGHT"
|
||||
row.operator("bim.export_cost_schedules",icon="EXPORT",text="Export All Schedules")
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text=f"{CostSchedulesData.data['total_cost_schedules']} Cost Schedules Found", icon="TEXT")
|
||||
else:
|
||||
row.label(text="No Cost Schedules found.", icon="TEXT")
|
||||
|
||||
row.operator("bim.add_cost_schedule", icon="ADD", text="")
|
||||
row.operator("import_cost_schedule_csv.bim",icon="IMPORT",text="")
|
||||
|
||||
for schedule in CostSchedulesData.data["schedules"]:
|
||||
self.draw_cost_schedule_ui(schedule)
|
||||
row2 = self.layout.row()
|
||||
row2.alignment = "RIGHT"
|
||||
row2.operator("bim.export_cost_schedules", text="Export all", icon="EXPORT")
|
||||
|
||||
def draw_cost_schedule_ui(self, cost_schedule):
|
||||
row = self.layout.row(align=True)
|
||||
@@ -236,6 +238,8 @@ class BIM_PT_cost_schedules(Panel):
|
||||
blenderbim.bim.helper.draw_attributes(self.props.cost_value_attributes, self.layout.box())
|
||||
|
||||
def draw_readonly_cost_value_ui(self, layout, cost_value):
|
||||
if cost_value["name"]:
|
||||
layout.label(text=f"{cost_value['name']}: ")
|
||||
if self.props.active_cost_value_id == cost_value["id"] and self.props.cost_value_editing_type == "FORMULA":
|
||||
layout.prop(self.props, "cost_value_formula", text="")
|
||||
else:
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
||||
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of BlenderBIM Add-on.
|
||||
#
|
||||
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# BlenderBIM Add-on is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
from . import prop, workspace
|
||||
|
||||
classes = (
|
||||
prop.BIMCoveringProperties,
|
||||
workspace.Hotkey,
|
||||
)
|
||||
|
||||
|
||||
def register():
|
||||
if not bpy.app.background:
|
||||
bpy.utils.register_tool(workspace.CoveringTool, after={"bim.structural_tool"}, separator=False, group=False)
|
||||
bpy.types.Scene.BIMCoveringProperties = bpy.props.PointerProperty(type=prop.BIMCoveringProperties)
|
||||
# bpy.types.Object.BIMObjectSpatialProperties = bpy.props.PointerProperty(type=prop.BIMObjectSpatialProperties)
|
||||
# bpy.types.Scene.BIMSpatialManagerProperties = bpy.props.PointerProperty(type=prop.BIMSpatialManagerProperties)
|
||||
|
||||
|
||||
def unregister():
|
||||
if not bpy.app.background:
|
||||
bpy.utils.unregister_tool(workspace.CoveringTool)
|
||||
del bpy.types.Scene.BIMCoveringProperties
|
||||
# del bpy.types.Object.BIMObjectSpatialProperties
|
||||
# del bpy.types.Scene.BIMSpatialManagerProperties
|
||||
Binary file not shown.
+6
-11
@@ -17,8 +17,8 @@
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
from blenderbim.bim.module.lca.data import LcaData
|
||||
from blenderbim.bim.prop import StrProperty, Attribute
|
||||
#from blenderbim.bim.module.spatial.data import SpatialData
|
||||
from bpy.types import PropertyGroup
|
||||
from bpy.props import (
|
||||
PointerProperty,
|
||||
@@ -30,15 +30,10 @@ from bpy.props import (
|
||||
FloatVectorProperty,
|
||||
CollectionProperty,
|
||||
)
|
||||
#import blenderbim.tool as tool
|
||||
#import blenderbim.core.geometry
|
||||
#import ifcopenshell
|
||||
|
||||
|
||||
def get_product_systems(self, context):
|
||||
if not LcaData.is_loaded:
|
||||
LcaData.load()
|
||||
return LcaData.data["product_systems"]
|
||||
|
||||
|
||||
class BIMLCAProperties(PropertyGroup):
|
||||
is_connected: BoolProperty(name="Is Connected")
|
||||
amount: FloatProperty(name="Amount")
|
||||
product_systems: EnumProperty(items=get_product_systems, name="Product Systems")
|
||||
class BIMCoveringProperties(PropertyGroup):
|
||||
ceiling_height: bpy.props.FloatProperty(name="ceiling_height", default=2.7, subtype="DISTANCE", description="Ceiling height")
|
||||
@@ -0,0 +1,272 @@
|
||||
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
||||
# Copyright (C) 2023 @Andrej730
|
||||
#
|
||||
# This file is part of BlenderBIM Add-on.
|
||||
#
|
||||
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# BlenderBIM Add-on is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
|
||||
import os
|
||||
import bpy
|
||||
import ifcopenshell
|
||||
import blenderbim.tool as tool
|
||||
from blenderbim.bim.helper import prop_with_search
|
||||
from blenderbim.bim.module.model.data import AuthoringData
|
||||
from bpy.types import WorkSpaceTool
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
import blenderbim.bim.handler
|
||||
|
||||
|
||||
# declaring it here to avoid circular import problems
|
||||
class Operator:
|
||||
def execute(self, context):
|
||||
IfcStore.execute_ifc_operator(self, context)
|
||||
blenderbim.bim.handler.refresh_ui_data()
|
||||
return {"FINISHED"}
|
||||
|
||||
class CoveringTool(WorkSpaceTool):
|
||||
bl_space_type = "VIEW_3D"
|
||||
bl_context_mode = "OBJECT"
|
||||
bl_idname = "bim.covering_tool"
|
||||
bl_label = "Covering Tool"
|
||||
bl_description = "Create and edit coverings"
|
||||
bl_icon = os.path.join(os.path.dirname(__file__), "ops.authoring.covering")
|
||||
bl_widget = None
|
||||
ifc_element_type = "IfcCoveringType"
|
||||
bl_keymap = tool.Blender.get_default_selection_keypmap() + (
|
||||
("bim.covering_hotkey", {"type": "A", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_A")]}),
|
||||
("bim.covering_hotkey", {"type": "G", "value": "PRESS", "shift": True}, {"properties": [("hotkey", "S_G")]}),
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def draw_settings(cls, context, layout, ws_tool):
|
||||
CoveringToolUI.draw(context, layout, ifc_element_type=cls.ifc_element_type)
|
||||
|
||||
def add_layout_hotkey(layout, text, hotkey, description):
|
||||
args = ["covering", layout, text, hotkey, description]
|
||||
tool.Blender.add_layout_hotkey_operator(*args)
|
||||
|
||||
class CoveringToolUI:
|
||||
@classmethod
|
||||
def draw(cls, context, layout, ifc_element_type = None):
|
||||
cls.layout = layout
|
||||
cls.props = context.scene.BIMModelProperties
|
||||
cls.covering_props = context.scene.BIMCoveringProperties
|
||||
|
||||
|
||||
row = cls.layout.row(align=True)
|
||||
if not tool.Ifc.get():
|
||||
row.label(text="No IFC Project", icon="ERROR")
|
||||
return
|
||||
|
||||
if not AuthoringData.is_loaded:
|
||||
AuthoringData.load(ifc_element_type)
|
||||
elif AuthoringData.data["ifc_element_type"] != ifc_element_type:
|
||||
AuthoringData.load(ifc_element_type)
|
||||
|
||||
if context.region.type == "TOOL_HEADER":
|
||||
cls.draw_header_interface()
|
||||
elif context.region.type in ("UI", "WINDOW"):
|
||||
cls.draw_basic_bim_tool_interface()
|
||||
|
||||
cls.draw_default_interface()
|
||||
|
||||
|
||||
|
||||
@classmethod
|
||||
def draw_header_interface(cls):
|
||||
cls.draw_type_selection_interface()
|
||||
|
||||
@classmethod
|
||||
def draw_default_interface(cls):
|
||||
row = cls.layout.row(align=True)
|
||||
row.prop(data=cls.props, property="rl3", text="RL")
|
||||
row = cls.layout.row(align=True)
|
||||
row.prop(data=cls.covering_props, property="ceiling_height", text="Ceiling Height")
|
||||
if AuthoringData.data["ifc_classes"]:
|
||||
active_obj = bpy.context.active_object
|
||||
element = tool.Ifc.get_entity(active_obj)
|
||||
collection = bpy.context.view_layer.active_layer_collection.collection
|
||||
collection_obj = collection.BIMCollectionProperties.obj
|
||||
|
||||
relating_type_id = int(cls.props.relating_type_id)
|
||||
type_material_usage = ifcopenshell.util.element.get_material(tool.Ifc.get().by_id(relating_type_id)).is_a()
|
||||
|
||||
# PLEASE KEEP COMMENTS AS A REMINDER
|
||||
# elif element and bpy.context.selected_objects and element.is_a("IfcSpace"):
|
||||
# op. = row.operator("bim.add_istance_flooring_from_spaces"):
|
||||
|
||||
if (type_material_usage == "IfcMaterialLayerSet" and
|
||||
not bpy.context.selected_objects):
|
||||
row = cls.layout.row(align=True)
|
||||
row.label(text="", icon="EVENT_SHIFT")
|
||||
row.label(text="", icon="EVENT_A")
|
||||
if tool.Ifc.get_entity(collection_obj):
|
||||
if AuthoringData.data["predefined_type"] == "FLOORING":
|
||||
op = row.operator("bim.add_instance_flooring_covering_from_cursor")
|
||||
elif AuthoringData.data["predefined_type"] == "CEILING":
|
||||
op = row.operator("bim.add_instance_ceiling_covering_from_cursor")
|
||||
else:
|
||||
op = row.operator("bim.add_constr_type_instance", text="Add")
|
||||
op.from_invoke = True
|
||||
if cls.props.relating_type_id.isnumeric():
|
||||
op.relating_type_id = int(cls.props.relating_type_id)
|
||||
|
||||
else:
|
||||
op = row.operator("bim.add_constr_type_instance", text="Add")
|
||||
op.from_invoke = True
|
||||
if cls.props.relating_type_id.isnumeric():
|
||||
op.relating_type_id = int(cls.props.relating_type_id)
|
||||
|
||||
elif (AuthoringData.data["predefined_type"] == "FLOORING" and
|
||||
type_material_usage == "IfcMaterialLayerSet" and
|
||||
element and
|
||||
bpy.context.selected_objects and
|
||||
element.is_a("IfcWall")):
|
||||
row = cls.layout.row(align=True)
|
||||
row.label(text="", icon="EVENT_SHIFT")
|
||||
row.label(text="", icon="EVENT_A")
|
||||
op = row.operator("bim.add_instance_flooring_coverings_from_walls")
|
||||
|
||||
elif (AuthoringData.data["predefined_type"] == "CEILING" and
|
||||
type_material_usage == "IfcMaterialLayerSet" and
|
||||
element and
|
||||
bpy.context.selected_objects and
|
||||
element.is_a("IfcWall")):
|
||||
row = cls.layout.row(align=True)
|
||||
row.label(text="", icon="EVENT_SHIFT")
|
||||
row.label(text="", icon="EVENT_A")
|
||||
op = row.operator("bim.add_instance_ceiling_coverings_from_walls")
|
||||
|
||||
elif (element and
|
||||
bpy.context.selected_objects and
|
||||
element.is_a("IfcCovering") and
|
||||
# AuthoringData.data["predefined_type"] == "FLOORING" and
|
||||
AuthoringData.data["active_material_usage"] == "LAYER3"):
|
||||
row = cls.layout.row(align=True)
|
||||
row.label(text="", icon="EVENT_SHIFT")
|
||||
row.label(text="", icon="EVENT_G")
|
||||
op = row.operator("bim.regen_selected_covering_object")
|
||||
|
||||
|
||||
|
||||
# elif AuthoringData.data["predefined_type"] == "CEILING":
|
||||
# row = cls.layout.row(align=True)
|
||||
# row.prop(data=cls.props, property="ceiling_height", text="ceiling height")
|
||||
# if element and bpy.context.selected_objects and element.is_a("IfcWall"):
|
||||
# op = row.operator("bim.add_instance_ceiling_coverings_from_walls")
|
||||
# elif element and bpy.context.selected_objects and element.is_a("IfcSpace"):
|
||||
# op. = row.operator("bim.add_istance_flooring_from_spaces"):
|
||||
# else:
|
||||
# op = row.operator("bim.add_instance_ceiling_from_cursor")
|
||||
# op = row.operator("bim.add_constr_type_instance", text="Add")
|
||||
# op.from_invoke = True
|
||||
# if cls.props.relating_type_id.isnumeric():
|
||||
# op.relating_type_id = int(cls.props.relating_type_id)
|
||||
else:
|
||||
row = cls.layout.row(align=True)
|
||||
row.label(text="", icon="EVENT_SHIFT")
|
||||
row.label(text="", icon="EVENT_A")
|
||||
op = row.operator("bim.add_constr_type_instance", text="Add")
|
||||
op.from_invoke = True
|
||||
if cls.props.relating_type_id.isnumeric():
|
||||
op.relating_type_id = int(cls.props.relating_type_id)
|
||||
|
||||
@classmethod
|
||||
def draw_type_selection_interface(cls):
|
||||
# shared by both sidebar and header
|
||||
row = cls.layout.row(align=True)
|
||||
if AuthoringData.data["ifc_classes"]:
|
||||
row = cls.layout.row(align=True)
|
||||
row.label(text="", icon="FILE_3D")
|
||||
prop_with_search(row, cls.props, "relating_type_id", text="")
|
||||
row.operator("bim.launch_type_manager", icon="LIGHTPROBE_GRID", text="")
|
||||
else:
|
||||
row.label(text=f"No {AuthoringData.data['ifc_element_type']} Found", icon="ERROR")
|
||||
row = cls.layout.row()
|
||||
row.operator("bim.launch_type_manager", icon="LIGHTPROBE_GRID", text="Launch Type Manager")
|
||||
|
||||
@classmethod
|
||||
def draw_basic_bim_tool_interface(cls):
|
||||
cls.draw_type_selection_interface()
|
||||
|
||||
if AuthoringData.data["ifc_classes"]:
|
||||
if cls.props.ifc_class:
|
||||
box = cls.layout.box()
|
||||
if AuthoringData.data["type_thumbnail"]:
|
||||
box.template_icon(icon_value=AuthoringData.data["type_thumbnail"], scale=5)
|
||||
else:
|
||||
op = box.operator("bim.load_type_thumbnails", text="Load Thumbnails", icon="FILE_REFRESH")
|
||||
op.ifc_class = cls.props.ifc_class
|
||||
|
||||
|
||||
class Hotkey(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.covering_hotkey"
|
||||
bl_label = "Hotkey"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
hotkey: bpy.props.StringProperty()
|
||||
description: bpy.props.StringProperty()
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return tool.Ifc.get()
|
||||
|
||||
@classmethod
|
||||
def description(cls, context, operator):
|
||||
return operator.description or ""
|
||||
|
||||
def _execute(self, context):
|
||||
# self.props = context.scene.BIMCoveringProperties
|
||||
getattr(self, f"hotkey_{self.hotkey}")()
|
||||
|
||||
def invoke(self, context, event):
|
||||
# https://blender.stackexchange.com/questions/276035/how-do-i-make-operators-remember-their-property-values-when-called-from-a-hotkey
|
||||
# self.props = context.scene.BIMSpatialProperties
|
||||
return self.execute(context)
|
||||
|
||||
def draw(self, context):
|
||||
pass
|
||||
|
||||
def hotkey_S_A(self):
|
||||
active_obj = bpy.context.active_object
|
||||
element = tool.Ifc.get_entity(active_obj)
|
||||
collection = bpy.context.view_layer.active_layer_collection.collection
|
||||
collection_obj = collection.BIMCollectionProperties.obj
|
||||
|
||||
if AuthoringData.data["predefined_type"] == "FLOORING":
|
||||
if element and bpy.context.selected_objects and element.is_a("IfcWall"):
|
||||
bpy.ops.bim.add_instance_flooring_coverings_from_walls()
|
||||
elif tool.Ifc.get_entity(collection_obj):
|
||||
bpy.ops.bim.add_instance_flooring_covering_from_cursor()
|
||||
else:
|
||||
bpy.ops.bim.add_constr_type_instance()
|
||||
elif AuthoringData.data["predefined_type"] == "CEILING":
|
||||
if element and bpy.context.selected_objects and element.is_a("IfcWall"):
|
||||
bpy.ops.bim.add_instance_ceiling_coverings_from_walls()
|
||||
elif tool.Ifc.get_entity(collection_obj):
|
||||
bpy.ops.bim.add_instance_ceiling_covering_from_cursor()
|
||||
else:
|
||||
bpy.ops.bim.add_constr_type_instance()
|
||||
else:
|
||||
bpy.ops.bim.add_constr_type_instance()
|
||||
|
||||
def hotkey_S_G(self):
|
||||
active_obj = bpy.context.active_object
|
||||
element = tool.Ifc.get_entity(active_obj)
|
||||
if (element and
|
||||
bpy.context.selected_objects and
|
||||
element.is_a("IfcCovering") and
|
||||
AuthoringData.data["active_material_usage"] == "LAYER3"):
|
||||
bpy.ops.bim.regen_selected_covering_object()
|
||||
|
||||
@@ -22,11 +22,11 @@ import json
|
||||
import ifccsv
|
||||
import logging
|
||||
import tempfile
|
||||
import webbrowser
|
||||
import ifcopenshell
|
||||
import blenderbim.tool as tool
|
||||
import blenderbim.bim.module.drawing.scheduler as scheduler
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from blenderbim.bim.handler import purge_module_data
|
||||
from blenderbim.bim.handler import refresh_ui_data
|
||||
|
||||
|
||||
class AddCsvAttribute(bpy.types.Operator):
|
||||
@@ -93,15 +93,26 @@ class ImportCsvAttributes(bpy.types.Operator):
|
||||
data = json.load(open(self.filepath))
|
||||
tool.Search.import_filter_query(data["query"], props.filter_groups)
|
||||
|
||||
for prop in [
|
||||
"should_generate_svg",
|
||||
"should_preserve_existing",
|
||||
"include_global_id",
|
||||
"null_value",
|
||||
"empty_value",
|
||||
"true_value",
|
||||
"false_value",
|
||||
"concat_value",
|
||||
"csv_delimiter",
|
||||
"format",
|
||||
"csv_custom_delimiter",
|
||||
]:
|
||||
setattr(props, prop, data["settings"][prop])
|
||||
|
||||
props.csv_attributes.clear()
|
||||
for attribute in data["attributes"]:
|
||||
new = props.csv_attributes.add()
|
||||
new.name = attribute["name"]
|
||||
new.header = attribute["header"]
|
||||
new.sort = attribute["sort"]
|
||||
new.group = attribute["group"]
|
||||
new.summary = attribute["summary"]
|
||||
new.formatting = attribute["formatting"]
|
||||
for prop in ["name", "header", "sort", "group", "summary", "formatting"]:
|
||||
setattr(new, prop, attribute[prop])
|
||||
return {"FINISHED"}
|
||||
|
||||
def invoke(self, context, event):
|
||||
@@ -121,6 +132,22 @@ class ExportCsvAttributes(bpy.types.Operator):
|
||||
def execute(self, context):
|
||||
props = context.scene.CsvProperties
|
||||
|
||||
settings = {}
|
||||
for prop in [
|
||||
"should_generate_svg",
|
||||
"should_preserve_existing",
|
||||
"include_global_id",
|
||||
"null_value",
|
||||
"empty_value",
|
||||
"true_value",
|
||||
"false_value",
|
||||
"concat_value",
|
||||
"csv_delimiter",
|
||||
"format",
|
||||
"csv_custom_delimiter",
|
||||
]:
|
||||
settings[prop] = getattr(props, prop)
|
||||
|
||||
data = {
|
||||
"query": tool.Search.export_filter_query(props.filter_groups),
|
||||
"attributes": [
|
||||
@@ -134,6 +161,7 @@ class ExportCsvAttributes(bpy.types.Operator):
|
||||
}
|
||||
for a in props.csv_attributes
|
||||
],
|
||||
"settings": settings,
|
||||
}
|
||||
|
||||
with open(self.filepath, "w") as outfile:
|
||||
@@ -208,11 +236,16 @@ class ExportIfcCsv(bpy.types.Operator):
|
||||
empty=props.empty_value,
|
||||
bool_true=props.true_value,
|
||||
bool_false=props.false_value,
|
||||
concat=props.concat_value,
|
||||
sort=sort,
|
||||
groups=groups,
|
||||
summaries=summaries,
|
||||
formatting=formatting,
|
||||
)
|
||||
|
||||
if props.format != "csv" and props.should_generate_svg:
|
||||
schedule_creator = scheduler.Scheduler()
|
||||
schedule_creator.schedule(self.filepath, tool.Drawing.get_path_with_ext(self.filepath, "svg"))
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -251,7 +284,7 @@ class ImportIfcCsv(bpy.types.Operator):
|
||||
)
|
||||
if not props.should_load_from_memory:
|
||||
ifc_file.write(props.csv_ifc_file)
|
||||
purge_module_data()
|
||||
refresh_ui_data()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
|
||||
@@ -17,8 +17,7 @@
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
from blenderbim.bim.module.search.prop import BIMFilterGroup
|
||||
from blenderbim.bim.prop import StrProperty
|
||||
from blenderbim.bim.prop import StrProperty, BIMFilterGroup
|
||||
from bpy.types import PropertyGroup
|
||||
from bpy.props import (
|
||||
PointerProperty,
|
||||
@@ -66,12 +65,14 @@ class CsvProperties(PropertyGroup):
|
||||
ifc_selector: StringProperty(default="", name="IFC Selector")
|
||||
filter_groups: CollectionProperty(type=BIMFilterGroup, name="Filter Groups")
|
||||
csv_attributes: CollectionProperty(name="CSV Attributes", type=CsvAttribute)
|
||||
should_generate_svg: BoolProperty(default=False, name="Generate SVG")
|
||||
should_preserve_existing: BoolProperty(default=False, name="Preserve Existing")
|
||||
include_global_id: BoolProperty(default=True, name="Include GlobalId")
|
||||
null_value: StringProperty(default="N/A", name="Null Value")
|
||||
empty_value: StringProperty(default="-", name="Empty String Value")
|
||||
true_value: StringProperty(default="YES", name="True Value")
|
||||
false_value: StringProperty(default="NO", name="False Value")
|
||||
concat_value: StringProperty(default=", ", name="Concat Value")
|
||||
csv_delimiter: EnumProperty(
|
||||
items=[
|
||||
(";", ";", ""),
|
||||
|
||||
@@ -67,6 +67,8 @@ class BIM_PT_ifccsv(Panel):
|
||||
row = layout.row(align=True)
|
||||
row.prop(props, "csv_custom_delimiter")
|
||||
|
||||
row = layout.row()
|
||||
row.prop(props, "should_generate_svg")
|
||||
row = layout.row()
|
||||
row.prop(props, "should_preserve_existing")
|
||||
row = layout.row()
|
||||
@@ -79,9 +81,11 @@ class BIM_PT_ifccsv(Panel):
|
||||
row.prop(props, "true_value")
|
||||
row = layout.row()
|
||||
row.prop(props, "false_value")
|
||||
row = layout.row()
|
||||
row.prop(props, "concat_value")
|
||||
layout.use_property_split = False
|
||||
|
||||
blenderbim.bim.helper.draw_filter(self.layout, props, SearchData, "csv")
|
||||
blenderbim.bim.helper.draw_filter(self.layout, props.filter_groups, SearchData, "csv")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.operator("bim.add_csv_attribute", icon="ADD")
|
||||
|
||||
@@ -20,23 +20,26 @@ import bpy
|
||||
from . import ui, prop, operator
|
||||
|
||||
classes = (
|
||||
operator.ConvertToBlender,
|
||||
operator.CopyDebugInformation,
|
||||
operator.CreateAllShapes,
|
||||
operator.CreateShapeFromStepId,
|
||||
operator.InspectFromObject,
|
||||
operator.InspectFromStepId,
|
||||
operator.OverrideDisplayType,
|
||||
operator.ParseExpress,
|
||||
operator.PrintIfcFile,
|
||||
operator.PrintObjectPlacement,
|
||||
operator.ProfileImportIFC,
|
||||
operator.PurgeHdf5Cache,
|
||||
operator.PurgeIfcLinks,
|
||||
operator.ConvertToBlender,
|
||||
operator.RewindInspector,
|
||||
operator.SelectExpressFile,
|
||||
operator.SelectHighPolygonMeshes,
|
||||
operator.SelectHighestPolygonMeshes,
|
||||
operator.ValidateIfcFile,
|
||||
operator.PrintUnusedElementStats,
|
||||
operator.PurgeUnusedElementsByClass,
|
||||
prop.BIMDebugProperties,
|
||||
ui.BIM_PT_debug,
|
||||
)
|
||||
|
||||
@@ -116,7 +116,7 @@ class PurgeIfcLinks(bpy.types.Operator):
|
||||
context.scene.BIMProperties.ifc_file = ""
|
||||
context.scene.BIMDebugProperties.attributes.clear()
|
||||
IfcStore.purge()
|
||||
blenderbim.bim.handler.purge_module_data()
|
||||
blenderbim.bim.handler.refresh_ui_data()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -136,7 +136,7 @@ class ConvertToBlender(bpy.types.Operator):
|
||||
m.BIMMaterialProperties.ifc_style_id = False
|
||||
bpy.context.scene.BIMProperties.ifc_file = ""
|
||||
IfcStore.purge()
|
||||
blenderbim.bim.handler.purge_module_data()
|
||||
blenderbim.bim.handler.refresh_ui_data()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -146,16 +146,33 @@ class ValidateIfcFile(bpy.types.Operator):
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return IfcStore.get_file()
|
||||
return tool.Ifc.get()
|
||||
|
||||
def execute(self, context):
|
||||
import ifcopenshell.validate
|
||||
|
||||
class LogDetectionHandler(logging.Handler):
|
||||
message_logged = False
|
||||
|
||||
def emit(self, record):
|
||||
if not self.message_logged:
|
||||
self.message_logged = True
|
||||
|
||||
logger = logging.getLogger("validate")
|
||||
logger.setLevel(logging.DEBUG)
|
||||
ifcopenshell.validate.validate(IfcStore.get_file(), logger, express_rules=True)
|
||||
|
||||
self.report({"INFO"}, "Check validation results in the system console.")
|
||||
# use LogDetectionHandler to check whether there were any validation errors
|
||||
# during `ifcopenshell.validate.validate`
|
||||
handler = LogDetectionHandler()
|
||||
logger.addHandler(handler)
|
||||
ifcopenshell.validate.validate(tool.Ifc.get(), logger, express_rules=True)
|
||||
logger.removeHandler(handler)
|
||||
|
||||
if handler.message_logged:
|
||||
self.report({"INFO"}, "Check validation results in the system console.")
|
||||
else:
|
||||
self.report({"INFO"}, "No validation issues found.")
|
||||
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
@@ -196,7 +213,7 @@ class CreateAllShapes(bpy.types.Operator):
|
||||
settings_2d.set(settings_2d.INCLUDE_CURVES, True)
|
||||
failures = []
|
||||
excludes = () # For the developer to debug with
|
||||
for i, element in enumerate(elements):
|
||||
for i, element in enumerate(elements, 1):
|
||||
if element.GlobalId in excludes:
|
||||
continue
|
||||
print(f"{i}/{total}:", element)
|
||||
@@ -218,7 +235,7 @@ class CreateAllShapes(bpy.types.Operator):
|
||||
len(shape.geometry.edges),
|
||||
len(shape.geometry.faces),
|
||||
)
|
||||
print(f"Failures: {len(failures)}")
|
||||
self.report({"INFO"}, f"Failed shapes: {len(failures)}, check the system console for details.")
|
||||
for failure in failures:
|
||||
print(failure)
|
||||
return {"FINISHED"}
|
||||
@@ -443,3 +460,166 @@ class PurgeHdf5Cache(bpy.types.Operator):
|
||||
def execute(self, context):
|
||||
core.purge_hdf5_cache(tool.Debug)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class OverrideDisplayType(bpy.types.Operator):
|
||||
bl_idname = "bim.override_display_type"
|
||||
bl_label = "Override Display Type"
|
||||
display: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
for obj in context.selected_objects:
|
||||
obj.display_type = self.display
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class PrintUnusedElementStats(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.print_unused_elements_stats"
|
||||
bl_label = "Print Unused Elements Stats"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
bl_description = (
|
||||
"Print all unused elements in current IFC project in system console, not limited to the selected class"
|
||||
)
|
||||
|
||||
ignore_contexts: bpy.props.BoolProperty(name="Ignore Contexts", default=True)
|
||||
ignore_relationships: bpy.props.BoolProperty(name="Ignore Relationships", default=True)
|
||||
ignore_types: bpy.props.BoolProperty(name="Ignore Types", default=True)
|
||||
ignore_styled_items: bpy.props.BoolProperty(name="Ignoer Styled Items", default=True)
|
||||
|
||||
def _execute(self, context):
|
||||
props = context.scene.BIMDebugProperties
|
||||
# ignore some classes that could have zero 0 inverse references by their nature
|
||||
ignore_classes = []
|
||||
if self.ignore_contexts:
|
||||
ignore_classes += ["IfcRepresentationContext"]
|
||||
if self.ignore_relationships:
|
||||
ignore_classes += ["IfcRelationship"]
|
||||
if self.ignore_types:
|
||||
ignore_classes += ["IfcTypeProduct"]
|
||||
if self.ignore_styled_items:
|
||||
ignore_classes += ["IfcStyledItem"]
|
||||
|
||||
unused_elements = tool.Debug.print_unused_elements_stats(props.ifc_class_purge, ignore_classes)
|
||||
self.report({"INFO"}, f"{unused_elements} unused elements found, check the system console for the details.")
|
||||
|
||||
|
||||
class PurgeUnusedElementsByClass(bpy.types.Operator, tool.Ifc.Operator):
|
||||
bl_idname = "bim.purge_unused_elements_by_class"
|
||||
bl_label = "Purge Unused Elements By Class"
|
||||
bl_description = (
|
||||
"Will find all elements of class that have no inverse refernces and will remove them, use very carefully"
|
||||
)
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||
filter_glob: bpy.props.StringProperty(default="*.ifc", options={"HIDDEN"})
|
||||
|
||||
def invoke(self, context, event):
|
||||
context.window_manager.fileselect_add(self)
|
||||
return {"RUNNING_MODAL"}
|
||||
|
||||
def _execute(self, context):
|
||||
props = context.scene.BIMDebugProperties
|
||||
if props.ifc_class_purge:
|
||||
purged_elements = core.purge_unused_elements(tool.Ifc, tool.Debug, props.ifc_class_purge)
|
||||
self.report({"INFO"}, f"{purged_elements} unused elements found and removed.")
|
||||
tool.Ifc.get().write(self.filepath)
|
||||
return
|
||||
|
||||
# A whitelisted class is a class that only contains simple data that
|
||||
# has no meaning by itself (only has meaning when combined with other
|
||||
# data). E.g. a colour by itself has no meaning so is whitelisted, but
|
||||
# a material by itself may be part of your materials library.
|
||||
|
||||
# There are classes I don't know enough about to decide. Not whitelisting in case.
|
||||
# IfcAlignmentParameterSegment
|
||||
# IfcBoundaryCondition
|
||||
# IfcStructuralConnectionCondition
|
||||
# IfcStructuralLoad
|
||||
|
||||
whitelisted_classes = [
|
||||
"IfcActorRole",
|
||||
"IfcAddress",
|
||||
"IfcApplication",
|
||||
"IfcAppliedValue",
|
||||
"IfcConnectionGeometry",
|
||||
"IfcCoordinateReferenceSystem",
|
||||
"IfcDerivedUnit",
|
||||
"IfcDerivedUnitElement",
|
||||
"IfcDimensionalExponents",
|
||||
"IfcExternalReference",
|
||||
"IfcGridAxis",
|
||||
"IfcIrregularTimeSeriesValue",
|
||||
"IfcLightDistributionData",
|
||||
"IfcLightIntensityDistribution",
|
||||
"IfcMeasureWithUnit",
|
||||
"IfcMonetaryUnit",
|
||||
"IfcNamedUnit",
|
||||
"IfcObjectPlacement",
|
||||
"IfcOrganization", # Should be referenced as part of an actor
|
||||
"IfcOwnerHistory",
|
||||
"IfcPerson", # Should be referenced as part of an actor
|
||||
"IfcPersonAndOrganization", # Should be referenced as part of an actor
|
||||
"IfcPhysicalQuantity",
|
||||
"IfcPresentationItem",
|
||||
"IfcProductDefinitionShape",
|
||||
"IfcPropertyAbstraction",
|
||||
"IfcRecurrencePattern",
|
||||
"IfcReference",
|
||||
"IfcRepresentation",
|
||||
"IfcRepresentationContext",
|
||||
"IfcRepresentationItem",
|
||||
"IfcRepresentationMap",
|
||||
"IfcPropertyDefinition", # A bit of a questionable one, and the odd one out from IfcRoot.
|
||||
"IfcSchedulingTime",
|
||||
"IfcShapeAspect",
|
||||
"IfcTable",
|
||||
"IfcTableColumn",
|
||||
"IfcTableRow",
|
||||
"IfcTextureCoordinateIndices",
|
||||
"IfcTimePeriod",
|
||||
"IfcTimeSeries",
|
||||
"IfcTimeSeriesValue",
|
||||
"IfcUnitAssignment",
|
||||
"IfcVirtualGridIntersection",
|
||||
]
|
||||
|
||||
total_purged = 0
|
||||
while True:
|
||||
total_batches = 0
|
||||
print("*" * 100)
|
||||
total_batch_purged = 0
|
||||
for ifc_class in whitelisted_classes:
|
||||
total_class_purged = 0
|
||||
try:
|
||||
elements = tool.Ifc.get().by_type(ifc_class)
|
||||
except:
|
||||
continue # Probably not in this schema?
|
||||
to_purge = set()
|
||||
for element in elements:
|
||||
try:
|
||||
if ifc_class == "IfcRepresentationItem" and element.is_a("IfcStyledItem") and element.Item:
|
||||
continue
|
||||
except:
|
||||
to_purge.add(element.id()) # It's invalid, definitely purge it.
|
||||
if tool.Ifc.get().get_total_inverses(element) == 0:
|
||||
to_purge.add(element.id())
|
||||
for element_id in to_purge:
|
||||
try:
|
||||
element = tool.Ifc.get().by_id(element_id)
|
||||
ifcopenshell.util.element.remove_deep2(tool.Ifc.get(), element)
|
||||
total_class_purged += 1
|
||||
except:
|
||||
continue
|
||||
if total_class_purged > 0:
|
||||
total_batch_purged += total_class_purged
|
||||
print(f"Auto purged {total_class_purged} {ifc_class}")
|
||||
if total_batch_purged > 0:
|
||||
total_purged += total_batch_purged
|
||||
print(f"Auto purged in batch: {total_batch_purged}")
|
||||
total_batches += 1
|
||||
if total_batch_purged == 0:
|
||||
break
|
||||
elif total_batches > 20:
|
||||
print("Finished 20 batches. Manually stopping in case of infinite loop.")
|
||||
self.report({"INFO"}, f"Auto purged {total_purged} orphaned elements")
|
||||
tool.Ifc.get().write(self.filepath)
|
||||
|
||||
@@ -40,3 +40,14 @@ class BIMDebugProperties(PropertyGroup):
|
||||
inverse_attributes: CollectionProperty(name="Inverse Attributes", type=Attribute)
|
||||
inverse_references: CollectionProperty(name="Inverse References", type=Attribute)
|
||||
express_file: StringProperty(name="Express File")
|
||||
display_type: EnumProperty(
|
||||
items=[
|
||||
("BOUNDS", "Bounds", ""),
|
||||
("WIRE", "Wire", ""),
|
||||
("SOLID", "Solid", ""),
|
||||
("TEXTURED", "Textured", ""),
|
||||
],
|
||||
name="Display Type",
|
||||
default="BOUNDS",
|
||||
)
|
||||
ifc_class_purge: StringProperty(name="Unused Elements IFC Class", default="")
|
||||
|
||||
@@ -37,7 +37,6 @@ class BIM_PT_debug(Panel):
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(context.scene.BIMProperties, "ifc_file", text="")
|
||||
row.operator("bim.validate_ifc_file", icon="CHECKMARK", text="")
|
||||
row.operator("bim.reload_selected_ifc_file", icon="FILE_REFRESH", text="")
|
||||
row.operator("bim.select_ifc_file", icon="FILE_FOLDER", text="")
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
@@ -45,6 +44,9 @@ class BIM_PT_debug(Panel):
|
||||
row.operator("bim.parse_express", icon="IMPORT", text="")
|
||||
row.operator("bim.select_express_file", icon="FILE_FOLDER", text="")
|
||||
|
||||
row = layout.row()
|
||||
row.operator("bim.reload_ifc_file", text="Incrementally Reload Changes")
|
||||
|
||||
row = layout.row()
|
||||
row.operator("bim.print_ifc_file")
|
||||
|
||||
@@ -83,6 +85,17 @@ class BIM_PT_debug(Panel):
|
||||
).percentile = context.scene.BIMDebugProperties.percentile_of_polygons
|
||||
row.prop(props, "percentile_of_polygons", text="")
|
||||
|
||||
row = layout.split(factor=0.5, align=True)
|
||||
row.prop(props, "display_type", text="")
|
||||
row.operator("bim.override_display_type").display = context.scene.BIMDebugProperties.display_type
|
||||
|
||||
layout.operator("bim.purge_unused_representations")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(context.scene.BIMDebugProperties, "ifc_class_purge", text="")
|
||||
row.operator("bim.purge_unused_elements_by_class", text="Purge Orphaned", icon="TRASH")
|
||||
row.operator("bim.print_unused_elements_stats", text="", icon="INFO")
|
||||
|
||||
if context.active_object and context.active_object.data:
|
||||
mprops = context.active_object.data.BIMMeshProperties
|
||||
row = layout.row()
|
||||
|
||||
@@ -20,11 +20,12 @@ import bpy
|
||||
from . import ui, prop, operator
|
||||
|
||||
classes = (
|
||||
operator.SelectDiffJsonFile,
|
||||
operator.VisualiseDiff,
|
||||
operator.SelectDiffOldFile,
|
||||
operator.SelectDiffNewFile,
|
||||
operator.ExecuteIfcDiff,
|
||||
operator.SelectDiffJsonFile,
|
||||
operator.SelectDiffNewFile,
|
||||
operator.SelectDiffObjects,
|
||||
operator.SelectDiffOldFile,
|
||||
operator.VisualiseDiff,
|
||||
prop.Relationships,
|
||||
prop.DiffProperties,
|
||||
ui.BIM_PT_diff,
|
||||
|
||||
@@ -18,10 +18,11 @@
|
||||
|
||||
import bpy
|
||||
import json
|
||||
import ifccsv
|
||||
import logging
|
||||
import ifcopenshell
|
||||
import blenderbim.bim.handler
|
||||
import blenderbim.tool as tool
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
|
||||
|
||||
class SelectDiffJsonFile(bpy.types.Operator):
|
||||
@@ -51,8 +52,37 @@ class VisualiseDiff(bpy.types.Operator):
|
||||
diff = json.load(file)
|
||||
for obj in context.visible_objects:
|
||||
obj.color = (1.0, 1.0, 1.0, 1.0)
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
if not element:
|
||||
|
||||
if "IfcDiff Deleted Elements" in obj.users_collection[0].name:
|
||||
obj.color = (1.0, 0.0, 0.0, 1.0)
|
||||
continue
|
||||
elif "IfcDiff Added Elements" in obj.users_collection[0].name:
|
||||
obj.color = (0.0, 1.0, 0.0, 1.0)
|
||||
continue
|
||||
elif "IfcDiff Changed Elements" in obj.users_collection[0].name:
|
||||
obj.color = (0.0, 0.0, 0.7, 1.0)
|
||||
continue
|
||||
|
||||
if not obj.BIMObjectProperties.ifc_definition_id:
|
||||
continue
|
||||
|
||||
ifc_file = ""
|
||||
for scene in obj.users_scene:
|
||||
if scene.BIMProperties.ifc_file:
|
||||
ifc_file = scene.BIMProperties.ifc_file
|
||||
if scene.library:
|
||||
break
|
||||
|
||||
if ifc_file:
|
||||
if ifc_file not in IfcStore.session_files:
|
||||
IfcStore.session_files[ifc_file] = ifcopenshell.open(ifc_file)
|
||||
element_file = IfcStore.session_files[ifc_file]
|
||||
else:
|
||||
element_file = ifc_file
|
||||
|
||||
try:
|
||||
element = element_file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||
except:
|
||||
continue
|
||||
global_id = getattr(element, "GlobalId", None)
|
||||
if not global_id:
|
||||
@@ -115,14 +145,140 @@ class ExecuteIfcDiff(bpy.types.Operator):
|
||||
def execute(self, context):
|
||||
import ifcdiff
|
||||
|
||||
old = ifcopenshell.open(context.scene.DiffProperties.old_file)
|
||||
new = ifcopenshell.open(context.scene.DiffProperties.new_file)
|
||||
relationships = [r.relationship for r in context.scene.DiffProperties.diff_relationships]
|
||||
query = context.scene.DiffProperties.diff_filter_elements
|
||||
self.props = context.scene.DiffProperties
|
||||
|
||||
if tool.Ifc.get():
|
||||
if self.props.active_file == "NONE":
|
||||
old = ifcopenshell.open(self.props.old_file)
|
||||
new = ifcopenshell.open(self.props.new_file)
|
||||
elif self.props.active_file == "NEW":
|
||||
old = ifcopenshell.open(self.props.old_file)
|
||||
new = tool.Ifc.get()
|
||||
elif self.props.active_file == "OLD":
|
||||
old = tool.Ifc.get()
|
||||
new = ifcopenshell.open(self.props.new_file)
|
||||
else:
|
||||
old = ifcopenshell.open(self.props.old_file)
|
||||
new = ifcopenshell.open(self.props.new_file)
|
||||
|
||||
relationships = [r.relationship for r in self.props.diff_relationships]
|
||||
query = self.props.diff_filter_elements
|
||||
|
||||
ifc_diff = ifcdiff.IfcDiff(old, new, relationships=relationships, filter_elements=query)
|
||||
ifc_diff.diff()
|
||||
ifc_diff.export(self.filepath)
|
||||
context.scene.DiffProperties.diff_json_file = self.filepath
|
||||
self.props.diff_json_file = self.filepath
|
||||
|
||||
self.load_changed_elements(ifc_diff)
|
||||
|
||||
blenderbim.bim.handler.refresh_ui_data()
|
||||
return {"FINISHED"}
|
||||
|
||||
def load_changed_elements(self, ifc_diff):
|
||||
if not tool.Ifc.get() or self.props.active_file == "NONE" or not self.props.should_load_changed_elements:
|
||||
return
|
||||
|
||||
active_ifc = tool.Ifc.get()
|
||||
logger = logging.getLogger("ImportIFC")
|
||||
ifc_import_settings = blenderbim.bim.import_ifc.IfcImportSettings.factory(bpy.context, None, logger)
|
||||
ifc_importer = blenderbim.bim.import_ifc.IfcImporter(ifc_import_settings)
|
||||
|
||||
if self.props.active_file == "NEW":
|
||||
tool.Ifc.set(ifc_diff.old)
|
||||
ifc_importer.file = ifc_diff.old
|
||||
ifc_importer.process_context_filter()
|
||||
ifc_importer.create_materials()
|
||||
ifc_importer.create_styles()
|
||||
|
||||
elements = {ifc_diff.old.by_guid(guid) for guid in ifc_diff.deleted_elements}
|
||||
ifc_importer.create_generic_elements(elements)
|
||||
self.place_objs_in_collection(ifc_importer.added_data.values(), "IfcDiff Deleted Elements")
|
||||
|
||||
ifc_importer.added_data = {}
|
||||
|
||||
elements = {ifc_diff.old.by_guid(guid) for guid in ifc_diff.change_register.keys()}
|
||||
ifc_importer.create_generic_elements(elements)
|
||||
self.place_objs_in_collection(ifc_importer.added_data.values(), "IfcDiff Changed Elements")
|
||||
elif self.props.active_file == "OLD":
|
||||
tool.Ifc.set(ifc_diff.new)
|
||||
ifc_importer.file = ifc_diff.new
|
||||
ifc_importer.process_context_filter()
|
||||
ifc_importer.create_materials()
|
||||
ifc_importer.create_styles()
|
||||
|
||||
elements = {ifc_diff.new.by_guid(guid) for guid in ifc_diff.added_elements}
|
||||
ifc_importer.create_generic_elements(elements)
|
||||
self.place_objs_in_collection(ifc_importer.added_data.values(), "IfcDiff Added Elements")
|
||||
|
||||
ifc_importer.added_data = {}
|
||||
|
||||
elements = {ifc_diff.new.by_guid(guid) for guid in ifc_diff.change_register.keys()}
|
||||
ifc_importer.create_generic_elements(elements)
|
||||
self.place_objs_in_collection(ifc_importer.added_data.values(), "IfcDiff Changed Elements")
|
||||
tool.Ifc.set(active_ifc)
|
||||
|
||||
def place_objs_in_collection(self, objs, name):
|
||||
collection = bpy.data.collections.get(name)
|
||||
if not collection:
|
||||
collection = bpy.data.collections.new(name)
|
||||
bpy.context.scene.collection.children.link(collection)
|
||||
|
||||
for obj in objs:
|
||||
if isinstance(obj, bpy.types.Object):
|
||||
collection.objects.link(obj)
|
||||
|
||||
|
||||
class SelectDiffObjects(bpy.types.Operator):
|
||||
bl_idname = "bim.select_diff_objects"
|
||||
bl_label = "Select Diff Objects"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
mode: bpy.props.StringProperty()
|
||||
|
||||
def execute(self, context):
|
||||
ifc_file = tool.Ifc.get()
|
||||
with open(context.scene.DiffProperties.diff_json_file, "r") as file:
|
||||
diff = json.load(file)
|
||||
for obj in context.visible_objects:
|
||||
obj.select_set(False)
|
||||
|
||||
if self.mode == "DELETED" and "IfcDiff Deleted Elements" in obj.users_collection[0].name:
|
||||
obj.select_set(True)
|
||||
continue
|
||||
elif self.mode == "ADDED" and "IfcDiff Added Elements" in obj.users_collection[0].name:
|
||||
obj.select_set(True)
|
||||
continue
|
||||
elif self.mode == "CHANGED" and "IfcDiff Changed Elements" in obj.users_collection[0].name:
|
||||
obj.select_set(True)
|
||||
continue
|
||||
|
||||
if not obj.BIMObjectProperties.ifc_definition_id:
|
||||
continue
|
||||
|
||||
ifc_file = ""
|
||||
for scene in obj.users_scene:
|
||||
if scene.BIMProperties.ifc_file:
|
||||
ifc_file = scene.BIMProperties.ifc_file
|
||||
if scene.library:
|
||||
break
|
||||
|
||||
if ifc_file:
|
||||
if ifc_file not in IfcStore.session_files:
|
||||
IfcStore.session_files[ifc_file] = ifcopenshell.open(ifc_file)
|
||||
element_file = IfcStore.session_files[ifc_file]
|
||||
else:
|
||||
element_file = ifc_file
|
||||
|
||||
try:
|
||||
element = element_file.by_id(obj.BIMObjectProperties.ifc_definition_id)
|
||||
except:
|
||||
continue
|
||||
global_id = getattr(element, "GlobalId", None)
|
||||
if not global_id:
|
||||
continue
|
||||
if self.mode == "DELETED" and global_id in diff["deleted"]:
|
||||
obj.select_set(True)
|
||||
elif self.mode == "ADDED" and global_id in diff["added"]:
|
||||
obj.select_set(True)
|
||||
elif self.mode == "CHANGED" and global_id in diff["changed"]:
|
||||
obj.select_set(True)
|
||||
return {"FINISHED"}
|
||||
|
||||
@@ -49,3 +49,13 @@ class DiffProperties(PropertyGroup):
|
||||
new_file: StringProperty(default="", name="New IFC File")
|
||||
diff_relationships: CollectionProperty(type=Relationships, name="Relationships")
|
||||
diff_filter_elements: StringProperty(default="", name="Filter")
|
||||
should_load_changed_elements: BoolProperty(name="Load Changed Elements", default=True)
|
||||
active_file: EnumProperty(
|
||||
items=[
|
||||
("NONE", "N/A", ""),
|
||||
("OLD", "Old", ""),
|
||||
("NEW", "New", ""),
|
||||
],
|
||||
name="Active File",
|
||||
default="NEW",
|
||||
)
|
||||
|
||||
@@ -44,13 +44,38 @@ class BIM_PT_diff(Panel):
|
||||
|
||||
layout.label(text="IFC Diff Setup:")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(props, "old_file")
|
||||
row.operator("bim.select_diff_old_file", icon="FILE_FOLDER", text="")
|
||||
if tool.Ifc.get():
|
||||
row = layout.row()
|
||||
row.prop(props, "active_file")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(props, "new_file")
|
||||
row.operator("bim.select_diff_new_file", icon="FILE_FOLDER", text="")
|
||||
if props.active_file == "NONE":
|
||||
row = layout.row(align=True)
|
||||
row.prop(props, "old_file")
|
||||
row.operator("bim.select_diff_old_file", icon="FILE_FOLDER", text="")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(props, "new_file")
|
||||
row.operator("bim.select_diff_new_file", icon="FILE_FOLDER", text="")
|
||||
elif props.active_file == "NEW":
|
||||
row = layout.row(align=True)
|
||||
row.prop(props, "old_file")
|
||||
row.operator("bim.select_diff_old_file", icon="FILE_FOLDER", text="")
|
||||
elif props.active_file == "OLD":
|
||||
row = layout.row(align=True)
|
||||
row.prop(props, "new_file")
|
||||
row.operator("bim.select_diff_new_file", icon="FILE_FOLDER", text="")
|
||||
|
||||
if props.active_file != "NONE":
|
||||
row = layout.row()
|
||||
row.prop(props, "should_load_changed_elements")
|
||||
else:
|
||||
row = layout.row(align=True)
|
||||
row.prop(props, "old_file")
|
||||
row.operator("bim.select_diff_old_file", icon="FILE_FOLDER", text="")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(props, "new_file")
|
||||
row.operator("bim.select_diff_new_file", icon="FILE_FOLDER", text="")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(props, "diff_relationships")
|
||||
@@ -82,10 +107,22 @@ class BIM_PT_diff(Panel):
|
||||
|
||||
if DiffData.data["diff_json"]:
|
||||
row = layout.row()
|
||||
row.alignment = "CENTER"
|
||||
row.label(text=f"{DiffData.data['total_added']} added")
|
||||
row.label(text=f"{DiffData.data['total_deleted']} deleted")
|
||||
row.label(text=f"{DiffData.data['total_changed']} changed")
|
||||
col = row.column(align=True)
|
||||
col.operator(
|
||||
"bim.select_diff_objects",
|
||||
icon="RESTRICT_SELECT_OFF",
|
||||
text=f"Select {DiffData.data['total_added']} Added",
|
||||
).mode = "ADDED"
|
||||
col.operator(
|
||||
"bim.select_diff_objects",
|
||||
icon="RESTRICT_SELECT_OFF",
|
||||
text=f"Select {DiffData.data['total_deleted']} Deleted",
|
||||
).mode = "DELETED"
|
||||
col.operator(
|
||||
"bim.select_diff_objects",
|
||||
icon="RESTRICT_SELECT_OFF",
|
||||
text=f"Select {DiffData.data['total_changed']} Changed",
|
||||
).mode = "CHANGED"
|
||||
|
||||
if DiffData.data["changes"]:
|
||||
box = layout.box()
|
||||
|
||||
@@ -29,7 +29,7 @@ class BIM_PT_documents(Panel):
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_project_setup"
|
||||
bl_parent_id = "BIM_PT_tab_project_setup"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
|
||||
@@ -30,11 +30,13 @@ classes = (
|
||||
operator.AddDrawingStyleAttribute,
|
||||
operator.AddDrawingToSheet,
|
||||
operator.AddReference,
|
||||
operator.AddReferenceImage,
|
||||
operator.AddReferenceToSheet,
|
||||
operator.AddSchedule,
|
||||
operator.AddScheduleToSheet,
|
||||
operator.AddSheet,
|
||||
operator.AddTextLiteral,
|
||||
operator.AssignSelectedObjectAsProduct,
|
||||
operator.BuildSchedule,
|
||||
operator.CleanWireframes,
|
||||
operator.ContractSheet,
|
||||
@@ -50,11 +52,13 @@ classes = (
|
||||
operator.DisableEditingText,
|
||||
operator.DuplicateDrawing,
|
||||
operator.EditAssignedProduct,
|
||||
operator.EditElementFilter,
|
||||
operator.EditSheet,
|
||||
operator.EditText,
|
||||
operator.EditTextPopup,
|
||||
operator.EnableAddAnnotationType,
|
||||
operator.EnableEditingAssignedProduct,
|
||||
operator.EnableEditingElementFilter,
|
||||
operator.EnableEditingText,
|
||||
operator.ExpandSheet,
|
||||
operator.ExpandTargetView,
|
||||
@@ -92,10 +96,11 @@ classes = (
|
||||
prop.BIMTextProperties,
|
||||
prop.BIMAssignedProductProperties,
|
||||
prop.BIMAnnotationProperties,
|
||||
ui.BIM_PT_camera,
|
||||
ui.BIM_PT_drawing_underlay,
|
||||
ui.BIM_PT_sheets,
|
||||
ui.BIM_PT_drawings,
|
||||
ui.BIM_PT_camera,
|
||||
ui.BIM_PT_element_filters,
|
||||
ui.BIM_PT_drawing_underlay,
|
||||
ui.BIM_PT_schedules,
|
||||
ui.BIM_PT_references,
|
||||
ui.BIM_PT_product_assignments,
|
||||
@@ -123,6 +128,7 @@ def register():
|
||||
bpy.types.TextCurve.BIMTextProperties = bpy.props.PointerProperty(type=prop.BIMTextProperties)
|
||||
bpy.app.handlers.load_post.append(handler.toggleDecorationsOnLoad)
|
||||
bpy.app.handlers.depsgraph_update_pre.append(handler.depsgraph_update_pre_handler)
|
||||
bpy.types.VIEW3D_MT_image_add.append(ui.add_object_button)
|
||||
|
||||
|
||||
def unregister():
|
||||
@@ -136,3 +142,4 @@ def unregister():
|
||||
del bpy.types.TextCurve.BIMTextProperties
|
||||
bpy.app.handlers.load_post.remove(handler.toggleDecorationsOnLoad)
|
||||
bpy.app.handlers.depsgraph_update_pre.remove(handler.depsgraph_update_pre_handler)
|
||||
bpy.types.VIEW3D_MT_image_add.remove(ui.add_object_button)
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
import os
|
||||
import bpy
|
||||
import json
|
||||
import ifcopenshell.util.element
|
||||
import ifcopenshell.util.representation
|
||||
import blenderbim.tool as tool
|
||||
@@ -29,6 +30,7 @@ def refresh():
|
||||
SheetsData.is_loaded = False
|
||||
DocumentsData.is_loaded = False
|
||||
DrawingsData.is_loaded = False
|
||||
ElementFiltersData.is_loaded = False
|
||||
AnnotationData.is_loaded = False
|
||||
DecoratorData.data = {}
|
||||
DecoratorData.cut_cache = {}
|
||||
@@ -123,6 +125,8 @@ class DrawingsData:
|
||||
[(str(s.id()), s.Name or "Unnamed", "") for s in tool.Ifc.get().by_type("IfcBuildingStorey")]
|
||||
)
|
||||
return results
|
||||
elif bpy.context.scene.DocProperties.target_view in ["MODEL_VIEW"]:
|
||||
return [(h.upper(), h, "") for h in ["Orthographic", "Perspective"]]
|
||||
return [(h.upper(), h, "") for h in ["North", "South", "East", "West"]]
|
||||
|
||||
@classmethod
|
||||
@@ -135,6 +139,55 @@ class DrawingsData:
|
||||
return ifcopenshell.util.element.get_pset(drawing, "EPset_Drawing")
|
||||
|
||||
|
||||
class ElementFiltersData:
|
||||
data = {}
|
||||
is_loaded = False
|
||||
|
||||
@classmethod
|
||||
def load(cls):
|
||||
cls.data = {
|
||||
"saved_searches": cls.saved_searches(),
|
||||
"has_include_filter": cls.has_include_filter(),
|
||||
"has_exclude_filter": cls.has_exclude_filter(),
|
||||
}
|
||||
cls.is_loaded = True
|
||||
|
||||
@classmethod
|
||||
def saved_searches(cls):
|
||||
if not tool.Ifc.get():
|
||||
return []
|
||||
groups = tool.Ifc.get().by_type("IfcGroup")
|
||||
results = []
|
||||
for group in groups:
|
||||
try:
|
||||
data = json.loads(group.Description)
|
||||
if isinstance(data, dict) and data.get("type", None) == "BBIM_Search" and data.get("query", None):
|
||||
results.append(group)
|
||||
except:
|
||||
pass
|
||||
return [(str(g.id()), g.Name or "Unnamed", "") for g in sorted(results, key=lambda x: x.Name or "Unnamed")]
|
||||
|
||||
@classmethod
|
||||
def has_include_filter(cls):
|
||||
obj = bpy.context.scene.camera
|
||||
if not obj:
|
||||
return
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
if not element:
|
||||
return
|
||||
return bool(ifcopenshell.util.element.get_pset(element, "EPset_Drawing", "Include"))
|
||||
|
||||
@classmethod
|
||||
def has_exclude_filter(cls):
|
||||
obj = bpy.context.scene.camera
|
||||
if not obj:
|
||||
return
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
if not element:
|
||||
return
|
||||
return bool(ifcopenshell.util.element.get_pset(element, "EPset_Drawing", "Exclude"))
|
||||
|
||||
|
||||
class DocumentsData:
|
||||
data = {}
|
||||
is_loaded = False
|
||||
|
||||
@@ -52,15 +52,20 @@ class profile_consequential:
|
||||
cls.test_name = test_name
|
||||
|
||||
@classmethod
|
||||
def log(cls):
|
||||
def log(cls, args=[]):
|
||||
if cls.start_time is not None:
|
||||
cls.lines.append(f"{cls.test_name}\t{timer() - cls.start_time:.10f}")
|
||||
args = "" if not args else "\t" + "\t".join(args)
|
||||
cls.lines.append(f"{cls.test_name}\t{timer() - cls.start_time:.10f}{args}")
|
||||
|
||||
@classmethod
|
||||
def stop(cls):
|
||||
cls.log()
|
||||
cls.start_time = None
|
||||
print("\n".join(cls.lines))
|
||||
lines = "\n".join(cls.lines)
|
||||
print(lines)
|
||||
import pyperclip
|
||||
|
||||
pyperclip.copy(lines)
|
||||
cls.lines = []
|
||||
|
||||
|
||||
@@ -156,9 +161,9 @@ class BaseDecorator:
|
||||
os.path.join(bpy.context.scene.BIMProperties.data_dir, "fonts", "OpenGost Type B TT.ttf")
|
||||
)
|
||||
|
||||
# 3D_POLYLINE_UNIFORM_COLOR is good for smoothed lines since `bgl.enable(GL_LINE_SMOOTH)` is deprecated
|
||||
self.line_shader = gpu.shader.from_builtin("3D_POLYLINE_UNIFORM_COLOR")
|
||||
self.base_shader = gpu.shader.from_builtin("3D_UNIFORM_COLOR")
|
||||
# POLYLINE_UNIFORM_COLOR is good for smoothed lines since `bgl.enable(GL_LINE_SMOOTH)` is deprecated
|
||||
self.line_shader = gpu.shader.from_builtin("POLYLINE_UNIFORM_COLOR")
|
||||
self.base_shader = gpu.shader.from_builtin("UNIFORM_COLOR")
|
||||
|
||||
def get_camera_width_mm(self):
|
||||
# Horrific prototype code to ensure bgl draws at drawing scales
|
||||
@@ -385,8 +390,6 @@ class BaseDecorator:
|
||||
# 0 is the default font, but we're fancier than that
|
||||
font_id = self.font_id
|
||||
|
||||
dpi = context.preferences.system.dpi
|
||||
|
||||
color = context.preferences.addons["blenderbim"].preferences.decorations_colour
|
||||
|
||||
ang = -Vector((1, 0)).angle_signed(text_dir)
|
||||
@@ -406,7 +409,7 @@ class BaseDecorator:
|
||||
font_size_px = int(0.004118616 * mm_to_px) * font_size_mm / 2.5
|
||||
pos = pos - line_no * font_size_px * rotation_matrix[1]
|
||||
|
||||
blf.size(font_id, font_size_px, dpi)
|
||||
blf.size(font_id, font_size_px)
|
||||
|
||||
if box_alignment or center or vcenter:
|
||||
w, h = blf.dimensions(font_id, text)
|
||||
@@ -798,7 +801,7 @@ class AngleDecorator(BaseDecorator):
|
||||
angle_rad = acos(cos_a)
|
||||
angle = angle_rad / pi * 180
|
||||
except ZeroDivisionError:
|
||||
angle = 0
|
||||
angle_rad, angle = 0, 0
|
||||
|
||||
# calculate angle position
|
||||
p0, p1, p2 = [location_3d_to_region_2d(region, region3d, p) for p in vertices[i0 : i1 + 2]]
|
||||
@@ -1558,15 +1561,15 @@ class CutDecorator:
|
||||
gpu.state.point_size_set(1)
|
||||
gpu.state.blend_set("ALPHA")
|
||||
|
||||
# 3D_POLYLINE_UNIFORM_COLOR is good for smoothed lines since `bgl.enable(GL_LINE_SMOOTH)` is deprecated
|
||||
self.line_shader = gpu.shader.from_builtin("3D_POLYLINE_UNIFORM_COLOR")
|
||||
# POLYLINE_UNIFORM_COLOR is good for smoothed lines since `bgl.enable(GL_LINE_SMOOTH)` is deprecated
|
||||
self.line_shader = gpu.shader.from_builtin("POLYLINE_UNIFORM_COLOR")
|
||||
self.line_shader.bind()
|
||||
# POLYLINE_UNIFORM_COLOR specific uniforms
|
||||
self.line_shader.uniform_float("viewportSize", (context.region.width, context.region.height))
|
||||
self.line_shader.uniform_float("lineWidth", 2.0)
|
||||
|
||||
# general shader
|
||||
self.shader = gpu.shader.from_builtin("3D_UNIFORM_COLOR")
|
||||
self.shader = gpu.shader.from_builtin("UNIFORM_COLOR")
|
||||
self.shader.bind()
|
||||
|
||||
black = (0, 0, 0, 1)
|
||||
@@ -1926,7 +1929,7 @@ class DecorationsHandler:
|
||||
if cls.installed:
|
||||
cls.uninstall()
|
||||
handler = cls()
|
||||
# NOTE: we USE POST_PIXEL here so that we can draw use both 3D_POLYLINE_UNIFORM_COLOR
|
||||
# NOTE: we USE POST_PIXEL here so that we can use both POLYLINE_UNIFORM_COLOR
|
||||
# and drawing text in the same handler. BUT this means that we supply coordinates in WINSPACE
|
||||
cls.installed = SpaceView3D.draw_handler_add(handler, (context,), "WINDOW", "POST_PIXEL")
|
||||
|
||||
@@ -1944,10 +1947,12 @@ class DecorationsHandler:
|
||||
self.decorators[object_type] = self.decorators["FALL"]
|
||||
|
||||
def get_objects_and_decorators(self, collection):
|
||||
# TODO: do it in data instead of the handler for performance?
|
||||
results = []
|
||||
viewport = bpy.context.space_data
|
||||
|
||||
for obj in collection.all_objects:
|
||||
if obj.hide_get():
|
||||
if not obj.visible_get(viewport=viewport):
|
||||
continue
|
||||
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
import bpy
|
||||
import blenderbim.bim.module.drawing.decoration as decoration
|
||||
import blenderbim.tool as tool
|
||||
from bpy.app.handlers import persistent
|
||||
|
||||
|
||||
@@ -37,10 +38,28 @@ def depsgraph_update_pre_handler(scene):
|
||||
def set_active_camera_resolution(scene):
|
||||
if not scene.camera or "/" not in scene.camera.name or not scene.DocProperties.drawings:
|
||||
return
|
||||
props = scene.camera.data.BIMCameraProperties
|
||||
ortho_scale = max((props.width, props.height))
|
||||
aspect_ratio = props.width / props.height
|
||||
if (
|
||||
scene.render.resolution_x != scene.camera.data.BIMCameraProperties.raster_x
|
||||
or scene.render.resolution_y != scene.camera.data.BIMCameraProperties.raster_y
|
||||
(scene.camera.data.ortho_scale != ortho_scale)
|
||||
or (scene.render.resolution_x / scene.render.resolution_y != aspect_ratio)
|
||||
):
|
||||
scene.render.resolution_x = scene.camera.data.BIMCameraProperties.raster_x
|
||||
scene.render.resolution_y = scene.camera.data.BIMCameraProperties.raster_y
|
||||
scene.camera.data.ortho_scale = ortho_scale
|
||||
|
||||
diagram_scale = tool.Drawing.get_diagram_scale(scene.camera)
|
||||
scale_ratio = tool.Drawing.get_scale_ratio(diagram_scale["Scale"])
|
||||
|
||||
if props.width > props.height:
|
||||
aspect_ratio = props.height / props.width
|
||||
raster_x = ortho_scale * scale_ratio * props.dpi / 0.0254
|
||||
raster_y = ortho_scale * aspect_ratio * scale_ratio * props.dpi / 0.0254
|
||||
else:
|
||||
aspect_ratio = props.width / props.height
|
||||
raster_x = ortho_scale * aspect_ratio * scale_ratio * props.dpi / 0.0254
|
||||
raster_y = ortho_scale * scale_ratio * props.dpi / 0.0254
|
||||
|
||||
scene.render.resolution_x = scene.camera.data.BIMCameraProperties.raster_x = int(raster_x)
|
||||
scene.render.resolution_y = scene.camera.data.BIMCameraProperties.raster_y = int(raster_y)
|
||||
|
||||
current_drawing = scene.DocProperties.drawings[scene.DocProperties.current_drawing_index]
|
||||
|
||||
@@ -182,8 +182,12 @@ def format_distance(
|
||||
|
||||
# Check values and compose string
|
||||
if inches == 12:
|
||||
feet += 1
|
||||
inches = 0
|
||||
if unit_length == "INCHES":
|
||||
inches = 12
|
||||
if unit_length == "FEET":
|
||||
feet += 1
|
||||
inches = 0
|
||||
|
||||
|
||||
if not isArea:
|
||||
add_inches = bool(inches) or not suppress_zero_inches
|
||||
|
||||
@@ -26,7 +26,6 @@ import shutil
|
||||
import hashlib
|
||||
import shapely
|
||||
import subprocess
|
||||
import webbrowser
|
||||
import numpy as np
|
||||
import multiprocessing
|
||||
import ifcopenshell
|
||||
@@ -42,15 +41,16 @@ import blenderbim.bim.module.drawing.annotation as annotation
|
||||
import blenderbim.bim.module.drawing.sheeter as sheeter
|
||||
import blenderbim.bim.module.drawing.scheduler as scheduler
|
||||
import blenderbim.bim.module.drawing.helper as helper
|
||||
import blenderbim.bim.export_ifc
|
||||
from blenderbim.bim.module.drawing.decoration import CutDecorator
|
||||
from blenderbim.bim.module.drawing.data import DecoratorData, DrawingsData
|
||||
import blenderbim.bim.export_ifc
|
||||
from lxml import etree
|
||||
from mathutils import Vector, Color
|
||||
from mathutils import Vector, Color, Matrix
|
||||
from timeit import default_timer as timer
|
||||
from blenderbim.bim.module.drawing.prop import RasterStyleProperty, Literal, RASTER_STYLE_PROPERTIES_EXCLUDE
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from pathlib import Path
|
||||
from bpy_extras.image_utils import load_image
|
||||
|
||||
cwd = os.path.dirname(os.path.realpath(__file__))
|
||||
|
||||
@@ -104,6 +104,9 @@ class AddAnnotationType(bpy.types.Operator, Operator):
|
||||
)
|
||||
element.ApplicableOccurrence = f"IfcAnnotation/{object_type}"
|
||||
|
||||
if props.create_representation_for_type and object_type == "IMAGE":
|
||||
bpy.ops.bim.add_reference_image("INVOKE_DEFAULT", use_existing_object_by_name=obj.name)
|
||||
|
||||
|
||||
class EnableAddAnnotationType(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.enable_add_annotation_type"
|
||||
@@ -260,7 +263,9 @@ class CreateDrawing(bpy.types.Operator):
|
||||
with profile("Combine SVG layers"):
|
||||
svg_path = self.combine_svgs(context, underlay_svg, linework_svg, annotation_svg)
|
||||
|
||||
tool.Drawing.open_with_user_command(context.preferences.addons["blenderbim"].preferences.svg_command, svg_path)
|
||||
tool.Drawing.open_with_user_command(
|
||||
context.preferences.addons["blenderbim"].preferences.svg_command, svg_path
|
||||
)
|
||||
|
||||
if self.print_all:
|
||||
bpy.ops.bim.activate_drawing(drawing=original_drawing_id, camera_view_point=False)
|
||||
@@ -489,6 +494,11 @@ class CreateDrawing(bpy.types.Operator):
|
||||
geom_settings = ifcopenshell.geom.settings(
|
||||
DISABLE_TRIANGULATION=True, STRICT_TOLERANCE=True, INCLUDE_CURVES=True
|
||||
)
|
||||
if ifc.by_id(body_context[0]).ContextType == "Plan" and "PLAN_VIEW" in target_view:
|
||||
offset = ifcopenshell.ifcopenshell_wrapper.float_array_3()
|
||||
# A 2mm Z offset to combat Z-fighting in plan or RCPs
|
||||
offset[2] = 0.002 if target_view == "PLAN_VIEW" else -0.002
|
||||
geom_settings.offset = offset
|
||||
geom_settings.set_context_ids(body_context)
|
||||
it = ifcopenshell.geom.iterator(
|
||||
geom_settings, ifc, multiprocessing.cpu_count(), include=elements
|
||||
@@ -508,6 +518,11 @@ class CreateDrawing(bpy.types.Operator):
|
||||
geom_settings = ifcopenshell.geom.settings(
|
||||
DISABLE_TRIANGULATION=True, STRICT_TOLERANCE=True, INCLUDE_CURVES=True
|
||||
)
|
||||
if ifc.by_id(annotation_context[0]).ContextType == "Plan" and "PLAN_VIEW" in target_view:
|
||||
offset = ifcopenshell.ifcopenshell_wrapper.float_array_3()
|
||||
# A 2mm Z offset to combat Z-fighting in plan or RCPs
|
||||
offset[2] = 0.002 if target_view == "PLAN_VIEW" else -0.002
|
||||
geom_settings.offset = offset
|
||||
geom_settings.set_context_ids(annotation_context)
|
||||
it = ifcopenshell.geom.iterator(
|
||||
geom_settings, ifc, multiprocessing.cpu_count(), include=elements
|
||||
@@ -535,7 +550,7 @@ class CreateDrawing(bpy.types.Operator):
|
||||
root = etree.fromstring(results)
|
||||
|
||||
group = root.find("{http://www.w3.org/2000/svg}g")
|
||||
if not group:
|
||||
if group is None:
|
||||
with open(svg_path, "wb") as svg:
|
||||
svg.write(etree.tostring(root))
|
||||
|
||||
@@ -919,7 +934,7 @@ class CreateDrawing(bpy.types.Operator):
|
||||
join_criteria = join_criteria.split(",")
|
||||
else:
|
||||
# Drawing convention states that same objects classes with the same material are merged when cut.
|
||||
join_criteria = ["class", "material.Name", 'r"Pset.*Common"."Status"']
|
||||
join_criteria = ["class", "material.Name", "/Pset_.*Common/.Status", "EPset_Status.Status"]
|
||||
|
||||
group = root.find("{http://www.w3.org/2000/svg}g")
|
||||
joined_paths = {}
|
||||
@@ -951,17 +966,21 @@ class CreateDrawing(bpy.types.Operator):
|
||||
# alone (e.g. dangles, cuts, invalids). See #3421.
|
||||
line_strings = []
|
||||
old_paths = []
|
||||
has_open_paths = False
|
||||
for path in el.findall("{http://www.w3.org/2000/svg}path"):
|
||||
for subpath in path.attrib["d"].split("M")[1:]:
|
||||
subpath = "M" + subpath.strip()
|
||||
coords = [[round(float(o), 1) for o in co[1:].split(",")] for co in subpath.split()]
|
||||
if coords[0] != coords[-1]:
|
||||
has_open_paths = True
|
||||
line_strings.append(shapely.LineString(coords))
|
||||
old_paths.append(path)
|
||||
unioned_line_strings = shapely.union_all(shapely.GeometryCollection(line_strings))
|
||||
if hasattr(unioned_line_strings, "geoms"):
|
||||
results = shapely.polygonize_full(unioned_line_strings.geoms)
|
||||
else:
|
||||
results = []
|
||||
|
||||
results = []
|
||||
if has_open_paths:
|
||||
unioned_line_strings = shapely.union_all(shapely.GeometryCollection(line_strings))
|
||||
if hasattr(unioned_line_strings, "geoms"):
|
||||
results = shapely.polygonize_full(unioned_line_strings.geoms)
|
||||
|
||||
# If we succeeded in generating new path geometry, remove all the
|
||||
# old paths and add new ones.
|
||||
@@ -1421,25 +1440,8 @@ class ActivateModel(bpy.types.Operator):
|
||||
CutDecorator.uninstall()
|
||||
|
||||
if not bpy.app.background:
|
||||
view3d_context = dict()
|
||||
|
||||
for window in bpy.context.window_manager.windows:
|
||||
screen = window.screen
|
||||
for area in screen.areas:
|
||||
if area.type == "VIEW_3D":
|
||||
view3d_context["window"] = window
|
||||
view3d_context["screen"] = screen
|
||||
view3d_context["area"] = area
|
||||
for region in area.regions:
|
||||
if region.type == "WINDOW":
|
||||
view3d_context["region"] = region
|
||||
break
|
||||
break
|
||||
if view3d_context:
|
||||
break
|
||||
|
||||
if view3d_context:
|
||||
bpy.ops.object.hide_view_clear(view3d_context)
|
||||
with context.temp_override(**tool.Blender.get_viewport_context()):
|
||||
bpy.ops.object.hide_view_clear()
|
||||
bpy.ops.bim.activate_status_filters()
|
||||
|
||||
subcontext = ifcopenshell.util.representation.get_context(tool.Ifc.get(), "Model", "Body", "MODEL_VIEW")
|
||||
@@ -2008,11 +2010,11 @@ class AddReferenceToSheet(bpy.types.Operator, Operator):
|
||||
props = context.scene.DocProperties
|
||||
active_reference = props.references[props.active_reference_index]
|
||||
active_sheet = tool.Drawing.get_active_sheet(context)
|
||||
reference = tool.Ifc.get().by_id(active_reference.ifc_definition_id)
|
||||
extref = tool.Ifc.get().by_id(active_reference.ifc_definition_id)
|
||||
if tool.Ifc.get_schema() == "IFC2X3":
|
||||
reference_location = tool.Drawing.get_path_with_ext(reference.DocumentReferences[0].Location, "svg")
|
||||
extref_location = tool.Drawing.get_path_with_ext(extref.DocumentReferences[0].Location, "svg")
|
||||
else:
|
||||
reference_location = tool.Drawing.get_path_with_ext(reference.HasDocumentReferences[0].Location, "svg")
|
||||
extref_location = tool.Drawing.get_path_with_ext(extref.HasDocumentReferences[0].Location, "svg")
|
||||
|
||||
sheet = tool.Ifc.get().by_id(active_sheet.ifc_definition_id)
|
||||
if not sheet.is_a("IfcDocumentInformation"):
|
||||
@@ -2020,30 +2022,30 @@ class AddReferenceToSheet(bpy.types.Operator, Operator):
|
||||
|
||||
references = tool.Drawing.get_document_references(sheet)
|
||||
|
||||
has_reference = False
|
||||
has_extref = False
|
||||
for reference in references:
|
||||
if reference.Location == reference_location:
|
||||
has_reference = True
|
||||
if reference.Location == extref_location:
|
||||
has_extref = True
|
||||
break
|
||||
if has_reference:
|
||||
if has_extref:
|
||||
return
|
||||
|
||||
if not tool.Drawing.does_file_exist(tool.Ifc.resolve_uri(reference_location)):
|
||||
self.report({"ERROR"}, f"Cannot find reference svg by path {reference_location}.")
|
||||
if not tool.Drawing.does_file_exist(tool.Ifc.resolve_uri(extref_location)):
|
||||
self.report({"ERROR"}, f"Cannot find reference svg by path {extref_location}.")
|
||||
return
|
||||
|
||||
reference = tool.Ifc.run("document.add_reference", information=sheet)
|
||||
id_attr = "ItemReference" if tool.Ifc.get_schema() == "IFC2X3" else "Identification"
|
||||
attributes = {
|
||||
id_attr: str(len([r for r in references if r.Description in ("DRAWING", "REFERENCE")]) + 1),
|
||||
"Location": reference_location,
|
||||
"Location": extref_location,
|
||||
"Description": "REFERENCE",
|
||||
}
|
||||
tool.Ifc.run("document.edit_reference", reference=reference, attributes=attributes)
|
||||
|
||||
sheet_builder = sheeter.SheetBuilder()
|
||||
sheet_builder.data_dir = context.scene.BIMProperties.data_dir
|
||||
sheet_builder.add_document(reference, reference, sheet)
|
||||
sheet_builder.add_document(reference, extref, sheet)
|
||||
|
||||
tool.Drawing.import_sheets()
|
||||
|
||||
@@ -2283,6 +2285,27 @@ class RemoveTextLiteral(bpy.types.Operator):
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class AssignSelectedObjectAsProduct(bpy.types.Operator):
|
||||
bl_idname = "bim.assign_selected_as_product"
|
||||
bl_label = "Assign Selected Object As Product"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
if len(context.selected_objects) != 2:
|
||||
cls.poll_message_set("2 objects need to be selected")
|
||||
return False
|
||||
return True
|
||||
|
||||
def execute(self, context):
|
||||
objs = context.selected_objects[:]
|
||||
objs.remove(context.active_object)
|
||||
other_selected_object = next(obj for obj in context.selected_objects if obj != context.active_object)
|
||||
context.active_object.BIMAssignedProductProperties.relating_product = other_selected_object
|
||||
bpy.ops.bim.edit_assigned_product()
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class EditAssignedProduct(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.edit_assigned_product"
|
||||
bl_label = "Edit Text Product"
|
||||
@@ -2522,3 +2545,156 @@ class SelectAssignedProduct(bpy.types.Operator, Operator):
|
||||
|
||||
def _execute(self, context):
|
||||
core.select_assigned_product(tool.Drawing, context)
|
||||
|
||||
|
||||
class EnableEditingElementFilter(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.enable_editing_element_filter"
|
||||
bl_label = "Enable Editing Element Filter"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
filter_mode: bpy.props.StringProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
obj = bpy.context.scene.camera
|
||||
if obj:
|
||||
obj.data.BIMCameraProperties.filter_mode = self.filter_mode
|
||||
|
||||
|
||||
class EditElementFilter(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.edit_element_filter"
|
||||
bl_label = "Edit Element Filter"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
filter_mode: bpy.props.StringProperty()
|
||||
|
||||
def _execute(self, context):
|
||||
props = context.active_object.data.BIMCameraProperties
|
||||
obj = bpy.context.scene.camera
|
||||
element = tool.Ifc.get_entity(obj)
|
||||
pset = tool.Pset.get_element_pset(element, "EPset_Drawing")
|
||||
if self.filter_mode == "INCLUDE":
|
||||
query = tool.Search.export_filter_query(props.include_filter_groups) or None
|
||||
ifcopenshell.api.run("pset.edit_pset", tool.Ifc.get(), pset=pset, properties={"Include": query})
|
||||
elif self.filter_mode == "EXCLUDE":
|
||||
query = tool.Search.export_filter_query(props.exclude_filter_groups) or None
|
||||
ifcopenshell.api.run("pset.edit_pset", tool.Ifc.get(), pset=pset, properties={"Exclude": query})
|
||||
obj.data.BIMCameraProperties.filter_mode = "NONE"
|
||||
bpy.ops.bim.activate_drawing(drawing=element.id(), camera_view_point=False)
|
||||
|
||||
|
||||
class AddReferenceImage(bpy.types.Operator, Operator):
|
||||
bl_idname = "bim.add_reference_image"
|
||||
bl_label = "Add Reference Image"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
|
||||
use_relative_path: bpy.props.BoolProperty(name="Use Relative Path", default=True)
|
||||
filepath: bpy.props.StringProperty(
|
||||
name="File Path", description="Filepath used to import from", maxlen=1024, default="", subtype="FILE_PATH"
|
||||
)
|
||||
filter_image: bpy.props.BoolProperty(default=True, options={"HIDDEN", "SKIP_SAVE"})
|
||||
filter_folder: bpy.props.BoolProperty(default=True, options={"HIDDEN", "SKIP_SAVE"})
|
||||
|
||||
override_existing_image: bpy.props.BoolProperty(
|
||||
name="Override Existing Image",
|
||||
default=True,
|
||||
description=(
|
||||
"Override image if it was previously loaded to Blender. If disabled, will always create a new image"
|
||||
),
|
||||
)
|
||||
use_existing_object_by_name: bpy.props.StringProperty(
|
||||
name="Use Existing Object By Name",
|
||||
description="Existing object name to add a style with reference image to. If not provided will create a new object.",
|
||||
options={"SKIP_SAVE"},
|
||||
)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
if Path(tool.Ifc.get_path()).is_file():
|
||||
layout.prop(self, "use_relative_path")
|
||||
else:
|
||||
self.use_relative_path = False
|
||||
layout.label(text="Save the .ifc file first ")
|
||||
layout.label(text="to use relative paths.")
|
||||
layout.prop(self, "override_existing_image")
|
||||
layout.prop(self, "use_existing_object_by_name")
|
||||
|
||||
def invoke(self, context, event):
|
||||
context.window_manager.fileselect_add(self)
|
||||
return {"RUNNING_MODAL"}
|
||||
|
||||
def _execute(self, context):
|
||||
abs_path = Path(self.filepath)
|
||||
if self.use_relative_path:
|
||||
image_filepath = abs_path.relative_to(Path(tool.Ifc.get_path()).parent)
|
||||
else:
|
||||
image_filepath = abs_path
|
||||
ifc_file = tool.Ifc.get()
|
||||
|
||||
if self.override_existing_image:
|
||||
params = {"check_existing": True, "force_reload": True}
|
||||
else:
|
||||
params = {"check_existing": False}
|
||||
image = load_image(abs_path.name, abs_path.parent, **params)
|
||||
|
||||
def bm_add_image_plane(mesh):
|
||||
bm = tool.Blender.get_bmesh_for_mesh(mesh, clean=True)
|
||||
plane_scale = (Vector(image.size) / min(image.size)).to_3d()
|
||||
matrix = Matrix.LocRotScale(None, None, plane_scale)
|
||||
bmesh.ops.create_grid(bm, x_segments=1, y_segments=1, size=1, matrix=matrix, calc_uvs=False)
|
||||
tool.Blender.apply_bmesh(mesh, bm)
|
||||
|
||||
if self.use_existing_object_by_name:
|
||||
obj = bpy.data.objects[self.use_existing_object_by_name]
|
||||
bm_add_image_plane(obj.data)
|
||||
bpy.ops.bim.update_representation(obj=obj.name, ifc_representation_class="")
|
||||
else:
|
||||
temp_mesh = bpy.data.meshes.new("temp_mesh")
|
||||
bm_add_image_plane(temp_mesh)
|
||||
obj = bpy.data.objects.new(image_filepath.stem, temp_mesh)
|
||||
tool.Drawing.run_root_assign_class(
|
||||
obj=obj,
|
||||
ifc_class="IfcAnnotation",
|
||||
predefined_type="IMAGE",
|
||||
should_add_representation=True,
|
||||
context=ifcopenshell.util.representation.get_context(ifc_file, "Model", "Body", "MODEL_VIEW"),
|
||||
ifc_representation_class=None,
|
||||
)
|
||||
tool.Blender.remove_data_block(temp_mesh)
|
||||
|
||||
tool.Blender.set_active_object(obj)
|
||||
|
||||
material = bpy.data.materials.new(name=image_filepath.stem)
|
||||
obj.data.materials.append(None) # new slot
|
||||
obj.material_slots[0].material = material
|
||||
bpy.ops.bim.add_style()
|
||||
|
||||
style = ifc_file.by_id(material.BIMMaterialProperties.ifc_style_id)
|
||||
tool.Style.assign_style_to_object(style, obj)
|
||||
|
||||
# TODO: IfcSurfaceStyleRendering is unnecessary here, added it only because
|
||||
# we don't support IfcSurfaceStyleWithTextures without Rendering yet
|
||||
shading_attributes = {
|
||||
"SurfaceColour": {
|
||||
"Red": 1.0,
|
||||
"Green": 1.0,
|
||||
"Blue": 1.0,
|
||||
},
|
||||
"Transparency": 0.0,
|
||||
"ReflectanceMethod": "NOTDEFINED",
|
||||
}
|
||||
ifcopenshell.api.run(
|
||||
"style.add_surface_style",
|
||||
tool.Ifc.get(),
|
||||
style=style,
|
||||
ifc_class="IfcSurfaceStyleRendering",
|
||||
attributes=shading_attributes,
|
||||
)
|
||||
texture = ifc_file.create_entity("IfcImageTexture", Mode="DIFFUSE", URLReference=image_filepath.as_posix())
|
||||
textures = [texture]
|
||||
ifc_file.create_entity("IfcTextureCoordinateGenerator", Maps=textures, Mode="COORD") # UV map
|
||||
tool.Ifc.run(
|
||||
"style.add_surface_style",
|
||||
style=style,
|
||||
ifc_class="IfcSurfaceStyleWithTextures",
|
||||
attributes={"Textures": textures},
|
||||
)
|
||||
tool.Style.reload_material_from_ifc(material)
|
||||
tool.Geometry.record_object_materials(obj)
|
||||
|
||||
@@ -25,6 +25,7 @@ import blenderbim.tool as tool
|
||||
import blenderbim.core.drawing as core
|
||||
import blenderbim.bim.module.drawing.annotation as annotation
|
||||
import blenderbim.bim.module.drawing.decoration as decoration
|
||||
from blenderbim.bim.prop import BIMFilterGroup
|
||||
from blenderbim.bim.module.drawing.data import DrawingsData, DecoratorData, SheetsData, AnnotationData
|
||||
from blenderbim.bim.module.drawing.data import refresh as refresh_drawing_data
|
||||
from pathlib import Path
|
||||
@@ -312,7 +313,6 @@ class DocProperties(PropertyGroup):
|
||||
should_use_underlay_cache: BoolProperty(name="Use Underlay Cache", default=False)
|
||||
should_use_linework_cache: BoolProperty(name="Use Linework Cache", default=False)
|
||||
should_use_annotation_cache: BoolProperty(name="Use Annotation Cache", default=False)
|
||||
should_extract: BoolProperty(name="Should Extract", default=True)
|
||||
is_editing_drawings: BoolProperty(name="Is Editing Drawings", default=False)
|
||||
is_editing_schedules: BoolProperty(name="Is Editing Schedules", default=False)
|
||||
is_editing_references: BoolProperty(name="Is Editing References", default=False)
|
||||
@@ -375,8 +375,14 @@ class BIMCameraProperties(PropertyGroup):
|
||||
custom_scale_denominator: bpy.props.StringProperty(default="100", update=update_diagram_scale)
|
||||
raster_x: IntProperty(name="Raster X", default=1000)
|
||||
raster_y: IntProperty(name="Raster Y", default=1000)
|
||||
dpi: IntProperty(name="DPI", default=75)
|
||||
width: FloatProperty(name="Width", default=50, subtype="DISTANCE")
|
||||
height: FloatProperty(name="Height", default=50, subtype="DISTANCE")
|
||||
is_nts: BoolProperty(name="Is NTS", update=update_is_nts)
|
||||
active_drawing_style_index: IntProperty(name="Active Drawing Style Index")
|
||||
filter_mode: StringProperty(name="Filter Mode", default="NONE")
|
||||
include_filter_groups: CollectionProperty(type=BIMFilterGroup, name="Include Filter")
|
||||
exclude_filter_groups: CollectionProperty(type=BIMFilterGroup, name="Exclude Filter")
|
||||
|
||||
# For now, this JSON dump are all the parameters that determine a camera's "Block representation"
|
||||
# By checking this, you will know whether or not the camera IFC representation needs to be refreshed
|
||||
@@ -509,6 +515,7 @@ ANNOTATION_TYPES_DATA = {
|
||||
"REVISION_CLOUD":("Revision Cloud", "Add revision cloud", "VOLUME_DATA", "mesh"),
|
||||
"FILL_AREA": ("Fill Area", "", "NODE_TEXTURE", "mesh"),
|
||||
"FALL": ("Fall", "", "SORT_ASC", "curve"),
|
||||
"IMAGE": ("Image", "Add reference image attached to the drawing", "TEXTURE", "mesh"),
|
||||
}
|
||||
# fmt: on
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
|
||||
from blenderbim.bim.module.drawing.svgwriter import SvgWriter
|
||||
import svgwrite
|
||||
import openpyxl
|
||||
|
||||
from odf.opendocument import load as load_ods
|
||||
from odf.table import Table, TableRow, TableColumn, TableCell
|
||||
@@ -62,6 +63,156 @@ class Scheduler:
|
||||
)
|
||||
self.padding = 1
|
||||
self.margin = 1
|
||||
if infile.endswith("ods"):
|
||||
self.schedule_ods(infile, outfile)
|
||||
elif infile.endswith("xlsx"):
|
||||
self.schedule_xlsx(infile, outfile)
|
||||
|
||||
def schedule_xlsx(self, infile, outfile):
|
||||
workbook = openpyxl.open(infile, data_only=True)
|
||||
sheet = workbook.active
|
||||
|
||||
column_dimensions = {k: v.width for k, v in sheet.column_dimensions.items()}
|
||||
row_dimensions = {k: v.height for k, v in sheet.row_dimensions.items()}
|
||||
default_width = 8.43 # 8.43 characters wide
|
||||
default_height = 15 # 15pt seems to be the default height
|
||||
|
||||
merged_cells = []
|
||||
for cell_range in sheet.merged_cells.ranges:
|
||||
pass
|
||||
|
||||
y = self.margin
|
||||
rows = list(sheet.iter_rows())
|
||||
total_rows = len(rows)
|
||||
for i, row in enumerate(rows):
|
||||
# The last row may contain only null values
|
||||
if i == (total_rows - 1) and not [c for c in row if c.value is not None]:
|
||||
continue
|
||||
|
||||
x = self.margin
|
||||
for cell in row:
|
||||
if isinstance(cell, openpyxl.cell.cell.MergedCell):
|
||||
column_letter = openpyxl.utils.get_column_letter(cell.column)
|
||||
width = column_dimensions.get(column_letter, default_width)
|
||||
else:
|
||||
width = column_dimensions.get(cell.column_letter, default_width)
|
||||
width = self.convert_character_width_to_mm(width)
|
||||
height = row_dimensions.get(cell.row, default_height)
|
||||
height = self.convert_to_mm(f"{height}pt")
|
||||
|
||||
if isinstance(cell, openpyxl.cell.cell.MergedCell):
|
||||
x += width
|
||||
continue
|
||||
|
||||
unmerged_width = width
|
||||
unmerged_height = height
|
||||
|
||||
for cell_range in sheet.merged_cells.ranges:
|
||||
if cell.coordinate not in cell_range:
|
||||
continue
|
||||
merged_width = 0
|
||||
merged_height = 0
|
||||
for merged_column in cell_range.cols:
|
||||
merged_cell = sheet.cell(*merged_column[0])
|
||||
column_letter = openpyxl.utils.get_column_letter(merged_cell.column)
|
||||
width = column_dimensions.get(cell.column_letter, default_width)
|
||||
width = self.convert_character_width_to_mm(width)
|
||||
merged_width += width
|
||||
for merged_row in cell_range.rows:
|
||||
merged_cell = sheet.cell(*merged_row[0])
|
||||
height = row_dimensions.get(merged_cell.row, default_height)
|
||||
height = self.convert_to_mm(f"{height}pt")
|
||||
merged_height += height
|
||||
width = merged_width
|
||||
height = merged_height
|
||||
break
|
||||
|
||||
if cell.fill.patternType:
|
||||
background_color = "#" + str(cell.fill.bgColor.rgb).lower()[2:]
|
||||
else:
|
||||
background_color = "#ffffff"
|
||||
|
||||
self.svg.add(
|
||||
self.svg.rect(
|
||||
insert=(x, y),
|
||||
size=(width, height),
|
||||
style=f"fill: {background_color}; stroke-width:.125; stroke: #000000;",
|
||||
)
|
||||
)
|
||||
|
||||
if not cell.value:
|
||||
x += unmerged_width
|
||||
continue
|
||||
|
||||
font_size = cell.font.size or 11 # 11pt default
|
||||
font_size = font_size / FONT_SIZE_PT * FONT_SIZE # Magic?
|
||||
|
||||
text_position = [0.0, 0.0]
|
||||
if cell.alignment.horizontal == "left":
|
||||
text_position[0] = x + self.padding
|
||||
horizontal_align = "left"
|
||||
elif cell.alignment.horizontal == "general" and isinstance(cell.value, str):
|
||||
text_position[0] = x + self.padding
|
||||
horizontal_align = "left"
|
||||
elif cell.alignment.horizontal in ("center", "justify", "centerContinuous", "distributed"):
|
||||
text_position[0] = x + width / 2
|
||||
horizontal_align = "middle"
|
||||
elif cell.alignment.horizontal == "right":
|
||||
text_position[0] = x + width - self.padding
|
||||
horizontal_align = "right"
|
||||
elif cell.alignment.horizontal == "general" and not isinstance(cell.value, str):
|
||||
text_position[0] = x + width - self.padding
|
||||
horizontal_align = "right"
|
||||
else:
|
||||
text_position[0] = x + self.padding
|
||||
horizontal_align = "left"
|
||||
|
||||
if cell.alignment.vertical == "top":
|
||||
text_position[1] = y + self.padding
|
||||
vertical_align = "top"
|
||||
elif cell.alignment.vertical in ("center", "justify", "distributed"):
|
||||
text_position[1] = y + height / 2
|
||||
vertical_align = "middle"
|
||||
elif cell.alignment.vertical == "bottom":
|
||||
text_position[1] = y + height - self.padding
|
||||
vertical_align = "bottom"
|
||||
else:
|
||||
text_position[1] = y + height - self.padding
|
||||
vertical_align = "bottom"
|
||||
|
||||
if vertical_align == "middle" and horizontal_align == "middle":
|
||||
box_alignment = "center"
|
||||
else:
|
||||
box_alignment = f"{vertical_align}-{horizontal_align}"
|
||||
|
||||
if cell.font.color:
|
||||
text_color = "#" + str(cell.font.color.rgb).lower()[2:]
|
||||
else:
|
||||
text_color = "#000000"
|
||||
|
||||
self.add_text(
|
||||
[cell.value],
|
||||
*text_position,
|
||||
font_size=font_size,
|
||||
box_alignment=box_alignment,
|
||||
wrap_text=cell.alignment.wrapText or False,
|
||||
cell_width=width,
|
||||
bold=cell.font.b,
|
||||
italic=cell.font.i,
|
||||
text_color=text_color,
|
||||
)
|
||||
|
||||
x += unmerged_width
|
||||
y += unmerged_height
|
||||
|
||||
total_width = x + self.margin
|
||||
total_height = y + self.margin
|
||||
self.svg["width"] = "{}mm".format(total_width)
|
||||
self.svg["height"] = "{}mm".format(total_height)
|
||||
self.svg["viewBox"] = "0 0 {} {}".format(total_width, total_height)
|
||||
self.svg.save(pretty=True)
|
||||
|
||||
def schedule_ods(self, infile, outfile):
|
||||
doc = load_ods(infile)
|
||||
|
||||
# useful for debugging ods
|
||||
@@ -386,6 +537,10 @@ class Scheduler:
|
||||
if len(text_lines) == 1 and not wrap_text:
|
||||
text_params.update(box_alignment_params)
|
||||
text_tag = self.svg.text(text_lines[0], insert=(x, y), **(text_params))
|
||||
if self.is_url(text_lines[0]):
|
||||
anchor = self.svg.a(text_lines[0].strip())
|
||||
anchor.add(text_tag)
|
||||
text_tag = anchor
|
||||
self.svg.add(text_tag)
|
||||
return
|
||||
|
||||
@@ -402,14 +557,44 @@ class Scheduler:
|
||||
else:
|
||||
wrapped_lines = text_lines
|
||||
|
||||
for line_number, text_line in enumerate(wrapped_lines[::-1]):
|
||||
if box_alignment.startswith("top"):
|
||||
dy_dir = 1
|
||||
line_number = 0
|
||||
elif box_alignment.startswith("bot"):
|
||||
dy_dir = -1
|
||||
line_number = 0
|
||||
else: # middle row
|
||||
# the idea is that the middle row should always stay in the center
|
||||
# e.g. dy offset for 3 lines is: 1, 0, -1
|
||||
# for 2 lines: 0.5, -0.5
|
||||
dy_dir = -1
|
||||
line_number = (len(wrapped_lines) - 1) / 2
|
||||
|
||||
for text_line in wrapped_lines[::dy_dir]:
|
||||
# position has to be inserted at tspan to avoid x offset between tspans
|
||||
tspan = self.svg.tspan(text_line, insert=(x, y), **text_params)
|
||||
# doing it here and not in tspan constructor because constructor adds unnecessary spaces
|
||||
tspan.update({"dy": f"-{line_number}em"})
|
||||
tspan.update({"dy": f"{line_number}em"})
|
||||
if self.is_url(text_line):
|
||||
anchor = self.svg.a(text_line.strip())
|
||||
anchor.add(tspan)
|
||||
tspan = anchor
|
||||
text_tag.add(tspan)
|
||||
line_number += dy_dir
|
||||
|
||||
self.svg.add(text_tag)
|
||||
|
||||
def is_url(self, value):
|
||||
return value.strip().startswith("http") and " " not in value.strip() and "://" in value # Wrong but fast
|
||||
|
||||
def convert_character_width_to_mm(self, value):
|
||||
# Excel measures widths in terms of "number of characters of the
|
||||
# default font", which is most commonly 11pt Calibri. The width of the
|
||||
# "0" character in Calibri is approximately 7px at 100% zoom.
|
||||
px_per_character = 7
|
||||
px_to_pt = 0.75
|
||||
return self.convert_to_mm(f"{value * px_per_character * px_to_pt}pt")
|
||||
|
||||
def convert_to_mm(self, value):
|
||||
# XSL is what defines the units of measurements in ODF
|
||||
# https://docs.oasis-open.org/office/v1.2/os/OpenDocument-v1.2-os-part1.html#datatype-positiveLength
|
||||
|
||||
@@ -288,9 +288,9 @@ class BaseShader:
|
||||
"""
|
||||
|
||||
def __init__(self):
|
||||
# 3D_POLYLINE_UNIFORM_COLOR is good for smoothed lines since `bgl.enable(GL_LINE_SMOOTH)` is deprecated
|
||||
self.line_shader = gpu.shader.from_builtin("3D_POLYLINE_UNIFORM_COLOR")
|
||||
self.base_shader = gpu.shader.from_builtin("3D_UNIFORM_COLOR")
|
||||
# POLYLINE_UNIFORM_COLOR is good for smoothed lines since `bgl.enable(GL_LINE_SMOOTH)` is deprecated
|
||||
self.line_shader = gpu.shader.from_builtin("POLYLINE_UNIFORM_COLOR")
|
||||
self.base_shader = gpu.shader.from_builtin("UNIFORM_COLOR")
|
||||
|
||||
def get_shader(self):
|
||||
"""Returns shader for this type"""
|
||||
|
||||
@@ -160,7 +160,8 @@ class SheetBuilder:
|
||||
x = float(image.attrib["x"])
|
||||
y = float(image.attrib["y"])
|
||||
if image.attrib["data-type"] == "view-title":
|
||||
image.attrib["x"] = str(x - readjust.x)
|
||||
image.attrib["x"] = str(x + readjust.x)
|
||||
# negate y offset because view-title comes AFTER foreground
|
||||
image.attrib["y"] = str(y - readjust.y)
|
||||
else:
|
||||
image.attrib["x"] = str(x + readjust.x)
|
||||
@@ -186,11 +187,11 @@ class SheetBuilder:
|
||||
|
||||
layout_tree.write(layout_path)
|
||||
|
||||
def add_document(self, reference, schedule, sheet):
|
||||
view_path = tool.Drawing.get_path_with_ext(tool.Drawing.get_document_uri(schedule), "svg")
|
||||
def add_document(self, reference, document, sheet):
|
||||
view_path = tool.Drawing.get_path_with_ext(tool.Drawing.get_document_uri(document), "svg")
|
||||
if not os.path.exists(view_path):
|
||||
tool.Drawing.create_svg_schedule(schedule)
|
||||
schedule_name = os.path.splitext(os.path.basename(view_path))[0]
|
||||
tool.Drawing.create_svg_document(document)
|
||||
document_name = os.path.splitext(os.path.basename(view_path))[0]
|
||||
layout_path = tool.Drawing.get_document_uri(sheet, "LAYOUT")
|
||||
layout_dir = os.path.dirname(layout_path)
|
||||
|
||||
@@ -206,12 +207,12 @@ class SheetBuilder:
|
||||
view_height = self.convert_to_mm(view_root.attrib.get("height"))
|
||||
|
||||
view = ET.SubElement(layout_root, "g")
|
||||
view.attrib["data-type"] = "schedule"
|
||||
view.attrib["data-id"] = str(reference.id())
|
||||
view.attrib["data-schedule"] = str(schedule.id())
|
||||
view.attrib["data-type"] = document.Scope.lower()
|
||||
view.attrib["data-document"] = str(document.id())
|
||||
|
||||
foreground = ET.SubElement(view, "image")
|
||||
foreground.attrib["data-type"] = "table"
|
||||
foreground.attrib["data-type"] = "content"
|
||||
foreground.attrib["xlink:href"] = os.path.relpath(view_path, layout_dir)
|
||||
foreground.attrib["x"] = str(DEFAULT_POSITION.x)
|
||||
foreground.attrib["y"] = str(DEFAULT_POSITION.y)
|
||||
@@ -262,7 +263,7 @@ class SheetBuilder:
|
||||
|
||||
self.build_titleblock(root, sheet)
|
||||
self.build_drawings(root, sheet)
|
||||
self.build_schedules(root, sheet)
|
||||
self.build_documents(root, sheet)
|
||||
|
||||
with open(sheet_path, "wb") as output:
|
||||
tree.write(output)
|
||||
@@ -345,8 +346,12 @@ class SheetBuilder:
|
||||
def build_drawings(self, root, sheet):
|
||||
for view in root.findall('{http://www.w3.org/2000/svg}g[@data-type="drawing"]'):
|
||||
drawing_id = int(view.attrib["data-id"])
|
||||
reference = tool.Ifc.get().by_id(int(view.attrib["data-id"]))
|
||||
drawing = tool.Ifc.get().by_id(view.attrib["data-drawing"])
|
||||
try:
|
||||
reference = tool.Ifc.get().by_id(int(view.attrib["data-id"]))
|
||||
drawing = tool.Ifc.get().by_id(view.attrib["data-drawing"])
|
||||
except:
|
||||
# Perhaps the SVG has outdated content or is edited externally which we cannot control.
|
||||
continue
|
||||
|
||||
images = view.findall("{http://www.w3.org/2000/svg}image")
|
||||
|
||||
@@ -385,10 +390,17 @@ class SheetBuilder:
|
||||
for image in images:
|
||||
view.remove(image)
|
||||
|
||||
def build_schedules(self, root, sheet):
|
||||
for view in root.findall('{http://www.w3.org/2000/svg}g[@data-type="schedule"]'):
|
||||
reference = tool.Ifc.get().by_id(int(view.attrib["data-id"]))
|
||||
schedule = tool.Ifc.get().by_id(int(view.attrib["data-schedule"]))
|
||||
def build_documents(self, root, sheet):
|
||||
schedules = root.findall('{http://www.w3.org/2000/svg}g[@data-type="schedule"]')
|
||||
references = root.findall('{http://www.w3.org/2000/svg}g[@data-type="reference"]')
|
||||
documents = schedules + references
|
||||
for view in documents:
|
||||
try:
|
||||
reference = tool.Ifc.get().by_id(int(view.attrib["data-id"]))
|
||||
document = tool.Ifc.get().by_id(int(view.attrib["data-document"]))
|
||||
except:
|
||||
# Perhaps the SVG has outdated content or is edited externally which we cannot control.
|
||||
continue
|
||||
|
||||
images = view.findall("{http://www.w3.org/2000/svg}image")
|
||||
|
||||
@@ -396,7 +408,7 @@ class SheetBuilder:
|
||||
view_title = None
|
||||
|
||||
for image in images:
|
||||
if image.attrib["data-type"] == "table":
|
||||
if image.attrib["data-type"] == "content":
|
||||
table = image
|
||||
elif image.attrib["data-type"] == "view-title":
|
||||
view_title = image
|
||||
@@ -409,7 +421,7 @@ class SheetBuilder:
|
||||
data = reference.get_info()
|
||||
data.update({"Sheet" + k: v for k, v in sheet.get_info().items()})
|
||||
if not data["Name"]:
|
||||
data["Name"] = schedule.Name or "Unnamed"
|
||||
data["Name"] = document.Name or "Unnamed"
|
||||
view.append(self.parse_embedded_svg(view_title, data))
|
||||
|
||||
for image in images:
|
||||
|
||||
@@ -160,7 +160,7 @@ class SvgWriter:
|
||||
def find_xml_symbol_by_id(self, id):
|
||||
tree = ET.parse(self.resource_paths["Symbols"])
|
||||
xml_symbol = tree.find(f'.//*[@id="{id}"]')
|
||||
return External(xml_symbol) if xml_symbol else None
|
||||
return External(xml_symbol) if xml_symbol is not None else None
|
||||
|
||||
def add_patterns(self):
|
||||
path = self.resource_paths["Patterns"]
|
||||
|
||||
@@ -25,34 +25,35 @@ from blenderbim.bim.module.drawing.data import (
|
||||
SheetsData,
|
||||
DocumentsData,
|
||||
DrawingsData,
|
||||
ElementFiltersData,
|
||||
DecoratorData,
|
||||
)
|
||||
from blenderbim.bim.module.drawing.prop import ANNOTATION_TYPES_DATA
|
||||
|
||||
|
||||
class BIM_PT_camera(Panel):
|
||||
bl_label = "Drawing Generation"
|
||||
bl_label = "Active Drawing"
|
||||
bl_idname = "BIM_PT_camera"
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "data"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.camera and hasattr(context.active_object.data, "BIMCameraProperties")
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_tab_drawings"
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
|
||||
if "/" not in context.active_object.name:
|
||||
layout.label(text="This is not a BIM camera.")
|
||||
if not (context.scene.camera and hasattr(context.scene.camera.data, "BIMCameraProperties")):
|
||||
row = self.layout.row()
|
||||
row.label(text="No Active Drawing", icon="ERROR")
|
||||
return
|
||||
|
||||
layout.use_property_split = True
|
||||
dprops = context.scene.DocProperties
|
||||
props = context.active_object.data.BIMCameraProperties
|
||||
if "/" not in context.scene.camera.name:
|
||||
self.layout.label(text="This is not a BIM camera.")
|
||||
return
|
||||
|
||||
col = layout.column(align=True)
|
||||
self.layout.use_property_split = True
|
||||
dprops = context.scene.DocProperties
|
||||
props = context.scene.camera.data.BIMCameraProperties
|
||||
|
||||
col = self.layout.column(align=True)
|
||||
row = col.row(align=True)
|
||||
row.prop(props, "has_underlay", icon="OUTLINER_OB_IMAGE")
|
||||
row.prop(dprops, "should_use_underlay_cache", text="", icon="FILE_REFRESH")
|
||||
@@ -63,32 +64,90 @@ class BIM_PT_camera(Panel):
|
||||
row.prop(props, "has_annotation", icon="MOD_EDGESPLIT")
|
||||
row.prop(dprops, "should_use_annotation_cache", text="", icon="FILE_REFRESH")
|
||||
|
||||
row = layout.row()
|
||||
row = self.layout.row()
|
||||
row.prop(props, "calculate_shapely_surfaces")
|
||||
row = layout.row()
|
||||
row = self.layout.row()
|
||||
row.prop(props, "calculate_svgfill_surfaces")
|
||||
|
||||
row = layout.row()
|
||||
row.prop(dprops, "should_extract")
|
||||
row = self.layout.row()
|
||||
row.prop(props, "width")
|
||||
row = self.layout.row()
|
||||
row.prop(props, "height")
|
||||
|
||||
row = layout.row()
|
||||
row.prop(props, "raster_x")
|
||||
row = layout.row()
|
||||
row.prop(props, "raster_y")
|
||||
row = self.layout.row()
|
||||
row.prop(context.scene.camera.data, "clip_end", text="Depth")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(props, "diagram_scale")
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(props, "diagram_scale", text="Scale")
|
||||
row.prop(props, "is_nts", text="", icon="MOD_EDGESPLIT")
|
||||
|
||||
if props.diagram_scale == "CUSTOM":
|
||||
row = layout.row(align=True)
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(props, "custom_scale_numerator", text="Custom Scale")
|
||||
row.prop(props, "custom_scale_denominator", text="")
|
||||
|
||||
row = layout.row(align=True)
|
||||
if props.has_underlay:
|
||||
row = self.layout.row()
|
||||
row.prop(props, "dpi")
|
||||
|
||||
row = self.layout.row(align=True)
|
||||
row.operator("bim.create_drawing", text="Create Drawing", icon="OUTPUT")
|
||||
op = row.operator("bim.open_drawing", icon="URL", text="")
|
||||
op.view = context.active_object.name.split("/")[1]
|
||||
op.view = context.scene.camera.name.split("/")[1]
|
||||
|
||||
|
||||
class BIM_PT_element_filters(Panel):
|
||||
bl_label = "Element Filters"
|
||||
bl_idname = "BIM_PT_element_filters"
|
||||
bl_options = {"DEFAULT_CLOSED"}
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_camera"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return (
|
||||
context.scene.camera
|
||||
and context.active_object
|
||||
and hasattr(context.active_object.data, "BIMCameraProperties")
|
||||
)
|
||||
|
||||
def draw(self, context):
|
||||
if not ElementFiltersData.is_loaded:
|
||||
ElementFiltersData.load()
|
||||
|
||||
props = context.scene.camera.data.BIMCameraProperties
|
||||
|
||||
if props.filter_mode == "INCLUDE":
|
||||
blenderbim.bim.helper.draw_filter(
|
||||
self.layout, props.include_filter_groups, ElementFiltersData, "drawing_include"
|
||||
)
|
||||
row = self.layout.row(align=True)
|
||||
row.operator(
|
||||
"bim.edit_element_filter", icon="CHECKMARK", text="Save Include Filter"
|
||||
).filter_mode = "INCLUDE"
|
||||
row.operator("bim.enable_editing_element_filter", icon="CANCEL", text="").filter_mode = "NONE"
|
||||
elif props.filter_mode == "EXCLUDE":
|
||||
blenderbim.bim.helper.draw_filter(
|
||||
self.layout, props.exclude_filter_groups, ElementFiltersData, "drawing_exclude"
|
||||
)
|
||||
row = self.layout.row(align=True)
|
||||
row.operator(
|
||||
"bim.edit_element_filter", icon="CHECKMARK", text="Save Exclude Filter"
|
||||
).filter_mode = "EXCLUDE"
|
||||
row.operator("bim.enable_editing_element_filter", icon="CANCEL", text="").filter_mode = "NONE"
|
||||
else:
|
||||
row = self.layout.row(align=True)
|
||||
text = "Include Filter" if ElementFiltersData.data["has_include_filter"] else "No Include Filter Found"
|
||||
icon = "GREASEPENCIL" if ElementFiltersData.data["has_include_filter"] else "ADD"
|
||||
row.label(text=text, icon="FILTER")
|
||||
row.operator("bim.enable_editing_element_filter", icon=icon, text="").filter_mode = "INCLUDE"
|
||||
row = self.layout.row(align=True)
|
||||
text = "Exclude Filter" if ElementFiltersData.data["has_exclude_filter"] else "No Exclude Filter Found"
|
||||
icon = "GREASEPENCIL" if ElementFiltersData.data["has_exclude_filter"] else "ADD"
|
||||
row.label(text=text, icon="FILTER")
|
||||
row.operator("bim.enable_editing_element_filter", icon=icon, text="").filter_mode = "EXCLUDE"
|
||||
|
||||
|
||||
class BIM_PT_drawing_underlay(Panel):
|
||||
@@ -97,12 +156,16 @@ class BIM_PT_drawing_underlay(Panel):
|
||||
bl_options = {"DEFAULT_CLOSED"}
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "data"
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_camera"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return context.camera and hasattr(context.active_object.data, "BIMCameraProperties")
|
||||
return (
|
||||
context.scene.camera
|
||||
and context.active_object
|
||||
and hasattr(context.active_object.data, "BIMCameraProperties")
|
||||
)
|
||||
|
||||
def draw(self, context):
|
||||
layout = self.layout
|
||||
@@ -164,10 +227,8 @@ class BIM_PT_drawings(Panel):
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return tool.Blender.is_tab(context, "DRAWINGS") and tool.Ifc.get()
|
||||
bl_parent_id = "BIM_PT_tab_drawings"
|
||||
bl_options = {"HIDE_HEADER"}
|
||||
|
||||
def draw(self, context):
|
||||
if not DrawingsData.is_loaded:
|
||||
@@ -245,10 +306,8 @@ class BIM_PT_schedules(Panel):
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return tool.Blender.is_tab(context, "DRAWINGS") and tool.Ifc.get()
|
||||
bl_parent_id = "BIM_PT_tab_schedules"
|
||||
bl_options = {"HIDE_HEADER"}
|
||||
|
||||
def draw(self, context):
|
||||
if not DocumentsData.is_loaded:
|
||||
@@ -297,10 +356,8 @@ class BIM_PT_references(Panel):
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return tool.Blender.is_tab(context, "DRAWINGS") and tool.Ifc.get()
|
||||
bl_parent_id = "BIM_PT_tab_references"
|
||||
bl_options = {"HIDE_HEADER"}
|
||||
|
||||
def draw(self, context):
|
||||
if not DocumentsData.is_loaded:
|
||||
@@ -341,10 +398,8 @@ class BIM_PT_sheets(Panel):
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
return tool.Blender.is_tab(context, "DRAWINGS") and tool.Ifc.get()
|
||||
bl_parent_id = "BIM_PT_tab_sheets"
|
||||
bl_options = {"HIDE_HEADER"}
|
||||
|
||||
def draw(self, context):
|
||||
if not SheetsData.is_loaded:
|
||||
@@ -413,13 +468,16 @@ class BIM_PT_product_assignments(Panel):
|
||||
if props.is_editing_product:
|
||||
row = self.layout.row(align=True)
|
||||
row.prop(props, "relating_product", text="")
|
||||
row.operator("bim.assign_selected_as_product", icon="OBJECT_DATA", text="")
|
||||
row.operator("bim.edit_assigned_product", icon="CHECKMARK", text="")
|
||||
row.operator("bim.disable_editing_assigned_product", icon="CANCEL", text="")
|
||||
else:
|
||||
row = self.layout.row(align=True)
|
||||
row.label(text=ProductAssignmentsData.data["relating_product"] or "No Relating Product", icon="OBJECT_DATA")
|
||||
row.operator("bim.enable_editing_assigned_product", icon="GREASEPENCIL", text="")
|
||||
row.operator("bim.select_assigned_product", icon="RESTRICT_SELECT_OFF", text="")
|
||||
col = row.column()
|
||||
col.operator("bim.select_assigned_product", icon="RESTRICT_SELECT_OFF", text="")
|
||||
col.enabled = bool(ProductAssignmentsData.data["relating_product"])
|
||||
|
||||
|
||||
class BIM_PT_text(Panel):
|
||||
@@ -601,3 +659,7 @@ class BIM_UL_sheets(bpy.types.UIList):
|
||||
if not flt_flags:
|
||||
return flt_flags, flt_neworder
|
||||
return flt_flags, flt_neworder
|
||||
|
||||
|
||||
def add_object_button(self, context):
|
||||
self.layout.operator("bim.add_reference_image", icon="TEXTURE", text="IFC Reference Image")
|
||||
|
||||
@@ -186,6 +186,9 @@ def create_annotation_occurrence(context):
|
||||
tool.Collector.assign(obj)
|
||||
tool.Blender.select_and_activate_single_object(context, obj)
|
||||
|
||||
if relating_type_repr is None and props.object_type == "IMAGE":
|
||||
bpy.ops.bim.add_reference_image("INVOKE_DEFAULT", use_existing_object_by_name=obj.name)
|
||||
|
||||
|
||||
def create_annotation():
|
||||
props = bpy.context.scene.BIMAnnotationProperties
|
||||
@@ -194,6 +197,10 @@ def create_annotation():
|
||||
else:
|
||||
object_type = props.object_type
|
||||
bpy.ops.bim.add_annotation(object_type=object_type, data_type=ANNOTATION_TYPES_DATA[object_type][-1])
|
||||
if props.object_type == "IMAGE":
|
||||
bpy.ops.bim.add_reference_image(
|
||||
"INVOKE_DEFAULT", use_existing_object_by_name=bpy.context.active_object.name
|
||||
)
|
||||
|
||||
|
||||
class AnnotationToolUI:
|
||||
|
||||
+9
-8
@@ -1,5 +1,5 @@
|
||||
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
||||
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
|
||||
# Copyright (C) 2023 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of BlenderBIM Add-on.
|
||||
#
|
||||
@@ -20,17 +20,18 @@ import bpy
|
||||
from . import ui, prop, operator
|
||||
|
||||
classes = (
|
||||
operator.SelectCobieIfcFile,
|
||||
operator.SelectCobieJsonFile,
|
||||
operator.ExecuteIfcCobie,
|
||||
prop.COBieProperties,
|
||||
ui.BIM_PT_cobie,
|
||||
operator.ExecuteIfcFM,
|
||||
operator.ExecuteIfcFMFederate,
|
||||
operator.SelectFMIfcFile,
|
||||
operator.SelectFMSpreadsheetFiles,
|
||||
prop.BIMFMProperties,
|
||||
ui.BIM_PT_fm,
|
||||
)
|
||||
|
||||
|
||||
def register():
|
||||
bpy.types.Scene.COBieProperties = bpy.props.PointerProperty(type=prop.COBieProperties)
|
||||
bpy.types.Scene.BIMFMProperties = bpy.props.PointerProperty(type=prop.BIMFMProperties)
|
||||
|
||||
|
||||
def unregister():
|
||||
del bpy.types.Scene.COBieProperties
|
||||
del bpy.types.Scene.BIMFMProperties
|
||||
+16
-17
@@ -1,5 +1,5 @@
|
||||
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
||||
# Copyright (C) 2021 Dion Moult <dion@thinkmoult.com>
|
||||
# Copyright (C) 2023 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of BlenderBIM Add-on.
|
||||
#
|
||||
@@ -16,34 +16,33 @@
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
import olca
|
||||
import blenderbim.tool as tool
|
||||
import os
|
||||
import ifcfm
|
||||
import importlib
|
||||
|
||||
|
||||
def refresh():
|
||||
LcaData.is_loaded = False
|
||||
FMData.is_loaded = False
|
||||
|
||||
|
||||
class LcaData:
|
||||
class FMData:
|
||||
data = {}
|
||||
is_loaded = False
|
||||
|
||||
@classmethod
|
||||
def load(cls):
|
||||
cls.data = {
|
||||
"product_systems": cls.product_systems(),
|
||||
}
|
||||
cls.is_loaded = True
|
||||
cls.data = {}
|
||||
cls.data["engine"] = cls.engine()
|
||||
|
||||
@classmethod
|
||||
def product_systems(cls):
|
||||
if not bpy.context.scene.BIMLCAProperties.is_connected:
|
||||
return []
|
||||
def engine(cls):
|
||||
results = []
|
||||
client = olca.Client(context.preferences.addons["blenderbim"].preferences.openlca_port)
|
||||
try:
|
||||
results = [(ps.name, ps.name, "") for ps in client.get_all(olca.ProductSystem)]
|
||||
except:
|
||||
pass
|
||||
fm_dir = os.path.dirname(ifcfm.__file__)
|
||||
for f in os.listdir(fm_dir):
|
||||
if f.endswith(".py") and not f.startswith("_"):
|
||||
preset = os.path.splitext(f)[0]
|
||||
module = importlib.import_module(f"ifcfm.{preset}")
|
||||
config = getattr(module, "config")
|
||||
results.append((preset, config["name"], config["description"]))
|
||||
return results
|
||||
@@ -0,0 +1,157 @@
|
||||
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
||||
# Copyright (C) 2023 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of BlenderBIM Add-on.
|
||||
#
|
||||
# BlenderBIM Add-on is free software: you can redistribute it and/or modify
|
||||
# it under the terms of the GNU General Public License as published by
|
||||
# the Free Software Foundation, either version 3 of the License, or
|
||||
# (at your option) any later version.
|
||||
#
|
||||
# BlenderBIM Add-on is distributed in the hope that it will be useful,
|
||||
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
# GNU General Public License for more details.
|
||||
#
|
||||
# You should have received a copy of the GNU General Public License
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import os
|
||||
import bpy
|
||||
import json
|
||||
import ifcfm
|
||||
import logging
|
||||
import tempfile
|
||||
import ifcopenshell
|
||||
import blenderbim.tool as tool
|
||||
|
||||
|
||||
class SelectFMIfcFile(bpy.types.Operator):
|
||||
bl_idname = "bim.select_fm_ifc_file"
|
||||
bl_label = "Select FM IFC File"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
filename_ext = ".ifc"
|
||||
filter_glob: bpy.props.StringProperty(default="*.ifc;*.ifczip;*.ifcxml", options={"HIDDEN"})
|
||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||
files: bpy.props.CollectionProperty(name="File Path", type=bpy.types.OperatorFileListElement)
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMFMProperties
|
||||
props.ifc_files.clear()
|
||||
dirname = os.path.dirname(self.filepath)
|
||||
for f in self.files:
|
||||
new = props.ifc_files.add()
|
||||
new.name = os.path.join(dirname, f.name)
|
||||
props.ifc_file = self.filepath
|
||||
return {"FINISHED"}
|
||||
|
||||
def invoke(self, context, event):
|
||||
context.window_manager.fileselect_add(self)
|
||||
return {"RUNNING_MODAL"}
|
||||
|
||||
|
||||
class ExecuteIfcFM(bpy.types.Operator):
|
||||
bl_idname = "bim.execute_ifcfm"
|
||||
bl_label = "Execute IfcFM"
|
||||
file_format: bpy.props.StringProperty()
|
||||
filter_glob: bpy.props.StringProperty(default="*.csv;*.ods;*.xlsx", options={"HIDDEN"})
|
||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
props = context.scene.BIMFMProperties
|
||||
return props.should_load_from_memory or props.ifc_file
|
||||
|
||||
def invoke(self, context, event):
|
||||
props = context.scene.BIMFMProperties
|
||||
self.filepath = bpy.path.ensure_ext(bpy.data.filepath, f".{props.format}")
|
||||
WindowManager = context.window_manager
|
||||
WindowManager.fileselect_add(self)
|
||||
return {"RUNNING_MODAL"}
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMFMProperties
|
||||
ifc_file = tool.Ifc.get()
|
||||
filepaths = []
|
||||
if not (ifc_file and props.should_load_from_memory):
|
||||
if len(props.ifc_files):
|
||||
ifc_files = [ifcopenshell.open(f.name) for f in props.ifc_files]
|
||||
filepaths = [f.name for f in props.ifc_files]
|
||||
else:
|
||||
ifc_files = [ifcopenshell.open(props.ifc_file)]
|
||||
else:
|
||||
ifc_files = [ifc_file]
|
||||
|
||||
for i, ifc_file in enumerate(ifc_files):
|
||||
if filepaths:
|
||||
dirname = os.path.dirname(self.filepath)
|
||||
prefix, _ = os.path.splitext(os.path.basename(filepaths[i]))
|
||||
basename = os.path.basename(self.filepath)
|
||||
filepath = os.path.join(dirname, f"{prefix}-{basename}")
|
||||
else:
|
||||
filepath = self.filepath
|
||||
parser = ifcfm.Parser(preset=props.engine)
|
||||
parser.parse(ifc_file)
|
||||
writer = ifcfm.Writer(parser)
|
||||
writer.write()
|
||||
if props.format == "csv":
|
||||
writer.write_csv("tmp/")
|
||||
elif props.format == "ods":
|
||||
writer.write_ods(filepath)
|
||||
elif props.format == "xlsx":
|
||||
writer.write_xlsx(filepath)
|
||||
return {"FINISHED"}
|
||||
|
||||
|
||||
class SelectFMSpreadsheetFiles(bpy.types.Operator):
|
||||
bl_idname = "bim.select_fm_spreadsheet_files"
|
||||
bl_label = "Select FM Spreadsheet Files"
|
||||
bl_options = {"REGISTER", "UNDO"}
|
||||
filter_glob: bpy.props.StringProperty(default="*.ods;*.xlsx", options={"HIDDEN"})
|
||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||
files: bpy.props.CollectionProperty(name="File Path", type=bpy.types.OperatorFileListElement)
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMFMProperties
|
||||
props.spreadsheet_files.clear()
|
||||
dirname = os.path.dirname(self.filepath)
|
||||
for f in self.files:
|
||||
new = props.spreadsheet_files.add()
|
||||
new.name = os.path.join(dirname, f.name)
|
||||
return {"FINISHED"}
|
||||
|
||||
def invoke(self, context, event):
|
||||
context.window_manager.fileselect_add(self)
|
||||
return {"RUNNING_MODAL"}
|
||||
|
||||
|
||||
class ExecuteIfcFMFederate(bpy.types.Operator):
|
||||
bl_idname = "bim.execute_ifcfm_federate"
|
||||
bl_label = "Execute IfcFM"
|
||||
file_format: bpy.props.StringProperty()
|
||||
filter_glob: bpy.props.StringProperty(default="*.ods;*.xlsx", options={"HIDDEN"})
|
||||
filepath: bpy.props.StringProperty(subtype="FILE_PATH")
|
||||
|
||||
@classmethod
|
||||
def poll(cls, context):
|
||||
props = context.scene.BIMFMProperties
|
||||
return props.spreadsheet_files
|
||||
|
||||
def invoke(self, context, event):
|
||||
props = context.scene.BIMFMProperties
|
||||
self.filepath = bpy.path.ensure_ext(bpy.data.filepath, f".{props.format}")
|
||||
WindowManager = context.window_manager
|
||||
WindowManager.fileselect_add(self)
|
||||
return {"RUNNING_MODAL"}
|
||||
|
||||
def execute(self, context):
|
||||
props = context.scene.BIMFMProperties
|
||||
parser = ifcfm.Parser(preset=props.engine)
|
||||
parser.federate([f.name for f in props.spreadsheet_files])
|
||||
writer = ifcfm.Writer(parser)
|
||||
writer.write()
|
||||
if props.format == "ods":
|
||||
writer.write_ods(self.filepath)
|
||||
elif props.format == "xlsx":
|
||||
writer.write_xlsx(self.filepath)
|
||||
return {"FINISHED"}
|
||||
+23
-6
@@ -1,5 +1,5 @@
|
||||
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
||||
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
|
||||
# Copyright (C) 2023 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of BlenderBIM Add-on.
|
||||
#
|
||||
@@ -17,6 +17,8 @@
|
||||
# along with BlenderBIM Add-on. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
import bpy
|
||||
from blenderbim.bim.module.fm.data import FMData
|
||||
from blenderbim.bim.prop import StrProperty
|
||||
from bpy.types import PropertyGroup
|
||||
from bpy.props import (
|
||||
PointerProperty,
|
||||
@@ -30,9 +32,24 @@ from bpy.props import (
|
||||
)
|
||||
|
||||
|
||||
class COBieProperties(PropertyGroup):
|
||||
cobie_ifc_file: StringProperty(default="", name="COBie IFC File")
|
||||
cobie_types: StringProperty(default=".COBieType", name="COBie Types")
|
||||
cobie_components: StringProperty(default=".COBie", name="COBie Components")
|
||||
cobie_json_file: StringProperty(default="", name="COBie JSON File")
|
||||
def get_engine(self, context):
|
||||
if not FMData.is_loaded:
|
||||
FMData.load()
|
||||
return FMData.data["engine"]
|
||||
|
||||
|
||||
class BIMFMProperties(PropertyGroup):
|
||||
ifc_file: StringProperty(default="", name="IFC File")
|
||||
ifc_files: CollectionProperty(name="IFC Files", type=StrProperty)
|
||||
spreadsheet_files: CollectionProperty(name="Spreadsheets", type=StrProperty)
|
||||
should_load_from_memory: BoolProperty(default=False, name="Load from Memory")
|
||||
engine: EnumProperty(items=get_engine, name="Engine")
|
||||
format: EnumProperty(
|
||||
items=[
|
||||
("csv", "csv", ""),
|
||||
("xlsx", "xlsx", ""),
|
||||
("ods", "ods", ""),
|
||||
],
|
||||
name="Format",
|
||||
default="ods",
|
||||
)
|
||||
+22
-17
@@ -1,5 +1,5 @@
|
||||
# BlenderBIM Add-on - OpenBIM Blender Add-on
|
||||
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
|
||||
# Copyright (C) 2023 Dion Moult <dion@thinkmoult.com>
|
||||
#
|
||||
# This file is part of BlenderBIM Add-on.
|
||||
#
|
||||
@@ -19,22 +19,26 @@
|
||||
import blenderbim.tool as tool
|
||||
from bpy.types import Panel
|
||||
from blenderbim.bim.ifc import IfcStore
|
||||
from blenderbim.bim.module.fm.data import FMData
|
||||
|
||||
|
||||
class BIM_PT_cobie(Panel):
|
||||
bl_label = "COBie"
|
||||
bl_idname = "BIM_PT_cobie"
|
||||
class BIM_PT_fm(Panel):
|
||||
bl_label = "Facility Management"
|
||||
bl_idname = "BIM_PT_fm"
|
||||
bl_space_type = "PROPERTIES"
|
||||
bl_region_type = "WINDOW"
|
||||
bl_context = "scene"
|
||||
bl_parent_id = "BIM_PT_tab_handover"
|
||||
|
||||
def draw(self, context):
|
||||
if not FMData.is_loaded:
|
||||
FMData.load()
|
||||
|
||||
layout = self.layout
|
||||
layout.use_property_split = True
|
||||
|
||||
scene = context.scene
|
||||
props = scene.COBieProperties
|
||||
props = scene.BIMFMProperties
|
||||
|
||||
if IfcStore.get_file():
|
||||
row = layout.row()
|
||||
@@ -42,22 +46,23 @@ class BIM_PT_cobie(Panel):
|
||||
|
||||
if not IfcStore.get_file() or not props.should_load_from_memory:
|
||||
row = layout.row(align=True)
|
||||
row.prop(props, "cobie_ifc_file")
|
||||
row.operator("bim.select_cobie_ifc_file", icon="FILE_FOLDER", text="")
|
||||
if len(props.ifc_files) > 1:
|
||||
row.label(text=f"{len(props.ifc_files)} Files Selected")
|
||||
else:
|
||||
row.prop(props, "ifc_file")
|
||||
row.operator("bim.select_fm_ifc_file", icon="FILE_FOLDER", text="")
|
||||
|
||||
row = layout.row()
|
||||
row.prop(props, "cobie_types")
|
||||
row.prop(props, "engine")
|
||||
row = layout.row()
|
||||
row.prop(props, "cobie_components")
|
||||
row.prop(props, "format")
|
||||
|
||||
row = layout.row()
|
||||
op = row.operator("bim.execute_ifcfm", text="Convert To Spreadsheet")
|
||||
|
||||
row = layout.row(align=True)
|
||||
row.prop(props, "cobie_json_file")
|
||||
row.operator("bim.select_cobie_json_file", icon="FILE_FOLDER", text="")
|
||||
row.label(text=f"{len(props.spreadsheet_files)} Spreadsheets Selected")
|
||||
row.operator("bim.select_fm_spreadsheet_files", icon="FILE_FOLDER", text="")
|
||||
|
||||
row = layout.row()
|
||||
op = row.operator("bim.execute_ifc_cobie", text="CSV")
|
||||
op.file_format = "csv"
|
||||
op = row.operator("bim.execute_ifc_cobie", text="ODS")
|
||||
op.file_format = "ods"
|
||||
op = row.operator("bim.execute_ifc_cobie", text="XLSX")
|
||||
op.file_format = "xlsx"
|
||||
op = row.operator("bim.execute_ifcfm_federate", text="Merge Spreadsheets")
|
||||
@@ -22,37 +22,57 @@ from . import ui, prop, operator
|
||||
classes = (
|
||||
operator.AddRepresentation,
|
||||
operator.CopyRepresentation,
|
||||
operator.DisableEditingRepresentationItems,
|
||||
operator.EditObjectPlacement,
|
||||
operator.EnableEditingRepresentationItems,
|
||||
operator.FlipObject,
|
||||
operator.GetRepresentationIfcParameters,
|
||||
operator.DuplicateMoveLinkedAggregate,
|
||||
operator.DuplicateMoveLinkedAggregateMacro,
|
||||
operator.OverrideDelete,
|
||||
operator.OverrideDuplicateMove,
|
||||
operator.OverrideDuplicateMoveAggregate,
|
||||
operator.OverrideDuplicateMoveAggregateMacro,
|
||||
operator.OverrideDuplicateMoveLinked,
|
||||
operator.OverrideDuplicateMoveLinkedMacro,
|
||||
operator.OverrideDuplicateMoveMacro,
|
||||
operator.OverrideJoin,
|
||||
operator.OverrideMeshSeparate,
|
||||
operator.OverrideModeSetEdit,
|
||||
operator.OverrideModeSetObject,
|
||||
operator.OverrideOriginSet,
|
||||
operator.OverrideOutlinerDelete,
|
||||
operator.OverridePasteBuffer,
|
||||
operator.PurgeUnusedRepresentations,
|
||||
operator.RefreshAggregate,
|
||||
operator.RefreshLinkedAggregate,
|
||||
operator.RemoveConnection,
|
||||
operator.RemoveRepresentation,
|
||||
operator.SelectConnection,
|
||||
operator.SwitchRepresentation,
|
||||
operator.UpdateParametricRepresentation,
|
||||
operator.UpdateRepresentation,
|
||||
operator.RemoveRepresentationItem,
|
||||
operator.EnableEditingRepresentationItemStyle,
|
||||
operator.EditRepresentationItemStyle,
|
||||
operator.DisableEditingRepresentationItemStyle,
|
||||
operator.UnassignRepresentationItemStyle,
|
||||
operator.EnableEditingRepresentationItemShapeAspect,
|
||||
operator.EditRepresentationItemShapeAspect,
|
||||
operator.DisableEditingRepresentationItemShapeAspect,
|
||||
operator.RemoveRepresentationItemFromShapeAspect,
|
||||
prop.RepresentationItem,
|
||||
prop.ShapeAspect,
|
||||
prop.BIMObjectGeometryProperties,
|
||||
prop.BIMGeometryProperties,
|
||||
ui.BIM_PT_derived_placements,
|
||||
ui.BIM_PT_placement,
|
||||
ui.BIM_PT_representations,
|
||||
ui.BIM_PT_representation_items,
|
||||
ui.BIM_PT_connections,
|
||||
ui.BIM_PT_mesh,
|
||||
ui.BIM_PT_derived_coordinates,
|
||||
ui.BIM_PT_workarounds,
|
||||
ui.BIM_MT_object_set_origin,
|
||||
ui.BIM_MT_separate,
|
||||
ui.BIM_MT_hotkey_separate,
|
||||
ui.BIM_UL_representation_items,
|
||||
)
|
||||
|
||||
|
||||
@@ -64,15 +84,16 @@ def register():
|
||||
operator.OverrideDuplicateMoveMacro.define("TRANSFORM_OT_translate")
|
||||
operator.OverrideDuplicateMoveLinkedMacro.define("BIM_OT_override_object_duplicate_move_linked")
|
||||
operator.OverrideDuplicateMoveLinkedMacro.define("TRANSFORM_OT_translate")
|
||||
operator.OverrideDuplicateMoveAggregateMacro.define("BIM_OT_override_object_duplicate_move_aggregate")
|
||||
operator.OverrideDuplicateMoveAggregateMacro.define("TRANSFORM_OT_translate")
|
||||
operator.DuplicateMoveLinkedAggregateMacro.define("BIM_OT_object_duplicate_move_linked_aggregate")
|
||||
operator.DuplicateMoveLinkedAggregateMacro.define("TRANSFORM_OT_translate")
|
||||
|
||||
bpy.types.Object.BIMGeometryProperties = bpy.props.PointerProperty(type=prop.BIMObjectGeometryProperties)
|
||||
bpy.types.Scene.BIMGeometryProperties = bpy.props.PointerProperty(type=prop.BIMGeometryProperties)
|
||||
bpy.types.OBJECT_PT_transform.append(ui.BIM_PT_transform)
|
||||
bpy.types.VIEW3D_MT_object.append(ui.object_menu)
|
||||
bpy.types.OUTLINER_MT_object.append(ui.outliner_menu)
|
||||
bpy.types.VIEW3D_MT_object_context_menu.append(ui.object_menu)
|
||||
bpy.types.VIEW3D_MT_edit_mesh.append(ui.edit_mesh_menu)
|
||||
bpy.types.VIEW3D_HT_header.append(ui.mode_menu)
|
||||
wm = bpy.context.window_manager
|
||||
if wm.keyconfigs.addon:
|
||||
km = wm.keyconfigs.addon.keymaps.new(name="Object Mode", space_type="EMPTY")
|
||||
@@ -82,7 +103,9 @@ def register():
|
||||
addon_keymaps.append((km, kmi))
|
||||
kmi = km.keymap_items.new("bim.override_object_duplicate_move_linked_macro", "D", "PRESS", alt=True)
|
||||
addon_keymaps.append((km, kmi))
|
||||
kmi = km.keymap_items.new("bim.override_object_duplicate_move_aggregate_macro", "D", "PRESS", ctrl=True, shift=True)
|
||||
kmi = km.keymap_items.new(
|
||||
"bim.object_duplicate_move_linked_aggregate_macro", "D", "PRESS", ctrl=True, shift=True
|
||||
)
|
||||
addon_keymaps.append((km, kmi))
|
||||
kmi = km.keymap_items.new("bim.override_paste_buffer", "V", "PRESS", ctrl=True)
|
||||
addon_keymaps.append((km, kmi))
|
||||
@@ -97,6 +120,9 @@ def register():
|
||||
km = wm.keyconfigs.addon.keymaps.new(name="Mesh", space_type="EMPTY")
|
||||
kmi = km.keymap_items.new("bim.override_mode_set_object", "TAB", "PRESS")
|
||||
addon_keymaps.append((km, kmi))
|
||||
kmi = km.keymap_items.new("wm.call_menu", "P", "PRESS")
|
||||
kmi.properties.name = ui.BIM_MT_hotkey_separate.bl_idname
|
||||
addon_keymaps.append((km, kmi))
|
||||
|
||||
km = wm.keyconfigs.addon.keymaps.new(name="Curve", space_type="EMPTY")
|
||||
kmi = km.keymap_items.new("bim.override_mode_set_object", "TAB", "PRESS")
|
||||
@@ -113,9 +139,10 @@ def register():
|
||||
|
||||
def unregister():
|
||||
bpy.types.VIEW3D_MT_object.remove(ui.object_menu)
|
||||
bpy.types.OBJECT_PT_transform.remove(ui.BIM_PT_transform)
|
||||
bpy.types.OUTLINER_MT_object.remove(ui.outliner_menu)
|
||||
bpy.types.VIEW3D_MT_object_context_menu.remove(ui.outliner_menu)
|
||||
bpy.types.VIEW3D_MT_edit_mesh.remove(ui.edit_mesh_menu)
|
||||
bpy.types.VIEW3D_HT_header.remove(ui.mode_menu)
|
||||
del bpy.types.Scene.BIMGeometryProperties
|
||||
del bpy.types.Object.BIMGeometryProperties
|
||||
wm = bpy.context.window_manager
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user