how to plot non-convex surface from set of n x 3 data

本秂侑毒 提交于 2020-01-02 07:32:07

问题


Is there a straight forward way to plot a non-convex surface in R?

I have used something like the following for convex surfaces and it works fine:

xyz <- cbind(y,x,z)
tbr <- t(surf.tri(xyz, delaunayn(xyz)))
rgl.triangles(xyz[tbr,1], xyz[tbr,2], xyz[tbr,3])

However, for non-convex surfaces, concave areas become filled. I think this is a problem with the function delaunayn() as it uses the Qhull library which does not support constrained Delaunay triangulations or mesh generation of non-convex objects.

Any suggestions appreciated.

P.S.

I have data as an ascii file but it has 3 columns and is 225 lines long. What is the best way of providing this?

Data available at: http://pastebin.com/R2p4Cf7d

The top of the plot should be concave! This is an image created using persp3d() of how the surface should look. It has been calculated using more grid points on a regular grid in polar coordinates, rather than using irregular collocation points.


回答1:


I feel deldir::deldir() does something better than geometry::delaunayn() in this case (as a memorial to a new function rgl::plot3d.deldir()). (I used OP's Data.)

library(rgl); library(deldir)

dxyz <- deldir(xyz[,1], xyz[,2], z=xyz[,3])

open3d()
plot3d(dxyz, col=cm.colors(256)[cut(xyz[,3], 256)], alpha=0.9)  # there isn't a bottom
wire3d(as.mesh3d(dxyz), col="black")




回答2:


The following solution is not perfect, but works if you have a copy of Matlab.

library(rgl)
library(geometry)
# Read in data - also at: http://pastebin.com/R2p4Cf7d
simDat <- read.csv("testDat.csv")
#
x   <- simDat[,1];y<-simDat[,2];z<-simDat[,3]
xyz <- cbind(simDat[,1],simDat[,2],simDat[,3])
#
triNodes <- delaunayn(xyz)
tbr1     <- t(surf.tri(xyz, triNodes ))
# Plot data from R generated triangles
open3d()
rgl.triangles(xyz[tbr1,1], xyz[tbr1,2], xyz[tbr1,3])
#
# Import data generated by Matlab function delaunay()
#  - also at: http://pastebin.com/vQV2Zaii
nodeDat_ML <- read.csv("testDatNodes.csv")
triNodes2  <- cbind(nodeDat_ML[,1], nodeDat_ML[,2], nodeDat_ML[,3],1)
#
tbr2 <- t(surf.tri(xyz, triNodes2))
# Plot data from Matlab generated triangles
open3d()
rgl.triangles(xyz[tbr2,1], xyz[tbr2,2], xyz[tbr2,3])

The code produces the following two surfaces. The left plot is based on triangulation generated by the R function delaunayn(), and the right plot is based on triangulation generated from the Matlab function delaunay().

The Matlab generated data is available at: http://pastebin.com/vQV2Zaii

and the associated Matblab code is:

fname = 'testDat.csv';
tt = table2array(readtable(fname)); % get data
x =  tt(:,1);y = tt(:,2);z = tt(:,3);
tri = delaunay(x,y); % the triangulation data
trisurf(tri,x(:,1),y(:,1),z(:,1)); % surface plot

The result is not entirely perfect as the final plot (right) has a spurious triangle.

I hope the above will be useful to anyone with a similar problem.



来源:https://stackoverflow.com/questions/24608883/how-to-plot-non-convex-surface-from-set-of-n-x-3-data

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!