mirror of
https://github.com/IfcOpenShell/IfcOpenShell.git
synced 2026-08-10 09:48:32 +00:00
Allow dimensions to use custom units from BBIM_Dimension Pset.
- Implementation of @theoryshaw PR #5922. - Note: `IfcPropertyEnumeration` allows multiple choices, but this is not applicable for this use case. Users must manually deselect other options; otherwise, it defaults to the first selected option.
This commit is contained in:
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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:
|
||||
|
||||
Reference in New Issue
Block a user