Skip to content

Mesh3d generates inaccurate mesh #2194

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
zakutin opened this issue Feb 14, 2020 · 11 comments
Open

Mesh3d generates inaccurate mesh #2194

zakutin opened this issue Feb 14, 2020 · 11 comments
Labels
bug something broken P3 backlog

Comments

@zakutin
Copy link

zakutin commented Feb 14, 2020

Mesh3d creates useless or phantom "walls" on rendering. The issue was already described in 2016 here (case 1, case 2) but was abandoned without solution or any bug report. Recently, I met the same behavior with my data (see picture below, red lines drawn manually).

image
From another view the edges are displayed properly.
image
This shall be displayed in proper way. I tested it in with similar data in Wolfram Mathematica.
image
Attached data (Jupyter notebook, and CSV data):
error_plots_bug.zip

@empet
Copy link

empet commented Feb 14, 2020

When a Mesh3d is defined only by vertices (the faces are not given), then the Delaunay triangulation of this set is generated, to associate faces (triangles). The Delaunay triangulation of a set of 3D points is unique if no four points are coplanar.
When there exist at least 4 coplanar points, the triangulation is not unique, and the algorithm behind Mesh3d selects one of them. From a visual inspection of your points it follows that there exist 4 coplanar points. That's why the associated triangulation is not the one you are expecting.
Since you have only a few points in your example, you can give the desired list of faces to get a surface different from that in your image.

@zakutin
Copy link
Author

zakutin commented Feb 14, 2020

Your solution can be used as temporary workaround for small amount of points, because in that case this is not applicable.

In my case, three points on two sides indicated by red lines are located on the vertical planes, and form a phantom face. The same three points on the opposite sides of the plot located on vertical planes as well, but they are without face, as it should be. So why then the phantom faces are not formed from each side everywhere?

If you plot the unit cube with delaunayaxis = 'z' enabled and without ijk, you will not see the lateral sides of the cube. You can test it in this example by commenting out ijk and adding delaunayaxis = 'z'. This happens if Delaunay axis is co-planar to the lateral faces of the cube, the faces cannot exist in this case. This is a normal behavior.

So why the faces suddenly appears in my case above, and here and here?

Anyway, I suppose this is a bug with strange behavior.

@zakutin
Copy link
Author

zakutin commented Feb 17, 2020

Some info on this issue here (Stabbing Delaunay Tetrahedralizations, Jonathan Richard Shewchuk, University of California at Berkeley).

On page 3, figure 3 displays the proper wrapping (triangulation) of the point cloud from the bottom (lower convex hull).

@empet
Copy link

empet commented Feb 17, 2020

I analyzed more deeply your issue and I realized that you made an unsuitable choice for triangulating your point cloud.
There is no Plotly tutorial that illustrates or suggests that Plotly Mesh3d can triangulate surfaces,
because the purpose of Mesh3d isn't surface triangulation.

Just try to triangulate a sphere, starting from a point cloud generated on it and you'll have a bigger surprise than in the case of your shared data, that led to this issue.

Mesh3d can generate and plot four types of geometric objects, depending on the alphahull value
https://plot.ly/python/reference/#mesh3d-alphahull

  1. when alphahull =-1 (the default value) and are provided x, y, z, but not the lists for i, j, k,
    Mesh3d performs a tetrahedralization of the point cloud, via Delaunay 3d, and plots the tetrahedra faces.
    In the particular cases when the face normals have slight deviation from the direction of the axis defined by delaunayaxis ('z', 'x' or 'y') then Mesh3d identifies a surface of type z=f(x,y), x=g(y,z), respectively y= h(x, z), and can draw the surface
    approximated by the derived Delaunay triangulation, but it isn't always successful.

  2. when alphahull = -1, and x, y, z, i, j, k are provided, i.e. the vertex coordinates and faces of a surface triangulation, then Mesh3d generates the corresponding surface. From docs we find out that For general use of mesh3d it is preferred that i, j, k are supplied.

  3. for alphahull = 0 Mesh3d generates the convexhull of the point cloud defined by the lists x, y, z

  4. for alphahull> 0 Mesh3d yields an alpha-shape, with alpha = 1/alphahull https://plot.ly/python/alpha-shapes/

Your surface can be easily triangulated as follows:

  • project your points onto the xy plane and triangulate the resulting 2d points via scipy.spatial.Delaunay
  • Lift the triangulation to 3d space
    See https://plot.ly/~empet/15527.

Your generated Mathematica plot is generated in the same way, not using a 3d Delaunay triangulation as you did.

