From 27eda698d4f93a45940d40c2ef76ed1ef4482894 Mon Sep 17 00:00:00 2001 From: Jeff Olander <58099798+JeffreyOI@users.noreply.github.com> Date: Tue, 15 Oct 2024 13:45:34 -0400 Subject: [PATCH 01/10] Update README.rst Added simple mesh (one triangle) to illustrate the structure of the mesh class. Some of this may belong in the src, but since everyone looks at the readme, I thought it helpful to do a little explanation here. --- README.rst | 33 +++++++++++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/README.rst b/README.rst index c1573bc..a2fc7ac 100644 --- a/README.rst +++ b/README.rst @@ -300,6 +300,39 @@ Extending Mesh objects # Show the plot to the screen pyplot.show() +Creating a single triangle +---------------------------------- + +.. code-block:: python + + import numpy + from stl import mesh + + # A unit triangle + tri_vectors = [[0,0,0],[0,1,0],[0,0,1]] + + # Create the vector data. It’s a numpy structured array with N entries, where N is the number of triangles (here N=1), and each entry is in the format ('normals','vectors','attr') + data = numpy.array([( + 0, # Set 'normals' to zero, and the mesh class will automatically calculate them at initialization + tri_vectors, # 'vectors' + 0 # 'attr' + )], dtype = mesh.Mesh.dtype) # The structure defined by the mesh class (N x ('normals','vectors','attr')) + + # Create the mesh object from the structured array + tri_mesh = mesh.Mesh(data) + + # Optionally make a plot for fun + # Load the plot tools + from matplotlib import pyplot + from mpl_toolkits import mplot3d + + # Create a new plot + figure = pyplot.figure() + axes = figure.add_subplot(projection='3d') + + # Add mesh to plot + axes.add_collection3d(mplot3d.art3d.Poly3DCollection(tri_mesh.vectors)) # Just need the 'vectors' attribute for display + Creating Mesh objects from a list of vertices and faces ------------------------------------------------------------------------------ From e983409e5643b2499886fd89cc275b5c6993f4a4 Mon Sep 17 00:00:00 2001 From: Jeff Olander <58099798+JeffreyOI@users.noreply.github.com> Date: Tue, 15 Oct 2024 14:10:48 -0400 Subject: [PATCH 02/10] Update appveyor.yml Missing setuptools installation. Causing AV check to fail. --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index 6827176..6586d95 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -28,7 +28,7 @@ install: build: false # Not a C# project, build stuff at the test step instead. before_test: - - py -m pip install tox numpy cython wheel + - py -m pip install tox numpy cython wheel setuptools test_script: - "py -m tox -e %TOXENV%" From b93960568b3805f7446d9c7d2acbafa35f1f3e87 Mon Sep 17 00:00:00 2001 From: Jeff Olander <58099798+JeffreyOI@users.noreply.github.com> Date: Wed, 16 Oct 2024 02:18:29 -0400 Subject: [PATCH 03/10] Update base.py --- stl/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/base.py b/stl/base.py index f3953ce..b4df68c 100644 --- a/stl/base.py +++ b/stl/base.py @@ -137,7 +137,7 @@ class BaseMesh(logger.Logged, abc.Mapping): >>> len(mesh) == len(list(mesh)) True - >>> (mesh.min_ < mesh.max_).all() + >>> bool((mesh.min_ < mesh.max_).all()) True >>> mesh.update_normals() >>> mesh.units.sum() From e63755323ff580b83942d3afd23d3e2909294cfb Mon Sep 17 00:00:00 2001 From: Jeff Olander <58099798+JeffreyOI@users.noreply.github.com> Date: Wed, 16 Oct 2024 02:23:46 -0400 Subject: [PATCH 04/10] Fixing doctest --- stl/base.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/stl/base.py b/stl/base.py index b4df68c..0fb478a 100644 --- a/stl/base.py +++ b/stl/base.py @@ -137,7 +137,7 @@ class BaseMesh(logger.Logged, abc.Mapping): >>> len(mesh) == len(list(mesh)) True - >>> bool((mesh.min_ < mesh.max_).all()) + >>> bool((mesh.min_ < mesh.max_).all()) True >>> mesh.update_normals() >>> mesh.units.sum() From c4d595a4d169aed13e3928d4bde0d746392b3f18 Mon Sep 17 00:00:00 2001 From: Jeff Olander <58099798+JeffreyOI@users.noreply.github.com> Date: Thu, 17 Oct 2024 01:40:26 -0400 Subject: [PATCH 05/10] Further doctest fixes --- stl/base.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/stl/base.py b/stl/base.py index 0fb478a..01af1f5 100644 --- a/stl/base.py +++ b/stl/base.py @@ -140,10 +140,10 @@ class BaseMesh(logger.Logged, abc.Mapping): >>> bool((mesh.min_ < mesh.max_).all()) True >>> mesh.update_normals() - >>> mesh.units.sum() + >>> float(mesh.units.sum()) 0.0 >>> mesh.v0[:] = mesh.v1[:] = mesh.v2[:] = 0 - >>> mesh.points.sum() + >>> float(mesh.points.sum()) 0.0 >>> mesh.v0 = mesh.v1 = mesh.v2 = 0 From 1d1fb0393350c094c2cc47a55f0a90a4b14a2180 Mon Sep 17 00:00:00 2001 From: Jeff Olander <58099798+JeffreyOI@users.noreply.github.com> Date: Thu, 17 Oct 2024 01:47:31 -0400 Subject: [PATCH 06/10] Final doctest fixes (hopefully) --- stl/base.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/stl/base.py b/stl/base.py index 01af1f5..df88867 100644 --- a/stl/base.py +++ b/stl/base.py @@ -150,19 +150,19 @@ class BaseMesh(logger.Logged, abc.Mapping): >>> mesh.x = mesh.y = mesh.z = 0 >>> mesh.attr = 1 - >>> (mesh.attr == 1).all() + >>> bool((mesh.attr == 1).all()) True >>> mesh.normals = 2 - >>> (mesh.normals == 2).all() + >>> bool((mesh.normals == 2).all()) True >>> mesh.vectors = 3 - >>> (mesh.vectors == 3).all() + >>> bool((mesh.vectors == 3).all()) True >>> mesh.points = 4 - >>> (mesh.points == 4).all() + >>> bool((mesh.points == 4).all()) True ''' #: - normals: :func:`numpy.float32`, `(3, )` From 4adae64bcfda99f9e2feab2bb00e06cd21e1e0f7 Mon Sep 17 00:00:00 2001 From: Jeff Olander <58099798+JeffreyOI@users.noreply.github.com> Date: Thu, 17 Oct 2024 11:20:08 -0400 Subject: [PATCH 07/10] ascii test failure, attempting a fix --- tests/test_ascii.py | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/tests/test_ascii.py b/tests/test_ascii.py index 229b90d..3965e9a 100644 --- a/tests/test_ascii.py +++ b/tests/test_ascii.py @@ -179,7 +179,16 @@ def test_ascii_io(): # Assert binary file is still only ascii characters. fh.getvalue().decode("ascii") + import tempfile + + with tempfile.NamedTemporaryFile(delete=False) as temp_file: + # Save the mesh to the temporary file + mesh_.save(temp_file.name, mode=Mode.ASCII) + + # Read the mesh back from the temporary file + read = mesh.Mesh.from_file(temp_file.name) + # Read the mesh back in. - read = mesh.Mesh.from_file("anonymous.stl", fh=io.BytesIO(fh.getvalue())) + # read = mesh.Mesh.from_file("anonymous.stl", fh=io.BytesIO(fh.getvalue())) # Check what comes out is the same as what went in. assert numpy.allclose(mesh_.vectors, read.vectors) From 3f7abfbac34c912b1e6d0cbfc26a8f794fb0b088 Mon Sep 17 00:00:00 2001 From: Jeff Olander <58099798+JeffreyOI@users.noreply.github.com> Date: Thu, 17 Oct 2024 11:25:35 -0400 Subject: [PATCH 08/10] Indentation error --- tests/test_ascii.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_ascii.py b/tests/test_ascii.py index 3965e9a..3e6b920 100644 --- a/tests/test_ascii.py +++ b/tests/test_ascii.py @@ -182,11 +182,11 @@ def test_ascii_io(): import tempfile with tempfile.NamedTemporaryFile(delete=False) as temp_file: - # Save the mesh to the temporary file - mesh_.save(temp_file.name, mode=Mode.ASCII) + # Save the mesh to the temporary file + mesh_.save(temp_file.name, mode=Mode.ASCII) - # Read the mesh back from the temporary file - read = mesh.Mesh.from_file(temp_file.name) + # Read the mesh back from the temporary file + read = mesh.Mesh.from_file(temp_file.name) # Read the mesh back in. # read = mesh.Mesh.from_file("anonymous.stl", fh=io.BytesIO(fh.getvalue())) From 5906571673644f5d41b10bcb8588067a3b674e18 Mon Sep 17 00:00:00 2001 From: Jeff Olander <58099798+JeffreyOI@users.noreply.github.com> Date: Thu, 17 Oct 2024 11:43:52 -0400 Subject: [PATCH 09/10] possible fp arithmetic errors, added tolerance to inertia check --- tests/test_meshProperties.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/tests/test_meshProperties.py b/tests/test_meshProperties.py index b2b4729..a0e4223 100644 --- a/tests/test_meshProperties.py +++ b/tests/test_meshProperties.py @@ -25,7 +25,7 @@ def test_mass_properties_for_half_donut(binary_ascii_path, speedups): assert close(cog, [1.500001, 0.209472, 1.500001]) assert close(inertia, [[+1.390429, +0.000000, +0.000000], [+0.000000, +2.701025, +0.000000], - [+0.000000, +0.000000, +1.390429]]) + [+0.000000, +0.000000, +1.390429]], atol=1e-5) def test_mass_properties_for_moon(binary_ascii_path, speedups): @@ -42,7 +42,7 @@ def test_mass_properties_for_moon(binary_ascii_path, speedups): assert close(cog, [0.906913, 0.170731, 1.500001]) assert close(inertia, [[+0.562097, -0.000457, +0.000000], [-0.000457, +0.656851, +0.000000], - [+0.000000, +0.000000, +0.112465]]) + [+0.000000, +0.000000, +0.112465]], atol=1e-5) @pytest.mark.parametrize('filename', ('Star.stl', 'StarWithEmptyHeader.stl')) @@ -63,7 +63,7 @@ def test_mass_properties_for_star(binary_ascii_path, filename, speedups): assert close(cog, [1.299040, 0.170197, 1.499999]) assert close(inertia, [[+0.509549, +0.000000, -0.000000], [+0.000000, +0.991236, +0.000000], - [-0.000000, +0.000000, +0.509550]]) + [-0.000000, +0.000000, +0.509550]], atol=1e-5) def test_mass_properties_for_half_donut_with_density( @@ -86,4 +86,4 @@ def test_mass_properties_for_half_donut_with_density( print(inertia) assert close(inertia, [[+1.71022851, +0.00000001, -0.00000011], [+0.00000001, +3.32226227, +0.00000002], - [-0.00000011, +0.00000002, +1.71022859]]) + [-0.00000011, +0.00000002, +1.71022859]], atol=1e-5) From 4bfcffe2c10fc9a4fd2fb81b1846a90317ea5c76 Mon Sep 17 00:00:00 2001 From: Jeff Olander <58099798+JeffreyOI@users.noreply.github.com> Date: Thu, 17 Oct 2024 11:58:02 -0400 Subject: [PATCH 10/10] my first edit failed, saw that tolerance was already set, increased 1e-6 -> 1e-5 --- tests/test_meshProperties.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/tests/test_meshProperties.py b/tests/test_meshProperties.py index a0e4223..38093ad 100644 --- a/tests/test_meshProperties.py +++ b/tests/test_meshProperties.py @@ -4,7 +4,7 @@ from stl import stl -tolerance = 1e-6 +tolerance = 1e-5 def close(a, b): @@ -25,7 +25,7 @@ def test_mass_properties_for_half_donut(binary_ascii_path, speedups): assert close(cog, [1.500001, 0.209472, 1.500001]) assert close(inertia, [[+1.390429, +0.000000, +0.000000], [+0.000000, +2.701025, +0.000000], - [+0.000000, +0.000000, +1.390429]], atol=1e-5) + [+0.000000, +0.000000, +1.390429]]) def test_mass_properties_for_moon(binary_ascii_path, speedups): @@ -42,7 +42,7 @@ def test_mass_properties_for_moon(binary_ascii_path, speedups): assert close(cog, [0.906913, 0.170731, 1.500001]) assert close(inertia, [[+0.562097, -0.000457, +0.000000], [-0.000457, +0.656851, +0.000000], - [+0.000000, +0.000000, +0.112465]], atol=1e-5) + [+0.000000, +0.000000, +0.112465]]) @pytest.mark.parametrize('filename', ('Star.stl', 'StarWithEmptyHeader.stl')) @@ -63,7 +63,7 @@ def test_mass_properties_for_star(binary_ascii_path, filename, speedups): assert close(cog, [1.299040, 0.170197, 1.499999]) assert close(inertia, [[+0.509549, +0.000000, -0.000000], [+0.000000, +0.991236, +0.000000], - [-0.000000, +0.000000, +0.509550]], atol=1e-5) + [-0.000000, +0.000000, +0.509550]]) def test_mass_properties_for_half_donut_with_density( @@ -86,4 +86,4 @@ def test_mass_properties_for_half_donut_with_density( print(inertia) assert close(inertia, [[+1.71022851, +0.00000001, -0.00000011], [+0.00000001, +3.32226227, +0.00000002], - [-0.00000011, +0.00000002, +1.71022859]], atol=1e-5) + [-0.00000011, +0.00000002, +1.71022859]])