Minor things for drawing profiling and a warning

This commit is contained in:
Thomas Krijnen
2022-06-21 12:14:15 +02:00
committed by Dion Moult
parent 4978a67e19
commit 104cabfb67
2 changed files with 92 additions and 67 deletions
@@ -41,6 +41,7 @@ import blenderbim.bim.module.drawing.helper as helper
import blenderbim.bim.export_ifc import blenderbim.bim.export_ifc
from lxml import etree from lxml import etree
from mathutils import Vector from mathutils import Vector
from timeit import default_timer as timer
from blenderbim.bim.module.drawing.prop import RasterStyleProperty from blenderbim.bim.module.drawing.prop import RasterStyleProperty
from blenderbim.bim.ifc import IfcStore from blenderbim.bim.ifc import IfcStore
from ifcopenshell.api.group.data import Data as GroupData from ifcopenshell.api.group.data import Data as GroupData
@@ -49,6 +50,21 @@ from ifcopenshell.api.pset.data import Data as PsetData
cwd = os.path.dirname(os.path.realpath(__file__)) cwd = os.path.dirname(os.path.realpath(__file__))
class profile:
"""
A python context manager timing utility
"""
def __init__(self, task):
self.task = task
def __enter__(self):
self.start = timer()
def __exit__(self, *args):
print(self.task, timer() - self.start)
def open_with_user_command(user_command, path): def open_with_user_command(user_command, path):
if user_command: if user_command:
commands = eval(user_command) commands = eval(user_command)
@@ -115,34 +131,39 @@ class CreateDrawing(bpy.types.Operator):
self.camera = context.scene.camera self.camera = context.scene.camera
self.camera_element = tool.Ifc.get_entity(self.camera) self.camera_element = tool.Ifc.get_entity(self.camera)
self.file = IfcStore.get_file() self.file = IfcStore.get_file()
self.time = None
start = time.time()
self.profile_code("Start drawing generation process")
self.props = context.scene.DocProperties
self.cprops = self.camera.data.BIMCameraProperties
self.drawing_name = self.file.by_id(self.camera.BIMObjectProperties.ifc_definition_id).Name
self.get_scale()
if self.cprops.update_representation(self.camera):
bpy.ops.bim.update_representation(obj=self.camera.name, ifc_representation_class="")
self.svg_writer = svgwriter.SvgWriter() with profile("Drawing generation process"):
self.svg_writer.human_scale = self.human_scale
self.svg_writer.scale = self.scale with profile("Initialize drawing generation process"):
self.svg_writer.data_dir = context.scene.BIMProperties.data_dir self.props = context.scene.DocProperties
self.svg_writer.camera = self.camera self.cprops = self.camera.data.BIMCameraProperties
self.svg_writer.camera_width, self.svg_writer.camera_height = self.get_camera_dimensions() self.drawing_name = self.file.by_id(self.camera.BIMObjectProperties.ifc_definition_id).Name
self.svg_writer.camera_projection = tuple(self.camera.matrix_world.to_quaternion() @ Vector((0, 0, -1))) self.get_scale()
if self.cprops.update_representation(self.camera):
bpy.ops.bim.update_representation(obj=self.camera.name, ifc_representation_class="")
self.svg_writer = svgwriter.SvgWriter()
self.svg_writer.human_scale = self.human_scale
self.svg_writer.scale = self.scale
self.svg_writer.data_dir = context.scene.BIMProperties.data_dir
self.svg_writer.camera = self.camera
self.svg_writer.camera_width, self.svg_writer.camera_height = self.get_camera_dimensions()
self.svg_writer.camera_projection = tuple(self.camera.matrix_world.to_quaternion() @ Vector((0, 0, -1)))
with profile("Generate underlay"):
underlay_svg = self.generate_underlay(context)
with profile("Generate linework"):
linework_svg = self.generate_linework(context)
with profile("Generate annotation"):
annotation_svg = self.generate_annotation(context)
with profile("Combine SVG layers"):
svg_path = self.combine_svgs(context, underlay_svg, linework_svg, annotation_svg)
underlay_svg = self.generate_underlay(context)
self.profile_code("Generate underlay")
linework_svg = self.generate_linework(context)
self.profile_code("Generate linework")
annotation_svg = self.generate_annotation(context)
self.profile_code("Generate annotation")
svg_path = self.combine_svgs(context, underlay_svg, linework_svg, annotation_svg)
self.profile_code("Combine SVG layers")
open_with_user_command(context.preferences.addons["blenderbim"].preferences.svg_command, svg_path) open_with_user_command(context.preferences.addons["blenderbim"].preferences.svg_command, svg_path)
print("Total Time: {:.2f}".format(time.time() - start))
return {"FINISHED"} return {"FINISHED"}
def get_camera_dimensions(self): def get_camera_dimensions(self):
@@ -155,12 +176,6 @@ class CreateDrawing(bpy.types.Operator):
width = height / render.resolution_y * render.resolution_x width = height / render.resolution_y * render.resolution_x
return width, height return width, height
def profile_code(self, message):
if not self.time:
self.time = time.time()
print("{} :: {:.2f}".format(message, time.time() - self.time))
self.time = time.time()
def combine_svgs(self, context, underlay, linework, annotation): def combine_svgs(self, context, underlay, linework, annotation):
# Hacky :) # Hacky :)
svg_path = os.path.join(context.scene.BIMProperties.data_dir, "diagrams", self.drawing_name + ".svg") svg_path = os.path.join(context.scene.BIMProperties.data_dir, "diagrams", self.drawing_name + ".svg")
@@ -255,13 +270,14 @@ class CreateDrawing(bpy.types.Operator):
if os.path.isfile(svg_path) and self.props.should_use_linework_cache: if os.path.isfile(svg_path) and self.props.should_use_linework_cache:
return svg_path return svg_path
# All very hackish whilst prototyping with profile("sync"):
exporter = blenderbim.bim.export_ifc.IfcExporter(None) # All very hackish whilst prototyping
exporter.file = tool.Ifc.get() exporter = blenderbim.bim.export_ifc.IfcExporter(None)
invalidated_guids = exporter.sync_deletions() exporter.file = tool.Ifc.get()
invalidated_elements = exporter.sync_all_objects() invalidated_guids = exporter.sync_deletions()
invalidated_elements += exporter.sync_edited_objects() invalidated_elements = exporter.sync_all_objects()
[invalidated_guids.append(e.GlobalId) for e in invalidated_elements if hasattr(e, "GlobalId")] invalidated_elements += exporter.sync_edited_objects()
[invalidated_guids.append(e.GlobalId) for e in invalidated_elements if hasattr(e, "GlobalId")]
# If we have already calculated it in the SVG in the past, don't recalculate # If we have already calculated it in the SVG in the past, don't recalculate
edited_guids = set() edited_guids = set()
@@ -312,40 +328,46 @@ class CreateDrawing(bpy.types.Operator):
cache = IfcStore.get_cache() cache = IfcStore.get_cache()
[cache.remove(guid) for guid in invalidated_guids] [cache.remove(guid) for guid in invalidated_guids]
if target_view_contexts and elements: with profile("Processing target view context"):
geom_settings = ifcopenshell.geom.settings( if target_view_contexts and elements:
DISABLE_TRIANGULATION=True, STRICT_TOLERANCE=True, INCLUDE_CURVES=True geom_settings = ifcopenshell.geom.settings(
) DISABLE_TRIANGULATION=True, STRICT_TOLERANCE=True, INCLUDE_CURVES=True
geom_settings.set_context_ids(target_view_contexts) )
it = ifcopenshell.geom.iterator(geom_settings, ifc, multiprocessing.cpu_count(), include=elements) geom_settings.set_context_ids(target_view_contexts)
it.set_cache(cache) it = ifcopenshell.geom.iterator(geom_settings, ifc, multiprocessing.cpu_count(), include=elements)
processed = set() it.set_cache(cache)
for elem in self.yield_from_iterator(it): processed = set()
processed.add(ifc.by_id(elem.id)) for elem in self.yield_from_iterator(it):
self.serialiser.write(elem) processed.add(ifc.by_id(elem.id))
elements -= processed self.serialiser.write(elem)
elements -= processed
if body_contexts and elements: with profile("Processing body context"):
if body_contexts and elements:
geom_settings = ifcopenshell.geom.settings(DISABLE_TRIANGULATION=True, STRICT_TOLERANCE=True)
geom_settings.set_context_ids(body_contexts)
it = ifcopenshell.geom.iterator(geom_settings, ifc, multiprocessing.cpu_count(), include=elements)
it.set_cache(cache)
for elem in self.yield_from_iterator(it):
self.serialiser.write(elem)
with profile("Camera element"):
# @todo tfk: is this needed?
geom_settings = ifcopenshell.geom.settings(DISABLE_TRIANGULATION=True, STRICT_TOLERANCE=True) geom_settings = ifcopenshell.geom.settings(DISABLE_TRIANGULATION=True, STRICT_TOLERANCE=True)
geom_settings.set_context_ids(body_contexts) it = ifcopenshell.geom.iterator(geom_settings, ifc, include=[self.camera_element])
it = ifcopenshell.geom.iterator(geom_settings, ifc, multiprocessing.cpu_count(), include=elements)
it.set_cache(cache)
for elem in self.yield_from_iterator(it): for elem in self.yield_from_iterator(it):
self.serialiser.write(elem) self.serialiser.write(elem)
geom_settings = ifcopenshell.geom.settings(DISABLE_TRIANGULATION=True, STRICT_TOLERANCE=True) with profile("Finalizing"):
it = ifcopenshell.geom.iterator(geom_settings, ifc, include=[self.camera_element]) self.serialiser.finalize()
for elem in self.yield_from_iterator(it):
self.serialiser.write(elem)
self.serialiser.finalize()
results = self.svg_buffer.get_value() results = self.svg_buffer.get_value()
root = etree.fromstring(results) with profile("Post processing"):
self.enrich_linework_with_metadata(root) root = etree.fromstring(results)
self.move_projection_to_bottom(root) self.enrich_linework_with_metadata(root)
with open(svg_path, "wb") as svg: self.move_projection_to_bottom(root)
svg.write(etree.tostring(root)) with open(svg_path, "wb") as svg:
svg.write(etree.tostring(root))
return svg_path return svg_path
@@ -487,8 +509,11 @@ class AddAnnotation(bpy.types.Operator, Operator):
def _execute(self, context): def _execute(self, context):
drawing = tool.Ifc.get_entity(context.scene.camera) drawing = tool.Ifc.get_entity(context.scene.camera)
if not drawing: if not drawing:
self.report({"WARNING"}, "Not a BIM camera")
return return
core.add_annotation(tool.Ifc, tool.Collector, tool.Drawing, drawing=drawing, object_type=self.object_type) r = core.add_annotation(tool.Ifc, tool.Collector, tool.Drawing, drawing=drawing, object_type=self.object_type)
if isinstance(r, str):
self.report({"WARNING"}, r)
class AddSheet(bpy.types.Operator, Operator): class AddSheet(bpy.types.Operator, Operator):
+1 -1
View File
@@ -190,7 +190,7 @@ def update_drawing_name(ifc, drawing_tool, drawing=None, name=None):
def add_annotation(ifc, collector, drawing_tool, drawing=None, object_type=None): def add_annotation(ifc, collector, drawing_tool, drawing=None, object_type=None):
context = drawing_tool.get_annotation_context(drawing_tool.get_drawing_target_view(drawing)) context = drawing_tool.get_annotation_context(drawing_tool.get_drawing_target_view(drawing))
if not context: if not context:
return return "No annotation context for drawing"
drawing_tool.show_decorations() drawing_tool.show_decorations()
obj = drawing_tool.create_annotation_object(drawing, object_type) obj = drawing_tool.create_annotation_object(drawing, object_type)
element = ifc.get_entity(obj) element = ifc.get_entity(obj)