Reimplement drawing material classes, fix cut projection order, and auto refresh camera representation

This commit is contained in:
Dion Moult
2021-10-30 22:13:25 +11:00
parent dcac1e69ca
commit 02461233a6
5 changed files with 58 additions and 8 deletions
+2 -2
View File
@@ -93,7 +93,7 @@ endif
cp -r blenderbim/* dist/blenderbim/
# Provides IfcOpenShell Python functionality
cd dist/working && wget https://s3.amazonaws.com/ifcopenshell-builds/ifcblender-python-$(PYNUMBER)-v0.7.0-58ee049-$(PLATFORM)64.zip
cd dist/working && wget https://s3.amazonaws.com/ifcopenshell-builds/ifcblender-python-$(PYNUMBER)-v0.7.0-93c5906-$(PLATFORM)64.zip
cd dist/working && unzip ifcblender*
cp -r dist/working/io_import_scene_ifc/ifcopenshell dist/blenderbim/libs/site/packages/
@@ -360,7 +360,7 @@ endif
cd dist/working/ && patch ../blenderbim/libs/site/packages/behave/runner_util.py < runner_util.patch
rm -rf dist/working
# Required by ids
# Required by ids - uh, not any more, but I'm trying it out in the drawing module
mkdir dist/working
cd dist/working && wget $(LXML_URL)
cd dist/working && cp *.whl lxml.zip && unzip lxml.zip
@@ -19,8 +19,8 @@
*/
* { stroke-linecap: round; stroke-linejoin: round; }
*[id] { fill: black; stroke: black; stroke-linecap: 'round'; stroke-width: 0.35; }
text { fill: black; stroke: none; }
.cut { fill: black; stroke: black; stroke-linecap: 'round'; stroke-width: 0.35; }
.projection { fill: white; stroke: black; stroke-linecap: 'round'; stroke-width: 0.25; }
.annotation { fill: none; stroke: black; stroke-linecap: 'round'; stroke-width: 0.25; }
.hidden { stroke-dasharray: 3, 2; }
@@ -149,6 +149,8 @@ class CreateDrawing(bpy.types.Operator):
self.props = context.scene.DocProperties
self.drawing_name = self.file.by_id(self.camera.BIMObjectProperties.ifc_definition_id).Name
self.get_scale()
if self.camera.data.BIMCameraProperties.update_representation(self.camera):
bpy.ops.bim.update_representation(obj=self.camera.name, ifc_representation_class="")
underlay_svg = self.generate_underlay(context)
self.profile_code("Generate underlay")
linework_svg = self.generate_linework(context)
@@ -307,12 +309,43 @@ class CreateDrawing(bpy.types.Operator):
iterators.append(ifcopenshell.geom.iterator(geom_settings, f, multiprocessing.cpu_count(), exclude=exclude))
with open(svg_path, "w") as svg:
results = ifcopenshell.draw.main(draw_settings, files, iterators=iterators, merge_projection=False)
svg.write(str(results))
results = ifcopenshell.draw.main(draw_settings, files, iterators=iterators, merge_projection=False)
from lxml import etree
root = etree.fromstring(results)
self.enrich_linework_with_metadata(root)
self.move_projection_to_bottom(root)
with open(svg_path, "wb") as svg:
svg.write(etree.tostring(root))
return svg_path
def enrich_linework_with_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]'):
classes = []
element = ifc.by_guid(el.get("{http://www.ifcopenshell.org/ns}guid"))
material = ifcopenshell.util.element.get_material(element, should_skip_usage=True)
if material:
if material.is_a("IfcMaterialLayerSet"):
name = material.LayerSetName or "null"
else:
name = getattr(material, "Name", "null")
name = self.canonicalise_class_name(name)
classes.append(f"material-{name}")
if classes:
el.set("class", (el.get("class", "") + " " + " ".join(classes)).strip())
def move_projection_to_bottom(self, root):
# 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[:] = sorted(group, key=lambda e : "projection" in e.get("class"))
group[:] = reversed(group)
def canonicalise_class_name(self, name):
return re.sub("[^0-9a-zA-Z]+", "", name)
def generate_annotation(self, context):
if not self.props.has_annotation:
return
@@ -18,6 +18,7 @@
import os
import bpy
import json
import ifcopenshell
import blenderbim.tool as tool
import blenderbim.bim.module.drawing.annotation as annotation
@@ -300,6 +301,7 @@ class DocProperties(PropertyGroup):
class BIMCameraProperties(PropertyGroup):
representation: StringProperty(name="Representation")
view_name: StringProperty(name="View Name")
target_view: EnumProperty(
items=[
@@ -332,6 +334,21 @@ class BIMCameraProperties(PropertyGroup):
cut_objects_custom: StringProperty(name="Custom Cut")
active_drawing_style_index: IntProperty(name="Active Drawing Style Index")
# For now, this JSON dump are all the parameters that determine a camera's "Block representation"
# By checking this, you will know whether or not the camera IFC representation needs to be refreshed
def update_representation(self, obj):
representation = json.dumps({
"matrix": [list(x) for x in obj.matrix_world],
"raster_x": self.raster_x,
"raster_y": self.raster_y,
"ortho_scale": obj.data.ortho_scale,
"clip_end": obj.data.clip_end,
})
if self.representation != representation:
self.representation = representation
return True
return False
class BIMTextProperties(PropertyGroup):
font_size: EnumProperty(
@@ -383,14 +383,14 @@ class OverrideDelete(bpy.types.Operator):
for obj in context.selected_objects:
if obj.BIMObjectProperties.ifc_definition_id:
element = file.by_id(obj.BIMObjectProperties.ifc_definition_id)
if element.FillsVoids:
if getattr(element, "FillsVoids", None):
self.remove_filling(element)
if element.is_a("IfcOpeningElement"):
for rel in element.HasFillings:
self.remove_filling(rel.RelatedBuildingElement)
if element.VoidsElements:
self.delete_opening_element(element)
elif element.HasOpenings:
elif getattr(element, "HasOpenings", None):
for rel in element.HasOpenings:
self.delete_opening_element(rel.RelatedOpeningElement)
bpy.data.objects.remove(obj)