mikedh / trimesh

Python library for loading and using triangular meshes.
https://trimesh.org
MIT License
3.02k stars 583 forks source link

Need help getting edges, with specific angles, and coloring them #2190

Closed Neiizo closed 8 months ago

Neiizo commented 8 months ago

Hi !

I am new to trimesh, and first, i'd like to thank you for your work ! The library seems extremely complete! This is also the reason for this post

I'd like to make a code that would detect all the corners in a mesh, and highlight them. At first, I wanted to hard code everything, but I realised there's already a lot available inside the library.

First, I saw Issue#1997, which helped me visualize the triangle individually. But is it normal this doesn't work properly inside a jupyter notebook?

But then, I saw issue#1260, which shows the adjacency angle threshold. However, regardless of the threshold, facets would provide the same results. Maybe I misunderstood how to use ?

And finally, I would like to highlight the corners that were found, like with a red line going along the entire corner found, but I didn't seem to find anything in the library that does this. Is this correct ? I have found how to colors faces, and how to get the edges, with .visual.face_colors, and .edges, but not how to color an edge. Is there any implementation already in trimesh that I did not find? If not, is there an approach you would recommend for this?

Thanks a lot !

mikedh commented 8 months ago

Hey, yeah the jupyter notebook support is pretty rudimentary. You might want a more visualization-focused library like vedo. Edges in meshes don't have colors, but you could make a scene with a Path3D and the mesh. If you want to find edges that are contained by pairs of faces with right angles you could do something like this:

In [1]: import numpy as np

In [2]: import trimesh

In [3]: m = trimesh.load('models/featuretype.STL')

In [5]: edges = np.isclose(m.face_adjacency_angles, np.radians(90))

In [6]: edges
Out[6]: array([ True, False, False, ..., False,  True,  True])

In [8]: trimesh.load_path(m.vertices[m.face_adjacency_edges[edges]])
Out[8]: <trimesh.Path3D(vertices.shape=(1698, 3), len(entities)=77)>

In [9]: right_angles = trimesh.load_path(m.vertices[m.face_adjacency_edges[edges]])

In [10]: right_angles.show()
Out[10]: SceneViewer(width=2403, height=1606)

In [11]: trimesh.Scene([m, right_angles]).show()
Out[11]: SceneViewer(width=1855, height=1427)

Screenshot from 2024-03-25 16-16-57

Neiizo commented 8 months ago

Hi ! Thanks a lot for highlighting this to me ! I ended up writing a codes that takes the normals of every faces and compares it to the normal of its neighbors. But now that you've shown this to me, I managed to make it even faster. The previous code was taking 2-3 min to execute for a mesh with ~150'000 faces. Now it only takes 2 secondes.

Here is my code

import trimesh
import numpy as np
car = trimesh.load_mesh('../example_car/meshes/10716a366de708b8fac96522b26f7fd.obj')

angle_threshold = 14 ## [radian] : angle above which we consider there's an angle between two faces
edges = car.face_adjacency_angles>= np.radians(angle_threshold)
id_to_color = np.unique((car.face_adjacency[edges,0], car.face_adjacency[edges,1]))
car.visual.face_colors[id_to_color] = [255, 0, 0, 255]

car.show()

We decided to work with the faces instead, for our neural network, and use their normal vector. However, I have another issue, that I didn't have in my previous algorithm. This code produces the following image image. However, in my previous code, I wanted to make those area a bit broader. I wanted to take the neighbors of the neighbors. So if two faces shares an angle above my threshold, I would take these 2 faces, and increase the area by taking the 4 others neighbors of these 2 faces ( 2 for each faces). This image showcases what I want to fix/fillimage I wanted to implement this by adding id_to_color = np.unique((id_to_color, car.face_adjacency[id_to_color,1])), however, it absolutely doesn't yield the expected results: image Do you have any clue why it is doing so ?