diff --git a/src/bonsai/bonsai/bim/data/pset/Psets_BBIM_Annotation.ifc b/src/bonsai/bonsai/bim/data/pset/Psets_BBIM_Annotation.ifc index 37278587a9..dd4851f9c5 100644 --- a/src/bonsai/bonsai/bim/data/pset/Psets_BBIM_Annotation.ifc +++ b/src/bonsai/bonsai/bim/data/pset/Psets_BBIM_Annotation.ifc @@ -28,11 +28,13 @@ DATA; #21=IFCSIMPLEPROPERTYTEMPLATE('1UDakJ5_f7kBhggNSW4$h5',$,'SymbolsPath','Default symbols SVG',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.); #22=IFCSIMPLEPROPERTYTEMPLATE('0d53LEtgLDQxnv__NfgH7i',$,'PatternsPath','Default patterns SVG',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.); #23=IFCSIMPLEPROPERTYTEMPLATE('26qFNMv7nCHgU6Jd7Anga5',$,'ShadingStylesPath','Default shading styles',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.); -#24=IFCPROPERTYSETTEMPLATE('0I9merLinF5Ap$aZwaclgm',$,'BBIM_Dimension','',.PSET_TYPEDRIVENOVERRIDE.,'IfcAnnotation/DIMENSION,IfcTypeProduct',(#25,#26,#27,#28)); +#24=IFCPROPERTYSETTEMPLATE('0I9merLinF5Ap$aZwaclgm',$,'BBIM_Dimension','',.PSET_TYPEDRIVENOVERRIDE.,'IfcAnnotation/DIMENSION,IfcAnnotation/RADIUS,IfcAnnotation/DIAMETER,IfcTypeProduct',(#25,#26,#27,#28,#30)); #25=IFCSIMPLEPROPERTYTEMPLATE('1rL2AbQsXD8RbpoWH5pYOV',$,'ShowDescriptionOnly','Hide the measurement values and show only annotation description',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.); #26=IFCSIMPLEPROPERTYTEMPLATE('0SVyOfB0rC2xNfdRYf3XvY',$,'SuppressZeroInches','Suppress 0 inch values in dimension annotation text (for example: 12'' - 0" -> 12'')',.P_SINGLEVALUE.,'IfcBoolean',$,$,$,$,$,.READWRITE.); #27=IFCSIMPLEPROPERTYTEMPLATE('2bUmj458PBqPAtUoI3MXsb',$,'TextPrefix','Text to add before annotation measurement value',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.); #28=IFCSIMPLEPROPERTYTEMPLATE('0bnzttUb9BPuN597uNTXOE',$,'TextSuffix','Text to add after annotation measurement value',.P_SINGLEVALUE.,'IfcLabel',$,$,$,$,$,.READWRITE.); #29=IFCSIMPLEPROPERTYTEMPLATE('2pJmUDpB50VBdCOib1zcJJ',$,'Newline_At','',.P_SINGLEVALUE.,'IfcInteger',$,$,$,$,$,.READWRITE.); +#30=IFCSIMPLEPROPERTYTEMPLATE('2TJn72t_v2cvBUG916Dpev',$,'CustomUnit','Dimension''s custom unit',.P_ENUMERATEDVALUE.,'IfcText',$,#31,$,$,$,.READWRITE.); +#31=IFCPROPERTYENUMERATION('CustomUnit',(IFCTEXT('Feet and Inches - Fractional'),IFCTEXT('Feet - Decimal'),IFCTEXT('Inches - Fractional'),IFCTEXT('Inches - Decimal'),IFCTEXT('Meters'),IFCTEXT('Decimeters'),IFCTEXT('Centimeters'),IFCTEXT('Millimeters')),$); ENDSEC; END-ISO-10303-21; diff --git a/src/bonsai/bonsai/bim/module/drawing/data.py b/src/bonsai/bonsai/bim/module/drawing/data.py index 30fda54828..579677cb98 100644 --- a/src/bonsai/bonsai/bim/module/drawing/data.py +++ b/src/bonsai/bonsai/bim/module/drawing/data.py @@ -386,6 +386,8 @@ class DecoratorData: suppress_zero_inches = pset_data.get("SuppressZeroInches", False) text_prefix = pset_data.get("TextPrefix", None) or "" text_suffix = pset_data.get("TextSuffix", None) or "" + custom_unit_list = pset_data.get("CustomUnit", None) or "" + custom_unit = custom_unit_list[0] if custom_unit_list else "" dimension_data = { "dimension_style": dimension_style, @@ -394,6 +396,7 @@ class DecoratorData: "text_prefix": text_prefix, "text_suffix": text_suffix, "fill_bg": fill_bg, + "custom_unit": custom_unit, } cls.data[obj.name] = dimension_data return dimension_data diff --git a/src/bonsai/bonsai/bim/module/drawing/decoration.py b/src/bonsai/bonsai/bim/module/drawing/decoration.py index 9c26c2b1c5..df68e7e8cd 100644 --- a/src/bonsai/bonsai/bim/module/drawing/decoration.py +++ b/src/bonsai/bonsai/bim/module/drawing/decoration.py @@ -495,14 +495,14 @@ class BaseDecorator: self.draw_label(context, text=text, line_no=line_number_start, multiline=True, **draw_label_kwargs) @lru_cache(maxsize=None) - def format_value(self, context, value): + def format_value(self, context, value, custom_unit=None): drawing_pset_data = DrawingsData.data["active_drawing_pset_data"] precision = drawing_pset_data.get("MetricPrecision", None) if not precision: precision = drawing_pset_data.get("ImperialPrecision", None) decimal_places = drawing_pset_data.get("DecimalPlaces", None) - return format_distance(value, precision=precision, decimal_places=decimal_places) + return format_distance(value, precision=precision, decimal_places=decimal_places, suppress_zero_inches=True, custom_unit=custom_unit) def draw_asterisk(self, context: bpy.types.Context, pos: Vector, rotation: float = 0.0, scale: float = 1.0) -> None: """`pos` is a world space position\n @@ -737,7 +737,7 @@ class DimensionDecorator(BaseDecorator): if not show_description_only: length = (v1 - v0).length - text = self.format_value(context, length) + text = self.format_value(context, length, custom_unit=dimension_data["custom_unit"]) if isinstance(self, DiameterDecorator): text = "D" + text text = text_prefix + text + text_suffix @@ -946,7 +946,7 @@ class RadiusDecorator(BaseDecorator): def get_text(): length = (spline_points[-1] - spline_points[-2]).length - return "R" + self.format_value(context, length) + return "R" + self.format_value(context, length, custom_unit=dimension_data["custom_unit"]) self.draw_dimension_text( context, get_text, description, dimension_data, pos=pos, text_dir=Vector((1, 0)), box_alignment="center" diff --git a/src/bonsai/bonsai/bim/module/drawing/helper.py b/src/bonsai/bonsai/bim/module/drawing/helper.py index f782cdbb7a..6a53de6c9f 100644 --- a/src/bonsai/bonsai/bim/module/drawing/helper.py +++ b/src/bonsai/bonsai/bim/module/drawing/helper.py @@ -130,30 +130,52 @@ def format_distance( decimal_places=None, suppress_zero_inches=False, in_unit_length=False, + custom_unit=None, ): # Get Blender Scene Unit Settings unit_scale = bpy.context.scene.unit_settings.scale_length unit_system = bpy.context.scene.unit_settings.system unit_length = bpy.context.scene.unit_settings.length_unit area_unit_symbol = " m2" if unit_system == "METRIC" else " ft2" + # Get IFC Unit Settings if tool.Ifc.get(): + unit_scale = 1 if length_unit := ifcopenshell.util.unit.get_project_unit(tool.Ifc.get(), "LENGTHUNIT"): unit_system = "METRIC" if length_unit.Name == "METRE" else "IMPERIAL" unit_length = length_unit.Name if hasattr(length_unit, "Prefix") and length_unit.Prefix: unit_length = length_unit.Prefix + length_unit.Name - string_conversion = { + unit_length_mapping = { "foot": "FEET", "inch": "INCHES", "METRE": "METERS", + "DECIMETRE": "DECIMETERS", "CENTIMETRE": "CENTIMETERS", "MILLIMETRE": "MILLIMETERS", } - unit_length = string_conversion[unit_length] + unit_length = unit_length_mapping[unit_length] + # For now we only format area in IFC Units if area_unit := ifcopenshell.util.unit.get_project_unit(tool.Ifc.get(), "AREAUNIT"): area_unit_symbol = " " + ifcopenshell.util.unit.get_unit_symbol(area_unit) + unit_fraction = True if unit_system == "IMPERIAL" else False + + # Custom Unit Settings + if custom_unit: + unit_mapping = { + "Feet and Inches - Fractional": ("IMPERIAL", "FEET", True), + "Feet - Decimal": ("IMPERIAL", "FEET", False), + "Inches - Fractional": ("IMPERIAL", "INCHES", True), + "Inches - Decimal": ("IMPERIAL", "INCHES", False), + "Meters": ("METRIC", "METERS", False), + "Decimeters": ("METRIC", "DECIMETERS", False), + "Centimeters": ("METRIC", "CENTIMETERS", False), + "Millimeters": ("METRIC", "MILLIMETERS", False), + } + if custom_unit in unit_mapping: + unit_system, unit_length, unit_fraction = unit_mapping[custom_unit] + value *= unit_scale # Imperial Formatting @@ -181,8 +203,11 @@ def format_distance( decInches = value * toInches # Separate ft and inches - # Unless Inches are the specified Length Unit - if unit_length != "INCHES": + # Unless Inches are the specified Length Unit or unit_fraction is False + if (unit_length == "FEET" and not unit_fraction): + feet = round(decInches / inPerFoot, 3) # keep decimal + decInches = 0 + elif unit_length != "INCHES": feet = int(decInches / inPerFoot) # remove decimal decInches -= feet * inPerFoot else: @@ -217,6 +242,10 @@ def format_distance( feet += 1 inches = 0 + # Check whether decimal or fractional + if not unit_fraction: + inches = round(decInches, 3) + frac = None if not isArea: add_inches = bool(inches) or not suppress_zero_inches or (inches == 0 and frac) tx_dist = "" @@ -265,6 +294,8 @@ def format_distance( # METRIC FORMATTING elif unit_system == "METRIC": if in_unit_length: + if unit_length == "DECIMETERS": + value = value / 10 if unit_length == "CENTIMETERS": value = value / 100 if unit_length == "MILLIMETERS": @@ -283,6 +314,14 @@ def format_distance( if hide_units is False: fmt += " m" tx_dist = fmt % value + # Decimeters + elif unit_length == "DECIMETERS": + if decimal_places is None: + fmt = "%1.1f" + if hide_units is False: + fmt += " dm" + d_dm = value * (10) + tx_dist = fmt % d_dm # Centimeters elif unit_length == "CENTIMETERS": if decimal_places is None: diff --git a/src/bonsai/bonsai/bim/module/drawing/svgwriter.py b/src/bonsai/bonsai/bim/module/drawing/svgwriter.py index 9a249450f7..ba9f69664e 100644 --- a/src/bonsai/bonsai/bim/module/drawing/svgwriter.py +++ b/src/bonsai/bonsai/bim/module/drawing/svgwriter.py @@ -1128,7 +1128,7 @@ class SvgWriter: def get_text(): radius = (points[-1].co - points[-2].co).length - radius = helper.format_distance(radius, precision=self.precision, decimal_places=self.decimal_places) + radius = helper.format_distance(radius, precision=self.precision, decimal_places=self.decimal_places, custom_unit=dimension_data["custom_unit"]) text = f"R{radius}" return text @@ -1256,6 +1256,7 @@ class SvgWriter: text_prefix=dimension_data["text_prefix"], text_suffix=dimension_data["text_suffix"], fill_bg=dimension_data["fill_bg"], + custom_unit=dimension_data["custom_unit"] ) def draw_dimension_annotations(self, obj): @@ -1280,6 +1281,7 @@ class SvgWriter: text_prefix=dimension_data["text_prefix"], text_suffix=dimension_data["text_suffix"], fill_bg=dimension_data["fill_bg"], + custom_unit=dimension_data["custom_unit"], ) def draw_measureit_arch_dimension_annotations(self): @@ -1306,6 +1308,7 @@ class SvgWriter: text_prefix="", text_suffix="", fill_bg=False, + custom_unit=None, ): offset = Vector([self.raw_width, self.raw_height]) / 2 v0 = self.project_point_onto_camera(v0_global) @@ -1339,6 +1342,7 @@ class SvgWriter: precision=self.precision, decimal_places=self.decimal_places, suppress_zero_inches=suppress_zero_inches, + custom_unit=custom_unit, ) text = text_prefix + str(dimension) + text_suffix else: