Beispiel #1
0
 def minor_axis(self) -> Vector:
     major_axis = Vector(self.dxf.major_axis)  # local x-axis, 0 rad
     extrusion = Vector(
         self.dxf.extrusion
     )  # local z-axis, normal vector of the ellipse plane
     minor_axis_length = major_axis.magnitude * self.dxf.ratio
     return extrusion.cross(major_axis).normalize(minor_axis_length)
Beispiel #2
0
    def vertices(self, params: Iterable[float]) -> Iterable[Vector]:
        """
        Yields vertices on ellipse for iterable `params` in WCS.

        Args:
            params: param values in the range from ``0`` to ``2*pi`` in radians, param goes counter clockwise around the
                    extrusion vector, major_axis = local x-axis = 0 rad.

        .. versionadded:: 0.11

        """
        # get main axis
        major_axis = Vector(self.dxf.major_axis)  # local x-axis, 0 rad
        extrusion = Vector(self.dxf.extrusion)  # local z-axis, normal vector of the ellipse plane
        minor_axis = extrusion.cross(major_axis)  # local y-axis, pi/2 rad, need only normalized direction

        # normal vectors for local x- and y-axis
        x_axis = major_axis.normalize()
        y_axis = minor_axis.normalize()

        # point on ellipse calculation
        radius_x = major_axis.magnitude
        radius_y = radius_x * self.dxf.ratio
        center = Vector(self.dxf.center)
        for param in params:
            # Ellipse params in radians by definition (DXF Reference)
            x = math.cos(param) * radius_x
            y = math.sin(param) * radius_y

            # construct WCS coordinates, do not convert from OCS to WCS, extrusion defines only the normal vector of
            # the ellipse plane.
            yield center + (x_axis * x) + (y_axis * y)
Beispiel #3
0
def test_arbitrary_ucs():
    origin = Vector(3, 3, 3)
    ux = Vector(1, 2, 0)
    def_point_in_xy_plane = Vector(3, 10, 4)
    uz = ux.cross(def_point_in_xy_plane - origin)
    ucs = UCS(origin=origin, ux=ux, uz=uz)
    def_point_in_ucs = ucs.from_wcs(def_point_in_xy_plane)
    assert def_point_in_ucs.z == 0
    assert ucs.to_wcs(def_point_in_ucs) == def_point_in_xy_plane
    assert ucs.is_cartesian is True
Beispiel #4
0
def cone_2p(
    count: int = 16,
    radius: float = 1.0,
    base_center=(0, 0, 0),
    apex=(0, 0, 1)) -> MeshTransformer:
    """
    Create a `cone <https://en.wikipedia.org/wiki/Cone>`_ as :class:`~ezdxf.render.MeshTransformer` object from
    two points, `base_center` is the center of the base circle and `apex` as the tip of the cone.

    Args:
        count: edge count of basis
        radius: radius of basis
        base_center: center point of base circle
        apex: tip of the cone

    Returns: :class:`~ezdxf.render.MeshTransformer`

    .. versionadded:: 0.11

    """
    # Copyright (c) 2011 Evan Wallace (http://madebyevan.com/), under the MIT license.
    # Python port Copyright (c) 2012 Tim Knip (http://www.floorplanner.com), under the MIT license.
    # Additions by Alex Pletzer (Pennsylvania State University)
    # Adaptation for ezdxf, Copyright (c) 2020, Manfred Moitzi, MIT License.
    start = Vector(base_center)
    end = Vector(apex)
    slices = int(count)
    ray = end - start
    z_axis = ray.normalize()
    is_y = (fabs(z_axis.y) > 0.5)
    x_axis = Vector(float(is_y), float(not is_y), 0).cross(z_axis).normalize()
    y_axis = x_axis.cross(z_axis).normalize()
    mesh = MeshVertexMerger()

    def vertex(angle) -> Vector:
        # radial direction pointing out
        out = x_axis * cos(angle) + y_axis * sin(angle)
        return start + out * radius

    dt = pi * 2.0 / slices
    for i in range(0, slices):
        t0 = i * dt
        i1 = (i + 1) % slices
        t1 = i1 * dt
        # coordinates and associated normal pointing outwards of the cone's
        # side
        p0 = vertex(t0)
        p1 = vertex(t1)
        # polygon on the low side (disk sector)
        mesh.add_face([start, p0, p1])
        # polygon extending from the low side to the tip
        mesh.add_face([p0, end, p1])

    return MeshTransformer.from_builder(mesh)
Beispiel #5
0
def cylinder_2p(
        count: int = 16,
        radius: float = 1,
        base_center=(0, 0, 0),
        top_center=(0, 0, 1),
) -> MeshTransformer:
    """
    Create a `cylinder <https://en.wikipedia.org/wiki/Cylinder>`_ as :class:`~ezdxf.render.MeshTransformer` object from
    two points, `base_center` is the center of the base circle and, `top_center` the center of the top circle.

    Args:
        count: profiles edge count
        radius: radius for bottom profile
        base_center: center of base circle
        top_center: center of top circle

    Returns: :class:`~ezdxf.render.MeshTransformer`

    .. versionadded:: 0.11

    """
    # Copyright (c) 2011 Evan Wallace (http://madebyevan.com/), under the MIT license.
    # Python port Copyright (c) 2012 Tim Knip (http://www.floorplanner.com), under the MIT license.
    # Additions by Alex Pletzer (Pennsylvania State University)
    # Adaptation for ezdxf, Copyright (c) 2020, Manfred Moitzi, MIT License.
    start = Vector(base_center)
    end = Vector(top_center)
    radius = float(radius)
    slices = int(count)
    ray = end - start

    z_axis = ray.normalize()
    is_y = (fabs(z_axis.y) > 0.5)
    x_axis = Vector(float(is_y), float(not is_y), 0).cross(z_axis).normalize()
    y_axis = x_axis.cross(z_axis).normalize()
    mesh = MeshVertexMerger()

    def vertex(stack, angle):
        out = (x_axis * cos(angle)) + (y_axis * sin(angle))
        return start + (ray * stack) + (out * radius)

    dt = pi * 2 / float(slices)
    for i in range(0, slices):
        t0 = i * dt
        i1 = (i + 1) % slices
        t1 = i1 * dt
        mesh.add_face([start, vertex(0, t0), vertex(0, t1)])
        mesh.add_face(
            [vertex(0, t1),
             vertex(0, t0),
             vertex(1, t0),
             vertex(1, t1)])
        mesh.add_face([end, vertex(1, t1), vertex(1, t0)])
    return MeshTransformer.from_builder(mesh)
Beispiel #6
0
def test_arbitrary_ucs():
    origin = Vector(3, 3, 3)
    ux = Vector(1, 2, 0)
    def_point_in_xy_plane = Vector(3, 10, 4)
    uz = ux.cross(def_point_in_xy_plane - origin)
    ucs = UCS(origin=origin, ux=ux, uz=uz)
    m = Matrix44.ucs(ucs.ux, ucs.uy, ucs.uz, ucs.origin)
    def_point_in_ucs = ucs.from_wcs(def_point_in_xy_plane)

    assert ucs.ux == m.ux
    assert ucs.uy == m.uy
    assert ucs.uz == m.uz
    assert ucs.origin == m.origin

    assert def_point_in_ucs == m.ucs_vertex_from_wcs(def_point_in_xy_plane)
    assert def_point_in_ucs.z == 0
    assert ucs.to_wcs(def_point_in_ucs) == def_point_in_xy_plane
    assert ucs.is_cartesian is True
Beispiel #7
0
    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