Skip to content

Commit

Permalink
Merge branch 'IfcOpenShell:v0.7.0' into v0.7.0
Browse files Browse the repository at this point in the history
  • Loading branch information
ppaawweeuu authored May 26, 2024
2 parents 3660dfc + 37cacfc commit 541bec8
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 15 deletions.
44 changes: 33 additions & 11 deletions src/blenderbim/blenderbim/bim/module/drawing/operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -529,28 +529,35 @@ def generate_linework(self, context: bpy.types.Context) -> Union[str, None]:

files = {context.scene.BIMProperties.ifc_file: tool.Ifc.get()}

for link in context.scene.BIMProjectProperties.links:
if link.name not in IfcStore.session_files:
IfcStore.session_files[link.name] = ifcopenshell.open(link.name)
files[link.name] = IfcStore.session_files[link.name]

target_view = ifcopenshell.util.element.get_psets(self.camera_element)["EPset_Drawing"]["TargetView"]
self.setup_serialiser(target_view)

tree = ifcopenshell.geom.tree()
tree.enable_face_styles(True)

for ifc_path, ifc in files.items():
# Don't use draw.main() just whilst we're prototyping and experimenting
# TODO: hash paths are never used
ifc_hash = hashlib.md5(ifc_path.encode("utf-8")).hexdigest()
ifc_cache_path = os.path.join(context.scene.BIMProperties.data_dir, "cache", f"{ifc_hash}.h5")

self.serialiser.setFile(ifc)
drawing_elements = tool.Drawing.get_drawing_elements(self.camera_element, ifc_file=ifc)

# Get all representation contexts to see what we're dealing with.
# Drawings only draw bodies and annotations (and facetation, due to a Revit bug).
# A drawing prioritises a target view context first, followed by a model view context as a fallback.
# Specifically for PLAN_VIEW and REFLECTED_PLAN_VIEW, any Plan context is also prioritised.
target_view = ifcopenshell.util.element.get_psets(self.camera_element)["EPset_Drawing"]["TargetView"]
contexts = self.get_linework_contexts(ifc, target_view)
drawing_elements = tool.Drawing.get_drawing_elements(self.camera_element)

self.setup_serialiser(ifc, target_view)
tree = ifcopenshell.geom.tree()
tree.enable_face_styles(True)

self.serialize_contexts_elements(ifc, tree, contexts, "body", drawing_elements, target_view)
self.serialize_contexts_elements(ifc, tree, contexts, "annotation", drawing_elements, target_view)

if self.camera_element not in drawing_elements:
if tool.Ifc.get() == ifc and self.camera_element not in drawing_elements:
with profile("Camera element"):
# The camera must always be included, regardless of any include/exclude filters.
geom_settings = ifcopenshell.geom.settings(DISABLE_TRIANGULATION=True, STRICT_TOLERANCE=True)
Expand Down Expand Up @@ -865,13 +872,12 @@ def format(x):

return svg_path

def setup_serialiser(self, ifc, target_view):
def setup_serialiser(self, target_view):
self.svg_settings = ifcopenshell.geom.settings(
DISABLE_TRIANGULATION=True, STRICT_TOLERANCE=True, INCLUDE_CURVES=True
)
self.svg_buffer = ifcopenshell.geom.serializers.buffer()
self.serialiser = ifcopenshell.geom.serializers.svg(self.svg_buffer, self.svg_settings)
self.serialiser.setFile(ifc)
self.serialiser.setWithoutStoreys(True)
self.serialiser.setPolygonal(True)
self.serialiser.setUseHlrPoly(True)
Expand Down Expand Up @@ -935,6 +941,18 @@ def is_manifold(self, obj):
self.is_manifold_cache[obj.data.name] = True
return True

def get_element_by_guid(self, guid):
try:
return tool.Ifc.get().by_guid(guid)
except:
for link in bpy.context.scene.BIMProjectProperties.links:
if link.name not in IfcStore.session_files:
IfcStore.session_files[link.name] = ifcopenshell.open(link.name)
try:
return IfcStore.session_files[link.name].by_guid(guid)
except:
continue

def merge_linework_and_add_metadata(self, root):
join_criteria = ifcopenshell.util.element.get_pset(self.camera_element, "EPset_Drawing", "JoinCriteria")
if join_criteria:
Expand All @@ -949,7 +967,7 @@ def merge_linework_and_add_metadata(self, root):

ifc = tool.Ifc.get()
for el in root.findall(".//{http://www.w3.org/2000/svg}g[@{http://www.ifcopenshell.org/ns}guid]"):
element = ifc.by_guid(el.get("{http://www.ifcopenshell.org/ns}guid"))
element = self.get_element_by_guid(el.get("{http://www.ifcopenshell.org/ns}guid"))

if "projection" in el.get("class", "").split():
classes = self.get_svg_classes(element)
Expand All @@ -962,6 +980,10 @@ def merge_linework_and_add_metadata(self, root):
el.set("class", " ".join(classes))

obj = tool.Ifc.get_object(element)

if not obj: # This is a linked model object. For now, do nothing.
continue

if not self.is_manifold(obj):
continue

Expand Down
2 changes: 1 addition & 1 deletion src/blenderbim/blenderbim/bim/module/profile/operator.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ def _execute(self, context):

def disable_editing_arbitrary_profile(context):
obj = context.active_object
if obj and obj.data and obj.data.BIMMeshProperties.subshape_type == "PROFILE":
if obj and obj.type == "MESH" and obj.data and obj.data.BIMMeshProperties.subshape_type == "PROFILE":
ProfileDecorator.uninstall()
bpy.ops.object.mode_set(mode="OBJECT")
profile_mesh = obj.data
Expand Down
12 changes: 9 additions & 3 deletions src/blenderbim/blenderbim/tool/drawing.py
Original file line number Diff line number Diff line change
Expand Up @@ -1625,11 +1625,17 @@ def has_annotation(cls, drawing):
return ifcopenshell.util.element.get_psets(drawing).get("EPset_Drawing", {}).get("HasAnnotation", False)

@classmethod
def get_drawing_elements(cls, drawing: ifcopenshell.entity_instance) -> set[ifcopenshell.entity_instance]:
def get_drawing_elements(
cls, drawing: ifcopenshell.entity_instance, ifc_file: Optional[ifcopenshell.file] = None
) -> set[ifcopenshell.entity_instance]:
"""returns a set of elements that are included in the drawing"""
ifc_file = tool.Ifc.get()
if ifc_file is None:
ifc_file = tool.Ifc.get()
elements = cls.get_elements_in_camera_view(tool.Ifc.get_object(drawing), bpy.data.objects)
else:
# This can probably be smarter
elements = set(ifc_file.by_type("IfcElement"))
pset = ifcopenshell.util.element.get_psets(drawing).get("EPset_Drawing", {})
elements = cls.get_elements_in_camera_view(tool.Ifc.get_object(drawing), bpy.data.objects)
include = pset.get("Include", None)
if include:
elements = ifcopenshell.util.selector.filter_elements(ifc_file, include)
Expand Down
1 change: 1 addition & 0 deletions src/ifcopenshell-python/ifcopenshell/util/selector.py
Original file line number Diff line number Diff line change
Expand Up @@ -371,6 +371,7 @@ def set_element_value(
elif key == "class":
if element.is_a().lower() != value.lower():
return ifcopenshell.util.schema.reassign_class(ifc_file, element, value)
return
elif key == "id":
return
elif key == "classification":
Expand Down

0 comments on commit 541bec8

Please sign in to comment.