获取以 180 度穿过 180 度子午线的两点之间的点
Get point between two points crossing the 180 degree meridian at 180 degrees
我正在 MapboxGL (js) 世界地图上绘制一条沿着轨道物体路径的线。我通过在对象轨道更新时向线几何数组添加一组新的十进制 longitude/latitude 坐标来实现此目的。
Mapbox(和其他)有一个已知问题,当绘制一条穿过 180° 子午线(经度)的线时,我们没有得到一条从 a 到 b 的漂亮直线,我们得到一条很长的线从 a 到 b 环绕整个地球:
而不是:我们得到:
/ /
//___
.../..... ......... 180° 子午线
/ ___
/ /
/ /
此处和 Mapbox 上的“已接受”答案建议转移到 0°/360° 经度范围,但这只会将问题从赤道转移到极点。这对于大多数一般建议来说很好,但对于我们可能穿过 0°/360° 子午线的轨道跟踪来说仍然是一个问题。
我的解决方案是使用 MultiLine 几何图形,并在我穿过这条子午线时将我的坐标分解成新的数组,但是,这总是会留下一个小间隙,或者,如果我在任一侧“180,纬度”,我们得到子午线上的“扭结”:
差距:或扭结:
/ /
/ /
.......... ......|... 180°子午线
/
/ /
/ /
所以我需要弄清楚如果经度在子午线上,那么精确纬度是多少,知道两边的起点和终点:
+170 | p2 /:
| / :
| / :
180 -|-----/ 像素? -- 180°经线
| /: :
(液化天然气) | / : :
| / : :
-170 |_/___:___:___
p1 x?
(纬度)
我需要求解纬度 x 以便生成 pX(如果经度为 180,则知道 p1 和 p2)。一旦我有了 pX,我就可以将它添加到最后一行的末尾和下一行的开头,从而缩小差距(或平滑“扭结”)。
我知道这是基本的 Trig,但我的老脑子又让我失望了.. ....
已解决!使用基本 Trig(在写问题时 - 所以无论如何我都会发布它,以防它帮助其他人):
我们基本上是在玩两个直角三角形:p1 到 p2,以及较小的直角三角形,其对边停止在子午线处,它们都具有相同的斜边角。所以,我们有:
+170 | p2 /|
| / |
| / |
180 -|-----/ pX? -- 180° meridian
| /: |
(lng) | / : A |
| / B: |
-170 |_/___:___|___
p1 x?
(lat)
其中A是我们p1到p2的直角三角形,B是从p1经度到子午线的三角形,我们需要计算其邻边。
毕达哥拉斯基本上告诉我们,我们所需要的只是直角三角形的两个数据点(除了直角)来解决任何其他问题。
我们已经有了A的相反和相邻的长度:
+170 | p2 /|
| /α|
| / |
180 -|-- / | -- 180° meridian
| / |
(lng) | / A | oppositeA
| / |
-170 |_/β______|___
p1 adjacentA
(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
现在我们需要 new 与 B 的对角(p1.lng 到 180)和我们计算出的 A 的角度来计算出 B 的新斜边,这样我们就可以得到B:
的新 adjacent
+170 | p2 /
| /
| /
180 -|-- / -- 180° meridian
| /: B
(lng) | /α:
| / : oppositeB
-170 |_/___:___ ___
p1 adjacentB
(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开始下一行,差距完美闭合!
高中数学(嗯,毕达哥拉斯的天才)来拯救!我知道它在那个老人脑子里的某个地方嘎嘎作响.....
以这种方式分割线的简单方法是使用 Turf 的 lineSplit
函数。类似于:
const meridian = turf.lineString([[180, -90], [180, 90]]);
const linePieces = turf.lineSplit(myline, meridian);
我没试过这个,所以不确定Turf本身在子午线上是否有任何怪异。如果是这样,您可能需要暂时将坐标转换到其他地方或其他地方。
在任何情况下都比自己做三角函数要好,尤其是因为它可能会在世界不平坦的情况下引入错误。
我正在 MapboxGL (js) 世界地图上绘制一条沿着轨道物体路径的线。我通过在对象轨道更新时向线几何数组添加一组新的十进制 longitude/latitude 坐标来实现此目的。
Mapbox(和其他)有一个已知问题,当绘制一条穿过 180° 子午线(经度)的线时,我们没有得到一条从 a 到 b 的漂亮直线,我们得到一条很长的线从 a 到 b 环绕整个地球:
而不是:我们得到: / / //___ .../..... ......... 180° 子午线 / ___ / / / /
此处和 Mapbox 上的“已接受”答案建议转移到 0°/360° 经度范围,但这只会将问题从赤道转移到极点。这对于大多数一般建议来说很好,但对于我们可能穿过 0°/360° 子午线的轨道跟踪来说仍然是一个问题。
我的解决方案是使用 MultiLine 几何图形,并在我穿过这条子午线时将我的坐标分解成新的数组,但是,这总是会留下一个小间隙,或者,如果我在任一侧“180,纬度”,我们得到子午线上的“扭结”:
差距:或扭结: / / / / .......... ......|... 180°子午线 / / / / /
所以我需要弄清楚如果经度在子午线上,那么精确纬度是多少,知道两边的起点和终点:
+170 | p2 /: | / : | / : 180 -|-----/ 像素? -- 180°经线 | /: : (液化天然气) | / : : | / : : -170 |_/___:___:___ p1 x? (纬度)
我需要求解纬度 x 以便生成 pX(如果经度为 180,则知道 p1 和 p2)。一旦我有了 pX,我就可以将它添加到最后一行的末尾和下一行的开头,从而缩小差距(或平滑“扭结”)。
我知道这是基本的 Trig,但我的老脑子又让我失望了.. ....
已解决!使用基本 Trig(在写问题时 - 所以无论如何我都会发布它,以防它帮助其他人):
我们基本上是在玩两个直角三角形:p1 到 p2,以及较小的直角三角形,其对边停止在子午线处,它们都具有相同的斜边角。所以,我们有:
+170 | p2 /| | / | | / | 180 -|-----/ pX? -- 180° meridian | /: | (lng) | / : A | | / B: | -170 |_/___:___|___ p1 x? (lat)
其中A是我们p1到p2的直角三角形,B是从p1经度到子午线的三角形,我们需要计算其邻边。
毕达哥拉斯基本上告诉我们,我们所需要的只是直角三角形的两个数据点(除了直角)来解决任何其他问题。
我们已经有了A的相反和相邻的长度:
+170 | p2 /| | /α| | / | 180 -|-- / | -- 180° meridian | / | (lng) | / A | oppositeA | / | -170 |_/β______|___ p1 adjacentA (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
现在我们需要 new 与 B 的对角(p1.lng 到 180)和我们计算出的 A 的角度来计算出 B 的新斜边,这样我们就可以得到B:
的新 adjacent+170 | p2 / | / | / 180 -|-- / -- 180° meridian | /: B (lng) | /α: | / : oppositeB -170 |_/___:___ ___ p1 adjacentB (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开始下一行,差距完美闭合!
高中数学(嗯,毕达哥拉斯的天才)来拯救!我知道它在那个老人脑子里的某个地方嘎嘎作响.....
以这种方式分割线的简单方法是使用 Turf 的 lineSplit
函数。类似于:
const meridian = turf.lineString([[180, -90], [180, 90]]);
const linePieces = turf.lineSplit(myline, meridian);
我没试过这个,所以不确定Turf本身在子午线上是否有任何怪异。如果是这样,您可能需要暂时将坐标转换到其他地方或其他地方。
在任何情况下都比自己做三角函数要好,尤其是因为它可能会在世界不平坦的情况下引入错误。