diff --git a/src/blenderbim/blenderbim/bim/module/drawing/annotation.py b/src/blenderbim/blenderbim/bim/module/drawing/annotation.py
index 10e1e59e5a..9188291f40 100644
--- a/src/blenderbim/blenderbim/bim/module/drawing/annotation.py
+++ b/src/blenderbim/blenderbim/bim/module/drawing/annotation.py
@@ -16,11 +16,13 @@
# You should have received a copy of the GNU General Public License
# along with BlenderBIM Add-on. If not, see .
-import bpy
import os
-import blenderbim.tool as tool
-from mathutils import Vector
+import bpy
+import math
import bmesh
+import blenderbim.tool as tool
+import ifcopenshell.util.element
+from mathutils import Vector, Matrix
class Annotator:
@@ -111,7 +113,7 @@ class Annotator:
def get_annotation_obj(drawing, object_type, data_type):
camera = tool.Ifc.get_object(drawing)
co1, _, _, _ = Annotator.get_placeholder_coords(camera)
- matrix_world = camera.matrix_world.copy()
+ matrix_world = tool.Drawing.get_camera_matrix(camera)
matrix_world.translation = co1
collection = camera.BIMObjectProperties.collection
@@ -154,6 +156,13 @@ class Annotator:
camera = bpy.context.scene.camera
z_offset = camera.matrix_world.to_quaternion() @ Vector((0, 0, -1))
+
+ if (
+ ifcopenshell.util.element.get_pset(tool.Ifc.get_entity(camera), "EPset_Drawing", "TargetView")
+ == "REFLECTED_PLAN_VIEW"
+ ):
+ z_offset *= -1
+
y = camera.data.ortho_scale / 4
res_x = bpy.context.scene.render.resolution_x
diff --git a/src/blenderbim/blenderbim/bim/module/drawing/decoration.py b/src/blenderbim/blenderbim/bim/module/drawing/decoration.py
index 13c66efa5f..6b21e95bee 100644
--- a/src/blenderbim/blenderbim/bim/module/drawing/decoration.py
+++ b/src/blenderbim/blenderbim/bim/module/drawing/decoration.py
@@ -520,7 +520,9 @@ class BaseDecorator:
return matrix.inverted()[i].to_3d().normalized()
text_dir_world_x_axis = get_basis_vector(obj.matrix_world)
- camera_matrix = camera.matrix_world.normalized()
+
+ camera_matrix = tool.Drawing.get_camera_matrix(camera)
+
text_dir = (camera_matrix.inverted().to_quaternion() @ text_dir_world_x_axis).to_2d().normalized()
pos = location_3d_to_region_2d(region, region3d, text_world_position)
diff --git a/src/blenderbim/blenderbim/bim/module/drawing/svgwriter.py b/src/blenderbim/blenderbim/bim/module/drawing/svgwriter.py
index 7021c9bfd2..a987157c63 100644
--- a/src/blenderbim/blenderbim/bim/module/drawing/svgwriter.py
+++ b/src/blenderbim/blenderbim/bim/module/drawing/svgwriter.py
@@ -805,7 +805,7 @@ class SvgWriter:
text_dir_world_x_axis = get_basis_vector(text_obj.matrix_world)
# RCP cameras may be scaled, so reset scales.
- camera_matrix = self.camera.matrix_world.normalized()
+ camera_matrix = tool.Drawing.get_camera_matrix(self.camera)
text_dir = (camera_matrix.inverted().to_quaternion() @ text_dir_world_x_axis).to_2d().normalized()
angle = math.degrees(-text_dir.angle_signed(Vector((1, 0))))
diff --git a/src/blenderbim/blenderbim/tool/drawing.py b/src/blenderbim/blenderbim/tool/drawing.py
index f78862baf9..bcf9c1ebae 100644
--- a/src/blenderbim/blenderbim/tool/drawing.py
+++ b/src/blenderbim/blenderbim/tool/drawing.py
@@ -1849,3 +1849,12 @@ class Drawing(blenderbim.core.tool.Drawing):
sheet_references.append(reference)
break
return sheet_references
+
+ def get_camera_matrix(self, camera):
+ matrix_world = camera.matrix_world.copy().normalized()
+ location, rotation, scale = matrix_world.decompose()
+ if scale.x < 0 or scale.y < 0 or scale.z < 0:
+ # RCPs may be inversely scaled. We discard the scale and rotate the Z to compensate.
+ rotate180z = mathutils.Matrix.Rotation(math.radians(180.0), 4, "Z")
+ return mathutils.Matrix.Translation(location) @ rotation.to_matrix().to_4x4() @ rotate180z
+ return mathutils.Matrix.Translation(location) @ rotation.to_matrix().to_4x4()
diff --git a/src/blenderbim/blenderbim/tool/geometry.py b/src/blenderbim/blenderbim/tool/geometry.py
index 3b78dfb8d4..0544c9d330 100644
--- a/src/blenderbim/blenderbim/tool/geometry.py
+++ b/src/blenderbim/blenderbim/tool/geometry.py
@@ -29,7 +29,7 @@ import blenderbim.core.spatial
import blenderbim.tool as tool
import blenderbim.bim.import_ifc
from math import radians
-from mathutils import Vector
+from mathutils import Vector, Matrix
from blenderbim.bim.ifc import IfcStore
@@ -59,6 +59,8 @@ class Geometry(blenderbim.core.tool.Geometry):
# Note that clearing scale has no impact on cameras.
if (obj.scale - Vector((1.0, 1.0, 1.0))).length > 1e-4:
if not obj.data:
+ location, rotation, _ = obj.matrix_world.decompose()
+ obj.matrix_world = Matrix.Translation(location) @ rotation.to_matrix().to_4x4()
obj.matrix_world.normalize()
elif obj.data.users == 1:
context_override = {}
diff --git a/src/blenderbim/docs/devs/writing_docs.rst b/src/blenderbim/docs/devs/writing_docs.rst
index c5be24d5b2..0d14e89bee 100644
--- a/src/blenderbim/docs/devs/writing_docs.rst
+++ b/src/blenderbim/docs/devs/writing_docs.rst
@@ -60,3 +60,11 @@ download.
See also blocks should be used to reference `further reading
`__ links.
+
+Tables can be very annoying to format. You can use a CSV table instead.
+
+.. csv-table::
+ :header: "Foo", "Bar", "Baz"
+
+ "ABC", "01", "02"
+ "DEF", "03", "04"
diff --git a/src/ifccsv/ifccsv.py b/src/ifccsv/ifccsv.py
index d8e31a2183..1f72bf6c54 100755
--- a/src/ifccsv/ifccsv.py
+++ b/src/ifccsv/ifccsv.py
@@ -258,7 +258,7 @@ class IfcCsv:
reverse = sort_data["order"] == "DESC"
self.results = sorted(self.results, key=lambda x: natural_sort(x[i]), reverse=reverse)
else:
- if include_global_id and len(list(self.results[0])) > 1:
+ if include_global_id and len(list(self.results)[0]) > 1:
self.results = sorted(self.results, key=lambda x: x[1])
elif not include_global_id:
self.results = sorted(self.results, key=lambda x: x[0])