Beispiel #1
0
def test_params_from_vertices_random():
    center = Vec3.random(5)
    major_axis = Vec3.random(5)
    extrusion = Vec3.random()
    ratio = 0.75
    e = ConstructionEllipse(center, major_axis, extrusion, ratio)

    params = [random.uniform(0.0001, math.tau - 0.0001) for _ in range(20)]
    vertices = e.vertices(params)
    new_params = e.params_from_vertices(vertices)
    for expected, param in zip(params, new_params):
        assert math.isclose(expected, param)

    # This creates the same vertex as v1 and v2
    v1, v2 = e.vertices([0, math.tau])
    assert v1.isclose(v2)

    # This should create the same param for v1 and v2, but
    # floating point inaccuracy produces unpredictable results:
    p1, p2 = e.params_from_vertices((v1, v2))

    assert math.isclose(p1, 0, abs_tol=1e-9) or math.isclose(
        p1, math.tau, abs_tol=1e-9)
    assert math.isclose(p2, 0, abs_tol=1e-9) or math.isclose(
        p2, math.tau, abs_tol=1e-9)
def test_intersection_ray_ray_3d_random():
    for _ in range(5):
        intersection_point = Vec3.random(5)
        ray1 = (intersection_point, intersection_point + Vec3.random())
        ray2 = (intersection_point, intersection_point - Vec3.random())

        result = intersection_ray_ray_3d(ray1, ray2)
        assert len(result) == 1
        assert result[0].isclose(intersection_point)
Beispiel #3
0
 def build():
     circle = Circle()
     vertices = list(circle.vertices(linspace(0, 360, vertex_count, endpoint=False)))
     m = Matrix44.chain(
         Matrix44.axis_rotate(axis=Vec3.random(), angle=random.uniform(0, math.tau)),
         Matrix44.translate(dx=random.uniform(-2, 2), dy=random.uniform(-2, 2), dz=random.uniform(-2, 2)),
     )
     return synced_transformation(circle, vertices, m)
Beispiel #4
0
def test_split_strategies(strategy):
    points = [Vec3.random(100) for _ in range(100)]
    nodes = strategy(points, 5)
    assert len(nodes) == 5
    for node in nodes:
        assert len(node) == 20
        assert isinstance(node, rtree.InnerNode) is True
        assert len(node.children) == 5
Beispiel #5
0
def test_circle_fast_translation():
    circle = Circle.new(dxfattribs={
        "center": (2, 3, 4),
        "extrusion": Vec3.random()
    })
    ocs = circle.ocs()
    offset = Vec3(1, 2, 3)
    center = ocs.to_wcs(circle.dxf.center) + offset
    circle.translate(*offset)
    assert ocs.to_wcs(circle.dxf.center).isclose(center, abs_tol=1e-9)
Beispiel #6
0
 def build():
     arc = Arc.new(dxfattribs={
         'start_angle': random.uniform(0, 360),
         'end_angle': random.uniform(0, 360),
     })
     vertices = list(arc.vertices(arc.angles(vertex_count)))
     m = Matrix44.chain(
         Matrix44.axis_rotate(axis=Vec3.random(), angle=random.uniform(0, math.tau)),
         Matrix44.translate(dx=random.uniform(-2, 2), dy=random.uniform(-2, 2), dz=random.uniform(-2, 2)),
     )
     return synced_transformation(arc, vertices, m)
Beispiel #7
0
 def build():
     ellipse = Ellipse.new(dxfattribs={
         'start_param': start,
         'end_param': end,
     })
     vertices = list(ellipse.vertices(ellipse.params(vertex_count)))
     m = Matrix44.chain(
         Matrix44.axis_rotate(axis=Vec3.random(), angle=random.uniform(0, math.tau)),
         Matrix44.translate(dx=random.uniform(-2, 2), dy=random.uniform(-2, 2), dz=random.uniform(-2, 2)),
     )
     return synced_transformation(ellipse, vertices, m)
