Fix #2472. BREAKING CHANGE. Annotations are now drawn in addition to body views, not in lieu of.

This commit is contained in:
Dion Moult
2023-02-03 21:31:15 +11:00
parent b4d633a34d
commit 6adbcdd8e1
@@ -116,11 +116,7 @@ class CreateDrawing(bpy.types.Operator):
@classmethod @classmethod
def poll(cls, context): def poll(cls, context):
return bool( return bool(tool.Ifc.get() and tool.Drawing.is_camera_orthographic() and tool.Drawing.is_drawing_active())
tool.Ifc.get()
and tool.Drawing.is_camera_orthographic()
and tool.Drawing.is_drawing_active()
)
def execute(self, context): def execute(self, context):
self.camera = context.scene.camera self.camera = context.scene.camera
@@ -300,54 +296,120 @@ class CreateDrawing(bpy.types.Operator):
ifc_hash = hashlib.md5(ifc_path.encode("utf-8")).hexdigest() 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") ifc_cache_path = os.path.join(context.scene.BIMProperties.data_dir, "cache", f"{ifc_hash}.h5")
# Get all representation contexts to see what we're dealing with # Get all representation contexts to see what we're dealing with.
# A drawing prioritises a target view context first, followed by a body context as a fallback # Drawings only draw bodies and annotations (and facetation, due to a Revit bug).
body_contexts = [] # A drawing prioritises a target view context first, followed by a model view context as a fallback.
target_view_contexts = [] # Specifically for PLAN_VIEW and REFLECTED_PLAN_VIEW, any Plan context is also prioritised.
plan_body_target_contexts = []
plan_body_model_contexts = []
model_body_target_contexts = []
model_body_model_contexts = []
plan_annotation_target_contexts = []
plan_annotation_model_contexts = []
model_annotation_target_contexts = []
model_annotation_model_contexts = []
target_view = ifcopenshell.util.element.get_psets(self.camera_element)["EPset_Drawing"]["TargetView"] target_view = ifcopenshell.util.element.get_psets(self.camera_element)["EPset_Drawing"]["TargetView"]
for rep_context in ifc.by_type("IfcGeometricRepresentationContext"): for rep_context in ifc.by_type("IfcGeometricRepresentationContext"):
if rep_context.is_a("IfcGeometricRepresentationSubContext"): if rep_context.is_a("IfcGeometricRepresentationSubContext"):
if rep_context.TargetView == target_view: if rep_context.ContextType == "Plan":
target_view_contexts.append(rep_context.id()) if rep_context.ContextIdentifier in ["Body", "Facetation"]:
continue if rep_context.TargetView == target_view:
if rep_context.ContextIdentifier in ["Body", "Facetation"]: plan_body_target_contexts.append(rep_context.id())
body_contexts.append(rep_context.id()) elif rep_context.TargetView == "MODEL_VIEW":
continue plan_body_model_contexts.append(rep_context.id())
if rep_context.is_a() == "IfcGeometricRepresentationContext" and rep_context.ContextType == "Model": elif rep_context.ContextIdentifier == "Annotation":
body_contexts.append(rep_context.id()) if rep_context.TargetView == target_view:
plan_annotation_target_contexts.append(rep_context.id())
elif rep_context.TargetView == "MODEL_VIEW":
plan_annotation_model_contexts.append(rep_context.id())
elif rep_context.ContextType == "Model":
if rep_context.ContextIdentifier in ["Body", "Facetation"]:
if rep_context.TargetView == target_view:
model_body_target_contexts.append(rep_context.id())
elif rep_context.TargetView == "MODEL_VIEW":
model_body_model_contexts.append(rep_context.id())
elif rep_context.ContextIdentifier == "Annotation":
if rep_context.TargetView == target_view:
model_annotation_target_contexts.append(rep_context.id())
elif rep_context.TargetView == "MODEL_VIEW":
model_annotation_model_contexts.append(rep_context.id())
elif rep_context.ContextType == "Model":
# You should never purely assign to a "Model" context, but
# if you do, this is what we assume your intention is.
model_body_model_contexts.append(rep_context.id())
continue continue
elements = tool.Drawing.get_drawing_elements(self.camera_element) body_contexts = (
[
plan_body_target_contexts,
plan_body_model_contexts,
model_body_target_contexts,
model_body_model_contexts,
]
if target_view in ["PLAN_VIEW", "REFLECTED_PLAN_VIEW"]
else [
model_body_target_contexts,
model_body_model_contexts,
]
)
annotation_contexts = (
[
plan_annotation_target_contexts,
plan_annotation_model_contexts,
model_annotation_target_contexts,
model_annotation_model_contexts,
]
if target_view in ["PLAN_VIEW", "REFLECTED_PLAN_VIEW"]
else [
model_annotation_target_contexts,
model_annotation_model_contexts,
]
)
drawing_elements = tool.Drawing.get_drawing_elements(self.camera_element)
self.setup_serialiser(ifc) self.setup_serialiser(ifc)
cache = IfcStore.get_cache() cache = IfcStore.get_cache()
[cache.remove(guid) for guid in invalidated_guids] [cache.remove(guid) for guid in invalidated_guids]
with profile("Processing target view context"): elements = drawing_elements.copy()
if target_view_contexts and elements: for body_context in body_contexts:
geom_settings = ifcopenshell.geom.settings( with profile("Processing body context"):
DISABLE_TRIANGULATION=True, STRICT_TOLERANCE=True, INCLUDE_CURVES=True if body_context and elements:
) geom_settings = ifcopenshell.geom.settings(DISABLE_TRIANGULATION=True, STRICT_TOLERANCE=True)
geom_settings.set_context_ids(target_view_contexts) geom_settings.set_context_ids(body_context)
it = ifcopenshell.geom.iterator(geom_settings, ifc, multiprocessing.cpu_count(), include=elements) it = ifcopenshell.geom.iterator(geom_settings, ifc, multiprocessing.cpu_count(), include=elements)
it.set_cache(cache) it.set_cache(cache)
processed = set() processed = set()
for elem in self.yield_from_iterator(it): for elem in self.yield_from_iterator(it):
processed.add(ifc.by_id(elem.id)) processed.add(ifc.by_id(elem.id))
self.serialiser.write(elem) self.serialiser.write(elem)
elements -= processed elements -= processed
with profile("Processing body context"): elements = drawing_elements.copy()
if body_contexts and elements: for annotation_context in annotation_contexts:
geom_settings = ifcopenshell.geom.settings(DISABLE_TRIANGULATION=True, STRICT_TOLERANCE=True) with profile("Processing annotation context"):
geom_settings.set_context_ids(body_contexts) if annotation_context and elements:
it = ifcopenshell.geom.iterator(geom_settings, ifc, multiprocessing.cpu_count(), include=elements) geom_settings = ifcopenshell.geom.settings(
it.set_cache(cache) DISABLE_TRIANGULATION=True, STRICT_TOLERANCE=True, INCLUDE_CURVES=True
for elem in self.yield_from_iterator(it): )
self.serialiser.write(elem) geom_settings.set_context_ids(annotation_context)
it = ifcopenshell.geom.iterator(geom_settings, ifc, multiprocessing.cpu_count(), include=elements)
it.set_cache(cache)
processed = set()
for elem in self.yield_from_iterator(it):
processed.add(ifc.by_id(elem.id))
self.serialiser.write(elem)
elements -= processed
with profile("Camera element"): with profile("Camera element"):
# @todo tfk: is this needed? # @todo tfk: is this needed?
# If the camera isn't serialised, then nothing gets serialised. Odd behaviour.
geom_settings = ifcopenshell.geom.settings(DISABLE_TRIANGULATION=True, STRICT_TOLERANCE=True) geom_settings = ifcopenshell.geom.settings(DISABLE_TRIANGULATION=True, STRICT_TOLERANCE=True)
it = ifcopenshell.geom.iterator(geom_settings, ifc, include=[self.camera_element]) it = ifcopenshell.geom.iterator(geom_settings, ifc, include=[self.camera_element])
for elem in self.yield_from_iterator(it): for elem in self.yield_from_iterator(it):
@@ -423,7 +485,7 @@ class CreateDrawing(bpy.types.Operator):
# https://stackoverflow.com/questions/36018627/sorting-child-elements-with-lxml-based-on-attribute-value # https://stackoverflow.com/questions/36018627/sorting-child-elements-with-lxml-based-on-attribute-value
group = root.find("{http://www.w3.org/2000/svg}g") group = root.find("{http://www.w3.org/2000/svg}g")
# group[:] = sorted(group, key=lambda e : "projection" in e.get("class")) # group[:] = sorted(group, key=lambda e : "projection" in e.get("class"))
if group: if len(group):
group[:] = reversed(group) group[:] = reversed(group)
def canonicalise_class_name(self, name): def canonicalise_class_name(self, name):
@@ -1338,6 +1400,7 @@ class ContractSheet(bpy.types.Operator):
core.load_sheets(tool.Drawing) core.load_sheets(tool.Drawing)
return {"FINISHED"} return {"FINISHED"}
class SelectAssignedProduct(bpy.types.Operator, Operator): class SelectAssignedProduct(bpy.types.Operator, Operator):
bl_idname = "bim.select_assigned_product" bl_idname = "bim.select_assigned_product"
bl_label = "Select Assigned Product" bl_label = "Select Assigned Product"