简体   繁体   中英

Matplotlib fill between slices

I'm working on creating a 3D-printer slicing algorithm in python. The algorithm uses numpy-STL to load an .stl into a numpy array and then calculates the intersection of some horizontal plane and the meshed triangles. I have succesfully managed to calculate the intersects and store the intersection points within another numpy array(format: [x1 y1 z1 x2 y2 z2 x3 y3 z3]). I then extract x vectors and y vectors for each slice and store them for plotting.

The problem comes when trying to visualize these slices. If I plot a scatter plot using:

import matplotlib as plt
plt.scatter(x_vec,y_vec)

I get: 环 Which is exactly what I'd expect.

However, when I try to connect the segments using:

plt.plot(x_vec,y_vec)

I get weird connections of lines between points that aren't local to each other: 怪异的线 . The shape I'm trying to slice here is a simple ring. I can't see any extraneous points when inspecting the scatter plot directly and when combing through the point data by hand it appears they are all ordered correctly as well.

Is this a problem with how matplotlib connects the nearest lines? If I use fill_between it gets very confused about which sections are interior and which aren't. Does mplot3D have a solution if I view multiple slices stacked in 3D? I've tried this with:

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')
ax.plot(x_vec, y_vec, z_vec, color = 'b')

but its the same thing just in 3D. Any advice on visualizing these slices? Other packages etc?

I think the connected lines are a result of how the slicer returns the numpy data. This function takes the array of (m,9) triangles and returns either (1,3) (1,6) or (1,9) arrays depending on the conditions:

def get_intersects(tri_entry, layer_h):
    # Calculate intersections for current triangles
    # 4 Cases

    # Case 1: 3 vertices on plane
    if check_points(tri_entry[2::3], layer_h) == 3:
        return tri_entry

    # Case 2: 2 vertices on plane
    if check_points(tri_entry[2::3], layer_h) == 2:
        return coords_on_plane(tri_entry, layer_h)

    # Case 3: 1 vertex on plane
    if check_points(tri_entry[2::3], layer_h) == 1:
        # 2 Sub cases

        # (1) Other 2 points on opposited sides of slice
        if check_z(tri_entry, layer_h) == 0:
            intersect = vec_intersect(tri_entry, layer_h)
            return np.hstack((intersect, coords_on_plane(tri_entry, layer_h)))

        # (2) Other 2 points on same side of slice
        if check_z(tri_entry, layer_h) == 1:
            return coords_on_plane(tri_entry, layer_h)

    # Case 4: 0 vertices on plane
    if check_points(tri_entry[2::3], layer_h) == 0:
       # Check which lines interesct
       a =  vec_intersect(tri_entry[0:6], layer_h)
       b =  vec_intersect(tri_entry[3:9], layer_h)
       c =  vec_intersect(tri_entry[[0,1,2,6,7,8]], layer_h)
       intersect = np.hstack((a, b, c))
       intersect = list(filter(None.__ne__,  intersect))
       return np.asarray(intersect) 

Trying to pass a vectorized list of all x's and y's without considering the dependence of the points is where I went wrong. I tried plotting each case separately and found this: Zoomed-colored

Single points are in red, two point segments in green, and 3 point segments in blue.

If you already have triangles at your disposal, you may want to look at plt.tripcolor . Since the exact dataformat you have is unclear, I can give no further help about that here.

Apart from that, you can split the data points into those of the inner and outer circle respectively and plot a filled Polygon of some color for the outer values. Then, draw a Polygon with the backgroundcolor for the inner values. The result will look like you have a ring there.

import matplotlib.pyplot as plt
import numpy as np

phi1 = np.linspace(0,2*np.pi)
x1 = np.cos(phi1)
y1 = -np.sin(phi1)

phi2 = np.linspace(0.06,2*np.pi+0.06)
x2 = 0.9*np.cos(phi2)
y2 = -0.9*np.sin(phi2)

fig, ax=plt.subplots()

p1 = plt.Polygon(np.c_[x1,y1], color="lightskyblue")
ax.add_patch(p1)
p2 = plt.Polygon(np.c_[x2,y2], color="white")
ax.add_patch(p2)

ax.scatter(x1,y1, s=10, zorder=4)
ax.scatter(x2,y2, s=10, zorder=4)

plt.show()

在此处输入图片说明

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM