【问题标题】:Draw a curved line with given radius, and two locations绘制具有给定半径和两个位置的曲线
【发布时间】:2014-08-06 16:15:33
【问题描述】:

我有两个位置,我必须在它们之间根据半径绘制一条曲线。我画了一张图:

我知道如何画一个圆。但是如何只画圆的一部分呢?

以下是已知参数:

  • 当前位置
  • 下一个位置
  • 曲线/圆的半径

如果有人能告诉我如何沿着当前位置和下一个位置之间的圆获得点,我可以使用折线来绘制曲线。但是如何计算位置呢?

【问题讨论】:

  • 当你不知道中心时,根据给定的细节有2个可能的段,你会如何决定应该画哪一个?
  • @Dr.Molle:你是说曲线应该画在当前位置的哪一边?
  • 是的(我猜我们的意思是一样的)
  • 我希望曲线像图中一样朝右。
  • 查看this以查找圆心。

标签: google-maps google-maps-api-3


【解决方案1】:

我为我的问题找到了解决方案。

我做的是

  • 获取两点之间的距离(当前位置和下一个位置)
  • 计算曲线的矢状's'值。
  • 计算当前位置和下一个位置的中点。
  • 计算行当前位置和下一个位置的航向。
  • 从中点开始,heading = 在上述步骤中计算的航向 + 90(如果您希望中心位于直线的右侧)或 heading = 在上述计算的航向step - 90(如果您希望中心位于线的左侧)和距离 = 半径 - 矢状面,计算偏移点。

矢状面可以使用以下公式计算:

在哪里,

l是当前位置到下一个位置距离的一半

r是曲线半径

s是射手

我使用的代码是:

function DrawCurvedLine(startLatitude, startLongitude, endLatitude, endLongitude, roc, lineColor) {
    var distance;
    var latLng1, latLng2;
    var sagitta;
    var midPoint;
    var heading;
    var roc;
    var center;
    var arc = new Array();

    curvePoints = [];
    // Create current and predicted latlng objects
    latLng1 = new google.maps.LatLng(startLatitude, startLongitude);
    latLng2 = new google.maps.LatLng(endLatitude, endLongitude);

    // Compute the distance between current location and predicted location
    distance = google.maps.geometry.spherical.computeDistanceBetween(currentLatLng, predictedLatLng);
    sagitta = computeSagitta(roc, (distance / 2));
    midPoint = getMidPoint(latLng1, latLng2);
    heading = google.maps.geometry.spherical.computeHeading(latLng1, latLng2);
    heading = headingClPl + 90;

    center = google.maps.geometry.spherical.computeOffset(midPoint, (roc - sagitta), headingClPl);

    var Heading1 = google.maps.geometry.spherical.computeHeading(center, latLng1);
    var Heading2 = google.maps.geometry.spherical.computeHeading(center, latLng2);

    var i = 0;
    while ((Heading1 + i) <= Heading2 || (Heading2 + i) <= Heading1) {
        if (radiusOfCurve < 0) {
            arcPts.push(google.maps.geometry.spherical.computeOffset(centerOfCurve, roc, Heading1 - i));
        }
        else {
            arcPts.push(google.maps.geometry.spherical.computeOffset(centerOfCurve, roc, Heading1 + i));
        }
        i++;
    }

    var curvedLine = new google.maps.Polyline({
        path: arcPts,
        icons: [{
            icon: {
            path: google.maps.SymbolPath.FORWARD_OPEN_ARROW,
            scale: 3,
            strokeColor: lineColor,
            strokeOpacity: 1,
            strokeWeight: 1.3,
            fillColor: 'transparent',
            fillOpacity: 0
            },
            offset: '100%'
        }],
        strokeColor: lineColor,
        strokeOpacity: 0.5,
        strokeWeight: 2,
        map: map
    });

    function computeSagitta(radius, length){
        // radius is radius of circle. length is the half length of chord
        return (radius - (Math.sqrt((radius * radius) - (length * length))));
    }

【讨论】:

  • 这个 sn-p 很不完整 mhm,重构会很棒!
【解决方案2】:

你可以用这个Answer来画弧线。

寻找圆弧的中心。

您可以使用 Google Geometry 库查找 2 个标记之间的弦长、其方位角和圆弧中心的位置。

来自文档

computeDistanceBetween(from:LatLng, to:LatLng, radius?:number) 返回 两个 LatLng 之间的距离,以米为单位。半径 默认为以米为单位的地球半径 (6378137)。

computeHeading(from:LatLng, to:LatLng) 从一开始返回航向 LatLng 到另一个 LatLng。标题以顺时针度数表示 从北在 [-180,180) 范围内作为数字。

computeOffset(from:LatLng, distance:number, heading:number, radius?:number) 返回移动距离产生的 La​​tLng 从指定航向的原点(以度数表示 从北顺时针)作为LatLng。

首先找到两个标记之间的距离

var spherical = google.maps.geometry.spherical; 
var point1 = markers[0].getPosition();
var point2 = markers[1].getPosition();
var length = google.maps.geometry.spherical.computeDistanceBetween(point1,point2);

然后找方位

 var heading = google.maps.geometry.spherical.computeHeading(point1,point2);

正如您现在知道三角形的 3 条边(弦长、半径(其他 2 条边)),您可以使用 law of cosines 计算圆心的方位角。(注意在 cmets 中讨论了 2 种解决方案)

    function solveAngle(a, b, c) {  // Returns angle C using law of cosines
    var temp = (b * b + c * c - a * a) / (2 * b * c);
    if (temp >= -1 && temp <= 1)
        return Math.acos(temp);
    else
        throw "No solution";
   }

var baseAngle = solveAngle(radius, radius, c);
var vertexAngle = solveAngle(c,radius,radius);

baseAngle用于查找中心点的方位。

vertexAngle是绘制圆弧时使用的点数。

知道方位和半径就可以找到圆心。

var centerPoint = spherical.computeOffset(point1,radius,heading+baseAngle);

注意以米为单位的距离。将方法中的半径更改为 3,959 英里。

如果半径改变中心改变。黄点是蓝点半径的2倍

【讨论】:

  • 嗨,大卫。我以您的 sn-p 为例并在我的代码中进行了尝试。但我发现中心点是在点 2 附近计算的。
  • 谷歌地图中线的方向是如何计算的?
  • 中心方向的计算依据是什么?当我尝试时,我总是向右。
  • 对于我的第一条评论,我得到了解决方案。我不知道 Math.acos() 以弧度返回。你能帮我解决另一个问题吗?圆圈的中心在右侧。如何以及为什么?
  • 当半径改变时,即a,b的值增加,中心应该是离前一点较远的点,但具有相同的航向。但是当我增加半径时,中心航向也会改变。
猜你喜欢
  • 2016-06-02
  • 1970-01-01
  • 2013-12-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-02-28
  • 2022-07-06
  • 2017-04-10
相关资源
最近更新 更多