D3中使用投影实现动态简化

3
我正在使用d3.geo.mercator()投影来绘制SVG地图。我还使用了缩放行为,并将transform应用于包含地图所有路径的<g>对象。
在查看Mike Bostock的动态简化示例(http://bl.ocks.org/mbostock/6252418)后,我想知道在我的情况下是否可以应用这样的算法,在缩小时重绘几何形状时使用更少的点?
在所有我见过的示例中,都有一个simplify函数,该函数跳过微不足道的点并将其余部分绘制为它们本来的样子,并将该函数用于var path = d3.geo.path().projection(simplify)。我无法像那样使用它,因为我需要它应用于已经存在的projection = d3.geo.mercator().scale(*).translate([*,*])之上。
如何在现有投影上使用动态简化?
1个回答

4
根据您引用的示例Dynamic Simplification IIsimplify函数可能如下:
var simplify = d3.geo.transform({
  point: function(x, y, z) {
    if (z >= area) {
        this.stream.point(x, y);
    }
  }
});

area 是一个阈值变量,您可以预先设置或根据缩放动态修改。

然后,您会将其用于 d3.geo.path()projection 方法,如下所示:

var path = d3.geo.path()
    .projection(simplify);

根据您在回答中所描述的情况,以下是更详细的说明。现在,根据Dynamic Simplification IV中所述,投影方法也可以定义为:

var path = d3.geo.path()
    .projection({
        stream: function(s) { 
            return simplify.stream(s); 
        }
     });

这与以前完全相同。它只是“扩展”了默认方法。d3.geo.path总是调用投影stream方法,因此您可以声明自己的流并将其转发到simplify.stream

现在,您需要使用d3.geo.mercator()重新投影路径。

var mercatorProjection = d3.geo.mercator().scale(*).translate([*,*]);

没有问题:这些流是可链式的。你可以这样做:

无需担心: 这些流是可链式的。您可以执行以下操作:

var path = d3.geo.path()
    .projection({
        stream: function(s) { 
            return simplify.stream(mercatorProjection.stream(s)); 
        }
     });

除此之外:

var path = d3.geo.path()
    .projection({
        stream: function(s) { 
            return mercatorProjection.stream(simplify.stream(s)); 
        }
     });

唯一的区别是,如果您处理WGS84、像素或其他坐标系统,则必须以不同方式计算阈值区域。
重要提示,simplify函数中的z参数不是海拔高度。它是每个点定义的三角形面积,这是TopoJSON的一部分预先计算的值。
恐怕这意味着您不能依赖此示例来简化常规geoJSON。如果要应用Visvalingam的算法,则必须添加自己的逻辑来计算每个点的相关区域,或者计算到最近点的距离(如果要应用Douglas-Peucker算法),或者实现自己的算法。
祝你好运。

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