Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/387.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 谷歌地图两个圆的交点_Javascript_Algorithm_Google Maps_Google Maps Api 3_Geometry - Fatal编程技术网

Javascript 谷歌地图两个圆的交点

Javascript 谷歌地图两个圆的交点,javascript,algorithm,google-maps,google-maps-api-3,geometry,Javascript,Algorithm,Google Maps,Google Maps Api 3,Geometry,是否有一种简单的方法可以获取两个in.的交点(如果可用)的lat/lng?还是我应该顺路走 编辑:在我的问题中,圆总是具有相同的半径,以便于求解。是的,对于相等的圆,可以详细说明相当简单的解: 第一个圆心是一个点,第二个圆心是F,中点是C,交点是B,D。ABC是带直角C的直角球面三角形 我们要找到角度A,这是偏离A-F方向的角度。球面三角法(右球面三角形的纳皮尔规则)为我们提供了公式: cos(A)=tg(AC)*ctg(AB) 其中一个符号表示球面角,双符号表示大圆弧的角度(AB,AC)。我

是否有一种简单的方法可以获取两个in.的交点(如果可用)的
lat
/
lng
?还是我应该顺路走


编辑:在我的问题中,圆总是具有相同的半径,以便于求解。

是的,对于相等的圆,可以详细说明相当简单的解:
第一个圆心是一个点,第二个圆心是F,中点是C,交点是B,D。ABC是带直角C的直角球面三角形

我们要找到角度A,这是偏离A-F方向的角度。球面三角法(右球面三角形的纳皮尔规则)为我们提供了公式:

cos(A)=tg(AC)*ctg(AB)
其中一个符号表示球面角,双符号表示大圆弧的角度(AB,AC)。我们可以看到AB=圆半径(当然是弧度),AC=大圆弧上A和F之间的一半距离。 要查找AC(和其他值),我将使用代码

我们的

AC = c/2
如果给定的圆半径Rd为公里,则

AB = Rd / R = Rd / 6371
现在我们可以找到角度了

A = arccos(tg(AC) * ctg(AB))
起动轴承(AF方向):

交点的方位:

B_bearing = brng - A
D_bearing = brng + A
交点坐标:

var latB = Math.asin( Math.sin(lat1)*Math.cos(Rd/R) + 
              Math.cos(lat1)*Math.sin(Rd/R)*Math.cos(B_bearing) );
var lonB = lon1.toRad() + Math.atan2(Math.sin(B_bearing)*Math.sin(Rd/R)*Math.cos(lat1), 
                     Math.cos(Rd/R)-Math.sin(lat1)*Math.sin(lat2));
D_轴承也是如此

latB、lonB以弧度为单位

可以简化r1=r2=:r的情况。我们仍然需要首先将圆心P1,P2从(lat,lng)转换为笛卡尔坐标(x,y,z)

但是,可以更容易地计算包含圆的平面的相交线。设
d
为实际圆心(平面内)到曲面上对应点P1或P2的距离。一个简单的推导表明(R为地球半径):

现在让S1和S2为交点,S为中点。通过
s=| OS |
t=| SS1 |=| SS2 |
(其中O=(0,0,0)是地球的中心),我们从简单的推导中得到:

var a = Math.acos(P1.x*P2.x + P1.y*P2.y + P1.z*P2.z); // the angle P1OP2
var s = (R-d)/Math.cos(a/2);
var t = Math.sqrt(R*R - s*s);
现在由于
r1=r2
点S、S1、S2位于P1和P2之间的中间平面上。对于
v_s=OS
我们得到:

function vecLen(v)
{ return Math.sqrt(v.x*v.x + v.y*v.y + v.z*v.z); }
function vecScale(scale,v)
{ return {x: scale*v.x, y: scale*v.y, z: scale*v.z}; }

var v = {x: P1.x+P2.x, y: P1.y+P2.y, z:P1.z+P2.z}; // P1+P2 is in the middle of OP1 and OP2
var S = vecScale(s/vecLen(v), v);

function crossProd(v1,v2)
{
  return {x: v1.y*v2.z - v1.z*v2.y,
          y: v1.z*v2.x - v1.x*v2.z,
          z: v1.x*v2.y - v1.y*v2.x};
}
var n = crossProd(P1,P2); // normal vector to plane OP1P2 = vector along S1S2
var SS1 = vecScale(t/vecLen(n),n);

var S1 = {x: S.x+SS1.x, y: S.y+SS1.y, z: S.z+SS1.z}; // S + SS1
var S2 = {x: S.x-SS1.x, y: S.y-SS2.y, z: S.z-SS1.z}; // S - SS1
最后,我们必须转换回(lat,lng):


Yazanpro,很抱歉回复得太晚

您可能对MBo方法的一个简明变体感兴趣,该方法在两个方面进行了简化:

  • 首先,通过利用google.mapsAPI的一些内置功能来避免很多困难的计算
  • 其次,采用二维模型计算夹角,代替MBo的球形模型。我最初不确定这种简化的有效性,但对测试感到满意,因为相对于地球的大小,除了最大的圆外,误差都很小(例如在低缩放级别)
下面是函数:

