d3:从不规则/散乱数据绘制等高线或曲面图

6
我可以使用Python和matplotlib的tricontour()函数一次性生成一组三元组[X,Y,Z]的平滑轮廓图。也可以使用plot.ly轻松生成轮廓线,但我发现它速度太慢了,无法接受。(此外,我不感兴趣MATLAB解决方案,因为它与Python类似)。 我正在寻找使用d3.js实现类似功能的方法。如果没有轮廓线,我可以接受“表面图”或“热力图”。
我可以看到如何生成彩色德劳内三角剖分和/或彩色沃罗诺伊图, 但是如何从不规则数据点在d3中生成等高线图的问题似乎仍然是一个开放性问题(尽管这个问题过早地被关闭了!)。到目前为止,我所看到的都是“手动”方法,使用径向基函数(高斯模糊)或使用重心插值进行网格插值。
我甚至愿意在Delaunay三角剖分上使用Gouraud着色或Coon渐变,但显然像Gourand或Coon渐变这样的"高级着色方法"并不在“常规”SVG中,但被提议用于SVG2...不确定这让我在d3和(常规)SVG方面处于什么位置。手动实现SVG渐变着色似乎会非常麻烦。
是否有一种“更好”的打包方式来完成这个,即不需要太多“自定义”代码的东西?(也许通过一些我还没有找到的多维Bezier例程?)
我会发布一个起点为彩色 Voronoi 图案的 Fiddle:https://jsfiddle.net/k2v2jy7s/1/。你能帮我将其从“方块状”变得更加“平滑”(甚至显示轮廓线)吗?
<svg width="960" height="500"></svg>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
    var svg = d3.select("svg"),
        width = +svg.attr("width"),
        height = +svg.attr("height");

    var npoints = 1000;
    var sites = d3.range(npoints)
        .map(function(d) { return [Math.random() * width, Math.random() * height]; });


    // values  at data points / colors being mapped = "zvals"
    var kx = 3.14159/(width*0.5);
    var ky = 3.14159/(height*0.5);
    var zvals = d3.range(npoints)
    for (i = 0; i < npoints; i++) { 
        zvals[i] = (1.0 + Math.cos(kx*sites[i][0]) * Math.cos(ky*sites[i][1]))/2.0;
        zvals[i] *= zvals[i];
    }

    var g = svg.append("g")
        .attr("transform", "translate(" + 0+ "," + 0 + ")");

    var voronoi = d3.voronoi()
        .extent([[-1, -1], [width + 1, height + 1]]);

    var polygon = svg.append("g")
        .attr("class", "polygons")
        .selectAll("path")
        .data(voronoi.polygons(sites))
        .enter().append("path")
        .style('fill', function(d,i){ return d3.hsl( zvals[i]*310,        1, .5); })
        .call(redrawPolygon);

    function redrawPolygon(polygon) {
      polygon
          .attr("d", function(d) { return d ? "M" + d.join("L") + "Z" : null; });
    }
</script>
< p > < em > 更新 :还发现了这篇关于"渐变热图"的blocks.org帖子,正如我之前提到的那样,这是我可以接受的结果类型,但再次强调,这需要大量的自定义代码。真的希望有一种紧凑的“库存”解决方案,类似于tricontour()。

1个回答

0

5年半了,这个问题还没有答案!

嗯,我也一直在研究如何在Javascript中从一系列[X,Y,Z]点生成轮廓线,但是还没有找到最好或最完整的解决方案。我通过谷歌搜索找到的许多解决方案(例如d3-contour)都是为等间距值的网格设计的,而不是像您从土地测量中获得的不规则点系列。

d3-tricontour

d3-tricontour库似乎是最有前途的,所以我可能会试着玩一下它。

这是它可以生成的一个示例:

d3-tricontour library example

(标签是可选的。)

显然它使用delaunaymeandering triangles算法将任意点转换为三角形,然后轮廓几何图形。该算法在O(n)中运行,其中n是边数,这意味着它非常快速且可以完美地扩展。

要了解更多信息,您可以访问他们的:

替代方案

否则,可能有其他方法来完成此操作。如果使用基于网格的库之一,则我认为一般过程应该是:

将任意的 [X,Y,Z] 点转换为网格 - Delaunay 算法可能是一个很好的起点(参见 d3-delaunay其他 Delaunay 库)。使用某种插值方法找到网格中每个点的 Z 值(关于数学方面我不太确定),然后将结果输入到基于网格的轮廓库中。

约束轮廓

还要注意,从现实世界的地形创建轮廓还需要"约束"一些边缘,使得轮廓不会越过它们不应该越过的山脊线。

CDT-JS 是一个计算约束Delaunay三角剖分的 web应用程序(目前尚无单独的库可用),对于此情况可能会有用。

否则,理论上来说,在渲染之前沿着你的约束线注入额外的[X,Y,Z]点可能会创建这种功能。但我还没有测试过这种方法。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接