def main_ellipse(layout):
    entity, vertices, axis_vertices = ellipse(start=math.pi / 2,
                                              end=-math.pi / 2)
    axis = Vec3.random()
    angle = random_angle()
    entity, vertices, axis_vertices = synced_rotation(entity,
                                                      vertices,
                                                      axis_vertices,
                                                      axis=axis,
                                                      angle=angle)
    entity, vertices, axis_vertices = synced_translation(
        entity,
        vertices,
        axis_vertices,
        dx=random.uniform(-2, 2),
        dy=random.uniform(-2, 2),
        dz=random.uniform(-2, 2),
    )

    for sx, sy, sz in UNIFORM_SCALING + NON_UNIFORM_SCALING:
        entity0, vertices0, axis0 = synced_scaling(entity, vertices,
                                                   axis_vertices, sx, sy, sz)
        add(layout, entity0, vertices0, layer=f"new ellipse")
        layout.add_line(
            axis0[0],
            axis0[2],
            dxfattribs={
                "color": 6,
                "linetype": "DASHED",
                "layer": "old axis"
            },
        )
        layout.add_line(
            axis0[1],
            axis0[3],
            dxfattribs={
                "color": 6,
                "linetype": "DASHED",
                "layer": "old axis"
            },
        )
        p = list(entity0.vertices([0, math.pi / 2, math.pi, math.pi * 1.5]))
        layout.add_line(p[0],
                        p[2],
                        dxfattribs={
                            "color": 1,
                            "layer": "new axis"
                        })
        layout.add_line(p[1],
                        p[3],
                        dxfattribs={
                            "color": 3,
                            "layer": "new axis"
                        })
def main_insert(layout):
    entity, vertices = insert()
    entity, vertices = synced_translation(entity, vertices, dx=1, dy=0, dz=0)
    axis = Vec3.random()
    angle = random_angle()

    for sx, sy, sz in NON_UNIFORM_SCALING:
        # 1. scale
        entity0, vertices0 = synced_scaling(entity,
                                            vertices,
                                            sx=sx,
                                            sy=sy,
                                            sz=sz)
        # 2. rotate
        entity0, vertices0 = synced_rotation(entity0,
                                             vertices0,
                                             axis=axis,
                                             angle=angle)
        # 3. translate
        entity0, vertices0 = synced_translation(
            entity0,
            vertices0,
            dx=random.uniform(-2, 2),
            dy=random.uniform(-2, 2),
            dz=random.uniform(-2, 2),
        )
        layout.entitydb.add(entity0)
        layout.add_entity(entity0)
        origin, x, y, z = list(vertices0)
        layout.add_line(origin,
                        x,
                        dxfattribs={
                            "color": 2,
                            "layer": "new axis"
                        })
        layout.add_line(origin,
                        y,
                        dxfattribs={
                            "color": 4,
                            "layer": "new axis"
                        })
        layout.add_line(origin,
                        z,
                        dxfattribs={
                            "color": 6,
                            "layer": "new axis"
                        })

        for line in entity0.virtual_entities():
            line.dxf.layer = "exploded axis"
            line.dxf.color = 7
            layout.entitydb.add(line)
            layout.add_entity(line)
Beispiel #10
0
def test_transformation():
    axis = Vec3.random()
    angle = 1.5
    ucs = UCS(origin=(3, 4, 5))
    m = Matrix44.axis_rotate(axis, angle)
    expected_origin = m.transform(ucs.origin)
    expected_ux = m.transform(ucs.ux)
    expected_uy = m.transform(ucs.uy)
    expected_uz = m.transform(ucs.uz)
    new = ucs.transform(m)

    assert new.origin.isclose(expected_origin)
    assert new.ux.isclose(expected_ux)
    assert new.uy.isclose(expected_uy)
    assert new.uz.isclose(expected_uz)
Beispiel #11
0
def test_random_block_reference_transformation(sx, sy, sz, doc1: "Drawing"):
    def insert():
        return (
            Insert.new(
                dxfattribs={
                    "name": "AXIS",
                    "insert": (0, 0, 0),
                    "xscale": 1,
                    "yscale": 1,
                    "zscale": 1,
                    "rotation": 0,
                    "layer": "insert",
                },
                doc=doc1,
            ),
            [Vec3(0, 0, 0), X_AXIS, Y_AXIS, Z_AXIS],
        )

    def check(lines, chk):
        origin, x, y, z = chk
        l1, l2, l3 = lines
        assert origin.isclose(l1.dxf.start)
        assert x.isclose(l1.dxf.end)
        assert origin.isclose(l2.dxf.start)
        assert y.isclose(l2.dxf.end)
        assert origin.isclose(l3.dxf.start)
        assert z.isclose(l3.dxf.end)

    entity0, vertices0 = insert()
    entity0, vertices0 = synced_scaling(entity0, vertices0, 1, 2, 3)

    m = Matrix44.chain(
        # Transformation order is important: scale - rotate - translate
        # Because scaling after rotation leads to a non orthogonal
        # coordinate system, which can not represented by the
        # INSERT entity.
        Matrix44.scale(sx, sy, sz),
        Matrix44.axis_rotate(axis=Vec3.random(),
                             angle=random.uniform(0, math.tau)),
        Matrix44.translate(
            dx=random.uniform(-2, 2),
            dy=random.uniform(-2, 2),
            dz=random.uniform(-2, 2),
        ),
    )
    entity, vertices = synced_transformation(entity0, vertices0, m)
    lines = list(entity.virtual_entities())
    check(lines, vertices)
