def transform(self, m: Matrix44) -> 'Text': """ Transform TEXT entity by transformation matrix `m` inplace. .. versionadded:: 0.13 """ dxf = self.dxf if not dxf.hasattr('align_point'): dxf.align_point = dxf.insert ocs = OCSTransform(self.dxf.extrusion, m) dxf.insert = ocs.transform_vertex(dxf.insert) dxf.align_point = ocs.transform_vertex(dxf.align_point) old_rotation = dxf.rotation new_rotation = ocs.transform_deg_angle(old_rotation) x_scale = ocs.transform_length(Vector.from_deg_angle(old_rotation)) y_scale = ocs.transform_length( Vector.from_deg_angle(old_rotation + 90.0)) if not ocs.scale_uniform: oblique_vec = Vector.from_deg_angle( old_rotation + 90.0 - dxf.oblique) new_oblique_deg = new_rotation + 90.0 - ocs.transform_direction( oblique_vec).angle_deg dxf.oblique = new_oblique_deg y_scale *= math.cos(math.radians(new_oblique_deg)) dxf.width *= x_scale / y_scale dxf.height *= y_scale dxf.rotation = new_rotation if dxf.hasattr('thickness'): # can be negative dxf.thickness = ocs.transform_length((0, 0, dxf.thickness), reflection=dxf.thickness) dxf.extrusion = ocs.new_extrusion return self
def add_dim(x, y, radius, dimtad): center = Vector(x, y) msp.add_circle((x, y), radius=3) dim_location = center + Vector.from_deg_angle(angle, radius) dim = msp.add_radius_dim(center=(x, y), radius=3, location=dim_location, dimstyle='EZ_RADIUS', override={ 'dimtad': dimtad, }) dim.render(discard=BRICSCAD)
def add_dim(x, y, radius, dimtad): center = Vector(x, y) msp.add_circle((x, y), radius=3) dim_location = center + Vector.from_deg_angle(angle, radius) dim = msp.add_diameter_dim(center=(x, y), radius=3, location=dim_location, dimstyle='EZ_RADIUS', override={ 'dimtad': dimtad, 'dimtih': 1, # force text inside horizontal }) dim.render(discard=BRICSCAD)
def vertices(self, angles: Iterable[float]) -> Iterable[Vector]: """ Yields vertices of the circle for iterable `angles` in WCS. Args: angles: iterable of angles in OCS as degrees, angle goes counter clockwise around the extrusion vector, ocs x-axis = 0 deg. """ ocs = self.ocs() for angle in angles: v = Vector.from_deg_angle(angle, self.dxf.radius) + self.dxf.center yield ocs.to_wcs(v)
def add_dim_user(msp, x, y, distance, override): center = Vector(x, y) msp.add_circle(center, radius=RADIUS) location = center + Vector.from_deg_angle(45, distance) add_mark(msp, location) dim = msp.add_radius_dim( center=center, radius=RADIUS, location=location, dimstyle='EZ_RADIUS', override=override) dim.render()
def transform_to_wcs(self, ucs: 'UCS') -> None: """ Transform MTEXT entity from local :class:`~ezdxf.math.UCS` coordinates to :ref:`WCS` coordinates. .. versionadded:: 0.11 """ if self.dxf.hasattr('rotation'): self.dxf.text_direction = Vector.from_deg_angle(self.dxf.rotation) self.dxf.discard('rotation') self.dxf.insert = ucs.to_wcs(self.dxf.insert) self.dxf.text_direction = ucs.direction_to_wcs(self.dxf.text_direction) self.dxf.extrusion = ucs.direction_to_wcs(self.dxf.extrusion)
def vertices(self, angles: Iterable[float]) -> Iterable[Vector]: """ Yields vertices of the circle for iterable `angles` in WCS. This method takes into account a local OCS. Args: angles: iterable of angles in OCS as degrees, angle goes counter clockwise around the extrusion vector, ocs x-axis = 0 deg. .. versionadded:: 0.11 """ ocs = self.ocs() for angle in angles: v = Vector.from_deg_angle(angle, self.dxf.radius) + self.dxf.center # convert from OCS to WCS yield ocs.to_wcs(v)
def transform(self, m: Matrix44) -> 'MText': """ Transform MTEXT entity by transformation matrix `m` inplace. .. versionadded:: 0.13 """ dxf = self.dxf old_extrusion = Vector(dxf.extrusion) new_extrusion, _ = transform_extrusion(old_extrusion, m) if dxf.hasattr('rotation') and not dxf.hasattr('text_direction'): # MTEXT is not an OCS entity, but I don't know how else to convert # a rotation angle for an entity just defined by an extrusion vector. # It's correct for the most common case: extrusion=(0, 0, 1) ocs = OCS(old_extrusion) dxf.text_direction = ocs.to_wcs(Vector.from_deg_angle( dxf.rotation)) dxf.discard('rotation') old_text_direction = Vector(dxf.text_direction) new_text_direction = m.transform_direction(old_text_direction) old_char_height_vec = old_extrusion.cross( old_text_direction).normalize(dxf.char_height) new_char_height_vec = m.transform_direction(old_char_height_vec) oblique = new_text_direction.angle_between(new_char_height_vec) dxf.char_height = new_char_height_vec.magnitude * math.sin(oblique) if dxf.hasattr('width'): width_vec = old_text_direction.normalize(dxf.width) dxf.width = m.transform_direction(width_vec).magnitude dxf.insert = m.transform(dxf.insert) dxf.text_direction = new_text_direction dxf.extrusion = new_extrusion return self
# License: MIT License # include-start import ezdxf from ezdxf.math import UCS, Vector doc = ezdxf.new('R2010') msp = doc.modelspace() # thickness for text works only with shx fonts not with true type fonts doc.styles.new('TXT', dxfattribs={'font': 'romans.shx'}) ucs = UCS(origin=(0, 2, 2), ux=(1, 0, 0), uz=(0, 1, 1)) # calculation of text direction as angle in OCS: # convert text rotation in degree into a vector in UCS text_direction = Vector.from_deg_angle(-45) # transform vector into OCS and get angle of vector in xy-plane rotation = ucs.to_ocs(text_direction).angle_deg text = msp.add_text( text="TEXT", dxfattribs={ # text rotation angle in degrees in OCS 'rotation': rotation, 'extrusion': ucs.uz, 'thickness': .333, 'color': 2, 'style': 'TXT', }) # set text position in OCS text.set_pos(ucs.to_ocs((0, 0, 0)), align='MIDDLE_CENTER')
dwg = ezdxf.new('R2010') msp = dwg.modelspace() # include-start ucs = UCS(origin=(0, 2, 2), ux=(1, 0, 0), uz=(0, 1, 1)) msp.add_arc( center=ucs.to_ocs((0, 0)), radius=1, start_angle=ucs.to_ocs_angle_deg(45), # shortcut end_angle=ucs.to_ocs_angle_deg(270), # shortcut dxfattribs={ 'extrusion': ucs.uz, 'color': 2, }) center = ucs.to_wcs((0, 0)) msp.add_line( start=center, end=ucs.to_wcs(Vector.from_deg_angle(45)), dxfattribs={'color': 2}, ) msp.add_line( start=center, end=ucs.to_wcs(Vector.from_deg_angle(270)), dxfattribs={'color': 2}, ) # include-end ucs.render_axis(msp) dwg.saveas('ocs_arc.dxf')
START_ANGLE = 45 END_ANGLE = 270 msp.add_arc( center=CENTER, radius=1, start_angle=START_ANGLE, end_angle=END_ANGLE, dxfattribs={ 'color': 6 }, ).transform(ucs.matrix) msp.add_line( start=CENTER, end=Vector.from_deg_angle(START_ANGLE), dxfattribs={ 'color': 6 }, ).transform(ucs.matrix) msp.add_line( start=CENTER, end=Vector.from_deg_angle(END_ANGLE), dxfattribs={ 'color': 6 }, ).transform(ucs.matrix) ucs.render_axis(msp) doc.saveas(OUT_DIR / 'ucs_arc.dxf')
OUT_DIR = Path('~/Desktop/Outbox').expanduser() doc = ezdxf.new('R2010') msp = doc.modelspace() # The center of the pentagon should be (0, 2, 2), and the shape is # rotated around x-axis about 45 degree, to accomplish this I use an # UCS with z-axis (0, 1, 1) and an x-axis parallel to WCS x-axis. ucs = UCS( origin=(0, 2, 2), # center of pentagon ux=(1, 0, 0), # x-axis parallel to WCS x-axis uz=(0, 1, 1), # z-axis ) # calculating corner points in local (UCS) coordinates points = [Vector.from_deg_angle((360 / 5) * n) for n in range(5)] # converting UCS into OCS coordinates ocs_points = list(ucs.points_to_ocs(points)) # LWPOLYLINE accepts only 2D points and has an separated DXF attribute elevation. # All points have the same z-axis (elevation) in OCS! elevation = ocs_points[0].z msp.add_lwpolyline( points=ocs_points, format='xy', # ignore z-axis dxfattribs={ 'elevation': elevation, 'extrusion': ucs.uz, 'closed': True, 'color': 1,
# Second spline defined only by fit points as reference, does not match the BricsCAD interpolation. spline = msp.add_spline(points, degree=3, dxfattribs={ 'layer': 'BricsCAD B-spline', 'color': 2 }) doc.saveas(DIR / 'fit-points-only.dxf') # 2. Store fit points, start- and end tangent values in DXF file: doc, msp = setup() # Tangent estimation method: "Total Chord Length", # returns sum of chords for m1 and m2 m1, m2 = estimate_end_tangent_magnitude(points, method='chord') # Multiply tangent vectors by total chord length for global interpolation: start_tangent = Vector.from_deg_angle(100) * m1 end_tangent = Vector.from_deg_angle(-100) * m2 # Interpolate control vertices from fit points and end derivatives as constraints s = global_bspline_interpolation(points, degree=3, tangents=(start_tangent, end_tangent)) msp.add_spline(dxfattribs={ 'color': 4, 'layer': 'Global Interpolation' }).apply_construction_tool(s) # Result matches the BricsCAD interpolation if fit points, start- and end # tangents are stored explicit in the DXF file. spline = msp.add_spline(points, degree=3, dxfattribs={ 'layer': 'BricsCAD B-spline',