tests/quadrilaterals.py

Thu, 26 Aug 2021 19:37:00 +0300

author
Teemu Piippo <teemu@hecknology.net>
date
Thu, 26 Aug 2021 19:37:00 +0300
changeset 148
8f621aa4cfd7
parent 106
d93ef722bba6
permissions
-rw-r--r--

Update license year

22
9bb00170780b refactor
Santeri Piippo
parents: 20
diff changeset
1 from math import radians
62
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
2 from testsuite import problem_type, report_problem
12
eb74680a5e43 commit work done on test suites...
Santeri Piippo
parents:
diff changeset
3 from geometry import *
eb74680a5e43 commit work done on test suites...
Santeri Piippo
parents:
diff changeset
4
eb74680a5e43 commit work done on test suites...
Santeri Piippo
parents:
diff changeset
5 def sign_consistency(container):
eb74680a5e43 commit work done on test suites...
Santeri Piippo
parents:
diff changeset
6 # Returns whether all elements in container have the same sign
eb74680a5e43 commit work done on test suites...
Santeri Piippo
parents:
diff changeset
7 return min(container) * max(container) >= 0
eb74680a5e43 commit work done on test suites...
Santeri Piippo
parents:
diff changeset
8
64
1c0884f5506e changed severity names to be better understood
Teemu Piippo <teemu@hecknology.net>
parents: 62
diff changeset
9 @problem_type('concave', severity = 'hold', message = 'concave quadrilateral')
12
eb74680a5e43 commit work done on test suites...
Santeri Piippo
parents:
diff changeset
10 def concave_test(model):
26
7c263b864371 Added command line option to list all checks.
Santeri Piippo
parents: 22
diff changeset
11 ''' Checks that all quadrilaterals are convex. '''
13
12d4ddc4bfd8 Got the skew test working
Santeri Piippo
parents: 12
diff changeset
12 for quadrilateral in model.quadrilaterals:
28
5933250813a3 Added bowtie check
Santeri Piippo
parents: 27
diff changeset
13 # Rotate the polygon into the XY plane. Then z is facing
5933250813a3 Added bowtie check
Santeri Piippo
parents: 27
diff changeset
14 # away from the quadrilateral.
14
d383f319f35b transform_to_xy implemented and concave test online
Santeri Piippo
parents: 13
diff changeset
15 geometry = transform_to_xy(quadrilateral.geometry)
28
5933250813a3 Added bowtie check
Santeri Piippo
parents: 27
diff changeset
16 # Now do a 2D concavity test:
5933250813a3 Added bowtie check
Santeri Piippo
parents: 27
diff changeset
17 # https://math.stackexchange.com/a/1745427
12
eb74680a5e43 commit work done on test suites...
Santeri Piippo
parents:
diff changeset
18 z_scores = [
eb74680a5e43 commit work done on test suites...
Santeri Piippo
parents:
diff changeset
19 cross_product(v2 - v1, v3 - v1).z
14
d383f319f35b transform_to_xy implemented and concave test online
Santeri Piippo
parents: 13
diff changeset
20 for v1, v2, v3 in pairs(geometry.vertices, count = 3)
12
eb74680a5e43 commit work done on test suites...
Santeri Piippo
parents:
diff changeset
21 ]
eb74680a5e43 commit work done on test suites...
Santeri Piippo
parents:
diff changeset
22 if not sign_consistency(z_scores):
62
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
23 yield report_problem('concave', bad_object = quadrilateral)
13
12d4ddc4bfd8 Got the skew test working
Santeri Piippo
parents: 12
diff changeset
24
62
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
25 @problem_type('skew-major',
64
1c0884f5506e changed severity names to be better understood
Teemu Piippo <teemu@hecknology.net>
parents: 62
diff changeset
26 severity = 'hold',
62
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
27 message = lambda skew_angle:
103
662de6b8cfc2 replaced the collinear test with a new one based on the hairline test that checks interior angles against official limits of 0.025 and 179.9
Teemu Piippo <teemu@hecknology.net>
parents: 90
diff changeset
28 str.format('skew (non-coplanar) quadrilateral (plane angle {})',
62
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
29 degree_rep(skew_angle),
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
30 ),
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
31 )
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
32 @problem_type('skew-minor',
64
1c0884f5506e changed severity names to be better understood
Teemu Piippo <teemu@hecknology.net>
parents: 62
diff changeset
33 severity = 'warning',
62
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
34 message = lambda skew_angle:
103
662de6b8cfc2 replaced the collinear test with a new one based on the hairline test that checks interior angles against official limits of 0.025 and 179.9
Teemu Piippo <teemu@hecknology.net>
parents: 90
diff changeset
35 str.format('slightly skew (non-coplanar) quadrilateral (plane angle {})',
62
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
36 degree_rep(skew_angle),
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
37 ),
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
38 )
13
12d4ddc4bfd8 Got the skew test working
Santeri Piippo
parents: 12
diff changeset
39 def skew_test(model):
26
7c263b864371 Added command line option to list all checks.
Santeri Piippo
parents: 22
diff changeset
40 ''' Checks that all quadrilaterals are coplanar. '''
13
12d4ddc4bfd8 Got the skew test working
Santeri Piippo
parents: 12
diff changeset
41 for quadrilateral in model.quadrilaterals:
14
d383f319f35b transform_to_xy implemented and concave test online
Santeri Piippo
parents: 13
diff changeset
42 for triangles in split_quadrilateral(quadrilateral.geometry):
d383f319f35b transform_to_xy implemented and concave test online
Santeri Piippo
parents: 13
diff changeset
43 plane_1 = triangle_plane_normal(triangles[0])
d383f319f35b transform_to_xy implemented and concave test online
Santeri Piippo
parents: 13
diff changeset
44 plane_2 = triangle_plane_normal(triangles[1])
16
09cc89622262 Commit work done on test loading
Santeri Piippo
parents: 14
diff changeset
45 skew_angle = vector_angle(plane_1, plane_2, normalized = True)
27
3089611c99d1 Changed threshold skew test, added warning for slightly skew quads
Santeri Piippo
parents: 26
diff changeset
46 if skew_angle > radians(3.0):
62
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
47 yield report_problem(
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
48 'skew-major',
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
49 bad_object = quadrilateral,
16
09cc89622262 Commit work done on test loading
Santeri Piippo
parents: 14
diff changeset
50 skew_angle = skew_angle,
09cc89622262 Commit work done on test loading
Santeri Piippo
parents: 14
diff changeset
51 )
13
12d4ddc4bfd8 Got the skew test working
Santeri Piippo
parents: 12
diff changeset
52 break
27
3089611c99d1 Changed threshold skew test, added warning for slightly skew quads
Santeri Piippo
parents: 26
diff changeset
53 elif skew_angle > radians(1.0):
62
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
54 yield report_problem(
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
55 'skew-minor',
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
56 bad_object = quadrilateral,
27
3089611c99d1 Changed threshold skew test, added warning for slightly skew quads
Santeri Piippo
parents: 26
diff changeset
57 skew_angle = skew_angle,
3089611c99d1 Changed threshold skew test, added warning for slightly skew quads
Santeri Piippo
parents: 26
diff changeset
58 )
3089611c99d1 Changed threshold skew test, added warning for slightly skew quads
Santeri Piippo
parents: 26
diff changeset
59 break
14
d383f319f35b transform_to_xy implemented and concave test online
Santeri Piippo
parents: 13
diff changeset
60
62
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
61 @problem_type('self-intersecting',
64
1c0884f5506e changed severity names to be better understood
Teemu Piippo <teemu@hecknology.net>
parents: 62
diff changeset
62 severity = 'hold',
106
d93ef722bba6 added a reference for bowtie quadrilaterals
Teemu Piippo <teemu@hecknology.net>
parents: 103
diff changeset
63 message = 'bowtie (self-intersecting) quadrilateral',
62
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
64 )
28
5933250813a3 Added bowtie check
Santeri Piippo
parents: 27
diff changeset
65 def bowtie_test(model):
5933250813a3 Added bowtie check
Santeri Piippo
parents: 27
diff changeset
66 for quadrilateral in model.quadrilaterals:
5933250813a3 Added bowtie check
Santeri Piippo
parents: 27
diff changeset
67 geometry = transform_to_xy(quadrilateral.geometry)
5933250813a3 Added bowtie check
Santeri Piippo
parents: 27
diff changeset
68 vertices = IndexRing(geometry.vertices)
5933250813a3 Added bowtie check
Santeri Piippo
parents: 27
diff changeset
69 for i in (0, 1):
5933250813a3 Added bowtie check
Santeri Piippo
parents: 27
diff changeset
70 line_1 = LineSegment(vertices[0 + i], vertices[1 + i])
5933250813a3 Added bowtie check
Santeri Piippo
parents: 27
diff changeset
71 line_2 = LineSegment(vertices[2 + i], vertices[3 + i])
5933250813a3 Added bowtie check
Santeri Piippo
parents: 27
diff changeset
72 intersection = line_segment_intersection_xy(line_1, line_2)
5933250813a3 Added bowtie check
Santeri Piippo
parents: 27
diff changeset
73 if intersection:
62
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
74 yield report_problem(
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
75 'self-intersecting',
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
76 bad_object = quadrilateral,
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
77 )
28
5933250813a3 Added bowtie check
Santeri Piippo
parents: 27
diff changeset
78 break
5933250813a3 Added bowtie check
Santeri Piippo
parents: 27
diff changeset
79
103
662de6b8cfc2 replaced the collinear test with a new one based on the hairline test that checks interior angles against official limits of 0.025 and 179.9
Teemu Piippo <teemu@hecknology.net>
parents: 90
diff changeset
80 @problem_type('collinear',
662de6b8cfc2 replaced the collinear test with a new one based on the hairline test that checks interior angles against official limits of 0.025 and 179.9
Teemu Piippo <teemu@hecknology.net>
parents: 90
diff changeset
81 severity = 'hold',
662de6b8cfc2 replaced the collinear test with a new one based on the hairline test that checks interior angles against official limits of 0.025 and 179.9
Teemu Piippo <teemu@hecknology.net>
parents: 90
diff changeset
82 message = lambda min_angle, max_angle: str.format(
662de6b8cfc2 replaced the collinear test with a new one based on the hairline test that checks interior angles against official limits of 0.025 and 179.9
Teemu Piippo <teemu@hecknology.net>
parents: 90
diff changeset
83 'collinear polygon (smallest interior angle {min_angle}, largest {max_angle})',
662de6b8cfc2 replaced the collinear test with a new one based on the hairline test that checks interior angles against official limits of 0.025 and 179.9
Teemu Piippo <teemu@hecknology.net>
parents: 90
diff changeset
84 min_angle = degree_rep(min_angle),
662de6b8cfc2 replaced the collinear test with a new one based on the hairline test that checks interior angles against official limits of 0.025 and 179.9
Teemu Piippo <teemu@hecknology.net>
parents: 90
diff changeset
85 max_angle = degree_rep(max_angle),
662de6b8cfc2 replaced the collinear test with a new one based on the hairline test that checks interior angles against official limits of 0.025 and 179.9
Teemu Piippo <teemu@hecknology.net>
parents: 90
diff changeset
86 ),
662de6b8cfc2 replaced the collinear test with a new one based on the hairline test that checks interior angles against official limits of 0.025 and 179.9
Teemu Piippo <teemu@hecknology.net>
parents: 90
diff changeset
87 )
30
0d9ca37901ed added test for collinearity, fixed bowtie test
Santeri Piippo
parents: 28
diff changeset
88 def collinear_test(model):
103
662de6b8cfc2 replaced the collinear test with a new one based on the hairline test that checks interior angles against official limits of 0.025 and 179.9
Teemu Piippo <teemu@hecknology.net>
parents: 90
diff changeset
89 from math import radians, cos, acos
662de6b8cfc2 replaced the collinear test with a new one based on the hairline test that checks interior angles against official limits of 0.025 and 179.9
Teemu Piippo <teemu@hecknology.net>
parents: 90
diff changeset
90 # according to the LDraw spec, all interior angles must be
662de6b8cfc2 replaced the collinear test with a new one based on the hairline test that checks interior angles against official limits of 0.025 and 179.9
Teemu Piippo <teemu@hecknology.net>
parents: 90
diff changeset
91 # between 0.025 degrees and 179.9 degrees. Note that between 0 and pi,
662de6b8cfc2 replaced the collinear test with a new one based on the hairline test that checks interior angles against official limits of 0.025 and 179.9
Teemu Piippo <teemu@hecknology.net>
parents: 90
diff changeset
92 # cos(x) is a downwards curve, so the minimum cosine is for the maximum
662de6b8cfc2 replaced the collinear test with a new one based on the hairline test that checks interior angles against official limits of 0.025 and 179.9
Teemu Piippo <teemu@hecknology.net>
parents: 90
diff changeset
93 # angle.
662de6b8cfc2 replaced the collinear test with a new one based on the hairline test that checks interior angles against official limits of 0.025 and 179.9
Teemu Piippo <teemu@hecknology.net>
parents: 90
diff changeset
94 min_cosine = cos(radians(179.9))
662de6b8cfc2 replaced the collinear test with a new one based on the hairline test that checks interior angles against official limits of 0.025 and 179.9
Teemu Piippo <teemu@hecknology.net>
parents: 90
diff changeset
95 max_cosine = cos(radians(0.025))
30
0d9ca37901ed added test for collinearity, fixed bowtie test
Santeri Piippo
parents: 28
diff changeset
96 for element in model.body:
0d9ca37901ed added test for collinearity, fixed bowtie test
Santeri Piippo
parents: 28
diff changeset
97 if hasattr(element, 'geometry') and len(element.geometry.vertices) >= 3:
103
662de6b8cfc2 replaced the collinear test with a new one based on the hairline test that checks interior angles against official limits of 0.025 and 179.9
Teemu Piippo <teemu@hecknology.net>
parents: 90
diff changeset
98 cosines = list(element.geometry.angle_cosines())
662de6b8cfc2 replaced the collinear test with a new one based on the hairline test that checks interior angles against official limits of 0.025 and 179.9
Teemu Piippo <teemu@hecknology.net>
parents: 90
diff changeset
99 if any(
662de6b8cfc2 replaced the collinear test with a new one based on the hairline test that checks interior angles against official limits of 0.025 and 179.9
Teemu Piippo <teemu@hecknology.net>
parents: 90
diff changeset
100 not(min_cosine < cosine < max_cosine)
662de6b8cfc2 replaced the collinear test with a new one based on the hairline test that checks interior angles against official limits of 0.025 and 179.9
Teemu Piippo <teemu@hecknology.net>
parents: 90
diff changeset
101 for cosine in cosines
662de6b8cfc2 replaced the collinear test with a new one based on the hairline test that checks interior angles against official limits of 0.025 and 179.9
Teemu Piippo <teemu@hecknology.net>
parents: 90
diff changeset
102 ):
62
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
103 yield report_problem(
103
662de6b8cfc2 replaced the collinear test with a new one based on the hairline test that checks interior angles against official limits of 0.025 and 179.9
Teemu Piippo <teemu@hecknology.net>
parents: 90
diff changeset
104 'collinear',
62
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
105 bad_object = element,
103
662de6b8cfc2 replaced the collinear test with a new one based on the hairline test that checks interior angles against official limits of 0.025 and 179.9
Teemu Piippo <teemu@hecknology.net>
parents: 90
diff changeset
106 min_angle = min(map(acos, cosines)),
662de6b8cfc2 replaced the collinear test with a new one based on the hairline test that checks interior angles against official limits of 0.025 and 179.9
Teemu Piippo <teemu@hecknology.net>
parents: 90
diff changeset
107 max_angle = max(map(acos, cosines)),
32
75f44d3063da Reworked web front, problems are now sorted by category as well as line number
Santeri Piippo
parents: 30
diff changeset
108 )
75f44d3063da Reworked web front, problems are now sorted by category as well as line number
Santeri Piippo
parents: 30
diff changeset
109
14
d383f319f35b transform_to_xy implemented and concave test online
Santeri Piippo
parents: 13
diff changeset
110 manifest = {
62
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
111 'tests': [
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
112 skew_test,
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
113 concave_test,
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
114 bowtie_test,
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
115 collinear_test,
f0a6bf48b05e Problem reporting revamp, program is now aware of its problem types
Teemu Piippo <teemu@hecknology.net>
parents: 32
diff changeset
116 ],
14
d383f319f35b transform_to_xy implemented and concave test online
Santeri Piippo
parents: 13
diff changeset
117 }

mercurial