Compare commits

...

1831 Commits

Author SHA1 Message Date
Thomas Krijnen 6aeddcabc0 Delete file 2021-02-05 11:54:03 +01:00
Thomas Krijnen 2703dce209 Small changes 2021-02-05 11:52:05 +01:00
Thomas Krijnen dc529d4146 Merge branch 'v0.6.0' into ifcopenshell_documentation 2021-02-05 11:47:35 +01:00
Thomas Krijnen 8648b16e00 Small changes to script 2021-02-05 11:41:44 +01:00
Thomas Krijnen c0a62e8593 more cleanup 2021-02-05 11:39:35 +01:00
Thomas Krijnen ef5d672d4d Also add prefix install path with _ 2021-02-05 11:24:50 +01:00
Long 01b1f4642f fix ifcpatch recipe import path (#1296) 2021-02-05 18:19:10 +11:00
Dion Moult e92a84f917 Bump IfcOpenShell to address bug #1293 and bug #1281. 2021-02-05 10:08:20 +11:00
Dion Moult 04a2949d75 Fix import bug where loading existing elements wouldn't work. 2021-02-05 08:54:46 +11:00
Dion Moult 031a0cec59 Minor fix 2021-02-05 08:30:54 +11:00
Dion Moult 5f8e77c292 New create shape debugging tool to help determine broken or crashing elements 2021-02-04 22:25:43 +11:00
Dion Moult 384d007770 Validating IFCs UI now moved over into debug panel 2021-02-04 21:59:08 +11:00
Dion Moult e14a3a99c0 Fix bug where spatial objects with representations didn't import correctly. 2021-02-04 14:50:46 +11:00
Dion Moult 96260cdb39 Minor fix 2021-02-04 12:35:34 +11:00
Dion Moult d7f526eafd Minor fix 2021-02-04 11:56:56 +11:00
Dion Moult 55b081edf7 Implement BIMTester web app mockup 2021-02-04 11:54:42 +11:00
Thomas Krijnen ffb8c016b6 #1287 Don't wel accross different rep items 2021-02-03 14:51:02 +01:00
Dion Moult 11697fbd47 You can now specify a set of custom step definitions to BIMTester. 2021-02-03 21:58:49 +11:00
Dion Moult 4b9520a1bb Fix #1289. Users can now reassign the IFC file location if it moves. 2021-02-03 19:15:25 +11:00
Dion Moult 9717d6b1eb Fix #1288 - error when importing consecutive files. 2021-02-03 17:30:19 +11:00
Dion Moult 2f2b4e7dc2 Fix bug where switching representations would not work or create duplicate meshes. 2021-02-03 16:41:41 +11:00
Dion Moult f6c2a18e63 Now, users don't need to consider include curves and 2D annotations will always be imported. See #1142. 2021-02-03 16:22:23 +11:00
Dion Moult 08d959f66d Fix #1282. Bug where unable to install add-on in older Blender versions. 2021-02-03 14:45:52 +11:00
Dion Moult aa41f698c1 Fix #1287. Back to IfcOpenShell for booleans. Optional conversion to Blender if the user decides to do so. 2021-02-03 13:49:36 +11:00
Dion Moult c6a7dfdadb There is now an ID and GUID map to Blender objects for easy access especially for devs 2021-02-03 13:47:09 +11:00
ahladik adf5af947b Some more fixes to the Windows build procedure (#1285) 2021-02-02 12:00:55 +01:00
Thomas Krijnen 55b63410bd #747 Apply typemaps and checks to spf header 2021-02-02 11:49:42 +01:00
Dion Moult 012a2cca0f Fix bug where BIMTester audit classes dropdown wouldn't show. 2021-02-02 20:46:17 +11:00
Dion Moult 5a722a792a You can now load the active IFC file into a BIMTester audit. Rapid auditing go go go! 2021-02-02 20:45:56 +11:00
Dion Moult c3f7410f76 Fix #1266. Standardise BIMTester quotes, always translate, and refactor. 2021-02-02 16:51:12 +11:00
Dion Moult 7c1a23e5e3 BIMTester custom schema is now specified as an argument, not as a test requirement, which is where it belongs. 2021-02-02 16:11:38 +11:00
Dion Moult ac95fb1aa2 BIMTester now operates on single feature files, which heavily improves usability 2021-02-02 12:34:14 +11:00
Dion Moult 1f4df32d04 Fix bunch of error messages (commonly seen in IFCCSV) when you try to get a property value which is None 2021-02-01 10:18:10 +11:00
Dion Moult b09d030e12 Owner histories now updated when assigning aggregates. 2021-01-31 11:10:14 +11:00
Dion Moult ed9557539d Remove cache dir 2021-01-31 11:10:14 +11:00
Thomas Krijnen 500467b3a8 Fix json logger on validator for arg formatting 2021-01-30 21:58:27 +01:00
Thomas Krijnen 1cee5c3108 SVG Exclude IfcGrid from HLR 2021-01-30 16:15:54 +01:00
Thomas Krijnen 5e84d8da83 SVG Move section/elevation to origin to workaround PolyHLR bug 2021-01-30 16:15:26 +01:00
Thomas Krijnen 1317263536 SVG: Explicitly cast object type 2021-01-29 15:57:57 +01:00
Thomas Krijnen f4ef17eea6 Also exclude spaces from HLR 2021-01-29 15:57:34 +01:00
Thomas Krijnen 5db0f78646 Add result_type typedef 2021-01-29 13:49:45 +01:00
Thomas Krijnen b185f56dcc SVG Dimension ObjectType and Boolean sub for slanted slabs 2021-01-29 13:03:44 +01:00
Dion Moult b8ab478416 Editing attributes now stores a modified owner history 2021-01-29 21:19:20 +11:00
Dion Moult 97d34a7061 WIP unbreak drawing generation and support box context generation. See #1222. 2021-01-29 17:44:52 +11:00
Dion Moult 3e6a737cdb Implement assigning annotation representation. See #1222. 2021-01-29 15:16:29 +11:00
Dion Moult 4c87ea321d Improve UX of assigning classes to multiple objects. See #1222. 2021-01-29 15:16:29 +11:00
Dion Moult 91c6fb402d Sync blender and IFC names. See #1222. 2021-01-29 15:16:29 +11:00
Thomas Krijnen 47d4ea00ca Include outline in HLR render 2021-01-28 16:32:16 +01:00
Dion Moult f55438e871 You can now add 2D representations. Also, we now support exporting "wireframe" or 2D meshes into IFC2X3 which we didn't before. See #1222. 2021-01-28 17:27:23 +11:00
Thomas Krijnen b1232ecb02 Option to use projection logic on floor plans 2021-01-27 22:34:19 +01:00
Dion Moult a37e124d8f You can now duplicate or linked duplicate objects in IFC. Neat. See #1222. 2021-01-27 19:00:35 +11:00
Dion Moult c472dc2f1b You can now unlink blender objects to IFC ones. See #1222. 2021-01-27 15:41:24 +11:00
Dion Moult c0ed4074d8 You can now assign reps to type products. See #1222. 2021-01-27 15:28:29 +11:00
Dion Moult c94cac29a5 Add ability to map representations. See #1222. 2021-01-27 15:02:34 +11:00
Dion Moult f90c56013e Editing placements and meshes now can happen in bulk. See #1222. 2021-01-27 15:02:07 +11:00
Dion Moult 572efd7ea6 Minor fixes for loading schema data. See #1222. 2021-01-27 09:14:47 +11:00
Dion Moult b71febab0d Clear IfcStore when you load a new file. See #1222. 2021-01-26 21:28:54 +11:00
Dion Moult bbde897113 Fix importing of grids and non contextual geometry. See #1222. 2021-01-26 21:13:33 +11:00
Dion Moult 4527d3a96e Only allow material assignment if we have available materials to assign. See #1222. 2021-01-26 20:01:16 +11:00
Dion Moult 447a7a0eb2 Minor fix. See #1222. 2021-01-26 19:50:50 +11:00
Dion Moult 92cb138ca8 WIP improved UI ordering, and print export time in console for convenience. See #1222. 2021-01-26 16:07:35 +11:00
Dion Moult fa7353c923 WIP owner model now records ADDED state for creating products. New feature. See #1222. 2021-01-26 13:56:38 +11:00
Dion Moult 1023c8bc1c WIP fix BIMTester packaging. See #1222. 2021-01-26 12:54:27 +11:00
Dion Moult 276dc0d894 WIP implement add/remove material. See #1222. 2021-01-26 11:45:58 +11:00
Dion Moult 8618befa0f WIP refactor clash and smart clash. See #1222. 2021-01-26 09:51:33 +11:00
Dion Moult 20ab036016 WIP implement presentation layers. Nicer UI. See #1222. 2021-01-25 18:10:18 +11:00
Long 911ff4484f Improve snapshot filename checking in bcf (#1274) 2021-01-25 14:59:16 +11:00
Dion Moult b4ecdfba69 WIP refactor model module with new pie menu for convenience. See #1222. 2021-01-25 14:58:12 +11:00
Dion Moult f9521eca54 WIP Refactor patch module. See #1222. 2021-01-24 19:57:22 +11:00
Dion Moult af3ed303d8 WIP port pset template module. It probably needs rewriting, but at least no regressions. See #1222. 2021-01-24 19:17:33 +11:00
Dion Moult 9d893d2c5a WIP merge MVDs into geometry workarounds UI. Cleaner, more usable import / export UI. Remove obsoleted MVD options. See #1222. 2021-01-24 14:33:56 +11:00
Dion Moult 900aa20e10 New "remove deep" function in the element util module. See #1228. 2021-01-24 14:32:04 +11:00
Dion Moult b68f490dbc WIP port covetool. See #1222. 2021-01-24 08:19:26 +11:00
Dion Moult 65f381a377 WIP minor tweaks to port IfcSverchok. See #1222. 2021-01-23 18:42:11 +11:00
Dion Moult 8b7d96893f WIP purge old export IFC. No going back! See #1222. 2021-01-23 18:29:59 +11:00
Dion Moult aa3a855b4c Refactor qto utils and migrate to bmesh volume calculation. See #1222. 2021-01-23 18:01:29 +11:00
Dion Moult f19b962ab1 WIP More import function purging - remove groups. Openings always imported. See #1222. 2021-01-23 16:40:27 +11:00
Dion Moult 9b6366ddac WIP port constraints module. See #1222. 2021-01-23 16:32:52 +11:00
Dion Moult d0b2bf85cc WIP port search module with new features! See #1222.
* New IFC class search
 * Slicker UI
 * Colour by class and reset colours now available in search panel
2021-01-23 14:17:50 +11:00
Dion Moult 86e3d1e548 WIP refactor root module properties. See #1222. 2021-01-23 12:54:27 +11:00
Dion Moult d1e2ac4c5a WIP port BCF to new refactored approach. See #1222. 2021-01-23 12:20:06 +11:00
Dion Moult 8c36217e26 Line ending git fix? 2021-01-23 12:02:41 +11:00
Dion Moult b7f574fa30 WIP implement document assign/unassign. See #1222. 2021-01-23 12:02:27 +11:00
Thomas Krijnen 395d63279f Log messages 2021-01-22 22:01:08 +01:00
root 55d24ba1ee No boost cmake flag 2021-01-22 20:47:05 +01:00
Thomas Krijnen 923771f448 #1269 implement SurfaceCurveSweptAreaSolid with non-planar ref 2021-01-22 16:32:51 +01:00
Dion Moult 2f2611e0cb WIP implement most of the document module apart from object references. See #1222. 2021-01-22 21:04:30 +11:00
ahladik 94737da1f5 Workaround for Visual C++ / OCCT conflict with x86 release
Workaround for Visual C++ hanging when compiling 32-bit release OCCT up to version 7.4.0.
See https://tracker.dev.opencascade.org/view.php?id=31628
2021-01-22 10:56:50 +01:00
ahladik 6a6025302e Update vs-cfg.cmd
Prefixed the build folders with a '_' to better distinguish them from source.
Removed a superfluous 'pause' command.
2021-01-22 10:56:50 +01:00
ahladik b92fac5c5e Update vs-cfg.cmd 2021-01-22 10:56:50 +01:00
ahladik 824f09a1e7 More changes to Visual Studio build process
Prevented incorrect linking to default libraries in Boost
Boost version updated to 1.74
2021-01-22 10:56:50 +01:00
ahladik 6a8d8139ed More changes to Windows build scripts
Limited compatibility to Visual Studio 2013 or newer
Fixed the missing 'd' suffix linking ....\opencollada\xmld.lib
Fixed failure when calling the scripts without specifying a generator
2021-01-22 10:56:50 +01:00
ahladik 36f51e19b5 Changes to the build scripts to support Visual Studio 2019
Changes to the build scripts to support Visual Studio 2019, to optionally use a toolset different from the default and to build correctly when more than a single Visual Studio version is installed.
2021-01-22 10:56:50 +01:00
Dion Moult 3bbdc3f277 WIP fix IFC2X3 errors in classification refactor 2021-01-22 16:55:38 +11:00
Dion Moult c67a99fb5d New IfcOpenShell date utility module, because we shouldn't need to think too hard about dates 2021-01-22 16:21:17 +11:00
Dion Moult 7522f8fb7a WIP fix issues in IFCCSV refactor. See #1222. 2021-01-22 16:15:39 +11:00
Dion Moult 84959d1cf8 You can now export container data from IFCCSV 2021-01-22 15:52:48 +11:00
Dion Moult 404a6c244c WIP deprecate merging/import aggregates setting as they are much more usable now. See #1222. 2021-01-22 10:20:38 +11:00
Dion Moult 83c22ebce3 Merge branch 'iospectar-feature/extract-openings' into v0.6.0 2021-01-22 08:27:02 +11:00
Dion Moult 28717beff8 Merge branch 'feature/extract-openings' of https://github.com/iospectar/IfcOpenShell into iospectar-feature/extract-openings
# Conflicts:
#	src/ifcpatch/recipes/ExtractElements.py
2021-01-22 08:26:18 +11:00
Bernd Hahnebach 02fa8c8413 [read carefully before decide merge] !!! normalize line endings of src files (#1268)
* all source: prepare to normalize line ending

* all src: normalize line endings
2021-01-22 08:22:34 +11:00
Manuel 3202174903 Attempt for compatibility with PythonOCC 7.4.1
Used import statement from occ_utils.py 
added an If-Statement to the GetObject()-call.

Calling SetSelectionPriority directly on ais, as proposed by aothms (https://github.com/IfcOpenShell/IfcOpenShell/issues/1098) did not work.
Could load some ifc-models but needs further testing.
2021-01-21 13:34:33 +01:00
Thomas Krijnen 37fe54d247 erase enitty mapping upon deletion 2021-01-21 13:24:18 +01:00
Dion Moult 73439e2114 WIP port classification module with new features. See #1222.
* Adaptive UI based on IFC version
 * You can now load new classification libraries on the fly
 * You can mix classification libraries with project references
2021-01-21 21:58:27 +11:00
Dion Moult 460cb85e4b Minor fixes. 2021-01-21 21:55:08 +11:00
Dion Moult b938e4b3c3 Add new get volume by material script 2021-01-21 10:54:48 +11:00
ihabelaghoury 37f35a7b2e Small Refactor to Bimtester + Diff Module (#1271)
* Refactoring of BIMTester Module

* Modification to Bimtester refactor + Diff refactor

Co-authored-by: Ihab El Aghoury <ihab_elaghoury@yahoo.ca>
Co-authored-by: Dion Moult <dion@thinkmoult.com>
2021-01-21 08:56:00 +11:00
Jesse Vander Does dc41ad5ab1 Adding openings from extracted elements 2021-01-20 09:51:46 -06:00
Dion Moult 8411333f66 WIP implement project UI to show basic project metadata. See #1222. 2021-01-20 16:53:34 +11:00
Dion Moult 95ce82a79e WIP implement deep removal of geometry. See #1222. See #1228. 2021-01-20 16:03:35 +11:00
Dion Moult 1d8a568a0b WIP finish refactoring owner module props. See #1222. 2021-01-20 10:44:43 +11:00
Dion Moult 70a45be904 WIP purge old aggregate system. See #1222. 2021-01-20 10:17:31 +11:00
Dion Moult e3444c60af WIP implement blender offsets for non-geolocated files. Also deprecate a whole bunch of geolocation vendor workarounds into a standard feature. See #1222. 2021-01-20 10:13:07 +11:00
Dion Moult 4cea2b7044 WIP code cleanup and deprecate legacy product import. Finally! See #1222. 2021-01-20 10:11:32 +11:00
Dion Moult 1142c5285c Geolocation util can now apply georeferencing to matrices 2021-01-20 10:07:48 +11:00
Dion Moult ea524767a0 WIP implement georeference module for correctly geolocated files. See #1222. 2021-01-19 11:18:26 +11:00
Bernd Hahnebach 45bba127ff bimtester: steps, remove comment 2021-01-17 22:40:11 +01:00
Bernd Hahnebach b9ba138d8d bimtester: normalize line endings 2021-01-17 22:30:04 +01:00
Bernd Hahnebach 2ea04f97f9 bimtester: add git attributes to be able to normalize line endings 2021-01-17 22:30:04 +01:00
Bernd Hahnebach d15c5c7e21 bimtester: recreate translation pot file and update lang po files 2021-01-17 22:30:04 +01:00
Bernd Hahnebach 9574b7e08f bimtester: start italian and dutch translation 2021-01-17 22:30:04 +01:00
Bernd Hahnebach 19ba6f86d7 bimtester: example feature files, add lang short cut to file name 2021-01-17 22:30:04 +01:00
Bernd Hahnebach c5c5bbd290 bimtester: example feature files, formating 2021-01-17 22:30:04 +01:00
Bernd Hahnebach bc9f7d214d bimtester: rename project of example ifcs 2021-01-17 22:30:04 +01:00
Dion Moult ee0b9004e3 WIP reimplement material psets with new features. See #1222.
* Data type sensitive UI
 * New standardised UI
 * Accomodate custom pset templates for materials
 * Explicitly disable IFC2X3 material psets which are horrible and I don't want to support it
2021-01-17 21:54:37 +11:00
Dion Moult 3fe5c88910 WIP implement material attributes panel. See #1222. 2021-01-17 21:07:01 +11:00
Dion Moult 25fb9be82e WIP port object material assignment with 3 new features. See message. See #1222.
* Full support for editing IfcMaterialList added
 * The reusability of material set relationships are now roundtripped
 * UI is sensitive to IFC schema version and adapts intelligently
2021-01-17 12:46:47 +11:00
Dion Moult fa4ba58cac Minor fix 2021-01-17 12:46:47 +11:00
Thomas Krijnen 5a11ac0545 Remove debugging statement 2021-01-16 15:12:19 +01:00
johltn 894bae66fd Clean branch 2021-01-16 14:52:07 +01:00
johltn ccb538c756 Clean branch 2021-01-16 14:50:09 +01:00
johltn c87baa1a50 Clean branch 2021-01-16 14:46:24 +01:00
johltn 30fa59960d Clean branch 2021-01-16 14:42:34 +01:00
johltn bdd86366bf Clean branch 2021-01-16 14:40:39 +01:00
johltn 142a38d402 Clean branch 2021-01-16 13:12:10 +01:00
johltn 257f4b2bf0 Clean branch 2021-01-16 13:03:28 +01:00
johltn 4e8a827822 Clean branch 2021-01-16 12:55:24 +01:00
Cyril Waechter b10ba45194 Allow to install ifcpatch separately (#1263)
Will allow to provide ifcpatch as a standard python package for
various usages (eg. standalone, blenderbim addon, FreeCAD)
* Copy folder instead of files [using svn](https://stackoverflow.com/a/18194523/4098083)
* Fetch recipes from ifcpatch module path
2021-01-16 10:42:45 +11:00
Bernd Hahnebach a04ce8a24d bimtester: steps, translate some project attribute tests 2021-01-15 21:03:45 +01:00
Bernd Hahnebach 1d0b13960f bimtester: steps, translate some attributes 2021-01-15 21:03:45 +01:00
Bernd Hahnebach 418574fe40 bimtester: steps, translate ifcdata provide ifc file by argument 2021-01-15 21:03:45 +01:00
Bernd Hahnebach 2e07fd1cde bimtester: steps, improve ifcdata schema test 2021-01-15 21:03:45 +01:00
Bernd Hahnebach 0123e2a69f Merge pull request #1262 from berndhahnebach/btprdev
bimtester
2021-01-15 10:59:45 +01:00
Bernd Hahnebach 843917a431 bimtester: run, merge run and run wich copy in temp 2021-01-15 10:58:14 +01:00
Bernd Hahnebach 2fce21fd88 bimtester: run, merge getting the behave arguments 2021-01-15 10:58:08 +01:00
Bernd Hahnebach c9e85c5d34 bimtester: run, merge run behave commands 2021-01-15 10:58:03 +01:00
Bernd Hahnebach 521a5a5981 bimtester: parse behave args to the gui too and other small gui
improvements
2021-01-15 10:57:55 +01:00
Bernd Hahnebach c6347e30be bimtester: rename project in example 1 2021-01-15 10:57:51 +01:00
Bernd Hahnebach 21d4203688 bimtester: parse ifcfile by behave user args 2021-01-15 10:57:47 +01:00
Bernd Hahnebach aefd4e3387 bimtester: run, move comments and add prints 2021-01-15 10:57:44 +01:00
Bernd Hahnebach 3df2c89b0a bimtester: report generator, add another parameter report file 2021-01-15 10:57:40 +01:00
Bernd Hahnebach ebd53250e7 bimtester: report, simplify generation code 2021-01-15 10:57:36 +01:00
johltn 6444376ecd Script to generate docs outside CMake 2021-01-15 07:30:09 +01:00
ihabelaghoury f5796eaed3 Refactoring of BIMTester Module (#1259)
Co-authored-by: Ihab El Aghoury <ihab_elaghoury@yahoo.ca>
2021-01-14 20:43:39 +11:00
Dion Moult a4b2285e8a Minor fix 2021-01-14 08:02:00 +11:00
ihabelaghoury 713e70ff63 Total refactoring for CSV into a blenderBim module + use of IfcStore (#1254)
* Add new feature to Load from IFCStore in Cobie

* Initial refactor for CSV to become a CSV Module

* Update __init__.py

* Address Dion's review

Co-authored-by: Ihab El Aghoury <ihab_elaghoury@yahoo.ca>
Co-authored-by: Dion Moult <dion@thinkmoult.com>
2021-01-14 07:53:48 +11:00
Thomas Krijnen 540f793940 Workaround: IfcLine as segment with IfcVector magnitude length in composite curve 2021-01-13 15:46:00 +01:00
Dion Moult 071c84ddf8 WIP implement qtos. See #1222. 2021-01-13 21:26:10 +11:00
Bernd Hahnebach f2b645b73f bimtester: get back dummy feautre file, deleted in 91773e8fc6 2021-01-13 08:38:51 +01:00
Bernd Hahnebach 7554714fff bimtester: sort command line args by abc 2021-01-13 08:29:33 +01:00
Bernd Hahnebach 2d04d988e7 bimtester: improve gui 2021-01-13 08:29:33 +01:00
Bernd Hahnebach 91773e8fc6 bimtester: improve and fix copy in temp and run 2021-01-13 08:29:33 +01:00
Bernd Hahnebach 6ee3c8fd98 bimtester: start script, improve arguments 2021-01-13 08:29:33 +01:00
Bernd Hahnebach a54b84b4c3 bimtester: run, better variable name 2021-01-13 08:29:33 +01:00
Bernd Hahnebach addf28c1e2 bimtester: run, improve method run copy in temp 2021-01-13 08:29:33 +01:00
Bernd Hahnebach aa82cb15d2 bimtester: run, rename method run copy in temp 2021-01-13 08:29:33 +01:00
Bernd Hahnebach 2e3c5c42bf bimtester: fix import 2021-01-13 08:29:33 +01:00
QwiglyDee a1be2ef868 #1234 section view decorations 2021-01-13 06:27:05 +07:00
Thomas Krijnen ab8aa95479 #1224 update inverse cache upon deletion 2021-01-12 21:49:17 +01:00
Dion Moult b78e710479 WIP implement add / remove fills. See #1222. 2021-01-12 16:39:01 +11:00
Dion Moult 9400eab0ff WIP implement void module with add / remove openings. See #1222. 2021-01-12 15:14:14 +11:00
QwiglyDee 1836136049 adding section annotations 2021-01-12 09:33:46 +07:00
QwiglyDee d1a2a12e94 close #1232 elevating grid in section views 2021-01-12 09:33:46 +07:00
QwiglyDee 6502b2c18d little drawing helper 2021-01-12 09:33:46 +07:00
ihabelaghoury 1779fe88ef Add new feature to Load from IFCStore in Cobie (#1253)
Co-authored-by: Ihab El Aghoury <ihab_elaghoury@yahoo.ca>
2021-01-12 11:26:59 +11:00
ihabelaghoury 497f793a6b Cobie Module Refactoring (#1252)
* Create Mylog.txt

* Remove Cobie references from ui and operator

* Update __init__.py

* Extra Updates

* Update operator.py

* Update ui.py

Co-authored-by: Ihab El Aghoury <ihab_elaghoury@yahoo.ca>
2021-01-12 10:02:37 +11:00
Bernd Hahnebach a85d7c66a5 bimtester: add simple example and translated feature files 2021-01-11 06:58:39 +01:00
Thomas Krijnen e1b68dafa4 #841 cpp implementation of get_info() 2021-01-10 12:36:47 +01:00
johltn df2f4b69e3 40 min waiting time 2021-01-10 09:02:27 +01:00
johltn e76d401d15 Use 4 threads 2021-01-09 19:05:32 +01:00
Thomas Krijnen 3182c75f14 Some changes after #1155 2021-01-09 15:08:30 +01:00
admin 68767c3656 #1097
fix:IFC file conversion obj file, some cases will be rotated 90 °
2021-01-09 14:51:01 +01:00
Thomas Krijnen 6976144d80 Fix syntax for py27 2021-01-09 14:25:26 +01:00
Thomas Krijnen 2a54fee41a Fix ifcopenshell.create_entity() by including schema 2021-01-09 11:59:34 +01:00
Thomas Krijnen 3d0c9378c1 Quickfix #1246 2021-01-09 11:49:30 +01:00
Dion Moult 8ef752f173 WIP port owner history setting to partial editing. See #1222. 2021-01-09 12:00:22 +11:00
Dion Moult 06e1ee7825 WIP implement organisation editing. Also new features see commit message. See #1222.
* Organisations are now imported.
 * Organisation identification attribute support is now added, which I missed before
2021-01-09 11:42:21 +11:00
Dion Moult 84de1f1b09 WIP port address and role editing to owner module. See #1222. 2021-01-08 20:53:51 +11:00
Bernd Hahnebach 2e85a80fc8 bimtester: geometric step translation improvement 2021-01-08 08:41:41 +01:00
Bernd Hahnebach 8eab1ec4a5 bimtester: code formating 2021-01-08 08:26:28 +01:00
Bernd Hahnebach 7871dea3ca bimtester: very small code improvements in reports 2021-01-08 08:26:28 +01:00
Bernd Hahnebach bf41ee013c bimtester: improve step translation 2021-01-08 08:26:28 +01:00
Bernd Hahnebach ef3f9489ea bimtester: improve some step method names 2021-01-08 08:26:28 +01:00
Dion Moult be2ea335f5 WIP partial port of IfcPerson to partial editing. New feature too! See message. See #1222.
* Previously, IfcPerson was not imported. Now it is! Funky.
2021-01-08 16:27:19 +11:00
Dion Moult 53de93e582 WIP move the IFC Debug code into its own module. See #1222. 2021-01-08 13:49:31 +11:00
Dion Moult 0dcdfcf46c WIP implement local placement tree. See #1222. 2021-01-08 13:29:59 +11:00
Dion Moult 2d061f63fb WIP port add aggregate and remove container. See #1222. 2021-01-08 11:41:54 +11:00
Dion Moult afbdedaee8 WIP minor fixes to aggregate and spatial collection handling. See #1222. 2021-01-07 21:02:46 +11:00
Dion Moult 30d9ad1fbc Fix #1194. Aggregates no longer use collection instances. 2021-01-07 20:21:41 +11:00
Dion Moult d673e845f6 WIP psets now use partial editing with new features! See full message. See #1222.
* Psets are now sensitive to data type
 * Psets now support null vs empty
 * Psets now respect shared STEP IDs
2021-01-07 19:09:55 +11:00
Dion Moult fcc2b9ee13 WIP migrate types to partial editing. See #1222. 2021-01-07 10:47:50 +11:00
Dion Moult 02ac150a51 WIP Implement style edit/add. See #1222. 2021-01-06 17:57:24 +11:00
Dion Moult d206dff9c0 WIP class dropdowns are now schema version specific and generated. See #1222. 2021-01-06 15:19:55 +11:00
Dion Moult cac635107e WIP spatial operator now updates the blender collection structure. See #1222. 2021-01-06 11:06:59 +11:00
Dion Moult 8eb9973045 WIP refactor mesh UI into geometry module and minor fixes. See #1222. 2021-01-06 10:28:22 +11:00
Dion Moult c4aecd6e61 Minor fix for #1235. 2021-01-06 08:45:34 +11:00
QwiglyDee cef3b9537a toggle decorations onload
fix #1237
2021-01-06 04:01:03 +07:00
QwiglyDee 02b01b2a44 refectored decorations.
fixed #1241 somehow
2021-01-06 03:52:40 +07:00
QwiglyDee db5418cbfe fixed #1233 grid cropping 2021-01-06 02:32:55 +07:00
Bernd Hahnebach 44d3ddbb7c bimtester: add log file and zoom smart view for failed elements tests 2021-01-05 18:06:09 +01:00
Bernd Hahnebach b2e5c904c3 bimtester: copy all files of source code features path to tmp run 2021-01-05 18:06:09 +01:00
QwiglyDee 19d07892f4 fix #1240 undoing add_grid 2021-01-05 21:33:38 +07:00
Dion Moult 113efa1206 WIP you can now start a fresh project with partial editing support. See #1222. 2021-01-05 21:15:52 +11:00
Dion Moult f76d792a25 WIP port unit assignment to partial editing. See #1222. 2021-01-05 21:13:44 +11:00
Dion Moult d74b344a95 WIP create aggregation module to manipulate aggregations. See #1222. 2021-01-05 16:29:14 +11:00
Dion Moult 30b3090386 WIP migrate attribute management to partial editing with 4 new features! See #1222.
New features include:

 - New clarity between null and empty string attributes
 - Attribute editing now shows appropriate UI widgets depending on data type
 - Attribute editing for enumerations now show a dropdown
 - Attribute editing is now schema sensitive
2021-01-05 13:16:31 +11:00
Dion Moult d4a219e54f WIP assigning a class also assigns the spatial container if possible. See #1222. 2021-01-04 16:23:36 +11:00
Dion Moult 23a66b3a72 WIP allow partial editing of spatial container. See #1222. 2021-01-04 15:57:25 +11:00
Dion Moult d9dbda6b5a Minor fix 2021-01-04 15:57:25 +11:00
QwiglyDee cbcd04c81d drawing grid clipping 2021-01-04 11:31:30 +07:00
Dion Moult 1fe2bd8332 Merge branch 'v0.6.0' of github.com:IfcOpenShell/IfcOpenShell into v0.6.0 2021-01-04 13:07:36 +11:00
Dion Moult 6387c03dbc WIP port reassign and unassign class to partial editing. See #1222. 2021-01-04 13:07:29 +11:00
Cyril Waechter 516869ba5d Use lru_cache for pset module (#1229)
New features
===========
* `get_by_name` : get pset template by name
* `is_templated` : allow to check if a pset template correspond to given name

Enhancement
============
* Use of lru_cache simplify code and enhance performance largely
(10+ times more requests in 4 less time)
kudo to aothms for the idea. See https://github.com/IfcOpenShell/IfcOpenShell/pull/1221#issuecomment-752902996.
* Take advantages of new caching system and new features in blenderbim
2021-01-04 12:13:04 +11:00
Dion Moult 0c0ffce908 WIP assigning a class now ported over to partial editing and creates an IFC element. See #1222. 2021-01-04 11:08:15 +11:00
johltn f120f0c77c Added travis_wait to CMake command 2021-01-03 14:42:49 +01:00
johltn 3961ecd322 Added travis_wait to CMake command 2021-01-03 14:01:26 +01:00
johltn 23c0e279be Added travis_wait to CMake command 2021-01-03 13:56:48 +01:00
johltn 6e4bb95e82 Update 2021-01-03 13:10:57 +01:00
Dion Moult af5350bb9f WIP refactor representation editing into geometry module. See #1222. Some new functionality as a result:
- Representations can now be added to any context, even invalid ones, non-subcontext, or missing target views
 - Switching representations now change all linked data objects
2021-01-03 19:45:40 +11:00
Dion Moult c5ec54ca7f WIP refactor context UI into its own module. Remove dependency to Blender properties. See #1222. 2021-01-03 12:08:00 +11:00
johltn efea9d429e Verbose 2021-01-02 15:48:34 +01:00
Thomas Krijnen b91dfb401d Rewrite svg array_to_string() 2021-01-02 13:08:01 +01:00
Thomas Krijnen 979f37d7c6 --svg-poly option and correct HLR view direction 2021-01-02 12:34:10 +01:00
Dion Moult 23abc604f9 WIP implement partial editing for adding / removing subcontexts. See #1222. 2021-01-02 20:28:52 +11:00
Dion Moult a997b2f999 WIP you can now partially edit the object placement of an object. See #1222. 2021-01-02 19:33:32 +11:00
Dion Moult 0ecf66f7fa New IfcOpenShell placement utility module 2021-01-02 19:32:27 +11:00
Dion Moult 2c6686846a WIP allow partial mesh geometry editing to preserve style assignments. See #1222. 2021-01-02 17:45:36 +11:00
Dion Moult 008014a89b WIP refactor ability to partially write a new shape representation. See #1222. 2021-01-02 15:39:24 +11:00
Dion Moult b016d39eca WIP refactoring representations to be incrementally edited. See #1222.
# Conflicts:
#	src/ifcblenderexport/blenderbim/bim/operator.py
2021-01-01 12:15:18 +11:00
QwiglyDee c773b5741b decorations anti-aliasing 2020-12-31 19:56:55 +07:00
Cyril Waechter 9060b6ee40 Rework python pset module (#1221)
New features
============
* Handle all syntax for ApplicableEntity as defined in IFC documentation. (drawback it increase request time by ~2/3)
* Allow to get applicable psets directly from template definition without caching.
This allow more general purpose usages. (drawback it increase request time by ~2.4)

To notice / discuss
===================
* `ifcwrap/CmakeLists` was installing only `.py` and `.bnf` files from `ifcopenshell-python`.
Why ? It now copy all files. Is it an issue ?
* property template file is now stored in ifcopenshell python module to allow usage
from every softwares. It was before only available for blenderbim addon.
* psets and qtos are now optionnally cached at object instead of module level.
This allow to work with multiple schema in the same python interpreter.
(eg. might help conversion between schemas)
* in blenderbim addon psetqto are now stored in `schema.psetqto`.
2020-12-31 21:39:33 +11:00
Thomas Krijnen c3d4ce8f51 Store drawing location in SVG 2020-12-31 11:31:05 +01:00
Thomas Krijnen a5adb01dff IfcConvert --svg-xmlns option 2020-12-30 14:44:43 +01:00
Thomas Krijnen de5ce28a78 --auto-section and --auto-elevation flags 2020-12-30 14:25:08 +01:00
Dion Moult 9def261316 Importing now stores a link to the original IFC representation contexts and subcontext IDs 2020-12-30 21:09:19 +11:00
Dion Moult c844076efb New experimental option to export file from memory in preparation for incremental editing 2020-12-30 13:50:10 +11:00
Dion Moult ee222628f3 Add Vim swp files to gitignore 2020-12-30 12:20:02 +11:00
Dion Moult cd6c258687 IFC Clash in the BlenderBIM Add-on now generates snapshots of clashes in BCF 2020-12-30 12:18:41 +11:00
QwiglyDee 0799a78e9a aligned grid labels horizontally 2020-12-30 02:44:46 +07:00
QwiglyDee a073015a9a Merge branch 'v0.6.0' of github.com:IfcOpenShell/IfcOpenShell into v0.6.0 2020-12-30 01:07:13 +07:00
QwiglyDee 01d59a1bc2 decoration code cleanedup/refactored 2020-12-30 01:05:48 +07:00
QwiglyDee 453dbd65ac grid decorations. 2020-12-29 21:43:35 +07:00
aothms 7ae685dbff Nix build: py39, boost1.71, no py34 on macos, boost url, no dae validator build 2020-12-29 07:59:52 -05:00
QwiglyDee 0d457ba0ce breakline decoration.
close #1214
2020-12-29 19:10:29 +07:00
Dion Moult ef8b3d60b7 Merge branch 'v0.6.0' of github.com:IfcOpenShell/IfcOpenShell into v0.6.0 2020-12-29 22:49:28 +11:00
Dion Moult c502d39aaf Add support for BCFXML export of IFC Clash results 2020-12-29 22:49:22 +11:00
QwiglyDee 397a09846e Merge branch 'v0.6.0' of github.com:IfcOpenShell/IfcOpenShell into v0.6.0 2020-12-29 18:18:45 +07:00
Dion Moult ceb7b0e13f Refactor BCF features into its own module 2020-12-29 14:15:15 +11:00
Dion Moult f49174cab4 Refactor main init to call module inits instead 2020-12-29 13:49:53 +11:00
Dion Moult 17e805e144 Minor fix - see #1062 2020-12-29 10:03:57 +11:00
Long 5c92bd7348 implement Open Drawing Camera button (#1220) 2020-12-29 10:00:49 +11:00
QwiglyDee 7c45181a6e fixed decoration of broken geom again 2020-12-29 02:15:28 +07:00
QwiglyDee 82468370a7 fixed Level decoration color
close #1213
2020-12-29 02:09:48 +07:00
QwiglyDee 7f49ebea55 fixed addin grid
close #1217, close #1215
2020-12-29 02:04:08 +07:00
Dion Moult c0381588f3 Implement add BCF related topic 2020-12-28 20:13:41 +11:00
Dion Moult 37e56c4011 Implement remove BCF related topic 2020-12-28 19:56:57 +11:00
Dion Moult ea83238e7a Implement support for adding BCF document references 2020-12-28 19:46:47 +11:00
Dion Moult fa6df3fa30 Implement support for deleting document references 2020-12-28 18:44:33 +11:00
johltn 424069893e Include ifcparse 2020-12-28 06:38:06 +01:00
johltn abb34d33e4 Update 2020-12-28 06:07:00 +01:00
Dion Moult 36a0119f40 Implement add BIM Snippet 2020-12-28 16:04:09 +11:00
Dion Moult 9fc5d97488 Merge pull request #1219 from htlcnn/v0.6.0
ifccsv delimiter
2020-12-28 15:03:55 +11:00
htlcnn f277733ff5 ifccsv delimiter 2020-12-28 10:18:55 +07:00
Dion Moult 510d756cc4 Implement delete BCF topic BIM snippet 2020-12-28 13:14:33 +11:00
Dion Moult bca9c82c3d Implement ability to edit labels 2020-12-28 12:50:22 +11:00
Dion Moult 3deba2e71e Implement support for adding BCF labels to topics 2020-12-28 12:46:52 +11:00
Dion Moult d5566785be Implement BCF delete label 2020-12-28 11:40:40 +11:00
Dion Moult 6cfa9f6e9b Implement ability to edit individual BCF reference links 2020-12-28 11:20:44 +11:00
Dion Moult 6a00f2f0d2 Implement adding BCF reference links 2020-12-27 17:07:02 +11:00
Dion Moult b9583c562d Implement support for deleting reference links 2020-12-27 16:53:40 +11:00
Dion Moult e51b7d3c85 Implement ability to add BCF header file 2020-12-27 16:20:35 +11:00
Maxim Vasilyev 5234c8086f fixed typo 2020-12-27 00:21:59 +07:00
QwiglyDee 7e306251c1 Misc annotation and decoration.
close #1209
2020-12-26 23:41:10 +07:00
QwiglyDee 8d05ceaea9 Merge branch 'v0.6.0' of github.com:IfcOpenShell/IfcOpenShell into v0.6.0 2020-12-26 23:26:00 +07:00
QwiglyDee abaae7f06d copying grid.
close #1210
2020-12-26 23:25:39 +07:00
QwiglyDee 3c2c591d6d breakline annotation
close #1208
2020-12-26 22:01:14 +07:00
Thomas Krijnen 315b32dd38 Nix build: assert cmake in path 2020-12-26 13:49:57 +01:00
Dion Moult 6699f2dccf Merge pull request #1212 from htlcnn/v0.6.0
fix IfcGetAttribute malfunction #1089
2020-12-26 15:13:09 +11:00
htlcnn f235f5765b fix IfcGetAttribute malfunction 2020-12-26 11:08:07 +07:00
aothms 877bf3207a Nix build: no longer build cmake, some fixes for 32bit crosscompiling 2020-12-24 20:46:42 +00:00
QwiglyDee 119a729319 fix #1165 imperial formatting 2020-12-24 21:55:27 +07:00
QwiglyDee 1b9b005820 decorations colour.
close #1197
2020-12-24 21:04:44 +07:00
QwiglyDee 1bea18d3cf fixed #1206, #1207 decorating incomplete and zero segments 2020-12-24 19:50:36 +07:00
Bernd Hahnebach 1b6857b8ba bimtester: also use gettext for html report translation 2020-12-23 11:41:35 +01:00
Bernd Hahnebach 666641bb18 bimtester: reports, code formating 2020-12-23 11:41:35 +01:00
Dion Moult 67f7e68fa7 Implement support for deleting BCF header files 2020-12-23 16:22:29 +11:00
Dion Moult 7b2fa3e877 Add support for adding BCF viewpoints 2020-12-23 15:53:38 +11:00
Dion Moult 4d2be3e3c5 Since current implementations will allow BCF FoV outside the 45-60 range, let's allow it 2020-12-23 15:53:18 +11:00
Dion Moult 5a1f2ec4fe Implement support for editing BCF comments 2020-12-23 13:58:28 +11:00
Bernd Hahnebach b22055a588 bimtester: once again move report data into resources dir 2020-12-22 20:37:41 +01:00
Bernd Hahnebach 27051cce8a bimtester: move report data into new directory 2020-12-22 20:29:56 +01:00
Bernd Hahnebach 4df8418e72 bimtester: steps, add more attributes tests 2020-12-22 20:14:05 +01:00
QwiglyDee 6dfeaf5509 bpy-based formatting units for decoration
close #1164
2020-12-22 22:46:49 +07:00
QwiglyDee 30f8350156 decorators for Levels 2020-12-22 22:28:55 +07:00
QwiglyDee 7a7caffaae fix #1198 stair decorator arrow shape 2020-12-22 19:35:29 +07:00
QwiglyDee a5530acfd7 fixed Hidden decotator in edit mode 2020-12-22 19:27:44 +07:00
QwiglyDee 8baf9b056d decorators cleanup 2020-12-22 18:47:50 +07:00
Dion Moult 6f84bc6ce5 Implement BCF add comment 2020-12-22 18:41:51 +11:00
Dion Moult 6a5d255c2f Implement delete BCF comment 2020-12-22 18:23:43 +11:00
Dion Moult ee42703f9f Implement delete BCF viewpoint 2020-12-22 16:22:29 +11:00
Bernd Hahnebach 2226d5a565 bimtester: steps, remove a newline added by accident 2020-12-21 17:14:12 +01:00
Bernd Hahnebach 7d138b8f72 bimtester: steps, add missing import 2020-12-21 17:09:46 +01:00
Bernd Hahnebach edd6e74813 bimtester: steps, add element class attributes test 2020-12-21 17:05:08 +01:00
Bernd Hahnebach 2a6efaaaa4 bimtester: step, prepare attributes eleclasses for translation 2020-12-21 17:05:08 +01:00
Bernd Hahnebach dafdd06b2e bimtester: steps, split steps testmodule 2020-12-21 16:37:13 +01:00
Bernd Hahnebach 1a48472b19 bimtester: steps, sort them according expression matcher 2020-12-21 16:08:21 +01:00
Bernd Hahnebach 8e78ed332f bimtester: steps, move project test into project test module 2020-12-21 16:08:21 +01:00
Bernd Hahnebach de5dc40e63 bimtester: steps, add new test module for spatial structure 2020-12-21 16:08:21 +01:00
Bernd Hahnebach 60dd74c64d bimtester: steps, better name for element class guid tests 2020-12-21 16:08:21 +01:00
QwiglyDee ff0a7891be decorators code cleanup 2020-12-21 20:22:23 +07:00
QwiglyDee a14c0f70a6 decorator for hidden close #1178 2020-12-21 20:22:23 +07:00
QwiglyDee babbd51e70 decorations for Dim, Eq, Leader, Stair
close #1177, #1176, #1158, #1150
2020-12-21 20:22:23 +07:00
QwiglyDee ec02c8600b refactored shaders 2020-12-21 20:22:23 +07:00
QwiglyDee 0c06639635 decorator classes for Dim/Eq/Leader/Stair/Hidden 2020-12-21 20:22:23 +07:00
QwiglyDee 97913e8592 fixed #1157 again with proper perspective correction 2020-12-21 20:22:23 +07:00
Bernd Hahnebach 26d537cb4f gitignore: add gettext binary translation files, used in bimtester 2020-12-21 12:16:55 +01:00
Bernd Hahnebach 3b856f446e bimtester: remove binary mo files from repository 2020-12-21 12:16:55 +01:00
Bernd Hahnebach b8fe04b7a9 bimtester: fix error in step code 2020-12-21 11:28:51 +01:00
Bernd Hahnebach 81326ba48f bimtester: improve and translate geometric representation class type test 2020-12-21 11:24:42 +01:00
Bernd Hahnebach 21a7599d45 bimtester: small code improvements 2020-12-21 11:24:42 +01:00
Bernd Hahnebach 1074c2431c bimtester: add dummy feature file to be able to run a command to get all implemented steps 2020-12-21 11:24:42 +01:00
johltn b77aa11776 Update 2020-12-21 10:15:39 +01:00
johltn b6cf97a291 Change RST file title 2020-12-21 09:32:52 +01:00
Dion Moult eb0f2de197 New snap spaces together utility for cleaning up spaces for energy modeling 2020-12-21 18:26:39 +11:00
Dion Moult 1a48343bcb Optimise import and editing for files with lots of aggregations 2020-12-21 10:44:14 +11:00
Dion Moult b0bd027f84 Optimise import to only consider surface styles 2020-12-21 10:43:21 +11:00
Thomas Krijnen 8bf530d0d7 Missing file that accompanies 9bcd932bed 2020-12-20 21:53:51 +01:00
Thomas Krijnen a3bc159359 #1173 mutex in get_default_style() 2020-12-20 14:38:54 +01:00
Thomas Krijnen 7d756138f2 Add generator expresss_parser.py 2020-12-20 11:10:21 +01:00
Dion Moult c16b63e5ae New import code profiler in the IFC debug panel 2020-12-20 13:48:37 +11:00
Dion Moult 3eee5aba78 Optimise presentation layer assignment which was ridiculously slow and badly implemented 2020-12-20 11:03:19 +11:00
Dion Moult 05d835410d Reimplement basic BCF metadata editing and further improve BCF UI 2020-12-19 21:48:23 +11:00
Dion Moult 03d8537a2d Revert borked submodules. See #1186. 2020-12-19 14:29:43 +11:00
Dion Moult 509ee78b67 Merge pull request #1184 from IFCRail/v0.6.0-ifcrail-mod
Set of improvements for BIMTester
2020-12-19 14:24:52 +11:00
Roch Bertucat 8cc546a9a2 Add path option for providing a schema in a step 2020-12-18 17:14:55 +01:00
Roch Bertucat 0ab82295f9 Fix a small issue in report path 2020-12-18 16:51:01 +01:00
Roch Bertucat 0f66f88420 Revert template change 2020-12-18 16:25:00 +01:00
Roch Bertucat 5572faf8b4 Fix an issue with localedir 2020-12-18 16:12:11 +01:00
Roch Bertucat 322860cc51 Merge remote-tracking branch 'origin/v0.6.0-ifcrail-contrib' into
v0.6.0-ifcrail-mod

Conflicts:
	src/ifcbimtester/bimtester/features/steps/ifcdata.py
	src/ifcbimtester/bimtester/features/template.html
	src/ifcbimtester/bimtester/reports.py
	src/ifcbimtester/bimtester/run.py
2020-12-18 15:44:46 +01:00
rbertucat 1bff04d2c0 Merge pull request #3 from IfcOpenShell/v0.6.0
Merge changes from main repo
2020-12-18 12:54:34 +01:00
Dion Moult de4f18e2af New UI to show BCF comments in the BCF panel as a subpanel 2020-12-18 22:14:31 +11:00
Roch Bertucat 03dd4c39b7 Add skipped step to the HTML template 2020-12-18 11:24:33 +01:00
Roch Bertucat fc7d05c691 Improve referencing files using the path if available 2020-12-18 11:24:01 +01:00
Roch Bertucat 854a0fe863 Add a way to specify a path to the arguments 2020-12-18 11:22:51 +01:00
Roch Bertucat 9ffc2874da Add a way to stop if fail step and improve report accordingly 2020-12-18 11:22:14 +01:00
Roch Bertucat e01b677845 Add build/dist folders to gitignore 2020-12-18 11:20:42 +01:00
Bernd Hahnebach 85a78a6e48 bimtester: se gettext for message translation 2020-12-18 17:25:05 +11:00
Bernd Hahnebach 3ae20637d7 bimtester: code formating 2020-12-18 17:25:05 +11:00
Dion Moult 7dd40149aa Migrate from bcfplugin to new bcf library in the BlenderBIM Add-on 2020-12-18 16:28:17 +11:00
Dion Moult d08da0a61d Document basic usage of bcf library 2020-12-17 22:47:15 +11:00
Dion Moult 1b09bb37e8 The BCF-XML library can now handle most data writing functions 2020-12-16 23:47:50 +11:00
Bernd Hahnebach 90f225e93b bimtester: improve submodule handling for step translation 2020-12-16 23:10:40 +11:00
QwiglyDee f00040c7d9 decorators for equal dimentions #1158 2020-12-16 17:29:15 +07:00
QwiglyDee b8286e8fb5 arrow size fix #1157 2020-12-16 17:06:36 +07:00
QwiglyDee dbafcc2fa1 fixed #1159 zero projection 2020-12-16 16:54:49 +07:00
Håkon Åmdal a869e88de0 fix: use correct initializer function when compiling with USE_MMAP 2020-12-15 13:25:48 +01:00
Dion Moult 5ad6abea1a Add simple BCF library to supersede bcfplugin, with bcfxml read capability 2020-12-15 14:49:29 +11:00
Bernd Hahnebach d00da09cdc start translation into German and French with one step as well as the report 2020-12-15 10:09:46 +11:00
Dion Moult 17a8b33387 You can new create new BCF projects from scratch 2020-12-14 13:51:01 +11:00
Dion Moult 4f2bf3a36f You can now add new BCF topics to a BCF project 2020-12-14 13:29:52 +11:00
Carlos Dias e208dd0381 Update selector.py
Changes fix problem with boolean values
2020-12-14 12:59:20 +11:00
Dion Moult a62a32d414 Support for setting the BCF author. You can also now edit basic BCF topic metadata. 2020-12-13 21:56:04 +11:00
Dion Moult 6a06c292a1 Fix #1148. Fix crash when creating drawings on Windows with Blender >= 2.91 2020-12-13 16:54:11 +11:00
Dion Moult 9dcf44fbea You can now view and edit the BCF project name 2020-12-13 16:35:51 +11:00
Dion Moult e39a997f5f Bump to latest bcfplugin, new operator to save BCF projects 2020-12-13 13:45:21 +11:00
Vincent Cadoret f3269b732f More sensible names for the Smart Clash Groups 2020-12-12 13:04:28 +11:00
Vincent Cadoret 14c726008d Split out clashes that were not grouped so they so up individually. 2020-12-12 13:04:28 +11:00
rbertucat c0b4115202 Merge pull request #1 from engisis-com/v0.6.0
Apply changes done under Engisis to the IFCRail fork
2020-12-11 15:48:56 +01:00
Dion Moult d5e6721ac4 Minor fix to support multiple dimension objects for decorations. See #1150. 2020-12-11 11:13:48 +11:00
QwiglyDee 48de2f77ab fix arrows heads 2020-12-11 10:11:47 +11:00
QwiglyDee f37283f61c drawing arrows 2020-12-11 10:11:47 +11:00
QwiglyDee cc5f34a705 text drawing 2020-12-11 10:11:47 +11:00
QwiglyDee 33bf7054bf ui and decorator handler 2020-12-11 10:11:47 +11:00
Thomas Krijnen 14193fb486 #1126 more elaborate polygonal curve segment check 2020-12-10 10:48:14 +01:00
Roch Bertucat 34174dd3f3 Add a set of steps to test aggregations in IFC files 2020-12-10 10:42:49 +01:00
Roch Bertucat 479b937f81 Add a way to load a custom IFC Schema and add util methods 2020-12-10 10:37:17 +01:00
Roch Bertucat cada9c9e3b Specify encoding for HTML report for special characters 2020-12-10 10:35:47 +01:00
Roch Bertucat 860d795ba1 Add a way to generate a report after the tests in the same command 2020-12-10 10:35:13 +01:00
Dion Moult 2ac0b75dbc New Link IFC operator to easily append IFCs from another Blend file into a master file 2020-12-10 13:52:29 +11:00
Dion Moult fb7998980d Fix bug where aggregates were accidentally hidden when generating drawings 2020-12-10 13:51:51 +11:00
Dion Moult b9af4906aa Fix bug where selecting the IFC file for drawing generation didn't work 2020-12-10 13:51:27 +11:00
Dion Moult ce6350a52f New clean wireframes operator to easily apply edge split modifier to nicer drawings 2020-12-10 13:50:43 +11:00
Dion Moult b65c1e94ad Purge old experimental painter algorithm code for vector background elements
In preparation to migrate this to C++
2020-12-09 10:38:13 +11:00
Dion Moult 0387783e9d Minor fix 2020-12-07 17:28:16 +11:00
Dion Moult b72b2aa7d7 Package new BIMTester for the BlenderBIM Add-on 2020-12-07 16:42:01 +11:00
Dion Moult c1bbb1e721 You can now bake parametric geometry to meshes 2020-12-07 15:33:51 +11:00
Dion Moult 0d28e741fc Fix bug where spatial elements didn't get styles exported correctly 2020-12-06 19:10:03 +11:00
Dion Moult 0d03b4e008 Allow graceful migration of IFC entities when exporting so the user doesn't need to fix every invalid schema attribute themselves3RlG$Bayj3kPlwh4EEvXJP 2020-12-06 11:38:02 +11:00
fbpyr 981f0c23c7 apply matrix to object in BlenderClasher
Since scale is not supported in fcl upstream as found in https://github.com/IfcOpenShell/IfcOpenShell/issues/1129
2020-12-04 19:05:53 +11:00
Dion Moult 884e8a5663 Fix #1071. New IFC file version 2X3<->4 upgrader and downgrader IfcPatch recipe 2020-12-04 11:52:18 +11:00
Dion Moult 06685f9768 Fix example script for printing out properties. See #1145. 2020-12-04 10:59:59 +11:00
Dion Moult 9a20de914b Add new workaround for the DESITE BIM application 2020-12-04 09:23:44 +11:00
Bernd Hahnebach 26f6e875ed bimtester: add more ifc file tests 2020-12-04 09:20:41 +11:00
Bernd Hahnebach cda131d6c1 bimtester: move ifc steps in separte module 2020-12-04 09:20:41 +11:00
Dion Moult e1fa6fb306 You can now apply drawing styles to elements with material set usages 2020-12-03 22:17:46 +11:00
Dion Moult 679c2bef02 Fix bug where aggregates cause drawing generation to fail 2020-12-03 21:52:17 +11:00
Dion Moult 8bb157ce0a Auto-add the currently loaded IFC when creating a drawing for the first time 2020-12-03 21:51:14 +11:00
Dion Moult bdaf8cd0f3 Fix import bug where duplicate material names with accents cause import to fail 2020-12-03 21:44:20 +11:00
Dion Moult 4e62c276ee Fix #1111 - issue where sometimes class and product dropdown gets out of sync. Also new utility function to query is_a() in the schema. 2020-12-02 09:51:00 +11:00
Dion Moult c70b41f21a Fix #1112. You can now tag material attributes. 2020-12-02 09:03:18 +11:00
Dion Moult aaf9b10a9e Fix #1128 with improved IFCCSV description 2020-12-02 08:50:15 +11:00
Thomas Krijnen 9281c8fbce #1126 Update serialization for trimmed curve 2020-12-01 14:03:07 +01:00
Dion Moult 5f76062575 Fix issue where invalidly declared representation contexts can confuse drawing creation 2020-12-01 22:26:02 +11:00
Dion Moult efd2663f15 Support layer set material names classes in drawings 2020-12-01 22:25:30 +11:00
Dion Moult 823b10e323 Dumb grids are auto placed in an IfcSite if it can be detected for convenience 2020-12-01 21:37:47 +11:00
Dion Moult 431de8d5a1 Package ExtractElements IfcPatch recipe with the BlenderBIM Add-on 2020-12-01 21:29:09 +11:00
Dion Moult dce730d9c2 Ship optimise IfcPatch recipe with BlenderBIM 2020-12-01 21:24:30 +11:00
Vincent Cadoret 50d7efa99b move import statements to make dependencies optional
so regular clashing doesn't break if the dependencies are not present.
2020-12-01 14:06:57 +11:00
Vincent Cadoret 957c719224 Skip clash_set if it has 0 clashes 2020-12-01 14:06:57 +11:00
Vincent Cadoret b407b815e2 Allow selection of max grouping distance in UI 2020-12-01 14:06:57 +11:00
Vincent Cadoret ac12a6785c Added a button to Load the smart clash groups for the active clash set 2020-12-01 14:06:57 +11:00
Vincent Cadoret 8aae7c95e6 Rename IsolateSmartGroup operator to SelectSmartGroup 2020-12-01 14:06:57 +11:00
Vincent Cadoret bbde4e7522 Added a ui to select input and output files to clash smart grouper. 2020-12-01 14:06:57 +11:00
Vincent Cadoret 803a4b6c12 cleanup unnecessary imports and prints 2020-12-01 14:06:57 +11:00
Vincent Cadoret 5a06bd5a57 Minimum viable protoype for Smart Clash Grouping completed 2020-12-01 14:06:57 +11:00
Vincent Cadoret 51dca4329c Add a more useful error message when no clashes are loaded for the given clashset 2020-12-01 14:06:57 +11:00
Vincent Cadoret 1921b4cecf Added clash manager basic interface to load smart grouped clashes 2020-12-01 14:06:57 +11:00
Dion Moult f7e05e011a Merge branch 'fix-roundtrip' into v0.6.0 2020-12-01 10:47:49 +11:00
Dion Moult 2596f90015 Fix #952. Implement roundtripping of all representation contexts. 2020-12-01 10:46:28 +11:00
Bernd Hahnebach 24c542e33a bimtester: small code improvements in gui 2020-11-30 17:54:10 +11:00
Dion Moult 7b7f756506 Add support of exporting material sets for construction types 2020-11-30 11:28:32 +11:00
Dion Moult 9ca124bf2f New UI to show inherited materials from related types 2020-11-30 11:27:51 +11:00
Dion Moult c9666015bb Fix error when creating a drawing of a file with material set usages 2020-11-30 09:51:42 +11:00
Thomas Krijnen 8815b74ff8 thanks @tpaviot 2020-11-29 16:16:11 +01:00
Dion Moult 98f45817a6 Improved UI for psets and qtos with collapsible panels and improved readibility 2020-11-29 23:24:56 +11:00
Dion Moult e3f61510ad The object psets panel now show inherited psets too 2020-11-29 22:26:51 +11:00
Bernd Hahnebach 864dcffef8 bimtester: startscript, add argument to start gui with some start directories 2020-11-28 08:27:24 +11:00
Bernd Hahnebach fae899823b bimtester: rename startscript, if startscript and package have the same name it is difficault to import the startscrip as the package has priority 2020-11-28 08:27:24 +11:00
Bernd Hahnebach 26d35a7644 bimtester: improve the signatures of the methods to run behave in temporary directory 2020-11-28 08:27:24 +11:00
Dion Moult 4a5fe83dab Fix minor regression where the section cutting plane doesn't work if you haven't selected an object 2020-11-27 22:07:32 +11:00
Dion Moult 78666caa47 Minor improvement to roundtripping. Combined with 2.91 booleans, this rocks. 2020-11-27 22:02:12 +11:00
Dion Moult 3ad2d0eaac Fix import bug where some IfcOpeningElements aren't put in the openings collection properly 2020-11-27 22:01:43 +11:00
Dion Moult 7ad35249b8 IfcOpeningElements now show up as wireframe for convenience by default 2020-11-27 22:01:15 +11:00
Dion Moult 259d467164 Add experimental support for non-IFC Blender clashing. See #1129. 2020-11-27 18:18:23 +11:00
Dion Moult cfa97be080 Be less accommodating to invalid Revit grids. See #1133. 2020-11-27 12:14:08 +11:00
Dion Moult fddea742b8 Support invalid IfcGrid elements coming from Revit. See #1133. 2020-11-27 09:31:00 +11:00
Bernd Hahnebach 6ebb69f62e bimtester: steps, improve imports 2020-11-27 09:07:01 +11:00
Dion Moult b0097d35b4 Merge branch 'v0.6.0' of github.com:IfcOpenShell/IfcOpenShell into v0.6.0 2020-11-26 21:31:52 +11:00
Dion Moult 15ea15d9ab Roundtripping geometry now works for one to many styled item relationships 2020-11-26 21:31:42 +11:00
Bernd Hahnebach b88eb37bdf bimtester: improve imports in steps 2020-11-26 19:00:57 +11:00
Bernd Hahnebach 5ce334019c bimtester: merge guibimtester into bimtester module 2020-11-26 19:00:57 +11:00
Bernd Hahnebach 15199152ac bimtester: code formating and comments 2020-11-26 19:00:57 +11:00
Dion Moult e346d5e3c6 Support invalid empty IFC properties coming from ArchiCAD. See #1131. 2020-11-26 12:48:03 +11:00
Dion Moult 957cc02157 Support exporting downgraded material definitions to IFC2X3 from IFC4 2020-11-26 09:53:05 +11:00
Bernd Hahnebach 32f99428c3 bimtester: move code into a package directory 2020-11-26 08:30:03 +11:00
Thomas Krijnen acb518613b #1118 check parallel and shape type 2020-11-25 11:02:57 +01:00
Dion Moult 25a26db360 Exporting classifications to IFC2X3 (including downgrading) is now supported 2020-11-25 20:35:11 +11:00
Dion Moult 5cbc924c85 Merge branch 'v0.6.0' of github.com:IfcOpenShell/IfcOpenShell into v0.6.0 2020-11-25 20:17:47 +11:00
Dion Moult 4bff3dc3dd Roundtripping native geometry now works across different IFC schema versions 2020-11-25 20:17:30 +11:00
Bernd Hahnebach a5b00f1ac9 bimtester: pass the ifc base file name to behave 2020-11-25 19:29:47 +11:00
Bernd Hahnebach a9a8213731 bimtester: comments and code formating 2020-11-25 19:29:47 +11:00
Dion Moult 33b2661464 Merge branch 'v0.6.0' of github.com:IfcOpenShell/IfcOpenShell into v0.6.0 2020-11-25 13:15:20 +11:00
Dion Moult 3085c88647 New experimental IfcOpenShell IFC2X3<->IFC4 version migration utility 2020-11-25 13:13:46 +11:00
Bernd Hahnebach 7ec91728be bimtester: remove the just added licence headers to avoid any confusion 2020-11-25 08:56:03 +11:00
Thomas Krijnen b1c4481795 Option to disable boolean results (sets result to first operand) 2020-11-24 16:58:05 +01:00
Bernd Hahnebach dd4902be18 bimtester: fix licence header 2020-11-24 18:04:34 +11:00
Dion Moult c057cb9aab Recreating round-tripped representations now preserves surface styles 2020-11-24 12:09:49 +11:00
Dion Moult e2543954c0 Native geometry round-tripping now works with decoupled surface styles 2020-11-24 10:18:16 +11:00
Bernd Hahnebach 7ba812c6c9 bimtester: some restructure work 2020-11-24 08:21:19 +11:00
Thomas Krijnen b15acfed42 Update IfcGeomShapes.cpp 2020-11-23 11:21:14 +01:00
Thomas Krijnen 648c976dd4 Remove debugging code #1121 2020-11-23 11:20:55 +01:00
Dion Moult dd0a3ad7b8 Minor fix. Forgot to commit when I cleaned up the simpler copy attributes operator. 2020-11-23 16:01:21 +11:00
Dion Moult b37ddb766f Native representation roundtripping now supports layer assignments and will "fix" representations to use subcontexts properly. See #952. 2020-11-23 16:00:45 +11:00
Dion Moult 7cc832ea15 Fix warnings in new simplified copy attribute to selection operator 2020-11-22 09:29:33 +11:00
johanrd fc5fcef079 Fix for #1119 (regression from 0984751) 2020-11-21 10:53:00 +01:00
Dion Moult 280466df53 Fix bug where a material wouldn't get assigned for multiple mapped representations 2020-11-20 23:31:52 +11:00
Dion Moult 2bd44e2fe8 Add support for importing IfcMaterial description and category attributes 2020-11-20 23:31:29 +11:00
Dion Moult 9a87f3673a Vendor workaround "treat styled item as material" deprecated, as new material & style system supports styles much better 2020-11-20 20:30:30 +11:00
Dion Moult 5af85ee7a3 Add support for IFC2X3 material data imports 2020-11-20 19:49:50 +11:00
Dion Moult e150e5f6c3 Fix default layer category to none, not load bearing, in case we import IFC2X3 where this is blank 2020-11-20 19:49:04 +11:00
Dion Moult 44dc5a92b7 Fix bug where no colour is set if only a styled item has a style but a material has no representation 2020-11-19 22:38:23 +11:00
Laurens Oostwegel 1f938c7f1a Deleted IfcWall duplicate in defaut styles 2020-11-19 20:35:56 +11:00
Dion Moult 225f8c788b Bump IFCJSON dep 2020-11-15 22:15:53 +11:00
Dion Moult 17d069e9b5 Bump IfcOpenShell & minor fix 2020-11-15 21:08:25 +11:00
Dion Moult 21b9557b97 Minor fix 2020-11-15 20:26:22 +11:00
Dion Moult 76b29cb174 Presentation layers are now assigned to meshes, and implement representation assignment. See #1109. 2020-11-15 17:00:50 +11:00
Dion Moult 1c24a59075 Merge branch 'v0.6.0' of github.com:IfcOpenShell/IfcOpenShell into v0.6.0 2020-11-14 22:18:14 +11:00
Dion Moult 9080744669 Minor fixes to new presentation layer features by Krande 2020-11-14 22:17:56 +11:00
Thomas Krijnen 47cd183e61 submodule 2020-11-14 11:04:12 +01:00
Dion Moult 9dcb2f9094 Merge branch 'Krande-presentationlayer' into v0.6.0 2020-11-14 19:55:09 +11:00
Dion Moult 2e762854fa Merge branch 'presentationlayer' of https://github.com/Krande/IfcOpenShell into Krande-presentationlayer 2020-11-14 19:54:51 +11:00
Dion Moult 819b62a747 Fix bug where a styled item could be incorrectly assigned if an element has more than one representation context 2020-11-14 14:33:58 +11:00
Dion Moult 599089ad67 Now materials that aren't also used as a styled item can be exported 2020-11-14 13:36:49 +11:00
Dion Moult ddfe0e0c98 IFCCSV will now skip GUIDS that it cannot find 2020-11-14 10:11:36 +11:00
Dion Moult 27a8e7c89a IFCCSV now continues to edit other attributes even if it cannot change a class 2020-11-14 10:07:08 +11:00
Kristoffer b9e34a107b Prepare for pull request 2020-11-13 14:45:08 +01:00
Dion Moult df3bb0428c Fix #1103 bug where importing multiple grids with the same name fails 2020-11-13 22:01:49 +11:00
htlcnn 728b60e8c3 remove unused imports 2020-11-13 20:13:07 +11:00
Dion Moult 808ef1a19e New UI to manage material psets instead of needing to use CSVs 2020-11-11 23:02:07 +11:00
Dion Moult d6397baa59 Blender materials now map 1:1 to IfcMaterial and can store attributes 2020-11-11 22:13:50 +11:00
htlcnn ecdc05d265 remove unused IfcElementType dropdown items 2020-11-11 11:35:14 +11:00
Bernd Hahnebach 7bb5860200 bimtester: fix in report creation on empty steps 2020-11-11 11:34:55 +11:00
Dion Moult b3d180a288 Add workaround to guess geolocation data from Revit 2020-11-10 22:43:05 +11:00
Dion Moult a9ae92883d Add support for importing material data for type elements with no representation geometry 2020-11-10 18:02:43 +11:00
Dion Moult 1866b7852a Provide support of upgrading a deprecated material list as a constituent set during import 2020-11-10 17:50:04 +11:00
krande aca90b38c8 further experimentation. Still not able to hide\unhide 2020-11-09 18:08:03 +01:00
Kristoffer 2eae3a70d9 Added support for importing Presentation Layers from Ifc 2020-11-09 16:44:56 +01:00
Kristoffer 26510de9e0 Cleaned up formatting to align with master v0.6 branch 2020-11-09 13:40:14 +01:00
Kristoffer 2a585c98d8 Merge branch 'v0.6.0' of https://github.com/IfcOpenShell/IfcOpenShell into presentationlayer 2020-11-09 13:35:15 +01:00
Kristoffer 9f86396edf Finished with creating, exporting Presentation Layer. Will start work on importing Presentation layer 2020-11-09 13:34:55 +01:00
Dion Moult 3477d3f1a2 Implement import support for material profile sets 2020-11-09 21:03:21 +11:00
htlcnn caa1677181 rearrange logic 2020-11-09 20:41:11 +11:00
htlcnn 84509b7cc2 add IfcClass selector for Ifc By Type node 2020-11-09 20:41:11 +11:00
Luis C. Pérez Tato 09847513ab Fixes #1038 2020-11-09 09:19:46 +01:00
Dion Moult 40e30eaa36 Support exporting more metadata labels like names and descriptions for profile sets 2020-11-09 19:15:23 +11:00
Dion Moult 527e6b0ca7 Minor fix 2020-11-09 15:26:16 +11:00
Dion Moult 8bdd24ba16 Add support for importing all attributes of material layers and consitutents 2020-11-09 15:01:39 +11:00
Dion Moult 4a6c980779 You can now rewind a breadcrumb trail when inspecting IFCs and show attribute lists 2020-11-09 11:45:53 +11:00
johltn 47af56cfa0 Fix typo 2020-11-08 18:13:13 +01:00
johltn e186bc8e15 Update 2020-11-08 18:08:16 +01:00
tpaviot ba094f2967 [clang-warning-fix] Removed unused format_edge and format_pnt functions from IfcGeomFunctions.cpp 2020-11-08 15:52:54 +01:00
tpaviot 8c507ea007 [g++-warning-fix] Fix wrong initialization order in SvgSerializer.h 2020-11-08 15:52:54 +01:00
tpaviot 640dc7cf5a [g++-warning-fix] Fix ambiguous parenthesis in SvgSerializer.cpp 2020-11-08 15:52:54 +01:00
tpaviot 28d9bccb6e [g++-warning-fix] Fix sign comparison in IfcGeomServer.cpp 2020-11-08 15:52:54 +01:00
tpaviot 1aa3e70d89 [g++-warning-fix] Removed unused function 2020-11-08 15:52:54 +01:00
tpaviot e4662cf209 [g++-warning-fix] Fix wrong enum compare 2020-11-08 15:52:54 +01:00
tpaviot f17702c66a [g++-warning-fix] Fix sign comparison, unused function, unused variables in IfcGeomShapes.cpp 2020-11-08 15:52:54 +01:00
tpaviot b8e0c21dcc [g++-warning-fix] Fixed comparison between signed and unsigned integer expressions 2020-11-08 15:52:54 +01:00
tpaviot 4ea56ba987 [g++-warning-fix] Fixed initialization reorder 2020-11-08 15:52:54 +01:00
tpaviot e793683668 [g++-warning-fix] Removed unused variable 2020-11-08 15:52:54 +01:00
johltn 9645b9f189 Update 2020-11-08 14:37:04 +01:00
johltn a0d2bc25b1 Update 2020-11-08 14:02:50 +01:00
Kristoffer a1cbf9a055 minor improvements in ui,export and operator 2020-11-08 13:52:20 +01:00
johltn 34e5cd9d16 Update 2020-11-08 13:37:01 +01:00
Dion Moult b37ea77934 Implement IFC element inspector interface, useful for training and teaching OpenBIM 2020-11-08 21:52:34 +11:00
johltn 7827b15479 Update 2020-11-08 11:32:09 +01:00
johltn f8e57b04b0 Update 2020-11-08 11:30:40 +01:00
Kristoffer 6423d13054 Merge branch 'v0.6.0' of https://github.com/IfcOpenShell/IfcOpenShell into presentationlayer 2020-11-08 11:25:04 +01:00
johltn 3ca2a8be39 Update 2020-11-08 10:42:17 +01:00
johltn 388ac5740d Update 2020-11-08 10:30:23 +01:00
johltn 7825adf8e0 Update Travis 2020-11-07 20:55:54 +01:00
johltn 1eaa2ca8b4 Update Doxyfile 2020-11-07 19:30:51 +01:00
johltn e366c15dde Update conf.py 2020-11-07 19:12:33 +01:00
johltn 63f0c87920 Try to fix index.rst and also incude python docs 2020-11-07 18:55:39 +01:00
johltn 247a285b68 Test customized Doxyfile 2020-11-07 18:41:15 +01:00
johltn ad9382de08 Create nojekyll file to handle underscore 2020-11-07 07:55:33 +01:00
Bernd Hahnebach 05c952073b bimtester: some small improvements 2020-11-07 10:24:08 +11:00
Kristoffer 9a385c2118 minor improvements 2020-11-06 16:53:42 +01:00
Kristoffer 5928ddba40 Merge branch 'v0.6.0' of https://github.com/IfcOpenShell/IfcOpenShell into presentationlayer 2020-11-06 12:24:06 +01:00
Dion Moult 19b867dae8 Full support added for exporting material layer and constituent set attributes 2020-11-06 21:57:34 +11:00
Dion Moult adf9ac52b2 Revert "add flake8 to travis-ci"
This reverts commit 990e6ee24e.
2020-11-06 20:53:02 +11:00
htlcnn 7c63370548 update travis-ci badge 2020-11-06 14:17:29 +11:00
htlcnn b8c3da4951 fix EnumProperty items 2020-11-06 13:52:22 +11:00
htlcnn 322f3773e4 Ifc By Type dropdown 2020-11-06 08:18:15 +11:00
htlcnn 990e6ee24e add flake8 to travis-ci 2020-11-06 08:18:15 +11:00
ofskrand 87e25cc597 Attempt to simplifying assigned items pointer. Stuck on read only 2020-11-05 16:32:49 +01:00
ofskrand 5009371e0f Ran into error when attempting to append EnumProperty. How is that done? 2020-11-05 13:54:20 +01:00
Thomas Krijnen f5c57d2a1c #1078 check optional opening attributes 2020-11-05 13:37:21 +01:00
Dion Moult ba09e08da5 Create new UI to manage material constituents 2020-11-05 22:41:43 +11:00
Dion Moult 4b2c129a4e Add IFC export to Navisworks workaround to enforce triangulation 2020-11-05 22:01:53 +11:00
Dion Moult 2fb67b09cd New category for IFC export workarounds for RIB iTWO costing program 2020-11-05 21:47:53 +11:00
Dion Moult 50b8718e3a Fix bug where setting north angle from a geolocated IFC was wrong 2020-11-05 21:37:26 +11:00
johltn e306da65c9 Update Travis file 2020-11-05 11:16:54 +01:00
johltn e57ffa9447 Change username 2020-11-05 09:04:01 +01:00
johltn 35a668f3a8 Add sudo to mv command 2020-11-05 08:38:17 +01:00
Dion Moult 6ecf7a80f5 You can now convert from global to local coordinates 2020-11-05 18:17:45 +11:00
johltn 4fe44d0f47 Fix directory path 2020-11-05 08:07:14 +01:00
ofskrand 227ec74a51 Merge branch 'v0.6.0' of https://github.com/IfcOpenShell/IfcOpenShell into presentationlayer 2020-11-05 08:00:24 +01:00
ofskrand 9560211307 debugging collection property 2020-11-05 07:57:24 +01:00
johltn 617cad0b1a Check current dir 2020-11-05 07:44:34 +01:00
Dion Moult 30afd6c95b New fancy UI for material layer set management 2020-11-04 21:28:47 +11:00
Cyril Waechter 04943b216b Add pyproject.toml
Following #1057. For this project black should apply a line lenghth of 120.
This is automatically set up with pyproject.toml
2020-11-04 18:54:58 +11:00
ofskrand aed4706e4c updated ui with Presentation Layer 2020-11-04 08:52:20 +01:00
ofskrand eeef2cfb3f Merge branch 'v0.6.0' of https://github.com/IfcOpenShell/IfcOpenShell into presentationlayer 2020-11-04 07:57:40 +01:00
Dion Moult 3240ec63b7 New recipe to extract out elements into its own IFC 2020-11-04 16:47:49 +11:00
Kristoffer ae25d97307 minor change [skip ci] 2020-11-03 15:55:08 +01:00
Dion Moult b07d999bce Fix #946. More intuitive UI for reassigning IFC class of the active object. 2020-11-03 22:59:35 +11:00
Dion Moult ad1cc7f0b9 Fix #1011. Add example tooltips of add-on preferences external commands. 2020-11-03 21:14:39 +11:00
Dion Moult 81cba70f33 You can now add / remove qtos in bulk. See #1060. 2020-11-03 21:04:50 +11:00
Dion Moult 8b0f0fe60f You can now add / remove psets in bulk. See #1060. 2020-11-03 20:59:48 +11:00
htlcnn cde2d55694 add .git-blame-ignore-revs 2020-11-03 17:15:05 +11:00
Dion Moult 67baad5182 Fix #971. New utility function to query which psets/qtos apply to a class. 2020-11-03 09:53:03 +11:00
Kristoffer d9ecd20414 testing with layers [skip ci] 2020-11-02 15:14:33 +01:00
johltn 0def2a9b13 See if output exists 2020-11-02 13:14:46 +01:00
johltn a75ced62ce Try first commit 2020-11-02 12:43:17 +01:00
Dion Moult 96b8bc638b Add support for deleting attributes in bulk. See #1060. 2020-11-02 22:12:31 +11:00
Dion Moult ba8689468e You can now add attributes in bulk by selecting multiple before adding. See #1060. 2020-11-02 22:05:47 +11:00
Kristoffer 2b1a7eec47 Merge remote-tracking branch 'origin/presentationlayer' into presentationlayer
# Conflicts:
#	src/ifcblenderexport/blenderbim/bim/prop.py
#	src/ifcblenderexport/blenderbim/libs/site/packages/.gitignore
2020-11-02 07:15:05 +01:00
Kristoffer 35bcaa804b testing with layers [skip ci] 2020-11-02 07:13:51 +01:00
Dion Moult 8660d22476 Minor fix. 2020-11-02 11:26:31 +11:00
Dion Moult 3bc4e756cb Add support for case insensitive file units on import 2020-11-02 10:20:44 +11:00
htlcnn 163075a821 black ifcblenderexport 2020-11-02 08:28:02 +11:00
htlcnn 286c77e3b0 black ifcopenshell-python 2020-11-02 08:28:02 +11:00
krande 19c8d13e86 Started on PresentationLayer support. Made necessary change to props set_unit enumerate list of tuples to adhere to actual IFC naming. 2020-11-01 15:59:43 +01:00
htlcnn 2c9d6a47f4 black ifcsverchok 2020-11-01 23:50:02 +11:00
htlcnn 4a6ec11f6f black ifccsv, ifcdiff 2020-11-01 23:50:02 +11:00
htlcnn d169a964dd black ifccobie 2020-11-01 23:50:02 +11:00
htlcnn 892be5444c black ifcclash 2020-11-01 23:50:02 +11:00
htlcnn d6881e833d black ifc2ca 2020-11-01 23:50:02 +11:00
htlcnn c14f5eeca0 black ifcbimtester 2020-11-01 23:50:02 +11:00
johltn c263012287 Modify conf 2020-11-01 12:13:54 +01:00
johltn 5aae70875d Change doxygen output directory abd try to commit generated docs 2020-11-01 12:03:49 +01:00
johltn 0fb6d5a903 Re Comment python doc generation in CMake 2020-11-01 11:09:00 +01:00
Dion Moult 1a570aea83 Fix #1063. Log error if you try to export an abstract IFC class. 2020-11-01 19:00:45 +11:00
johltn 2669819292 Install sphinx after exhale 2020-11-01 08:39:10 +01:00
johltn a9c986020b Try other version of sphinx 2020-11-01 08:28:07 +01:00
johltn 9d6468bbf6 Install sphinx with apt-get 2020-11-01 08:12:01 +01:00
Ryan Schultz 5c89a386ca added drop down menus for area_unit and volume_unit 2020-11-01 15:29:42 +11:00
johltn 348c58a387 Uncomment test section 2020-10-31 20:43:18 +01:00
johltn cb0a5c90e3 Test sphinx directly from Travis 2020-10-31 20:02:04 +01:00
johltn 6267187950 New test 2020-10-31 19:44:09 +01:00
johltn 3575aff235 Comment test section 2020-10-31 19:15:24 +01:00
johltn 54d5d4cc63 Try pip install for sphinx 2020-10-31 16:35:35 +01:00
johltn f2bdcda369 Try without python docs generation 2020-10-31 15:31:23 +01:00
johltn 4020e9a1ce Update conf.py 2020-10-31 15:20:35 +01:00
johltn 1d51d6cac0 Update conf.py 2020-10-31 15:03:30 +01:00
Dion Moult 9447e87ebd Add support for rounding metric and imperial units in drawings 2020-10-31 21:46:09 +11:00
johltn d1f8832af6 Cleaner RST file 2020-10-31 11:21:30 +01:00
Thomas Krijnen b08346cc64 #1054 initialize memory in case of too few attribute values 2020-10-30 09:59:01 +01:00
Dion Moult 3fdcf3c7b7 Add support for multiple dimension objects per view 2020-10-30 10:58:02 +11:00
Dion Moult 84c0ad9ded Auto fix incorrect file format settings when creating drawings 2020-10-30 09:17:57 +11:00
Dion Moult 0061d9d1a9 Fix bug where Views wasn't allowed to be in the IfcProject 2020-10-30 09:11:43 +11:00
johltn 6e589527db Update CMakeLists.txt 2020-10-29 20:55:42 +01:00
johltn cac5203523 Find Sphinx module 2020-10-29 20:43:24 +01:00
johltn dafa6a546c Install doxygen and sphinx 2020-10-29 20:22:34 +01:00
Dion Moult e08260d6a2 Whoops. See #1056. 2020-10-29 20:49:49 +11:00
johltn e42f96faa7 Test modif on Travis file 2020-10-29 07:21:52 +01:00
Dion Moult 23abd3def4 Fix #1056. Fix error in case you switch drawing styles and the style it used to have was deleted. 2020-10-29 16:27:48 +11:00
htlcnn 5e844682ea unformat log messages 2020-10-29 09:15:07 +11:00
johltn b2e7809ee5 Test Travis 2020-10-28 11:44:38 +01:00
johltn fb75906fab Test Travis 2020-10-28 11:26:02 +01:00
johltn 0a6d5a733a Submodule 2020-10-28 11:07:19 +01:00
Dion Moult f15d62c35e Merge branch 'v0.6.0' of github.com:IfcOpenShell/IfcOpenShell into v0.6.0 2020-10-28 20:20:52 +11:00
Dion Moult 970f735b76 Fix bug where non uniform translations of spatial elements are exported wrongly. See #1052. 2020-10-28 20:20:25 +11:00
Thomas Krijnen aa49db07d3 Validate entity is_abstract in ifcopenshell.geom.validate 2020-10-27 11:41:39 +01:00
Dion Moult 6fd5f8d8c7 Support import of IFC2X3 document information / reference date times and formats 2020-10-27 11:08:22 +11:00
Thomas Krijnen e70241fc53 #1047 add swig array wrapper 2020-10-26 14:10:13 +01:00
Dion Moult e68f25bcfb ResetAbsoluteCoordinates recipe now attempts to avoid changing object placement coordinates, instead focusing on geometry coordinates.
This prevents a double up when combining with the OffsetObjectPlacement recipe when doing tricky patching.
2020-10-26 14:59:18 +11:00
Dion Moult 3bd58b7738 You can now specify user coordinates to ResetAbsoluteCoordinates recipe 2020-10-26 14:58:23 +11:00
Dion Moult 76af85264f Fix bug where attributes wouldn't import for some IFC classes 2020-10-26 14:25:39 +11:00
Dion Moult 473d97649c Implement workaround when importing ProStructures files that aggregate elements of different types together 2020-10-26 14:06:06 +11:00
Dion Moult e1c1cf6c9b Implement model offset workaround for Bentley ProStructures. See #1047.
In an ideal world, projects are geolocated properly in IFC. If not, they tend to store it in the spatial structure placement which is then inherited (e.g. Revit) or in the geometry coords themselves (e.g. 12D). In the case of Bentley ProStructures, it seemas s though large coords can be found in both object placements and geometry coords and who knows where else. In this scenario, a model offset is a clean solution rather than patching. However, it will lead to mesh inaccuracies in Blender due to the mixing of large numbers in both object locations and geometry coordinates.

Also model offsetting is useful to have available in general.
2020-10-26 13:36:18 +11:00
johltn 2243e0ab14 Set BUILD_DOCUMENTATION to OFF by default and ignore ifcopenshell python documentation generation 2020-10-25 12:52:48 +01:00
Johan Luttun a25c6245bf Update conf.py 2020-10-25 12:28:51 +01:00
Johan Luttun 0b6d55a8a3 Delete make.bat 2020-10-25 12:20:48 +01:00
Johan Luttun 9eaeea5462 Delete Makefile 2020-10-25 12:20:38 +01:00
Johan Luttun 483fb34e3a Delete Doxyfile.in 2020-10-25 12:20:26 +01:00
Johan Luttun 001fbeb525 Delete Doxyfile.out 2020-10-25 12:20:16 +01:00
Johan Luttun 8fd685b4dc Delete Doxyfile 2020-10-25 12:20:03 +01:00
johltn 1f76f73aa6 Upload files to generate documentation 2020-10-25 12:17:21 +01:00
Thomas Krijnen ef0f00792a #1034 Compound fallback for boolean union 2020-10-25 11:57:59 +01:00
johltn 5ed0b4d972 Added test submodule 2020-10-25 10:45:43 +01:00
johltn f3282003f4 Modify gitignore 2020-10-25 10:44:57 +01:00
johltn b534dc2199 Add Optimise recipe to ifcpatch 2020-10-25 18:22:33 +11:00
Dion Moult 5df723b9db Package IFCSverchok 2020-10-25 18:17:10 +11:00
Dion Moult b5d43b1d58 Fix #1036. Fix export issue where units aren't set explicitly, or set to adaptive. 2020-10-25 13:12:14 +11:00
Dion Moult 4ebed8d029 Fix export of classifications if they are only applied to a type or spatial element, not a regular element. See #1031. 2020-10-25 12:48:35 +11:00
johltn 25a5b435a6 Automatic documentation generation 2020-10-24 14:48:03 +02:00
Dion Moult 8872a13fd8 Classification trees are now stored in the blend instead of an external file for portability. See #1036. 2020-10-24 21:35:01 +11:00
Dion Moult ee6e96c226 Auto add owner history on IFC2X3 so the user doesn't need to do that manually 2020-10-24 18:20:42 +11:00
Dion Moult 4013a7e8b7 IFC Clash now uses iterator filters for faster clashing when using filters 2020-10-22 13:01:04 +11:00
Dion Moult 1a09658ec9 Fix IfcClash bug where spatial elements wouldn't get affected by user filters 2020-10-21 23:14:42 +11:00
Dion Moult 982166ac62 Increase maximum contacts threshold default so that it works out of the box for larger projects 2020-10-21 23:14:09 +11:00
Dion Moult 44d6060924 IFC clash now optimistically skips clashes that are likely to be merely coincident, thus resulting in less false positives 2020-10-21 23:13:43 +11:00
Jesusbill 95d6685597 add curve connections 2020-10-14 11:13:23 +02:00
Thomas Krijnen a625a8aea3 Update img urls 2020-10-13 17:13:50 +02:00
Thomas Krijnen 7131c62600 Add docs/geom/settings 2020-10-13 17:12:24 +02:00
Dion Moult 88e20582dd New node to get IFC attribute 2020-10-13 20:30:00 +11:00
Dion Moult 56209fa0ec New IFC get property node 2020-10-13 20:25:35 +11:00
Dion Moult d7e2f29eae New node to read IFC entities 2020-10-13 20:13:59 +11:00
Dion Moult 2ead44e1c5 New node to generate IFC guid 2020-10-13 19:40:42 +11:00
Thomas Krijnen fd18916b20 Add express.bnf to install 2020-10-11 14:23:54 +02:00
Thomas Krijnen d7f246c86d #1020 Map BezierCurve to BSplineWithKnots 2020-10-11 10:38:38 +02:00
Dion Moult 38e5321dbb Add IFC remove node 2020-10-11 13:13:33 +11:00
Dion Moult 275fa479d6 New IFC add node 2020-10-11 12:32:23 +11:00
CyrilWaechter 60147a8ec9 Fix collections deprecation warning
```python
ifcopenshell/geom/occ_utils.py:28ifcopenshell/geom/occ_utils.py:28
  /home/cyril/git/BIMxBEM/ifcopenshell/geom/occ_utils.py:28: DeprecationWarning: Using or importing the ABCs from 'collections' instead of from 'collections.abc' is deprecated since Python 3.3, and in 3.9 it will stop working
    from collections import namedtuple, Iterable
```
2020-10-10 10:30:08 +02:00
Dion Moult 8b982df1c0 New IFC create shape node for Sverchok 2020-10-10 10:21:17 +11:00
Dion Moult 688c799d1b New select blender objects node - select objects in the Blender scene based off entities in an IFC file 2020-10-09 21:17:18 +11:00
Dion Moult cc778778ee Add new by query IFC node 2020-10-09 21:05:00 +11:00
Dion Moult b5fa993531 Fix #1007. Bug where box representations don't respect project units. 2020-10-09 20:42:07 +11:00
CyrilWaechter 85e7ed380e Import materials psets and display it
Import psets similarly to objects.
Display in the UI similarly to objects.
Basic handling for ConstituentSet and MaterialList.
2020-10-09 13:22:34 +11:00
Thomas Krijnen fcc056e204 #1032 Consider swept disk Start- and EndParam on single circle/ellipse edge 2020-10-08 16:51:01 +02:00
Thomas Krijnen 16663d4db3 Swept disk revolution processing on face instead of wire 2020-10-08 16:50:05 +02:00
Thomas Krijnen c24a91c42a #1030 Check for intersecting axis and sweptarea 2020-10-08 16:23:55 +02:00
Thomas Krijnen 681fd43599 #1019 check if trimmedcurve compcurve parent has siblings 2020-10-08 13:05:06 +02:00
Dion Moult 1fa7791b8b Three new nodes for IfcSverchok. By ID, By Guid, and By Type 2020-10-08 20:22:18 +11:00
Thomas Krijnen 38e5b17b0f Update schema feature detection in serialization. #1020 2020-10-07 14:12:31 +02:00
Thomas Krijnen ac40b90f27 Python settings.__init__ and settings.__repr__ 2020-10-05 15:39:19 +02:00
Thomas Krijnen 11657207c2 Python settings.__init__ and settings.__repr__ 2020-10-05 15:38:26 +02:00
Dion Moult 8982c8d045 Experimental create entity node created 2020-10-01 14:47:42 +10:00
Thomas Krijnen 373fd417eb #1022 2020-09-30 10:24:50 +02:00
fluider e3831be16e Warning iterator invalidation in removeEntity 2020-09-30 10:22:12 +02:00
Dion Moult b4f4d9b3c5 Improve prototype of native round-tripping by reading from original file and preserving styles 2020-09-28 22:14:03 +10:00
Thomas Krijnen e70d08c3a1 update_default_style() and default material for IfcSpace 2020-09-27 16:01:59 +02:00
Thomas Krijnen a13e28930a SVG drawing center option 2020-09-27 14:29:27 +02:00
Thomas Krijnen fd90d558b3 Correct X axis in SVG elevations 2020-09-27 14:28:47 +02:00
Thomas Krijnen 88bfa6fa96 smaller font-size in SVG print 2020-09-27 14:28:07 +02:00
Thomas Krijnen e17c6e4c9f SVG use stylesheet for all styling 2020-09-27 11:51:23 +02:00
Thomas Krijnen ee1e9b4aec --force-space-transparency 2020-09-27 11:51:00 +02:00
Thomas Krijnen 64153eb39a Fix SVG elevation direction 2020-09-27 11:10:44 +02:00
Thomas Krijnen f489487a20 --force-space-transparency option in IfcConvert 2020-09-27 10:43:11 +02:00
Walter Stanish 44306b036d Fix #1013 2020-09-24 11:51:33 +10:00
Thomas Krijnen bead7192fe #1008 via tpaviot 2020-09-22 14:10:38 +02:00
Dion Moult c01fd01c92 Implement read, create, and write for IfcSverchok 2020-09-22 21:22:10 +10:00
Thomas Krijnen 788c5b32f3 Proper orientation on SVG sections and elevations 2020-09-20 16:39:01 +02:00
Thomas Krijnen 08d773e346 Correctly name SVG section 2020-09-20 15:50:41 +02:00
Thomas Krijnen 5864de6dff Sort SVG drawings plans before elevations 2020-09-20 15:43:57 +02:00
Thomas Krijnen 2dd1a00834 Draw door arcs only on floor plans 2020-09-20 15:37:47 +02:00
Thomas Krijnen 76896fe9d6 write svg drawing name in data-name 2020-09-20 15:36:43 +02:00
Thomas Krijnen 46c82d07d0 submodule 2020-09-20 15:26:09 +02:00
Thomas Krijnen 3e9210d29f support for section and elevation references as annotation lines 2020-09-20 15:08:52 +02:00
Thomas Krijnen 0fba3bde2d Update Travis ICU version after dist upgrade 2020-09-20 14:05:25 +02:00
Thomas Krijnen ca8cf3620a Disable gltf validation on Travis. Stuck on building DART code. 2020-09-20 13:34:04 +02:00
Thomas Krijnen 8f43a65b74 Update travis to bionic 2020-09-20 13:14:47 +02:00
Thomas Krijnen bf57258895 #1005 Check degenerate edges on trimmed linear curves bounded by parameter value as well. 2020-09-20 12:59:11 +02:00
Dion Moult cbeaee8501 Fix bug where spatial elements with representations would import twice 2020-09-20 20:36:38 +10:00
Thomas Krijnen 32ebd08158 #996 Handle CompSolid/Compound in Slicer output 2020-09-20 11:12:57 +02:00
Thomas Krijnen 757e3b5272 #996 Correct thickness computation 2020-09-20 11:11:44 +02:00
Dion Moult 6cc4ce46c2 Proof of concept of native representation roundtripping 2020-09-17 17:28:17 +10:00
Dion Moult 2310bf628f You can now set facet tolerances (angular and deflection tolerance) when importing. See #766. 2020-09-15 15:59:52 +10:00
Dion Moult 85d77798c3 You can now modify IFC classes using IFC CSV 2020-09-15 14:58:17 +10:00
Dion Moult d4a629cbe8 Exporting now sets the IFC file if unset for convenience 2020-09-15 14:57:38 +10:00
Thomas Krijnen 3440dd4bf7 #766 2020-09-14 14:03:35 +02:00
Thomas Krijnen df886b3a6b Add missing express module init 2020-09-12 11:08:31 +02:00
Dion Moult ce831c0e05 Bump IfcOpenShell 2020-09-12 11:07:19 +10:00
Dion Moult 1a04e54f03 Fix bug where multiple presentation style assignments in IFC2X3 would get ignored 2020-09-12 10:59:45 +10:00
Dion Moult aac61a8948 Let users set their own app to open SVGs and PDFs 2020-09-11 19:02:33 +10:00
Dion Moult e25629e64f Remove papercuts when creating drawings to minimise manual tasks 2020-09-11 18:29:09 +10:00
Dion Moult 518c3eb6f0 Remove deprecated representation item operators in the mesh properties 2020-09-11 16:33:33 +10:00
Dion Moult c6a5bdf4eb Fix bugs in geocoding and geolocation MicroMVDs. 2020-09-10 17:43:30 +10:00
Dion Moult 9c591ce285 Add support for exporting addresses to the site and building 2020-09-10 16:11:33 +10:00
johltn a70429d2c8 New cmake for doc 2020-09-09 20:45:42 +02:00
Dion Moult 970832411c Enable exporting the plan context by default 2020-09-09 23:21:24 +10:00
Dion Moult 38765c8f0e Adding openings now detects if you've selected the filling object instead 2020-09-09 23:20:29 +10:00
Dion Moult 681083e757 Fix bug in autodetection of wireframe meshes in case you use a modifier 2020-09-09 23:20:01 +10:00
Thomas Krijnen ac2494968c Actualize trapezium profile per https://forums.buildingsmart.org/t/how-are-the-sides-of-ifctrapeziumprofiledefs-bounding-box-calculated-in-most-implementations/2945/8 2020-09-09 14:20:15 +02:00
Dion Moult 68a821b0ec Drawing styles store the render type and include outlines for more CAD-like drawings, and store shadow and lighting settings 2020-09-09 18:49:27 +10:00
Dion Moult 7f95759df0 Implement model federation MicroMVD for BIMTester 2020-09-09 16:44:36 +10:00
Dion Moult ca6adffc25 Fix incorrect auditing of geolocation MicroMVD in BIMTester 2020-09-09 14:21:10 +10:00
Dion Moult c58db675e3 You can now audit high poly objects using BIMTester 2020-09-09 11:23:11 +10:00
Thomas Krijnen 1494657368 Merge branch 'v0.6.0' of https://github.com/IfcOpenShell/IfcOpenShell into v0.6.0 2020-09-08 14:40:37 +02:00
Thomas Krijnen d506ad77b7 python changes for latebound schema manipulation from python 2020-09-08 14:40:27 +02:00
Thomas Krijnen 95a29dec7b cpp changes for latebound schema manipulation from Python 2020-09-08 14:37:50 +02:00
Thomas Krijnen 27f358b314 Move express parser into module code 2020-09-08 14:36:57 +02:00
Thomas Krijnen fa4ff3e46b Merge branch 'v0.6.0' of https://github.com/IfcOpenShell/IfcOpenShell into v0.6.0 2020-09-08 14:36:14 +02:00
Thomas Krijnen 44565b320c Submodule 2020-09-08 14:36:05 +02:00
Dion Moult f2de8ce8df Implement imperial formatting for drawing dimensions 2020-09-08 22:13:41 +10:00
Thomas Krijnen 6ceda94cd4 Submodule 2020-09-08 10:49:57 +02:00
Dion Moult 635e84610e Fix #986. Text IfcAnnotation now stores classes and metadata like all IFC objects in SVG. 2020-09-08 18:32:11 +10:00
Dion Moult 94bd8da75e Fix #985. If the active object is a camera, the temporary section plane matches the camera orientation. 2020-09-08 18:14:39 +10:00
Dion Moult 627be5725a Fix #983. Minor fix. 2020-09-08 17:17:45 +10:00
Dion Moult cd5786d2a7 Fix bug where sometimes you cannot add a context 2020-09-07 22:09:48 +10:00
Dion Moult 9c190d74bb Fix #981. Incorrect and inaccurate conversion to imperial units in quantities. 2020-09-07 21:46:13 +10:00
Dion Moult b43f77bc01 Fix #980. You can now have rotated text in drawings. 2020-09-07 19:54:36 +10:00
Dion Moult f351d80453 Fix #979. Include IfcSpace in the preset for cut objects for an overall plan / section 2020-09-07 18:16:39 +10:00
Dion Moult ffebc44c64 Make stroke linecaps use round ends. They're just nicer, you know. 2020-09-07 17:50:04 +10:00
Dion Moult 22d7aef7be You can now refresh the drawing list, in case you are manually creating drawings 2020-09-07 17:47:19 +10:00
Dion Moult 36bd903736 Switch between drawings with one click, with access from the 3D view 2020-09-07 17:08:04 +10:00
Dion Moult 24c00c0235 New feature to select high polygon meshes 2020-09-07 11:28:35 +10:00
Dion Moult 14c824dfee If objects are not selected, export entire project to IFC 2020-09-06 10:21:12 +10:00
Dion Moult dae5adc38b Dumb walls are now even simpler, using two modifiers by default. Plane walls are still available as an option. 2020-09-05 14:23:43 +10:00
Dion Moult 57bc6f7763 Fix #978. Minor fix. 2020-09-05 14:15:37 +10:00
Dion Moult 45b805b05f New debug panel to create shapes from STEP IDs. See #977. 2020-09-05 12:58:53 +10:00
Dion Moult 0522ea61f6 Minor cleanup 2020-09-05 12:20:16 +10:00
Dion Moult a2f24a265a Support exporting qtos related to a spatial element 2020-09-05 10:33:50 +10:00
Dion Moult 0583a5f430 Fix #975. Add error message if drawing not created when adding to sheet 2020-09-05 08:08:50 +10:00
Dion Moult 7e80615fe0 Minor fix 2020-09-03 23:02:41 +10:00
Dion Moult 71fffa41a9 Minor: add demolish hatch pattern 2020-09-03 23:02:00 +10:00
Dion Moult b2e6075aa3 Fix bug where enum properties won't export 2020-09-03 19:36:35 +10:00
Dion Moult d1852b2415 Minor fix 2020-09-03 19:36:06 +10:00
Dion Moult 0b0876877e Provide 3 default hatching styles for orthogonal squares (e.g. for tiling) 2020-09-03 19:35:51 +10:00
Dion Moult 147bf664cc You can now copy properties to selection even if the pset doesn't exist yet 2020-09-03 19:24:55 +10:00
Dion Moult dbbc56ef0d You can now store arbitrary IFC data in the SVG, depending on the drawing style 2020-09-02 21:51:58 +10:00
Dion Moult 9c8f8ba56f You can now add arbitrary annotation to a drawing, not just belonging to one of the preset types 2020-09-02 21:50:58 +10:00
Dion Moult 73e5f1adf2 Switching cameras now automatically sets all of the drawing styles on the fly 2020-09-02 21:49:18 +10:00
Dion Moult 311174b1e7 Fix bug where Plan RL tag was not projected correctly onto the drawing 2020-09-02 21:48:16 +10:00
Dion Moult cba30f0831 Fix bug where 2D annotation curves geometry would be mangled on export. 2020-09-01 22:44:51 +10:00
Dion Moult 03b8503049 2D annotation now extracts from IFC directly, and considers bounding box intersection with the section plane 2020-09-01 22:44:28 +10:00
Dion Moult 3c8c411dc5 Fix #963. Allow getting / setting north to / from IFC and Blender sun position. 2020-09-01 22:43:00 +10:00
Dion Moult 2e6150b5ef You can now set the viewport shadow from the sun angle, useful for shadow studies 2020-09-01 22:26:57 +10:00
Dion Moult 55a54098dd Fix #961. Reloading is now more robust, and detects opening and projection changes to geometry 2020-09-01 12:18:48 +10:00
Dion Moult f1269c7618 Fix #964. Allow import of nested IfcSpace. 2020-09-01 09:46:40 +10:00
Dion Moult 6ac56cbcf6 Fix #965. Improve canonicalisation of material names to fix import failure. 2020-08-31 22:31:15 +10:00
Dion Moult 6f6a1aede6 You can now export to DXF automatically when creating sheets 2020-08-31 10:38:48 +10:00
Thomas Krijnen 1e3dc6ba16 Update validate.py 2020-08-30 15:21:21 +02:00
Dion Moult 1b2c8bdf8e Enable multiprocessing by default. Let's see how stable it is. 2020-08-30 21:41:46 +10:00
Dion Moult 9107c65ad0 New default site boundary CSS stroke style 2020-08-30 21:41:25 +10:00
Dion Moult 8d80c58e2d You can now render OpenGL for drawings - allowing much better wireframe views 2020-08-30 21:41:01 +10:00
Dion Moult 9c50e909e3 Fix bug where adding text no longer works with new scales 2020-08-30 21:40:21 +10:00
Thomas Krijnen b31caf3310 --json option for validate command line usage 2020-08-30 13:01:16 +02:00
Thomas Krijnen fac949cf95 Remove duplicate import 2020-08-30 13:00:56 +02:00
Dion Moult 880a269e21 Fix silly bug causing uninstall to fail 2020-08-29 20:10:25 +10:00
Dion Moult aca70434be Minor fix 2020-08-29 20:07:33 +10:00
Dion Moult f6280dec68 Bump IfcOpenShell 2020-08-29 19:00:33 +10:00
Dion Moult 4c4bc8ffd7 You can now generate annotation references for building storey levels 2020-08-29 18:56:23 +10:00
Dion Moult 2f4c96b9dc Drawings can now be associated with an IFC geometric subcontext target view 2020-08-29 18:55:38 +10:00
Thomas Krijnen bc2ce0ee62 Update express parser to retain AST parse tree 2020-08-29 10:23:59 +02:00
Dion Moult 77d686724e Annotation tools are now in the viewport instead of in properties for easier access 2020-08-29 11:02:43 +10:00
Dion Moult c5dd9a24cb Different drawings can now have different aspect ratios. Finally! 2020-08-29 10:28:34 +10:00
Dion Moult 6bc05c5bdc Add support for custom titleblocks, and provide presets for A1, A2, A3 sizes 2020-08-28 23:16:25 +10:00
Dion Moult 0c145dd885 Fix #956. Add support for imperial and custom drawing scales. 2020-08-28 21:40:24 +10:00
Dion Moult e7aa8d0e27 Support all ODS units for creating schedules (e.g. LibreOffice and Microsoft Excel have different defaults from a quick test) 2020-08-28 18:31:45 +10:00
Dion Moult c368ae6596 Fix #882. All SVG scales are now standardised to human units with appropriate spacing and placement. Views now appear within the titleblock border. 2020-08-28 11:45:57 +10:00
Dion Moult eea7b6547e Fix bug where mapped representations belonging to a context fails to import 2020-08-28 08:24:32 +10:00
Dion Moult 6cbf8cc8db Creating drawing sheets now understand templates in any CSS unit 2020-08-26 20:37:48 +10:00
Dion Moult d2fcf07b37 Utility to get all descriptions of IFC entities 2020-08-26 20:09:14 +10:00
Dion Moult c552e90897 Utility to extract documentation for all maintainable assets 2020-08-26 20:08:28 +10:00
Dion Moult 345ef27b15 Support IFC2X3 classification CalendarDates 2020-08-26 20:04:07 +10:00
Thomas Krijnen c872ee8844 Support writing SVG to scale 2020-08-25 15:01:07 +02:00
Thomas Krijnen 34c51fa9be #823 fallback to BRepBuilderAPI_Transformed in case of errors 2020-08-25 14:43:31 +02:00
Thomas Krijnen 5c20e7b62a #816 Use more than one cycle of self intersections in IfcArbitraryClosedProfileDef 2020-08-25 13:51:59 +02:00
Thomas Krijnen c15fdc7fa9 Remove erouneous line related to #939 2020-08-25 13:00:54 +02:00
Thomas Krijnen d0c207f6b9 #941 version numbers 2020-08-23 14:01:43 +02:00
Thomas Krijnen 1893f6cea4 #941 version numbers 2020-08-23 14:00:53 +02:00
Bruno Postle a2fa3a39e9 configure cmake to use linux/unix soname conventions for shared libraries, initial soversion is 0 2020-08-23 13:59:48 +02:00
Thomas Krijnen 628f9a2879 Iteration of inverse attribute list 2020-08-23 13:54:23 +02:00
Dion Moult 6ec368901b Types are now categorised in the project upon assignment 2020-08-22 19:34:52 +10:00
Dion Moult af05f72010 Grids in drawings now read from the AxisTag attribute when possible 2020-08-22 19:25:58 +10:00
Dion Moult a66b4f138a Support export of IfcCircleProfileDef 2020-08-22 19:11:17 +10:00
Dion Moult 609a2d3a7d Add dumb opening feature 2020-08-21 20:38:57 +10:00
Dion Moult afd6811c08 Improve error reporting for BIMTester auditing lists 2020-08-21 19:52:50 +10:00
Dion Moult ff5bc25228 Support tessellated polygonal face set for much more efficient files (44kb vs 84kb Suzanne!) 2020-08-21 18:14:46 +10:00
Dion Moult 09dd778f97 You can now specify custom attribute mappings to COBie spreadsheets 2020-08-21 14:38:41 +10:00
Dion Moult 668edbc45e Add support to override COBie types/components selection 2020-08-21 11:38:43 +10:00
Dion Moult f64e0c9acc Minor fix 2020-08-20 23:37:03 +10:00
Thomas Krijnen 99a76b5a6e #949 remove trailing dot from tmp filename 2020-08-19 12:56:43 +02:00
Dion Moult 3968bb2bf5 Auto add to drawings IFCs at export time for usability improvement 2020-08-18 15:58:46 +10:00
Dion Moult df382d3e64 Fix bug where predefined types aren't audited correctly by BIMTester 2020-08-18 13:36:07 +10:00
Dion Moult b6f51bc080 You can now add schedules to sheets 2020-08-18 10:04:19 +10:00
Jesusbill cf6ec3777f update changelog - ifc2ca 2020-08-17 20:35:16 +02:00
Thomas Krijnen 48f3d52880 Fix brace init with struct defaults #951 2020-08-17 18:02:59 +02:00
Jesusbill 7f48923153 add rigid connections - add spring stiffness for point connections 2020-08-17 17:05:31 +02:00
Dion Moult eac72dc852 Convert ODS schedules into SVG schedules for inclusion in drawings 2020-08-17 22:10:06 +10:00
Dion Moult d3da378ba3 New UI to add and manage schedules from ODS spreadsheets 2020-08-17 21:43:33 +10:00
Dion Moult 78d33b4ffd Support converting drawings to PDF on the fly 2020-08-17 21:12:31 +10:00
Dion Moult db0c266a17 Update titleblock with white background 2020-08-17 21:11:59 +10:00
Dion Moult 75b34b6a95 Support import of native IfcCircleProfileDef 2020-08-17 10:22:27 +10:00
Thomas Krijnen 1978ffa8df --log-file option 2020-08-16 16:17:38 +02:00
Thomas Krijnen d4afc6d1c0 #923 2020-08-16 14:35:39 +02:00
Thomas Krijnen 6eee9476a6 Default initialize verbosity 2020-08-16 13:40:58 +02:00
Thomas Krijnen 45c16e5318 Option for realtime logging with -vv 2020-08-16 13:37:58 +02:00
Thomas Krijnen f2884f9b0f Annotations with arrow heads and reuse path_objects 2020-08-16 11:41:40 +02:00
Thomas Krijnen 431e703137 Don't emit material warnings without faces 2020-08-16 11:41:07 +02:00
Dion Moult 31c349b0f1 Exports now automatically detect curve representations 2020-08-16 12:54:41 +10:00
Dion Moult b7bb7815ad Improved user friendly UI for sheet creation 2020-08-16 11:54:05 +10:00
Dion Moult b5acf81be2 COBie now shows log too when generating spreadsheet 2020-08-16 10:57:05 +10:00
Dion Moult 2c79f07abf New purge classifications feature, and imported systems shows up immediately 2020-08-15 18:37:03 +10:00
Dion Moult bd02c8e34b Fix bug where aggregate creation doesn't work if the aggregates collection doesn't exist 2020-08-15 17:34:13 +10:00
Dion Moult c359e35747 Enforce directories when selecting features directory for usability 2020-08-15 13:13:30 +10:00
Dion Moult 0a7c365d78 Selecting multiple objects will now guess quantities in bulk 2020-08-15 13:05:09 +10:00
Dion Moult a1e5135a9e More robust footprint area calculation with support for IfcSpace floor area 2020-08-15 12:40:55 +10:00
Dion Moult e9e0dbabe4 You can now implement element filters for drawing styles 2020-08-15 11:52:58 +10:00
Dion Moult 75b14d4c15 Added button to conveniently edit the vector style CSS within Blender 2020-08-15 09:45:20 +10:00
Dion Moult 217098132f Windows now generate a 2D annotation symbol 2020-08-15 09:27:42 +10:00
Dion Moult 6c064ecd51 Doors now have 2D annotation symbols generated too 2020-08-14 21:27:36 +10:00
Dion Moult cc4a29fc11 New feature to quickly add an Ifc Grid system object 2020-08-14 20:43:44 +10:00
Dion Moult 7386da14dc Support export of grids and UVW grid axes 2020-08-14 18:23:24 +10:00
Dion Moult 0a657be394 Grid axes are now categorised in UVW and have attributes on import 2020-08-14 18:22:07 +10:00
Dion Moult 9062d9720b Add import support for IfcGrid itself, not just the grid axes 2020-08-14 16:54:47 +10:00
Dion Moult 43186e4e59 You can now pick the vector style for each drawing style 2020-08-13 20:38:50 +10:00
Dion Moult 3254bc3c14 Merge branch 'v0.6.0' of github.com:IfcOpenShell/IfcOpenShell into v0.6.0 2020-08-13 20:23:36 +10:00
Dion Moult cee53689aa Fix bug in extracting smart data for annotation tags 2020-08-13 20:23:26 +10:00
Thomas Krijnen afb2aaab5a Fixes for polygonal facesets and skip over errors in SVG 2020-08-13 12:22:03 +02:00
Dion Moult e9b791adaa Improve drawings management UI from a single dropdown to a proper list 2020-08-13 20:17:51 +10:00
Dion Moult 7f6c9e61c8 Add highly incomplete proof of concept DXF2IFC script 2020-08-13 17:47:56 +10:00
Dion Moult a7c76b1f48 Drawing styles now can store rudimentary rendering settings 2020-08-13 09:22:27 +10:00
Dion Moult a47d1ac32a Add prototype drawing style UI 2020-08-12 21:50:57 +10:00
Dion Moult 01d0d125a6 Utility to quickly set object colours, also colour mode is automatically changed now 2020-08-12 19:59:30 +10:00
Dion Moult 5db2a46369 Aggregation matrix inversion is no longer required now that relative placements are fixed from the previous commit 2020-08-12 19:04:47 +10:00
Dion Moult 4c3913353c Fix bug where parts of an aggregate were not placed relative to the whole 2020-08-12 18:27:31 +10:00
Dion Moult 71e59922ec Support IfcIndexedPolyCurve for more robust 2D representations 2020-08-12 12:39:39 +10:00
Dion Moult d56dd25245 Add dumb window 2020-08-12 08:57:58 +10:00
Dion Moult a477a2046d Add dumb slab feature 2020-08-11 21:10:02 +10:00
Dion Moult f6e8d5e281 Create dumb door feature 2020-08-11 20:54:54 +10:00
Dion Moult 0d221fa759 New dumb stair tool 2020-08-11 19:05:26 +10:00
Dion Moult e2fd9add83 Add dumb wall feature 2020-08-11 17:24:30 +10:00
Dion Moult e858930755 Enable export with auto-generated bounding box representations 2020-08-11 16:32:59 +10:00
Dion Moult ffa4e7570d Add button for camera to quickly open relevant drawing 2020-08-11 15:04:09 +10:00
Dion Moult cd6bd0e3cc Body subcontext added by default when a new rep is added, with a cloned mesh 2020-08-11 14:50:21 +10:00
Dion Moult ef41daedb9 Users can now specify what objects to cut for documentation with presets 2020-08-11 13:52:16 +10:00
Dion Moult 114e835d4a Implement multiprocessing in shape creation for IFC drawings 2020-08-10 21:47:37 +10:00
Dion Moult 12345b14ac Minor fix 2020-08-10 14:38:46 +10:00
Dion Moult 1e02353922 Minor fix 2020-08-10 13:01:42 +10:00
Dion Moult 6c868033e3 Fix project setup MicroMVD 2020-08-10 11:21:33 +10:00
Dion Moult 1e6e6a4977 Publish MicroMVD definitions for classifications 2020-08-10 10:40:19 +10:00
Thomas Krijnen f9bf6f814d #945 don't fail on degenerate edges in polygonal faceset 2020-08-09 20:55:44 +02:00
Thomas Krijnen 06b512c2e3 #939 break up closed loops for swept disk 2020-08-09 20:50:39 +02:00
Dion Moult 64db48276c Add a blank material style for documentation 2020-08-09 18:19:05 +10:00
Dion Moult 34fc2136c6 Fix #839. Add upstream support for IFCJSON, including compact, v4, and v5a 2020-08-09 18:10:30 +10:00
Dion Moult fb5c25bb68 Fix #873 2020-08-09 17:32:54 +10:00
Dion Moult d12643197e Bump IfcOpenShell 2020-08-09 17:22:20 +10:00
Dion Moult f58847502e Support transparency in non-nodal materials 2020-08-09 17:13:01 +10:00
Dion Moult 57d44c9066 Hotfix IfcOpenShell util module 2020-08-09 13:26:11 +10:00
Dion Moult b1842de9fa New function to add ifc opening relationships 2020-08-09 13:09:29 +10:00
Dion Moult f2dcd8bb75 Add feature to calculate multiple object volumes 2020-08-09 11:46:14 +10:00
Dion Moult 829b97a0d8 New feature to calculate area of selected faces 2020-08-09 11:33:47 +10:00
Dion Moult be4fe1b684 Simplify UI by making GlobalId generation more automated and show in context 2020-08-09 11:21:00 +10:00
Dion Moult 09af3b052b Move object structural properties to its own panel 2020-08-09 11:14:11 +10:00
Dion Moult 3292b98080 Allow export of type relations in IFCCSV 2020-08-08 17:58:45 +10:00
Dion Moult 11a66ee181 Convert units to project settings when guessing quantities 2020-08-08 16:31:27 +10:00
Dion Moult 7d976b1bc7 Add support for importing area and volume units 2020-08-08 14:47:33 +10:00
Dion Moult 43f0f396ab New feature to calculate total length of selected edges 2020-08-08 14:22:48 +10:00
Dion Moult ec66d7c0b8 Split object psets and qto into their own panels for usability 2020-08-08 13:19:56 +10:00
Dion Moult c79ef17a58 Minor fix 2020-08-07 20:18:43 +10:00
Dion Moult 0dbe7b9cc1 Add perimeter quantity calculation 2020-08-07 20:00:45 +10:00
Dion Moult 1d2677543d Allow calculation of depth 2020-08-07 18:23:50 +10:00
Dion Moult e56648e393 Simple recipe to merge two IFC files 2020-08-06 20:27:10 +10:00
Dion Moult 562dc72129 Publish implementation of geocoding MicroMVD 2020-08-06 18:32:33 +10:00
Thomas Krijnen bc8b377d6d #928 make trim param precision comparison dependent on radius 2020-08-05 10:40:25 +02:00
Dion Moult b60438b51c New UI in Blender to run IFCPatch 2020-08-05 17:18:10 +10:00
Dion Moult 277786771c Optimise the optimisation recipe. See #944. 2020-08-05 15:12:23 +10:00
Dion Moult 61f6ecbf17 New IFCPatch recipe to optimise IFCs by recycling non rooted elements 2020-08-04 21:11:37 +10:00
Dion Moult 6772886e65 New utility function to replace an attribute 2020-08-04 21:08:49 +10:00
Dion Moult 2a22acfdc9 Make util.element.get_psets() support IfcComplexProperty 2020-08-04 20:18:08 +10:00
Dion Moult 323dddf082 New feature to visualise IFC diff changes 2020-08-04 19:00:34 +10:00
Dion Moult a2454cf5ee Add support for dimensions added with MeasureIt-ARCH 2020-08-03 21:43:48 +10:00
Dion Moult 91917dcbb4 Minor fix for OCC import 2020-08-03 21:43:10 +10:00
Thomas Krijnen 97f03d3933 Skip degenerate triangles in IfcTriangulatedFaceSet #934 2020-08-03 10:57:10 +02:00
Thomas Krijnen 0d28978a48 Reuse py build dir in build script to speed up builds 2020-08-01 19:32:50 +02:00
Dion Moult 8ad9c215af Allow keyboard shortcuts for import and export.
Turns out operators need to start with import/export. Odd.
2020-08-01 09:31:28 +10:00
Dion Moult ecebb4b853 Fix #932 - bug where a material_id of -1 will not import. 2020-07-31 20:28:01 +10:00
Dion Moult 3e985facdd When absolute coordinates are offset during import, record the offset 2020-07-31 20:10:05 +10:00
Dion Moult 6c7ddcca9c Fix #940 2020-07-31 16:12:14 +10:00
Dion Moult e9cd48c62d Fix import bug getting geometry type of objects without a representation
E.g. an IfcGridAxis
2020-07-31 15:41:38 +10:00
Dion Moult e63f083a40 Fix bug where IFC2X3 files cannot have coordinates reset properly 2020-07-31 09:32:08 +10:00
Dion Moult a376ec1b12 Accommodate blank qto names. Probably invalid IFC though. 2020-07-31 09:31:31 +10:00
Dion Moult a3e38d2322 Merge branch 'v0.6.0' of github.com:IfcOpenShell/IfcOpenShell into v0.6.0 2020-07-30 19:15:19 +10:00
Dion Moult e7446dc6cb Fix bug #936 where long, duplicate, material names fail to import. 2020-07-30 19:15:06 +10:00
Thomas Krijnen 75cff21efe #939 closed sweep 2020-07-30 11:12:55 +02:00
Dion Moult 5c2ded1486 Merge branch 'v0.6.0' of github.com:IfcOpenShell/IfcOpenShell into v0.6.0 2020-07-30 17:09:44 +10:00
Dion Moult 8197621232 Curves, if they are a swept disk solid, may belong to multiple items.
Not sure if this is the best approach. It'll probably bite me in the future.
2020-07-30 17:09:09 +10:00
Bruno Postle 0cc816922c Fix shebang in command-line scripts 2020-07-30 10:11:32 +10:00
Dion Moult a337c480a9 Support exporting IfcSweptDiskSolid for curves with no bevel profile 2020-07-29 21:46:16 +10:00
Thomas Krijnen cc40726618 Fix SVG storey sorting and element naming 2020-07-28 12:19:05 +02:00
Dion Moult 7f58df876b Allow explicit checking for null attributes and properties 2020-07-28 17:31:26 +10:00
Dion Moult 330aa1b6e3 Publish element classes MicroMVD definitions 2020-07-28 17:31:11 +10:00
Dion Moult 252479189c Refactor geolocation MicroMVD definitions 2020-07-28 16:41:13 +10:00
Dion Moult f56269301f Fix bug where IFCCSV won't correctly store boolean data types 2020-07-28 11:47:22 +10:00
CyrilWaechter d87ea93e89 Restore OCC 0.18.1 support 2020-07-27 23:03:25 +10:00
Dion Moult 1d6f0c8e63 Document dependencies 2020-07-27 21:01:16 +10:00
Dion Moult 9359c388d1 Add true north conversion function to IfcOpenShell geolocation util lib 2020-07-27 18:38:34 +10:00
Dion Moult e2621e0207 Publish definitions for geolocation and project setup MicroMVD 2020-07-27 18:38:13 +10:00
Dion Moult 2837f75d50 BIMTester will now report unspecified tests with fancy colours 2020-07-27 18:37:05 +10:00
CyrilWaechter ab1f7337a5 Support for pythonocc-core 7.4.0 2020-07-27 08:39:28 +10:00
Cyril Waechter 21a4680811 Adapt data type for python-fcl/fcl 0.6.1
Credit to @aothms #919 
Need testing with python-fc 0.0.12l / fcl 0.5 to make sure it breaks nothing
2020-07-26 10:53:25 +10:00
Dion Moult 019f460af2 IFCPatch can now be used as a library or as a CLI 2020-07-25 18:38:35 +10:00
Thomas Krijnen 2a7c406412 #916 2020-07-23 10:49:45 +02:00
blocovin 1018118341 Add center-model-geometry 2020-07-23 10:47:48 +02:00
Dion Moult 5fbb324d7d New GUI to run IFCCOBie using the BlenderBIM Add-on 2020-07-23 17:02:48 +10:00
Dion Moult 7d4c760332 IFCCOBie now supports the ODS format, not just XLSX and CSV 2020-07-23 15:36:25 +10:00
Dion Moult d636775cad Create a better CLI for IFCCOBie, and don't create CSVs when you just need a XLSX 2020-07-23 13:43:57 +10:00
Dion Moult 18a2996a93 Fix bug where COBie convert fails on empty names of related objects for assemblies 2020-07-23 13:42:41 +10:00
Thomas Krijnen 4f1aca8ceb #921 2020-07-22 12:25:24 +02:00
HeySora 416640891f Use cerr_ instead of std::cerr
It was crashing on UNICODE builds.
2020-07-22 10:36:03 +02:00
Yoni Chechik 02bb7bea92 fixed broken url
fixed broken url (thanks https://github.com/IfcOpenShell/IfcOpenShell/issues/656)
2020-07-21 11:39:53 +02:00
Thomas Krijnen f92d1708f2 #924 2020-07-21 11:35:56 +02:00
Dion Moult 37e32738b9 Minor fix 2020-07-21 16:40:33 +10:00
Dion Moult 2d3ede02da BIMTester can now audit predefined types 2020-07-21 16:37:11 +10:00
Dion Moult 95f97efa72 Minor fix 2020-07-21 15:26:43 +10:00
Dion Moult a89f7dc116 New UI to run BIMTester from BlenderBIM Add-on 2020-07-20 22:08:39 +10:00
Dion Moult f1ed9d5b53 More granular reporting from BIMTester, and ability to run without packaging 2020-07-20 16:59:16 +10:00
Dion Moult e7afa0b3e4 Improved error reporting on failed BIMTester tests 2020-07-20 16:58:18 +10:00
Thomas Krijnen 20303ed6a8 Check for unbounded composite curve segments 2020-07-18 10:32:18 +02:00
Thomas Krijnen fdfe1097c4 Minor changes after #916 2020-07-18 09:59:07 +02:00
Stefan Fink ea71a1f8a7 IfcSiPrefix.cpp changes for MSVC 2013
IfcHierarchyHelper.h:176,185 changes in addRelatedObject about throw exception
exception comes from

ifcparse/IfcHierarchyHelper.h line 176 get_parent_of_relation(rel)
if (get_parent_of_relation(rel) == relating_object) {

ifcparse/IfcHierarchyHelper.h line 47
IfcUtil::IfcBaseClass* get_parent_of_relation(IfcUtil::IfcBaseClass* t)

ifcparse/IfcSchema.h
ptrdiff_t attribute_index(const std::string& attr_name) const {

ptrdiff_t index = -1;

-1 return but getArgument(..) Parameter is unsigned int
in the methode -1 is ca. 42123423423423 and throw IfcParse::IfcAttributeOutOfRangeException
we catch this exception and all works as expected and before in 0.5-rc1
2020-07-18 09:55:31 +02:00
Dion Moult 9d6e7c2481 Allow for wildcard expansion in IFCCSV export 2020-07-18 17:29:40 +10:00
Dion Moult 41c539965c Add automatic quantities calculated at export. See #898. 2020-07-18 14:22:18 +10:00
Dion Moult ab432ba3dd Allow "none" geometry types for objects with no body representation 2020-07-18 13:11:13 +10:00
Dion Moult 11472f9aa9 Allow export of mesh edges for structural curve members 2020-07-18 13:10:28 +10:00
Dion Moult 1ec78e57ce Minor fix 2020-07-16 17:35:57 +10:00
Dion Moult 418e4133b7 Minor fix 2020-07-16 17:19:07 +10:00
Dion Moult 2e1a32d540 Provide manual length, area, volume calc operators in qto UI. See #898. 2020-07-16 17:12:11 +10:00
Dion Moult c885652338 Minor fix 2020-07-16 13:05:50 +10:00
Dion Moult ee4a93c0d3 Remove TK interface for BIMTester. Will provide a Blender UI instead. 2020-07-16 12:59:28 +10:00
Dion Moult 9f63f42e6e Support import of IfcObjective constraints 2020-07-16 11:52:51 +10:00
Dion Moult 4d30be716e You can now select all COBie defined assets and types using the selector 2020-07-16 11:37:56 +10:00
Dion Moult e3de339ab2 Fix import bug where truncated material names cause import failure 2020-07-16 11:11:47 +10:00
Jesusbill 2a6b3b981a update changelog 2020-07-15 00:33:06 +02:00
Jesusbill a8d261f271 add zero-length springs for point connections and connection-to-member 2020-07-14 21:48:54 +02:00
Jesusbill 6c22894a93 import elements with no material or profile 2020-07-14 21:44:14 +02:00
Jesusbill 6e8eca37ef experimental ca2ifc (json -> ifc) for creating example files 2020-07-14 21:40:23 +02:00
Dion Moult 63e65b2114 Fix broken selector utility 2020-07-14 19:27:56 +10:00
Dion Moult 1222716e16 BIMTester UI updated to new Gherkin syntax conventions 2020-07-14 18:22:32 +10:00
Thomas Krijnen 98ed21a1e2 Merge branch 'v0.6.0' of https://github.com/IfcOpenShell/IfcOpenShell into v0.6.0 2020-07-13 13:20:08 +02:00
Thomas Krijnen 093ebb2d8f Don't try to apply opening elements marked as Reference 2020-07-13 13:19:28 +02:00
Dion Moult 42f597a7af New experimental mode to allow users to profile import progress 2020-07-13 16:15:23 +10:00
Dion Moult 88331d16a2 Fix bug where imported materials that duplicated a name could be incorrectly assigned 2020-07-13 16:12:34 +10:00
Dion Moult fa1926fa84 Exporting now uses custom people and organisations defined from the UI. See #875. 2020-07-13 15:29:06 +10:00
Dion Moult bdbe988dc7 Don't bother creation relationships to invalid psets.
An invalid pset can occur when the pset doesn't contain any properties. This can happen when all properties are not part of the pset definition template. This may lead to unwanted data loss, but strictly enforces buildingSMART pset definitions.
2020-07-12 11:06:14 +10:00
Dion Moult 6b07aeb703 Allow export of positioning elements (only IfcGrid for now) See #911 2020-07-12 10:19:22 +10:00
Thomas Krijnen 4015c5b5b2 --door-arcs option in SVG serializer 2020-07-11 23:26:21 +02:00
Thomas Krijnen a62fd01725 Move late bound inverse access to IfcBaseEntity 2020-07-11 23:24:49 +02:00
Dion Moult 58fad83d4f No longer require object linked materials in Blender in preparation for new material system 2020-07-11 22:25:06 +10:00
Thomas Krijnen 1e916896ab --section-height-from-storeys 2020-07-11 13:39:09 +02:00
Thomas Krijnen 803cc66abb #873 2020-07-11 11:55:00 +02:00
Thomas Krijnen 8500daf1cc #915 2020-07-11 11:40:27 +02:00
Dion Moult 4baec5754d Allow you to specify whether to recut all, or just recut selected. See #901. 2020-07-10 21:22:22 +10:00
Dion Moult 607e506767 Users no longer need to manually select types for collections when exporting 2020-07-10 14:08:04 +10:00
Dion Moult 65821c4367 Group all aggregates into a single collection and update aggregate operators 2020-07-10 13:52:34 +10:00
s-leger fd283b9c84 Update export_ifc.py
Fix for objects where material index > material slots
Keep material indexes in material slots range (index % slots is blender default behavior)
Fallback to a minimal slot count to 1 for objects without material slots
2020-07-10 12:09:10 +10:00
Dion Moult 2132706c6e Migrate import geolocation to util module 2020-07-10 12:00:54 +10:00
Dion Moult e781dbd789 Export now supports Ifc2x3 style classes in IFC4 2020-07-10 11:59:21 +10:00
Dion Moult 07f8f8c489 Support IfcSpatialElementTypes for export 2020-07-10 11:55:45 +10:00
Dion Moult a7e1eb15ab Add support for triangular grids in IFC import 2020-07-10 10:30:41 +10:00
Dion Moult a27b00e616 Allow import of invalid grids coming from Revit. See #911. 2020-07-10 10:18:33 +10:00
Dion Moult c7211ed171 Create basic UI to manage people and organisations. See #875. 2020-07-09 20:46:50 +10:00
Dion Moult fbaa6cd2ed New UI to assign constraints to objects and export 2020-07-07 12:33:41 +10:00
Dion Moult e2868f871a Support export of scaled curve bevel objects. See #900. 2020-07-06 19:14:27 +10:00
Dion Moult b866106293 Exported constraints are now managed using the new UI, no CSV required 2020-07-06 17:48:00 +10:00
Dion Moult fda508e3f8 New UI to manage IFC constraints in the file 2020-07-06 17:26:38 +10:00
Thomas Krijnen 436eb3a637 msvc utf8 conversion in wrapper write() 2020-07-05 11:40:17 +02:00
Dion Moult 155a1eeca9 Fix incorrect dimension export of rectangle profiles 2020-07-04 13:26:14 +10:00
Dion Moult 79fdfa878c Rename "documentation" to "drawings and sheets" for more universal terminology. See #881. 2020-07-03 22:00:25 +10:00
Dion Moult 9a026d93fb Update fetch object passport to substitute a mesh from a Blender file only. See #871. 2020-07-03 21:54:22 +10:00
Dion Moult 125c0ced6e New feature to remove a representation subcontext. See #870. 2020-07-03 21:08:40 +10:00
Dion Moult 36b262dff9 Allow for null data in exporting georeferencing 2020-06-30 21:28:46 +10:00
Dion Moult 4d8b130f2d Fix IfcPatch ResetAbsoluteCoordinates recipe to account for coordinate lists 2020-06-30 21:24:08 +10:00
Dion Moult d22d903a36 Improve absolute coordinate support for georeferencing 2020-06-29 11:16:49 +10:00
Yorik van Havre c76c72c017 Added USERSPACE_PYTHON_PREFIX cmake variable to allow install IfcPython in userspace instead of system-wide. 2020-06-28 12:48:25 +02:00
Dion Moult 3e9fff6c19 New feature to unassign/reassign IFC class easily 2020-06-23 23:42:33 +10:00
Dion Moult da7ba7b1e9 Fix bug for exporting slots with no materials 2020-06-23 22:49:56 +10:00
Dion Moult 794e55aadd Fallback to non-native if boolean operations exist. See #865. 2020-06-23 08:02:46 +10:00
Dion Moult ebc305c0e1 Bump IfcOpenShell 2020-06-21 19:43:58 +10:00
Dion Moult 358d9ef1c8 Reimplement edge based mesh import
We don't use foreach_set, since for some reason doing it with foreach_set requires edit mode to be toggled for the edges to be visible. We make the assumption that an object is either edge based or face based, but not both.
2020-06-21 09:48:54 +10:00
Dion Moult a931c5ced9 Fix bug with incorrect unit scales on native elements 2020-06-20 21:23:53 +10:00
Dion Moult 189177300a Allow export of native faceted breps 2020-06-20 21:23:15 +10:00
Dion Moult b77ed5aab6 Fix bug where group subtypes are imported as the wrong class 2020-06-20 21:22:49 +10:00
Harald Geyer 501447fa5f Fix building with -DIFCXML_SUPPORT=OFF 2020-06-20 08:47:42 +02:00
Dion Moult 8962e3bcf4 Don't fail on importing case insensitive file extensions 2020-06-19 16:43:22 +10:00
Dion Moult d3f07c4ac4 Support native export of IfcArbitraryClosedProfileDef and IfcRectangleProfileDef 2020-06-18 21:55:07 +10:00
Dion Moult 1280eed00e Merge branch 'v0.6.0' of github.com:IfcOpenShell/IfcOpenShell into v0.6.0 2020-06-18 11:50:54 +10:00
Dion Moult 391ae80e36 Add support for storing subitems of a representation, like a profile. See #865. 2020-06-18 11:50:23 +10:00
Thomas Krijnen 67754ecfb8 opencascade_knotspec_to_ifc multiple definition 2020-06-16 10:34:48 +02:00
Thomas Krijnen e155cb4ab0 #586 Edge curve point projection error logging 2020-06-15 16:24:45 +02:00
Thomas Krijnen 89a7584d0c --edge-arrows debugging setting 2020-06-15 16:24:16 +02:00
Thomas Krijnen f01ae4a45b #842 IFC4X3 schema and some other schema init cruft 2020-06-15 12:48:30 +02:00
Thomas Krijnen b8d0e22aa8 #891 silence gcc-10 bug 2020-06-15 11:56:04 +02:00
Thomas Krijnen e2784fb69b Backwards pyocc compatibility in occ_utils 2020-06-15 11:36:13 +02:00
Thomas Krijnen e9a9c1ab7a #891 fix wrapper compilation 2020-06-15 10:34:47 +02:00
Thomas Krijnen 724d8c405b Fix constructors and assignment op for Kernel 2020-06-14 16:08:50 +02:00
Thomas Krijnen 4ca158e47b Merge branch '672' into v0.6.0 2020-06-14 13:06:38 +02:00
blocovin 32511bd9e9 Move center-model, model-offset and model-rotation under geom_options instead of serializer_options 2020-06-14 12:16:20 +02:00
blocovin e1af6d34e4 Update IfcConvert documentation 2020-06-14 12:16:20 +02:00
blocovin 6e2038c1f5 Use model-offset in IfcGeom::Kernel and add model-rotation 2020-06-14 12:16:20 +02:00
Dion Moult 76e7205692 Add experimental native support for faceted breps import 2020-06-14 19:19:54 +10:00
Dion Moult 7e362110d2 Optimise import process. See commit notes.
* When there is only one material slot, there is no need to assign materials as the slot becomes the default
 * Don't loop through collections to find the collection you need, we now store aggregate collcetions
 * The project collection is not added to the scene collection until the very end. Apparently linking objects to collections when the collection is enabled in the view_layer causes it to be twice as slow. Therefore all view layer operations happen at the end.
 * Don't print the progress bar, as excessive prints and calls to the iterator.progress() makes it very, very slow. Like, so slow you wouldn't even wait for the file to finish you'd just give up. See #895.
 * Only create materials once per mesh. Nobody seems to be using styled items properly as an object override anyways.
 * Use foreach_set to create meshes instead of mesh.from_pydata. This is much faster.
 * Similarly use foreach_set to set material indexes. This leads to a crazy speed increase on big meshes.
2020-06-14 19:17:58 +10:00
Dion Moult 7b98e48b9c Prevent adding a crazy number of material slots, especially in messy IFCs coming from Revit 2020-06-14 19:03:43 +10:00
Dion Moult d8373715e2 Disable mesh cleaning if objects >= 10000, for import optimisations 2020-06-12 21:48:35 +10:00
Dion Moult 9961f6172f Users can now choose whether to import type representations, disabled by default 2020-06-12 21:46:28 +10:00
Thomas Krijnen e2e217700d #843 SetTransparency requires theToUpdateViewer 2020-06-12 11:18:30 +02:00
Dion Moult 2035cf64c2 Improve i18n support in section plane tool and fix bug for invalid materials 2020-06-12 16:59:27 +10:00
Dion Moult 8b7850b3ff New IFC Patch recipe to split an IFC by building storey 2020-06-11 15:15:54 +10:00
Dion Moult 2f8ea33da5 Native elements are now always processed separately with multithreading, reducing bugs with 2D axis representation parsing too. See #865. 2020-06-11 10:57:29 +10:00
Dion Moult edc3aa6157 Support import whitelists and blacklist filters. Groundwork for #865. 2020-06-11 10:52:00 +10:00
Dion Moult 4a6868495e Opening elements now create a boolean relationship. See #865. 2020-06-11 09:58:40 +10:00
Dion Moult 9ae3adf0d7 Distinct representation items are now stored in different vertex groups. See #865 2020-06-08 17:04:36 +10:00
Dion Moult a8a51eb212 Add support for styled surfaces for native elements. See #865 2020-06-08 12:06:15 +10:00
Thomas Krijnen afb05f42db Merge branch 'master' into v0.6.0 2020-06-07 20:23:00 +02:00
Thomas Krijnen 2a42a582fd Merge branch 'master' into HEAD 2020-06-07 19:46:34 +02:00
Thomas Krijnen 86d7205760 layerset-first setting 2020-06-07 19:46:10 +02:00
Thomas Krijnen c8cca08dfa TODO note 2020-06-07 16:44:42 +02:00
Thomas Krijnen 603cf011c3 Implement LINE primitives in glb exporter #864 2020-06-07 16:39:23 +02:00
Thomas Krijnen 91bfd116e8 Fix correspondence between material_ids and edges 2020-06-07 16:13:20 +02:00
Thomas Krijnen 95c953fd52 Share vertices amonst edge-segments 2020-06-07 15:47:19 +02:00
Dion Moult 0237f12ceb Add native element processor for extruded solids and swept disks. See #865 #885
* New user option to enable native element processing
 * Native element geometry will be substituted with dummy geometry so that the iterator doesn't waste time on it
 * IfcArbitraryClosedProfileDef and IfcRectangleProfileDef are supported for IfcExtrudedAreaSolid
 * Old rebar code full of assumptiosn deleted for a more globally applicable native support for IfcSweptDiskSolid
 * Probably created a whole bunch of new useful utility functions in the process, which can contribute to #829
2020-06-07 22:53:33 +10:00
Thomas Krijnen a17b211983 rename by_type_excl_subtypes 2020-06-07 12:49:39 +02:00
Dion Moult a575b701b7 Merge pull request #888 from robertguetzkow/v0.6.0
Fix #883 by adding correct number of edges
2020-06-07 08:12:27 +10:00
Robert Gützkow 7c7587f167 Fix #833 by adding correct number of edges
The mesh structure was invalid because the vertex indices for only one edge were set. The other edge had the same index for both vertices.
2020-06-06 23:42:24 +02:00
Dion Moult 793c1c8ec6 Enable curve imports by default, so rebar, profiles, are imported without user confusion. See #771 and #865. 2020-06-06 11:55:22 +10:00
Dion Moult 9c111a1470 Disable limited dissolve, which can break geometric accuracy. 2020-06-05 21:24:28 +10:00
Dion Moult f21ae53950 Merge pull request #880 from globalcitizen/v0.6.0
Section Plane -> Temporary Section Cutaway
2020-06-05 21:11:04 +10:00
Walter Stanish 8ab42cf09f Section Plane -> Temporary Section Cutaway 2020-06-05 20:53:20 +10:00
Dion Moult a6a4cb81c5 Merge pull request #876 from globalcitizen/v0.6.0
Minor UX and documentation tweaks
2020-06-04 12:05:16 +10:00
Walter Stanish 619abdae51 Update strings as per pull request 2020-06-04 11:42:29 +10:00
Walter Stanish f5d01a90a9 Note on platform specificity 2020-06-04 11:08:34 +10:00
Walter Stanish 3a8a4b7c86 Normalize UI panel naming 2020-06-04 11:06:46 +10:00
Dion Moult d0f02f9247 Users are prompted to assign an IFC class prior to changing IFC metadata. See #869. 2020-06-04 10:47:51 +10:00
Dion Moult 12bb14da48 Minor fix. See #874. 2020-06-04 10:33:05 +10:00
Dion Moult b708c25f90 Minor fix 2020-06-03 22:03:30 +10:00
Dion Moult 4f1514022a Material layer set usage data is now half-imported, with no metadata. See #865. 2020-06-03 11:21:10 +10:00
Dion Moult 43abb87e82 Fix incorrect type assignment on non-unique type names bug. See #865. 2020-06-02 20:48:36 +10:00
Dion Moult 2e19d7697a IFC4 georeferencing data is now imported 2020-06-02 09:34:24 +10:00
Dion Moult 72a1c00e46 Switching contexts are now more tolerant of broken IFCs. See #865. 2020-06-01 22:37:11 +10:00
Dion Moult fa461502a0 Store the IFC geometry type on import. See #865. 2020-06-01 21:57:56 +10:00
Dion Moult 0ec205ad1d Retain material data if a surface style overrides it on import. See #865 2020-06-01 20:55:14 +10:00
Jesusbill 82ada5c102 minor fix in ifc2ca (revert a bad modification :|) 2020-06-01 01:41:20 +02:00
Jesusbill 9fa89651c4 minor fixes in ifc2ca 2020-06-01 01:26:35 +02:00
Thomas Krijnen 6aa32fb77a Remove debugging statement 2020-05-31 17:11:00 +02:00
Thomas Krijnen be96cee77d Iterator include/exclude of entity_instance in Python 2020-05-31 17:08:19 +02:00
Thomas Krijnen 4ffa658faf Don't segfault on empty multithreaded iterator result set 2020-05-31 17:07:41 +02:00
Thomas Krijnen 1eea532c9e python interator include/exlude entity types 2020-05-31 12:51:21 +02:00
Dion Moult ee7ea5445a Covetool now reads north angle from project geolocation 2020-05-30 19:40:05 +10:00
Dion Moult 7e77c0c92c You can now submit custom geometry for covetool environmental analysis 2020-05-29 19:18:57 +10:00
Dion Moult ec8a07ec6a Setup a default project if one hasn't been setup yet instead of an error 2020-05-29 09:24:07 +10:00
Dion Moult bdf17e5c12 Allow for objects with no placement 2020-05-28 22:34:54 +10:00
Jesusbill e071c7812f major update, refactoring to consider generalization of connections 2020-05-27 05:33:36 +02:00
Dion Moult 8bef6b9347 Bump IfcOpenShell build 2020-05-25 20:42:35 +10:00
Dion Moult 11b3f1c70c Minor fix 2020-05-25 20:38:18 +10:00
Dion Moult e75cc10988 New feature to select IFC clash results 2020-05-25 19:07:09 +10:00
Dion Moult 0d93633326 Update docstrings as per aothms comments 2020-05-22 11:30:45 +02:00
Dion Moult 295b2fb56b More documentation 2020-05-22 11:30:45 +02:00
Dion Moult d62bbd995f Add sphinx docstrings to ifcopenshell python binding 2020-05-22 11:30:45 +02:00
Dion Moult 1361c7b7e5 Users can now switch between IFC4 and IFC2X3 for exporting 2020-05-22 12:06:55 +10:00
Dion Moult 3b81a69591 You can now export psets for spatial elements 2020-05-22 11:08:54 +10:00
Dion Moult 72a2ab93c3 When importing, existing rooted elements are reused 2020-05-21 20:26:08 +10:00
Dion Moult d3590c2325 You can now specify relationships to IFC Diff in Blender 2020-05-21 19:26:28 +10:00
Dion Moult 5ead8995e1 BIMTester now purges data based on the latest MicroMVD syntax spec 2020-05-21 12:46:27 +10:00
Jesusbill ea1c3079cb add export to .ifcjson, related #839 2020-05-21 04:10:20 +02:00
Thomas Krijnen d81196316d Alternative implementation to #801 2020-05-20 16:27:59 +02:00
kukalaka eba631d245 Add missing IFC_PARSE_API 2020-05-20 16:15:08 +02:00
didi-ux 2ee9dafd16 Fix visualization for pythonocc 7.4.0
Following up the issue disscused here: https://sourceforge.net/p/ifcopenshell/discussion/1782717/thread/06e3103d93/

The yield and for-loop in initialize_display() changed slightly, 'GetHandles' and 'SetDiffuse' were removed. The directions are now V3d_TypeOfOrientation enumerations (randomly chosen by me) instead of tuples of integers.
2020-05-20 16:14:41 +02:00
Thomas Krijnen 839ca49a7a Fix #861 2020-05-20 11:55:59 +02:00
Dion Moult 3d06af0001 New simple energy/daylight analysis through cove.tool integration 2020-05-20 10:42:48 +10:00
Dion Moult f081c9dbcb Add support for import and export of clash sets from Blender 2020-05-19 20:35:00 +10:00
Dion Moult bc56196f27 New UI to create, manage, and run clash sets within BlenderBIM Add-on 2020-05-19 15:08:54 +10:00
Dion Moult e45f5d867b IFC Clash now supports clashing multiple clash sets and recording the results for each clash set 2020-05-18 19:40:01 +10:00
carlopav 35ea0b1b8b further fix to geolocation.py 2020-05-17 15:26:54 +02:00
Thomas Krijnen 3427b99521 libxml2.so on travis 2020-05-17 13:46:36 +02:00
carlopav 8fe4eb1dba util/geolocation.py fix imports and dms2dd 2020-05-17 12:32:52 +02:00
Dion Moult b08fb47a47 You can now perform internal collision checks 2020-05-17 19:53:13 +10:00
Dion Moult b0bb05bcdb Minor fix. See #854. 2020-05-17 19:41:26 +10:00
Dion Moult 6193a18734 You can now filter elements in IfcClash with either inclusion or exclusion IFC selectors 2020-05-17 19:32:04 +10:00
Dion Moult c7e3dba8c4 Add util module to IfcOpenShell, including element, geolocation, unit, and selector. See #829. 2020-05-17 18:32:56 +10:00
Dion Moult 1ac37d9110 Users can now configure clash tolerance distance and results show the greatest distance 2020-05-17 14:40:48 +10:00
Dion Moult ca4b257188 You can now clash multiple IFC files against multiple IFC files 2020-05-17 14:35:08 +10:00
Dion Moult ef5f86273e Minor fix.
Use PyPi windows build of fcl instead. https://github.com/BerkeleyAutomation/python-fcl/issues/17
2020-05-17 08:34:50 +10:00
Dion Moult e44eaf0ccd Implement import and export of relative placements of spatial hierarchy. See #852. 2020-05-16 21:36:34 +10:00
Dion Moult 3235d2495a Minor fix. See #852. 2020-05-16 20:04:51 +10:00
Dion Moult 81b3711c33 Bump IOS build and add support for IFCXML import. See #854. 2020-05-16 16:07:12 +10:00
Dion Moult 588549ca91 If you export two IfcProjects, they get merged into one by default. See #852. 2020-05-16 15:10:11 +10:00
Dion Moult 64fe2e978e Bundle IFC Clash in Blender for clash detection for Windows and Linux 2020-05-16 12:54:26 +10:00
Dion Moult 3e223b53e4 Move utility as it is starting to mature 2020-05-16 09:16:54 +10:00
Thomas Krijnen 64c0679a7e FIx code generation import for schema_class 2020-05-15 14:28:56 +02:00
Dion Moult 67cf93d182 Let IFCClash be used either as a standalone or as a library 2020-05-15 21:08:27 +10:00
Dion Moult fd821f3553 Allow ifcclash to patch coordinates to aid clash accuracy 2020-05-15 21:01:18 +10:00
Dion Moult e3c36a28f2 Fix bug where type mapped representations were not isolated to a single IFC 2020-05-15 16:39:40 +10:00
Dion Moult 480a1100ea Allow custom Qto quantities to be exported 2020-05-14 21:37:33 +10:00
Dion Moult 25f5407933 Fix inability to export due to truncated object names 2020-05-14 21:36:21 +10:00
Dion Moult 395d5ebea7 Fix round-trip bug when IFC2X3 classifications are imported. See #851. 2020-05-14 21:35:43 +10:00
Dion Moult dd525d8a30 Fix bug where a subcontext is always assumed during import, causing a fail 2020-05-14 16:30:16 +10:00
Dion Moult 32c621139b Fix bug where monetary unit causes import to fail 2020-05-14 16:29:56 +10:00
Dion Moult 5d7a841380 Rewrite IFCClash to get good results 2020-05-13 22:08:30 +10:00
Dion Moult 619416f7ad Merge branch 'v0.6.0' of github.com:IfcOpenShell/IfcOpenShell into v0.6.0 2020-05-12 13:32:01 +10:00
Dion Moult df12d6bab1 New feature to convert from local to global coordinates 2020-05-12 13:31:16 +10:00
Thomas Krijnen ad4e7fa14f Fix amiguous implicit cast 2020-05-11 11:19:54 +02:00
Dion Moult df62643fc7 Minor fix 2020-05-11 17:55:26 +10:00
Dion Moult 42f325295e Refactor SVG writer class to make multiprocessing easier in Blender 2020-05-11 17:46:38 +10:00
Dion Moult 48341176df Minor fix 2020-05-11 17:29:35 +10:00
Dion Moult 754ebaba1f Forgot to commit this 2020-05-11 17:24:56 +10:00
Dion Moult 7728e83f1e Default to IfcAnnotation for all annotation objects 2020-05-11 17:13:27 +10:00
Dion Moult 42634e9c60 Export views as groups, and text annotation as IfcTextLiteralWithExtents 2020-05-11 15:30:31 +10:00
Dion Moult 1d7865c558 Add support for IfcAnnotation elements 2020-05-11 15:17:39 +10:00
Dion Moult c481b77e73 Add support for breakline annotations 2020-05-11 10:00:54 +10:00
Dion Moult 4871243445 New door tag symbol 2020-05-11 08:34:10 +10:00
Dion Moult 1a31999abf Release new optimised patterns with caching for polygon metadata 2020-05-10 22:11:20 +10:00
Thomas Krijnen b8f790ca8b SVG: Sort storeys and output elements names 2020-05-10 11:48:39 +02:00
Thomas Krijnen 1c82d8c936 svg print space areas 2020-05-10 11:10:30 +02:00
Dion Moult 58a40316af Stair annotations now work in 3D 2020-05-09 22:45:16 +10:00
Dion Moult af11ebdc4f Annotation contexts are now drawn as solid lines in section cuts 2020-05-09 22:26:39 +10:00
Dion Moult 2a8251fc94 New UI to manage representation contexts for each object 2020-05-09 18:14:10 +10:00
Dion Moult 561009c330 Support solid line annotations using curve data 2020-05-09 16:38:05 +10:00
Dion Moult e270cf6989 Improved section caching, with annotation objects not cut. 2020-05-09 15:50:24 +10:00
Dion Moult 752a7c9b1c Minor fix for IFC2X3 2020-05-09 12:47:26 +10:00
Dion Moult c83af5fc2a Switching contexts and pushing contexts now works on object types 2020-05-09 12:02:10 +10:00
Dion Moult b857d9a37b Type representations are now properly mapped to instance representations if they share a rep 2020-05-08 20:40:06 +10:00
Dion Moult ac49d1f7aa For IFC2X3, IfcDoorStyle and IfcWindowStyle metadata will be imported 2020-05-08 10:18:32 +10:00
Dion Moult 1b237ccefe Type representations are now imported too, not just element representations 2020-05-08 10:18:02 +10:00
Dion Moult cdbe3433c0 New feature to add/override a single representation to an existing IFC file 2020-05-07 22:15:16 +10:00
Dion Moult 6300b27ac4 IFC unit settings are now preserved on import 2020-05-07 21:25:53 +10:00
Dion Moult bbc429bb99 New feature to switch / load / create new contexts per object 2020-05-07 16:57:14 +10:00
Dion Moult 673f12dd8a New feature to bulk add smart annotations to objects 2020-05-07 09:36:38 +10:00
Dion Moult 0af8902dde Allow text annotation formatting functions 2020-05-06 21:10:39 +10:00
Dion Moult 4ed3517c47 Minor fix 2020-05-06 20:23:37 +10:00
Dion Moult ef88f574c1 Namespace import/export operator so we can use it headlessly 2020-05-06 09:59:22 +10:00
Thomas Krijnen 9fca1aca3a catch errors during iterator construction 2020-05-05 13:08:38 +02:00
Thomas Krijnen 9c5c05202f more defensive XML parsing 2020-05-05 13:08:09 +02:00
Thomas Krijnen c9c2f76960 parse_xml can return nullptr 2020-05-05 13:07:55 +02:00
Dion Moult 23f5c808e8 Add export support for profile 3d geometry representations 2020-05-05 18:39:14 +10:00
Dion Moult 956e9ab034 Support Annotation 2D and 3D geometry representations 2020-05-05 18:30:43 +10:00
Dion Moult 0288af196d Support FootPrint GeomSet geometry representations 2020-05-05 18:17:12 +10:00
Dion Moult 9384cc04b8 Support 2D axis representations, and curves from either mesh or curves 2020-05-05 18:07:21 +10:00
Dion Moult 01e82620aa Make IFC export more granular to only export contexts that are specified
This allows us to build up highly specific IFC exports instead of monolithic files.
2020-05-05 15:25:48 +10:00
Dion Moult fa8b12497c Reuse materials on subsequent imports if they already exist 2020-05-05 09:35:15 +10:00
Dion Moult 534ede4839 Relevant types are auto selected for export if you don't select them 2020-05-04 18:47:57 +10:00
Dion Moult c3b04d554c Lat/longs are converted to decimal degrees when imported from DMS 2020-05-04 18:46:47 +10:00
Dion Moult 3fedbad7bb Fix classification round-trip bug 2020-05-04 18:46:19 +10:00
Dion Moult 11362becc8 Geometric representation contexts and subcontexts are now imported 2020-05-04 15:27:12 +10:00
Jesusbill 2d2c5cfc3d add orientation in the json file for point and line geometries 2020-05-04 05:34:19 +02:00
Dion Moult 3ce71e855f Text annotation can now extract dynamic variables from IFC data 2020-05-04 12:20:34 +10:00
Dion Moult dce5c40007 Aggregates are now placed inside IfcProject during import 2020-05-04 10:21:28 +10:00
Dion Moult 7410d75ef5 Users can now specify a symbol for text annotation 2020-05-04 09:35:35 +10:00
Dion Moult be2556aa0c Minor fix 2020-05-04 07:46:25 +10:00
Dion Moult 97ac0e09b7 Add option to use cached render during documentation 2020-05-03 20:37:51 +10:00
Dion Moult 61a2eb4a43 Feature to set and resize text to 1.8, 2.5, 3.5, 5 and 7 sizes 2020-05-03 19:54:27 +10:00
Dion Moult 7deedf6ec9 New UI to add annotation objects 2020-05-03 15:41:05 +10:00
Dion Moult 9e250a9616 Cache IFC metadata so you don't need to reload the IFC file on every view generation 2020-05-03 11:24:52 +10:00
Dion Moult a712861633 Grid annotations now work in 3D too 2020-05-03 11:24:22 +10:00
Dion Moult 280c7df79a Don't cut rooms in documentation, fix non single material bug, and add view present for construction style documentation 2020-05-02 21:01:39 +10:00
Dion Moult 47eb032689 Users can now specify which IFC files they want to cut 2020-05-02 17:33:16 +10:00
Dion Moult 741ae2575d Full classification HasReferences hierarchy is now exported 2020-05-02 13:57:11 +10:00
Dion Moult 70f298baae Support import of document information and relationships 2020-05-02 09:21:13 +10:00
Dion Moult 04afc101a3 You can now relate and export document references and information entities 2020-05-01 19:13:54 +10:00
Dion Moult 784a394298 New document reference UI, where all docs are imported regardless of object association, and you can edit almost all metadata 2020-05-01 17:24:59 +10:00
Dion Moult 6e0fb6145e Author and export document information metadata 2020-05-01 12:56:57 +10:00
Dion Moult 7b5d8a4079 Import rebar more efficiently without needing to create a profile 2020-05-01 10:23:19 +10:00
Dion Moult 9d9911c4c0 Import all document association metadata, not just location 2020-05-01 09:58:15 +10:00
Dion Moult 7ac2dc6712 Import element classification references 2020-05-01 08:33:50 +10:00
Dion Moult ce00b3d5f8 Import classifications, as well as the hierarchy tree which can be browsed 2020-04-30 17:03:01 +10:00
Dion Moult 38167af916 Fix section planes not cutting through aggregates and appearing at cursor 2020-04-30 08:28:00 +10:00
Dion Moult adb4a3f72a New feature to select similar type 2020-04-29 20:26:36 +10:00
Dion Moult a34a05262e Minor fix 2020-04-29 18:11:44 +10:00
Dion Moult fcd528abfa Aggregate metadata is now imported (attributes / psets / types / etc) 2020-04-29 09:29:55 +10:00
Dion Moult 3eee143bed New option to merge aggregates into a single object for artists 2020-04-29 09:20:30 +10:00
Dion Moult 203fcc1dca Bump bcfplugin dependency to latest version 2020-04-28 18:32:45 +10:00
Dion Moult 2fa49d36d8 New operator to reload an existing IFC file 2020-04-28 14:52:04 +10:00
Dion Moult 7bb7d91c7e Improve usability of IFCDiff by prompting for export JSON file 2020-04-28 11:42:08 +10:00
Dion Moult 1fdd3352ec Add support for BCF bitmaps 2020-04-28 10:46:08 +10:00
Dion Moult 6d26e1c31f Add support for BCF clipping planes 2020-04-27 14:30:33 +10:00
Dion Moult bb935bf167 Add support for BCF line annotations 2020-04-27 13:35:39 +10:00
Dion Moult 01cd5d1d79 Let user control section plane colour 2020-04-27 09:33:00 +10:00
Dion Moult 9f5ef32173 Eyedrop tool to visually select objects to export to IFC 2020-04-27 08:32:01 +10:00
Dion Moult d65f2b432b New import workaround for vendors who create a silly amount of materials like DDS-CAD 2020-04-26 22:06:27 +10:00
Dion Moult b8ea5dc3be IFCCSV now supports queries for inverse spatial or type relationships 2020-04-26 17:33:18 +10:00
Dion Moult cbfd41ad28 Package IFCCSV with BlenderBIM, with UI to import export CSV IFC data 2020-04-26 14:41:38 +10:00
Dion Moult 753fdae0d4 Allow export of IFC class into CSV 2020-04-26 14:40:33 +10:00
Dion Moult 011c50a042 IFCCSV can now be included as a library in your app! 2020-04-26 14:21:11 +10:00
Dion Moult a695eecd9a Minor fix to IFCCSV when exporting non-existant attributes 2020-04-26 14:12:31 +10:00
Dion Moult 3d45f9afeb New feature to only apply section planes to specific objects 2020-04-25 19:17:47 +10:00
Dion Moult 82e38e3abe New feature to remove a section plane 2020-04-25 19:09:34 +10:00
Dion Moult 3671953472 New feature to have multiple section planes at any angle 2020-04-25 17:40:24 +10:00
Dion Moult b250472d60 New feature to create a section plane on a model in real-time 2020-04-25 16:21:15 +10:00
Thomas Krijnen 2ee0cda83e delitem in ifc express parser schema 2020-04-24 13:56:28 +02:00
Thomas Krijnen 186da7ce8b Better formatting in IFC express parser 2020-04-24 13:56:06 +02:00
Dion Moult 4db3b83681 Deprecate CSV-based pset assignment 2020-04-24 20:54:24 +10:00
Dion Moult 13fef5a452 New workaround for importing Civil 3D files with absolute coords 2020-04-24 19:55:00 +10:00
Dion Moult 80863f94d3 New feature to write new property set templates 2020-04-24 18:05:59 +10:00
Dion Moult 9ad57d658e New feature to read pset template files 2020-04-24 17:14:07 +10:00
Dion Moult a90ad6e16c Only bundle Uniclass and Omniclass. Other systems can be downloaded online. 2020-04-23 18:16:04 +10:00
Dion Moult 19130b109e New hierarchical classification navigator, reading class data from IFCs. Thanks to Lucyon Oak (Teck-Freak) 2020-04-23 16:05:06 +10:00
Dion Moult 9217af315b New Graphisoft classification XML to IFC converter utility 2020-04-23 14:31:58 +10:00
Dion Moult 13d434c00f Fix incorrect OffsetObjectPlacement patch when coordinates or directions are recycled 2020-04-23 09:48:52 +10:00
Dion Moult 2bb57aebb5 New IfcPatch recipe to offset and rotate an entire model 2020-04-21 18:55:28 +10:00
Dion Moult 048966bda2 Read from model precision to determine tolerance when doing diffs 2020-04-21 17:29:47 +10:00
Dion Moult ee69bfedcb New feature to copy attributes or psets to all selected objects courtesy of Lucyon Oak (Teck-Freak) 2020-04-20 11:06:34 +10:00
Dion Moult f63ac9609b Optimise rebar profile creation on IFC import 2020-04-16 13:40:46 +10:00
Dion Moult 7adf4934aa Add support for importing IFC groups 2020-04-15 10:08:09 +10:00
Dion Moult 66afa9872d Minor fix 2020-04-14 20:53:32 +10:00
Dion Moult 4e0347fb05 Fix IFC grids imported in wrong location 2020-04-14 20:51:38 +10:00
Dion Moult 442ab790d4 Add export support for CAD presentation layer assignment 2020-04-13 18:24:47 +10:00
Dion Moult ddc37ab4d1 Minor fix 2020-04-13 13:23:53 +10:00
Dion Moult c3a795c825 Add support for BCF orthogonal camera scales 2020-04-12 21:00:13 +10:00
Dion Moult 88bb7da0b2 Add support for BCF component visibility, colouring, and selection sets 2020-04-12 20:40:07 +10:00
Dion Moult d180c4732f Support for exporting IFCZIP files. See #834 2020-04-12 09:51:10 +10:00
Dion Moult bdfe197c64 Support for importing IFCZIP files. See #834 2020-04-12 09:17:26 +10:00
Thomas Krijnen 42fedf81c4 Add parse_ifcxml to ifcopenshell_wrapper 2020-04-11 14:13:19 +02:00
Dion Moult c93a4b6808 Fix schema-invalid exports for booleans, mat slots without polys, and linked duplicate objects having duplicate materials 2020-04-11 21:54:36 +10:00
Dion Moult 3562b566d0 Remove unnecessary cmake files for linux builds 2020-04-11 11:11:53 +10:00
Dion Moult 65a9d6ac50 Fix potential infinite loop during export thanks to Stephen Leger 2020-04-11 11:03:29 +10:00
Dion Moult 2e21c97d82 Remove obsolete IFC file 2020-04-11 10:40:35 +10:00
Dion Moult efc8533c2d Delete obsolete ifcdoc tool 2020-04-11 10:38:12 +10:00
Dion Moult 407e64632e Reorganise libs into its own folder thanks to Stephen Leger 2020-04-11 10:37:47 +10:00
Dion Moult 3d1c796f14 Minor fix 2020-04-09 18:14:55 +10:00
Dion Moult 2db3cf0aa0 Merge pull request #830 from s-leger/patch-3
Remove hardcoded selection
2020-04-09 10:51:57 +10:00
s-leger f59f017bde Remove hardcoded selection
use selected_objects argument of exporter
2020-04-09 02:46:38 +02:00
s-leger abbaef459b Remove hardcoded input objects
Small cleanup of add_spatial_elements_if_unselected using sets
IfcExporter.export and IfcParser.parse take selected_objects as argument
2020-04-09 02:42:03 +02:00
Dion Moult dd1b0a1056 Merge pull request #828 from s-leger/patch-2
Use ifcExportSettings.factory()
2020-04-09 08:26:55 +10:00
Dion Moult 79b741225b Merge pull request #827 from s-leger/patch-1
Settings factory
2020-04-09 08:26:45 +10:00
s-leger c78bb18c8d Use ifcExportSettings.factory() 2020-04-08 15:43:45 +02:00
s-leger 4cf3479036 Settings factory
Use a static "factory" method to keep init logic near settings definition.
```python
logger = logging.getLogger('ExportIFC')
            logging.basicConfig(
                filename=context.scene.BIMProperties.data_dir + 'process.log',
                filemode='a', level=logging.DEBUG)
            output_file = bpy.path.ensure_ext(self.filepath, '.ifc')
            ifc_export_settings = export_ifc.IfcExportSettings.factory(context, output_file, logger)
            ifc_parser = export_ifc.IfcParser(ifc_export_settings)
            ifc_export_settings.logger.info('Starting export')
```
2020-04-08 15:40:12 +02:00
Thomas Krijnen 8bf8cdf51b Guarantee schemas are initialized for serialization and tesselation 2020-04-08 15:04:17 +02:00
Thomas Krijnen a59633ae0b Update MVD submodule 2020-04-08 12:34:18 +02:00
Dion Moult f6db62c758 Psets and qtos can be selected from a list instead of typed 2020-04-08 14:15:36 +10:00
Dion Moult 44b49f4ce9 Minor fix 2020-04-08 12:07:27 +10:00
Dion Moult b6e97dd26c Optimise spatial tree creation during import 2020-04-08 11:05:27 +10:00
Dion Moult 67bb18b580 Bump to latest IfcOpenShell build 2020-04-08 11:04:18 +10:00
Jesusbill 4786dc78a3 create ifc2ca dedicated folder and populate with existing scripts 2020-04-07 16:10:42 +02:00
Dion Moult fb51e85f79 Minor fix 2020-04-07 19:01:57 +10:00
Dion Moult acf1289d50 Import rebar as an extruded circle instead of a brep 2020-04-07 18:50:07 +10:00
Dion Moult b8edcb880d Minor fix 2020-04-07 18:49:16 +10:00
Dion Moult e86839d2db Diffs are now supported in non-legacy importer 2020-04-07 15:44:54 +10:00
Dion Moult 3049d24f6f Accomodate invalid psets without properties created by Solidworks 2020-04-07 14:46:58 +10:00
Dion Moult 28d5d11474 Spatial elements without geometry are now imported too 2020-04-07 14:34:24 +10:00
Dion Moult 503fcee432 Remove uninstall feature, as the built-in Blender remove plugin now handles this 2020-04-07 12:57:07 +10:00
Dion Moult 4c3051267e Repackage BlenderBIM Add-on in single add-on dir thanks to Stephen Leger from Archipack 2020-04-07 12:02:44 +10:00
Dion Moult df14ab57bf Fix wrapped data values in COBie extracts 2020-04-06 17:30:02 +10:00
Dion Moult 374d5a5d1d New optional GUI for BIMTester for user friendly testing 2020-04-06 16:55:36 +10:00
Dion Moult ee288bf7f9 Implement Project setup MicroMVD steps in BIMTester 2020-04-06 11:59:28 +10:00
Dion Moult 96ab539a0f Allow people to export context / project metadata 2020-04-06 10:18:23 +10:00
Dion Moult 1662b11fb2 Support different aspect ratios for BCF snapshots 2020-04-03 17:35:45 +11:00
Dion Moult 7ee385866a Minor fix 2020-04-03 16:08:49 +11:00
Dion Moult f3590f2b7b Allow people to check all inverse relationships without filters 2020-04-03 11:15:29 +11:00
Dion Moult 22e4eb4570 Allow to diff inverse relationships 2020-04-03 11:10:14 +11:00
Dion Moult 82c38f67ba BIMTester can now package test definitions for portability 2020-04-02 18:38:42 +11:00
Dion Moult 4c58cec393 Fix bug where missing styles in invalid IFCs cause imports to fail 2020-04-02 13:11:07 +11:00
Dion Moult 02e29955bf Merge pull request #819 from Jesusbill/v0.6.0
udpate ifc2ca.py - major revision
2020-04-02 09:04:00 +11:00
Jesusbill f4681b2053 udpate ifc2ca.py - major revision 2020-04-01 15:39:49 +02:00
Thomas Krijnen b41d3ed2e6 SVG --print-space-names and entity classes 2020-04-01 12:19:56 +02:00
Dion Moult 55f3f20531 Add experimental multicore import to IFCClash 2020-04-01 15:11:05 +11:00
Dion Moult a6c88a1d01 Accomodate deprecreated IfcPresentationStyleAssignment better 2020-04-01 09:25:34 +11:00
Dion Moult 3ff4b056b7 Support multiple materials per object on import 2020-03-31 19:37:04 +11:00
Dion Moult a5fd66706a Add support for BCF header files 2020-03-31 12:35:17 +11:00
Thomas Krijnen 293ba0db51 Don't fail on parse errors in multithreaded mode #746 2020-03-30 10:53:08 +02:00
Dion Moult d5d36f85be Change exception to error log 2020-03-30 10:20:15 +02:00
Dion Moult f921b6a7e7 Make validate module write to logger 2020-03-30 10:20:15 +02:00
Dion Moult fe633d9698 Add support for ordered BCF viewpoint snapshot images 2020-03-30 18:27:28 +11:00
Dion Moult c4cd6ef710 New feature to validate IFC files against specification 2020-03-30 12:47:14 +11:00
Thomas Krijnen df81490f86 Don't run wire intersection checks on parallel edge pairs 2020-03-27 13:26:34 +01:00
Dion Moult c99bf6e63a Compile views and sheets with automatic numbers, names, and scales 2020-03-27 18:23:46 +11:00
Dion Moult 46c878341d Fix broken ResetAbsoluteCoordinates IfcPatch recipe 2020-03-27 09:04:20 +11:00
Thomas Krijnen 21c9598409 Remove duplicate element quantity from XML #802 2020-03-26 18:53:57 +01:00
Dion Moult 03a23958a3 Store scale and view title in views on sheets, so it can be post-processed 2020-03-26 21:44:54 +11:00
Dion Moult f37e5e5d83 New buttons to open views and sheets instead of browsing manually 2020-03-26 20:47:21 +11:00
Dion Moult bf4eb330e0 New feature to add a sheet, and add a view to a sheet 2020-03-26 18:26:35 +11:00
Dion Moult cdb7a00f0a Merge branch 'v0.6.0' of https://github.com/IfcOpenShell/IfcOpenShell into v0.6.0 2020-03-26 18:23:36 +11:00
Dion Moult 8613834129 Optimise titleblock template. Skip pattern adding until it is optimised. 2020-03-26 18:23:27 +11:00
Thomas Krijnen 8625aab5f0 Check CWD in builds-deps.cmd #804 2020-03-25 14:20:47 +01:00
Thomas Krijnen 7e6ebbebe0 Update docs in accordance with #804 2020-03-25 14:09:22 +01:00
Thomas Krijnen ed98983687 Tolerance handling, error detection and triangulation on tesselation geometry #814 2020-03-25 14:05:22 +01:00
Dion Moult 3a590e4ba1 Implement BCF related topics 2020-03-25 17:55:52 +11:00
Dion Moult 1971bfe014 Support BCF topic document references 2020-03-25 17:12:02 +11:00
Dion Moult dd98ac3a89 Add links to project homepage, docs, wiki, and community 2020-03-25 16:32:14 +11:00
Dion Moult 2678dc3a09 Add support for BCF topic BIM snippets 2020-03-25 16:20:24 +11:00
Dion Moult f2e203d699 Show topic reference links and allow browsing of links 2020-03-25 15:03:06 +11:00
Dion Moult 52ff61a91c Show BCF topic metadata in UI 2020-03-24 17:53:58 +11:00
Dion Moult 8a22169036 Add support for viewing BCF comments 2020-03-24 14:44:03 +11:00
Dion Moult 7c66c5e4fc Allow users to select just objects for convenience when exporting 2020-03-24 11:25:27 +11:00
Dion Moult 44d884590a Allow any type of curve to be used for construction documentation annotation 2020-03-24 10:34:58 +11:00
Dion Moult 662a9fdad7 Allow users to see different BCF viewpoints through a camera 2020-03-23 19:35:02 +11:00
Dion Moult 648aaaa778 Show list of BCF viewpoints in UI for each topic 2020-03-22 20:39:22 +11:00
Dion Moult a8cb855613 Add button and operator to uninstall add-on 2020-03-22 15:25:57 +11:00
Dion Moult 7079e2aee2 Package BCF 2.1 schemas with distribution 2020-03-21 21:54:53 +11:00
Dion Moult 65a5dcbe25 Add list of BCF topics in UI 2020-03-21 21:44:02 +11:00
Dion Moult 5454521c2a Minor fix 2020-03-21 00:25:26 +01:00
Dion Moult 9932e7f012 Add ability to select a BCF file to be loaded 2020-03-20 21:22:32 +11:00
Dion Moult a7b52b5578 Add dependencies for patched bcfplugin 2020-03-20 21:21:23 +11:00
Dion Moult 114611d173 Do limited dissolve on imported meshes 2020-03-20 14:42:43 +11:00
Dion Moult 3b8b0cbbbf Don't assume the first representation when checking materials 2020-03-20 09:38:41 +11:00
Thomas Krijnen 83bba733c7 Update .travis.yml 2020-03-19 14:37:11 +01:00
Thomas Krijnen c991b9812f Update .travis.yml 2020-03-19 13:51:45 +01:00
Dion Moult 5454c5b1e7 Allow manually specified qto values to be exported 2020-03-19 18:16:30 +11:00
Dion Moult 7fe067498f Allow qtos to be imported 2020-03-19 16:48:50 +11:00
Dion Moult ea71485f3b Allow import of contained in IfcSpace relationship 2020-03-19 15:53:36 +11:00
Dion Moult 41acb6c985 Allow export of objects contained inside IfcSpace and other spatial elements 2020-03-19 14:37:18 +11:00
Dion Moult 772468d1ec Minor fix 2020-03-19 10:41:07 +11:00
Dion Moult 296ae71606 Merge remote-tracking branch 'refs/remotes/origin/v0.6.0' into v0.6.0 2020-03-19 10:35:07 +11:00
Dion Moult 160c055906 Add workaround for IfcOpenShell e44221c - see bug #812 2020-03-19 10:33:31 +11:00
Thomas Krijnen 86b02a9adf Address some warnings 2020-03-18 11:59:11 +01:00
Thomas Krijnen 30b28d5a8f Update .travis.yml 2020-03-18 11:42:00 +01:00
Thomas Krijnen d02182793b Product names in STP export thanks to luuk https://sourceforge.net/p/ifcopenshell/discussion/1782717/thread/55558229/?limit=25#a843 2020-03-18 10:12:54 +01:00
Dion Moult 358323492e Add new feature to auto-clean mesh on import 2020-03-18 17:49:08 +11:00
Dion Moult e99c775d51 Fix bug where some objects inside spaces won't import 2020-03-18 17:48:42 +11:00
Dion Moult e068776141 Fix bug where aggregate objects might not be exported 2020-03-18 14:22:44 +11:00
Dion Moult 130d732745 Support multiple materials per object on IFC export 2020-03-18 14:22:01 +11:00
Thomas Krijnen f24db3402f Support for 3D part of IfcSurfaceCurve 2020-03-17 15:13:36 +01:00
Thomas Krijnen 0cfbde13b9 PERMISSIVE_EXTRUSION preproc directive 2020-03-17 11:57:43 +01:00
Thomas Krijnen 9a99f85026 IfcCraneRailAShapeProfileDef for better or worse 2020-03-17 11:55:54 +01:00
Thomas Krijnen 481c6165ca Parametrize code generation actions from the command line 2020-03-17 11:55:28 +01:00
Dion Moult dc8e73b822 Add support for IfcSpatialElements and exclude abstract classes. 2020-03-17 19:16:11 +11:00
Dion Moult 8ba9b37ec9 Add icon and embed common.lark for packaging IFCCSV 2020-03-16 14:54:45 +11:00
Dion Moult a5b5b10d29 Add IFCCSV tool - import and export data from CSV 2020-03-16 13:19:35 +11:00
Thomas Krijnen 3e55297eb0 Propagate hierarchy helper template archument to IfcFile schema name 2020-03-11 16:19:13 +01:00
Thomas Krijnen bd27ff150a Place fills under openings in XML 2020-03-11 15:16:18 +01:00
Thomas Krijnen cb872a5bff Miirror SVG output to account for coordinate systems 2020-03-11 14:45:58 +01:00
Dion Moult f540e3495c Allow user toggle if aggregates are created. Useful for artists. 2020-03-11 15:44:00 +11:00
Dion Moult 9ce34ce395 Add feature to merge by material when importing, useful for artists 2020-03-11 15:27:03 +11:00
Dion Moult 608abf2e55 Calculate position of hidden lines in views in absolute coordinates
Very useful for creating projection lines in axonometrics
2020-03-10 18:28:03 +11:00
Dion Moult c6e10abc51 New feature to merge import geometry by class, which is useful for artists who don't care too much about the data 2020-03-10 09:56:34 +11:00
Thomas Krijnen 4df2feabe2 Add py38 to nix build 2020-03-08 10:14:47 +01:00
Thomas Krijnen 3c355b4848 Add py38 to nix build 2020-03-08 10:13:35 +01:00
Dion Moult a7c14bc7c3 Fix bug where placing spaces in a spatial structure fails with non-unique names 2020-03-08 14:51:32 +11:00
Dion Moult 3a91ed1382 Support IFC2X3 materials without transparency 2020-03-06 22:03:01 +11:00
Dion Moult e2cfc676d8 New test to check that no elements exist of a particular type 2020-03-06 11:35:05 +11:00
Dion Moult 8008ad16b1 Fix import bug where not all objects are typed 2020-03-06 10:17:00 +11:00
Dion Moult 5dd919f028 Create argument to specify a single feature in BIMTester, and separate report generation into its own function 2020-03-06 10:16:30 +11:00
Dion Moult 43348ce236 Bump to latest IfcOpenShell build 2020-02-28 11:24:43 +11:00
AlaaB2020 9f2443e01c Update IfcGeomFunctions.cpp
Changing comment to be suitable for the code change
2020-02-26 10:42:23 +02:00
Dion Moult c8cb9d8a7c Auto detect badly geolocated site from Tekla upon import 2020-02-25 17:47:32 +11:00
Dion Moult ffc8ec8c8d Accomodate deprecated IFC2X3 ways of relating type products 2020-02-25 17:43:48 +11:00
AlaaB2020 9cab063671 Update IfcGeomFunctions.cpp
get the first material even if there are more than one material layer
2020-02-24 13:08:21 +02:00
Dion Moult baf5f1891f New import option to toggle the import of space objects 2020-02-21 11:43:48 +11:00
Dion Moult bdc8caa5f6 New feature to colour code objects by attribute or pset values 2020-02-21 09:41:35 +11:00
Dion Moult 7a5ec24d8d Add ability to search with regex for pset values 2020-02-20 17:31:38 +11:00
Dion Moult eac8925134 Minor UI clean-up to hide panels by default 2020-02-19 17:24:28 +11:00
Dion Moult c3ffe9c3de Build new attribute search operator with regex support and ignorecase 2020-02-19 17:24:01 +11:00
Dion Moult 6c47ff73fd Specially import grids even though they are 2D as grids are pretty important. 2020-02-19 16:20:02 +11:00
Dion Moult cfe18d41d6 Implement support for importing pset data 2020-02-19 14:43:34 +11:00
Dion Moult 5beb3dc755 Show percentage results in BIMTester, add tests for element existance, attributes from a list, and more generic attribute checking 2020-02-18 14:03:32 +11:00
Thomas Krijnen e44221c9c2 XML serializer decomposition fixes for IFC4 2020-02-10 16:36:56 +01:00
Thomas Krijnen 56e3353879 Add inverse attribute availability to schema definition macros 2020-02-10 16:36:38 +01:00
Sander Boer 861dab0d9e proposed fix for #739, build with swig4 2020-02-07 10:45:14 +01:00
Dion Moult 7c97ad05fd New IFCPatch tool, which can "patch" an IFC, including adjusting coordinates and elevations. 2020-02-06 16:20:15 +11:00
Dion Moult bf55214e1a IFC2CA made more IFC specific - Merge pull request #778 from Jesusbill/v0.6.0
minor update of ifc2ca.py
2020-02-05 22:05:01 +11:00
Dion Moult 207359ec2c Minor fix 2020-02-04 17:38:08 +11:00
Dion Moult 1f89a00896 Allow people to maintain parametric modifiers, or bake the results 2020-02-04 11:57:06 +11:00
Dion Moult b449f8afaa Handle scenarios where the data block name is the name for meshes and curves 2020-02-04 11:56:39 +11:00
Dion Moult 2d53c691f5 Prevent duplicate GlobalIds if the author manually creates a collision 2020-02-04 11:55:54 +11:00
Thomas Krijnen 3b0585ae4b Merge branch 'v0.6.0' of https://github.com/IfcOpenShell/IfcOpenShell into v0.6.0 2020-02-03 14:00:51 +01:00
Thomas Krijnen 2e6f5c1bd9 Fix #776 IfcPolygonalFaceSet units 2020-02-03 14:00:21 +01:00
Dion Moult c87903d3d7 Allow arbitrary locations for leaders and section levels. 2020-02-03 18:01:41 +11:00
Dion Moult e03e961a2f Add support for projection elements 2020-02-02 20:28:51 +11:00
Dion Moult c7c3d366bc Allow 3D dimension annotations with arbitrary origins for flexibility. 2020-02-01 22:50:49 +11:00
Dion Moult 691cc8759a New operator to quickly set diagram render options 2020-02-01 22:49:35 +11:00
Jesusbill 2786d7a20c minor update of ifc2ca.py 2020-01-31 16:52:15 +01:00
Dion Moult 9571d4a67b Allow users to toggle import of opening elements. 2020-01-31 12:52:44 +11:00
Dion Moult bb462659a3 Fix import of multiple spatial elements with the same name 2020-01-31 12:44:02 +11:00
Dion Moult 85e55b6deb Implement import and association of type products 2020-01-30 17:23:57 +11:00
Dion Moult e354354b1a Fix curve profile orientation on export. 2020-01-30 15:33:01 +11:00
Dion Moult 56a2f9eedc Minor fix where enum position would get lost when refreshed 2020-01-30 08:57:20 +11:00
Dion Moult 9cf81d5c7b Record the source IFC file as metadata in preparation for partial writes 2020-01-29 11:42:43 +11:00
Dion Moult 1800ebc893 Sites now can have a long/lat attribute exported. 2020-01-29 11:29:29 +11:00
Dion Moult 9895ff3c22 Quick project set up now creates spatial objects. 2020-01-29 11:28:26 +11:00
Dion Moult 52fae93a14 Allow export of objects for spatial tree 2020-01-28 22:06:58 +11:00
Dion Moult 5a3303837d You can now write BIMTester tests directly to the features dir. 2020-01-28 18:10:33 +11:00
Dion Moult f501aaeb01 Add new import workaround for 12D files with absolute coordinates. 2020-01-24 10:19:44 +11:00
Dion Moult 98e082ccac Assign product types using a property, not by parenting for scalability. 2020-01-23 15:23:19 +11:00
Dion Moult 9e67b05df9 Add workaround for importing wrongly geolocated Revit buildings. 2020-01-22 21:43:18 +11:00
Dion Moult f80e700997 Add autodoc for IfcOpenShell-python. See #755. 2020-01-21 21:34:32 +11:00
Dion Moult 2f1b5ff2d4 Add doc pages for utilities, rename doc to IfcOpenShell 2020-01-21 18:03:15 +11:00
Dion Moult 9b5265e6fd Merge IfcOpenShell documentation structure. See #755. 2020-01-21 17:53:05 +11:00
Dion Moult b88739eed8 Add progress bar when importing. Fix #759. 2020-01-21 14:55:35 +11:00
Dion Moult 3108d3ecfe Add experimental IFC to Code_Aster converter script. See #756. 2020-01-21 09:55:40 +11:00
Dion Moult f78a0ec88a Assign all structural members to group. See #756. 2020-01-20 20:15:06 +11:00
Dion Moult afaab7c9e0 Allow export of structural analysis models. See #756. 2020-01-20 17:26:41 +11:00
Dion Moult 8dce661830 Allow export of structural member connections. See #756. 2020-01-20 16:22:24 +11:00
Dion Moult 47723b4e63 Allow export of boundary conditions. See #756. 2020-01-20 15:06:24 +11:00
Dion Moult f50722c4bc New UI to add structural boundary condition data. See #756. 2020-01-19 18:41:57 +11:00
Dion Moult a34588179d Extract select attributes from XSD into JSON. 2020-01-19 18:40:39 +11:00
Dion Moult 3fb268f687 Properly detect all possible representation contexts for an object. See #756. 2020-01-18 12:47:55 +11:00
Dion Moult 368f76b713 Minor fix 2020-01-17 14:13:11 +11:00
Dion Moult 09e4fe56f4 Add junit dir argument 2020-01-17 12:52:55 +11:00
Dion Moult e077235eee Add bimtester definitions related to model setup tests 2020-01-16 17:55:37 +11:00
Thomas Krijnen d9805185ee Fix boolean op style selection 2020-01-15 11:50:44 +01:00
Thomas Krijnen f58d9243fa Fix trimmed curve where vertex order does not agree with linear curve geom 2020-01-15 10:35:31 +01:00
Dion Moult 9a2f101df7 Allow structural point connections to be exported. See #756. 2020-01-15 17:43:21 +11:00
Dion Moult af278b5724 Add UI for pset overrides without the need to create a CSV. 2020-01-15 17:17:03 +11:00
Dion Moult 71f836d013 Add ability to export parameterised profiles for material profiles. 2020-01-14 17:38:54 +11:00
Dion Moult 8490dc7841 Allow material profile sets to be exported. 2020-01-14 16:11:11 +11:00
Dion Moult 2dbcd6712e Create UI to add/remove material attributes 2020-01-14 15:38:22 +11:00
Dion Moult ef919ab431 Create UI to change material definition type 2020-01-14 13:28:48 +11:00
Dion Moult 29b7b2963e Allow topological reference export of structural members. See #756. 2020-01-14 12:11:26 +11:00
Dion Moult 8ae8042d65 Only show predefined type and user defined type if it is a valid input 2020-01-13 17:42:59 +11:00
Dion Moult c4af52e8ee Allow IfcStructural* elements to be exported. See #756. 2020-01-13 17:35:56 +11:00
Thomas Krijnen 9ef9498c35 Submodule 2020-01-12 15:21:09 +01:00
Thomas Krijnen 68763f4988 Don't raise error on eliminated compcurve polygon points 2020-01-12 15:18:12 +01:00
Thomas Krijnen 98d8a3477d Limit max angle for trimmed curve approx 2020-01-12 15:17:48 +01:00
Thomas Krijnen 07756ab2da Renable wire segmentation for #468 and #674 2020-01-12 14:40:27 +01:00
Dion Moult a2003101a0 Support export of point clouds to IFC 2020-01-12 20:47:06 +11:00
Dion Moult ce5bf5749f Minor fix 2020-01-12 20:45:55 +11:00
Dion Moult 7519447966 Add sample data for doors and window. 2020-01-12 19:02:32 +11:00
Dion Moult e1cfa68dcb Allow export of material properties. Related to #756. 2020-01-12 19:01:35 +11:00
Thomas Krijnen 614348d3a2 Update testfile submodule 2020-01-11 14:45:36 +01:00
Thomas Krijnen 4320888d9d Fix #726, #728, #730 by other transition mode, more aggressive curve approx and custom revolution implementation 2020-01-11 14:23:16 +01:00
Dion Moult d84cfeffcc Export an axis representation for beveled curves. Related to #756. 2020-01-11 22:58:53 +11:00
Dion Moult a762afc7c1 All export of vector curve objects. Related to #756 2020-01-11 09:55:39 +11:00
Dion Moult 7c0f5ca7bc Allow import of site objects 2020-01-11 07:51:57 +11:00
Thomas Krijnen 6047addfae #include <Message_Msg.hxx> 2020-01-10 10:05:31 +01:00
Dion Moult b66e5e9911 Document context panel 2020-01-10 18:44:05 +11:00
Dion Moult e5cd71dd1e Minor fix 2020-01-10 18:24:05 +11:00
Dion Moult 28e043f97a Minor makefile fix 2020-01-09 06:00:30 +01:00
Dion Moult af2dd8f9bb Minor fix 2020-01-09 15:52:11 +11:00
Dion Moult 0f1be45990 Automatically detect and set import workarounds for Revit 2020-01-09 15:30:43 +11:00
Dion Moult d91fa69e83 Write documentation for BIM panel and owner history panel 2020-01-09 13:49:11 +11:00
Dion Moult a286082a1c Add scene documentation 2020-01-09 07:28:30 +11:00
Dion Moult fde80896a1 Add assign context operator and minor UI cleanup 2020-01-08 16:58:59 +11:00
Dion Moult 579d3d9f86 Add feature to explode an aggregation. 2020-01-08 15:58:39 +11:00
Dion Moult f11021b505 Place opening elements into collection on import. Fix #750. 2020-01-08 15:26:31 +11:00
Dion Moult 21ed3ea515 Import aggregations into collections. Fix #750. 2020-01-08 15:07:29 +11:00
Dion Moult e927ac49ac Add basic sphinx docs 2020-01-08 10:58:52 +11:00
Thomas Krijnen e8494dcbfd Fix placement on STP and IGS export 2020-01-07 15:37:22 +01:00
Thomas Krijnen 99706bdf5a Fix #741 2020-01-07 14:17:55 +01:00
Dion Moult 6b9a01c50d Add STEP header metadata 2020-01-07 16:12:11 +11:00
Dion Moult 13e0b77c7f Fallback to legacy importer if diff feature enabled 2020-01-07 15:48:54 +11:00
Dion Moult dcaef14b5f Add dependencies for IFC Diff 2020-01-07 14:42:03 +11:00
Dion Moult 6d6f7af3d7 Create UI to run IFCDiff tool from Blender 2020-01-07 14:27:34 +11:00
Dion Moult dfe8149b17 Package IFC diff utility for Windows 2020-01-06 17:39:04 +11:00
Dion Moult fc220efb6c Create UI to switch between views easily 2020-01-06 14:30:44 +11:00
Dion Moult 6d83815ab1 Allow view scales to be set per camera instead of global 2020-01-06 11:46:42 +11:00
Dion Moult 461b1735dd New interface to quickly create a new view for documentation 2020-01-06 10:41:59 +11:00
Dion Moult 642738e0c0 Merge branch 'v0.6.0' of https://github.com/IfcOpenShell/IfcOpenShell into v0.6.0 2020-01-06 08:49:24 +11:00
Dion Moult 99c77fff5e Remove unnecessary example blend file 2020-01-06 08:48:14 +11:00
Dion Moult 8a255d3b0d Fix duplicate material assignment bug on import 2020-01-03 21:21:36 +11:00
Dion Moult 94d2a11096 Minor fix when ignoring site coordinates 2020-01-03 16:56:32 +11:00
Dion Moult 403cda5bc8 Allow you to select person and organisation when exporting owner history metadata 2020-01-03 15:53:57 +11:00
Dion Moult d6b9810b94 Add about 50 hatches in SVG pattern format taken from LibreCAD 2020-01-03 12:46:29 +11:00
Dion Moult 7c6e7742a8 Implement "should recut" to force recutting of a diagram 2020-01-03 08:44:51 +11:00
Dion Moult 220826f141 Turn BIMTester into a CLI app with ability to set arguments to Behave 2020-01-02 15:02:40 +11:00
Dion Moult 2007277bfc Add unit tests to check for names, shapes, attributes, properties, and quantities 2020-01-02 13:01:17 +11:00
Dion Moult f74295127b Allow people to create spatial structure elements 2020-01-02 13:00:18 +11:00
Dion Moult 4ed4bcf660 Implement multicore importer using IfcOpenShell iterator with Revit material hack 2019-12-31 16:32:20 +11:00
Dion Moult 4da2f9c9e7 Don't strictly enforce Ifc naming in objects or meshes 2019-12-29 07:28:54 +11:00
Dion Moult 782b10fbde Add AI-enabled web 2.0 hypermedia API generate digital twin button 2019-12-20 10:43:39 +11:00
Dion Moult 4bb5248593 Minor fix 2019-12-19 16:49:27 +11:00
Dion Moult 5127555740 Implement Conda Mac and Linux lib loading workaround 2019-12-19 15:31:00 +11:00
Dion Moult 276ac5c1d1 Isolate libs for macos and linux builds 2019-12-19 05:05:57 +01:00
Dion Moult d6e16c5373 Fix bug with loading absolute dependencies on a fresh install 2019-12-19 04:35:19 +01:00
Dion Moult a93844bb83 Support multiline annotation, improve RL tags, detect active camera 2019-12-19 13:00:19 +11:00
Dion Moult 6f5a6418a7 Fix rotated dimensions, add engineering style dimensions 2019-12-19 08:17:14 +11:00
Dion Moult f63161e40a Add view cut caching, equal dims, and RL tags 2019-12-17 17:05:03 +11:00
Dion Moult b500dab88a Fix PDF dimension annotation rendering bug 2019-12-17 17:04:00 +11:00
Dion Moult eed5d05af5 Convert template to OpenGOST typeface 2019-12-17 14:59:02 +11:00
Adrien Scho 4b6fe80fb2 chore: updated broken links in readme 2019-12-16 13:43:52 +01:00
Adrien Scho 05a5c3c3f9 fix: #734 - No XML serializer registered for IFC4X1 2019-12-16 13:43:52 +01:00
Thomas Krijnen 3937d995b6 Merge branch 'master' into v0.6.0
# Conflicts:
#	src/ifcopenshell-python/ifcopenshell/geom/main.py
2019-12-16 13:41:54 +01:00
Dion Moult 1b2af78e65 Experimental packaging with OCC and SVG deps 2019-12-16 05:44:52 +01:00
Thomas Krijnen 974e3fa904 Correct clean up in Iterator 2019-12-14 13:23:40 +01:00
Dion Moult c0cd0ce07e Add section cut multiprocessing, grids, hidden lines, stair arrows, text annotations, and leaders 2019-12-13 17:25:52 +11:00
Dion Moult 4f7925580a Implement dimension text rotation, technical font, and dimension position 2019-12-12 18:17:39 +11:00
Dion Moult e87bff736e Add simple section cut results caching 2019-12-12 18:16:02 +11:00
Dion Moult 948ff287f1 Standardise line thicknesses and dimension tick styles 2019-12-12 18:14:44 +11:00
Dion Moult b452d7c794 Add support for different view scales 2019-12-12 12:51:47 +11:00
Mieszko Boczkowski 1426c7066b Move has_occ() function to __init__ 2019-12-11 11:54:56 +01:00
Mieszko Boczkowski f84982f99a Change exception on failed import for Python 2 compatibility 2019-12-11 11:54:56 +01:00
Mieszko Boczkowski 8d4f34461e Fix OCC imports in Python 2019-12-11 11:54:56 +01:00
Dion Moult 516757ba38 Support placing a view / section / diagram on a sheet 2019-12-11 18:50:01 +11:00
Dion Moult 25dfa32b7e Switch to absolute paths for module loading 2019-12-11 18:44:46 +11:00
Dion Moult 2eeb507b78 WIP support for cutting a section with dimension annotation lines 2019-12-10 18:54:26 +11:00
Dion Moult 1d04a3a5c7 Move section generator into plugin to prepare for integration 2019-12-09 21:26:29 +11:00
Dion Moult d3b56bd79b Experimental code to merge background faces in a section cut 2019-12-08 21:14:04 +11:00
Dion Moult 53d64348fd Allow people to configure exportable contexts 2019-12-07 21:33:44 +11:00
Dion Moult d46ba7d1cd Simplify UI for context management 2019-12-07 17:02:59 +11:00
Dion Moult c339a97443 Allow IFC clash utility to run as a command line app 2019-12-05 17:28:34 +11:00
Dion Moult dfc30c2137 Add sample material pass files and fix relative material locations 2019-12-05 09:54:35 +11:00
Dion Moult e9418bfb0b Allow IFC diff utility to read from command line input 2019-12-04 21:58:59 +11:00
Dion Moult f7116d70e7 Add experimental UI to manage geometric contexts 2019-12-04 17:49:28 +11:00
Dion Moult 2d495e6124 Add support to do basic import of document relationships 2019-12-04 15:30:33 +11:00
Dion Moult 5df2b3aa0a Experimental support to proxy one shape for another in IFC 2019-12-03 17:27:22 +11:00
Dion Moult a00449e34b Export clash results to JSON with metadata 2019-12-01 22:17:23 +11:00
Dion Moult 6250f903ff Implement experimental clash detection with a tolerance 2019-12-01 22:04:28 +11:00
Dion Moult 5bb59f3136 Allow fetching Eevee or Cycles materials from a material pass file 2019-11-30 22:42:04 +11:00
Dion Moult d76a67450c Import externally defined materials 2019-11-30 12:05:56 +11:00
Dion Moult a38df48d5a Support styled item surface colours on IFC import 2019-11-30 11:26:02 +11:00
Thomas Krijnen e283b51dbc Add includes for older occt versions 2019-11-26 12:47:43 +01:00
Dion Moult 44491c6167 Make the audit class a drop down in the panel UI 2019-11-26 21:05:05 +11:00
stephassoria afaa34ffc2 IfcOpenShell v0.6.0 as subrepo 2019-11-26 10:09:16 +01:00
Dion Moult 031fd1baff Mostly stable implementation of mirror modifier 2019-11-26 11:49:14 +11:00
Dion Moult e643966191 Fix incorrect version replacement 2019-11-25 07:49:13 +11:00
Dion Moult ad7ef0be4f Implement experimental support for mirror modifier 2019-11-24 22:11:57 +11:00
Dion Moult b9e6665eab Fix reuse of representation maps. See #724 2019-11-24 18:12:33 +11:00
Thomas Krijnen 9bcd932bed fixes for macos catalina 2019-11-22 18:45:11 +01:00
Thomas Krijnen bfaa9ed5f9 Old OCC compatibility 2019-11-22 13:12:39 +01:00
Johan Luttun a2418cf260 added faceset feature (#714)
* added faceset feature

* indented code correctly

* better indentation on selected hunk
2019-11-22 12:58:30 +01:00
Dion Moult 69a6f5ee36 Minor fix to build script 2019-11-21 21:49:18 +11:00
Dion Moult e781df10b8 Merge branch 'v0.6.0' of github.com:IfcOpenShell/IfcOpenShell into v0.6.0 2019-11-21 21:27:49 +11:00
Dion Moult f16861d5a9 Implement support for IfcLibraryInformation like a Git server 2019-11-21 21:27:32 +11:00
Dion Moult ad504ff081 Add sentences to exempt IFC files from BIMTester auditing 2019-11-21 09:46:37 +11:00
Dion Moult 9a18198988 Partial implementation of project library information 2019-11-21 07:09:08 +11:00
Dion Moult de64e3afc3 Reorder BIM property panels for better user experience 2019-11-21 06:48:22 +11:00
Dion Moult 7253b07b0c Fix broken select IFC type operator 2019-11-21 06:43:35 +11:00
Dion Moult b4f344627d Merge pull request #725 from s-leger/patch-5
Fix bug in boolean modifier support
2019-11-19 07:42:59 +11:00
Thomas Krijnen c385257c92 Add more warning related to rep usage. See #724 2019-11-18 12:59:48 +01:00
s-leger 859afaeece Fix negative right axis 2019-11-18 07:54:11 +01:00
s-leger e510d5a197 Fix resolve_boolean_modifier
Use matrix col for axis instead of row ..
Store product indexes in resolve_boolean_modifier
Remove get_product_from_raw_name
2019-11-18 07:51:09 +01:00
Dion Moult 33967953b7 Merge pull request #723 from s-leger/patch-5
Implement element voiding and clean up to PEP8
2019-11-18 15:55:14 +11:00
s-leger 34c2cd3c06 Update export_ifc.py
Fix function names, spaces, "type" shadowing 
improve vertices export using list comprehension
Check for empty material slot
2019-11-18 05:46:52 +01:00
s-leger 5cd6f44e73 Update export_ifc.py
Fix translation and axis of type_products
2019-11-18 04:23:41 +01:00
s-leger b75f1e1758 Merge branch 'v0.6.0' into patch-5 2019-11-18 04:07:26 +01:00
Stephen Leger f12e732854 fix merge error 2019-11-18 03:49:04 +01:00
Stephen Leger c9a5fbf221 merge 0.6 into patch-5 2019-11-18 03:45:24 +01:00
Dion Moult c930b8f155 Optimise select audited operator 2019-11-18 11:30:08 +11:00
Dion Moult 1e802bd0a3 Bugfix for BIMTester purge function to overwrite existing feature files 2019-11-18 10:48:50 +11:00
Dion Moult c46167073b Specifying an IFC diff now does an incremental import 2019-11-18 10:18:21 +11:00
Thomas Krijnen 5237f4a634 Add warning related to rep usage. See #724 2019-11-17 14:07:32 +01:00
s-leger b54be81408 Update export_ifc.py
fix typo in product
2019-11-17 14:00:05 +01:00
s-leger 39a5ecb6d2 Update export_ifc.py
Replace object by obj   - never override native var "object" 
Implements get_axis from matrix helper
2019-11-17 13:25:41 +01:00
s-leger a6128f118a Update export_ifc.py 2019-11-17 13:12:22 +01:00
Dion Moult 448a56afe9 Minor scale fix and code cleanup 2019-11-17 20:41:53 +11:00
Dion Moult 0d243beb36 Implement export for objects with non-uniform scale 2019-11-17 19:08:29 +11:00
s-leger 9e4092a050 Update export_ifc.py
Retrieve product from raw name
2019-11-17 03:15:46 +01:00
s-leger 44d4d9e563 process booleans
process booleans as RelFillsElements and RelVoidsElements
Fills are expected to be parent of holes so when you move a fill hole follow in real time
2019-11-17 02:52:20 +01:00
Dion Moult f249d55d3c Add version string to Makefile so users know their version 2019-11-17 12:40:14 +11:00
Dion Moult 85076dc697 Rename plugin to "BlenderBIM" 2019-11-17 12:29:02 +11:00
Dion Moult c074bd455f Ensure null values cannot be picked which result in bad IFC data 2019-11-17 11:59:35 +11:00
Dion Moult c04e8f98ec Refactor Blender property definitions in its own file 2019-11-17 11:38:56 +11:00
Dion Moult ef6dcd9291 Fix location for parented and constrained objects 2019-11-16 07:38:21 +11:00
s-leger c51c8602a3 Update ui.py
Dynamic enum cache
Update on change
Use direct propertygroup access in enum functions
2019-11-15 17:33:11 +11:00
Dion Moult 9659de6ebf Support export of people and organisations 2019-11-15 15:44:04 +11:00
Dion Moult 396979954f Add ability to purge tests of deleted elements 2019-11-15 15:43:33 +11:00
Dion Moult 836e350a15 Merge pull request #721 from s-leger/patch-3
Update ui.py
2019-11-15 15:03:59 +11:00
s-leger 0532048f37 Update ui.py 2019-11-15 04:59:51 +01:00
s-leger 78e18f0a01 Update ui.py
Fix for dynamic enum function signature
2019-11-15 04:53:58 +01:00
Dion Moult e1bf82b88e Merge pull request #720 from s-leger/patch-2
Class naming convention
2019-11-15 14:18:44 +11:00
Dion Moult ed0dffb409 Merge pull request #719 from s-leger/patch-1
Dynamic enumerators
2019-11-15 14:18:29 +11:00
s-leger c66a2589d8 Class naming convention
Fix naming convention for Panel classes
2019-11-15 01:48:20 +01:00
s-leger 7140b2c4e8 Dynamic enumerators
Dynamic enums require to hold proper reference to enum array. (may lead to access violation and strange ui behaviour)
Cleanup bpy.props.xxx and bpy.types.xxx
Fix in path for files with hardcoded "/"
BIM_PT_ prefixes for Panel classes
Use poll method for panels
2019-11-15 01:44:29 +01:00
Dion Moult 21e87095dc Minor fix 2019-11-14 07:51:47 +11:00
Dion Moult cfe030378a New UI to assign multiple swept solids per object 2019-11-13 18:48:12 +11:00
Dion Moult 556a476f9f Improved extrusion algorithm calculates extrusion profiles per face
Bugfixes incorrect extrusion axis locations, and also decouples object matrix_world from the extrusion axis, allowing you to have multiple extrusion per object in the future.
2019-11-12 17:57:59 +11:00
Dion Moult 49efce7eca New option to ignore site, to import incorrectly geolocated IFCs
This behaviour occurs extensively in IFC files coming from Revit
2019-11-08 17:24:15 +11:00
Dion Moult c425b44ca9 Store generated GlobalId values for parametric geometry 2019-11-08 16:45:39 +11:00
Dion Moult af16e64fd9 Add UI option to import curves and tolerate invalid IfcSite objects 2019-11-08 16:02:57 +11:00
Dion Moult 60b3daf686 Create legacy features to export materials into broken BIM programs like Revit 2019-11-08 15:10:51 +11:00
Dion Moult 80dccfeb54 Add support for inner curves in mesh extrusions and fix position bug 2019-11-08 12:39:34 +11:00
Thomas Krijnen c89d268986 More elaborate shape fixing on face surface 2019-11-07 14:04:45 +01:00
Dion Moult ee7956d921 Add support for plan representations and all target views 2019-11-07 21:49:14 +11:00
Dion Moult 609ef5f3a7 Add support for exporting survey points geometry 2019-11-07 17:59:37 +11:00
Dion Moult 0477910fc0 Add support for export of imperial units 2019-11-07 16:40:57 +11:00
Dion Moult 85a3a97d13 Fix import of conversion based units 2019-11-07 14:20:54 +11:00
Dion Moult 9eb035e6f5 Fix export bug with uncast attribute data types 2019-11-07 09:11:25 +11:00
Thomas Krijnen 2a407f007c Document fontconfig dependency for occt 7.4 2019-11-06 14:05:05 +01:00
Thomas Krijnen 5992cdfdaf Build script changes for occt 7.4 2019-11-06 12:03:32 +01:00
Dion Moult 0d7d843fc9 Support extruded vector curves and tilts 2019-11-06 17:37:51 +11:00
Dion Moult fae405bfe0 Add support for importing curves, such as for survey point curve sets 2019-11-06 11:10:51 +11:00
Thomas Krijnen c59c74aeed Confitionally select num_bytes, see #699 2019-11-05 17:23:13 +01:00
Thomas Krijnen e36357d381 Log error about missing triangulation 2019-11-05 15:47:02 +01:00
Thomas Krijnen 8d96f40934 Check for inner wires before reinitializing face builder 2019-11-05 15:27:39 +01:00
Thomas Krijnen a1253b004d Fixes for closed/non-periodic nurbs curve edges #586 2019-11-05 15:13:34 +01:00
Thomas Krijnen ee79401a34 Correct attribute_filter notice 2019-11-05 14:43:37 +01:00
Dion Moult 37990310eb Experimental half-broken support for curves added 2019-11-05 21:49:17 +11:00
Dion Moult d806c6ab55 Cull-backfaces and cache geometry creation in IfcDoc 2019-11-02 20:08:34 +11:00
Thomas Krijnen ed013db011 throw exception on invalid nested aggregates 2019-11-01 16:11:46 +01:00
Thomas Krijnen 5fcee9dfe5 spherical toroidal surface 2019-11-01 16:11:26 +01:00
Thomas Krijnen 159ce931b4 Break up sweeps along adjacent non-linear segments. 2019-11-01 15:06:04 +01:00
Dion Moult 2d0d0ed786 New UI to add and remove classifications 2019-11-01 17:44:10 +11:00
Dion Moult 635ad552d3 New UI to create, edit, and save aggregates 2019-11-01 16:32:11 +11:00
Thomas Krijnen d3eab88ab9 Create FUNDING.yml 2019-10-30 08:31:30 +01:00
Dion Moult c3a36b7cdb Support cartesian transformations on mapped representations on import 2019-10-30 13:15:03 +11:00
Thomas Krijnen f231db0aff Remove newlines and other characters from material names 2019-10-29 10:06:02 +01:00
Dion Moult 0a610f88e0 New UI to set features dir and diff JSON file 2019-10-29 18:13:10 +11:00
Dion Moult e2764c9764 Merge branch 'v0.6.0' of github.com:IfcOpenShell/IfcOpenShell into v0.6.0 2019-10-28 21:02:03 +11:00
Dion Moult d6ef64aef4 Proof of concept for IFC construction documentation 2019-10-28 21:01:32 +11:00
Dion Moult cf454c6306 IFC cutting tool now supports multiple files and classes 2019-10-28 20:59:16 +11:00
Dion Moult 18daa6aacd Allow gbXML export of simple objects that don't have vertex groups
Also record space names
2019-10-28 17:53:13 +11:00
Dion Moult 55717756e6 Create IFC Diff tool, showing added, removed, and modified.
It produces a JSON output of exactly what changed. It requires a patched version of the DeepDiff library, which I will provide.
2019-10-25 16:42:49 +11:00
Dion Moult 852df6e2ce Some bugfixes and package IFC COBie for alpha release 2019-10-25 08:22:16 +11:00
Dion Moult bc2bce8fae Add experimental support for openings in gbXML export 2019-10-23 13:29:25 +11:00
Dion Moult e5efa2803a Fix BIMTester file overwrite bug and template re-reading. 2019-10-23 13:28:18 +11:00
Dion Moult d3ccd9ee61 Merge branch 'v0.6.0' of https://github.com/IfcOpenShell/IfcOpenShell into v0.6.0 2019-10-23 11:33:05 +11:00
Dion Moult 593af0509f Optimise import to only create shapes once. Much faster. 2019-10-23 11:32:30 +11:00
Thomas Krijnen 60073da049 Update validate.py 2019-10-22 10:49:07 +02:00
Dion Moult 681a3c3a5c Test new way of getting element position matrix in import 2019-10-22 15:54:38 +11:00
Dion Moult f63c0293bf IFC import now supports IFC attributes 2019-10-21 17:44:06 +11:00
Dion Moult 7e8cda6c12 Add interface to add or remove documents to objects 2019-10-21 15:31:10 +11:00
Dion Moult 1bdb64d9e7 Refactor properties to have prefix to prevent name clashes with other addons 2019-10-21 14:56:40 +11:00
Dion Moult e2ada7ce90 Implement IFC import mesh reuse for mapped representations 2019-10-21 14:33:51 +11:00
Dion Moult 2751b7728f Add new feature to select object by GlobalId 2019-10-19 17:38:25 +11:00
Dion Moult 9ee708fbe6 Create UI to input georeferencing variables 2019-10-19 15:15:42 +11:00
Dion Moult 851acca4b2 Support custom psets 2019-10-19 14:45:07 +11:00
Dion Moult 4cddd95337 Fix bug where blank predefined types could be added by accident 2019-10-19 13:59:05 +11:00
Dion Moult 5a7acda57d Allow to add attributes from a drop down for ease of use 2019-10-19 13:48:07 +11:00
Dion Moult 62f04fc9a6 Move pset definitions into a property group and create a UI for it 2019-10-19 11:36:29 +11:00
Dion Moult 4dbe7d92aa Merge branch 'v0.6.0' of github.com:IfcOpenShell/IfcOpenShell into v0.6.0 2019-10-19 10:47:15 +11:00
Dion Moult c79db0380d Create quick project setup button for convenience 2019-10-19 10:47:00 +11:00
Demetrio92 e6cae6e7b9 minor bugfix
should be OR, not AN;  color is spelled without U everywhere else; exception call itself was breaking
2019-10-17 14:14:15 +02:00
Dion Moult 791be5006b Couple of minor fixes to make importing more robust 2019-10-17 18:47:01 +11:00
Dion Moult 240b642d6d Test light schedule data for gbxml 2019-10-17 18:46:06 +11:00
Dion Moult 574d9a3036 Add attributes interface 2019-10-16 23:17:48 +11:00
Dion Moult 34e5dac549 Merge branch 'v0.6.0' of github.com:IfcOpenShell/IfcOpenShell into v0.6.0 2019-10-16 07:23:39 +11:00
Dion Moult 1fc06da7a2 Create UI to assign and remove Psets 2019-10-16 07:23:03 +11:00
Thomas Krijnen 4000fef4c7 Don't apply too many half space subtraction operands at once 2019-10-15 15:06:51 +02:00
Thomas Krijnen 503029733c Fix face-face distance calc and hardcode tolerance independent of precision. 2019-10-15 14:14:50 +02:00
Thomas Krijnen 734c456fa5 Properly adjust wire intersection tolerance based on vertex clustering 2019-10-15 12:53:44 +02:00
Thomas Krijnen 5b81d7a0c1 Fix previous commit 2019-10-15 10:39:58 +02:00
Thomas Krijnen f9b76ce022 Don't write materials without diffuse color in geom server 2019-10-15 10:38:49 +02:00
Dion Moult fa3431f983 Fix bug with Revit where Revit expects normalised unit vectors.
I think IFC doesn't require it, but fine, we'll play with Revit.
2019-10-15 18:11:06 +11:00
Dion Moult 2d673acb1d Styled items repeat per product, so this should be a list, not a dict 2019-10-15 18:10:32 +11:00
Dion Moult 05c05b5700 Purge old BIMTester files 2019-10-15 16:30:10 +11:00
Dion Moult 58b7c42fc5 Create features template 2019-10-15 11:58:26 +11:00
Dion Moult f78fb0a4f0 Package up BIMTester - basically a super lightweight wrapper around Behave and a JUnit HTML formatter. 2019-10-15 11:19:44 +11:00
Dion Moult 2b34d66ca4 Include Behave configuration 2019-10-14 18:27:17 +11:00
Dion Moult f21fac9edc Change build url 2019-10-13 20:30:01 +11:00
Dion Moult 15a93b1651 Merge branch 'v0.6.0' of github.com:IfcOpenShell/IfcOpenShell into v0.6.0 2019-10-13 20:23:53 +11:00
Dion Moult b7ffd4e350 Fix makefile to build just one plugin, since import and export are merged now 2019-10-13 20:20:48 +11:00
Thomas Krijnen 833d16404f Update attribute filter in accordance with help string 2019-10-13 07:45:19 +02:00
Dion Moult c55dbfc7fa Implement UI to toggle wireframe / swept solid, and assign profiles and extrusions
Also allow file browser to select a location for an external material
2019-10-13 15:36:49 +11:00
Dion Moult 4476cce08c Create interface panel to select external materials 2019-10-13 11:14:49 +11:00
Dion Moult 3db6f42f04 Add latest features into readme 2019-10-13 09:46:12 +11:00
Dion Moult 4732dae384 Allow to define surface styles via object, rather than by material 2019-10-12 22:20:09 +11:00
Dion Moult a9397e23ba Refactor material creation to follow IFC data, not rely on ifcopenshell geom, since we want to retain a bunch of smart IFC data later 2019-10-12 20:09:41 +11:00
Dion Moult c5645a1084 Prevent infinite loops on broken spatial trees 2019-10-12 18:54:12 +11:00
Dion Moult 556766bf2b Spatial elements should check both class and name to prevent issue where two elements have the same name 2019-10-12 18:53:40 +11:00
Dion Moult 33bea4bf6c Merge branch 'v0.6.0' of https://github.com/IfcOpenShell/IfcOpenShell into v0.6.0 2019-10-11 17:24:53 +11:00
Dion Moult bf31ced530 Create JUnit to HTML converter 2019-10-11 17:23:54 +11:00
Dion Moult 642fd08d1f Define a few more steps 2019-10-11 17:23:20 +11:00
Dion Moult 9d0bbf52a2 Don't include IfcSpace since there can be _lots_ in a large file, and ifc spaces actually have geometry 2019-10-10 21:13:00 +11:00
Dion Moult 9056fd7fd1 Remove some abstract entities 2019-10-10 21:12:40 +11:00
Dion Moult 7513906aaa Implement basic Gherkin-based QA system 2019-10-10 18:29:22 +11:00
Dion Moult 7b15edb44c Implement CSV and XLS writer with logging features for COBie 2019-10-09 14:44:10 +11:00
Dion Moult e25bdd009b Remove unnecessary files 2019-10-09 10:45:30 +11:00
Dion Moult 72f09e6a22 Merge branch 'v0.6.0' of https://github.com/IfcOpenShell/IfcOpenShell into v0.6.0 2019-10-09 10:13:37 +11:00
Dion Moult 7b8a4501e6 Bug #663 - Implement support for COBie issues spreadsheet 2019-10-09 10:12:38 +11:00
Dion Moult ba443232b3 Bug #663 - Implement support for COBie coordinates spreadsheet 2019-10-09 10:01:41 +11:00
Dion Moult 71153abaf6 Bug #663 - Implement support for COBie attributes spreadsheet 2019-10-09 09:43:22 +11:00
Dion Moult d9ebd2d08e Merge experimental new importer plugin into export plugin 2019-10-08 23:05:27 +11:00
Dion Moult 792c9b65b1 Build "select by class / type" feature in the UI panel 2019-10-08 22:09:39 +11:00
Dion Moult 202a4c0a08 Bug #663 - Implement support for COBie documents spreadsheet 2019-10-08 18:35:56 +11:00
Dion Moult 8cb8e22cdc Bug #663 - Implement support for COBie impacts spreadsheet 2019-10-08 18:16:32 +11:00
Dion Moult 38972d7ee4 Bug #663 - Implement support for COBie jobs spreadsheet 2019-10-08 17:33:14 +11:00
Dion Moult 959609db99 Bug #663 - Implement support for COBie resources spreadsheet 2019-10-08 16:56:37 +11:00
Dion Moult e3d24856b9 Bug #663 - Implement support for COBie spares spreadsheet 2019-10-08 16:51:56 +11:00
Dion Moult 6513cb6a88 Bug #663 - Implement support for COBie connections spreadsheet 2019-10-08 16:14:00 +11:00
Dion Moult 77578b0ade Bug #663 - Implement support for COBie assemblies spreadsheet 2019-10-08 15:45:23 +11:00
Dion Moult 32f51086ca Bug #663 - Implement support for COBie systems spreadsheet 2019-10-08 14:52:30 +11:00
Dion Moult f426f2c0af Bug #663 - Implement support for COBie components spreadsheet 2019-10-08 14:32:10 +11:00
Dion Moult a6916e1f59 Bug #663 - Implement support for COBie types spreadsheet 2019-10-08 13:45:48 +11:00
Dion Moult 8f757810e7 Bug #663 - Implement support for COBie zones spreadsheet 2019-10-08 12:22:05 +11:00
Dion Moult 2b786ef945 Bug #663 - Implement suport for COBie spaces spreadsheet 2019-10-08 11:47:49 +11:00
Dion Moult dc7fb6eb98 Bug #663 - Implement support for COBie floors spreadsheet 2019-10-08 10:54:32 +11:00
Dion Moult 3ff9af1421 Bug #663 - Implement support for COBie facilities spreadsheet extraction 2019-10-08 10:18:39 +11:00
Dion Moult fc44b4e0d4 Allow user option to export without representations 2019-10-07 22:23:31 +11:00
Dion Moult 0ebb33da18 Improve error messaging for incorrect psets 2019-10-07 22:14:52 +11:00
Dion Moult eceba6932c Fix date in dist filename 2019-10-07 21:20:39 +11:00
Dion Moult 1f6f7f570e Refactor operators into their own file and provide logging capabilities 2019-10-07 21:11:11 +11:00
Dion Moult 23d65da0e2 Add makefile 2019-10-06 19:59:41 +11:00
Dion Moult 824b30b3da Bundle and implement basic UI with addon 2019-10-05 21:15:53 +10:00
Dion Moult 90fee4ef7f Throw in bootstrap file for when you don't want to reload blender to test the plugin 2019-10-04 17:28:57 +10:00
Dion Moult adeb3dea61 Include utility to merge materials by diffuse colour to clean up bad IFC files 2019-10-04 17:26:15 +10:00
Dion Moult 75f254d162 Extract definitions and descriptions for use in plugin 2019-10-04 17:24:49 +10:00
Dion Moult 00aad53181 Bug #663 - Implement experimental support for cobie IFC->CSV conversion for contact information 2019-10-04 17:22:03 +10:00
Dion Moult bf7005acfc Add experimental support for gbxml - make importer import spaces, as it is very important for energy modeling 2019-10-04 17:20:19 +10:00
Dion Moult e37c882fe2 Experimental code for a user interface 2019-10-03 22:11:05 +10:00
Dion Moult 624888adab Half-implement experimental support for space boundary relationships 2019-10-03 17:56:45 +10:00
Dion Moult 144df86380 Throw in experimental import and bulk rename script 2019-10-01 18:37:33 +10:00
Dion Moult 50c51530e7 Add pset examples 2019-10-01 18:03:16 +10:00
Dion Moult 7312b8cbe7 Merge branch 'v0.6.0' of https://github.com/IfcOpenShell/IfcOpenShell into v0.6.0 2019-10-01 18:01:55 +10:00
Dion Moult 4e878f5848 Move pset into pset dir 2019-10-01 18:00:54 +10:00
Thomas Krijnen d99b5fb2f9 Merge branch 'master' into v0.6.0 2019-09-30 09:11:04 +02:00
Dion Moult 51e0097db1 Add prepackaged installation instructions. 2019-09-30 10:10:50 +10:00
Dion Moult 1cac87fa50 Bump readme with new features 2019-09-30 08:07:56 +10:00
Dion Moult e688f781f5 Parenting is reserved for type assignment, whereas a named child of constraint now specifys a nesting relationship
This allows you to have a defined by type and a rel nests at the same time. Using parenting for types is the more common operation, whereas nesting is a less frequent operation.
2019-09-29 22:41:26 +10:00
Dion Moult 2f2c40406f Implement support for window attributes 2019-09-29 22:29:06 +10:00
Dion Moult a406f3d78a Implement support for door attributes 2019-09-29 22:12:51 +10:00
Dion Moult 22d35cf89a Fix placement rel to for nested elements for a start. 2019-09-28 23:43:50 +10:00
Dion Moult 8e2723951d Fix #670 - fix compilation with OCE and C++11 range based for loop 2019-09-28 23:14:08 +10:00
Dion Moult 4d4c111d5f Implement nested relationships between elements 2019-09-28 14:08:09 +10:00
Dion Moult 0c294a58bf Implement support for material constituent sets 2019-09-28 12:41:51 +10:00
Dion Moult 81864def9e Implement support for material layer sets 2019-09-28 10:54:10 +10:00
Thomas Krijnen 6771c91224 Remove duplicate swig dependency statement 2019-09-27 15:45:48 +02:00
Thomas Krijnen 596e13b24c Add null check on trimmed curve 2019-09-27 15:12:35 +02:00
Dion Moult a07c2cb1f8 Minor fix to packaging 2019-09-27 08:43:49 +10:00
Thomas Krijnen ae6dfce7e3 Add an excemption for the requirement of boolean op result to be manifold 2019-09-26 15:14:23 +02:00
Dion Moult 1f371f3319 Create Blender export plugin 2019-09-26 21:55:30 +10:00
Dion Moult a41e7fc298 Add SVG sectioning utility 2019-09-26 07:37:08 +10:00
Dion Moult 739c5fb326 Roundtrip export of swept solid for basic extrusions for programs like Revit 2019-09-20 09:15:32 +10:00
Dion Moult 8b40b9944f Provide support for center of gravity representations 2019-09-18 11:30:07 +10:00
Dion Moult 19d587d17c Allow generated mesh representations such as bounding box 2019-09-17 12:56:43 +10:00
Dion Moult 45678c8536 Merge branch 'v0.6.0' of https://github.com/IfcOpenShell/IfcOpenShell into v0.6.0 2019-09-17 11:21:05 +10:00
Dion Moult c21c9c24f8 Handle materials which don't have nodes 2019-09-17 11:20:22 +10:00
Dion Moult 32588c63eb Bump readme with new features 2019-09-16 19:36:44 +10:00
Dion Moult 611f0e7248 Minor fixes to representation detection 2019-09-16 17:25:00 +10:00
Dion Moult 2d408eb985 Add support for footprint and reference subcontexts 2019-09-16 16:53:34 +10:00
Dion Moult ac166691c4 Allow support for clearance geometry 2019-09-16 16:47:48 +10:00
Dion Moult 7516177304 Add support for multiple representations such as body and axis 2019-09-16 16:28:26 +10:00
Birger Brekke f8d713a412 fixup! Use model-offset in IfcGeom::Kernel and add model-rotation 2019-09-16 07:54:10 +02:00
Dion Moult 6d36ee3f53 Relate documents and classifications to project itself 2019-09-16 13:16:58 +10:00
Birger Brekke e6606e363a Use model-offset in IfcGeom::Kernel and add model-rotation
Applying model-offset in IfcGeom::Kernel makes it work
independently of the serializer.

`model-rotation` was also added to support rotation in the same
manner as `model-offset` supports offset.
2019-09-13 16:09:11 +02:00
Dion Moult dee8af6ec9 Implement associations to qualitative objective constraints 2019-09-11 16:50:27 +10:00
Dion Moult 00af240915 Implement rel associate classifications for objects and types 2019-09-11 14:47:53 +10:00
Dion Moult 730057ed4d Allow objects and types to be associated with external documents 2019-09-11 12:44:36 +10:00
Dion Moult 675ba205ef Bump readme with new features 2019-09-11 09:23:02 +10:00
Dion Moult 9ab13a3e0c Maintain GlobalIds for type products 2019-09-10 20:11:58 +10:00
Dion Moult 9b7ea1e83c Allow for psets to be assigned to types, and pset overrides 2019-09-10 20:11:37 +10:00
Dion Moult 2c84a07bdc Don't hardcode unit definitions 2019-09-10 17:08:45 +10:00
Dion Moult dd1ddfcd8e Merge branch 'v0.6.0' of https://github.com/IfcOpenShell/IfcOpenShell into v0.6.0 2019-09-10 05:26:43 +01:00
Dion Moult cd21611646 Define diffuse colour, and give possibility for externally defined material URI 2019-09-10 14:18:50 +10:00
Dion Moult 360767a6eb Bump feature list 2019-09-09 22:00:12 +10:00
Dion Moult 2bf89f11c8 Minor code cleanup 2019-09-09 15:11:32 +10:00
Dion Moult 018123aa21 Export basic material information 2019-09-09 15:11:07 +10:00
Dion Moult 0bf149c894 Fix minor bug where libraries don't exist 2019-09-09 12:48:42 +10:00
Dion Moult b0797db321 Maintain GlobalIds for projects and spatial structures 2019-09-08 20:51:59 +10:00
Dion Moult 58e870d185 Relate objects to psets 2019-09-08 19:02:00 +10:00
Dion Moult 70ec98a9e0 Add ability to detect data types from property set templates so that psets are easier to insert 2019-09-08 18:30:16 +10:00
Dion Moult 22bb5cc276 Relate types to their respective project library 2019-09-08 14:55:23 +10:00
Dion Moult cecb623e76 Prevent unnecessary duplicate creation of the same representation 2019-09-08 11:24:41 +10:00
Dion Moult 04aa0ad04d Support IfcProjectLibrary as related to IfcProject 2019-09-08 11:07:40 +10:00
Dion Moult 58be8e95b0 Bump readme with new features 2019-09-07 22:32:41 +10:00
Dion Moult 5f8a792cf4 Allow the creation and storage of map conversions and CRSes 2019-09-07 22:27:52 +10:00
Dion Moult 5dbbe174de Allow wireframe geometry exports 2019-09-07 08:05:42 +10:00
Dion Moult 9908e5cf05 Clean up trailing whitespace 2019-09-07 08:04:49 +10:00
Dion Moult 3d11a98eef Fix #665 - Display curves too, not just solid elements 2019-09-07 07:40:16 +10:00
Dion Moult 5ce8917c82 Allow type definitions which have no representation, to be used as simply ways to inherit properties 2019-09-05 21:38:52 +10:00
Dion Moult 9c11e6bd09 Update readme with new features 2019-09-05 18:50:32 +10:00
Dion Moult dd3df2258d Allow settings to toggle export of representations and quantities 2019-09-05 17:18:13 +10:00
Dion Moult 826280f35c Add support for multiple collection instances 2019-09-05 12:04:34 +10:00
Dion Moult 5536bd5d59 Minor fix where qto calculator wasn't passed in, whoops 2019-09-05 12:03:07 +10:00
Krzysztof Trzciński 90bf32c342 Fix reusing meshes and mesh naming 2019-09-05 07:14:08 +10:00
Dion Moult d917e738db Merge pull request #662 from elmopl/blender_ifc_280rc1
Fix reusing meshes and mesh naming
2019-09-05 07:13:16 +10:00
Krzysztof Trzciński 42307972a8 Fix reusing meshes and mesh naming 2019-09-04 21:02:47 +01:00
Dion Moult bd9aa18053 Record and remember globalids between exports 2019-09-04 17:46:58 +10:00
Dion Moult 3074242aa0 Add basic support for some forms of quantity take-off 2019-09-04 16:53:10 +10:00
Dion Moult 684e687b6a Simplify unnecessary code to get representations 2019-09-04 11:58:18 +10:00
Krzysztof Trzciński 1dff84ace3 Fix clash of mesh names (fixes #661) 2019-09-04 09:01:09 +10:00
Krzysztof Trzciński 99d8e96a35 Add support for collections 2019-09-04 09:01:00 +10:00
Krzysztof Trzciński c3a3cbee3f Fix filename -> ifcopenshell.file 2019-09-04 09:00:41 +10:00
Krzysztof Trzciński 748f826418 Introduce defaultdict instead of checks 2019-09-04 08:58:48 +10:00
Dion Moult 032a4743ac Merge pull request #641 from elmopl/blender_ifc_280rc1
Blender ifc 2.80rc1 collections enhancement
2019-09-04 08:55:46 +10:00
Krzysztof Trzciński 7c99294ba8 Fix clash of mesh names (fixes #661) 2019-09-03 17:57:39 +01:00
Dion Moult 1665d8e0f6 Merge remote-tracking branch 'blender-bim-ifc/master' into v0.6.0 2019-09-03 21:06:15 +10:00
Dion Moult 6e9f24af66 Move to subdir 2019-09-03 21:02:57 +10:00
Dion Moult 359b55aeab Add feature about IfcRelAggregates to readme 2019-09-03 20:55:10 +10:00
Dion Moult b1dda0a679 Support element decomposition through IfcRelAggregates 2019-09-03 20:52:22 +10:00
Dion Moult a7286e5527 Add a timer for export times 2019-09-03 20:51:58 +10:00
Dion Moult c055a8e9e8 Allow objects to be an arbitrary collection as long as some parent is part of the spatial tree 2019-09-03 20:51:39 +10:00
Dion Moult 8c0a24c463 Add screenshots 2019-09-02 21:38:14 +10:00
Dion Moult 164c249a48 Add instruction about adding to path 2019-09-02 21:28:53 +10:00
Dion Moult adb3a08638 Bump readme with demo blend file 2019-09-02 21:27:24 +10:00
Dion Moult cba28fbb72 Minor fix to template so that it isn't syntatically incorrect, at least.
We'll fix the hardcoded variables later.
2019-09-02 21:18:22 +10:00
Dion Moult 4de35bc252 Fix missing data for type products 2019-09-02 21:16:21 +10:00
Dion Moult 27407b8642 Parse array modifiers and create instances. Take into account local vs global rotation. 2019-09-02 19:43:55 +10:00
Dion Moult 3490b1b388 Report exceptions about spatial structure 2019-09-02 19:43:11 +10:00
Dion Moult 46c5cd4ee2 Describe newly coded features in readme 2019-09-01 22:17:49 +10:00
Dion Moult 73b387011d Add example pset 2019-09-01 22:03:40 +10:00
Dion Moult 931b00d651 Add types schema 2019-09-01 22:03:33 +10:00
Dion Moult c461a483b3 Now allow the creation of psets in a crude form 2019-09-01 22:03:02 +10:00
Dion Moult 36a74a212c Only parse selected types, not all types in the type collection 2019-09-01 19:30:58 +10:00
Dion Moult 291a54d07e Support IfcRelDefinesByType 2019-09-01 18:40:20 +10:00
Dion Moult 6a5bedc02e Support exporting product types 2019-09-01 17:23:48 +10:00
Dion Moult e11d4e4e4c Support custom attributes for products 2019-09-01 13:22:26 +10:00
Dion Moult fdb6af4ce3 Clean up files I should've put in gitignore 2019-09-01 11:46:11 +10:00
Dion Moult 1c28055afe Support object instancing, so product representations are reused if the mesh data is the same 2019-09-01 11:45:32 +10:00
Dion Moult 72fa983e81 Allow export of any product class 2019-09-01 11:21:24 +10:00
Dion Moult bb29a493c7 Don't hardcode spatial structure elements. Make a sensible assumption instead that all collections are either contexts or spatial structures. 2019-09-01 10:33:06 +10:00
Dion Moult 1c647c5365 Print errors in case the name cannot be detected 2019-09-01 10:32:22 +10:00
Dion Moult 6b53ebdc5e Hardcode context names, since there are unlikely to be many 2019-09-01 10:27:05 +10:00
Dion Moult c2cb11c594 Remove useless function 2019-09-01 10:26:54 +10:00
Dion Moult 153d6fe337 Use an IFC4 template. Don't let 2X3 hold us back! 2019-09-01 10:26:33 +10:00
Dion Moult 11e187fc76 We don't need this ifc_schema class, it seems 2019-09-01 10:14:31 +10:00
Dion Moult fa38317438 Whitespace cleanup 2019-09-01 09:45:57 +10:00
Dion Moult 7c2d640106 Refactor representation creation into its own function 2019-09-01 09:44:06 +10:00
Dion Moult 64b23393a0 Remove unnecessary comment 2019-09-01 09:43:36 +10:00
Dion Moult ae9fce8c45 Support dynamic contexts and trees of spatial structures 2019-08-31 23:51:53 +10:00
Dion Moult bd35a9924e Refactor into a class. It's gonna get big! 2019-08-31 17:37:53 +10:00
Dion Moult 2f4e82e0b9 Rename to sensible name 2019-08-31 17:16:16 +10:00
Dion Moult e9649a5217 Basic geometry export 2019-08-29 23:11:12 +10:00
gpioto 98f4c8518e Casting default timestamp template to integer
The documentation of IFC indicates that the timestamp must be of type Integer. (https://standards.buildingsmart.org/IFC/DEV/IFC4_2/FINAL/HTML/link/ifctimestamp.htm)
If not, it cause some problems importing the generated IFC file in some platforms
2019-08-28 09:01:13 +02:00
Thomas Krijnen 75b24c2352 Put maximum length on layerset wall end point intersection 2019-08-21 11:59:30 +02:00
Thomas Krijnen 16ce1f0823 Make sure layerset fold is parallel to other wall axis curve 2019-08-16 10:42:48 +02:00
Thomas Krijnen af1853de04 Iterative epsilon in faceset helper 2019-08-09 17:48:56 +02:00
Thomas Krijnen b3711ad8cb thread_local define for clang 2019-08-09 10:05:49 +02:00
Krzysztof Trzciński e450101a12 Add support for collections 2019-07-16 19:31:16 +01:00
Krzysztof Trzciński 3f3b548d74 Fix filename -> ifcopenshell.file 2019-07-16 18:33:54 +01:00
Krzysztof Trzciński 6284b3960d Introduce defaultdict instead of checks 2019-07-16 18:30:03 +01:00
595 changed files with 267774 additions and 55436 deletions
+8
View File
@@ -0,0 +1,8 @@
c14f5eeca042232025797990396232e4feab53e7
d6881e833da0b6278313870d37d42ca6ece8686a
892be5444c5bd01a601c99243ac8d3e7b2f0e779
d169a964dd7e9ab5c98b35a82bcbc76dc6229a7a
4a6ec11f6f84a3d1fed2ee9b2f85d783ac3daa9d
2c9d6a47f4d24a923069775206bf734feeb14830
8f1743ed64a2a52c201a1ef5e312b4d3a7a922cf
ad7f030344c405e10cfa7d5cf06d82c121eeb825
+3
View File
@@ -0,0 +1,3 @@
# These are supported funding model platforms
github: [aothms]
+11
View File
@@ -12,3 +12,14 @@ __pycache__
.vscode
# PyCharm files
.idea
# Docs
/docs/output
/docs/rst_files
/docs/doxygen
/src/ifcblenderexport/docs/_build
# gettext binary translation files
*.mo
# Vim
*.swp
+9 -9
View File
@@ -1,7 +1,7 @@
language: cpp
compiler: gcc
os: linux
dist: xenial
dist: bionic
sudo: required
before_install:
@@ -17,11 +17,11 @@ install:
build-essential cmake python2.7 libpython2.7-dev swig zlib1g liblzma5 opencollada-dev wget apt-transport-https
- sudo mkdir -p /usr/include/json/nlohmann/
- sudo wget https://github.com/nlohmann/json/releases/download/v3.6.1/json.hpp -O /usr/include/json/nlohmann/json.hpp
- sudo sh -c 'curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -'
- sudo sh -c 'curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > /etc/apt/sources.list.d/dart_stable.list'
- sudo apt-get update -qq && sudo apt-get install -y dart
- export PATH=$PATH:/usr/lib/dart/bin:$HOME/.pub-cache/bin
- git clone https://github.com/KhronosGroup/glTF-Validator && pushd glTF-Validator && pub get && pub global activate --source path ./ && popd
# - sudo sh -c 'curl https://dl-ssl.google.com/linux/linux_signing_key.pub | apt-key add -'
# - sudo sh -c 'curl https://storage.googleapis.com/download.dartlang.org/linux/debian/dart_stable.list > /etc/apt/sources.list.d/dart_stable.list'
# - sudo apt-get update -qq && sudo apt-get install -y dart
# - export PATH=$PATH:/usr/lib/dart/bin:$HOME/.pub-cache/bin
# - git clone https://github.com/KhronosGroup/glTF-Validator && pushd glTF-Validator && pub get && pub global activate --source path ./ && popd
script:
- pwd
@@ -36,7 +36,7 @@ script:
-DPYTHON_INCLUDE_DIR=/usr/include/python2.7 \
-DPYTHON_EXECUTABLE=/usr/bin/python2.7 \
-DLIBXML2_INCLUDE_DIR=/usr/include/libxml2 \
-DLIBXML2_LIBRARIES="/usr/lib/x86_64-linux-gnu/libxml2.a;/lib/x86_64-linux-gnu/libz.so.1;/lib/x86_64-linux-gnu/liblzma.so.5;/usr/lib/x86_64-linux-gnu/libicuuc.so.55;/usr/lib/x86_64-linux-gnu/libicudata.so.55" \
-DLIBXML2_LIBRARIES="/usr/lib/x86_64-linux-gnu/libxml2.so;/lib/x86_64-linux-gnu/libz.so.1;/lib/x86_64-linux-gnu/liblzma.so.5;/usr/lib/x86_64-linux-gnu/libicuuc.so.60;/usr/lib/x86_64-linux-gnu/libicudata.so.60" \
-DGLTF_SUPPORT=On \
-DJSON_INCLUDE_DIR=/usr/include/json \
..
@@ -48,9 +48,9 @@ script:
- cd input
- /usr/local/bin/IfcConvert -yv acad2010_walls.ifc acad2010_walls.glb
- gltf_validator acad2010_walls.glb
# - gltf_validator acad2010_walls.glb
- python -c "from __future__ import print_function; from io import open; import ifcopenshell; f = ifcopenshell.open('encoding.ifc'); print(f[1][0], file=open('encoding.txt', 'w', encoding='utf-8'))" && grep "'a' 1m³ ≤ 5m³ ≥ 10m³" encoding.txt
- /usr/bin/python2.7 -c "from __future__ import print_function; from io import open; import ifcopenshell; f = ifcopenshell.open('encoding.ifc'); assert list(map(ord, f[1][0])) == [39, 97, 39, 32, 49, 109, 179, 32, 8804, 32, 53, 109, 179, 32, 8805, 32, 49, 48, 109, 179]"
- |
(for i in *.ifc; do \
+7 -5
View File
@@ -7,7 +7,7 @@ For more information, see
* [http://ifcopenshell.org](http://ifcopenshell.org)
* [http://academy.ifcopenshell.org](http://academy.ifcopenshell.org)
[![Build Status](https://api.travis-ci.org/IfcOpenShell/IfcOpenShell.png)](https://api.travis-ci.org/IfcOpenShell/IfcOpenShell)
[![Build Status](https://travis-ci.org/IfcOpenShell/IfcOpenShell.svg?branch=v0.6.0)](https://travis-ci.org/IfcOpenShell/IfcOpenShell)
Prerequisites
-------------
@@ -46,6 +46,8 @@ Instructions in a nutshell (**assuming Visual Studio 2015 x64 environment variab
> build-deps.cmd
> run-cmake.bat
NB: `build-deps.cmd` need to be ran from the directory containing it, i.e. the `./win` folder.
You can now open and build the solution file in Visual Studio:
> ..\build-vs2015-x64\IfcOpenShell.sln
@@ -156,7 +158,7 @@ Usage examples
**Using the IfcOpenShell Python interface**
$ wget -O duplex.zip http://projects.buildingsmartalliance.org/files/?artifact_id=4278
$ wget -O duplex.zip https://portal.nibs.org/files/wl/?id=4DsTgHFQAcOXzFetxbpRCECPbbfUqpgo
$ unzip duplex.zip
$ python
>>> import ifcopenshell
@@ -216,9 +218,9 @@ Usage examples
>>> f.write("out.ifc")
[LGPL]: https://github.com/IfcOpenShell/IfcOpenShell/tree/master/COPYING "LGPL"
[IFC]: http://www.buildingsmart-tech.org/specifications/ifc-overview "IFC"
[IFC2x3 TC1]: http://www.buildingsmart-tech.org/specifications/ifc-releases/ifc2x3-tc1-release "IFC2x3 TC1"
[IFC4 Add1]: http://www.buildingsmart-tech.org/specifications/ifc-releases/ifc4-add1-release "IFC4 Add1"
[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"
[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"
+25 -5
View File
@@ -36,6 +36,7 @@ OPTION(IFCXML_SUPPORT "Build IfcParse with ifcXML support (requires libxml2)." O
OPTION(ENABLE_BUILD_OPTIMIZATIONS "Enable certain compiler and linker optimizations on RelWithDebInfo and Release builds." OFF)
OPTION(IFCCONVERT_DOUBLE_PRECISION "IfcConvert: Use double precision floating-point numbers." ON)
OPTION(BUILD_IFCGEOM "Build IfcGeom." ON)
OPTION(BUILD_DOCUMENTATION "Build IfcOpenShell Documentation." OFF)
OPTION(BUILD_IFCPYTHON "Build IfcPython." ON)
OPTION(BUILD_EXAMPLES "Build example applications." ON)
OPTION(BUILD_GEOMSERVER "Build IfcGeomServer executable." ON)
@@ -49,6 +50,7 @@ endif()
if (${BUILD_CONVERT})
OPTION(GLTF_SUPPORT "Build IfcConvert with glTF support (requires json.hpp)." OFF)
endif()
OPTION(USERSPACE_PYTHON_PREFIX "Installs IfcPython for the current user only instead of system-wide." OFF)
# TODO QtViewer is deprecated ATM as it uses the 0.4 API
# OPTION(BUILD_QTVIEWER "Build IfcOpenShell Qt GUI Viewer (requires Qt 4 framework)." OFF)
@@ -142,6 +144,14 @@ IF(WIN32 AND ("$ENV{CONDA_BUILD}" STREQUAL ""))
SET(Boost_USE_STATIC_LIBS ON)
SET(Boost_USE_STATIC_RUNTIME ON)
SET(Boost_USE_MULTITHREADED ON)
# Disable Boost's autolinking as the libraries to be linked to are supplied
# already by CMake, and wrong libraries would be asked for when code is
# compiled with a toolset different from default.
if(MSVC)
ADD_DEFINITIONS(-DBOOST_ALL_NO_LIB)
# Necessary for boost version >= 1.67
SET(BCRYPT_LIBRARIES "bcrypt.lib")
ENDIF()
ELSE()
# Disable Boost's autolinking as the libraries to be linked to are supplied
# already by CMake, and it's going to conflict if there are multiple, as is
@@ -208,6 +218,10 @@ endfunction()
if(BUILD_IFCGEOM)
IF(MSVC)
add_debug_variants(LIBXML2_LIBRARIES "${LIBXML2_LIBRARIES}" d)
ENDIF()
# Find Open CASCADE
IF("${OCC_INCLUDE_DIR}" STREQUAL "")
SET(OCC_INCLUDE_DIR "/usr/include/oce/" CACHE FILEPATH "Open CASCADE header files")
@@ -227,7 +241,7 @@ ENDIF()
SET(OPENCASCADE_LIBRARY_NAMES
TKernel TKMath TKBRep TKGeomBase TKGeomAlgo TKG3d TKG2d TKShHealing TKTopAlgo TKMesh TKPrim TKBool TKBO
TKFillet TKSTEP TKSTEPBase TKSTEPAttr TKXSBase TKSTEP209 TKIGES TKOffset
TKFillet TKSTEP TKSTEPBase TKSTEPAttr TKXSBase TKSTEP209 TKIGES TKOffset TKHLR
)
IF("${OCC_LIBRARY_DIR}" STREQUAL "")
@@ -459,7 +473,7 @@ function(files_for_ifc_version IFC_VERSION RESULT_NAME)
)
endfunction()
set(SCHEMA_VERSIONS "2x3" "4" "4x1" "4x2")
set(SCHEMA_VERSIONS "2x3" "4" "4x1" "4x2" "4x3_rc1")
if(COMPILE_SCHEMA)
# @todo, this appears to be untested at the moment
@@ -543,7 +557,7 @@ file(GLOB IFCPARSE_CPP_FILES ../src/ifcparse/*.cpp)
set(IFCPARSE_FILES ${IFCPARSE_CPP_FILES} ${IFCPARSE_H_FILES})
add_library(IfcParse ${IFCPARSE_FILES})
set_target_properties(IfcParse PROPERTIES COMPILE_FLAGS -DIFC_PARSE_EXPORTS)
set_target_properties(IfcParse PROPERTIES COMPILE_FLAGS -DIFC_PARSE_EXPORTS VERSION "0.6.0" SOVERSION "0.6")
TARGET_LINK_LIBRARIES(IfcParse ${Boost_LIBRARIES} ${BCRYPT_LIBRARIES} ${LIBXML2_LIBRARIES})
@@ -566,7 +580,7 @@ file(GLOB SCHEMA_AGNOSTIC_CPP_FILES ../src/ifcgeom_schema_agnostic/*.cpp)
set(SCHEMA_AGNOSTIC_FILES ${SCHEMA_AGNOSTIC_H_FILES} ${SCHEMA_AGNOSTIC_CPP_FILES})
add_library(IfcGeom ${SCHEMA_AGNOSTIC_FILES})
set_target_properties(IfcGeom PROPERTIES COMPILE_FLAGS -DIFC_GEOM_EXPORTS)
set_target_properties(IfcGeom PROPERTIES COMPILE_FLAGS -DIFC_GEOM_EXPORTS VERSION "0.6.0" SOVERSION "0.6")
if (UNIX)
find_package(Threads)
@@ -593,7 +607,7 @@ foreach(s ${SCHEMA_VERSIONS})
endforeach()
add_library(Serializers ${SERIALIZERS_FILES})
set_target_properties(Serializers PROPERTIES COMPILE_FLAGS "-DIFC_GEOM_EXPORTS ${CONVERT_PRECISION}")
set_target_properties(Serializers PROPERTIES COMPILE_FLAGS "-DIFC_GEOM_EXPORTS ${CONVERT_PRECISION}" VERSION "0.6.0" SOVERSION "0.6")
TARGET_LINK_LIBRARIES(Serializers ${SERIALIZER_SCHEMA_LIBRARIES})
@@ -642,6 +656,12 @@ INSTALL(TARGETS IfcGeomServer
endif()
# Documentation
IF(BUILD_DOCUMENTATION)
set(CMAKE_MODULE_PATH "../docs/cmake")
ADD_SUBDIRECTORY(../docs docs)
ENDIF()
IF(BUILD_IFCPYTHON)
ADD_SUBDIRECTORY(../src/ifcwrap ifcwrap)
ENDIF()
+40
View File
@@ -0,0 +1,40 @@
#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)
find_package(Doxygen REQUIRED)
#find_package(Sphinx REQUIRED)
set(SPHINX_SOURCE ${CMAKE_CURRENT_SOURCE_DIR})
set(SPHINX_BUILD ${CMAKE_CURRENT_BINARY_DIR}/docs/sphinx)
MESSAGE(STATUS "SPHINX BUILD ${CMAKE_CURRENT_BINARY_DIR}")
file(MAKE_DIRECTORY ./output/doxygen)
if (DOXYGEN_FOUND)
add_custom_target(Sphinx ALL
COMMAND
${SPHINX_EXECUTABLE} -v -T -b html
${SPHINX_SOURCE} ${CMAKE_CURRENT_SOURCE_DIR}/output
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/output
COMMENT "Generating documentation with Sphinx")
# add_custom_target(ifcopenshell_python_docs ALL
# COMMAND make html
# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../src/ifcblenderexport/docs
# OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/../src/ifcblenderexport/docs
# COMMENT "Generating documentation with Sphinx")
else (DOXYGEN_FOUND)
message("Doxygen need to be installed to generate the doxygen documentation")
endif (DOXYGEN_FOUND)
+2531
View File
File diff suppressed because it is too large Load Diff
+11
View File
@@ -0,0 +1,11 @@
#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)
+11
View File
@@ -0,0 +1,11 @@
#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)
+48
View File
@@ -0,0 +1,48 @@
import textwrap
# The `extensions` list should already be in here from `sphinx-quickstart`
extensions = [
# there may be others here already, e.g. 'sphinx.ext.mathjax'
'breathe',
'exhale',
'sphinx.ext.intersphinx'
]
project = 'IfcOpenShell'
copyright = '2020, IfcOpenShell'
author = ''
# Setup the breathe extension
breathe_projects = {
"My Project": "./output/doxygen/xml"
}
breathe_default_project = "My Project"
# Setup the exhale extension
exhale_args = {
# These arguments are required
"containmentFolder": "./rst_files",
"rootFileName": "library_root.rst",
"rootFileTitle": "IfcOpenShell",
"doxygenStripFromPath": "..",
# Suggested optional arguments
"createTreeView": True,
# TIP: if using the sphinx-bootstrap-theme, you need
# "treeViewIsBootstrap": True,
"exhaleExecutesDoxygen": True,
# "exhaleDoxygenStdin": "INPUT = ../src/serializers/ ../src/ifcgeom",
"exhaleUseDoxyfile": True
}
# html_theme = 'sphinx_rtd_theme'
# # Tell sphinx what the primary language being documented is.
# primary_domain = 'cpp'
# # Tell sphinx what the pygments highlight language should be.
# highlight_language = 'cpp'
+52
View File
@@ -0,0 +1,52 @@
# This program requires doxygen, sphinx, breathe and exhale.
import os
import os.path
import subprocess
from sys import platform
def copy_content(content, container):
with open(content) as f:
with open(container, "w") as f1:
for line in f:
f1.write(line)
conf_path = "./conf.py"
index_path = "./index.rst"
if not os.path.isdir("./output/doxygen/xml"):
os.makedirs("output/doxygen/xml")
if os.path.isfile(conf_path) and not os.path.isfile(index_path):
os.remove(conf_path)
if os.path.isfile(index_path) and not os.path.isfile(conf_path):
os.remove(index_path)
if not (os.path.isfile(conf_path) and os.path.isfile(index_path)):
subprocess.run(["sphinx-quickstart", "-q", "-p", "IfcOpenShell"])
conf_copy = ["./conf_to_copy.py", "./conf.py"]
index_copy = ["./index_to_copy.rst", "./index.rst"]
copy_content(conf_copy[0], conf_copy[1])
copy_content(index_copy[0], index_copy[1])
if platform == "linux" or platform == "linux2":
subprocess.run(["make", "html"])
if not os.path.isdir("/output/_build"):
subprocess.run(["cd","../src/ifcblenderexport/docs"])
subprocess.run(["make", "html"])
subprocess.run(["cd", "../../../docs"])
subprocess.run(["mv" "../src/ifcblenderexport/docs/_build", "./output"])
elif platform == "win32" or platform == "win64":
subprocess.run(["make.bat", "html"])
Binary file not shown.

After

Width:  |  Height:  |  Size: 16 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 20 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 14 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 120 KiB

+240
View File
@@ -0,0 +1,240 @@
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
![Image of d1.dae](images/settings-1.png)
Duplex_A_20110907_optimized.ifc d2.dae --enable-layerset-slicing -yv --include attribute GlobalId 2O2Fr$t4X7Zf8NOew3FNr2
![Image of d2.dae](images/settings-2.png)
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
![Image of d1.dae](images/settings-1.png)
Duplex_A_20110907_optimized.ifc d3.dae --disable-opening-subtraction -yv --include attribute GlobalId 2O2Fr$t4X7Zf8NOew3FNr2
![Image of d3.dae](images/settings-3.png)
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
![Image of d4.dae](images/settings-4.png)
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
![Image of d5.dae with a UV grid applied in Blender](images/settings-5.png)
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
()
+10
View File
@@ -0,0 +1,10 @@
IfcOpenShell
============
.. toctree::
:maxdepth: 3
rst_files/library_root
`ifcopenshell-python documentation <_build/html/index.html>`_
+10
View File
@@ -0,0 +1,10 @@
IfcOpenShell
============
.. toctree::
:maxdepth: 3
rst_files/library_root
`ifcopenshell-python documentation <_build/html/index.html>`_
+54 -49
View File
@@ -23,11 +23,14 @@
# This script builds IfcOpenShell and its dependencies #
# #
# Prerequisites for this script to function correctly: #
# * git * bzip2 * tar * c(++) compilers * yacc * autoconf #
# * cmake * git * bzip2 * tar * c(++) compilers * yacc * autoconf #
# #
# if building with USE_OCCT additionally: #
# * freetype * glx.h #
# #
# if building with OCCT 7.4.0 additionally: #
# * libfontconfig1-dev #
# #
# if building with -shared #
# * libgl1-mesa-dev libxext-dev libxmu-dev libxmu-headers libxi-dev #
# #
@@ -35,15 +38,15 @@
# * libffi(-dev[el]) #
# #
# on debian 7.8 these can be obtained with: #
# $ apt-get install git gcc g++ autoconf bison bzip2 #
# libfreetype6-dev mesa-common-dev libffi-dev #
# $ apt-get install git gcc g++ autoconf bison bzip2 cmake #
# libfreetype6-dev mesa-common-dev libffi-dev libfontconfig1-dev #
# #
# on ubuntu 14.04: #
# $ apt-get install git gcc g++ autoconf bison make #
# libfreetype6-dev mesa-common-dev libffi-dev #
# $ apt-get install git gcc g++ autoconf bison make cmake #
# libfreetype6-dev mesa-common-dev libffi-dev libfontconfig1-dev #
# #
# on OS X El Capitan with homebrew: #
# $ brew install git bison autoconf automake freetype libffi #
# $ brew install git bison autoconf automake freetype libffi cmake #
# #
###############################################################################
@@ -76,7 +79,7 @@ ch.setLevel(logging.INFO)
logger.addHandler(ch)
PROJECT_NAME="IfcOpenShell"
PYTHON_VERSIONS=["2.7.16", "3.2.6", "3.3.6", "3.4.6", "3.5.3", "3.6.2", "3.7.3"]
PYTHON_VERSIONS=["2.7.16", "3.2.6", "3.3.6", "3.4.6", "3.5.3", "3.6.2", "3.7.3", "3.8.6", "3.9.1"]
JSON_VERSION="v3.6.1"
OCE_VERSION="0.18"
# OCCT_VERSION="7.1.0"
@@ -84,13 +87,11 @@ OCE_VERSION="0.18"
# OCCT_VERSION="7.2.0"
# OCCT_HASH="88af392"
OCCT_VERSION="7.3.0p3"
BOOST_VERSION="1.59.0"
BOOST_VERSION="1.71.0"
#PCRE_VERSION="8.39"
PCRE_VERSION="8.41"
#LIBXML2_VERSION="2.9.3"
LIBXML2_VERSION="2.9.9"
CMAKE_VERSION="3.4.1"
#CMAKE_VERSION="3.14.5"
SWIG_VERSION="3.0.12"
#SWIG_VERSION="4.0.0"
#OPENCOLLADA_VERSION="v1.6.63"
@@ -156,6 +157,13 @@ TOOLSET = None
if get_os() == "Darwin":
# C++11 features used in OCCT 7+ need a more recent stdlib
TOOLSET = "10.9" if USE_OCCT else "10.6"
# python 3.4 doesn't seem to build anymore on recent versions of clang
if get_os() == "Darwin":
try:
PYTHON_VERSIONS.remove("3.4.6")
except ValueError as e:
pass
try:
IFCOS_NUM_BUILD_PROCS = os.environ["IFCOS_NUM_BUILD_PROCS"]
@@ -225,7 +233,6 @@ dependency_tree = {
'boost': (),
'libxml2': (),
'python': (),
'swig': (),
'occ': (),
'pcre': (),
'json': ()
@@ -257,7 +264,7 @@ print("Building:", *sorted(targets, key=lambda t: len(list(v(t)))))
# Check that required tools are in PATH
for cmd in [git, bunzip2, tar, cc, cplusplus, autoconf, automake, yacc, make, "patch"]:
for cmd in [git, bunzip2, tar, cc, cplusplus, autoconf, automake, yacc, make, "patch", "cmake"]:
if which(cmd) is None:
raise ValueError("Required tool '%s' not installed or not added to PATH" % (cmd,))
@@ -301,10 +308,9 @@ def run(cmds, cwd=None):
return stdout.strip()
BOOST_VERSION_UNDERSCORE=BOOST_VERSION.replace(".", "_")
CMAKE_VERSION_2=CMAKE_VERSION[:CMAKE_VERSION.rindex('.')]
OCE_LOCATION="https://github.com/tpaviot/oce/archive/OCE-%s.tar.gz" % (OCE_VERSION,)
BOOST_LOCATION="http://downloads.sourceforge.net/project/boost/boost/%s/boost_%s.tar.bz2" % (BOOST_VERSION, BOOST_VERSION_UNDERSCORE)
BOOST_LOCATION="https://dl.bintray.com/boostorg/release/%s/source/" % (BOOST_VERSION,)
# Helper functions
@@ -320,8 +326,7 @@ def run_cmake(arg1, cmake_args, cmake_dir=None, cwd=None):
P=".."
else:
P=cmake_dir
cmake_path= os.path.join(DEPS_DIR, "install", "cmake-%s" % (CMAKE_VERSION,), "bin", "cmake")
run([cmake_path, P]+cmake_args+["-DCMAKE_BUILD_TYPE=%s" % (BUILD_CFG,)], cwd=cwd)
run(["cmake", P]+cmake_args+["-DCMAKE_BUILD_TYPE=%s" % (BUILD_CFG,)], cwd=cwd)
def git_clone_or_pull_repository(clone_url, target_dir, revision=None):
"""Lazily clones the `git` repository denoted by `clone_url` into
@@ -422,7 +427,7 @@ def build_dependency(name, mode, build_tool_args, download_url, download_name, d
else:
raise ValueError()
logger.info("\rBuilding %s... " % (name,))
run([make, "-j%s" % (IFCOS_NUM_BUILD_PROCS,)], cwd=extract_build_dir)
run([make, "-j%s" % (IFCOS_NUM_BUILD_PROCS,), "VERBOSE=1"], cwd=extract_build_dir)
logger.info( "\rInstalling %s... " % (name,))
run([make, "install"], cwd=extract_build_dir)
logger.info( "\rInstalled %s \n" % (name,))
@@ -443,7 +448,10 @@ cecho("Collecting dependencies:", GREEN)
ADDITIONAL_ARGS=[]
BOOST_ADDRESS_MODEL=[]
if TARGET_ARCH == "i686" and run([uname, "-m"]).strip() == "x86_64":
ADDITIONAL_ARGS=["-m32", "-arch i386"]
if get_os() == "Darwin":
ADDITIONAL_ARGS=["-m32", "-arch i386"]
else:
ADDITIONAL_ARGS=["-m32"]
BOOST_ADDRESS_MODEL=["architecture=x86", "address-model=32"]
if get_os() == "Darwin":
@@ -482,25 +490,8 @@ os.environ["CFLAGS"] = CFLAGS
os.environ["LDFLAGS"] = LDFLAGS
# Some dependencies need a more recent CMake version than most distros provide
build_dependency(name="cmake-%s" % (CMAKE_VERSION,), mode="autoconf", build_tool_args=[], download_url="https://cmake.org/files/v%s" % (CMAKE_VERSION_2,), download_name="cmake-%s.tar.gz" % (CMAKE_VERSION,))
# Extract compiler flags from CMake to harmonize settings with other autoconf dependencies
CMAKE_FLAG_EXTRACT_DIR="ifcopenshell_cmake_test_%s" % (time.time(),)
# was sp.check_output([bash, "-c", "cat /dev/urandom | env LC_CTYPE=C tr -dc 'a-zA-Z0-9' | head -c 32"]), in bash script, unclear what the exact required format is and whether it's needed
if os.path.exists(CMAKE_FLAG_EXTRACT_DIR):
shutil.rmtree(CMAKE_FLAG_EXTRACT_DIR)
os.makedirs(CMAKE_FLAG_EXTRACT_DIR)
BUILD_CFG_UPPER=BUILD_CFG.upper()
for FL in ["C", "CXX"]:
run([bash, "-c", """echo "
message(\"\${CMAKE_%s_FLAGS_%s}\")
" > CMakeLists.txt""" % (FL, BUILD_CFG_UPPER)], cwd=CMAKE_FLAG_EXTRACT_DIR)
FL="%sFLAGS" % (FL,)
FLM="%sFLAGS_MINIMAL" % (FL,)
# @TODO: bash code unclear
# exec("%sFLAGS=%s" % (FL, sp.check_output([os.path.join(DEPS_DIR, "install", "cmake-%s" % (CMAKE_VERSION,), "bin", "cmake"), "."
# declare ${FL}FLAGS_MINIMAL="`$DEPS_DIR/install/cmake-$CMAKE_VERSION/bin/cmake . 2>&1 >/dev/null` ${!FLM}"
shutil.rmtree(CMAKE_FLAG_EXTRACT_DIR)
# @tfk: this is no longer needed
# build_dependency(name="cmake-%s" % (CMAKE_VERSION,), mode="autoconf", build_tool_args=[], download_url="https://cmake.org/files/v%s" % (CMAKE_VERSION_2,), download_name="cmake-%s.tar.gz" % (CMAKE_VERSION,))
if "json" in targets:
json_url = "https://github.com/nlohmann/json/releases/download/{JSON_VERSION}/json.hpp".format(**locals())
@@ -525,7 +516,7 @@ if "swig" in targets:
build_dependency(
name="swig",
mode="autoconf",
build_tool_args=["--with-pcre-prefix={DEPS_DIR}/install/pcre-{PCRE_VERSION}".format(**locals())],
build_tool_args=["--disable-ccache", "--with-pcre-prefix={DEPS_DIR}/install/pcre-{PCRE_VERSION}".format(**locals())],
download_url="https://github.com/swig/swig.git",
download_name="swig",
download_tool=download_tool_git,
@@ -540,11 +531,12 @@ if USE_OCCT and "occ" in targets:
"-DINSTALL_DIR={DEPS_DIR}/install/occt-{OCCT_VERSION}".format(**locals()),
"-DBUILD_LIBRARY_TYPE={LINK_TYPE_UCFIRST}".format(**locals()),
"-DBUILD_MODULE_Draw=0",
"-DBUILD_RELEASE_DISABLE_EXCEPTIONS=Off"
],
download_url = "https://git.dev.opencascade.org/repos/occt.git",
download_name = "occt",
download_tool=download_tool_git,
patch="./patches/occt/enable-exception-handling.patch",
patch=None if OCCT_VERSION >= "7.4" else "./patches/occt/enable-exception-handling.patch",
revision="V" + OCCT_VERSION.replace('.', '_')
)
elif "occ" in targets:
@@ -595,6 +587,7 @@ if "OpenCOLLADA" in targets:
download_url="https://github.com/KhronosGroup/OpenCOLLADA.git",
download_name="OpenCOLLADA",
download_tool=download_tool_git,
patch="./patches/opencollada/pr622_and_disable_subdirs.patch",
revision=OPENCOLLADA_VERSION
)
@@ -622,13 +615,19 @@ if "python" in targets:
yield v, unicode_conf, abi_tag
for PYTHON_VERSION, unicode_conf, abi_tag in PYTHON_VERSION_CONFS():
build_dependency(
"python-{PYTHON_VERSION}{abi_tag}".format(**locals()),
"autoconf",
PYTHON_CONFIGURE_ARGS + [unicode_conf],
"http://www.python.org/ftp/python/{PYTHON_VERSION}/".format(**locals()),
"Python-{PYTHON_VERSION}.tgz".format(**locals())
)
try:
build_dependency(
"python-{PYTHON_VERSION}{abi_tag}".format(**locals()),
"autoconf",
PYTHON_CONFIGURE_ARGS + [unicode_conf],
"http://www.python.org/ftp/python/{PYTHON_VERSION}/".format(**locals()),
"Python-{PYTHON_VERSION}.tgz".format(**locals())
)
except Exception as e:
pyver2 = PYTHON_VERSION[:PYTHON_VERSION.rfind('.')]
if os.path.exists("{DEPS_DIR}/install/python-{PYTHON_VERSION}{abi_tag}/bin/python{pyver2}".format(**locals())):
print("Installation partially failed")
else: raise e
os.environ["CXXFLAGS"]=OLD_CXX_FLAGS
os.environ["CFLAGS"]=OLD_C_FLAGS
@@ -652,7 +651,7 @@ if "boost" in targets:
list(map(str_concat("cxxflags"), CXXFLAGS.strip().split(' '))) + \
list(map(str_concat("linkflags"), LDFLAGS.strip().split(' '))) + \
["stage", "-s", "NO_BZIP2=1"],
download_url="http://downloads.sourceforge.net/project/boost/boost/{BOOST_VERSION}/".format(**locals()),
download_url=BOOST_LOCATION,
download_name="boost_{BOOST_VERSION_UNDERSCORE}.tar.bz2".format(**locals())
)
@@ -682,7 +681,8 @@ cmake_args=[
"-DCMAKE_INSTALL_PREFIX=" "{DEPS_DIR}/install/ifcopenshell".format(**locals()),
"-DBOOST_ROOT=" "{DEPS_DIR}/install/boost-{BOOST_VERSION}".format(**locals()),
"-DGLTF_SUPPORT=" "ON",
"-DJSON_INCLUDE_DIR=" "{DEPS_DIR}/install/json".format(**locals())
"-DJSON_INCLUDE_DIR=" "{DEPS_DIR}/install/json".format(**locals()),
"-DBoost_NO_BOOST_CMAKE=" "On"
]
if "occ" in targets and USE_OCCT:
@@ -738,10 +738,15 @@ if "IfcOpenShell-Python" in targets:
for PYTHON_VERSION, _, TAG in PYTHON_VERSION_CONFS():
logger.info("\rConfiguring python {PYTHON_VERSION}{TAG} wrapper...".format(**locals()))
python_dir = os.path.join(IFCOS_DIR, "python-{PYTHON_VERSION}{TAG}".format(**locals()))
# python_dir = os.path.join(IFCOS_DIR, "python-{PYTHON_VERSION}{TAG}".format(**locals()))
python_dir = os.path.join(IFCOS_DIR, "pythonwrapper")
if not os.path.exists(python_dir):
os.makedirs(python_dir)
cache_path = os.path.join(python_dir, "CMakeCache.txt")
if os.path.exists(cache_path):
os.unlink(cache_path)
PYTHON_LIBRARY=run([bash, "-c", "ls {DEPS_DIR}/install/python-{PYTHON_VERSION}{TAG}/lib/libpython*.*".format(**locals())])
PYTHON_INCLUDE=run([bash, "-c", "ls -d {DEPS_DIR}/install/python-{PYTHON_VERSION}{TAG}/include/python*".format(**locals())])
PYTHON_EXECUTABLE=os.path.join(DEPS_DIR, "install", "python-{PYTHON_VERSION}{TAG}".format(**locals()), "bin", "python{PYTHON_VERSION[0]}".format(**locals()))
@@ -0,0 +1,29 @@
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 95abbe21..293c951c 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -284,10 +284,10 @@ add_subdirectory(COLLADASaxFrameworkLoader)
add_subdirectory(COLLADAStreamWriter)
# building COLLADAValidator app
-add_subdirectory(COLLADAValidator)
+# add_subdirectory(COLLADAValidator)
# DAE validator app
-add_subdirectory(DAEValidator)
+# add_subdirectory(DAEValidator)
# Library export
install(EXPORT LibraryExport DESTINATION ${OPENCOLLADA_INST_CMAKECONFIG} FILE OpenCOLLADATargets.cmake)
diff --git a/GeneratedSaxParser/src/GeneratedSaxParserUtils.cpp b/GeneratedSaxParser/src/GeneratedSaxParserUtils.cpp
index 1f9a3eef..dd6f5c59 100644
--- a/GeneratedSaxParser/src/GeneratedSaxParserUtils.cpp
+++ b/GeneratedSaxParser/src/GeneratedSaxParserUtils.cpp
@@ -10,6 +10,7 @@
#include "GeneratedSaxParserUtils.h"
#include <math.h>
+#include <cmath>
#include <memory>
#include <string.h>
#include <limits>
+22
View File
@@ -0,0 +1,22 @@
From a0deb4ce8b43cf3c8b8c0a4225c6be5296446dbd Mon Sep 17 00:00:00 2001
From: Adam Eri <adam.eri@blackmirror.media>
Date: Tue, 3 Sep 2019 23:30:20 +0200
Subject: [PATCH] Resolves compile error on macOS
Resolves "no member named 'isnan' in namespace 'std'" on macOS
---
GeneratedSaxParser/src/GeneratedSaxParserUtils.cpp | 1 +
1 file changed, 1 insertion(+)
diff --git a/GeneratedSaxParser/src/GeneratedSaxParserUtils.cpp b/GeneratedSaxParser/src/GeneratedSaxParserUtils.cpp
index 1f9a3eef..dd6f5c59 100644
--- a/GeneratedSaxParser/src/GeneratedSaxParserUtils.cpp
+++ b/GeneratedSaxParser/src/GeneratedSaxParserUtils.cpp
@@ -10,6 +10,7 @@
#include "GeneratedSaxParserUtils.h"
#include <math.h>
+#include <cmath>
#include <memory>
#include <string.h>
#include <limits>
+2
View File
@@ -0,0 +1,2 @@
[tool.black]
line-length = 120
+64
View File
@@ -0,0 +1,64 @@
# ****************************************************************************
# line endings
# to suppress line ending changes in github, add ?w=1 at link end of a diff
# for more information see
# FreeCAD source code src/Mod/.gitattributes
# FreeCAD forum topic https://forum.freecadweb.org/viewtopic.php?f=17&t=41117
# FreeCAD pull request https://github.com/FreeCAD/FreeCAD/pull/2752
# get all used file types
# in a directory in a bash use
# find . -type f -name '*.*' | sed 's|.*\.||' | sort -u
# search for a specific file ending
# find . -type f -name '*.ico'
# normalize the line endings of the following files
*.cpp text
*.css text
*.csv text
*.feature text
*.gitattributes text
*.gitignore text
*.gitkeep
*.h text
*.html text
*.ifc text
*.json text
*.md text
*.po text
*.pot text
*.py text
*.txt text
# files not normalized ATM
# bat
# bnf
# blend
# i
# ico
# mo
# mpass
# png
# pth
# pyc
# rst
# svg
# ttf
# xsd
# line endings of all directories will be normalized
# to exclude a directory from being normalized add it here
# example: to exclude dirctory ifcbimtester use the following line without #
# ifcbimtester/** -text
# use git to manually correct the file endings
# git add --renormalize .
+59
View File
@@ -0,0 +1,59 @@
# bcf
A simple Python implementation of BCF. The data model is described in `data.py`.
Manipulation of BCF-XML is available via `bcfxml.py` and manipulation of BCF-API
is available via `bcfapi.py`.
Currently supports BCF version 2.1.
## bcfxml
The `bcfxml` module lets you interact with the BCF-XML standard.
```
from bcf.bcfxml import BcfXml
bcfxml = BcfXml()
# Load a project
project = bcfxml.get_project("/path/to/file.bcf")
# The project is also stored in the module
# project == bcfxml.project
print(project.name)
# To edit a project, just modify the object directly
bcfxml.project.name = "New name"
bcfxml.edit_project()
# The BCF file is extracted to this temporary directory
print(bcfxml.filepath)
# Get a dictionary of topics
topics = bcfxml.get_topics()
# Note: topics == bcfxml.topics
for guid, topic in bcfxml.topics.items():
print("Topic guid is", guid)
print("Topic guid is", topic.guid)
print("Topic title is", topic.title)
# Fetch extra data about a topic
header = bcfxml.get_header(guid)
comments = bcfxml.get_comments(guid)
viewpoints = bcfxml.get_viewpoints(guid)
# Note: comments == topic.comments, and so on
for comment_guid, comment in comments.items():
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.edit_topic(topic)
```
+762
View File
@@ -0,0 +1,762 @@
import os
import uuid
import shutil
import zipfile
import logging
import tempfile
import bcf.data
from datetime import datetime
from xml.dom import minidom
from xmlschema import XMLSchema
from contextlib import contextmanager
from shutil import copyfile
cwd = os.path.dirname(os.path.realpath(__file__))
@contextmanager
def cd(newdir):
prevdir = os.getcwd()
os.chdir(os.path.expanduser(newdir))
try:
yield
finally:
os.chdir(prevdir)
class BcfXml:
def __init__(self):
self.filepath = None
self.logger = logging.getLogger("bcfxml")
self.author = "john@doe.com"
self.project = bcf.data.Project()
self.version = "2.1"
self.topics = {}
def new_project(self):
self.project.project_id = str(uuid.uuid4())
self.project.name = "New Project"
self.topics = {}
if self.filepath:
self.close_project()
self.filepath = tempfile.mkdtemp()
self.edit_project()
self.edit_version()
def get_project(self, filepath=None):
if not filepath:
return self.project
zip_file = zipfile.ZipFile(filepath)
self.filepath = tempfile.mkdtemp()
zip_file.extractall(self.filepath)
data = self._read_xml("project.bcfp", "project.xsd")
self.project.project_id = data["Project"]["@ProjectId"]
self.project.name = data["Project"]["Name"]
return self.project
def edit_project(self):
self.document = minidom.Document()
root = self._create_element(self.document, "ProjectExtension")
project = self._create_element(root, "Project", {"ProjectId": self.project.project_id})
self._create_element(project, "Name", text=self.project.name)
self._create_element(root, "ExtensionSchema", text="extensions.xsd")
with open(os.path.join(self.filepath, "project.bcfp"), "wb") as f:
f.write(self.document.toprettyxml(encoding="utf-8"))
def save_project(self, filepath):
with cd(self.filepath):
zip_file = zipfile.ZipFile(filepath, "w", zipfile.ZIP_DEFLATED)
for root, dirs, files in os.walk("./"):
for file in files:
zip_file.write(os.path.join(root, file))
zip_file.close()
def get_version(self):
data = self._read_xml("bcf.version", "version.xsd")
self.version = data["@VersionId"]
return self.version
def edit_version(self):
self.document = minidom.Document()
root = self._create_element(self.document, "Version", {"VersionId": self.version})
version = self._create_element(root, "DetailedVersion", text=self.version)
with open(os.path.join(self.filepath, "bcf.version"), "wb") as f:
f.write(self.document.toprettyxml(encoding="utf-8"))
def get_topics(self):
self.topics = {}
topics = []
subdirs = []
for (dirpath, dirnames, filenames) in os.walk(self.filepath):
subdirs = dirnames
break
for subdir in subdirs:
self.topics[subdir] = self.get_topic(subdir)
return self.topics
def get_header(self, guid):
data = self._read_xml(os.path.join(guid, "markup.bcf"), "markup.xsd")
if "Header" not in data:
return
header = bcf.data.Header()
for item in data["Header"]["File"]:
header_file = bcf.data.HeaderFile()
optional_keys = {
"filename": "Filename",
"date": "Date",
"reference": "Reference",
"ifc_project": "@IfcProject",
"ifc_spatial_structure_element": "@IfcSpatialStructureElement",
"is_external": "@isExternal",
}
for key, value in optional_keys.items():
if value in item:
setattr(header_file, key, item[value])
header.files.append(header_file)
self.topics[guid].header = header
return header
def get_topic(self, guid):
if guid in self.topics:
return self.topics[guid]
data = self._read_xml(os.path.join(guid, "markup.bcf"), "markup.xsd")
topic = bcf.data.Topic()
self.topics[guid] = topic
mandatory_keys = {
"guid": "@Guid",
"title": "Title",
"creation_date": "CreationDate",
"creation_author": "CreationAuthor",
}
for key, value in mandatory_keys.items():
setattr(topic, key, data["Topic"][value])
optional_keys = {
"priority": "Priority",
"index": "Index",
"labels": "Labels",
"reference_links": "ReferenceLink",
"modified_date": "ModifiedDate",
"modified_author": "ModifiedAuthor",
"due_date": "DueDate",
"assigned_to": "AssignedTo",
"stage": "Stage",
"description": "Description",
"topic_status": "@TopicStatus",
"topic_type": "@TopicType",
}
for key, value in optional_keys.items():
if value in data["Topic"]:
setattr(topic, key, data["Topic"][value])
if "BimSnippet" in data["Topic"]:
bim_snippet = bcf.data.BimSnippet()
keys = {
"snippet_type": "@SnippetType",
"is_external": "@IsExternal",
"reference": "Reference",
"reference_schema": "ReferenceSchema",
}
for key, value in keys.items():
if value in data["Topic"]["BimSnippet"]:
setattr(bim_snippet, key, data["Topic"]["BimSnippet"][value])
topic.bim_snippet = bim_snippet
if "DocumentReference" in data["Topic"]:
for item in data["Topic"]["DocumentReference"]:
document_reference = bcf.data.DocumentReference()
keys = {
"referenced_document": "ReferencedDocument",
"is_external": "@IsExternal",
"guid": "@Guid",
"description": "Description",
}
for key, value in keys.items():
if value in item:
setattr(document_reference, key, item[value])
topic.document_references.append(document_reference)
if "RelatedTopic" in data["Topic"]:
for item in data["Topic"]["RelatedTopic"]:
related_topic = bcf.data.RelatedTopic()
related_topic.guid = item["@Guid"]
topic.related_topics.append(related_topic)
return topic
def add_topic(self, topic=None):
if topic is None:
topic = bcf.data.Topic()
if not topic.guid:
topic.guid = str(uuid.uuid4())
if not topic.title:
topic.title = "New Topic"
os.mkdir(os.path.join(self.filepath, topic.guid))
self.edit_topic(topic)
return topic
def edit_topic(self, topic):
if not topic.creation_date:
topic.creation_date = datetime.utcnow().isoformat()
topic.creation_author = self.author
else:
topic.modified_date = datetime.utcnow().isoformat()
topic.modified_author = self.author
self.document = minidom.Document()
root = self._create_element(self.document, "Markup")
self.write_header(topic.header, root)
topic_el = self._create_element(
root,
"Topic",
{
"Guid": topic.guid,
"TopicType": topic.topic_type,
"TopicStatus": topic.topic_status,
},
)
for reference_link in topic.reference_links:
self._create_element(topic_el, "ReferenceLink", text=reference_link)
text_map = {
"Title": topic.title,
"Priority": topic.priority,
"Index": topic.index,
}
for key, value in text_map.items():
if value:
self._create_element(topic_el, key, text=value)
for label in topic.labels:
self._create_element(topic_el, "Labels", text=label)
text_map = {
"CreationDate": topic.creation_date,
"CreationAuthor": topic.creation_author,
"ModifiedDate": topic.modified_date,
"ModifiedAuthor": topic.modified_author,
"DueDate": topic.due_date,
"AssignedTo": topic.assigned_to,
"Stage": topic.stage,
"Description": topic.description,
}
for key, value in text_map.items():
if value:
self._create_element(topic_el, key, text=value)
if topic.bim_snippet:
bim_snippet = self._create_element(
topic_el,
"BimSnippet",
{"SnippetType": topic.bim_snippet.snippet_type, "isExternal": topic.bim_snippet.is_external},
)
self._create_element(bim_snippet, "Reference", text=topic.bim_snippet.reference)
self._create_element(bim_snippet, "ReferenceSchema", text=topic.bim_snippet.reference_schema)
for reference in topic.document_references:
reference_el = self._create_element(
topic_el, "DocumentReference", {"Guid": reference.guid, "isExternal": reference.is_external}
)
self._create_element(reference_el, "ReferencedDocument", text=reference.referenced_document)
self._create_element(reference_el, "Description", text=reference.description)
for related_topic in topic.related_topics:
self._create_element(topic_el, "RelatedTopic", {"Guid": related_topic.guid})
self.write_comments(topic.comments, root)
self.write_viewpoints(topic.viewpoints, root, topic)
with open(os.path.join(self.filepath, topic.guid, "markup.bcf"), "wb") as f:
f.write(self.document.toprettyxml(encoding="utf-8"))
def write_header(self, header, root):
if not header or not header.files:
return
header_el = self._create_element(root, "Header")
for f in header.files:
file_el = self._create_element(
header_el,
"File",
{
"IfcProject": f.ifc_project,
"IfcSpatialStructureElement": f.ifc_spatial_structure_element,
"isExternal": f.is_external,
},
)
self._create_element(file_el, "Filename", text=f.filename)
self._create_element(file_el, "Date", text=f.date)
self._create_element(file_el, "Reference", text=f.reference)
def write_comments(self, comments, root):
for comment in comments.values():
comment_el = self._create_element(root, "Comment", {"Guid": comment.guid})
text_map = {
"Date": comment.date,
"Author": comment.author,
"Comment": comment.comment,
"ModifiedDate": comment.modified_date,
"ModifiedAuthor": comment.modified_author,
}
for key, value in text_map.items():
if value:
self._create_element(comment_el, key, text=value)
if comment.viewpoint:
self._create_element(comment_el, "Viewpoint", {"Guid": comment.viewpoint.guid})
def add_comment(self, topic, comment=None):
if comment is None:
comment = bcf.data.Comment()
if not comment.guid:
comment.guid = str(uuid.uuid4())
if not comment.comment:
comment.comment = "'Free software' is a matter of liberty, not price. To understand the concept, you should think of 'free' as in 'free speech,' not as in 'free beer'."
topic.comments[comment.guid] = comment
self.edit_comment(comment, topic)
def edit_comment(self, comment, topic):
if not comment.date:
comment.date = datetime.utcnow().isoformat()
comment.author = self.author
else:
comment.modified_date = datetime.utcnow().isoformat()
comment.modified_author = self.author
self.edit_topic(topic)
def delete_comment(self, guid, topic):
if guid in topic.comments:
del topic.comments[guid]
self.edit_topic(topic)
def delete_topic(self, guid):
if guid in self.topics:
del self.topics[guid]
shutil.rmtree(os.path.join(self.filepath, guid))
def write_viewpoints(self, viewpoints, root, topic):
for viewpoint in viewpoints.values():
viewpoint_el = self._create_element(root, "Viewpoints", {"Guid": viewpoint.guid})
text_map = {"Viewpoint": viewpoint.viewpoint, "Snapshot": viewpoint.snapshot, "Index": viewpoint.index}
for key, value in text_map.items():
if value:
self._create_element(viewpoint_el, key, text=value)
self.write_viewpoint(viewpoint, topic)
def write_viewpoint(self, viewpoint, topic):
document = minidom.Document()
root = self._create_element(document, "VisualizationInfo", {"Guid": viewpoint.guid})
self.write_viewpoint_components(viewpoint, root)
self.write_viewpoint_orthogonal_camera(viewpoint, root)
self.write_viewpoint_perspective_camera(viewpoint, root)
self.write_viewpoint_lines(viewpoint, root)
self.write_viewpoint_clipping_planes(viewpoint, root)
self.write_viewpoint_bitmaps(viewpoint, root)
with open(os.path.join(self.filepath, topic.guid, viewpoint.viewpoint), "wb") as f:
f.write(document.toprettyxml(encoding="utf-8"))
def write_viewpoint_components(self, viewpoint, parent):
if not viewpoint.components:
return
components_el = self._create_element(parent, "Components")
if viewpoint.components.view_setup_hints:
view_setup_hints = self._create_element(
components_el,
"ViewSetupHints",
{
"SpacesVisible": viewpoint.components.view_setup_hints.spaces_visible,
"SpaceBoundariesVisible": viewpoint.components.view_setup_hints.space_boundaries_visible,
"OpeningsVisible": viewpoint.components.view_setup_hints.openings_visible,
},
)
if viewpoint.components.selection:
selection_el = self._create_element(components_el, "Selection")
for selection in viewpoint.components.selection:
self.write_component(selection, selection_el)
visibility = self._create_element(
components_el, "Visibility", {"DefaultVisibility": viewpoint.components.visibility.default_visibility}
)
if viewpoint.components.visibility.exceptions:
exceptions_el = self._create_element(visibility, "Exceptions")
for exception in viewpoint.components.visibility.exceptions:
self.write_component(exception, exceptions_el)
if viewpoint.components.coloring:
coloring_el = self._create_element(components_el, "Coloring")
for color in viewpoint.components.coloring:
color_el = self._create_element(coloring_el, "Color", {"Color": color.color})
for component in color.components:
self.write_component(component, color_el)
def write_viewpoint_orthogonal_camera(self, viewpoint, parent):
if not viewpoint.orthogonal_camera:
return
camera = viewpoint.orthogonal_camera
camera_el = self._create_element(parent, "OrthogonalCamera")
camera_view_point = self._create_element(camera_el, "CameraViewPoint")
self.write_vector(camera_view_point, camera.camera_view_point)
camera_direction = self._create_element(camera_el, "CameraDirection")
self.write_vector(camera_direction, camera.camera_direction)
camera_up_vector = self._create_element(camera_el, "CameraUpVector")
self.write_vector(camera_up_vector, camera.camera_up_vector)
self._create_element(camera_el, "ViewToWorldScale", text=camera.view_to_world_scale)
def write_viewpoint_perspective_camera(self, viewpoint, parent):
if not viewpoint.perspective_camera:
return
camera = viewpoint.perspective_camera
camera_el = self._create_element(parent, "PerspectiveCamera")
camera_view_point = self._create_element(camera_el, "CameraViewPoint")
self.write_vector(camera_view_point, camera.camera_view_point)
camera_direction = self._create_element(camera_el, "CameraDirection")
self.write_vector(camera_direction, camera.camera_direction)
camera_up_vector = self._create_element(camera_el, "CameraUpVector")
self.write_vector(camera_up_vector, camera.camera_up_vector)
self._create_element(camera_el, "FieldOfView", text=camera.field_of_view)
def write_viewpoint_lines(self, viewpoint, parent):
if not viewpoint.lines:
return
lines_el = self._create_element(parent, "Lines")
for line in viewpoint.lines:
line_el = self._create_element(lines_el, "Line")
start_point_el = self._create_element(line_el, "StartPoint")
self.write_vector(start_point_el, line.start_point)
end_point_el = self._create_element(line_el, "EndPoint")
self.write_vector(end_point_el, line.end_point)
def write_viewpoint_clipping_planes(self, viewpoint, parent):
if not viewpoint.clipping_planes:
return
planes_el = self._create_element(parent, "ClippingPlanes")
for plane in viewpoint.clipping_planes:
plane_el = self._create_element(planes_el, "ClippingPlane")
location_el = self._create_element(plane_el, "Location")
self.write_vector(location_el, plane.location)
direction_el = self._create_element(plane_el, "Direction")
self.write_vector(direction_el, plane.direction)
def write_viewpoint_bitmaps(self, viewpoint, parent):
if not viewpoint.bitmaps:
return
for bitmap in viewpoint.bitmaps:
bitmap_el = self._create_element(parent, "Bitmap")
text_map = {"Bitmap": bitmap.bitmap_type, "Reference": bitmap.reference}
for key, value in text_map.items():
self._create_element(bitmap_el, key, text=value)
location_el = self._create_element(bitmap_el, "Location")
self.write_vector(location_el, bitmap.location)
normal_el = self._create_element(bitmap_el, "Normal")
self.write_vector(normal_el, bitmap.normal)
up_el = self._create_element(bitmap_el, "Up")
self.write_vector(up_el, bitmap.up)
self._create_element(bitmap_el, "Height", text=bitmap.height)
def write_vector(self, parent, from_obj):
self._create_element(parent, "X", text=from_obj.x)
self._create_element(parent, "Y", text=from_obj.y)
self._create_element(parent, "Z", text=from_obj.z)
def write_component(self, data, parent):
component_el = self._create_element(parent, "Component", {"IfcGuid": data.ifc_guid})
text_map = {"OriginatingSystem": data.originating_system, "AuthoringToolId": data.authoring_tool_id}
for key, value in text_map.items():
if value:
self._create_element(component_el, key, text=value)
def add_viewpoint(self, topic, viewpoint=None):
if not viewpoint:
viewpoint = bcf.data.Viewpoint()
if not viewpoint.guid:
viewpoint.guid = str(uuid.uuid4())
if not viewpoint.viewpoint:
viewpoint.viewpoint = f"{viewpoint.guid}.bcfv"
if viewpoint.snapshot:
topic_filepath = os.path.join(self.filepath, topic.guid)
filepath = os.path.join(topic_filepath, viewpoint.snapshot)
if not os.path.exists(filepath):
filename = viewpoint.guid + os.path.splitext(viewpoint.snapshot)[-1]
copyfile(viewpoint.snapshot, os.path.join(topic_filepath, filename))
viewpoint.snapshot = filename
topic.viewpoints[viewpoint.guid] = viewpoint
self.edit_topic(topic)
def delete_viewpoint(self, guid, topic):
if guid not in topic.viewpoints:
return
viewpoint = topic.viewpoints[guid]
if viewpoint.snapshot:
filepath = os.path.join(self.filepath, topic.guid, viewpoint.snapshot)
if os.path.exists(filepath):
os.remove(filepath)
if viewpoint.viewpoint:
filepath = os.path.join(self.filepath, topic.guid, viewpoint.viewpoint)
if os.path.exists(filepath):
os.remove(filepath)
for bitmap in viewpoint.bitmaps:
if not bitmap.reference:
continue
filepath = os.path.join(self.filepath, topic.guid, bitmap.reference)
if os.path.exists(filepath):
os.remove(filepath)
del topic.viewpoints[guid]
self.edit_topic(topic)
def delete_file(self, topic, index):
if not topic.header:
return
f = topic.header.files.pop(index)
filepath = os.path.join(self.filepath, topic.guid, f.reference)
if not f.is_external and os.path.exists(filepath):
os.remove(filepath)
self.edit_topic(topic)
def delete_bim_snippet(self, topic):
if not topic.bim_snippet:
return
if topic.bim_snippet.reference and not topic.bim_snippet.is_external:
filepath = os.path.join(self.filepath, topic.guid, topic.bim_snippet.reference)
if os.path.exists(filepath):
os.remove(filepath)
topic.bim_snippet = None
self.edit_topic(topic)
def delete_document_reference(self, topic, index):
document_reference = topic.document_references[index]
if document_reference.referenced_document and not document_reference.is_external:
filepath = os.path.join(self.filepath, topic.guid, document_reference.referenced_document)
if os.path.exists(filepath):
os.remove(filepath)
del topic.document_references[index]
self.edit_topic(topic)
def add_document_reference(self, topic, document_reference):
if os.path.exists(document_reference.referenced_document):
topic_filepath = os.path.join(self.filepath, topic.guid)
filename = os.path.basename(document_reference.referenced_document)
copyfile(document_reference.referenced_document, os.path.join(topic_filepath, filename))
document_reference.referenced_document = filename
document_reference.is_external = False
else:
document_reference.is_external = True
if not document_reference.guid:
document_reference.guid = str(uuid.uuid4())
topic.document_references.append(document_reference)
self.edit_topic(topic)
def add_bim_snippet(self, topic, bim_snippet):
if topic.bim_snippet:
self.delete_bim_snippet(topic)
if os.path.exists(bim_snippet.reference):
topic_filepath = os.path.join(self.filepath, topic.guid)
filename = os.path.basename(bim_snippet.reference)
copyfile(bim_snippet.reference, os.path.join(topic_filepath, filename))
bim_snippet.reference = filename
bim_snippet.is_external = False
else:
bim_snippet.is_external = True
topic.bim_snippet = bim_snippet
self.edit_topic(topic)
def add_file(self, topic, header_file):
if os.path.exists(header_file.reference):
topic_filepath = os.path.join(self.filepath, topic.guid)
header_file.filename = os.path.basename(header_file.reference)
copyfile(header_file.reference, os.path.join(topic_filepath, header_file.filename))
header_file.reference = header_file.filename
header_file.is_external = False
header_file.date = datetime.utcnow().isoformat()
if not topic.header:
topic.header = bcf.data.Header()
topic.header.files.append(header_file)
self.edit_topic(topic)
def get_comments(self, guid):
comments = {}
data = self._read_xml(os.path.join(guid, "markup.bcf"), "markup.xsd")
if "Comment" not in data:
return comments
for item in data["Comment"]:
comment = bcf.data.Comment()
mandatory_keys = {"guid": "@Guid", "date": "Date", "author": "Author", "comment": "Comment"}
for key, value in mandatory_keys.items():
setattr(comment, key, item[value])
optional_keys = {"modified_date": "ModifiedDate", "modified_author": "ModifiedAuthor"}
for key, value in optional_keys.items():
if value in item:
setattr(comment, key, item[value])
if "Viewpoint" in item:
viewpoint = bcf.data.Viewpoint()
viewpoint.guid = item["Viewpoint"]["@Guid"]
comment.viewpoint = viewpoint
comments[comment.guid] = comment
self.topics[guid].comments = comments
return comments
def get_viewpoints(self, guid):
viewpoints = {}
data = self._read_xml(os.path.join(guid, "markup.bcf"), "markup.xsd")
if "Viewpoints" not in data:
return viewpoints
for item in data["Viewpoints"]:
viewpoint = self.get_viewpoint(item, guid)
viewpoints[viewpoint.guid] = viewpoint
self.topics[guid].viewpoints = viewpoints
return viewpoints
def get_viewpoint(self, data, topic_guid):
viewpoint = bcf.data.Viewpoint()
viewpoint.guid = data["@Guid"]
optional_keys = {"viewpoint": "Viewpoint", "snapshot": "Snapshot", "index": "Index"}
for key, value in optional_keys.items():
if value in data:
setattr(viewpoint, key, data[value])
visinfo = self._read_xml(os.path.join(topic_guid, viewpoint.viewpoint), "visinfo.xsd")
viewpoint.components = self.get_viewpoint_components(visinfo)
viewpoint.orthogonal_camera = self.get_viewpoint_orthogonal_camera(visinfo)
viewpoint.perspective_camera = self.get_viewpoint_perspective_camera(visinfo)
viewpoint.lines = self.get_viewpoint_lines(visinfo)
viewpoint.clipping_planes = self.get_viewpoint_clipping_planes(visinfo)
viewpoint.bitmaps = self.get_viewpoint_bitmaps(visinfo)
return viewpoint
def get_viewpoint_components(self, visinfo):
if "Components" not in visinfo:
return None
components = bcf.data.Components()
data = visinfo["Components"]
if "ViewSetupHints" in data:
view_setup_hints = bcf.data.ViewSetupHints()
optional_keys = {
"spaces_visible": "@SpacesVisible",
"space_boundaries_visible": "@SpaceBoundariesVisible",
"openings_visible": "@OpeningsVisible",
}
for key, value in optional_keys.items():
if value in data["ViewSetupHints"]:
setattr(view_setup_hints, key, data["ViewSetupHints"][value])
components.view_setup_hints = view_setup_hints
if "Selection" in data and "Component" in data["Selection"]:
for item in data["Selection"]["Component"]:
components.selection.append(self.get_component(item))
if "Visibility" in data:
component_visibility = bcf.data.ComponentVisibility()
if "@DefaultVisibility" in data["Visibility"]:
component_visibility.default_visibility = data["Visibility"]["@DefaultVisibility"]
if "Exceptions" in data["Visibility"] and "Component" in data["Visibility"]["Exceptions"]:
for item in data["Visibility"]["Exceptions"]["Component"]:
component_visibility.exceptions.append(self.get_component(item))
components.visibility = component_visibility
if "Coloring" in data and "Color" in data["Coloring"]:
for item in data["Coloring"]["Color"]:
color = bcf.data.Color()
color.color = item["@Color"]
for item2 in item["Component"]:
color.components.append(self.get_component(item2))
components.coloring.append(color)
return components
def get_viewpoint_orthogonal_camera(self, visinfo):
if "OrthogonalCamera" not in visinfo:
return None
camera = bcf.data.OrthogonalCamera()
data = visinfo["OrthogonalCamera"]
self.set_vector(camera.camera_view_point, data["CameraViewPoint"])
self.set_vector(camera.camera_direction, data["CameraDirection"])
self.set_vector(camera.camera_up_vector, data["CameraUpVector"])
camera.view_to_world_scale = data["ViewToWorldScale"]
return camera
def get_viewpoint_perspective_camera(self, visinfo):
if "PerspectiveCamera" not in visinfo:
return None
camera = bcf.data.PerspectiveCamera()
data = visinfo["PerspectiveCamera"]
self.set_vector(camera.camera_view_point, data["CameraViewPoint"])
self.set_vector(camera.camera_direction, data["CameraDirection"])
self.set_vector(camera.camera_up_vector, data["CameraUpVector"])
camera.field_of_view = data["FieldOfView"]
return camera
def get_viewpoint_lines(self, visinfo):
if "Lines" not in visinfo:
return []
lines = []
for item in visinfo["Lines"]["Line"]:
line = bcf.data.Line()
self.set_vector(line.start_point, item["StartPoint"])
self.set_vector(line.end_point, item["EndPoint"])
lines.append(line)
return lines
def get_viewpoint_clipping_planes(self, visinfo):
if "ClippingPlanes" not in visinfo:
return []
planes = []
for item in visinfo["ClippingPlanes"]["ClippingPlane"]:
plane = bcf.data.ClippingPlane()
self.set_vector(plane.location, item["Location"])
self.set_vector(plane.direction, item["Direction"])
planes.append(plane)
return planes
def get_viewpoint_bitmaps(self, visinfo):
if "Bitmap" not in visinfo:
return []
bitmaps = []
for item in visinfo["Bitmap"]:
bitmap = bcf.data.Bitmap()
bitmap.reference = item["Reference"]
bitmap.bitmap_type = item["Bitmap"].upper()
self.set_vector(bitmap.location, item["Location"])
self.set_vector(bitmap.normal, item["Normal"])
self.set_vector(bitmap.up, item["Up"])
bitmap.height = item["Height"]
bitmaps.append(bitmap)
return bitmaps
def set_vector(self, to_obj, from_xml):
to_obj.x = from_xml["X"]
to_obj.y = from_xml["Y"]
to_obj.z = from_xml["Z"]
def get_component(self, data):
component = bcf.data.Component()
optional_keys = {
"originating_system": "OriginatingSystem",
"authoring_tool_id": "AuthoringToolId",
"ifc_guid": "@IfcGuid",
}
for key, value in optional_keys.items():
if value in data:
setattr(component, key, data[value])
return component
def close_project(self):
shutil.rmtree(self.filepath)
def _read_xml(self, filename, xsd):
schema = XMLSchema(os.path.join(cwd, "xsd", xsd))
filepath = os.path.join(self.filepath, filename)
(data, errors) = schema.to_dict(filepath, validation="lax")
for error in errors:
self.logger.error(error)
return data
def _create_element(self, parent, name, attributes={}, text=None):
element = self.document.createElement(name)
for key, value in attributes.items():
if isinstance(value, bool):
element.setAttribute(key, str(value).lower())
elif value:
element.setAttribute(key, value)
if text is not None:
text = self.document.createTextNode(str(text))
element.appendChild(text)
parent.appendChild(element)
return element
def __del__(self):
self.close_project()
+178
View File
@@ -0,0 +1,178 @@
class Project:
def __init__(self):
self.project_id = ""
self.name = ""
class BimSnippet:
def __init__(self):
self.snippet_type = None
self.is_external = False
self.reference = None
self.reference_schema = None
class DocumentReference:
def __init__(self):
self.referenced_document = None
self.description = None
self.guid = None
self.is_external = False
class RelatedTopic:
def __init__(self):
self.guid = None
class HeaderFile:
def __init__(self):
self.filename = None
self.date = None
self.reference = None
self.ifc_project = None
self.ifc_spatial_structure_element = None
self.is_external = True
class Header:
def __init__(self):
self.files = []
class Topic:
def __init__(self):
self.reference_links = []
self.title = ""
self.priority = None
self.index = None # Deprecated, stored, but ignored
self.labels = []
self.creation_date = None
self.creation_author = None
self.modified_date = None
self.modified_author = None
self.due_date = None
self.assigned_to = None
self.stage = None
self.description = None
self.bim_snippet = None
self.document_references = []
self.related_topics = []
self.topic_status = None
self.topic_type = None
self.guid = None
self.header = None
self.comments = {}
self.viewpoints = {}
class Comment:
def __init__(self):
self.guid = None
self.date = None
self.author = None
self.comment = None
self.viewpoint = None
self.modified_date = None
self.modified_author = None
self.topic_guid = None # Part of BCF-API
class ViewSetupHints:
def __init__(self):
self.spaces_visible = False
self.space_boundaries_visible = False
self.openings_visible = False
class Component:
def __init__(self):
self.originating_system = None
self.authoring_tool_id = None
self.ifc_guid = None
class ComponentVisibility:
def __init__(self):
self.exceptions = []
self.default_visibility = False
class Color:
def __init__(self):
self.color = None
self.components = []
class Components:
def __init__(self):
self.view_setup_hints = None
self.selection = []
self.visibility = None
self.coloring = []
class Point:
def __init__(self):
self.x = 0
self.y = 0
self.z = 0
class Direction(Point):
pass
class OrthogonalCamera:
def __init__(self):
self.camera_view_point = Point()
self.camera_direction = Direction()
self.camera_up_vector = Direction()
self.view_to_world_scale = 1.0
class PerspectiveCamera:
def __init__(self):
self.camera_view_point = Point()
self.camera_direction = Direction()
self.camera_up_vector = Direction()
self.field_of_view = 60.0
class Line:
def __init__(self):
self.start_point = Point()
self.end_point = Point()
class ClippingPlane:
def __init__(self):
self.location = Point()
self.direction = Direction()
class Bitmap:
def __init__(self):
self.reference = "" # Only in BCF-XML
self.bitmap_data = None # Only in BCF-API
self.bitmap_type = "PNG" # Enum of png or jpg
self.location = Point()
self.normal = Direction()
self.up = Direction()
self.height = 1.0
class Viewpoint:
def __init__(self):
self.guid = None
self.viewpoint = None
self.snapshot = None
self.index = None
self.components = None # It's not a list, despite the plural name
self.orthogonal_camera = None
self.perspective_camera = None
self.lines = []
self.clipping_planes = []
self.bitmaps = []
+154
View File
@@ -0,0 +1,154 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Mit XMLSpy v2011 rel. 2 sp1 (http://www.altova.com) von Klaus Linhard (IABI e.V.) bearbeitet -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Markup">
<xs:complexType>
<xs:sequence>
<xs:element name="Header" type="Header" minOccurs="0"/>
<xs:element name="Topic" type="Topic"/>
<xs:element name="Comment" type="Comment" minOccurs="0" maxOccurs="unbounded"/>
<!-- ISG Jira issue BCF-9. Add support for several viewpoints and snapshots per issue -->
<xs:element name="Viewpoints" type="ViewPoint" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="Header">
<xs:sequence>
<xs:element name="File" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="Filename" type="xs:string" minOccurs="0"/>
<xs:element name="Date" type="xs:dateTime" minOccurs="0"/>
<!-- Reference (URL) of the file -->
<xs:element name="Reference" type="xs:string" minOccurs="0"/>
</xs:sequence>
<xs:attributeGroup ref="FileAttributes"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
<!-- ISG Jira issue BCF-9. Add support for several viewpoints and snapshots per issue -->
<xs:complexType name="ViewPoint">
<xs:sequence>
<!-- viewpoint file (xml) -->
<xs:element name="Viewpoint" type="xs:string" minOccurs="0"/>
<!-- the snapshot png -->
<xs:element name="Snapshot" type="xs:string" minOccurs="0"/>
<!-- the viewpoint index (sort order) -->
<xs:element name="Index" type="xs:int" minOccurs="0"/>
</xs:sequence>
<xs:attribute name="Guid" type="Guid" use="required"/>
<!-- Guid of the viewpoint -->
</xs:complexType>
<!-- BimSnippet -->
<xs:complexType name="BimSnippet">
<xs:sequence>
<!--
Name of the file in the topic folder containing the snippet or a URL.
E.G.- Expresscode containing p.e Issue, Request
// Maybe some header infos ?? // IfcEntites // Geometry
-->
<!-- Reference (name) to the snippet file -->
<xs:element name="Reference" type="xs:string"/>
<xs:element name="ReferenceSchema" type="xs:string"/>
</xs:sequence>
<xs:attribute name="SnippetType" type="xs:string" use="required"/>
<xs:attribute name="isExternal" type="xs:boolean" default="false"/>
<!-- This flag is true when the reference is a URL pointing outside of the BCF file-->
</xs:complexType>
<xs:complexType name="Topic">
<xs:sequence>
<xs:element name="ReferenceLink" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="Title" type="xs:string"/>
<xs:element name="Priority" type="Priority" minOccurs="0"/>
<!-- ISG Jira issue BCF-8 Add a way save order the topics -->
<xs:element name="Index" type="xs:int" minOccurs="0"/>
<xs:element name="Labels" type="TopicLabel" minOccurs="0" maxOccurs="unbounded"/>
<xs:element name="CreationDate" type="xs:dateTime" minOccurs="1"/>
<xs:element name="CreationAuthor" type="UserIdType" minOccurs="1"/>
<xs:element name="ModifiedDate" type="xs:dateTime" minOccurs="0"/>
<xs:element name="ModifiedAuthor" type="UserIdType" minOccurs="0"/>
<xs:element name="DueDate" type="xs:dateTime" minOccurs="0"/>
<xs:element name="AssignedTo" type="UserIdType" minOccurs="0"/>
<xs:element name="Stage" type="Stage" minOccurs="0"/>
<xs:element name="Description" type="xs:string" minOccurs="0"/>
<xs:element name="BimSnippet" type="BimSnippet" minOccurs="0"/>
<!-- Name of the file in the topic folder or url -->
<xs:element name="DocumentReference" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<!-- Name of the file in the topic folder or url -->
<xs:element name="ReferencedDocument" type="xs:string" minOccurs="0"/>
<!-- Human readable name of the document -->
<xs:element name="Description" type="xs:string" minOccurs="0"/>
</xs:sequence>
<xs:attributeGroup ref="DocumentReference"/>
</xs:complexType>
</xs:element>
<xs:element name="RelatedTopic" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:attribute name="Guid" type="Guid" use="required"/>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="Guid" type="Guid" use="required"/>
<xs:attribute name="TopicType" type="TopicType"/>
<xs:attribute name="TopicStatus" type="TopicStatus"/>
</xs:complexType>
<!-- Reference to a document inside of the topic folder or a url pointing to the web -->
<xs:attributeGroup name="DocumentReference">
<!-- Guid of the DocumentReference -->
<xs:attribute name="Guid" type="Guid"/>
<!-- A flag that is true when the ReferencedDocument points outside of the BCF file (a URL) -->
<xs:attribute name="isExternal" type="xs:boolean" default="false"/>
</xs:attributeGroup>
<xs:complexType name="Comment">
<xs:sequence>
<xs:element name="Date" type="xs:dateTime"/>
<xs:element name="Author" type="UserIdType"/>
<xs:element name="Comment" type="xs:string"/>
<xs:element name="Viewpoint" minOccurs="0">
<xs:complexType>
<xs:attribute name="Guid" type="Guid" use="required"/>
</xs:complexType>
</xs:element>
<xs:element name="ModifiedDate" type="xs:dateTime" minOccurs="0"/>
<xs:element name="ModifiedAuthor" type="UserIdType" minOccurs="0"/>
</xs:sequence>
<xs:attribute name="Guid" type="Guid" use="required"/>
</xs:complexType>
<xs:simpleType name="TopicStatus">
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:simpleType name="TopicType">
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:simpleType name="TopicLabel">
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:simpleType name="Priority">
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:simpleType name="UserIdType">
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:simpleType name="Stage">
<xs:restriction base="xs:string"/>
</xs:simpleType>
<xs:simpleType name="Guid">
<xs:restriction base="xs:string">
<xs:pattern value="[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="IfcGuid">
<xs:restriction base="xs:string">
<xs:length value="22"/>
<xs:pattern value="[0-9,A-Z,a-z,_$]*"/>
</xs:restriction>
</xs:simpleType>
<xs:attributeGroup name="FileAttributes">
<xs:attribute name="IfcProject" type="IfcGuid"/>
<xs:attribute name="IfcSpatialStructureElement" type="IfcGuid"/>
<xs:attribute name="isExternal" type="xs:boolean" default="true"/>
</xs:attributeGroup>
</xs:schema>
+18
View File
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Mit XMLSpy v2011 rel. 2 sp1 (http://www.altova.com) von Klaus Linhard (IABI e.V.) bearbeitet -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="ProjectExtension">
<xs:complexType>
<xs:sequence>
<xs:element name="Project" type="Project" minOccurs="0"/>
<xs:element name="ExtensionSchema" type="xs:anyURI"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:complexType name="Project">
<xs:sequence>
<xs:element name="Name" type="xs:string" minOccurs="0"/>
</xs:sequence>
<xs:attribute name="ProjectId" type="xs:string" use="required"/>
</xs:complexType>
</xs:schema>
+12
View File
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Mit XMLSpy v2011 rel. 3 (http://www.altova.com) von Klaus Linhard (IABI e.V.) bearbeitet -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<xs:element name="Version">
<xs:complexType>
<xs:sequence>
<xs:element name="DetailedVersion" type="xs:string" minOccurs="0"/>
</xs:sequence>
<xs:attribute name="VersionId" type="xs:string"/>
</xs:complexType>
</xs:element>
</xs:schema>
+191
View File
@@ -0,0 +1,191 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Mit XMLSpy v2011 rel. 2 sp1 (http://www.altova.com) von Klaus Linhard (IABI e.V.) bearbeitet -->
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema" elementFormDefault="qualified" attributeFormDefault="unqualified">
<xs:element name="VisualizationInfo">
<xs:annotation>
<xs:documentation>VisualizationInfo documentation</xs:documentation>
</xs:annotation>
<xs:complexType>
<xs:sequence>
<xs:element name="Components" type="Components" minOccurs="0"/>
<xs:element name="OrthogonalCamera" type="OrthogonalCamera" minOccurs="0"/>
<xs:element name="PerspectiveCamera" type="PerspectiveCamera" minOccurs="0"/>
<xs:element name="Lines" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="Line" type="Line" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<xs:element name="ClippingPlanes" minOccurs="0">
<xs:complexType>
<xs:sequence>
<xs:element name="ClippingPlane" type="ClippingPlane" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
<!-- ISG Jira issue BCF-17: Add support for text in the viewpoints -->
<xs:element name="Bitmap" minOccurs="0" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="Bitmap" type="BitmapFormat"/>
<!-- Name of the bitmap file in the topic folder -->
<xs:element name="Reference" type="xs:string"/>
<!-- Location of the center of the bitmap -->
<xs:element name="Location" type="Point"/>
<!-- Normal of the bitmap -->
<xs:element name="Normal" type="Direction"/>
<!-- Upvector of the bitmap -->
<xs:element name="Up" type="Direction"/>
<!-- Height of the bitmap -->
<xs:element name="Height" type="xs:double"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<!-- Guid of the viewpoint -->
<xs:attribute name="Guid" type="Guid" use="required"/>
</xs:complexType>
</xs:element>
<xs:complexType name="OrthogonalCamera">
<xs:sequence>
<xs:element name="CameraViewPoint" type="Point"/>
<xs:element name="CameraDirection" type="Direction"/>
<xs:element name="CameraUpVector" type="Direction"/>
<xs:element name="ViewToWorldScale" type="xs:double">
<xs:annotation>
<xs:documentation>view's visible size in meters</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="PerspectiveCamera">
<xs:sequence>
<xs:element name="CameraViewPoint" type="Point"/>
<xs:element name="CameraDirection" type="Direction"/>
<xs:element name="CameraUpVector" type="Direction"/>
<xs:element name="FieldOfView" type="FieldOfView">
<xs:annotation>
<xs:documentation>
It is currently limited to a value between 45 and 60 degrees.
This limitation will be dropped in the next release and viewers
should be expect values outside this range in current implementations.
</xs:documentation>
</xs:annotation>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Point">
<xs:sequence>
<xs:element name="X" type="xs:double"/>
<xs:element name="Y" type="xs:double"/>
<xs:element name="Z" type="xs:double"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Direction">
<xs:sequence>
<xs:element name="X" type="xs:double"/>
<xs:element name="Y" type="xs:double"/>
<xs:element name="Z" type="xs:double"/>
</xs:sequence>
</xs:complexType>
<xs:simpleType name="FieldOfView">
<xs:restriction base="xs:double">
<xs:minInclusive value="1"/>
<xs:maxInclusive value="170"/>
</xs:restriction>
</xs:simpleType>
<xs:complexType name="Components">
<xs:sequence>
<xs:element name="ViewSetupHints" type="ViewSetupHints" minOccurs="0" />
<!-- Components with relevance to the viewpoint. They should be displayed highlighted or selected in a viewer -->
<xs:element name="Selection" type="ComponentSelection" minOccurs="0" />
<xs:element name="Visibility" type="ComponentVisibility" minOccurs="1" />
<xs:element name="Coloring" type="ComponentColoring" minOccurs="0" />
</xs:sequence>
</xs:complexType>
<xs:complexType name="ViewSetupHints">
<xs:attribute name="SpacesVisible" type="xs:boolean"/>
<xs:attribute name="SpaceBoundariesVisible" type="xs:boolean"/>
<xs:attribute name="OpeningsVisible" type="xs:boolean"/>
</xs:complexType>
<xs:complexType name="ComponentSelection">
<xs:sequence>
<xs:element name="Component" type="Component" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="ComponentVisibility">
<xs:sequence>
<xs:element name="Exceptions" minOccurs="0">
<!-- List Components that are different than the DefaultVisibility. E.g. if DefaultVisibility = false then list
Components that should be visible -->
<xs:complexType>
<xs:sequence>
<xs:element name="Component" type="Component" maxOccurs="unbounded"/>
</xs:sequence>
</xs:complexType>
</xs:element>
</xs:sequence>
<xs:attribute name="DefaultVisibility" type="xs:boolean"/>
</xs:complexType>
<xs:complexType name="ComponentColoring">
<xs:sequence>
<xs:element name="Color" maxOccurs="unbounded">
<xs:complexType>
<xs:sequence>
<xs:element name="Component" type="Component" maxOccurs="unbounded"/>
</xs:sequence>
<xs:attribute ref="Color"/>
</xs:complexType>
</xs:element>
</xs:sequence>
</xs:complexType>
<xs:complexType name="Component">
<xs:sequence>
<xs:element name="OriginatingSystem" type="xs:string" minOccurs="0"/>
<xs:element name="AuthoringToolId" type="xs:string" minOccurs="0"/>
</xs:sequence>
<xs:attribute ref="IfcGuid"/>
<!-- ISG Jira Issue BCF-14 -->
</xs:complexType>
<xs:attribute name="Color">
<xs:simpleType>
<xs:restriction base="xs:normalizedString">
<!-- Should either match 3 or 4 hex bytes , e.g. "FF00FF" or "FF00FF99" -->
<xs:pattern value="[0-9,a-f,A-F]{6}([0-9,a-f,A-F]{2})?"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:attribute name="IfcGuid">
<xs:simpleType>
<xs:restriction base="xs:normalizedString">
<xs:length value="22"/>
<xs:pattern value="[0-9,A-Z,a-z,_$]*"/>
</xs:restriction>
</xs:simpleType>
</xs:attribute>
<xs:complexType name="Line">
<xs:sequence>
<xs:element name="StartPoint" type="Point"/>
<xs:element name="EndPoint" type="Point"/>
</xs:sequence>
</xs:complexType>
<xs:complexType name="ClippingPlane">
<xs:sequence>
<xs:element name="Location" type="Point"/>
<xs:element name="Direction" type="Direction"/>
</xs:sequence>
</xs:complexType>
<!-- ISG Jira issue BCF-17: Add support for text in the viewpoints -->
<xs:simpleType name="BitmapFormat">
<xs:restriction base="xs:string">
<xs:enumeration value="PNG"/>
<xs:enumeration value="JPG"/>
</xs:restriction>
</xs:simpleType>
<xs:simpleType name="Guid">
<xs:restriction base="xs:string">
<xs:pattern value="[a-fA-F0-9]{8}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{4}-[a-fA-F0-9]{12}"/>
</xs:restriction>
</xs:simpleType>
</xs:schema>
+143 -143
View File
@@ -1,143 +1,143 @@
/********************************************************************************
* *
* This file is part of IfcOpenShell. *
* *
* IfcOpenShell is free software: you can redistribute it and/or modify *
* it under the terms of the Lesser GNU General Public License as published by *
* the Free Software Foundation, either version 3.0 of the License, or *
* (at your option) any later version. *
* *
* IfcOpenShell 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 *
* Lesser GNU General Public License for more details. *
* *
* You should have received a copy of the Lesser GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
/********************************************************************************
* *
* Example of curve rebar. *
* *
********************************************************************************/
#include <iostream>
#include <string>
#include <fstream>
#include "ifcparse\Ifc2x3.h"
#include "ifcparse\IfcUtil.h"
#include "ifcparse\IfcHierarchyHelper.h"
#include "ifcgeom\IfcGeom.h"
typedef std::string S;
typedef IfcParse::IfcGlobalId guid;
boost::none_t const null = boost::none;
void create_curve_rebar(IfcHierarchyHelper& file)
{
int dia = 24;
int R = 3 * dia;
int length = 12 * dia;
double crossSectionarea = M_PI * (dia / 2) * 2;
IfcSchema::IfcReinforcingBar* rebar = new IfcSchema::IfcReinforcingBar(
guid(), 0, S("test"), null,
null, 0, 0,
null, S("SR24"), //SteelGrade
dia, //diameter
crossSectionarea, //crossSectionarea = math.pi*(12.0/2)**2
0,
IfcSchema::IfcReinforcingBarRoleEnum::IfcReinforcingBarRoleEnum::IfcReinforcingBarRole_LIGATURE,
IfcSchema::IfcReinforcingBarSurfaceEnum::IfcReinforcingBarSurfaceEnum::IfcReinforcingBarSurface_PLAIN //PLAIN or TEXTURED
);
file.addBuildingProduct(rebar);
rebar->setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
IfcSchema::IfcCompositeCurveSegment::list::ptr segments(new IfcSchema::IfcCompositeCurveSegment::list());
IfcSchema::IfcCartesianPoint* p1 = file.addTriplet<IfcSchema::IfcCartesianPoint>(0, 0, 1000.);
IfcSchema::IfcCartesianPoint* p2 = file.addTriplet<IfcSchema::IfcCartesianPoint>(0, 0, 0);
IfcSchema::IfcCartesianPoint* p3 = file.addTriplet<IfcSchema::IfcCartesianPoint>(0, R, 0);
IfcSchema::IfcCartesianPoint* p4 = file.addTriplet<IfcSchema::IfcCartesianPoint>(0, R, -R);
IfcSchema::IfcCartesianPoint* p5 = file.addTriplet<IfcSchema::IfcCartesianPoint>(0, R + length, -R);
/*first segment - line */
IfcSchema::IfcCartesianPoint::list::ptr points1(new IfcSchema::IfcCartesianPoint::list());
points1->push(p1);
points1->push(p2);
file.addEntities(points1->generalize());
IfcSchema::IfcPolyline* poly1 = new IfcSchema::IfcPolyline(points1);
file.addEntity(poly1);
IfcSchema::IfcCompositeCurveSegment* segment1 = new IfcSchema::IfcCompositeCurveSegment(IfcSchema::IfcTransitionCode::IfcTransitionCode_CONTINUOUS, true, poly1);
file.addEntity(segment1);
segments->push(segment1);
/*second segment - arc */
IfcSchema::IfcAxis2Placement3D* axis1 = new IfcSchema::IfcAxis2Placement3D(p3, file.addTriplet<IfcSchema::IfcDirection>(1, 0, 0), file.addTriplet<IfcSchema::IfcDirection>(0, 1, 0));
file.addEntity(axis1);
IfcSchema::IfcCircle* circle = new IfcSchema::IfcCircle(axis1, R);
file.addEntity(circle);
IfcEntityList::ptr trim1(new IfcEntityList);
IfcEntityList::ptr trim2(new IfcEntityList);
trim1->push(new IfcSchema::IfcParameterValue(180));
trim1->push(p2);
trim2->push(new IfcSchema::IfcParameterValue(270));
trim2->push(p4);
IfcSchema::IfcTrimmedCurve* trimmed_curve = new IfcSchema::IfcTrimmedCurve(circle, trim1, trim2, false, IfcSchema::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER);
file.addEntity(trimmed_curve);
IfcSchema::IfcCompositeCurveSegment* segment2 = new IfcSchema::IfcCompositeCurveSegment(IfcSchema::IfcTransitionCode::IfcTransitionCode_CONTSAMEGRADIENT, false, trimmed_curve);
file.addEntity(segment2);
segments->push(segment2);
/*third segment - line */
IfcSchema::IfcCartesianPoint::list::ptr points2(new IfcSchema::IfcCartesianPoint::list());
points2->push(p4);
points2->push(p5);
file.addEntities(points2->generalize());
IfcSchema::IfcPolyline* poly2 = new IfcSchema::IfcPolyline(points2);
file.addEntity(poly2);
IfcSchema::IfcCompositeCurveSegment* segment3 = new IfcSchema::IfcCompositeCurveSegment(IfcSchema::IfcTransitionCode::IfcTransitionCode_CONTINUOUS, true, poly2);
file.addEntity(segment3);
segments->push(segment3);
IfcSchema::IfcCompositeCurve* curve = new IfcSchema::IfcCompositeCurve(segments, false);
file.addEntity(curve);
IfcSchema::IfcSweptDiskSolid* solid = new IfcSchema::IfcSweptDiskSolid(curve, dia / 2, null, 0, 1);
IfcSchema::IfcRepresentation::list::ptr reps(new IfcSchema::IfcRepresentation::list());
IfcSchema::IfcRepresentationItem::list::ptr items(new IfcSchema::IfcRepresentationItem::list());
items->push(solid);
IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(
file.getSingle<IfcSchema::IfcRepresentationContext>(), S("Body"), S("AdvancedSweptSolid"), items);
reps->push(rep);
IfcSchema::IfcProductDefinitionShape* shape = new IfcSchema::IfcProductDefinitionShape(null, null, reps);
file.addEntity(shape);
rebar->setRepresentation(shape);
IfcSchema::IfcObjectPlacement* storey_placement = file.getSingle<IfcSchema::IfcBuildingStorey>()->ObjectPlacement();
rebar->setObjectPlacement(file.addLocalPlacement(storey_placement, 0, 0, 0));
}
int main()
{
IfcHierarchyHelper file;
file.header().file_name().name("ifc_curve_rebar.ifc");
create_curve_rebar(file);
std::ofstream f("ifc_curve_rebar.ifc");
f << file;
return 0;
}
/********************************************************************************
* *
* This file is part of IfcOpenShell. *
* *
* IfcOpenShell is free software: you can redistribute it and/or modify *
* it under the terms of the Lesser GNU General Public License as published by *
* the Free Software Foundation, either version 3.0 of the License, or *
* (at your option) any later version. *
* *
* IfcOpenShell 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 *
* Lesser GNU General Public License for more details. *
* *
* You should have received a copy of the Lesser GNU General Public License *
* along with this program. If not, see <http://www.gnu.org/licenses/>. *
* *
********************************************************************************/
/********************************************************************************
* *
* Example of curve rebar. *
* *
********************************************************************************/
#include <iostream>
#include <string>
#include <fstream>
#include "ifcparse\Ifc2x3.h"
#include "ifcparse\IfcUtil.h"
#include "ifcparse\IfcHierarchyHelper.h"
#include "ifcgeom\IfcGeom.h"
typedef std::string S;
typedef IfcParse::IfcGlobalId guid;
boost::none_t const null = boost::none;
void create_curve_rebar(IfcHierarchyHelper& file)
{
int dia = 24;
int R = 3 * dia;
int length = 12 * dia;
double crossSectionarea = M_PI * (dia / 2) * 2;
IfcSchema::IfcReinforcingBar* rebar = new IfcSchema::IfcReinforcingBar(
guid(), 0, S("test"), null,
null, 0, 0,
null, S("SR24"), //SteelGrade
dia, //diameter
crossSectionarea, //crossSectionarea = math.pi*(12.0/2)**2
0,
IfcSchema::IfcReinforcingBarRoleEnum::IfcReinforcingBarRoleEnum::IfcReinforcingBarRole_LIGATURE,
IfcSchema::IfcReinforcingBarSurfaceEnum::IfcReinforcingBarSurfaceEnum::IfcReinforcingBarSurface_PLAIN //PLAIN or TEXTURED
);
file.addBuildingProduct(rebar);
rebar->setOwnerHistory(file.getSingle<IfcSchema::IfcOwnerHistory>());
IfcSchema::IfcCompositeCurveSegment::list::ptr segments(new IfcSchema::IfcCompositeCurveSegment::list());
IfcSchema::IfcCartesianPoint* p1 = file.addTriplet<IfcSchema::IfcCartesianPoint>(0, 0, 1000.);
IfcSchema::IfcCartesianPoint* p2 = file.addTriplet<IfcSchema::IfcCartesianPoint>(0, 0, 0);
IfcSchema::IfcCartesianPoint* p3 = file.addTriplet<IfcSchema::IfcCartesianPoint>(0, R, 0);
IfcSchema::IfcCartesianPoint* p4 = file.addTriplet<IfcSchema::IfcCartesianPoint>(0, R, -R);
IfcSchema::IfcCartesianPoint* p5 = file.addTriplet<IfcSchema::IfcCartesianPoint>(0, R + length, -R);
/*first segment - line */
IfcSchema::IfcCartesianPoint::list::ptr points1(new IfcSchema::IfcCartesianPoint::list());
points1->push(p1);
points1->push(p2);
file.addEntities(points1->generalize());
IfcSchema::IfcPolyline* poly1 = new IfcSchema::IfcPolyline(points1);
file.addEntity(poly1);
IfcSchema::IfcCompositeCurveSegment* segment1 = new IfcSchema::IfcCompositeCurveSegment(IfcSchema::IfcTransitionCode::IfcTransitionCode_CONTINUOUS, true, poly1);
file.addEntity(segment1);
segments->push(segment1);
/*second segment - arc */
IfcSchema::IfcAxis2Placement3D* axis1 = new IfcSchema::IfcAxis2Placement3D(p3, file.addTriplet<IfcSchema::IfcDirection>(1, 0, 0), file.addTriplet<IfcSchema::IfcDirection>(0, 1, 0));
file.addEntity(axis1);
IfcSchema::IfcCircle* circle = new IfcSchema::IfcCircle(axis1, R);
file.addEntity(circle);
IfcEntityList::ptr trim1(new IfcEntityList);
IfcEntityList::ptr trim2(new IfcEntityList);
trim1->push(new IfcSchema::IfcParameterValue(180));
trim1->push(p2);
trim2->push(new IfcSchema::IfcParameterValue(270));
trim2->push(p4);
IfcSchema::IfcTrimmedCurve* trimmed_curve = new IfcSchema::IfcTrimmedCurve(circle, trim1, trim2, false, IfcSchema::IfcTrimmingPreference::IfcTrimmingPreference_PARAMETER);
file.addEntity(trimmed_curve);
IfcSchema::IfcCompositeCurveSegment* segment2 = new IfcSchema::IfcCompositeCurveSegment(IfcSchema::IfcTransitionCode::IfcTransitionCode_CONTSAMEGRADIENT, false, trimmed_curve);
file.addEntity(segment2);
segments->push(segment2);
/*third segment - line */
IfcSchema::IfcCartesianPoint::list::ptr points2(new IfcSchema::IfcCartesianPoint::list());
points2->push(p4);
points2->push(p5);
file.addEntities(points2->generalize());
IfcSchema::IfcPolyline* poly2 = new IfcSchema::IfcPolyline(points2);
file.addEntity(poly2);
IfcSchema::IfcCompositeCurveSegment* segment3 = new IfcSchema::IfcCompositeCurveSegment(IfcSchema::IfcTransitionCode::IfcTransitionCode_CONTINUOUS, true, poly2);
file.addEntity(segment3);
segments->push(segment3);
IfcSchema::IfcCompositeCurve* curve = new IfcSchema::IfcCompositeCurve(segments, false);
file.addEntity(curve);
IfcSchema::IfcSweptDiskSolid* solid = new IfcSchema::IfcSweptDiskSolid(curve, dia / 2, null, 0, 1);
IfcSchema::IfcRepresentation::list::ptr reps(new IfcSchema::IfcRepresentation::list());
IfcSchema::IfcRepresentationItem::list::ptr items(new IfcSchema::IfcRepresentationItem::list());
items->push(solid);
IfcSchema::IfcShapeRepresentation* rep = new IfcSchema::IfcShapeRepresentation(
file.getSingle<IfcSchema::IfcRepresentationContext>(), S("Body"), S("AdvancedSweptSolid"), items);
reps->push(rep);
IfcSchema::IfcProductDefinitionShape* shape = new IfcSchema::IfcProductDefinitionShape(null, null, reps);
file.addEntity(shape);
rebar->setRepresentation(shape);
IfcSchema::IfcObjectPlacement* storey_placement = file.getSingle<IfcSchema::IfcBuildingStorey>()->ObjectPlacement();
rebar->setObjectPlacement(file.addLocalPlacement(storey_placement, 0, 0, 0));
}
int main()
{
IfcHierarchyHelper file;
file.header().file_name().name("ifc_curve_rebar.ifc");
create_curve_rebar(file);
std::ofstream f("ifc_curve_rebar.ifc");
f << file;
return 0;
}
+17
View File
@@ -0,0 +1,17 @@
# ifc2ca
Files and scripts for the use of [`Code_Aster`](https://code-aster.org) in IFC-driven FEM analyses
### File Organisation
#### Scripts:
- [`ifc2ca.py`](ifc2ca.py): a python script to extract and create a `json` file from an `ifc` file
- [`scriptSalome.py`](scriptSalome.py): a python script to run in the [`Salome-Meca`](https://www.code-aster.org/spip.php?article303) environment. Creates the geometry and the mesh of the structure
- [`scriptCodeAster.py`](scriptCodeAster.py): a python script to create the input file (`.comm`) for Code_Aster
#### Analysis Models
A number of analysis models with all the relative input/output and script files are provided in [this repository](https://github.com/IfcOpenShell/analysis-models) within the IfcOpenShell Organization
---
### Current Status
Read [Change Log](changelog.md)
+504
View File
@@ -0,0 +1,504 @@
import json
import ifcopenshell
import os
class CA2IFC:
def __init__(self, inputFilename, outputFilename):
self.inputFilename = inputFilename
self.outputFilename = outputFilename
self.data = None
self.f = None
self.reps = {}
self.origin = None
self.xAxis = None
self.yAxis = None
self.zAxis = None
def convert(self):
# load json file
with open(self.inputFilename) as dataFile:
self.data = json.load(dataFile)
# initiate ifc file
self.f = ifcopenshell.file()
# create header
self.create_header()
# create global axes
globalAxes = self.create_global_axes()
localPlacement = self.f.createIfcLocalPlacement(None, globalAxes)
# TODO: create units
lengthUnit = self.f.createIfcSIUnit(None, "LENGTHUNIT", None, "METRE")
unitAssignment = self.f.createIfcUnitAssignment((lengthUnit,))
# create owner history
ownerHistory = self.create_owner_history()
# create representations and subrepresentations
self.reps = self.create_reference_subrep(globalAxes)
# create project and model
project = self.f.createIfcProject(
self.guid(), ownerHistory, "A Project", None, None, None, None, (self.reps["model"],), unitAssignment
)
model = self.f.createIfcStructuralAnalysisModel(
self.guid(),
ownerHistory,
self.data["name"],
None,
None,
"NOTDEFINED",
globalAxes,
None,
None,
localPlacement,
)
self.f.createIfcRelDeclares(self.guid(), ownerHistory, None, None, project, (model,))
# create materials
ifcMaterials = [None for _ in range(len(self.data["db"]["materials"]))]
for i, material in enumerate(self.data["db"]["materials"]):
ifcMaterials[i] = self.create_material(material)
# create profiles
ifcProfiles = [None for _ in range(len(self.data["db"]["profiles"]))]
for i, profile in enumerate(self.data["db"]["profiles"]):
ifcProfiles[i] = self.create_profile(profile)
# create material-profile sets
mpSets = list(
set([el["material"] + "-" + el["profile"] for el in self.data["elements"] if el["geometryType"] == "line"])
)
ifcMaterialProfileSets = [None for _ in range(len(mpSets))]
for i, mpSet in enumerate(mpSets):
materialIndex = [mat["ifcName"] for mat in self.data["db"]["materials"]].index(mpSet.split("-")[0])
profileIndex = [prof["ifcName"] for prof in self.data["db"]["profiles"]].index(mpSet.split("-")[1])
material = ifcMaterials[materialIndex]
profile = ifcProfiles[profileIndex]
matProf = self.f.createIfcMaterialProfile(
self.data["db"]["materials"][materialIndex]["name"]
+ " | "
+ self.data["db"]["profiles"][profileIndex]["profileName"],
None,
material,
profile,
)
ifcMaterialProfileSets[i] = self.f.createIfcMaterialProfileSet(None, None, (matProf,))
# create structural elements
ifcElements = [None for _ in range(len(self.data["elements"]))]
for i, el in enumerate(self.data["elements"]):
# geometry - product definition shape
prodDefShape = self.create_geometry(el)
if el["geometryType"] == "line":
# z axis TODO: group by elements
localZAxis = self.f.createIfcDirection(tuple(el["orientation"][2]))
# element
ifcElements[i] = self.f.createIfcStructuralCurveMember(
self.guid(),
ownerHistory,
el["name"],
None,
None,
localPlacement,
prodDefShape,
el["predefinedType"],
localZAxis,
)
if el["geometryType"] == "surface":
ifcElements[i] = self.f.createIfcStructuralSurfaceMember(
self.guid(),
ownerHistory,
el["name"],
None,
None,
localPlacement,
prodDefShape,
el["predefinedType"],
el["thickness"],
)
# create structural point connections
ifcConnections = [None for _ in range(len(self.data["connections"]))]
for i, conn in enumerate(self.data["connections"]):
# geometry - product definition shape
prodDefShape = self.create_geometry(conn)
# boundary conditions
if conn["appliedCondition"]:
bc = self.create_applied_conditions(conn["appliedCondition"], conn["geometryType"])
if conn["geometryType"] == "point":
appliedCondition = self.f.createIfcBoundaryNodeCondition(
None, bc["dx"], bc["dy"], bc["dz"], bc["drx"], bc["dry"], bc["drz"]
)
if conn["geometryType"] == "line":
appliedCondition = self.f.createIfcBoundaryEdgeCondition(
None, bc["dx"], bc["dy"], bc["dz"], bc["drx"], bc["dry"], bc["drz"]
)
if conn["geometryType"] == "surface":
appliedCondition = self.f.createIfcBoundaryFaceCondition(None, bc["dx"], bc["dy"], bc["dz"])
else:
appliedCondition = None
if conn["geometryType"] == "point":
# local axes
localAxes = self.create_orientation(conn["orientation"])
# connection
ifcConnections[i] = self.f.createIfcStructuralPointConnection(
self.guid(),
ownerHistory,
conn["name"],
None,
None,
localPlacement,
prodDefShape,
appliedCondition,
localAxes,
)
if conn["geometryType"] == "line":
# z axis TODO: group by elements
localZAxis = self.f.createIfcDirection(tuple(conn["orientation"][2]))
# connection
ifcConnections[i] = self.f.createIfcStructuralCurveConnection(
self.guid(),
ownerHistory,
conn["name"],
None,
None,
localPlacement,
prodDefShape,
appliedCondition,
localZAxis,
)
if conn["geometryType"] == "surface":
ifcConnections[i] = self.f.createIfcStructuralSurfaceConnection(
self.guid(), ownerHistory, conn["name"], None, None, localPlacement, prodDefShape, appliedCondition
)
# assign material-profile-sets
for i, mpSet in enumerate(mpSets):
groupOfElements = []
for j, el in enumerate(self.data["elements"]):
if el["geometryType"] == "line" and el["material"] + "-" + el["profile"] == mpSet:
groupOfElements.append(ifcElements[j])
if groupOfElements:
self.f.createIfcRelAssociatesMaterial(
self.guid(), ownerHistory, None, None, tuple(groupOfElements), ifcMaterialProfileSets[i]
)
# assign materials
for i, mat in enumerate(self.data["db"]["materials"]):
groupOfElements = []
for j, el in enumerate(self.data["elements"]):
if el["geometryType"] == "surface" and el["material"] == mat["ifcName"]:
groupOfElements.append(ifcElements[j])
if groupOfElements:
self.f.createIfcRelAssociatesMaterial(
self.guid(), ownerHistory, None, None, tuple(groupOfElements), ifcMaterials[i]
)
# create connections with elements
for i, el in enumerate(self.data["elements"]):
for conn in el["connections"]:
j = [c["ifcName"] for c in self.data["connections"]].index(conn["relatedConnection"])
geometryType = self.data["connections"][j]["geometryType"]
if conn["appliedCondition"]:
bc = self.create_applied_conditions(conn["appliedCondition"], geometryType)
if geometryType == "point":
appliedCondition = self.f.createIfcBoundaryNodeCondition(
None, bc["dx"], bc["dy"], bc["dz"], bc["drx"], bc["dry"], bc["drz"]
)
if geometryType == "line":
appliedCondition = self.f.createIfcBoundaryEdgeCondition(
None, bc["dx"], bc["dy"], bc["dz"], bc["drx"], bc["dry"], bc["drz"]
)
if geometryType == "surface":
appliedCondition = self.f.createIfcBoundaryFaceCondition(None, bc["dx"], bc["dy"], bc["dz"])
else:
appliedCondition = None
# local axes
localAxes = self.create_orientation(conn["orientation"])
if geometryType == "point":
if not conn["eccentricity"]:
self.f.createIfcRelConnectsStructuralMember(
self.guid(),
ownerHistory,
None,
None,
ifcElements[i],
ifcConnections[j],
appliedCondition,
None,
None,
localAxes,
)
else:
pointOnElement = self.f.createIfcCartesianPoint(tuple(conn["eccentricity"]["pointOnElement"]))
vector = conn["eccentricity"]["vector"]
connPointEcc = self.f.createIfcConnectionPointEccentricity(
pointOnElement, None, vector[0], vector[1], vector[2]
)
self.f.createIfcRelConnectsWithEccentricity(
self.guid(),
ownerHistory,
None,
None,
ifcElements[i],
ifcConnections[j],
appliedCondition,
None,
None,
localAxes,
connPointEcc,
)
if geometryType in ["line", "surface"]:
self.f.createIfcRelConnectsStructuralMember(
self.guid(),
ownerHistory,
None,
None,
ifcElements[i],
ifcConnections[j],
appliedCondition,
None,
None,
localAxes,
)
# assign elements and connections to group
self.f.createIfcRelAssignsToGroup(
self.guid(), ownerHistory, None, None, tuple(ifcElements + ifcConnections), None, model
)
# finalize ifc file
self.f.write(self.outputFilename)
def guid(self):
return ifcopenshell.guid.new()
def create_header(self):
self.f.wrapped_data.header.file_name.name = os.path.basename(self.outputFilename)
def create_global_axes(self):
self.xAxis = self.f.createIfcDirection((1.0, 0.0, 0.0))
self.yAxis = self.f.createIfcDirection((0.0, 1.0, 0.0))
self.zAxis = self.f.createIfcDirection((0.0, 0.0, 1.0))
self.origin = self.f.createIfcCartesianPoint((0.0, 0.0, 0.0))
axes = self.f.createIfcAxis2Placement3D(self.origin, self.zAxis, self.xAxis)
return axes
def create_orientation(self, orientation):
xAxis = self.f.createIfcDirection(tuple(orientation[0]))
zAxis = self.f.createIfcDirection(tuple(orientation[2]))
axes = self.f.createIfcAxis2Placement3D(self.origin, zAxis, xAxis)
return axes
def create_owner_history(self):
actor = self.f.createIfcActorRole("ENGINEER", None, None)
person = self.f.createIfcPerson("Christovasilis", None, "Ioannis", None, None, None, (actor,))
organization = self.f.createIfcOrganization(
None,
"IfcOpenShell",
"IfcOpenShell, an open source (LGPL) software library that helps users and software developers to work with the IFC file format.",
)
p_o = self.f.createIfcPersonAndOrganization(person, organization)
application = self.f.createIfcApplication(organization, "v0.0.x", "IFC2CA", "IFC2CA")
ownerHistory = self.f.createIfcOwnerHistory(p_o, application, "READWRITE", None, None, p_o, application)
return ownerHistory
def create_reference_subrep(self, globalAxes):
modelRep = self.f.createIfcGeometricRepresentationContext(None, "Model", 3, 1.0e-05, globalAxes, None)
bodySubRep = self.f.createIfcGeometricRepresentationSubContext(
"Body", "Model", None, None, None, None, modelRep, None, "MODEL_VIEW", None
)
refSubRep = self.f.createIfcGeometricRepresentationSubContext(
"Reference", "Model", None, None, None, None, modelRep, None, "GRAPH_VIEW", None
)
return {"model": modelRep, "body": bodySubRep, "reference": refSubRep}
def create_material(self, material):
ifcMaterial = self.f.createIfcMaterial(material["name"], None, material["category"])
mechProps = []
if "youngModulus" in material["mechProps"]:
youngModulus = self.f.createIfcPropertySingleValue(
"YoungModulus", None, self.f.createIfcModulusOfElasticityMeasure(material["mechProps"]["youngModulus"])
)
mechProps.append(youngModulus)
if "shearModulus" in material["mechProps"]:
shearModulus = self.f.createIfcPropertySingleValue(
"ShearModulus", None, self.f.createIfcModulusOfElasticityMeasure(material["mechProps"]["shearModulus"])
)
mechProps.append(shearModulus)
if "poissonRatio" in material["mechProps"]:
poissonRatio = self.f.createIfcPropertySingleValue(
"PoissonRatio", None, self.f.createIfcPositiveRatioMeasure(material["mechProps"]["poissonRatio"])
)
mechProps.append(poissonRatio)
if mechProps:
self.f.createIfcMaterialProperties(
"Pset_MaterialMechanical", material["name"], tuple(mechProps), ifcMaterial
)
commonProps = []
if "massDensity" in material["commonProps"]:
massDensity = self.f.createIfcPropertySingleValue(
"MassDensity", None, self.f.createIfcMassDensityMeasure(material["commonProps"]["massDensity"])
)
commonProps.append(massDensity)
if commonProps:
self.f.createIfcMaterialProperties("Pset_MaterialCommon", material["name"], tuple(commonProps), ifcMaterial)
return ifcMaterial
def create_profile(self, profile):
if profile["profileShape"] == "rectangular":
ifcProfile = self.f.createIfcRectangleProfileDef(
profile["profileType"], profile["profileName"], None, profile["xDim"], profile["yDim"]
)
if profile["profileShape"] == "iSymmetrical":
ifcProfile = self.f.createIfcIShapeProfileDef(
profile["profileType"],
profile["profileName"],
None,
profile["commonProps"]["overallWidth"],
profile["commonProps"]["overallDepth"],
profile["commonProps"]["webThickness"],
profile["commonProps"]["flangeThickness"],
profile["commonProps"]["filletRadius"],
)
mechProps = []
if "massPerLength" in profile["mechProps"]:
massPerLength = self.f.createIfcPropertySingleValue(
"MassPerLength", None, self.f.createIfcMassPerLengthMeasure(profile["mechProps"]["massPerLength"])
)
mechProps.append(massPerLength)
if "crossSectionArea" in profile["mechProps"]:
crossSectionArea = self.f.createIfcPropertySingleValue(
"CrossSectionArea", None, self.f.createIfcAreaMeasure(profile["mechProps"]["crossSectionArea"])
)
mechProps.append(crossSectionArea)
if "momentOfInertiaY" in profile["mechProps"]:
momentOfInertiaY = self.f.createIfcPropertySingleValue(
"MomentOfInertiaY",
None,
self.f.createIfcMomentOfInertiaMeasure(profile["mechProps"]["momentOfInertiaY"]),
)
mechProps.append(momentOfInertiaY)
if "momentOfInertiaZ" in profile["mechProps"]:
momentOfInertiaZ = self.f.createIfcPropertySingleValue(
"MomentOfInertiaZ",
None,
self.f.createIfcMomentOfInertiaMeasure(profile["mechProps"]["momentOfInertiaZ"]),
)
mechProps.append(momentOfInertiaZ)
if "torsionalConstantX" in profile["mechProps"]:
torsionalConstantX = self.f.createIfcPropertySingleValue(
"TorsionalConstantX",
None,
self.f.createIfcMomentOfInertiaMeasure(profile["mechProps"]["torsionalConstantX"]),
)
mechProps.append(torsionalConstantX)
if mechProps:
self.f.createIfcProfileProperties(
"Pset_ProfileMechanical", profile["profileName"], tuple(mechProps), ifcProfile
)
return ifcProfile
def create_geometry(self, object):
if object["geometryType"] == "point":
point = self.f.createIfcCartesianPoint(tuple(object["geometry"]))
vertex = self.f.createIfcVertexPoint(point)
vertexTopologyRep = self.f.createIfcTopologyRepresentation(
self.reps["reference"], "Reference", "Vertex", (vertex,)
)
vertexProdDefShape = self.f.createIfcProductDefinitionShape(None, None, (vertexTopologyRep,))
return vertexProdDefShape
if object["geometryType"] == "line":
startPoint = self.f.createIfcCartesianPoint(tuple(object["geometry"][0]))
startVertex = self.f.createIfcVertexPoint(startPoint)
endPoint = self.f.createIfcCartesianPoint(tuple(object["geometry"][1]))
endVertex = self.f.createIfcVertexPoint(endPoint)
edge = self.f.createIfcEdge(startVertex, endVertex)
edgeTopologyRep = self.f.createIfcTopologyRepresentation(
self.reps["reference"], "Reference", "Edge", (edge,)
)
edgeProdDefShape = self.f.createIfcProductDefinitionShape(None, None, (edgeTopologyRep,))
return edgeProdDefShape
if object["geometryType"] == "surface":
verts = [None for _ in range(len(object["geometry"]))]
for i, p in enumerate(object["geometry"]):
point = self.f.createIfcCartesianPoint(tuple(p))
verts[i] = self.f.createIfcVertexPoint(point)
orientedEdges = [None for _ in range(len(object["geometry"]))]
for i, v in enumerate(verts):
v2Index = (i + 1) if i < len(verts) - 1 else 0
edge = self.f.createIfcEdge(v, verts[v2Index])
orientedEdges[i] = self.f.createIfcOrientedEdge(None, None, edge, True)
edgeLoop = self.f.createIfcEdgeLoop(tuple(orientedEdges))
localAxes = self.create_orientation(object["orientation"])
plane = self.f.createIfcPlane(localAxes)
faceBound = self.f.createIfcFaceBound(edgeLoop, True)
face = self.f.createIfcFaceSurface((faceBound,), plane, True)
faceTopologyRep = self.f.createIfcTopologyRepresentation(
self.reps["reference"], "Reference", "Face", (face,)
)
faceProdDefShape = self.f.createIfcProductDefinitionShape(None, None, (faceTopologyRep,))
return faceProdDefShape
def create_applied_conditions(self, bc, geometryType):
for dof in ["dx", "dy", "dz"]:
if isinstance(bc[dof], bool):
bc[dof] = self.f.createIfcBoolean(bc[dof])
else:
if geometryType == "point":
bc[dof] = self.f.createIfcLinearStiffnessMeasure(bc[dof])
if geometryType == "line":
bc[dof] = self.f.createIfcModulusOfLinearSubgradeReactionMeasure(bc[dof])
if geometryType == "surface":
bc[dof] = self.f.createIfcModulusOfSubgradeReactionMeasure(bc[dof])
for dof in ["drx", "dry", "drz"]:
if isinstance(bc[dof], bool):
bc[dof] = self.f.createIfcBoolean(bc[dof])
else:
if geometryType == "point":
bc[dof] = self.f.createIfcRotationalStiffnessMeasure(bc[dof])
if geometryType == "line":
bc[dof] = self.f.createIfcModulusOfRotationalSubgradeReactionMeasure(bc[dof])
return bc
if __name__ == "__main__":
inputFilename = "structure_01.json"
outputFilename = "structure_01.ifc"
ca2ifc = CA2IFC(inputFilename, outputFilename)
ca2ifc.convert()
+34
View File
@@ -0,0 +1,34 @@
## A change log of the ifc2ca files
##### 14/10/20
- Add curve connections betweeen elements and as supports according to the defined orientation - stiffness is not yet considered
##### 17/08/20
- Add rigid links for point connection to elements
##### 14/07/20
- Add internal springs for point connection to elements according to the defined orientation
- Add external springs for point connections according to the defined orientation
##### 27/05/20
- Add orientation for point, curve and surface geometries
- Calculate final geometry and orientation based on object placement transformation
- Add warnings in the json file to show any corrections considered while parsing the ifc file from ETABS with a model with rigid links
- Reduce file size by adding material and profile db in the json file and referencing them in the element objects
- Implement internal releases for curve-to-point connections with any arbitrary orientation
##### 22/03/20
- Calculation of section properties for I symmetric profile if not provided (assuming fillet radius is zero)
- Added geometry of planar structural surface members
- Refactored the ifc2ca.py script
- Added support for rigid links
- Added advanced meshing script to correctly simulate connections and independent meshing of structural elements (no common nodes)
##### 26/02/20
- Changed section to profile and added I profile
- Modified material and profile schema with mechanical and common properties
- Added geometry identification for point connection from representation
- Added connections along with supports based on the number of elements a connection is applied to
##### 09/02/20
- First implementation for straight structural curve elements and point connections
+547
View File
@@ -0,0 +1,547 @@
from __future__ import division
from __future__ import print_function
import json
import ifcopenshell
import numpy as np
class IFC2CA:
def __init__(self, filename):
self.filename = filename
self.file = None
self.result = {}
self.warnings = []
self.tol = 1e-06
def convert(self):
self.file = ifcopenshell.open(self.filename)
for model in self.file.by_type("IfcStructuralAnalysisModel"):
elements = self.get_structural_items(model, item_type="IfcStructuralMember")
connections = self.get_structural_items(model, item_type="IfcStructuralConnection")
materialdb = []
materials = list(dict.fromkeys([e["material"] for e in elements]))
for mat in [mat for mat in materials if mat]:
id = int(mat.split("|")[1])
material = self.get_material_properties(self.file.by_id(id))
material["relatedElements"] = [
e["ifcName"] for e in elements if "material" in e and e["material"] == mat
]
materialdb.append(material)
profiledb = []
profiles = list(dict.fromkeys([e["profile"] for e in elements if "profile" in e]))
for prof in [prof for prof in profiles if prof]:
id = int(prof.split("|")[1])
profile = self.get_profile_properties(self.file.by_id(id))
profile["relatedElements"] = [e["ifcName"] for e in elements if "profile" in e and e["profile"] == prof]
profiledb.append(profile)
self.result = {
"ifcName": model.is_a() + "|" + str(model.id()),
"name": model.Name,
"id": model.GlobalId,
"elements": elements,
"connections": connections,
"db": {"materials": materialdb, "profiles": profiledb},
"warnings": self.warnings,
}
print('Model "%s" converted' % model.Name)
print("Number of elements: ", len(elements))
print("Number of connections: ", len(connections))
print("Number of materials: ", len(materialdb))
print("Number of profiles: ", len(profiledb))
print("")
break
def get_structural_items(self, model, item_type="IfcStructuralItem"):
items = []
for group in model.IsGroupedBy:
for item in group.RelatedObjects:
if not item.is_a(item_type):
continue
data = self.get_item_data(item)
if data:
items.append(data)
return items
def get_item_data(self, item):
transformation = self.get_transformation(item.ObjectPlacement)
if item.is_a("IfcStructuralCurveMember"):
representation = self.get_representation(item, "Edge")
material_profile = self.get_material_profile(item)
if not representation:
self.warnings.append(
"No representation defined for %s. Member excluded" % (item.is_a() + "|" + str(item.id()))
)
return
if not material_profile:
self.warnings.append("No material defined for in %s" % (item.is_a() + "|" + str(item.id())))
self.warnings.append("No profile defined for in %s" % (item.is_a() + "|" + str(item.id())))
materialId = None
profileId = None
else:
material = material_profile.Material
materialId = material.is_a() + "|" + str(material.id())
profile = material_profile.Profile
profileId = profile.is_a() + "|" + str(profile.id())
geometry = self.get_geometry(representation)
orientation = self.get_1D_orientation(geometry, item.Axis)
connections = self.get_connection_data(item.ConnectedBy)
for conn in connections:
if not conn["orientation"]:
conn["orientation"] = orientation
# --> Correct pointOnElement for eccentricity connection for ETABS files
length = np.linalg.norm(np.array(geometry[1]) - np.array(geometry[0]))
for c in connections:
if c["eccentricity"]:
if np.linalg.norm(np.array(c["eccentricity"]["pointOnElement"])) > length + self.tol:
print(np.linalg.norm(np.array(c["eccentricity"]["pointOnElement"])), ">", length)
self.warnings.append("Eccentricity in %s corrected" % (item.is_a() + "|" + str(item.id())))
c["eccentricity"]["pointOnElement"][0] = length
# End <--
if transformation:
geometry = self.transform_vectors(geometry, transformation)
orientation = self.transform_vectors(orientation, transformation, include_translation=False)
for c in connections:
c["orientation"] = self.transform_vectors(
c["orientation"], transformation, include_translation=False
)
if c["eccentricity"]:
c["eccentricity"]["vector"] = self.transform_vectors(
c["eccentricity"]["vector"], transformation, include_translation=False
)
return {
"ifcName": item.is_a() + "|" + str(item.id()),
"name": item.Name,
"id": item.GlobalId,
"geometryType": "line",
"predefinedType": item.PredefinedType,
"geometry": geometry,
"orientation": orientation,
"material": materialId,
"profile": profileId,
"connections": connections,
}
elif item.is_a("IfcStructuralSurfaceMember"):
representation = self.get_representation(item, "Face")
material = self.get_material_profile(item)
if not representation:
self.warnings.append(
"No representation defined for %s. Member excluded" % (item.is_a() + "|" + str(item.id()))
)
return
if not material:
self.warnings.append("No material defined for in %s" % (item.is_a() + "|" + str(item.id())))
materialId = None
else:
materialId = material.is_a() + "|" + str(material.id())
geometry = self.get_geometry(representation)
orientation = self.get_2D_orientation(representation)
connections = self.get_connection_data(item.ConnectedBy)
for conn in connections:
if not conn["orientation"]:
conn["orientation"] = orientation
if transformation:
geometry = self.transform_vectors(geometry, transformation)
orientation = self.transform_vectors(orientation, transformation, include_translation=False)
for c in connections:
c["orientation"] = self.transform_vectors(
c["orientation"], transformation, include_translation=False
)
return {
"ifcName": item.is_a() + "|" + str(item.id()),
"name": item.Name,
"id": item.GlobalId,
"geometryType": "surface",
"predefinedType": item.PredefinedType,
"thickness": item.Thickness,
"geometry": geometry,
"orientation": orientation,
"material": materialId,
"connections": connections,
}
elif item.is_a("IfcStructuralPointConnection"):
representation = self.get_representation(item, "Vertex")
if not representation:
self.warnings.append(
"No representation defined for %s. Connection excluded" % (item.is_a() + "|" + str(item.id()))
)
return
geometry = self.get_geometry(representation)
orientation = self.get_0D_orientation(item.ConditionCoordinateSystem)
if not orientation:
orientation = np.eye(3).tolist()
if transformation:
geometry = self.transform_vectors(geometry, transformation)
orientation = self.transform_vectors(orientation, transformation, include_translation=False)
return {
"ifcName": item.is_a() + "|" + str(item.id()),
"name": item.Name,
"id": item.GlobalId,
"geometryType": "point",
"geometry": geometry,
"orientation": orientation,
"appliedCondition": self.get_connection_input(item, "point"),
"relatedElements": [con.is_a() + "|" + str(con.id()) for con in item.ConnectsStructuralMembers],
}
elif item.is_a("IfcStructuralCurveConnection"):
representation = self.get_representation(item, "Edge")
if not representation:
self.warnings.append(
"No representation defined for %s. Connection excluded" % (item.is_a() + "|" + str(item.id()))
)
return
geometry = self.get_geometry(representation)
orientation = self.get_1D_orientation(geometry, item.Axis)
if not orientation:
orientation = np.eye(3).tolist()
if transformation:
geometry = self.transform_vectors(geometry, transformation)
orientation = self.transform_vectors(orientation, transformation, include_translation=False)
return {
"ifcName": item.is_a() + "|" + str(item.id()),
"name": item.Name,
"id": item.GlobalId,
"geometryType": "line",
"geometry": geometry,
"orientation": orientation,
"appliedCondition": self.get_connection_input(item, "line"),
"relatedElements": [con.is_a() + "|" + str(con.id()) for con in item.ConnectsStructuralMembers],
}
def get_transformation(self, placement):
if not placement:
return None
if placement.is_a("IfcLocalPlacement"):
if placement.PlacementRelTo:
print("Warning! Object Placement with PlacementRelTo attribute is not supported and will be neglected")
axes = placement.RelativePlacement
location = np.array(self.get_coordinate(axes.Location))
if axes.Axis and axes.RefDirection:
xAxis = np.array(axes.RefDirection.DirectionRatios) # this can be not accurate (in the xz plane)
zAxis = np.array(axes.Axis.DirectionRatios)
zAxis /= np.linalg.norm(zAxis)
yAxis = np.cross(zAxis, xAxis)
yAxis /= np.linalg.norm(yAxis)
xAxis = np.cross(yAxis, zAxis)
xAxis /= np.linalg.norm(xAxis)
else:
if np.allclose(location, np.array([0.0, 0.0, 0.0])):
return None
xAxis = np.array([1.0, 0.0, 0.0])
yAxis = np.array([0.0, 1.0, 0.0])
zAxis = np.array([0.0, 0.0, 1.0])
if (
np.allclose(location, np.array([0.0, 0.0, 0.0]))
and np.allclose(xAxis, np.array([1.0, 0.0, 0.0]))
and np.allclose(yAxis, np.array([0.0, 1.0, 0.0]))
and np.allclose(zAxis, np.array([0.0, 0.0, 1.0]))
):
return None
return {"location": location, "rotationMatrix": np.array([xAxis, yAxis, zAxis]).transpose()}
else:
print(
"Warning! Object Placement is of type %s, which is not supported. Default considered" % placement.is_a()
)
return None
def get_representation(self, element, rep_type):
if not element.Representation:
return None
for representation in element.Representation.Representations:
rep = self.get_specific_representation(representation, "Reference", rep_type)
if rep:
return rep
else:
# print('Trying without rep identifier')
for representation in element.Representation.Representations:
rep = self.get_specific_representation(representation, None, rep_type)
if rep:
return rep
def get_specific_representation(self, representation, rep_id, rep_type):
if (
representation.RepresentationIdentifier == rep_id or rep_id is None
) and representation.RepresentationType == rep_type:
return representation
if representation.RepresentationType == "MappedRepresentation":
return self.get_specific_representation(
representation.Items[0].MappingSource.MappedRepresentation, rep_id, rep_type
)
def get_geometry(self, representation):
# Maybe IfcOpenShell can use create_shape here to simplify this, but
# supposedly structural models are very simple anyway, so perhaps we
# can do without it.
item = representation.Items[0]
if item.is_a("IfcEdge"):
return [
self.get_coordinate(item.EdgeStart.VertexGeometry),
self.get_coordinate(item.EdgeEnd.VertexGeometry),
]
elif item.is_a("IfcFaceSurface"):
edges = item.Bounds[0].Bound.EdgeList
coords = []
for edge in edges:
coords.append(self.get_coordinate(edge.EdgeElement.EdgeStart.VertexGeometry))
return coords
elif item.is_a("IfcVertexPoint"):
return self.get_coordinate(item.VertexGeometry)
def get_coordinate(self, point):
if point.is_a("IfcCartesianPoint"):
return list(point.Coordinates)
def get_0D_orientation(self, axes):
if axes and axes.Axis and axes.RefDirection:
xAxis = np.array(
axes.RefDirection.DirectionRatios
) # this can be not strictly perpendicular (in the xz plane)
zAxis = np.array(axes.Axis.DirectionRatios)
zAxis /= np.linalg.norm(zAxis)
yAxis = np.cross(zAxis, xAxis)
yAxis /= np.linalg.norm(yAxis)
xAxis = np.cross(yAxis, zAxis)
xAxis /= np.linalg.norm(xAxis)
return [xAxis.tolist(), yAxis.tolist(), zAxis.tolist()]
else: # return None and copy the elements orientation
return None
def get_1D_orientation(self, geometry, zAxis):
xAxis = np.array(geometry[1]) - np.array(geometry[0])
xAxis /= np.linalg.norm(xAxis)
zAxis = np.array(zAxis.DirectionRatios) # this can be not strictly perpendicular (in the xz plane)
yAxis = np.cross(zAxis, xAxis)
yAxis /= np.linalg.norm(yAxis)
zAxis = np.cross(xAxis, yAxis)
zAxis /= np.linalg.norm(zAxis)
return [xAxis.tolist(), yAxis.tolist(), zAxis.tolist()]
def get_2D_orientation(self, representation):
item = representation.Items[0]
if item.is_a("IfcFaceSurface"):
item.SameSense
axes = item.FaceSurface.Position
orientation = self.get_0D_orientation(axes)
if not item.SameSense:
orientation = [[-v for v in vec] for vec in orientation]
return orientation
def transform_vectors(self, geometry, trsf, include_translation=True):
if not any(isinstance(el, list) for el in geometry): # single point which contains no list
geometry = [geometry]
globalGeometry = []
for p in geometry:
gp = trsf["rotationMatrix"].dot(np.array(p))
if include_translation:
gp += trsf["location"]
globalGeometry.append(gp.tolist())
if len(globalGeometry) == 1: # single point
globalGeometry = globalGeometry[0]
return globalGeometry
def get_material_profile(self, element):
if not element.HasAssociations:
return None
for association in element.HasAssociations:
if not association.is_a("IfcRelAssociatesMaterial"):
continue
material = association.RelatingMaterial
if material.is_a("IfcMaterialProfileSet"):
# For now, we only deal with a single profile
return material.MaterialProfiles[0]
if material.is_a("IfcMaterialProfileSetUsage"):
return material.ForProfileSet.MaterialProfiles[0]
if material.is_a("IfcMaterial"):
return material
def get_material_properties(self, material):
psets = material.HasProperties
if self.get_pset_properties(psets, "Pset_MaterialMechanical"):
mechProps = self.get_pset_properties(psets, "Pset_MaterialMechanical")
else:
mechProps = self.get_pset_properties(psets, None)
if self.get_pset_properties(psets, "Pset_MaterialCommon"):
commonProps = self.get_pset_properties(psets, "Pset_MaterialCommon")
else:
commonProps = self.get_pset_properties(psets, None)
return {
"ifcName": material.is_a() + "|" + str(material.id()),
"name": material.Name,
"category": material.Category,
"mechProps": mechProps,
"commonProps": commonProps,
}
def get_pset_property(self, psets, pset_name, prop_name):
for pset in psets:
if pset.Name == pset_name or pset_name is None:
for prop in pset.Properties:
if prop.Name == prop_name:
return prop.NominalValue.wrappedValue
def get_pset_properties(self, psets, pset_name):
for pset in psets:
if pset.Name == pset_name or pset_name is None:
d = {}
for prop in pset.Properties:
propName = prop.Name[0].lower() + prop.Name[1:]
d[propName] = prop.NominalValue.wrappedValue
return d
def get_profile_properties(self, profile):
if profile.is_a("IfcRectangleProfileDef"):
return {
"ifcName": profile.is_a() + "|" + str(profile.id()),
"profileName": profile.ProfileName,
"profileType": profile.ProfileType,
"profileShape": "rectangular",
"xDim": profile.XDim,
"yDim": profile.YDim,
}
if profile.is_a("IfcIShapeProfileDef"):
psets = profile.HasProperties
if self.get_pset_properties(psets, "Pset_ProfileMechanical"):
mechProps = self.get_pset_properties(psets, "Pset_ProfileMechanical")
else:
mechProps = self.get_i_section_properties(profile, "iSymmetrical")
return {
"ifcName": profile.is_a() + "|" + str(profile.id()),
"profileName": profile.ProfileName,
"profileType": profile.ProfileType,
"profileShape": "iSymmetrical",
"mechProps": mechProps,
"commonProps": {
"flangeThickness": profile.FlangeThickness,
"webThickness": profile.WebThickness,
"overallDepth": profile.OverallDepth,
"overallWidth": profile.OverallWidth,
"filletRadius": profile.FilletRadius,
},
}
def get_connection_data(self, itemList):
return [
{
"ifcName": rel.is_a() + "|" + str(rel.id()),
"id": rel.GlobalId,
"relatingElement": rel.RelatingStructuralMember.is_a() + "|" + str(rel.RelatingStructuralMember.id()),
"relatedConnection": rel.RelatedStructuralConnection.is_a()
+ "|"
+ str(rel.RelatedStructuralConnection.id()),
"orientation": self.get_0D_orientation(rel.ConditionCoordinateSystem),
"appliedCondition": self.get_connection_input(
rel, self.get_geometry_type_from_connection(rel.RelatedStructuralConnection)
),
"eccentricity": None
if not rel.is_a("IfcRelConnectsWithEccentricity")
else {
"vector": [
0.0
if not rel.ConnectionConstraint.EccentricityInX
else rel.ConnectionConstraint.EccentricityInX,
0.0
if not rel.ConnectionConstraint.EccentricityInY
else rel.ConnectionConstraint.EccentricityInY,
0.0
if not rel.ConnectionConstraint.EccentricityInZ
else rel.ConnectionConstraint.EccentricityInZ,
],
"pointOnElement": self.get_coordinate(rel.ConnectionConstraint.PointOnRelatingElement),
},
}
for rel in itemList
]
def get_geometry_type_from_connection(self, connection):
if connection.is_a("IfcStructuralPointConnection"):
return "point"
if connection.is_a("IfcStructuralCurveConnection"):
return "line"
if connection.is_a("IfcStructuralSurfaceConnection"):
return "surface"
def get_connection_input(self, connection, geometryType):
if connection.AppliedCondition:
if geometryType == "point":
return {
"dx": connection.AppliedCondition.TranslationalStiffnessX.wrappedValue,
"dy": connection.AppliedCondition.TranslationalStiffnessY.wrappedValue,
"dz": connection.AppliedCondition.TranslationalStiffnessZ.wrappedValue,
"drx": connection.AppliedCondition.RotationalStiffnessX.wrappedValue,
"dry": connection.AppliedCondition.RotationalStiffnessY.wrappedValue,
"drz": connection.AppliedCondition.RotationalStiffnessZ.wrappedValue,
}
if geometryType == "line":
return {
"dx": connection.AppliedCondition.TranslationalStiffnessByLengthX.wrappedValue,
"dy": connection.AppliedCondition.TranslationalStiffnessByLengthY.wrappedValue,
"dz": connection.AppliedCondition.TranslationalStiffnessByLengthZ.wrappedValue,
"drx": connection.AppliedCondition.RotationalStiffnessByLengthX.wrappedValue,
"dry": connection.AppliedCondition.RotationalStiffnessByLengthY.wrappedValue,
"drz": connection.AppliedCondition.RotationalStiffnessByLengthZ.wrappedValue,
}
if geometryType == "surface":
return {
"dx": connection.AppliedCondition.TranslationalStiffnessByAreaX.wrappedValue,
"dy": connection.AppliedCondition.TranslationalStiffnessByAreaY.wrappedValue,
"dz": connection.AppliedCondition.TranslationalStiffnessByAreaZ.wrappedValue,
}
return connection.AppliedCondition
def get_i_section_properties(self, profile, profileShape):
if profileShape == "iSymmetrical":
tf = profile.FlangeThickness
tw = profile.WebThickness
h = profile.OverallDepth
b = profile.OverallWidth
A = b * h - (b - tw) * (h - 2 * tf)
Iy = b * (h ** 3) / 12 - (b - tw) * ((h - 2 * tf) ** 3) / 12
Iz = (2 * tf) * (b ** 3) / 12 + (h - 2 * tf) * (tw ** 3) / 12
Jx = 1 / 3 * ((h - tf) * (tw ** 3) + 2 * b * (tf ** 3))
return {"crossSectionArea": A, "momentOfInertiaY": Iy, "momentOfInertiaZ": Iz, "torsionalConstantX": Jx}
if __name__ == "__main__":
fileNames = ["cantilever_01", "portal_01", "grid_of_beams", "slab_01", "structure_01"]
files = fileNames
for fileName in files:
BASE_PATH = "/home/jesusbill/Dev-Projects/github.com/IfcOpenShell/analysis-models/ifcFiles/"
ifc2ca = IFC2CA(BASE_PATH + fileName + ".ifc")
ifc2ca.convert()
with open(BASE_PATH + fileName + ".json", "w") as f:
f.write(json.dumps(ifc2ca.result, indent=4))
+903
View File
@@ -0,0 +1,903 @@
import json
import numpy as np
import itertools
flatten = itertools.chain.from_iterable
class COMMANDFILE:
def __init__(self, dataFilename, asterFilename):
self.dataFilename = dataFilename
self.asterFilename = asterFilename
self.create()
def getGroupName(self, name):
info = name.split("|")
sortName = "".join(c for c in info[0] if c.isupper())
return str(sortName + "_" + info[1])
def create(self):
AccelOfGravity = 9.806 # m/sec^2
# Read data from input file
with open(self.dataFilename) as dataFile:
data = json.load(dataFile)
elements = data["elements"]
connections = data["connections"]
# --> Delete this reference data and repopulate it with the objects
# while going through elements
for conn in connections:
conn["relatedElements"] = []
self.calculateRestraints(conn)
for el in elements:
for rel in el["connections"]:
conn = [c for c in connections if c["ifcName"] == rel["relatedConnection"]][0]
rel["conn_string"] = None
if conn["geometryType"] == "point":
rel["conn_string"] = "_0DC_"
rel["springGroupName"] = (
self.getGroupName(rel["relatingElement"])
+ "_1DS_"
+ self.getGroupName(rel["relatedConnection"])
)
if conn["geometryType"] == "line":
rel["conn_string"] = "_1DC_"
rel["springGroupName"] = None
if conn["geometryType"] == "surface":
rel["conn_string"] = "_2DC_"
rel["springGroupName"] = None
rel["groupName1"] = (
self.getGroupName(rel["relatingElement"])
+ rel["conn_string"]
+ self.getGroupName(rel["relatedConnection"])
)
if rel["eccentricity"]:
rel["groupName2"] = (
self.getGroupName(rel["relatedConnection"])
+ "_0DC_"
+ self.getGroupName(rel["relatingElement"])
)
rel["index"] = len(conn["relatedElements"]) + 1
rel["unifiedGroupName"] = self.getGroupName(rel["relatedConnection"]) + "_0DC_%g" % rel["index"]
else:
rel["groupName2"] = self.getGroupName(rel["relatedConnection"])
self.calculateConstraints(rel)
conn["relatedElements"].append(rel)
# End <--
materials = data["db"]["materials"]
profiles = data["db"]["profiles"]
edgeGroupNames = tuple([self.getGroupName(el["ifcName"]) for el in elements if el["geometryType"] == "line"])
faceGroupNames = tuple([self.getGroupName(el["ifcName"]) for el in elements if el["geometryType"] == "surface"])
point0DGroupNames = tuple(
[self.getGroupName(el["ifcName"]) + "_0D" for el in connections if el["geometryType"] == "point"]
)
spring1DGroupNames = tuple(
flatten(
[[rel["springGroupName"] for rel in el["connections"] if rel["springGroupName"]] for el in elements]
)
)
point1DGroupNames = tuple(
[self.getGroupName(el["ifcName"]) + "_0D" for el in connections if el["geometryType"] == "line"]
)
unifiedConnection = False
rigidLinkGroupNames = []
for conn in connections:
conn["unifiedGroupNames"] = [
rel["unifiedGroupName"] for rel in conn["relatedElements"] if rel["eccentricity"]
]
# if not conn['appliedCondition'] and len(conn['unifiedGroupNames']) == 1:
# conn['appliedCondition'] = {
# 'dx': True,
# 'dy': True,
# 'dz': True
# }
if len(conn["unifiedGroupNames"]) >= 1:
conn["unifiedGroupNames"].insert(0, self.getGroupName(conn["ifcName"]))
conn["unifiedGroupNames"] = tuple(conn["unifiedGroupNames"])
unifiedConnection = True
rigidLinkGroupNames.extend(
[
self.getGroupName(rel["relatingElement"]) + "_1DR_" + self.getGroupName(conn["ifcName"])
for rel in conn["relatedElements"]
if rel["eccentricity"]
]
)
rigidLinkGroupNames = tuple(rigidLinkGroupNames)
# Define file to write command file for code_aster
f = open(self.asterFilename, "w")
f.write("# Command file generated by IfcOpenShell/ifc2ca scripts\n")
f.write("\n")
f.write("# Linear Static Analysis With Self-Weight\n")
f.write(
"""
# STEP: INITIALIZE STUDY
DEBUT(
PAR_LOT = 'NON'
)
"""
)
f.write(
"""
# STEP: READ MED FILE
mesh = LIRE_MAILLAGE(
FORMAT = 'MED',
UNITE = 20
)
"""
)
f.write(
"""
# STEP: DEFINE MODEL
model = AFFE_MODELE(
MAILLAGE = mesh,
AFFE = (
_F(
TOUT = 'OUI',
PHENOMENE = 'MECANIQUE',
MODELISATION = '3D'
),"""
)
if faceGroupNames:
template = """
_F(
GROUP_MA = {groupNames},
PHENOMENE = 'MECANIQUE',
MODELISATION = 'DKT'
),"""
context = {"groupNames": faceGroupNames}
f.write(template.format(**context))
if edgeGroupNames:
template = """
_F(
GROUP_MA = {groupNames},
PHENOMENE = 'MECANIQUE',
MODELISATION = 'POU_D_E'
),"""
context = {"groupNames": edgeGroupNames}
f.write(template.format(**context))
if point0DGroupNames:
template = """
_F(
GROUP_MA = {groupNames},
PHENOMENE = 'MECANIQUE',
MODELISATION = 'DIS_TR'
),"""
context = {"groupNames": tuple(flatten([point0DGroupNames, spring1DGroupNames]))}
f.write(template.format(**context))
if point1DGroupNames:
template = """
_F(
GROUP_MA = {groupNames},
PHENOMENE = 'MECANIQUE',
MODELISATION = 'DIS_TR'
),"""
context = {"groupNames": point1DGroupNames}
f.write(template.format(**context))
if rigidLinkGroupNames:
template = """
_F(
GROUP_MA = {groupNames},
PHENOMENE = 'MECANIQUE',
MODELISATION = 'POU_D_E'
),"""
context = {"groupNames": rigidLinkGroupNames}
f.write(template.format(**context))
f.write(
"""
)
)\n
"""
)
f.write("# STEP: DEFINE MATERIALS")
for i, material in enumerate(materials):
template = """
{matNameID} = DEFI_MATERIAU(
ELAS = _F(
E = {youngModulus},
NU = {poissonRatio},
RHO = {massDensity}
)
)
"""
if "poissonRatio" in material["mechProps"]:
poissonRatio = material["mechProps"]["poissonRatio"]
else:
if "shearModulus" in material["mechProps"]:
poissonRatio = (
material["mechProps"]["youngModulus"] / 2.0 / material["mechProps"]["shearModulus"]
) - 1
else:
poissonRatio = 0.0
context = {
"matNameID": "mat" + "_%s" % i,
"youngModulus": float(material["mechProps"]["youngModulus"]),
"poissonRatio": float(poissonRatio),
"massDensity": float(material["commonProps"]["massDensity"]),
}
f.write(template.format(**context))
f.write(
"""
material = AFFE_MATERIAU(
MAILLAGE = mesh,
AFFE = ("""
)
for i, material in enumerate(materials):
template = """
_F(
GROUP_MA = {groupNames},
MATER = {matNameID},
),"""
context = {
"groupNames": tuple([self.getGroupName(rel) for rel in material["relatedElements"]]),
"matNameID": "mat" + "_%s" % i,
}
f.write(template.format(**context))
if rigidLinkGroupNames:
template = """
_F(
GROUP_MA = {groupNames},
MATER = {matNameID},
),"""
context = {"groupNames": rigidLinkGroupNames, "matNameID": "mat_0"}
f.write(template.format(**context))
f.write(
"""
)
)
"""
)
f.write(
"""
# STEP: DEFINE ELEMENTS
element = AFFE_CARA_ELEM(
MODELE = model,
POUTRE = ("""
)
for profile in profiles:
if profile["profileShape"] == "rectangular" and profile["profileType"] == "AREA":
template = """
_F(
GROUP_MA = {groupNames},
SECTION = 'RECTANGLE',
CARA = ('HY', 'HZ'),
VALE = {profileDimensions}
),"""
context = {
"groupNames": tuple([self.getGroupName(rel) for rel in profile["relatedElements"]]),
"profileDimensions": (profile["xDim"], profile["yDim"]),
}
f.write(template.format(**context))
elif profile["profileShape"] == "iSymmetrical" and profile["profileType"] == "AREA":
template = """
_F(
GROUP_MA = {groupNames},
SECTION = 'GENERALE',
CARA = ('A', 'IY', 'IZ', 'JX'),
VALE = {profileProperties}
),"""
context = {
"groupNames": tuple([self.getGroupName(rel) for rel in profile["relatedElements"]]),
"profileProperties": (
profile["mechProps"]["crossSectionArea"],
profile["mechProps"]["momentOfInertiaY"],
profile["mechProps"]["momentOfInertiaZ"],
profile["mechProps"]["torsionalConstantX"],
),
}
f.write(template.format(**context))
if rigidLinkGroupNames:
template = """
_F(
GROUP_MA = {groupNames},
SECTION = 'RECTANGLE',
CARA = ('HY', 'HZ'),
VALE = {profileDimensions}
),"""
context = {"groupNames": rigidLinkGroupNames, "profileDimensions": (1, 1)}
f.write(template.format(**context))
f.write(
"""
),
COQUE = ("""
)
for el in [el for el in elements if el["geometryType"] == "surface"]:
template = """
_F(
GROUP_MA = '{groupName}',
EPAIS = {thickness},
VECTEUR = {localAxisX}
),"""
context = {
"groupName": self.getGroupName(el["ifcName"]),
"thickness": el["thickness"],
"localAxisX": tuple(el["orientation"][0]),
}
f.write(template.format(**context))
f.write(
"""
),"""
)
f.write(
"""
DISCRET = ("""
)
for conn in [conn for conn in connections if conn["geometryType"] == "point"]:
template = """
_F(
GROUP_MA = '{groupName}',
CARA = 'K_TR_D_N',
VALE = {stiffnesses},
REPERE = 'LOCAL'
),"""
context = {"groupName": self.getGroupName(conn["ifcName"]) + "_0D", "stiffnesses": conn["stiffnesses"]}
f.write(template.format(**context))
for rel in conn["relatedElements"]:
template = """
_F(
GROUP_MA = '{groupName}',
CARA = 'K_TR_D_L',
VALE = {stiffnesses},
REPERE = 'LOCAL'
),"""
context = {"groupName": rel["springGroupName"], "stiffnesses": rel["stiffnesses"]}
f.write(template.format(**context))
for conn in [conn for conn in connections if conn["geometryType"] == "line"]:
template = """
_F(
GROUP_MA = '{groupName}',
CARA = 'K_TR_D_N',
VALE = {stiffnesses},
REPERE = 'LOCAL'
),"""
context = {"groupName": self.getGroupName(conn["ifcName"]) + "_0D", "stiffnesses": conn["stiffnesses"]}
f.write(template.format(**context))
f.write(
"""
),"""
)
f.write(
"""
ORIENTATION = ("""
)
for el in [el for el in elements if el["geometryType"] == "line"]:
template = """
_F(
GROUP_MA = '{groupName}',
CARA = 'VECT_Y',
VALE = {localAxisY}
),"""
context = {"groupName": self.getGroupName(el["ifcName"]), "localAxisY": tuple(el["orientation"][1])}
f.write(template.format(**context))
for conn in [conn for conn in connections if conn["geometryType"] == "point"]:
template = """
_F(
GROUP_MA = '{groupName}',
CARA = 'VECT_X_Y',
VALE = {localAxesXY}
),"""
context = {
"groupName": self.getGroupName(conn["ifcName"]) + "_0D",
"localAxesXY": tuple(conn["orientation"][0] + conn["orientation"][1]),
}
f.write(template.format(**context))
for rel in conn["relatedElements"]:
template = """
_F(
GROUP_MA = '{groupName}',
CARA = 'VECT_X_Y',
VALE = {localAxesXY}
),"""
context = {
"groupName": rel["springGroupName"],
"localAxesXY": tuple(rel["orientation"][0] + rel["orientation"][1]),
}
f.write(template.format(**context))
for conn in [conn for conn in connections if conn["geometryType"] == "line"]:
template = """
_F(
GROUP_MA = '{groupName}',
CARA = 'VECT_X_Y',
VALE = {localAxesXY}
),"""
context = {
"groupName": self.getGroupName(conn["ifcName"]) + "_0D",
"localAxesXY": tuple(conn["orientation"][0] + conn["orientation"][1]),
}
f.write(template.format(**context))
f.write(
"""
),"""
)
f.write(
"""
)\n
"""
)
f.write("# STEP: DEFINE SUPPORTS AND CONSTRAINTS")
f.write(
"""
liaisons = AFFE_CHAR_MECA(
MODELE = model,
LIAISON_DDL = ("""
)
for conn in [conn for conn in connections if conn["geometryType"] == "point"]:
if conn["appliedCondition"]:
for i in range(len(conn["liaisons"]["coeffs"])):
template = """
_F(
GROUP_NO = {groupNames},
DDL = {dofs},
COEF_MULT = {coeffs},
COEF_IMPO = 0.0
),"""
context = {
"groupNames": conn["liaisons"]["groupNames"],
"dofs": conn["liaisons"]["dofs"][i],
"coeffs": conn["liaisons"]["coeffs"][i],
}
f.write(template.format(**context))
for rel in conn["relatedElements"]:
for i in range(len(rel["liaisons"]["coeffs"])):
template = """
_F(
GROUP_NO = {groupNames},
DDL = {dofs},
COEF_MULT = {coeffs},
COEF_IMPO = 0.0
),"""
context = {
"groupNames": rel["liaisons"]["groupNames"],
"dofs": rel["liaisons"]["dofs"][i],
"coeffs": rel["liaisons"]["coeffs"][i],
}
f.write(template.format(**context))
f.write(
"""
),"""
)
f.write(
"""
LIAISON_GROUP = ("""
)
for conn in [conn for conn in connections if conn["geometryType"] == "line"]:
if conn["appliedCondition"]:
for i in range(len(conn["liaisons"]["coeffs"])):
template = """
_F(
GROUP_NO_1 = {groupName_1},
GROUP_NO_2 = {groupName_1},
DDL_1 = {dofs},
DDL_2 = {dofs},
COEF_MULT_1 = {coeffs},
COEF_MULT_2 = (0.0, 0.0, 0.0),
COEF_IMPO = 0.0
),"""
context = {
"groupName_1": tuple([conn["liaisons"]["groupNames"][0]]),
"dofs": conn["liaisons"]["dofs"][i],
"coeffs": conn["liaisons"]["coeffs"][i],
}
f.write(template.format(**context))
for rel in conn["relatedElements"]:
for i in range(len(rel["liaisons"]["coeffs"])):
template = """
_F(
GROUP_NO_1 = {groupName_1},
GROUP_NO_2 = {groupName_2},
DDL_1 = {dofs},
DDL_2 = {dofs},
COEF_MULT_1 = {coeffs_1},
COEF_MULT_2 = {coeffs_2},
COEF_IMPO = 0.0
),"""
context = {
"groupName_1": tuple([rel["liaisons"]["groupNames"][0]]),
"groupName_2": tuple([rel["liaisons"]["groupNames"][3]]),
"dofs": tuple(list(rel["liaisons"]["dofs"][i])[:3]),
"coeffs_1": tuple(list(rel["liaisons"]["coeffs"][i])[:3]),
"coeffs_2": tuple(list(rel["liaisons"]["coeffs"][i])[3:]),
}
f.write(template.format(**context))
f.write(
"""
),"""
)
if unifiedConnection:
f.write(
"""
LIAISON_UNIF = ("""
)
for conn in [conn for conn in connections if len(conn["unifiedGroupNames"]) > 1]:
template = """
_F(
GROUP_NO = {groupNames},
DDL = ('DX', 'DY', 'DZ', 'DRX', 'DRY', 'DRZ')
),"""
context = {"groupNames": conn["unifiedGroupNames"]}
f.write(template.format(**context))
f.write(
"""
),"""
)
if rigidLinkGroupNames:
f.write(
"""
LIAISON_SOLIDE = ("""
)
for groupName in rigidLinkGroupNames:
template = """
_F(
GROUP_MA = '{groupName}'
),"""
context = {"groupName": groupName}
f.write(template.format(**context))
f.write(
"""
),"""
)
f.write(
"""
)
"""
)
template = """
# STEP: DEFINE LOAD
gravLoad = AFFE_CHAR_MECA(
MODELE = model,
PESANTEUR = _F(
GRAVITE = {AccelOfGravity},
DIRECTION = (0.0, 0.0, -1.0)
)
)
"""
context = {
"AccelOfGravity": AccelOfGravity,
}
f.write(template.format(**context))
f.write(
"""
# STEP: RUN ANALYSIS
res_Bld = MECA_STATIQUE(
MODELE = model,
CHAM_MATER = material,
CARA_ELEM = element,
EXCIT = (
_F(
CHARGE = liaisons
),
_F(
CHARGE = gravLoad
)
)
)
"""
)
# f.write(
# '''
# # STEP: POST-PROCESSING
# res_Bld = CALC_CHAMP(
# reuse = res_Bld,
# RESULTAT = res_Bld,
# # CONTRAINTE = ('SIEF_ELNO', 'SIGM_ELNO', 'EFGE_ELNO',),
# FORCE = ('REAC_NODA', 'FORC_NODA',)
# )
# '''
# )
#
# template = \
# '''
# # STEP: MASS EXTRACTION FOR EACH ASSEMBLE
# FaceMass = POST_ELEM(
# TITRE = 'TotMass',
# MODELE = model,
# CARA_ELEM = element,
# CHAM_MATER = material,
# MASS_INER = _F(
# GROUP_MA = {massList},
# ),
# )\n'''
#
# context = {
# 'massList': massList,
# }
#
# f.write(template.format(**context))
#
# f.write(
# '''
# IMPR_TABLE(
# UNITE = 10,
# TABLE = FaceMass,
# SEPARATEUR = ',',
# NOM_PARA = ('LIEU', 'MASSE', 'CDG_X', 'CDG_Y', 'CDG_Z'),
# # FORMAT_R = '1PE15.6',
# )
# '''
# )
#
# template = \
# '''
# # STEP: REACTION EXTRACTION AT THE BASE
# Reacs = POST_RELEVE_T(
# ACTION = _F(
# INTITULE = 'sumReac',
# GROUP_NO = {groupNames},
# RESULTAT = res_Bld,
# NOM_CHAM = 'REAC_NODA',
# RESULTANTE = ('DX','DY','DZ',),
# MOMENT = ('DRX','DRY','DRZ',),
# POINT = (0,0,0,),
# OPERATION = 'EXTRACTION'
# )
# )
# '''
#
# context = {
# 'groupNames': point0DGroupNames,
# }
#
# f.write(template.format(**context))
#
# f.write(
# '''
# IMPR_TABLE(
# UNITE = 10,
# TABLE = Reacs,
# SEPARATEUR = ',',
# # NOM_PARA = ('INTITULE', 'RESU', 'NOM_CHAM', 'INST', 'DX','DY','DZ'),
# FORMAT_R = '1PE12.3',
# )
# '''
# )
#
f.write(
"""
# STEP: DEFORMED SHAPE EXTRACTION
IMPR_RESU(
FORMAT = 'MED',
UNITE = 80,
RESU = _F(
RESULTAT = res_Bld,
NOM_CHAM = ('DEPL',), # 'REAC_NODA', 'FORC_NODA',
NOM_CHAM_MED = ('Bld_DISP',), # 'Bld_REAC', 'Bld_FORC'
)
)
"""
)
f.write(
"""
# STEP: CONCLUDE STUDY
FIN()
"""
)
f.close()
def calculateConstraints(self, rel):
gr1 = rel["groupName1"]
gr2 = rel["groupName2"]
o = np.array(rel["orientation"]).transpose().tolist()
liaisons = {"groupNames": (gr1, gr1, gr1, gr2, gr2, gr2), "coeffs": [], "dofs": []}
stiffnesses = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
if not rel["appliedCondition"]:
rel["appliedCondition"] = {"dx": True, "dy": True, "dz": True, "drx": True, "dry": True, "drz": True}
if isinstance(rel["appliedCondition"]["dx"], bool) and rel["appliedCondition"]["dx"]:
liaisons["coeffs"].append((o[0][0], o[1][0], o[2][0], -o[0][0], -o[1][0], -o[2][0]))
liaisons["dofs"].append(("DX", "DY", "DZ", "DX", "DY", "DZ"))
elif isinstance(rel["appliedCondition"]["dx"], float) and rel["appliedCondition"]["dx"] > 0:
stiffnesses[0] = rel["appliedCondition"]["dx"]
if isinstance(rel["appliedCondition"]["dy"], bool) and rel["appliedCondition"]["dy"]:
liaisons["coeffs"].append((o[0][1], o[1][1], o[2][1], -o[0][1], -o[1][1], -o[2][1]))
liaisons["dofs"].append(("DX", "DY", "DZ", "DX", "DY", "DZ"))
elif isinstance(rel["appliedCondition"]["dy"], float) and rel["appliedCondition"]["dy"] > 0:
stiffnesses[1] = rel["appliedCondition"]["dy"]
if isinstance(rel["appliedCondition"]["dz"], bool) and rel["appliedCondition"]["dz"]:
liaisons["coeffs"].append((o[0][2], o[1][2], o[2][2], -o[0][2], -o[1][2], -o[2][2]))
liaisons["dofs"].append(("DX", "DY", "DZ", "DX", "DY", "DZ"))
elif isinstance(rel["appliedCondition"]["dz"], float) and rel["appliedCondition"]["dz"] > 0:
stiffnesses[2] = rel["appliedCondition"]["dz"]
if isinstance(rel["appliedCondition"]["drx"], bool) and rel["appliedCondition"]["drx"]:
liaisons["coeffs"].append((o[0][0], o[1][0], o[2][0], -o[0][0], -o[1][0], -o[2][0]))
liaisons["dofs"].append(("DRX", "DRY", "DRZ", "DRX", "DRY", "DRZ"))
elif isinstance(rel["appliedCondition"]["drx"], float) and rel["appliedCondition"]["drx"] > 0:
stiffnesses[3] = rel["appliedCondition"]["drx"]
if isinstance(rel["appliedCondition"]["dry"], bool) and rel["appliedCondition"]["dry"]:
liaisons["coeffs"].append((o[0][1], o[1][1], o[2][1], -o[0][1], -o[1][1], -o[2][1]))
liaisons["dofs"].append(("DRX", "DRY", "DRZ", "DRX", "DRY", "DRZ"))
elif isinstance(rel["appliedCondition"]["dry"], float) and rel["appliedCondition"]["dry"] > 0:
stiffnesses[4] = rel["appliedCondition"]["dry"]
if isinstance(rel["appliedCondition"]["drz"], bool) and rel["appliedCondition"]["drz"]:
liaisons["coeffs"].append((o[0][2], o[1][2], o[2][2], -o[0][2], -o[1][2], -o[2][2]))
liaisons["dofs"].append(("DRX", "DRY", "DRZ", "DRX", "DRY", "DRZ"))
elif isinstance(rel["appliedCondition"]["drz"], float) and rel["appliedCondition"]["drz"] > 0:
stiffnesses[5] = rel["appliedCondition"]["drz"]
rel["liaisons"] = liaisons
rel["stiffnesses"] = tuple(stiffnesses)
def calculateRestraints(self, conn):
group = self.getGroupName(conn["ifcName"])
o = np.array(conn["orientation"]).transpose().tolist()
liaisons = {"groupNames": (group, group, group), "coeffs": [], "dofs": []}
stiffnesses = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0]
if not conn["appliedCondition"]:
conn["liaisons"] = liaisons
conn["stiffnesses"] = tuple(stiffnesses)
return
if isinstance(conn["appliedCondition"]["dx"], bool) and conn["appliedCondition"]["dx"]:
liaisons["coeffs"].append((o[0][0], o[1][0], o[2][0]))
liaisons["dofs"].append(("DX", "DY", "DZ"))
elif isinstance(conn["appliedCondition"]["dx"], float) and conn["appliedCondition"]["dx"] > 0:
stiffnesses[0] = conn["appliedCondition"]["dx"]
if isinstance(conn["appliedCondition"]["dy"], bool) and conn["appliedCondition"]["dy"]:
liaisons["coeffs"].append((o[0][1], o[1][1], o[2][1]))
liaisons["dofs"].append(("DX", "DY", "DZ"))
elif isinstance(conn["appliedCondition"]["dy"], float) and conn["appliedCondition"]["dy"] > 0:
stiffnesses[1] = conn["appliedCondition"]["dy"]
if isinstance(conn["appliedCondition"]["dz"], bool) and conn["appliedCondition"]["dz"]:
liaisons["coeffs"].append((o[0][2], o[1][2], o[2][2]))
liaisons["dofs"].append(("DX", "DY", "DZ"))
elif isinstance(conn["appliedCondition"]["dz"], float) and conn["appliedCondition"]["dz"] > 0:
stiffnesses[2] = conn["appliedCondition"]["dz"]
if isinstance(conn["appliedCondition"]["drx"], bool) and conn["appliedCondition"]["drx"]:
liaisons["coeffs"].append((o[0][0], o[1][0], o[2][0]))
liaisons["dofs"].append(("DRX", "DRY", "DRZ"))
elif isinstance(conn["appliedCondition"]["drx"], float) and conn["appliedCondition"]["drx"] > 0:
stiffnesses[3] = conn["appliedCondition"]["drx"]
if isinstance(conn["appliedCondition"]["dry"], bool) and conn["appliedCondition"]["dry"]:
liaisons["coeffs"].append((o[0][1], o[1][1], o[2][1]))
liaisons["dofs"].append(("DRX", "DRY", "DRZ"))
elif isinstance(conn["appliedCondition"]["dry"], float) and conn["appliedCondition"]["dry"] > 0:
stiffnesses[4] = conn["appliedCondition"]["dry"]
if isinstance(conn["appliedCondition"]["drz"], bool) and conn["appliedCondition"]["drz"]:
liaisons["coeffs"].append((o[0][2], o[1][2], o[2][2]))
liaisons["dofs"].append(("DRX", "DRY", "DRZ"))
elif isinstance(conn["appliedCondition"]["drz"], float) and conn["appliedCondition"]["drz"] > 0:
stiffnesses[5] = conn["appliedCondition"]["drz"]
conn["liaisons"] = liaisons
conn["stiffnesses"] = tuple(stiffnesses)
if __name__ == "__main__":
fileNames = ["cantilever_01", "portal_01", "grid_of_beams", "slab_01", "structure_01"]
files = fileNames
for fileName in files:
BASE_PATH = "/home/jesusbill/Dev-Projects/github.com/IfcOpenShell/analysis-models/models/"
DATAFILENAME = BASE_PATH + fileName + "/" + fileName + ".json"
ASTERFILENAME = BASE_PATH + fileName + "/" + fileName + ".comm"
COMMANDFILE(DATAFILENAME, ASTERFILENAME)
+467
View File
@@ -0,0 +1,467 @@
from __future__ import division
from __future__ import print_function
import os
import time
import json
import salome
import salome_notebook
import salome_version
import numpy as np
import itertools
flatten = itertools.chain.from_iterable
class MODEL:
def __init__(self, dataFilename, medFilename, meshSize):
self.dataFilename = dataFilename
self.medFilename = medFilename
self.meshSize = meshSize
self.tolLoc = 0
self.mesh = None
self.meshNodes = None
self.create()
def getGroupName(self, name):
info = name.split("|")
sortName = "".join(c for c in info[0] if c.isupper())
return str(sortName + "_" + info[1])
def makePoint(self, pl):
"""Function to define a Point from
a polyline (list of 1 point)"""
(x, y, z) = pl
return self.geompy.MakeVertex(x, y, z)
def makeLine(self, pl):
"""Function to define a Line from
a polyline (list of 2 points)"""
(x, y, z) = pl[0]
P1 = self.geompy.MakeVertex(x, y, z)
(x, y, z) = pl[1]
P2 = self.geompy.MakeVertex(x, y, z)
return self.geompy.MakeLineTwoPnt(P1, P2)
def makeFace(self, pl):
"""Function to define a Face from
a polyline (list of points)"""
pointList = [None for _ in range(len(pl))]
for ip, (x, y, z) in enumerate(pl):
pointList[ip] = self.geompy.MakeVertex(x, y, z)
LineList = [None for _ in range(len(pl))]
for ip, P2 in enumerate(pointList):
P1 = pointList[ip - 1]
LineList[ip] = self.geompy.MakeLineTwoPnt(P1, P2)
return self.geompy.MakeFaceWires(LineList, 1)
def makeObject(self, geometry, geometryType):
if geometryType == "point":
return self.makePoint(geometry)
if geometryType == "line":
return self.makeLine(geometry)
if geometryType == "surface":
return self.makeFace(geometry)
def makePartition(self, objects, geometryType):
if geometryType == "point":
shapeType = "VERTEX"
if geometryType == "line":
shapeType = "EDGE"
if geometryType == "surface":
shapeType = "FACE"
return self.geompy.MakePartition(objects, [], [], [], self.geompy.ShapeType[shapeType], 0, [], 1)
def getLinkGeometry(self, ecc, orientation, finalPoint):
vector = np.array(orientation).transpose().dot(ecc["vector"])
initialPoint = (np.array(finalPoint) - vector).tolist()
return [initialPoint, finalPoint]
def length(self, geometry):
return (
(geometry[1][0] - geometry[0][0]) ** 2
+ (geometry[1][1] - geometry[0][1]) ** 2
+ (geometry[1][2] - geometry[0][2]) ** 2
) ** 0.5
def create(self):
# Read data from input file
with open(self.dataFilename) as dataFile:
data = json.load(dataFile)
elements = data["elements"]
connections = data["connections"]
# --> Delete this reference data and repopulate it with the objects
# while going through elements
for conn in connections:
conn["relatedElements"] = []
# End <--
meshSize = self.meshSize
dec = 7 # 4 decimals for length in mm
tol = 10 ** (-dec - 3 + 1)
self.tolLoc = tol * 10 * 2
tolLoc = self.tolLoc
NEW_SALOME = int(salome_version.getVersion()[0]) >= 9
salome.salome_init()
theStudy = salome.myStudy
notebook = salome_notebook.NoteBook(theStudy)
###
### GEOM component
###
import GEOM
from salome.geom import geomBuilder
import math
import SALOMEDS
gg = salome.ImportComponentGUI("GEOM")
if NEW_SALOME:
geompy = geomBuilder.New()
else:
geompy = geomBuilder.New(theStudy)
self.geompy = geompy
O = geompy.MakeVertex(0, 0, 0)
OX = geompy.MakeVectorDXDYDZ(1, 0, 0)
OY = geompy.MakeVectorDXDYDZ(0, 1, 0)
OZ = geompy.MakeVectorDXDYDZ(0, 0, 1)
geompy.addToStudy(O, "O")
geompy.addToStudy(OX, "OX")
geompy.addToStudy(OY, "OY")
geompy.addToStudy(OZ, "OZ")
if len([e for e in elements if e["geometryType"] == "line"]) > 0:
buildingShapeType = "EDGE"
if len([e for e in elements if e["geometryType"] == "surface"]) > 0:
buildingShapeType = "FACE"
### Define entities ###
start_time = time.time()
print("Defining Object Geometry")
init_time = start_time
# Loop 1
for el in elements:
el["elemObj"] = self.makeObject(el["geometry"], el["geometryType"])
el["connObjs"] = [None for _ in el["connections"]]
el["linkObjs"] = [None for _ in el["connections"]]
el["linkPointObjs"] = [[None, None] for _ in el["connections"]]
for j, rel in enumerate(el["connections"]):
conn = [c for c in connections if c["ifcName"] == rel["relatedConnection"]][0]
if rel["eccentricity"]:
rel["index"] = len(conn["relatedElements"]) + 1
conn["relatedElements"].append(rel)
if not rel["eccentricity"]:
el["connObjs"][j] = self.makeObject(conn["geometry"], conn["geometryType"])
else:
if conn["geometryType"] == "point":
geometry = self.getLinkGeometry(rel["eccentricity"], el["orientation"], conn["geometry"])
el["connObjs"][j] = self.makeObject(geometry[0], conn["geometryType"])
el["linkPointObjs"][j][0] = self.geompy.MakeVertex(
geometry[0][0], geometry[0][1], geometry[0][2]
)
el["linkPointObjs"][j][1] = self.geompy.MakeVertex(
geometry[1][0], geometry[1][1], geometry[1][2]
)
el["linkObjs"][j] = self.geompy.MakeLineTwoPnt(
el["linkPointObjs"][j][0], el["linkPointObjs"][j][1]
)
else:
print("Eccentricity defined for a %s geometryType" % conn["geometryType"])
el["partObj"] = self.makePartition([el["elemObj"]] + el["connObjs"], el["geometryType"])
el["elemObj"] = geompy.GetInPlace(el["partObj"], el["elemObj"])
for j, rel in enumerate(el["connections"]):
el["connObjs"][j] = geompy.GetInPlace(el["partObj"], el["connObjs"][j])
for conn in connections:
conn["connObj"] = self.makeObject(conn["geometry"], conn["geometryType"])
# Make assemble of Building Object
bldObjs = []
bldObjs.extend([el["partObj"] for el in elements])
bldObjs.extend(flatten([[link for link in el["linkObjs"] if link] for el in elements]))
bldObjs.extend([conn["connObj"] for conn in connections])
bldComp = geompy.MakeCompound(bldObjs)
# bldComp = geompy.MakePartition(bldObjs, [], [], [], self.geompy.ShapeType[buildingShapeType], 0, [], 1)
geompy.addToStudy(bldComp, "bldComp")
# Loop 2
for el in elements:
# geompy.addToStudy(el['partObj'], self.getGroupName(el['ifcName']))
geompy.addToStudyInFather(el["partObj"], el["elemObj"], self.getGroupName(el["ifcName"]))
for j, rel in enumerate(el["connections"]):
conn = [c for c in connections if c["ifcName"] == rel["relatedConnection"]][0]
rel["conn_string"] = None
if conn["geometryType"] == "point":
rel["conn_string"] = "_0DC_"
if conn["geometryType"] == "line":
rel["conn_string"] = "_1DC_"
if conn["geometryType"] == "surface":
rel["conn_string"] = "_2DC_"
geompy.addToStudyInFather(
el["partObj"],
el["connObjs"][j],
self.getGroupName(el["ifcName"]) + rel["conn_string"] + self.getGroupName(rel["relatedConnection"]),
)
if rel["eccentricity"]:
pass
# geompy.addToStudy(el['linkObjs'][j], self.getGroupName(el['ifcName']) + '_1DR_' + self.getGroupName(rel['relatedConnection']))
# geompy.addToStudyInFather(el['linkObjs'][j], el['linkPointObjs'][j][0], self.getGroupName(rel['relatedConnection']) + '_0DC_' + self.getGroupName(el['ifcName']))
# geompy.addToStudyInFather(el['linkObjs'][j], el['linkPointObjs'][j][0], self.getGroupName(rel['relatedConnection']) + '_0DC_%g' % rel['index'])
for conn in connections:
# geompy.addToStudy(conn['connObj'], self.getGroupName(conn['ifcName']))
geompy.addToStudyInFather(conn["connObj"], conn["connObj"], self.getGroupName(conn["ifcName"]))
elapsed_time = time.time() - init_time
init_time += elapsed_time
print("Building Geometry Defined in %g sec" % (elapsed_time))
if len([e for e in elements if e["geometryType"] == "line"]) > 0:
buildingShapeType = "EDGE"
if len([e for e in elements if e["geometryType"] == "surface"]) > 0:
buildingShapeType = "FACE"
# Define and add groups for all curve and surface members
if len([e for e in elements if e["geometryType"] == "line"]) > 0:
# Make compound of requested group
compoundTemp = geompy.MakeCompound([e["elemObj"] for e in elements if e["geometryType"] == "line"])
# Define group object and add to study
curveCompound = geompy.GetInPlace(bldComp, compoundTemp)
geompy.addToStudyInFather(bldComp, curveCompound, "CurveMembers")
if len([e for e in elements if e["geometryType"] == "surface"]) > 0:
# Make compound of requested group
compoundTemp = geompy.MakeCompound([e["elemObj"] for e in elements if e["geometryType"] == "surface"])
# Define group object and add to study
surfaceCompound = geompy.GetInPlace(bldComp, compoundTemp)
geompy.addToStudyInFather(bldComp, surfaceCompound, "SurfaceMembers")
# Loop 3
for el in elements:
# el['partObj'] = geompy.RestoreGivenSubShapes(bldComp, [el['partObj']], GEOM.FSM_GetInPlace, False, False)[0]
geompy.addToStudyInFather(bldComp, el["elemObj"], self.getGroupName(el["ifcName"]))
for j, rel in enumerate(el["connections"]):
geompy.addToStudyInFather(
bldComp,
el["connObjs"][j],
self.getGroupName(el["ifcName"]) + rel["conn_string"] + self.getGroupName(rel["relatedConnection"]),
)
if rel["eccentricity"]: # point geometry
geompy.addToStudyInFather(
bldComp,
el["linkObjs"][j],
self.getGroupName(el["ifcName"]) + "_1DR_" + self.getGroupName(rel["relatedConnection"]),
)
geompy.addToStudyInFather(
bldComp,
el["linkPointObjs"][j][0],
self.getGroupName(rel["relatedConnection"]) + "_0DC_" + self.getGroupName(el["ifcName"]),
)
geompy.addToStudyInFather(
bldComp,
el["linkPointObjs"][j][1],
self.getGroupName(rel["relatedConnection"]) + "_0DC_%g" % rel["index"],
)
for conn in connections:
# conn['connObj'] = geompy.RestoreGivenSubShapes(bldComp, [conn['connObj']], GEOM.FSM_GetInPlace, False, False)[0]
geompy.addToStudyInFather(bldComp, conn["connObj"], self.getGroupName(conn["ifcName"]))
elapsed_time = time.time() - init_time
init_time += elapsed_time
print("Building Geometry Groups Defined in %g sec" % (elapsed_time))
###
### SMESH component
###
import SMESH
from salome.smesh import smeshBuilder
print("Defining Mesh Components")
if NEW_SALOME:
smesh = smeshBuilder.New()
else:
smesh = smeshBuilder.New(theStudy)
bldMesh = smesh.Mesh(bldComp)
Regular_1D = bldMesh.Segment()
Local_Length_1 = Regular_1D.LocalLength(meshSize, None, tolLoc)
if buildingShapeType == "FACE":
NETGEN2D_ONLY = bldMesh.Triangle(algo=smeshBuilder.NETGEN_2D)
NETGEN2D_Pars = NETGEN2D_ONLY.Parameters()
NETGEN2D_Pars.SetMaxSize(meshSize)
NETGEN2D_Pars.SetOptimize(1)
NETGEN2D_Pars.SetFineness(2)
NETGEN2D_Pars.SetMinSize(meshSize / 5.0)
NETGEN2D_Pars.SetUseSurfaceCurvature(1)
NETGEN2D_Pars.SetQuadAllowed(1)
NETGEN2D_Pars.SetSecondOrder(0)
NETGEN2D_Pars.SetFuseEdges(254)
isDone = bldMesh.Compute()
## Set names of Mesh objects
smesh.SetName(Regular_1D.GetAlgorithm(), "Regular_1D")
smesh.SetName(Local_Length_1, "Local_Length_1")
if buildingShapeType == "FACE":
smesh.SetName(NETGEN2D_ONLY.GetAlgorithm(), "NETGEN2D_ONLY")
smesh.SetName(NETGEN2D_Pars, "NETGEN2D_Pars")
smesh.SetName(bldMesh.GetMesh(), "bldMesh")
elapsed_time = time.time() - init_time
init_time += elapsed_time
print("Meshing Operations Completed in %g sec" % (elapsed_time))
# Define and add groups for all curve and surface members
if len([e for e in elements if e["geometryType"] == "line"]) > 0:
tempgroup = bldMesh.GroupOnGeom(curveCompound, "CurveMembers", SMESH.EDGE)
smesh.SetName(tempgroup, "CurveMembers")
if len([e for e in elements if e["geometryType"] == "surface"]) > 0:
tempgroup = bldMesh.GroupOnGeom(surfaceCompound, "SurfaceMembers", SMESH.FACE)
smesh.SetName(tempgroup, "SurfaceMembers")
# Define groups in Mesh
for el in elements:
if el["geometryType"] == "line":
shapeType = SMESH.EDGE
if el["geometryType"] == "surface":
shapeType = SMESH.FACE
tempgroup = bldMesh.GroupOnGeom(el["elemObj"], self.getGroupName(el["ifcName"]), shapeType)
smesh.SetName(tempgroup, self.getGroupName(el["ifcName"]))
for j, rel in enumerate(el["connections"]):
tempgroup = bldMesh.GroupOnGeom(
el["connObjs"][j],
self.getGroupName(el["ifcName"]) + rel["conn_string"] + self.getGroupName(rel["relatedConnection"]),
SMESH.NODE,
)
smesh.SetName(
tempgroup,
self.getGroupName(el["ifcName"]) + rel["conn_string"] + self.getGroupName(rel["relatedConnection"]),
)
rel["node"] = (bldMesh.GetIDSource(tempgroup.GetNodeIDs(), SMESH.NODE)).GetIDs()[0]
if rel["eccentricity"]:
tempgroup = bldMesh.GroupOnGeom(
el["linkObjs"][j],
self.getGroupName(el["ifcName"]) + "_1DR_" + self.getGroupName(rel["relatedConnection"]),
SMESH.EDGE,
)
smesh.SetName(
tempgroup,
self.getGroupName(el["ifcName"]) + "_1DR_" + self.getGroupName(rel["relatedConnection"]),
)
tempgroup = bldMesh.GroupOnGeom(
el["linkPointObjs"][j][0],
self.getGroupName(rel["relatedConnection"]) + "_0DC_" + self.getGroupName(el["ifcName"]),
SMESH.NODE,
)
smesh.SetName(
tempgroup,
self.getGroupName(rel["relatedConnection"]) + "_0DC_" + self.getGroupName(el["ifcName"]),
)
rel["eccNode"] = (bldMesh.GetIDSource(tempgroup.GetNodeIDs(), SMESH.NODE)).GetIDs()[0]
tempgroup = bldMesh.GroupOnGeom(
el["linkPointObjs"][j][1],
self.getGroupName(rel["relatedConnection"])
+ "_0DC_"
+ self.getGroupName(rel["relatedConnection"]),
SMESH.NODE,
)
smesh.SetName(tempgroup, self.getGroupName(rel["relatedConnection"]) + "_0DC_%g" % rel["index"])
for conn in connections:
tempgroup = bldMesh.GroupOnGeom(conn["connObj"], self.getGroupName(conn["ifcName"]), SMESH.NODE)
smesh.SetName(tempgroup, self.getGroupName(conn["ifcName"]))
nodesId = bldMesh.GetIDSource(tempgroup.GetNodeIDs(), SMESH.NODE)
tempgroup = bldMesh.Add0DElementsToAllNodes(nodesId, self.getGroupName(conn["ifcName"]))
smesh.SetName(tempgroup, self.getGroupName(conn["ifcName"] + "_0D"))
if conn["geometryType"] == "point":
conn["node"] = nodesId.GetIDs()[0]
if conn["geometryType"] == "line":
tempgroup = bldMesh.GroupOnGeom(conn["connObj"], self.getGroupName(conn["ifcName"]), SMESH.EDGE)
smesh.SetName(tempgroup, self.getGroupName(conn["ifcName"]))
if conn["geometryType"] == "surface":
tempgroup = bldMesh.GroupOnGeom(conn["connObj"], self.getGroupName(conn["ifcName"]), SMESH.FACE)
smesh.SetName(tempgroup, self.getGroupName(conn["ifcName"]))
# create 1D SEG2 spring elements
for el in elements:
for j, rel in enumerate(el["connections"]):
conn = [c for c in connections if c["ifcName"] == rel["relatedConnection"]][0]
if conn["geometryType"] == "point":
grpName = bldMesh.CreateEmptyGroup(
SMESH.EDGE,
self.getGroupName(el["ifcName"]) + "_1DS_" + self.getGroupName(rel["relatedConnection"]),
)
smesh.SetName(
grpName,
self.getGroupName(el["ifcName"]) + "_1DS_" + self.getGroupName(rel["relatedConnection"]),
)
if not rel["eccentricity"]:
conn = [conn for conn in connections if conn["ifcName"] == rel["relatedConnection"]][0]
grpName.Add([bldMesh.AddEdge([conn["node"], rel["node"]])])
else:
grpName.Add([bldMesh.AddEdge([rel["eccNode"], rel["node"]])])
self.mesh = bldMesh
self.meshNodes = bldMesh.GetNodesId()
elapsed_time = time.time() - init_time
init_time += elapsed_time
print("Mesh Groups Defined in %g sec" % (elapsed_time))
try:
if NEW_SALOME:
bldMesh.ExportMED(
self.medFilename, auto_groups=0, minor=40, overwrite=1, meshPart=None, autoDimension=0
)
else:
bldMesh.ExportMED(self.medFilename, 0, SMESH.MED_V2_2, 1, None, 0)
except:
print("ExportMED() failed. Invalid file name?")
if salome.sg.hasDesktop():
if NEW_SALOME:
salome.sg.updateObjBrowser()
else:
salome.sg.updateObjBrowser(1)
elapsed_time = init_time - start_time
print("ALL Operations Completed in %g sec" % (elapsed_time))
if __name__ == "__main__":
fileNames = ["structure_01"]
files = fileNames
meshSize = 0.1
for fileName in files:
BASE_PATH = "/home/jesusbill/Dev-Projects/github.com/IfcOpenShell/analysis-models/models/"
DATAFILENAME = BASE_PATH + fileName + "/" + fileName + ".json"
MEDFILENAME = BASE_PATH + fileName + "/" + fileName + ".med"
model = MODEL(DATAFILENAME, MEDFILENAME, meshSize)
+3
View File
@@ -0,0 +1,3 @@
# Dependency and build folders created by the build scripts
/build/
/dist/
+122
View File
@@ -0,0 +1,122 @@
# BIMTester
BIMTester lets you specify a set of exchange requirements, and automatically check whether or not BIM data, typically an
IFC file, complies with the requirements. You can run it automatically from a server, integrate it to your own
application, or use a GUI. It can generate reports in various formats including:
* HTML
* JSON
* XUnit
* BCF
* Zoom Smart View
Your exchange requirements are written in plain language which you can use to communicate to project teams and include
in contracts. Multiple languages are supported. A series of exchange requirement templates are provided to get started,
but you can, and are encouraged to, write your own tailored to your project. An example of a requirement looks like
this:
```
Feature: Project setup
In order to view the BIM data
As any interested stakeholder
We need an IFC file
Scenario: Receiving a file
* IFC data must use the IFC4 schema
```
Languages supported include (in alphabetical order):
* Dutch
* English
* French
* German
* Italian
If you are not a developer, we highly recommend simply installing an integrated version of BIMTester.
* If you use Blender, install the [BlenderBIM Add-on](https://blenderbim.org)
* If you use FreeCAD, install the [FreeCAD BIMTester Workbench](https://github.com/bimtester/bimtesterfc)
If you are a developer, read on!
## Installation
The following packages are required for BIMTester to function:
* behave
* pystache
* ifcopenshell
* PySide2 (optional: needed for GUI)
The repository does not contain translation files. You can generate them as shown.
```
cd IfcOpenShell/src/ifcbimtester/bimtester/locale
pybabel compile -d .
```
## CLI Usage
BIMTester has a command line application. Check it out:
```
$ python cli.py -h
usage: cli.py [-h] [-a ACTION] [--advanced-arguments ADVANCED_ARGUMENTS] [-c]
-f FEATURE -i IFC [-p PATH] [-r REPORT] [--lang LANG]
Runs unit tests for BIM data
optional arguments:
-h, --help show this help message and exit
-a ACTION, --action ACTION
Action to perform, from run/purge
--advanced-arguments ADVANCED_ARGUMENTS
Specify arguments to Behave
-c, --console Show results in the console
-f FEATURE, --feature FEATURE
Specify a feature file to test
-i IFC, --ifc IFC Specify a ifc file
-p PATH, --path PATH Define a path for use in tests
-r REPORT, --report REPORT
Specify an output file for a HTML report
--lang LANG Specify a language
```
You can turn it into a regular command by symlinking it to your bin folder.
```
$ ln -s /path/to/IfcOpenShell/src/ifcbimtester/cli.py /usr/local/bin/bimtester
$ bimtester -h
```
To run a test, we need an IFC to check and a feature file filled with requirements. The feature file is plaintext. Feel
free to copy the minimal example above.
```
# To see output in the console
$ bimtester -i test.ifc -f test.feature -c
# Or, if you want to generate a HTML report
$ bimtester -i test.ifc -f test.feature -r report.html
```
```
python ./gui.py
```
## Create a binary out of the Python package
TODO: Check if this works
Unix:
```
$ pyinstaller --onefile --clean --icon=icon.ico --add-data "features:features" bimtester.py
```
Windows:
```
$ pyinstaller --onefile --clean --icon=icon.ico --add-data "features;features" bimtester.py
```
+5
View File
@@ -0,0 +1,5 @@
from os.path import dirname
from os.path import realpath
package_path = dirname(realpath(__file__))
+47
View File
@@ -0,0 +1,47 @@
import ifcopenshell
import os
from pathlib import Path
class TestPurger:
def __init__(self):
self.file = None
def purge(self):
filenames = []
if os.path.exists("features"):
for filename in Path("features/").glob("*.feature"):
filenames.append(filename)
for f in os.listdir("."):
if f.endswith(".feature"):
filenames.append(f)
for filename in filenames:
with open(filename, "r") as feature_file:
old_file = feature_file.readlines()
with open(filename, "w") as new_file:
for line in old_file:
is_purged = False
if 'The IFC file "' in line and '" must be provided' in line:
filename = line.split('"')[1]
print("Loading file {} ...".format(filename))
self.file = ifcopenshell.open(filename)
if line.strip()[0:2] == "* ":
words = line.strip().split()
for word in words:
if self.is_a_global_id(word):
if not self.does_global_id_exist(word):
print("Test for {} purged ...".format(word))
is_purged = True
if not is_purged:
new_file.write(line)
def is_a_global_id(self, word):
return word[0] in ["0", "1", "2", "3"] and len(word) == 22
def does_global_id_exist(self, global_id):
try:
self.file.by_guid(global_id)
return True
except Exception:
return False
@@ -0,0 +1,54 @@
import os
from behave.model import Scenario
from logfile import create_logfile
from logfile import append_logfile
from zoom_smart_view import append_zoom_smartview
from zoom_smart_view import create_zoom_smartview
from bimtester.ifc import IfcStore
from bimtester.lang import switch_locale
this_path = os.path.dirname(os.path.realpath(__file__))
def before_all(context):
userdata = context.config.userdata
if context.config.lang:
switch_locale(userdata.get("localedir"), context.config.lang)
continue_after_failed = userdata.getbool("runner.continue_after_failed_step", True)
Scenario.continue_after_failed_step = continue_after_failed
# TODO: refactor smart view support into a decoupled module
# context.ifc_path = userdata.get("ifc", "")
# context.ifc_basename = os.path.basename(
# os.path.splitext(context.ifc_path)[0]
# )
# context.outpath = os.path.join(this_path, "..")
# context.thelogfile = os.path.join(context.outpath, context.ifc_basename + ".log")
# create_logfile(
# context.thelogfile,
# context.ifc_basename,
# )
# # set up smart view file
# context.smview_file = os.path.join(context.outpath, context.ifc_basename + ".bcsv")
# create_zoom_smartview(
# context.smview_file,
# context.ifc_basename,
# )
def after_step(context, step):
pass
# TODO: refactor smart view support into a decoupled module
#if step.status == "failed":
# # append log file
# append_logfile(context, step)
# # extend smart view
# if hasattr(context, "falseguids"):
# append_zoom_smartview(context.smview_file, step.name, context.falseguids)
@@ -0,0 +1,30 @@
import json
def create_logfile(thelogfile, ifcbasename):
logfile = open(thelogfile, "w")
logfile.write("BIMTester log file\n")
logfile.write("------------------\n\n")
logfile.write("ifc base file name: {}\n".format(ifcbasename))
logfile.close()
def append_logfile(thecontext, step):
# step attributes (also these set by user) scope is the scenario
# https://behave.readthedocs.io/en/latest/thecontext_attributes.html
print("Step '{}' failed".format(step.name))
# log file
logfile = open(thecontext.thelogfile, "a")
logfile.write("\n\nStep '{}' failed\n".format(step.name))
if hasattr(thecontext, "falseelems"):
logfile.write("{}\n".format(
json.dumps(thecontext.falseelems, indent=4)
))
if hasattr(thecontext, "falseprops"):
logfile.write("{}\n".format(
json.dumps(thecontext.falseprops, indent=4)
))
logfile.close()
@@ -0,0 +1,15 @@
use_step_matcher("parse")
from bimtester.features.steps.classification import en
use_step_matcher("parse")
from bimtester.features.steps.element_classes import en
use_step_matcher("parse")
from bimtester.features.steps.geocoding import en
use_step_matcher("parse")
from bimtester.features.steps.geolocation import en
use_step_matcher("parse")
from bimtester.features.steps.geometric_detail import en
use_step_matcher("parse")
from bimtester.features.steps.model_federation import en
use_step_matcher("parse")
from bimtester.features.steps.project_setup import de, en, fr, it, nl
use_step_matcher("parse")
@@ -0,0 +1,70 @@
import json
from behave import step
from bimtester import util
from bimtester.ifc import IfcStore
from bimtester.lang import _
def get_classification(name):
classifications = [c for c in IfcStore.file.by_type("IfcClassification") if c.Name == name]
if len(classifications) != 1:
assert False, f'The classification "{name}" was not found'
return classifications[0]
@step('The classification "{name}" must be used')
def step_impl(context, name):
get_classification(name)
@step('The classification "{name}" is published by "{source}"')
def step_impl(context, name, source):
util.assert_attribute(get_classification(name), "Source", source)
@step('The classification "{name}" is the edition "{edition}" on "{edition_date}"')
def step_impl(context, name, edition, edition_date):
element = get_classification(name)
util.assert_attribute(element, "Edition", edition)
util.assert_attribute(element, "EditionDate", edition_date)
@step('The classification "{name}" has the description "{description}"')
def step_impl(context, name, description):
util.assert_attribute(get_classification(name), "Description", description)
@step('The classification "{name}" is referenced by the website "{location}"')
def step_impl(context, name, location):
util.assert_attribute(get_classification(name), "Location", location)
@step('The classification "{name}" has a hierarchy denoted by the tokens "{tokens}"')
def step_impl(context, name, tokens):
try:
tokens = json.loads(tokens)
except:
assert False, _("Tokens {} are not specified as a JSON list").format(tokens)
util.assert_attribute(get_classification(name), "ReferenceTokens", tokens)
@step('The element "{guid}" is classified as a "{identification}" with name "{reference_name}"')
def step_impl(context, guid, identification, reference_name):
element = util.assert_guid(IfcStore.file, guid)
if not hasattr(element, "HasAssociations") or not element.HasAssociations:
assert False, _("The element {} has no associations.").format(element)
references = [a.RelatingClassification for a in element.HasAssociations if a.is_a("IfcRelAssociatesClassification")]
if not references:
assert False, _("The element {element} has no associated classification references.").format(element)
is_success = False
for reference in references:
try:
util.assert_attribute(reference, "Identification", identification)
util.assert_attribute(reference, "Name", reference_name)
is_success = True
except:
pass
if not is_success:
assert False, _(
"No classification references met the requirement for an identification {} and name {} for the element {}. The references we found were: {}"
).format(identification, reference_name, element, references)
@@ -0,0 +1,40 @@
from behave import step
from bimtester import util
from bimtester.ifc import IfcStore
from bimtester.lang import _
@step('The element "{guid}" is an "{ifc_class}" only')
def step_impl(context, guid, ifc_class):
element = util.assert_guid(IfcStore.file, guid)
util.assert_type(element, ifc_class, is_exact=True)
@step('The element "{guid}" is an "{ifc_class}"')
def step_impl(context, guid, ifc_class):
element = util.assert_guid(IfcStore.file, guid)
util.assert_type(element, ifc_class)
@step('The element "{guid}" is further defined as a "{predefined_type}"')
def step_impl(context, guid, predefined_type):
element = util.assert_guid(IfcStore.file, guid)
if (
hasattr(element, "PredefinedType")
and element.PredefinedType == "USERDEFINED"
and hasattr(element, "ObjectType")
):
util.assert_attribute(element, "ObjectType", predefined_type)
elif hasattr(element, "PredefinedType"):
util.assert_attribute(element, "PredefinedType", predefined_type)
else:
assert False, _("The element {} does not have a PredefinedType or ObjectType attribute").format(element)
@step('The element "{guid}" should not exist because "{reason}"')
def step_impl(context, guid, reason):
try:
element = IfcStore.file.by_id(guid)
except:
return
assert False, _("This element {} should be reevaluated.").format(element)
@@ -0,0 +1,83 @@
from behave import step, use_step_matcher
from bimtester import util
from bimtester.ifc import IfcStore
from bimtester.lang import _
def get_ifc_class_from_spatial_type(spatial_type):
if spatial_type == "site":
return "IfcSite"
elif spatial_type == "building":
return "IfcBuilding"
return "IfcFacility"
def check_geocode_attribute(guid, spatial_type, name, value):
element = util.assert_guid(IfcStore.file, guid)
util.assert_type(element, get_ifc_class_from_spatial_type(spatial_type))
util.assert_attribute(element, name, value)
def check_geocode_address(guid, spatial_type, name, value):
element = util.assert_guid(IfcStore.file, guid)
ifc_class = get_ifc_class_from_spatial_type(spatial_type)
util.assert_type(element, ifc_class)
if ifc_class == "IfcSite":
address_name = "SiteAddress"
elif ifc_class == "IfcBuilding":
address_name = "BuildingAddress"
util.assert_attribute(element, address_name)
util.assert_attribute(getattr(element, address_name), name, value)
use_step_matcher("re")
@step('The (site|building|facility) "(?P<guid>.*)" has a name of "(?P<name>.*)"')
def step_impl(context, spatial_type, guid, name):
check_geocode_attribute(guid, spatial_type, "Name", name)
@step('The (site|building|facility) "(?P<guid>.*)" has a description of "(?P<description>.*)"')
def step_impl(context, spatial_type, guid, description):
check_geocode_attribute(guid, spatial_type, "Description", description)
@step('The site "(?P<guid>.*)" has a land title number of "(?P<land_title_number>.*)"')
def step_impl(context, guid, land_title_number):
check_geocode_attribute(guid, "site", "LandTitleNumber", land_title_number)
@step('The (site|building) "(?P<guid>.*)" has the address "(?P<address_lines>.*)"')
def step_impl(context, spatial_type, guid, address_lines):
check_geocode_address(guid, spatial_type, "AddressLines", address_lines.split("\\n"))
@step('The (site|building) "(?P<guid>.*)" has a postal box of "(?P<postal_box>.*)"')
def step_impl(context, spatial_type, guid, postal_box):
check_geocode_address(guid, spatial_type, "PostalBox", postal_box)
@step('The (site|building) "(?P<guid>.*)" is in the town "(?P<town>.*)"')
def step_impl(context, spatial_type, guid, town):
check_geocode_address(guid, spatial_type, "Town", town)
@step('The (site|building) "(?P<guid>.*)" is in the region "(?P<region>.*)"')
def step_impl(context, spatial_type, guid, region):
check_geocode_address(guid, spatial_type, "Region", region)
@step('The (site|building) "(?P<guid>.*)" has a post code of "(?P<post_code>.*)"')
def step_impl(context, spatial_type, guid, post_code):
check_geocode_address(guid, spatial_type, "PostalCode", post_code)
@step('The (site|building) "(?P<guid>.*)" is in the country "(?P<country>.*)"')
def step_impl(context, spatial_type, guid, country):
check_geocode_address(guid, spatial_type, "Country", country)
@step('The (site|building) "(?P<guid>.*)" has an address description of "(?P<description>.*)"')
def step_impl(context, spatial_type, guid, description):
check_geocode_address(guid, spatial_type, "Description", description)
@@ -0,0 +1,214 @@
import math
import ifcopenshell
import ifcopenshell.util.element
import ifcopenshell.util.geolocation
from behave import step
from bimtester import util
from bimtester.ifc import IfcStore
from bimtester.lang import _
@step(u'There must be at least one "{ifc_class}" element')
def step_impl(context, ifc_class):
assert len(IfcStore.file.by_type(ifc_class)) >= 1, _("An element of {} could not be found").format(ifc_class)
def check_ifc4_geolocation(entity_name, prop_name=None, value=None, should_assert=True):
if entity_name not in IfcStore.bookmarks:
has_entity = False
project = IfcStore.file.by_type("IfcProject")[0]
for context in project.RepresentationContexts:
if entity_name == "IfcMapConversion":
if (
context.is_a("IfcGeometricRepresentationContext")
and context.ContextType == "Model"
and context.HasCoordinateOperation
):
IfcStore.bookmarks[entity_name] = context.HasCoordinateOperation[0]
has_entity = True
elif entity_name == "IfcProjectedCRS":
if (
context.is_a("IfcGeometricRepresentationContext")
and context.ContextType == "Model"
and context.HasCoordinateOperation
and context.HasCoordinateOperation[0].TargetCRS
):
IfcStore.bookmarks[entity_name] = context.HasCoordinateOperation[0].TargetCRS
has_entity = True
if not has_entity:
assert False, _("No model geometric representation contexts refer to an {}").format(entity_name)
if not prop_name:
return
actual_value = getattr(IfcStore.bookmarks[entity_name], prop_name)
if should_assert:
assert actual_value == value, _('We expected a value of "{}" but instead got "{}"').format(value, actual_value)
else:
return actual_value
@step(u"The project must have coordinate reference system data")
def step_impl(context):
if IfcStore.file.schema == "IFC2X3":
for site in IfcStore.file.by_type("IfcSite"):
util.assert_pset(site, "EPset_ProjectedCRS")
return
check_ifc4_geolocation("IfcProjectedCRS")
@step(u'The name of the CRS must be "{coordinate_reference_name}"')
def step_impl(context, coordinate_reference_name):
if IfcStore.file.schema == "IFC2X3":
for site in IfcStore.file.by_type("IfcSite"):
util.assert_pset(site, "EPset_ProjectedCRS", "Name", coordinate_reference_name)
return
check_ifc4_geolocation("IfcProjectedCRS", "Name", coordinate_reference_name)
@step(u'The description of the CRS must be "{value}"')
def step_impl(context, value):
if IfcStore.file.schema == "IFC2X3":
for site in IfcStore.file.by_type("IfcSite"):
util.assert_pset(site, "EPset_ProjectedCRS", "Description", value)
return
check_ifc4_geolocation("IfcProjectedCRS", "Description", value)
@step(u'The geodetic datum must be "{coordinate_reference_name}"')
def step_impl(context, coordinate_reference_name):
if IfcStore.file.schema == "IFC2X3":
for site in IfcStore.file.by_type("IfcSite"):
util.assert_pset(site, "EPset_ProjectedCRS", "GeodeticDatum", coordinate_reference_name)
return
check_ifc4_geolocation("IfcProjectedCRS", "GeodeticDatum", coordinate_reference_name)
@step(u'The vertical datum must be "{coordinate_reference_name}"')
def step_impl(context, coordinate_reference_name):
if IfcStore.file.schema == "IFC2X3":
for site in IfcStore.file.by_type("IfcSite"):
util.assert_pset(site, "EPset_ProjectedCRS", "VerticalDatum", coordinate_reference_name)
return
check_ifc4_geolocation("IfcProjectedCRS", "VerticalDatum", coordinate_reference_name)
@step(u'The map projection must be "{coordinate_reference_name}"')
def step_impl(context, coordinate_reference_name):
if IfcStore.file.schema == "IFC2X3":
for site in IfcStore.file.by_type("IfcSite"):
util.assert_pset(site, "EPset_ProjectedCRS", "MapProjection", coordinate_reference_name)
return
check_ifc4_geolocation("IfcProjectedCRS", "MapProjection", coordinate_reference_name)
@step(u'The map zone must be "{coordinate_reference_name}"')
def step_impl(context, coordinate_reference_name):
if IfcStore.file.schema == "IFC2X3":
for site in IfcStore.file.by_type("IfcSite"):
util.assert_pset(site, "EPset_ProjectedCRS", "MapZone", coordinate_reference_name)
return
check_ifc4_geolocation("IfcProjectedCRS", "MapZone", coordinate_reference_name)
@step(u'The map unit must be "{unit}"')
def step_impl(context, unit):
if IfcStore.file.schema == "IFC2X3":
for site in IfcStore.file.by_type("IfcSite"):
util.assert_pset(site, "EPset_ProjectedCRS", "MapUnit", unit)
return
actual_value = check_ifc4_geolocation("IfcProjectedCRS", "MapUnit", should_assert=False)
if not actual_value:
assert False, _("A unit was not provided in the projected CRS")
if actual_value.is_a("IfcSIUnit"):
prefix = actual_value.Prefix if actual_value.Prefix else ""
actual_value = prefix + actual_value.Name
elif actual_value.is_a("IfcConversionBasedUnit"):
actual_value = actual_value.Name
assert actual_value == unit, _('We expected a value of "{}" but instead got "{}"').format(unit, actual_value)
@step(u"The project must have coordinate transformations to convert from local to global coordinates")
def step_impl(context):
if IfcStore.file.schema == "IFC2X3":
for site in IfcStore.file.by_type("IfcSite"):
util.assert_pset(site, "EPset_MapConversion")
check_ifc4_geolocation("IfcMapConversion")
@step(u'The eastings of the model must be offset by "{number}" to derive its global coordinates')
def step_impl(context, number):
number = util.assert_number(number)
if IfcStore.file.schema == "IFC2X3":
for site in IfcStore.file.by_type("IfcSite"):
util.assert_pset(site, "EPset_MapConversion", "Eastings", number)
return
check_ifc4_geolocation("IfcMapConversion", "Eastings", number)
@step(u'The northings of the model must be offset by "{number}" to derive its global coordinates')
def step_impl(context, number):
number = util.assert_number(number)
if IfcStore.file.schema == "IFC2X3":
for site in IfcStore.file.by_type("IfcSite"):
util.assert_pset(site, "EPset_MapConversion", "Northings", number)
return
check_ifc4_geolocation("IfcMapConversion", "Northings", number)
@step(u'The height of the model must be offset by "{number}" to derive its global coordinates')
def step_impl(context, number):
number = util.assert_number(number)
if IfcStore.file.schema == "IFC2X3":
for site in IfcStore.file.by_type("IfcSite"):
util.assert_pset(site, "EPset_MapConversion", "OrthogonalHeight", number)
return
check_ifc4_geolocation("IfcMapConversion", "OrthogonalHeight", number)
@step(u'The model must be rotated clockwise by "{number}" to derive its global coordinates')
def step_impl(context, number):
number = util.assert_number(number)
if IfcStore.file.schema == "IFC2X3":
return check_ifc2x3_geolocation("EPset_MapConversion", "Height", number)
abscissa = check_ifc4_geolocation("IfcMapConversion", "XAxisAbscissa", should_assert=False)
ordinate = check_ifc4_geolocation("IfcMapConversion", "XAxisOrdinate", should_assert=False)
actual_value = round(ifcopenshell.util.geolocation.xy2angle(abscissa, ordinate), 3)
value = round(number, 3)
assert actual_value == value, _('We expected a value of "{}" but instead got "{}"').format(value, actual_value)
@step(u'The model must be scaled along the horizontal axis by "{number}" to derive its global coordinates')
def step_impl(context, number):
number = util.assert_number(number)
if IfcStore.file.schema == "IFC2X3":
for site in IfcStore.file.by_type("IfcSite"):
util.assert_pset(site, "EPset_MapConversion", "Scale", number)
return
check_ifc4_geolocation("IfcMapConversion", "Scale", number)
@step(u'The site "{guid}" has a longitude of "{number}"')
def step_impl(context, guid, number):
number = util.assert_number(number)
site = util.assert_guid(IfcStore.file, guid)
util.assert_type(site, "IfcSite")
ref = util.assert_attribute(site, "RefLongitude")
number = ifcopenshell.util.geolocation.dd2dms(number, use_ms=(len(ref) == 4))
util.assert_attribute(site, "RefLongitude", number)
@step(u'The site "{guid}" has a latitude of "{number}"')
def step_impl(context, guid, number):
number = util.assert_number(number)
site = util.assert_guid(IfcStore.file, guid)
util.assert_type(site, "IfcSite")
ref = util.assert_attribute(site, "RefLatitude")
number = ifcopenshell.util.geolocation.dd2dms(number, use_ms=(len(ref) == 4))
util.assert_attribute(site, "RefLatitude", number)
@step(u'The site "{guid}" has an elevation of "{number}"')
def step_impl(context, guid, number):
number = util.assert_number(number)
site = util.assert_guid(IfcStore.file, guid)
util.assert_type(site, "IfcSite")
util.assert_attribute(site, "RefElevation", number)
@@ -0,0 +1,29 @@
from behave import step
from bimtester import util
from bimtester.ifc import IfcStore
from bimtester.lang import _
@step('All elements must be under "{number}" polygons')
def step_impl(context, number):
number = int(number)
errors = []
for element in IfcStore.file.by_type("IfcElement"):
if not element.Representation:
continue
total_polygons = 0
tree = IfcStore.file.traverse(element.Representation)
for e in tree:
if e.is_a("IfcFace"):
total_polygons += 1
elif e.is_a("IfcPolygonalFaceSet"):
total_polygons += len(e.Faces)
elif e.is_a("IfcTriangulatedFaceSet"):
total_polygons += len(e.CoordIndex)
if total_polygons > number:
errors.append((total_polygons, element))
if errors:
message = "The following {} elements are over 500 polygons:\n".format(len(errors))
for error in errors:
message += "Polygons: {} - {}\n".format(error[0], error[1])
assert False, message
@@ -0,0 +1,95 @@
import ifcopenshell.util.geolocation
import ifcopenshell.util.placement
from behave import step
from bimtester import util
from bimtester.ifc import IfcStore
from bimtester.lang import _
def get_decimal_points(value):
try:
return len(value.split(".")[1])
except:
return 0
def get_containing_spatial_elements(element):
results = []
if element.is_a("IfcSpatialElement"):
results.append(element)
for rel in element.Decomposes:
if rel.is_a("IfcRelAggregates"):
results.append(get_containing_spatial_elements(rel.RelatingObject))
elif element.is_a("IfcElement"):
for rel in element.ContainedInStructure:
if rel.is_a("ifcRelContainedInSpatialStructure"):
results.append(get_containing_spatial_elements(rel.RelatingStructure))
return results
@step('There is a datum element "{guid}" as an "{ifc_class}"')
def step_impl(context, guid, ifc_class):
element = utils.assert_guid(IfcStore.file, guid)
util.assert_type(element, ifc_class)
@step(
'The element "{guid}" has a global easting, northing, and elevation of "{easting}", "{northing}", and "{elevation}" respectively'
)
def step_impl(context, guid, easting, northing, elevation):
if IfcStore.file.schema == "IFC2X3":
if element.is_a("IfcSite"):
site = element
else:
potential_sites = [s for s in get_containing_spatial_elements(element) if s.is_a("IfcSite")]
if potential_sites:
site = potential_sites[0]
else:
assert False, _("The datum element does not belong to a geolocated site")
map_conversion = assert_pset(site, "EPset_MapConversion")
else:
map_conversion = IfcStore.file.by_type("IfcMapConversion")
if map_conversion:
map_conversion = map_conversion[0].get_info()
else:
assert False, _("No map conversion was found in the file")
element = utils.assert_guid(IfcStore.file, guid)
if not element.ObjectPlacement:
assert False, _("The element does not have an object placement: {}").format(element)
m = ifcopenshell.util.placement.get_local_placement(element.ObjectPlacement)
e, n, h = ifcopenshell.util.geolocation.xyz2enh(
m[0][3],
m[1][3],
m[2][3],
float(map_conversion["Eastings"]),
float(map_conversion["Northings"]),
float(map_conversion["OrthogonalHeight"]),
float(map_conversion["XAxisAbscissa"]),
float(map_conversion["XAxisOrdinate"]),
float(map_conversion["Scale"]),
)
element_x = round(e, get_decimal_points(easting))
element_y = round(n, get_decimal_points(northing))
element_z = round(h, get_decimal_points(elevation))
expected_placement = (util.assert_number(easting), util.assert_number(northing), util.assert_number(elevation))
if (element_x, element_y, element_z) != expected_placement:
assert False, _("The element {} is meant to have a location of {} but instead we found {}").format(
element, expected_placement, (element_x, element_y, element_z)
)
@step('The element "{guid}" has a local X, Y, and Z coordinate of "{x}", "{y}", and "{z}" respectively')
def step_impl(context, guid, x, y, z):
element = utils.assert_guid(IfcStore.file, guid)
if not element.ObjectPlacement:
assert False, _("The element does not have an object placement: {}").format(element)
m = ifcopenshell.util.placement.get_local_placement(element.ObjectPlacement)
element_x = round(m[0][3], get_decimal_points(x))
element_y = round(m[1][3], get_decimal_points(y))
element_z = round(m[2][3], get_decimal_points(z))
expected_placement = (util.assert_number(x), util.assert_number(y), util.assert_number(z))
if (element_x, element_y, element_z) != expected_placement:
assert False, _("The element {} is meant to have a location of {} but instead we found {}").format(
element, expected_placement, (element_x, element_y, element_z)
)
@@ -0,0 +1,16 @@
from behave import step
@step('Die IFC-Daten müssen das "{schema}" Schema benutzen')
def step_impl(context, schema):
context.execute_steps(f'* IFC data must use the "{schema}" schema')
@step('Die Globale Identifikationskennung (Globally Unique Identifier = GUID) des Projektes ist "{guid}"')
def step_impl(context, guid):
context.execute_steps(f'* The project must have an identifier of "{guid}"')
@step('Der Name, die Abkürzung oder die Kurzkennung des Projektes ist "{value}"')
def step_impl(context, value):
context.execute_steps(f'* The project name, code, or short identifier must be "{value}"')
@@ -0,0 +1,91 @@
from behave import step
from bimtester import util
from bimtester.ifc import IfcStore
from bimtester.lang import _
@step('IFC data must use the "{schema}" schema')
def step_impl(context, schema):
real_schema = IfcStore.file.schema
assert real_schema == schema, _("We expected a schema of {} but instead got {}").format(schema, real_schema)
@step('The IFC file "{file}" is exempt from being provided')
def step_impl(context, file):
pass
@step('No further requirements are specified because "{reason}"')
def step_impl(context, reason):
pass
@step('The project must have an identifier of "{guid}"')
def step_impl(context, guid):
util.assert_attribute(IfcStore.file.by_type("IfcProject")[0], "GlobalId", guid)
@step('The project name, code, or short identifier must be "{value}"')
def step_impl(context, value):
util.assert_attribute(IfcStore.file.by_type("IfcProject")[0], "Name", value)
@step('The project must have a longer form name of "{value}"')
def step_impl(context, value):
util.assert_attribute(IfcStore.file.by_type("IfcProject")[0], "LongName", value)
@step('The project must be described as "{value}"')
def step_impl(context, value):
util.assert_attribute(IfcStore.file.by_type("IfcProject")[0], "Description", value)
@step('The project must be categorised under "{value}"')
def step_impl(context, value):
util.assert_attribute(IfcStore.file.by_type("IfcProject")[0], "ObjectType", value)
@step('The project must contain information about the "{value}" phase')
def step_impl(context, value):
util.assert_attribute(IfcStore.file.by_type("IfcProject")[0], "Phase", value)
@step("The project must contain 3D geometry representing the shape of objects")
def step_impl(context):
assert get_subcontext("Body", "Model", "MODEL_VIEW")
@step("The project must contain 3D geometry representing clearance zones")
def step_impl(context):
assert get_subcontext("Clearance", "Model", "MODEL_VIEW")
@step("The project must contain 3D geometry representing the center of gravity of objects")
def step_impl(context):
assert get_subcontext("CoG", "Model", "MODEL_VIEW")
@step("The project must contain 3D geometry representing the object bounding boxes")
def step_impl(context):
assert get_subcontext("Box", "Model", "MODEL_VIEW")
def get_subcontext(identifier, type, target_view):
project = IfcStore.file.by_type("IfcProject")[0]
for rep_context in project.RepresentationContexts:
for subcontext in rep_context.HasSubContexts:
if (
subcontext.ContextIdentifier == identifier
and subcontext.ContextType == type
and subcontext.TargetView == target_view
):
return True
assert False, "The subcontext with identifier {}, type {}, and target view {} could not be found".format(
identifier, type, target_view
)
@step('the project has a {attribute_name} attribute with a value of "{attribute_value}"')
def step_impl(context, attribute_name, attribute_value):
project = IfcStore.file.by_type("IfcProject")[0]
assert getattr(project, attribute_name) == attribute_value
@@ -0,0 +1,6 @@
from behave import step
@step('Les données IFC doivent utiliser le schéma "{schema}"')
def step_impl(context, schema):
context.execute_steps(f'* IFC data must use the "{schema}" schema')
@@ -0,0 +1,11 @@
from behave import step
@step('I dati IFC devono seguire lo schema "{schema}"')
def step_impl(context, schema):
context.execute_steps(f'* IFC data must use the "{schema}" schema')
@step('Il nome del progetto, codice o identificatore breve deve essere "{value}"')
def step_impl(context, value):
context.execute_steps(f'* "The project name, code, or short identifier must be "{value}"')
@@ -0,0 +1,11 @@
from behave import step
@step('IFC-gegevens moeten het "{schema}" -schema gebruiken')
def step_impl(context, schema):
context.execute_steps(f'* IFC data must use the "{schema}" schema')
@step('De projectnaam, code of korte ID moet "{value}"')
def step_impl(context, value):
context.execute_steps(f'* "The project name, code, or short identifier must be "{value}"')
@@ -0,0 +1,138 @@
import fileinput
def create_zoom_smartview(sm_file, ifcbasename):
smf = open(sm_file, "w")
smf.write('<?xml version="1.0"?>\n')
smf.write("<bimcollabsmartviewfile>\n")
smf.write(" <version>5</version>\n")
smf.write(" <applicationversion>Win - Version: ")
# next line belongs to last, because of line length
smf.write("3.4 (build 3.4.13.559)</applicationversion>\n")
smf.write("</bimcollabsmartviewfile>\n")
smf.write("\n")
smf.write("<SMARTVIEWSETS>\n")
smf.write(" <SMARTVIEWSET>\n")
smf.write(" <TITLE>BIMTester {}</TITLE>\n".format(ifcbasename))
smf.write(" <DESCRIPTION></DESCRIPTION>\n")
smf.write(" <GUID>a2ddfaf7-97f2-4519-aabd-f2d94f6b4d6b</GUID>\n")
smf.write(" <MODIFICATIONDATE>2020-10-30T13:23:30")
# next line belongs to last, because of line length
smf.write("</MODIFICATIONDATE>\n")
smf.write(" <SMARTVIEWS>\n")
smf.write(" </SMARTVIEWS>\n")
smf.write(" </SMARTVIEWSET>\n")
smf.write("</SMARTVIEWSETS>\n")
smf.close()
def append_zoom_smartview(sm_file, step_name, false_elements_guid):
# build the smartview string
smview_string = " <SMARTVIEW>\n"
smview_string += (
" <TITLE>GUID filter, {}</TITLE>\n"
.format(step_name)
)
smview_string += "{}\n".format(each_smartview_string_before)
for guid in false_elements_guid:
smview_string += (
"{}{}{}\n".format(
rule_string_before,
guid,
rule_string_after)
)
smview_string += "{}\n".format(each_smartview_string_after)
# insert smartview string into file
theline = " </SMARTVIEWS>"
newtext = smview_string + theline
for line in fileinput.FileInput(sm_file, inplace=True):
# the print replaces the line in the file
# and add the line afterwards
print(line.replace(theline, newtext), end="")
each_smartview_string_title = """ <SMARTVIEW>
<TITLE>Filter GUID</TITLE>
<DESCRIPTION></DESCRIPTION>"""
each_smartview_string_before = """ <CREATOR>bernd@bimstatik.ch</CREATOR>
<CREATIONDATE>2020-10-30T13:18:45</CREATIONDATE>
<MODIFIER>bernd@bimstatik.ch</MODIFIER>
<MODIFICATIONDATE>2020-10-30T13:23:30</MODIFICATIONDATE>
<GUID>15fda94f-b4bf-43be-8ef4-15d3121137e1</GUID>
<RULES>
<RULE>
<IFCTYPE>Any</IFCTYPE>
<PROPERTY>
<NAME>None</NAME>
<PROPERTYSETNAME>None</PROPERTYSETNAME>
<TYPE>None</TYPE>
<VALUETYPE>None</VALUETYPE>
<UNIT>None</UNIT>
</PROPERTY>
<CONDITION>
<TYPE>Is</TYPE>
<VALUE></VALUE>
</CONDITION>
<ACTION>
<TYPE>AddSetColored</TYPE>
<R>187</R>
<G>187</G>
<B>187</B>
</ACTION>
</RULE>
<RULE>
<IFCTYPE>Any</IFCTYPE>
<PROPERTY>
<NAME>None</NAME>
<PROPERTYSETNAME>None</PROPERTYSETNAME>
<TYPE>None</TYPE>
<VALUETYPE>None</VALUETYPE>
<UNIT>None</UNIT>
</PROPERTY>
<CONDITION>
<TYPE>Is</TYPE>
<VALUE></VALUE>
</CONDITION>
<ACTION>
<TYPE>SetTransparent</TYPE>
</ACTION>
</RULE>"""
each_smartview_string_after = """ </RULES>
<INFORMATIONTAKEOFF>
<PROPERTYSETNAME>None</PROPERTYSETNAME>
<PROPERTYNAME>None</PROPERTYNAME>
<OPERATION>0</OPERATION>
</INFORMATIONTAKEOFF>
</SMARTVIEW>"""
rule_string_before = """ <RULE>
<IFCTYPE>Any</IFCTYPE>
<PROPERTY>
<NAME>GUID</NAME>
<PROPERTYSETNAME>Summary</PROPERTYSETNAME>
<TYPE>Summary</TYPE>
<VALUETYPE>StringValue</VALUETYPE>
<UNIT>None</UNIT>
</PROPERTY>
<CONDITION>
<TYPE>Is</TYPE>
<VALUE>"""
rule_string_after = """</VALUE>
</CONDITION>
<ACTION>
<TYPE>SetColored</TYPE>
<R>255</R>
<G>10</G>
<B>10</B>
</ACTION>
</RULE>"""
+153
View File
@@ -0,0 +1,153 @@
import os
import sys
import bimtester.run
from PySide2 import QtCore
from PySide2 import QtGui
from PySide2 import QtWidgets
def run():
app = QtWidgets.QApplication(sys.argv)
form = GuiWidgetBimTester()
form.show()
sys.exit(app.exec_())
class GuiWidgetBimTester(QtWidgets.QWidget):
def __init__(self, args=[]):
super(GuiWidgetBimTester, self).__init__()
self.args = args
self._setup_ui()
# http://forum.freecadweb.org/viewtopic.php?f=18&t=10732&start=10#p86493
def __del__(self):
return
def _setup_ui(self):
package_path = os.path.dirname(os.path.realpath(__file__))
iconpath = os.path.join(package_path, "resources", "icons", "bimtester.ico")
"""
# as svg
# https://stackoverflow.com/a/35138314
theicon = QtSvg.QSvgWidget(iconpath)
# none works ...
#theicon.setGeometry(20,20,200,200)
#theicon.setSizePolicy(
# QtGui.QSizePolicy.Policy.Maximum,
# QtGui.QSizePolicy.Policy.Maximum
#)
#theicon.sizeHint()
"""
# as pixmap
theicon = QtWidgets.QLabel(self)
iconpixmap = QtGui.QPixmap(iconpath)
iconpixmap = iconpixmap.scaled(100, 100, QtCore.Qt.KeepAspectRatio)
theicon.setPixmap(iconpixmap)
# ifc file
_ifcfile_label = QtWidgets.QLabel("IFC file", self)
self.ifcfile_text = QtWidgets.QLineEdit()
_ifcfile_browse_btn = QtWidgets.QToolButton()
_ifcfile_browse_btn.setText("...")
_ifcfile_browse_btn.clicked.connect(self.select_ifcfile)
# feature files path
# use a layout with a frame and a title, see solver framework tp
# beside button
ffifc_str = "Feature files in a directory 'features' beside the IFC file."
featuredirfromifc_label = QtWidgets.QLabel(ffifc_str, self)
# path browser and line edit
_ffdir_str = "Feature files directory. " "'features' directory has to be in there."
_featurefilesdir_label = QtWidgets.QLabel(_ffdir_str, self)
self.featurefilesdir_text = QtWidgets.QLineEdit()
self.feafilesdir_browse_btn = QtWidgets.QToolButton()
self.feafilesdir_browse_btn.setText("...")
self.feafilesdir_browse_btn.clicked.connect(self.select_featurefilesdir)
# buttons
self.run_button = QtWidgets.QPushButton(QtGui.QIcon.fromTheme("document-new"), "Run")
self.close_button = QtWidgets.QPushButton(QtGui.QIcon.fromTheme("window-close"), "Close")
self.run_button.clicked.connect(self.run_bimtester)
self.close_button.clicked.connect(self.close_widget)
_buttons = QtWidgets.QHBoxLayout()
_buttons.addWidget(self.run_button)
_buttons.addWidget(self.close_button)
# Layout:
layout = QtWidgets.QGridLayout()
layout.addWidget(theicon, 1, 0, alignment=QtCore.Qt.AlignRight)
layout.addWidget(featuredirfromifc_label, 2, 0)
layout.addWidget(_featurefilesdir_label, 3, 0)
layout.addWidget(self.featurefilesdir_text, 4, 0)
layout.addWidget(self.feafilesdir_browse_btn, 4, 1)
layout.addWidget(_ifcfile_label, 5, 0)
layout.addWidget(self.ifcfile_text, 6, 0)
layout.addWidget(_ifcfile_browse_btn, 6, 1)
layout.addLayout(_buttons, 7, 0)
# row stretches by 10 compared to the others, std is 0
# first parameter is the row number
# second is the stretch factor.
layout.setRowStretch(0, 10)
self.setLayout(layout)
def select_ifcfile(self):
ifcfile = QtWidgets.QFileDialog.getOpenFileName(self, dir=self.get_ifcfile())[0]
self.set_ifcfile(ifcfile)
def set_ifcfile(self, a_file):
self.ifcfile_text.setText(a_file)
def get_ifcfile(self):
return self.ifcfile_text.text()
def select_featurefilesdir(self):
thedir = self.featurefilesdir_text.text()
features_path = QtWidgets.QFileDialog.getExistingDirectory(
self,
caption="Choose features directory ...",
dir=thedir,
options=QtWidgets.QFileDialog.HideNameFilterDetails,
)
self.set_featurefilesdir(features_path)
def set_featurefilesdir(self, a_directory):
self.featurefilesdir_text.setText(a_directory)
def get_featurefilesdir(self):
return self.featurefilesdir_text.text()
def run_bimtester(self):
print("Run BIMTester by the GUI")
QtWidgets.QApplication.setOverrideCursor(QtCore.Qt.WaitCursor)
the_features_path = self.get_featurefilesdir()
print(the_features_path)
# get ifc file
the_ifcfile = self.get_ifcfile()
print(the_ifcfile)
# overwrite the_features_path and ifcfile in args
patched_args = self.args
patched_args["featuresdir"] = the_features_path
patched_args["ifcfile"] = the_ifcfile
bimtester.run.TestRunner("file.ifc").run({})
QtWidgets.QApplication.restoreOverrideCursor()
def close_widget(self):
self.close()
def closeEvent(self, ev):
pw = self.parentWidget()
if pw and pw.inherits("QDockWidget"):
pw.deleteLater()
+4
View File
@@ -0,0 +1,4 @@
class IfcStore:
path = ""
file = None
bookmarks = {}
+15
View File
@@ -0,0 +1,15 @@
import gettext
translation = None
def _(message):
if translation:
return translation(message)
return message
def switch_locale(locale_dir, locale_id="en"):
global translation
newlang = gettext.translation("messages", localedir=locale_dir, languages=[locale_id])
newlang.install()
translation = newlang.gettext
@@ -0,0 +1,200 @@
# German translations for PROJECT.
# Copyright (C) 2020 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
#
msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2021-01-17 10:55+0100\n"
"PO-Revision-Date: 2020-12-23 11:20+0100\n"
"Last-Translator: \n"
"Language: de\n"
"Language-Team: de <LL@li.org>\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.6.0\n"
#: reports.py:158
msgid "en"
msgstr "de"
#: reports.py:159
msgid "Success"
msgstr "Bestanden"
#: reports.py:160
msgid "Failure"
msgstr "Durchgefallen"
#: reports.py:161
msgid "Tests passed"
msgstr "Erfolgreiche Tests"
#: reports.py:162
msgid "Duration"
msgstr "Dauer"
#: reports.py:163
msgid "OpenBIM auditing is a feature of"
msgstr "OpenBIM auditing ist eine Funktionalität von"
#: reports.py:164
msgid "and"
msgstr "und"
#: features/steps/attributes_eleclasses_methods.py:26
msgid "All {elemcount} elements in the file are {ifc_class}."
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:34
msgid "{falsecount} of {elemcount} element are {ifc_class} elements: {falseelems}"
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:43
#: features/steps/utils.py:158
msgid "Error in falsecount, something went wrong."
msgstr "Fehler in falsecount, es ist etwas falsch gelaufen."
#: features/steps/attributes_eleclasses_methods.py:84
msgid ""
"For all {elemcount} {ifc_class} elements at least one of these class "
"attributes {parameter} has no value."
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:85
msgid ""
"For the following {falsecount} out of {elemcount} {ifc_class} elements at"
" least one of these class attributes {parameter} has no value: "
"{falseelems}"
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:86
#: features/steps/attributes_eleclasses_methods.py:112
#: features/steps/attributes_eleclasses_methods.py:139
#: features/steps/attributes_psets_methods.py:33
#: features/steps/geometric_detail_methods.py:56
#: features/steps/geometric_detail_methods.py:134
msgid "There are no {ifc_class} elements in the IFC file."
msgstr "Es sind keine {ifc_class} Bauteile in der IFC-Datei."
#: features/steps/attributes_eleclasses_methods.py:110
msgid "The name of all {elemcount} {elemcount} elements is not set."
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:111
msgid ""
"The name of {falsecount} out of {elemcount} {ifc_class} elements is not "
"set: {falseelems}"
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:137
msgid "The description of all {elemcount} {elemcount} elements is not set."
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:138
msgid ""
"The description of {falsecount} out of {elemcount} {ifc_class} elements "
"is not set: {falseelems}"
msgstr ""
#: features/steps/attributes_psets_methods.py:31
msgid ""
"All {elemcount} {ifc_class} elements are missing the property {parameter}"
" in the pset."
msgstr ""
#: features/steps/attributes_psets_methods.py:32
msgid ""
"The following {falsecount} of {elemcount} {ifc_class} elements are "
"missing the property {parameter} in the pset: {falseelems}"
msgstr ""
#: features/steps/geometric_detail_methods.py:54
msgid "All {elemcount} {ifc_class} elements are not a {parameter} representation."
msgstr ""
"Alle {elemcount} {ifc_class} Bauteile haben keine geometrische "
"Repräsentation der Klasse {parameter}."
#: features/steps/geometric_detail_methods.py:55
msgid ""
"The following {falsecount} of {elemcount} {ifc_class} elements are not a "
"{parameter} representation: {falseelems}"
msgstr ""
"Die Anzahl Bauteile {falsecount} von allen {elemcount} {ifc_class} "
"Bauteilen haben keine geometrische Repräsentation der Klasse {parameter}:"
" {falseelems}"
#: features/steps/geometric_detail_methods.py:132
msgid "The geometry of all {elemcount} {ifc_class} elements have errors."
msgstr ""
"Die geometrischen Repräsentationen von allen {elemcount} {ifc_class} "
"Bauteilen haben Fehler."
#: features/steps/geometric_detail_methods.py:133
msgid ""
"The geometry of {falsecount} out of all {elemcount} {ifc_class} elements "
"have errors: {falseelems}"
msgstr ""
"Die geometrischen Repräsentationen von {falsecount} von allen {elemcount}"
" {ifc_class} Bauteilen haben Fehler: {falseelems}"
#: features/steps/ifcdata_methods.py:9
msgid "The IFC {} file could not be loaded"
msgstr ""
#: features/steps/ifcdata_methods.py:17
msgid "We expected a schema of {} but instead got {}"
msgstr "Wir haben das Schema {} erwartet, aber die Daten nutzen das Schema {}"
#~ msgid "The geometry of all {} {} elements have errors."
#~ msgstr ""
#~ "Die geometrischen Repräsentationen von allen"
#~ " {} {} Bauteilen haben Fehler."
#~ msgid "The geometry of {} out of all {} {} elements have errors: {}"
#~ msgstr ""
#~ "Die geometrischen Repräsentationen von {} "
#~ "von allen {} {} Bauteilen haben "
#~ "Fehler: {}"
#~ msgid "There are no {} elements in the IFC file."
#~ msgstr "Es sind keine {} Bauteile in der IFC-Datei."
#~ msgid "All {} {} elements are not a IfcFacetedBrep representation."
#~ msgstr ""
#~ "Alle {} {} Bauteile haben keine "
#~ "geometrische Repräsentation der Klasse "
#~ "IfcFacetedBrep."
#~ msgid ""
#~ "The following {} of {} {} elements"
#~ " are not a IfcFacetedBrep representation:"
#~ " {}"
#~ msgstr ""
#~ "Die Anzahl Bauteile {} von allen "
#~ "{} {} Bauteilen haben keine geometrische"
#~ " Repräsentation der Klasse IfcFacetedBrep: "
#~ "{}"
#~ msgid ""
#~ "All {elemcount} {ifc_class} elements are "
#~ "not a IfcFacetedBrep representation."
#~ msgstr ""
#~ "Alle {elemcount} {ifc_class} Bauteile haben"
#~ " keine geometrische Repräsentation der "
#~ "Klasse IfcFacetedBrep."
#~ msgid ""
#~ "The following {falsecount} of {elemcount} "
#~ "{ifc_class} elements are not a "
#~ "IfcFacetedBrep representation: {falseelems}"
#~ msgstr ""
#~ "Die Anzahl Bauteile {falsecount} von "
#~ "allen {elemcount} {ifc_class} Bauteilen haben"
#~ " keine geometrische Repräsentation der "
#~ "Klasse IfcFacetedBrep: {falseelems}"
@@ -0,0 +1,172 @@
# German translations for PROJECT.
# Copyright (C) 2020 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
#
msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2021-01-17 10:55+0100\n"
"PO-Revision-Date: 2020-12-18 11:41+0100\n"
"Last-Translator: \n"
"Language: en\n"
"Language-Team: en <LL@li.org>\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.6.0\n"
#: reports.py:158
msgid "en"
msgstr ""
#: reports.py:159
msgid "Success"
msgstr ""
#: reports.py:160
msgid "Failure"
msgstr ""
#: reports.py:161
msgid "Tests passed"
msgstr ""
#: reports.py:162
msgid "Duration"
msgstr ""
#: reports.py:163
msgid "OpenBIM auditing is a feature of"
msgstr ""
#: reports.py:164
msgid "and"
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:26
msgid "All {elemcount} elements in the file are {ifc_class}."
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:34
msgid "{falsecount} of {elemcount} element are {ifc_class} elements: {falseelems}"
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:43
#: features/steps/utils.py:158
msgid "Error in falsecount, something went wrong."
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:84
msgid ""
"For all {elemcount} {ifc_class} elements at least one of these class "
"attributes {parameter} has no value."
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:85
msgid ""
"For the following {falsecount} out of {elemcount} {ifc_class} elements at"
" least one of these class attributes {parameter} has no value: "
"{falseelems}"
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:86
#: features/steps/attributes_eleclasses_methods.py:112
#: features/steps/attributes_eleclasses_methods.py:139
#: features/steps/attributes_psets_methods.py:33
#: features/steps/geometric_detail_methods.py:56
#: features/steps/geometric_detail_methods.py:134
msgid "There are no {ifc_class} elements in the IFC file."
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:110
msgid "The name of all {elemcount} {elemcount} elements is not set."
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:111
msgid ""
"The name of {falsecount} out of {elemcount} {ifc_class} elements is not "
"set: {falseelems}"
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:137
msgid "The description of all {elemcount} {elemcount} elements is not set."
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:138
msgid ""
"The description of {falsecount} out of {elemcount} {ifc_class} elements "
"is not set: {falseelems}"
msgstr ""
#: features/steps/attributes_psets_methods.py:31
msgid ""
"All {elemcount} {ifc_class} elements are missing the property {parameter}"
" in the pset."
msgstr ""
#: features/steps/attributes_psets_methods.py:32
msgid ""
"The following {falsecount} of {elemcount} {ifc_class} elements are "
"missing the property {parameter} in the pset: {falseelems}"
msgstr ""
#: features/steps/geometric_detail_methods.py:54
msgid "All {elemcount} {ifc_class} elements are not a {parameter} representation."
msgstr ""
#: features/steps/geometric_detail_methods.py:55
msgid ""
"The following {falsecount} of {elemcount} {ifc_class} elements are not a "
"{parameter} representation: {falseelems}"
msgstr ""
#: features/steps/geometric_detail_methods.py:132
msgid "The geometry of all {elemcount} {ifc_class} elements have errors."
msgstr ""
#: features/steps/geometric_detail_methods.py:133
msgid ""
"The geometry of {falsecount} out of all {elemcount} {ifc_class} elements "
"have errors: {falseelems}"
msgstr ""
#: features/steps/ifcdata_methods.py:9
msgid "The IFC {} file could not be loaded"
msgstr ""
#: features/steps/ifcdata_methods.py:17
msgid "We expected a schema of {} but instead got {}"
msgstr ""
#~ msgid "The geometry of all {} {} elements have errors."
#~ msgstr ""
#~ msgid "The geometry of {} out of all {} {} elements have errors: {}"
#~ msgstr ""
#~ msgid "There are no {} elements in the IFC file."
#~ msgstr ""
#~ msgid "All {} {} elements are not a IfcFacetedBrep representation."
#~ msgstr ""
#~ msgid ""
#~ "The following {} of {} {} elements"
#~ " are not a IfcFacetedBrep representation:"
#~ " {}"
#~ msgstr ""
#~ msgid ""
#~ "All {elemcount} {ifc_class} elements are "
#~ "not a IfcFacetedBrep representation."
#~ msgstr ""
#~ msgid ""
#~ "The following {falsecount} of {elemcount} "
#~ "{ifc_class} elements are not a "
#~ "IfcFacetedBrep representation: {falseelems}"
#~ msgstr ""
@@ -0,0 +1,143 @@
# French translations for PROJECT.
# Copyright (C) 2020 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
#
msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2021-01-17 10:55+0100\n"
"PO-Revision-Date: 2020-12-23 11:21+0100\n"
"Last-Translator: \n"
"Language: fr\n"
"Language-Team: fr <LL@li.org>\n"
"Plural-Forms: nplurals=2; plural=(n > 1)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.6.0\n"
#: reports.py:158
msgid "en"
msgstr "fr"
#: reports.py:159
msgid "Success"
msgstr "Succès"
#: reports.py:160
msgid "Failure"
msgstr "Échec"
#: reports.py:161
msgid "Tests passed"
msgstr "Tests réussis"
#: reports.py:162
msgid "Duration"
msgstr "Durée"
#: reports.py:163
msgid "OpenBIM auditing is a feature of"
msgstr "L'audit OpenBIM auditing est une fonctionnalité de"
#: reports.py:164
msgid "and"
msgstr "et"
#: features/steps/attributes_eleclasses_methods.py:26
msgid "All {elemcount} elements in the file are {ifc_class}."
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:34
msgid "{falsecount} of {elemcount} element are {ifc_class} elements: {falseelems}"
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:43
#: features/steps/utils.py:158
msgid "Error in falsecount, something went wrong."
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:84
msgid ""
"For all {elemcount} {ifc_class} elements at least one of these class "
"attributes {parameter} has no value."
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:85
msgid ""
"For the following {falsecount} out of {elemcount} {ifc_class} elements at"
" least one of these class attributes {parameter} has no value: "
"{falseelems}"
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:86
#: features/steps/attributes_eleclasses_methods.py:112
#: features/steps/attributes_eleclasses_methods.py:139
#: features/steps/attributes_psets_methods.py:33
#: features/steps/geometric_detail_methods.py:56
#: features/steps/geometric_detail_methods.py:134
msgid "There are no {ifc_class} elements in the IFC file."
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:110
msgid "The name of all {elemcount} {elemcount} elements is not set."
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:111
msgid ""
"The name of {falsecount} out of {elemcount} {ifc_class} elements is not "
"set: {falseelems}"
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:137
msgid "The description of all {elemcount} {elemcount} elements is not set."
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:138
msgid ""
"The description of {falsecount} out of {elemcount} {ifc_class} elements "
"is not set: {falseelems}"
msgstr ""
#: features/steps/attributes_psets_methods.py:31
msgid ""
"All {elemcount} {ifc_class} elements are missing the property {parameter}"
" in the pset."
msgstr ""
#: features/steps/attributes_psets_methods.py:32
msgid ""
"The following {falsecount} of {elemcount} {ifc_class} elements are "
"missing the property {parameter} in the pset: {falseelems}"
msgstr ""
#: features/steps/geometric_detail_methods.py:54
msgid "All {elemcount} {ifc_class} elements are not a {parameter} representation."
msgstr ""
#: features/steps/geometric_detail_methods.py:55
msgid ""
"The following {falsecount} of {elemcount} {ifc_class} elements are not a "
"{parameter} representation: {falseelems}"
msgstr ""
#: features/steps/geometric_detail_methods.py:132
msgid "The geometry of all {elemcount} {ifc_class} elements have errors."
msgstr ""
#: features/steps/geometric_detail_methods.py:133
msgid ""
"The geometry of {falsecount} out of all {elemcount} {ifc_class} elements "
"have errors: {falseelems}"
msgstr ""
#: features/steps/ifcdata_methods.py:9
msgid "The IFC {} file could not be loaded"
msgstr ""
#: features/steps/ifcdata_methods.py:17
msgid "We expected a schema of {} but instead got {}"
msgstr ""
@@ -0,0 +1,196 @@
# Italian translations for PROJECT.
# Copyright (C) 2020 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2020.
#
msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2021-01-17 10:55+0100\n"
"PO-Revision-Date: 2020-12-18 11:41+0100\n"
"Last-Translator: \n"
"Language: it\n"
"Language-Team: it <LL@li.org>\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.6.0\n"
#: reports.py:158
msgid "en"
msgstr "it"
#: reports.py:159
msgid "Success"
msgstr "Successo"
#: reports.py:160
msgid "Failure"
msgstr "Errore"
#: reports.py:161
msgid "Tests passed"
msgstr "Test superati"
#: reports.py:162
msgid "Duration"
msgstr "Durata"
#: reports.py:163
msgid "OpenBIM auditing is a feature of"
msgstr "L'auditing OpenBIM è una caratteristica di"
#: reports.py:164
msgid "and"
msgstr "e"
#: features/steps/attributes_eleclasses_methods.py:26
msgid "All {elemcount} elements in the file are {ifc_class}."
msgstr "Tutti {elemcount} elementi nel file sono classificati {ifc_class}"
#: features/steps/attributes_eleclasses_methods.py:34
msgid "{falsecount} of {elemcount} element are {ifc_class} elements: {falseelems}"
msgstr ""
"{falsecount} di {elemcount} elementi sono elementi {ifc_class}: "
"{falseelems}"
#: features/steps/attributes_eleclasses_methods.py:43
#: features/steps/utils.py:158
msgid "Error in falsecount, something went wrong."
msgstr "Errore in falsecount, qualcosa è andato storto."
#: features/steps/attributes_eleclasses_methods.py:84
msgid ""
"For all {elemcount} {ifc_class} elements at least one of these class "
"attributes {parameter} has no value."
msgstr ""
"Per tutti {elemcount} elementi {ifc_class} almeno uno di questa "
"classedegli attributi {parameter} non contiene alcun valore"
#: features/steps/attributes_eleclasses_methods.py:85
msgid ""
"For the following {falsecount} out of {elemcount} {ifc_class} elements at"
" least one of these class attributes {parameter} has no value: "
"{falseelems}"
msgstr ""
"Per i seguenti {falsecount} di {elemcount} elementi {ifc_class}almeno uno"
" degli attributi {parameter} non contiene alcun valore"
#: features/steps/attributes_eleclasses_methods.py:86
#: features/steps/attributes_eleclasses_methods.py:112
#: features/steps/attributes_eleclasses_methods.py:139
#: features/steps/attributes_psets_methods.py:33
#: features/steps/geometric_detail_methods.py:56
#: features/steps/geometric_detail_methods.py:134
msgid "There are no {ifc_class} elements in the IFC file."
msgstr "Il file IFC non contiene elementi della classe {ifc_class}."
#: features/steps/attributes_eleclasses_methods.py:110
msgid "The name of all {elemcount} {elemcount} elements is not set."
msgstr "Il nome di {elemcount} {elemcount} elementi non è impostato"
#: features/steps/attributes_eleclasses_methods.py:111
msgid ""
"The name of {falsecount} out of {elemcount} {ifc_class} elements is not "
"set: {falseelems}"
msgstr "Il nome di {falsecount} su {elemcount} elementi {ifc_class} non èimpostato"
#: features/steps/attributes_eleclasses_methods.py:137
msgid "The description of all {elemcount} {elemcount} elements is not set."
msgstr "La descrizione di tutti {elemcount} {elemcount} elementi non èimpostato "
#: features/steps/attributes_eleclasses_methods.py:138
msgid ""
"The description of {falsecount} out of {elemcount} {ifc_class} elements "
"is not set: {falseelems}"
msgstr ""
"la descrizione di {falsecount} su {elemcount} elementi {ifc_class} non "
"èimpostato"
#: features/steps/attributes_psets_methods.py:31
msgid ""
"All {elemcount} {ifc_class} elements are missing the property {parameter}"
" in the pset."
msgstr ""
"A {elemcount} gli elementi {ifc_class} manca la proprietà "
"{parameter}nello pset."
#: features/steps/attributes_psets_methods.py:32
msgid ""
"The following {falsecount} of {elemcount} {ifc_class} elements are "
"missing the property {parameter} in the pset: {falseelems}"
msgstr ""
"Ai seguenti {falsecount} di {elemcount} elementi {ifc_class} manca la "
"proprietà{parameter} nello pset: {falseelems}"
#: features/steps/geometric_detail_methods.py:54
msgid "All {elemcount} {ifc_class} elements are not a {parameter} representation."
msgstr "Tutti {elemcount} elementi {ifc_class} non rappresentano {parameter}"
#: features/steps/geometric_detail_methods.py:55
msgid ""
"The following {falsecount} of {elemcount} {ifc_class} elements are not a "
"{parameter} representation: {falseelems}"
msgstr ""
"I seguenti {falsecount} di {elemcount} elementi {ifc_class} non "
"rappresentano{parameter}: {falseelems}"
#: features/steps/geometric_detail_methods.py:132
msgid "The geometry of all {elemcount} {ifc_class} elements have errors."
msgstr "La geometria di tutti {elemcount} elementi {ifc_class} contiene errori"
#: features/steps/geometric_detail_methods.py:133
msgid ""
"The geometry of {falsecount} out of all {elemcount} {ifc_class} elements "
"have errors: {falseelems}"
msgstr ""
"La geometria di {falsecount} su {elemcount} elementi {ifc_class} "
"contieneerrori: {falseelems}"
#: features/steps/ifcdata_methods.py:9
msgid "The IFC {} file could not be loaded"
msgstr ""
#: features/steps/ifcdata_methods.py:17
msgid "We expected a schema of {} but instead got {}"
msgstr "Ci aspettavamo uno schema di {} ma invece abbiamo ottenuto {}"
#~ msgid "The geometry of all {} {} elements have errors."
#~ msgstr "La geometria di tutti gli elementi {} {} contiene errori."
#~ msgid "The geometry of {} out of all {} {} elements have errors: {}"
#~ msgstr "La geometria di {} su {} {} elementi contiene errori."
#~ msgid "There are no {} elements in the IFC file."
#~ msgstr "Non ci sono {} elementi nel file IFC."
#~ msgid "All {} {} elements are not a IfcFacetedBrep representation."
#~ msgstr "Tutti gli elementi {} {} non sono una rappresentazioneIfcFacetedBrep."
#~ msgid ""
#~ "The following {} of {} {} elements"
#~ " are not a IfcFacetedBrep representation:"
#~ " {}"
#~ msgstr ""
#~ "I seguenti {} di {} {} elementi"
#~ " non sono una rappresentazioneIfcFacetedBrep. "
#~ "{}"
#~ msgid ""
#~ "All {elemcount} {ifc_class} elements are "
#~ "not a IfcFacetedBrep representation."
#~ msgstr ""
#~ "Tutti {elemcount} elementi {ifc_class} non"
#~ " sono una rappresentazioneIfcFacetedBrep."
#~ msgid ""
#~ "The following {falsecount} of {elemcount} "
#~ "{ifc_class} elements are not a "
#~ "IfcFacetedBrep representation: {falseelems}"
#~ msgstr ""
#~ "I seguenti {falsecount} su {elemcount} "
#~ "elementi {ifc_class} non sonouna "
#~ "rappresentazione IfcFacetedBrep."
@@ -0,0 +1,142 @@
# Translations template for PROJECT.
# Copyright (C) 2021 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
# FIRST AUTHOR <EMAIL@ADDRESS>, 2021.
#
#, fuzzy
msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSION\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n"
"POT-Creation-Date: 2021-01-17 10:55+0100\n"
"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n"
"Last-Translator: FULL NAME <EMAIL@ADDRESS>\n"
"Language-Team: LANGUAGE <LL@li.org>\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.6.0\n"
#: reports.py:158
msgid "en"
msgstr ""
#: reports.py:159
msgid "Success"
msgstr ""
#: reports.py:160
msgid "Failure"
msgstr ""
#: reports.py:161
msgid "Tests passed"
msgstr ""
#: reports.py:162
msgid "Duration"
msgstr ""
#: reports.py:163
msgid "OpenBIM auditing is a feature of"
msgstr ""
#: reports.py:164
msgid "and"
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:26
msgid "All {elemcount} elements in the file are {ifc_class}."
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:34
msgid "{falsecount} of {elemcount} element are {ifc_class} elements: {falseelems}"
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:43
#: features/steps/utils.py:158
msgid "Error in falsecount, something went wrong."
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:84
msgid ""
"For all {elemcount} {ifc_class} elements at least one of these class "
"attributes {parameter} has no value."
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:85
msgid ""
"For the following {falsecount} out of {elemcount} {ifc_class} elements at"
" least one of these class attributes {parameter} has no value: "
"{falseelems}"
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:86
#: features/steps/attributes_eleclasses_methods.py:112
#: features/steps/attributes_eleclasses_methods.py:139
#: features/steps/attributes_psets_methods.py:33
#: features/steps/geometric_detail_methods.py:56
#: features/steps/geometric_detail_methods.py:134
msgid "There are no {ifc_class} elements in the IFC file."
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:110
msgid "The name of all {elemcount} {elemcount} elements is not set."
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:111
msgid ""
"The name of {falsecount} out of {elemcount} {ifc_class} elements is not "
"set: {falseelems}"
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:137
msgid "The description of all {elemcount} {elemcount} elements is not set."
msgstr ""
#: features/steps/attributes_eleclasses_methods.py:138
msgid ""
"The description of {falsecount} out of {elemcount} {ifc_class} elements "
"is not set: {falseelems}"
msgstr ""
#: features/steps/attributes_psets_methods.py:31
msgid ""
"All {elemcount} {ifc_class} elements are missing the property {parameter}"
" in the pset."
msgstr ""
#: features/steps/attributes_psets_methods.py:32
msgid ""
"The following {falsecount} of {elemcount} {ifc_class} elements are "
"missing the property {parameter} in the pset: {falseelems}"
msgstr ""
#: features/steps/geometric_detail_methods.py:54
msgid "All {elemcount} {ifc_class} elements are not a {parameter} representation."
msgstr ""
#: features/steps/geometric_detail_methods.py:55
msgid ""
"The following {falsecount} of {elemcount} {ifc_class} elements are not a "
"{parameter} representation: {falseelems}"
msgstr ""
#: features/steps/geometric_detail_methods.py:132
msgid "The geometry of all {elemcount} {ifc_class} elements have errors."
msgstr ""
#: features/steps/geometric_detail_methods.py:133
msgid ""
"The geometry of {falsecount} out of all {elemcount} {ifc_class} elements "
"have errors: {falseelems}"
msgstr ""
#: features/steps/ifcdata_methods.py:9
msgid "The IFC {} file could not be loaded"
msgstr ""
#: features/steps/ifcdata_methods.py:17
msgid "We expected a schema of {} but instead got {}"
msgstr ""
@@ -0,0 +1,196 @@
# Dutch translations for Bimtester.
# Copyright (C) 2021 ORGANIZATION
# This file is distributed under the same license as the PROJECT project.
# Marcel Plomp , 2021.
#
msgid ""
msgstr ""
"Project-Id-Version: PROJECT VERSIE\n"
"Report-Msgid-Bugs-To: EMAIL@ADDRES\n"
"POT-Creation-Date: 2021-01-17 10:55+0100\n"
"PO-Revision-Date: 2020-12-18 11:41+0100\n"
"Last-Translator: \n"
"Language: nl\n"
"Language-Team: nl <LL@li.org>\n"
"Plural-Forms: nplurals=2; plural=(n != 1)\n"
"MIME-Version: 1.0\n"
"Content-Type: text/plain; charset=utf-8\n"
"Content-Transfer-Encoding: 8bit\n"
"Generated-By: Babel 2.6.0\n"
#: reports.py:158
msgid "en"
msgstr "nl"
#: reports.py:159
msgid "Success"
msgstr "Succes"
#: reports.py:160
msgid "Failure"
msgstr "Fout"
#: reports.py:161
msgid "Tests passed"
msgstr "Tests geslaagd"
#: reports.py:162
msgid "Duration"
msgstr "Tijdsduur"
#: reports.py:163
msgid "OpenBIM auditing is a feature of"
msgstr "OpenBIM-auditing is een kenmerk van"
#: reports.py:164
msgid "and"
msgstr "en"
#: features/steps/attributes_eleclasses_methods.py:26
msgid "All {elemcount} elements in the file are {ifc_class}."
msgstr "Alle {elemcount} de elementen in het bestand zijn {ifc_class}"
#: features/steps/attributes_eleclasses_methods.py:34
msgid "{falsecount} of {elemcount} element are {ifc_class} elements: {falseelems}"
msgstr ""
"{falsecount} van de {elemcount} elementen zijn {ifc_class} elementen: "
"{falseelems}"
#: features/steps/attributes_eleclasses_methods.py:43
#: features/steps/utils.py:158
msgid "Error in falsecount, something went wrong."
msgstr "Fout in de telling, er is iets misgegaan."
#: features/steps/attributes_eleclasses_methods.py:84
msgid ""
"For all {elemcount} {ifc_class} elements at least one of these class "
"attributes {parameter} has no value."
msgstr ""
"Voor alle {elemcount} {ifc_class} elementen heeft ten minste één van deze"
" class attributen {parameter} heeft geen waarde."
#: features/steps/attributes_eleclasses_methods.py:85
msgid ""
"For the following {falsecount} out of {elemcount} {ifc_class} elements at"
" least one of these class attributes {parameter} has no value: "
"{falseelems}"
msgstr ""
"Van de {falsecount} uit {elemcount} {ifc_class} elementen op ten minste "
"een van deze class-attributen {parameter} heeft geen waarde:{falseelems}"
#: features/steps/attributes_eleclasses_methods.py:86
#: features/steps/attributes_eleclasses_methods.py:112
#: features/steps/attributes_eleclasses_methods.py:139
#: features/steps/attributes_psets_methods.py:33
#: features/steps/geometric_detail_methods.py:56
#: features/steps/geometric_detail_methods.py:134
msgid "There are no {ifc_class} elements in the IFC file."
msgstr "Er zijn geen {ifc_class} elementen in het IFC-bestand."
#: features/steps/attributes_eleclasses_methods.py:110
msgid "The name of all {elemcount} {elemcount} elements is not set."
msgstr "De naam van alle {elemcount} {elemcount} elementen is niet ingesteld."
#: features/steps/attributes_eleclasses_methods.py:111
msgid ""
"The name of {falsecount} out of {elemcount} {ifc_class} elements is not "
"set: {falseelems}"
msgstr ""
"De naam van {falsecount} van de {elemcount} {ifc_class} elementen is "
"nietset: {falseelems}"
#: features/steps/attributes_eleclasses_methods.py:137
msgid "The description of all {elemcount} {elemcount} elements is not set."
msgstr ""
"De beschrijving van alle {elemcount} {elemcount} elementen is niet "
"ingesteld."
#: features/steps/attributes_eleclasses_methods.py:138
msgid ""
"The description of {falsecount} out of {elemcount} {ifc_class} elements "
"is not set: {falseelems}"
msgstr ""
"De beschrijving van {falsecount} uit {elemcount} {ifc_class} elementen is"
" niet ingesteld: {falseelems}"
#: features/steps/attributes_psets_methods.py:31
msgid ""
"All {elemcount} {ifc_class} elements are missing the property {parameter}"
" in the pset."
msgstr ""
"Alle {elemcount} {ifc_class} elementen missen de eigenschap {parameter} "
"in de pset."
#: features/steps/attributes_psets_methods.py:32
msgid ""
"The following {falsecount} of {elemcount} {ifc_class} elements are "
"missing the property {parameter} in the pset: {falseelems}"
msgstr ""
"De volgende {falsecount} van {elemcount} {ifc_class} elementen zijn "
"ontbreekt de eigenschap {parameter} in de pset: {falseelems}"
#: features/steps/geometric_detail_methods.py:54
msgid "All {elemcount} {ifc_class} elements are not a {parameter} representation."
msgstr ""
"Alle {elemcount} {ifc_class} elementen zijn geen {parameter} "
"representatie."
#: features/steps/geometric_detail_methods.py:55
msgid ""
"The following {falsecount} of {elemcount} {ifc_class} elements are not a "
"{parameter} representation: {falseelems}"
msgstr ""
"De volgende {falsecount} van {elemcount} {ifc_class} -elementen zijn geen"
" {parameter} representatie: {falseelems}"
#: features/steps/geometric_detail_methods.py:132
msgid "The geometry of all {elemcount} {ifc_class} elements have errors."
msgstr ""
"De geometrie van alle {elemcount} de {ifc_class} elementen bevatten "
"fouten."
#: features/steps/geometric_detail_methods.py:133
msgid ""
"The geometry of {falsecount} out of all {elemcount} {ifc_class} elements "
"have errors: {falseelems}"
msgstr ""
"De geometrie van {falsecount} van alle {elemcount} {ifc_class} elementen "
"hebben fouten: {falseelems}"
#: features/steps/ifcdata_methods.py:9
msgid "The IFC {} file could not be loaded"
msgstr ""
#: features/steps/ifcdata_methods.py:17
msgid "We expected a schema of {} but instead got {}"
msgstr "We verwachtten een schema van {} maar kregen in plaats daarvan {}"
#~ msgid "The geometry of all {} {} elements have errors."
#~ msgstr ""
#~ msgid "The geometry of {} out of all {} {} elements have errors: {}"
#~ msgstr ""
#~ msgid "There are no {} elements in the IFC file."
#~ msgstr ""
#~ msgid "All {} {} elements are not a IfcFacetedBrep representation."
#~ msgstr ""
#~ msgid ""
#~ "The following {} of {} {} elements"
#~ " are not a IfcFacetedBrep representation:"
#~ " {}"
#~ msgstr ""
#~ msgid ""
#~ "All {elemcount} {ifc_class} elements are "
#~ "not a IfcFacetedBrep representation."
#~ msgstr ""
#~ msgid ""
#~ "The following {falsecount} of {elemcount} "
#~ "{ifc_class} elements are not a "
#~ "IfcFacetedBrep representation: {falseelems}"
#~ msgstr ""
+130
View File
@@ -0,0 +1,130 @@
import datetime
import json
import os
import pystache
from bimtester.lang import _
class ReportGenerator:
def __init__(self):
try:
# PyInstaller creates a temp folder and stores path in _MEIPASS
self.base_path = sys._MEIPASS
except Exception:
self.base_path = os.path.dirname(os.path.realpath(__file__))
def generate(self, report_json, output_file):
print("# Generating HTML reports.")
report = json.loads(open(report_json).read())
for feature in report:
self.generate_feature_report(feature, output_file)
def generate_feature_report(self, feature, output_file):
file_name = os.path.basename(feature["location"]).split(":")[0]
data = {
"file_name": file_name,
"time": datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"name": feature["name"],
"description": feature["description"],
"is_success": feature["status"] == "passed",
"scenarios": [],
}
if "elements" not in feature:
if "status" in feature and feature["status"] == "skipped":
print("Feature was skipped. No html report will be created.")
else:
print("For a unknown reason no html report well be created.")
# happens if the feature file does not consist of any valid Scenario
return
for scenario in feature["elements"]:
scenario_data = self.process_scenario(scenario)
if scenario_data:
data["scenarios"].append(scenario_data)
data["total_passes"] = sum([s["total_passes"] for s in data["scenarios"]])
data["total_steps"] = sum([s["total_steps"] for s in data["scenarios"]])
data["pass_rate"] = round((data["total_passes"] / data["total_steps"]) * 100)
data.update(self.get_template_strings())
with open(output_file, "w", encoding="utf8") as out:
with open(
os.path.join(self.base_path, "resources", "reports", "template.html"), encoding="utf8"
) as template:
out.write(pystache.render(template.read(), data))
def process_scenario(self, scenario):
if len(scenario["steps"]) == 0:
print("Scenario '{}' in feature '{}' has no steps.".format(scenario["name"], feature["name"]))
return
steps = []
total_duration = 0
for step in scenario["steps"]:
step_data = self.process_step(step)
total_duration += step_data["time_raw"]
steps.append(step_data)
total_passes = len([s for s in steps if s["is_success"] is True])
total_steps = len(steps)
pass_rate = round((total_passes / total_steps) * 100)
return {
"name": scenario["name"],
# on behave < 1.2.6 there is no 'status' thus report fails
"is_success": scenario["status"] == "passed",
"time": round(total_duration, 2),
"steps": steps,
"total_passes": total_passes,
"total_steps": total_steps,
"pass_rate": pass_rate,
}
def process_step(self, step):
name = step["name"]
if "match" in step and "arguments" in step["match"]:
for a in step["match"]["arguments"]:
name = name.replace(a["value"], "<b>" + a["value"] + "</b>")
if "result" not in step:
step["result"] = {}
step["result"]["status"] = "skipped"
step["result"]["duration"] = 0
step["result"][
"error_message"
] = "This requirement has been skipped due to a previous failing step."
elif step["result"]["status"] == "undefined":
step["result"] = {}
step["result"]["status"] = "undefined"
step["result"]["duration"] = 0
step["result"]["error_message"] = "This requirement has not yet been specified."
data = {
"name": name,
"time_raw": step["result"]["duration"],
"time": round(step["result"]["duration"], 2),
"is_success": step["result"]["status"] == "passed",
"is_unspecified": step["result"]["status"] == "undefined",
"is_skipped": step["result"]["status"] == "skipped",
"error_message": None
if step["result"]["status"] == "passed"
else step["result"]["error_message"],
}
# TODO: there is probably a better way of doing this
if isinstance(data["error_message"], list):
data["error_message"] = data["error_message"][1]
return data
def get_template_strings(self):
return {
"_lang": _("en"),
"_success": _("Success"),
"_failure": _("Failure"),
"_tests_passed": _("Tests passed"),
"_duration": _("Duration"),
"_auditing": _("OpenBIM auditing is a feature of"),
"_and": _("and"),
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 104 KiB

@@ -0,0 +1,79 @@
<!DOCTYPE html>
<html lang={{_lang}}>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta name="description" content="foobaro">
<title>{{name}}</title>
<link href="https://fonts.googleapis.com/css?family=Comfortaa|Inconsolata|Open+Sans&display=swap" rel="stylesheet">
<style>
body { font-family: 'Arial', sans-serif; padding: 10px 40px; }
span.time { color: #999; font-style: italic; float: right; }
span.step-time { float: right; color: #555; font-size: 0.8em; font-style: italic; }
span.success { background-color: #97cc64; padding: 5px; border-radius: 5px; color: #FFF; font-weight: bold; }
span.failure { background-color: #fb5a3e; padding: 5px; border-radius: 5px; color: #FFF; font-weight: bold; }
p.failure { background-color: #fb5a3e; padding: 5px; border-radius: 5px; color: #fff; }
p.unspecified { background-color: #994f00; padding: 5px; border-radius: 5px; color: #fff; }
p.skipped { background-color: #8b8d8f; padding: 5px; border-radius: 5px; color: #fff; }
p.description { background-color: #eee; border-radius: 5px; padding: 20px; margin-left: auto; margin-right: auto; display: inline-block; font-weight: bold;}
li { padding: 10px; font-family: monospace; }
li.success { background-color: #b6cca1; color: #333; }
li.failure { background-color: #fbb4a8; color: #900; }
li.unspecified { background-color: #ffd37f; color: #a30; }
li.skipped { background-color: #f5f5f5; color: #333; }
li p { margin-bottom: 0px; }
footer { color: #999; font-size: 0.8em; }
header { text-align: center; }
hr { margin: 20px; margin-left: 0px; margin-right: 0px; border: none; border-top: 1px solid #ccc; }
</style>
</head>
<body>
<header>
<h1>{{name}}</h1>
<p><strong>{{time}} {{file_name}}</strong></p>
<hr>
<span class="{{#is_success}}success{{/is_success}}{{^is_success}}failure{{/is_success}}">{{#is_success}}{{_success}}{{/is_success}}{{^is_success}}{{_failure}}{{/is_success}}</span>
{{_tests_passed}}: <strong>{{total_passes}} / {{total_steps}}</strong> ({{pass_rate}}%)
<br />
<p class="description">
{{#description}}
{{.}}<br />
{{/description}}
</p>
<hr>
</header>
{{#scenarios}}
<section>
<h2>{{name}}</h2>
<p>
<span class="{{#is_success}}success{{/is_success}}{{^is_success}}failure{{/is_success}}">{{#is_success}}{{_success}}{{/is_success}}{{^is_success}}{{_failure}}{{/is_success}}</span>
{{_tests_passed}}: <strong>{{total_passes}} / {{total_steps}}</strong> ({{pass_rate}}%)
<span class="time">
{{_duration}}: {{time}}s
</span>
</p>
<ol>
{{#steps}}
<li class="{{#is_success}}success{{/is_success}}{{^is_success}}failure{{/is_success}}{{#is_unspecified}} unspecified{{/is_unspecified}}{{#is_skipped}} skipped{{/is_skipped}}">
{{{name}}}
<span class="step-time">{{time}}s</span>
{{^is_success}}
<p class="failure{{#is_unspecified}} unspecified{{/is_unspecified}}{{#is_skipped}} skipped{{/is_skipped}}">
{{#error_message}}
{{.}}<br />
{{/error_message}}
</p>
{{/is_success}}
</li>
{{/steps}}
</ol>
</section>
{{/scenarios}}
<hr>
<footer>
<p>
{{_auditing}} <a href="https://blenderbim.org/">BlenderBIM</a> {{_and}} <a href="http://ifcopenshell.org/">IfcOpenShell</a>.
</p>
</footer>
</body>
</html>
+62
View File
@@ -0,0 +1,62 @@
import os
import sys
import shutil
import tempfile
import ifcopenshell
try:
import ifcopenshell.express
except:
pass # They are using an old version of IfcOpenShell. Gracefully degrade for now.
import behave.formatter.pretty # Needed for pyinstaller to package it
from bimtester.ifc import IfcStore
from distutils.dir_util import copy_tree
from behave.__main__ import main as behave_main
class TestRunner:
def __init__(self, ifc_path, ifc=None):
IfcStore.path = ifc_path
IfcStore.file = ifc if ifc else ifcopenshell.open(ifc_path)
try:
# PyInstaller creates a temp folder and stores path in _MEIPASS
self.base_path = sys._MEIPASS
except Exception:
self.base_path = os.path.dirname(os.path.realpath(__file__))
self.locale_path = os.path.join(self.base_path, "locale")
def run(self, args):
if args["schema_file"]:
schema = ifcopenshell.express.parse(args["schema_file"])
ifcopenshell.register_schema(args["schema_name"])
tmpdir = tempfile.mkdtemp()
features_path = os.path.join(tmpdir, "features")
steps_path = os.path.join(features_path, "steps")
report_json = os.path.join(tmpdir, "report.json")
shutil.copytree(os.path.join(self.base_path, "features"), features_path)
shutil.copy(args["feature"], features_path)
if args["steps"]:
if os.path.isfile(args["steps"]):
shutil.copy(args["steps"], steps_path)
elif os.path.isdir(args["steps"]):
copy_tree(args["steps"], steps_path)
behave_main(self.get_behave_args(args, features_path, report_json))
return report_json
def get_behave_args(self, args, features_path, report_json):
behave_args = [features_path]
behave_args.extend(["--define", "localedir={}".format(self.locale_path)])
if args["advanced_arguments"]:
behave_args.extend(args["advanced_arguments"].split())
if args["ifc"]:
behave_args.extend(["--define", "ifc={}".format(args["ifc"])])
if args["path"]:
behave_args.extend(["--define", "path={}".format(args["path"])])
if args["lang"]:
behave_args.extend(["--lang={}".format(args["lang"])])
if not args["console"]:
# https://github.com/behave/behave/issues/346
behave_args.extend(["--no-capture", "--format", "json.pretty", "--outfile", report_json])
return behave_args
+105
View File
@@ -0,0 +1,105 @@
import ifcopenshell
import ifcopenshell.util.element
from bimtester.lang import _
def assert_guid(ifc, guid):
try:
return ifc.by_guid(guid)
except:
assert False, _("An element with the ID {} could not be found.").format(guid)
def assert_number(number):
try:
return float(number)
except ValueError:
assert False, _("A number should be specified, not {}").format(number)
def assert_type(element, ifc_class, is_exact=False):
if is_exact:
assert element.is_a() == ifc_class, _("The element {} is an {} instead of {}.").format(
element, element.is_a(), ifc_class
)
else:
assert element.is_a(ifc_class), _("The element {} is an {} instead of {}.").format(
element, element.is_a(), ifc_class
)
def assert_attribute(element, name, value=None):
if not hasattr(element, name):
assert False, _("The element {} does not have the attribute {}").format(element, name)
if not value:
if getattr(element, name) is None:
assert False, _("The element {} does not have a value for the attribute {}").format(element, name)
return getattr(element, name)
if value == "NULL":
value = None
actual_value = getattr(element, name)
if isinstance(value, list) and actual_value:
actual_value = list(actual_value)
assert actual_value == value, _('We expected a value of "{}" but instead got "{}" for the element {}').format(
value, actual_value, element
)
def assert_pset(element, pset_name, prop_name=None, value=None):
if value == "NULL":
value = None
psets = ifcopenshell.util.element.get_psets(site)
if pset_name not in psets:
assert False, _("The element {} does not have a property set named {}").format(element, pset_name)
if prop_name is None:
return psets[pset_name]
if prop_name not in psets[pset_name]:
assert False, _('The element {} does not have a property named "{}" in the pset "{}"').format(
element, prop_name, pset_name
)
if value is None:
return psets[pset_name][prop_name]
actual_value = psets[pset_name][prop_name]
assert actual_value == value, _('We expected a value of "{}" but instead got "{}" for the element {}').format(
value, actual_value, element
)
# TODO: what is this?
def assert_elements(
ifc_class,
elemcount,
falsecount,
falseelems,
message_all_falseelems,
message_some_falseelems,
message_no_elems,
parameter=None,
):
if elemcount > 0 and falsecount == 0:
return # Test OK
elif elemcount == 0:
assert False, message_no_elems.format(ifc_class=ifc_class)
elif falsecount == elemcount:
if parameter is None:
assert False, message_all_falseelems.format(elemcount=elemcount, ifc_class=ifc_class)
else:
assert False, message_all_falseelems.format(elemcount=elemcount, ifc_class=ifc_class, parameter=parameter)
elif falsecount > 0 and falsecount < elemcount:
if parameter is None:
assert False, message_some_falseelems.format(
falsecount=falsecount,
elemcount=elemcount,
ifc_class=ifc_class,
falseelems=falseelems,
)
else:
assert False, message_some_falseelems.format(
falsecount=falsecount,
elemcount=elemcount,
ifc_class=ifc_class,
falseelems=falseelems,
parameter=parameter,
)
else:
assert False, _("Error in falsecount, something went wrong.")
+29
View File
@@ -0,0 +1,29 @@
#!/usr/bin/env python3
import os
import argparse
import bimtester.clean
import bimtester.reports
import bimtester.run
parser = argparse.ArgumentParser(description="Runs unit tests for BIM data")
parser.add_argument("-a", "--action", type=str, help="Action to perform, from run/purge", default="run")
parser.add_argument("--advanced-arguments", type=str, help="Specify arguments to Behave", default="")
parser.add_argument("-c", "--console", action="store_true", help="Show results in the console")
parser.add_argument("-f", "--feature", type=str, help="Specify a feature file to test", required=True)
parser.add_argument("-i", "--ifc", type=str, help="Specify an IFC file to test", required=True)
parser.add_argument("-p", "--path", type=str, help="Define a path for use in test steps that use relative paths")
parser.add_argument("-r", "--report", type=str, help="Specify an output file for a HTML report")
parser.add_argument("--steps", type=str, help="Specify a custom step definition Python file or directory")
parser.add_argument("--schema-file", type=str, help="Path to a custom IFC schema, used with --schema-name")
parser.add_argument("--schema-name", type=str, help="The name of a custom IFC schema, used with --schema-file")
parser.add_argument("--lang", type=str, help="Specify a language e.g. en/de/fr/it", default="")
args = vars(parser.parse_args())
if args["action"] == "run":
report_json = bimtester.run.TestRunner(args["ifc"]).run(args)
if args["report"]:
bimtester.reports.ReportGenerator().generate(report_json, args["report"])
elif args["action"] == "purge":
bimtester.clean.TestPurger().purge()
@@ -0,0 +1,54 @@
ISO-10303-21;
HEADER;
FILE_DESCRIPTION(('ViewDefinition [CoordinationView]'),'2;1');
FILE_NAME('col.ifc','2021-01-11T05:16:43',('',''),(''),'IfcOpenShell 0.6.0b0','IfcOpenShell 0.6.0b0','');
FILE_SCHEMA(('IFC2X3'));
ENDSEC;
DATA;
#1=IFCPERSON($,$,'',$,$,$,$,$);
#2=IFCORGANIZATION($,'',$,$,$);
#3=IFCPERSONANDORGANIZATION(#1,#2,$);
#4=IFCAPPLICATION(#2,'0.19 build 23652 (Git)','FreeCAD','118df2cf_ed21_438e_a41');
#5=IFCOWNERHISTORY(#3,#4,$,.ADDED.,1610342203,#3,#4,1610342203);
#6=IFCDIRECTION((1.,0.,0.));
#7=IFCDIRECTION((0.,0.,1.));
#8=IFCCARTESIANPOINT((0.,0.,0.));
#9=IFCAXIS2PLACEMENT3D(#8,#7,#6);
#10=IFCDIRECTION((0.,1.,0.));
#12=IFCDIMENSIONALEXPONENTS(0,0,0,0,0,0,0);
#13=IFCSIUNIT(*,.LENGTHUNIT.,$,.METRE.);
#14=IFCSIUNIT(*,.AREAUNIT.,$,.SQUARE_METRE.);
#15=IFCSIUNIT(*,.VOLUMEUNIT.,$,.CUBIC_METRE.);
#16=IFCSIUNIT(*,.PLANEANGLEUNIT.,$,.RADIAN.);
#17=IFCMEASUREWITHUNIT(IFCPLANEANGLEMEASURE(0.017453292519943295),#16);
#18=IFCCONVERSIONBASEDUNIT(#12,.PLANEANGLEUNIT.,'DEGREE',#17);
#19=IFCUNITASSIGNMENT((#13,#14,#15,#18));
#20=IFCDIRECTION((0.,1.));
#21=IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,1.E-05,#9,#20);
#22=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Body','Model',*,*,*,*,#21,$,.MODEL_VIEW.,$);
#23=IFCPROJECT('2iAYrakL9FABNNwZfj$CbO',#5,'BIMTester Example 1 - IFC2X3',$,$,$,$,(#21),#19);
#24=IFCDIRECTION((1.,0.));
#25=IFCCARTESIANPOINT((0.,0.));
#26=IFCAXIS2PLACEMENT2D(#25,#24);
#27=IFCCIRCLEPROFILEDEF(.AREA.,$,#26,0.2);
#28=IFCCARTESIANPOINT((0.,0.,0.));
#29=IFCAXIS2PLACEMENT3D(#28,#7,#6);
#30=IFCEXTRUDEDAREASOLID(#27,#29,#7,5.);
#31=IFCCOLOURRGB($,1.,0.5,1.);
#32=IFCSURFACESTYLERENDERING(#31,$,$,$,$,$,$,$,.FLAT.);
#33=IFCSURFACESTYLE($,.BOTH.,(#32));
#34=IFCPRESENTATIONSTYLEASSIGNMENT((#33));
#35=IFCSTYLEDITEM(#30,(#34),$);
#36=IFCLOCALPLACEMENT($,#9);
#37=IFCSHAPEREPRESENTATION(#22,'Body','SweptSolid',(#30));
#38=IFCPRODUCTDEFINITIONSHAPE($,$,(#37));
#39=IFCBUILDINGELEMENTPROXY('3JNmm1CUH9H9P6lVsx1y3W',#5,'Structure','',$,#36,#38,$,.ELEMENT.);
#40=IFCSITE('2PJ1ax1HL4SgHFFReEEwE$',#5,'Default Site','',$,$,$,$,.ELEMENT.,$,$,$,$,$);
#41=IFCRELAGGREGATES('1J6GQExT511x6QRu5FmkD2',#5,'ProjectLink','',#23,(#40));
#42=IFCBUILDING('1tIoXRzCXF3vuIMrF6RVcd',#5,'Default Building','',$,$,$,$,.ELEMENT.,$,$,$);
#43=IFCRELAGGREGATES('2GkPanCgnAzQY_0xv8dnHH',#5,'SiteLink','',#40,(#42));
#44=IFCBUILDINGSTOREY('1L8$GCIw116uw35vpyjSsO',#5,'Default Storey','',$,$,$,$,.ELEMENT.,$);
#45=IFCRELAGGREGATES('1lB$$h00nFaPQb2gvlhRX$',#5,'DefaultStoreyLink','',#42,(#44));
#46=IFCRELCONTAINEDINSPATIALSTRUCTURE('3dnpjDLD5DvuyUGcyHqRvU',#5,'UnassignedObjectsLink','',(#39),#44);
ENDSEC;
END-ISO-10303-21;
@@ -0,0 +1,54 @@
ISO-10303-21;
HEADER;
FILE_DESCRIPTION(('ViewDefinition [CoordinationView]'),'2;1');
FILE_NAME('col.ifc','2021-01-11T05:12:19',('',''),(''),'IfcOpenShell 0.6.0b0','IfcOpenShell 0.6.0b0','');
FILE_SCHEMA(('IFC4'));
ENDSEC;
DATA;
#1=IFCPERSON($,$,'',$,$,$,$,$);
#2=IFCORGANIZATION($,'',$,$,$);
#3=IFCPERSONANDORGANIZATION(#1,#2,$);
#4=IFCAPPLICATION(#2,'0.19 build 23652 (Git)','FreeCAD','118df2cf_ed21_438e_a41');
#5=IFCOWNERHISTORY(#3,#4,$,.ADDED.,1610341939,#3,#4,1610341939);
#6=IFCDIRECTION((1.,0.,0.));
#7=IFCDIRECTION((0.,0.,1.));
#8=IFCCARTESIANPOINT((0.,0.,0.));
#9=IFCAXIS2PLACEMENT3D(#8,#7,#6);
#10=IFCDIRECTION((0.,1.,0.));
#12=IFCDIMENSIONALEXPONENTS(0,0,0,0,0,0,0);
#13=IFCSIUNIT(*,.LENGTHUNIT.,$,.METRE.);
#14=IFCSIUNIT(*,.AREAUNIT.,$,.SQUARE_METRE.);
#15=IFCSIUNIT(*,.VOLUMEUNIT.,$,.CUBIC_METRE.);
#16=IFCSIUNIT(*,.PLANEANGLEUNIT.,$,.RADIAN.);
#17=IFCMEASUREWITHUNIT(IFCPLANEANGLEMEASURE(0.017453292519943295),#16);
#18=IFCCONVERSIONBASEDUNIT(#12,.PLANEANGLEUNIT.,'DEGREE',#17);
#19=IFCUNITASSIGNMENT((#13,#14,#15,#18));
#20=IFCDIRECTION((0.,1.));
#21=IFCGEOMETRICREPRESENTATIONCONTEXT($,'Model',3,1.E-05,#9,#20);
#22=IFCGEOMETRICREPRESENTATIONSUBCONTEXT('Body','Model',*,*,*,*,#21,$,.MODEL_VIEW.,$);
#23=IFCPROJECT('2iAYrakL9FABNNwZfj$CbO',#5,'BIMTester Example 1 - IFC4',$,$,$,$,(#21),#19);
#24=IFCDIRECTION((1.,0.));
#25=IFCCARTESIANPOINT((0.,0.));
#26=IFCAXIS2PLACEMENT2D(#25,#24);
#27=IFCCIRCLEPROFILEDEF(.AREA.,$,#26,0.2);
#28=IFCCARTESIANPOINT((0.,0.,0.));
#29=IFCAXIS2PLACEMENT3D(#28,#7,#6);
#30=IFCEXTRUDEDAREASOLID(#27,#29,#7,5.);
#31=IFCCOLOURRGB($,1.,0.5,1.);
#32=IFCSURFACESTYLERENDERING(#31,$,$,$,$,$,$,$,.FLAT.);
#33=IFCSURFACESTYLE($,.BOTH.,(#32));
#34=IFCPRESENTATIONSTYLEASSIGNMENT((#33));
#35=IFCSTYLEDITEM(#30,(#34),$);
#36=IFCLOCALPLACEMENT($,#9);
#37=IFCSHAPEREPRESENTATION(#22,'Body','SweptSolid',(#30));
#38=IFCPRODUCTDEFINITIONSHAPE($,$,(#37));
#39=IFCBUILDINGELEMENTPROXY('3JNmm1CUH9H9P6lVsx1y3W',#5,'Structure','',$,#36,#38,$,.COMPLEX.);
#40=IFCSITE('2PJ1ax1HL4SgHFFReEEwE$',#5,'Default Site','',$,$,$,$,.ELEMENT.,$,$,$,$,$);
#41=IFCRELAGGREGATES('1J6GQExT511x6QRu5FmkD2',#5,'ProjectLink','',#23,(#40));
#42=IFCBUILDING('1tIoXRzCXF3vuIMrF6RVcd',#5,'Default Building','',$,$,$,$,.ELEMENT.,$,$,$);
#43=IFCRELAGGREGATES('2GkPanCgnAzQY_0xv8dnHH',#5,'SiteLink','',#40,(#42));
#44=IFCBUILDINGSTOREY('1L8$GCIw116uw35vpyjSsO',#5,'Default Storey','',$,$,$,$,.ELEMENT.,$);
#45=IFCRELAGGREGATES('1lB$$h00nFaPQb2gvlhRX$',#5,'DefaultStoreyLink','',#42,(#44));
#46=IFCRELCONTAINEDINSPATIALSTRUCTURE('3dnpjDLD5DvuyUGcyHqRvU',#5,'UnassignedObjectsLink','',(#39),#44);
ENDSEC;
END-ISO-10303-21;
@@ -0,0 +1,18 @@
# language: de
Funktionalität: Basisdaten
Um BIM-Daten anzusehen
Für alle beteiligten Akteure
Wir brauchen eine IFC-Datei
Szenario: Bereitstellen von IFC-Daten
* Die IFC-Datei wurde durch einen Startparameter zur Verfügung gestellt
* Die IFC-Daten müssen das IFC2X3 Schema benutzen
Szenario: Projektinformationen
* Der Name, die Abkürzung oder die Kurzkennung des Projektes ist "BIMTester Example 1 - IFC2X3"
@@ -0,0 +1,18 @@
# language: en
Feature: Base setup
In order to view the BIM data
As any interested stakeholder
We need an IFC file
Scenario: Receiving a file
* The IFC file has been provided through an argument
* IFC data must use the IFC2X3 schema
Scenario: Project information
* The project name, code, or short identifier must be "BIMTester Example 1 - IFC2X3"
@@ -0,0 +1,18 @@
# language: fr
Fonctionnalité: Base setup
In order to view the BIM data
As any interested stakeholder
We need an IFC file
Scénario: Recevoir e fichier
* The IFC file has been provided through an argument
* Les données IFC doivent utiliser le schéma IFC2X3
Scénario: Project information
* The project name, code, or short identifier must be "BIMTester Example 1 - IFC2X3"
@@ -0,0 +1,18 @@
# language: it
Funzionalità: Dati di base
Per poter consultare dati BIM
a tutti gli attori partecipanti
serve un file IFC
Scenario: Preparare Dati IFC
* Il file IFC è stato fornito attraverso un argumento
* I dati IFC devono seguire lo schema IFC2X3
Scenario: Project information
* Il nome del progetto, codice o identificatore breve deve essere "BIMTester Example 1 - IFC2X3"
@@ -0,0 +1,18 @@
# language: nl
Functionaliteit: Basisgegevens
Om BIM-gegevens te bekijken
Zoals elke geïnteresseerde stakeholder
We hebben een IFC-bestand nodig
Scenario: Bestand ontvangen
* The IFC file has been provided through an argument
* IFC-gegevens moeten het IFC2X3 -schema gebruiken
Scenario: Project informatie
* De projectnaam, code of korte ID moet "BIMTester Example 1 - IFC2X3"
@@ -0,0 +1,144 @@
from behave import step, given, when, then, use_step_matcher
use_step_matcher("parse")
@step("There must be exactly {number} {ifc_class} element")
@step("There must be exactly {number} {ifc_class} elements")
def step_impl(context, number, ifc_class):
num = len(IfcStore.file.by_type(ifc_class))
assert num == int(number), "Could not find {} elements of {}. Found {} element(s).".format(number, ifc_class, num)
@given("a set of specific related elements")
def step_impl(context):
model = getattr(context, "model", None)
if not model:
context.model = TableModel()
for row in context.table:
context.model.add_row(row["RelatedObjects"], row["RelatingGroup"])
@given('a set of specific related elements taken from the file "{path_file}"')
def step_impl(context, path_file):
import csv
import os
model = getattr(context, "model", None)
if not model:
context.model = TableModel()
if context.config.userdata.get("path"):
path_file = os.path.join(context.config.userdata.get("path"), path_file)
if not os.path.exists(path_file):
assert False, "File {} not found".format(path_file)
with open(path_file, "r", encoding="utf-8-sig") as csvfile:
reader = csv.DictReader(csvfile)
for row in reader:
context.model.add_row(row["RelatedObjects"], row["RelatingGroup"])
@then("there must be exactly a number of {ifc_class} equals to the number of distinct row value")
def step_impl(context, ifc_class):
try:
context.execute_steps(
"""
then There must be exactly {number} {ifc_class} elements
""".format(
ifc_class=ifc_class, number=context.model.get_count_distinct_values()
)
)
except AssertionError as error:
str_error = str(error)
assert False, str_error[: str_error.find("Traceback")]
assert True
@then(
"there is a relationship {ifc_class} with {left_attribute} and {right_attribute} between the two elements of each row"
)
def step_impl(context, ifc_class, left_attribute, right_attribute):
rows = context.model.rows
elements = IfcStore.file.by_type(ifc_class)
errors = []
for key, value in rows.items():
found = False
for element in elements:
if (
any(x.Name == key for x in getattr(element, left_attribute))
and getattr(element, right_attribute).Name == value
):
found = True
if not found:
errors.append(f"The row ({key}, {value}) does not have the relationship.")
assert not errors, "Errors occured:\n{}".format("\n".join(errors))
use_step_matcher("re")
@step("all IfcGroup must be linked to a type in the list (?P<linked_ifc_classes>.*)")
def step_impl(context, linked_ifc_classes):
groups = IfcStore.file.by_type("IfcGroup")
errors = []
for group in groups:
if not hasattr(group, "IsGroupedBy"):
errors.append(f'The element "{group.Name}" has no "IsGroupedBy" attribute.')
else:
for grouped_by in getattr(group, "IsGroupedBy"):
if not hasattr(grouped_by, "RelatedObjects"):
errors.append(f'The element "{grouped_by.Name}" has no "RelatedObjects" attribute.')
else:
for related_object in getattr(grouped_by, "RelatedObjects"):
found = False
for linked_ifc_class in linked_ifc_classes.split(","):
if related_object.is_a(linked_ifc_class):
found = True
if not found:
errors.append(
f'The element "{related_object.Name}" does not have the right associated type.'
)
assert not errors, "Errors occured:\n{}".format("\n".join(errors))
@then("there is an element of type (?P<ifc_types>.*) with a (?P<attribute_name>.*) attribute for each row key")
def step_impl(context, ifc_types, attribute_name):
check_if_element_exists_by_types_with_attribute_name(ifc_types, attribute_name, context.model.rows.keys())
@then("there is an element of type (?P<ifc_types>.*) with a (?P<attribute_name>.*) attribute for each row value")
def step_impl(context, ifc_types, attribute_name):
values = set(context.model.rows.values())
check_if_element_exists_by_types_with_attribute_name(ifc_types, attribute_name, values)
def check_if_element_exists_by_types_with_attribute_name(ifc_types, attribute_name, attribute_values):
errors = []
elements = []
for ifc_type in ifc_types.split(","):
elements += ifc.by_type(ifc_type.strip())
for attribute_value in attribute_values:
found = False
for element in elements:
if hasattr(element, attribute_name) and getattr(element, attribute_name) == attribute_value:
found = True
if not found:
errors.append(f'An element with {attribute_name} attribute "{attribute_value}" was not found.')
assert not errors, "Errors occured:\n{}".format("\n".join(errors))
class TableModel(object):
"""This class represents a table of data."""
def __init__(self):
self.rows = dict()
def add_row(self, related, relating):
self.rows[related] = relating
def get_count(self):
return len(self.rows)
def get_count_distinct_values(self):
return len(set(self.rows.values()))
@@ -0,0 +1,52 @@
import gettext
from behave import given
from behave import step
from utils import IfcFile
from bimtester.ifc import IfcStore
from bimtester.lang import _
@step("The IFC file must be exported by application full name {fullname}")
def step_impl(context, fullname):
real_fullname = IfcStore.file.by_type("IfcApplication")[0].ApplicationFullName
assert real_fullname == fullname, (
"The IFC file was not exported by application full name {} "
"instead it was exported by application full name {}".format(fullname, real_fullname)
)
@step("The IFC file must be exported by application identifier {identifier}")
def step_impl(context, identifier):
real_identifier = IfcStore.file.by_type("IfcApplication")[0].ApplicationIdentifier
assert (
real_identifier == identifier
), "The IFC file was not exported by application identifier {} " "instead it was exported by identifier {}".format(
identifier, real_identifier
)
@step("The IFC file must be exported by the application version {version}")
def step_impl(context, version):
real_version = IfcStore.file.by_type("IfcApplication")[0].Version
assert (
real_version == version
), "The IFC file was not exported by application version {} " "instead it was exported by version {}".format(
version, real_version
)
@step(
"IFC data header must have a file description of {header_file_description} such as the new Allplan IFC exporter creates it"
)
def step_impl(context, header_file_description):
is_header_file_description = IfcStore.file.wrapped_data.header.file_description.description
assert (
str(is_header_file_description) == header_file_description
), "The file was not exported by the new ifc exporter in Allplan. File description header: {}".format(
is_header_file_description
)
@@ -0,0 +1,91 @@
from behave import step
import attributes_eleclasses_methods as aem
from utils import assert_elements
from utils import IfcFile
@step("There are no {ifc_class} elements")
def step_impl(context, ifc_class):
aem.no_eleclass(context, ifc_class)
@step("There are no {ifc_class} elements because {reason}")
def step_impl(context, ifc_class, reason):
aem.no_eleclass(context, ifc_class)
@step("All {ifc_class} elements class attributes have a value")
def step_impl(context, ifc_class):
aem.eleclass_have_class_attributes_with_a_value(context, ifc_class)
@step("All {ifc_class} elements have a name given")
def step_impl(context, ifc_class):
aem.eleclass_has_name_with_a_value(context, ifc_class)
@step("All {ifc_class} elements have a description given")
def step_impl(context, ifc_class):
aem.eleclass_has_description_with_a_value(context, ifc_class)
@step('all {ifc_class} elements have a name matching the pattern "{pattern}"')
def step_impl(context, ifc_class, pattern):
import re
elements = IfcFile.get().by_type(ifc_class)
for element in elements:
if not re.search(pattern, element.Name):
assert False
@step('there is an {ifc_class} element with a {attribute_name} attribute with a value of "{attribute_value}"')
def step_impl(context, ifc_class, attribute_name, attribute_value):
elements = IfcFile.get().by_type(ifc_class)
for element in elements:
if hasattr(element, attribute_name) and getattr(element, attribute_name) == attribute_value:
return
assert False
use_step_matcher("re")
@step("all (?P<ifc_class>.*) elements have an? (?P<attribute>.*) attribute")
def step_impl(context, ifc_class, attribute):
elements = IfcFile.get().by_type(ifc_class)
for element in elements:
if not getattr(element, attribute):
assert False
@step('all (?P<ifc_class>.*) elements have an? (?P<attribute>.*) matching the pattern "(?P<pattern>.*)"')
def step_impl(context, ifc_class, attribute, pattern):
import re
elements = IfcFile.get().by_type(ifc_class)
for element in elements:
value = getattr(element, attribute)
print(f'Checking value "{value}" for {element}')
assert re.search(pattern, value)
@step('all (?P<ifc_class>.*) elements have an? (?P<attributes>.*) taken from the list in "(?P<list_file>.*)"')
def step_impl(context, ifc_class, attributes, list_file):
import csv
values = []
with open(list_file) as csvfile:
reader = csv.reader(csvfile)
for row in reader:
values.append(row)
elements = IfcFile.get().by_type(ifc_class)
for element in elements:
attribute_values = []
for attribute in attributes.split(","):
if not hasattr(element, attribute):
assert False, f"Failed at element {element.GlobalId}"
attribute_values.append(getattr(element, attribute))
if attribute_values not in values:
assert False, f"Failed at element {element.GlobalId}"
@@ -0,0 +1,26 @@
from behave import step
@step("Es sind keine {ifc_class} Bauteile vorhanden")
def step_impl(context, ifc_class):
context.execute_steps(f"* There are no {ifc_class} elements")
@step("Aus folgendem Grund gibt es keine {ifc_class} Bauteile: {reason}")
def step_impl(context, ifc_class, reason):
context.execute_steps(f"* There are no {ifc_class} elements because {reason}")
@step("Alle {ifc_class} Bauteilklassenattribute haben einen Wert")
def step_impl(context, ifc_class):
context.execute_steps(f"* All {ifc_class} elements class attributes have a value")
@step("Bei allen {ifc_class} Bauteile ist der Name angegeben")
def step_impl(context, ifc_class):
context.execute_steps(f"* All {ifc_class} elements have a name given")
@step("Bei allen {ifc_class} Bauteile ist die Beschreibung angegeben")
def step_impl(context, ifc_class):
context.execute_steps(f"* All {ifc_class} elements have a description given")
@@ -0,0 +1,140 @@
import gettext # noqa
from utils import assert_elements
from utils import IfcFile
def no_eleclass(
context, ifc_class
):
context.falseelems = []
context.falseguids = []
elements = IfcFile.get().by_type(ifc_class)
for elem in elements:
context.falseelems.append(str(elem))
context.falseguids.append(elem.GlobalId)
context.elemcount = len(elements)
context.falsecount = len(context.falseelems)
if context.elemcount == 0 and context.falsecount == 0:
return # Test OK, thus we can not use the assert_elements method
elif context.falsecount == context.elemcount:
assert False, (
_("All {elemcount} elements in the file are {ifc_class}.")
.format(
elemcount=context.elemcount,
ifc_class=ifc_class
)
)
elif context.falsecount > 0 and fcontext.alsecount < context.elemcount:
assert False, (
_("{falsecount} of {elemcount} element are {ifc_class} elements: {falseelems}")
.format(
falsecount=context.falsecount,
elemcount=context.elemcount,
ifc_class=ifc_class,
falseelems=context.falseelems,
)
)
else:
assert False, _("Error in falsecount, something went wrong.")
def eleclass_have_class_attributes_with_a_value(
context, ifc_class
):
from ifcopenshell.ifcopenshell_wrapper import schema_by_name
# schema = schema_by_name("IFC2X3")
schema = schema_by_name(IfcFile.get().schema)
class_attributes = []
for cl_attrib in schema.declaration_by_name(ifc_class).all_attributes():
class_attributes.append(cl_attrib.name())
# print(class_attributes)
context.falseelems = []
context.falseguids = []
context.falseprops = {}
elements = IfcFile.get().by_type(ifc_class)
for elem in elements:
failed_attribs = []
elem_failed = False
for cl_attrib in class_attributes:
attrib_value = getattr(elem, cl_attrib)
if not attrib_value:
elem_failed = True
failed_attribs.append(cl_attrib)
# print(attrib_value)
if elem_failed is True:
context.falseelems.append(str(elem))
context.falseguids.append(elem.GlobalId)
context.falseprops[elem.id()] = failed_attribs
context.elemcount = len(elements)
context.falsecount = len(context.falseelems)
assert_elements(
ifc_class,
context.elemcount,
context.falsecount,
context.falseelems,
message_all_falseelems=_("For all {elemcount} {ifc_class} elements at least one of these class attributes {parameter} has no value."),
message_some_falseelems=_("For the following {falsecount} out of {elemcount} {ifc_class} elements at least one of these class attributes {parameter} has no value: {falseelems}"),
message_no_elems=_("There are no {ifc_class} elements in the IFC file."),
parameter=failed_attribs
)
def eleclass_has_name_with_a_value(context, ifc_class):
context.falseelems = []
context.falseguids = []
elements = IfcFile.get().by_type(ifc_class)
for elem in elements:
# print(elem.Name)
if not elem.Name:
context.falseelems.append(str(elem))
context.falseguids.append(elem.GlobalId)
context.elemcount = len(elements)
context.falsecount = len(context.falseelems)
assert_elements(
ifc_class,
context.elemcount,
context.falsecount,
context.falseelems,
message_all_falseelems=_("The name of all {elemcount} {elemcount} elements is not set."),
message_some_falseelems=_("The name of {falsecount} out of {elemcount} {ifc_class} elements is not set: {falseelems}"),
message_no_elems=_("There are no {ifc_class} elements in the IFC file."),
)
def eleclass_has_description_with_a_value(
context, ifc_class
):
context.falseelems = []
context.falseguids = []
elements = IfcFile.get().by_type(ifc_class)
for elem in elements:
# print(elem.Description)
if not elem.Description:
context.falseelems.append(str(elem))
context.falseguids.append(elem.GlobalId)
context.elemcount = len(elements)
context.falsecount = len(context.falseelems)
assert_elements(
ifc_class,
context.elemcount,
context.falsecount,
context.falseelems,
message_all_falseelems=_("The description of all {elemcount} {elemcount} elements is not set."),
message_some_falseelems=_("The description of {falsecount} out of {elemcount} {ifc_class} elements is not set: {falseelems}"),
message_no_elems=_("There are no {ifc_class} elements in the IFC file."),
)
@@ -0,0 +1,53 @@
from behave import step
import attributes_psets_methods as apm
from utils import assert_elements
from utils import IfcFile
from utils import switch_locale
the_lang = "en"
@step("all {ifc_class} elements have an {aproperty} property in the {pset} pset")
def step_impl(context, ifc_class, aproperty, pset):
switch_locale(context.localedir, the_lang)
apm.eleclass_has_property_in_pset(
context,
ifc_class,
aproperty,
pset
)
# ------------------------------------------------------------------------
# STEPS with Regular Expression Matcher ("re")
# ------------------------------------------------------------------------
use_step_matcher("re")
@step("all (?P<ifc_class>.*) elements have an? (?P<property_path>.*\..*) property")
def step_impl(context, ifc_class, property_path):
pset_name, property_name = property_path.split(".")
elements = IfcFile.get().by_type(ifc_class)
for element in elements:
if not IfcFile.get_property(element, pset_name, property_name):
assert False
@step(
'all (?P<ifc_class>.*) elements have an? (?P<property_path>.*\..*) property value matching the pattern "(?P<pattern>.*)"'
)
def step_impl(context, ifc_class, property_path, pattern):
import re
pset_name, property_name = property_path.split(".")
elements = IfcFile.get().by_type(ifc_class)
for element in elements:
prop = IfcFile.get_property(element, pset_name, property_name)
if not prop:
assert False
# For now, we only check single values
if prop.is_a("IfcPropertySingleValue"):
if not (prop.NominalValue and re.search(pattern, prop.NominalValue.wrappedValue)):
assert False
@@ -0,0 +1,18 @@
from behave import step
import attributes_psets_methods as apm
from utils import switch_locale
the_lang = "de"
@step("An alle {ifc_class} Bauteile ist im PSet {pset} das Attribut {aproperty} angehängt")
def step_impl(context, ifc_class, aproperty, pset):
switch_locale(context.localedir, the_lang)
apm.eleclass_has_property_in_pset(
context,
ifc_class,
aproperty,
pset
)
@@ -0,0 +1,21 @@
from behave import step
import attributes_psets_methods as apm
from utils import switch_locale
the_lang = "fr"
"""
# TODO the next line needs translation
@step("All {ifc_class} elements have an {aproperty} property in the {pset} pset")
def step_impl(context, ifc_class, aproperty, pset):
switch_locale(context.localedir, the_lang)
apm.eleclass_has_property_in_pset(
context,
ifc_class,
aproperty,
pset
)
"""
@@ -0,0 +1,36 @@
import gettext # noqa
from utils import assert_elements
from utils import IfcFile
def eleclass_has_property_in_pset(
context, ifc_class, aproperty, pset
):
context.falseelems = []
context.falseguids = []
context.falseprops = {}
from ifcopenshell.util.element import get_psets
elements = IfcFile.get().by_type(ifc_class)
for elem in elements:
psets = get_psets(elem)
if not (pset in psets and aproperty in psets[pset]):
context.falseelems.append(str(elem))
context.falseguids.append(elem.GlobalId)
context.falseprops[elem.id()] = str(psets)
context.elemcount = len(elements)
context.falsecount = len(context.falseelems)
assert_elements(
ifc_class,
context.elemcount,
context.falsecount,
context.falseelems,
message_all_falseelems=_("All {elemcount} {ifc_class} elements are missing the property {parameter} in the pset."),
message_some_falseelems=_("The following {falsecount} of {elemcount} {ifc_class} elements are missing the property {parameter} in the pset: {falseelems}"),
message_no_elems=_("There are no {ifc_class} elements in the IFC file."),
parameter=aproperty
)
# the pset name is missing in the failing message, but it is in the step test name
@@ -0,0 +1,19 @@
from behave import step
from utils import IfcFile
@step("all {ifc_class} elements have a {qto_name}.{quantity_name} quantity")
def step_impl(context, ifc_class, qto_name, quantity_name):
elements = IfcFile.get().by_type(ifc_class)
for element in elements:
is_successful = False
if not element.IsDefinedBy:
assert False
for relationship in element.IsDefinedBy:
if relationship.RelatingPropertyDefinition.Name == qto_name:
for quantity in relationship.RelatingPropertyDefinition.Quantities:
if quantity.Name == quantity_name:
is_successful = True
if not is_successful:
assert False
@@ -0,0 +1,47 @@
from behave import step
import geometric_detail_methods as gdm
from utils import assert_elements
from utils import IfcFile
from utils import switch_locale
the_lang = "en"
@step("All elements must be under {number} polygons")
def step_impl(context, number):
number = int(number)
errors = []
for element in IfcFile.get().by_type("IfcElement"):
if not element.Representation:
continue
total_polygons = 0
tree = IfcFile.get().traverse(element.Representation)
for e in tree:
if e.is_a("IfcFace"):
total_polygons += 1
elif e.is_a("IfcPolygonalFaceSet"):
total_polygons += len(e.Faces)
elif e.is_a("IfcTriangulatedFaceSet"):
total_polygons += len(e.CoordIndex)
if total_polygons > number:
errors.append((total_polygons, element))
if errors:
message = (
"The following {} elements are over 500 polygons:\n"
.format(len(errors))
)
for error in errors:
message += "Polygons: {} - {}\n".format(error[0], error[1])
assert False, message
@step("all {ifc_class} elements have an {representation_class} representation")
def step_impl(context, ifc_class, representation_class):
switch_locale(context.localedir, the_lang)
gdm.eleclass_has_geometric_representation_of_specific_class(
context,
ifc_class,
representation_class
)
@@ -0,0 +1,17 @@
from behave import step
import geometric_detail_methods as gdm
from utils import switch_locale
the_lang = "de"
@step("Alle {ifc_class} Bauteile müssen eine geometrische Repräsentation der Klasse {representation_class} verwenden")
def step_impl(context, ifc_class, representation_class):
switch_locale(context.localedir, the_lang)
gdm.eleclass_has_geometric_representation_of_specific_class(
context,
ifc_class,
representation_class
)
@@ -0,0 +1,58 @@
import gettext # noqa
from utils import assert_elements
from utils import IfcFile
def eleclass_has_geometric_representation_of_specific_class(
context,
ifc_class,
representation_class
):
def is_item_a_representation(item, representation):
if "/" in representation:
for cls in representation.split("/"):
if item.is_a(cls):
return True
elif item.is_a(representation):
return True
context.falseelems = []
context.falseguids = []
context.falseprops = {}
rep = None
elements = IfcFile.get().by_type(ifc_class)
for elem in elements:
if not elem.Representation:
continue
has_representation = False
for representation in elem.Representation.Representations:
for item in representation.Items:
if item.is_a("IfcMappedItem"):
# We only check one more level deep.
for item2 in item.MappingSource.MappedRepresentation.Items:
if is_item_a_representation(item2, representation_class):
has_representation = True
rep = item2
else:
if is_item_a_representation(item, representation_class):
has_representation = True
rep = item
if not has_representation:
context.falseelems.append(str(elem))
context.falseguids.append(elem.GlobalId)
context.falseprops[elem.id()] = str(rep)
context.elemcount = len(elements)
context.falsecount = len(context.falseelems)
assert_elements(
ifc_class,
context.elemcount,
context.falsecount,
context.falseelems,
message_all_falseelems=_("All {elemcount} {ifc_class} elements are not a {parameter} representation."),
message_some_falseelems=_("The following {falsecount} of {elemcount} {ifc_class} elements are not a {parameter} representation: {falseelems}"),
message_no_elems=_("There are no {ifc_class} elements in the IFC file."),
parameter=representation_class
)
@@ -0,0 +1,10 @@
from behave import step
from utils import IfcFile
@step("all buildings have an address")
def step_impl(context):
for building in IfcFile.get().by_type("IfcBuilding"):
if not building.BuildingAddress:
assert False, f'The building "{building.Name}" has no address.'
+6
View File
@@ -0,0 +1,6 @@
#!/usr/bin/env python3
from bimtester.guiwidget import run
run()
Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.9 KiB

+5
View File
@@ -0,0 +1,5 @@
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icon-css-de" viewBox="0 0 640 480">
<path fill="#ffce00" d="M0 320h640v160H0z"/>
<path d="M0 0h640v160H0z"/>
<path fill="#d00" d="M0 160h640v160H0z"/>
</svg>

After

Width:  |  Height:  |  Size: 212 B

+7
View File
@@ -0,0 +1,7 @@
<svg xmlns="http://www.w3.org/2000/svg" id="flag-icon-css-fr" viewBox="0 0 640 480">
<g fill-rule="evenodd" stroke-width="1pt">
<path fill="#fff" d="M0 0h640v480H0z"/>
<path fill="#00267f" d="M0 0h213.3v480H0z"/>
<path fill="#f31830" d="M426.7 0H640v480H426.7z"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 291 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

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