Это ошибка google.maps.geometry.computeOffset?

Я пытаюсь нарисовать прямую линию, постоянно указывающую на северо-восток (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>

Руме — река длиной 48 км (30 миль) в Нижней Саксонии, Германия. Источник: википедия.

MrUpsidown 25.03.2024 14:46

Извини, моя ошибка. я предпочитаю, если это рифма

Hoy Cheung 25.03.2024 16:01
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
2
2
73
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Из Википедии Румба, прямая линия — это дуга, пересекающая все меридианы долготы под одним и тем же углом.

Акцент на пересечении всех меридианов под одним углом, на потом.

На карте Меркатора (поскольку она сохраняет углы вокруг всех мест) любая прямая линия является прямой.

Так что это уже намек и на то, что использование большего количества меньших сегментов — правильный подход, но зачем это нужно?

Именно добиться пересечения всех меридианов под одним углом. В противном случае, если вы возьмете только одну начальную точку и пойдете по постоянному курсу, исходя из угла, пересекающего первый меридиан, вы не пересечете следующий под тем же углом.

Еще раз цитирую Википедию Румба:

На большом круге азимут на пункт назначения не остается постоянным. Если бы кто-то вел машину по большому кругу, нужно было бы держать руль неподвижно, но чтобы следовать по прямой линии, нужно было бы поворачивать колесо, поворачивая его тем сильнее по мере приближения к столбам.

Таким образом, если вы используете один сегмент, вы получите большой круг, но если вам нужна линия Румба, вам понадобится много сегментов; теоретически бесконечное количество, на практике столько же, сколько пикселей на карте.

Ответ принят как подходящий

Прежде всего, чтобы ответить на ваш вопрос: да, вы можете быть уверены, что 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;
}

Полный пример я разместил здесь.

Другие вопросы по теме