function getIntersections(circleA, circleB) {
    /* 
     * Find the points of intersection of two google maps circles or equal radius
     * circleA: a google.maps.Circle object 
     * circleB: a google.maps.Circle object
     * returns: null if 
     *    the two radii are not equal 
     *    the two circles are coincident
     *    the two circles don't intersect
     * otherwise returns: array containing the two points of intersection of circleA and circleB
     */

    var R, centerA, centerB, D, h, h_;

    try {

        R = circleA.getRadius();
        centerA = circleA.getCenter();
        centerB = circleB.getCenter();

        if(R !== circleB.getRadius()) {
            throw( new Error("Radii are not equal.") );
        }
        if(centerA.equals(centerB)) {
            throw( new Error("Circle centres are coincident.") );
        }

        D = google.maps.geometry.spherical.computeDistanceBetween(centerA, centerB); //Distance between the two centres (in meters)

        // Check that the two circles intersect
        if(D > (2 * R)) {
            throw( new Error("Circles do not intersect.") );
        }

        h = google.maps.geometry.spherical.computeHeading(centerA, centerB); //Heading from centre of circle A to centre of circle B. (in degrees)
        h_ = Math.acos(D / 2 / R) * 180 / Math.PI; //Included angle between the intersections (for either of the two circles) (in degrees). This is trivial only because the two radii are equal.

        //Return an array containing the two points of intersection as google.maps.latLng objects
        return [
            google.maps.geometry.spherical.computeOffset(centerA, R, h + h_),
            google.maps.geometry.spherical.computeOffset(centerA, R, h - h_)
        ];
    }
    catch(e) {
        console.error("getIntersections() :: " + e.message);
        return null;
    }
}

顺便说一句,这不是对MBo的不尊重——这是一个很好的答案。

不幸的是,函数不起作用(很可能我遗漏了什么)。请检查一下这把小提琴,让我知道我遗漏了什么?请注意,您的'lonSol1=…`表达式中的lon1仍然以度为单位,但atan2返回弧度!我在这里修复了它,但仍然没有显示预期的结果。感谢您指出这一点。让我惊讶的是,你的解决方案在地图上比MBo的更精确,甚至你认为是2D!Yazanpro,是的,我在发布后玩了一会儿,发现了同样的东西。有一件事要考虑的是,我的解决方案只在一个方面是二维的——<代码> Hy(MBo的<代码> A<代码>)。我只能假设,总体计算对这种简化并不特别敏感,而使用google.maps.geometry.Spherec API进行
.ComputedDistanceBeween()'、
.computeHeading()`和
.computeOffset()
的计算精度更高@MBo可能对此有看法-他似乎比我更了解整个主题(尽管我的解决方案更准确:-))。
var R = 6371; // earth radius in km
var r = 100; // the direct distance (in km) of the given points to the intersections points
// if the value rs for the distance along the surface is known, it has to be converted:
// var r = 2*R*Math.sin(rs/(2*R*Math.PI));
var d = r*r/(2*R);
var a = Math.acos(P1.x*P2.x + P1.y*P2.y + P1.z*P2.z); // the angle P1OP2
var s = (R-d)/Math.cos(a/2);
var t = Math.sqrt(R*R - s*s);
function vecLen(v)
{ return Math.sqrt(v.x*v.x + v.y*v.y + v.z*v.z); }
function vecScale(scale,v)
{ return {x: scale*v.x, y: scale*v.y, z: scale*v.z}; }

var v = {x: P1.x+P2.x, y: P1.y+P2.y, z:P1.z+P2.z}; // P1+P2 is in the middle of OP1 and OP2
var S = vecScale(s/vecLen(v), v);

function crossProd(v1,v2)
{
  return {x: v1.y*v2.z - v1.z*v2.y,
          y: v1.z*v2.x - v1.x*v2.z,
          z: v1.x*v2.y - v1.y*v2.x};
}
var n = crossProd(P1,P2); // normal vector to plane OP1P2 = vector along S1S2
var SS1 = vecScale(t/vecLen(n),n);

var S1 = {x: S.x+SS1.x, y: S.y+SS1.y, z: S.z+SS1.z}; // S + SS1
var S2 = {x: S.x-SS1.x, y: S.y-SS2.y, z: S.z-SS1.z}; // S - SS1
function Cartesian2LatLng(P)
{
  var P_xy = {x: P.x, y:P.y, z:0}
  return {lat: Math.atan2(P.y,P.x)/DEG2RAD, lng: Math.atan2(P.z,vecLen(P_xy))/DEG2RAD};
}
var S1_latlng = Cartesian2LatLng(S1);
var S2_latlng = Cartesian2LatLng(S2);
function getIntersections(circleA, circleB) {
    /* 
     * Find the points of intersection of two google maps circles or equal radius
     * circleA: a google.maps.Circle object 
     * circleB: a google.maps.Circle object
     * returns: null if 
     *    the two radii are not equal 
     *    the two circles are coincident
     *    the two circles don't intersect
     * otherwise returns: array containing the two points of intersection of circleA and circleB
     */

    var R, centerA, centerB, D, h, h_;

    try {

        R = circleA.getRadius();
        centerA = circleA.getCenter();
        centerB = circleB.getCenter();

        if(R !== circleB.getRadius()) {
            throw( new Error("Radii are not equal.") );
        }
        if(centerA.equals(centerB)) {
            throw( new Error("Circle centres are coincident.") );
        }

        D = google.maps.geometry.spherical.computeDistanceBetween(centerA, centerB); //Distance between the two centres (in meters)

        // Check that the two circles intersect
        if(D > (2 * R)) {
            throw( new Error("Circles do not intersect.") );
        }

        h = google.maps.geometry.spherical.computeHeading(centerA, centerB); //Heading from centre of circle A to centre of circle B. (in degrees)
        h_ = Math.acos(D / 2 / R) * 180 / Math.PI; //Included angle between the intersections (for either of the two circles) (in degrees). This is trivial only because the two radii are equal.

        //Return an array containing the two points of intersection as google.maps.latLng objects
        return [
            google.maps.geometry.spherical.computeOffset(centerA, R, h + h_),
            google.maps.geometry.spherical.computeOffset(centerA, R, h - h_)
        ];
    }
    catch(e) {
        console.error("getIntersections() :: " + e.message);
        return null;
    }
}