Skip to content

Commit

Permalink
improve the ezdxf.render.dim_base.Measurement class
Browse files Browse the repository at this point in the history
Improves the text override feature of the Measurement class.
Replaces the first occurrence of "<>" in then replacement text,
so string interpolation from "$<> xyz" to "$300 xyz" for a
measurement of 300 units is now possible.

Replaces only the first "<>" like BricsCAD.
The override text "<><>" evaluates to "300<>" for the previous
measurement.
  • Loading branch information
mozman committed Dec 5, 2024
1 parent 3ff4011 commit fb9c618
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 12 deletions.
55 changes: 48 additions & 7 deletions examples/render/dimension_linear.py
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,50 @@ def example_background_fill(dxfversion=DXFVERSION):
doc.saveas(CWD / f"background_fill_example_{dxfversion}.dxf")


def example_text_override(dxfversion=DXFVERSION):
"""This example shows how to override the measurement text."""
doc = ezdxf.new(dxfversion, setup=True)
msp = doc.modelspace()

# custom text
dim = msp.add_linear_dim(
base=(0, 2),
p1=(0, 0),
p2=(3, 0),
)
dim.set_text("=<>= <>") # the first "<>" will be replaced by the measurement text
dim.render()

# suppress text
dim = msp.add_linear_dim(
base=(5, 2),
p1=(5, 0),
p2=(8, 0),
)
dim.set_text(" ")
dim.render()

# regular measurement text
dim = msp.add_linear_dim(
base=(10, 2),
p1=(10, 0),
p2=(13, 0),
)
dim.set_text("")
dim.render()

# regular measurement text
dim = msp.add_linear_dim(
base=(15, 2),
p1=(15, 0),
p2=(18, 0),
)
dim.set_text("<>")
dim.render()

doc.saveas(CWD / f"text_override_example_{dxfversion}.dxf")


def example_for_all_text_placings_R12():
doc = ezdxf.new("R12", setup=True)
example_for_all_text_placings(doc, "dim_linear_text_placing_R12.dxf")
Expand Down Expand Up @@ -788,15 +832,10 @@ def linear_EZ_MM(fmt):
doc.saveas(CWD / f"dim_linear_R12_{fmt}.dxf")


ALL = True
ALL = False

if __name__ == "__main__":
example_for_all_text_placings_ucs_R12()
# todo: TEXT entities transformed into 3D space do not work as expected
# for DXF R12!
example_for_all_text_placings_in_space_R12()
example_for_all_text_placings_ucs_R2007()
example_for_all_text_placings_in_space_R2007()
example_text_override("R2007")

if ALL:
linear_tutorial("R2007")
Expand All @@ -809,6 +848,8 @@ def linear_EZ_MM(fmt):
linear_tutorial("R2007")
linear_tutorial("R12")
example_background_fill("R2007")
example_text_override("R2007")

example_for_all_text_placings_R12()
example_for_all_text_placings_R2007()

Expand Down
11 changes: 6 additions & 5 deletions src/ezdxf/render/dim_base.py
Original file line number Diff line number Diff line change
Expand Up @@ -451,7 +451,7 @@ def __init__(
text_style = get_text_style(doc, style_name)
self.text_height: float = get_char_height(dim_style, text_style) * scale
self.text_width_factor: float = text_style.get_dxf_attrib("width", 1.0)
self.stored_dim_text = dimension.dxf.text
self.stored_dim_text: str = dimension.dxf.text

# text_gap: gap between dimension line an dimension text
self.text_gap: float = get("dimgap", 0.625) * scale
Expand Down Expand Up @@ -655,10 +655,11 @@ def text_override(self, measurement: float) -> str:
text = self.stored_dim_text
if text == " ": # suppresses text
return ""
elif text == "" or text == "<>": # measured distance
return self.format_text(measurement)
else: # user override
return text
formatted_measurement = self.format_text(measurement)
if text:
# only replace the first "<>", like BricsCAD
return text.replace("<>", formatted_measurement, 1)
return formatted_measurement

def location_override(self, location: UVec, leader=False, relative=False) -> None:
"""Set user defined dimension text location. ezdxf defines a user
Expand Down
64 changes: 64 additions & 0 deletions tests/test_07_render/test_704a_render_measurement_text.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# Copyright (c) 2024 Manfred Moitzi
# License: MIT License
import pytest
import ezdxf
from ezdxf.layouts import Modelspace


@pytest.fixture(scope="module")
def msp() -> Modelspace:
doc = ezdxf.new("R2007", setup=True)
return doc.modelspace()


@pytest.mark.parametrize("text", ["", "<>"])
def test_regular_measurement_text(msp, text):
dim = msp.add_linear_dim(
base=(0, 2),
p1=(0, 0),
p2=(3, 0),
)
dim.set_text(text)

block = dim.render().geometry.layout
mtext = block.query("MTEXT").first
assert mtext.text == "300"


def test_suppress_measurement_text(msp):
dim = msp.add_linear_dim(
base=(0, 2),
p1=(0, 0),
p2=(3, 0),
)
dim.set_text(" ")

block = dim.render().geometry.layout
assert len(block.query("MTEXT")) == 0 # no MTEXT entity expected


@pytest.mark.parametrize(
"text,expected",
[
("<>", "300"),
("Ø <>", "Ø 300"),
("<> cm", "300 cm"),
("[ <> ]", "[ 300 ]"),
("<> <>", "300 <>"), # only the first "<>" will be replaced
],
)
def test_override_measurement_text(msp, text, expected):
dim = msp.add_linear_dim(
base=(0, 2),
p1=(0, 0),
p2=(3, 0),
)
dim.set_text(text)

block = dim.render().geometry.layout
mtext = block.query("MTEXT").first
assert mtext.text == expected


if __name__ == "__main__":
pytest.main([__file__])

0 comments on commit fb9c618

Please sign in to comment.