|
1 from math import acos, degrees, radians, pi as π |
|
2 from testsuite import warning, error |
|
3 from geometry import * |
|
4 |
|
5 def sign_consistency(container): |
|
6 # Returns whether all elements in container have the same sign |
|
7 return min(container) * max(container) >= 0 |
|
8 |
|
9 def concave_test(model): |
|
10 for quadrilateral in model.quadrilaterals: |
|
11 geometry = transform_to_xy(quadrilateral.geometry) |
|
12 z_scores = [ |
|
13 cross_product(v2 - v1, v3 - v1).z |
|
14 for v1, v2, v3 in pairs(geometry.vertices, count = 3) |
|
15 ] |
|
16 if not sign_consistency(z_scores): |
|
17 yield error(quadrilateral, 'concave-error') |
|
18 |
|
19 def skew_test(model): |
|
20 ''' Test for non-coplanar quadrilaterals. ''' |
|
21 for quadrilateral in model.quadrilaterals: |
|
22 for triangles in split_quadrilateral(quadrilateral.geometry): |
|
23 plane_1 = triangle_plane_normal(triangles[0]) |
|
24 plane_2 = triangle_plane_normal(triangles[1]) |
|
25 skew_angle = vector_angle(plane_1, plane_2, normalized = True) |
|
26 if skew_angle > radians(0.1): |
|
27 yield error(quadrilateral, 'skew-error', |
|
28 skew_angle = skew_angle, |
|
29 ) |
|
30 break |
|
31 |
|
32 manifest = { |
|
33 'tests': { |
|
34 'skew': skew_test, |
|
35 'concave': concave_test, |
|
36 }, |
|
37 'messages': { |
|
38 'skew-error': lambda skew_angle: |
|
39 str.format('skew quadrilateral (plane angle {}°)', |
|
40 '%.2f' % degrees(skew_angle), |
|
41 ), |
|
42 'concave-error': 'concave quadrilateral', |
|
43 }, |
|
44 } |