Files
stepanalyser/.venv/lib/python3.12/site-packages/ezdxf/render/dim_diameter.py
Christian Anetzberger a197de9456 initial
2026-01-22 20:23:51 +01:00

176 lines
6.6 KiB
Python

# Copyright (c) 2018-2022, Manfred Moitzi
# License: MIT License
from __future__ import annotations
from typing import TYPE_CHECKING, Optional
from ezdxf.math import Vec2, UCS
from ezdxf.entities.dimstyleoverride import DimStyleOverride
from .dim_radius import (
RadiusDimension,
add_center_mark,
Measurement,
RadiusMeasurement,
)
if TYPE_CHECKING:
from ezdxf.entities import Dimension
PREFIX = "Ø"
class DiameterDimension(RadiusDimension):
"""
Diameter dimension line renderer.
Supported render types:
- default location inside, text aligned with diameter dimension line
- default location inside horizontal text
- default location outside, text aligned with diameter dimension line
- default location outside horizontal text
- user defined location, text aligned with diameter dimension line
- user defined location horizontal text
Args:
dimension: DXF entity DIMENSION
ucs: user defined coordinate system
override: dimension style override management object
"""
def init_measurement(self, color: int, scale: float) -> Measurement:
return RadiusMeasurement(self.dim_style, color, scale, PREFIX)
def _center(self):
return Vec2(self.dimension.dxf.defpoint).lerp(
self.dimension.dxf.defpoint4
)
def __init__(
self,
dimension: Dimension,
ucs: Optional[UCS] = None,
override: Optional[DimStyleOverride] = None,
):
# Diameter dimension has the same styles for inside text as radius dimension, except for the
# measurement text
super().__init__(dimension, ucs, override)
self.point_on_circle2 = Vec2(self.dimension.dxf.defpoint)
def add_text(
self, text: str, pos: Vec2, rotation: float, dxfattribs
) -> None:
# escape diameter sign
super().add_text(text.replace(PREFIX, "%%c"), pos, rotation, dxfattribs)
def get_default_text_location(self) -> Vec2:
"""Returns default text midpoint based on `text_valign` and
`text_outside`.
"""
measurement = self.measurement
if measurement.text_is_outside and measurement.text_outside_horizontal:
return super().get_default_text_location()
text_direction = Vec2.from_deg_angle(measurement.text_rotation)
vertical_direction = text_direction.orthogonal(ccw=True)
vertical_distance = measurement.text_vertical_distance()
if measurement.text_is_inside:
text_midpoint = self.center
else:
hdist = (
self._total_text_width / 2.0
+ self.arrows.arrow_size
+ measurement.text_gap
)
text_midpoint = self.point_on_circle + (self.dim_line_vec * hdist)
return text_midpoint + (vertical_direction * vertical_distance)
def _add_arrow_1(self, rotate=False):
if not self.arrows.suppress1:
return self.add_arrow(self.point_on_circle, rotate=rotate)
else:
return self.point_on_circle
def _add_arrow_2(self, rotate=True):
if not self.arrows.suppress2:
return self.add_arrow(self.point_on_circle2, rotate=rotate)
else:
return self.point_on_circle2
def render_default_location(self) -> None:
"""Create dimension geometry at the default dimension line locations."""
measurement = self.measurement
if measurement.text_is_outside:
connection_point1 = self._add_arrow_1(rotate=True)
if self.outside_text_force_dimline:
self.add_diameter_dim_line(
connection_point1, self._add_arrow_2()
)
else:
add_center_mark(self)
if measurement.text_outside_horizontal:
self.add_horiz_ext_line_default(connection_point1)
else:
self.add_radial_ext_line_default(connection_point1)
else:
connection_point1 = self._add_arrow_1(rotate=False)
if measurement.text_movement_rule == 1:
# move text, add leader -> dimline from text to point on circle
self.add_radial_dim_line_from_text(
self.center, connection_point1
)
add_center_mark(self)
else:
# dimline from center to point on circle
self.add_diameter_dim_line(
connection_point1, self._add_arrow_2()
)
def render_user_location(self) -> None:
"""Create dimension geometry at user defined dimension locations."""
measurement = self.measurement
preserve_outside = measurement.text_is_outside
leader = measurement.text_movement_rule != 2
if not leader:
# render dimension line like text inside
measurement.text_is_outside = False
# add arrow symbol (block references)
connection_point1 = self._add_arrow_1(
rotate=measurement.text_is_outside
)
if measurement.text_is_outside:
if self.outside_text_force_dimline:
self.add_radial_dim_line(self.point_on_circle)
else:
add_center_mark(self)
if measurement.text_outside_horizontal:
self.add_horiz_ext_line_user(connection_point1)
else:
self.add_radial_ext_line_user(connection_point1)
else:
if measurement.text_inside_horizontal:
self.add_horiz_ext_line_user(connection_point1)
else:
if measurement.text_movement_rule == 2: # move text, no leader!
# dimline across the circle
connection_point2 = self._add_arrow_2(rotate=True)
self.add_line(
connection_point1,
connection_point2,
dxfattribs=self.dimension_line.dxfattribs(),
remove_hidden_lines=True,
)
else:
# move text, add leader -> dimline from text to point on circle
self.add_radial_dim_line_from_text(
measurement.user_location, connection_point1
)
add_center_mark(self)
measurement.text_is_outside = preserve_outside
def add_diameter_dim_line(self, start: Vec2, end: Vec2) -> None:
"""Add diameter dimension line."""
attribs = self.dimension_line.dxfattribs()
self.add_line(start, end, dxfattribs=attribs, remove_hidden_lines=True)