176 lines
6.6 KiB
Python
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)
|