Merge branch 'v0.6.0' into hdf5

This commit is contained in:
johltn
2021-02-10 16:04:56 +01:00
36 changed files with 3175 additions and 204 deletions
+7
View File
@@ -12,6 +12,13 @@ __pycache__
.vscode .vscode
# PyCharm files # PyCharm files
.idea .idea
# Docs
/docs/output
/docs/rst_files
/docs/doxygen
/src/ifcblenderexport/docs/_build
# gettext binary translation files # gettext binary translation files
*.mo *.mo
# Vim # Vim
+7
View File
@@ -36,6 +36,7 @@ OPTION(IFCXML_SUPPORT "Build IfcParse with ifcXML support (requires libxml2)." O
OPTION(ENABLE_BUILD_OPTIMIZATIONS "Enable certain compiler and linker optimizations on RelWithDebInfo and Release builds." OFF) OPTION(ENABLE_BUILD_OPTIMIZATIONS "Enable certain compiler and linker optimizations on RelWithDebInfo and Release builds." OFF)
OPTION(IFCCONVERT_DOUBLE_PRECISION "IfcConvert: Use double precision floating-point numbers." ON) OPTION(IFCCONVERT_DOUBLE_PRECISION "IfcConvert: Use double precision floating-point numbers." ON)
OPTION(BUILD_IFCGEOM "Build IfcGeom." ON) OPTION(BUILD_IFCGEOM "Build IfcGeom." ON)
OPTION(BUILD_DOCUMENTATION "Build IfcOpenShell Documentation." OFF)
OPTION(BUILD_IFCPYTHON "Build IfcPython." ON) OPTION(BUILD_IFCPYTHON "Build IfcPython." ON)
OPTION(BUILD_EXAMPLES "Build example applications." ON) OPTION(BUILD_EXAMPLES "Build example applications." ON)
OPTION(BUILD_GEOMSERVER "Build IfcGeomServer executable." ON) OPTION(BUILD_GEOMSERVER "Build IfcGeomServer executable." ON)
@@ -685,6 +686,12 @@ INSTALL(TARGETS IfcGeomServer
endif() endif()
# Documentation
IF(BUILD_DOCUMENTATION)
set(CMAKE_MODULE_PATH "../docs/cmake")
ADD_SUBDIRECTORY(../docs docs)
ENDIF()
IF(BUILD_IFCPYTHON) IF(BUILD_IFCPYTHON)
ADD_SUBDIRECTORY(../src/ifcwrap ifcwrap) ADD_SUBDIRECTORY(../src/ifcwrap ifcwrap)
ENDIF() ENDIF()
+40
View File
@@ -0,0 +1,40 @@
#Look for an executable called sphinx-build
find_program(SPHINX_EXECUTABLE
NAMES sphinx-build
DOC "Path to sphinx-build executable")
include(FindPackageHandleStandardArgs)
#Handle standard arguments to find_package like REQUIRED and QUIET
find_package_handle_standard_args(Sphinx
"Failed to find sphinx-build executable"
SPHINX_EXECUTABLE)
find_package(Doxygen REQUIRED)
#find_package(Sphinx REQUIRED)
set(SPHINX_SOURCE ${CMAKE_CURRENT_SOURCE_DIR})
set(SPHINX_BUILD ${CMAKE_CURRENT_BINARY_DIR}/docs/sphinx)
MESSAGE(STATUS "SPHINX BUILD ${CMAKE_CURRENT_BINARY_DIR}")
file(MAKE_DIRECTORY ./output/doxygen)
if (DOXYGEN_FOUND)
add_custom_target(Sphinx ALL
COMMAND
${SPHINX_EXECUTABLE} -v -T -b html
${SPHINX_SOURCE} ${CMAKE_CURRENT_SOURCE_DIR}/output
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/output
COMMENT "Generating documentation with Sphinx")
# add_custom_target(ifcopenshell_python_docs ALL
# COMMAND make html
# WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/../src/ifcblenderexport/docs
# OUTPUT ${CMAKE_CURRENT_SOURCE_DIR}/../src/ifcblenderexport/docs
# COMMENT "Generating documentation with Sphinx")
else (DOXYGEN_FOUND)
message("Doxygen need to be installed to generate the doxygen documentation")
endif (DOXYGEN_FOUND)
+2531
View File
File diff suppressed because it is too large Load Diff
+11
View File
@@ -0,0 +1,11 @@
#Look for an executable called sphinx-build
find_program(SPHINX_EXECUTABLE
NAMES sphinx-build
DOC "Path to sphinx-build executable")
include(FindPackageHandleStandardArgs)
#Handle standard arguments to find_package like REQUIRED and QUIET
find_package_handle_standard_args(Sphinx
"Failed to find sphinx-build executable"
SPHINX_EXECUTABLE)
+11
View File
@@ -0,0 +1,11 @@
#Look for an executable called sphinx-build
find_program(SPHINX_EXECUTABLE
NAMES sphinx-build
DOC "Path to sphinx-build executable")
include(FindPackageHandleStandardArgs)
#Handle standard arguments to find_package like REQUIRED and QUIET
find_package_handle_standard_args(Sphinx
"Failed to find sphinx-build executable"
SPHINX_EXECUTABLE)
+37
View File
@@ -0,0 +1,37 @@
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
@@ -0,0 +1,10 @@
IfcOpenShell
============
.. toctree::
:maxdepth: 3
rst_files/library_root
* `ifcopenshell-python documentation <python/html/index.html>`_
+39
View File
@@ -0,0 +1,39 @@
# 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
@@ -0,0 +1,10 @@
IfcOpenShell
============
.. toctree::
:maxdepth: 3
rst_files/library_root
* `ifcopenshell-python documentation <python/html/index.html>`_
+4 -2
View File
@@ -33,12 +33,14 @@ class IfcStore:
@staticmethod @staticmethod
def link_element(element, obj): def link_element(element, obj):
IfcStore.id_map[element.id()] = obj IfcStore.id_map[element.id()] = obj
IfcStore.guid_map[element.GlobalId] = obj if hasattr(element, "GlobalId"):
IfcStore.guid_map[element.GlobalId] = obj
obj.BIMObjectProperties.ifc_definition_id = element.id() obj.BIMObjectProperties.ifc_definition_id = element.id()
@staticmethod @staticmethod
def unlink_element(element, obj=None): def unlink_element(element, obj=None):
del IfcStore.id_map[element.id()] del IfcStore.id_map[element.id()]
del IfcStore.guid_map[element.GlobalId] if hasattr(element, "GlobalId"):
del IfcStore.guid_map[element.GlobalId]
if obj: if obj:
obj.BIMObjectProperties.ifc_definition_id = 0 obj.BIMObjectProperties.ifc_definition_id = 0
@@ -335,8 +335,6 @@ class IfcImporter:
self.profile_code("Create project") self.profile_code("Create project")
self.create_spatial_hierarchy() self.create_spatial_hierarchy()
self.profile_code("Create spatial hierarchy") self.profile_code("Create spatial hierarchy")
self.create_type_products()
self.profile_code("Create type products")
self.create_aggregates() self.create_aggregates()
self.profile_code("Create aggregates") self.profile_code("Create aggregates")
self.create_openings_collection() self.create_openings_collection()
@@ -347,14 +345,16 @@ class IfcImporter:
# self.parse_native_elements() # self.parse_native_elements()
# self.profile_code("Parsing native elements") # self.profile_code("Parsing native elements")
self.create_grids() self.create_grids()
self.profile_code("Creating grids") self.profile_code("Create grids")
# TODO: Deprecate # TODO: Deprecate
# self.create_native_products() # self.create_native_products()
# self.profile_code("Creating native products") # self.profile_code("Create native products")
self.create_products() self.create_products()
self.profile_code("Creating meshified products") self.profile_code("Create products")
self.create_type_products()
self.profile_code("Create type products")
self.create_annotation() self.create_annotation()
self.profile_code("Creating annotation") self.profile_code("Create annotation")
self.place_objects_in_spatial_tree() self.place_objects_in_spatial_tree()
self.profile_code("Placing objects in spatial tree") self.profile_code("Placing objects in spatial tree")
if self.ifc_import_settings.should_merge_by_class: if self.ifc_import_settings.should_merge_by_class:
@@ -633,16 +633,17 @@ class IfcImporter:
return return
representation_map = self.get_type_product_body_representation_map(element) representation_map = self.get_type_product_body_representation_map(element)
mesh = None mesh = None
if self.ifc_import_settings.should_import_type_representations and representation_map: if representation_map:
try: representation = representation_map.MappedRepresentation
shape = ifcopenshell.geom.create_shape(self.settings, representation_map.MappedRepresentation) mesh_name = "{}/{}".format(representation.ContextOfItems.id(), representation.id())
mesh_name = f"mesh-{shape.id}" mesh = self.meshes.get(mesh_name)
mesh = self.meshes.get(mesh_name) if mesh is None:
if mesh is None: try:
shape = ifcopenshell.geom.create_shape(self.settings, representation_map.MappedRepresentation)
mesh = self.create_mesh(element, shape) mesh = self.create_mesh(element, shape)
self.meshes[mesh_name] = mesh self.meshes[mesh_name] = mesh
except: except:
self.ifc_import_settings.logger.error("Failed to generate shape for %s", element) self.ifc_import_settings.logger.error("Failed to generate shape for %s", element)
obj = bpy.data.objects.new(self.get_name(element), mesh) obj = bpy.data.objects.new(self.get_name(element), mesh)
obj.BIMObjectProperties.ifc_definition_id = element.id() obj.BIMObjectProperties.ifc_definition_id = element.id()
self.material_creator.create(element, obj, mesh) self.material_creator.create(element, obj, mesh)
@@ -761,8 +762,7 @@ class IfcImporter:
self.ifc_import_settings.logger.info("Creating object %s", element) self.ifc_import_settings.logger.info("Creating object %s", element)
if shape: if shape:
# TODO: make names more meaningful mesh_name = self.get_mesh_name(shape.geometry)
mesh_name = f"mesh-{shape.geometry.id}"
mesh = self.meshes.get(mesh_name) mesh = self.meshes.get(mesh_name)
if mesh is None: if mesh is None:
if element.GlobalId in self.native_elements: if element.GlobalId in self.native_elements:
@@ -1388,6 +1388,16 @@ class IfcImporter:
): ):
return representation.Items[0].MappingTarget return representation.Items[0].MappingTarget
def get_mesh_name(self, geometry):
representation_id = geometry.id
if "-" in representation_id:
representation_id = int(re.sub(r"\D", "", representation_id.split("-")[0]))
else:
representation_id = int(re.sub(r"\D", "", representation_id))
representation = self.file.by_id(representation_id)
context_id = representation.ContextOfItems.id() if hasattr(representation, "ContextOfItems") else 0
return "{}/{}".format(context_id, representation_id)
def create_mesh(self, element, shape, is_curve=False): def create_mesh(self, element, shape, is_curve=False):
try: try:
if hasattr(shape, "geometry"): if hasattr(shape, "geometry"):
@@ -1398,14 +1408,7 @@ class IfcImporter:
if is_curve: if is_curve:
return self.create_curve(geometry) return self.create_curve(geometry)
representation_id = geometry.id mesh = bpy.data.meshes.new(self.get_mesh_name(geometry))
if "-" in representation_id:
representation_id = int(re.sub(r"\D", "", representation_id.split("-")[0]))
else:
representation_id = int(re.sub(r"\D", "", representation_id))
representation = self.file.by_id(representation_id)
context_id = representation.ContextOfItems.id() if hasattr(representation, "ContextOfItems") else 0
mesh = bpy.data.meshes.new("{}/{}".format(context_id, representation_id))
props = bpy.context.scene.BIMGeoreferenceProperties props = bpy.context.scene.BIMGeoreferenceProperties
if props.has_blender_offset and props.blender_offset_type == "CARTESIAN_POINT": if props.has_blender_offset and props.blender_offset_type == "CARTESIAN_POINT":
@@ -1574,7 +1577,6 @@ class IfcImportSettings:
self.logger = None self.logger = None
self.input_file = None self.input_file = None
self.diff_file = None self.diff_file = None
self.should_import_type_representations = False
self.should_import_spaces = False self.should_import_spaces = False
self.should_auto_set_workarounds = True self.should_auto_set_workarounds = True
self.should_use_cpu_multiprocessing = True self.should_use_cpu_multiprocessing = True
@@ -17,9 +17,12 @@ class Data:
return return
cls.products[product_id] = [] cls.products[product_id] = []
product = file.by_id(product_id) product = file.by_id(product_id)
if not hasattr(product, "Representation") or not product.Representation: representations = []
return if product.is_a("IfcProduct"):
for representation in product.Representation.Representations: representations = product.Representation.Representations
elif product.is_a("IfcTypeProduct"):
representations = [rm.MappedRepresentation for rm in product.RepresentationMaps]
for representation in representations:
c = representation.ContextOfItems c = representation.ContextOfItems
rep_id = int(representation.id()) rep_id = int(representation.id())
cls.representations[rep_id] = { cls.representations[rep_id] = {
@@ -1,26 +1,24 @@
class Usecase: class Usecase:
def __init__(self, file, settings=None): def __init__(self, file, settings=None):
self.file = file self.file = file
self.settings = { self.settings = {"representation": None}
"product": None,
"representation": None,
}
self.ifc_vertices = [] self.ifc_vertices = []
for key, value in settings.items(): for key, value in settings.items():
self.settings[key] = value self.settings[key] = value
def execute(self): def execute(self):
self.zero = self.file.createIfcCartesianPoint((0.0, 0.0, 0.0)) mapping_source = self.get_mapping_source()
self.x_axis = self.file.createIfcDirection((1.0, 0.0, 0.0))
self.y_axis = self.file.createIfcDirection((0.0, 1.0, 0.0))
self.z_axis = self.file.createIfcDirection((0.0, 0.0, 1.0))
self.get_mapping_source() if not mapping_source:
return
mapping_target = self.file.createIfcCartesianTransformationOperator3D( zero = self.file.createIfcCartesianPoint((0.0, 0.0, 0.0))
self.x_axis, self.y_axis, self.zero, 1, self.z_axis x_axis = self.file.createIfcDirection((1.0, 0.0, 0.0))
) y_axis = self.file.createIfcDirection((0.0, 1.0, 0.0))
mapped_item = self.file.createIfcMappedItem(self.get_mapping_source(), mapping_target) z_axis = self.file.createIfcDirection((0.0, 0.0, 1.0))
mapping_target = self.file.createIfcCartesianTransformationOperator3D(x_axis, y_axis, zero, 1, z_axis)
mapped_item = self.file.createIfcMappedItem(mapping_source, mapping_target)
return self.file.create_entity( return self.file.create_entity(
"IfcShapeRepresentation", "IfcShapeRepresentation",
**{ **{
@@ -32,12 +30,6 @@ class Usecase:
) )
def get_mapping_source(self): def get_mapping_source(self):
if self.settings["representation"].RepresentationMap: for inverse in self.file.get_inverse(self.settings["representation"]):
return self.settings["representation"].RepresentationMap[0] if inverse.is_a("IfcRepresentationMap"):
return self.file.create_entity( return inverse
"IfcRepresentationMap",
**{
"MappingOrigin": self.file.createIfcAxis2Placement3D(self.zero, self.z_axis, self.x_axis),
"MappedRepresentation": self.settings["representation"],
}
)
@@ -8,6 +8,7 @@ import blenderbim.bim.module.geometry.add_representation as add_representation
import blenderbim.bim.module.geometry.map_representation as map_representation import blenderbim.bim.module.geometry.map_representation as map_representation
import blenderbim.bim.module.geometry.assign_styles as assign_styles import blenderbim.bim.module.geometry.assign_styles as assign_styles
import blenderbim.bim.module.geometry.assign_representation as assign_representation import blenderbim.bim.module.geometry.assign_representation as assign_representation
import blenderbim.bim.module.geometry.unassign_representation as unassign_representation
import blenderbim.bim.module.geometry.remove_representation as remove_representation import blenderbim.bim.module.geometry.remove_representation as remove_representation
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from blenderbim.bim import import_ifc from blenderbim.bim import import_ifc
@@ -202,13 +203,21 @@ class SwitchRepresentation(bpy.types.Operator):
class RemoveRepresentation(bpy.types.Operator): class RemoveRepresentation(bpy.types.Operator):
bl_idname = "bim.remove_representation" bl_idname = "bim.remove_representation"
bl_label = "Remove Representation" bl_label = "Remove Representation"
ifc_definition_id: bpy.props.IntProperty() obj: bpy.props.StringProperty() # TODO
representation_id: bpy.props.IntProperty()
def execute(self, context): def execute(self, context):
self.file = IfcStore.get_file() self.file = IfcStore.get_file()
representation = self.file.by_id(self.ifc_definition_id) representation = self.file.by_id(self.representation_id)
obj = bpy.context.active_object obj = bpy.context.active_object
mesh = bpy.data.meshes.get("{}/{}".format(representation.ContextOfItems.id(), representation.id())) product = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
if representation.RepresentationType == "MappedRepresentation":
mesh_name = "{}/{}".format(
representation.ContextOfItems.id(), representation.Items[0].MappingSource.MappedRepresentation.id()
)
else:
mesh_name = "{}/{}".format(representation.ContextOfItems.id(), representation.id())
mesh = bpy.data.meshes.get(mesh_name)
if mesh: if mesh:
if obj.data == mesh: if obj.data == mesh:
# TODO we can do better than this # TODO we can do better than this
@@ -216,9 +225,12 @@ class RemoveRepresentation(bpy.types.Operator):
if not void_mesh: if not void_mesh:
void_mesh = bpy.data.meshes.new("Void") void_mesh = bpy.data.meshes.new("Void")
obj.data = void_mesh obj.data = void_mesh
bpy.data.meshes.remove(mesh) if representation.RepresentationType != "MappedRepresentation":
bpy.data.meshes.remove(mesh)
product = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
unassign_representation.Usecase(self.file, {"product": product, "representation": representation}).execute()
remove_representation.Usecase(self.file, {"representation": representation}).execute() remove_representation.Usecase(self.file, {"representation": representation}).execute()
Data.load(obj.BIMObjectProperties.ifc_definition_id) Data.load(product.id())
return {"FINISHED"} return {"FINISHED"}
@@ -237,22 +249,10 @@ class MapRepresentation(bpy.types.Operator):
for obj in objs: for obj in objs:
bpy.ops.bim.edit_object_placement(obj=obj.name) bpy.ops.bim.edit_object_placement(obj=obj.name)
product = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id) product = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
if obj.data.BIMMeshProperties.ifc_definition_id:
old_representation = self.file.by_id(obj.data.BIMMeshProperties.ifc_definition_id)
else:
old_representation = None
target_representation = self.file.by_id(obj_data.BIMMeshProperties.ifc_definition_id) target_representation = self.file.by_id(obj_data.BIMMeshProperties.ifc_definition_id)
obj.data = obj_data obj.data = obj_data
result = map_representation.Usecase( result = map_representation.Usecase(self.file, {"representation": target_representation}).execute()
self.file,
{
"product": product,
"representation": target_representation,
},
).execute()
assign_representation.Usecase(self.file, {"product": product, "representation": result}).execute() assign_representation.Usecase(self.file, {"product": product, "representation": result}).execute()
if old_representation:
bpy.ops.bim.remove_representation(ifc_definition_id=old_representation.id())
Data.load(obj.BIMObjectProperties.ifc_definition_id) Data.load(obj.BIMObjectProperties.ifc_definition_id)
return {"FINISHED"} return {"FINISHED"}
@@ -1,5 +1,6 @@
import ifcopenshell.util.element import ifcopenshell.util.element
class Usecase: class Usecase:
def __init__(self, file, settings=None): def __init__(self, file, settings=None):
self.file = file self.file = file
@@ -8,6 +9,20 @@ class Usecase:
self.settings[key] = value self.settings[key] = value
def execute(self): def execute(self):
if self.settings["representation"].RepresentationType == "MappedRepresentation":
return self.remove_mapped_representation_portion_only()
return self.remove_entire_representation_tree()
def remove_mapped_representation_portion_only(self):
dummy_context = self.file.create_entity("IfcRepresentationContext")
dummy_representation_map = self.file.createIfcRepresentationMap()
self.settings["representation"].ContextOfItems = dummy_context
for item in self.settings["representation"].Items:
item.MappingSource = dummy_representation_map
ifcopenshell.util.element.remove_deep(self.file, self.settings["representation"])
self.file.remove(self.settings["representation"])
def remove_entire_representation_tree(self):
dummy_context = self.file.create_entity("IfcRepresentationContext") dummy_context = self.file.create_entity("IfcRepresentationContext")
for subelement in self.file.traverse(self.settings["representation"]): for subelement in self.file.traverse(self.settings["representation"]):
if subelement.is_a("IfcRepresentationItem") and subelement.StyledByItem: if subelement.is_a("IfcRepresentationItem") and subelement.StyledByItem:
@@ -26,11 +41,4 @@ class Usecase:
self.file.remove(inverse) self.file.remove(inverse)
else: else:
assigned_items.remove(element) assigned_items.remove(element)
inverse.AssignedItems == list(assigned_items) inverse.AssignedItems = list(assigned_items)
elif inverse.is_a("IfcProductRepresentation"):
representations = set(inverse.Representations)
if len(representations) == 1:
self.file.remove(inverse)
else:
representations.remove(element)
inverse.Representations = list(representations)
@@ -41,7 +41,7 @@ class BIM_PT_representations(Panel):
op = row.operator("bim.switch_representation", icon="OUTLINER_DATA_MESH", text="") op = row.operator("bim.switch_representation", icon="OUTLINER_DATA_MESH", text="")
op.ifc_definition_id = ifc_definition_id op.ifc_definition_id = ifc_definition_id
op.disable_opening_subtractions = False op.disable_opening_subtractions = False
row.operator("bim.remove_representation", icon="X", text="").ifc_definition_id = ifc_definition_id row.operator("bim.remove_representation", icon="X", text="").representation_id = ifc_definition_id
class BIM_PT_mesh(Panel): class BIM_PT_mesh(Panel):
@@ -0,0 +1,57 @@
import blenderbim.bim.module.geometry.remove_representation as remove_representation
import ifcopenshell.util.element
class Usecase:
def __init__(self, file, settings=None):
self.file = file
self.settings = {"product": None, "representation": None}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
if self.settings["product"].is_a("IfcProduct"):
self.unassign_product_representation(self.settings["product"], self.settings["representation"])
elif self.settings["product"].is_a("IfcTypeProduct"):
self.unassign_type_representation()
def unassign_product_representation(self, product, representation):
representations = list(product.Representation.Representations or [])
representations.remove(representation)
if not representations:
self.file.remove(product.Representation)
else:
product.Representation.Representations = representations
def unassign_type_representation(self):
for representation_map in self.settings["product"].RepresentationMaps or []:
if representation_map.MappedRepresentation == self.settings["representation"]:
self.unassign_products_using_mapped_representation(representation_map)
self.remove_representation_map_only(representation_map)
break
self.settings["product"].RepresentationMaps = self.settings["product"].RepresentationMaps or None
def remove_representation_map_only(self, representation_map):
dummy_representation = self.file.createIfcShapeRepresentation()
representation_map.MappedRepresentation = dummy_representation
ifcopenshell.util.element.remove_deep(self.file, representation_map)
self.file.remove(representation_map)
def unassign_products_using_mapped_representation(self, representation_map):
mapped_representations = []
just_representations = []
for map_usage in representation_map.MapUsage or []:
for inverse in self.file.get_inverse(map_usage):
if not inverse.is_a("IfcShapeRepresentation"):
continue
for definition in inverse.OfProductRepresentation or []:
for product in definition.ShapeOfProduct or []:
mapped_representations.append({
"product": product,
"representation": inverse
})
just_representations.append(inverse)
for item in mapped_representations:
self.unassign_product_representation(item["product"], item["representation"])
for representation in just_representations:
remove_representation.Usecase(self.file, {"representation": representation}).execute()
@@ -0,0 +1,53 @@
import ifcopenshell
import ifcopenshell.util.unit
import ifcopenshell.util.placement
from mathutils import Matrix # For now, we depend on Blender
from blenderbim.bim.module.owner.api import create_owner_history
class Usecase:
def __init__(self, file, settings=None):
self.file = file
self.settings = {
"AxisTag": "A",
"AxisCurve": None, # A Blender object
"SameSense": True,
"UVWAxes": "UAxes", # Choose which axes
"Grid": None,
}
for key, value in settings.items():
self.settings[key] = value
def execute(self):
self.settings["unit_scale"] = ifcopenshell.util.unit.calculate_unit_scale(self.file)
points = [
Matrix(ifcopenshell.util.placement.get_local_placement(self.settings["Grid"].ObjectPlacement)).inverted()
@ (self.settings["AxisCurve"].matrix_world @ v.co)
for v in self.settings["AxisCurve"].data.vertices[0:2]
]
self.settings["AxisCurve"] = self.file.createIfcPolyline(
[
self.create_cartesian_point(points[0][0], points[0][1], points[0][2]),
self.create_cartesian_point(points[1][0], points[1][1], points[1][2]),
]
)
element = self.file.create_entity("IfcGridAxis", **{
"AxisTag": self.settings["AxisTag"],
"AxisCurve": self.settings["AxisCurve"],
"SameSense": self.settings["SameSense"]
})
axes = list(getattr(self.settings["Grid"], self.settings["UVWAxes"]) or [])
axes.append(element)
setattr(self.settings["Grid"], self.settings["UVWAxes"], axes)
return element
def create_cartesian_point(self, x, y, z=None):
x = self.convert_si_to_unit(x)
y = self.convert_si_to_unit(y)
if z is None:
return self.file.createIfcCartesianPoint((x, y))
z = self.convert_si_to_unit(z)
return self.file.createIfcCartesianPoint((x, y, z))
def convert_si_to_unit(self, co):
return co / self.settings["unit_scale"]
@@ -3,8 +3,8 @@ import math
import ifcopenshell import ifcopenshell
from bpy.types import Operator from bpy.types import Operator
from bpy.props import FloatProperty from bpy.props import FloatProperty
from bpy_extras.object_utils import AddObjectHelper, object_data_add
from mathutils import Vector from mathutils import Vector
from blenderbim.bim.ifc import IfcStore
def add_object(self, context): def add_object(self, context):
@@ -79,7 +79,11 @@ def add_object(self, context):
faces = [[0, 1, 2, 3, 4, 5]] faces = [[0, 1, 2, 3, 4, 5]]
mesh = bpy.data.meshes.new(name="Dumb Door Profile") mesh = bpy.data.meshes.new(name="Dumb Door Profile")
mesh.from_pydata(verts, edges, faces) mesh.from_pydata(verts, edges, faces)
obj = object_data_add(context, mesh, operator=self) obj = bpy.data.objects.new("Door Profile", mesh)
context.view_layer.active_layer_collection.collection.objects.link(obj)
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
bpy.ops.object.convert(target="CURVE") bpy.ops.object.convert(target="CURVE")
# Door lining sweep # Door lining sweep
@@ -93,7 +97,11 @@ def add_object(self, context):
faces = [] faces = []
mesh = bpy.data.meshes.new(name="Dumb Door") mesh = bpy.data.meshes.new(name="Dumb Door")
mesh.from_pydata(verts, edges, faces) mesh.from_pydata(verts, edges, faces)
obj2 = object_data_add(context, mesh, operator=self) obj2 = bpy.data.objects.new("Door", mesh)
context.view_layer.active_layer_collection.collection.objects.link(obj2)
bpy.context.view_layer.objects.active = obj2
obj2.select_set(True)
bpy.ops.object.convert(target="CURVE") bpy.ops.object.convert(target="CURVE")
obj2.data.dimensions = "2D" obj2.data.dimensions = "2D"
@@ -116,10 +124,14 @@ def add_object(self, context):
faces = [[0, 1, 2, 3]] faces = [[0, 1, 2, 3]]
mesh = bpy.data.meshes.new(name="Dumb Door Panel") mesh = bpy.data.meshes.new(name="Dumb Door Panel")
mesh.from_pydata(verts, edges, faces) mesh.from_pydata(verts, edges, faces)
obj3 = object_data_add(context, mesh, operator=self) obj3 = bpy.data.objects.new("Door Panel", mesh)
modifier = obj3.modifiers.new("Panel Height", "SOLIDIFY") modifier = obj3.modifiers.new("Panel Height", "SOLIDIFY")
modifier.offset = 1 modifier.offset = 1
modifier.thickness = self.overall_height - 0.045 modifier.thickness = self.overall_height - 0.045
context.view_layer.active_layer_collection.collection.objects.link(obj3)
bpy.context.view_layer.objects.active = obj3
obj3.select_set(True)
bpy.ops.object.convert(target="MESH") bpy.ops.object.convert(target="MESH")
ctx = bpy.context.copy() ctx = bpy.context.copy()
@@ -138,11 +150,16 @@ def add_object(self, context):
faces = [[0, 1, 2, 3]] faces = [[0, 1, 2, 3]]
mesh = bpy.data.meshes.new(name="Dumb Door Opening") mesh = bpy.data.meshes.new(name="Dumb Door Opening")
mesh.from_pydata(verts, edges, faces) mesh.from_pydata(verts, edges, faces)
obj4 = object_data_add(context, mesh, operator=self) obj4 = bpy.data.objects.new("Door Opening", mesh)
modifier = obj4.modifiers.new("Panel Height", "SOLIDIFY") modifier = obj4.modifiers.new("Panel Height", "SOLIDIFY")
modifier.offset = -1 modifier.offset = -1
modifier.thickness = self.overall_height + 0.1 modifier.thickness = self.overall_height + 0.1
context.view_layer.active_layer_collection.collection.objects.link(obj4)
bpy.context.view_layer.objects.active = obj4
obj4.select_set(True)
bpy.ops.object.convert(target="MESH") bpy.ops.object.convert(target="MESH")
obj4.display_type = "WIRE" obj4.display_type = "WIRE"
obj4.parent = obj2 obj4.parent = obj2
obj4.matrix_parent_inverse = obj2.matrix_world.inverted() obj4.matrix_parent_inverse = obj2.matrix_world.inverted()
@@ -150,6 +167,11 @@ def add_object(self, context):
obj4.name = "Door Opening" obj4.name = "Door Opening"
obj2.name = "Door" obj2.name = "Door"
if IfcStore.get_file():
bpy.ops.bim.assign_class(obj=obj2.name, ifc_class="IfcDoor")
obj2.location = context.scene.cursor.location
#obj2.data.name = "Model/Body/MODEL_VIEW/" + guid #obj2.data.name = "Model/Body/MODEL_VIEW/" + guid
#obj2.data.use_fake_user = True #obj2.data.use_fake_user = True
@@ -165,10 +187,9 @@ def add_object(self, context):
#rep.target_view = "PLAN_VIEW" #rep.target_view = "PLAN_VIEW"
class BIM_OT_add_object(Operator, AddObjectHelper): class BIM_OT_add_object(Operator):
bl_idname = "mesh.add_door" bl_idname = "mesh.add_door"
bl_label = "Dumb Door" bl_label = "Dumb Door"
bl_options = {"REGISTER", "UNDO"}
overall_width: FloatProperty(name="Overall Width", default=0.85) overall_width: FloatProperty(name="Overall Width", default=0.85)
overall_height: FloatProperty(name="Overall Height", default=2.1) overall_height: FloatProperty(name="Overall Height", default=2.1)
@@ -1,19 +1,16 @@
import bpy import bpy
import blenderbim.bim.module.grid.create_grid_axis as create_grid_axis
from bpy.types import Operator from bpy.types import Operator
from bpy.props import FloatProperty, IntProperty from bpy.props import FloatProperty, IntProperty
from bpy_extras.object_utils import AddObjectHelper, object_data_add
from mathutils import Vector from mathutils import Vector
from blenderbim.bim.ifc import IfcStore
def add_object(self, context): def add_object(self, context):
obj = object_data_add(context, None, operator=self) obj = bpy.data.objects.new("Grid", None)
obj.name = "IfcGrid/Grid" obj.name = "Grid"
name = obj.name.split("/")[1]
default_collection = obj.users_collection[0] collection = bpy.data.collections.new(obj.name)
default_collection.objects.unlink(obj)
collection = bpy.data.collections.new("IfcGrid/" + name)
has_site_collection = False has_site_collection = False
for child in bpy.context.view_layer.layer_collection.children: for child in bpy.context.view_layer.layer_collection.children:
if "IfcProject/" not in child.name: if "IfcProject/" not in child.name:
@@ -28,6 +25,13 @@ def add_object(self, context):
bpy.context.view_layer.active_layer_collection.collection.children.link(collection) bpy.context.view_layer.active_layer_collection.collection.children.link(collection)
collection.objects.link(obj) collection.objects.link(obj)
self.file = IfcStore.get_file()
if self.file:
bpy.ops.bim.assign_class(obj=obj.name, ifc_class="IfcGrid")
grid = self.file.by_id(obj.BIMObjectProperties.ifc_definition_id)
if has_site_collection:
bpy.ops.bim.assign_container(relating_structure=grandchild.name, related_element=obj.name)
axes_collection = bpy.data.collections.new("UAxes") axes_collection = bpy.data.collections.new("UAxes")
collection.children.link(axes_collection) collection.children.link(axes_collection)
for i in range(0, self.total_u): for i in range(0, self.total_u):
@@ -39,14 +43,16 @@ def add_object(self, context):
faces = [] faces = []
mesh = bpy.data.meshes.new(name="Grid Axis") mesh = bpy.data.meshes.new(name="Grid Axis")
mesh.from_pydata(verts, edges, faces) mesh.from_pydata(verts, edges, faces)
obj = object_data_add(context, mesh, operator=self)
tag = chr(ord("A") + i) tag = chr(ord("A") + i)
obj.name = "IfcGridAxis/" + tag obj = bpy.data.objects.new(f"IfcGridAxis/{tag}", mesh)
default_collection.objects.unlink(obj)
axes_collection.objects.link(obj) axes_collection.objects.link(obj)
attribute = obj.BIMObjectProperties.attributes.add()
attribute.name = "AxisTag" if self.file:
attribute.string_value = tag result = create_grid_axis.Usecase(
self.file, {"AxisTag": tag, "AxisCurve": obj, "UVWAxes": "UAxes", "Grid": grid}
).execute()
obj.BIMObjectProperties.ifc_definition_id = result.id()
axes_collection = bpy.data.collections.new("VAxes") axes_collection = bpy.data.collections.new("VAxes")
collection.children.link(axes_collection) collection.children.link(axes_collection)
@@ -59,17 +65,19 @@ def add_object(self, context):
faces = [] faces = []
mesh = bpy.data.meshes.new(name="Grid Axis") mesh = bpy.data.meshes.new(name="Grid Axis")
mesh.from_pydata(verts, edges, faces) mesh.from_pydata(verts, edges, faces)
obj = object_data_add(context, mesh, operator=self)
tag = str(i + 1).zfill(2) tag = str(i + 1).zfill(2)
obj.name = "IfcGridAxis/" + tag obj = bpy.data.objects.new(f"IfcGridAxis/{tag}", mesh)
default_collection.objects.unlink(obj)
axes_collection.objects.link(obj) axes_collection.objects.link(obj)
attribute = obj.BIMObjectProperties.attributes.add()
attribute.name = "AxisTag" if IfcStore.get_file():
attribute.string_value = tag result = create_grid_axis.Usecase(
self.file, {"AxisTag": tag, "AxisCurve": obj, "UVWAxes": "VAxes", "Grid": grid}
).execute()
obj.BIMObjectProperties.ifc_definition_id = result.id()
class BIM_OT_add_object(Operator, AddObjectHelper): class BIM_OT_add_object(Operator):
bl_idname = "mesh.add_grid" bl_idname = "mesh.add_grid"
bl_label = "Grid" bl_label = "Grid"
bl_options = {"REGISTER", "UNDO"} bl_options = {"REGISTER", "UNDO"}
@@ -1,8 +1,8 @@
import bpy import bpy
from bpy.types import Operator from bpy.types import Operator
from bpy.props import FloatProperty from bpy.props import FloatProperty
from bpy_extras.object_utils import AddObjectHelper, object_data_add
from mathutils import Vector from mathutils import Vector
from blenderbim.bim.ifc import IfcStore
def add_object(self, context): def add_object(self, context):
@@ -17,18 +17,21 @@ def add_object(self, context):
mesh = bpy.data.meshes.new(name="Dumb Slab") mesh = bpy.data.meshes.new(name="Dumb Slab")
mesh.from_pydata(verts, edges, faces) mesh.from_pydata(verts, edges, faces)
obj = object_data_add(context, mesh, operator=self) obj = bpy.data.objects.new("Slab", mesh)
modifier = obj.modifiers.new("Slab Depth", "SOLIDIFY") modifier = obj.modifiers.new("Slab Depth", "SOLIDIFY")
modifier.use_even_offset = True modifier.use_even_offset = True
modifier.offset = 1 modifier.offset = 1
modifier.thickness = self.depth modifier.thickness = self.depth
obj.name = "Slab" obj.name = "Slab"
context.view_layer.active_layer_collection.collection.objects.link(obj)
if IfcStore.get_file():
bpy.ops.bim.assign_class(obj=obj.name, ifc_class="IfcSlab")
obj.location = context.scene.cursor.location
class BIM_OT_add_object(Operator, AddObjectHelper): class BIM_OT_add_object(Operator):
bl_idname = "mesh.add_slab" bl_idname = "mesh.add_slab"
bl_label = "Dumb Slab" bl_label = "Dumb Slab"
bl_options = {"REGISTER", "UNDO"}
length: FloatProperty(name="Length", default=2) length: FloatProperty(name="Length", default=2)
width: FloatProperty(name="Width", default=2) width: FloatProperty(name="Width", default=2)
@@ -1,8 +1,8 @@
import bpy import bpy
from bpy.types import Operator from bpy.types import Operator
from bpy.props import FloatProperty, BoolProperty from bpy.props import FloatProperty, BoolProperty
from bpy_extras.object_utils import AddObjectHelper, object_data_add
from mathutils import Vector from mathutils import Vector
from blenderbim.bim.ifc import IfcStore
def add_object(self, context): def add_object(self, context):
@@ -25,7 +25,8 @@ def add_object(self, context):
mesh = bpy.data.meshes.new(name="Dumb Wall") mesh = bpy.data.meshes.new(name="Dumb Wall")
mesh.from_pydata(verts, edges, faces) mesh.from_pydata(verts, edges, faces)
obj = object_data_add(context, mesh, operator=self) obj = bpy.data.objects.new("Wall", mesh)
context.view_layer.active_layer_collection.collection.objects.link(obj)
if not self.use_plane: if not self.use_plane:
modifier = obj.modifiers.new("Wall Height", "SCREW") modifier = obj.modifiers.new("Wall Height", "SCREW")
modifier.angle = 0 modifier.angle = 0
@@ -39,13 +40,15 @@ def add_object(self, context):
modifier.use_even_offset = True modifier.use_even_offset = True
modifier.thickness = self.width modifier.thickness = self.width
obj.name = "Wall" obj.name = "Wall"
if IfcStore.get_file():
bpy.ops.bim.assign_class(obj=obj.name, ifc_class="IfcWall")
obj.location = context.scene.cursor.location
return obj return obj
class BIM_OT_add_object(Operator, AddObjectHelper): class BIM_OT_add_object(Operator):
bl_idname = "mesh.add_wall" bl_idname = "mesh.add_wall"
bl_label = "Dumb Wall" bl_label = "Dumb Wall"
bl_options = {"REGISTER", "UNDO"}
height: FloatProperty(name="Height", default=3) height: FloatProperty(name="Height", default=3)
length: FloatProperty(name="Length", default=1) length: FloatProperty(name="Length", default=1)
@@ -3,8 +3,8 @@ import math
import ifcopenshell import ifcopenshell
from bpy.types import Operator from bpy.types import Operator
from bpy.props import FloatProperty from bpy.props import FloatProperty
from bpy_extras.object_utils import AddObjectHelper, object_data_add
from mathutils import Vector from mathutils import Vector
from blenderbim.bim.ifc import IfcStore
def add_object(self, context): def add_object(self, context):
@@ -64,7 +64,11 @@ def add_object(self, context):
faces = [[0, 1, 2, 3]] faces = [[0, 1, 2, 3]]
mesh = bpy.data.meshes.new(name="Dumb Window Profile") mesh = bpy.data.meshes.new(name="Dumb Window Profile")
mesh.from_pydata(verts, edges, faces) mesh.from_pydata(verts, edges, faces)
obj = object_data_add(context, mesh, operator=self) obj = bpy.data.objects.new("Window Profile", mesh)
context.view_layer.active_layer_collection.collection.objects.link(obj)
bpy.context.view_layer.objects.active = obj
obj.select_set(True)
bpy.ops.object.convert(target="CURVE") bpy.ops.object.convert(target="CURVE")
# Window lining sweep # Window lining sweep
@@ -78,7 +82,11 @@ def add_object(self, context):
faces = [] faces = []
mesh = bpy.data.meshes.new(name="Dumb Window") mesh = bpy.data.meshes.new(name="Dumb Window")
mesh.from_pydata(verts, edges, faces) mesh.from_pydata(verts, edges, faces)
obj2 = object_data_add(context, mesh, operator=self) obj2 = bpy.data.objects.new("Window", mesh)
context.view_layer.active_layer_collection.collection.objects.link(obj2)
bpy.context.view_layer.objects.active = obj2
obj2.select_set(True)
bpy.ops.object.convert(target="CURVE") bpy.ops.object.convert(target="CURVE")
obj2.data.splines[0].use_cyclic_u = True obj2.data.splines[0].use_cyclic_u = True
@@ -102,10 +110,14 @@ def add_object(self, context):
faces = [[0, 1, 2, 3]] faces = [[0, 1, 2, 3]]
mesh = bpy.data.meshes.new(name="Dumb Window Panel") mesh = bpy.data.meshes.new(name="Dumb Window Panel")
mesh.from_pydata(verts, edges, faces) mesh.from_pydata(verts, edges, faces)
obj3 = object_data_add(context, mesh, operator=self) obj3 = bpy.data.objects.new("Window Panel", mesh)
modifier = obj3.modifiers.new("Panel Height", "SOLIDIFY") modifier = obj3.modifiers.new("Panel Height", "SOLIDIFY")
modifier.offset = 1 modifier.offset = 1
modifier.thickness = self.overall_height - 0.08 modifier.thickness = self.overall_height - 0.08
context.view_layer.active_layer_collection.collection.objects.link(obj3)
bpy.context.view_layer.objects.active = obj3
obj3.select_set(True)
bpy.ops.object.convert(target="MESH") bpy.ops.object.convert(target="MESH")
ctx = bpy.context.copy() ctx = bpy.context.copy()
@@ -124,10 +136,14 @@ def add_object(self, context):
faces = [[0, 1, 2, 3]] faces = [[0, 1, 2, 3]]
mesh = bpy.data.meshes.new(name="Dumb Window Opening") mesh = bpy.data.meshes.new(name="Dumb Window Opening")
mesh.from_pydata(verts, edges, faces) mesh.from_pydata(verts, edges, faces)
obj4 = object_data_add(context, mesh, operator=self) obj4 = bpy.data.objects.new("Window Opening", mesh)
modifier = obj4.modifiers.new("Panel Height", "SOLIDIFY") modifier = obj4.modifiers.new("Panel Height", "SOLIDIFY")
modifier.offset = -1 modifier.offset = -1
modifier.thickness = self.overall_height modifier.thickness = self.overall_height
context.view_layer.active_layer_collection.collection.objects.link(obj4)
bpy.context.view_layer.objects.active = obj4
obj4.select_set(True)
bpy.ops.object.convert(target="MESH") bpy.ops.object.convert(target="MESH")
obj4.display_type = "WIRE" obj4.display_type = "WIRE"
obj4.parent = obj2 obj4.parent = obj2
@@ -135,7 +151,10 @@ def add_object(self, context):
obj4.hide_render = True obj4.hide_render = True
obj4.name = "Window Opening" obj4.name = "Window Opening"
if IfcStore.get_file():
bpy.ops.bim.assign_class(obj=obj2.name, ifc_class="IfcWindow")
obj2.name = "Window" obj2.name = "Window"
obj2.location = context.scene.cursor.location
#obj2.data.name = "Model/Body/MODEL_VIEW/" + guid #obj2.data.name = "Model/Body/MODEL_VIEW/" + guid
#obj2.data.use_fake_user = True #obj2.data.use_fake_user = True
@@ -150,10 +169,9 @@ def add_object(self, context):
#rep.target_view = "PLAN_VIEW" #rep.target_view = "PLAN_VIEW"
class BIM_OT_add_object(Operator, AddObjectHelper): class BIM_OT_add_object(Operator):
bl_idname = "mesh.add_window" bl_idname = "mesh.add_window"
bl_label = "Dumb Window" bl_label = "Dumb Window"
bl_options = {"REGISTER", "UNDO"}
overall_width: FloatProperty(name="Overall Width", default=0.7) overall_width: FloatProperty(name="Overall Width", default=0.7)
overall_height: FloatProperty(name="Overall Height", default=1) overall_height: FloatProperty(name="Overall Height", default=1)
@@ -63,6 +63,7 @@ class ExportIFC(bpy.types.Operator):
bl_idname = "export_ifc.bim" bl_idname = "export_ifc.bim"
bl_label = "Export IFC" bl_label = "Export IFC"
filename_ext = ".ifc" filename_ext = ".ifc"
filter_glob: bpy.props.StringProperty(default="*.ifc;*.ifczip;*.ifcxml;*.ifcjson", options={"HIDDEN"})
filepath: bpy.props.StringProperty(subtype="FILE_PATH") filepath: bpy.props.StringProperty(subtype="FILE_PATH")
json_version: bpy.props.EnumProperty(items=[("4", "4", ""), ("5a", "5a", "")], name="IFC JSON Version") json_version: bpy.props.EnumProperty(items=[("4", "4", ""), ("5a", "5a", "")], name="IFC JSON Version")
json_compact: bpy.props.BoolProperty(name="Export Compact IFCJSON", default=False) json_compact: bpy.props.BoolProperty(name="Export Compact IFCJSON", default=False)
@@ -111,7 +112,6 @@ class ImportIFC(bpy.types.Operator, ImportHelper):
filename_ext = ".ifc" filename_ext = ".ifc"
filter_glob: bpy.props.StringProperty(default="*.ifc;*.ifczip;*.ifcxml", options={"HIDDEN"}) filter_glob: bpy.props.StringProperty(default="*.ifc;*.ifczip;*.ifcxml", options={"HIDDEN"})
should_import_type_representations: bpy.props.BoolProperty(name="Import Type Representations", default=False)
should_import_spaces: bpy.props.BoolProperty(name="Import Spaces", default=False) should_import_spaces: bpy.props.BoolProperty(name="Import Spaces", default=False)
should_auto_set_workarounds: bpy.props.BoolProperty(name="Automatically Set Vendor Workarounds", default=True) should_auto_set_workarounds: bpy.props.BoolProperty(name="Automatically Set Vendor Workarounds", default=True)
should_use_cpu_multiprocessing: bpy.props.BoolProperty(name="Import with CPU Multiprocessing", default=True) should_use_cpu_multiprocessing: bpy.props.BoolProperty(name="Import with CPU Multiprocessing", default=True)
@@ -138,7 +138,6 @@ class ImportIFC(bpy.types.Operator, ImportHelper):
) )
settings = import_ifc.IfcImportSettings.factory(context, self.filepath, logger) settings = import_ifc.IfcImportSettings.factory(context, self.filepath, logger)
settings.should_import_type_representations = self.should_import_type_representations
settings.should_import_spaces = self.should_import_spaces settings.should_import_spaces = self.should_import_spaces
settings.should_auto_set_workarounds = self.should_auto_set_workarounds settings.should_auto_set_workarounds = self.should_auto_set_workarounds
settings.should_use_cpu_multiprocessing = self.should_use_cpu_multiprocessing settings.should_use_cpu_multiprocessing = self.should_use_cpu_multiprocessing
@@ -10,6 +10,7 @@ from . import annotation
from . import helper from . import helper
from mathutils import Vector from mathutils import Vector
from mathutils import geometry from mathutils import geometry
from blenderbim.bim.ifc import IfcStore
try: try:
from OCC.Core import BRep, BRepTools, TopExp, TopAbs from OCC.Core import BRep, BRepTools, TopExp, TopAbs
@@ -140,11 +141,7 @@ class SvgWriter:
line["marker-start"] = "url(#grid-marker)" line["marker-start"] = "url(#grid-marker)"
line["marker-end"] = "url(#grid-marker)" line["marker-end"] = "url(#grid-marker)"
line["stroke-dasharray"] = "12.5, 3, 3, 3" line["stroke-dasharray"] = "12.5, 3, 3, 3"
axis_tag = grid_obj.BIMObjectProperties.attributes.get("AxisTag") axis_tag = IfcStore.get_file().by_id(grid_obj.BIMObjectProperties.ifc_definition_id).AxisTag
if axis_tag:
axis_tag = axis_tag.string_value
else:
axis_tag = grid_obj.name.split("/")[1]
self.svg.add( self.svg.add(
self.svg.text( self.svg.text(
axis_tag, axis_tag,
+13 -1
View File
@@ -339,7 +339,13 @@ int main(int argc, char** argv) {
("default-material-file", new po::typed_value<path_t, char_t>(&default_material_filename), ("default-material-file", new po::typed_value<path_t, char_t>(&default_material_filename),
"Specifies a material file that describes the material object types will have" "Specifies a material file that describes the material object types will have"
"if an object does not have any specified material in the IFC file.") "if an object does not have any specified material in the IFC file.")
("validate", "Checks whether geometrical output conforms to the included explicit quantities."); ("validate", "Checks whether geometrical output conforms to the included explicit quantities.")
("no-wire-intersection-check", "Skip wire intersection check.")
("no-wire-intersection-tolerance", "Set wire intersection tolerance to 0.")
("strict-tolerance", "Use exact tolerance from model. Default is a 10 "
"times increase for more permissive edge curves and fewer artifacts after "
"boolean operations at the expense of geometric detail "
"due to vertex collapsing and wire intersection fuzziness.");
std::string bounds; std::string bounds;
#ifdef HAVE_ICU #ifdef HAVE_ICU
@@ -481,6 +487,9 @@ int main(int argc, char** argv) {
const bool generate_uvs = vmap.count("generate-uvs") != 0; const bool generate_uvs = vmap.count("generate-uvs") != 0;
const bool validate = vmap.count("validate") != 0; const bool validate = vmap.count("validate") != 0;
const bool edge_arrows = vmap.count("edge-arrows") != 0; const bool edge_arrows = vmap.count("edge-arrows") != 0;
const bool no_wire_intersection_check = vmap.count("no-wire-intersection-check") != 0;
const bool no_wire_intersection_tolerance = vmap.count("no-wire-intersection-tolerance") != 0;
const bool strict_tolerance = vmap.count("strict-tolerance") != 0;
if (!quiet || vmap.count("version")) { if (!quiet || vmap.count("version")) {
print_version(); print_version();
@@ -741,6 +750,9 @@ int main(int argc, char** argv) {
settings.set(IfcGeom::IteratorSettings::SITE_LOCAL_PLACEMENT, site_local_placement); settings.set(IfcGeom::IteratorSettings::SITE_LOCAL_PLACEMENT, site_local_placement);
settings.set(IfcGeom::IteratorSettings::BUILDING_LOCAL_PLACEMENT, building_local_placement); settings.set(IfcGeom::IteratorSettings::BUILDING_LOCAL_PLACEMENT, building_local_placement);
settings.set(IfcGeom::IteratorSettings::VALIDATE_QUANTITIES, validate); settings.set(IfcGeom::IteratorSettings::VALIDATE_QUANTITIES, validate);
settings.set(IfcGeom::IteratorSettings::NO_WIRE_INTERSECTION_CHECK, no_wire_intersection_check);
settings.set(IfcGeom::IteratorSettings::NO_WIRE_INTERSECTION_TOLERANCE, no_wire_intersection_tolerance);
settings.set(IfcGeom::IteratorSettings::STRICT_TOLERANCE, strict_tolerance);
settings.set(SerializerSettings::USE_ELEMENT_NAMES, use_element_names); settings.set(SerializerSettings::USE_ELEMENT_NAMES, use_element_names);
settings.set(SerializerSettings::USE_ELEMENT_GUIDS, use_element_guids); settings.set(SerializerSettings::USE_ELEMENT_GUIDS, use_element_guids);
+6
View File
@@ -224,6 +224,9 @@ private:
double modelling_precision; double modelling_precision;
double dimensionality; double dimensionality;
double layerset_first; double layerset_first;
double no_wire_intersection_check;
double no_wire_intersection_tolerance;
double precision_factor;
// For stopping PlacementRelTo recursion in convert(const IfcSchema::IfcObjectPlacement* l, gp_Trsf& trsf) // For stopping PlacementRelTo recursion in convert(const IfcSchema::IfcObjectPlacement* l, gp_Trsf& trsf)
const IfcParse::declaration* placement_rel_to; const IfcParse::declaration* placement_rel_to;
@@ -256,6 +259,9 @@ public:
, faceset_helper_(nullptr) , faceset_helper_(nullptr)
, layerset_first(-1.) , layerset_first(-1.)
, disable_boolean_result(-1.) , disable_boolean_result(-1.)
, no_wire_intersection_check(-1)
, no_wire_intersection_tolerance(-1)
, precision_factor(10.)
{} {}
MAKE_TYPE_NAME(Kernel)(const MAKE_TYPE_NAME(Kernel)& other) MAKE_TYPE_NAME(Kernel)(const MAKE_TYPE_NAME(Kernel)& other)
+28 -5
View File
@@ -1415,6 +1415,15 @@ void IfcGeom::Kernel::setValue(GeomValue var, double value) {
case GV_DISABLE_BOOLEAN_RESULT: case GV_DISABLE_BOOLEAN_RESULT:
disable_boolean_result = value; disable_boolean_result = value;
break; break;
case GV_NO_WIRE_INTERSECTION_CHECK:
no_wire_intersection_check = value;
break;
case GV_PRECISION_FACTOR:
precision_factor = value;
break;
case GV_NO_WIRE_INTERSECTION_TOLERANCE:
no_wire_intersection_tolerance = value;
break;
default: default:
throw std::runtime_error("Invalid setting"); throw std::runtime_error("Invalid setting");
} }
@@ -1444,6 +1453,12 @@ double IfcGeom::Kernel::getValue(GeomValue var) const {
return layerset_first; return layerset_first;
case GV_DISABLE_BOOLEAN_RESULT: case GV_DISABLE_BOOLEAN_RESULT:
return disable_boolean_result; return disable_boolean_result;
case GV_NO_WIRE_INTERSECTION_CHECK:
return no_wire_intersection_check;
case GV_PRECISION_FACTOR:
return precision_factor;
case GV_NO_WIRE_INTERSECTION_TOLERANCE:
return no_wire_intersection_tolerance;
} }
throw std::runtime_error("Invalid setting"); throw std::runtime_error("Invalid setting");
} }
@@ -3794,6 +3809,11 @@ namespace {
} }
bool IfcGeom::Kernel::wire_intersections(const TopoDS_Wire& wire, TopTools_ListOfShape& wires) { bool IfcGeom::Kernel::wire_intersections(const TopoDS_Wire& wire, TopTools_ListOfShape& wires) {
if (getValue(GV_NO_WIRE_INTERSECTION_CHECK) > 0.) {
return false;
}
if (!wire.Closed()) { if (!wire.Closed()) {
wires.Append(wire); wires.Append(wire);
return false; return false;
@@ -3836,11 +3856,14 @@ bool IfcGeom::Kernel::wire_intersections(const TopoDS_Wire& wire, TopTools_ListO
// TopoDS_Face face = BRepBuilderAPI_MakeFace(wire, true).Face(); // TopoDS_Face face = BRepBuilderAPI_MakeFace(wire, true).Face();
// ShapeAnalysis_Wire saw(wd, face, getValue(GV_PRECISION)); // ShapeAnalysis_Wire saw(wd, face, getValue(GV_PRECISION));
const double eps = faceset_helper_ double eps = 0;
// eps is added to both ends of the parametric domain, so 3. is chosen to be on the safe side here. if (getValue(GV_NO_WIRE_INTERSECTION_TOLERANCE) < 0.) {
? (faceset_helper_->epsilon() / 3.) eps = faceset_helper_
// @todo re-evaluate 2. here for the reasons above: // eps is added to both ends of the parametric domain, so 3. is chosen to be on the safe side here.
: (std::min)(min_edge_length(wire) / 2., getValue(GV_PRECISION) * 10.); ? (faceset_helper_->epsilon() / 3.)
// @todo re-evaluate 2. here for the reasons above:
: (std::min)(min_edge_length(wire) / 2., getValue(GV_PRECISION) * 10.);
}
for (int i = 2; i < n; ++i) { for (int i = 2; i < n; ++i) {
+17 -1
View File
@@ -350,7 +350,7 @@ namespace IfcGeom {
if (any_precision_encountered) { if (any_precision_encountered) {
// Some arbitrary factor that has proven to work better for the models in the set of test files. // Some arbitrary factor that has proven to work better for the models in the set of test files.
lowest_precision_encountered *= 10.; lowest_precision_encountered *= kernel.getValue(IfcGeom::Kernel::GV_PRECISION_FACTOR);
lowest_precision_encountered *= unit_magnitude; lowest_precision_encountered *= unit_magnitude;
if (lowest_precision_encountered < 1.e-7) { if (lowest_precision_encountered < 1.e-7) {
@@ -1003,6 +1003,22 @@ namespace IfcGeom {
? +1.0 ? +1.0
: -1.0 : -1.0
); );
kernel.setValue(IfcGeom::Kernel::GV_NO_WIRE_INTERSECTION_CHECK,
settings.get(IteratorSettings::NO_WIRE_INTERSECTION_CHECK)
? +1.0
: -1.0
);
kernel.setValue(IfcGeom::Kernel::GV_NO_WIRE_INTERSECTION_TOLERANCE,
settings.get(IteratorSettings::NO_WIRE_INTERSECTION_TOLERANCE)
? +1.0
: -1.0
);
kernel.setValue(IfcGeom::Kernel::GV_PRECISION_FACTOR,
settings.get(IteratorSettings::STRICT_TOLERANCE)
? 1.0
: 10.0
);
kernel.setValue(IfcGeom::Kernel::GV_DISABLE_BOOLEAN_RESULT, kernel.setValue(IfcGeom::Kernel::GV_DISABLE_BOOLEAN_RESULT,
settings.get(IteratorSettings::DISABLE_BOOLEAN_RESULT) settings.get(IteratorSettings::DISABLE_BOOLEAN_RESULT)
? +1.0 ? +1.0
+7 -1
View File
@@ -94,8 +94,14 @@ namespace IfcGeom
EDGE_ARROWS = 1 << 19, EDGE_ARROWS = 1 << 19,
/// Disables the evaluation of IfcBooleanResult and simply returns FirstOperand /// Disables the evaluation of IfcBooleanResult and simply returns FirstOperand
DISABLE_BOOLEAN_RESULT = 1 << 20, DISABLE_BOOLEAN_RESULT = 1 << 20,
// Disables wire intersection checks
NO_WIRE_INTERSECTION_CHECK = 1 << 21,
// Set wire intersection tolerance to 0
NO_WIRE_INTERSECTION_TOLERANCE = 1 << 22,
// Sets kernel precision factor to 1
STRICT_TOLERANCE = 1 << 23,
/// Number of different setting flags. /// Number of different setting flags.
NUM_SETTINGS = 20 NUM_SETTINGS = 24,
}; };
/// Used to store logical OR combination of setting flags. /// Used to store logical OR combination of setting flags.
typedef unsigned SettingField; typedef unsigned SettingField;
+28 -11
View File
@@ -869,21 +869,38 @@ bool IfcGeom::Kernel::convert(const IfcSchema::IfcGeometricSet* l, IfcRepresenta
if ( !elements->size() ) return false; if ( !elements->size() ) return false;
bool part_succes = false; bool part_succes = false;
const IfcGeom::SurfaceStyle* parent_style = get_style(l); const IfcGeom::SurfaceStyle* parent_style = get_style(l);
for ( IfcEntityList::it it = elements->begin(); it != elements->end(); ++ it ) { for (IfcEntityList::it it = elements->begin(); it != elements->end(); ++it) {
IfcSchema::IfcGeometricSetSelect* element = *it; IfcSchema::IfcGeometricSetSelect* element = *it;
TopoDS_Shape s; TopoDS_Shape s;
if (convert_shape(element, s)) { if (shape_type(element) == ST_SHAPELIST) {
part_succes = true; IfcRepresentationShapeItems items;
const IfcGeom::SurfaceStyle* style = 0; if (!(convert_shapes(element, items) && flatten_shape_list(items, s, false))) {
if (element->declaration().is(IfcSchema::IfcPoint::Class())) { continue;
style = get_style((IfcSchema::IfcPoint*) element);
} else if (element->declaration().is(IfcSchema::IfcCurve::Class())) {
style = get_style((IfcSchema::IfcCurve*) element);
} else if (element->declaration().is(IfcSchema::IfcSurface::Class())) {
style = get_style((IfcSchema::IfcSurface*) element);
} }
shapes.push_back(IfcRepresentationShapeItem(l->data().id(), s, style ? style : parent_style)); } else if (shape_type(element) == ST_SHAPE) {
if (!convert_shape(element, s)) {
continue;
}
} else if (shape_type(element) == ST_WIRE) {
TopoDS_Wire w;
if (!convert_wire(element, w)) {
continue;
}
s = w;
} }
part_succes = true;
const IfcGeom::SurfaceStyle* style = 0;
if (element->declaration().is(IfcSchema::IfcPoint::Class())) {
style = get_style((IfcSchema::IfcPoint*) element);
}
else if (element->declaration().is(IfcSchema::IfcCurve::Class())) {
style = get_style((IfcSchema::IfcCurve*) element);
}
else if (element->declaration().is(IfcSchema::IfcSurface::Class())) {
style = get_style((IfcSchema::IfcSurface*) element);
}
shapes.push_back(IfcRepresentationShapeItem(l->data().id(), s, style ? style : parent_style));
} }
return part_succes; return part_succes;
} }
+5 -2
View File
@@ -53,8 +53,11 @@ namespace IfcGeom {
GV_PRECISION, GV_PRECISION,
// Whether to process shapes of type Face or higher (1) Wire or lower (-1) or all (0) // Whether to process shapes of type Face or higher (1) Wire or lower (-1) or all (0)
GV_DIMENSIONALITY, GV_DIMENSIONALITY,
GV_LAYERSET_FIRST, GV_LAYERSET_FIRST,
GV_DISABLE_BOOLEAN_RESULT GV_DISABLE_BOOLEAN_RESULT,
GV_NO_WIRE_INTERSECTION_CHECK,
GV_PRECISION_FACTOR,
GV_NO_WIRE_INTERSECTION_TOLERANCE,
}; };
Kernel(IfcParse::IfcFile* file_ = 0); Kernel(IfcParse::IfcFile* file_ = 0);
+69 -50
View File
@@ -788,73 +788,92 @@ void SvgSerializer::write(const geometry_data& data) {
auto ot_arg = data.product->get("ObjectType"); auto ot_arg = data.product->get("ObjectType");
if (!ot_arg->isNull()) { if (!ot_arg->isNull()) {
object_type = (std::string) *ot_arg; object_type = (std::string) *ot_arg;
object_type.erase(std::remove_if(object_type.begin(), object_type.end(), [](char c) { return !std::isalnum(c); }), object_type.end());
} }
if (data.product->declaration().is("IfcAnnotation") && // is an Annotation if (data.product->declaration().is("IfcAnnotation") && // is an Annotation
object_type == "Dimension" && // with ObjectType='Dimension'
(proj.Magnitude() > 1.e-5) && // when projected onto the view has a length (proj.Magnitude() > 1.e-5) && // when projected onto the view has a length
zmin >= range.first && zmin <= range.second) // the Z-coords are within the range of the building storey zmin >= range.first && zmin <= range.second) // the Z-coords are within the range of the building storey
{ {
auto svg_name = data.svg_name;
if (object_type.size()) {
// postfix the object_type for CSS matching
boost::replace_all(svg_name, "class=\"IfcAnnotation\"", "class=\"IfcAnnotation " + object_type + "\"");
}
if (po == nullptr) { if (po == nullptr) {
if (storey) { if (storey) {
po = &start_path(pln, storey, data.svg_name); po = &start_path(pln, storey, svg_name);
} else { } else {
po = &start_path(pln, drawing_name, data.svg_name); po = &start_path(pln, drawing_name, svg_name);
} }
} }
TopExp_Explorer exp(subshape, TopAbs_EDGE, TopAbs_FACE); if (object_type == "Dimension") {
for (; exp.More(); exp.Next()) {
const auto& e = TopoDS::Edge(exp.Current());
TopoDS_Vertex v0, v1;
TopExp::Vertices(e, v0, v1);
gp_Pnt p0 = BRep_Tool::Pnt(v0);
gp_Pnt p1 = BRep_Tool::Pnt(v1);
// @todo should we take the average parameter value instead?
gp_XYZ center = (p0.XYZ() + p1.XYZ()) / 2.;
BRep_Builder B;
TopoDS_Wire W;
B.MakeWire(W);
B.Add(W, e);
write(*po, W);
TopExp_Explorer exp(subshape, TopAbs_EDGE, TopAbs_FACE);
for (; exp.More(); exp.Next()) {
const auto& e = TopoDS::Edge(exp.Current());
TopoDS_Vertex v0, v1;
TopExp::Vertices(e, v0, v1);
gp_Pnt p0 = BRep_Tool::Pnt(v0);
gp_Pnt p1 = BRep_Tool::Pnt(v1);
BRep_Builder B;
TopoDS_Wire W;
B.MakeWire(W);
B.Add(W, e);
write(*po, W);
// @todo should we take the average parameter value instead?
gp_XYZ center = (p0.XYZ() + p1.XYZ()) / 2.;
util::string_buffer path;
util::string_buffer path; // dominant-baseline="central" is not well supported in IE.
// dominant-baseline="central" is not well supported in IE. // so we add a 0.35 offset to the dy of the tspans
// so we add a 0.35 offset to the dy of the tspans path.add(" <text class=\"IfcAnnotation\" text-anchor=\"middle\" x=\"");
path.add(" <text class=\"IfcAnnotation\" text-anchor=\"middle\" x=\"");
xcoords.push_back(path.add(center.X()));
path.add("\" y=\"");
ycoords.push_back(path.add(center.Y()));
path.add("\">");
std::vector<std::string> labels{};
GProp_GProps prop;
BRepGProp::LinearProperties(e, prop);
const double area = prop.Mass();
std::stringstream ss;
ss << std::setprecision(2) << std::fixed << std::showpoint << area;
labels.push_back(ss.str() + "m");
for (auto lit = labels.begin(); lit != labels.end(); ++lit) {
const auto& l = *lit;
double dy = labels.begin() == lit
? 0.35 - (labels.size() - 1.) / 2.
: 1.0; // <- dy is relative to the previous text element, so
// always 1 for successive spans.
path.add("<tspan x=\"");
xcoords.push_back(path.add(center.X())); xcoords.push_back(path.add(center.X()));
path.add("\" dy=\""); path.add("\" y=\"");
path.add(boost::lexical_cast<std::string>(dy)); ycoords.push_back(path.add(center.Y()));
path.add("em\">"); path.add("\">");
path.add(l); std::vector<std::string> labels{};
path.add("</tspan>");
GProp_GProps prop;
BRepGProp::LinearProperties(e, prop);
const double area = prop.Mass();
std::stringstream ss;
ss << std::setprecision(2) << std::fixed << std::showpoint << area;
labels.push_back(ss.str() + "m");
for (auto lit = labels.begin(); lit != labels.end(); ++lit) {
const auto& l = *lit;
double dy = labels.begin() == lit
? 0.35 - (labels.size() - 1.) / 2.
: 1.0; // <- dy is relative to the previous text element, so
// always 1 for successive spans.
path.add("<tspan x=\"");
xcoords.push_back(path.add(center.X()));
path.add("\" dy=\"");
path.add(boost::lexical_cast<std::string>(dy));
path.add("em\">");
path.add(l);
path.add("</tspan>");
}
path.add("</text>");
po->second.push_back(path);
} }
path.add("</text>");
po->second.push_back(path); } else if (object_type == "Symbol") {
TopExp_Explorer exp(subshape, TopAbs_WIRE, TopAbs_FACE);
for (; exp.More(); exp.Next()) {
const auto& W = TopoDS::Wire(exp.Current());
write(*po, W);
}
} }
// We're finished processing IfcAnnotation instances
continue; continue;
} }
@@ -1396,7 +1415,7 @@ void SvgSerializer::writeHeader() {
" .IfcSpace path {\n" " .IfcSpace path {\n"
" fill-opacity: .2;\n" " fill-opacity: .2;\n"
" }\n" " }\n"
" .IfcAnnotation path {\n" " .dimension path {\n"
" marker-end: url(#arrowend);\n" " marker-end: url(#arrowend);\n"
" marker-start: url(#arrowstart);\n" " marker-start: url(#arrowstart);\n"
" }\n"; " }\n";
+3 -3
View File
@@ -73,7 +73,7 @@ if not (%1)==() (
) )
pushd .. pushd ..
set CMAKE_INSTALL_PREFIX=%CD%\installed-%GEN_SHORTHAND% set CMAKE_INSTALL_PREFIX=%CD%\_installed-%GEN_SHORTHAND%
popd popd
IF NOT EXIST ..\%BUILD_DIR%. mkdir ..\%BUILD_DIR% IF NOT EXIST ..\%BUILD_DIR%. mkdir ..\%BUILD_DIR%
@@ -136,9 +136,9 @@ if not (%1)==() if exist CMakeCache.txt. del /Q CMakeCache.txt
call cecho.cmd 0 13 "Running CMake for %PROJECT_NAME%." call cecho.cmd 0 13 "Running CMake for %PROJECT_NAME%."
IF DEFINED VS_TOOLSET ( IF DEFINED VS_TOOLSET (
cmake.exe %CMAKELISTS_DIR% -G %GENERATOR% -A %VS_PLATFORM% -T %VS_TOOLSET% -DCMAKE_INSTALL_PREFIX="%CMAKE_INSTALL_PREFIX%" %ARGUMENTS% cmake.exe %CMAKELISTS_DIR% -G %GENERATOR% -A %VS_PLATFORM% -T %VS_TOOLSET% -DCMAKE_INSTALL_PREFIX="%CMAKE_INSTALL_PREFIX%" -DBoost_NO_BOOST_CMAKE=On %ARGUMENTS%
) ELSE ( ) ELSE (
cmake.exe %CMAKELISTS_DIR% -G %GENERATOR% -A %VS_PLATFORM% -DCMAKE_INSTALL_PREFIX="%CMAKE_INSTALL_PREFIX%" %ARGUMENTS% cmake.exe %CMAKELISTS_DIR% -G %GENERATOR% -A %VS_PLATFORM% -DCMAKE_INSTALL_PREFIX="%CMAKE_INSTALL_PREFIX%" -DBoost_NO_BOOST_CMAKE=On %ARGUMENTS%
) )
IF NOT %ERRORLEVEL%==0 GOTO :Error IF NOT %ERRORLEVEL%==0 GOTO :Error