Beispiel #1
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_vector
        radius: radius of basis_vector
        base_center: center point of base circle
        apex: tip of the cone

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

    """
    # 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 = Vec3(base_center)
    end = Vec3(apex)
    slices = int(count)
    ray = end - start
    z_axis = ray.normalize()
    is_y = (fabs(z_axis.y) > 0.5)
    x_axis = Vec3(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) -> Vec3:
        # 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 #2
0
def cone(
    count: int = 16,
    radius: float = 1.0,
    apex: "Vertex" = (0, 0, 1),
    caps=True,
    ngons=True,
) -> MeshTransformer:
    """Create a `cone <https://en.wikipedia.org/wiki/Cone>`_ as
    :class:`~ezdxf.render.MeshTransformer` object, the base center is fixed in
    the origin (0, 0, 0).

    Args:
        count: edge count of basis_vector
        radius: radius of basis_vector
        apex: tip of the cone
        caps: add a bottom face if ``True``
        ngons: use ngons for caps if ``True`` else subdivide caps into triangles

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

    """
    mesh = MeshVertexMerger()
    base_circle = list(circle(count, radius, close=True))
    for p1, p2 in zip(base_circle, base_circle[1:]):
        mesh.add_face([p1, p2, apex])
    if caps:
        base_circle = reversed(  # type: ignore
            base_circle
        )  # for correct outside pointing normals
        if ngons:
            mesh.add_face(base_circle)
        else:
            for face in ngon_to_triangles(base_circle):
                mesh.add_face(face)

    return MeshTransformer.from_builder(mesh)
Beispiel #3
0
def cone(count: int,
         radius: float,
         apex: 'Vertex' = (0, 0, 1),
         caps: bool = True) -> MeshVertexMerger:
    """
    Create a `cone <https://en.wikipedia.org/wiki/Cone>`_ as :class:`~ezdxf.render.MeshVertexMerger` object.

    Args:
        count: edge count of basis
        radius: radius of basis
        apex: apex of the cone
        caps: add a bottom face if true

    """
    mesh = MeshVertexMerger()
    base_circle = list(circle(count, radius, close=True))
    for p1, p2 in zip(base_circle, base_circle[1:]):
        mesh.add_face([p1, p2, apex])
    if caps:
        mesh.add_face(base_circle)
    return mesh
Beispiel #4
0
def cone(count: int,
         radius: float,
         apex: 'Vertex' = (0, 0, 1),
         caps: bool = True) -> MeshVertexMerger:
    """
    Cone as Mesh.

    Args:
        count: edge count of basis
        radius: radius of basis
        apex: apex of the cone
        caps: add a bottom face if true

    Returns: MeshVertexMerger()

    """
    mesh = MeshVertexMerger()
    base_circle = list(circle(count, radius, close=True))
    for p1, p2 in zip(base_circle, base_circle[1:]):
        mesh.add_face([p1, p2, apex])
    if caps:
        mesh.add_face(base_circle)
    return mesh
Beispiel #5
0
def cone(count: int = 16,
         radius: float = 1.0,
         apex: 'Vertex' = (0, 0, 1),
         caps: bool = True) -> MeshTransformer:
    """
    Create a `cone <https://en.wikipedia.org/wiki/Cone>`_ as :class:`~ezdxf.render.MeshTransformer` object, the base
    center is fixed in the origin (0, 0, 0).

    Args:
        count: edge count of basis
        radius: radius of basis
        apex: tip of the cone
        caps: add a bottom face if ``True``

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

    """
    mesh = MeshVertexMerger()
    base_circle = list(circle(count, radius, close=True))
    for p1, p2 in zip(base_circle, base_circle[1:]):
        mesh.add_face([p1, p2, apex])
    if caps:
        mesh.add_face(base_circle)
    return MeshTransformer.from_builder(mesh)
Beispiel #6
0
def sphere(count: int = 16, stacks: int = 8, radius: float = 1, quads=True) -> MeshTransformer:
    """
    Create a `sphere <https://en.wikipedia.org/wiki/Sphere>`_ as :class:`~ezdxf.render.MeshTransformer` object,
    center is fixed at origin (0, 0, 0).

    Args:
        count: longitudinal slices
        stacks: latitude slices
        radius: radius of sphere
        quads: use quads for body faces if ``True`` else triangles

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

    .. versionadded:: 0.11

    """
    radius = float(radius)
    slices = int(count)
    stacks_2 = int(stacks) // 2  # stacks from -stack/2 to +stack/2
    delta_theta = pi * 2.0 / float(slices)
    delta_phi = pi / float(stacks)
    mesh = MeshVertexMerger()

    def radius_of_stack(stack: float) -> float:
        return radius * cos(delta_phi * stack)

    def vertex(slice_: float, r: float, z: float) -> Vector:
        actual_theta = delta_theta * slice_
        return Vector(cos(actual_theta) * r, sin(actual_theta) * r, z)

    def cap_triangles(stack, top=False):
        z = sin(stack * delta_phi) * radius
        cap_vertex = Vector(0, 0, radius) if top else Vector(0, 0, -radius)
        r1 = radius_of_stack(stack)
        for slice_ in range(slices):
            v1 = vertex(slice_, r1, z)
            v2 = vertex(slice_ + 1, r1, z)
            if top:
                mesh.add_face((v1, v2, cap_vertex))
            else:
                mesh.add_face((cap_vertex, v2, v1))

    # bottom triangle faces
    cap_triangles(-stacks_2 + 1, top=False)

    # add body faces
    for actual_stack in range(-stacks_2 + 1, stacks_2 - 1):
        next_stack = actual_stack + 1
        r1 = radius_of_stack(actual_stack)
        r2 = radius_of_stack(next_stack)
        z1 = sin(delta_phi * actual_stack) * radius
        z2 = sin(delta_phi * next_stack) * radius
        for i in range(slices):
            v1 = vertex(i, r1, z1)
            v2 = vertex(i + 1, r1, z1)
            v3 = vertex(i + 1, r2, z2)
            v4 = vertex(i, r2, z2)
            if quads:
                mesh.add_face([v1, v2, v3, v4])
            else:
                center = vertex(
                    i + 0.5,
                    radius_of_stack(actual_stack + 0.5),
                    sin(delta_phi * (actual_stack + 0.5)) * radius,
                )
                mesh.add_face([v1, v2, center])
                mesh.add_face([v2, v3, center])
                mesh.add_face([v3, v4, center])
                mesh.add_face([v4, v1, center])

    # top triangle faces
    cap_triangles(stacks_2 - 1, top=True)

    return MeshTransformer.from_builder(mesh)
Beispiel #7
0
def from_profiles_linear(profiles: Iterable[Iterable['Vertex']], close=True,
                         caps=False, ngons=True) -> MeshTransformer:
    """
    Create MESH entity by linear connected `profiles`.

    Args:
        profiles: list of profiles
        close: close profile polygon if ``True``
        caps: close hull with bottom cap and top cap
        ngons: use ngons for caps if ``True`` else subdivide caps into triangles

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

    """
    mesh = MeshVertexMerger()
    profiles = list(profiles)
    if close:
        profiles = [close_polygon(p) for p in profiles]
    if caps:
        base = reversed(profiles[0])  # for correct outside pointing normals
        top = profiles[-1]
        if ngons:
            mesh.add_face(base)
            mesh.add_face(top)
        else:
            for face in ngon_to_triangles(base):
                mesh.add_face(face)
            for face in ngon_to_triangles(top):
                mesh.add_face(face)

    for profile1, profile2 in zip(profiles, profiles[1:]):
        prev_v1, prev_v2 = None, None
        for v1, v2 in zip(profile1, profile2):
            if prev_v1 is not None:
                mesh.add_face([prev_v1, v1, v2, prev_v2])
            prev_v1 = v1
            prev_v2 = v2

    return MeshTransformer.from_builder(mesh)
def test_vertex_merger_indices():
    merger = MeshVertexMerger()
    indices = merger.add_vertices([(1, 2, 3), (4, 5, 6)])
    indices2 = merger.add_vertices([(1, 2, 3), (4, 5, 6)])
    assert indices == indices2
def test_vertex_merger_vertices():
    merger = MeshVertexMerger()
    merger.add_vertices([(1, 2, 3), (4, 5, 6)])
    merger.add_vertices([(1, 2, 3), (4, 5, 6)])
    assert merger.vertices == [(1, 2, 3), (4, 5, 6)]
def test_from_polyface_182_2(polyface_181_2):
    mesh = MeshVertexMerger.from_polyface(polyface_181_2)
    assert len(mesh.vertices) == 8