Compare commits

..

195 Commits

Author SHA1 Message Date
Stefano Beccaletto 62386c663a Added default constructor to IfcHierarchyHelper 2021-01-22 11:00:14 +01:00
Thomas Krijnen a10e852a35 Fixes for placement cloning that affected layersets 2019-09-22 14:01:35 +02:00
Thomas Krijnen 7f5d733ed8 Propagate static runtime settings to voxel tk 2019-09-22 12:57:36 +02:00
Thomas Krijnen cdfbde8f18 Subtract interior voxel volumes 2019-09-01 08:56:56 +02:00
Thomas Krijnen 0d7f6af681 Mesh compound prior to voxelization 2019-08-28 16:15:28 +02:00
Thomas Krijnen d76c599477 geom server client getattr; yield from process() 2019-08-28 14:56:09 +02:00
Thomas Krijnen c09de2c568 Test geom server voxels 2019-08-24 13:44:42 +02:00
Thomas Krijnen 3f7290cdc6 Lower voxel resolution, use padding 2019-08-23 14:59:31 +02:00
Thomas Krijnen 7bd4699f65 Update geom server client to parse entity bodies 2019-08-23 14:54:16 +02:00
Thomas Krijnen e137036bbb Update .travis.yml 2019-08-09 13:59:24 +02:00
Thomas Krijnen b1a0e2a62b Update .travis.yml 2019-08-09 11:59:04 +02:00
Thomas Krijnen a97577d272 Update .travis.yml 2019-08-09 11:53:20 +02:00
Thomas Krijnen 53bcb333da Update .travis.yml 2019-08-09 11:34:55 +02:00
Thomas Krijnen 49fb919fbc thread_local define for clang 2019-08-09 10:06:55 +02:00
Thomas Krijnen 5dbbd917d1 gcc and clang on travis 2019-08-08 12:13:06 +02:00
Thomas Krijnen 10d11031e5 Remove redundant occt library links to executables and python wrapper 2019-08-04 12:49:22 +02:00
Thomas Krijnen c8def0474e Update examples 2019-08-03 16:11:02 +02:00
Thomas Krijnen f6aa7c8930 Additional merge issues 2019-08-03 15:43:14 +02:00
Thomas Krijnen 92f7d26835 Work on Python wrapper 2019-08-03 15:09:50 +02:00
Thomas Krijnen 5ccc7213a0 Merge remote-tracking branch 'origin/v0.6.0' into v0.7.0 2019-08-03 14:50:08 +02:00
Thomas Krijnen fd9c57b77d Merge branch 'v0.6.0' into v0.7.0 2019-08-02 17:56:45 +02:00
Thomas Krijnen b08e52bd9b Merge remote-tracking branch 'origin/v0.6.0' into v0.7.0 2019-08-02 13:23:41 +02:00
Thomas Krijnen 0cb2c81227 Rough draft of a client application for the C++ IfcGeomServer binary 2019-05-15 17:13:29 +02:00
Thomas Krijnen bbf271a10e Fix volume calculation with voxels in geom server 2019-05-15 17:07:16 +02:00
Thomas Krijnen d45d843173 Fix CMake error 2019-05-15 14:27:31 +02:00
Thomas Krijnen 4fa283fb3c Write voxelization logic in geom server 2019-05-15 13:57:50 +02:00
Thomas Krijnen 4400a6ea4f Make use of cgal configurable 2019-05-15 11:13:58 +02:00
Thomas Krijnen 9cb321e73d Move include up for M_PI def on MSVC 2019-05-10 14:38:42 +02:00
Thomas Krijnen e566af84c2 Fix geom server for schema agnosticism 2019-05-10 14:35:42 +02:00
Thomas Krijnen 310013dfe4 Fix compilation error from merge 2019-05-10 14:35:20 +02:00
Thomas Krijnen de3633e742 Cmake find voxels 2019-05-10 14:35:00 +02:00
Thomas Krijnen a24ad023a5 CGAL win build script 2019-05-10 13:46:13 +02:00
Thomas Krijnen adc0e92528 Fix remaining conflict 2019-05-10 13:42:16 +02:00
Thomas Krijnen 46ba5661d6 Merge branch 'v0.6.0' into v0.7.0 2019-05-10 13:37:42 +02:00
Thomas Krijnen 33bcf786fd MPIR and MPFR in win build script 2019-05-03 10:46:59 +02:00
Thomas Krijnen 8e6a6ec56d Add voxelization_toolkit to win build script 2019-04-30 14:36:55 +02:00
Thomas Krijnen b862f633db Fix voxel library in nix build script 2019-04-30 13:24:28 +02:00
Thomas Krijnen f9e839817d Add opensourceBIM/voxel to nix build script 2019-04-27 14:37:31 +02:00
Thomas Krijnen a0c01ff756 Merge branch 'v0.6.0' into v0.7.0
# Conflicts:
#	cmake/CMakeLists.txt
#	src/ifcconvert/IfcConvert.cpp
#	src/ifcgeom/IfcGeomRepresentation.h
#	src/ifcgeom/IfcRepresentationShapeItem.h
#	src/ifcgeom/kernels/opencascade/IfcGeomFunctions.cpp
#	src/ifcgeom/schema_agnostic/IfcGeomRepresentation.cpp
#	src/ifcgeom/schema_agnostic/Kernel.cpp
#	src/ifcgeom/schema_agnostic/Kernel.h
#	src/ifcgeomserver/IfcGeomServer.cpp
#	src/serializers/schema_dependent/XmlSerializer.cpp
2019-04-26 15:07:50 +02:00
Thomas Krijnen 5b066c9f95 Don't convert to Nef if there are no voids 2019-01-25 15:19:52 +01:00
Thomas Krijnen 3afb9169b1 Implement missing virtual function in CgalKernel 2019-01-25 14:25:34 +01:00
Thomas Krijnen 24b552a822 Merge fixes 2019-01-23 17:27:13 +01:00
Thomas Krijnen 884064f213 Merge remote-tracking branch 'cgal/cgal' into v0.7.0 2019-01-23 15:44:19 +01:00
Thomas Krijnen 4d39dbca2a Build static cgal, fix null pointer access 2019-01-23 15:10:20 +01:00
Thomas Krijnen 30479ca0a6 Fixes for compilation of cgal kernel 2019-01-23 12:34:21 +01:00
Thomas Krijnen a7a1ad129e Merge commit '6b47e9ca1d18df4b1cd2c66e488ad91f9730ecdf' into v0.7.0
# Conflicts:
#	cmake/CMakeLists.txt
#	nix/build-all.py
#	test/input
2019-01-22 13:00:49 +01:00
Thomas Krijnen bea627d01e Merge commit '6b47e9ca1d18df4b1cd2c66e488ad91f9730ecdf' into v0.7.0 2019-01-22 12:47:21 +01:00
Thomas Krijnen 059a1cb14b Merge commit '4d12bf7e8df4bd144526eeb5994802d308b40297' into v0.7.0 2019-01-22 12:38:02 +01:00
Thomas Krijnen 8c5349feaa Introduce AbstractKernel 2019-01-20 13:16:42 +01:00
Thomas Krijnen fa0a33f3c0 Option to select Kernel from IfcConvert 2019-01-19 12:39:47 +01:00
Thomas Krijnen 5a7c7ed048 Shuffle project structure 2019-01-18 16:43:38 +01:00
Thomas Krijnen 16d6420352 More work on enabling cgal kernel 2019-01-18 15:19:00 +01:00
Thomas Krijnen d804575974 Cgal kernel skeleton 2019-01-18 12:10:18 +01:00
Thomas Krijnen ad24b6be0f Isolate (most of the) geometry processing code into separate opencascade kernel 2019-01-18 11:23:19 +01:00
Thomas Krijnen 0072e1f247 CMake CGAL version of IfcGeom 2019-01-16 14:44:43 +01:00
Thomas Krijnen 116b80cf91 Fix MPFR download location 2019-01-16 14:41:34 +01:00
Thomas Krijnen 208f6d4d74 Small fixes to build script 2019-01-16 14:18:36 +01:00
Thomas Krijnen a0dfdc78ef Add cgal to IfcGeom deps 2019-01-16 14:06:17 +01:00
Thomas Krijnen cf2dd2aa8d Add GMP MPFR CGAL to build script 2019-01-16 14:04:05 +01:00
Thomas Krijnen 6737b54457 Add GMP MPFR CGAL to build script 2019-01-16 13:59:10 +01:00
Thomas Krijnen 9ae55ab303 Small fixes to transformations 2017-06-06 17:12:46 +02:00
Ken Arroyo Ohori 8baf6197d5 Merge pull request #16 from kenohori/cgal
Validation code to catch more cases of invalid objects
2017-04-25 10:22:33 -05:00
Ken Arroyo Ohori 42f23a786f Output all errors as separate files 2017-04-25 13:45:18 +02:00
Ken Arroyo Ohori 8b539d2b93 Requirement for self-intersection tests 2017-04-25 13:44:57 +02:00
Ken Arroyo Ohori b732759388 Comprehensive validation code for opening subtractions 2017-04-25 13:44:34 +02:00
Ken Arroyo Ohori 02244400ab Remove old debug code 2017-04-25 13:43:55 +02:00
Ken Arroyo Ohori 85a36738d2 Comment out triangulation code 2017-04-25 13:42:38 +02:00
Ken Arroyo Ohori 164e67a50b Catching some more CGAL errors, allow non-closed meshes, start of new code to triangulate faces 2017-04-21 15:43:19 +02:00
Ken Arroyo Ohori de83633891 Merge pull request #15 from kenohori/cgal
Catching some errors during conversion to/from Nef, tapered extrusions
2017-04-12 23:10:46 -05:00
Ken Arroyo Ohori 9f2a617ad7 Catch a few nasty cases in triangulation, more efficient to only compute face normals 2017-04-10 18:54:30 -05:00
Ken Arroyo Ohori 26bd03e407 Ditto 2017-04-10 18:53:52 -05:00
Ken Arroyo Ohori 248c73c2ab Catch failures to convert Nef to Polyhedron_3 2017-04-10 18:53:28 -05:00
Thomas Krijnen 8d9acfa677 Attempt to fix travis build w/ CGAL 2017-04-06 15:23:45 +02:00
Thomas Krijnen 7b7f9b4852 Attempt to fix travis build w/ CGAL 2017-04-06 14:57:10 +02:00
Thomas Krijnen 7189219aa4 Attempt to fix travis build w/ CGAL 2017-04-06 14:44:57 +02:00
Ken Arroyo Ohori f03a228280 Merge pull request #3 from aothms/cgal
Thomas fixed the transformations
2017-04-05 18:07:32 -05:00
Thomas Krijnen 91e5b337d3 Reverse matrix multiplication order 2017-04-05 16:06:07 +02:00
Thomas Krijnen 009f50abe1 Fix compilation on MSVC 2017-04-05 15:57:21 +02:00
Ken Arroyo Ohori c9267d7ace Fixed orientation bug in tapered extrusions 2017-03-30 21:11:05 -06:00
Ken Arroyo Ohori 4a340027bf IfcExtrudedAreaSolidTapered (with problems?) 2017-03-30 20:12:23 -06:00
Ken Arroyo Ohori 612f8f36db Merge pull request #14 from kenohori/cgal
Bugfixes + some validation code when creating New polyhedra
2017-03-30 19:16:48 -06:00
Ken Arroyo Ohori c1887f3f1f And the rest 2017-03-30 19:16:11 -06:00
Ken Arroyo Ohori 71ad7dd4bc Forgot one line 2017-03-30 19:06:47 -06:00
Ken Arroyo Ohori ed9676ed38 Squashed some bugs 2017-03-30 19:04:39 -06:00
Ken Arroyo Ohori a6195290f5 Merge pull request #13 from kenohori/cgal
Move shapes back to Polyhedron_3, more IFC entities supported, bugfixes
2017-03-23 20:33:52 -06:00
Ken Arroyo Ohori 583c334802 Removed sphere radius at some point 2017-03-23 20:31:41 -06:00
Ken Arroyo Ohori f8f4db72ec IfcDerivedProfileDef 2017-03-23 20:25:54 -06:00
Ken Arroyo Ohori dd206a2a52 A few more simple IFC classes to fill in things 2017-03-23 20:20:43 -06:00
Ken Arroyo Ohori 12967790ba Switched back to Polyhedron_3 for shapes. Should be checked. 2017-03-23 19:49:15 -06:00
Ken Arroyo Ohori d0b71a2e57 Merge pull request #12 from kenohori/cgal
Reorganisation, export of non-simple New polyhedra, (very slow) solution to create open meshes
2017-03-20 20:59:19 -06:00
Ken Arroyo Ohori 4061f93560 Export non-simple Nef too 2017-03-20 20:57:17 -06:00
Ken Arroyo Ohori 71d7bbd6ba Ordering things… 2017-03-20 20:06:48 -06:00
Ken Arroyo Ohori 62ca6f6a7d Checked shapes with styles. Found bug? 2017-03-20 16:45:27 -06:00
Ken Arroyo Ohori 8090bb4c00 Shapes with styles in separate file 2017-03-20 16:35:14 -06:00
Ken Arroyo Ohori cf6bd5a629 Enabled missing Cartesian transformations 2017-03-20 16:31:06 -06:00
Ken Arroyo Ohori cf9605f108 Missing Shapes, support for voids 2017-03-20 15:56:31 -06:00
Ken Arroyo Ohori 507d4778fa Merge pull request #11 from kenohori/cgal
Bugfixes in placements, half space solids and validation code
2017-03-17 19:27:34 -06:00
Ken Arroyo Ohori 95e6c14f39 Hack to solve issues with IfcHalfSpaceSolid. Not ideal. 2017-03-17 19:24:51 -06:00
Ken Arroyo Ohori 2bbe80fd28 Problems with extended kernel experiment, but this should be incorporated in any case 2017-03-17 16:12:24 -06:00
Ken Arroyo Ohori 0ffa633a6d Better validation 2017-03-16 19:30:39 -06:00
Ken Arroyo Ohori 30e88210b2 Simplified code by moving Nef creation outside 2017-03-16 19:20:41 -06:00
Ken Arroyo Ohori 98ce04ed64 Fix logic of transformations 2017-03-16 18:44:25 -06:00
Ken Arroyo Ohori d2aef0fcbd 2D Cartesian transformations (untested) 2017-03-13 22:32:12 -06:00
Ken Arroyo Ohori 38cbdbc0f4 Correct way to create trimmed parametric curves? 2017-03-13 20:22:19 -06:00
Ken Arroyo Ohori 83689a1cec Merge pull request #10 from kenohori/cgal
Basic support for (trimmed) curves
2017-03-13 19:29:20 -06:00
Ken Arroyo Ohori 81cb7f379e Ignore output files in /test/ 2017-03-13 19:26:54 -06:00
Ken Arroyo Ohori 7d16b725a3 IfcTrimmedCurve. Needs projection to closest point in curve? 2017-03-13 19:08:50 -06:00
Ken Arroyo Ohori 54331062c3 Basic curve types 2017-03-13 19:08:23 -06:00
Ken Arroyo Ohori 4419331710 Merge pull request #9 from kenohori/cgal
Fix issue with opening placements
2017-03-10 18:29:01 -06:00
Ken Arroyo Ohori 81a33309f3 Merge pull request #2 from aothms/cgal
Merge pull request #8 from kenohori/cgal
2017-03-10 18:28:17 -06:00
Ken Arroyo Ohori d02918070d Remove debug code 2017-03-10 18:26:15 -06:00
Ken Arroyo Ohori ac7099ab39 Fixed bug with opening placements 2017-03-10 18:21:15 -06:00
Ken Arroyo Ohori b5e79b2558 Debug code 2017-03-10 17:44:19 -06:00
Ken Arroyo Ohori b1df91ffd9 Merge pull request #8 from kenohori/cgal
More profiles (T, U, Z) and support for openings
2017-03-09 18:45:34 -06:00
Ken Arroyo Ohori 287fb9f0ed Convert openings and subtract them 2017-03-09 18:42:54 -06:00
Ken Arroyo Ohori 06c10dc4da Correct plane creation? 2017-03-09 17:04:37 -06:00
Ken Arroyo Ohori 3972727f9d Z profiles 2017-03-09 16:55:33 -06:00
Ken Arroyo Ohori 3e918180d2 U profiles 2017-03-09 16:46:09 -06:00
Ken Arroyo Ohori 0fbadc2985 T profiles 2017-03-09 16:29:14 -06:00
Ken Arroyo Ohori 8f89498a32 Merge pull request #1 from aothms/cgal
Merging back Thomas' latest changes
2017-03-09 09:46:48 -06:00
Thomas Krijnen 7bcd0d0a8d Apply transformation to IfcExtrudedAreaSolid 2017-03-09 15:35:29 +01:00
Thomas Krijnen 0596827b9d Fix null pointer access in tesselation of opencascade shape 2017-03-09 15:04:54 +01:00
Thomas Krijnen 619b4fbed5 Fix CGAL library linking on windows, conditional IfcTriangulatedFaceSet based on schema 2017-03-09 12:14:00 +01:00
Ken Arroyo Ohori deea0f6558 Merge pull request #7 from kenohori/cgal
Composite curves, some profiles (C, I, L)
2017-03-08 20:13:33 -06:00
Ken Arroyo Ohori 15e4e1952f I profiles (untested) 2017-03-08 20:11:45 -06:00
Ken Arroyo Ohori e922212357 L profiles 2017-03-08 19:55:17 -06:00
Ken Arroyo Ohori 0d36693780 C profiles 2017-03-08 19:38:25 -06:00
Ken Arroyo Ohori cb7ed51fc6 IfcCartesianTransformationOperator3DnonUniform (untested) 2017-03-07 20:00:32 -06:00
Ken Arroyo Ohori a3df0556aa Composite curves 2017-03-07 19:39:59 -06:00
Ken Arroyo Ohori 3f94d4af37 Skeleton for planes+halfspaces. Might be wrong. 2017-03-07 14:30:48 -06:00
Ken Arroyo Ohori 7f96b3a523 Merge pull request #6 from kenohori/cgal
Added several types of shapes and profiles
2017-03-07 13:55:15 -06:00
Ken Arroyo Ohori 27d8e86024 Hollow rectangle profiles, all tested now 2017-03-07 13:52:29 -06:00
Ken Arroyo Ohori 66048610e2 Rounded rectangles work now, def must be before rectangles 2017-03-07 13:41:04 -06:00
Ken Arroyo Ohori 31d4de228a Extrusions with holes (Nef) 2017-03-07 13:18:49 -06:00
Ken Arroyo Ohori 29021d8b06 Hollow circles 2017-03-07 13:04:22 -06:00
Ken Arroyo Ohori 1fb76a9749 Switched to normals per vertex per face 2017-03-07 12:50:06 -06:00
Ken Arroyo Ohori b299c27473 Switched to Nef_polyhedron_3. Some problems... 2017-03-06 19:28:12 -06:00
Ken Arroyo Ohori 64e385c361 Skeleton for IfcEdgeLoop and IfcOrientedEdge 2017-03-06 17:45:55 -06:00
Ken Arroyo Ohori 27b5fd0fc5 Debug code 2017-03-06 17:29:20 -06:00
Ken Arroyo Ohori 4f5ecee81e Removing duplicate points, IfcCartesianTransformationOperator3D with problems 2017-03-06 16:03:29 -06:00
Ken Arroyo Ohori ca19d447cc Zero-radius rounded rectangles 2017-03-06 15:03:57 -06:00
Ken Arroyo Ohori 484cea968e IfcTriangulatedFaceSet 2017-03-06 11:41:58 -06:00
Ken Arroyo Ohori 033a2e7482 IfcFaceBasedSurfaceModel 2017-03-06 11:28:57 -06:00
Ken Arroyo Ohori 1d3732aa62 IfcEllipseProfileDef 2017-03-06 11:23:37 -06:00
Ken Arroyo Ohori 584b2e5584 IfcTrapeziumProfileDef 2017-03-06 11:18:51 -06:00
Ken Arroyo Ohori 1bcc369c7a Rounded rectangles 2017-03-06 11:12:06 -06:00
Ken Arroyo Ohori 64bc8e9d4f Circular profiles, added missing transformation for rectangles 2017-03-06 10:52:57 -06:00
Ken Arroyo Ohori b9828b029c Right way to output more than one object 2017-03-03 15:25:45 -06:00
Ken Arroyo Ohori 749071601e Merge pull request #5 from aothms/ken_first_steps
Reorganised code, Boolean ops seem to work
2017-03-03 13:59:58 -06:00
Ken Arroyo Ohori bbe0b74f83 Boolean ops working? 2017-03-03 13:56:08 -06:00
Ken Arroyo Ohori efb8bce25a Didn’t save sphere output 2017-03-03 13:20:47 -06:00
Ken Arroyo Ohori c59ae03cb3 Fixed bug in cylinders/cones 2017-03-03 13:12:05 -06:00
Ken Arroyo Ohori 7145b1ae85 Some debugging code, checking transformations 2017-03-03 12:58:52 -06:00
Ken Arroyo Ohori 596c4f8b77 Adding some validation code 2017-03-03 09:58:17 -06:00
Ken Arroyo Ohori 302e7b2db8 IfcRightCircularCone 2017-03-02 18:42:10 -06:00
Ken Arroyo Ohori bece7053a0 IfcRightCircularCylinder 2017-03-02 18:39:18 -06:00
Ken Arroyo Ohori 82cd4056b7 IfcRectangularPyramid 2017-03-02 18:22:34 -06:00
Ken Arroyo Ohori 6297ff74f1 Boolean ops using Nef polyhedra (untested) 2017-03-02 18:11:11 -06:00
Ken Arroyo Ohori c9633273a6 Several more classes, needs testing 2017-03-02 17:11:58 -06:00
Ken Arroyo Ohori 2cb53a860d Entities for basic CSG 2017-03-02 15:09:05 -06:00
Ken Arroyo Ohori db85bebc1a Merge branch 'cgal' into ken_first_steps 2017-03-01 17:48:37 -06:00
Ken Arroyo Ohori 57fae25de8 Putting functions into files per geometric type 2017-03-01 17:48:19 -06:00
Thomas Krijnen 451ccd4e21 Merge pull request #4 from aothms/ken_first_steps
IfcManifoldSolidBrep and IfcConnectedFaceSet
2017-02-23 13:53:02 +01:00
Ken Arroyo Ohori b893f5a3f0 Take into account extrusion height 2017-02-22 18:15:27 -06:00
Ken Arroyo Ohori 64eb707996 Fixed issue with transformations? 2017-02-21 18:40:27 -06:00
Ken Arroyo Ohori c0732f5197 Trying to find out why placements don’t arrive at Triangulate() 2017-02-21 15:37:38 -06:00
Ken Arroyo Ohori e47d128b18 Brep and swept solid working now 2017-02-20 20:14:49 -06:00
Ken Arroyo Ohori 9d4463b73a Check for NULL placement 2017-02-13 15:26:06 -06:00
Ken Arroyo Ohori d9d5f17725 Should be working now 2017-02-13 11:45:17 -06:00
Ken Arroyo Ohori f4274e4b46 Skeleton for IfcExtrudedAreaSolid 2017-02-13 11:12:04 -06:00
Ken Arroyo Ohori b463dfe88a Changed --kernel parameter to --opencascade. Was conflicting with positional options for input. 2017-02-09 14:46:02 -06:00
Ken Arroyo Ohori 44634eb42d Remove implemented throws, add faces and materials 2017-02-08 17:12:56 -06:00
Ken Arroyo Ohori 1755752ab7 IfcAxis2Placement2D 2017-02-08 16:56:59 -06:00
Ken Arroyo Ohori 7051104bc7 Basic code to output triangulation, something goes wrong when getting materials... 2017-02-08 16:12:19 -06:00
Ken Arroyo Ohori 2894b0cb92 Nothing is a pointer now. Initialisation is easier… 2017-02-07 20:37:47 -06:00
Ken Arroyo Ohori 42b512960b Filling in most of the placement code. To check. 2017-02-07 20:25:04 -06:00
Ken Arroyo Ohori 96e9c8ecc1 Skeleton for IfcObjectPlacement and IfcAxis2Placement3D 2017-02-07 19:51:16 -06:00
Ken Arroyo Ohori bae84b6753 Directions as CGAL Vector_3, more robust points 2017-02-07 19:50:51 -06:00
Ken Arroyo Ohori e1702fc0cf Return value for transformation, still needs to be initialised somewhere… 2017-02-06 16:22:54 -06:00
Ken Arroyo Ohori 6aff3d0f3d Conversion result for breps 2017-02-06 16:22:36 -06:00
Thomas Krijnen 6b47e9ca1d Add GMP MPFR and CGAL include/libs to cmake and build script 2017-02-04 16:38:57 +01:00
Ken Arroyo Ohori 1525cf6bfc Polyhedra built with the incremental builder, IfcConvert crashes 2017-02-02 14:29:26 -06:00
Ken Arroyo Ohori 5724e1ac34 Face from IfcFace 2017-02-01 17:53:12 -06:00
Ken Arroyo Ohori f2a45b7057 Fixed pointer bug, wires seem okay now 2017-02-01 15:57:25 -06:00
Ken Arroyo Ohori 233aaeaca2 Points and wires 2017-01-31 19:03:15 -06:00
Ken Arroyo Ohori 9c21e05184 Skeleton reaching all the way up to points, to be filled in 2017-01-31 18:53:00 -06:00
Ken Arroyo Ohori 0821dd4702 Skeleton for IfcManifoldSolidBrep and IfcConnectedFaceSet 2017-01-27 18:40:38 -06:00
Ken Arroyo Ohori cac9c91c56 Mac metadata 2017-01-27 15:31:37 -06:00
Ken Arroyo Ohori a4264f3143 Replaced macros, added basic CGAL definitions 2017-01-27 15:31:22 -06:00
Thomas Krijnen 4d12bf7e8d Cgal kernel skeleton (#3)
Cgal kernel skeleton
2017-01-16 14:04:31 +01:00
Thomas Krijnen 3958204c1c Don't build Python wrapper on Travis 2017-01-13 20:51:12 +01:00
Thomas Krijnen d17f714dc5 Isolate geometry processing code into separate opencascade kernel 2017-01-13 20:51:12 +01:00
Thomas Krijnen 4fa7f293d6 cd to correct repository folder 2017-01-13 18:11:05 +01:00
Thomas Krijnen 7e3f96e410 Add GMP MPFR CGAL to build script 2017-01-09 17:14:49 +01:00
Thomas Krijnen 8018c9cc44 Add GMP MPFR CGAL to build script 2017-01-09 17:14:49 +01:00
2599 changed files with 119362 additions and 2608274 deletions
-8
View File
@@ -1,8 +0,0 @@
c14f5eeca042232025797990396232e4feab53e7
d6881e833da0b6278313870d37d42ca6ece8686a
892be5444c5bd01a601c99243ac8d3e7b2f0e779
d169a964dd7e9ab5c98b35a82bcbc76dc6229a7a
4a6ec11f6f84a3d1fed2ee9b2f85d783ac3daa9d
2c9d6a47f4d24a923069775206bf734feeb14830
8f1743ed64a2a52c201a1ef5e312b4d3a7a922cf
ad7f030344c405e10cfa7d5cf06d82c121eeb825
-4
View File
@@ -1,4 +0,0 @@
# These are supported funding model platforms
github: [aothms]
open_collective: opensourcebim
-118
View File
@@ -1,118 +0,0 @@
name: CD
on:
push:
jobs:
activate:
runs-on: ubuntu-latest
if: |
github.repository == 'IfcOpenShell/IfcOpenShell' &&
!startsWith(github.event.head_commit.message, 'Release ') &&
!contains(github.event.head_commit.message, 'ci skip')
steps:
- run: echo ok go
build:
runs-on: ubuntu-latest
needs: activate
steps:
- uses: actions/checkout@v2
with:
submodules: recursive
- name: Install dependencies
run: |
sudo apt update
sudo apt-get install --no-install-recommends \
git cmake gcc g++ libboost-all-dev python3-all-dev swig libpcre3-dev libxml2-dev \
libocct-foundation-dev libocct-modeling-algorithms-dev libocct-modeling-data-dev libocct-ocaf-dev libocct-visualization-dev libocct-data-exchange-dev \
libhdf5-dev libcgal-dev nlohmann-json3-dev
-
name: ccache
uses: hendrikmuhs/ccache-action@v1
-
name: Build ifcopenshell
run: |
mkdir build && cd build
cmake \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_INSTALL_PREFIX=$PWD/install/ \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH=/usr \
-DCMAKE_SYSTEM_PREFIX_PATH=/usr \
-DBUILD_PACKAGE=On \
-DOCC_INCLUDE_DIR=/usr/include/opencascade \
-DOCC_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
-DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/python3 \
-DPYTHON_INCLUDE_DIR:PATH=/usr/include/python3.8 \
-DPYTHON_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libpython3.8.so \
-DCOLLADA_SUPPORT=Off \
-DLIBXML2_INCLUDE_DIR=/usr/include/libxml2 \
-DLIBXML2_LIBRARIES=/usr/lib/x86_64-linux-gnu/libxml2.so \
-DCGAL_INCLUDE_DIR=/usr/include \
-DGMP_INCLUDE_DIR=/usr/include \
-DMPFR_INCLUDE_DIR=/usr/include \
-DGMP_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
-DMPFR_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
-DHDF5_INCLUDE_DIR=/usr/include/hdf5/serial \
-DGLTF_SUPPORT=On \
-DJSON_INCLUDE_DIR=/usr/include \
../cmake
make -j $(nproc)
make install
-
name: Package
run: |
make package
working-directory: build
- name: Upload
uses: actions/upload-artifact@v2
with:
# Artifact name
name: ifcos-artifacts
# Directory containing files to upload
path: build/assets/Ifc*
deliver:
runs-on: ubuntu-latest
needs: build
name: Docker Build, Tag, Push
steps:
- uses: actions/checkout@v2
with:
lfs: true
- name: Download
uses: actions/download-artifact@v2
with:
# Artifact name
name: ifcos-artifacts
path: artifacts/
-
name: Set up QEMU
uses: docker/setup-qemu-action@v1
-
name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
-
name: Login to Dockerhub
uses: docker/login-action@v1
with:
username: aecgeeks
password: ${{ secrets.DOCKER_HUB_TOKEN }}
-
name: Build container image
uses: docker/build-push-action@v2
with:
context: artifacts
repository: aecgeeks/ifcopenshell
tags: aecgeeks/ifcopenshell:latest
file: ./Dockerfile
push: true
-104
View File
@@ -1,104 +0,0 @@
import pathlib
import shutil
import requests
import zipfile
import os
# To test this locally, set these environment variables
REPO_OWNER = os.environ.get("REPO_OWNER", "IfcOpenShell/IfcOpenShell")
MY_WORKFLOW = os.environ.get("MY_WORKFLOW", "ci-ifcopenshell-conda-daily")
WORKFLOW_RUN_ID = os.environ.get("WORKFLOW_RUN_ID", None)
TOKEN = os.environ.get("GITHUB_TOKEN", None)
# To test this locally create a fine-grained personal access token for this repo with permissions "actions:read"
# See https://github.com/settings/tokens?type=beta
# This is a list of strings that indicate that a job has stopped abruptly.
SIGNS_OF_STOPPAGE = [
"Error: The operation was canceled.",
"fatal error C1060: compiler is out of heap space",
]
def start_request_session():
s = requests.Session()
headers = {
"Accept": "application/vnd.github+json",
"X-GitHub-Api-Version": "2022-11-28",
}
if TOKEN:
headers["Authorization"] = f"Bearer {TOKEN}"
s.headers = headers
return s
def get_ci_run(repo_name, run_id):
url = f"https://api.github.com/repos/{repo_name}/actions/runs/{run_id}"
s = start_request_session()
response = s.get(url)
return response.json()
def evaluate_log_file_for_abrupt_stop(log_file):
with open(log_file) as f:
for i, line in enumerate(f):
for sign in SIGNS_OF_STOPPAGE:
if sign in line:
print(f"Found sign of abrupt stoppage in [line {i}]: '{sign}'")
return True
return False
def get_ci_specific_run_specific_failure_details(repo_name, run_id):
url = f"https://api.github.com/repos/{repo_name}/actions/runs/{run_id}/attempts/1/logs"
s = start_request_session()
response = s.get(url)
# SAVE zip file
with open("logs.zip", "wb") as f:
f.write(response.content)
# unzip file
with zipfile.ZipFile("logs.zip", "r") as zip_ref:
zip_ref.extractall("logs")
failed_logs = []
for file in pathlib.Path("logs").iterdir():
if file.is_dir():
continue
if evaluate_log_file_for_abrupt_stop(file):
failed_logs.append(file)
return failed_logs
def restart_job(repo_name, job_id):
url = f"https://api.github.com/repos/{repo_name}/actions/runs/{job_id}/rerun-failed-jobs"
s = start_request_session()
response = s.post(url)
return response.json()
def eval_jobs():
run = get_ci_run(REPO_OWNER, WORKFLOW_RUN_ID)
if run["run_attempt"] > 1:
print("This is not the first attempt. Exiting")
return
failed_logs = get_ci_specific_run_specific_failure_details(REPO_OWNER, WORKFLOW_RUN_ID)
if len(failed_logs) == 0:
print("No runs exhibit signs of abrupt stoppage")
return
print("restarting job", WORKFLOW_RUN_ID)
r = restart_job(REPO_OWNER, WORKFLOW_RUN_ID)
print(r)
shutil.rmtree("logs")
os.remove("logs.zip")
if __name__ == "__main__":
eval_jobs()
-57
View File
@@ -1,57 +0,0 @@
name: ci-bcf-pypi
on:
schedule:
# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
# * * * * *
- cron: "0 0 18 * *"
push:
paths:
- '.github/workflows/ci-bcf-pypi.yml'
workflow_dispatch:
env:
major: 0
minor: 0
name: ifcopenshell
jobs:
activate:
runs-on: ubuntu-latest
if: |
github.repository == 'IfcOpenShell/IfcOpenShell'
steps:
- name: Set env
run: echo ok go
build:
needs: activate
name: ${{ matrix.config.name }}-${{ matrix.pyver }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
steps:
- uses: actions/checkout@v2 # https://github.com/actions/checkout
- uses: actions/setup-python@v2 # https://github.com/actions/setup-python
with:
python-version: '3.10' # Version range or exact version of a Python version to use, using SemVer's version range syntax
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
- run: echo ${{ env.DATE }}
- name: Get current date
id: date
run: echo "::set-output name=date::$(date +'%y%m%d')"
- name: Compile
run: |
pip install build
cd src/bcf &&
make dist
- name: Publish a Python distribution to PyPI
uses: ortega2247/pypi-upload-action@master
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
packages_dir: src/bcf/dist
-92
View File
@@ -1,92 +0,0 @@
name: Publish-blenderbim-chocolatey package
on:
schedule:
# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
# * * * * *
- cron: "30 0 * * *" # 30min past utc midnight
env:
major: 0
minor: 0
name: blenderbim
choco_version: 1.1.0
CHOCO_TOKEN: ${{ secrets.CHOCO_TOKEN }}
jobs:
activate:
runs-on: ubuntu-latest
if: |
github.repository == 'IfcOpenShell/IfcOpenShell'
steps:
- name: Set env
run: echo ok go
build:
needs: activate
name: ${{ matrix.config.name }}-${{ matrix.pyver }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
pyver: [py310]
config:
- {
name: "Windows Build",
short_name: win,
}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2 # https://github.com/actions/setup-python
with:
python-version: '3.10.9' # Version range or exact version of a Python version to use, using SemVer's version range syntax
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
- run: echo ${{ env.DATE }}
- name: Check in published releases if we should do a choco release
id: do_choco
run: |
echo "::set-output name=choco_release::$(python3 /home/runner/work/IfcOpenShell/IfcOpenShell/choco/blenderbim/check_repo_infos.py --do_choco_release?)"
- name: Fill chocolatey scripts on win with latest blender python
if: ${{steps.do_choco.outputs.choco_release}} == 'do_choco_release'
run: |
yesterday_non_iso="$(date --date='yesterday' +'%y%m%d' | tr -d '\n')" &&
target_os=${{ matrix.config.short_name }} &&
latest_blender_python_version_maj_min=$(python3 /home/runner/work/IfcOpenShell/IfcOpenShell/choco/blenderbim/check_repo_infos.py --latest_blender_python_version_maj_min?) &&
echo "latest_blender_python_version_maj_min?: $latest_blender_python_version_maj_min" &&
pyver=$(python3 /home/runner/work/IfcOpenShell/IfcOpenShell/choco/blenderbim/check_repo_infos.py --pyver?) &&
export latest_blender_version_maj_min=$(python3 /home/runner/work/IfcOpenShell/IfcOpenShell/choco/blenderbim/check_repo_infos.py --latest_blender_release_maj_min?) &&
export latest_blender_version_maj_min_pat=$(python3 /home/runner/work/IfcOpenShell/IfcOpenShell/choco/blenderbim/check_repo_infos.py --latest_blender_release_maj_min_pat?) &&
echo latest_blender_version_maj_min_pat?: $latest_blender_version_maj_min_pat &&
export blenderbim_build_version="${{ env.major }}.${{ env.minor }}.$yesterday_non_iso" &&
export url_blenderbim_py310_win_zip="https://github.com/IfcOpenShell/IfcOpenShell/releases/download/blenderbim-$yesterday_non_iso/blenderbim-$yesterday_non_iso-$pyver-$target_os.zip" &&
wget $url_blenderbim_py310_win_zip --no-verbose &&
export sha256sum_blenderbim_py310_win_zip=$( sha256sum blenderbim-$yesterday_non_iso-$pyver-$target_os.zip --tag | cut -d ' ' -f 4 | tr -d '\n') &&
echo sha256sum_blenderbim_py310_win_zip: $sha256sum_blenderbim_py310_win_zip &&
python3 choco/blenderbim/fill_dynamic_parameters.py &&
echo __build choco with mono &&
wget "https://github.com/chocolatey/choco/archive/refs/tags/$choco_version.tar.gz" --quiet &&
tar -xzf "$choco_version.tar.gz" &&
cd choco-$choco_version &&
chmod +x build.sh zip.sh &&
./build.sh &&
cp -r build_output/chocolatey /opt/chocolatey &&
cd /home/runner/work/IfcOpenShell/IfcOpenShell/choco/blenderbim/ &&
echo __choco pack &&
mono /opt/chocolatey/choco.exe --version &&
mono /opt/chocolatey/choco.exe pack --allow-unofficial &&
echo __choco set apiKey &&
mono /opt/chocolatey/choco.exe setapikey --key="$CHOCO_TOKEN" --source="https://push.chocolatey.org/" --allow-unofficial # &&
echo __choco push &&
mono /opt/chocolatey/choco.exe push --source="https://push.chocolatey.org/" --key="$CHOCO_TOKEN" --allow-unofficial --verbose
- name: Inform user about not packaging
if: ${{steps.do_choco.outputs.choco_release}} != 'do_choco_release'
run: |
echo "no releases found today ${{ env.DATE }}, therefore choco packaging is skipped."
@@ -1,83 +0,0 @@
name: Publish-blenderbim-multiplatform
on:
push:
paths:
- '.github/workflows/ci-blenderbim-matrix.yml'
- 'src/blenderbim/**'
- 'src/ifcopenshell-python/ifcopenshell/**'
- 'src/bcf/src/bcf/**'
- 'src/ifcclash/ifcclash/**'
- 'src/ifccobie/**'
- 'src/ifcdiff/**'
- 'src/ifccsv/**'
- 'src/ifcpatch/ifcpatch/**'
- 'src/ifc4d/ifc4d/**'
- 'src/ifc5d/ifc5d/**'
- 'src/ifccityjson/**'
branches:
- v0.7.0
env:
major: 0
minor: 0
name: blenderbim
jobs:
activate:
runs-on: ubuntu-latest
if: |
github.repository == 'IfcOpenShell/IfcOpenShell'
steps:
- name: Set env
run: echo ok go
build:
needs: activate
name: ${{ matrix.config.name }}-${{ matrix.pyver }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
pyver: [py39, py310, py311]
config:
- {
name: "Windows Build",
short_name: win,
}
- {
name: "Linux Build",
short_name: linux
}
- {
name: "MacOS Build",
short_name: macos
}
- {
name: "MacOS ARM Build",
short_name: macosm1
}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2 # https://github.com/actions/setup-python
with:
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
python-version: '3.11'
- run: echo ${{ env.DATE }}
- name: Get current date
id: date
run: echo "::set-output name=date::$(date +'%y%m%d')"
- name: Compile
run: |
cp -r src/blenderbim src/blenderbim_${{ matrix.config.short_name }}_${{ matrix.pyver }} &&
cd src/blenderbim_${{ matrix.config.short_name }}_${{ matrix.pyver }} &&
make dist PLATFORM=${{ matrix.config.short_name }} PYVERSION=${{ matrix.pyver }}
- name: Upload Zip file to release
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: src/blenderbim_${{ matrix.config.short_name }}_${{ matrix.pyver }}/dist/blenderbim-${{steps.date.outputs.date}}-${{ matrix.pyver }}-${{ matrix.config.short_name }}.zip
asset_name: blenderbim-${{steps.date.outputs.date}}-${{ matrix.pyver }}-${{ matrix.config.short_name }}.zip
tag: "blenderbim-${{steps.date.outputs.date}}"
overwrite: true
body: "Daily developer testing build blenderbim-${{steps.date.outputs.date}}"
-48
View File
@@ -1,48 +0,0 @@
name: ci-bsdd-pypi
on:
schedule:
# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
# * * * * *
- cron: "0 0 18 * *"
workflow_dispatch:
env:
major: 0
minor: 0
name: ifcopenshell
jobs:
activate:
runs-on: ubuntu-latest
if: |
github.repository == 'IfcOpenShell/IfcOpenShell'
steps:
- name: Set env
run: echo ok go
build:
needs: activate
runs-on: ubuntu-latest
strategy:
fail-fast: false
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2 # https://github.com/actions/setup-python
with:
python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax
- name: Compile
run: |
pip install build
cd src/bsdd &&
make dist
- name: Publish a Python distribution to PyPI
uses: ortega2247/pypi-upload-action@master
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
packages_dir: src/bsdd/dist
-48
View File
@@ -1,48 +0,0 @@
name: ci-ifcclash-pypi
on:
schedule:
# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
# * * * * *
- cron: "0 0 18 * *"
workflow_dispatch:
env:
major: 0
minor: 0
name: ifcopenshell
jobs:
activate:
runs-on: ubuntu-latest
if: |
github.repository == 'IfcOpenShell/IfcOpenShell'
steps:
- name: Set env
run: echo ok go
build:
needs: activate
runs-on: ubuntu-latest
strategy:
fail-fast: false
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2 # https://github.com/actions/setup-python
with:
python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax
- name: Compile
run: |
pip install build
cd src/ifcclash &&
make dist
- name: Publish a Python distribution to PyPI
uses: ortega2247/pypi-upload-action@master
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
packages_dir: src/ifcclash/dist
-48
View File
@@ -1,48 +0,0 @@
name: ci-ifccsv-pypi
on:
schedule:
# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
# * * * * *
- cron: "0 0 18 * *"
workflow_dispatch:
env:
major: 0
minor: 0
name: ifcopenshell
jobs:
activate:
runs-on: ubuntu-latest
if: |
github.repository == 'IfcOpenShell/IfcOpenShell'
steps:
- name: Set env
run: echo ok go
build:
needs: activate
runs-on: ubuntu-latest
strategy:
fail-fast: false
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2 # https://github.com/actions/setup-python
with:
python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax
- name: Compile
run: |
pip install build
cd src/ifccsv &&
make dist
- name: Publish a Python distribution to PyPI
uses: ortega2247/pypi-upload-action@master
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
packages_dir: src/ifccsv/dist
@@ -1,67 +0,0 @@
name: ci-ifcopenshell-conda-daily
on:
workflow_dispatch:
schedule:
# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
# * * * * *
- cron: "49 23 * * *" # 11min before utc midnight every day
jobs:
test:
name: ${{ matrix.platform.distver }}-${{ matrix.pyver.name }}-${{ matrix.variant }}
runs-on: ${{ matrix.platform.distver }}
defaults:
run:
shell: bash -l {0}
strategy:
fail-fast: false
matrix:
pyver: [
{ name: py311, distver: '3.11'},
{ name: py312, distver: '3.12'}
]
platform: [
{ name: Windows, distver: windows-2022, upload: 'true' },
{ name: Linux, distver: ubuntu-22.04, upload: 'true' },
{ name: macOS, distver: macos-12, upload: 'true' }
]
variant: [
'novtk',
# 'all'
]
steps:
- uses: actions/checkout@v3
with:
submodules: recursive
- name: Download MacOSX SDK
if: ${{ matrix.platform.name == 'macOS' }}
run: |
curl -o MacOSX10.13.sdk.tar.xz -L https://github.com/phracker/MacOSX-SDKs/releases/download/11.3/MacOSX10.13.sdk.tar.xz && \
tar xf MacOSX10.13.sdk.tar.xz && \
sudo mv -v MacOSX10.13.sdk /opt/ && \
ls /opt/
- uses: mamba-org/setup-micromamba@v1 # https://github.com/mamba-org/setup-micromamba
with:
environment-name: build-env
cache-environment: true
condarc: |
channels:
- conda-forge
channel_priority: strict
create-args: >-
python=3.11
anaconda-client
boa
- name: build, test and upload ifcopenshell
if: ${{ matrix.platform.upload == 'true' }}
run: |
conda mambabuild . --python ${{ matrix.pyver.distver }} -c conda-forge --variants "{variant: ${{ matrix.variant }}}" --token ${{ secrets.ANACONDA_TOKEN }} --user ifcopenshell
working-directory: ./conda
@@ -1,78 +0,0 @@
name: ci-ifcopenshell-pypi
on:
workflow_dispatch:
schedule:
# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
# * * * * *
- cron: "0 0 18 * *"
push:
paths:
- '.github/workflows/ci-ifcopenshell-pypi.yml'
env:
major: 0
minor: 0
name: ifcopenshell
jobs:
activate:
runs-on: ubuntu-latest
if: |
github.repository == 'IfcOpenShell/IfcOpenShell'
steps:
- name: Set env
run: echo ok go
build:
needs: activate
name: ${{ matrix.config.name }}-${{ matrix.pyver }}
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
pyver: [py39, py310, py311, py312]
config:
- {
name: "Windows Build",
short_name: win,
}
- {
name: "Linux Build",
short_name: linux
}
- {
name: "MacOS Build",
short_name: macos
}
- {
name: "MacOS ARM Build",
short_name: macosm1
}
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2 # https://github.com/actions/setup-python
with:
python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
- run: echo ${{ env.DATE }}
- name: Get current date
id: date
run: echo "::set-output name=date::$(date +'%y%m%d')"
- name: Compile
run: |
pip install build
cp -r src/ifcopenshell-python src/ifcopenshell_${{ matrix.config.short_name }}_${{ matrix.pyver }} &&
cd src/ifcopenshell_${{ matrix.config.short_name }}_${{ matrix.pyver }} &&
make dist PLATFORM=${{ matrix.config.short_name }} PYVERSION=${{ matrix.pyver }}
- name: Publish a Python distribution to PyPI
uses: ortega2247/pypi-upload-action@master
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
packages_dir: src/ifcopenshell_${{ matrix.config.short_name }}_${{ matrix.pyver }}/dist
-48
View File
@@ -1,48 +0,0 @@
name: ci-ifcpatch-pypi
on:
schedule:
# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
# * * * * *
- cron: "0 0 18 * *"
workflow_dispatch:
env:
major: 0
minor: 0
name: ifcopenshell
jobs:
activate:
runs-on: ubuntu-latest
if: |
github.repository == 'IfcOpenShell/IfcOpenShell'
steps:
- name: Set env
run: echo ok go
build:
needs: activate
runs-on: ubuntu-latest
strategy:
fail-fast: false
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2 # https://github.com/actions/setup-python
with:
python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax
- name: Compile
run: |
pip install build
cd src/ifcpatch &&
make dist
- name: Publish a Python distribution to PyPI
uses: ortega2247/pypi-upload-action@master
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
packages_dir: src/ifcpatch/dist
@@ -1,53 +0,0 @@
name: Publish-ifcsverchok
on:
push:
paths:
- '.github/workflows/ci-ifcsverchok-build.yml'
- 'src/ifcsverchok/*'
branches:
- v0.7.0
env:
major: 0
minor: 0
name: ifcsverchok
jobs:
activate:
runs-on: ubuntu-latest
if: |
github.repository == 'IfcOpenShell/IfcOpenShell'
steps:
- name: Set env
run: echo ok go
build:
needs: activate
name: ifcsverchok
runs-on: ubuntu-latest
strategy:
fail-fast: false
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2 # https://github.com/actions/setup-python
with:
architecture: 'x64' # optional x64 or x86. Defaults to x64 if not specified
python-version: '3.11'
- run: echo ${{ env.DATE }}
- name: Get current date
id: date
run: echo "::set-output name=date::$(date +'%y%m%d')"
- name: Compile
run: |
cd src/ifcsverchok
make dist
- name: Upload Zip file to release
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: src/ifcsverchok/dist/ifcsverchok-${{steps.date.outputs.date}}.zip
asset_name: ifcsverchok-${{steps.date.outputs.date}}.zip
tag: "ifcsverchok-${{steps.date.outputs.date}}"
overwrite: true
body: "ifcsverchok build for ${{steps.date.outputs.date}}"
-48
View File
@@ -1,48 +0,0 @@
name: ci-ifctester-pypi
on:
schedule:
# ┌───────────── minute (0 - 59)
# │ ┌───────────── hour (0 - 23)
# │ │ ┌───────────── day of the month (1 - 31)
# │ │ │ ┌───────────── month (1 - 12 or JAN-DEC)
# │ │ │ │ ┌───────────── day of the week (0 - 6 or SUN-SAT)
# * * * * *
- cron: "0 0 18 * *"
workflow_dispatch:
env:
major: 0
minor: 0
name: ifcopenshell
jobs:
activate:
runs-on: ubuntu-latest
if: |
github.repository == 'IfcOpenShell/IfcOpenShell'
steps:
- name: Set env
run: echo ok go
build:
needs: activate
runs-on: ubuntu-latest
strategy:
fail-fast: false
steps:
- uses: actions/checkout@v2
- uses: actions/setup-python@v2 # https://github.com/actions/setup-python
with:
python-version: '3.11' # Version range or exact version of a Python version to use, using SemVer's version range syntax
- name: Compile
run: |
pip install build
cd src/ifctester &&
make dist
- name: Publish a Python distribution to PyPI
uses: ortega2247/pypi-upload-action@master
with:
user: __token__
password: ${{ secrets.PYPI_API_TOKEN }}
packages_dir: src/ifctester/dist
@@ -1,34 +0,0 @@
name: Restart failed daily conda builds
on:
workflow_run:
workflows: [ ci-ifcopenshell-conda-daily ]
types:
- completed
env:
REPO_OWNER: IfcOpenShell/IfcOpenShell
MY_WORKFLOW: ci-ifcopenshell-conda-daily
jobs:
restart-failed-runs:
runs-on: ubuntu-latest
if: ${{ github.event.workflow_run.conclusion == 'failure' }}
steps:
- name: checkout
uses: actions/checkout@v3
- name: Use python 3.11
uses: actions/setup-python@v2
with:
python-version: 3.11
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install requests
- name: Check for failed runs
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
WORKFLOW_RUN_ID: ${{ github.event.workflow_run.id }}
run: |
python check_repo_ci_jobs.py
working-directory: .github/workflows
-127
View File
@@ -1,127 +0,0 @@
name: ci
on:
push:
paths:
- 'src/ifcblender/**'
- 'src/ifcconvert/**'
- 'src/ifcgeom/**'
- 'src/ifcgeom_schema_agnostic/**'
- 'src/ifcgeomserver/**'
- 'src/ifcjni/**'
- 'src/ifcmax/**'
- 'src/ifcopenshell-python/**'
- '!src/ifcopenshell-python/docs/**'
- 'src/ifcparse/**'
- 'src/ifcwrap/**'
- 'src/qtviewer/**'
- 'src/serializers/**'
- 'conda/**'
- 'cmake/**'
- '.github/workflows/ci.yml'
pull_request:
jobs:
activate:
runs-on: ubuntu-latest
if: |
github.repository == 'IfcOpenShell/IfcOpenShell' &&
!contains(github.event.head_commit.message, 'skip ci')
steps:
- run: echo ok go
build:
runs-on: ubuntu-latest
needs: activate
steps:
- uses: actions/checkout@v4
with:
submodules: recursive
- name: Set up Python
uses: actions/setup-python@v5
with:
python-version: 3.11
- name: Install dependencies
run: |
python -m pip install --upgrade pip
pip install xmlschema xsdata numpy lxml pytest isodate lark networkx tabulate python-dateutil
pip install src/bcf --no-deps
pip install https://github.com/Andrej730/aud/archive/refs/heads/master-reduced-size.zip
- name: Install C++ dependencies
run: |
sudo apt update
sudo apt-get install --no-install-recommends \
git cmake gcc g++ \
libboost-date-time-dev \
libboost-filesystem-dev \
libboost-iostreams-dev \
libboost-program-options-dev \
libboost-regex-dev \
libboost-system-dev \
libboost-thread-dev \
swig libpcre3-dev libxml2-dev \
libtbb-dev nlohmann-json3-dev \
libocct-foundation-dev libocct-modeling-algorithms-dev libocct-modeling-data-dev libocct-ocaf-dev libocct-visualization-dev libocct-data-exchange-dev \
libhdf5-dev libcgal-dev
- name: ccache
uses: hendrikmuhs/ccache-action@v1
with:
key: ${GITHUB_WORKFLOW}
- name: Build ifcopenshell
run: |
echo $Python3_ROOT_DIR
echo ${{ env.pythonLocation }}
mkdir build && cd build
cmake \
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH=/usr \
-DCMAKE_SYSTEM_PREFIX_PATH=/usr \
-DOCC_INCLUDE_DIR=/usr/include/opencascade \
-DOCC_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
-DPYTHON_EXECUTABLE:FILEPATH=${{ env.pythonLocation }}/bin/python \
-DPYTHON_INCLUDE_DIR:PATH=${{ env.pythonLocation }}/include/python3.11 \
-DPYTHON_LIBRARY:FILEPATH=${{ env.pythonLocation }}/lib/libpython3.11.so \
-DCOLLADA_SUPPORT=Off \
"-DSCHEMA_VERSIONS=2x3;4;4x3_add1" \
-DGLTF_SUPPORT=On \
-DJSON_INCLUDE_DIR=/usr/include \
-DCGAL_INCLUDE_DIR=/usr/include \
-DGMP_INCLUDE_DIR=/usr/include \
-DMPFR_INCLUDE_DIR=/usr/include \
-DGMP_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
-DMPFR_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
-DHDF5_INCLUDE_DIR=/usr/include/hdf5/serial \
../cmake
sudo make -j $(nproc)
sudo make install
- name: Run IfcConvert on Sample files
run: |
(find test/input src/blenderbim/test/files -name '*.ifc' | while read i; do \
echo $i | tee -a log; \
timeout 1m "$(which IfcConvert)" -yv "$i" "$i.obj" --validate >> log 2>&1; \
echo $i $? >> statuses; \
done) || true
echo Failed
grep -v 0$ statuses
grep -v 0$ statuses | wc -l
echo Succeeded
grep 0$ statuses
grep 0$ statuses | wc -l
- name: Test ifcopenshell-python
run: |
cd test
python tests.py
cd ../src/ifcopenshell-python
mv ifcopenshell ifcopenshell-local # Force testing on installed module
make test-safe
-117
View File
@@ -1,117 +0,0 @@
name: Release
on:
push:
tags:
- 'v[0-9].[0-9].[0-9]*'
jobs:
activate:
if: github.repository == 'IfcOpenShell/IfcOpenShell'
runs-on: ubuntu-latest
steps:
- run: echo ok go
build:
needs: activate
runs-on: ubuntu-20.04
steps:
- name: Checkout
uses: actions/checkout@v2
with:
submodules: recursive
- name: Install C++ dependencies
run: |
sudo apt update
sudo apt-get install --no-install-recommends \
git cmake gcc g++ \
libboost-date-time-dev \
libboost-filesystem-dev \
libboost-iostreams-dev \
libboost-program-options-dev \
libboost-regex-dev \
libboost-system-dev \
libboost-thread-dev \
python3-all-dev python3-pip \
swig libpcre3-dev libxml2-dev \
libtbb-dev nlohmann-json3-dev \
libocct-foundation-dev libocct-modeling-algorithms-dev libocct-modeling-data-dev libocct-ocaf-dev libocct-visualization-dev libocct-data-exchange-dev \
libhdf5-dev libcgal-dev opencollada-dev
- name: Build
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
CHANGELOG_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
run: |
mkdir build && cd build
cmake \
-DCMAKE_INSTALL_PREFIX=$PWD/install/ \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH=/usr \
-DCMAKE_SYSTEM_PREFIX_PATH=/usr \
-DBUILD_PACKAGE=On \
-DOCC_INCLUDE_DIR=/usr/include/opencascade \
-DOCC_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
-DPYTHON_EXECUTABLE:FILEPATH=/usr/bin/python3 \
-DPYTHON_INCLUDE_DIR:PATH=/usr/include/python3.8 \
-DPYTHON_LIBRARY:FILEPATH=/usr/lib/x86_64-linux-gnu/libpython3.8.so \
-DLIBXML2_INCLUDE_DIR=/usr/include/libxml2 \
-DLIBXML2_LIBRARIES=/usr/lib/x86_64-linux-gnu/libxml2.so \
-DGLTF_SUPPORT=On \
-DJSON_INCLUDE_DIR=/usr/include \
-DCGAL_INCLUDE_DIR=/usr/include \
-DGMP_INCLUDE_DIR=/usr/include \
-DMPFR_INCLUDE_DIR=/usr/include \
-DGMP_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
-DMPFR_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
-DHDF5_INCLUDE_DIR=/usr/include/hdf5/serial \
-DOPENCOLLADA_INCLUDE_DIR=/usr/include/opencollada \
-DOPENCOLLADA_LIBRARY_DIR=/usr/lib/opencollada/ \
../cmake
make -j $(nproc)
make install
- name: Package
id: package
run: |
make package
echo ::set-output name=tgz::$( ls assets/*.tar.gz | head -n 1 | xargs basename )
echo ::set-output name=deb::$( ls assets/*.deb | head -n 1 | xargs basename )
working-directory: build
env:
CHANGELOG_GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Release
id: release
uses: actions/create-release@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
tag_name: ${{ github.ref }}
release_name: Release ${{ github.ref }}
draft: false
prerelease: true
body: |
Changes to this release
- add github actions support #1306
- add boost depends to ifcopenshell deb packaging
- <add more changes here>
See more details in the documentation
# body_path: build/CHANGELOG.md
- name: Upload TGZ
id: upload-tgz
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
asset_path: build/assets/${{ steps.package.outputs.tgz }}
asset_name: ${{ steps.package.outputs.tgz }}
asset_content_type: application/x-gzip
- name: Upload DEB
id: upload-deb
uses: actions/upload-release-asset@v1
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
with:
upload_url: ${{ steps.release.outputs.upload_url }} # This pulls from the CREATE RELEASE step above, referencing it's ID to get its outputs object, which include a `upload_url`. See this blog post for more info: https://jasonet.co/posts/new-features-of-github-actions/#passing-data-to-future-steps
asset_path: build/assets/${{ steps.package.outputs.deb }}
asset_name: ${{ steps.package.outputs.deb }}
asset_content_type: application/vnd.debian.binary-package
+6 -93
View File
@@ -1,103 +1,16 @@
# Dependency and build folders created by the build scripts
/_deps/
/_build-vs*-x*/
/_deps-vs*-x*-installed/
/_installed-vs*-x*/
/build/
# output directories
/cmake/out/
/src/examples/out/
/src/ifcmax/out/
/src/ifcwrap/out/
/src/qtviewer/out/
/deps*/
/build*/
/install*/
/win/BuildDepsCache*.txt
# IfcExpressParser residue
/src/ifcexpressparser/express_parser.py
# General Python residue
__pycache__
*.py.bak
# Visual Studio Code files
.vscode
.vs
# PyCharm files
.idea
# Docs
/docs/cpp-api/output
# gettext binary translation files
*.mo
# Vim
*.swp
*.swo
# Flask
instance/*
!instance/.gitignore
.webassets-cache
.env
*.db
# Byte-compiled / optimized / DLL files
*.py[cod]
*$py.class
# pipenv
Pipfile
Pipfile.lock
# Database
*.db
# PyTest
htmlcov
.coverage
# Blender
*.blend1
# Sphinx
_build/
# IDS Docs
src/ifcopenshell-python/test/build
# tox cache
.tox/
*.egg-info/
# mypy cache
.mypy_cache
# blenderbim libs
src/blenderbim/blenderbim/libs
# blenderbim i18n
src/blenderbim/blenderbim/translations.py
# blenderbim test temp files
src/blenderbim/test/files/temp
src/blenderbim/test/files/basic.ifc.cache.blend
src/blenderbim/test/files/basic.ifc.cache.sqlite
src/blenderbim/drawings
src/blenderbim/layouts
# ifcopenshell swig and compiled files
src/ifcopenshell-python/ifcopenshell/_ifcopenshell_wrapper.so
src/ifcopenshell-python/ifcopenshell/ifcopenshell_wrapper.py
# apple
# OSX files
.DS_Store
# clangd config
.clangd
# clangd cache
.cache
# Brickschema
src/blenderbim/blenderbim/bim/schema/Brick.ttl
-9
View File
@@ -5,12 +5,3 @@
[submodule "src/ifcopenshell-python/ifcopenshell/mvd"]
path = src/ifcopenshell-python/ifcopenshell/mvd
url = https://github.com/opensourceBIM/python-mvdxml/
[submodule "src/svgfill"]
path = src/svgfill
url = https://github.com/IfcOpenShell/svgfill
[submodule "src/ifcopenshell-python/test/Sample-BIM-Files"]
path = src/ifcopenshell-python/test/Sample-BIM-Files
url = https://github.com/IfcOpenShell/ids-test-files
[submodule "docs/cpp-api/assets/doxygen-awesome-css"]
path = docs/cpp-api/assets/doxygen-awesome-css
url = https://github.com/jothepro/doxygen-awesome-css.git
+68
View File
@@ -0,0 +1,68 @@
language: cpp
compiler:
- gcc
- clang
os: linux
dist: bionic
sudo: required
before_install:
- "sudo add-apt-repository -y ppa:freecad-community/ppa"
- sudo apt-get update -qq
install:
- |
sudo apt-get install -y \
libocct-data-exchange-dev libocct-foundation-dev libocct-modeling-algorithms-dev libocct-modeling-data-dev \
libboost-system-dev libboost-program-options-dev libboost-regex-dev libboost-thread-dev libboost-date-time-dev libboost-iostreams-dev libboost-filesystem-dev \
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
script:
- pwd
- cd cmake
- mkdir build
- cd build
- |
cmake \
-DOCC_INCLUDE_DIR=/usr/include/opencascade \
-DOCC_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu \
-DPYTHON_LIBRARY=/usr/lib/python2.7/config-x86_64-linux-gnu/libpython2.7.so \
-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;/usr/lib/x86_64-linux-gnu/libicudata.so" \
-DGLTF_SUPPORT=On \
-DJSON_INCLUDE_DIR=/usr/include/json \
..
- sudo make -j2 install
- cd ../../test
- /usr/bin/python2.7 tests.py
- cd input
- /usr/local/bin/IfcConvert -yv acad2010_walls.ifc 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
- |
(for i in *.ifc; do \
echo $i | tee -a log; \
timeout 1m /usr/local/bin/IfcConvert -yv "$i" "$i.dae" --validate >> log 2>&1; \
echo $i $? >> statuses; \
done) || true
- echo Failed
- grep -v 0$ statuses
- grep -v 0$ statuses | wc -l
- echo Succeeded
- grep 0$ statuses
- grep 0$ statuses | wc -l
+2 -2
View File
@@ -1,7 +1,7 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
@@ -618,4 +618,4 @@ an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
END OF TERMS AND CONDITIONS
+1 -1
View File
@@ -1,7 +1,7 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
-39
View File
@@ -1,39 +0,0 @@
# -*- mode: Dockerfile -*-
FROM ubuntu:focal
ARG CHANNEL
ENV CHANNEL=${CHANNEL:-latest}
RUN apt-get update \
&& apt-get install -y \
vim \
ssh \
sudo \
wget \
software-properties-common ;\
rm -rf /var/lib/apt/lists/*
RUN useradd --user-group --create-home --shell /bin/bash IfcOpenShell ;\
echo "IfcOpenShell ALL=(ALL) NOPASSWD:ALL" >> /etc/sudoers
ENV DEBIAN_FRONTEND=noninteractive
RUN echo "deb http://archive.ubuntu.com/ubuntu focal-proposed main restricted" | tee -a /etc/apt/sources.list; \
echo "deb http://archive.ubuntu.com/ubuntu focal-proposed universe" | tee -a /etc/apt/sources.list; \
echo "deb http://archive.ubuntu.com/ubuntu focal-proposed multiverse" | tee -a /etc/apt/sources.list; \
apt-get -qq update; \
apt-get -y install tzdata dos2unix rsync; \
apt-get -y install python3 libxml2 libpython3.8 \
libboost-all-dev \
libocct-foundation-dev libocct-modeling-algorithms-dev libocct-modeling-data-dev \
libocct-ocaf-dev libocct-visualization-dev libocct-data-exchange-dev \
libhdf5-serial-dev python3-pytest ; \
rm -rf /var/lib/apt/lists/* ;
COPY . /home/IfcOpenShell/
RUN ls -lrtR /home/IfcOpenShell
RUN dpkg -i /home/IfcOpenShell/*.deb
USER IfcOpenShell
+209 -68
View File
@@ -1,83 +1,224 @@
IfcOpenShell
============
IfcOpenShell is an open source ([LGPL]) software library for working with the Industry Foundation Classes ([IFC])
file format. Currently supported IFC releases are [IFC2x3 TC1] and [IFC4 Add2 TC1].
<p align="center">
<img src="https://github.com/IfcOpenShell/IfcOpenShell/assets/88302/34901387-e2dd-4a0c-8e38-9ffc32a66cde">
</p>
For more information, see
* [http://ifcopenshell.org](http://ifcopenshell.org)
* [http://academy.ifcopenshell.org](http://academy.ifcopenshell.org)
IfcOpenShell is an open source ([LGPL]) software library for working with Industry Foundation Classes ([IFC]). Complete
parsing support is provided for [IFC2x3 TC1], [IFC4 Add2 TC1], IFC4x1, IFC4x2, and [IFC4x3 Add2]. Extensive geometric support
is implemented for the IFC releases [IFC2x3 TC1] and [IFC4 Add2 TC1]. Extending with support for arbitrary IFC schemas
is possible at compile-time when using C++ and at run-time when using Python.
[![Build Status](https://api.travis-ci.org/IfcOpenShell/IfcOpenShell.png)](https://api.travis-ci.org/IfcOpenShell/IfcOpenShell)
In addition to a C++ and Python API, IfcOpenShell comes with an ecosystem of tools, notably including IfcConvert (an application
to convert IFC models to other formats), the BlenderBIM Add-on (an add-on to Blender providing a graphical IFC authoring platform),
and many other libraries, CLI apps, and more. Support is also provided for auxiliary standards such as BCF and IDS.
Prerequisites
-------------
* Git
* CMake (2.6 or newer)
* Windows: [Visual Studio] 2008 or newer with C++ toolset (or [Visual C++ Build Tools]) or [MSYS2] + MinGW
* *nix: GCC 4.7 or newer, or Clang (any version)
For more information, see:
Dependencies
-------------
* [Boost](http://www.boost.org/)
* [Open Cascade](http://opencascade.org) - *optional*, but required for building IfcGeom
([official](http://www.opencascade.org/getocc/download/loadocc/), "OCCT", or [community edition](https://github.com/tpaviot/oce), "OCE")
For converting IFC representation items into BRep solids and tesselated meshes
* [OpenCOLLADA](https://github.com/khronosGroup/OpenCOLLADA/) - *optional*
For IfcConvert to be able to write tessellated Collada (.dae) files
* [SWIG](http://www.swig.org/) and [Python](https://www.python.org/) - *optional*
For building the IfcOpenShell Python interface and the Blender add-on
* [3ds Max SDK](http://www.autodesk.com/products/3ds-max/free-trial) - *optional*
For building the 3ds Max plug-in.
All recent versions of 3ds Max (2014 and newer) are 64-bit only, so a 64-bit installation is assumed.
* [IfcOpenShell Website](http://ifcopenshell.org)
* [IfcOpenShell Documentation](https://docs.ifcopenshell.org)
* [IfcOpenShell C++ Installation](https://docs.ifcopenshell.org/ifcopenshell/installation.html)
* [IfcOpenShell Python Installation](https://docs.ifcopenshell.org/ifcopenshell-python/installation.html)
* [IfcOpenShell Python Hello World Tutorial](https://docs.ifcopenshell.org/ifcopenshell-python/hello_world.html)
* [BlenderBIM Add-on Website](https://blenderbim.org)
* [BlenderBIM Add-on Documentation](https://docs.blenderbim.org/index.html)
* [Add-on Installation](https://docs.blenderbim.org/users/installation.html)
* [Exploring an IFC model](https://docs.blenderbim.org/users/exploring_an_ifc_model.html)
Building IfcOpenShell
---------------------
| Service | Status |
| ----------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| Anaconda Daily Build | [![Anaconda-Server Badge](https://img.shields.io/conda/vn/ifcopenshell/ifcopenshell)](https://anaconda.org/ifcopenshell/ifcopenshell) |
| Anaconda v0.7.0 Stable | [![Anaconda-Server Badge](https://img.shields.io/conda/vn/conda-forge/ifcopenshell)](https://anaconda.org/conda-forge/ifcopenshell) |
| PyPi Daily Build | [![PyPi Badge](https://img.shields.io/pypi/v/ifcopenshell)](https://pypi.org/project/ifcopenshell/) |
| ArchLinux AUR Package Stable | [![AUR Badge](https://img.shields.io/aur/version/ifcopenshell)](https://aur.archlinux.org/packages/ifcopenshell) |
| ArchLinux AUR Package git | [![AUR Badge](https://img.shields.io/aur/version/ifcopenshell-git)](https://aur.archlinux.org/packages/ifcopenshell-git) |
| BlenderBIM Add-on Chocolatey (under moderation) | [![Chocolatey Badge](https://img.shields.io/chocolatey/v/blenderbim-nightly)](https://community.chocolatey.org/packages/blenderbim-nightly/) |
| Sponsor development on OpenCollective | [![Financial Contributors](https://opencollective.com/opensourcebim/tiers/badge.svg)](https://opencollective.com/opensourcebim/) |
| Docker hub | [![Docker Pulls](https://img.shields.io/docker/pulls/aecgeeks/ifcopenshell)](https://hub.docker.com/r/aecgeeks/ifcopenshell) |
**Note:** The path where the source code is cloned to can contain spaces but non-ASCII characters are very likely to cause problems with the build.
Contents
--------
### Compiling on Windows
The preferred way to fetch and build this project's dependencies is to use the build scripts
in win/ folder. **See [win/readme.md] for more information**.
Those marked with an asterisk are part of IfcOpenShell.
#### Using Visual Studio
Instructions in a nutshell (**assuming Visual Studio 2015 x64 environment variables set**):
| Name | Description | License |
| ------------------------- | --------------------------------------------------------------------- | ------------------- |
| bcf | Library to read and write BCF-XML and query OpenCDE BCF-API modules | LGPL-3.0-or-later |
| blenderbim | Add-on to Blender providing a graphical native IFC authoring platform | GPL-3.0-or-later |
| bsdd | Library to query the bSDD API | LGPL-3.0-or-later |
| ifc2ca | Utility to convert IFC structural analysis models to Code_Aster | LGPL-3.0-or-later |
| ifc4d | Convert to and from IFC and project management software | LGPL-3.0-or-later |
| ifc5d | Report and optimise cost information from IFC | LGPL-3.0-or-later |
| ifcbimtester | Wrapper for Gherkin based unit testing for IFC models | LGPL-3.0-or-later |
| ifcblender | Historic Blender IFC import add-on | LGPL-3.0-or-later\* |
| ifccityjson | Convert CityJSON to IFC | LGPL-3.0-or-later |
| ifcclash | Clash detection library and CLI app | LGPL-3.0-or-later |
| ifcconvert | CLI app to convert IFC to many other formats | LGPL-3.0-or-later\* |
| ifccsv | Library and CLI app to export and import schedules from IFC | LGPL-3.0-or-later |
| ifcdiff | Compare changes between IFC models | LGPL-3.0-or-later |
| ifcfm | Extract IFC data for FM handover requirements | LGPL-3.0-or-later |
| ifcgeom | Internal library for IfcOpenShell | LGPL-3.0-or-later\* |
| ifcgeom\_schema\_agnostic | Internal library for IfcOpenShell | LGPL-3.0-or-later\* |
| ifcgeomserver | Internal library for IfcOpenShell | LGPL-3.0-or-later\* |
| ifcjni | Internal library for IfcOpenShell | LGPL-3.0-or-later\* |
| ifcmax | Historic extension for IFC support in 3DS Max | LGPL-3.0-or-later\* |
| ifcopenshell-python | Python library for IFC manipulation | LGPL-3.0-or-later\* |
| ifcparse | Internal library for IfcOpenShell | LGPL-3.0-or-later\* |
| ifcpatch | Utility to run pre-packaged scripts to manipulate IFCs | LGPL-3.0-or-later |
| ifcsverchok | Blender Add-on for visual node programming with IFC | GPL-3.0-or-later |
| ifctester | Library, CLI and webapp for IDS model auditing | LGPL-3.0-or-later |
| ifcwrap | Internal library for IfcOpenShell | LGPL-3.0-or-later\* |
| qtviewer | Internal library for IfcOpenShell | LGPL-3.0-or-later\* |
| serializers | Internal library for IfcOpenShell | LGPL-3.0-or-later\* |
> cd IfcOpenShell\win
> build-deps.cmd
> run-cmake.bat
[LGPL]: https://github.com/IfcOpenShell/IfcOpenShell/tree/master/COPYING.LESSER "LGPL-3.0-or-later"
[IFC]: https://technical.buildingsmart.org/standards/ifc/ "IFC"
[IFC2x3 TC1]: https://standards.buildingsmart.org/IFC/RELEASE/IFC2x3/TC1/HTML/ "IFC2x3 TC1"
[IFC4 Add2 TC1]: https://standards.buildingsmart.org/IFC/RELEASE/IFC4/ADD2_TC1/HTML/ "IFC4 Add2 TC1"
[IFC4x3 Add2]: https://standards.buildingsmart.org/IFC/RELEASE/IFC4_3/ "IFC4x3 Add2"
You can now open and build the solution file in Visual Studio:
> ..\build-vs2015-x64\IfcOpenShell.sln
As the scripts default to using the `RelWithDebInfo` configuration, and a freshly created solution by CMake defaults
to `Debug`, make sure to switch the used build configuration. Build the `INSTALL` project (right-click -> Project
Only) to deploy the headers and binaries into a single location if wanted/needed.
Alternatively, one can use the utility batch file(s) to build and install the project easily from the command-line
(installing a project will build it also, if required):
> install-ifcopenshell.bat
#### Using MSYS2 + MinGW
Start the MSYS2 Shell and then:
$ cd IfcOpenShell/win
$ ./build-deps.sh
$ ./run-cmake.sh
$ ./install-ifcopenshell.sh
#### Using Bash on Ubuntu on Windows
Start Bash on Ubuntu on Windows and follow the instructions below. Compiling on Ubuntu 14.04.4 LTS using GCC 4.8.4
or Clang 3.5 has been confirmed to work.
### Compiling on *nix
The following instructions are for Ubuntu, modify as required for other operating systems. [nix/build-all.py] script
can be experimented with and studied for pointers for other operating systems, but note that this script is not currently
meant to be used for a typical IfcOpenShell workspace setup.
Note: where `make -j` is written, add a number roughly equal to the amount of CPU cores + 1.
**1)** Install most of the prerequisites and dependencies:
$ sudo apt-get install git cmake gcc g++ libboost-all-dev
**2a)** Either use an OCE package from your operating system's software repository
$ sudo apt-get install liboce-foundation-dev liboce-modeling-dev liboce-ocaf-dev liboce-visualization-dev liboce-ocaf-lite-dev
**2b)** or (if not available, or the latest code is wanted) compile OCE yourself (note that the build takes a long time):
$ sudo apt-get install libftgl-dev libtbb2 libtbb-dev libgl1-mesa-dev libfreetype6-dev
$ git clone https://github.com/tpaviot/oce.git
$ cd oce
$ mkdir build && cd build
$ cmake ..
$ make -j
$ sudo make install
**2c)** or obtain and compile OCCT from http://www.opencascade.org/getocc/download/loadocc/
**3)** For building IfcConvert with COLLADA (.dae) support (on by default), OpenCOLLADA is needed:
$ sudo apt-get install libpcre3-dev libxml2-dev
$ git clone https://github.com/KhronosGroup/OpenCOLLADA.git
$ cd OpenCOLLADA
Using a known good revision, but HEAD should work too:
$ git checkout 064a60b65c2c31b94f013820856bc84fb1937cc6
$ mkdir build && cd build
$ cmake ..
$ make -j
$ sudo make install
**4)** For building the IfcPython wrapper (on by default), SWIG and Python development are needed, if not already available:
$ sudo apt-get install python-all-dev swig
**5)** To build IfcOpenShell please take the following steps. Alternatively use environment variables for setting the
dependencies' paths. `OCC_INCLUDE_DIR` might be needed to set also. `OPENCOLLADA_INCLUDE_DIR` and `OPENCOLLADA_LIBRARY_DIR`
(and potentially `PCRE_LIBRARY_DIR`) are needed if building with COLLADA support. (`-DCOLLADA_SUPPORT=0` disables it).
$ cd /path/to/IfcOpenShell
$ mkdir build && cd build
$ cmake ../cmake -DOCC_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu/ \
-DOPENCOLLADA_INCLUDE_DIR="/usr/local/include/opencollada" \
-DOPENCOLLADA_LIBRARY_DIR="/usr/local/lib/opencollada" \
-DPCRE_LIBRARY_DIR=/usr/lib/x86_64-linux-gnu/
$ make -j
If all worked out correctly you can now use IfcOpenShell. See the examples below.
**6)** Install the project if wanted:
$ sudo make install
Installing IfcOpenShell with Conda
----------------------------------
Another option for building and installing IfcOpenShell is to use the popular
[Anaconda Python Distribution](https://www.anaconda.com/download).
The requirements are spread across a number of channels.
You can add these channels to your configuration, or specify them all on the command line:
$ conda install -c conda-forge -c oce -c dlr-sc -c ifcopenshell ifcopenshell
Usage examples
--------------
**Invoking IfcConvert from the command line**
$ wget ftp://ftp.dds.no/pub/ifc/Munkerud/Munkerud_hus6_BE.zip
$ unzip Munkerud_hus6_BE.zip
$ ./IfcConvert Munkerud_hus6_BE.ifc
$ less Munkerud_hus6_BE.obj
**Using the IfcOpenShell Python interface**
$ wget -O duplex.zip http://projects.buildingsmartalliance.org/files/?artifact_id=4278
$ unzip duplex.zip
$ python
>>> import ifcopenshell
>>> f = ifcopenshell.open("Duplex_A_20110907_optimized.ifc")
>>>
>>> # Accessing entity instances by type:
>>> f.by_type("ifcwall")[:2]
[#91=IfcWallStandardCase('2O2Fr$t4X7Zf8NOew3FL9r',#1,'Basic Wall:Interior - Partition (92mm Stud):144586',$,'Basic Wall:Interior - Partition (92mm Stud):128360',#5198,#18806,'144586'), #92=IfcWallStandardCase('2O2Fr$t4X7Zf8NOew3FLIE',#1,'Basic Wall:Interior - Partition (92mm Stud):143921',$,'Basic Wall:Interior - Partition (92mm Stud):128360',#5206,#18805,'143921')]
>>> wall = _[0]
>>> len(wall) # number of EXPRESS attributes
8
>>>
>>> # Accessing EXPRESS attributes by name:
>>> wall.GlobalId
'2O2Fr$t4X7Zf8NOew3FL9r'
>>> wall.Name = "My wall"
>>> wall.NonExistingAttr
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File ".\ifcopenshell.py", line 14, in __getattr__
except: raise AttributeError("entity instance of type '%s' has no attribute'%s'"%(self.wrapped_data.is_a(), name)) from None
AttributeError: entity instance of type 'IfcWallStandardCase' has no attribute 'NonExistingAttr'
>>> wall.GlobalId = 3
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File ".\ifcopenshell.py", line 26, in __setattr__
self[self.wrapped_data.get_argument_index(key)] = value
File ".\ifcopenshell.py", line 30, in __setitem__
self.wrapped_data.set_argument(idx, entity_instance.map_value(value))
File ".\ifc_wrapper.py", line 118, in <lambda>
set_argument = lambda self,x,y: self._set_argument(x) if y is None else self
._set_argument(x,y)
File ".\ifc_wrapper.py", line 114, in _set_argument
def _set_argument(self, *args): return _ifc_wrapper.entity_instance__set_argument(self, *args)
RuntimeError: INT is not a valid type for 'GlobalId'
>>> # Creating new entity instances
>>> f.createIfcCartesianPoint(Coordinates=(1.0,1.5,2.0))
#27530=IfcCartesianPoint((1.,1.5,2.))
>>>
>>> # Working with GlobalId attributes:
>>> import uuid
>>> ifcopenshell.guid.compress(uuid.uuid1().hex)
'3x4C8Q_6qHuv$P$FYkANRX'
>>> new_guid = _
>>> owner_hist = f.by_type("IfcOwnerHistory")[0]
>>> new_wall = f.createIfcWallStandardCase(new_guid, owner_hist, None, None, Tag='my_tag')
>>> new_wall.ObjectType = ''
>>> new_wall.ObjectPlacement = new_wall.Representation = None
>>>
>>> # Accessing entity instances by instance id or GlobalId:
>>> f[92]
#92=IfcWallStandardCase('2O2Fr$t4X7Zf8NOew3FLIE',#1,'Basic Wall:Interior - Partition (92mm Stud):143921',$,'Basic Wall:Interior - Partition (92mm Stud):128360',#5206,#18805,'143921')
>>> f['2O2Fr$t4X7Zf8NOew3FLIE']
#92=IfcWallStandardCase('2O2Fr$t4X7Zf8NOew3FLIE',#1,'Basic Wall:Interior - Partition (92mm Stud):143921',$,'Basic Wall:Interior - Partition (92mm Stud):128360',#5206,#18805,'143921')
>>>
>>> # Writing IFC-SPF files to disk:
>>> 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"
[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"
-40
View File
@@ -1,40 +0,0 @@
# Dockerfile for Running AWS Lambda Function with Python and IfcOpenShell
# Base image: Python 3.9 from AWS's public container registry
FROM public.ecr.aws/docker/library/python:3.9 AS build
# Set the location of your Lambda function code
ARG FUNCTION_DIR="/var/task"
# Install necessary packages
RUN apt-get -y update && apt-get -y install unzip curl
# Install AWS Lambda runtime interface client
RUN pip install --target ${FUNCTION_DIR} awslambdaric
# Set the IfcOpenShell build version (check available builds at: https://docs.ifcopenshell.org/ifcopenshell-python/installation.html)
ARG IFC_OPENSHELL_BUILD="39-v0.7.0-476ab50"
# Download and extract IfcOpenShell
RUN curl https://s3.amazonaws.com/ifcopenshell-builds/ifcopenshell-python-${IFC_OPENSHELL_BUILD}-linux64.zip -O && \
unzip ifcopenshell-python-${IFC_OPENSHELL_BUILD}-linux64.zip && \
mv ifcopenshell ${FUNCTION_DIR} && \
rm ifcopenshell-python-${IFC_OPENSHELL_BUILD}-linux64.zip
# Copy the requirements file and install dependencies
COPY requirements.txt .
RUN pip install -r requirements.txt
# Copy the Lambda function code
COPY ./example_handler ${FUNCTION_DIR}/example_handler
# Set the working directory
WORKDIR ${FUNCTION_DIR}
# Set the entrypoint for the Lambda function
ENTRYPOINT [ "/usr/local/bin/python", "-m", "awslambdaric" ]
# Set the Python import path to the Lambda function handler
# This path is relative to the root of the Lambda function code (FUNCTION_DIR)
# Lambda invocation will look for this path
CMD ["example_handler.extract_wall_psets_handler"]
-27
View File
@@ -1,27 +0,0 @@
import ifcopenshell
import ifcopenshell.util.element
import boto3
s3 = boto3.client('s3')
def extract_wall_psets_handler(event, context):
print("Hello from lambda")
print("Event: {}".format(event))
print("Context: {}".format(context))
filename = event['body']['filename']
s3.download_file('my_ifc_files_bucket', filename, f'/tmp/{filename}')
ifc_file = ifcopenshell.open(f'/tmp/{filename}')
walls = ifc_file.by_type('IfcWall')
psets = []
for wall in walls:
wall_data = ifcopenshell.util.element.get_psets(wall)
wall_data['id'] = wall.GlobalId
psets.append(wall_data)
return {
'statusCode': 200,
'body': psets
}
-1
View File
@@ -1 +0,0 @@
boto3
-34
View File
@@ -1,34 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Do not remove this test for UTF-8: if “Ω” doesnt appear as greek uppercase omega letter enclosed in quotation marks, you should use an editor that supports UTF-8, not this one. -->
<package xmlns="http://schemas.microsoft.com/packaging/2015/06/nuspec.xsd">
<metadata>
<id>blenderbim-nightly</id>
<version>blenderbim_build_version-alpha</version>
<packageSourceUrl>https://github.com/IfcOpenShell/IfcOpenShell</packageSourceUrl>
<owners>fbpyr</owners>
<!-- == SOFTWARE SPECIFIC SECTION == -->
<title>BlenderBIM install nightly</title>
<authors>Dion Moult and many more, see: https://github.com/IfcOpenShell/IfcOpenShell/graphs/contributors</authors>
<projectUrl>https://github.com/IfcOpenShell/IfcOpenShell</projectUrl>
<iconUrl>https://rawcdn.githack.com/IfcOpenShell/IfcOpenShell/c6ee1d1679d1298de0d7447ff108c22709c68e54/choco/blenderbim/blenderbim.png</iconUrl>
<!-- <copyright>Year Software Vendor</copyright> -->
<licenseUrl>https://github.com/IfcOpenShell/IfcOpenShell/blob/v0.7.0/COPYING</licenseUrl>
<requireLicenseAcceptance>true</requireLicenseAcceptance>
<projectSourceUrl>https://github.com/IfcOpenShell/IfcOpenShell</projectSourceUrl>
<docsUrl>https://docs.blenderbim.org/</docsUrl>
<!--<mailingListUrl></mailingListUrl>-->
<bugTrackerUrl>https://github.com/IfcOpenShell/IfcOpenShell/issues</bugTrackerUrl>
<tags>blender bim blenderbim ifc python opensource foss</tags>
<summary>opensource bim</summary>
<description>opensource bim addon for blender - source code at: https://github.com/IfcOpenShell/IfcOpenShell</description>
<!-- <releaseNotes>__REPLACE_OR_REMOVE__MarkDown_Okay</releaseNotes> -->
<dependencies>
<dependency id="blender" version="latest_blender_version_maj_min_pat" />
<dependency id="7zip" version="22.1"/>
</dependencies>
</metadata>
<files>
<file src="tools\**" target="tools" />
</files>
</package>
Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

-89
View File
@@ -1,89 +0,0 @@
import datetime
import re
import sys
from urllib import request
def request_repo_info(url: str):
req = request.Request(url)
resp = request.urlopen(req)
if not resp.status == 200:
print(f"[ERROR] could not contact server: {url}")
quit(1)
return resp
def get_choco_package_info() -> str:
resp = request_repo_info(URL_CHOCO_PACKAGE)
html_txt = str(resp.read())
return html_txt
def get_latest_blender_version() -> list:
html_txt = get_choco_package_info()
return re.findall(RE_BLENDER_VERSION_MIN_MAJ_PAT, html_txt)
URL_IFCOS_RELEASES = "https://github.com/IfcOpenShell/IfcOpenShell/releases"
URL_CHOCO_PACKAGE = "https://community.chocolatey.org/packages/blender"
URL_BLENDER_CMAKE = "https://raw.githubusercontent.com/blender/blender/{}/build_files/cmake/Modules/FindPythonLibsUnix.cmake"
RE_BLENDER_VERSION_MIN_MAJ = r"Latest Version.+<span>Blender (\d+\.\d+)\..+</span>"
RE_BLENDER_VERSION_MIN_MAJ_PAT = r"Latest Version.+<span>Blender (\d+\.\d+\.\d+)</span>"
RE_BLENDER_PYTHON_VERSION_MAJ_MIN = r"(?:set|SET)\(_PYTHON_VERSION_SUPPORTED (\d+\.\d+)\)"
if sys.argv[1] == "--do_choco_release?":
now = datetime.datetime.now()
blenderbim_date = (now - datetime.timedelta(days=1)).strftime("%y%m%d")
resp = request_repo_info(URL_IFCOS_RELEASES)
text = str(resp.read())
if blenderbim_date in text:
print("do_choco_release", end="")
elif sys.argv[1] == "--latest_blender_release_maj_min_pat?":
latest_blender_version = get_latest_blender_version()
if latest_blender_version:
print(latest_blender_version[0], end="")
else:
print("[ERROR] could not determine blender_version_min_maj_pat")
quit(1)
elif sys.argv[1] == "--latest_blender_release_maj_min?":
html_txt = get_choco_package_info()
blender_version_min_maj = re.findall(RE_BLENDER_VERSION_MIN_MAJ, html_txt)
if blender_version_min_maj:
print(blender_version_min_maj[0], end="")
else:
print("[ERROR] could not determine blender_version_min_maj")
quit(1)
elif sys.argv[1] == "--latest_blender_python_version_maj_min?":
latest_blender_version = get_latest_blender_version()
if latest_blender_version:
latest_blender_version_tag = f"v{latest_blender_version[0]}"
resp = request_repo_info(URL_BLENDER_CMAKE.format(latest_blender_version_tag))
html_txt = str(resp.read())
found = re.findall(RE_BLENDER_PYTHON_VERSION_MAJ_MIN, html_txt)
if found:
print(found[0], end="")
else:
print("[ERROR] could not determine blender_python_version_maj_min")
quit(1)
elif sys.argv[1] == "--pyver?":
latest_blender_version = get_latest_blender_version()
if latest_blender_version:
latest_blender_version_tag = f"v{latest_blender_version[0]}"
resp = request_repo_info(URL_BLENDER_CMAKE.format(latest_blender_version_tag))
html_txt = str(resp.read())
found = re.findall(RE_BLENDER_PYTHON_VERSION_MAJ_MIN, html_txt)
if found:
print(f"py{found[0].replace('.', '')}", end="")
else:
print("[ERROR] could not determine pyver")
quit(1)
@@ -1,49 +0,0 @@
import os
from pathlib import Path
print("[INFO] inserting dynamic chocolatey package parameters")
HERE_DIR = Path(__file__).parent.absolute()
# print(f"[INFO] HERE_DIR: {HERE_DIR}")
topics = {
"spec": {
"path": HERE_DIR / "blenderbim.nuspec",
"env_vars": {
"latest_blender_version_maj_min_pat",
"blenderbim_build_version",
},
},
"install": {
"path": HERE_DIR / "tools" / "chocolateyinstall.ps1",
"env_vars": {
"url_blenderbim_py310_win_zip",
"sha256sum_blenderbim_py310_win_zip",
"latest_blender_version_maj_min",
},
},
"uninstall": {
"path": HERE_DIR / "tools" / "chocolateyuninstall.ps1",
"env_vars": {
"latest_blender_version_maj_min",
},
},
}
for topic, info in topics.items():
print(f"[INFO] {topic}:")
for env_var_name in info["env_vars"]:
print(f"[INFO] {env_var_name} exists?: {os.environ[env_var_name]}")
with open(info["path"], encoding="utf-8") as txt:
content = txt.read()
for env_var_name in info["env_vars"]:
# print(f"[INFO] replace: {env_var_name}")
content = content.replace(env_var_name, os.environ[env_var_name])
with open(info["path"], "w", encoding="utf-8") as txt:
txt.write(content)
print(f"[INFO] written: {info['path']}")
print("[INFO] inserting dynamic chocolatey package parameters successful")
@@ -1,11 +0,0 @@
$processName = "blender"
$blenderIsRunning = Get-Process -Name $processName -ErrorAction SilentlyContinue
if($blenderIsRunning -eq $null) {
echo "Blender is not running ready for next action."
}
else {
Write-Warning "$processName is still running - installer cannot safely proceed to next action."
Write-Warning "Please retry after closing all running blender applications."
exit 1
}
@@ -1,29 +0,0 @@
$ErrorActionPreference = 'Stop'
$url64 = 'url_blenderbim_py310_win_zip'
$checksum64 = 'sha256sum_blenderbim_py310_win_zip'
$checksumType64 = 'sha256'
$appDataUserDir = [System.Environment]::GetEnvironmentVariable('appdata')
$unzipTargetDir = "$appDataUserDir\Blender Foundation\Blender\latest_blender_version_maj_min\scripts\addons"
$chocoBaseDir = [System.Environment]::GetEnvironmentVariable('ChocolateyInstall')
$addonEnable = "$chocoBaseDir\lib\blenderbim-nightly\tools\enable_blenderbim_addon.py"
$programFilesDir = [System.Environment]::GetEnvironmentVariable('ProgramFiles')
$blenderExePath = "$env:ProgramFiles\Blender Foundation\Blender latest_blender_version_maj_min\blender.exe"
$processName = "blender"
$blenderIsRunning = Get-Process -Name $processName -ErrorAction SilentlyContinue
if($blenderIsRunning -eq $null) {
echo "attempting to install blenderbim."
Install-ChocolateyZipPackage -PackageName $env:ChocolateyPackageName -Url64 $url64 -Checksum64 $checksum64 -checksumType $checksumType64 -UnzipLocation $unzipTargetDir
Start-Process -FilePath $blenderExePath -ArgumentList "-b", "-y", "--python", "$addonEnable"
}
else {
Write-Warning "$processName is still running - blenderbim cannot be safely installed."
Write-Warning "Please retry after closing all running blender applications."
exit 1
}
@@ -1,22 +0,0 @@
$appDataUserDir = [System.Environment]::GetEnvironmentVariable('appdata')
$unzippedDir = "$appDataUserDir\Blender Foundation\Blender\latest_blender_version_maj_min\scripts\addons\blenderbim"
$chocoBaseDir = [System.Environment]::GetEnvironmentVariable('ChocolateyInstall')
$addonDisable = "$chocoBaseDir\lib\blenderbim-nightly\tools\disable_blenderbim_addon.py"
$programFilesDir = [System.Environment]::GetEnvironmentVariable('ProgramFiles')
$blenderExePath = "$env:ProgramFiles\Blender Foundation\Blender latest_blender_version_maj_min\blender.exe"
$processName = "blender"
$blenderIsRunning = Get-Process -Name $processName -ErrorAction SilentlyContinue
if($blenderIsRunning -eq $null) {
echo "attempting to uninstall blenderbim."
Start-Process -FilePath $blenderExePath -ArgumentList "-b", "-y", "--python", "$addonDisable"
Remove-Item -LiteralPath $unzippedDir -Force -Recurse
}
else {
Write-Warning "$processName is still running - blenderbim cannot be safely uninstalled."
Write-Warning "Please retry after closing all running blender applications."
exit 1
}
@@ -1,8 +0,0 @@
import bpy
bpy.ops.preferences.addon_disable(module='blenderbim')
bpy.ops.wm.save_userpref()
print("disabled blenderbim addon successfully.")
@@ -1,8 +0,0 @@
import bpy
bpy.ops.preferences.addon_enable(module='blenderbim')
bpy.ops.wm.save_userpref()
print("enabled blenderbim addon successfully.")
+526 -907
View File
File diff suppressed because it is too large Load Diff
-43
View File
@@ -1,43 +0,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/>. #
# #
################################################################################
if(NOT EXISTS "@CMAKE_BINARY_DIR@/install_manifest.txt")
message(FATAL_ERROR "Cannot find install manifest: @CMAKE_BINARY_DIR@/install_manifest.txt")
endif()
file(READ "@CMAKE_BINARY_DIR@/install_manifest.txt" files)
string(REGEX REPLACE "\n" ";" files "${files}")
foreach(file ${files})
message(STATUS "Uninstalling $ENV{DESTDIR}${file}")
if(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
exec_program(
"@CMAKE_COMMAND@" ARGS "-E remove \"$ENV{DESTDIR}${file}\""
OUTPUT_VARIABLE rm_out
RETURN_VALUE rm_retval
)
if(NOT "${rm_retval}" STREQUAL 0)
message(FATAL_ERROR "Problem when removing $ENV{DESTDIR}${file}")
endif()
else(IS_SYMLINK "$ENV{DESTDIR}${file}" OR EXISTS "$ENV{DESTDIR}${file}")
message(STATUS "File $ENV{DESTDIR}${file} does not exist.")
endif()
endforeach()
+21 -37
View File
@@ -1,45 +1,29 @@
mkdir build && cd build
REM Remove dot from PY_VER for use in library name
REM From https://github.com/tpaviot/pythonocc-core/blob/master/ci/conda/bld.bat
set MY_PY_VER=%PY_VER:.=%
set LIBXML2="%LIBRARY_PREFIX%/lib/libxml2.lib"
cmake -G "Ninja" ^
-D SCHEMA_VERSIONS="2x3;4;4x1;4x3;4x3_add1" ^
-D CMAKE_BUILD_TYPE:STRING=Release ^
-D CMAKE_INSTALL_PREFIX:FILEPATH="%LIBRARY_PREFIX%" ^
-D CMAKE_PREFIX_PATH:FILEPATH="%LIBRARY_PREFIX%" ^
-D CMAKE_SYSTEM_PREFIX_PATH:FILEPATH="%LIBRARY_PREFIX%" ^
-D OCC_INCLUDE_DIR:FILEPATH="%LIBRARY_PREFIX%\include\opencascade" ^
-D OCC_LIBRARY_DIR:FILEPATH="%LIBRARY_PREFIX%\lib" ^
-D CGAL_INCLUDE_DIR:FILEPATH="%LIBRARY_PREFIX%\include" ^
-D GMP_INCLUDE_DIR:FILEPATH="%LIBRARY_PREFIX%\include" ^
-D GMP_LIBRARY_DIR:FILEPATH="%LIBRARY_PREFIX%\lib" ^
-D MPFR_LIBRARY_DIR:FILEPATH="%LIBRARY_PREFIX%\lib" ^
-D COLLADA_SUPPORT=OFF ^
-D HDF5_SUPPORT=ON ^
-D HDF5_INCLUDE_DIR="%LIBRARY_PREFIX%\include" ^
-D HDF5_LIBRARY_DIR="%LIBRARY_PREFIX%\lib" ^
-D JSON_INCLUDE_DIR="%LIBRARY_PREFIX%\include" ^
-D PYTHON_INCLUDE_DIR=%PREFIX%\include ^
-D PYTHON_EXECUTABLE:FILEPATH=%PREFIX%\python.exe ^
-D PYTHON_LIBRARY:FILEPATH="%PREFIX%"\libs/python%MY_PY_VER%.lib ^
-D BUILD_IFCPYTHON=ON ^
-D BUILD_IFCGEOM=ON ^
-D COLLADA_SUPPORT:BOOL=OFF ^
-D BUILD_EXAMPLES:BOOL=OFF ^
-D BUILD_GEOMSERVER:BOOL=OFF ^
-D GLTF_SUPPORT:BOOL=ON ^
-D BUILD_CONVERT:BOOL=ON ^
-D BUILD_IFCMAX:BOOL=OFF ^
-D IFCXML_SUPPORT:BOOL=ON ^
-D Boost_LIBRARYDIR:FILEPATH="%LIBRARY_PREFIX%\lib" ^
-D Boost_INCLUDEDIR:FILEPATH="%LIBRARY_PREFIX%\include" ^
-D Boost_USE_STATIC_LIBS:BOOL=OFF ^
%SRC_DIR%/cmake
cmake -G "NMake Makefiles" ^
-DCMAKE_INSTALL_PREFIX="%LIBRARY_PREFIX%" ^
-DCMAKE_BUILD_TYPE=Release ^
-DCMAKE_PREFIX_PATH="%LIBRARY_PREFIX%" ^
-DCMAKE_SYSTEM_PREFIX_PATH="%LIBRARY_PREFIX%" ^
-DPYTHON_EXECUTABLE="%PYTHON%" ^
-DPYTHON_INCLUDE_DIR="%PREFIX%"/include ^
-DPYTHON_LIBRARY="%PREFIX%"/libs/python%MY_PY_VER%.lib ^
-DBOOST_LIBRARYDIR="%LIBRARY_PREFIX%\lib" ^
-DBOOST_INCLUDEDIR="%LIBRARY_PREFIX%\include" ^
-DOCC_INCLUDE_DIR="%LIBRARY_PREFIX%\include\oce" ^
-DOCC_LIBRARY_DIR="%LIBRARY_PREFIX%\lib" ^
-DCOLLADA_SUPPORT=Off ^
-DBUILD_EXAMPLES=Off ^
-DBUILD_GEOMSERVER=Off ^
-DBUILD_CONVERT=Off ^
../cmake
if errorlevel 1 exit 1
:: Build and install
cmake --build . -- install
cmake --build . --target INSTALL --config Release
if errorlevel 1 exit 1
+24 -35
View File
@@ -1,45 +1,34 @@
#!/bin/bash
declare -a CMAKE_PLATFORM_FLAGS
if [[ ${HOST} =~ .*linux.* ]]; then
CMAKE_PLATFORM_FLAGS+=(-DCMAKE_TOOLCHAIN_FILE=$RECIPE_DIR/cross-linux.cmake)
# From https://github.com/tpaviot/pythonocc-core/blob/master/ci/conda/build.sh
if [ "$PY3K" == "1" ]; then
MY_PY_VER="${PY_VER}m"
else
MY_PY_VER="${PY_VER}"
fi
if [ `uname` == Darwin ]; then
export CFLAGS="$CFLAGS -Wl,-flat_namespace,-undefined,suppress"
export CXXFLAGS="$CXXFLAGS -Wl,-flat_namespace,-undefined,suppress"
export LDFLAGS="$LDFLAGS -Wl,-flat_namespace,-undefined,suppress"
PY_LIB="libpython${MY_PY_VER}.dylib"
export CFLAGS="$CFLAGS -Wl,-flat_namespace,-undefined,suppress"
export CXXFLAGS="$CXXFLAGS -Wl,-flat_namespace,-undefined,suppress"
export LDFLAGS="$LDFLAGS -Wl,-flat_namespace,-undefined,suppress"
else
PY_LIB="libpython${MY_PY_VER}.so"
fi
cmake -G Ninja \
-DSCHEMA_VERSIONS="2x3;4;4x1;4x3;4x3_add1" \
-DCMAKE_BUILD_TYPE=Release \
mkdir build && cd build
cmake \
-DCMAKE_INSTALL_PREFIX=$PREFIX \
${CMAKE_PLATFORM_FLAGS[@]} \
-DCMAKE_BUILD_TYPE=Release \
-DCMAKE_PREFIX_PATH=$PREFIX \
-DCMAKE_SYSTEM_PREFIX_PATH=$PREFIX \
-DPYTHON_EXECUTABLE:FILEPATH=$PYTHON \
-DGMP_LIBRARY_DIR=$PREFIX/lib \
-DMPFR_LIBRARY_DIR=$PREFIX/lib \
-DOCC_INCLUDE_DIR=$PREFIX/include/opencascade \
-DOCC_INCLUDE_DIR=$PREFIX/include/oce \
-DOCC_LIBRARY_DIR=$PREFIX/lib \
-DHDF5_SUPPORT:BOOL=ON \
-DHDF5_INCLUDE_DIR=$PREFIX/include \
-DHDF5_LIBRARY_DIR=$PREFIX/lib \
-DJSON_INCLUDE_DIR=$PREFIX/include \
-DCGAL_INCLUDE_DIR=$PREFIX/include \
-DCOLLADA_SUPPORT=0 \
-DBUILD_EXAMPLES:BOOL=OFF \
-DIFCXML_SUPPORT:BOOL=ON \
-DGLTF_SUPPORT:BOOL=ON \
-DBUILD_CONVERT:BOOL=ON \
-DBUILD_IFCPYTHON:BOOL=ON \
-DBUILD_IFCGEOM:BOOL=ON \
-DBUILD_GEOMSERVER:BOOL=OFF \
-DBOOST_USE_STATIC_LIBS:BOOL=OFF \
./cmake
-DPYTHON_EXECUTABLE:FILEPATH=$PYTHON \
-DPYTHON_INCLUDE_DIR:PATH=$PREFIX/include/python$MY_PY_VER \
-DPYTHON_LIBRARY:FILEPATH=$PREFIX/lib/${PY_LIB} \
-DCOLLADA_SUPPORT=Off \
../cmake
ninja
ninja install -j 1
make -j$CPU_COUNT _ifcopenshell_wrapper
cd ifcwrap
make install/local
-6
View File
@@ -1,6 +0,0 @@
CONDA_BUILD_SYSROOT:
- /opt/MacOSX10.13.sdk # [osx]
variant:
- novtk
- all
-16
View File
@@ -1,16 +0,0 @@
# this one is important
set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_PLATFORM Linux)
# specify the cross compiler
set(CMAKE_C_COMPILER $ENV{CC})
set(CMAKE_CXX_COMPILER $ENV{CXX})
# where is the target environment
set(CMAKE_FIND_ROOT_PATH $ENV{PREFIX} $ENV{BUILD_PREFIX}/$ENV{HOST}/sysroot)
# search for programs in the build host directories
set(CMAKE_FIND_ROOT_PATH_MODE_PROGRAM NEVER)
# for libraries and headers in the target directories
set(CMAKE_FIND_ROOT_PATH_MODE_LIBRARY ONLY)
set(CMAKE_FIND_ROOT_PATH_MODE_INCLUDE ONLY)
+23 -55
View File
@@ -1,68 +1,36 @@
{% set name = "ifcopenshell" %}
{% set version = "0.7.0" %}
{% set build = 1 %}
# Higher number -> Always prioritize "novtk" variant over "all" variant
{% set build = build + 200 %} # [variant == "novtk"]
{% set build = build + 100 %} # [variant == "all"]
package:
name: {{ name }}
version: {{ version }}
name: ifcopenshell
version: "0.6.0a1"
source:
path: ..
git_rev: "v0.6.0a1"
git_url: https://github.com/IfcOpenShell/IfcOpenShell
build:
string: py{{ CONDA_PY }}_{{ variant }}_h{{ PKG_HASH }}_{{ build }}
binary_relocation: false [osx]
number: {{ build }}
number: 0
features:
- vc9 # [win and py27]
- vc10 # [win and py34]
- vc14 # [win and py35]
- vc14 # [win and py36]
requirements:
build:
- {{ compiler('c') }}
- {{ compiler('cxx') }}
- ninja >=1.10.2
- gcc # [osx]
- make
- python
- oce ==0.18.3
- cmake
- swig 4.1.1
host:
- python
- boost-cpp
- occt 7.7.2 *{{ variant }}*
- libxml2
- cgal-cpp
- hdf5
- mpfr
- gmp # [unix]
- mpir # [win]
- nlohmann_json
- zlib
- swig >=3.0.9
- libboost
- icu
run:
- libgcc # [osx]
- python
- occt 7.7.2 *{{ variant }}*
- {{ pin_compatible('cgal-cpp', max_pin='x.x.x') }}
- {{ pin_compatible('boost-cpp', max_pin='x.x.x') }}
- {{ pin_compatible('hdf5', max_pin='x.x.x') }}
- libxml2
- mpfr
- gmp # [unix]
- mpir # [win]
- nlohmann_json
- zlib
test:
imports:
- ifcopenshell
- oce ==0.18.3
- libboost
- icu
about:
home: https://ifcopenshell.org
license: LGPL-3.0-or-later
license_file: COPYING
summary: 'IfcOpenShell is a library to support the IFC file format'
description: |
IfcOpenShell is an open source (LGPL) software library for
working with the Industry Foundation Classes (IFC) file format.
doc_url: https://ifcopenshell.org/
dev_url: https://github.com/IfcOpenShell/IfcOpenShell
home: http://ifcopenshell.org
license: LGPL
-37
View File
@@ -1,37 +0,0 @@
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 C++",
"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
}
cpp_id_attributes = ['IFC_PARSE_API', 'IFC_GEOM_API']
-10
View File
@@ -1,10 +0,0 @@
IfcOpenShell
============
.. toctree::
:maxdepth: 3
rst_files/library_root
* `ifcopenshell-python documentation <python/html/index.html>`_
-40
View File
@@ -1,40 +0,0 @@
#Look for an executable called sphinx-build
find_program(SPHINX_EXECUTABLE
NAMES sphinx-build
DOC "Path to sphinx-build executable")
include(FindPackageHandleStandardArgs)
#Handle standard arguments to find_package like REQUIRED and QUIET
find_package_handle_standard_args(Sphinx
"Failed to find sphinx-build executable"
SPHINX_EXECUTABLE)
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)
File diff suppressed because it is too large Load Diff
-33
View File
@@ -1,33 +0,0 @@
# IfcOpenShell C++ API documentation
This folder contains the setup to build the IfcOpenShell C++ API documentation from the source code.
## Generating the documentation
> Prerequisites:
>
> Make sure to have [Doxygen](https://www.doxygen.nl) and [Graphviz](https://graphviz.org) installed into your `$PATH` variable.
>
> The documentation also use the [doxygen-awesome](https://jothepro.github.io/doxygen-awesome-css) theme as a git submodule.
Build with the command (from within the `/docs/cpp-api` folder):
```shell
$ doxygen
```
To include the current git commit hash into the build documentation, use the following command:
```shell
$ PROJECT_NUMBER=$(git rev-parse --short HEAD) doxygen
```
This will extract the current commit hash in short version and sets the propper ENV variable used by doxygen.
The generation of the documentation might take a while depending on your systems hardware, as it is configured to generate the Class graphs using .
The resulting documentation is located unter `/cpp-api/output/html` and can be directly accessed with your browser:
```shell
$ open ./output/html/index.html
```
-39
View File
@@ -1,39 +0,0 @@
# This program requires doxygen, sphinx, breathe and exhale.
import os
import sys
import shutil
import subprocess
import multiprocessing
# some extra check to see if we can find sphinx in pypy bin dir
sphinx_build = os.path.join(os.path.dirname(sys.executable), 'sphinx-build')
if not os.path.exists(sphinx_build):
sphinx_build = "sphinx-build"
# else:
# os.environ['PATH'] = os.pathsep + os.path.dirname(sys.executable)
# not used, -j caused issues in my sphinx install
j = str(multiprocessing.cpu_count())
if not os.path.isdir("./output/doxygen/xml"):
os.makedirs("output/doxygen/xml")
subprocess.check_call([sphinx_build, "-b", "html", ".", "output"])
if sys.platform == "linux" or sys.platform == "linux2":
if os.path.isdir("output/python"):
shutil.rmtree("output/python")
if not os.path.exists(os.path.join("../src/ifcblenderexport/docs", "contents.rst")):
subprocess.check_call(["ln", "index.rst", "contents.rst"], cwd="../src/ifcblenderexport/docs")
subprocess.check_call(["sed", "-i", "s/html_theme/# html_theme/g", "conf.py"], cwd="../src/ifcblenderexport/docs")
subprocess.check_call(["make", "html"], cwd="../src/ifcblenderexport/docs")
subprocess.check_call(["git", "checkout", "conf.py"], cwd="../src/ifcblenderexport/docs")
shutil.move("../src/ifcblenderexport/docs/_build", "./output")
os.rename("./output/_build", "./output/python")
elif sys.platform == "win32" or sys.platform == "win64":
subprocess.check_call(["make.bat", "html"])
-10
View File
@@ -1,10 +0,0 @@
IfcOpenShell
============
.. toctree::
:maxdepth: 3
rst_files/library_root
* `ifcopenshell-python documentation <python/html/index.html>`_
+392 -505
View File
File diff suppressed because it is too large Load Diff
-20
View File
@@ -1,20 +0,0 @@
--- a/tools/build/src/tools/emscripten.jam
+++ b/tools/build/src/tools/emscripten.jam
@@ -6,6 +6,7 @@
import feature ;
import os ;
import toolset ;
+import generators ;
import common ;
import gcc ;
import type ;
@@ -52,6 +53,8 @@
<debug-symbols>off <debug-symbols>on
<rtti>off <rtti>on
;
+generators.override builtin.lib-generator : emscripten.prebuilt ;
+generators.override emscripten.searched-lib-generator : searched-lib-generator ;
type.set-generated-target-suffix EXE : <toolset>emscripten : "js" ;
type.set-generated-target-suffix OBJ : <toolset>emscripten : "bc" ;
-99
View File
@@ -1,99 +0,0 @@
diff --git a/src/Message/Message_PrinterSystemLog.cxx b/src/Message/Message_PrinterSystemLog.cxx
index 0c82c2167..a2e9e6d68 100644
--- a/src/Message/Message_PrinterSystemLog.cxx
+++ b/src/Message/Message_PrinterSystemLog.cxx
@@ -55,27 +55,6 @@
return ANDROID_LOG_DEBUG;
}
#elif defined(__EMSCRIPTEN__)
- #include <emscripten/emscripten.h>
-
- //! Print message to console.debug().
- EM_JS(void, occJSConsoleDebug, (const char* theStr), {
- console.debug(UTF8ToString(theStr));
- });
-
- //! Print message to console.info().
- EM_JS(void, occJSConsoleInfo, (const char* theStr), {
- console.info(UTF8ToString(theStr));
- });
-
- //! Print message to console.warn().
- EM_JS(void, occJSConsoleWarn, (const char* theStr), {
- console.warn(UTF8ToString(theStr));
- });
-
- //! Print message to console.error().
- EM_JS(void, occJSConsoleError, (const char* theStr), {
- console.error(UTF8ToString(theStr));
- });
#else
#include <syslog.h>
@@ -169,16 +148,6 @@ void Message_PrinterSystemLog::send (const TCollection_AsciiString& theString,
#elif defined(__ANDROID__)
__android_log_write (getAndroidLogPriority (theGravity), myEventSourceName.ToCString(), theString.ToCString());
#elif defined(__EMSCRIPTEN__)
- // don't use bogus emscripten_log() corrupting UNICODE strings
- switch (theGravity)
- {
- case Message_Trace: occJSConsoleDebug(theString.ToCString()); return;
- case Message_Info: occJSConsoleInfo (theString.ToCString()); return;
- case Message_Warning: occJSConsoleWarn (theString.ToCString()); return;
- case Message_Alarm: occJSConsoleError(theString.ToCString()); return;
- case Message_Fail: occJSConsoleError(theString.ToCString()); return;
- }
- occJSConsoleWarn (theString.ToCString());
#else
syslog (getSysLogPriority (theGravity), "%s", theString.ToCString());
#endif
diff --git a/src/OSD/OSD_MemInfo.cxx b/src/OSD/OSD_MemInfo.cxx
index 08a939beb..7c1fc79b3 100644
--- a/src/OSD/OSD_MemInfo.cxx
+++ b/src/OSD/OSD_MemInfo.cxx
@@ -37,15 +37,6 @@
#include <OSD_MemInfo.hxx>
-#if defined(__EMSCRIPTEN__)
- #include <emscripten.h>
-
- //! Return WebAssembly heap size in bytes.
- EM_JS(size_t, OSD_MemInfo_getModuleHeapLength, (), {
- return Module.HEAP8.length;
- });
-#endif
-
// =======================================================================
// function : OSD_MemInfo
// purpose :
@@ -156,29 +147,6 @@ void OSD_MemInfo::Update()
}
#elif defined(__EMSCRIPTEN__)
- if (IsActive (MemHeapUsage)
- || IsActive (MemWorkingSet)
- || IsActive (MemWorkingSetPeak))
- {
- // /proc/%d/status is not emulated - get more info from mallinfo()
- const struct mallinfo aMI = mallinfo();
- if (IsActive (MemHeapUsage))
- {
- myCounters[MemHeapUsage] = aMI.uordblks;
- }
- if (IsActive (MemWorkingSet))
- {
- myCounters[MemWorkingSet] = aMI.uordblks;
- }
- if (IsActive (MemWorkingSetPeak))
- {
- myCounters[MemWorkingSetPeak] = aMI.usmblks;
- }
- }
- if (IsActive (MemVirtual))
- {
- myCounters[MemVirtual] = OSD_MemInfo_getModuleHeapLength();
- }
#elif (defined(__linux__) || defined(__linux))
if (IsActive (MemHeapUsage))
{
@@ -1,29 +0,0 @@
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>
-81
View File
@@ -1,81 +0,0 @@
diff --git a/COLLADABaseUtils/include/COLLADABUhash_map.h b/COLLADABaseUtils/include/COLLADABUhash_map.h
index 8ab0fb9b..12503bfb 100644
--- a/COLLADABaseUtils/include/COLLADABUhash_map.h
+++ b/COLLADABaseUtils/include/COLLADABUhash_map.h
@@ -32,9 +32,9 @@
#include <unordered_map>
#include <unordered_set>
- #define COLLADABU_HASH_MAP std::tr1::unordered_map
- #define COLLADABU_HASH_MULTIMAP std::tr1::unordered_multimap
- #define COLLADABU_HASH_SET std::tr1::unordered_set
+ #define COLLADABU_HASH_MAP std::unordered_map
+ #define COLLADABU_HASH_MULTIMAP std::unordered_multimap
+ #define COLLADABU_HASH_SET std::unordered_set
#define COLLADABU_HASH_NAMESPACE_OPEN std { namespace tr1
#define COLLADABU_HASH_NAMESPACE_CLOSE }
#define COLLADABU_HASH_FUN hash
@@ -50,12 +50,12 @@
#define COLLADABU_HASH_FUN hash
#endif
#elif defined(__MINGW32__) || defined(__MINGW64__)
- #include <tr1/unordered_map>
- #include <tr1/unordered_set>
+ #include <unordered_map>
+ #include <unordered_set>
- #define COLLADABU_HASH_MAP std::tr1::unordered_map
- #define COLLADABU_HASH_MULTIMAP std::tr1::unordered_multimap
- #define COLLADABU_HASH_SET std::tr1::unordered_set
+ #define COLLADABU_HASH_MAP std::unordered_map
+ #define COLLADABU_HASH_MULTIMAP std::unordered_multimap
+ #define COLLADABU_HASH_SET std::unordered_set
#define COLLADABU_HASH_NAMESPACE_OPEN std { namespace tr1
#define COLLADABU_HASH_NAMESPACE_CLOSE }
#define COLLADABU_HASH_FUN hash
@@ -107,12 +107,12 @@
#define COLLADABU_HASH_NAMESPACE_CLOSE
#define COLLADABU_HASH_FUN hash
#else
- #include <tr1/unordered_map>
- #include <tr1/unordered_set>
+ #include <unordered_map>
+ #include <unordered_set>
- #define COLLADABU_HASH_MAP std::tr1::unordered_map
- #define COLLADABU_HASH_MULTIMAP std::tr1::unordered_multimap
- #define COLLADABU_HASH_SET std::tr1::unordered_set
+ #define COLLADABU_HASH_MAP std::unordered_map
+ #define COLLADABU_HASH_MULTIMAP std::unordered_multimap
+ #define COLLADABU_HASH_SET std::unordered_set
#define COLLADABU_HASH_NAMESPACE_OPEN std { namespace tr1
#define COLLADABU_HASH_NAMESPACE_CLOSE }
#define COLLADABU_HASH_FUN hash
diff --git a/common/libBuffer/include/CommonFWriteBufferFlusher.h b/common/libBuffer/include/CommonFWriteBufferFlusher.h
index c7af45b2..fac4f133 100644
--- a/common/libBuffer/include/CommonFWriteBufferFlusher.h
+++ b/common/libBuffer/include/CommonFWriteBufferFlusher.h
@@ -15,12 +15,12 @@
#if (defined(WIN64) || defined(_WIN64) || defined(__WIN64__)) || (defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) || defined(__APPLE__))
#if defined(__GNUC__) && !defined(_LIBCPP_VERSION)
-# include <tr1/unordered_map>
+# include <unordered_map>
#else
# include <unordered_map>
#endif
#else
-# include <tr1/unordered_map>
+# include <unordered_map>
#endif
#ifdef _LIBCPP_VERSION
@@ -58,7 +58,7 @@ namespace Common
#else
typedef __int64 FilePosType;
#endif
- typedef std::tr1::unordered_map<MarkId, FilePosType > MarkIdToFilePos;
+ typedef std::unordered_map<MarkId, FilePosType > MarkIdToFilePos;
public:
static const size_t DEFAUL_BUFFER_SIZE = 64*1024;
-22
View File
@@ -1,22 +0,0 @@
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>
-18
View File
@@ -1,18 +0,0 @@
package:
name: ifcopenshell
version: 0.7.0
source:
path: IfcOpenShell
build:
script: |
python nix/build-all.py --without-hdf5 --without-opencollada --without-swig --without-pcre -v --wasm --py310 IfcOpenShell-Python
cp pyodide/setup.py .
about:
home: http://ifcopenshell.org
license: LGPL-3.0-or-later
summary: |
IfcOpenShell is an open source (LGPL) software library for
working with the Industry Foundation Classes (IFC) file format.
-11
View File
@@ -1,11 +0,0 @@
from setuptools import setup, find_packages
setup(name='IfcOpenShell',
version='0.7.0',
description='IfcOpenShell is an open source (LGPL) software library for working with the Industry Foundation Classes (IFC) file format.',
author='Thomas Krijnen',
author_email='thomas@aecgeeks.com',
url='http://ifcopenshell.org',
packages=find_packages(),
package_data={'': ['*.so']},
)
-2
View File
@@ -1,2 +0,0 @@
[tool.black]
line-length = 120
-64
View File
@@ -1,64 +0,0 @@
# ****************************************************************************
# 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 .
-1
View File
@@ -1 +0,0 @@
.tox
-20
View File
@@ -1,20 +0,0 @@
# This CITATION.cff file was generated with cffinit.
# Visit https://bit.ly/cffinit to generate yours today!
cff-version: 1.2.0
title: bcf
message: >-
If you use this software, please cite it using the
metadata from this file.
type: software
authors:
- name: "IfcOpenShell contributors"
repository-code: >-
https://github.com/IfcOpenShell/IfcOpenShell/tree/v0.7.0/src/bcf
abstract: >-
Library to read and write BCF-XML and query OpenCDE
BCF-API modules
keywords:
- BCF
- IFC
license: LGPL-3.0-or-later
-621
View File
@@ -1,621 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
-165
View File
@@ -1,165 +0,0 @@
GNU LESSER GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <https://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
This version of the GNU Lesser General Public License incorporates
the terms and conditions of version 3 of the GNU General Public
License, supplemented by the additional permissions listed below.
0. Additional Definitions.
As used herein, "this License" refers to version 3 of the GNU Lesser
General Public License, and the "GNU GPL" refers to version 3 of the GNU
General Public License.
"The Library" refers to a covered work governed by this License,
other than an Application or a Combined Work as defined below.
An "Application" is any work that makes use of an interface provided
by the Library, but which is not otherwise based on the Library.
Defining a subclass of a class defined by the Library is deemed a mode
of using an interface provided by the Library.
A "Combined Work" is a work produced by combining or linking an
Application with the Library. The particular version of the Library
with which the Combined Work was made is also called the "Linked
Version".
The "Minimal Corresponding Source" for a Combined Work means the
Corresponding Source for the Combined Work, excluding any source code
for portions of the Combined Work that, considered in isolation, are
based on the Application, and not on the Linked Version.
The "Corresponding Application Code" for a Combined Work means the
object code and/or source code for the Application, including any data
and utility programs needed for reproducing the Combined Work from the
Application, but excluding the System Libraries of the Combined Work.
1. Exception to Section 3 of the GNU GPL.
You may convey a covered work under sections 3 and 4 of this License
without being bound by section 3 of the GNU GPL.
2. Conveying Modified Versions.
If you modify a copy of the Library, and, in your modifications, a
facility refers to a function or data to be supplied by an Application
that uses the facility (other than as an argument passed when the
facility is invoked), then you may convey a copy of the modified
version:
a) under this License, provided that you make a good faith effort to
ensure that, in the event an Application does not supply the
function or data, the facility still operates, and performs
whatever part of its purpose remains meaningful, or
b) under the GNU GPL, with none of the additional permissions of
this License applicable to that copy.
3. Object Code Incorporating Material from Library Header Files.
The object code form of an Application may incorporate material from
a header file that is part of the Library. You may convey such object
code under terms of your choice, provided that, if the incorporated
material is not limited to numerical parameters, data structure
layouts and accessors, or small macros, inline functions and templates
(ten or fewer lines in length), you do both of the following:
a) Give prominent notice with each copy of the object code that the
Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the object code with a copy of the GNU GPL and this license
document.
4. Combined Works.
You may convey a Combined Work under terms of your choice that,
taken together, effectively do not restrict modification of the
portions of the Library contained in the Combined Work and reverse
engineering for debugging such modifications, if you also do each of
the following:
a) Give prominent notice with each copy of the Combined Work that
the Library is used in it and that the Library and its use are
covered by this License.
b) Accompany the Combined Work with a copy of the GNU GPL and this license
document.
c) For a Combined Work that displays copyright notices during
execution, include the copyright notice for the Library among
these notices, as well as a reference directing the user to the
copies of the GNU GPL and this license document.
d) Do one of the following:
0) Convey the Minimal Corresponding Source under the terms of this
License, and the Corresponding Application Code in a form
suitable for, and under terms that permit, the user to
recombine or relink the Application with a modified version of
the Linked Version to produce a modified Combined Work, in the
manner specified by section 6 of the GNU GPL for conveying
Corresponding Source.
1) Use a suitable shared library mechanism for linking with the
Library. A suitable mechanism is one that (a) uses at run time
a copy of the Library already present on the user's computer
system, and (b) will operate properly with a modified version
of the Library that is interface-compatible with the Linked
Version.
e) Provide Installation Information, but only if you would otherwise
be required to provide such information under section 6 of the
GNU GPL, and only to the extent that such information is
necessary to install and execute a modified version of the
Combined Work produced by recombining or relinking the
Application with a modified version of the Linked Version. (If
you use option 4d0, the Installation Information must accompany
the Minimal Corresponding Source and Corresponding Application
Code. If you use option 4d1, you must provide the Installation
Information in the manner specified by section 6 of the GNU GPL
for conveying Corresponding Source.)
5. Combined Libraries.
You may place library facilities that are a work based on the
Library side by side in a single library together with other library
facilities that are not Applications and are not covered by this
License, and convey such a combined library under terms of your
choice, if you do both of the following:
a) Accompany the combined library with a copy of the same work based
on the Library, uncombined with any other library facilities,
conveyed under the terms of this License.
b) Give prominent notice with the combined library that part of it
is a work based on the Library, and explaining where to find the
accompanying uncombined form of the same work.
6. Revised Versions of the GNU Lesser General Public License.
The Free Software Foundation may publish revised and/or new versions
of the GNU Lesser General Public License from time to time. Such new
versions will be similar in spirit to the present version, but may
differ in detail to address new problems or concerns.
Each version is given a distinguishing version number. If the
Library as you received it specifies that a certain numbered version
of the GNU Lesser General Public License "or any later version"
applies to it, you have the option of following the terms and
conditions either of that published version or of any later version
published by the Free Software Foundation. If the Library as you
received it does not specify a version number of the GNU Lesser
General Public License, you may choose any version of the GNU Lesser
General Public License ever published by the Free Software Foundation.
If the Library as you received it specifies that a proxy can decide
whether future versions of the GNU Lesser General Public License shall
apply, that proxy's public statement of acceptance of any version is
permanent authorization for you to choose that version for the
Library.
-2
View File
@@ -1,2 +0,0 @@
include src/bcf/v2/xsd/*.xsd
include src/bcf/v3/xsd/*.xsd
-30
View File
@@ -1,30 +0,0 @@
VERSION:=`date '+%y%m%d'`
SED:=sed -i
ifeq ($(UNAME_S),Darwin)
SED:=sed -i '' -e
endif
.PHONY: ci
ci:
tox
.PHONY: license
license:
copyright-header --license LGPL3 --copyright-holder "Andrea Ghensi <andrea.ghensi@gmail.com>" --copyright-year "2022" --copyright-software "IfcOpenShell" --copyright-software-description "BCF XML file handling" -a ./ -o ./
# TODO: make this based on xsd file presence
.PHONY: models
models:
cd src && xsdata generate -p bcf.v2.model --unnest-classes --kw-only --slots -ds Google bcf/v2/xsd
cd src && xsdata generate -p bcf.v3.model --unnest-classes --kw-only --slots -ds Google bcf/v3/xsd
.PHONY: dist
dist:
rm -rf dist
$(SED) "s/999999/$(VERSION)/" pyproject.toml
python -m build
$(SED) "s/$(VERSION)/999999/" pyproject.toml
# .PHONY
# api:
# openapi-python-client generate --url https://api.swaggerhub.com/apis/buildingSMART/BCF/3.0
-5
View File
@@ -1,5 +0,0 @@
# bcf
A simple Python implementation of the BCF standard. Manipulation of BCF-XML is
available via `bcfxml.py` and manipulation of BCF-API is available via
`bcfapi.py`.
-141
View File
@@ -1,141 +0,0 @@
[build-system]
requires = [
"setuptools>=61",
"wheel"
]
build-backend = "setuptools.build_meta"
[project]
name = "bcf-client"
# author = "IfcOpenShell"
description = "BCF-XML file handler."
readme = "README.md"
requires-python = ">=3.8"
keywords = ["IFC", "BCF", "BIM"]
dependencies = [
"xsdata",
"numpy",
"ifcopenshell",
]
version = "0.0.999999"
classifiers = [
"License :: OSI Approved :: GNU General Public License v3 (GPLv3)",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Topic :: Scientific/Engineering",
"Topic :: Utilities",
]
[project.urls]
Source = "https://github.com/IfcOpenShell/IfcOpenShell"
Issues = "https://github.com/IfcOpenShell/IfcOpenShell/issues"
[tool.black]
line-length = 120
extend-exclude = "model"
[tool.isort]
profile = "black"
extend_skip_glob = ["src/bcf/*/model/*"]
[tool.coverage.paths]
source = ["src"]
[tool.coverage.run]
branch = true
source = ["bcf"]
omit = ["*/model/*"]
[tool.coverage.report]
show_missing = true
fail_under = 65
exclude_lines = [
"pragma: no cover",
"if TYPE_CHECKING",
"if __name__ == .__main__.:",
"Protocol",
]
[tool.tox]
legacy_tox_ini = """
[tox]
env_list = lint, type, py3{10,11}
skip_missing_interpreters = true
[testenv]
deps =
pytest
pytest-cov
coverage
commands = pytest --cov --cov-report=term tests
[testenv:lint]
description = run linters
skip_install = true
deps =
black
isort
pylint
commands =
black {posargs:.}
isort {posargs:.}
pylint {posargs:.} --output-format=colorized
[testenv:type]
description = run type checks
deps =
mypy>=0.991
commands =
- mypy {posargs:src}
"""
[tool.mypy]
check_untyped_defs = true
disallow_any_generics = true
disallow_incomplete_defs = true
disallow_subclassing_any = true
disallow_untyped_calls = true
disallow_untyped_defs = true
no_implicit_optional = true
#no_implicit_reexport = true
show_column_numbers = true
show_error_codes = true
show_error_context = true
strict_equality = true
strict_optional = true
warn_redundant_casts = true
#warn_return_any = true
warn_unreachable = true
warn_unused_configs = true
warn_unused_ignores = true
exclude= "src/bcf/v(2|3)/model"
plugins = "numpy.typing.mypy_plugin"
[[tool.mypy.overrides]]
module = "tests"
disallow_untyped_decorators = false
disallow_untyped_defs = false
[[tool.mypy.overrides]]
module = [
"pytest",
"pytest_mock",
"ifcopenshell",
"ifcopenshell.*",
]
ignore_missing_imports = true
[tool.pylint.main]
ignore = ["model"]
ignored-modules = ["bcf.v2.model", "bcf.v3.model", "xsdata"]
jobs = 0
disable="all"
enable="E" # B,B9,BLK,C,D,E,F,I,N,S,W
[tool.pylint.design]
max-args = 10
max-attributes = 10
[tool.pylint.format]
expected-line-ending-format = "LF"
max-line-length = 120
-6
View File
@@ -1,6 +0,0 @@
black
mypy
pylint
isort
xsdata
tox==3.27.1
-3
View File
@@ -1,3 +0,0 @@
from setuptools import setup
setup()
-17
View File
@@ -1,17 +0,0 @@
# BCF - BCF Python library
# Copyright (C) 2021 Prabhat Singh <singh01prabhat@gmail.com>
#
# This file is part of BCF.
#
# BCF is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BCF is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with BCF. If not, see <http://www.gnu.org/licenses/>.
-73
View File
@@ -1,73 +0,0 @@
"""
BCF - BCF Python library
Copyright (C) 2021 Prabhat Singh <singh01prabhat@gmail.com>
Copyright (C) 2022 Andrea Ghensi <andrea.ghensi@gmail.com>
This file is part of BCF.
BCF is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
BCF is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with BCF. If not, see <http://www.gnu.org/licenses/>.
"""
import zipfile
from pathlib import Path
from typing import Optional, Union
from bcf.v2.bcfxml import BcfXml as BcfXml2
from bcf.v2.model import Version as Version2
from bcf.v3.bcfxml import BcfXml as BcfXml3
from bcf.v3.model import Version as Version3
from bcf.xml_parser import AbstractXmlParserSerializer, XmlParserSerializer
def load(
filepath: Path, xml_handler: Optional[AbstractXmlParserSerializer] = None
) -> Optional[Union[BcfXml2, BcfXml3]]:
"""
Load a BCF file.
Args:
filepath: The path to the BCF file.
Returns:
The loaded BCF file.
Raises:
ValueError: If the BCF version is not supported.
"""
xml_handler = xml_handler or XmlParserSerializer()
version_id = _get_version(filepath, xml_handler)
if version_id in {"2.1", "2.0"}:
return BcfXml2.load(filepath, xml_handler)
if version_id == "3.0":
return BcfXml3.load(filepath, xml_handler)
raise ValueError(f"Version {version_id} not supported.")
def _get_version(filepath: Union[str, Path], xml_handler: Optional[AbstractXmlParserSerializer] = None) -> str:
"""
Returns the version of the BCF file.
Args:
filepath: The path to the BCF file.
xml_handler: The XML handler. If none is given, XmlParserSerializer is used.
Returns:
The version of the BCF file.
"""
xml_handler = xml_handler or XmlParserSerializer()
with zipfile.ZipFile(filepath) as bcf_zip:
try:
version = xml_handler.parse(bcf_zip.read("bcf.version"), Version3)
except:
version = xml_handler.parse(bcf_zip.read("bcf.version"), Version2)
return version.version_id
-64
View File
@@ -1,64 +0,0 @@
from typing import Optional
import numpy as np
from numpy.typing import NDArray
def camera_vectors_from_element_placement(
elem_placement: NDArray[np.float_],
) -> tuple[NDArray[np.float_], NDArray[np.float_], NDArray[np.float_]]:
"""
Calculate the vectors of a camera pointing to an element.
Args:
elem_placement: Placement matrix of an element.
Returns:
Camera position, direction and up vectors
"""
target_position = elem_placement[:3, 3]
return camera_vectors_from_target_position(target_position)
def camera_vectors_from_target_position(
target_position: NDArray[np.float_], offset: Optional[NDArray[np.float_]] = None
) -> tuple[NDArray[np.float_], NDArray[np.float_], NDArray[np.float_]]:
"""
Calculate the vectors of a camera pointing to a target point.
Args:
target_position: point the camera is pointing to.
camera_offset: offset of the camera from the target point.
Returns:
Camera position, direction and up vectors
"""
camera_offset = np.array((5, 5, 5)) if offset is None else offset
camera_position = target_position + camera_offset
camera_direction = unit_vector(-camera_offset) # pylint: disable=invalid-unary-operand-type
camera_right = unit_vector(np.cross(np.array([0.0, 0.0, 1.0]), camera_direction))
camera_up = unit_vector(np.cross(camera_direction, camera_right))
return camera_position, camera_direction, camera_up
# rotation_transform = np.eye(4)
# rotation_transform[0, :3] = camera_right
# rotation_transform[1, :3] = camera_up
# rotation_transform[2, :3] = camera_direction
# translation_transform = np.eye(4)
# translation_transform[:3, -1] = -camera_position
# look_at_transform = np.matmul(rotation_transform, translation_transform)
# mat = np.linalg.inv(look_at_transform)
# return camera_position, -mat[:3, 2], mat[:3, 1]
def unit_vector(v: NDArray[np.float_]) -> NDArray[np.float_]:
"""
Return the unit vector of a vector.
Args:
v: vector
Returns:
unit vector.
"""
norm = np.linalg.norm(v)
return v if norm == 0 else v / norm
-55
View File
@@ -1,55 +0,0 @@
"""
In Memory Zip File management, taken from ruamel.std.zipfile
Copyright (c) 2017-2020 Anthon van der Neut, Ruamel bvba
original idea from https://stackoverflow.com/a/19722365/1307905
"""
import zipfile
from io import BytesIO
from os import PathLike
from pathlib import Path
from typing import Any, Optional, Protocol
class ZipFileInterface(Protocol):
def writestr(self, filename_in_zip: str | zipfile.ZipInfo, file_contents: bytes | str) -> None:
...
class InMemoryZipFile:
def __init__(
self, file_name: Optional[str | Path] = None, compression: int = zipfile.ZIP_DEFLATED, debug: int = 0
) -> None:
# Create the in-memory file-like object
self._file_name: Optional[str | Path] = str(file_name) if hasattr(file_name, "_from_parts") else file_name
self.in_memory_data = BytesIO()
# Create the in-memory zipfile
self.in_memory_zip = zipfile.ZipFile(self.in_memory_data, "w", compression, False)
self.in_memory_zip.debug = debug
def writestr(self, filename_in_zip: str | zipfile.ZipInfo, file_contents: bytes | str) -> None:
"""Appends a file with name filename_in_zip and contents of
file_contents to the in-memory zip."""
self.in_memory_zip.writestr(filename_in_zip, file_contents)
def write_to_file(self, filename: str | bytes | PathLike[str] | PathLike[bytes] | int) -> None:
"""Writes the in-memory zip to a file."""
# Mark the files as having been created on Windows so that
# Unix permissions are not inferred as 0000
for zfile in self.in_memory_zip.filelist:
zfile.create_system = 0
self.in_memory_zip.close()
with open(filename, "wb") as f:
f.write(self.data)
@property
def data(self) -> bytes:
return self.in_memory_data.getvalue()
def __enter__(self) -> "InMemoryZipFile":
return self
def __exit__(self, exc_type: Any, exc_value: Any, traceback: Any) -> None:
if self._file_name:
self.write_to_file(self._file_name)
View File
-17
View File
@@ -1,17 +0,0 @@
# BCF - BCF Python library
# Copyright (C) 2020, 2021 Dion Moult <dion@thinkmoult.com>
#
# This file is part of BCF.
#
# BCF is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BCF is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with BCF. If not, see <http://www.gnu.org/licenses/>.
-275
View File
@@ -1,275 +0,0 @@
"""BCF XML V2 handler."""
import uuid
import warnings
import zipfile
from pathlib import Path
from typing import Any, NoReturn, Optional, TypeVar
import bcf.v2.model as mdl
from bcf.inmemory_zipfile import InMemoryZipFile, ZipFileInterface
from bcf.v2.topic import TopicHandler
from bcf.xml_parser import AbstractXmlParserSerializer, XmlParserSerializer
T = TypeVar("T")
class BcfXml:
"""BCF XML handler."""
def __init__(
self, filename: Optional[Path] = None, xml_handler: Optional[AbstractXmlParserSerializer] = None
) -> None:
self._filename = filename
self._xml_handler = xml_handler or XmlParserSerializer()
self._version: Optional[mdl.Version] = None
self._project_info: Optional[mdl.ProjectExtension] = None
self._topics: dict[str, TopicHandler] = {}
self._extension_schema: Optional[bytes] = None
self._zip_file = self._load_zip_file()
def __enter__(self) -> "BcfXml":
return self
def __exit__(self, *args: Any) -> None:
self.close()
def __del__(self) -> None:
self.close()
def close(self) -> None:
if self._zip_file:
self._zip_file.close()
def _load_zip_file(self) -> Optional[zipfile.ZipFile]:
return zipfile.ZipFile(self._filename) if self._filename else None
@property
def version(self) -> mdl.Version:
"""Bcf Version."""
if not self._version:
self._version = (
self._xml_handler.parse(self._zip_file.read("bcf.version"), mdl.Version)
if self._zip_file
else mdl.Version(version_id="2.1")
)
return self._version
@version.setter
def version(self, value: mdl.Version) -> None:
self._version = value
@property
def project_info(self) -> Optional[mdl.ProjectExtension]:
"""BCF project information."""
if not self._project_info and self._zip_file and zipfile.Path(self._zip_file, "project.bcfp").exists():
self._project_info = self._xml_handler.parse(self._zip_file.read("project.bcfp"), mdl.ProjectExtension)
return self._project_info
@project_info.setter
def project_info(self, value: Optional[mdl.ProjectExtension]) -> None:
self._project_info = value
@property
def project(self) -> Optional[mdl.Project]:
"""BCF project."""
return self.project_info.project if self.project_info else None
@property
def extension_schema(self) -> Optional[bytes]:
if not self._extension_schema and self._zip_file and self.project_info and self.project_info.extension_schema:
self._extension_schema = self._zip_file.read(self.project_info.extension_schema)
return self._extension_schema
@extension_schema.setter
def extension_schema(self, value: bytes) -> None:
self._extension_schema = value
@property
def topics(self) -> dict[str, TopicHandler]:
"""BCF topics."""
if not self._topics and self._zip_file:
self._topics = self._load_topics(self._zip_file, self._xml_handler)
return self._topics
def _load_topics(
self, zip_file: zipfile.ZipFile, xml_handler: AbstractXmlParserSerializer
) -> dict[str, TopicHandler]:
topics = {}
for topic_dir in zipfile.Path(zip_file).iterdir():
if not topic_dir.is_dir():
continue
markup_path = topic_dir.joinpath("markup.bcf")
if not markup_path.exists():
continue
topics[topic_dir.name] = TopicHandler(topic_dir, xml_handler)
return topics
@classmethod
def load(cls, filename: Path, xml_handler: Optional[AbstractXmlParserSerializer] = None) -> Optional["BcfXml"]:
"""
Create a BcfXml object from a file.
Args:
filename: Path to the file.
xml_handler: XML parser and serializer.
Returns:
A BcfXml object with the file contents.
Raises:
ValueError: If the file name is null or empty
"""
if not filename:
raise ValueError("filename is required")
xml_handler = xml_handler or XmlParserSerializer()
return cls(xml_handler=xml_handler, filename=filename)
@classmethod
def create_new(
cls,
project_name: Optional[str] = None,
xml_handler: Optional[AbstractXmlParserSerializer] = None,
) -> "BcfXml":
"""
Create a new BcfXml object.
Args:
project_name: The name of the project.
xml_handler: XML parser and serializer.
Returns:
A new BcfXml object.
"""
instance = cls(xml_handler=xml_handler or XmlParserSerializer())
instance.project_info = mdl.ProjectExtension(
project=mdl.Project(name=project_name, project_id=str(uuid.uuid4())), extension_schema=""
)
return instance
def save(self, filename: Optional[Path] = None, keep_open: bool = False) -> None:
"""Save the BCF file to the given filename."""
if not filename and not self._filename:
raise ValueError("No file name specified, cannot save BCF file.")
if filename:
self._filename = filename
with InMemoryZipFile(self._filename) as bcf_zip:
self._save_project(bcf_zip)
self._save_version(bcf_zip)
self._save_topics(bcf_zip)
if keep_open:
self._zip_file = self._load_zip_file()
def _save_project(self, destination_zip: ZipFileInterface) -> None:
self._smart_save_xml(destination_zip, self._project_info, "project.bcfp")
if self.extension_schema and self.project_info:
destination_zip.writestr(self.project_info.extension_schema, self.extension_schema)
def _save_version(self, destination_zip: ZipFileInterface) -> None:
if not self._version and self._zip_file:
destination_zip.writestr("bcf.version", self._zip_file.read("bcf.version"))
else:
self._save_xml(destination_zip, "bcf.version", self.version)
def _smart_save_xml(self, destination_zip: ZipFileInterface, item: Any, target: str) -> None:
if item:
self._save_xml(destination_zip, target, item)
elif self._zip_file and zipfile.Path(self._zip_file, target).exists():
destination_zip.writestr(target, self._zip_file.read(target))
def _save_xml(self, destination_zip: ZipFileInterface, inner_file: str, xml_obj: Any) -> None:
destination_zip.writestr(inner_file, self._xml_handler.serialize(xml_obj))
def _save_topics(self, destination_zip: ZipFileInterface) -> None:
for topic_handler in self.topics.values():
topic_handler.save(destination_zip)
def add_topic(
self, title: str, description: str, author: str, topic_type: str = "", topic_status: str = ""
) -> TopicHandler:
"""
Add a new topic to the BCF.
Args:
title: The title of the topic.
description: The description of the topic.
author: The author of the topic.
topic_type: The type of the topic.
topic_status: The status of the topic.
Returns:
The newly created topic wrapped inside a TopicHandler object.
"""
topic_handler = TopicHandler.create_new(
title,
description,
author,
topic_type=topic_type,
topic_status=topic_status,
xml_handler=self._xml_handler,
)
self.topics[topic_handler.guid] = topic_handler
return topic_handler
def __eq__(self, other: object) -> bool | NoReturn:
return (
self.version == other.version and self.project_info == other.project_info
if isinstance(other, BcfXml)
else NotImplemented
)
# region Deprecated methods
def new_project(self) -> "BcfXml":
"""Deprecated method."""
warnings.warn("new_project is deprecated, use create_new instead.", DeprecationWarning)
return self.create_new()
def get_project(self, _filepath: Optional[str] = None) -> Optional[mdl.Project]:
"""Deprecated method."""
warnings.warn("get_project is deprecated, use project_info.project instead.", DeprecationWarning)
return self.project
def edit_project(self) -> None:
"""Deprecated method."""
warnings.warn("edit_project is deprecated, there's no need to use it.", DeprecationWarning)
def save_project(self, filepath: Path) -> None:
"""Deprecated method."""
warnings.warn("save_project is deprecated, use save instead.", DeprecationWarning)
self.save(filepath)
def get_version(self) -> Optional[str]:
warnings.warn("get_version is deprecated, use version.version_id instead.", DeprecationWarning)
return self.version.version_id
def edit_version(self) -> None:
"""Deprecated method."""
warnings.warn("edit_version is deprecated, there's no need to use it.", DeprecationWarning)
def get_topics(self) -> dict[str, TopicHandler]:
"""Deprecated method."""
warnings.warn("get_topics is deprecated, use topics instead.", DeprecationWarning)
return self.topics
def get_topic(self, guid: str) -> TopicHandler:
"""Return a topic by its GUID."""
warnings.warn("get_topic is deprecated, use topics[guid] instead", DeprecationWarning)
return self.topics[guid]
def get_header(self, guid: str) -> Optional[mdl.Header]:
"""Return the header of a Topic by its GUID."""
return self.topics[guid].header
def edit_topic(self) -> None:
"""Deprecated method."""
warnings.warn("edit_topic is deprecated, there's no need to use it.", DeprecationWarning)
def add_comment(self, _topic: mdl.Topic, _comment: Optional[mdl.Comment] = None) -> None:
"""Deprecated method."""
warnings.warn("add_comment is deprecated, use topics methods instead.", DeprecationWarning)
def edit_comment(self) -> None:
"""Deprecated method."""
warnings.warn("edit_comment is deprecated, there's no need to use it.", DeprecationWarning)
# TODO: deprecate other methods
# endregion
-70
View File
@@ -1,70 +0,0 @@
from bcf.v2.model.markup import (
BimSnippet,
Comment,
CommentViewpoint,
Header,
HeaderFile,
Markup,
Topic,
TopicDocumentReference,
TopicRelatedTopic,
ViewPoint,
)
from bcf.v2.model.project import Project, ProjectExtension
from bcf.v2.model.version import Version
from bcf.v2.model.visinfo import (
BitmapFormat,
ClippingPlane,
Component,
ComponentColoring,
ComponentColoringColor,
Components,
ComponentSelection,
ComponentVisibility,
ComponentVisibilityExceptions,
Direction,
Line,
OrthogonalCamera,
PerspectiveCamera,
Point,
ViewSetupHints,
VisualizationInfo,
VisualizationInfoBitmap,
VisualizationInfoClippingPlanes,
VisualizationInfoLines,
)
__all__ = [
"BimSnippet",
"Comment",
"CommentViewpoint",
"Header",
"HeaderFile",
"Markup",
"Topic",
"TopicDocumentReference",
"TopicRelatedTopic",
"ViewPoint",
"Project",
"ProjectExtension",
"Version",
"BitmapFormat",
"ClippingPlane",
"Component",
"ComponentColoring",
"ComponentColoringColor",
"ComponentSelection",
"ComponentVisibility",
"ComponentVisibilityExceptions",
"Components",
"Direction",
"Line",
"OrthogonalCamera",
"PerspectiveCamera",
"Point",
"ViewSetupHints",
"VisualizationInfo",
"VisualizationInfoBitmap",
"VisualizationInfoClippingPlanes",
"VisualizationInfoLines",
]
-461
View File
@@ -1,461 +0,0 @@
from dataclasses import dataclass, field
from typing import List, Optional
from xsdata.models.datatype import XmlDateTime
@dataclass(slots=True, kw_only=True)
class BimSnippet:
reference: str = field(
metadata={
"name": "Reference",
"type": "Element",
"namespace": "",
"required": True,
}
)
reference_schema: str = field(
metadata={
"name": "ReferenceSchema",
"type": "Element",
"namespace": "",
"required": True,
}
)
snippet_type: str = field(
metadata={
"name": "SnippetType",
"type": "Attribute",
"required": True,
}
)
is_external: bool = field(
default=False,
metadata={
"name": "isExternal",
"type": "Attribute",
}
)
@dataclass(slots=True, kw_only=True)
class CommentViewpoint:
class Meta:
global_type = False
guid: str = field(
metadata={
"name": "Guid",
"type": "Attribute",
"required": True,
"pattern": r"[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}",
}
)
@dataclass(slots=True, kw_only=True)
class HeaderFile:
class Meta:
global_type = False
filename: Optional[str] = field(
default=None,
metadata={
"name": "Filename",
"type": "Element",
"namespace": "",
}
)
date: Optional[XmlDateTime] = field(
default=None,
metadata={
"name": "Date",
"type": "Element",
"namespace": "",
}
)
reference: Optional[str] = field(
default=None,
metadata={
"name": "Reference",
"type": "Element",
"namespace": "",
}
)
ifc_project: Optional[str] = field(
default=None,
metadata={
"name": "IfcProject",
"type": "Attribute",
"length": 22,
"pattern": r"[0-9,A-Z,a-z,_$]*",
}
)
ifc_spatial_structure_element: Optional[str] = field(
default=None,
metadata={
"name": "IfcSpatialStructureElement",
"type": "Attribute",
"length": 22,
"pattern": r"[0-9,A-Z,a-z,_$]*",
}
)
is_external: bool = field(
default=True,
metadata={
"name": "isExternal",
"type": "Attribute",
}
)
@dataclass(slots=True, kw_only=True)
class TopicDocumentReference:
class Meta:
global_type = False
referenced_document: Optional[str] = field(
default=None,
metadata={
"name": "ReferencedDocument",
"type": "Element",
"namespace": "",
}
)
description: Optional[str] = field(
default=None,
metadata={
"name": "Description",
"type": "Element",
"namespace": "",
}
)
guid: Optional[str] = field(
default=None,
metadata={
"name": "Guid",
"type": "Attribute",
"pattern": r"[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}",
}
)
is_external: bool = field(
default=False,
metadata={
"name": "isExternal",
"type": "Attribute",
}
)
@dataclass(slots=True, kw_only=True)
class TopicRelatedTopic:
class Meta:
global_type = False
guid: str = field(
metadata={
"name": "Guid",
"type": "Attribute",
"required": True,
"pattern": r"[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}",
}
)
@dataclass(slots=True, kw_only=True)
class ViewPoint:
viewpoint: Optional[str] = field(
default=None,
metadata={
"name": "Viewpoint",
"type": "Element",
"namespace": "",
}
)
snapshot: Optional[str] = field(
default=None,
metadata={
"name": "Snapshot",
"type": "Element",
"namespace": "",
}
)
index: Optional[int] = field(
default=None,
metadata={
"name": "Index",
"type": "Element",
"namespace": "",
}
)
guid: str = field(
metadata={
"name": "Guid",
"type": "Attribute",
"required": True,
"pattern": r"[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}",
}
)
@dataclass(slots=True, kw_only=True)
class Comment:
date: XmlDateTime = field(
metadata={
"name": "Date",
"type": "Element",
"namespace": "",
"required": True,
}
)
author: str = field(
metadata={
"name": "Author",
"type": "Element",
"namespace": "",
"required": True,
}
)
comment: str = field(
metadata={
"name": "Comment",
"type": "Element",
"namespace": "",
"required": True,
}
)
viewpoint: Optional[CommentViewpoint] = field(
default=None,
metadata={
"name": "Viewpoint",
"type": "Element",
"namespace": "",
}
)
modified_date: Optional[XmlDateTime] = field(
default=None,
metadata={
"name": "ModifiedDate",
"type": "Element",
"namespace": "",
}
)
modified_author: Optional[str] = field(
default=None,
metadata={
"name": "ModifiedAuthor",
"type": "Element",
"namespace": "",
}
)
guid: str = field(
metadata={
"name": "Guid",
"type": "Attribute",
"required": True,
"pattern": r"[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}",
}
)
@dataclass(slots=True, kw_only=True)
class Header:
file: List[HeaderFile] = field(
default_factory=list,
metadata={
"name": "File",
"type": "Element",
"namespace": "",
"min_occurs": 1,
}
)
@dataclass(slots=True, kw_only=True)
class Topic:
reference_link: List[str] = field(
default_factory=list,
metadata={
"name": "ReferenceLink",
"type": "Element",
"namespace": "",
}
)
title: str = field(
metadata={
"name": "Title",
"type": "Element",
"namespace": "",
"required": True,
}
)
priority: Optional[str] = field(
default=None,
metadata={
"name": "Priority",
"type": "Element",
"namespace": "",
}
)
index: Optional[int] = field(
default=None,
metadata={
"name": "Index",
"type": "Element",
"namespace": "",
}
)
labels: List[str] = field(
default_factory=list,
metadata={
"name": "Labels",
"type": "Element",
"namespace": "",
}
)
creation_date: XmlDateTime = field(
metadata={
"name": "CreationDate",
"type": "Element",
"namespace": "",
"required": True,
}
)
creation_author: str = field(
metadata={
"name": "CreationAuthor",
"type": "Element",
"namespace": "",
"required": True,
}
)
modified_date: Optional[XmlDateTime] = field(
default=None,
metadata={
"name": "ModifiedDate",
"type": "Element",
"namespace": "",
}
)
modified_author: Optional[str] = field(
default=None,
metadata={
"name": "ModifiedAuthor",
"type": "Element",
"namespace": "",
}
)
due_date: Optional[XmlDateTime] = field(
default=None,
metadata={
"name": "DueDate",
"type": "Element",
"namespace": "",
}
)
assigned_to: Optional[str] = field(
default=None,
metadata={
"name": "AssignedTo",
"type": "Element",
"namespace": "",
}
)
stage: Optional[str] = field(
default=None,
metadata={
"name": "Stage",
"type": "Element",
"namespace": "",
}
)
description: Optional[str] = field(
default=None,
metadata={
"name": "Description",
"type": "Element",
"namespace": "",
}
)
bim_snippet: Optional[BimSnippet] = field(
default=None,
metadata={
"name": "BimSnippet",
"type": "Element",
"namespace": "",
}
)
document_reference: List[TopicDocumentReference] = field(
default_factory=list,
metadata={
"name": "DocumentReference",
"type": "Element",
"namespace": "",
}
)
related_topic: List[TopicRelatedTopic] = field(
default_factory=list,
metadata={
"name": "RelatedTopic",
"type": "Element",
"namespace": "",
}
)
guid: str = field(
metadata={
"name": "Guid",
"type": "Attribute",
"required": True,
"pattern": r"[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}",
}
)
topic_type: Optional[str] = field(
default=None,
metadata={
"name": "TopicType",
"type": "Attribute",
}
)
topic_status: Optional[str] = field(
default=None,
metadata={
"name": "TopicStatus",
"type": "Attribute",
}
)
@dataclass(slots=True, kw_only=True)
class Markup:
header: Optional[Header] = field(
default=None,
metadata={
"name": "Header",
"type": "Element",
"namespace": "",
}
)
topic: Topic = field(
metadata={
"name": "Topic",
"type": "Element",
"namespace": "",
"required": True,
}
)
comment: List[Comment] = field(
default_factory=list,
metadata={
"name": "Comment",
"type": "Element",
"namespace": "",
}
)
viewpoints: List[ViewPoint] = field(
default_factory=list,
metadata={
"name": "Viewpoints",
"type": "Element",
"namespace": "",
}
)
-41
View File
@@ -1,41 +0,0 @@
from dataclasses import dataclass, field
from typing import Optional
@dataclass(slots=True, kw_only=True)
class Project:
name: Optional[str] = field(
default=None,
metadata={
"name": "Name",
"type": "Element",
"namespace": "",
}
)
project_id: str = field(
metadata={
"name": "ProjectId",
"type": "Attribute",
"required": True,
}
)
@dataclass(slots=True, kw_only=True)
class ProjectExtension:
project: Optional[Project] = field(
default=None,
metadata={
"name": "Project",
"type": "Element",
"namespace": "",
}
)
extension_schema: str = field(
metadata={
"name": "ExtensionSchema",
"type": "Element",
"namespace": "",
"required": True,
}
)
-21
View File
@@ -1,21 +0,0 @@
from dataclasses import dataclass, field
from typing import Optional
@dataclass(slots=True, kw_only=True)
class Version:
detailed_version: Optional[str] = field(
default=None,
metadata={
"name": "DetailedVersion",
"type": "Element",
"namespace": "",
}
)
version_id: Optional[str] = field(
default=None,
metadata={
"name": "VersionId",
"type": "Attribute",
}
)
-476
View File
@@ -1,476 +0,0 @@
from dataclasses import dataclass, field
from enum import Enum
from typing import List, Optional
class BitmapFormat(Enum):
PNG = "PNG"
JPG = "JPG"
@dataclass(slots=True, kw_only=True)
class Component:
originating_system: Optional[str] = field(
default=None,
metadata={
"name": "OriginatingSystem",
"type": "Element",
}
)
authoring_tool_id: Optional[str] = field(
default=None,
metadata={
"name": "AuthoringToolId",
"type": "Element",
}
)
ifc_guid: Optional[str] = field(
default=None,
metadata={
"name": "IfcGuid",
"type": "Attribute",
"length": 22,
"pattern": r"[0-9,A-Z,a-z,_$]*",
}
)
@dataclass(slots=True, kw_only=True)
class Direction:
x: float = field(
metadata={
"name": "X",
"type": "Element",
"required": True,
}
)
y: float = field(
metadata={
"name": "Y",
"type": "Element",
"required": True,
}
)
z: float = field(
metadata={
"name": "Z",
"type": "Element",
"required": True,
}
)
@dataclass(slots=True, kw_only=True)
class Point:
x: float = field(
metadata={
"name": "X",
"type": "Element",
"required": True,
}
)
y: float = field(
metadata={
"name": "Y",
"type": "Element",
"required": True,
}
)
z: float = field(
metadata={
"name": "Z",
"type": "Element",
"required": True,
}
)
@dataclass(slots=True, kw_only=True)
class ViewSetupHints:
spaces_visible: Optional[bool] = field(
default=None,
metadata={
"name": "SpacesVisible",
"type": "Attribute",
}
)
space_boundaries_visible: Optional[bool] = field(
default=None,
metadata={
"name": "SpaceBoundariesVisible",
"type": "Attribute",
}
)
openings_visible: Optional[bool] = field(
default=None,
metadata={
"name": "OpeningsVisible",
"type": "Attribute",
}
)
@dataclass(slots=True, kw_only=True)
class ClippingPlane:
location: Point = field(
metadata={
"name": "Location",
"type": "Element",
"required": True,
}
)
direction: Direction = field(
metadata={
"name": "Direction",
"type": "Element",
"required": True,
}
)
@dataclass(slots=True, kw_only=True)
class ComponentColoringColor:
class Meta:
global_type = False
component: List[Component] = field(
default_factory=list,
metadata={
"name": "Component",
"type": "Element",
"min_occurs": 1,
}
)
color: Optional[str] = field(
default=None,
metadata={
"name": "Color",
"type": "Attribute",
"pattern": r"[0-9,a-f,A-F]{6}([0-9,a-f,A-F]{2})?",
}
)
@dataclass(slots=True, kw_only=True)
class ComponentSelection:
component: List[Component] = field(
default_factory=list,
metadata={
"name": "Component",
"type": "Element",
"min_occurs": 1,
}
)
@dataclass(slots=True, kw_only=True)
class ComponentVisibilityExceptions:
class Meta:
global_type = False
component: List[Component] = field(
default_factory=list,
metadata={
"name": "Component",
"type": "Element",
"min_occurs": 1,
}
)
@dataclass(slots=True, kw_only=True)
class Line:
start_point: Point = field(
metadata={
"name": "StartPoint",
"type": "Element",
"required": True,
}
)
end_point: Point = field(
metadata={
"name": "EndPoint",
"type": "Element",
"required": True,
}
)
@dataclass(slots=True, kw_only=True)
class OrthogonalCamera:
"""
Attributes
camera_view_point:
camera_direction:
camera_up_vector:
view_to_world_scale: view's visible size in meters
"""
camera_view_point: Point = field(
metadata={
"name": "CameraViewPoint",
"type": "Element",
"required": True,
}
)
camera_direction: Direction = field(
metadata={
"name": "CameraDirection",
"type": "Element",
"required": True,
}
)
camera_up_vector: Direction = field(
metadata={
"name": "CameraUpVector",
"type": "Element",
"required": True,
}
)
view_to_world_scale: float = field(
metadata={
"name": "ViewToWorldScale",
"type": "Element",
"required": True,
}
)
@dataclass(slots=True, kw_only=True)
class PerspectiveCamera:
"""
Attributes
camera_view_point:
camera_direction:
camera_up_vector:
field_of_view: 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.
"""
camera_view_point: Point = field(
metadata={
"name": "CameraViewPoint",
"type": "Element",
"required": True,
}
)
camera_direction: Direction = field(
metadata={
"name": "CameraDirection",
"type": "Element",
"required": True,
}
)
camera_up_vector: Direction = field(
metadata={
"name": "CameraUpVector",
"type": "Element",
"required": True,
}
)
field_of_view: float = field(
metadata={
"name": "FieldOfView",
"type": "Element",
"required": True,
"min_inclusive": 1.0,
"max_inclusive": 170.0,
}
)
@dataclass(slots=True, kw_only=True)
class VisualizationInfoBitmap:
class Meta:
global_type = False
bitmap: BitmapFormat = field(
metadata={
"name": "Bitmap",
"type": "Element",
"required": True,
}
)
reference: str = field(
metadata={
"name": "Reference",
"type": "Element",
"required": True,
}
)
location: Point = field(
metadata={
"name": "Location",
"type": "Element",
"required": True,
}
)
normal: Direction = field(
metadata={
"name": "Normal",
"type": "Element",
"required": True,
}
)
up: Direction = field(
metadata={
"name": "Up",
"type": "Element",
"required": True,
}
)
height: float = field(
metadata={
"name": "Height",
"type": "Element",
"required": True,
}
)
@dataclass(slots=True, kw_only=True)
class ComponentColoring:
color: List[ComponentColoringColor] = field(
default_factory=list,
metadata={
"name": "Color",
"type": "Element",
"min_occurs": 1,
}
)
@dataclass(slots=True, kw_only=True)
class ComponentVisibility:
exceptions: Optional[ComponentVisibilityExceptions] = field(
default=None,
metadata={
"name": "Exceptions",
"type": "Element",
}
)
default_visibility: Optional[bool] = field(
default=None,
metadata={
"name": "DefaultVisibility",
"type": "Attribute",
}
)
@dataclass(slots=True, kw_only=True)
class VisualizationInfoClippingPlanes:
class Meta:
global_type = False
clipping_plane: List[ClippingPlane] = field(
default_factory=list,
metadata={
"name": "ClippingPlane",
"type": "Element",
}
)
@dataclass(slots=True, kw_only=True)
class VisualizationInfoLines:
class Meta:
global_type = False
line: List[Line] = field(
default_factory=list,
metadata={
"name": "Line",
"type": "Element",
"min_occurs": 1,
}
)
@dataclass(slots=True, kw_only=True)
class Components:
view_setup_hints: Optional[ViewSetupHints] = field(
default=None,
metadata={
"name": "ViewSetupHints",
"type": "Element",
}
)
selection: Optional[ComponentSelection] = field(
default=None,
metadata={
"name": "Selection",
"type": "Element",
}
)
visibility: ComponentVisibility = field(
metadata={
"name": "Visibility",
"type": "Element",
"required": True,
}
)
coloring: Optional[ComponentColoring] = field(
default=None,
metadata={
"name": "Coloring",
"type": "Element",
}
)
@dataclass(slots=True, kw_only=True)
class VisualizationInfo:
"""
VisualizationInfo documentation.
"""
components: Optional[Components] = field(
default=None,
metadata={
"name": "Components",
"type": "Element",
}
)
orthogonal_camera: Optional[OrthogonalCamera] = field(
default=None,
metadata={
"name": "OrthogonalCamera",
"type": "Element",
}
)
perspective_camera: Optional[PerspectiveCamera] = field(
default=None,
metadata={
"name": "PerspectiveCamera",
"type": "Element",
}
)
lines: Optional[VisualizationInfoLines] = field(
default=None,
metadata={
"name": "Lines",
"type": "Element",
}
)
clipping_planes: Optional[VisualizationInfoClippingPlanes] = field(
default=None,
metadata={
"name": "ClippingPlanes",
"type": "Element",
}
)
bitmap: List[VisualizationInfoBitmap] = field(
default_factory=list,
metadata={
"name": "Bitmap",
"type": "Element",
}
)
guid: str = field(
metadata={
"name": "Guid",
"type": "Attribute",
"required": True,
"pattern": r"[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}",
}
)
-306
View File
@@ -1,306 +0,0 @@
"""BCF XML V2 Topic handler."""
import datetime
import tempfile
import uuid
import zipfile
from pathlib import Path
from typing import Any, NoReturn, Optional
import numpy as np
from ifcopenshell import entity_instance
from numpy.typing import NDArray
from xsdata.models.datatype import XmlDateTime
import bcf.v2.model as mdl
from bcf.inmemory_zipfile import ZipFileInterface
from bcf.v2.visinfo import VisualizationInfoHandler
from bcf.xml_parser import AbstractXmlParserSerializer, XmlParserSerializer
class TopicHandler:
"""BCF Topic and related objects handler."""
def __init__(
self,
topic_dir: Optional[zipfile.Path] = None,
xml_handler: Optional[AbstractXmlParserSerializer] = None,
) -> None:
self._markup: Optional[mdl.Markup] = None
self._viewpoints: dict[str, VisualizationInfoHandler] = {}
self._reference_files: dict[str, bytes] = {}
self._document_references: dict[str, bytes] = {}
self._bim_snippet: Optional[bytes] = None
self._xml_handler = xml_handler or XmlParserSerializer()
self._topic_dir = topic_dir
@property
def markup(self) -> Optional[mdl.Markup]:
if not self._markup:
markup_path = self._topic_dir.joinpath("markup.bcf")
if markup_path.exists():
self._markup = self._xml_handler.parse(markup_path.read_bytes(), mdl.Markup)
return self._markup
@markup.setter
def markup(self, value: mdl.Markup) -> None:
self._markup = value
@property
def topic(self) -> mdl.Topic:
"""Return the Topic object."""
return self.markup.topic
@property
def guid(self) -> str:
"""Return the GUID of the topic."""
if self._markup:
return self.topic.guid
return self._topic_dir.name if self._topic_dir else ""
@property
def header(self) -> Optional[mdl.Header]:
"""Return the header of the topic."""
return self.markup.header if self.markup else None
@property
def comments(self) -> list[mdl.Comment]:
"""Return the comments of the topic."""
return self.markup.comment if self.markup else []
@property
def bim_snippet(self) -> Optional[bytes]:
if not self._bim_snippet and self._topic_dir:
self._bim_snippet = self._load_bim_snippet()
return self._bim_snippet
@bim_snippet.setter
def bim_snippet(self, value: bytes) -> None:
self._bim_snippet = value
@property
def viewpoints(self) -> dict[str, VisualizationInfoHandler]:
if not self._viewpoints and self._topic_dir:
self._viewpoints = self._load_viewpoints()
return self._viewpoints
@property
def reference_files(self) -> dict[str, bytes]:
if self._reference_files or not self.header:
return self._reference_files
for ref in self.header.file:
if ref.is_external:
continue
real_path = self._topic_dir
for path_part in ref.reference.split("/"):
real_path = real_path.parent if path_part == ".." else real_path.joinpath(path_part)
self._reference_files[ref.reference] = real_path.read_bytes()
return self._reference_files
@property
def document_references(self) -> dict[str, bytes]:
if self._document_references or not self.topic:
return self._document_references
for doc in self.topic.document_reference:
if doc.is_external or not doc.referenced_document:
continue
real_path = self._topic_dir
for path_part in doc.referenced_document.split("/"):
real_path = real_path.parent if path_part == ".." else real_path.joinpath(path_part)
self._document_references[doc.referenced_document] = real_path.read_bytes()
return self._document_references
def _load_bim_snippet(self) -> Optional[bytes]:
bim_snippet_obj = self.topic.bim_snippet
if bim_snippet_obj and not bim_snippet_obj.is_external:
bim_snippet_path = self._topic_dir.joinpath(bim_snippet_obj.reference)
if bim_snippet_path.exists():
return bim_snippet_path.read_bytes()
return None
def _load_viewpoints(self) -> dict[str, VisualizationInfoHandler]:
if self.markup and (viewpoints := self.markup.viewpoints):
return VisualizationInfoHandler.from_topic_viewpoints(self._topic_dir, viewpoints)
return {}
@classmethod
def create_new(
cls,
title: str,
description: str,
author: str,
topic_type: str = "",
topic_status: str = "",
xml_handler: Optional[AbstractXmlParserSerializer] = None,
) -> "TopicHandler":
"""
Create a new BCF topic.
Args:
title: The title of the topic.
description: The description of the topic.
author: The author of the topic.
topic_type: The type of the topic.
topic_status: The status of the topic.
xml_handler: The XML parser/serializer to use.
Returns:
The BCF topic definition.
"""
creation_date = XmlDateTime.from_datetime(datetime.datetime.now())
guid = str(uuid.uuid4())
topic = mdl.Topic(
title=title,
description=description,
creation_author=author,
creation_date=creation_date,
guid=guid,
topic_type=topic_type,
topic_status=topic_status,
)
markup = mdl.Markup(topic=topic)
obj = cls(topic_dir=Path(guid), xml_handler=xml_handler or XmlParserSerializer())
obj.markup = markup
return obj
def save(self, destination_zip: ZipFileInterface) -> None:
"""
Save the topic to a BCF zip file.
Args:
bcf_zip: The BCF zip file to save to.
"""
topic_dir = self.guid
self._save_xml(destination_zip, self._markup, "markup.bcf")
self._save_viewpoints(destination_zip, topic_dir)
self._save_bim_snippet(destination_zip)
self._save_reference_files(destination_zip)
self._save_document_references(destination_zip)
def _save_viewpoints(self, destination_zip: ZipFileInterface, topic_dir: str) -> None:
if not self.markup or not (viewpoints := self.markup.viewpoints):
return
for vpt in viewpoints:
if vpt.viewpoint:
self.viewpoints[vpt.viewpoint].save(destination_zip, topic_dir, vpt)
def _save_xml(self, destination_zip: ZipFileInterface, item: Any, target: str) -> None:
if self._topic_dir is None:
return
to_write = self._xml_handler.serialize(item) if item else self._topic_dir.joinpath(target).read_bytes()
destination_zip.writestr(f"{self._topic_dir.name}/{target}", to_write)
def _save_bim_snippet(self, destination_zip: ZipFileInterface) -> None:
snippet = self.topic.bim_snippet
if not snippet or snippet.is_external:
return
ref_filename = Path(snippet.reference).name
if self.bim_snippet:
destination_zip.writestr(f"{self.topic.guid}/{ref_filename}", self.bim_snippet)
def _save_reference_files(self, destination_zip: ZipFileInterface) -> None:
if not self.header:
return
for ref in self.header.file:
if ref.is_external or not ref.reference:
continue
real_path = self._topic_dir
for path_part in ref.reference.split("/"):
real_path = real_path.parent if path_part == ".." else real_path.joinpath(path_part)
destination_zip.writestr(real_path.at, self.reference_files[ref.reference])
def _save_document_references(self, destination_zip: ZipFileInterface) -> None:
if not self.topic:
return
for doc in self.topic.document_reference:
if doc.is_external or not doc.referenced_document:
continue
real_path = self._topic_dir
for path_part in doc.referenced_document.split("/"):
real_path = real_path.parent if path_part == ".." else real_path.joinpath(path_part)
destination_zip.writestr(real_path.at, self.document_references[doc.referenced_document])
def extract_file(self, entity, outfile: Optional[Path] = None) -> Path:
"""Extracts an element with a file into a temporary directory
These include header files, bim snippets, document references, and
viewpoint bitmaps. External reference are not downloaded. Instead, the
URI reference is returned.
:param entity: The entity with a file reference to extract
:type entity: bcf.v2.model.HeaderFile,bcf.v2.model.BimSnippet,bcf.v2.model.TopicDocumentReference
:param outfile: If provided, save the header file to that location.
Otherwise, a temporary directory is created and the filename is
derived from the header's original filename.
:type outfile: pathlib.Path,optional
:return: The filepath of the extracted file. It may be a URL if the
header file is external.
:rtype: Path
"""
if hasattr(entity, "reference"):
reference = entity.reference
else:
reference = entity.referenced_document
if not reference:
return
if getattr(entity, "is_external", False):
return entity.reference
resolved_reference = self._topic_dir
for part in Path(reference).parts:
if part == "..":
resolved_reference = resolved_reference.parent
else:
resolved_reference = resolved_reference.joinpath(part)
if not outfile:
if getattr(entity, "filename", None):
filename = entity.filename
else:
filename = resolved_reference.name
outfile = Path(tempfile.mkdtemp()) / filename
with open(outfile, "wb") as f:
f.write(resolved_reference.read_bytes())
return outfile
def add_viewpoint(self, element: entity_instance) -> None:
"""Add a viewpoint pointed at the placement of an IFC element to the topic.
Args:
element: The IFC element.
"""
new_viewpoint = VisualizationInfoHandler.create_new(element, self._xml_handler)
self.add_visinfo_handler(new_viewpoint)
return new_viewpoint
def add_viewpoint_from_point_and_guids(self, position: NDArray[np.float_], *guids: str) -> None:
"""Add a viewpoint pointing at an XYZ point in space
Args:
position: the XYZ point in space
guids: one or more element GlobalIds.
"""
vi_handler = VisualizationInfoHandler.create_from_point_and_guids(
position, *guids, xml_handler=self._xml_handler
)
self.add_visinfo_handler(vi_handler)
return vi_handler
def add_visinfo_handler(self, new_viewpoint: VisualizationInfoHandler) -> None:
self.viewpoints[new_viewpoint.guid + ".bcfv"] = new_viewpoint
self.markup.viewpoints.append(mdl.ViewPoint(viewpoint=new_viewpoint.guid + ".bcfv", guid=new_viewpoint.guid))
def __eq__(self, other: object) -> bool | NoReturn:
return (
(
self.markup == other.markup
and self.viewpoints == other.viewpoints
and self.bim_snippet == other.bim_snippet
)
if isinstance(other, TopicHandler)
else NotImplemented
)
-299
View File
@@ -1,299 +0,0 @@
import uuid
import zipfile
from functools import lru_cache
from typing import Any, Iterable, Optional
import numpy as np
from ifcopenshell import entity_instance
import ifcopenshell.util.unit
import ifcopenshell.util.placement
from numpy.typing import NDArray
import bcf.v2.model as mdl
from bcf.geometry import (
camera_vectors_from_element_placement,
camera_vectors_from_target_position,
)
from bcf.inmemory_zipfile import ZipFileInterface
from bcf.xml_parser import AbstractXmlParserSerializer, XmlParserSerializer
class VisualizationInfoHandler:
"""Handle the VisualizationInfo and related objects."""
def __init__(
self,
visualization_info: mdl.VisualizationInfo,
snapshot: Optional[bytes] = None,
bitmaps: Optional[dict[str, bytes]] = None,
xml_handler: Optional[AbstractXmlParserSerializer] = None,
) -> None:
self.visualization_info = visualization_info
self.snapshot = snapshot
self.bitmaps = bitmaps or {}
self._xml_handler = xml_handler or XmlParserSerializer()
@property
def guid(self) -> str:
"""Return the GUID of the visualization info."""
return self.visualization_info.guid
@classmethod
def from_topic_viewpoints(
cls,
topic_dir: zipfile.Path,
vps: Iterable[mdl.ViewPoint],
xml_handler: Optional[AbstractXmlParserSerializer] = None,
) -> dict[str, "VisualizationInfoHandler"]:
"""Create VisualizationInfoHandler objects of a Topic's ViewPoints."""
viewpoints = {}
for vpt in vps:
visinfo = cls.load(topic_dir, vpt, xml_handler)
if visinfo and vpt.viewpoint:
viewpoints[vpt.viewpoint] = visinfo
return viewpoints
@classmethod
def load(
cls,
topic_dir: zipfile.Path,
vpt: mdl.ViewPoint,
xml_handler: Optional[AbstractXmlParserSerializer] = None,
) -> Optional["VisualizationInfoHandler"]:
"""
Load the VisualizationInfo and related objects from a BCF zip file.
Args:
topic_dir: The directory in the BCF zip file to load from.
vpt: The ViewPoint to load.
xml_handler: The XML handler to use to parse the VisualizationInfo.
Returns:
The VisualizationInfoHandler object.
"""
visinfo = cls._load_visinfo(topic_dir, vpt.viewpoint, xml_handler)
if not visinfo:
return None
snapshot = cls._load_snapshot(topic_dir, vpt.snapshot)
bitmaps = cls._load_bitmaps(topic_dir, visinfo)
return cls(visinfo, snapshot, bitmaps, xml_handler)
@staticmethod
def _load_visinfo(
topic_dir: zipfile.Path,
vp_name: Optional[str],
xml_handler: Optional[AbstractXmlParserSerializer] = None,
) -> Optional[mdl.VisualizationInfo]:
if not vp_name:
return None
vp_path = topic_dir.joinpath(vp_name)
if vp_path.exists():
xml_handler = xml_handler or XmlParserSerializer()
return xml_handler.parse(vp_path.read_bytes(), mdl.VisualizationInfo)
return None
@staticmethod
def _load_snapshot(topic_dir: zipfile.Path, vp_snapshot: Optional[str]) -> Optional[bytes]:
if vp_snapshot:
snapshot_path = topic_dir.joinpath(vp_snapshot)
if snapshot_path.exists():
return snapshot_path.read_bytes()
return None
@staticmethod
def _load_bitmaps(topic_dir: zipfile.Path, visinfo: Optional[mdl.VisualizationInfo]) -> dict[str, bytes]:
if not visinfo or not (bitmaps := visinfo.bitmap):
return {}
bitmaps_dict = {}
for bitmap in bitmaps:
if not bitmap.reference:
continue
bitmap_path = topic_dir.joinpath(bitmap.reference)
if bitmap_path.exists():
bitmaps_dict[bitmap.reference] = bitmap_path.read_bytes()
return bitmaps_dict
def save(
self,
bcf_zip: ZipFileInterface,
topic_dir: str,
vpt: mdl.ViewPoint,
) -> None:
"""
Save the VisualizationInfo and related objects to a BCF zip file.
Args:
bcf_zip: The BCF zip file to save to.
topic_dir: The directory in the BCF zip file to save to.
vpt: The ViewPoint to save.
"""
if not (vp_name := vpt.viewpoint):
return
self._save_visinfo(bcf_zip, topic_dir, vp_name)
self._save_snapshot(bcf_zip, topic_dir, vpt.snapshot)
self._save_bitmaps(bcf_zip, topic_dir)
def _save_snapshot(self, bcf_zip: ZipFileInterface, topic_dir: str, filename: Optional[str]) -> None:
if self.snapshot and filename:
bcf_zip.writestr(f"{topic_dir}/{filename}", self.snapshot)
def _save_visinfo(self, bcf_zip: ZipFileInterface, topic_dir: str, vp_name: str) -> None:
bcf_zip.writestr(
f"{topic_dir}/{vp_name}",
self._xml_handler.serialize(self.visualization_info),
)
def _save_bitmaps(self, bcf_zip: ZipFileInterface, topic_dir: str) -> None:
if not self.bitmaps:
return
if not (bitmaps_defs := self.visualization_info.bitmap):
return
for bitmap_def in bitmaps_defs:
if not (bitmap_name := bitmap_def.reference):
continue
if bitmap_name in self.bitmaps:
bcf_zip.writestr(f"{topic_dir}/{bitmap_name}", self.bitmaps[bitmap_name])
@classmethod
def create_new(
cls,
element: entity_instance,
xml_handler: Optional[AbstractXmlParserSerializer] = None,
) -> "VisualizationInfoHandler":
"""
Create a new VisualizationInfoHandler object from an IFC element.
Args:
element: The IFC element to point at.
xml_handler: The XML handler to use.
Returns:
The VisualizationInfoHandler object.
"""
xml_handler = xml_handler or XmlParserSerializer()
return cls(visualization_info=build_viewpoint(element), xml_handler=xml_handler)
@classmethod
def create_from_point_and_guids(
cls,
position: NDArray[np.float_],
*guids: str,
xml_handler: Optional[AbstractXmlParserSerializer] = None,
) -> "VisualizationInfoHandler":
"""
Create a new VisualizationInfoHandler object from an IFC element.
Args:
position: target point coordinates.
*guids: One or more IFC element GUID.
xml_handler: The XML handler to use.
Returns:
The VisualizationInfoHandler object.
"""
xml_handler = xml_handler or XmlParserSerializer()
return cls(
visualization_info=build_viewpoint_from_position_and_guids(position, *guids), xml_handler=xml_handler
)
@lru_cache(maxsize=None)
def build_viewpoint(element: entity_instance) -> mdl.VisualizationInfo:
"""
Return a BCF viewpoint of an IFC element.
This function is cached to speedudp the creation of multiple BCF topics regarding the same element.
Args:
element: The IFC element to point at.
Returns:
The BCF viewpoint definition.
"""
ifc_file = element.wrapped_data.file
unit_scale = ifcopenshell.util.unit.calculate_unit_scale(ifc_file)
elem_placement = ifcopenshell.util.placement.get_local_placement(element.ObjectPlacement)
elem_placement[0][3] *= unit_scale
elem_placement[1][3] *= unit_scale
elem_placement[2][3] *= unit_scale
return mdl.VisualizationInfo(
guid=str(uuid.uuid4()),
components=build_components(element.GlobalId),
perspective_camera=build_camera(elem_placement),
)
def build_viewpoint_from_position_and_guids(position: NDArray[np.float_], *guids: str) -> mdl.VisualizationInfo:
"""
Return a BCF viewpoint of an IFC element.
This function is cached to speedudp the creation of multiple BCF topics regarding the same element.
Args:
position: target point coordinates.
*guids: One or more IFC element GUID.
Returns:
The BCF viewpoint definition.
"""
return mdl.VisualizationInfo(
guid=str(uuid.uuid4()),
components=build_components(*guids),
perspective_camera=build_camera_from_vectors(*camera_vectors_from_target_position(position)),
)
def build_components(*guids: str) -> mdl.Components:
"""
Return the BCF components from an IFC element GUID.
Args:
*guids: One or more IFC element GUID.
Returns:
The BCF components definition.
"""
components = [mdl.Component(ifc_guid=guid) for guid in guids]
return mdl.Components(
selection=mdl.ComponentSelection(component=components),
visibility=mdl.ComponentVisibility(default_visibility=True),
)
def build_camera(elem_placement: NDArray[np.float_]) -> mdl.PerspectiveCamera:
"""
Return a BCF camera for an IFC element placement matrix.
Args:
elem_placement: The IFC element placement as a rototranslation matrix.
Returns:
The BCF camera definition.
"""
return build_camera_from_vectors(*camera_vectors_from_element_placement(elem_placement))
def build_camera_from_vectors(
camera_position: NDArray[np.float_], camera_dir: NDArray[np.float_], camera_up: NDArray[np.float_]
) -> mdl.PerspectiveCamera:
"""
Return a BCF camera for an IFC element placement matrix.
Args:
camera_position: camera position array
camera_dir: camera direction versor
camera_up_vector: camera up versor
Returns:
The BCF camera definition.
"""
camera_viewpoint = mdl.Point(x=camera_position[0], y=camera_position[1], z=camera_position[2])
camera_direction = mdl.Direction(x=camera_dir[0], y=camera_dir[1], z=camera_dir[2])
camera_up_vector = mdl.Direction(x=camera_up[0], y=camera_up[1], z=camera_up[2])
return mdl.PerspectiveCamera(
camera_view_point=camera_viewpoint,
camera_direction=camera_direction,
camera_up_vector=camera_up_vector,
field_of_view=60.0,
)
-154
View File
@@ -1,154 +0,0 @@
<?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
@@ -1,18 +0,0 @@
<?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
@@ -1,12 +0,0 @@
<?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
@@ -1,191 +0,0 @@
<?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>
-1
View File
@@ -1 +0,0 @@
"""BCF XML v3 handler."""
-591
View File
@@ -1,591 +0,0 @@
# BCF - BCF Python library
# Copyright (C) 2021 Prabhat Singh <singh01prabhat@gmail.com>
#
# This file is part of BCF.
#
# BCF is free software: you can redistribute it and/or modify
# it under the terms of the GNU Lesser General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# BCF is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public License
# along with BCF. If not, see <http://www.gnu.org/licenses/>.
import base64
import http.server
import os
import tempfile
import time
import urllib
import uuid
import webbrowser
from re import A
from typing import Any, Optional, Tuple
import requests
client_id, client_secret = "", ""
class OAuthReceiver(http.server.BaseHTTPRequestHandler):
def do_GET(self) -> None:
query = urllib.parse.parse_qs(urllib.parse.urlparse(self.path).query)
self.server.auth_code = query.get("code", [""])[0] # type:ignore
self.server.auth_state = query.get("state", [""])[0] # type:ignore
self.send_response(200)
self.send_header("Content-type", "text/plain")
self.end_headers()
self.wfile.write("You have now authenticated :) You may now close this browser window.".encode("utf-8"))
class FoundationClient:
def __init__(
self, client_id: str, client_secret: str, base_url: Optional[str] = None, redirect_subdir: Optional[str] = None
) -> None:
self.baseurl = base_url
self.access_token = ""
self.refresh_token = ""
self.access_token_expires_on = time.time()
self.refresh_token_expires_on = float("inf")
self.token_endpoint = ""
self.client_id = client_id
self.client_secret = client_secret
self.auth_method: Optional[str] = None
self.redirect_subdir = redirect_subdir
def get_access_token(self) -> str:
if self.access_token and self.access_token_expires_on > time.time():
return self.access_token
elif self.refresh_token and self.refresh_token_expires_on > time.time():
self.get_refresh_token()
else:
self.login()
return self.access_token
def get_auth_methods(self) -> list[Any]:
resp = requests.get(f"{self.baseurl}foundation/1.0/auth")
return resp.json()["supported_oauth2_flows"]
def get_versions(self) -> list[Any]:
resp = requests.get(f"{self.baseurl}foundation/versions")
return resp.json()["versions"]
def login(self) -> None:
resp = requests.get(f"{self.baseurl}foundation/1.0/auth")
values = resp.json()
auth_endpoint = values["oauth2_auth_url"]
self.token_endpoint = values["oauth2_token_url"]
with http.server.HTTPServer(("", 8080), OAuthReceiver) as server:
state = str(uuid.uuid4())
query = urllib.parse.urlencode(
{
"client_id": self.client_id,
"response_type": "code",
"state": state,
"redirect_uri": f"http://localhost:{server.server_address[1]}/{self.redirect_subdir}",
}
)
if "?" in auth_endpoint:
webbrowser.open(f"{auth_endpoint}&{query}")
else:
webbrowser.open(f"{auth_endpoint}?{query}")
server.timeout = 100
server.handle_request()
if server.auth_code and server.auth_state == state: # pylint: disable=E1101
data = {
"grant_type": "authorization_code",
"code": server.auth_code, # pylint: disable=E1101 type:ignore
"redirect_uri": f"http://localhost:{server.server_address[1]}/{self.redirect_subdir}",
}
headers = self._get_access_token_headers()
self.set_tokens_from_response(requests.post(self.token_endpoint, data=data, headers=headers))
def get_refresh_token(self) -> None:
self.set_tokens_from_response(
requests.post(
self.token_endpoint,
params={
"grant_type": "refresh_token",
"refresh_token": self.refresh_token,
},
).json()
)
def get_new_access_token(self) -> None:
headers = self._get_access_token_headers()
self.set_tokens_from_response(
requests.post(
self.token_endpoint,
data={
"grant_type": "refresh_token",
"refresh_token": self.refresh_token,
},
headers=headers,
).json()
)
def _get_access_token_headers(self) -> dict[str, str]:
auth_string = f"{self.client_id}:{self.client_secret}"
header_string = base64.b64encode(auth_string.encode("utf-8")).decode("utf-8")
return {"Authorization": f"Basic {header_string}"}
def set_auth_method(self, method: str = "authorization_code_grant") -> None:
if method != "authorization_code_grant":
raise NotImplementedError(f"{method} not supported")
else:
self.auth_method = method
def set_tokens_from_response(self, response: requests.Response) -> None:
response_dict = response.json()
self.access_token = response_dict["access_token"]
self.refresh_token = response_dict["refresh_token"]
self.access_token_expires_on = time.time() + response_dict["expires_in"]
if "refresh_token_expires_in" in response_dict:
self.refresh_token_expires_on = time.time() + response_dict["refresh_token_expires_in"]
class BcfClient:
def __init__(self, foundation_client: FoundationClient) -> None:
self.foundation_client = foundation_client
self.version_id: Optional[str] = None
self.baseurl: Optional[str] = None
self.filepath = tempfile.mkdtemp()
def set_version(self, version: dict[str, str]) -> None:
self.version_id = version["version_id"]
self.baseurl = version["api_base_url"]
def get(self, endpoint: str, params: Any = None, is_auth_required: bool = False) -> Any:
# TODO: handle error http status codes and raise exception. Follow error.json standard.
headers = {"Authorization": f"Bearer {self.foundation_client.get_access_token()}"}
response = requests.get(f"{self.baseurl}{endpoint}", headers=headers, params=params or None)
try:
response = requests.get(f"{self.baseurl}{endpoint}", headers=headers, params=params or None)
if response.status_code == 200:
return response.json()
response.raise_for_status()
except requests.exceptions.HTTPError as e:
print(f"message: {response.reason}' '{response.status_code}' '{ e }")
def post(self, endpoint: str, data: Any = None, params: Any = None) -> Tuple[int, str]:
headers = {
"Authorization": f"Bearer {self.foundation_client.get_access_token()}",
"Content-type": "application/json",
}
try:
response = requests.post(
f"{self.baseurl}{endpoint}", headers=headers, params=params or None, data=data or None
)
if response.status_code != 201:
response.raise_for_status()
return response.status_code, response.text
except requests.exceptions.HTTPError as errh:
print(f"message: {response.reason}' '{response.status_code}, {errh}")
return response.status_code, response.reason
def put(self, endpoint: str, data: Any = None, params: Any = None) -> Tuple[int, str]:
headers = {
"Authorization": f"Bearer {self.foundation_client.get_access_token()}",
"Content-type": "application/json",
}
try:
response = requests.put(
f"{self.baseurl}{endpoint}", headers=headers, params=params or None, data=data or None
)
if response.status_code != 200:
response.raise_for_status()
return response.status_code, response.text
except requests.exceptions.HTTPError as errh:
print(f"message: {response.reason}' '{response.status_code}, {errh}")
return response.status_code, response.reason
def delete(self, endpoint: str, params: Any = None) -> Tuple[int, str]:
headers = {
"Authorization": f"Bearer {self.foundation_client.get_access_token()}",
"Content-type": "application/json",
}
try:
response = requests.delete(f"{self.baseurl}{endpoint}", headers=headers, params=params or None)
if response.status_code != 200:
response.raise_for_status()
return response.status_code, response.text
except requests.exceptions.HTTPError as errh:
print(f"message: {response.reason}' '{response.status_code}, {errh}")
return response.status_code, response.reason
def get_projects(self) -> list[Any]:
return self.get("/projects")
def get_project(self, project_id: str = "") -> dict[str, Any]:
return self.get(
f"/projects/{project_id}",
{
"project_id": project_id,
},
)
def update_project(self, project_id: str = "", data: Any = None) -> Tuple[int, str]:
url = f"{self.baseurl}/projects/{project_id}"
headers = {"Authorization": f"Bearer {self.foundation_client.get_access_token()}"}
resp = requests.put(url, headers=headers, data=data)
return resp.status_code, resp.text
def get_extensions(self, project_id: str = "") -> dict[str, Any]:
return self.get(
f"/projects/{project_id}/extensions",
{
"project_id": project_id,
},
)
def get_topics(
self,
project_id: str = "",
topics: str = "",
query_string: Optional[str] = None,
) -> list[Any]:
# return self.get(
# f"/projects/{project_id}/topics",
# {
# "project_id": project_id,
# "topics": topics,
# "query_string": query_string,
# },
# )
pass
def get_topic(self, project_id: str = "", topic_id: str = "") -> dict[str, Any]:
return self.get(
f"/projects/{project_id}/topics/{topic_id}",
{
"project_id": project_id,
"topic_id": topic_id,
},
)
def create_topic(self, project_id: str = "", data: Any = None) -> Tuple[int, str]:
return self.post(f"/projects/{project_id}/topics", data=data)
def update_topic(self, project_id: str = "", topic_id: str = "", data: Any = None) -> Tuple[int, str]:
return self.put(f"/projects/{project_id}/topics/{topic_id}", data=data)
def delete_topic(self, project_id: str = "", topic_id: str = "") -> Tuple[int, str]:
return self.delete(f"/projects/{project_id}/topics/{topic_id}")
def get_snippet(self, project_id: str = "", topic_id: str = "") -> Tuple[int, str]:
headers = {
"Authorization": f"Bearer {self.foundation_client.get_access_token()}",
"Content-type": "application/octet-stream",
}
response = requests.get(f"{self.baseurl}/projects/{project_id}/topics/{topic_id}/snippet", headers=headers)
content = response.content.decode("utf-8")
with open(os.path.join(self.filepath, f"{project_id}_{topic_id}_snippet.txt"), "w") as f:
f.write(content)
return response.status_code, content
def update_snippet(self, project_id: str = "", topic_id: str = "", files: Any = None, data: Any = None) -> int:
headers = {
"Authorization": f"Bearer {self.foundation_client.get_access_token()}",
"Content-type": "application/octet-stream",
}
response = requests.put(
f"{self.baseurl}/projects/{project_id}/topics/{topic_id}/snippet", headers=headers, files=files
)
return response.status_code
def get_files_information(self, project_id: str = "") -> list[Any]:
return self.get(
f"/projects/{project_id}/files_information",
{
"project_id": project_id,
},
)
def get_files(self, project_id: str = "", topic_id: str = "") -> list[Any]:
return self.get(
f"/projects/{project_id}/topics/{topic_id}/files",
{
"project_id": project_id,
"topic_id": topic_id,
},
)
def update_files(
self,
project_id: str = "",
topic_id: str = "",
data: Any = None,
params: Any = None,
) -> Tuple[int, str]:
return self.put(
f"/projects/{project_id}/topics/{topic_id}/files",
data=data,
)
def get_comments(self, project_id: str = "", topic_id: str = "") -> None:
pass
def create_comments(
self,
project_id: str = "",
topic_id: str = "",
data: Any = None,
params: Any = None,
) -> Tuple[int, str]:
return self.post(
f"/projects/{project_id}/topics/{topic_id}/comments",
data=data,
)
def get_comment(self, project_id: str = "", topic_id: str = "", comment_id: str = "") -> dict[str, Any]:
return self.get(
f"/projects/{project_id}/topics/{topic_id}/comments/{comment_id}",
{
"project_id": project_id,
"topic_id": topic_id,
"comment_id": comment_id,
},
)
def delete_comment(self, project_id: str = "", topic_id: str = "", comment_id: str = "") -> Tuple[int, str]:
return self.delete(f"/projects/{project_id}/topics/{topic_id}/comments/{comment_id}")
def update_comment(
self,
project_id: str = "",
topic_id: str = "",
comment_id: str = "",
data: Any = None,
) -> Tuple[int, str]:
return self.put(
f"/projects/{project_id}/topics/{topic_id}/comments/{comment_id}",
data=data,
)
def get_viewpoints(self, project_id: str = "", topic_id: str = "") -> list[Any]:
return self.get(
f"/projects/{project_id}/topics/{topic_id}/viewpoints",
{
"project_id": project_id,
"topic_id": topic_id,
},
)
def create_viewpoints(self, project_id: str = "", topic_id: str = "", data: Any = None) -> Tuple[int, str]:
return self.post(
f"/projects/{project_id}/topics/{topic_id}/viewpoints",
data=data,
)
def get_viewpoint(self, project_id: str = "", topic_id: str = "", viewpoint_id: str = "") -> dict[str, Any]:
return self.get(
f"/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}",
{
"project_id": project_id,
"topic_id": topic_id,
"viewpoint_id": viewpoint_id,
},
)
def delete_viewpoint(
self,
project_id: str = "",
topic_id: str = "",
viewpoint_id: str = "",
) -> Tuple[int, str]:
return self.delete(
f"/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}",
)
def get_snapshot(self, project_id: str = "", topic_id: str = "", viewpoint_id: str = "") -> str:
return self.get(
f"/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}/snapshot",
{
"project_id": project_id,
"topic_id": topic_id,
"viewpoint_id": viewpoint_id,
},
)
def get_bitmap(self, project_id: str = "", topic_id: str = "", viewpoint_id: str = "", bitmap_id: str = "") -> str:
return self.get(
f"/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}/bitmaps/{bitmap_id}",
{
"project_id": project_id,
"topic_id": topic_id,
"viewpoint_id": viewpoint_id,
"bitmap_id": bitmap_id,
},
)
def get_selection(self, project_id: str = "", topic_id: str = "", viewpoint_id: str = "") -> dict[str, Any]:
return self.get(
f"/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}/selection",
{
"project_id": project_id,
"topic_id": topic_id,
"viewpoint_id": viewpoint_id,
},
)
def get_coloring(self, project_id: str = "", topic_id: str = "", viewpoint_id: str = "") -> dict[str, Any]:
return self.get(
f"/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}/coloring",
{
"project_id": project_id,
"topic_id": topic_id,
"viewpoint_id": viewpoint_id,
},
)
def get_visibility(self, project_id: str = "", topic_id: str = "", viewpoint_id: str = "") -> dict[str, Any]:
return self.get(
f"/projects/{project_id}/topics/{topic_id}/viewpoints/{viewpoint_id}/visibility",
{
"project_id": project_id,
"topic_id": topic_id,
"viewpoint_id": viewpoint_id,
},
)
def get_related_topics(self, project_id: str = "", topic_id: str = "") -> list[Any]:
return self.get(
f"/projects/{project_id}/topics/{topic_id}/related_topics",
{
"project_id": project_id,
"topic_id": topic_id,
},
)
def update_related_topics(
self,
project_id: str = "",
topic_id: str = "",
data: Any = None,
) -> Tuple[int, str]:
return self.put(
f"/projects/{project_id}/topics/{topic_id}/related_topics",
data=data,
)
def get_document_references(self, project_id: str = "", topic_id: str = "") -> list[Any]:
return self.get(
f"/projects/{project_id}/topics/{topic_id}/document_references",
{
"project_id": project_id,
"topic_id": topic_id,
},
)
def create_document_reference(
self,
project_id: str = "",
topic_id: str = "",
data: Any = None,
) -> Tuple[int, str]:
return self.post(
f"/projects/{project_id}/topics/{topic_id}/document_references",
data=data,
)
def update_document_references(
self,
project_id: str = "",
topic_id: str = "",
document_reference_id: str = "",
data: Any = None,
) -> Tuple[int, str]:
return self.put(
f"/projects/{project_id}/topics/{topic_id}/document_references/{document_reference_id}",
data=data,
)
def get_documents(self, project_id: str = "", topic_id: str = "") -> list[Any]:
return self.get(
f"/projects/{project_id}/topics/{topic_id}/documents",
{
"project_id": project_id,
"topic_id": topic_id,
},
)
def create_document(
self, project_id: str = "", topic_id: str = "", guid: Optional[str] = None, files: Any = None, data: Any = None
) -> int:
headers = {
"Authorization": f"Bearer {self.foundation_client.get_access_token()}",
"Content-type": "application/octet-stream",
}
response = requests.post(
f"/projects/{project_id}/topics/{topic_id}/documents",
data=data,
params={"guid": guid},
files=files,
headers=headers,
)
return response.status_code
def get_document(self, project_id: str = "", topic_id: str = "", document_id: str = "") -> Tuple[int, str]:
headers = {
"Authorization": f"Bearer {self.foundation_client.get_access_token()}",
"Content-type": "application/octet-stream",
}
response = requests.get(f"{self.baseurl}/projects/{project_id}/topics/documents/{document_id}", headers=headers)
content = response.content.decode("utf-8")
with open(os.path.join(self.filepath, f"{project_id}_{topic_id}_{document_id}_document.txt"), "w") as f:
f.write(content)
return response.status_code, content
def get_topics_events(self, project_id: str = "") -> list[Any]:
return self.get(
f"/projects/{project_id}/topics/events",
{
"project_id": project_id,
},
)
def get_topic_events(self, project_id: str = "", topic_id: str = "") -> list[Any]:
return self.get(
f"/projects/{project_id}/topics/{topic_id}/events",
{
"project_id": project_id,
"topic_id": topic_id,
},
)
def get_comments_events(self, project_id: str = "") -> list[Any]:
return self.get(
f"/projects/{project_id}/topics/comments/events",
{
"project_id": project_id,
},
)
def get_comment_events(self, project_id: str = "", topic_id: str = "", comment_id: str = "") -> list[Any]:
return self.get(
f"/projects/{project_id}/topics/{topic_id}/comments/{comment_id}/events",
{
"project_id": project_id,
"topic_id": topic_id,
"comment_id": comment_id,
},
)
-291
View File
@@ -1,291 +0,0 @@
"""BCF XML V3 handlers."""
import uuid
import warnings
import zipfile
from pathlib import Path
from typing import Any, NoReturn, Optional, TypeVar
import bcf.v3.model as mdl
from bcf.inmemory_zipfile import InMemoryZipFile, ZipFileInterface
from bcf.v3.document import DocumentsHandler
from bcf.v3.topic import TopicHandler
from bcf.xml_parser import AbstractXmlParserSerializer, XmlParserSerializer
T = TypeVar("T")
class BcfXml:
"""BCF XML handler."""
def __init__(
self, filename: Optional[Path] = None, xml_handler: Optional[AbstractXmlParserSerializer] = None
) -> None:
self._filename = filename
self._xml_handler = xml_handler or XmlParserSerializer()
self._version: Optional[mdl.Version] = None
self._project_info: Optional[mdl.ProjectInfo] = None
self._extensions: Optional[mdl.Extensions] = None
self._topics: dict[str, TopicHandler] = {}
self._documents: Optional[DocumentsHandler] = None
self._zip_file = self._load_zip_file()
def __enter__(self) -> "BcfXml":
return self
def __exit__(self, *args: Any) -> None:
self.close()
def __del__(self) -> None:
self.close()
def close(self) -> None:
if self._zip_file:
self._zip_file.close()
def _load_zip_file(self) -> Optional[zipfile.ZipFile]:
return zipfile.ZipFile(self._filename) if self._filename else None
@property
def version(self) -> mdl.Version:
"""Bcf Version."""
if not self._version:
self._version = (
self._xml_handler.parse(self._zip_file.read("bcf.version"), mdl.Version)
if self._zip_file
else mdl.Version(version_id="3.0")
)
return self._version
@version.setter
def version(self, value: mdl.Version) -> None:
self._version = value
@property
def project_info(self) -> Optional[mdl.ProjectInfo]:
"""BCF project information."""
if not self._project_info and self._zip_file and zipfile.Path(self._zip_file, "project.bcfp").exists():
self._project_info = self._xml_handler.parse(self._zip_file.read("project.bcfp"), mdl.ProjectInfo)
return self._project_info
@project_info.setter
def project_info(self, value: Optional[mdl.ProjectInfo]) -> None:
self._project_info = value
@property
def project(self) -> Optional[mdl.Project]:
"""BCF project."""
return self.project_info.project if self.project_info else None
@property
def extensions(self) -> Optional[mdl.Extensions]:
"""BCF extensions."""
if not self._extensions and self._zip_file:
self._extensions = self._xml_handler.parse(self._zip_file.read("extensions.xml"), mdl.Extensions)
return self._extensions
@extensions.setter
def extensions(self, value: Optional[mdl.Extensions]) -> None:
self._extensions = value
@property
def topics(self) -> dict[str, TopicHandler]:
"""BCF topics."""
if not self._topics and self._zip_file:
self._load_topics()
return self._topics
def _load_topics(self) -> None:
for topic_dir in zipfile.Path(self._zip_file).iterdir():
if not topic_dir.is_dir():
continue
markup_path = topic_dir.joinpath("markup.bcf")
if not markup_path.exists():
continue
self._topics[topic_dir.name] = TopicHandler(topic_dir, self._xml_handler)
@property
def documents(self) -> Optional[DocumentsHandler]:
"""Documents stored in the BCF file."""
if not self._documents and self._zip_file:
self._documents = DocumentsHandler.load(self._zip_file, self._xml_handler)
return self._documents
@classmethod
def load(cls, filename: Path, xml_handler: Optional[AbstractXmlParserSerializer] = None) -> Optional["BcfXml"]:
"""
Create a BcfXml object from a file.
Args:
filename: Path to the file.
xml_handler: XML parser and serializer.
Returns:
A BcfXml object with the file contents.
Raises:
ValueError: If the file name is null or empty
"""
if not filename:
raise ValueError("filename is required")
xml_handler = xml_handler or XmlParserSerializer()
return cls(xml_handler=xml_handler, filename=filename)
@classmethod
def create_new(
cls,
project_name: Optional[str] = None,
extensions: Optional[mdl.Extensions] = None,
xml_handler: Optional[AbstractXmlParserSerializer] = None,
) -> "BcfXml":
"""
Create a new BcfXml object.
Args:
project_name: The name of the project.
extensions: The Extension XML object. Defaults to an empty one.
xml_handler: XML parser and serializer.
Returns:
A new BcfXml object.
"""
instance = cls(xml_handler=xml_handler or XmlParserSerializer())
instance.project_info = mdl.ProjectInfo(project=mdl.Project(name=project_name, project_id=str(uuid.uuid4())))
instance.extensions = extensions or mdl.Extensions()
return instance
def save(self, filename: Optional[Path] = None, keep_open: bool = False) -> None:
"""Save the BCF file to the given filename."""
if not filename and not self._filename:
raise ValueError("No file name specified, cannot save BCF file.")
if filename:
self._filename = filename
with InMemoryZipFile(self._filename) as bcf_zip:
self._save_project(bcf_zip)
self._save_version(bcf_zip)
self._save_extensions(bcf_zip)
self._save_documents(bcf_zip)
self._save_topics(bcf_zip)
if keep_open:
self._zip_file = self._load_zip_file()
def _save_project(self, destination_zip: ZipFileInterface) -> None:
self._smart_save_xml(destination_zip, self._project_info, "project.bcfp")
def _save_version(self, destination_zip: ZipFileInterface) -> None:
if not self._version and self._zip_file:
destination_zip.writestr("bcf.version", self._zip_file.read("bcf.version"))
else:
self._save_xml(destination_zip, "bcf.version", self.version)
def _save_extensions(self, destination_zip: ZipFileInterface) -> None:
self._smart_save_xml(destination_zip, self._extensions, "extensions.xml")
def _smart_save_xml(self, destination_zip: ZipFileInterface, item: Any, target: str) -> None:
if item:
self._save_xml(destination_zip, target, item)
elif self._zip_file and zipfile.Path(self._zip_file, target).exists():
destination_zip.writestr(target, self._zip_file.read(target))
def _save_xml(self, destination_zip: ZipFileInterface, inner_file: str, xml_obj: Any) -> None:
destination_zip.writestr(inner_file, self._xml_handler.serialize(xml_obj))
def _save_documents(self, bcf_zip: ZipFileInterface) -> None:
if self.documents:
self.documents.save(bcf_zip)
def _save_topics(self, destination_zip: ZipFileInterface) -> None:
for topic_handler in self.topics.values():
topic_handler.save(destination_zip)
def add_topic(
self, title: str, description: str, author: str, topic_type: str = "", topic_status: str = ""
) -> TopicHandler:
"""
Add a new topic to the BCF.
Args:
title: The title of the topic.
description: The description of the topic.
author: The author of the topic.
topic_type: The type of the topic.
topic_status: The status of the topic.
Returns:
The newly created topic wrapped inside a TopicHandler object.
"""
topic_handler = TopicHandler.create_new(
title,
description,
author,
topic_type=topic_type,
topic_status=topic_status,
xml_handler=self._xml_handler,
)
self.topics[topic_handler.guid] = topic_handler
return topic_handler
def __eq__(self, other: object) -> bool | NoReturn:
return (
self.version == other.version
and self.project_info == other.project_info
and self.extensions == other.extensions
if isinstance(other, BcfXml)
else NotImplemented
)
# region Deprecated methods
def new_project(self) -> "BcfXml":
"""Deprecated method."""
warnings.warn("new_project is deprecated, use create_new instead.", DeprecationWarning)
return self.create_new()
def get_project(self, _filepath: Optional[str] = None) -> Optional[mdl.Project]:
"""Deprecated method."""
warnings.warn("get_project is deprecated, use project_info.project instead.", DeprecationWarning)
return self.project
def edit_project(self) -> None:
"""Deprecated method."""
warnings.warn("edit_project is deprecated, there's no need to use it.", DeprecationWarning)
def save_project(self, filepath: Path) -> None:
"""Deprecated method."""
warnings.warn("save_project is deprecated, use save instead.", DeprecationWarning)
self.save(filepath)
def get_version(self) -> str:
warnings.warn("get_version is deprecated, use version.version_id instead.", DeprecationWarning)
return self.version.version_id
def edit_version(self) -> None:
"""Deprecated method."""
warnings.warn("edit_version is deprecated, there's no need to use it.", DeprecationWarning)
def get_topics(self) -> dict[str, TopicHandler]:
"""Deprecated method."""
warnings.warn("get_topics is deprecated, use topics instead.", DeprecationWarning)
return self.topics
def get_topic(self, guid: str) -> TopicHandler:
"""Return a topic by its GUID."""
warnings.warn("get_topic is deprecated, use topics[guid] instead", DeprecationWarning)
return self.topics[guid]
def get_header(self, guid: str) -> Optional[mdl.Header]:
"""Return the header of a Topic by its GUID."""
return self.topics[guid].header
def edit_topic(self) -> None:
"""Deprecated method."""
warnings.warn("edit_topic is deprecated, there's no need to use it.", DeprecationWarning)
def add_comment(self, _topic: mdl.Topic, _comment: Optional[mdl.Comment] = None) -> None:
"""Deprecated method."""
warnings.warn("add_comment is deprecated, use topics methods instead.", DeprecationWarning)
def edit_comment(self) -> None:
"""Deprecated method."""
warnings.warn("edit_comment is deprecated, there's no need to use it.", DeprecationWarning)
# TODO: deprecate other methods
# endregion
-61
View File
@@ -1,61 +0,0 @@
"""BCF XML V3 Documents handler."""
import zipfile
from typing import Any, Optional
import bcf.v3.model as mdl
from bcf.inmemory_zipfile import ZipFileInterface
from bcf.xml_parser import AbstractXmlParserSerializer, XmlParserSerializer
class DocumentsHandler:
"""BCF documents handler."""
def __init__(
self,
definition: mdl.DocumentInfo,
documents: Optional[dict[str, bytes]] = None,
xml_handler: Optional[AbstractXmlParserSerializer] = None,
) -> None:
self.definition = definition
self.documents = documents or {}
self._xml_handler = xml_handler or XmlParserSerializer()
@classmethod
def load(
cls,
zip_file: zipfile.ZipFile,
xml_handler: Optional[AbstractXmlParserSerializer] = None,
) -> Optional["DocumentsHandler"]:
"""
Loads the documents from the given zip file directory.
Args:
zip_path: The directory path inside the zip file.
xml_handler: The xml parser/serializer to use.
Returns:
The documents handler.
"""
xml_handler = xml_handler or XmlParserSerializer()
file_to_open = zipfile.Path(zip_file, "documents.xml")
if not file_to_open.exists():
return None
definition = xml_handler.parse(file_to_open.read_bytes(), mdl.DocumentInfo)
documents = {}
if def_docs := definition.documents:
for document in def_docs.document:
document_path = zipfile.Path(zip_file, f"documents/{document.guid}")
if document_path.exists():
documents[document.filename] = document_path.read_bytes()
return cls(definition, documents=documents)
def save(self, bcf_zip: ZipFileInterface) -> None:
"""Save the documents to the zip file."""
bcf_zip.writestr("documents.xml", self._xml_handler.serialize(self.definition))
if documents := self.definition.documents:
for doc in documents.document:
if doc.filename in self.documents:
bcf_zip.writestr(
f"documents/{doc.guid}",
self.documents[doc.filename],
)
-110
View File
@@ -1,110 +0,0 @@
from bcf.v3.model.documents import Document, DocumentInfo, DocumentInfoDocuments
from bcf.v3.model.extensions import (
Extensions,
ExtensionsPriorities,
ExtensionsSnippetTypes,
ExtensionsStages,
ExtensionsTopicLabels,
ExtensionsTopicStatuses,
ExtensionsTopicTypes,
ExtensionsUsers,
)
from bcf.v3.model.markup import (
BimSnippet,
Comment,
CommentViewpoint,
DocumentReference,
File,
Header,
HeaderFiles,
Markup,
Topic,
TopicComments,
TopicDocumentReferences,
TopicLabels,
TopicReferenceLinks,
TopicRelatedTopics,
TopicRelatedTopicsRelatedTopic,
TopicViewpoints,
ViewPoint,
)
from bcf.v3.model.project import Project, ProjectInfo
from bcf.v3.model.version import Version
from bcf.v3.model.visinfo import (
Bitmap,
BitmapFormat,
ClippingPlane,
Component,
ComponentColoring,
ComponentColoringColor,
ComponentColoringColorComponents,
Components,
ComponentSelection,
ComponentVisibility,
ComponentVisibilityExceptions,
Direction,
Line,
OrthogonalCamera,
PerspectiveCamera,
Point,
ViewSetupHints,
VisualizationInfo,
VisualizationInfoBitmaps,
VisualizationInfoClippingPlanes,
VisualizationInfoLines,
)
__all__ = [
"Document",
"DocumentInfo",
"DocumentInfoDocuments",
"Extensions",
"ExtensionsPriorities",
"ExtensionsSnippetTypes",
"ExtensionsStages",
"ExtensionsTopicLabels",
"ExtensionsTopicStatuses",
"ExtensionsTopicTypes",
"ExtensionsUsers",
"BimSnippet",
"Comment",
"CommentViewpoint",
"DocumentReference",
"File",
"Header",
"HeaderFiles",
"Markup",
"Topic",
"TopicComments",
"TopicDocumentReferences",
"TopicLabels",
"TopicReferenceLinks",
"TopicRelatedTopics",
"TopicRelatedTopicsRelatedTopic",
"TopicViewpoints",
"ViewPoint",
"Project",
"ProjectInfo",
"Version",
"Bitmap",
"BitmapFormat",
"ClippingPlane",
"Component",
"ComponentColoring",
"ComponentColoringColor",
"ComponentColoringColorComponents",
"ComponentSelection",
"ComponentVisibility",
"ComponentVisibilityExceptions",
"Components",
"Direction",
"Line",
"OrthogonalCamera",
"PerspectiveCamera",
"Point",
"ViewSetupHints",
"VisualizationInfo",
"VisualizationInfoBitmaps",
"VisualizationInfoClippingPlanes",
"VisualizationInfoLines",
]
-61
View File
@@ -1,61 +0,0 @@
from dataclasses import dataclass, field
from typing import List, Optional
@dataclass(slots=True, kw_only=True)
class Document:
filename: str = field(
metadata={
"name": "Filename",
"type": "Element",
"namespace": "",
"required": True,
"min_length": 1,
"white_space": "collapse",
}
)
description: Optional[str] = field(
default=None,
metadata={
"name": "Description",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
}
)
guid: str = field(
metadata={
"name": "Guid",
"type": "Attribute",
"required": True,
"pattern": r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}",
}
)
@dataclass(slots=True, kw_only=True)
class DocumentInfoDocuments:
class Meta:
global_type = False
document: List[Document] = field(
default_factory=list,
metadata={
"name": "Document",
"type": "Element",
"namespace": "",
}
)
@dataclass(slots=True, kw_only=True)
class DocumentInfo:
documents: Optional[DocumentInfoDocuments] = field(
default=None,
metadata={
"name": "Documents",
"type": "Element",
"namespace": "",
}
)
-181
View File
@@ -1,181 +0,0 @@
from dataclasses import dataclass, field
from typing import List, Optional
@dataclass(slots=True, kw_only=True)
class ExtensionsPriorities:
class Meta:
global_type = False
priority: List[str] = field(
default_factory=list,
metadata={
"name": "Priority",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
}
)
@dataclass(slots=True, kw_only=True)
class ExtensionsSnippetTypes:
class Meta:
global_type = False
snippet_type: List[str] = field(
default_factory=list,
metadata={
"name": "SnippetType",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
}
)
@dataclass(slots=True, kw_only=True)
class ExtensionsStages:
class Meta:
global_type = False
stage: List[str] = field(
default_factory=list,
metadata={
"name": "Stage",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
}
)
@dataclass(slots=True, kw_only=True)
class ExtensionsTopicLabels:
class Meta:
global_type = False
topic_label: List[str] = field(
default_factory=list,
metadata={
"name": "TopicLabel",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
}
)
@dataclass(slots=True, kw_only=True)
class ExtensionsTopicStatuses:
class Meta:
global_type = False
topic_status: List[str] = field(
default_factory=list,
metadata={
"name": "TopicStatus",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
}
)
@dataclass(slots=True, kw_only=True)
class ExtensionsTopicTypes:
class Meta:
global_type = False
topic_type: List[str] = field(
default_factory=list,
metadata={
"name": "TopicType",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
}
)
@dataclass(slots=True, kw_only=True)
class ExtensionsUsers:
class Meta:
global_type = False
user: List[str] = field(
default_factory=list,
metadata={
"name": "User",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
}
)
@dataclass(slots=True, kw_only=True)
class Extensions:
topic_types: Optional[ExtensionsTopicTypes] = field(
default=None,
metadata={
"name": "TopicTypes",
"type": "Element",
"namespace": "",
}
)
topic_statuses: Optional[ExtensionsTopicStatuses] = field(
default=None,
metadata={
"name": "TopicStatuses",
"type": "Element",
"namespace": "",
}
)
priorities: Optional[ExtensionsPriorities] = field(
default=None,
metadata={
"name": "Priorities",
"type": "Element",
"namespace": "",
}
)
topic_labels: Optional[ExtensionsTopicLabels] = field(
default=None,
metadata={
"name": "TopicLabels",
"type": "Element",
"namespace": "",
}
)
users: Optional[ExtensionsUsers] = field(
default=None,
metadata={
"name": "Users",
"type": "Element",
"namespace": "",
}
)
snippet_types: Optional[ExtensionsSnippetTypes] = field(
default=None,
metadata={
"name": "SnippetTypes",
"type": "Element",
"namespace": "",
}
)
stages: Optional[ExtensionsStages] = field(
default=None,
metadata={
"name": "Stages",
"type": "Element",
"namespace": "",
}
)
-616
View File
@@ -1,616 +0,0 @@
from dataclasses import dataclass, field
from typing import List, Optional
from xsdata.models.datatype import XmlDateTime
@dataclass(slots=True, kw_only=True)
class BimSnippet:
reference: str = field(
metadata={
"name": "Reference",
"type": "Element",
"namespace": "",
"required": True,
"min_length": 1,
"white_space": "collapse",
}
)
reference_schema: str = field(
metadata={
"name": "ReferenceSchema",
"type": "Element",
"namespace": "",
"required": True,
"min_length": 1,
"white_space": "collapse",
}
)
snippet_type: str = field(
metadata={
"name": "SnippetType",
"type": "Attribute",
"required": True,
"min_length": 1,
"white_space": "collapse",
}
)
is_external: bool = field(
default=False,
metadata={
"name": "IsExternal",
"type": "Attribute",
}
)
@dataclass(slots=True, kw_only=True)
class CommentViewpoint:
class Meta:
global_type = False
guid: str = field(
metadata={
"name": "Guid",
"type": "Attribute",
"required": True,
"pattern": r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}",
}
)
@dataclass(slots=True, kw_only=True)
class DocumentReference:
document_guid: Optional[str] = field(
default=None,
metadata={
"name": "DocumentGuid",
"type": "Element",
"namespace": "",
"pattern": r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}",
}
)
url: Optional[str] = field(
default=None,
metadata={
"name": "Url",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
}
)
description: Optional[str] = field(
default=None,
metadata={
"name": "Description",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
}
)
guid: str = field(
metadata={
"name": "Guid",
"type": "Attribute",
"required": True,
"pattern": r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}",
}
)
@dataclass(slots=True, kw_only=True)
class File:
filename: Optional[str] = field(
default=None,
metadata={
"name": "Filename",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
}
)
date: Optional[XmlDateTime] = field(
default=None,
metadata={
"name": "Date",
"type": "Element",
"namespace": "",
}
)
reference: Optional[str] = field(
default=None,
metadata={
"name": "Reference",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
}
)
ifc_project: Optional[str] = field(
default=None,
metadata={
"name": "IfcProject",
"type": "Attribute",
"length": 22,
"pattern": r"[0-9A-Za-z_$]*",
}
)
ifc_spatial_structure_element: Optional[str] = field(
default=None,
metadata={
"name": "IfcSpatialStructureElement",
"type": "Attribute",
"length": 22,
"pattern": r"[0-9A-Za-z_$]*",
}
)
is_external: bool = field(
default=True,
metadata={
"name": "IsExternal",
"type": "Attribute",
}
)
@dataclass(slots=True, kw_only=True)
class TopicLabels:
class Meta:
global_type = False
label: List[str] = field(
default_factory=list,
metadata={
"name": "Label",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
}
)
@dataclass(slots=True, kw_only=True)
class TopicReferenceLinks:
class Meta:
global_type = False
reference_link: List[str] = field(
default_factory=list,
metadata={
"name": "ReferenceLink",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
}
)
@dataclass(slots=True, kw_only=True)
class TopicRelatedTopicsRelatedTopic:
class Meta:
global_type = False
guid: str = field(
metadata={
"name": "Guid",
"type": "Attribute",
"required": True,
"pattern": r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}",
}
)
@dataclass(slots=True, kw_only=True)
class ViewPoint:
viewpoint: Optional[str] = field(
default=None,
metadata={
"name": "Viewpoint",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
}
)
snapshot: Optional[str] = field(
default=None,
metadata={
"name": "Snapshot",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
}
)
index: Optional[int] = field(
default=None,
metadata={
"name": "Index",
"type": "Element",
"namespace": "",
}
)
guid: str = field(
metadata={
"name": "Guid",
"type": "Attribute",
"required": True,
"pattern": r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}",
}
)
@dataclass(slots=True, kw_only=True)
class Comment:
date: XmlDateTime = field(
metadata={
"name": "Date",
"type": "Element",
"namespace": "",
"required": True,
}
)
author: str = field(
metadata={
"name": "Author",
"type": "Element",
"namespace": "",
"required": True,
"min_length": 1,
"white_space": "collapse",
}
)
comment: Optional[str] = field(
default=None,
metadata={
"name": "Comment",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
}
)
viewpoint: Optional[CommentViewpoint] = field(
default=None,
metadata={
"name": "Viewpoint",
"type": "Element",
"namespace": "",
}
)
modified_date: Optional[XmlDateTime] = field(
default=None,
metadata={
"name": "ModifiedDate",
"type": "Element",
"namespace": "",
}
)
modified_author: Optional[str] = field(
default=None,
metadata={
"name": "ModifiedAuthor",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
}
)
guid: str = field(
metadata={
"name": "Guid",
"type": "Attribute",
"required": True,
"pattern": r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}",
}
)
@dataclass(slots=True, kw_only=True)
class HeaderFiles:
class Meta:
global_type = False
file: List[File] = field(
default_factory=list,
metadata={
"name": "File",
"type": "Element",
"namespace": "",
}
)
@dataclass(slots=True, kw_only=True)
class TopicDocumentReferences:
class Meta:
global_type = False
document_reference: List[DocumentReference] = field(
default_factory=list,
metadata={
"name": "DocumentReference",
"type": "Element",
"namespace": "",
}
)
@dataclass(slots=True, kw_only=True)
class TopicRelatedTopics:
class Meta:
global_type = False
related_topic: List[TopicRelatedTopicsRelatedTopic] = field(
default_factory=list,
metadata={
"name": "RelatedTopic",
"type": "Element",
"namespace": "",
}
)
@dataclass(slots=True, kw_only=True)
class TopicViewpoints:
class Meta:
global_type = False
view_point: List[ViewPoint] = field(
default_factory=list,
metadata={
"name": "ViewPoint",
"type": "Element",
"namespace": "",
}
)
@dataclass(slots=True, kw_only=True)
class Header:
files: Optional[HeaderFiles] = field(
default=None,
metadata={
"name": "Files",
"type": "Element",
"namespace": "",
}
)
@dataclass(slots=True, kw_only=True)
class TopicComments:
class Meta:
global_type = False
comment: List[Comment] = field(
default_factory=list,
metadata={
"name": "Comment",
"type": "Element",
"namespace": "",
}
)
@dataclass(slots=True, kw_only=True)
class Topic:
reference_links: Optional[TopicReferenceLinks] = field(
default=None,
metadata={
"name": "ReferenceLinks",
"type": "Element",
"namespace": "",
}
)
title: str = field(
metadata={
"name": "Title",
"type": "Element",
"namespace": "",
"required": True,
"min_length": 1,
"white_space": "collapse",
}
)
priority: Optional[str] = field(
default=None,
metadata={
"name": "Priority",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
}
)
index: Optional[int] = field(
default=None,
metadata={
"name": "Index",
"type": "Element",
"namespace": "",
}
)
labels: Optional[TopicLabels] = field(
default=None,
metadata={
"name": "Labels",
"type": "Element",
"namespace": "",
}
)
creation_date: XmlDateTime = field(
metadata={
"name": "CreationDate",
"type": "Element",
"namespace": "",
"required": True,
}
)
creation_author: str = field(
metadata={
"name": "CreationAuthor",
"type": "Element",
"namespace": "",
"required": True,
"min_length": 1,
"white_space": "collapse",
}
)
modified_date: Optional[XmlDateTime] = field(
default=None,
metadata={
"name": "ModifiedDate",
"type": "Element",
"namespace": "",
}
)
modified_author: Optional[str] = field(
default=None,
metadata={
"name": "ModifiedAuthor",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
}
)
due_date: Optional[XmlDateTime] = field(
default=None,
metadata={
"name": "DueDate",
"type": "Element",
"namespace": "",
}
)
assigned_to: Optional[str] = field(
default=None,
metadata={
"name": "AssignedTo",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
}
)
stage: Optional[str] = field(
default=None,
metadata={
"name": "Stage",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
}
)
description: Optional[str] = field(
default=None,
metadata={
"name": "Description",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
}
)
bim_snippet: Optional[BimSnippet] = field(
default=None,
metadata={
"name": "BimSnippet",
"type": "Element",
"namespace": "",
}
)
document_references: Optional[TopicDocumentReferences] = field(
default=None,
metadata={
"name": "DocumentReferences",
"type": "Element",
"namespace": "",
}
)
related_topics: Optional[TopicRelatedTopics] = field(
default=None,
metadata={
"name": "RelatedTopics",
"type": "Element",
"namespace": "",
}
)
comments: Optional[TopicComments] = field(
default=None,
metadata={
"name": "Comments",
"type": "Element",
"namespace": "",
}
)
viewpoints: Optional[TopicViewpoints] = field(
default=None,
metadata={
"name": "Viewpoints",
"type": "Element",
"namespace": "",
}
)
guid: str = field(
metadata={
"name": "Guid",
"type": "Attribute",
"required": True,
"pattern": r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}",
}
)
server_assigned_id: Optional[str] = field(
default=None,
metadata={
"name": "ServerAssignedId",
"type": "Attribute",
"min_length": 1,
"white_space": "collapse",
}
)
topic_type: str = field(
metadata={
"name": "TopicType",
"type": "Attribute",
"required": True,
"min_length": 1,
"white_space": "collapse",
}
)
topic_status: str = field(
metadata={
"name": "TopicStatus",
"type": "Attribute",
"required": True,
"min_length": 1,
"white_space": "collapse",
}
)
@dataclass(slots=True, kw_only=True)
class Markup:
header: Optional[Header] = field(
default=None,
metadata={
"name": "Header",
"type": "Element",
"namespace": "",
}
)
topic: Topic = field(
metadata={
"name": "Topic",
"type": "Element",
"namespace": "",
"required": True,
}
)
-37
View File
@@ -1,37 +0,0 @@
from dataclasses import dataclass, field
from typing import Optional
@dataclass(slots=True, kw_only=True)
class Project:
name: Optional[str] = field(
default=None,
metadata={
"name": "Name",
"type": "Element",
"namespace": "",
"min_length": 1,
"white_space": "collapse",
}
)
project_id: str = field(
metadata={
"name": "ProjectId",
"type": "Attribute",
"required": True,
"min_length": 1,
"white_space": "collapse",
}
)
@dataclass(slots=True, kw_only=True)
class ProjectInfo:
project: Project = field(
metadata={
"name": "Project",
"type": "Element",
"namespace": "",
"required": True,
}
)
-12
View File
@@ -1,12 +0,0 @@
from dataclasses import dataclass, field
@dataclass(slots=True, kw_only=True)
class Version:
version_id: str = field(
metadata={
"name": "VersionId",
"type": "Attribute",
"required": True,
}
)
-524
View File
@@ -1,524 +0,0 @@
from dataclasses import dataclass, field
from enum import Enum
from typing import List, Optional
class BitmapFormat(Enum):
PNG = "png"
JPG = "jpg"
@dataclass(slots=True, kw_only=True)
class Component:
originating_system: Optional[str] = field(
default=None,
metadata={
"name": "OriginatingSystem",
"type": "Element",
"min_length": 1,
"white_space": "collapse",
}
)
authoring_tool_id: Optional[str] = field(
default=None,
metadata={
"name": "AuthoringToolId",
"type": "Element",
"min_length": 1,
"white_space": "collapse",
}
)
ifc_guid: Optional[str] = field(
default=None,
metadata={
"name": "IfcGuid",
"type": "Attribute",
"length": 22,
"pattern": r"[0-9A-Za-z_$]*",
}
)
@dataclass(slots=True, kw_only=True)
class Direction:
x: float = field(
metadata={
"name": "X",
"type": "Element",
"required": True,
}
)
y: float = field(
metadata={
"name": "Y",
"type": "Element",
"required": True,
}
)
z: float = field(
metadata={
"name": "Z",
"type": "Element",
"required": True,
}
)
@dataclass(slots=True, kw_only=True)
class Point:
x: float = field(
metadata={
"name": "X",
"type": "Element",
"required": True,
}
)
y: float = field(
metadata={
"name": "Y",
"type": "Element",
"required": True,
}
)
z: float = field(
metadata={
"name": "Z",
"type": "Element",
"required": True,
}
)
@dataclass(slots=True, kw_only=True)
class ViewSetupHints:
spaces_visible: bool = field(
default=False,
metadata={
"name": "SpacesVisible",
"type": "Attribute",
}
)
space_boundaries_visible: bool = field(
default=False,
metadata={
"name": "SpaceBoundariesVisible",
"type": "Attribute",
}
)
openings_visible: bool = field(
default=False,
metadata={
"name": "OpeningsVisible",
"type": "Attribute",
}
)
@dataclass(slots=True, kw_only=True)
class Bitmap:
format: BitmapFormat = field(
metadata={
"name": "Format",
"type": "Element",
"required": True,
}
)
reference: str = field(
metadata={
"name": "Reference",
"type": "Element",
"required": True,
"min_length": 1,
"white_space": "collapse",
}
)
location: Point = field(
metadata={
"name": "Location",
"type": "Element",
"required": True,
}
)
normal: Direction = field(
metadata={
"name": "Normal",
"type": "Element",
"required": True,
}
)
up: Direction = field(
metadata={
"name": "Up",
"type": "Element",
"required": True,
}
)
height: float = field(
metadata={
"name": "Height",
"type": "Element",
"required": True,
}
)
@dataclass(slots=True, kw_only=True)
class ClippingPlane:
location: Point = field(
metadata={
"name": "Location",
"type": "Element",
"required": True,
}
)
direction: Direction = field(
metadata={
"name": "Direction",
"type": "Element",
"required": True,
}
)
@dataclass(slots=True, kw_only=True)
class ComponentColoringColorComponents:
class Meta:
global_type = False
component: List[Component] = field(
default_factory=list,
metadata={
"name": "Component",
"type": "Element",
"min_occurs": 1,
}
)
@dataclass(slots=True, kw_only=True)
class ComponentSelection:
component: List[Component] = field(
default_factory=list,
metadata={
"name": "Component",
"type": "Element",
}
)
@dataclass(slots=True, kw_only=True)
class ComponentVisibilityExceptions:
class Meta:
global_type = False
component: List[Component] = field(
default_factory=list,
metadata={
"name": "Component",
"type": "Element",
}
)
@dataclass(slots=True, kw_only=True)
class Line:
start_point: Point = field(
metadata={
"name": "StartPoint",
"type": "Element",
"required": True,
}
)
end_point: Point = field(
metadata={
"name": "EndPoint",
"type": "Element",
"required": True,
}
)
@dataclass(slots=True, kw_only=True)
class OrthogonalCamera:
"""
Attributes
camera_view_point:
camera_direction:
camera_up_vector:
view_to_world_scale: view's visible vertical size in meters
aspect_ratio: Proportional relationship between the width and
the height of the view (w/h).
"""
camera_view_point: Point = field(
metadata={
"name": "CameraViewPoint",
"type": "Element",
"required": True,
}
)
camera_direction: Direction = field(
metadata={
"name": "CameraDirection",
"type": "Element",
"required": True,
}
)
camera_up_vector: Direction = field(
metadata={
"name": "CameraUpVector",
"type": "Element",
"required": True,
}
)
view_to_world_scale: float = field(
metadata={
"name": "ViewToWorldScale",
"type": "Element",
"required": True,
}
)
aspect_ratio: float = field(
metadata={
"name": "AspectRatio",
"type": "Element",
"required": True,
"min_exclusive": 0.0,
}
)
@dataclass(slots=True, kw_only=True)
class PerspectiveCamera:
"""
Attributes
camera_view_point:
camera_direction:
camera_up_vector:
field_of_view: Vertical field of view, in degrees. 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.
aspect_ratio: Proportional relationship between the width and
the height of the view (w/h).
"""
camera_view_point: Point = field(
metadata={
"name": "CameraViewPoint",
"type": "Element",
"required": True,
}
)
camera_direction: Direction = field(
metadata={
"name": "CameraDirection",
"type": "Element",
"required": True,
}
)
camera_up_vector: Direction = field(
metadata={
"name": "CameraUpVector",
"type": "Element",
"required": True,
}
)
field_of_view: float = field(
metadata={
"name": "FieldOfView",
"type": "Element",
"required": True,
"min_exclusive": 0.0,
"max_exclusive": 180.0,
}
)
aspect_ratio: float = field(
metadata={
"name": "AspectRatio",
"type": "Element",
"required": True,
"min_exclusive": 0.0,
}
)
@dataclass(slots=True, kw_only=True)
class ComponentColoringColor:
class Meta:
global_type = False
components: ComponentColoringColorComponents = field(
metadata={
"name": "Components",
"type": "Element",
"required": True,
}
)
color: str = field(
metadata={
"name": "Color",
"type": "Attribute",
"required": True,
"pattern": r"[0-9A-Fa-f]{6}([0-9A-Fa-f]{2})?",
}
)
@dataclass(slots=True, kw_only=True)
class ComponentVisibility:
view_setup_hints: Optional[ViewSetupHints] = field(
default=None,
metadata={
"name": "ViewSetupHints",
"type": "Element",
}
)
exceptions: Optional[ComponentVisibilityExceptions] = field(
default=None,
metadata={
"name": "Exceptions",
"type": "Element",
}
)
default_visibility: bool = field(
default=False,
metadata={
"name": "DefaultVisibility",
"type": "Attribute",
}
)
@dataclass(slots=True, kw_only=True)
class VisualizationInfoBitmaps:
class Meta:
global_type = False
bitmap: List[Bitmap] = field(
default_factory=list,
metadata={
"name": "Bitmap",
"type": "Element",
}
)
@dataclass(slots=True, kw_only=True)
class VisualizationInfoClippingPlanes:
class Meta:
global_type = False
clipping_plane: List[ClippingPlane] = field(
default_factory=list,
metadata={
"name": "ClippingPlane",
"type": "Element",
}
)
@dataclass(slots=True, kw_only=True)
class VisualizationInfoLines:
class Meta:
global_type = False
line: List[Line] = field(
default_factory=list,
metadata={
"name": "Line",
"type": "Element",
}
)
@dataclass(slots=True, kw_only=True)
class ComponentColoring:
color: List[ComponentColoringColor] = field(
default_factory=list,
metadata={
"name": "Color",
"type": "Element",
}
)
@dataclass(slots=True, kw_only=True)
class Components:
selection: Optional[ComponentSelection] = field(
default=None,
metadata={
"name": "Selection",
"type": "Element",
}
)
visibility: Optional[ComponentVisibility] = field(
default=None,
metadata={
"name": "Visibility",
"type": "Element",
}
)
coloring: Optional[ComponentColoring] = field(
default=None,
metadata={
"name": "Coloring",
"type": "Element",
}
)
@dataclass(slots=True, kw_only=True)
class VisualizationInfo:
"""
VisualizationInfo documentation.
"""
components: Optional[Components] = field(
default=None,
metadata={
"name": "Components",
"type": "Element",
}
)
orthogonal_camera: Optional[OrthogonalCamera] = field(
default=None,
metadata={
"name": "OrthogonalCamera",
"type": "Element",
}
)
perspective_camera: Optional[PerspectiveCamera] = field(
default=None,
metadata={
"name": "PerspectiveCamera",
"type": "Element",
}
)
lines: Optional[VisualizationInfoLines] = field(
default=None,
metadata={
"name": "Lines",
"type": "Element",
}
)
clipping_planes: Optional[VisualizationInfoClippingPlanes] = field(
default=None,
metadata={
"name": "ClippingPlanes",
"type": "Element",
}
)
bitmaps: Optional[VisualizationInfoBitmaps] = field(
default=None,
metadata={
"name": "Bitmaps",
"type": "Element",
}
)
guid: str = field(
metadata={
"name": "Guid",
"type": "Attribute",
"required": True,
"pattern": r"[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}",
}
)

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