Tue, 23 Jan 2018 15:30:48 +0200
added test for collinearity, fixed bowtie test
24 | 1 | from testsuite import warning, error |
2 | from geometry import * | |
3 | from os.path import dirname | |
4 | from pathlib import Path | |
5 | from configparser import ConfigParser | |
6 | ini_path = Path(dirname(__file__)) / 'library-standards.ini' | |
7 | library_standards = ConfigParser() | |
8 | ||
9 | with open(ini_path) as file: | |
10 | library_standards.read_file(file) | |
23 | 11 | |
12 | def determinant_test(model): | |
26
7c263b864371
Added command line option to list all checks.
Santeri Piippo
parents:
24
diff
changeset
|
13 | ''' |
7c263b864371
Added command line option to list all checks.
Santeri Piippo
parents:
24
diff
changeset
|
14 | Checks all subfile references for matrices with rows or columns all |
7c263b864371
Added command line option to list all checks.
Santeri Piippo
parents:
24
diff
changeset
|
15 | zero. |
7c263b864371
Added command line option to list all checks.
Santeri Piippo
parents:
24
diff
changeset
|
16 | ''' |
24 | 17 | yield from ( |
23 | 18 | error(subfile_reference, 'zero-determinant') |
19 | for subfile_reference in model.subfile_references | |
20 | if abs(subfile_reference.matrix.determinant() - 0) < 1e-15 | |
24 | 21 | ) |
22 | ||
23 | def scaling_description(scaling, axes = 'xyz'): | |
24 | ''' | |
25 | Returns a pretty description of a scaling vector. The axes parameter | |
26 | controls what axes are printed and can be used to filter away | |
27 | uninteresting values. | |
28 | ''' | |
29 | return ', '.join( | |
30 | str.format('{} = {}', letter, getattr(scaling, letter)) | |
31 | for letter in axes | |
32 | ) | |
33 | ||
34 | def check_scaling(scaling, axes): | |
35 | ''' Returns whether all given axes on the given scaling vector are 1. ''' | |
36 | return all( | |
37 | abs(getattr(scaling, axis) - 1) < 1e-5 | |
38 | for axis in axes | |
39 | ) | |
40 | ||
41 | # Restriction to checking function mapping. | |
42 | restriction_tests = { | |
43 | 'no scaling': lambda scaling: check_scaling(scaling, 'xyz'), | |
44 | 'y-scaling only': lambda scaling: check_scaling(scaling, 'xz'), | |
45 | 'stud3-like scaling': lambda scaling: all([ | |
46 | check_scaling(scaling, 'xz'), | |
47 | # check if y-scaling is 1 or -1 | |
48 | abs(abs(scaling.y) - 1) < 1e-5, | |
49 | ]), | |
50 | } | |
51 | ||
52 | def scaling_legality_test(model): | |
26
7c263b864371
Added command line option to list all checks.
Santeri Piippo
parents:
24
diff
changeset
|
53 | ''' |
7c263b864371
Added command line option to list all checks.
Santeri Piippo
parents:
24
diff
changeset
|
54 | Checks the part against primitive references with bad scaling. Some |
7c263b864371
Added command line option to list all checks.
Santeri Piippo
parents:
24
diff
changeset
|
55 | primitives (e.g. pegs) are not allowed to be scaled in the |
7c263b864371
Added command line option to list all checks.
Santeri Piippo
parents:
24
diff
changeset
|
56 | X or Z directions. Some (e.g. most studs) are not allowed to be scaled |
7c263b864371
Added command line option to list all checks.
Santeri Piippo
parents:
24
diff
changeset
|
57 | in the Y direction either. |
7c263b864371
Added command line option to list all checks.
Santeri Piippo
parents:
24
diff
changeset
|
58 | ''' |
24 | 59 | from fnmatch import fnmatch |
60 | scaling_restrictions = library_standards['scaling restrictions'] | |
61 | for subfile_reference in model.subfile_references: | |
62 | primitive = subfile_reference.subfile_path.lower() | |
63 | scaling = subfile_reference.matrix.scaling_vector() | |
64 | # Find all restrictions that apply to this subfile reference. | |
65 | restrictions = { | |
66 | restriction | |
67 | for pattern, restriction in scaling_restrictions.items() | |
68 | if fnmatch(primitive, pattern) | |
69 | } | |
70 | # Check restrictions against the subfile. If any restrictions were | |
71 | # found then the scaling vector must pass at least one of them. | |
72 | if restrictions and not any( | |
73 | restriction_tests[restriction](scaling) | |
74 | for restriction in restrictions | |
75 | ): | |
76 | interesting_axes = ''.join( | |
77 | axis | |
78 | for axis in 'xyz' | |
79 | if abs(getattr(scaling, axis) - 1) > 1e-5 | |
80 | ) | |
81 | yield warning(subfile_reference, 'illegal-scaling', | |
82 | primitive = primitive, | |
83 | axes = interesting_axes, | |
84 | scaling = scaling) | |
23 | 85 | |
86 | manifest = { | |
87 | 'tests': { | |
88 | 'determinant': determinant_test, | |
24 | 89 | 'scaling-legality': scaling_legality_test, |
23 | 90 | }, |
91 | 'messages': { | |
92 | 'zero-determinant': 'matrix determinant is zero ' | |
93 | '(row or column all zero)', | |
24 | 94 | 'illegal-scaling': lambda primitive, scaling, axes: |
95 | str.format('scaling of unscalable primitive {} ({})', | |
96 | primitive, | |
97 | scaling_description(scaling, axes), | |
98 | ), | |
23 | 99 | }, |
100 | } |