如何在d3制图光栅重投影上修复地图边界? [英] How to fix map boundaries on d3 cartographic raster reprojection?

查看:157
本文介绍了如何在d3制图光栅重投影上修复地图边界?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我尝试在此示例之后使用光栅重投影地图。如果我通过Azimuthal Equidistant投影更改示例 kavrayskiy7 投影,

I try to use the raster reprojection of a map following this example. If I change the example kavrayskiy7 projection by the Azimuthal Equidistant projection,

var projection = d3.geo.azimuthalEquidistant()
    .scale(90)
    .translate([width / 2, height / 2])
    .clipAngle(180 - 1e-3)
    .precision(.1);

它应该将地球投影到光盘上(投影地图的图像)。但是,光栅重投影超出了该光盘并用扩展图像填充整个画布(反投影函数不是单射的,地图上的几个x / y点对应于单个lon / lat坐标)。在原始示例中,应该使用行

it should project the Earth onto a disc (the image of the projection map). However, the raster reprojection goes beyond that disc and fills the entire canvas with an extended picture (the inverse projection function is not injective, several x/y points on the map correspond to a single lon/lat coordinates). In the original example, this should be avoided with the line

if (λ > 180 || λ < -180 || φ > 90 || φ < -90) { i += 4; continue; }

但是这个例子不起作用。我发现其他故障,例如当使用Mollweide投影(两条线出现在极点)时,由于相同的效果。

but for this example that does not work. I found other glitches for instance when using the Mollweide projection (two lines appear at the poles) due to the same efect.

要解决这个问题,一种方法是修复反向投影使得当x / y输入超出范围时它们返回错误或无。我的尝试是使用整个球体的前向投影来检查点是否在范围内以获得具有地图边界的SVG路径,如下面的代码所示:

To solve this, one way would be to fix the inverse projections so they return error or None when the x/y input is out of range. My attempt was to check if a point is on range using the forward projection of the whole sphere to obtain a SVG path with the boundary of the map, as given by this code:

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

var bdry = svg.append("defs").append("path")
    .datum({type: "Sphere"})
    .attr("id", "sphere")
    .attr("d", path);

(例如参见这个例子)。但是,我找不到简单的方法来检查点 [x,y] 是否在SVG封闭路径内。

(see for instance this example). However, I found no easy method to check whether a point [x,y] is inside a SVG closed path.

所以我的问题是:


  • 反投影是否有错误,或者我没有正确使用它们?

  • 我怎么能找到一个 [x,y] 点在svg路径内,假设这是最好的方法?

  • 由于好奇心,d3 路径函数的算法代码在哪里获取地图的边界轮廓?我在github回购中找不到它。

  • Is there a bug on the inverse projections, or am I not using them correctly?
  • How could I find if a [x,y] point is inside the svg path, assuming that this is the best approach?
  • By curiosity, where is the algorithm code of the d3 path function to obtain the boundary profile of the map? I could not find it on the github repo.

谢谢。

编辑:我完成了所有44个预测这个例子我发现以下25个小故障:

I went through all the 44 projections in this example and I found glitches on the following 25:

Albers,Bromley,Collignon,Eckert II,Eckert IV,Eckert VI,Hammer,Hill,Goode Homolosine,Lambert圆柱形等面积,Larrivée,Laskowski,McBryde-Thomas平极抛物线,McBryde-Thomas Flat -Polar Quartic,McBryde-Thomas Flat-Polar Sinusoidal,Mollweide,Natural Earth,Nell-Hammer,Polyconic,Sinu-Mollweide,van der Grinten,van der Grinten IV,Wagner IV,Wagner VII,Winkel Tripel。

Albers, Bromley, Collignon, Eckert II, Eckert IV, Eckert VI, Hammer, Hill, Goode Homolosine, Lambert cylindrical equal-area, Larrivée, Laskowski, McBryde–Thomas Flat-Polar Parabolic, McBryde–Thomas Flat-Polar Quartic, McBryde–Thomas Flat-Polar Sinusoidal, Mollweide, Natural Earth, Nell–Hammer, Polyconic, Sinu-Mollweide, van der Grinten, van der Grinten IV, Wagner IV, Wagner VII, Winkel Tripel.

推荐答案

我正在使用第二个答案,因为这是解决同一问题的另一种方法。同样,这个答案是一种替代方法,试图避免多边形解决方案中使用投影范围的svg轮廓的点。

I'm using a second answer only because this is a different approach to the same problem. Again, this answer is an alternative approach that tries to avoid a point in polygon solution that uses an svg outline of the projection extent.

此替代应该(我只尝试了一些)投影任何投影,而我的其他答案仅适用于投影到光盘的投影。其次,这种方法不会尝试定义投影区域以确定是否应该渲染像素,而是使用d3.projection本身。

This alternative should (I've only tried a handful) work for any projection while my other answer works only for projections projected to a disc. Secondly, this approach doesn't attempt to define the projection area to determine if a pixel should be rendered, but uses d3.projection itself.

由于多个点可以使用projection.invert返回相同的值,我们可以运行前向投影来验证是否应该绘制像素。

As multiple points can return the same value with projection.invert, we can run a forward projection to verify if a pixel should be drawn.

如果 projection(projection.invert(point))== point 然后该点在我们预测的范围内。

If projection(projection.invert(point)) == point then the point is within the bounds of our projection.

当然,这可能存在一些精度/舍入误差,因此可以指定一定程度的容差。

Granted, there may be some precision/rounding errors in this, so some degree of tolerance could be specified.

此检查符合for循环:

This check fits within the for loop:

for (var y = 0, i = -1; y < height; ++y) {
    for (var x = 0; x < width; ++x) {

        var p = projection.invert([x, y]), λ = p[0], φ = p[1];

        var pxy = projection(p);

        var tolerance = 0.5;
        if ( λ > 180 || λ < -180 || φ > 90 || φ < -90 ) { i += 4; continue; }
        if ( (Math.abs(pxy[0] - x) < tolerance ) && (Math.abs(pxy[1] - y) < tolerance ) ) {

            var q = ((90 - φ) / 180 * dy | 0) * dx + ((180 + λ) / 360 * dx | 0) << 2;
            targetData[++i] = sourceData[q];
            targetData[++i] = sourceData[++q];
            targetData[++i] = sourceData[++q];
            targetData[++i] = 255;

        }
        else {
            i += 4;
        } 
    }
}

与其他答案一样,我在其中构建了一个块这里

As with the other answer, I built a block out of it here.

我没有检查这个答案的性能,看起来很奇怪需要这种检查,但它可能是你问题中提出的svg方法的一种合适的替代方法。

I haven't checked this answer for performance, and it seems odd that this sort of check is needed, but it might be a suitable alternative approach to the svg approach proposed in your question.

这篇关于如何在d3制图光栅重投影上修复地图边界?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