1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199
|
# Copyright (c) 2021, Manfred Moitzi
# License: MIT License
import pytest
import ezdxf
from ezdxf.lldxf import const
from ezdxf.math import (
required_fit_points,
required_control_points,
required_knot_values,
uniform_knot_vector,
)
from ezdxf.audit import Auditor, AuditError
@pytest.fixture(scope="module")
def doc():
return ezdxf.new()
@pytest.fixture
def auditor(doc):
return Auditor(doc)
@pytest.fixture
def spline(doc):
msp = doc.modelspace()
return msp.add_spline()
@pytest.mark.parametrize(
"order, expected", [(0, 2), (1, 2), (2, 2), (3, 3), (4, 4), (5, 5)]
)
def test_required_fit_points_without_given_end_tangents(order, expected):
assert required_fit_points(order, tangents=False) == expected
@pytest.mark.parametrize(
"order, expected", [(0, 2), (1, 2), (2, 2), (3, 2), (4, 2), (5, 3)]
)
def test_required_fit_points_with_given_end_tangents(order, expected):
assert required_fit_points(order, tangents=True) == expected
@pytest.mark.parametrize(
"order, expected",
[
(0, 2),
(1, 2),
(2, 2),
(3, 3),
(4, 4),
],
)
def test_required_control_points_calculation(order, expected):
assert required_control_points(order) == expected
def test_any_points_present(auditor, spline):
spline.audit(auditor)
assert len(auditor.fixes) == 1
assert auditor.fixes[0].code == AuditError.INVALID_SPLINE_DEFINITION
# Test if invalid spline will be destroyed:
auditor.empty_trashcan()
assert spline.is_alive is False
def test_degree_of_spline(auditor, spline):
# Attribute validator prevents setting an invalid degree:
with pytest.raises(const.DXFValueError):
spline.dxf.degree = 0
# But could be loaded from DXF file:
# Hack to test entity validator for degree < 1
spline.dxf.__dict__["degree"] = 0
spline.audit(auditor)
assert len(auditor.fixes) == 1
assert auditor.fixes[0].code == AuditError.INVALID_SPLINE_DEFINITION
# Test if invalid spline will be destroyed:
auditor.empty_trashcan()
assert spline.is_alive is False
def add_n_fit_points(s, count: int):
for x in range(count):
s.fit_points.append([x, 0, 0])
class TestFitPoints:
@pytest.mark.parametrize("degree", [1, 2, 3, 4])
def test_if_fit_point_count_is_valid(self, auditor, spline, degree):
order = degree + 1
spline.dxf.degree = degree
add_n_fit_points(spline, required_fit_points(order, tangents=True) - 1)
spline.audit(auditor)
assert len(auditor.fixes) == 1
assert (
auditor.fixes[0].code == AuditError.INVALID_SPLINE_FIT_POINT_COUNT
)
# Test if invalid spline will be destroyed:
auditor.empty_trashcan()
assert spline.is_alive is False
def test_remove_unused_knot_values(self, auditor, spline):
add_n_fit_points(spline, 4)
# Add arbitrary knot values -- have no meaning for splines defined
# by fit points:
spline.knots = [1, 2, 3, 4]
spline.audit(auditor)
assert len(auditor.fixes) == 1
assert (
auditor.fixes[0].code == AuditError.INVALID_SPLINE_KNOT_VALUE_COUNT
)
assert len(spline.knots) == 0
# Spline is usable, test if spline will not be destroyed:
auditor.empty_trashcan()
assert spline.is_alive is True
def test_remove_unused_weights(self, auditor, spline):
add_n_fit_points(spline, 4)
# Add arbitrary weights -- have no meaning for splines defined by fit
# points:
spline.weights = [1, 2, 2, 1]
spline.audit(auditor)
assert len(auditor.fixes) == 1
assert auditor.fixes[0].code == AuditError.INVALID_SPLINE_WEIGHT_COUNT
assert len(spline.weights) == 0
# Spline is usable, test if spline will not be destroyed:
auditor.empty_trashcan()
assert spline.is_alive is True
def add_n_control_points(s, count: int):
for x in range(count):
s.control_points.append([x, 0, 0])
class TestControlPoints:
@pytest.mark.parametrize("degree", [1, 2, 3, 4])
def test_auditing_control_point_count(self, auditor, spline, degree):
order = degree + 1
spline.dxf.degree = degree
add_n_control_points(spline, required_control_points(order) - 1)
spline.audit(auditor)
assert len(auditor.fixes) == 1
assert (
auditor.fixes[0].code
== AuditError.INVALID_SPLINE_CONTROL_POINT_COUNT
)
# Test if invalid spline will be destroyed:
auditor.empty_trashcan()
assert spline.is_alive is False
@pytest.mark.parametrize("degree", [1, 2, 3, 4])
def test_auditing_knot_value_count(self, auditor, spline, degree):
order = degree + 1
spline.dxf.degree = degree
add_n_control_points(spline, required_control_points(order))
spline.knots = [1, 2, 3]
spline.audit(auditor)
assert len(auditor.fixes) == 1
assert (
auditor.fixes[0].code == AuditError.INVALID_SPLINE_KNOT_VALUE_COUNT
)
# Test if invalid spline will be destroyed:
auditor.empty_trashcan()
assert spline.is_alive is False
@pytest.mark.parametrize("degree", [1, 2, 3, 4])
def test_auditing_weight_count(self, auditor, spline, degree):
order = degree + 1
spline.dxf.degree = degree
count = required_control_points(order)
add_n_control_points(spline, count)
spline.knots = uniform_knot_vector(count, order)
spline.weights = range(count - 1)
spline.audit(auditor)
assert len(auditor.fixes) == 1
assert auditor.fixes[0].code == AuditError.INVALID_SPLINE_WEIGHT_COUNT
# Test if invalid spline will be destroyed:
auditor.empty_trashcan()
assert spline.is_alive is False
if __name__ == "__main__":
pytest.main([__file__])
|