如何从给定坐标中获取中心坐标? [关闭]
Posted
技术标签:
【中文标题】如何从给定坐标中获取中心坐标? [关闭]【英文标题】:how can I get the center coordinate from the given coordinates? [closed] 【发布时间】:2021-10-23 10:05:08 【问题描述】:我正在使用 vue2 谷歌地图包,我有这样的数组对象:
markers:[
lat: 14.692734621176195, lng: 120.9642877585083 ,
lat: 14.691963317641529, lng: 120.9715473253784 ,
lat: 14.702160611177580, lng: 120.9621292582138
]
此外,对象 markers 是动态的,因此它可以包含多于/少于 3 个对象。
问题:谷歌地图在渲染时没有对齐中心,因为我不知道如何找到中心坐标。有什么解决方法或建议如何将谷歌地图居中对齐?
【问题讨论】:
这里的“中心坐标”是什么? 你可以在这里看到这两种方法的区别:q2k0r.csb.app。您将蓝色方法标记为正确的“中心”。 重复Center/Set Zoom of Map to cover all visible Markers? @MrUpsidown,从技术上讲,这个问题并不要求fitBounds
,这意味着更改缩放级别。它只要求一个公式来找到一组标记的中心点。您指出的问题不包含这样的公式。
从技术上讲,这个问题很模糊,没有提供任何背景或细节。 fitBounds
通常是前往地图上“中心”标记的方式。
【参考方案1】:
This website提供了查找坐标中心的功能。
function findCenter(markers)
let lat = 0;
let lng = 0;
for(let i = 0; i < markers.length; ++i)
lat += markers[i].lat;
lng += markers[i].lng;
lat /= markers.length;
lng /= markers.length;
return lat: lat, lng: lng
输出是
lat: 14.695619516665102,
lng: 120.96598811403351
jsfiddle
编辑坐标生成的任意形状 正如 tao 所提到的,这个公式对于“任何类型的坐标数组”并不完美。 This 和 this 链接对如何实现您想要的有更好的解释和公式。
【讨论】:
那个方法不对,它计算的是中位数。假设您有 9 个点,lat
的 10
和一个 lat
的点 20
的“中心”,根据您的公式将有一个 lat
的 11
。但实际上应该是15
。您需要一个函数,它可以获取lat
和lng
数组的min
和max
,并获取这些限制之间的中间值。这就是“中心”。
@tao 是的,你说得有道理。我再次检查过,似乎当“坐标创建三角形或正多边形”时,这种方法被告知可以正常工作。见gis.stackexchange.com/questions/12120/… 和en.wikipedia.org/wiki/Centroid#By_geometric_decomposition
这是一个失败的三角形示例:[lat: 10, lng: 120, lat: 10, lng: 130, lat: 20, lng: 120]
。您的方法返回lat: 13.333333333333334, lng: 123.33333333333333
。正确的结果是 lat: 15, lng: 125
。
您的公式计算所谓的“质心”或“重心”或“质心”。这意味着如果您有更多点靠近一侧,它们会将“重心”拉向那一侧。而我们不想要这个。我们只想找到包含所有点的屏幕中间(矩形),而不管有多少点靠近一侧。
我制作了一个代码框,以提供我上面的 cmets 的图形(更直观)解释:q2k0r.csb.app。蓝色(重心)是您答案中的方法,绿色(限制中位数)是我在答案中概述的方法。编码愉快!【参考方案2】:
如果您想做的是适合屏幕上的当前标记选择,您可能正在寻找fitBounds 方法。另请参阅这两个答案:
Center/Set Zoom of Map to cover all visible Markers? Calculate the center point of multiple latitude/longitude coordinate pairs谢谢你,@MrUpsidown。
如果您有兴趣在不更改缩放级别的情况下找到标记选择的“中间”,这是我的原始答案:
“寻找中心”可能是一个复杂的几何问题,但在您的情况下,您似乎想要找到包含所有点的最小 NS/EW 矩形的对角线的交点。
这意味着您应该获取lat
和lng
数组的min
和max
,并为每个数组找到这些限制的中值。
// this fails when polygon crosses 180th meridian!
function findCenter(markers)
const lats = markers.map(m => m.lat);
const lngs = markers.map(m => m.lng);
return
lat: (Math.min(...lats) + Math.max(...lats)) / 2,
lng: (Math.min(...lngs) + Math.max(...lngs)) / 2
;
但是,正如@MrUpsidown 所指出的,对于穿过 180 度子午线的多边形,上述代码会产生错误结果。包含该案例的正确代码是:
function getMiddle(prop, markers)
let values = markers.map(m => m[prop]);
let min = Math.min(...values);
let max = Math.max(...values);
if (prop === 'lng' && (max - min > 180))
values = values.map(val => val < max - 180 ? val + 360 : val);
min = Math.min(...values);
max = Math.max(...values);
let result = (min + max) / 2;
if (prop === 'lng' && result > 180)
result -= 360
return result;
function findCenter(markers)
return
lat: getMiddle('lat', markers),
lng: getMiddle('lng', markers)
// tests:
console.log(findCenter([
lat: 14.692734621176195, lng: 120.9642877585083 ,
lat: 14.691963317641529, lng: 120.9715473253784 ,
lat: 14.702160611177580, lng: 120.9621292582138 ,
]));
// => "lat": 14.697061964409555, "lng": 120.96683829179611
console.log(findCenter([
lat: 50, lng: 45 ,
lat: 0, lng: 125 ,
lat: -50, lng: -100
]))
// => "lat": 0, "lng": 152.5
我的答案(绿色)和tugrul's answer(蓝色)之间的区别在此处以图形方式描述:https://q2k0r.csb.app/
正如@mrupidown 所指出的,Google 地图 API 提供了计算点集合中心的实用程序:
创建一个LatLngBounds
对象并从标记集合中扩展它
在创建的边界对象上使用.getCenter()
。
【讨论】:
如果您发现任何失败的案例,我将非常乐意改进它。感谢您的调查。 jsfiddle.net/upsidown/sj8v7phc - 黄色中心标记是用边界对象计算的 - 蓝色是你的函数 - 红色矩形是边界对象。我认为 issue 仅与矩形外边缘上考虑的点有关。地球是圆的... 公平点,我会用免责声明更新。毕竟,世界是圆的 :) 为什么不添加您自己的答案?公平地说,我应该认为地图 API 应该有一些实用程序来解决这个问题。LatLng
对象所做的另一件事是,它会限制纬度并包裹经度以处理错误/超出范围的值,如 here 所述。
@MrUpsidown,我知道谷歌地图很棒。我的回答和谷歌地图没有做的一件小事是,它提供了一种有用的方法来为任何地图产品(mapbox、传单、openstreetmaps、maplibre)的用户获取“中心”。但你是对的,我的自定义方法不适用于无效坐标。感谢您提供宝贵的反馈和建议。以上是关于如何从给定坐标中获取中心坐标? [关闭]的主要内容,如果未能解决你的问题,请参考以下文章
给定中心坐标(纬度/经度)、半径(米)和中心角(度)的球体(地球)上的圆弧面积 [关闭]