如何根据以公里为单位的真实半径在地图上绘制圆(使用 UnfoldingMaps 和 Java 中的处理)

How to draw a circle on a map according to its real radius in kilometers (Using UnfoldingMaps and Processing in Java)

Earthquake threat circle on the map

我正在使用UnfoldingMaps在地图上显示地震信息。 我打算在地图上显示威胁圈。

根据圆的半径和中心位置(以像素为单位)绘制一个圆。如何获取半径是我遇到的问题。

假设我有以公里为单位的威胁圆半径 R 和中心标记 A。 我想在圆上创建一个标记B,这样我就可以使用屏幕距离作为屏幕半径。

我决定创建与 A 具有相同经度但不同纬度的 B。我将 R 更改为增量纬度。

但是画完圆圈后发现不对,因为红色三角形按照距离应该在圆圈内。

主要的难点就是如何根据千米来计算屏幕半径。

public void calcThreatCircleOnScreen(UnfoldingMap map) {
    float radius = 0;
    float deltaLat=(float) (threatCircle()/6371/2/3.1415927*360);

    Location centerLocation = this.getLocation();
    Location upperLocation = new Location(centerLocation);
    upperLocation.setLat(centerLocation.getLat() + deltaLat);

    SimplePointMarker upperMarker = new SimplePointMarker(upperLocation);
    ScreenPosition center = this.getScreenPosition(map);
    ScreenPosition upper = upperMarker.getScreenPosition(map);
    radius = Math.abs(upper.y - center.y);      
    setThreatCircleOnScreen(radius);
}

这取决于两件事:地图的缩放级别和您使用的投影。

您需要取消投影 公里到像素,您可能可以使用 google 和 the Unfolding API.[=13= 弄清楚如何做到这一点]

例如,我找到了一个 MercatorProjection class,其中包含一个采用缩放级别的构造函数,以及在世界坐标和像素坐标之间投影和取消投影点的方法。

这只是一个起点,因为我不确定这些方法采用的是什么单位,但希望这是您进行谷歌搜索和试验的方向。

我建议尝试让某些东西正常工作,如果遇到困难,请发帖 MCVE。祝你好运。

现在我有了这个问题的答案。希望对其他人有帮助。 Earthquake threat circle on the map

  1. 我早期根据 km 计算半径(以像素为单位)的解决方案是正确的。我认为这是一个简单而强大的想法(独立于投影API) 唯一的问题是我在画圆时应该使用直径而不是半径。我应该像这样用d=2r画画

    float d = 2 * threatCircleRadius(); 
    pg.noFill(); 
    pg.ellipse(x,y,d,d); 
    
  2. 我通过咨询 UnfoldingMaps 的作者找到了另一个更清晰的解决方案,如下所示。 (https://github.com/tillnagel/unfolding/issues/124) 我早期的解决方案首先将距离更改为三角纬度,然后通过更改纬度创建新位置。 新方案使用 API GeoUtils.getDestinationLocation(sourceLocation, compassBearingDegree, distanceKm) 直接获取新位置! 另外,我不需要创建一个新的标记来找到它的屏幕位置。

    public void calcThreatCircleOnScreen(UnfoldingMap map) {
        float radius = 0;
        Location centerLocation = this.getLocation();
        Location upperLocation = GeoUtils.getDestinationLocation(centerLocation, 0, threatCircle());
    
        //SimplePointMarker upperMarker = new SimplePointMarker(upperLocation);
    
        ScreenPosition center = map.getScreenPosition(centerLocation);
        ScreenPosition upper = map.getScreenPosition(upperLocation);
        radius = PApplet.dist(center.x, center.y, upper.x, upper.y);        
        setThreatCircleOnScreen(radius);
    

    }