def random_point(start, end): dist = end - start return Vector(start + random.random() * dist, start + random.random() * dist)
from ezdxf.math.transformtools import transform_extrusion from ezdxf.lldxf.attributes import DXFAttr, DXFAttributes, DefSubclass, XType from ezdxf.lldxf.const import SUBCLASS_MARKER, DXF2000 from .dxfentity import base_class, SubclassProcessor from .dxfgfx import DXFGraphic, acdb_entity from .factory import register_entity if TYPE_CHECKING: from ezdxf.eztypes import TagWriter, DXFNamespace, UCS, Matrix44 __all__ = ['Tolerance'] acdb_tolerance = DefSubclass('AcDbFcf', { 'dimstyle': DXFAttr(3, default='Standard'), 'insert': DXFAttr(10, xtype=XType.point3d, default=Vector(0, 0, 0)), # Insertion point (in WCS) 'content': DXFAttr(1, default=""), # String representing the visual representation of the tolerance 'extrusion': DXFAttr(210, xtype=XType.point3d, default=Vector(0, 0, 1), optional=True), # Extrusion direction 'x_axis_vector': DXFAttr(11, xtype=XType.point3d, default=Vector(1, 0, 0)), # X-axis direction vector (in WCS) }) @register_entity class Tolerance(DXFGraphic): """ DXF TOLERANCE entity """ DXFTYPE = 'TOLERANCE' DXFATTRIBS = DXFAttributes(base_class, acdb_entity, acdb_tolerance) MIN_DXF_VERSION_FOR_EXPORT = DXF2000 def load_dxf_attribs(self, processor: SubclassProcessor = None) -> 'DXFNamespace': dxf = super().load_dxf_attribs(processor)
def virtual_entities(point: 'Point', pdsize: float = 1, pdmode: int = 0) -> List['DXFGraphic']: """ Yields point graphic as DXF primitives LINE and CIRCLE entities. The dimensionless point is rendered as zero-length line! Check for this condition:: e.dxftype() == 'LINE' and e.dxf.start.isclose(e.dxf.end) if the rendering engine can't handle zero-length lines. Args: point: DXF POINT entity pdsize: point size in drawing units pdmode: point styling mode, see :class:`~ezdxf.entities.Point` class .. versionadded:: 0.15 """ def add_line_symmetrical(offset: Vector): dxfattribs['start'] = ucs.to_wcs(-offset) dxfattribs['end'] = ucs.to_wcs(offset) entities.append(factory.new('LINE', dxfattribs)) def add_line(s: Vector, e: Vector): dxfattribs['start'] = ucs.to_wcs(s) dxfattribs['end'] = ucs.to_wcs(e) entities.append(factory.new('LINE', dxfattribs)) center = point.dxf.location # This is not a real OCS! Defines just the point orientation, # location is in WCS! ocs = point.ocs() ucs = UCS(origin=center, ux=ocs.ux, uz=ocs.uz) # The point angle is clockwise oriented: ucs = ucs.rotate_local_z(math.radians(-point.dxf.angle)) entities = [] gfx = point.graphic_properties() radius = pdsize * 0.5 has_circle = bool(pdmode & 32) has_square = bool(pdmode & 64) style = pdmode & 7 dxfattribs = dict(gfx) if style == 0: # . dimensionless point as zero-length line add_line_symmetrical(NULLVEC) # style == 1: no point symbol elif style == 2: # + cross add_line_symmetrical(Vector(pdsize, 0)) add_line_symmetrical(Vector(0, pdsize)) elif style == 3: # x cross add_line_symmetrical(Vector(pdsize, pdsize)) add_line_symmetrical(Vector(pdsize, -pdsize)) elif style == 4: # ' tick add_line(NULLVEC, Vector(0, radius)) if has_square: x1 = -radius x2 = radius y1 = -radius y2 = radius add_line(Vector(x1, y1), Vector(x2, y1)) add_line(Vector(x2, y1), Vector(x2, y2)) add_line(Vector(x2, y2), Vector(x1, y2)) add_line(Vector(x1, y2), Vector(x1, y1)) if has_circle: dxfattribs = dict(gfx) if point.dxf.hasattr('extrusion'): dxfattribs['extrusion'] = ocs.uz dxfattribs['center'] = ocs.from_wcs(center) else: dxfattribs['center'] = center dxfattribs['radius'] = radius entities.append(factory.new('CIRCLE', dxfattribs)) # noinspection PyTypeChecker return entities
from ezdxf.lldxf.attributes import DXFAttr, DXFAttributes, DefSubclass, XType from ezdxf.lldxf.const import DXF12, SUBCLASS_MARKER from .dxfentity import base_class, SubclassProcessor from .dxfgfx import DXFGraphic, acdb_entity from .factory import register_entity if TYPE_CHECKING: from ezdxf.eztypes import TagWriter, DXFNamespace, UCS __all__ = ['Point'] acdb_point = DefSubclass( 'AcDbPoint', { 'location': DXFAttr(10, xtype=XType.point3d, default=Vector(0, 0, 0)), 'thickness': DXFAttr(39, default=0, optional=True), 'extrusion': DXFAttr( 210, xtype=XType.point3d, default=Vector(0, 0, 1), optional=True), # angle of the X axis for the UCS in effect when the point was drawn (optional, default = 0); used when PDMODE is # nonzero 'angle': DXFAttr(50, default=0, optional=True), }) @register_entity class Point(DXFGraphic): """ DXF POINT entity """
def test_vertext_attribs_xy(): result = vertex_attribs((1, 2), format='xy') assert result == {'location': Vector(1, 2)}
def random_pos(lower_left=(0, 0), upper_right=(100, 100)): x0, y0 = lower_left x1, y1 = upper_right x = random_in_range(x0, x1) y = random_in_range(y0, y1) return Vector(x, y)
def set_vertices(self, vertices: Iterable['Vertex']): """ Set vertices of the leader, vertices is an iterable of ``(x, y [,z])`` tuples or :class:`~ezdxf.math.Vector`. """ self.vertices = [Vector(v) for v in vertices]
# 64 = The polyline is a polyface mesh # 128 = The linetype pattern is generated continuously around the vertices of this polyline 'default_start_width': DXFAttr(40, default=0, optional=True), 'default_end_width': DXFAttr(41, default=0, optional=True), 'm_count': DXFAttr(71, default=0, optional=True), 'n_count': DXFAttr(72, default=0, optional=True), 'm_smooth_density': DXFAttr(73, default=0, optional=True), 'n_smooth_density': DXFAttr(74, default=0, optional=True), # Curves and smooth surface type; integer codes, not bit-coded: 'smooth_type': DXFAttr(75, default=0, optional=True), # 0 = No smooth surface fitted # 5 = Quadratic B-spline surface # 6 = Cubic B-spline surface # 8 = Bezier surface 'thickness': DXFAttr(39, default=0, optional=True), 'extrusion': DXFAttr(210, xtype=XType.point3d, default=Vector(0, 0, 1), optional=True), }) @register_entity class Polyline(DXFGraphic): """ DXF POLYLINE entity """ DXFTYPE = 'POLYLINE' DXFATTRIBS = DXFAttributes(base_class, acdb_entity, acdb_polyline) # polyline flags (70) CLOSED = 1 MESH_CLOSED_M_DIRECTION = CLOSED CURVE_FIT_VERTICES_ADDED = 2 SPLINE_FIT_VERTICES_ADDED = 4 POLYLINE_3D = 8 POLYMESH = 16
def new_face_record() -> 'DXFVertex': dxfattribs['flags'] = const.VTX_3D_POLYFACE_MESH_VERTEX # location of face record vertex is always (0, 0, 0) dxfattribs['location'] = Vector() return self._new_compound_entity('VERTEX', dxfattribs)
def test_transform_interface(): curve = Bezier4P(DEFPOINTS3D) new = curve.transform(Matrix44.translate(1, 2, 3)) assert new.control_points[0] == Vector(DEFPOINTS3D[0]) + (1, 2, 3) assert new.control_points[0] != curve.control_points[ 0], 'expected a new object'
from ezdxf.lldxf.attributes import DXFAttr, DXFAttributes, DefSubclass, XType from ezdxf.lldxf.const import DXF12, SUBCLASS_MARKER, VERTEXNAMES from .dxfentity import base_class, SubclassProcessor from .dxfgfx import DXFGraphic, acdb_entity from .factory import register_entity if TYPE_CHECKING: from ezdxf.eztypes import TagWriter, DXFNamespace, UCS __all__ = ['Solid', 'Trace', 'Face3d'] acdb_trace = DefSubclass( 'AcDbTrace', { 'vtx0': DXFAttr(10, xtype=XType.point3d, default=Vector( 0, 0, 0)), # 1. corner Solid WCS; Trace OCS 'vtx1': DXFAttr(11, xtype=XType.point3d, default=Vector( 0, 0, 0)), # 2. corner Solid WCS; Trace OCS 'vtx2': DXFAttr(12, xtype=XType.point3d, default=Vector( 0, 0, 0)), # 3. corner Solid WCS; Trace OCS # If only three corners are entered to define the SOLID, then the fourth corner coordinate is the same as the third. 'vtx3': DXFAttr(13, xtype=XType.point3d, default=Vector( 0, 0, 0)), # 4. corner Solid WCS; Trace OCS 'thickness': DXFAttr(39, default=0, optional=True), # Thickness 'extrusion': DXFAttr( 210, xtype=XType.point3d, default=Vector(
# 0 = Off # <positive value> = On and active. The value indicates the order of # stacking for the viewports, where 1 is the active viewport, 2 is the next, # and so on: 'status': DXFAttr(68, default=0), 'id': DXFAttr(69, default=2), # View center point (in DCS): 'view_center_point': DXFAttr(12, xtype=XType.point2d, default=NULLVEC), 'snap_base_point': DXFAttr(13, xtype=XType.point2d, default=NULLVEC), 'snap_spacing': DXFAttr(14, xtype=XType.point2d, default=Vector(10, 10)), 'grid_spacing': DXFAttr(15, xtype=XType.point2d, default=Vector(10, 10)), # View direction vector (WCS): 'view_direction_vector': DXFAttr(16, xtype=XType.point3d, default=NULLVEC), # View target point (in WCS): 'view_target_point': DXFAttr(17, xtype=XType.point3d, default=NULLVEC), 'perspective_lens_length': DXFAttr(42, default=50), 'front_clip_plane_z_value': DXFAttr(43, default=0), 'back_clip_plane_z_value': DXFAttr(44, default=0), # View height (in model space units):
from .factory import register_entity if TYPE_CHECKING: from ezdxf.eztypes import TagWriter, DXFNamespace, UCS __all__ = ['Helix'] acdb_helix = DefSubclass( 'AcDbHelix', { 'major_release_number': DXFAttr(90, default=29), 'maintenance_release_number': DXFAttr(91, default=63), 'axis_base_point': DXFAttr(10, xtype=XType.point3d, default=Vector(0, 0, 0)), 'start_point': DXFAttr(11, xtype=XType.point3d, default=Vector(1, 0, 0)), 'axis_vector': DXFAttr(12, xtype=XType.point3d, default=Vector(0, 0, 1)), 'radius': DXFAttr(40, default=1), 'turns': DXFAttr(41, default=1), 'turn_height': DXFAttr(42, default=1), # Handedness: 0=left, 1=right 'handedness': DXFAttr(290, default=1),
# Text annotation height 'text_height': DXFAttr(40, default=1, optional=True), # Text annotation width 'text_width': DXFAttr(41, default=1, optional=True), # 76: Number of vertices in leader (ignored for OPEN) # 10, 20, 30: Vertex coordinates (one entry for each vertex) # Color to use if leader's DIMCLRD = BYBLOCK 'block_color': DXFAttr(77, default=7, optional=True), # Hard reference to associated annotation (mtext, tolerance, or insert entity) 'annotation_handle': DXFAttr(340, default='0', optional=True), 'normal_vector': DXFAttr(210, xtype=XType.point3d, default=Vector(0, 0, 1), optional=True), # 'horizontal' direction for leader 'horizontal_direction': DXFAttr(211, xtype=XType.point3d, default=Vector(1, 0, 0), optional=True), # Offset of last leader vertex from block reference insertion point 'leader_offset_block_ref': DXFAttr(212, xtype=XType.point3d, default=Vector(0, 0, 0), optional=True), # Offset of last leader vertex from annotation placement point 'leader_offset_annotation_placement': DXFAttr(213, xtype=XType.point3d, default=Vector(0, 0, 0), optional=True), # Xdata belonging to the application ID "ACAD" follows a leader entity if any dimension overrides # have been applied to this entity. See Dimension Style Overrides. })
def get_measurement(self) -> Union[float, Vector]: """ Returns the actual dimension measurement in :ref:`WCS` units, no scaling applied for linear dimensions. Returns angle in degrees for angular dimension from 2 lines and angular dimension from 3 points. Returns vector from origin to feature location for ordinate dimensions. """ def angle_between(v1: Vector, v2: Vector) -> float: angle = v2.angle_deg - v1.angle_deg return angle + 360 if angle < 0 else angle if self.dimtype in (0, 1): # linear, aligned return linear_measurement( self.dxf.defpoint2, self.dxf.defpoint3, math.radians(self.dxf.get('angle', 0)), self.ocs(), ) elif self.dimtype in (3, 4): # diameter, radius p1 = Vector(self.dxf.defpoint) p2 = Vector(self.dxf.defpoint4) return (p2 - p1).magnitude elif self.dimtype == 2: # angular from 2 lines p1 = Vector(self.dxf.defpoint2) # 1. point of 1. extension line p2 = Vector(self.dxf.defpoint3) # 2. point of 1. extension line p3 = Vector(self.dxf.defpoint4) # 1. point of 2. extension line p4 = Vector(self.dxf.defpoint) # 2. point of 2. extension line dir1 = p2 - p1 # direction of 1. extension line dir2 = p4 - p3 # direction of 2. extension line return angle_between(dir1, dir2) elif self.dimtype == 5: # angular from 2 lines p1 = Vector(self.dxf.defpoint4) # center p2 = Vector(self.dxf.defpoint2) # 1. extension line p3 = Vector(self.dxf.defpoint3) # 2. extension line dir1 = p2 - p1 # direction of 1. extension line dir2 = p3 - p1 # direction of 2. extension line return angle_between(dir1, dir2) elif self.dimtype == 6: # ordinate origin = Vector(self.dxf.defpoint) feature_location = Vector(self.dxf.defpoint2) return feature_location - origin else: logger.debug( f"get_measurement() - unknown DIMENSION type {self.dimtype}.") return 0
from ezdxf.lldxf.attributes import DXFAttr, DXFAttributes, DefSubclass, XType from ezdxf.lldxf.const import SUBCLASS_MARKER, DXF2000 from .dxfentity import base_class, SubclassProcessor from .dxfgfx import DXFGraphic, acdb_entity from .factory import register_entity if TYPE_CHECKING: from ezdxf.eztypes import TagWriter, DXFNamespace, UCS __all__ = ['Ellipse'] acdb_ellipse = DefSubclass( 'AcDbEllipse', { 'center': DXFAttr(10, xtype=XType.point3d, default=Vector(0, 0, 0)), 'major_axis': DXFAttr(11, xtype=XType.point3d, default=Vector( 1, 0, 0)), # relative to the center # extrusion does not establish an OCS, it is just the normal vector of the ellipse plane. 'extrusion': DXFAttr(210, xtype=XType.point3d, default=(0, 0, 1), optional=True), 'ratio': DXFAttr(40, default=1), # has to be in range 1e-6 to 1 'start_param': DXFAttr(41, default=0), # this value is 0.0 for a full ellipse 'end_param': DXFAttr(42, default=math.tau), # this value is 2*pi for a full ellipse }) HALF_PI = math.pi / 2.0
def _transform_path(path: Path, transform: Matrix44) -> Path: vertices = transform.transform_vertices( [Vector(x, y) for x, y in path.vertices]) return Path([(v.x, v.y) for v in vertices], path.codes)
from .dxfgfx import DXFGraphic, acdb_entity from .dxfobj import DXFObject from .objectcollection import ObjectCollection from .factory import register_entity if TYPE_CHECKING: from ezdxf.eztypes import TagWriter, DXFNamespace, Tags, Drawing __all__ = ['ACADTable'] acdb_block_reference = DefSubclass( 'AcDbBlockReference', { 'geometry': DXFAttr(2), # Block name; an anonymous block begins with a *T value 'insert': DXFAttr(10, xtype=XType.point3d, default=Vector( 0, 0, 0)), # Insertion point }) acdb_table = DefSubclass( 'AcDbTable', { 'version': DXFAttr(280), # Table data version number: 0 = 2010 'table_style_id': DXFAttr(342), # Hard pointer ID of the TABLESTYLE object 'block_record': DXFAttr(343), # Hard pointer ID of the owning BLOCK record 'horizontal_direction': DXFAttr(11), # Horizontal direction vector 'table_value': DXFAttr(90), # Flag for table value (unsigned integer) 'n_rows': DXFAttr(91), # Number of rows 'n_cols': DXFAttr(92), # Number of columns 'override_flag': DXFAttr(93), # Flag for an override
from ezdxf.lldxf import const from ezdxf.lldxf.const import DXF12, SUBCLASS_MARKER from .dxfentity import base_class, SubclassProcessor from .dxfgfx import DXFGraphic, acdb_entity from .factory import register_entity if TYPE_CHECKING: from ezdxf.eztypes import TagWriter, Vertex, DXFNamespace __all__ = ['Text', 'acdb_text'] acdb_text = DefSubclass( 'AcDbText', { 'insert': DXFAttr(10, xtype=XType.point3d, default=Vector( 0, 0, 0)), # First alignment point (in OCS) 'height': DXFAttr(40, default=2.5, optional=True), # Text height 'text': DXFAttr(1, default=''), # Default value (the string itself) 'rotation': DXFAttr(50, default=0, optional=True ), # Text rotation (optional) in degrees (circle = 360deg) 'oblique': DXFAttr(51, default=0, optional=True ), # Oblique angle (optional) in degrees, vertical = 0deg 'style': DXFAttr(7, default='Standard', optional=True), # Text style name (optional) 'width': DXFAttr(41, default=1,
def vertices_in_ocs(self) -> Iterable['Vertex']: """ Returns iterable of all polyline points as Vector(x, y, z) in :ref:`OCS`. """ elevation = self.get_dxf_attrib('elevation', default=0.) for x, y in self.vertices(): yield Vector(x, y, elevation)
from typing import TYPE_CHECKING from ezdxf.math import Vector from ezdxf.lldxf.attributes import DXFAttr, DXFAttributes, DefSubclass, XType from ezdxf.lldxf.const import SUBCLASS_MARKER, DXF2000 from .dxfentity import base_class, SubclassProcessor from .dxfgfx import DXFGraphic, acdb_entity from .factory import register_entity if TYPE_CHECKING: from ezdxf.eztypes import TagWriter, DXFNamespace, UCS __all__ = ['Ray', 'XLine'] acdb_xline = DefSubclass( 'AcDbXline', { 'start': DXFAttr(10, xtype=XType.point3d, default=Vector(0, 0, 0)), 'unit_vector': DXFAttr( 11, xtype=XType.point3d, default=Vector(1, 0, 0)), }) @register_entity class XLine(DXFGraphic): """ DXF XLINE entity """ DXFTYPE = 'XLINE' DXFATTRIBS = DXFAttributes(base_class, acdb_entity, acdb_xline) MIN_DXF_VERSION_FOR_EXPORT = DXF2000 XLINE_SUBCLASS = 'AcDbXline' def load_dxf_attribs(self, processor: SubclassProcessor = None
def start(self, location: 'Vertex') -> None: if len(self._commands): raise ValueError('Requires an empty path.') else: self._start = Vector(location)
from .dxfentity import base_class, SubclassProcessor from .dxfgfx import DXFGraphic, acdb_entity from .factory import register_entity if TYPE_CHECKING: from ezdxf.eztypes import TagWriter, DXFNamespace, UCS, Matrix44 __all__ = ['Shape'] acdb_shape = DefSubclass( 'AcDbShape', { 'thickness': DXFAttr(39, default=0, optional=True), # Thickness 'insert': DXFAttr(10, xtype=XType.point3d, default=Vector( 0, 0, 0)), # Insertion point (in WCS) 'size': DXFAttr(40, default=1), 'name': DXFAttr(2, default=''), # Shape name 'rotation': DXFAttr(50, default=0, optional=True), # Rotation angle in degrees 'xscale': DXFAttr(41, default=1, optional=True), # Relative X scale factor 'oblique': DXFAttr(51, default=0, optional=True), # Oblique angle 'extrusion': DXFAttr( 210, xtype=XType.point3d, default=Vector( 0, 0, 1), optional=True), # Extrusion direction })
def wcs(vertex): if ocs and ocs.transform: return ocs.to_wcs((vertex.x, vertex.y, elevation)) else: return Vector(vertex)
def test_vertext_attribs_xyb(): result = vertex_attribs((1, 2, .5), format='xyb') assert result == {'location': Vector(1, 2), 'bulge': 0.5}
def __init__(self, start: 'Vertex' = NULLVEC): self._start = Vector(start) self._commands: List[PathElement] = []
# Flag (bit-coded) to control the following: # 1 = Indicates the PSLTSCALE value for this layout when this layout is current # 2 = Indicates the LIMCHECK value for this layout when this layout is current 'layout_flags': DXFAttr(70, default=1), # Tab order: This number is an ordinal indicating this layout's ordering in # the tab control that is attached to the AutoCAD drawing frame window. # Note that the "Model" tab always appears as the first tab regardless of # its tab order. 'taborder': DXFAttr(71, default=1), # Minimum limits: 'limmin': DXFAttr(10, xtype=XType.point2d, default=Vector(-3.175, -3.175)), # Maximum limits: 'limmax': DXFAttr(11, xtype=XType.point2d, default=Vector(293.857, 206.735)), # Insertion base point for this layout: 'insert_base': DXFAttr(12, xtype=XType.point3d, default=NULLVEC), # Minimum extents for this layout: 'extmin': DXFAttr(14, xtype=XType.point3d, default=Vector(29.068, 20.356, 0)), # Maximum extents for this layout: 'extmax':
from ezdxf.math import Vector from ezdxf.lldxf.attributes import DXFAttr, DXFAttributes, DefSubclass, XType from ezdxf.lldxf.const import DXF12, SUBCLASS_MARKER from .dxfentity import base_class, SubclassProcessor from .dxfgfx import DXFGraphic, acdb_entity from .factory import register_entity if TYPE_CHECKING: from ezdxf.eztypes import TagWriter, DXFNamespace __all__ = ['Circle'] acdb_circle = DefSubclass( 'AcDbCircle', { 'center': DXFAttr(10, xtype=XType.point3d, default=Vector(0, 0, 0)), 'radius': DXFAttr(40, default=1), 'thickness': DXFAttr(39, default=0, optional=True), 'extrusion': DXFAttr(210, xtype=XType.point3d, default=(0, 0, 1), optional=True), }) @register_entity class Circle(DXFGraphic): """ DXF CIRCLE entity """ DXFTYPE = 'CIRCLE' DXFATTRIBS = DXFAttributes(base_class, acdb_entity, acdb_circle)
def line_to(self, location: 'Vertex') -> None: """ Add a line from actual path end point to `location`. """ self._commands.append((Command.LINE_TO, Vector(location)))
def user_text_free(dimstyle, x=0, y=0, leader=False): """ User defined dimension text placing. Args: dimstyle: dimstyle to use x: start point x y: start point y leader: use leader line if True """ override = { 'dimdle': 0., 'dimexe': .5, # length of extension line above dimension line 'dimexo': .5, # extension line offset 'dimtfill': 2, # custom text fill 'dimtfillclr': 4 # cyan } base = (x, y + 2) dim = msp.add_linear_dim(base=base, p1=(x, y), p2=(x + 3, y), dimstyle=dimstyle, override=override) # type: DimStyleOverride location = Vector(x + 3, y + 3, 0) dim.set_location(location, leader=leader) dim.render(ucs=ucs, discard=BRICSCAD) add_text([f'usr absolute={location}', f'leader={leader}'], insert=Vector(x, y)) x += 4 dim = msp.add_linear_dim(base=base, p1=(x, y), p2=(x + 3, y), dimstyle=dimstyle, override=override) # type: DimStyleOverride relative = Vector(-1, +1) # relative to dimline center dim.set_location(relative, leader=leader, relative=True) dim.render(ucs=ucs, discard=BRICSCAD) add_text([f'usr relative={relative}', f'leader={leader}'], insert=Vector(x, y)) x += 4 dim = msp.add_linear_dim(base=base, p1=(x, y), p2=(x + 3, y), dimstyle=dimstyle, override=override) # type: DimStyleOverride dh = -.7 dv = 1.5 dim.shift_text(dh, dv) dim.render(ucs=ucs, discard=BRICSCAD) add_text([ f'shift text=({dh}, {dv})', ], insert=Vector(x, y)) override['dimtix'] = 1 # force text inside x += 4 dim = msp.add_linear_dim(base=base, p1=(x, y), p2=(x + .3, y), dimstyle=dimstyle, override=override) # type: DimStyleOverride dh = 0 dv = 1 dim.shift_text(dh, dv) dim.render(ucs=ucs, discard=BRICSCAD) add_text([ f'shift text=({dh}, {dv})', ], insert=Vector(x, y))