mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-09-21 14:23:53 +00:00
Minor things for drawing profiling and a warning
This commit is contained in:
committed by
Dion Moult
parent
4978a67e19
commit
104cabfb67
@@ -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):
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
Reference in New Issue
Block a user