Files
IfcOpenShell/src/blenderbim/blenderbim/bim/module/drawing/annotation.py
T

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

168 lines
6.0 KiB
Python
Raw Normal View History

2020-05-03 15:41:05 +10:00
import bpy
import os
2020-05-03 15:41:05 +10:00
from mathutils import Vector
2020-11-01 20:08:48 +07:00
class Annotator:
@staticmethod
def get_svg_text_size(size):
sizes = {
2020-11-01 20:08:48 +07:00
"1.8": "2.97",
"2.5": "4.13",
"3.5": "5.78",
"5.0": "8.25",
"7.0": "11.55",
}
return float(sizes[str(size)])
2020-05-03 15:41:05 +10:00
@staticmethod
def add_text(context, related_element=None):
curve = bpy.data.curves.new(type="FONT", name="Text")
2020-11-01 20:08:48 +07:00
curve.body = "TEXT"
obj = bpy.data.objects.new("Text", curve)
obj.matrix_world = context.scene.camera.matrix_world
if related_element is None:
location, _, _, _ = Annotator.get_placeholder_coords(context)
else:
obj.data.BIMTextProperties.related_element = related_element
location = related_element.location
obj.location = location
2020-05-03 15:41:05 +10:00
obj.hide_render = True
2020-11-01 20:08:48 +07:00
font = bpy.data.fonts.get("OpenGost TypeB TT")
if not font:
2020-11-01 20:08:48 +07:00
font = bpy.data.fonts.load(
os.path.join(context.scene.BIMProperties.data_dir, "fonts", "OpenGost Type B TT.ttf")
2020-11-01 20:08:48 +07:00
)
font.name = "OpenGost Type B TT"
obj.data.font = font
2020-11-01 20:08:48 +07:00
obj.data.BIMTextProperties.font_size = "2.5"
collection = context.scene.camera.users_collection[0]
collection.objects.link(obj)
Annotator.resize_text(obj)
2020-05-03 15:41:05 +10:00
return obj
@staticmethod
def resize_text(text_obj):
camera = None
for obj in text_obj.users_collection[0].objects:
if isinstance(obj.data, bpy.types.Camera):
camera = obj
break
if not camera:
return
# This is a magic number for OpenGost
font_size = 1.6 / 1000
font_size *= float(text_obj.data.BIMTextProperties.font_size)
2020-11-01 20:08:48 +07:00
if camera.data.BIMCameraProperties.diagram_scale == "CUSTOM":
human_scale, fraction = camera.data.BIMCameraProperties.custom_diagram_scale.split("|")
else:
2020-11-01 20:08:48 +07:00
human_scale, fraction = camera.data.BIMCameraProperties.diagram_scale.split("|")
numerator, denominator = fraction.split("/")
font_size /= float(numerator) / float(denominator)
text_obj.data.size = font_size
2020-05-03 15:41:05 +10:00
@staticmethod
def add_line_to_annotation(obj, context, co1=None, co2=None):
if co1 is None:
co1, co2, _, _ = Annotator.get_placeholder_coords(context)
co1 = obj.matrix_world.inverted() @ co1
co2 = obj.matrix_world.inverted() @ co2
2020-05-03 15:41:05 +10:00
if isinstance(obj.data, bpy.types.Mesh):
obj.data.vertices.add(2)
obj.data.vertices[-2].co = co1
obj.data.vertices[-1].co = co2
2020-06-06 23:42:24 +02:00
obj.data.edges.add(1)
2020-05-03 15:41:05 +10:00
obj.data.edges[-1].vertices = (obj.data.vertices[-2].index, obj.data.vertices[-1].index)
if isinstance(obj.data, bpy.types.Curve):
2020-11-01 20:08:48 +07:00
polyline = obj.data.splines.new("POLY")
2020-05-03 15:41:05 +10:00
polyline.points.add(1)
polyline.points[-2].co = list(co1) + [1]
polyline.points[-1].co = list(co2) + [1]
return obj
2020-12-26 21:59:57 +07:00
@staticmethod
def add_plane_to_annotation(obj, context):
co1, co2, co3, co4 = Annotator.get_placeholder_coords(context)
2020-12-26 21:59:57 +07:00
co1 = obj.matrix_world.inverted() @ co1 # bot left
co2 = obj.matrix_world.inverted() @ co2 # top left
co3 = obj.matrix_world.inverted() @ co3 # bot right
co4 = obj.matrix_world.inverted() @ co4 # top right
obj.data.vertices.add(4)
v1 = obj.data.vertices[-4]
v2 = obj.data.vertices[-3]
v3 = obj.data.vertices[-2]
v4 = obj.data.vertices[-1]
v1.co = co4
v2.co = co2
v3.co = co1
v4.co = co3
obj.data.edges.add(4)
e1 = obj.data.edges[-4]
e2 = obj.data.edges[-3]
e3 = obj.data.edges[-2]
e4 = obj.data.edges[-1]
e1.vertices = (v1.index, v2.index)
e2.vertices = (v2.index, v3.index)
e3.vertices = (v3.index, v4.index)
e4.vertices = (v4.index, v1.index)
obj.data.loops.add(4)
l1 = obj.data.loops[-4]
l2 = obj.data.loops[-3]
l3 = obj.data.loops[-2]
l4 = obj.data.loops[-1]
l1.vertex_index = v1.index
l1.edge_index = e1.index
l2.vertex_index = v2.index
l2.edge_index = e2.index
l3.vertex_index = v3.index
l3.edge_index = e3.index
l4.vertex_index = v4.index
l4.edge_index = e4.index
obj.data.polygons.add(1)
p1 = obj.data.polygons[-1]
p1.vertices = (v1.index, v2.index, v3.index, v4.index)
p1.loop_start = l1.index
p1.loop_total = 4
return obj
2020-05-03 15:41:05 +10:00
@staticmethod
def get_annotation_obj(name, data_type, context):
collection = context.scene.camera.users_collection[0]
2020-05-03 15:41:05 +10:00
for obj in collection.objects:
if name in obj.name:
return obj
2020-11-01 20:08:48 +07:00
if data_type == "mesh":
data = bpy.data.meshes.new(name)
2020-11-01 20:08:48 +07:00
elif data_type == "curve":
data = bpy.data.curves.new(name, type="CURVE")
2020-11-01 20:08:48 +07:00
data.dimensions = "3D"
2020-05-03 15:41:05 +10:00
data.resolution_u = 2
obj = bpy.data.objects.new(name, data)
2020-05-03 15:41:05 +10:00
collection.objects.link(obj)
return obj
@staticmethod
def get_placeholder_coords(context):
camera = context.scene.camera
2020-05-03 15:41:05 +10:00
z_offset = camera.matrix_world.to_quaternion() @ Vector((0, 0, -1))
if context.scene.render.resolution_x > context.scene.render.resolution_y:
2020-11-01 20:08:48 +07:00
y = (
camera.data.ortho_scale
* (context.scene.render.resolution_y / context.scene.render.resolution_x)
2020-11-01 20:08:48 +07:00
/ 4
)
2020-05-03 15:41:05 +10:00
else:
y = camera.data.ortho_scale / 4
y_offset = camera.matrix_world.to_quaternion() @ Vector((0, y, 0))
2020-12-26 21:59:57 +07:00
x_offset = camera.matrix_world.to_quaternion() @ Vector((y/2, 0, 0))
return (camera.location + z_offset,
camera.location + z_offset + y_offset,
camera.location + z_offset + x_offset,
camera.location + z_offset + x_offset + y_offset)