Beispiel #12
0
def test_random_ellipse_transformations(sx, sy, sz, start, end):
    vertex_count = 8

    for angle in linspace(0, math.tau, 19):
        for dx, dy, dz in product([2, 0, -2], repeat=3):
            axis = Vec3.random()  # TODO: fixed rotation axis

            config = f"CONFIG sx={sx}, sy={sy}, sz={sz}; " \
                     f"start={start:.4f}, end={end:.4f}; angle={angle};" \
                     f"dx={dx}, dy={dy}, dz={dz}; axis={str(axis)}"
            ellipse0, vertices0 = build(angle, dx, dy, dz, axis, start, end,
                                        vertex_count)
            assert check(ellipse0, vertices0, vertex_count) is True, config
            ellipse1, vertices1 = synced_scaling(ellipse0, vertices0, sx, sy,
                                                 sz)
            assert check(ellipse1, vertices1, vertex_count) is True, config
Beispiel #13
0
def test_random_ellipse_transformations(sx, sy, sz, start, end):
    vertex_count = 8

    def build(angle, dx, dy, dz, axis):
        ellipse = Ellipse.new(dxfattribs={
            "start_param": start,
            "end_param": end,
        })
        vertices = list(ellipse.vertices(ellipse.params(vertex_count)))
        m = Matrix44.chain(
            Matrix44.axis_rotate(axis=axis, angle=angle),
            Matrix44.translate(dx=dx, dy=dy, dz=dz),
        )
        return synced_transformation(ellipse, vertices, m)

    def check(ellipse, vertices):
        ellipse_vertices = list(ellipse.vertices(ellipse.params(vertex_count)))
        # Ellipse vertices may appear in reverse order
        if not vertices[0].isclose(ellipse_vertices[0], abs_tol=1e-5):
            ellipse_vertices.reverse()

        for vtx, chk in zip(ellipse_vertices, vertices):
            assert vtx.isclose(chk, abs_tol=1e-5) is True, config

    for _ in range(10):
        angle = random.uniform(0, math.tau)
        dx = random.uniform(-2, 2)
        dy = random.uniform(-2, 2)
        dz = random.uniform(-2, 2)
        axis = Vec3.random()

        config = (
            f"CONFIG sx={sx}, sy={sy}, sz={sz}; "
            f"start={start:.4f}, end={end:.4f}; "
            f"angle={angle}; dx={dx}, dy={dy}, dz={dz}; axis={str(axis)}")

        ellipse0, vertices0 = build(angle, dx, dy, dz, axis)
        check(ellipse0, vertices0)
        check(*synced_scaling(ellipse0, vertices0, sx, sy, sz))
Beispiel #14
0
 def test_contains_all_random_points(self):
     points = [Vec3.random(50) for _ in range(100)]
     tree = RTree(points, 5)
     for point in points:
         assert tree.contains(point) is True
Beispiel #15
0
def test_avg_nn_distance_of_random_points():
    tree = RTree([Vec3.random(100) for _ in range(100)])
    nn_dist = tree.avg_nn_distance()
    assert nn_dist > 10.0
Beispiel #16
0
def test_avg_spherical_envelope_radius_of_random_points():
    tree = RTree([Vec3.random(100) for _ in range(100)])
    radius = tree.avg_spherical_envelope_radius()
    assert radius > 10.0
Beispiel #17
0
def test_average_leaf_size_of_random_points():
    tree = RTree([Vec3.random(100) for _ in range(100)])
    size = tree.avg_leaf_size()
    assert size > 10.0
Beispiel #18
0
def test_collect_leafs():
    tree = RTree([Vec3.random(100) for _ in range(100)])
    assert sum(len(leaf) for leaf in rtree.collect_leafs(tree._root)) == 100
Beispiel #19
0
def random_points(n, size=1.0):
    return [Vec3.random() * size for _ in range(n)]
Beispiel #20
0
#  Copyright (c) 2022, Manfred Moitzi
#  License: MIT License

import pytest
from ezdxf.math import Vec3, k_means, average_cluster_radius, average_intra_cluster_distance

POINTS = [Vec3.random(100) for _ in range(100)]


@pytest.mark.parametrize("k", [4, 5, 6])
def test_cluster_random_points(k):
    clusters = k_means(POINTS, k, max_iter=5)
    assert len(clusters) == k
    assert sum(map(len, clusters)) == 100


def test_measure_average_cluster_radius():
    clusters = k_means(POINTS, 5, max_iter=5)
    assert average_cluster_radius(clusters) > 10.0


def test_measure_average_intra_cluster_distance():
    clusters = k_means(POINTS, 5, max_iter=5)
    assert average_intra_cluster_distance(clusters) > 10.0


if __name__ == "__main__":
    pytest.main([__file__])