Wed, 29 May 2019 16:36:23 +0300
fixed the formatting of the license
from testsuite import warning, error from geometry import * from os.path import dirname from pathlib import Path from configparser import ConfigParser ini_path = Path(dirname(__file__)) / 'library-standards.ini' library_standards = ConfigParser() with ini_path.open() as file: library_standards.read_file(file) def determinant_test(model): ''' Checks all subfile references for matrices with rows or columns all zero. ''' yield from ( error(subfile_reference, 'zero-determinant') for subfile_reference in model.subfile_references if abs(subfile_reference.matrix.determinant() - 0) < 1e-15 ) def scaling_description(scaling, axes = 'xyz'): ''' Returns a pretty description of a scaling vector. The axes parameter controls what axes are printed and can be used to filter away uninteresting values. ''' return ', '.join( str.format('{} = {}', letter, getattr(scaling, letter)) for letter in axes ) def check_scaling(scaling, axes): ''' Returns whether all given axes on the given scaling vector are 1. ''' return all( abs(getattr(scaling, axis) - 1) < 1e-5 for axis in axes ) # Restriction to checking function mapping. restriction_tests = { 'no scaling': lambda scaling: check_scaling(scaling, 'xyz'), 'y-scaling only': lambda scaling: check_scaling(scaling, 'xz'), 'stud3-like scaling': lambda scaling: all([ check_scaling(scaling, 'xz'), # check if y-scaling is 1 or -1 abs(abs(scaling.y) - 1) < 1e-5, ]), } def scaling_legality_test(model): ''' Checks the part against primitive references with bad scaling. Some primitives (e.g. pegs) are not allowed to be scaled in the X or Z directions. Some (e.g. most studs) are not allowed to be scaled in the Y direction either. ''' from fnmatch import fnmatch scaling_restrictions = library_standards['scaling restrictions'] for subfile_reference in model.subfile_references: primitive = subfile_reference.subfile_path.lower() scaling = subfile_reference.matrix.scaling_vector() # Find all restrictions that apply to this subfile reference. restrictions = { restriction for pattern, restriction in scaling_restrictions.items() if fnmatch(primitive, pattern) } # Check restrictions against the subfile. If any restrictions were # found then the scaling vector must pass at least one of them. if restrictions and not any( restriction_tests[restriction](scaling) for restriction in restrictions ): interesting_axes = ''.join( axis for axis in 'xyz' if abs(getattr(scaling, axis) - 1) > 1e-5 ) yield warning(subfile_reference, 'illegal-scaling', primitive = primitive, axes = interesting_axes, scaling = scaling) manifest = { 'tests': { 'determinant': determinant_test, 'scaling-legality': scaling_legality_test, }, 'messages': { 'zero-determinant': 'matrix determinant is zero ' '(row or column all zero)', 'illegal-scaling': lambda primitive, scaling, axes: str.format('scaling of unscalable primitive {} ({})', primitive, scaling_description(scaling, axes), ), }, }