Как узнать широту и долготу прямоугольника, если я знаю координаты GPS в центре и в верхнем левом углу?
Фон:
Я пытаюсь использовать наземное наложение карт Google, но нам не хватает позиций GPS.
У нас есть карта для наложения, которая была нарисована на скриншоте Google Maps. На этом скриншоте мы записали верхнюю левую и центральную позицию.
Нам требуется нижнее правое положение, чтобы точно наложить эти изображения. Увидеть ниже:
Начальное мышление находит разницу между двумя точками и добавляет ее к центральной точке.
Попытка логики:
В JavaScript:
var topLeft = [-32.8830055, 151.686214];
var centerCenter = [-32.9293803, 151.756686];
var difference1 = centerCenter[0] - ( (topLeft[0] - centerCenter[0] ) ) ;
var difference2 = centerCenter[1] - ( (topLeft[1] - centerCenter[1] ) ) ;
// being bottom right this should be "bigger" than above values
// outputs [-32.97575509999999, 151.827158];
var bottomRight = [difference1 , difference2];
Проблема:
Однако, похоже, что именно здесь изгиб земли выбрасывает эту простую математику за дверь. Я предполагаю, что то, что происходит ниже, - вот почему.
Поэтому, учитывая, что у меня есть наложение прямоугольника, и я знаю верхнюю левую точку и центральную точку, могу ли я определить широту и долготу нижней правой точки Ie X на приведенной выше диаграмме. Заметьте, я не знаю реальных расстояний этого прямоугольника.
Примечание: я также знаю, что мне придется изменить их на NW / SE, чтобы использовать наземные наложения.
5 ответов
Подход (с использованием геометрии-библиотеки):
рассчитать курс с северо-запада на центр
google.maps.geometry.spherical.computeHeading(northwest, center);
рассчитать расстояние от северо-запада до центра
google.maps.geometry.spherical.computeDistanceBetween(northwest, center);
рассчитать юго-восток с помощью
google.maps.geometry.spherical.computeOffset(center, calculatedDistance, calculatedHeading);
function initialize() {
var nw = new google.maps.LatLng(62.400471, -150.287132),
center = new google.maps.LatLng(62.341145, -150.14637),
map = new google.maps.Map(document.getElementById('map_canvas'), {
zoom: 9,
center: center
}),
heading, distance, se;
heading = google.maps.geometry.spherical.computeHeading(nw, center);
distance = google.maps.geometry.spherical.computeDistanceBetween(nw, center);
se = google.maps.geometry.spherical.computeOffset(center, distance, heading);
new google.maps.Marker({
map: map,
position: center
});
new google.maps.Marker({
map: map,
position: nw
});
new google.maps.Marker({
map: map,
position: se
});
new google.maps.GroundOverlay(
'https://developers.google.com/maps/documentation/' +
'javascript/examples/full/images/talkeetna.png', {
north: nw.lat(),
south: se.lat(),
west: nw.lng(),
east: se.lng()
}, {
map: map
});
}
google.maps.event.addDomListener(window, 'load', initialize);
html,
body,
#map_canvas {
height: 100%;
margin: 0;
padding: 0;
}
<div id="map_canvas"></div>
<script src="https://maps.googleapis.com/maps/api/js?v=3&libraries=geometry"></script>
Вы не хотите использовать библиотеку, которая уже поддерживает расчет центральных точек Haversine? (С тестами для загрузки)
Проверьте Geolib: https://github.com/manuelbieh/Geolib
var center = geolib.getCenter([
{latitude: 52.516272, longitude: 13.377722},
{latitude: 51.515, longitude: 7.453619},
{latitude: 51.503333, longitude: -0.119722}
]);
console.log(center);
// Output:
//
// {
// "latitude": "52.009802",
// "longitude": "6.629000",
// "distance": 932.209
// }
Демоверсию Codepen, с которой вы можете поиграть: http://codepen.io/anon/pen/grbGrz/?editors=1010
Вы всегда можете уменьшить его до нужной вам функции.
Чтобы не начинать с начала вашего запроса. у вас есть два значения, и теперь вы хотите получить значение прямоугольника.
мы сначала перейдем к части расчета, а затем к части программирования. предположения
центральная точка = е
верхний левый = A
верхний правый = B
справа внизу = C
внизу слева = D
средняя точка нашей эры = f
средняя точка AB = g
Расчетная часть
параметры местоположения g- лат. длин., длинный.
параметры местоположения - шир. лат., длинн. -длинный
расстояние от А до g равно = А. расстояние (г)
расстояние от A до f is = A.distanceTo (f)
точка B = 2Ag от A
точка C = 2Af от B
точка D = 2Af от A
Часть программирования
LatLng A = null, B = null, C = null, D = null, e = null, f = null, g = null,temp=null;
e.latitude = your center latitude value;
e.longitude = your center longitude value;
A.latitude=your top left point latitude value;
A.longitude=your top left point longitude value;
f.latitude = e.latitude;
f.longitude = A.longitude;
g.latitude = A.latitude;
g.longitude = e.longitude;
double[] Ag = new double[1];
double[] Af = new double[1];
Location.distanceBetween(A.latitude, A.longitude, g.latitude, g.longitude, Ag);
Location.distanceBetween(A.latitude, A.longitude, f.latitude, f.longitude, Af);
temp=getDestinationPoint(A,90,(2*Ag));
B.latitude=temp.latitude;
B.longitude=temp.longitude;
temp=getDestinationPoint(B,180,(2*Af));
C.latitude=temp.latitude;
C.longitude=temp.longitude;
temp=getDestinationPoint(A,180,(2*Af));
D.latitude=temp.latitude;
D.longitude=temp.longitude;
private LatLng getDestinationPoint (LatLng source,double brng, double dist){
dist = dist / 6371;
brng = Math.toRadians(brng);
double lat1 = Math.toRadians(source.latitude), lon1 = Math.toRadians(source.longitude);
double lat2 = Math.asin(Math.sin(lat1) * Math.cos(dist) +
Math.cos(lat1) * Math.sin(dist) * Math.cos(brng));
double lon2 = lon1 + Math.atan2(Math.sin(brng) * Math.sin(dist) *
Math.cos(lat1),
Math.cos(dist) - Math.sin(lat1) *
Math.sin(lat2));
if (Double.isNaN(lat2) || Double.isNaN(lon2)) {
return null;
}
return new LatLng(Math.toDegrees(lat2), Math.toDegrees(lon2));
}
объяснение
точки f и g являются средними точками прямой AD и AB соответственно. мы можем получить его, изменив значения lat и long точек A и e. и по этим двум длинам (Af и Ag) мы можем получить четыре точки прямоугольника, как вам нужно.
благодарю вас
Скорее всего, вам понадобится формула Haversine для такого расчета. Математическая математика, очевидно, находится на более высоком уровне, чем обычно для ответов SO, поэтому ваш вопрос может фактически принадлежать к обменам стеками gis или math, где некоторые более опытные пользователи SO могут дать вам более подробный ответ / пример.
Используйте приведенную ниже функцию javascript для получения списка широты и длины прямоугольника на основе центра и расстояния. LatLngArr - это список точек прямоугольника.
Number.prototype.degreeToRadius = function () {
return this * (Math.PI / 180);
};
Number.prototype.radiusToDegree = function () {
return (180 * this) / Math.PI;
};
function getBoundingBox(fsLatitude, fsLongitude, fiDistanceInKM) {
if (fiDistanceInKM == null || fiDistanceInKM == undefined || fiDistanceInKM == 0)
fiDistanceInKM = 1;
var MIN_LAT, MAX_LAT, MIN_LON, MAX_LON, ldEarthRadius, ldDistanceInRadius, lsLatitudeInDegree, lsLongitudeInDegree,
lsLatitudeInRadius, lsLongitudeInRadius, lsMinLatitude, lsMaxLatitude, lsMinLongitude, lsMaxLongitude, deltaLon;
// coordinate limits
MIN_LAT = (-90).degreeToRadius();
MAX_LAT = (90).degreeToRadius();
MIN_LON = (-180).degreeToRadius();
MAX_LON = (180).degreeToRadius();
// Earth's radius (km)
ldEarthRadius = 6378.1;
// angular distance in radians on a great circle
ldDistanceInRadius = fiDistanceInKM / ldEarthRadius;
// center point coordinates (deg)
lsLatitudeInDegree = fsLatitude;
lsLongitudeInDegree = fsLongitude;
// center point coordinates (rad)
lsLatitudeInRadius = lsLatitudeInDegree.degreeToRadius();
lsLongitudeInRadius = lsLongitudeInDegree.degreeToRadius();
// minimum and maximum latitudes for given distance
lsMinLatitude = lsLatitudeInRadius - ldDistanceInRadius;
lsMaxLatitude = lsLatitudeInRadius + ldDistanceInRadius;
// minimum and maximum longitudes for given distance
lsMinLongitude = void 0;
lsMaxLongitude = void 0;
// define deltaLon to help determine min and max longitudes
deltaLon = Math.asin(Math.sin(ldDistanceInRadius) / Math.cos(lsLatitudeInRadius));
if (lsMinLatitude > MIN_LAT && lsMaxLatitude < MAX_LAT) {
lsMinLongitude = lsLongitudeInRadius - deltaLon;
lsMaxLongitude = lsLongitudeInRadius + deltaLon;
if (lsMinLongitude < MIN_LON) {
lsMinLongitude = lsMinLongitude + 2 * Math.PI;
}
if (lsMaxLongitude > MAX_LON) {
lsMaxLongitude = lsMaxLongitude - 2 * Math.PI;
}
}
// a pole is within the given distance
else {
lsMinLatitude = Math.max(lsMinLatitude, MIN_LAT);
lsMaxLatitude = Math.min(lsMaxLatitude, MAX_LAT);
lsMinLongitude = MIN_LON;
lsMaxLongitude = MAX_LON;
}
return [
lsMinLatitude.radiusToDegree(),
lsMinLongitude.radiusToDegree(),
lsMaxLatitude.radiusToDegree(),
lsMaxLongitude.radiusToDegree()
];
};
используйте приведенный ниже код для создания массива прямоугольников широты и долготы.
var lsRectangleLatLong = getBoundingBox(parseFloat(latitude), parseFloat(longitude), lsDistance);
if (lsRectangleLatLong != null && lsRectangleLatLong != undefined) {
latLngArr.push({ lat: lsRectangleLatLong[0], lng: lsRectangleLatLong[1] });
latLngArr.push({ lat: lsRectangleLatLong[0], lng: lsRectangleLatLong[3] });
latLngArr.push({ lat: lsRectangleLatLong[2], lng: lsRectangleLatLong[3] });
latLngArr.push({ lat: lsRectangleLatLong[2], lng: lsRectangleLatLong[1] });
}