在180度处穿过180度子午线的两点之间取一点



我正在MapboxGL(js(世界地图上绘制一条线,沿着轨道物体的路径绘制。我通过在对象轨道更新时向线几何阵列添加一组新的十进制经度/纬度坐标来实现这一点。

Mapbox(和其他(有一个已知的问题,即当绘制一条穿过180°子午线(经度(的线时,我们不会得到一条从a到b的直线,而是得到一条非常长的线,从a到b:

而不是:我们得到:////___…/。。。。。。。。。子午线180°/___////

";接受";这里和Mapbox的答案建议将经度范围改为0°/360°,但这只是将问题从赤道转移到了极点。这对于大多数一般的提议来说都是好的,但对于我们可能穿过0°/360°子午线的轨道跟踪来说仍然是一个问题。

我的解决方案是使用MultiLine几何体,当我穿过这条子午线时,将我的坐标分解成新的阵列,然而,这总是会留下一个小间隙,或者,如果我";180;无论哪一方,我们都会得到一个";"扭结";子午线:

间隙:或扭结:////…..…..|。。。子午线180°/////

所以我需要弄清楚如果经度在子午线上,的确切纬度是多少,知道两边的起点和终点:

+170|p2/:|/:|/:180-|------/pX?--子午线180°|/::(lng(|/:|/::-170 |_/_____:___:___p1 x?(lat(

我需要求解纬度x,这样我就可以生成pX(如果经度为180,则知道p1和p2(。一旦我有了pX,我就可以把它加到最后一行的末尾和下一行的开头,从而缩小差距(或平滑"扭结"(。

我知道这是基本的Trig,但我老人的大脑让我失望了。。再一次

以这种方式分割一行的简单方法是使用Turf的lineSplit函数。类似于:

const meridian = turf.lineString([[180, -90], [180, 90]]);
const linePieces = turf.lineSplit(myline, meridian);

我没有试过这个,所以不确定草皮本身在子午线上是否有任何奇怪之处。如果是这样,您可能需要临时将坐标转换到其他位置或其他位置。

无论如何,这比自己做三角法要好,尤其是因为它可能会在世界不平坦的情况下引入错误。

已解决!使用基本的Trig(在写问题时,所以我无论如何都会发布它,以防它对其他人有帮助(:

我们基本上是在玩两个直角三角形:p1到p2,以及较小的直角三角形,其中相对的一侧停在子午线上,两者都有相同的斜边角。因此,我们有:

+170|p2/||/||/|180-|------/pX?--子午线180°|/:|(lng(|/:A||/B:|-170 |_/__:___|___p1 x?(lat(

其中A是我们从p1到p2的直角三角形,B是从p1经度到子午线的三角形,我们需要计算出它的邻边。

毕达哥拉斯基本上告诉我们,我们所需要的只是直角三角形的两个数据点(除直角外(来求解其他数据点。

我们已经有了A的相反和相邻长度:

+170|p2/||/α||/|180°子午线|/|(lng(|/A|相反|/|-170 |_/β______|___p1相邻A(lat(

因此,从这里我们需要计算A的斜边,以获得A(α(斜边的角度,这样我们以后可以使用它:

// add 360 to a negative longitude to shift lng from -180/+180, to 0/360
p1 = { lng: p1.lng < 0 ? p1.lng + 360 : p1.lng, lat: p1.lat }
p2 = { lng: p2.lng < 0 ? p2.lng + 360 : p2.lng, lat: p2.lat }
let oppositeA = Math.abs(p2.lng - p1.lng) // get A opposite length
let adjacentA = Math.abs(p2.lat - p1.lat) // get A adjacent length
let hypotenuseA = Math.sqrt(Math.pow(oppositeA,2) + Math.pow(adjacentA,2)) // calc A hypotenuse
let angleA = Math.asin(oppositeA / hypotenuseA) // calc A hypotenuse angle

现在我们需要B的对立面(p1.lng到180(和我们计算的A的角度来计算B的新斜边,这样我们就可以得到B的新相邻

+170|p2/|/|/180°子午线|/:B(lng(|/α:|/:反面B-170 |_/_____:______p1相邻B(lat(
let oppositeB = Math.abs(180 - p1.lng) // get B opposite
let hypotenuseB = oppositeB / Math.cos(angleA) // calc B hypotenuse using A angle
let adjacentB = Math.sqrt(Math.pow(oppositeB,2) + Math.pow(hypotenuseB,2)); calc B adjacent

现在我们将新的相邻纬度添加到p1,我们就得到了x!因此:

let pX = { lng: 180, lat: p1.lat + adjacentB }

结束最后一个行数组,用pX开始下一个行,间隙完美闭合!

高中数学(好吧,毕达哥拉斯的天才(拯救了我们!我知道它在那个老人的脑子里嗡嗡作响。。。。。

最新更新