Beispiel #1
0
 def _convert_entity(self):
     e: 'LWPolyline' = cast('LWPolyline', self.entity)
     if e.has_width:  # use a mesh representation:
         tb = TraceBuilder.from_polyline(e)
         mb = MeshVertexMerger()  # merges coincident vertices
         for face in tb.faces():
             mb.add_face(Vec3.generate(face))
         self._mesh = MeshBuilder.from_builder(mb)
     else:  # use a path representation to support bulges!
         self._path = make_path(e)
Beispiel #2
0
 def filling() -> "Hatch":
     attribs = _dxfattribs(mline)
     attribs["color"] = style.dxf.fill_color
     attribs["elevation"] = Vec3(ocs.from_wcs(bottom_border[0])).replace(
         x=0, y=0)
     attribs["extrusion"] = mline.dxf.extrusion
     hatch = cast("Hatch", factory.new("HATCH", dxfattribs=attribs,
                                       doc=doc))
     bulges: List[float] = [0.0] * (len(bottom_border) * 2)
     points = chain(
         Vec3.generate(ocs.points_from_wcs(bottom_border)),
         Vec3.generate(ocs.points_from_wcs(reversed(top_border))),
     )
     if not closed:
         if style.get_flag_state(style.END_ROUND):
             bulges[len(bottom_border) - 1] = 1.0
         if style.get_flag_state(style.START_ROUND):
             bulges[-1] = 1.0
     lwpoints = ((v.x, v.y, bulge) for v, bulge in zip(points, bulges))
     hatch.paths.add_polyline_path(lwpoints, is_closed=True)
     return hatch
Beispiel #3
0
 def line(self,
          x1: float,
          y1: float,
          x2: float,
          y2: float,
          m: Matrix44 = None) -> None:
     points = [(x1, y1), (x2, y2)]
     if m is not None:
         p1, p2 = m.transform_vertices(points)
     else:
         p1, p2 = Vec3.generate(points)
     self.backend.draw_line(p1, p2, self.properties)
Beispiel #4
0
 def test_to_splines_and_polylines(self, path):
     entities = list(to_splines_and_polylines([path]))
     assert len(entities) == 2
     polyline = entities[0]
     spline = entities[1]
     assert polyline.dxftype() == "POLYLINE"
     assert spline.dxftype() == "SPLINE"
     assert polyline.vertices[0].dxf.location.isclose((0, 0))
     assert polyline.vertices[1].dxf.location.isclose((4, 0))
     assert close_vectors(
         Vec3.generate(spline.control_points),
         [(4, 0, 0), (3, 1, 1), (1, 1, 1), (0, 0, 0)],
     )
Beispiel #5
0
def scale(
    vertices: Iterable["Vertex"], scaling=(1.0, 1.0, 1.0)
) -> Iterable[Vec3]:
    """Scale `vertices` around the origin (0, 0), faster than a Matrix44
    transformation.

    Args:
        vertices: iterable of vertices
        scaling: scale factors as tuple of floats for x-, y- and z-axis

    Returns: yields scaled vertices

    """
    sx, sy, sz = scaling
    for v in Vec3.generate(vertices):
        yield Vec3(v.x * sx, v.y * sy, v.z * sz)
Beispiel #6
0
 def test_to_edge_path_hatches(self, path):
     hatches = list(to_hatches(path, edge_path=True))
     assert len(hatches) == 1
     h0 = hatches[0]
     assert h0.dxftype() == "HATCH"
     assert len(h0.paths) == 1
     edge_path = h0.paths[0]
     assert edge_path.type == BoundaryPathType.EDGE
     line, spline = edge_path.edges
     assert line.type == EdgeType.LINE
     assert line.start == (0, 0)
     assert line.end == (4, 0)
     assert spline.type == EdgeType.SPLINE
     assert close_vectors(
         Vec3.generate(spline.control_points),
         [(4, 0), (3, 1), (1, 1), (0, 0)],
     )
Beispiel #7
0
    def transform(self, m: Matrix44) -> 'Bezier4P':
        """ General transformation interface, returns a new :class:`Bezier4p`
        curve and it is always a 3D curve.

        Args:
             m: 4x4 transformation matrix (:class:`ezdxf.math.Matrix44`)

        .. versionadded:: 0.14

        """
        if len(self._control_points[0]) == 2:
            defpoints = Vec3.generate(self._control_points)
        else:
            defpoints = self._control_points

        defpoints = tuple(m.transform_vertices(defpoints))
        return Bezier4P(defpoints)
 def test_to_edge_path_hatches(self, path):
     hatches = list(to_hatches(path, edge_path=True))
     assert len(hatches) == 1
     h0 = hatches[0]
     assert h0.dxftype() == 'HATCH'
     assert len(h0.paths) == 1
     edge_path = h0.paths[0]
     assert edge_path.PATH_TYPE == 'EdgePath'
     line, spline = edge_path.edges
     assert line.EDGE_TYPE == 'LineEdge'
     assert line.start == (0, 0)
     assert line.end == (4, 0)
     assert spline.EDGE_TYPE == 'SplineEdge'
     assert close_vectors(Vec3.generate(spline.control_points), [(4, 0),
                                                                 (3, 1),
                                                                 (1, 1),
                                                                 (0, 0)])
