def has_matrix_3d_stretching(m: Matrix44) -> bool: """Returns ``True`` if matrix `m` performs a non-uniform xyz-scaling. Uniform scaling is not stretching in this context. Does not check if the target system is a cartesian coordinate system, use the :class:`~ezdxf.math.Matrix44` property :attr:`~ezdxf.math.Matrix44.is_cartesian` for that. """ ux_mag_sqr = m.transform_direction(X_AXIS).magnitude_square uy = m.transform_direction(Y_AXIS) uz = m.transform_direction(Z_AXIS) return not math.isclose( ux_mag_sqr, uy.magnitude_square ) or not math.isclose(ux_mag_sqr, uz.magnitude_square)
def transform(self, m: Matrix44) -> 'XLine': """ Transform the XLINE/RAY entity by transformation matrix `m` inplace. """ self.dxf.start = m.transform(self.dxf.start) self.dxf.unit_vector = m.transform_direction( self.dxf.unit_vector).normalize() return self
def draw_text( self, text: str, transform: Matrix44, properties: Properties, cap_height: float, ): if not text.strip(): return # no point rendering empty strings font_properties = self.get_font_properties(properties.font) assert self.current_entity is not None text = prepare_string_for_rendering(text, self.current_entity.dxftype()) x, y, _, _ = transform.get_row(3) rotation = transform.transform_direction(X_AXIS).angle_deg self.ax.text( x, y, text.replace("$", "\\$"), color=properties.color, size=cap_height * self._text_size_scale, rotation=rotation, in_layout=True, fontproperties=font_properties, transform_rotates_text=True, zorder=self._get_z(), )
def transform(self, m: Matrix44) -> 'MText': """ Transform the MTEXT entity by transformation matrix `m` inplace. """ dxf = self.dxf old_extrusion = Vec3(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(Vec3.from_deg_angle(dxf.rotation)) dxf.discard('rotation') old_text_direction = Vec3(dxf.text_direction) new_text_direction = m.transform_direction(old_text_direction) old_vertical_direction = old_extrusion.cross(old_text_direction) old_char_height_vec = old_vertical_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 if self.has_columns: hscale = m.transform_direction( old_text_direction.normalize()).magnitude vscale = m.transform_direction( old_vertical_direction.normalize()).magnitude self._columns.transform(m, hscale, vscale) return self
def transform_xdata_tags(tags: Tags, m: Matrix44) -> Iterator[DXFTag]: for tag in tags: code, value = tag if code == 1011: # move, scale, rotate and mirror yield dxftag(code, m.transform(Vec3(value))) elif code == 1012: # scale, rotate and mirror yield dxftag(code, m.transform_direction(Vec3(value))) elif code == 1013: # rotate and mirror vec = Vec3(value) length = vec.magnitude if length > 1e-12: vec = m.transform_direction(vec).normalize(length) yield dxftag(code, vec) else: yield tag elif code == 1041 or code == 1042: # scale distance and factor, works only for uniform scaling vec = m.transform_direction(Vec3(value, 0, 0)) yield dxftag(code, vec.magnitude) else: yield tag