Any surface of equation z=f(x,y), as well as any parameterized surface can be triangulated and the corresponding x, y, z, i,j, k passed to the Mesh3d constructor.
https://plot.ly/~empet/15522.

For implicit surfaces of equation, F(x,y,z)=constant, Plotly provides the class go.Isosurface to carve that surface into a volume https://plot.ly/~empet/15143

You can also read a 3d mesh from an obj off, ply, or stl file and plot the corresponding Mesh3d.

Hence there are a lot of possibilities to use Plotly Mesh3d, but unfortunately I chose a wrong way to get your data triangulated.

@zakutin
Copy link
Author

zakutin commented Feb 17, 2020

@empet, thank you for you explanation, everything you wrote is right, there are different ways how to triangulate the point cloud, I'm aware of them :)

However, my point is about this exact default/pure Mesh3D method, without ijk, alphahull and other stuff defined. The problem is with default Mesh3D usage. In other words, the consistency issue.

Why the default Mesh3d method works on points 5-6-7 and 7-8-1, and suddenly does not work on points 1-2-3 and 3-4-5, even if they are coplanar and projected on a line?

image

The same happens here, with default Mesh3d implementation. By the way, I'm pretty sure that the wall-foming points in this example are coplanar as well and projected on the line.
image

Should the average user deal with this behavior as with usual/normal one, or this is a bug of Mesh3d (or math behind)?

@empet
Copy link

empet commented Feb 17, 2020

An user should read the Plotly docs and learn that Mesh3d is not devised to perform surface triangulation, and as a consequence to triangulate his point cloud using one of the methods I outlined in the answer above.

I repeat: The Mesh3d generates from x, y, z, a 3d Delaunay triangulation, i.e. a tetrahedralization.
Only planes orthogonal to the delaunayaxis can be triangulated when are provided only x, y, z.

@zakutin
Copy link
Author

zakutin commented Feb 17, 2020

@empet, let's abstract from everything written above.

Look, there is the "Simple 3D Mesh example", right the first one here. It tells me, that I can create a surface represented by a point cloud. Let's call it "surface", even if it is very rough. If you rotate it, it is a thin surface. I did the same with my points, because this feature is present in plotly and I can use it.

Please, understand me right, I'm not asking for technical support and the better way how to solve my task :) I'm just curious about this strange and rare behavior applicable to this simple mesh3d with xyz only.

Is it possible to explain, why do these walls appear, even if they should not be there?

@empet
Copy link

empet commented Feb 17, 2020

These are examples of tetrahedralization. They are generated from random 3d data, and exhibit vertical "walls", as tetrahedra faces. The same data, https://raw.githubusercontent.com/plotly/datasets/master/mesh_dataset.txt, generate the following tetrahedralization with `delaunayaxis='y':
delaunay-y

@zakutin
Copy link
Author

zakutin commented Feb 17, 2020

I got your point. If we change the delaunayaxis say to "x" the vertices of the tetrahedrons formed by the point cloud will form a surface "coated" from x direction. That is fine. That is clear.

So, why is there a wall from one side in my example and on the other side is not? Points 5-6-7 belong to one tetrahedron and points 1-2-3 belong to another one. In first case (5-6-7) there is no tetrahedron face, in another case (1-2-3) there is a tetrahedron face. Why?

@empet
Copy link

empet commented Feb 17, 2020

The two plots (that generated in the Plotly tutorial, and this one with delaunayais='y') are not smooth surfaces and we cannot affirm that they are graph of functions of the form z=f(x,y), respectively y = g(x,z), because they can exhibit vertical triangles, respectively triangles parallel to yaxis in the second case.

In your much discussed case the point cloud consists in a discretization of a surface of type z=f(x,y), and in this case Mesh3d attempts to to remove from tetrahedra the faces that are not on the surface but it fails because this surface is far from being a slight perturbation of a z-plane, i.e. a plane of equation z=constant, for which the algorithm works.

@cottrell
Copy link

Just skimmed this thread (it's probably stale now) but wondering if anyone has found a better solution to tell plotly to do the triangulation in 2d (x, y) for the (x, y, z) plotting? I think that is one of the confusing issues people are hitting. I can manually do a delaunay and pass that through but seems like plotly is doing this itself just need a way of saying (use only these coords)

https://plotly.com/python/3d-mesh/#mesh-tetrahedron

@gvwilson gvwilson self-assigned this Jul 3, 2024
@gvwilson gvwilson removed their assignment Aug 2, 2024
@gvwilson gvwilson added P3 backlog bug something broken labels Aug 12, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug something broken P3 backlog
Projects
None yet
Development

No branches or pull requests

4 participants