Beispiel #9
0
    def add_vertices(self, vertices: Iterable['Vertex']) -> Sequence[int]:
        """
        Add new vertices to the mesh, each vertex is a ``(x, y, z)`` tuple or a :class:`~ezdxf.math.Vec3` object,
        returns the indices of the `vertices` added to the :attr:`vertices` list.

        e.g. adding 4 vertices to an empty mesh, returns the indices ``(0, 1, 2, 3)``, adding additional 4 vertices
        returns the indices ``(4, 5, 6, 7)``.

        Args:
            vertices: list of vertices, vertex as ``(x, y, z)`` tuple or :class:`~ezdxf.math.Vec3` objects

        Returns:
            tuple: indices of the `vertices` added to the :attr:`vertices` list

        """
        start_index = len(self.vertices)
        self.vertices.extend(Vec3.generate(vertices))
        return tuple(range(start_index, len(self.vertices)))
Beispiel #10
0
def corner_vertices(
    left: float,
    bottom: float,
    right: float,
    top: float,
    m: Matrix44 = None,
) -> Iterable[Vec3]:
    corners = [  # closed polygon: fist vertex  == last vertex
        (left, top),
        (right, top),
        (right, bottom),
        (left, bottom),
        (left, top),
    ]
    if m is None:
        return Vec3.generate(corners)
    else:
        return m.transform_vertices(corners)
Beispiel #11
0
    def draw_polyline_entity(self, entity: DXFGraphic,
                             properties: Properties) -> None:
        dxftype = entity.dxftype()
        if dxftype == 'POLYLINE':
            e = cast(Polyface, entity)
            if e.is_polygon_mesh or e.is_poly_face_mesh:
                # draw 3D mesh or poly-face entity
                self.draw_mesh_builder_entity(
                    MeshBuilder.from_polyface(e),
                    properties,
                )
                return

        entity = cast(Union[LWPolyline, Polyline], entity)
        is_lwpolyline = dxftype == 'LWPOLYLINE'

        if entity.has_width:  # draw banded 2D polyline
            elevation = 0.0
            ocs = entity.ocs()
            transform = ocs.transform
            if transform:
                if is_lwpolyline:  # stored as float
                    elevation = entity.dxf.elevation
                else:  # stored as vector (0, 0, elevation)
                    elevation = Vec3(entity.dxf.elevation).z

            trace = TraceBuilder.from_polyline(
                entity, segments=self.circle_approximation_count // 2
            )
            for polygon in trace.polygons():  # polygon is a sequence of Vec2()
                if transform:
                    points = ocs.points_to_wcs(
                        Vec3(v.x, v.y, elevation) for v in polygon
                    )
                else:
                    points = Vec3.generate(polygon)
                # Set default SOLID filling for LWPOLYLINE
                properties.filling = Filling()
                self.out.draw_filled_polygon(points, properties)
            return

        path = Path.from_lwpolyline(entity) \
            if is_lwpolyline else Path.from_polyline(entity)
        self.out.draw_path(path, properties)
Beispiel #12
0
    def params_from_vertices(self,
                             vertices: Iterable['Vertex']) -> Iterable[float]:
        """
        Yields ellipse params for all given `vertices`.

        The vertex don't has to be exact on the ellipse curve or in the range from start- to end param or even
        in the ellipse plane. Param is calculated from the intersection point of the ray projected on the ellipse
        plane from the center of the ellipse through the vertex.

        .. warning::

            An input for start- and end vertex at param 0 and 2*pi return unpredictable results because of
            floating point inaccuracy, sometimes 0 and sometimes 2*pi.

        """
        x_axis = self.major_axis.normalize()
        y_axis = self.minor_axis.normalize()
        ratio = self.ratio
        center = self.center
        for v in Vec3.generate(vertices):
            v -= center
            yield math.atan2(y_axis.dot(v) / ratio, x_axis.dot(v)) % math.tau
Beispiel #13
0
 def fit_points(self, points: Iterable["Vertex"]) -> None:
     self._fit_points: Vertices = cast(
         Vertices,
         VertexArray(chain.from_iterable(Vec3.generate(points))),
     )
def test_distance_point_line_3d(points, expected):
    p, a, b = Vec3.generate(points)
    assert distance_point_line_3d(p, a, b) == pytest.approx(expected)
Beispiel #15
0
 def fit_points(self, points: Iterable['Vertex']) -> None:
     self._fit_points = VertexArray(
         chain.from_iterable(Vec3.generate(points)))