From 1b50a1c9092759d94a8e73d64fba5c039d3360f1 Mon Sep 17 00:00:00 2001 From: Ludovico Caveglia Curtil Date: Thu, 28 Mar 2024 17:23:13 +0200 Subject: [PATCH 01/11] fix writing solid name to ASCII STL --- tests/test_stl.py | 5 +++++ trimesh/exchange/stl.py | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/tests/test_stl.py b/tests/test_stl.py index 5b9aa7a28..bf82e41fa 100644 --- a/tests/test_stl.py +++ b/tests/test_stl.py @@ -72,6 +72,11 @@ def test_ascii_multibody(self): assert len(s.geometry) == 2 assert set(s.geometry.keys()) == {"bodyA", "bodyB"} + def test_ascii_solid_name(self): + mesh = g.trimesh.creation.icosphere(subdivisions=1, radius=1.0) + mesh.metadata = {"name": "solid_A"} + assert g.trimesh.exchange.stl.export_stl_ascii(mesh).splitlines()[0] == "solid solid_A" + def test_empty(self): # demo files to check empty_files = ["stl_empty_ascii.stl", "stl_empty_bin.stl"] diff --git a/trimesh/exchange/stl.py b/trimesh/exchange/stl.py index d5e5e47a7..a82a6d0de 100644 --- a/trimesh/exchange/stl.py +++ b/trimesh/exchange/stl.py @@ -309,7 +309,7 @@ def export_stl_ascii(mesh) -> str: name = "" # concatenate the header, data, and footer, and a new line - return "\n".join(["solid {name}", formatter.format(*blob.reshape(-1)), "endsolid\n"]) + return "\n".join([f"solid {name}", formatter.format(*blob.reshape(-1)), "endsolid\n"]) _stl_loaders = {"stl": load_stl, "stl_ascii": load_stl} From f4aa1707fa8c3dcb1281799a6709705d2c303b92 Mon Sep 17 00:00:00 2001 From: Michael Dawson-Haggerty Date: Thu, 28 Mar 2024 13:10:49 -0400 Subject: [PATCH 02/11] apply preview unsafe fixes --- pyproject.toml | 2 +- trimesh/__init__.py | 6 +++--- trimesh/caching.py | 2 +- trimesh/creation.py | 6 ++---- trimesh/exchange/binvox.py | 4 ++-- trimesh/exchange/load.py | 2 +- trimesh/exchange/threemf.py | 2 +- trimesh/graph.py | 2 +- trimesh/nsphere.py | 2 +- trimesh/path/exchange/dxf.py | 2 +- trimesh/path/exchange/load.py | 2 +- trimesh/path/path.py | 4 ++-- trimesh/path/segments.py | 2 +- trimesh/path/simplify.py | 2 +- trimesh/points.py | 4 ++-- trimesh/proximity.py | 6 +++--- trimesh/ray/__init__.py | 2 +- trimesh/ray/ray_triangle.py | 2 +- trimesh/ray/ray_util.py | 2 +- trimesh/registration.py | 10 +++++----- trimesh/typed.py | 22 +++++++++++----------- trimesh/util.py | 4 ++-- trimesh/viewer/__init__.py | 6 +++--- trimesh/voxel/base.py | 2 +- trimesh/voxel/creation.py | 4 ++-- trimesh/voxel/ops.py | 2 +- 26 files changed, 52 insertions(+), 54 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index ab8923c37..b1d51ac1e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -129,7 +129,7 @@ select = [ "E", # style errors "F", # flakes "I", # import sorting - "RUF100", # meta + "RUF", # ruff specific rules "UP", # upgrade "W", # style warnings "YTT", # sys.version diff --git a/trimesh/__init__.py b/trimesh/__init__.py index 829869223..ca2e449a2 100644 --- a/trimesh/__init__.py +++ b/trimesh/__init__.py @@ -73,9 +73,8 @@ __all__ = [ "PointCloud", - "Trimesh", "Scene", - "util", + "Trimesh", "__version__", "available_formats", "boolean", @@ -87,6 +86,7 @@ "creation", "curvature", "decomposition", + "exceptions", "geometry", "graph", "grouping", @@ -114,7 +114,7 @@ "triangles", "unitize", "units", + "util", "utilScene", "voxel", - "exceptions", ] diff --git a/trimesh/caching.py b/trimesh/caching.py index 2fbe4f85c..05aea98fc 100644 --- a/trimesh/caching.py +++ b/trimesh/caching.py @@ -654,7 +654,7 @@ def __setitem__(self, key, data): # will raise if this is not a hashable type hash(data) except BaseException: - raise ValueError("unhashable `{key}:{type(data)}`") + raise ValueError(f"unhashable `{key}:{type(data)}`") tracked = data # apply our mutability setting diff --git a/trimesh/creation.py b/trimesh/creation.py index e7afcec23..f2d12b3dd 100644 --- a/trimesh/creation.py +++ b/trimesh/creation.py @@ -383,7 +383,7 @@ def extrude_triangulation( # a sequence of zero- indexed faces, which will then be appended # with offsets to create the final mesh faces_seq = [faces[:, ::-1], faces.copy(), vertical_faces] - vertices_seq = [vertices_3D, vertices_3D.copy() + [0.0, 0, height], vertical] + vertices_seq = [vertices_3D, [*vertices_3D.copy(), 0.0, 0, height], vertical] # append sequences into flat nicely indexed arrays vertices, faces = util.append_faces(vertices_seq, faces_seq) @@ -1452,9 +1452,7 @@ def torus( Mesh of a torus """ phi = np.linspace(0, 2 * np.pi, minor_sections, endpoint=False) - linestring = np.column_stack( - (minor_radius * np.cos(phi), minor_radius * np.sin(phi)) - ) + [major_radius, 0] + linestring = [*np.column_stack((minor_radius * np.cos(phi), minor_radius * np.sin(phi))), major_radius, 0] if "metadata" not in kwargs: kwargs["metadata"] = {} diff --git a/trimesh/exchange/binvox.py b/trimesh/exchange/binvox.py index bef8e9a8f..5480f37ad 100644 --- a/trimesh/exchange/binvox.py +++ b/trimesh/exchange/binvox.py @@ -426,7 +426,7 @@ def __init__( raise ValueError("Maximum dimension using exact is 1024, got %d" % dimension) if file_type not in Binvoxer.SUPPORTED_OUTPUT_TYPES: raise ValueError( - f"file_type {file_type} not in set of supported output types {str(Binvoxer.SUPPORTED_OUTPUT_TYPES)}" + f"file_type {file_type} not in set of supported output types {Binvoxer.SUPPORTED_OUTPUT_TYPES!s}" ) args = [encoder, "-d", str(dimension), "-t", file_type] if exact: @@ -513,7 +513,7 @@ def __call__(self, path, overwrite=False): ext = ext[1:].lower() if ext not in Binvoxer.SUPPORTED_INPUT_TYPES: raise ValueError( - f"file_type {ext} not in set of supported input types {str(Binvoxer.SUPPORTED_INPUT_TYPES)}" + f"file_type {ext} not in set of supported input types {Binvoxer.SUPPORTED_INPUT_TYPES!s}" ) out_path = f"{head}.{self._file_type}" if os.path.isfile(out_path) and not overwrite: diff --git a/trimesh/exchange/load.py b/trimesh/exchange/load.py index 8922bb058..0ac7c0987 100644 --- a/trimesh/exchange/load.py +++ b/trimesh/exchange/load.py @@ -215,7 +215,7 @@ def load_mesh( # show the repr for loaded, loader used, and time log.debug( - f"loaded {str(loaded)} using `{loader.__name__}` in {now() - tic:0.4f}s" + f"loaded {loaded!s} using `{loader.__name__}` in {now() - tic:0.4f}s" ) finally: # if we failed to load close file diff --git a/trimesh/exchange/threemf.py b/trimesh/exchange/threemf.py index c6a254f19..f1c024496 100644 --- a/trimesh/exchange/threemf.py +++ b/trimesh/exchange/threemf.py @@ -29,7 +29,7 @@ def load_3MF(file_obj, postprocess=True, **kwargs): model = next(iter(v for k, v in archive.items() if "3d/3dmodel.model" in k.lower())) # read root attributes only from XML first - event, root = next(etree.iterparse(model, tag=("{*}model"), events=("start",))) + _event, root = next(etree.iterparse(model, tag=("{*}model"), events=("start",))) # collect unit information from the tree if "unit" in root.attrib: metadata = {"units": root.attrib["unit"]} diff --git a/trimesh/graph.py b/trimesh/graph.py index 22f77c1b1..f3f670df2 100644 --- a/trimesh/graph.py +++ b/trimesh/graph.py @@ -487,7 +487,7 @@ def connected_component_labels(edges, node_count=None): Component labels for each node """ matrix = edges_to_coo(edges, node_count) - body_count, labels = csgraph.connected_components(matrix, directed=False) + _body_count, labels = csgraph.connected_components(matrix, directed=False) if node_count is not None: assert len(labels) == node_count diff --git a/trimesh/nsphere.py b/trimesh/nsphere.py index 6475557f7..a23de86cc 100644 --- a/trimesh/nsphere.py +++ b/trimesh/nsphere.py @@ -187,6 +187,6 @@ def is_nsphere(points): check : bool True if input points are on an nsphere """ - center, radius, error = fit_nsphere(points) + _center, _radius, error = fit_nsphere(points) check = error < tol.merge return check diff --git a/trimesh/path/exchange/dxf.py b/trimesh/path/exchange/dxf.py index 32140681e..0d4626798 100644 --- a/trimesh/path/exchange/dxf.py +++ b/trimesh/path/exchange/dxf.py @@ -363,7 +363,7 @@ def convert_text(e): # origin point origin = np.array([e["10"], e["20"]], dtype=np.float64) # an origin-relative point (so transforms work) - vector = origin + [np.cos(angle), np.sin(angle)] + vector = [*origin, np.cos(angle), np.sin(angle)] # try to extract a (horizontal, vertical) text alignment align = ["center", "center"] try: diff --git a/trimesh/path/exchange/load.py b/trimesh/path/exchange/load.py index b7baaaab6..f3d012b2f 100644 --- a/trimesh/path/exchange/load.py +++ b/trimesh/path/exchange/load.py @@ -66,7 +66,7 @@ def load_path(file_obj, file_type=None, **kwargs): raise ValueError("Not a supported object type!") result = load_kwargs(kwargs) - util.log.debug(f"loaded {str(result)} in {util.now() - tic:0.4f}s") + util.log.debug(f"loaded {result!s} in {util.now() - tic:0.4f}s") return result diff --git a/trimesh/path/path.py b/trimesh/path/path.py index 7d615e18c..50ce9702f 100644 --- a/trimesh/path/path.py +++ b/trimesh/path/path.py @@ -403,7 +403,7 @@ def vertex_graph(self): graph : networkx.Graph Holds vertex indexes """ - graph, closed = traversal.vertex_graph(self.entities) + graph, _closed = traversal.vertex_graph(self.entities) return graph @caching.cache_decorator @@ -606,7 +606,7 @@ def remove_duplicate_entities(self): self.entities: length same or shorter """ entity_hashes = np.array([hash(i) for i in self.entities]) - unique, inverse = grouping.unique_rows(entity_hashes) + unique, _inverse = grouping.unique_rows(entity_hashes) if len(unique) != len(self.entities): self.entities = self.entities[unique] diff --git a/trimesh/path/segments.py b/trimesh/path/segments.py index b8a0fc2ef..840afb4bd 100644 --- a/trimesh/path/segments.py +++ b/trimesh/path/segments.py @@ -121,7 +121,7 @@ def colinear_pairs(segments, radius=0.01, angle=0.01, length=None): # convert segments to parameterized origins # which are the closest point on the line to # the actual zero- origin - origins, vectors, param = segments_to_parameters(segments) + origins, vectors, _param = segments_to_parameters(segments) # create a kdtree for origins tree = spatial.cKDTree(origins) diff --git a/trimesh/path/simplify.py b/trimesh/path/simplify.py index 13ca517d7..04c5b6091 100644 --- a/trimesh/path/simplify.py +++ b/trimesh/path/simplify.py @@ -283,7 +283,7 @@ def points_to_spline_entity(points, smooth=None, count=None): points = np.asanyarray(points, dtype=np.float64) closed = np.linalg.norm(points[0] - points[-1]) < tol.merge - knots, control, degree = splprep(points.T, s=smooth)[0] + knots, control, _degree = splprep(points.T, s=smooth)[0] control = np.transpose(control) index = np.arange(len(control)) diff --git a/trimesh/points.py b/trimesh/points.py index f5cf44f7a..7ff60ec25 100644 --- a/trimesh/points.py +++ b/trimesh/points.py @@ -59,7 +59,7 @@ def major_axis(points): axis : (dimension,) float Vector along approximate major axis """ - U, S, V = np.linalg.svd(points) + _U, S, V = np.linalg.svd(points) axis = util.unitize(np.dot(S, V)) return axis @@ -269,7 +269,7 @@ def k_means(points, k, **kwargs): points_std = points.std(axis=0) points_std[points_std < tol.zero] = 1 whitened = points / points_std - centroids_whitened, distortion = kmeans(whitened, k, **kwargs) + centroids_whitened, _distortion = kmeans(whitened, k, **kwargs) centroids = centroids_whitened * points_std # find which centroid each point is closest to diff --git a/trimesh/proximity.py b/trimesh/proximity.py index 2332bafce..e7a423162 100644 --- a/trimesh/proximity.py +++ b/trimesh/proximity.py @@ -400,7 +400,7 @@ def longest_ray(mesh, points, directions): if len(points) != len(directions): raise ValueError("number of points must equal number of directions!") - faces, rays, locations = mesh.ray.intersects_id( + _faces, rays, locations = mesh.ray.intersects_id( points, directions, return_locations=True, multiple_hits=True ) if len(rays) > 0: @@ -503,7 +503,7 @@ def max_tangent_sphere( n_iter = 0 while not_converged.sum() > 0 and n_iter < max_iter: n_iter += 1 - n_points, n_dists, n_faces = mesh.nearest.on_surface(centers[not_converged]) + n_points, n_dists, _n_faces = mesh.nearest.on_surface(centers[not_converged]) # If the distance to the nearest point is the same as the distance # to the start point then we are done. @@ -572,7 +572,7 @@ def thickness(mesh, points, exterior=False, normals=None, method="max_sphere"): normals = mesh.face_normals[closest_point(mesh, points)[2]] if method == "max_sphere": - centers, radius = max_tangent_sphere( + _centers, radius = max_tangent_sphere( mesh=mesh, points=points, inwards=not exterior, normals=normals ) thickness = radius * 2 diff --git a/trimesh/ray/__init__.py b/trimesh/ray/__init__.py index 373b4ef0e..fa8812a98 100644 --- a/trimesh/ray/__init__.py +++ b/trimesh/ray/__init__.py @@ -12,4 +12,4 @@ has_embree = False # add to __all__ as per pep8 -__all__ = ["ray_triangle", "ray_pyembree"] +__all__ = ["ray_pyembree", "ray_triangle"] diff --git a/trimesh/ray/ray_triangle.py b/trimesh/ray/ray_triangle.py index 805909eb8..48ad767e1 100644 --- a/trimesh/ray/ray_triangle.py +++ b/trimesh/ray/ray_triangle.py @@ -146,7 +146,7 @@ def intersects_any(self, ray_origins, ray_directions, **kwargs): hit : (m,) bool Whether any ray hit any triangle on the mesh """ - index_tri, index_ray = self.intersects_id(ray_origins, ray_directions) + _index_tri, index_ray = self.intersects_id(ray_origins, ray_directions) hit_any = np.zeros(len(ray_origins), dtype=bool) hit_idx = np.unique(index_ray) if len(hit_idx) > 0: diff --git a/trimesh/ray/ray_util.py b/trimesh/ray/ray_util.py index 292c7c1a9..57293eaec 100644 --- a/trimesh/ray/ray_util.py +++ b/trimesh/ray/ray_util.py @@ -51,7 +51,7 @@ def contains_points(intersector, points, check_direction=None): ) # cast a ray both forwards and backwards - location, index_ray, c = intersector.intersects_location( + _location, index_ray, _c = intersector.intersects_location( np.vstack((points[inside_aabb], points[inside_aabb])), np.vstack((ray_directions, -ray_directions)), ) diff --git a/trimesh/registration.py b/trimesh/registration.py index 21e476f7a..83600ed4e 100644 --- a/trimesh/registration.py +++ b/trimesh/registration.py @@ -147,7 +147,7 @@ def key_points(m, count): ) # run first pass ICP - matrix, junk, cost = icp( + matrix, _junk, cost = icp( a=points, b=search, initial=a_to_b, max_iterations=int(icp_first), scale=scale ) @@ -156,7 +156,7 @@ def key_points(m, count): costs[i] = cost # run a final ICP refinement step - matrix, junk, cost = icp( + matrix, _junk, cost = icp( a=points, b=search, initial=transforms[np.argmin(costs)], @@ -268,7 +268,7 @@ def procrustes( ((b - bcenter) / bscale).T, ((a - acenter) / ascale) * w.reshape((-1, 1)) ) - u, s, vh = np.linalg.svd(target) + u, _s, vh = np.linalg.svd(target) if reflection: R = np.dot(u, vh) @@ -349,9 +349,9 @@ def icp(a, b, initial=None, threshold=1e-5, max_iterations=20, **kwargs): for _ in range(max_iterations): # Closest point in b to each point in a if is_mesh: - closest, distance, faces = b.nearest.on_surface(a) + closest, _distance, _faces = b.nearest.on_surface(a) else: - distances, ix = btree.query(a, 1) + _distances, ix = btree.query(a, 1) closest = b[ix] # align a with closest points diff --git a/trimesh/typed.py b/trimesh/typed.py index e8e6bc180..a95611934 100644 --- a/trimesh/typed.py +++ b/trimesh/typed.py @@ -41,21 +41,21 @@ Number = Union[float, floating, Integer] __all__ = [ - "NDArray", - "ArrayLike", - "Optional", - "Sequence", - "Iterable", - "Loadable", "IO", + "Any", + "ArrayLike", "BinaryIO", - "List", "Dict", - "Any", + "Integer", + "Iterable", + "List", + "Loadable", + "NDArray", + "Number", + "Optional", + "Sequence", + "Stream", "Tuple", "float64", "int64", - "Number", - "Integer", - "Stream", ] diff --git a/trimesh/util.py b/trimesh/util.py index 1f3a5331a..78a1de197 100644 --- a/trimesh/util.py +++ b/trimesh/util.py @@ -238,8 +238,8 @@ def is_sequence(obj) -> bool: True if object is sequence """ seq = ( - not hasattr(obj, "strip") - and hasattr(obj, "__getitem__") + (not hasattr(obj, "strip") + and hasattr(obj, "__getitem__")) or hasattr(obj, "__iter__") ) diff --git a/trimesh/viewer/__init__.py b/trimesh/viewer/__init__.py index 78ea03399..e92b649e4 100644 --- a/trimesh/viewer/__init__.py +++ b/trimesh/viewer/__init__.py @@ -30,10 +30,10 @@ # explicitly list imports in __all__ # as otherwise flake8 gets mad __all__ = [ - "SceneWidget", "SceneViewer", - "render_scene", + "SceneWidget", "in_notebook", - "scene_to_notebook", + "render_scene", "scene_to_html", + "scene_to_notebook", ] diff --git a/trimesh/voxel/base.py b/trimesh/voxel/base.py index 502163cf9..24ad67269 100644 --- a/trimesh/voxel/base.py +++ b/trimesh/voxel/base.py @@ -413,7 +413,7 @@ def revoxelized(self, shape): shape = tuple(shape) bounds = self.bounds.copy() extents = self.extents - points = util.grid_linspace(bounds, shape).reshape(shape + (3,)) + points = util.grid_linspace(bounds, shape).reshape((*shape, 3)) dense = self.is_filled(points) scale = extents / np.asanyarray(shape) translate = bounds[0] diff --git a/trimesh/voxel/creation.py b/trimesh/voxel/creation.py index c65b42352..7859a3de6 100644 --- a/trimesh/voxel/creation.py +++ b/trimesh/voxel/creation.py @@ -38,7 +38,7 @@ def voxelize_subdivide(mesh, pitch: float, max_iter: int = 10, edge_factor: floa # get the same mesh sudivided so every edge is shorter # than a factor of our pitch - v, f, idx = remesh.subdivide_to_size( + v, _f, _idx = remesh.subdivide_to_size( mesh.vertices, mesh.faces, max_edge=max_edge, max_iter=max_iter, return_index=True ) @@ -48,7 +48,7 @@ def voxelize_subdivide(mesh, pitch: float, max_iter: int = 10, edge_factor: floa hit = np.round(v / pitch).astype(int) # remove duplicates - unique, inverse = grouping.unique_rows(hit) + unique, _inverse = grouping.unique_rows(hit) # get the voxel centers in model space occupied_index = hit[unique] diff --git a/trimesh/voxel/ops.py b/trimesh/voxel/ops.py index c96552bf7..f29b45ac0 100644 --- a/trimesh/voxel/ops.py +++ b/trimesh/voxel/ops.py @@ -148,7 +148,7 @@ def matrix_to_marching_cubes(matrix, pitch=1.0): vertices, faces = meshed normals = None elif len(meshed) == 4: - vertices, faces, normals, vals = meshed + vertices, faces, normals, _vals = meshed # Return to the origin, add in the pad_width vertices = np.subtract(vertices, pad_width * pitch) From 8ef75348ddf9f595717fc06a3d42e86179e87611 Mon Sep 17 00:00:00 2001 From: Michael Dawson-Haggerty Date: Thu, 28 Mar 2024 13:16:04 -0400 Subject: [PATCH 03/11] apply ruff suggestions to tests --- .github/workflows/release.yml | 2 +- .github/workflows/test.yml | 6 ++---- tests/test_align.py | 4 ++-- tests/test_creation.py | 2 +- tests/test_export.py | 2 +- tests/test_gltf.py | 14 ++++++++------ tests/test_obj.py | 6 +++--- tests/test_packing.py | 6 +++--- tests/test_paths.py | 2 +- tests/test_permutate.py | 4 ++-- tests/test_points.py | 4 ++-- tests/test_polygons.py | 4 ++-- tests/test_poses.py | 6 +++--- tests/test_proximity.py | 4 ++-- tests/test_ray.py | 10 +++++----- tests/test_registration.py | 8 ++++---- tests/test_render.py | 2 +- tests/test_sample.py | 8 ++++---- tests/test_section.py | 4 ++-- tests/test_segments.py | 2 +- tests/test_simplify.py | 2 +- tests/test_smooth.py | 2 +- tests/test_stl.py | 5 ++++- tests/test_visual.py | 4 ++-- trimesh/creation.py | 6 +++++- trimesh/exchange/load.py | 4 +--- trimesh/util.py | 6 ++---- 27 files changed, 66 insertions(+), 63 deletions(-) diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 46ab54f14..b46f5d2fe 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -20,7 +20,7 @@ jobs: run: | pip install ruff - name: Check Formatting - run: ruff . + run: ruff check . tests: name: Run Unit Tests needs: formatting diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index ddc3873ea..1defa397c 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -16,11 +16,9 @@ jobs: with: python-version: "3.11" - name: Install - run: pip install ruff black + run: pip install ruff - name: Run Ruff - run: ruff . -# - name: Run Black -# run: black --check . + run: ruff check . tests: name: Run Unit Tests diff --git a/tests/test_align.py b/tests/test_align.py index cc237ea3f..2a36075ac 100644 --- a/tests/test_align.py +++ b/tests/test_align.py @@ -37,7 +37,7 @@ def test_align(self): unitized = g.trimesh.unitize(vectors) for unit_dest, dest in zip(unitized[-10:], vectors[-10:]): for unit, vector in zip(unitized, vectors): - T, a = align(vector, dest, return_angle=True) + T, _a = align(vector, dest, return_angle=True) assert is_rigid(T) assert g.np.isclose(g.np.linalg.det(T), 1.0) # rotate vector with transform @@ -97,7 +97,7 @@ def test_rigid(self): vector_1 = g.np.array([7.12106798e-07, -7.43194705e-08, 1.00000000e00]) vector_2 = g.np.array([0, 0, -1]) - T, angle = align(vector_1, vector_2, return_angle=True) + T, _angle = align(vector_1, vector_2, return_angle=True) assert g.np.isclose(g.np.linalg.det(T), 1.0) diff --git a/tests/test_creation.py b/tests/test_creation.py index bc06f9cb8..647e51fb0 100644 --- a/tests/test_creation.py +++ b/tests/test_creation.py @@ -267,7 +267,7 @@ def test_triangulate(self): ) except BaseException: g.log.error("failed to benchmark triangle", exc_info=True) - g.log.info(f"benchmarked triangulation on {len(bench)} polygons: {str(times)}") + g.log.info(f"benchmarked triangulation on {len(bench)} polygons: {times!s}") def test_triangulate_plumbing(self): """ diff --git a/tests/test_export.py b/tests/test_export.py index 1125b5bd7..380761d69 100644 --- a/tests/test_export.py +++ b/tests/test_export.py @@ -312,7 +312,7 @@ def test_parse_file_args(self): def test_buffered_random(self): """Test writing to non-standard file""" - mesh = list(g.get_meshes(1))[0] + mesh = next(iter(g.get_meshes(1))) with io.BufferedRandom(io.BytesIO()) as rw: mesh.export(rw, "STL") rw.seek(0) diff --git a/tests/test_gltf.py b/tests/test_gltf.py index a44aeb056..95aec4634 100644 --- a/tests/test_gltf.py +++ b/tests/test_gltf.py @@ -433,7 +433,7 @@ def to_integer(args): ) assert len(reloaded.geometry) == 1 # get meshes back - sphere_b = list(reloaded.geometry.values())[0] + sphere_b = next(iter(reloaded.geometry.values())) assert (sphere_b.visual.material.baseColorFactor == (255, 0, 0, 255)).all() def test_material_hash(self): @@ -1047,11 +1047,13 @@ def test_unitize_normals_null_values(self): # Export the mesh export = mesh.export(file_type="glb", unitize_normals=True) - reimported_mesh = list( - g.trimesh.load( - g.trimesh.util.wrap_as_stream(export), file_type="glb" - ).geometry.values() - )[0] + reimported_mesh = next( + iter( + g.trimesh.load( + g.trimesh.util.wrap_as_stream(export), file_type="glb" + ).geometry.values() + ) + ) # Check that the normals are still null assert g.np.allclose(reimported_mesh.vertex_normals[0], [0, 0, 0]) diff --git a/tests/test_obj.py b/tests/test_obj.py index 8000ff327..226781f09 100644 --- a/tests/test_obj.py +++ b/tests/test_obj.py @@ -110,7 +110,7 @@ def test_obj_simple_order(self): m = g.trimesh.load(file_name, process=False) # use trivial loading to compare with fancy performant one with open(file_name) as f: - f, v, vt = simple_load(f.read()) + f, v, _vt = simple_load(f.read()) # trimesh loader should return the same face order assert g.np.allclose(f, m.faces) assert g.np.allclose(v, m.vertices) @@ -123,7 +123,7 @@ def test_order_tex(self): m = g.trimesh.load(file_name, process=False, maintain_order=True) # use trivial loading to compare with fancy performant one with open(file_name) as f: - f, v, vt = simple_load(f.read()) + f, v, _vt = simple_load(f.read()) # trimesh loader should return the same face order assert g.np.allclose(f, m.faces) assert g.np.allclose(v, m.vertices) @@ -448,7 +448,7 @@ def test_export_normals(self): def test_export_mtl_args(self): mesh = g.trimesh.creation.box() # check for a crash with no materials defined - a, b = g.trimesh.exchange.obj.export_obj( + _a, _b = g.trimesh.exchange.obj.export_obj( mesh, return_texture=True, mtl_name="hi.mtl" ) diff --git a/tests/test_packing.py b/tests/test_packing.py index c56437232..6b500ee00 100644 --- a/tests/test_packing.py +++ b/tests/test_packing.py @@ -72,7 +72,7 @@ def test_obb(self): from trimesh.path import packing nestable = [g.Polygon(i) for i in g.data["nestable"]] - inserted, transforms = packing.polygons(nestable) + _inserted, _transforms = packing.polygons(nestable) def test_image(self): from trimesh.path import packing @@ -157,11 +157,11 @@ def test_3D(self): ) # try packing these 3D boxes - bounds, consume = packing.rectangles_single(e) + _bounds, consume = packing.rectangles_single(e) assert consume.all() # try packing these 3D boxes - bounds, consume = packing.rectangles_single(e, size=[14, 14, 1]) + _bounds, consume = packing.rectangles_single(e, size=[14, 14, 1]) assert not consume.all() def test_transform(self): diff --git a/tests/test_paths.py b/tests/test_paths.py index 1230e4cc1..61c2a44dd 100644 --- a/tests/test_paths.py +++ b/tests/test_paths.py @@ -282,7 +282,7 @@ def test_section(self): ) # Path3D -> Path2D - planar, T = section.to_planar() + planar, _T = section.to_planar() # tube should have one closed polygon assert len(planar.polygons_full) == 1 diff --git a/tests/test_permutate.py b/tests/test_permutate.py index 47debca74..96298c003 100644 --- a/tests/test_permutate.py +++ b/tests/test_permutate.py @@ -22,7 +22,7 @@ def make_assertions(mesh, test, rigid=False): close(test.face_adjacency, mesh.face_adjacency) and len(mesh.faces) > MIN_FACES ): - g.log.error(f"face_adjacency unchanged: {str(test.face_adjacency)}") + g.log.error(f"face_adjacency unchanged: {test.face_adjacency!s}") raise ValueError( "face adjacency of %s the same after permutation!", mesh.metadata["file_name"], @@ -33,7 +33,7 @@ def make_assertions(mesh, test, rigid=False): and len(mesh.faces) > MIN_FACES ): g.log.error( - f"face_adjacency_edges unchanged: {str(test.face_adjacency_edges)}" + f"face_adjacency_edges unchanged: {test.face_adjacency_edges!s}" ) raise ValueError( "face adjacency edges of %s the same after permutation!", diff --git a/tests/test_points.py b/tests/test_points.py index 4c28953ba..1b3724eaf 100644 --- a/tests/test_points.py +++ b/tests/test_points.py @@ -102,7 +102,7 @@ def test_plane(self): # so the true normal should be Z then rotated truth = g.trimesh.transform_points([[0, 0, 1]], matrix, translate=False)[0] # run the plane fit - C, N = g.trimesh.points.plane_fit(p) + _C, N = g.trimesh.points.plane_fit(p) # sign of normal is arbitrary on fit so check both assert g.np.allclose(truth, N) or g.np.allclose(truth, -N) # make sure plane fit works with multiple point sets at once @@ -130,7 +130,7 @@ def test_plane(self): [[0, 0, 1]], matrix, translate=False )[0] # run the plane fit - C, N = g.trimesh.points.plane_fit(p) + _C, N = g.trimesh.points.plane_fit(p) # sign of normal is arbitrary on fit so check both cosines = g.np.einsum("ij,ij->i", N, truths) diff --git a/tests/test_polygons.py b/tests/test_polygons.py index 9b204567e..005923da8 100644 --- a/tests/test_polygons.py +++ b/tests/test_polygons.py @@ -71,7 +71,7 @@ def test_sample(self): assert radius < (1.0 + 1e-8) # try getting OBB of samples - T, extents = g.trimesh.path.polygons.polygon_obb(s) + _T, extents = g.trimesh.path.polygons.polygon_obb(s) # OBB of samples should be less than diameter of circle diameter = g.np.reshape(p.bounds, (2, 2)).ptp(axis=0).max() assert (extents <= diameter).all() @@ -260,7 +260,7 @@ def test_native_centroid(self): for p, c in zip(polygons, coords): # area will be signed with respect to counter-clockwise - ccw, area, centroid = g.trimesh.util.is_ccw(c, return_all=True) + _ccw, area, centroid = g.trimesh.util.is_ccw(c, return_all=True) assert g.np.allclose(centroid, g.np.array(p.centroid.coords)[0]) assert g.np.isclose(abs(area), p.area) diff --git a/tests/test_poses.py b/tests/test_poses.py index 4b183c8c2..43dc4adda 100644 --- a/tests/test_poses.py +++ b/tests/test_poses.py @@ -29,7 +29,7 @@ def test_multiple(self): copied.apply_transform(matrix) # Compute the stable poses of the icosahedron - trans, probs = copied.compute_stable_poses() + _trans, probs = copied.compute_stable_poses() # we are only testing primitives with point symmetry # AKA 3 principal components of inertia are the same @@ -43,8 +43,8 @@ def test_multiple(self): def test_round(self): mesh = g.trimesh.primitives.Cylinder(radius=1.0, height=10.0) - transforms, probabilities = mesh.compute_stable_poses() - transforms, probabilities = mesh.compute_stable_poses(n_samples=10) + _transforms, _probabilities = mesh.compute_stable_poses() + _transforms, _probabilities = mesh.compute_stable_poses(n_samples=10) if __name__ == "__main__": diff --git a/tests/test_proximity.py b/tests/test_proximity.py index 93bd38dbe..83d6cdf44 100644 --- a/tests/test_proximity.py +++ b/tests/test_proximity.py @@ -20,7 +20,7 @@ def test_naive(self): triangles = sphere.triangles # NOQA # do the check - closest, distance, tid = g.trimesh.proximity.closest_point_naive(sphere, points) + closest, distance, _tid = g.trimesh.proximity.closest_point_naive(sphere, points) # the distance from a sphere of radius 1.0 to a sphere of radius 2.0 # should be pretty darn close to 1.0 @@ -98,7 +98,7 @@ def points_on_circle(count): # create a mesh with one triangle mesh = g.Trimesh(**g.trimesh.triangles.to_kwargs([triangle])) - result, result_distance, result_tid = fun(mesh, query) + result, result_distance, _result_tid = fun(mesh, query) polygon = g.Polygon(triangle[:, 0:2]) polygon_buffer = polygon.buffer(1e-5) diff --git a/tests/test_ray.py b/tests/test_ray.py index 46c4f1d6c..37493e955 100644 --- a/tests/test_ray.py +++ b/tests/test_ray.py @@ -102,7 +102,7 @@ def test_on_vertex(self): assert m.ray.intersects_any(ray_origins=origins, ray_directions=vectors).all() - (locations, index_ray, index_tri) = m.ray.intersects_location( + (_locations, index_ray, _index_tri) = m.ray.intersects_location( ray_origins=origins, ray_directions=vectors ) @@ -146,14 +146,14 @@ def test_multiple_hits(self): # Perform 256 * 256 raycasts, one for each pixel on the image # plane. We only want the 'first' hit. - index_triangles, index_ray = cube_mesh.ray.intersects_id( + index_triangles, _index_ray = cube_mesh.ray.intersects_id( ray_origins=ray_origins, ray_directions=ray_directions, multiple_hits=False, ) assert len(g.np.unique(index_triangles)) == 2 - index_triangles, index_ray = cube_mesh.ray.intersects_id( + index_triangles, _index_ray = cube_mesh.ray.intersects_id( ray_origins=ray_origins, ray_directions=ray_directions, multiple_hits=True ) assert len(g.np.unique(index_triangles)) > 2 @@ -192,7 +192,7 @@ def test_box(self): # (n,3) float intersection position in space # (n,) int, index of original ray # (m,) int, index of mesh.faces - pos, ray, tri = mesh.ray.intersects_location( + pos, ray, _tri = mesh.ray.intersects_location( ray_origins=origins, ray_directions=vectors ) @@ -218,7 +218,7 @@ def test_broken(self): for kwargs in [{"use_embree": True}, {"use_embree": False}]: mesh = g.get_mesh("broken.STL", **kwargs) - locations, index_ray, index_tri = mesh.ray.intersects_location( + locations, _index_ray, _index_tri = mesh.ray.intersects_location( ray_origins=ray_origins, ray_directions=ray_directions ) diff --git a/tests/test_registration.py b/tests/test_registration.py index a295a9c9a..0a7025a66 100644 --- a/tests/test_registration.py +++ b/tests/test_registration.py @@ -109,8 +109,8 @@ def test_icp_mesh(self): # see if ICP alignment works with meshes m = g.trimesh.creation.box() X = m.sample(10) - X = X + [0.1, 0.1, 0.1] - matrix, transformed, cost = g.trimesh.registration.icp(X, m, scale=False) + X = [*X, 0.1, 0.1, 0.1] + _matrix, _transformed, cost = g.trimesh.registration.icp(X, m, scale=False) assert cost < 0.01 def test_icp_points(self): @@ -157,7 +157,7 @@ def test_mesh(self): truth = g.trimesh.creation.box(extents=extents) for a, b in [[truth, scan], [scan, truth]]: - a_to_b, cost = a.register(b) + a_to_b, _cost = a.register(b) a_check = a.copy() a_check.apply_transform(a_to_b) @@ -172,7 +172,7 @@ def test_mesh(self): points = g.trimesh.transform_points( scan.sample(100), matrix=g.trimesh.transformations.random_rotation_matrix() ) - truth_to_points, cost = truth.register(points) + truth_to_points, _cost = truth.register(points) truth.apply_transform(truth_to_points) distance = truth.nearest.on_surface(points)[1] diff --git a/tests/test_render.py b/tests/test_render.py index 052fd0128..8af7944c9 100644 --- a/tests/test_render.py +++ b/tests/test_render.py @@ -33,7 +33,7 @@ def test_args(self): assert len(args) == 6 assert len(args_auto) == len(args) - P20, T = P30.to_planar() + P20, _T = P30.to_planar() args = rendering.path_to_vertexlist(P20) args_auto = rendering.convert_to_vertexlist(P20) assert len(args) == 6 diff --git a/tests/test_sample.py b/tests/test_sample.py index f9f42f0e5..a34e2094d 100644 --- a/tests/test_sample.py +++ b/tests/test_sample.py @@ -14,7 +14,7 @@ def test_sample(self): distance = m.nearest.signed_distance(samples) assert g.np.abs(distance).max() < 1e-4 - even, index = g.trimesh.sample.sample_surface_even(m, 1000) + even, _index = g.trimesh.sample.sample_surface_even(m, 1000) # check to make sure all samples are on the mesh surface distance = m.nearest.signed_distance(even) assert g.np.abs(distance).max() < 1e-4 @@ -27,7 +27,7 @@ def test_weights(self): weights[0] = 1.0 # sample with passed weights - points, fid = m.sample(count=100, return_index=True, face_weight=weights) + _points, fid = m.sample(count=100, return_index=True, face_weight=weights) # all faces should be on single face assert (fid == 0).all() @@ -42,13 +42,13 @@ def test_color(self): # sample a textured mesh m = g.get_mesh("fuze.obj") - points, index, color = g.trimesh.sample.sample_surface(m, 100, sample_color=True) + points, _index, color = g.trimesh.sample.sample_surface(m, 100, sample_color=True) assert len(points) == len(color) # sample a color mesh m = g.get_mesh("machinist.XAML") assert m.visual.kind == "face" - points, index, color = g.trimesh.sample.sample_surface(m, 100, sample_color=True) + points, _index, color = g.trimesh.sample.sample_surface(m, 100, sample_color=True) assert len(points) == len(color) def test_sample_volume(self): diff --git a/tests/test_section.py b/tests/test_section.py index 2b8e91710..20c6cb040 100644 --- a/tests/test_section.py +++ b/tests/test_section.py @@ -57,7 +57,7 @@ def test_section(self): assert g.np.allclose(section.vertices[:, 2], z) assert len(section.centroid) == 3 - planar, to_3D = section.to_planar() + planar, _to_3D = section.to_planar() assert planar.is_closed assert len(planar.polygons_full) > 0 assert len(planar.centroid) == 2 @@ -72,7 +72,7 @@ def test_section(self): ) # call the multiplane method directly - lines, faces, T = g.trimesh.intersections.mesh_multiplane( + lines, _faces, _T = g.trimesh.intersections.mesh_multiplane( mesh=mesh, plane_origin=[0, 0, 0], plane_normal=plane_normal, diff --git a/tests/test_segments.py b/tests/test_segments.py index 7a023155c..86f44e596 100644 --- a/tests/test_segments.py +++ b/tests/test_segments.py @@ -107,7 +107,7 @@ def test_resample(self): assert g.np.isclose(length(res), length(seg)) # now try with indexes returned - res, index = resample(seg, maxlen=maxlen, return_index=True) + res, _index = resample(seg, maxlen=maxlen, return_index=True) # check lengths of the resampled result assert (length(res, summed=False) < maxlen).all() # make sure overall length hasn't changed diff --git a/tests/test_simplify.py b/tests/test_simplify.py index f9eacd69c..45e4529e9 100644 --- a/tests/test_simplify.py +++ b/tests/test_simplify.py @@ -64,7 +64,7 @@ def test_spline(self): m = scene.geometry["disc_cam_A"] path_3D = m.outline(m.facets[m.facets_area.argmax()]) - path_2D, to_3D = path_3D.to_planar() + path_2D, _to_3D = path_3D.to_planar() simple = g.trimesh.path.simplify.simplify_spline( path_2D, smooth=0.01, verbose=True diff --git a/tests/test_smooth.py b/tests/test_smooth.py index 2f81e1384..66e786b5a 100644 --- a/tests/test_smooth.py +++ b/tests/test_smooth.py @@ -13,7 +13,7 @@ def test_smooth(self): check = g.np.hstack((s.visual.uv, s.vertices)) tree = g.spatial.cKDTree(ori) - distances, index = tree.query(check, k=1) + distances, _index = tree.query(check, k=1) assert distances.max() < 1e-8 # g.texture_equal(m, s) diff --git a/tests/test_stl.py b/tests/test_stl.py index bf82e41fa..151e0c80f 100644 --- a/tests/test_stl.py +++ b/tests/test_stl.py @@ -75,7 +75,10 @@ def test_ascii_multibody(self): def test_ascii_solid_name(self): mesh = g.trimesh.creation.icosphere(subdivisions=1, radius=1.0) mesh.metadata = {"name": "solid_A"} - assert g.trimesh.exchange.stl.export_stl_ascii(mesh).splitlines()[0] == "solid solid_A" + assert ( + g.trimesh.exchange.stl.export_stl_ascii(mesh).splitlines()[0] + == "solid solid_A" + ) def test_empty(self): # demo files to check diff --git a/tests/test_visual.py b/tests/test_visual.py index af8da5b7f..01816a73e 100644 --- a/tests/test_visual.py +++ b/tests/test_visual.py @@ -15,7 +15,7 @@ def test_face_subset_texture_visuals(self): check = m.visual.face_subset(face_index).uv tree = g.spatial.cKDTree(ori) - distances, index = tree.query(check, k=1) + distances, _index = tree.query(check, k=1) assert distances.max() < 1e-8 def test_face_subset_color_visuals(self): @@ -33,7 +33,7 @@ def test_face_subset_color_visuals(self): check = m.visual.face_subset(face_index).vertex_colors tree = g.spatial.cKDTree(ori) - distances, index = tree.query(check, k=1) + distances, _index = tree.query(check, k=1) assert distances.max() < 1e-8 # def test_face_subset_vertex_color(self): diff --git a/trimesh/creation.py b/trimesh/creation.py index f2d12b3dd..55138cdfe 100644 --- a/trimesh/creation.py +++ b/trimesh/creation.py @@ -1452,7 +1452,11 @@ def torus( Mesh of a torus """ phi = np.linspace(0, 2 * np.pi, minor_sections, endpoint=False) - linestring = [*np.column_stack((minor_radius * np.cos(phi), minor_radius * np.sin(phi))), major_radius, 0] + linestring = [ + *np.column_stack((minor_radius * np.cos(phi), minor_radius * np.sin(phi))), + major_radius, + 0, + ] if "metadata" not in kwargs: kwargs["metadata"] = {} diff --git a/trimesh/exchange/load.py b/trimesh/exchange/load.py index 0ac7c0987..34f71c0a9 100644 --- a/trimesh/exchange/load.py +++ b/trimesh/exchange/load.py @@ -214,9 +214,7 @@ def load_mesh( loaded = loaded[0] # show the repr for loaded, loader used, and time - log.debug( - f"loaded {loaded!s} using `{loader.__name__}` in {now() - tic:0.4f}s" - ) + log.debug(f"loaded {loaded!s} using `{loader.__name__}` in {now() - tic:0.4f}s") finally: # if we failed to load close file if opened: diff --git a/trimesh/util.py b/trimesh/util.py index 78a1de197..aaf03d00c 100644 --- a/trimesh/util.py +++ b/trimesh/util.py @@ -237,10 +237,8 @@ def is_sequence(obj) -> bool: is_sequence : bool True if object is sequence """ - seq = ( - (not hasattr(obj, "strip") - and hasattr(obj, "__getitem__")) - or hasattr(obj, "__iter__") + seq = (not hasattr(obj, "strip") and hasattr(obj, "__getitem__")) or hasattr( + obj, "__iter__" ) # check to make sure it is not a set, string, or dictionary From 5a2f1a8dbea99a70b03d86a8c5ededee1a62ac20 Mon Sep 17 00:00:00 2001 From: Michael Dawson-Haggerty Date: Thu, 28 Mar 2024 13:40:06 -0400 Subject: [PATCH 04/11] revert incorrect array extends --- trimesh/creation.py | 3 ++- trimesh/path/exchange/dxf.py | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/trimesh/creation.py b/trimesh/creation.py index 55138cdfe..6596d58ae 100644 --- a/trimesh/creation.py +++ b/trimesh/creation.py @@ -382,8 +382,9 @@ def extrude_triangulation( # a sequence of zero- indexed faces, which will then be appended # with offsets to create the final mesh + heights = np.array([0.0, 0.0, height], dtype=np.float64) faces_seq = [faces[:, ::-1], faces.copy(), vertical_faces] - vertices_seq = [vertices_3D, [*vertices_3D.copy(), 0.0, 0, height], vertical] + vertices_seq = [vertices_3D, vertices_3D.copy() + heights, vertical] # append sequences into flat nicely indexed arrays vertices, faces = util.append_faces(vertices_seq, faces_seq) diff --git a/trimesh/path/exchange/dxf.py b/trimesh/path/exchange/dxf.py index 0d4626798..36673ea41 100644 --- a/trimesh/path/exchange/dxf.py +++ b/trimesh/path/exchange/dxf.py @@ -363,7 +363,7 @@ def convert_text(e): # origin point origin = np.array([e["10"], e["20"]], dtype=np.float64) # an origin-relative point (so transforms work) - vector = [*origin, np.cos(angle), np.sin(angle)] + vector = origin + np.array([np.cos(angle), np.sin(angle)], dtype=np.float64) # try to extract a (horizontal, vertical) text alignment align = ["center", "center"] try: From debdc81b8dace5eb03587f15e3b3a70bbfb6527a Mon Sep 17 00:00:00 2001 From: Michael Dawson-Haggerty Date: Thu, 28 Mar 2024 15:10:28 -0400 Subject: [PATCH 05/11] more RUF005 reverts --- pyproject.toml | 1 + trimesh/voxel/base.py | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index b1d51ac1e..f25c8a483 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -143,6 +143,7 @@ ignore = [ "E501", # Line too long ({width} > {limit} characters) "B904", # raise ... from err "B905", # zip() without an explicit strict= parameter + "RUF005", # recommends non-type-aware expansion ] # don't allow implicit string concatenation diff --git a/trimesh/voxel/base.py b/trimesh/voxel/base.py index 24ad67269..502163cf9 100644 --- a/trimesh/voxel/base.py +++ b/trimesh/voxel/base.py @@ -413,7 +413,7 @@ def revoxelized(self, shape): shape = tuple(shape) bounds = self.bounds.copy() extents = self.extents - points = util.grid_linspace(bounds, shape).reshape((*shape, 3)) + points = util.grid_linspace(bounds, shape).reshape(shape + (3,)) dense = self.is_filled(points) scale = extents / np.asanyarray(shape) translate = bounds[0] From 0aabb759c767a5269353c5f6142f6f66cb67ad31 Mon Sep 17 00:00:00 2001 From: Michael Dawson-Haggerty Date: Thu, 28 Mar 2024 15:11:47 -0400 Subject: [PATCH 06/11] revert dxf --- trimesh/path/exchange/dxf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/trimesh/path/exchange/dxf.py b/trimesh/path/exchange/dxf.py index 36673ea41..32140681e 100644 --- a/trimesh/path/exchange/dxf.py +++ b/trimesh/path/exchange/dxf.py @@ -363,7 +363,7 @@ def convert_text(e): # origin point origin = np.array([e["10"], e["20"]], dtype=np.float64) # an origin-relative point (so transforms work) - vector = origin + np.array([np.cos(angle), np.sin(angle)], dtype=np.float64) + vector = origin + [np.cos(angle), np.sin(angle)] # try to extract a (horizontal, vertical) text alignment align = ["center", "center"] try: From 025d8085679d62606925fd8ec90167a14d2ef22e Mon Sep 17 00:00:00 2001 From: Michael Dawson-Haggerty Date: Thu, 28 Mar 2024 15:13:15 -0400 Subject: [PATCH 07/11] revert RUF005 on creation --- trimesh/creation.py | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/trimesh/creation.py b/trimesh/creation.py index 6596d58ae..e7afcec23 100644 --- a/trimesh/creation.py +++ b/trimesh/creation.py @@ -382,9 +382,8 @@ def extrude_triangulation( # a sequence of zero- indexed faces, which will then be appended # with offsets to create the final mesh - heights = np.array([0.0, 0.0, height], dtype=np.float64) faces_seq = [faces[:, ::-1], faces.copy(), vertical_faces] - vertices_seq = [vertices_3D, vertices_3D.copy() + heights, vertical] + vertices_seq = [vertices_3D, vertices_3D.copy() + [0.0, 0, height], vertical] # append sequences into flat nicely indexed arrays vertices, faces = util.append_faces(vertices_seq, faces_seq) @@ -1453,11 +1452,9 @@ def torus( Mesh of a torus """ phi = np.linspace(0, 2 * np.pi, minor_sections, endpoint=False) - linestring = [ - *np.column_stack((minor_radius * np.cos(phi), minor_radius * np.sin(phi))), - major_radius, - 0, - ] + linestring = np.column_stack( + (minor_radius * np.cos(phi), minor_radius * np.sin(phi)) + ) + [major_radius, 0] if "metadata" not in kwargs: kwargs["metadata"] = {} From 4c7dab8729096c6e174d4d3e759521fdb451e6b2 Mon Sep 17 00:00:00 2001 From: Michael Dawson-Haggerty Date: Thu, 28 Mar 2024 15:13:29 -0400 Subject: [PATCH 08/11] version bump --- pyproject.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pyproject.toml b/pyproject.toml index f25c8a483..4d4bdc156 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ requires = ["setuptools >= 61.0", "wheel"] [project] name = "trimesh" requires-python = ">=3.7" -version = "4.2.2" +version = "4.2.3" authors = [{name = "Michael Dawson-Haggerty", email = "mikedh@kerfed.com"}] license = {file = "LICENSE.md"} description = "Import, export, process, analyze and view triangular meshes." From 42d0063843bf0336aed88676ca28af2e3c3ded09 Mon Sep 17 00:00:00 2001 From: Michael Dawson-Haggerty Date: Thu, 28 Mar 2024 15:44:13 -0400 Subject: [PATCH 09/11] revert RUF005 in test --- tests/test_registration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_registration.py b/tests/test_registration.py index 0a7025a66..44f422cfb 100644 --- a/tests/test_registration.py +++ b/tests/test_registration.py @@ -109,7 +109,7 @@ def test_icp_mesh(self): # see if ICP alignment works with meshes m = g.trimesh.creation.box() X = m.sample(10) - X = [*X, 0.1, 0.1, 0.1] + X = X + [0.1, 0.1, 0.1] _matrix, _transformed, cost = g.trimesh.registration.icp(X, m, scale=False) assert cost < 0.01 From 6bb7cb10dc6a8e3ec98924303032316e7f5785b9 Mon Sep 17 00:00:00 2001 From: Amin Yahyaabadi Date: Thu, 28 Mar 2024 16:14:59 -0700 Subject: [PATCH 10/11] fix: export Geometry to allow referencing the load_mesh return type Because Geometry is not exported, it's not possible to use `trimesh.parent.Geometry` in a typed Python expression like this: ```py mesh: List[trimesh.parent.Geometry] ``` This PR fixes it --- trimesh/__init__.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/trimesh/__init__.py b/trimesh/__init__.py index 829869223..d680934b6 100644 --- a/trimesh/__init__.py +++ b/trimesh/__init__.py @@ -41,6 +41,7 @@ ) # geometry objects +from .parent import Geometry from .base import Trimesh # general numeric tolerances @@ -73,6 +74,7 @@ __all__ = [ "PointCloud", + "Geometry", "Trimesh", "Scene", "util", From c512b2f28b570f33cd2d2d1f48483a2e1557a492 Mon Sep 17 00:00:00 2001 From: Michael Dawson-Haggerty Date: Fri, 29 Mar 2024 14:52:47 -0400 Subject: [PATCH 11/11] ruff --- trimesh/__init__.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/trimesh/__init__.py b/trimesh/__init__.py index 72bc81600..7a0472089 100644 --- a/trimesh/__init__.py +++ b/trimesh/__init__.py @@ -39,9 +39,6 @@ units, util, ) - -# geometry objects -from .parent import Geometry from .base import Trimesh # general numeric tolerances @@ -49,6 +46,9 @@ # loader functions from .exchange.load import available_formats, load, load_mesh, load_path, load_remote + +# geometry objects +from .parent import Geometry from .points import PointCloud from .scene.scene import Scene from .transformations import transform_points