tests and examples¶
tests.stl_corruption module¶
import struct
import sys
import numpy as np
import pytest
from stl import mesh
_STL_FILE = """
solid test.stl
facet normal -0.014565 0.073223 -0.002897
outer loop
vertex 0.399344 0.461940 1.044090
vertex 0.500000 0.500000 1.500000
vertex 0.576120 0.500000 1.117320
endloop
endfacet
endsolid test.stl
""".lstrip()
def test_valid_ascii(tmpdir, speedups):
tmp_file = tmpdir.join('tmp.stl')
with tmp_file.open('w+') as fh:
fh.write(_STL_FILE)
fh.seek(0)
mesh.Mesh.from_file(str(tmp_file), fh=fh, speedups=speedups)
def test_end_solid(tmpdir, speedups):
tmp_file = tmpdir.join('tmp.stl')
with tmp_file.open('w+') as fh:
fh.write(_STL_FILE.replace('endsolid', 'end solid'))
fh.seek(0)
mesh.Mesh.from_file(str(tmp_file), fh=fh, speedups=speedups)
def test_ascii_with_missing_name(tmpdir, speedups):
tmp_file = tmpdir.join('tmp.stl')
with tmp_file.open('w+') as fh:
# Split the file into lines
lines = _STL_FILE.splitlines()
# Remove everything except solid
lines[0] = lines[0].split()[0]
# Join the lines to test files that start with solid without space
fh.write('\n'.join(lines))
fh.seek(0)
mesh.Mesh.from_file(str(tmp_file), fh=fh, speedups=speedups)
def test_ascii_with_blank_lines(tmpdir, speedups):
_stl_file = """
solid test.stl
facet normal -0.014565 0.073223 -0.002897
outer loop
vertex 0.399344 0.461940 1.044090
vertex 0.500000 0.500000 1.500000
vertex 0.576120 0.500000 1.117320
endloop
endfacet
endsolid test.stl
""".lstrip()
tmp_file = tmpdir.join('tmp.stl')
with tmp_file.open('w+') as fh:
fh.write(_stl_file)
fh.seek(0)
mesh.Mesh.from_file(str(tmp_file), fh=fh, speedups=speedups)
def test_incomplete_ascii_file(tmpdir, speedups):
tmp_file = tmpdir.join('tmp.stl')
with tmp_file.open('w+') as fh:
fh.write('solid some_file.stl')
fh.seek(0)
with pytest.raises(AssertionError):
mesh.Mesh.from_file(str(tmp_file), fh=fh, speedups=speedups)
for offset in (-20, 82, 100):
with tmp_file.open('w+') as fh:
fh.write(_STL_FILE[:-offset])
fh.seek(0)
with pytest.raises(AssertionError):
mesh.Mesh.from_file(str(tmp_file), fh=fh, speedups=speedups)
def test_corrupt_ascii_file(tmpdir, speedups):
tmp_file = tmpdir.join('tmp.stl')
with tmp_file.open('w+') as fh:
fh.write(_STL_FILE)
fh.seek(40)
print('####\n' * 100, file=fh)
fh.seek(0)
if speedups and sys.version_info.major != 2:
with pytest.raises(AssertionError):
mesh.Mesh.from_file(str(tmp_file), fh=fh, speedups=speedups)
with tmp_file.open('w+') as fh:
fh.write(_STL_FILE)
fh.seek(40)
print(' ' * 100, file=fh)
fh.seek(80)
fh.write(struct.pack('<i', 10).decode('utf-8'))
fh.seek(0)
with pytest.raises(AssertionError):
mesh.Mesh.from_file(str(tmp_file), fh=fh, speedups=speedups)
def test_corrupt_binary_file(tmpdir, speedups):
tmp_file = tmpdir.join('tmp.stl')
with tmp_file.open('w+') as fh:
fh.write('#########\n' * 8)
fh.write('#\0\0\0')
fh.seek(0)
mesh.Mesh.from_file(str(tmp_file), fh=fh, speedups=speedups)
with tmp_file.open('w+') as fh:
fh.write('#########\n' * 9)
fh.seek(0)
with pytest.raises(AssertionError):
mesh.Mesh.from_file(str(tmp_file), fh=fh, speedups=speedups)
with tmp_file.open('w+') as fh:
fh.write('#########\n' * 8)
fh.write('#\0\0\0')
fh.seek(0)
fh.write('solid test.stl')
fh.seek(0)
mesh.Mesh.from_file(str(tmp_file), fh=fh, speedups=speedups)
def test_duplicate_polygons():
data = np.zeros(3, dtype=mesh.Mesh.dtype)
data['vectors'][0] = np.array([[0, 0, 0], [1, 0, 0], [0, 1, 1.0]])
data['vectors'][0] = np.array([[0, 0, 0], [2, 0, 0], [0, 2, 1.0]])
data['vectors'][0] = np.array([[0, 0, 0], [3, 0, 0], [0, 3, 1.0]])
assert not mesh.Mesh(data, remove_empty_areas=False).check() # type: ignore[reportAttributeAccessIssue]
tests.test_commandline module¶
import contextlib
import sys
from stl import main
def test_main(ascii_file, binary_file, tmpdir, speedups):
original_argv = sys.argv[:]
args_pre = ['stl']
args_post = [str(tmpdir.join('output.stl'))]
if not speedups:
args_pre.append('-s')
try:
sys.argv[:] = [*args_pre, ascii_file, *args_post]
main.main()
sys.argv[:] = [*args_pre, '-r', ascii_file, *args_post]
main.main()
sys.argv[:] = [*args_pre, '-a', binary_file, *args_post]
main.main()
sys.argv[:] = [*args_pre, '-b', ascii_file, *args_post]
main.main()
finally:
sys.argv[:] = original_argv
def test_args(ascii_file, tmpdir):
parser = main._get_parser('')
def _get_name(*args) -> str:
return str(main._get_name(parser.parse_args(list(map(str, args)))))
assert _get_name('--name', 'foobar') == 'foobar'
assert _get_name('-', tmpdir.join('binary.stl')).endswith('binary.stl')
assert _get_name(ascii_file, '-').endswith('HalfDonut.stl')
assert _get_name('-', '-')
def test_ascii(binary_file, tmpdir, speedups):
original_argv = sys.argv[:]
try:
sys.argv[:] = [
'stl',
'-s' if not speedups else '',
binary_file,
str(tmpdir.join('ascii.stl')),
]
with contextlib.suppress(SystemExit):
main.to_ascii()
finally:
sys.argv[:] = original_argv
def test_binary(ascii_file, tmpdir, speedups):
original_argv = sys.argv[:]
try:
sys.argv[:] = [
'stl',
'-s' if not speedups else '',
ascii_file,
str(tmpdir.join('binary.stl')),
]
with contextlib.suppress(SystemExit):
main.to_binary()
finally:
sys.argv[:] = original_argv
tests.test_convert module¶
import tempfile
import py.path # type: ignore[import]
import pytest
from stl import stl
def _test_conversion(from_, to, mode, speedups):
# For some reason the test fails when using pathlib instead of py.path
from_ = py.path.local(from_)
to = py.path.local(to)
for name in from_.listdir():
source_file = from_.join(name)
expected_file = to.join(name)
if not expected_file.exists():
continue
mesh = stl.StlMesh(source_file, speedups=speedups)
with open(str(expected_file), 'rb') as expected_fh:
expected = expected_fh.read()
# For binary files, skip the header
if mode is stl.BINARY:
expected = expected[80:]
with tempfile.TemporaryFile() as dest_fh:
mesh.save(name, dest_fh, mode)
# Go back to the beginning to read
dest_fh.seek(0)
dest = dest_fh.read()
# For binary files, skip the header
if mode is stl.BINARY:
dest = dest[80:]
assert dest.strip() == expected.strip()
def test_ascii_to_binary(ascii_path, binary_path, speedups):
_test_conversion(
ascii_path, binary_path, mode=stl.BINARY, speedups=speedups
)
def test_binary_to_ascii(ascii_path, binary_path, speedups):
_test_conversion(
binary_path, ascii_path, mode=stl.ASCII, speedups=speedups
)
def test_stl_mesh(ascii_file, tmpdir, speedups):
tmp_file = tmpdir.join('tmp.stl')
mesh = stl.StlMesh(ascii_file, speedups=speedups)
with pytest.raises(ValueError):
mesh.save(filename=str(tmp_file), mode='test') # type: ignore[reportArgumentType]
mesh.save(str(tmp_file))
mesh.save(str(tmp_file), update_normals=False)
tests.test_mesh module¶
# type: ignore[reportAttributeAccessIssue]
import numpy as np
from stl.base import BaseMesh, RemoveDuplicates
from stl.mesh import Mesh
from . import utils
def test_units_1d():
data = np.zeros(1, dtype=Mesh.dtype)
data['vectors'][0] = np.array([[0, 0, 0], [1, 0, 0], [2, 0, 0]])
mesh = Mesh(data, remove_empty_areas=False)
mesh.update_units()
assert mesh.areas == 0
assert np.allclose(mesh.centroids, [[1, 0, 0]])
utils.array_equals(mesh.normals, [0, 0, 0])
utils.array_equals(mesh.units, [0, 0, 0])
utils.array_equals(mesh.get_unit_normals(), [0, 0, 0])
def test_units_2d():
data = np.zeros(2, dtype=Mesh.dtype)
data['vectors'][0] = np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0]])
data['vectors'][1] = np.array([[1, 0, 0], [0, 1, 0], [1, 1, 0]])
mesh = Mesh(data, remove_empty_areas=False)
mesh.update_units()
assert np.allclose(mesh.areas, [0.5, 0.5])
assert np.allclose(mesh.centroids, [[1 / 3, 1 / 3, 0], [2 / 3, 2 / 3, 0]])
assert np.allclose(mesh.normals, [[0.0, 0.0, 1.0], [0.0, 0.0, -1.0]])
assert np.allclose(mesh.units, [[0, 0, 1], [0, 0, -1]])
assert np.allclose(
mesh.get_unit_normals(), [[0.0, 0.0, 1.0], [0.0, 0.0, -1.0]]
)
def test_units_3d():
data = np.zeros(1, dtype=Mesh.dtype)
data['vectors'][0] = np.array([[0, 0, 0], [1, 0, 0], [0, 1, 1.0]])
mesh = Mesh(data, remove_empty_areas=False)
mesh.update_units()
assert (mesh.areas - 2**0.5) < 0.0001
assert np.allclose(mesh.centroids, [1 / 3, 1 / 3, 1 / 3])
assert np.allclose(mesh.normals, [0.0, -1.0, 1.0])
assert np.allclose(mesh.units[0], [0.0, -0.70710677, 0.70710677])
assert np.allclose(np.linalg.norm(mesh.units, axis=-1), 1)
assert np.allclose(mesh.get_unit_normals(), [0.0, -0.70710677, 0.70710677])
def test_duplicate_polygons():
data = np.zeros(6, dtype=Mesh.dtype)
data['vectors'][0] = np.array([[1, 0, 0], [0, 0, 0], [0, 0, 0]])
data['vectors'][1] = np.array([[2, 0, 0], [0, 0, 0], [0, 0, 0]])
data['vectors'][2] = np.array([[0, 0, 0], [0, 0, 0], [0, 0, 0]])
data['vectors'][3] = np.array([[2, 0, 0], [0, 0, 0], [0, 0, 0]])
data['vectors'][4] = np.array([[1, 0, 0], [0, 0, 0], [0, 0, 0]])
data['vectors'][5] = np.array([[0, 0, 0], [0, 0, 0], [0, 0, 0]])
mesh = Mesh(data)
assert mesh.data.size == 6
mesh = Mesh(data, remove_duplicate_polygons=0)
assert mesh.data.size == 6
mesh = Mesh(data, remove_duplicate_polygons=False)
assert mesh.data.size == 6
mesh = Mesh(data, remove_duplicate_polygons=None)
assert mesh.data.size == 6
mesh = Mesh(data, remove_duplicate_polygons=RemoveDuplicates.NONE)
assert mesh.data.size == 6
mesh = Mesh(data, remove_duplicate_polygons=RemoveDuplicates.SINGLE)
assert mesh.data.size == 3
mesh = Mesh(data, remove_duplicate_polygons=True)
assert mesh.data.size == 3
assert np.allclose(
mesh.vectors[0], np.array([[1, 0, 0], [0, 0, 0], [0, 0, 0]])
)
assert np.allclose(
mesh.vectors[1], np.array([[2, 0, 0], [0, 0, 0], [0, 0, 0]])
)
assert np.allclose(
mesh.vectors[2], np.array([[0, 0, 0], [0, 0, 0], [0, 0, 0]])
)
mesh = Mesh(data, remove_duplicate_polygons=RemoveDuplicates.ALL)
assert mesh.data.size == 3
assert np.allclose(
mesh.vectors[0], np.array([[1, 0, 0], [0, 0, 0], [0, 0, 0]])
)
assert np.allclose(
mesh.vectors[1], np.array([[2, 0, 0], [0, 0, 0], [0, 0, 0]])
)
assert np.allclose(
mesh.vectors[2], np.array([[0, 0, 0], [0, 0, 0], [0, 0, 0]])
)
def test_remove_all_duplicate_polygons():
data = np.zeros(5, dtype=Mesh.dtype)
data['vectors'][0] = np.array([[0, 0, 0], [0, 0, 0], [0, 0, 0]])
data['vectors'][1] = np.array([[1, 0, 0], [0, 0, 0], [0, 0, 0]])
data['vectors'][2] = np.array([[2, 0, 0], [0, 0, 0], [0, 0, 0]])
data['vectors'][3] = np.array([[3, 0, 0], [0, 0, 0], [0, 0, 0]])
data['vectors'][4] = np.array([[3, 0, 0], [0, 0, 0], [0, 0, 0]])
mesh = Mesh(data, remove_duplicate_polygons=False)
assert mesh.data.size == 5
Mesh.remove_duplicate_polygons(mesh.data, RemoveDuplicates.NONE)
mesh = Mesh(data, remove_duplicate_polygons=RemoveDuplicates.ALL)
assert mesh.data.size == 3
assert (
mesh.vectors[0] == np.array([[0, 0, 0], [0, 0, 0], [0, 0, 0]])
).all()
assert (
mesh.vectors[1] == np.array([[1, 0, 0], [0, 0, 0], [0, 0, 0]])
).all()
assert (
mesh.vectors[2] == np.array([[2, 0, 0], [0, 0, 0], [0, 0, 0]])
).all()
def test_empty_areas():
data = np.zeros(3, dtype=Mesh.dtype)
data['vectors'][0] = np.array([[0, 0, 0], [1, 0, 0], [0, 1, 0]])
data['vectors'][1] = np.array([[1, 0, 0], [0, 1, 0], [1, 0, 0]])
data['vectors'][2] = np.array([[1, 0, 0], [0, 1, 0], [1, 0, 0]])
mesh = Mesh(data, calculate_normals=False, remove_empty_areas=False)
assert mesh.data.size == 3
# Test the normals recalculation which also calculates the areas by default
mesh.areas[1] = 1
mesh.areas[2] = 2
assert np.allclose(mesh.areas, [[0.5], [1.0], [2.0]])
mesh.centroids[1] = [1, 2, 3]
mesh.centroids[2] = [4, 5, 6]
assert np.allclose(
mesh.centroids, [[1 / 3, 1 / 3, 0], [1, 2, 3], [4, 5, 6]]
)
mesh.update_normals(update_areas=False, update_centroids=False)
assert np.allclose(mesh.areas, [[0.5], [1.0], [2.0]])
assert np.allclose(
mesh.centroids, [[1 / 3, 1 / 3, 0], [1, 2, 3], [4, 5, 6]]
)
mesh.update_normals(update_areas=True, update_centroids=True)
assert np.allclose(mesh.areas, [[0.5], [0.0], [0.0]])
assert np.allclose(
mesh.centroids,
[[1 / 3, 1 / 3, 0], [2 / 3, 1 / 3, 0], [2 / 3, 1 / 3, 0]],
)
mesh = Mesh(data, remove_empty_areas=True)
assert mesh.data.size == 1
def test_base_mesh():
data = np.zeros(10, dtype=BaseMesh.dtype)
mesh = BaseMesh(data, remove_empty_areas=False)
# Increment vector 0 item 0
mesh.v0[0] += 1
mesh.v1[0] += 2
# Check item 0 (contains v0, v1 and v2)
assert (
mesh[0]
== np.array(
[1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 0.0, 0.0, 0.0], dtype=np.float32
)
).all()
assert (
mesh.vectors[0]
== np.array(
[[1.0, 1.0, 1.0], [2.0, 2.0, 2.0], [0.0, 0.0, 0.0]],
dtype=np.float32,
)
).all()
assert (mesh.v0[0] == np.array([1.0, 1.0, 1.0], dtype=np.float32)).all()
assert (
mesh.points[0]
== np.array(
[1.0, 1.0, 1.0, 2.0, 2.0, 2.0, 0.0, 0.0, 0.0], dtype=np.float32
)
).all()
assert (mesh.x[0] == np.array([1.0, 2.0, 0.0], dtype=np.float32)).all()
mesh[0] = 3
assert (
mesh[0]
== np.array(
[3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0, 3.0], dtype=np.float32
)
).all()
assert len(mesh) == len(list(mesh))
assert (mesh.min_ < mesh.max_).all()
mesh.update_normals()
assert mesh.units.sum() == 0.0
mesh.v0[:] = mesh.v1[:] = mesh.v2[:] = 0
assert mesh.points.sum() == 0.0
tests.test_multiple module¶
import zipfile
import pytest
from stl import mesh
_STL_FILE = b"""
solid test.stl
facet normal -0.014565 0.073223 -0.002897
outer loop
vertex 0.399344 0.461940 1.044090
vertex 0.500000 0.500000 1.500000
vertex 0.576120 0.500000 1.117320
endloop
endfacet
endsolid test.stl
"""
def test_single_stl(tmpdir, speedups):
tmp_file = tmpdir / 'tmp.stl'
with tmp_file.open('wb+') as fh:
fh.write(_STL_FILE)
fh.seek(0)
for m in mesh.Mesh.from_multi_file(
str(tmp_file), fh=fh, speedups=speedups
):
pass
def test_multiple_stl(tmpdir, speedups):
tmp_file = tmpdir / 'tmp.stl'
with tmp_file.open('wb+') as fh:
for _ in range(10):
fh.write(_STL_FILE)
fh.seek(0)
i = 0
for i, m in enumerate(
mesh.Mesh.from_multi_file(str(tmp_file), fh=fh, speedups=speedups)
):
assert m.name == b'test.stl'
assert i == 9
def test_single_stl_file(tmpdir, speedups):
tmp_file = tmpdir / 'tmp.stl'
with tmp_file.open('wb+') as fh:
fh.write(_STL_FILE)
fh.seek(0)
for m in mesh.Mesh.from_multi_file(str(tmp_file), speedups=speedups):
pass
def test_multiple_stl_file(tmpdir, speedups):
tmp_file = tmpdir / 'tmp.stl'
with tmp_file.open('wb+') as fh:
for _ in range(10):
fh.write(_STL_FILE)
fh.seek(0)
i = -1
for i, m in enumerate(
mesh.Mesh.from_multi_file(str(tmp_file), speedups=speedups)
):
assert m.name == b'test.stl'
assert i == 9
def test_multiple_stl_files(tmpdir, speedups):
tmp_file = tmpdir / 'tmp.stl'
with tmp_file.open('wb+') as fh:
fh.write(_STL_FILE)
fh.seek(0)
filenames = [str(tmp_file)] * 10
m = mesh.Mesh.from_files(filenames, speedups=speedups)
assert m.data.size == 10
def test_3mf_file(three_mf_path):
for m in mesh.Mesh.from_3mf_file(three_mf_path / 'Moon.3mf'):
print(m)
def test_3mf_missing_file(three_mf_path):
with pytest.raises(FileNotFoundError):
for m in mesh.Mesh.from_3mf_file(three_mf_path / 'some_file.3mf'):
print(m)
def test_3mf_wrong_file(ascii_file):
with pytest.raises(zipfile.BadZipfile):
for m in mesh.Mesh.from_3mf_file(ascii_file):
print(m)
tests.test_rotate module¶
# type: ignore[reportAttributeAccessIssue]
import math
import numpy as np
import pytest
from stl.mesh import Mesh
from . import utils
def test_rotation():
# Create 6 faces of a cube
data = np.zeros(6, dtype=Mesh.dtype)
# Top of the cube
data['vectors'][0] = np.array([[0, 1, 1], [1, 0, 1], [0, 0, 1]])
data['vectors'][1] = np.array([[1, 0, 1], [0, 1, 1], [1, 1, 1]])
# Right face
data['vectors'][2] = np.array([[1, 0, 0], [1, 0, 1], [1, 1, 0]])
data['vectors'][3] = np.array([[1, 1, 1], [1, 0, 1], [1, 1, 0]])
# Left face
data['vectors'][4] = np.array([[0, 0, 0], [1, 0, 0], [1, 0, 1]])
data['vectors'][5] = np.array([[0, 0, 0], [0, 0, 1], [1, 0, 1]])
mesh = Mesh(data, remove_empty_areas=False)
# Since the cube faces are from 0 to 1 we can move it to the middle by
# substracting .5
data['vectors'] -= 0.5
# Rotate 90 degrees over the X axis followed by the Y axis followed by the
# X axis
mesh.rotate([0.5, 0.0, 0.0], math.radians(90))
mesh.rotate([0.0, 0.5, 0.0], math.radians(90))
mesh.rotate([0.5, 0.0, 0.0], math.radians(90))
# Since the cube faces are from 0 to 1 we can move it to the middle by
# substracting .5
data['vectors'] += 0.5
# We use a slightly higher absolute tolerance here, for ppc64le
# https://github.com/WoLpH/numpy-stl/issues/78
assert np.allclose(
mesh.vectors,
np.array(
[
[[1, 0, 0], [0, 1, 0], [0, 0, 0]],
[[0, 1, 0], [1, 0, 0], [1, 1, 0]],
[[0, 1, 1], [0, 1, 0], [1, 1, 1]],
[[1, 1, 0], [0, 1, 0], [1, 1, 1]],
[[0, 0, 1], [0, 1, 1], [0, 1, 0]],
[[0, 0, 1], [0, 0, 0], [0, 1, 0]],
]
),
atol=1e-07,
)
def test_rotation_over_point():
# Create a single face
data = np.zeros(1, dtype=Mesh.dtype)
data['vectors'][0] = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
mesh = Mesh(data, remove_empty_areas=False)
mesh.rotate([1, 0, 0], math.radians(180), point=[1, 2, 3])
utils.array_equals(
mesh.vectors,
np.array([[[1.0, 4.0, 6.0], [0.0, 3.0, 6.0], [0.0, 4.0, 5.0]]]),
)
mesh.rotate([1, 0, 0], math.radians(-180), point=[1, 2, 3])
utils.array_equals(
mesh.vectors, np.array([[[1, 0, 0], [0, 1, 0], [0, 0, 1]]])
)
mesh.rotate([1, 0, 0], math.radians(180), point=0.0)
utils.array_equals(
mesh.vectors,
np.array([[[1.0, 0.0, -0.0], [0.0, -1.0, -0.0], [0.0, 0.0, -1.0]]]),
)
with pytest.raises(TypeError):
mesh.rotate([1, 0, 0], math.radians(180), point='x')
def test_double_rotation():
# Create a single face
data = np.zeros(1, dtype=Mesh.dtype)
data['vectors'][0] = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]])
mesh = Mesh(data, remove_empty_areas=False)
rotation_matrix = mesh.rotation_matrix([1, 0, 0], math.radians(180))
combined_rotation_matrix = np.dot(rotation_matrix, rotation_matrix)
mesh.rotate_using_matrix(combined_rotation_matrix)
utils.array_equals(
mesh.vectors,
np.array([[[1.0, 0.0, 0.0], [0.0, 1.0, 0.0], [0.0, 0.0, 1.0]]]),
)
def test_no_rotation():
# Create a single face
data = np.zeros(1, dtype=Mesh.dtype)
data['vectors'][0] = np.array([[0, 1, 1], [1, 0, 1], [0, 0, 1]])
mesh = Mesh(data, remove_empty_areas=False)
# Rotate by 0 degrees
mesh.rotate([0.5, 0.0, 0.0], math.radians(0))
assert np.allclose(
mesh.vectors, np.array([[[0, 1, 1], [1, 0, 1], [0, 0, 1]]])
)
# Use a zero rotation matrix
mesh.rotate([0.0, 0.0, 0.0], math.radians(90))
assert np.allclose(
mesh.vectors, np.array([[[0, 1, 1], [1, 0, 1], [0, 0, 1]]])
)
def test_no_translation():
# Create a single face
data = np.zeros(1, dtype=Mesh.dtype)
data['vectors'][0] = np.array([[0, 1, 1], [1, 0, 1], [0, 0, 1]])
mesh = Mesh(data, remove_empty_areas=False)
assert np.allclose(
mesh.vectors, np.array([[[0, 1, 1], [1, 0, 1], [0, 0, 1]]])
)
# Translate mesh with a zero vector
mesh.translate([0.0, 0.0, 0.0])
assert np.allclose(
mesh.vectors, np.array([[[0, 1, 1], [1, 0, 1], [0, 0, 1]]])
)
def test_translation():
# Create a single face
data = np.zeros(1, dtype=Mesh.dtype)
data['vectors'][0] = np.array([[0, 1, 1], [1, 0, 1], [0, 0, 1]])
mesh = Mesh(data, remove_empty_areas=False)
assert np.allclose(
mesh.vectors, np.array([[[0, 1, 1], [1, 0, 1], [0, 0, 1]]])
)
# Translate mesh with vector [1, 2, 3]
mesh.translate([1.0, 2.0, 3.0])
assert np.allclose(
mesh.vectors, np.array([[[1, 3, 4], [2, 2, 4], [1, 2, 4]]])
)
def test_no_transformation():
# Create a single face
data = np.zeros(1, dtype=Mesh.dtype)
data['vectors'][0] = np.array([[0, 1, 1], [1, 0, 1], [0, 0, 1]])
mesh = Mesh(data, remove_empty_areas=False)
assert np.allclose(
mesh.vectors, np.array([[[0, 1, 1], [1, 0, 1], [0, 0, 1]]])
)
# Transform mesh with identity matrix
mesh.transform(np.eye(4))
assert np.allclose(
mesh.vectors, np.array([[[0, 1, 1], [1, 0, 1], [0, 0, 1]]])
)
assert np.allclose(mesh.areas, 0.5)
def test_transformation():
# Create a single face
data = np.zeros(1, dtype=Mesh.dtype)
data['vectors'][0] = np.array([[0, 1, 1], [1, 0, 1], [0, 0, 1]])
mesh = Mesh(data, remove_empty_areas=False)
assert np.allclose(
mesh.vectors, np.array([[[0, 1, 1], [1, 0, 1], [0, 0, 1]]])
)
# Transform mesh with identity matrix
tr = np.zeros((4, 4))
tr[0:3, 0:3] = Mesh.rotation_matrix([0, 0, 1], 0.5 * np.pi)
tr[0:3, 3] = [1, 2, 3]
mesh.transform(tr)
assert np.allclose(
mesh.vectors, np.array([[[0, 2, 4], [1, 3, 4], [1, 2, 4]]])
)
assert np.allclose(mesh.areas, 0.5)