This commit is contained in:
Thomas Krijnen
2020-09-08 14:36:14 +02:00
2 changed files with 158 additions and 7 deletions
@@ -1,4 +1,5 @@
import math
import bpy
# TODO: Deprecate this in favour of ifcopenshell.util.unit
@@ -101,3 +102,144 @@ class SIUnitHelper:
value *= (1 / SIUnitHelper.get_prefix_multiplier(to_prefix))
value *= (1 / SIUnitHelper.get_prefix_multiplier(to_prefix))
return value
# This function stolen from https://github.com/kevancress/MeasureIt_ARCH/blob/dcf607ce0896aa2284463c6b4ae9cd023fc54cbe/measureit_arch_baseclass.py
# MeasureIt-ARCH is GPL-v3
# In the future I will need to rewrite this to allow the user to have custom
# settings for each annotation object, not read from Blender.
def format_distance(value, isArea=False, hide_units=True):
s_code = "\u00b2" # Superscript two THIS IS LEGACY (but being kept for when Area Measurements are re-implimented)
# Get Scene Unit Settings
scaleFactor = bpy.context.scene.unit_settings.scale_length
unit_system = bpy.context.scene.unit_settings.system
unit_length = bpy.context.scene.unit_settings.length_unit
imperial_precision = 32
# (('1', "1\"", "1 Inch"),
# ('2', "1/2\"", "1/2 Inch"),
# ('4', "1/4\"", "1/4 Inch"),
# ('8', "1/8\"", "1/8th Inch"),
# ('16', "1/16\"", "1/16th Inch"),
# ('32', "1/32\"", "1/32th Inch"),
# ('64', "1/64\"", "1/64th Inch")),
toInches = 39.3700787401574887
inPerFoot = 11.999
if isArea:
toInches = 1550
inPerFoot = 143.999
value *= scaleFactor
# Imperial Formating
if unit_system == "IMPERIAL":
base = int(imperial_precision)
decInches = value * toInches
# Seperate ft and inches
# Unless Inches are the specified Length Unit
if unit_length != 'INCHES':
feet = math.floor(decInches/inPerFoot)
decInches -= feet*inPerFoot
else:
feet = 0
#Seperate Fractional Inches
inches = math.floor(decInches)
if inches != 0:
frac = round(base*(decInches-inches))
else:
frac = round(base*(decInches))
#Set proper numerator and denominator
if frac != base:
numcycles = int(math.log2(base))
for i in range(numcycles):
if frac%2 == 0:
frac = int(frac/2)
base = int(base/2)
else:
break
else:
frac = 0
inches += 1
# Check values and compose string
if inches == 12:
feet += 1
inches = 0
if inches !=0:
inchesString = str(inches)
if frac != 0: inchesString += "-"
else: inchesString += "\""
else: inchesString = ""
if feet != 0:
feetString = str(feet) + "' "
else: feetString = ""
if frac != 0:
fracString = str(frac) + "/" + str(base) +"\""
else: fracString = ""
if not isArea:
tx_dist = feetString + inchesString + fracString
else:
tx_dist = str('%1.3f' % (value*toInches/inPerFoot)) + " sq. ft."
# METRIC FORMATING
elif unit_system == "METRIC":
# Meters
if unit_length == 'METERS':
fmt = '%1.3f'
if hide_units is False:
fmt += " m"
tx_dist = fmt % value
# Centimeters
elif unit_length == 'CENTIMETERS':
fmt = '%1.1f'
if hide_units is False:
fmt += " cm"
d_cm = value * (100)
tx_dist = fmt % d_cm
#Millimeters
elif unit_length == 'MILLIMETERS':
fmt = '%1.0f'
if hide_units is False:
fmt += " mm"
d_mm = value * (1000)
tx_dist = fmt % d_mm
# Otherwise Use Adaptive Units
else:
if round(value, 2) >= 1.0:
fmt = '%1.3f'
if hide_units is False:
fmt += " m"
tx_dist = fmt % value
else:
if round(value, 2) >= 0.01:
fmt = '%1.1f'
if hide_units is False:
fmt += " cm"
d_cm = value * (100)
tx_dist = fmt % d_cm
else:
fmt = '%1.0f'
if hide_units is False:
fmt += " mm"
d_mm = value * (1000)
tx_dist = fmt % d_mm
if isArea:
tx_dist += s_code
else:
tx_dist = fmt % value
return tx_dist
@@ -7,6 +7,7 @@ import xml.etree.ElementTree as ET
import svgwrite
import ifcopenshell
from . import annotation
from . import helper
from mathutils import Vector
from mathutils import geometry
@@ -189,14 +190,18 @@ class SvgWriter():
(x_offset + projected_points[0].x) * self.scale,
((y_offset - projected_points[0].y) * self.scale) - 2.5
))
# TODO: unhardcode m unit
# TODO: allow metric to be configurable
rl = ((matrix_world @
points[0].co).xyz + self.ifc_cutter.plan_level_obj.location).z
if bpy.context.scene.unit_settings.system == 'IMPERIAL':
rl = helper.format_distance(rl)
else:
rl = '{:.3f}m'.format(rl)
if projected_points[0].x > projected_points[-1].x:
text_anchor = 'end'
else:
text_anchor = 'start'
self.svg.add(self.svg.text('RL +{:.3f}m'.format(rl), insert=tuple(text_position), **{
self.svg.add(self.svg.text('RL +{}'.format(rl), insert=tuple(text_position), **{
'font-size': annotation.Annotator.get_svg_text_size(2.5),
'font-family': 'OpenGost Type B TT',
'text-anchor': text_anchor,
@@ -221,9 +226,13 @@ class SvgWriter():
(x_offset + projected_points[0].x) * self.scale,
((y_offset - projected_points[0].y) * self.scale) - 3.5
))
# TODO: unhardcode m unit
# TODO: allow metric to be configurable
rl = (matrix_world @ points[0].co.xyz).z
self.svg.add(self.svg.text('RL +{:.3f}m'.format(rl), insert=tuple(text_position), **{
if bpy.context.scene.unit_settings.system == 'IMPERIAL':
rl = helper.format_distance(rl)
else:
rl = '{:.3f}m'.format(rl)
self.svg.add(self.svg.text('RL +{}'.format(rl), insert=tuple(text_position), **{
'font-size': annotation.Annotator.get_svg_text_size(2.5),
'font-family': 'OpenGost Type B TT',
'text-anchor': 'start',
@@ -485,10 +494,10 @@ class SvgWriter():
start = Vector(((x_offset + v0.x), (y_offset - v0.y)))
end = Vector(((x_offset + v1.x), (y_offset - v1.y)))
mid = ((end - start) / 2) + start
# TODO: hardcoded meters to mm conversion, until I properly do units
vector = end - start
perpendicular = Vector((vector.y, -vector.x)).normalized()
dimension = (v1_global - v0_global).length * 1000
dimension = (v1_global - v0_global).length
dimension = helper.format_distance(dimension)
sheet_dimension = ((end*self.scale) - (start*self.scale)).length
if sheet_dimension < 5: # annotation can't fit
# offset text to right of marker
@@ -503,7 +512,7 @@ class SvgWriter():
if text_override is not None:
text = text_override
else:
text = str(round(dimension))
text = str(dimension)
self.svg.add(self.svg.text(text, insert=tuple(text_position), **{
'transform': 'rotate({} {} {})'.format(
rotation,