mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-27 02:31:09 +00:00
Merge branch 'v0.8.0' into ifcmax/initial-refresh
This commit is contained in:
@@ -42,9 +42,6 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
mkdir build && cd build
|
mkdir build && cd build
|
||||||
cmake \
|
cmake \
|
||||||
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
|
||||||
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache \
|
|
||||||
-DCMAKE_CXX_STANDARD=17 \
|
|
||||||
-DCMAKE_INSTALL_PREFIX=$PWD/install/ \
|
-DCMAKE_INSTALL_PREFIX=$PWD/install/ \
|
||||||
-DCMAKE_BUILD_TYPE=Release \
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
-DCMAKE_PREFIX_PATH=/usr \
|
-DCMAKE_PREFIX_PATH=/usr \
|
||||||
|
|||||||
+12
-10
@@ -55,6 +55,11 @@ jobs:
|
|||||||
- name: Install C++ dependencies
|
- name: Install C++ dependencies
|
||||||
run: |
|
run: |
|
||||||
sudo apt update
|
sudo apt update
|
||||||
|
# `occt-misc` is only needed for 22.04, since it has cmake configs.
|
||||||
|
# In 24.04+, the needed files were moved `libocct-foundation-dev` and `occt-misc` can be removed.
|
||||||
|
# Other libs in `OCCT_CMAKE_DEPS` are needed only for cmake config to work properly, they're not used directly.
|
||||||
|
OCCT_CMAKE_DEPS="occt-misc libocct-draw-dev tcl-dev tk-dev libxi-dev"
|
||||||
|
|
||||||
sudo apt-get install --no-install-recommends \
|
sudo apt-get install --no-install-recommends \
|
||||||
git cmake gcc g++ \
|
git cmake gcc g++ \
|
||||||
libboost-date-time-dev \
|
libboost-date-time-dev \
|
||||||
@@ -67,6 +72,7 @@ jobs:
|
|||||||
libpcre3-dev libxml2-dev \
|
libpcre3-dev libxml2-dev \
|
||||||
libtbb-dev nlohmann-json3-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 \
|
libocct-foundation-dev libocct-modeling-algorithms-dev libocct-modeling-data-dev libocct-ocaf-dev libocct-visualization-dev libocct-data-exchange-dev \
|
||||||
|
${OCCT_CMAKE_DEPS} \
|
||||||
libhdf5-dev libcgal-dev libeigen3-dev
|
libhdf5-dev libcgal-dev libeigen3-dev
|
||||||
|
|
||||||
- name: ccache
|
- name: ccache
|
||||||
@@ -150,9 +156,8 @@ jobs:
|
|||||||
# Remove default swig to avoid conflicts.
|
# Remove default swig to avoid conflicts.
|
||||||
sudo apt remove --purge swig swig4.0
|
sudo apt remove --purge swig swig4.0
|
||||||
sudo apt-get install -y libpcre2-dev bison
|
sudo apt-get install -y libpcre2-dev bison
|
||||||
git clone https://github.com/swig/swig
|
git clone https://github.com/swig/swig --branch v4.1.0 --depth 1
|
||||||
cd swig
|
cd swig
|
||||||
git checkout v4.1.0
|
|
||||||
mkdir build && cd build
|
mkdir build && cd build
|
||||||
cmake .. \
|
cmake .. \
|
||||||
-DCMAKE_BUILD_TYPE=Release \
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
@@ -166,15 +171,10 @@ jobs:
|
|||||||
echo ${{ env.pythonLocation }}
|
echo ${{ env.pythonLocation }}
|
||||||
|
|
||||||
mkdir build && cd build
|
mkdir build && cd build
|
||||||
# Ubuntu 22.04's libocct-foundation-dev package doesn't have Config.cmake, so we provide OCC paths directly.
|
|
||||||
# In later versions of Ubuntu, this can be simplified and the OCC paths can be removed.
|
|
||||||
cmake \
|
cmake \
|
||||||
-DCMAKE_CXX_STANDARD=17 \
|
|
||||||
-DCMAKE_BUILD_TYPE=Release \
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
-DCMAKE_PREFIX_PATH=/usr \
|
-DCMAKE_PREFIX_PATH=/usr \
|
||||||
-DCMAKE_SYSTEM_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_EXECUTABLE:FILEPATH=${{ env.pythonLocation }}/bin/python \
|
||||||
-DPYTHON_INCLUDE_DIR:PATH=${{ env.pythonLocation }}/include/python3.11 \
|
-DPYTHON_INCLUDE_DIR:PATH=${{ env.pythonLocation }}/include/python3.11 \
|
||||||
-DUSE_MMAP=On \
|
-DUSE_MMAP=On \
|
||||||
@@ -207,11 +207,13 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
cd src/examples
|
cd src/examples
|
||||||
mkdir build && cd build
|
mkdir build && cd build
|
||||||
cmake .. -DCMAKE_BUILD_TYPE=Release
|
cmake .. -DCMAKE_BUILD_TYPE=Release \
|
||||||
|
-DCMAKE_C_COMPILER_LAUNCHER=ccache \
|
||||||
|
-DCMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||||
cmake --build .
|
cmake --build .
|
||||||
./IfcParseExamples "../IfcParseExamples_test.ifc"
|
./IfcParseExamples "../IfcParseExamples_test.ifc"
|
||||||
# ./IfcOpenHouse
|
./IfcOpenHouse
|
||||||
# ./IfcAdvancedHouse
|
./IfcAdvancedHouse
|
||||||
./IfcAlignment
|
./IfcAlignment
|
||||||
./IfcSimplifiedAlignment
|
./IfcSimplifiedAlignment
|
||||||
|
|
||||||
|
|||||||
@@ -46,7 +46,6 @@ jobs:
|
|||||||
mkdir build && cd build
|
mkdir build && cd build
|
||||||
cmake \
|
cmake \
|
||||||
-DCMAKE_INSTALL_PREFIX=$PWD/install/ \
|
-DCMAKE_INSTALL_PREFIX=$PWD/install/ \
|
||||||
-DCMAKE_CXX_STANDARD=17 \
|
|
||||||
-DCMAKE_BUILD_TYPE=Release \
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
-DCMAKE_PREFIX_PATH=/usr \
|
-DCMAKE_PREFIX_PATH=/usr \
|
||||||
-DCMAKE_SYSTEM_PREFIX_PATH=/usr \
|
-DCMAKE_SYSTEM_PREFIX_PATH=/usr \
|
||||||
|
|||||||
@@ -208,8 +208,6 @@ endforeach()
|
|||||||
|
|
||||||
if(BUILD_IFCGEOM AND WITH_OPENCASCADE)
|
if(BUILD_IFCGEOM AND WITH_OPENCASCADE)
|
||||||
find_package(OpenCASCADE REQUIRED)
|
find_package(OpenCASCADE REQUIRED)
|
||||||
# Map OpenCASCADE_LIBRARIES variable from OpenCASCADEConfig.cmake to OpenCASCADE_LIBRARIES used by kernel generic cmake file
|
|
||||||
set(OpenCASCADE_LIBRARIES ${OpenCASCADE_LIBRARIES})
|
|
||||||
add_definitions(-DIFOPSH_WITH_OPENCASCADE)
|
add_definitions(-DIFOPSH_WITH_OPENCASCADE)
|
||||||
set(SWIG_DEFINES ${SWIG_DEFINES} -DIFOPSH_WITH_OPENCASCADE)
|
set(SWIG_DEFINES ${SWIG_DEFINES} -DIFOPSH_WITH_OPENCASCADE)
|
||||||
list(APPEND GEOMETRY_KERNELS opencascade)
|
list(APPEND GEOMETRY_KERNELS opencascade)
|
||||||
|
|||||||
@@ -39,7 +39,14 @@ if(NOT OCC_INCLUDE_DIR AND NOT OCC_LIBRARY_DIR)
|
|||||||
mark_as_advanced(OpenCASCADE_DIR)
|
mark_as_advanced(OpenCASCADE_DIR)
|
||||||
message(STATUS "Found OpenCASCADE config: ${OpenCASCADE_DIR}")
|
message(STATUS "Found OpenCASCADE config: ${OpenCASCADE_DIR}")
|
||||||
|
|
||||||
if(OpenCASCADE_VERSION VERSION_LESS "7.9.0")
|
if(OpenCASCADE_VERSION VERSION_LESS "7.7.0")
|
||||||
|
# cmake configs < 7.7.0 were not adding include directories to targets automatically.
|
||||||
|
set_target_properties(TKernel PROPERTIES
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "${OpenCASCADE_INCLUDE_DIR}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
|
if(OpenCASCADE_VERSION VERSION_LESS "7.9.0" AND WIN32)
|
||||||
# Bug in OCCT cmake configs < 7.9.0 - missing linked library.
|
# Bug in OCCT cmake configs < 7.9.0 - missing linked library.
|
||||||
list(APPEND OpenCASCADE_LIBRARIES WSOCK32.lib)
|
list(APPEND OpenCASCADE_LIBRARIES WSOCK32.lib)
|
||||||
endif()
|
endif()
|
||||||
@@ -145,8 +152,10 @@ if(OCCT_STATIC)
|
|||||||
endif()
|
endif()
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
add_library(OpenCASCADE_INTERFACE INTERFACE IMPORTED)
|
add_library(OpenCASCADE_INTERFACE INTERFACE)
|
||||||
target_include_directories(OpenCASCADE_INTERFACE INTERFACE "${OCC_INCLUDE_DIR}")
|
target_include_directories(OpenCASCADE_INTERFACE INTERFACE "${OCC_INCLUDE_DIR}")
|
||||||
target_link_libraries(OpenCASCADE_INTERFACE INTERFACE ${OpenCASCADE_LIBRARIES})
|
target_link_libraries(OpenCASCADE_INTERFACE INTERFACE ${OpenCASCADE_LIBRARIES})
|
||||||
target_link_directories(OpenCASCADE_INTERFACE INTERFACE "${OCC_LIBRARY_DIR}")
|
target_link_directories(OpenCASCADE_INTERFACE INTERFACE "${OCC_LIBRARY_DIR}")
|
||||||
set(OpenCASCADE_LIBRARIES OpenCASCADE_INTERFACE)
|
set(OpenCASCADE_LIBRARIES OpenCASCADE_INTERFACE)
|
||||||
|
install(TARGETS OpenCASCADE_INTERFACE
|
||||||
|
EXPORT ${IFCOPENSHELL_EXPORT_TARGETS})
|
||||||
|
|||||||
+2
-3
@@ -9,7 +9,6 @@ set LIBXML2="%LIBRARY_PREFIX%/lib/libxml2.lib"
|
|||||||
cmake -G "Ninja" ^
|
cmake -G "Ninja" ^
|
||||||
-D SCHEMA_VERSIONS="2x3;4;4x1;4x3_add2" ^
|
-D SCHEMA_VERSIONS="2x3;4;4x1;4x3_add2" ^
|
||||||
-D CMAKE_BUILD_TYPE:STRING=Release ^
|
-D CMAKE_BUILD_TYPE:STRING=Release ^
|
||||||
-D CMAKE_CXX_STANDARD=17 ^
|
|
||||||
-D CMAKE_INSTALL_PREFIX:FILEPATH="%LIBRARY_PREFIX%" ^
|
-D CMAKE_INSTALL_PREFIX:FILEPATH="%LIBRARY_PREFIX%" ^
|
||||||
-D CMAKE_PREFIX_PATH:FILEPATH="%LIBRARY_PREFIX%" ^
|
-D CMAKE_PREFIX_PATH:FILEPATH="%LIBRARY_PREFIX%" ^
|
||||||
-D CMAKE_SYSTEM_PREFIX_PATH:FILEPATH="%LIBRARY_PREFIX%" ^
|
-D CMAKE_SYSTEM_PREFIX_PATH:FILEPATH="%LIBRARY_PREFIX%" ^
|
||||||
@@ -43,7 +42,7 @@ cmake -G "Ninja" ^
|
|||||||
-D Boost_INCLUDE_DIR:FILEPATH="%LIBRARY_PREFIX%\include" ^
|
-D Boost_INCLUDE_DIR:FILEPATH="%LIBRARY_PREFIX%\include" ^
|
||||||
-D Boost_USE_STATIC_LIBS:BOOL=OFF ^
|
-D Boost_USE_STATIC_LIBS:BOOL=OFF ^
|
||||||
../cmake
|
../cmake
|
||||||
|
|
||||||
if errorlevel 1 exit 1
|
if errorlevel 1 exit 1
|
||||||
|
|
||||||
ninja install -j 1
|
ninja install -j 1
|
||||||
@@ -52,4 +51,4 @@ if errorlevel 1 exit 1
|
|||||||
|
|
||||||
python %RECIPE_DIR%/update_version_init.py %PKG_VERSION% %SP_DIR%/ifcopenshell/__init__.py
|
python %RECIPE_DIR%/update_version_init.py %PKG_VERSION% %SP_DIR%/ifcopenshell/__init__.py
|
||||||
|
|
||||||
if errorlevel 1 exit 1
|
if errorlevel 1 exit 1
|
||||||
|
|||||||
@@ -16,7 +16,6 @@ cmake ${CMAKE_ARGS} -G Ninja \
|
|||||||
-DSCHEMA_VERSIONS="2x3;4;4x1;4x3_add2" \
|
-DSCHEMA_VERSIONS="2x3;4;4x1;4x3_add2" \
|
||||||
-DCMAKE_BUILD_TYPE=Release \
|
-DCMAKE_BUILD_TYPE=Release \
|
||||||
-DCMAKE_INSTALL_PREFIX=$PREFIX \
|
-DCMAKE_INSTALL_PREFIX=$PREFIX \
|
||||||
-DCMAKE_CXX_STANDARD=17 \
|
|
||||||
${CMAKE_PLATFORM_FLAGS[@]} \
|
${CMAKE_PLATFORM_FLAGS[@]} \
|
||||||
-DCMAKE_PREFIX_PATH=$PREFIX \
|
-DCMAKE_PREFIX_PATH=$PREFIX \
|
||||||
-DCMAKE_SYSTEM_PREFIX_PATH=$PREFIX \
|
-DCMAKE_SYSTEM_PREFIX_PATH=$PREFIX \
|
||||||
|
|||||||
@@ -405,8 +405,6 @@ if any(f.startswith("py-") for f in flags):
|
|||||||
if any(f.startswith("occt-") for f in flags):
|
if any(f.startswith("occt-") for f in flags):
|
||||||
OCCT_VERSION = next(f.split("-", 1)[1] for f in flags if f.startswith("occt-"))
|
OCCT_VERSION = next(f.split("-", 1)[1] for f in flags if f.startswith("occt-"))
|
||||||
|
|
||||||
print(OCCT_VERSION)
|
|
||||||
|
|
||||||
if explicit_targets:
|
if explicit_targets:
|
||||||
targets = {dep for target in explicit_targets for dep in gather_dependencies(target)}
|
targets = {dep for target in explicit_targets for dep in gather_dependencies(target)}
|
||||||
else:
|
else:
|
||||||
@@ -1332,7 +1330,6 @@ os.makedirs(executables_dir, exist_ok=True)
|
|||||||
|
|
||||||
|
|
||||||
cmake_args = [
|
cmake_args = [
|
||||||
"-DCMAKE_CXX_STANDARD=17",
|
|
||||||
"-DUSE_MMAP=OFF",
|
"-DUSE_MMAP=OFF",
|
||||||
"-DBUILD_EXAMPLES=OFF",
|
"-DBUILD_EXAMPLES=OFF",
|
||||||
"-DBUILD_SHARED_LIBS=" + OFF_ON[not BUILD_STATIC],
|
"-DBUILD_SHARED_LIBS=" + OFF_ON[not BUILD_STATIC],
|
||||||
|
|||||||
@@ -18,10 +18,12 @@
|
|||||||
|
|
||||||
import bpy
|
import bpy
|
||||||
from . import ui, prop, operator, handler, gizmos, workspace
|
from . import ui, prop, operator, handler, gizmos, workspace
|
||||||
|
import bonsai.tool as tool
|
||||||
|
|
||||||
classes = (
|
classes = (
|
||||||
operator.ActivateDrawing,
|
operator.ActivateDrawing,
|
||||||
operator.ActivateDrawingFromSheet,
|
operator.ActivateDrawingFromSheet,
|
||||||
|
operator.ActivateDrawingByAnnotation,
|
||||||
operator.ActivateDrawingStyle,
|
operator.ActivateDrawingStyle,
|
||||||
operator.ActivateModel,
|
operator.ActivateModel,
|
||||||
operator.AddAnnotation,
|
operator.AddAnnotation,
|
||||||
@@ -134,6 +136,13 @@ classes = (
|
|||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def menu_func(self, context):
|
||||||
|
active_obj = context.active_object
|
||||||
|
if active_obj:
|
||||||
|
element = tool.Ifc.get_entity(active_obj)
|
||||||
|
if element and element.is_a("IfcAnnotation") and element.ObjectType in ["SECTION", "ELEVATION"]:
|
||||||
|
self.layout.operator("bim.activate_drawing_by_annotation", text="Go to Drawing")
|
||||||
|
|
||||||
def register():
|
def register():
|
||||||
if not bpy.app.background:
|
if not bpy.app.background:
|
||||||
bpy.utils.register_tool(workspace.AnnotationTool, after={"bim.bim_tool"}, separator=True, group=False)
|
bpy.utils.register_tool(workspace.AnnotationTool, after={"bim.bim_tool"}, separator=True, group=False)
|
||||||
@@ -146,6 +155,7 @@ def register():
|
|||||||
bpy.app.handlers.load_post.append(handler.load_post)
|
bpy.app.handlers.load_post.append(handler.load_post)
|
||||||
bpy.app.handlers.depsgraph_update_pre.append(handler.depsgraph_update_pre_handler)
|
bpy.app.handlers.depsgraph_update_pre.append(handler.depsgraph_update_pre_handler)
|
||||||
bpy.types.VIEW3D_MT_image_add.append(ui.add_object_button)
|
bpy.types.VIEW3D_MT_image_add.append(ui.add_object_button)
|
||||||
|
bpy.types.VIEW3D_MT_object_context_menu.append(menu_func)
|
||||||
|
|
||||||
|
|
||||||
def unregister():
|
def unregister():
|
||||||
@@ -160,3 +170,4 @@ def unregister():
|
|||||||
bpy.app.handlers.load_post.remove(handler.load_post)
|
bpy.app.handlers.load_post.remove(handler.load_post)
|
||||||
bpy.app.handlers.depsgraph_update_pre.remove(handler.depsgraph_update_pre_handler)
|
bpy.app.handlers.depsgraph_update_pre.remove(handler.depsgraph_update_pre_handler)
|
||||||
bpy.types.VIEW3D_MT_image_add.remove(ui.add_object_button)
|
bpy.types.VIEW3D_MT_image_add.remove(ui.add_object_button)
|
||||||
|
bpy.types.VIEW3D_MT_object_context_menu.remove(menu_func)
|
||||||
|
|||||||
@@ -3050,10 +3050,21 @@ class AddReference(bpy.types.Operator, tool.Ifc.Operator, ImportHelper):
|
|||||||
filter_glob: bpy.props.StringProperty(default="*.svg", options={"HIDDEN"})
|
filter_glob: bpy.props.StringProperty(default="*.svg", options={"HIDDEN"})
|
||||||
use_relative_path: bpy.props.BoolProperty(name="Use Relative Path", default=True)
|
use_relative_path: bpy.props.BoolProperty(name="Use Relative Path", default=True)
|
||||||
filename_ext = ".svg"
|
filename_ext = ".svg"
|
||||||
|
|
||||||
|
files: bpy.props.CollectionProperty(type=bpy.types.OperatorFileListElement)
|
||||||
|
directory: bpy.props.StringProperty(subtype='DIR_PATH')
|
||||||
|
|
||||||
def _execute(self, context):
|
def _execute(self, context):
|
||||||
filepath = tool.Ifc.get_uri(self.filepath, use_relative_path=self.use_relative_path)
|
# Handle both single and multiple file selection
|
||||||
core.add_document(tool.Ifc, tool.Drawing, "REFERENCE", uri=filepath)
|
if self.files:
|
||||||
|
for file_elem in self.files:
|
||||||
|
filepath = os.path.join(self.directory, file_elem.name)
|
||||||
|
uri = tool.Ifc.get_uri(filepath, use_relative_path=self.use_relative_path)
|
||||||
|
core.add_document(tool.Ifc, tool.Drawing, "REFERENCE", uri=uri)
|
||||||
|
else:
|
||||||
|
# Fallback for single file (backward compatibility)
|
||||||
|
filepath = tool.Ifc.get_uri(self.filepath, use_relative_path=self.use_relative_path)
|
||||||
|
core.add_document(tool.Ifc, tool.Drawing, "REFERENCE", uri=filepath)
|
||||||
|
|
||||||
|
|
||||||
class RemoveReference(bpy.types.Operator, tool.Ifc.Operator):
|
class RemoveReference(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
@@ -3876,3 +3887,67 @@ class ExcludeAnnotation(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
if referenced_element := tool.Drawing.get_annotation_element(element):
|
if referenced_element := tool.Drawing.get_annotation_element(element):
|
||||||
tool.Drawing.exclude_annotation_from_drawing(referenced_element, drawing)
|
tool.Drawing.exclude_annotation_from_drawing(referenced_element, drawing)
|
||||||
core.sync_references(tool.Ifc, tool.Collector, tool.Drawing, drawing=drawing)
|
core.sync_references(tool.Ifc, tool.Collector, tool.Drawing, drawing=drawing)
|
||||||
|
|
||||||
|
class ActivateDrawingByAnnotation(bpy.types.Operator, tool.Ifc.Operator):
|
||||||
|
bl_idname = "bim.activate_drawing_by_annotation"
|
||||||
|
bl_label = "Activate Drawing"
|
||||||
|
bl_description = "Activate the drawing corresponding to the selected annotation"
|
||||||
|
bl_options = {"REGISTER", "UNDO"}
|
||||||
|
|
||||||
|
@classmethod
|
||||||
|
def poll(cls, context):
|
||||||
|
# Check if an annotation object is selected
|
||||||
|
if not context.selected_objects:
|
||||||
|
cls.poll_message_set("No object selected")
|
||||||
|
return False
|
||||||
|
|
||||||
|
active_obj = context.active_object
|
||||||
|
if not active_obj:
|
||||||
|
cls.poll_message_set("No active object")
|
||||||
|
return False
|
||||||
|
|
||||||
|
element = tool.Ifc.get_entity(active_obj)
|
||||||
|
if not element:
|
||||||
|
cls.poll_message_set("Selected object is not an IFC element")
|
||||||
|
return False
|
||||||
|
|
||||||
|
# Check if it's an IfcAnnotation with ObjectType = "SECTION" or "ELEVATION"
|
||||||
|
if not element.is_a("IfcAnnotation") or element.ObjectType not in ["SECTION", "ELEVATION"]:
|
||||||
|
cls.poll_message_set("Selected object is not a drawing annotation")
|
||||||
|
return False
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
def _execute(self, context):
|
||||||
|
active_obj = context.active_object
|
||||||
|
element = tool.Ifc.get_entity(active_obj)
|
||||||
|
|
||||||
|
if not element or not element.is_a("IfcAnnotation") or element.ObjectType not in ["SECTION", "ELEVATION"]:
|
||||||
|
self.report({"ERROR"}, "Selected object is not a drawing annotation")
|
||||||
|
return {"CANCELLED"}
|
||||||
|
|
||||||
|
# Find the drawing/camera element that this annotation references
|
||||||
|
drawing_element = self.find_drawing_from_annotation(element)
|
||||||
|
|
||||||
|
if not drawing_element:
|
||||||
|
self.report({"ERROR"}, "Could not find drawing element for this annotation")
|
||||||
|
return {"CANCELLED"}
|
||||||
|
|
||||||
|
# Use the existing ActivateDrawing operator with the drawing element's ID
|
||||||
|
bpy.ops.bim.activate_drawing(drawing=drawing_element.id())
|
||||||
|
|
||||||
|
return {"FINISHED"}
|
||||||
|
|
||||||
|
def find_drawing_from_annotation(self, annotation_element):
|
||||||
|
"""Find the drawing/camera element that this annotation references."""
|
||||||
|
ifc = tool.Ifc.get()
|
||||||
|
|
||||||
|
# Check IfcRelAssignsToProduct relationships
|
||||||
|
for rel in ifc.get_inverse(annotation_element):
|
||||||
|
if rel.is_a("IfcRelAssignsToProduct") and rel.RelatingProduct:
|
||||||
|
if rel.RelatingProduct.is_a("IfcAnnotation"):
|
||||||
|
# Found the drawing element!
|
||||||
|
return rel.RelatingProduct
|
||||||
|
|
||||||
|
|
||||||
|
return None
|
||||||
@@ -151,11 +151,29 @@ class FilledOpeningGenerator:
|
|||||||
existing_opening_occurrence, "Model", "Body", "MODEL_VIEW"
|
existing_opening_occurrence, "Model", "Body", "MODEL_VIEW"
|
||||||
)
|
)
|
||||||
assert representation
|
assert representation
|
||||||
representation = ifcopenshell.util.representation.resolve_representation(representation)
|
|
||||||
|
# Check if mapped representation - preserve it
|
||||||
|
if (representation.RepresentationType == 'MappedRepresentation' and
|
||||||
|
len(representation.Items) == 1 and
|
||||||
|
representation.Items[0].is_a("IfcMappedItem")):
|
||||||
|
source_rep = representation.Items[0].MappingSource.MappedRepresentation
|
||||||
|
representation = ifcopenshell.util.element.copy_deep(
|
||||||
|
tool.Ifc.get(),
|
||||||
|
source_rep,
|
||||||
|
exclude=["IfcGeometricRepresentationContext"]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
representation = ifcopenshell.util.representation.resolve_representation(representation)
|
||||||
else:
|
else:
|
||||||
representation = self.generate_opening_from_filling(
|
# Check for library template before generating from filling
|
||||||
filling, filling_obj, opening_thickness_si=opening_thickness_si
|
template_rep = self.get_opening_template_from_type(filling)
|
||||||
)
|
|
||||||
|
if template_rep:
|
||||||
|
representation = template_rep
|
||||||
|
else:
|
||||||
|
representation = self.generate_opening_from_filling(
|
||||||
|
filling, filling_obj, opening_thickness_si=opening_thickness_si
|
||||||
|
)
|
||||||
|
|
||||||
mapped_representation = ifcopenshell.api.geometry.map_representation(
|
mapped_representation = ifcopenshell.api.geometry.map_representation(
|
||||||
tool.Ifc.get(), representation=representation
|
tool.Ifc.get(), representation=representation
|
||||||
@@ -204,38 +222,85 @@ class FilledOpeningGenerator:
|
|||||||
voided_element = opening.VoidsElements[0].RelatingBuildingElement
|
voided_element = opening.VoidsElements[0].RelatingBuildingElement
|
||||||
|
|
||||||
opening_rep = ifcopenshell.util.representation.get_representation(opening, "Model", "Body", "MODEL_VIEW")
|
opening_rep = ifcopenshell.util.representation.get_representation(opening, "Model", "Body", "MODEL_VIEW")
|
||||||
|
|
||||||
|
# ALWAYS preserve the existing opening representation (Tessellation, SweptSolid, etc.)
|
||||||
|
preserved_representation = None
|
||||||
|
if opening_rep:
|
||||||
|
if (opening_rep.RepresentationType == 'MappedRepresentation' and
|
||||||
|
len(opening_rep.Items) == 1 and
|
||||||
|
opening_rep.Items[0].is_a("IfcMappedItem")):
|
||||||
|
# For mapped representations, copy the underlying representation
|
||||||
|
preserved_representation = ifcopenshell.util.element.copy_deep(
|
||||||
|
tool.Ifc.get(),
|
||||||
|
opening_rep.Items[0].MappingSource.MappedRepresentation,
|
||||||
|
exclude=["IfcGeometricRepresentationContext"]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
# For direct representations (non-mapped), copy them too
|
||||||
|
preserved_representation = ifcopenshell.util.element.copy_deep(
|
||||||
|
tool.Ifc.get(),
|
||||||
|
opening_rep,
|
||||||
|
exclude=["IfcGeometricRepresentationContext"]
|
||||||
|
)
|
||||||
|
|
||||||
ifcopenshell.api.geometry.unassign_representation(tool.Ifc.get(), product=opening, representation=opening_rep)
|
ifcopenshell.api.geometry.unassign_representation(tool.Ifc.get(), product=opening, representation=opening_rep)
|
||||||
ifcopenshell.api.geometry.remove_representation(tool.Ifc.get(), representation=opening_rep)
|
ifcopenshell.api.geometry.remove_representation(tool.Ifc.get(), representation=opening_rep)
|
||||||
|
|
||||||
existing_opening_occurrence = self.get_existing_opening_occurrence_if_any(filling)
|
existing_opening_occurrence = self.get_existing_opening_occurrence_if_any(filling)
|
||||||
|
|
||||||
|
# Priority order for choosing representation:
|
||||||
|
# 1. Existing occurrence with Tessellation (best quality)
|
||||||
|
# 2. Library template with Tessellation
|
||||||
|
# 3. Preserved representation from old opening (maintain user's work)
|
||||||
|
# 4. Generate from filling (last resort)
|
||||||
|
|
||||||
|
representation_to_use = None
|
||||||
|
|
||||||
if existing_opening_occurrence:
|
if existing_opening_occurrence:
|
||||||
representation = ifcopenshell.util.representation.get_representation(
|
representation = ifcopenshell.util.representation.get_representation(
|
||||||
existing_opening_occurrence, "Model", "Body", "MODEL_VIEW"
|
existing_opening_occurrence, "Model", "Body", "MODEL_VIEW"
|
||||||
)
|
)
|
||||||
representation = ifcopenshell.util.representation.resolve_representation(representation)
|
|
||||||
mapped_representation = ifcopenshell.api.geometry.map_representation(
|
if (representation and
|
||||||
tool.Ifc.get(), representation=representation
|
representation.RepresentationType == 'MappedRepresentation' and
|
||||||
)
|
len(representation.Items) == 1 and
|
||||||
ifcopenshell.api.geometry.assign_representation(
|
representation.Items[0].is_a("IfcMappedItem")):
|
||||||
tool.Ifc.get(), product=opening, representation=mapped_representation
|
source_rep = representation.Items[0].MappingSource.MappedRepresentation
|
||||||
)
|
# Prefer Tessellation from existing occurrence over preserved representation
|
||||||
else:
|
if source_rep.RepresentationType == 'Tessellation':
|
||||||
|
representation_to_use = ifcopenshell.util.element.copy_deep(
|
||||||
|
tool.Ifc.get(),
|
||||||
|
source_rep,
|
||||||
|
exclude=["IfcGeometricRepresentationContext"]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
representation_to_use = ifcopenshell.util.representation.resolve_representation(representation)
|
||||||
|
|
||||||
|
if not representation_to_use:
|
||||||
|
template_rep = self.get_opening_template_from_type(filling)
|
||||||
|
if template_rep and template_rep.RepresentationType == 'Tessellation':
|
||||||
|
representation_to_use = template_rep
|
||||||
|
|
||||||
|
if not representation_to_use and preserved_representation:
|
||||||
|
representation_to_use = preserved_representation
|
||||||
|
|
||||||
|
if not representation_to_use:
|
||||||
opening_obj = tool.Ifc.get_object(opening)
|
opening_obj = tool.Ifc.get_object(opening)
|
||||||
if opening_obj:
|
if opening_obj:
|
||||||
tool.Ifc.unlink(element=opening)
|
tool.Ifc.unlink(element=opening)
|
||||||
tool.Blender.remove_data_blocks([opening_obj], remove_unused_data=True)
|
tool.Blender.remove_data_blocks([opening_obj], remove_unused_data=True)
|
||||||
|
|
||||||
filling_obj = tool.Ifc.get_object(filling)
|
filling_obj = tool.Ifc.get_object(filling)
|
||||||
representation = self.generate_opening_from_filling(filling, filling_obj)
|
representation_to_use = self.generate_opening_from_filling(filling, filling_obj)
|
||||||
mapped_representation = ifcopenshell.api.geometry.map_representation(
|
|
||||||
tool.Ifc.get(), representation=representation
|
|
||||||
)
|
|
||||||
ifcopenshell.api.geometry.assign_representation(
|
|
||||||
tool.Ifc.get(), product=opening, representation=mapped_representation
|
|
||||||
)
|
|
||||||
|
|
||||||
# update voided object representation or all it's parts if it's an aggregate
|
mapped_representation = ifcopenshell.api.geometry.map_representation(
|
||||||
|
tool.Ifc.get(), representation=representation_to_use
|
||||||
|
)
|
||||||
|
ifcopenshell.api.geometry.assign_representation(
|
||||||
|
tool.Ifc.get(), product=opening, representation=mapped_representation
|
||||||
|
)
|
||||||
|
|
||||||
|
# update voided object representation...
|
||||||
voided_elements = ifcopenshell.util.element.get_parts(voided_element) or [voided_element]
|
voided_elements = ifcopenshell.util.element.get_parts(voided_element) or [voided_element]
|
||||||
for voided_element in voided_elements:
|
for voided_element in voided_elements:
|
||||||
voided_obj = tool.Ifc.get_object(voided_element)
|
voided_obj = tool.Ifc.get_object(voided_element)
|
||||||
@@ -249,6 +314,36 @@ class FilledOpeningGenerator:
|
|||||||
representation=representation,
|
representation=representation,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
def get_opening_template_from_type(self, filling: ifcopenshell.entity_instance) -> Union[ifcopenshell.entity_instance, None]:
|
||||||
|
"""
|
||||||
|
Check if the filling's type has a stored opening template from library import.
|
||||||
|
"""
|
||||||
|
element_type = ifcopenshell.util.element.get_type(filling)
|
||||||
|
|
||||||
|
if not element_type:
|
||||||
|
return None
|
||||||
|
|
||||||
|
desc = element_type.Description
|
||||||
|
|
||||||
|
if not desc or "||BonsaiOpeningTemplate:" not in desc:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Extract template ID
|
||||||
|
marker = desc.split("||BonsaiOpeningTemplate:")[-1]
|
||||||
|
template_id = int(marker.split("||")[0])
|
||||||
|
|
||||||
|
try:
|
||||||
|
template_rep = tool.Ifc.get().by_id(template_id)
|
||||||
|
# Make a copy so we don't reuse the same representation instance
|
||||||
|
copied = ifcopenshell.util.element.copy_deep(
|
||||||
|
tool.Ifc.get(),
|
||||||
|
template_rep,
|
||||||
|
exclude=["IfcGeometricRepresentationContext"]
|
||||||
|
)
|
||||||
|
return copied
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
def generate_opening_from_filling(
|
def generate_opening_from_filling(
|
||||||
self,
|
self,
|
||||||
filling: ifcopenshell.entity_instance,
|
filling: ifcopenshell.entity_instance,
|
||||||
|
|||||||
@@ -611,6 +611,8 @@ class AppendLibraryElement(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
if not element:
|
if not element:
|
||||||
return {"FINISHED"}
|
return {"FINISHED"}
|
||||||
if element.is_a("IfcTypeProduct"):
|
if element.is_a("IfcTypeProduct"):
|
||||||
|
# Store opening template from library if it exists
|
||||||
|
self.store_opening_template_from_library(element, library_file)
|
||||||
self.import_type_from_ifc(element, context)
|
self.import_type_from_ifc(element, context)
|
||||||
elif element.is_a("IfcProduct"):
|
elif element.is_a("IfcProduct"):
|
||||||
# NOTE: Non-types are not exposed in UI directly
|
# NOTE: Non-types are not exposed in UI directly
|
||||||
@@ -712,6 +714,56 @@ class AppendLibraryElement(bpy.types.Operator, tool.Ifc.Operator):
|
|||||||
ifc_importer.create_style(element)
|
ifc_importer.create_style(element)
|
||||||
|
|
||||||
|
|
||||||
|
def store_opening_template_from_library(
|
||||||
|
self,
|
||||||
|
element: ifcopenshell.entity_instance,
|
||||||
|
library_file: ifcopenshell.file
|
||||||
|
) -> None:
|
||||||
|
"""
|
||||||
|
Find an opening representation in the library and copy it to the current file
|
||||||
|
as a template. Store the template ID on the type for later retrieval.
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
library_element = library_file.by_guid(element.GlobalId)
|
||||||
|
except:
|
||||||
|
return
|
||||||
|
|
||||||
|
# Find occurrences with openings in the library
|
||||||
|
library_occurrences = ifcopenshell.util.element.get_types(library_element)
|
||||||
|
|
||||||
|
for occurrence in library_occurrences:
|
||||||
|
if not getattr(occurrence, "FillsVoids", None):
|
||||||
|
continue
|
||||||
|
|
||||||
|
library_opening = occurrence.FillsVoids[0].RelatingOpeningElement
|
||||||
|
library_opening_rep = ifcopenshell.util.representation.get_representation(
|
||||||
|
library_opening, "Model", "Body", "MODEL_VIEW"
|
||||||
|
)
|
||||||
|
|
||||||
|
if not library_opening_rep:
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Check if mapped representation
|
||||||
|
if (library_opening_rep.RepresentationType == 'MappedRepresentation' and
|
||||||
|
len(library_opening_rep.Items) == 1 and
|
||||||
|
library_opening_rep.Items[0].is_a("IfcMappedItem")):
|
||||||
|
|
||||||
|
mapped_rep = library_opening_rep.Items[0].MappingSource.MappedRepresentation
|
||||||
|
|
||||||
|
# Store ALL representation types (Tessellation, SweptSolid, etc.)
|
||||||
|
template_rep = ifcopenshell.util.element.copy_deep(
|
||||||
|
self.file,
|
||||||
|
mapped_rep,
|
||||||
|
exclude=["IfcGeometricRepresentationContext"]
|
||||||
|
)
|
||||||
|
|
||||||
|
# Store reference in type's Description
|
||||||
|
current_desc = element.Description or ""
|
||||||
|
element.Description = f"{current_desc}||BonsaiOpeningTemplate:{template_rep.id()}"
|
||||||
|
return
|
||||||
|
break
|
||||||
|
|
||||||
|
|
||||||
class EditProjectLibrary(bpy.types.Operator):
|
class EditProjectLibrary(bpy.types.Operator):
|
||||||
bl_idname = "bim.edit_project_library"
|
bl_idname = "bim.edit_project_library"
|
||||||
bl_label = "Edit Project Library"
|
bl_label = "Edit Project Library"
|
||||||
|
|||||||
@@ -91,16 +91,37 @@ class Root(bonsai.core.tool.Root):
|
|||||||
elif dest.is_a("IfcTypeProduct"):
|
elif dest.is_a("IfcTypeProduct"):
|
||||||
if not source.RepresentationMaps:
|
if not source.RepresentationMaps:
|
||||||
return copied_entities
|
return copied_entities
|
||||||
dest.RepresentationMaps = [
|
|
||||||
ifcopenshell.util.element.copy_deep(
|
# Copy representation maps while preserving mapped representation structures
|
||||||
tool.Ifc.get(),
|
new_maps = []
|
||||||
m,
|
for i, rep_map in enumerate(source.RepresentationMaps):
|
||||||
exclude=["IfcGeometricRepresentationContext"],
|
source_rep = rep_map.MappedRepresentation
|
||||||
exclude_callback=exclude_callback,
|
|
||||||
copied_entities=copied_entities,
|
|
||||||
)
|
# Copy the map itself
|
||||||
for m in source.RepresentationMaps
|
new_map = ifcopenshell.util.element.copy(tool.Ifc.get(), rep_map)
|
||||||
]
|
|
||||||
|
# Handle the mapped representation - preserve mapping structure if present
|
||||||
|
if (source_rep.RepresentationType == 'MappedRepresentation' and
|
||||||
|
len(source_rep.Items) == 1 and
|
||||||
|
source_rep.Items[0].is_a("IfcMappedItem")):
|
||||||
|
# This is a mapped representation - preserve the structure
|
||||||
|
new_rep = ifcopenshell.util.element.copy(tool.Ifc.get(), source_rep)
|
||||||
|
new_rep.Items = [ifcopenshell.util.element.copy(tool.Ifc.get(), item) for item in source_rep.Items]
|
||||||
|
new_map.MappedRepresentation = new_rep
|
||||||
|
else:
|
||||||
|
# Not a mapped representation - use copy_deep as before
|
||||||
|
new_map.MappedRepresentation = ifcopenshell.util.element.copy_deep(
|
||||||
|
tool.Ifc.get(),
|
||||||
|
source_rep,
|
||||||
|
exclude=["IfcGeometricRepresentationContext"],
|
||||||
|
exclude_callback=exclude_callback,
|
||||||
|
copied_entities=copied_entities,
|
||||||
|
)
|
||||||
|
|
||||||
|
new_maps.append(new_map)
|
||||||
|
|
||||||
|
dest.RepresentationMaps = new_maps
|
||||||
return copied_entities
|
return copied_entities
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
|
|||||||
@@ -927,3 +927,69 @@ class TestAddReferenceImage(NewFile):
|
|||||||
|
|
||||||
uv_node = material_nodes["Texture Coordinate"]
|
uv_node = material_nodes["Texture Coordinate"]
|
||||||
assert len(uv_node.outputs["Generated"].links[:]) == 1
|
assert len(uv_node.outputs["Generated"].links[:]) == 1
|
||||||
|
|
||||||
|
class TestAddReference(NewFile):
|
||||||
|
def test_add_single_reference(self):
|
||||||
|
"""Test adding a single reference file (backward compatibility)"""
|
||||||
|
bpy.ops.bim.create_project()
|
||||||
|
ifc_path = Path("test/files/temp/test.ifc").absolute()
|
||||||
|
bpy.ops.bim.save_project(filepath=str(ifc_path), should_save_as=True)
|
||||||
|
|
||||||
|
# Create a temporary SVG file
|
||||||
|
svg_path = Path("test/files/temp/reference.svg").absolute()
|
||||||
|
svg_path.parent.mkdir(parents=True, exist_ok=True)
|
||||||
|
with open(svg_path, "w") as f:
|
||||||
|
f.write('<svg xmlns="http://www.w3.org/2000/svg"></svg>')
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Add single reference
|
||||||
|
bpy.ops.bim.add_reference(filepath=str(svg_path))
|
||||||
|
|
||||||
|
# Verify reference was added
|
||||||
|
ifc = tool.Ifc.get()
|
||||||
|
references = [doc for doc in ifc.by_type("IfcDocumentInformation") if doc.Scope == "REFERENCE"]
|
||||||
|
assert len(references) == 1
|
||||||
|
assert references[0].Name == "reference"
|
||||||
|
finally:
|
||||||
|
# Cleanup
|
||||||
|
if svg_path.exists():
|
||||||
|
svg_path.unlink()
|
||||||
|
|
||||||
|
def test_add_multiple_references(self):
|
||||||
|
"""Test adding multiple reference files at once"""
|
||||||
|
bpy.ops.bim.create_project()
|
||||||
|
ifc_path = Path("test/files/temp/test.ifc").absolute()
|
||||||
|
bpy.ops.bim.save_project(filepath=str(ifc_path), should_save_as=True)
|
||||||
|
|
||||||
|
# Create temporary SVG files
|
||||||
|
temp_dir = Path("test/files/temp").absolute()
|
||||||
|
temp_dir.mkdir(parents=True, exist_ok=True)
|
||||||
|
|
||||||
|
svg_files = []
|
||||||
|
for i in range(3):
|
||||||
|
svg_path = temp_dir / f"reference_{i}.svg"
|
||||||
|
with open(svg_path, "w") as f:
|
||||||
|
f.write('<svg xmlns="http://www.w3.org/2000/svg"></svg>')
|
||||||
|
svg_files.append(svg_path)
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Test by directly calling core.add_document multiple times
|
||||||
|
# (simulating what the operator does with multiple files)
|
||||||
|
ifc = tool.Ifc.get()
|
||||||
|
for svg_file in svg_files:
|
||||||
|
uri = tool.Ifc.get_uri(str(svg_file), use_relative_path=True)
|
||||||
|
from bonsai.bim import core
|
||||||
|
core.drawing.add_document(tool.Ifc, tool.Drawing, "REFERENCE", uri=uri)
|
||||||
|
|
||||||
|
# Verify all references were added
|
||||||
|
references = [doc for doc in ifc.by_type("IfcDocumentInformation") if doc.Scope == "REFERENCE"]
|
||||||
|
assert len(references) == 3
|
||||||
|
|
||||||
|
reference_names = {ref.Name for ref in references}
|
||||||
|
expected_names = {f"reference_{i}" for i in range(3)}
|
||||||
|
assert reference_names == expected_names
|
||||||
|
finally:
|
||||||
|
# Cleanup
|
||||||
|
for svg_file in svg_files:
|
||||||
|
if svg_file.exists():
|
||||||
|
svg_file.unlink()
|
||||||
|
|||||||
@@ -55,8 +55,7 @@ if(SCHEMA_VERSIONS MATCHES "2x3")
|
|||||||
endif()
|
endif()
|
||||||
install(TARGETS IfcParseExamples)
|
install(TARGETS IfcParseExamples)
|
||||||
|
|
||||||
# TODO: enable after figuring out where to get get OCCT config for CI.
|
if(WITH_OPENCASCADE)
|
||||||
if(WITH_OPENCASCADE AND NOT STANDALONE_PROJECT)
|
|
||||||
add_executable(IfcOpenHouse IfcOpenHouse.cpp)
|
add_executable(IfcOpenHouse IfcOpenHouse.cpp)
|
||||||
add_executable(IfcAdvancedHouse IfcAdvancedHouse.cpp)
|
add_executable(IfcAdvancedHouse IfcAdvancedHouse.cpp)
|
||||||
add_library(IfcHouseInterface INTERFACE)
|
add_library(IfcHouseInterface INTERFACE)
|
||||||
@@ -66,6 +65,13 @@ if(SCHEMA_VERSIONS MATCHES "2x3")
|
|||||||
find_package(CGAL CONFIG REQUIRED)
|
find_package(CGAL CONFIG REQUIRED)
|
||||||
find_package(OpenCASCADE CONFIG REQUIRED)
|
find_package(OpenCASCADE CONFIG REQUIRED)
|
||||||
|
|
||||||
|
if(OpenCASCADE_VERSION VERSION_LESS "7.7.0")
|
||||||
|
# cmake configs < 7.7.0 were not adding include directories to targets automatically.
|
||||||
|
set_target_properties(TKernel PROPERTIES
|
||||||
|
INTERFACE_INCLUDE_DIRECTORIES "${OpenCASCADE_INCLUDE_DIR}"
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
target_link_libraries(IfcHouseInterface INTERFACE IfcOpenShell::IfcParse IfcOpenShell::geometry_serializer)
|
target_link_libraries(IfcHouseInterface INTERFACE IfcOpenShell::IfcParse IfcOpenShell::geometry_serializer)
|
||||||
else()
|
else()
|
||||||
target_link_libraries(IfcHouseInterface INTERFACE IfcParse geometry_serializer)
|
target_link_libraries(IfcHouseInterface INTERFACE IfcParse geometry_serializer)
|
||||||
|
|||||||
@@ -32,7 +32,6 @@ set(IFCPARSE_FILES ${IFCPARSE_CPP_FILES} ${IFCPARSE_H_FILES})
|
|||||||
|
|
||||||
add_library(IfcParse ${IFCPARSE_FILES})
|
add_library(IfcParse ${IFCPARSE_FILES})
|
||||||
target_compile_definitions(IfcParse PUBLIC ${SCHEMA_DEFINITIONS})
|
target_compile_definitions(IfcParse PUBLIC ${SCHEMA_DEFINITIONS})
|
||||||
target_include_directories(IfcParse PUBLIC $<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>)
|
|
||||||
set_target_properties(IfcParse
|
set_target_properties(IfcParse
|
||||||
PROPERTIES
|
PROPERTIES
|
||||||
COMPILE_FLAGS -DIFC_PARSE_EXPORTS
|
COMPILE_FLAGS -DIFC_PARSE_EXPORTS
|
||||||
@@ -60,4 +59,5 @@ target_link_libraries(IfcParse ${ROCKSDB_LIBRARIES})
|
|||||||
install(TARGETS IfcParse
|
install(TARGETS IfcParse
|
||||||
EXPORT ${IFCOPENSHELL_EXPORT_TARGETS}
|
EXPORT ${IFCOPENSHELL_EXPORT_TARGETS}
|
||||||
PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/ifcparse"
|
PUBLIC_HEADER DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/ifcparse"
|
||||||
|
INCLUDES DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}"
|
||||||
)
|
)
|
||||||
|
|||||||
Reference in New Issue
Block a user