diff --git a/cmake/CMakeLists.txt b/cmake/CMakeLists.txt
index 0bace9a278..71963665ca 100644
--- a/cmake/CMakeLists.txt
+++ b/cmake/CMakeLists.txt
@@ -17,7 +17,7 @@
# #
################################################################################
-cmake_minimum_required (VERSION 2.6)
+cmake_minimum_required (VERSION 2.8.5)
project (IfcOpenShell)
@@ -297,11 +297,23 @@ if(COMPILE_SCHEMA)
set(IFC_RELEASE_NOT_USED "2x3" "4")
# Install pyparsing if necessary
- execute_process(COMMAND ${PYTHON_EXECUTABLE} -m pip "list" OUTPUT_VARIABLE PYTHON_PACKAGE_LIST)
+ execute_process(COMMAND ${PYTHON_EXECUTABLE} -m pip freeze OUTPUT_VARIABLE PYTHON_PACKAGE_LIST)
+ if ("${PYTHON_PACKAGE_LIST}" STREQUAL "")
+ execute_process(COMMAND pip freeze OUTPUT_VARIABLE PYTHON_PACKAGE_LIST)
+ if ("${PYTHON_PACKAGE_LIST}" STREQUAL "")
+ message(WARNING "Failed to find pip. Pip is required to automatically install pyparsing")
+ endif()
+ endif()
string(FIND "${PYTHON_PACKAGE_LIST}" pyparsing PYPARSING_FOUND)
if ("${PYPARSING_FOUND}" STREQUAL "-1")
message(STATUS "Installing pyparsing")
- execute_process(COMMAND ${PYTHON_EXECUTABLE} -m pip "install" --user pyparsing)
+ execute_process(COMMAND ${PYTHON_EXECUTABLE} -m pip "install" --user pyparsing RESULT_VARIABLE SUCCESS)
+ if (NOT "${SUCCESS}" STREQUAL "0")
+ execute_process(COMMAND pip "install" --user pyparsing RESULT_VARIABLE SUCCESS)
+ if (NOT "${SUCCESS}" STREQUAL "0")
+ message(WARNING "Failed to automatically install pyparsing. Please install manually")
+ endif()
+ endif()
else()
message(STATUS "Python interpreter with pyparsing found")
endif()
@@ -310,7 +322,12 @@ if(COMPILE_SCHEMA)
message(STATUS "Compiling schema, this will take a while...")
execute_process(COMMAND ${PYTHON_EXECUTABLE} bootstrap.py express.bnf
WORKING_DIRECTORY ../src/ifcexpressparser
- OUTPUT_FILE express_parser.py)
+ OUTPUT_FILE express_parser.py
+ RESULT_VARIABLE SUCCESS)
+
+ if (NOT "${SUCCESS}" STREQUAL "0")
+ MESSAGE(FATAL_ERROR "Failed to bootstrap parser. Make sure pyparsing is installed")
+ endif()
# Generate code
execute_process(COMMAND ${PYTHON_EXECUTABLE} ../ifcexpressparser/express_parser.py ../../${COMPILE_SCHEMA}
@@ -318,10 +335,12 @@ if(COMPILE_SCHEMA)
OUTPUT_VARIABLE COMPILED_SCHEMA_NAME)
# Prevent the schema that had just been compiled from being excluded
- if(${COMPILED_SCHEMA_NAME} STREQUAL "IFC2X3")
+ if("${COMPILED_SCHEMA_NAME}" STREQUAL "IFC2X3")
list(REMOVE_ITEM IFC_RELEASE_NOT_USED "2x3")
- elseif(${COMPILED_SCHEMA_NAME} STREQUAL "IFC4")
+ add_definitions(-DUSE_IFC2x3)
+ elseif("${COMPILED_SCHEMA_NAME}" STREQUAL "IFC4")
list(REMOVE_ITEM IFC_RELEASE_NOT_USED "4")
+ add_definitions(-DUSE_IFC4)
endif()
else()
if(USE_IFC4)
diff --git a/src/ifcexpressparser/codegen.py b/src/ifcexpressparser/codegen.py
new file mode 100644
index 0000000000..6370b3dc87
--- /dev/null
+++ b/src/ifcexpressparser/codegen.py
@@ -0,0 +1,34 @@
+###############################################################################
+# #
+# 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 . #
+# #
+###############################################################################
+
+class Base(object):
+ """
+ A base class for all code generation classes. Currently only working around
+ some python 2/3 incompatibilities in terms of unicode file handling.
+ """
+ def emit(self):
+ import platform
+ if tuple(map(int, platform.python_version_tuple())) < (2, 8):
+ from io import open as unicode_open
+ else:
+ unicode_open = open
+ unicode = lambda x, *args, **kwargs: x
+ f = unicode_open(self.file_name, 'w', encoding='utf-8')
+ f.write(unicode(repr(self), encoding='utf-8', errors='ignore'))
+ f.close()
diff --git a/src/ifcexpressparser/enum_header.py b/src/ifcexpressparser/enum_header.py
index 96993ec13f..eb382a3e7a 100644
--- a/src/ifcexpressparser/enum_header.py
+++ b/src/ifcexpressparser/enum_header.py
@@ -18,8 +18,9 @@
###############################################################################
import templates
+import codegen
-class EnumHeader:
+class EnumHeader(codegen.Base):
def __init__(self, mapping):
enumerable_types = sorted(set([name for name, type in mapping.schema.types.items()] + [name for name, type in mapping.schema.entities.items()]))
@@ -30,9 +31,9 @@ class EnumHeader:
}
self.schema_name = mapping.schema.name.capitalize()
+
+ self.file_name = '%senum.h'%self.schema_name
+
+
def __repr__(self):
return self.str
- def emit(self):
- f = open('%senum.h'%self.schema_name, 'w', encoding='utf-8')
- f.write(str(self))
- f.close()
diff --git a/src/ifcexpressparser/header.py b/src/ifcexpressparser/header.py
index 51f4a89242..449506bc0f 100644
--- a/src/ifcexpressparser/header.py
+++ b/src/ifcexpressparser/header.py
@@ -17,10 +17,11 @@
# #
###############################################################################
+import codegen
import templates
import documentation
-class Header:
+class Header(codegen.Base):
def __init__(self, mapping):
declarations = []
@@ -123,10 +124,9 @@ class Header:
}
self.schema_name = mapping.schema.name.capitalize()
+
+ self.file_name = '%s.h'%self.schema_name
+
+
def __repr__(self):
return self.str
- def emit(self):
- f = open('%s.h'%self.schema_name, 'w', encoding='utf-8')
- f.write(str(self))
- f.close()
-
diff --git a/src/ifcexpressparser/implementation.py b/src/ifcexpressparser/implementation.py
index f4e0759da3..f26581cf0e 100644
--- a/src/ifcexpressparser/implementation.py
+++ b/src/ifcexpressparser/implementation.py
@@ -17,9 +17,10 @@
# #
###############################################################################
+import codegen
import templates
-class Implementation:
+class Implementation(codegen.Base):
def __init__(self, mapping):
enumeration_functions = []
entity_implementations = []
@@ -230,10 +231,9 @@ class Implementation:
}
self.schema_name = mapping.schema.name.capitalize()
+
+ self.file_name = '%s.cpp'%self.schema_name
+
+
def __repr__(self):
return self.str
- def emit(self):
- f = open('%s.cpp'%self.schema_name, 'w', encoding='utf-8')
- f.write(str(self))
- f.close()
-
diff --git a/src/ifcexpressparser/latebound_header.py b/src/ifcexpressparser/latebound_header.py
index bf2db78f3e..251a288073 100644
--- a/src/ifcexpressparser/latebound_header.py
+++ b/src/ifcexpressparser/latebound_header.py
@@ -17,9 +17,10 @@
# #
###############################################################################
+import codegen
import templates
-class LateBoundHeader:
+class LateBoundHeader(codegen.Base):
def __init__(self, mapping):
self.str = templates.lb_header % {
'schema_name_upper' : mapping.schema.name.upper(),
@@ -27,9 +28,9 @@ class LateBoundHeader:
}
self.schema_name = mapping.schema.name.capitalize()
+
+ self.file_name = '%s-latebound.h'%self.schema_name
+
+
def __repr__(self):
return self.str
- def emit(self):
- f = open('%s-latebound.h'%self.schema_name, 'w', encoding='utf-8')
- f.write(str(self))
- f.close()
diff --git a/src/ifcexpressparser/latebound_implementation.py b/src/ifcexpressparser/latebound_implementation.py
index fe9e600ecd..1303d000ff 100644
--- a/src/ifcexpressparser/latebound_implementation.py
+++ b/src/ifcexpressparser/latebound_implementation.py
@@ -17,9 +17,10 @@
# #
###############################################################################
+import codegen
import templates
-class LateBoundImplementation:
+class LateBoundImplementation(codegen.Base):
def __init__(self, mapping):
schema_name = mapping.schema.name.capitalize()
@@ -110,10 +111,9 @@ class LateBoundImplementation:
}
self.schema_name = mapping.schema.name.capitalize()
+
+ self.file_name = '%s-latebound.cpp'%self.schema_name
+
+
def __repr__(self):
return self.str
- def emit(self):
- f = open('%s-latebound.cpp'%self.schema_name, 'w', encoding='utf-8')
- f.write(str(self))
- f.close()
-
diff --git a/src/ifcexpressparser/mapping.py b/src/ifcexpressparser/mapping.py
index ee536697fd..5b9721e191 100644
--- a/src/ifcexpressparser/mapping.py
+++ b/src/ifcexpressparser/mapping.py
@@ -17,6 +17,8 @@
# #
###############################################################################
+from __future__ import print_function
+
import sys
import nodes
import templates
@@ -33,11 +35,11 @@ class Mapping:
'binary' : 'boost::dynamic_bitset<>'
}
- supported_argument_types = {
+ supported_argument_types = set([
'INT', 'BOOL', 'DOUBLE', 'STRING', 'BINARY', 'ENUMERATION', 'ENTITY_INSTANCE',
'AGGREGATE_OF_INT', 'AGGREGATE_OF_DOUBLE', 'AGGREGATE_OF_STRING', 'AGGREGATE_OF_BINARY', 'AGGREGATE_OF_ENTITY_INSTANCE',
'AGGREGATE_OF_AGGREGATE_OF_INT', 'AGGREGATE_OF_AGGREGATE_OF_DOUBLE', 'AGGREGATE_OF_AGGREGATE_OF_ENTITY_INSTANCE',
- }
+ ])
def __init__(self, schema):
self.schema = schema
diff --git a/src/ifcexpressparser/schema.py b/src/ifcexpressparser/schema.py
index 74d62bfacb..18335f3cdf 100644
--- a/src/ifcexpressparser/schema.py
+++ b/src/ifcexpressparser/schema.py
@@ -18,8 +18,13 @@
###############################################################################
import nodes
+import platform
import collections
+if tuple(map(int, platform.python_version_tuple())) < (2, 7):
+ import ordereddict
+ collections.OrderedDict = ordereddict.OrderedDict
+
class Schema:
def is_enumeration(self, v):
return str(v) in self.enumerations
@@ -34,12 +39,12 @@ class Schema:
def __init__(self, parsetree):
self.name = parsetree[1]
- sort = lambda d: collections.OrderedDict(sorted(d.items()))
+ sort = lambda d: collections.OrderedDict(sorted(d))
- self.types = sort({t.name:t for t in parsetree if isinstance(t, nodes.TypeDeclaration)})
- self.entities = sort({t.name:t for t in parsetree if isinstance(t, nodes.EntityDeclaration)})
+ self.types = sort([(t.name,t) for t in parsetree if isinstance(t, nodes.TypeDeclaration)])
+ self.entities = sort([(t.name,t) for t in parsetree if isinstance(t, nodes.EntityDeclaration)])
- of_type = lambda *types: sort({a: b.type.type for a,b in self.types.items() if any(isinstance(b.type.type, ty) for ty in types)})
+ of_type = lambda *types: sort([(a, b.type.type) for a,b in self.types.items() if any(isinstance(b.type.type, ty) for ty in types)])
self.enumerations = of_type(nodes.EnumerationType)
self.selects = of_type(nodes.SelectType)
diff --git a/src/ifcgeom/IfcGeomFaces.cpp b/src/ifcgeom/IfcGeomFaces.cpp
index 6d83f90609..91753fc137 100644
--- a/src/ifcgeom/IfcGeomFaces.cpp
+++ b/src/ifcgeom/IfcGeomFaces.cpp
@@ -893,7 +893,11 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcPlane* l, TopoDS_Shape& face)
gp_Pln pln;
convert(l, pln);
Handle_Geom_Surface surf = new Geom_Plane(pln);
+#if OCC_VERSION_HEX < 0x60502
+ face = BRepBuilderAPI_MakeFace(surf);
+#else
face = BRepBuilderAPI_MakeFace(surf, getValue(GV_PRECISION));
+#endif
return true;
}
@@ -942,7 +946,11 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcBSplineSurfaceWithKnots* l, To
}
Handle_Geom_Surface surf = new Geom_BSplineSurface(Poles, UKnots, VKnots, UMults, VMults, UDegree, VDegree);
+#if OCC_VERSION_HEX < 0x60502
+ face = BRepBuilderAPI_MakeFace(surf);
+#else
face = BRepBuilderAPI_MakeFace(surf, getValue(GV_PRECISION));
+#endif
return true;
}
diff --git a/src/ifcgeom/IfcGeomFunctions.cpp b/src/ifcgeom/IfcGeomFunctions.cpp
index 1ed8ee1627..14dd47230f 100644
--- a/src/ifcgeom/IfcGeomFunctions.cpp
+++ b/src/ifcgeom/IfcGeomFunctions.cpp
@@ -63,6 +63,9 @@
#include
#include
#include
+#include
+
+#include
#include
#include
@@ -95,7 +98,6 @@
#include
#include
-#include
#include
#include
#include
@@ -106,7 +108,11 @@
#include "../ifcgeom/IfcGeom.h"
#if OCC_VERSION_HEX < 0x60900
+#ifdef _MSC_VER
#pragma message("warning: You are linking against Open CASCADE version " OCC_VERSION_COMPLETE ". Version 6.9.0 introduces various improvements with relation to boolean operations. You are advised to upgrade.")
+#else
+#warning "You are linking against linking against an older version of Open CASCADE. Version 6.9.0 introduces various improvements with relation to boolean operations. You are advised to upgrade."
+#endif
#endif
bool IfcGeom::Kernel::create_solid_from_compound(const TopoDS_Shape& compound, TopoDS_Shape& shape) {
diff --git a/src/ifcgeom/IfcGeomShapes.cpp b/src/ifcgeom/IfcGeomShapes.cpp
index 0e1b0747cb..008ce6a9e8 100644
--- a/src/ifcgeom/IfcGeomShapes.cpp
+++ b/src/ifcgeom/IfcGeomShapes.cpp
@@ -65,6 +65,8 @@
#include
#include
#include
+#include
+
#include
#include
@@ -859,7 +861,11 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcCylindricalSurface* l, TopoDS_
gp_Trsf trsf;
IfcGeom::Kernel::convert(l->Position(),trsf);
+#if OCC_VERSION_HEX < 0x60502
+ face = BRepBuilderAPI_MakeFace(new Geom_CylindricalSurface(gp::XOY(), l->Radius())).Face().Moved(trsf);
+#else
face = BRepBuilderAPI_MakeFace(new Geom_CylindricalSurface(gp::XOY(), l->Radius()), getValue(GV_PRECISION)).Face().Moved(trsf);
+#endif
return true;
}
diff --git a/src/ifcparse/IfcGlobalId.cpp b/src/ifcparse/IfcGlobalId.cpp
index f6ab34b48c..e70189071f 100644
--- a/src/ifcparse/IfcGlobalId.cpp
+++ b/src/ifcparse/IfcGlobalId.cpp
@@ -23,6 +23,8 @@
#include
#include
#include
+#include
+#include
#include "../ifcparse/IfcGlobalId.h"
#include "../ifcparse/IfcException.h"
@@ -87,7 +89,11 @@ IfcParse::IfcGlobalId::IfcGlobalId() {
std::vector v(uuid_data.size());
std::copy(uuid_data.begin(), uuid_data.end(), v.begin());
string_data = compress(&v[0]);
+#if BOOST_VERSION < 104400
+ formatted_string = boost::lexical_cast(uuid_data);
+#else
formatted_string = boost::uuids::to_string(uuid_data);
+#endif
#ifndef NDEBUG
std::vector test_vector;
@@ -106,7 +112,11 @@ IfcParse::IfcGlobalId::IfcGlobalId(const std::string& s)
std::vector v;
expand(string_data, v);
std::copy(v.begin(), v.end(), uuid_data.begin());
+#if BOOST_VERSION < 104400
+ formatted_string = boost::lexical_cast(uuid_data);
+#else
formatted_string = boost::uuids::to_string(uuid_data);
+#endif
#ifndef NDEBUG
const std::string test_string = compress(&uuid_data.data[0]);