def __init__(self, extrusion: "Vertex" = Z_AXIS): Az = Vec3(extrusion).normalize() self.transform = not Az.isclose(Z_AXIS) if self.transform: if (abs(Az.x) < _1_OVER_64) and (abs(Az.y) < _1_OVER_64): Ax = Y_AXIS.cross(Az) else: Ax = Z_AXIS.cross(Az) Ax = Ax.normalize() Ay = Az.cross(Ax).normalize() self.matrix = Matrix44.ucs(Ax, Ay, Az)
def to_polylines2d( paths: Iterable[Path], *, distance: float = MAX_DISTANCE, segments: int = MIN_SEGMENTS, extrusion: "Vertex" = Z_AXIS, dxfattribs=None, ) -> Iterable[Polyline]: """Convert the given `paths` into 2D :class:`~ezdxf.entities.Polyline` entities. The `extrusion` vector is applied to all paths, all vertices are projected onto the plane normal to this extrusion vector. The default extrusion vector is the WCS z-axis. The plane elevation is the distance from the WCS origin to the start point of the first path. Args: paths: iterable of :class:`Path` objects distance: maximum distance, see :meth:`Path.flattening` segments: minimum segment count per Bézier curve extrusion: extrusion vector for all paths dxfattribs: additional DXF attribs Returns: iterable of 2D :class:`~ezdxf.entities.Polyline` objects .. versionadded:: 0.16 """ if isinstance(paths, Path): paths = [paths] else: paths = list(paths) if len(paths) == 0: return [] extrusion = Vec3(extrusion) reference_point = paths[0].start dxfattribs = dict(dxfattribs or {}) if not Z_AXIS.isclose(extrusion): ocs, elevation = _get_ocs(extrusion, reference_point) paths = tools.transform_paths_to_ocs(paths, ocs) dxfattribs["elevation"] = Vec3(0, 0, elevation) dxfattribs["extrusion"] = extrusion elif reference_point.z != 0: dxfattribs["elevation"] = Vec3(0, 0, reference_point.z) for path in tools.single_paths(paths): if len(path) > 0: p = Polyline.new(dxfattribs=dxfattribs) p.append_vertices(path.flattening(distance, segments)) yield p
def to_matplotlib_path(paths: Iterable[Path], extrusion: "Vertex" = Z_AXIS): """Convert the given `paths` into a single :class:`matplotlib.path.Path` object. The `extrusion` vector is applied to all paths, all vertices are projected onto the plane normal to this extrusion vector.The default extrusion vector is the WCS z-axis. The Matplotlib :class:`Path` is a 2D object with :ref:`OCS` coordinates and the z-elevation is lost. (requires Matplotlib) Args: paths: iterable of :class:`Path` objects extrusion: extrusion vector for all paths Returns: matplotlib `Path`_ in OCS! .. versionadded:: 0.16 """ from matplotlib.path import Path as MatplotlibPath if not Z_AXIS.isclose(extrusion): paths = tools.transform_paths_to_ocs(paths, OCS(extrusion)) else: paths = list(paths) if len(paths) == 0: raise ValueError("one or more paths required") def add_command(code: MplCmd, point: Vec3): codes.append(code) vertices.append((point.x, point.y)) vertices: List[Tuple[float, float]] = [] codes: List[MplCmd] = [] for path in paths: add_command(MplCmd.MOVETO, path.start) for cmd in path.commands(): if cmd.type == Command.LINE_TO: add_command(MplCmd.LINETO, cmd.end) elif cmd.type == Command.MOVE_TO: add_command(MplCmd.MOVETO, cmd.end) elif cmd.type == Command.CURVE3_TO: add_command(MplCmd.CURVE3, cmd.ctrl) # type: ignore add_command(MplCmd.CURVE3, cmd.end) elif cmd.type == Command.CURVE4_TO: add_command(MplCmd.CURVE4, cmd.ctrl1) # type: ignore add_command(MplCmd.CURVE4, cmd.ctrl2) # type: ignore add_command(MplCmd.CURVE4, cmd.end) # STOP command is currently not required assert len(vertices) == len(codes) return MatplotlibPath(vertices, codes)
def to_qpainter_path(paths: Iterable[Path], extrusion: "Vertex" = Z_AXIS): """Convert the given `paths` into a :class:`QtGui.QPainterPath` object. The `extrusion` vector is applied to all paths, all vertices are projected onto the plane normal to this extrusion vector. The default extrusion vector is the WCS z-axis. The :class:`QPainterPath` is a 2D object with :ref:`OCS` coordinates and the z-elevation is lost. (requires Qt bindings) Args: paths: iterable of :class:`Path` objects extrusion: extrusion vector for all paths Returns: `QPainterPath`_ in OCS! .. versionadded:: 0.16 """ from ezdxf.addons.xqt import QPainterPath, QPointF if not Z_AXIS.isclose(extrusion): paths = tools.transform_paths_to_ocs(paths, OCS(extrusion)) else: paths = list(paths) if len(paths) == 0: raise ValueError("one or more paths required") def qpnt(v: Vec3): return QPointF(v.x, v.y) qpath = QPainterPath() for path in paths: qpath.moveTo(qpnt(path.start)) for cmd in path.commands(): if cmd.type == Command.LINE_TO: qpath.lineTo(qpnt(cmd.end)) elif cmd.type == Command.MOVE_TO: qpath.moveTo(qpnt(cmd.end)) elif cmd.type == Command.CURVE3_TO: qpath.quadTo(qpnt(cmd.ctrl), qpnt(cmd.end)) # type: ignore elif cmd.type == Command.CURVE4_TO: qpath.cubicTo(qpnt(cmd.ctrl1), qpnt(cmd.ctrl2), qpnt(cmd.end)) # type: ignore return qpath
def _polygon_converter( cls: Type[TPolygon], paths: Iterable[Path], add_boundary: BoundaryFactory, extrusion: "Vertex" = Z_AXIS, dxfattribs=None, ) -> Iterable[TPolygon]: if isinstance(paths, Path): paths = [paths] else: paths = list(paths) if len(paths) == 0: return [] extrusion = Vec3(extrusion) reference_point = paths[0].start _dxfattribs: Dict = dict(dxfattribs or {}) if not Z_AXIS.isclose(extrusion): ocs, elevation = _get_ocs(extrusion, reference_point) paths = tools.transform_paths_to_ocs(paths, ocs) _dxfattribs["elevation"] = Vec3(0, 0, elevation) _dxfattribs["extrusion"] = extrusion elif reference_point.z != 0: _dxfattribs["elevation"] = Vec3(0, 0, reference_point.z) _dxfattribs.setdefault("solid_fill", 1) _dxfattribs.setdefault("pattern_name", "SOLID") _dxfattribs.setdefault("color", const.BYLAYER) for group in group_paths(tools.single_paths(paths)): if len(group) == 0: continue polygon = cls.new(dxfattribs=_dxfattribs) boundaries = polygon.paths external = group[0] external.close() add_boundary(boundaries, external, 1) for hole in group[1:]: hole.close() add_boundary(boundaries, hole, 0) yield polygon