【问题标题】:Drawing a fixed-length circle in D3.js在 D3.js 中绘制一个固定长度的圆
【发布时间】:2015-04-19 18:57:59
【问题描述】:

这似乎应该很简单,但我正在努力弄清楚。

在D3.js的地图投影上画圆很容易,例如

p = projection([-73.94,40.7]);
 svg
    .append("svg:circle")
        .attr("cx", function(d, i) { return p[0]; }) //x position translated through projection function
        .attr("cy", function(d, i) { return p[1]; }) //y position           
        .attr("r", function(d, i) { return 20; }) 
        ;

好的,但是如果不是将半径设置为像素值(如上所示,设置为 20 像素),我想将其设置为可以适当缩放到投影的距离值怎么办?

简而言之,这归结为我问,“这个投影中 20 公里的像素值是多少?”现在我知道这会因投影而有所不同——例如在墨卡托,一个 20 公里的圆在赤道附近(接近球形)与在两极附近(高度拉长)看起来非常不同。

D3.js 可以解决许多其他巧妙的投影问题,我惊讶地发现我无法在这里轻易地想出某种可接受的答案。有什么建议么?我在想,好吧,你可以计算一个圆圈的一些纬度/经度点,然后将它绘制成某种路径......这对于 D3.js 来说感觉非常异常笨重。有没有更简单的方法?

【问题讨论】:

  • 您可以在圆上投影第二个点,并根据两个投影点的差确定半径。如果你知道半径是一个角度,你也可以使用d3.geo.circle。
  • 嗨 Lars — 在我的一生中,我无法弄清楚如何使用 d3.geo.circle 来做这件事,并且找不到对做这类事情有用的示例。我在下面找到了解决方法。

标签: javascript svg d3.js


【解决方案1】:

好的,所以我想出了一种方法。它有点笨重——感觉像是应该更自动的东西——但它确实有效。它只涉及使用圆点手动构建路径元素。下面是两个函数和一个使用示例:

//example — draws a 15 km circle centered on New York City using my existing projection
var circle = svg
    .append("path")
    .attr("d", "M"+circlePath( 40.7, -73.94, 15, projection).join("L")+"Z")
    .attr("fill","none")
    .attr("stroke","red")
    .attr("stroke-width",2);

//this function generates the points for the path. If a projection is specified, it will
//automatically convert them to it. If not, it returns lat/lon positions.
//from http://stackoverflow.com/questions/20130186/d3-geo-buffer-around-a-feature with modifications
function circlePath(lat, lon, radius, projection) {
    var intervals = 72;
    var intervalAngle = (360 / intervals);
    var pointsData = [];
    for(var i = 0; i < intervals; i++){
        pointsData.push(getDestinationPoint(lat, lon, i * intervalAngle, radius));
    }
    if(projection) {
        pointsData2 = [];
        for(i in pointsData) {
            pointsData2.push([projection([pointsData[i][1],pointsData[i][0]])[0],projection([pointsData[i][1],pointsData[i][0]])[1]]);
        }
        return pointsData2;
    } else {
        return pointsData;
    }
}

//function to get destination points given an initial lat/lon, bearing, distance
//from http://www.movable-type.co.uk/scripts/latlong.html
function getDestinationPoint(lat,lon, brng, d) {
    var R = 6371; //earth's radius in km — change to whatever unit you plan on using (e.g. miles = 3959) 
    var deg2rad = Math.PI/180; var rad2deg = 180/Math.PI; 
    brng*=deg2rad; lat*=deg2rad; lon*=deg2rad; 
    var lat2 = Math.asin( Math.sin(lat)*Math.cos(d/R) +
                        Math.cos(lat)*Math.sin(d/R)*Math.cos(brng) );
    var lon2 = lon + Math.atan2(Math.sin(brng)*Math.sin(d/R)*Math.cos(lat),
                             Math.cos(d/R)-Math.sin(lat)*Math.sin(lat2));
    return  [lat2*rad2deg, lon2*rad2deg];              
}

【讨论】:

    猜你喜欢
    • 2017-09-03
    • 2013-06-21
    • 1970-01-01
    • 2015-05-17
    • 1970-01-01
    • 2020-06-03
    • 2012-10-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多