Я пытаюсь нарисовать прямую линию, постоянно указывающую на северо-восток (45 градусов) на картах Google. Это означает, что если я буду плыть по этой линии, всякий раз, когда я смотрю на компас, я всегда буду идти на северо-запад. Это JS-код, который я создал с помощью API карт Google. (пожалуйста, замените ключ API, если вы попытаетесь его протестировать)
Я предполагаю, что независимо от того, нарисую ли я одну линию или несколько линий с разными интервалами, они всегда будут перекрывать друг друга. Но результата оказалось нет. Чем больше точек вы наносите на линию, тем ближе она к экрану под углом 45 градусов. Это из-за точности или есть ошибка? Правильно ли работает google.maps.geometry.computeOffset? Стоит ли доверять этой функции?
function initMap() {
var mapOptions = {
zoom: 1,
center: {
lat: 30.363,
lng: 250.044
}
};
var map = new google.maps.Map(document.getElementById('map'), mapOptions);
var origin = new google.maps.LatLng(-25.363, 214.044);
var fineLoxo = drawRhumbLine(origin.lat(), origin.lng(), 45, 1000);
var fineDrawingPath = new google.maps.Polyline({
path: fineLoxo,
geodesic: false, // Set to false because loxodrome is not eodesic
strokeColor: '#000',
strokeOpacity: 1.0,
strokeWeight: 5
});
fineDrawingPath.setMap(map);
var brokenLoxoPath = drawRhumbLine(origin.lat(), origin.lng(), 45, 4000000);
var mediumDrawingPath = new google.maps.Polyline({
path: brokenLoxoPath,
geodesic: false, // Set to false because loxodrome is not geodesic
strokeColor: '#FF0000',
strokeOpacity: 1.0,
strokeWeight: 2
});
mediumDrawingPath.setMap(map);
var oneLoxoPath = drawRhumbLine(origin.lat(), origin.lng(), 45, 16000000);
var straightDrawingPath = new google.maps.Polyline({
path: oneLoxoPath,
geodesic: false, // Set to false because loxodrome is not geodesic
strokeColor: '#00F',
strokeOpacity: 1.0,
strokeWeight: 2
});
straightDrawingPath.setMap(map);
}
function drawRhumbLine(startLat, startLng, bearingDegrees, interval) {
var dots = []
dots.push({
lat: startLat,
lng: startLng
});
for (let i = 0; i < 16000000 / interval; i++) {
var tempOrigin = new google.maps.LatLng(startLat, startLng)
var dest = google.maps.geometry.spherical.computeOffset(tempOrigin, interval, bearingDegrees);
startLat = dest.lat();
startLng = dest.lng();
dots.push({
lat: startLat,
lng: startLng
});
}
return dots;
}<div id = "map" style = "height: 180px; width: 100%;"></div>
<script src = "https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&libraries=geometry&callback=initMap"
async defer></script>Извини, моя ошибка. я предпочитаю, если это рифма





Из Википедии Румба, прямая линия — это дуга, пересекающая все меридианы долготы под одним и тем же углом.
Акцент на пересечении всех меридианов под одним углом, на потом.
На карте Меркатора (поскольку она сохраняет углы вокруг всех мест) любая прямая линия является прямой.
Так что это уже намек и на то, что использование большего количества меньших сегментов — правильный подход, но зачем это нужно?
Именно добиться пересечения всех меридианов под одним углом. В противном случае, если вы возьмете только одну начальную точку и пойдете по постоянному курсу, исходя из угла, пересекающего первый меридиан, вы не пересечете следующий под тем же углом.
Еще раз цитирую Википедию Румба:
На большом круге азимут на пункт назначения не остается постоянным. Если бы кто-то вел машину по большому кругу, нужно было бы держать руль неподвижно, но чтобы следовать по прямой линии, нужно было бы поворачивать колесо, поворачивая его тем сильнее по мере приближения к столбам.
Таким образом, если вы используете один сегмент, вы получите большой круг, но если вам нужна линия Румба, вам понадобится много сегментов; теоретически бесконечное количество, на практике столько же, сколько пикселей на карте.
Прежде всего, чтобы ответить на ваш вопрос: да, вы можете быть уверены, что google.maps.geometry.pherical.computeOffset работает правильно.
Во-вторых, ваши функции drawRhumbLine на самом деле не вычисляют линию Румба или локсодрому, поскольку они используют google.maps.geometry.pherical.computeOffset. Эта функция, как следует из названия, использует сферические вычисления для больших расстояний по окружности, это не то, что вам нужно для локсодромий.
Вместо этого, если вам нужен локсодром и у вас есть проекция Меркатора, вам следует использовать математику Меркатора. Эта замечательная статья довольно хорошо это объясняет. Я использовал его для своей версии drawRhumbLine.
Таким образом, ваша функция drawRhumbLine должна быть такой:
function drawRhumbLine(startLat, startLng, bearingDegrees, interval) {
var dots = []
const bearing = bearingDegrees * Math.PI / 180;
const bearingB = (180 - 90 - bearingDegrees) * Math.PI / 180;
for (let i = 0; i <= 113.137085 / interval; i++) {
let lat = startLat + i*interval * Math.cos(bearing);
let lat1 = (lat/2+45)*Math.PI/180;
let lat0 = (startLat/2+45)*Math.PI/180;
let dest = {
lat: startLat + i*interval * Math.cos(bearing),
lng: startLng + (Math.tan(bearing)*180/Math.PI) * Math.log(Math.tan(lat1) / Math.tan(lat0))
};
dots.push(dest);
}
return dots;
}
Полный пример я разместил здесь.
Руме — река длиной 48 км (30 миль) в Нижней Саксонии, Германия. Источник: википедия.