I would like to create 2D cross-sections from 3D files, without losing the information of what is material and what is air.
In the end, I would like to obtain a dictionary which contains the outer-most points that make up the material and air inclusions (can be multiple), i.e.
"material" : [[x1,y1],[x2,y2]...]
"air_inclusions": [[[x11,y11],[x12,y12],...],[[x21,y21],[x22,y22],...],[[x31,y31],[x32,y32],...]]
Here is an example of how I am trying to do it:
I have the following .stl file, which you can download here https://filebin.net/c9o0zy4bnv8dvuew
Using the amazing python package trimesh, I can import the .stl file
import trimesh
import numpy as np
mesh = trimesh.load_mesh(r"PATH_TO_FILE")
# give it a color
mesh.visual.face_colors = [100, 100, 100, 255]
# and show it
mesh.show(viewer='gl')
Creating the 2D slide
# I can create a 2D slice of the geometry at origin [0,0,5] and slice-plane with normal direction [0,0,1]
slice = mesh.section(plane_origin=[0,0,5],
plane_normal=[0,0,1])
slice.show(viewer='gl')
Extracting the vertices
# take 2D slice (before was still 3D)
slice_2D, to_3D = slice.to_planar()
# get vertices
vertices = np.asanyarray(slice_2D.vertices)
# plot
import matplotlib.pyplot as plt
x,y = vertices.T
plt.scatter(x,y,s=0.4)
plt.show()
My approach to retrieve the information about what is material and what is air
My assumption
The outer most points define the border for the material. All points within define the border of air inclusions.
I get the outer most point -> convex hull
from scipy.spatial import ConvexHull
# compute the hull
hull = ConvexHull(vertices)
# plot
plt.plot(vertices[:,0], vertices[:,1], 'o')
for simplex in hull.simplices:
plt.plot(vertices[simplex, 0], vertices[simplex, 1], 'k-')
To know all the points inside of the hull, I use this answer What's an efficient way to find if a point lies in the convex hull of a point cloud?
# Source: https://stackoverflow.com/questions/16750618/whats-an-efficient-way-to-find-if-a-point-lies-in-the-convex-hull-of-a-point-cl
def in_hull(p, hull):
"""
Test if points in `p` are in `hull`
`p` should be a `NxK` coordinates of `N` points in `K` dimensions
`hull` is either a scipy.spatial.Delaunay object or the `MxK` array of the
coordinates of `M` points in `K`dimensions for which Delaunay triangulation
will be computed
"""
from scipy.spatial import Delaunay
if not isinstance(hull,Delaunay):
hull = Delaunay(hull)
return hull.find_simplex(p)>=0
I gather the remaining points
# Remaining points
remaining = []
for i,in_hull in enumerate(in_hull(vertices,hull.simplices)):
if in_hull:
remaining.append(vertices[i])
The issues
The remaining points are only two points, but it should be many more, as can be seen in the plot above. Why is that and how can I fix it?
[TrackedArray([21.60581633, 8.99397324]), TrackedArray([12.95590211, 23.97608075])]
Do you have any idea of how I could find all air inclusions if there are more than one? i.e.
you can find the file here: https://filebin.net/6blzvrrwhanv0jib