7

Это немного вопрос с некоторым уровнем детализации, поэтому позвольте мне сначала объяснить ситуацию, затем мою реализацию и последний вопрос, чтобы вы лучше поняли.Неверный ответ службы сервиса «Карты Google» при расщеплении слишком большого пути

По состоянию на 4 апреля добавлено обновление и проблемы сужены до одной незавершенной проблемы, см. Нижнюю часть этого вопроса для актуальной информации.

TLDR;

У меня есть длинный маршрут, возвращаемый API Google Maps Directions и требующий диаграмму высоты для этого маршрута. Слишком плохо, что он не работает, потому что он запрашивается через GET, а максимальная длина URL - 2.048 символов, которые превышают. Я разделил запросы; гарантировал правильный порядок обработки, используя Promises; но данные Evelation не всегда полны для полного маршрута, не всегда отображаются в правильном порядке, не всегда следуют заданному пути, а местоположение промежуточной высоты занимает иногда несколько километров.

Введение;

Пытается создать диаграмму высот для ответа на Google Maps DirectionsService. Я столкнулся с проблемой слишком длинных маршрутов (это, похоже, не связано с расстоянием, а не с числом LatLngs за просмотр_просмотра). Это связано с тем, что ElevationService запрашивается через GET, а максимальная длина URL - 2048 символов. Эта проблема - described on SO here as well.

Реализация;

Я полагал, что я умнее, чем Google (не очень, но, по крайней мере, пытаюсь найти способ работать вокруг него), чтобы разделить путь, возвращаемый DirectionsService (overview_path собственности) в партии и сцепить результаты (elevations, возвращенный методом ElevationService getElevationsAlongPath).

  • Чтобы получить наилучший уровень детализации, я запрашиваю ElevationService с 512 сэмплами за партию;
  • и потому, что ElevationService распространяется на образцах по длине пути я создал максимальное количество LatLng на замес и проверить сколько партий требуются для обработки полного пути (totalBatches = overview_path.length/maxBatchSize);
  • и, наконец, получить равномерное распределение по моим направлениям, приведет к попытке , чтобы получить равный уровень детализации для всего маршрута (batchSize = Math.ceil(overview_path.length/totalBatches)).

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

Мой код

var maxBatchSize = 200; 
var currentBatch = 0; 
var promise = Promise.resolve(); 
var totalElevationBatches = Math.ceil(directions.routes[0].overview_path.length/maxBatchSize); 
var batchSize = Math.ceil(directions.routes[0].overview_path.length/totalElevationBatches); 

while(currentBatch < totalElevationBatches) { 
    promise = addToChain(promise, currentBatch, batchSize); 
    currentBatch++; 
} 

promise.then(function() { 
    drawRouteElevationChart(); // this uses the routeElevations to draw an AreaChart 
}); 

function getRouteElevationChartDataBatchPromise(batch, batchSize) { 
    return new Promise(function(resolve, reject) { 
     var elevator = new google.maps.ElevationService(); 
     var thisBatchPath = []; 

     for (var j = batch * batchSize; j < batch * batchSize + batchSize; j++) { 
      if (j < directions.routes[0].overview_path.length) { 
       thisBatchPath.push(directions.routes[0].overview_path[j]); 
      } else { 
       break; 
      } 
     } 

     elevator.getElevationAlongPath({ 
      path: thisBatchPath, 
      samples: 512 
     }, function (elevations, status) { 
      if (status != google.maps.ElevationStatus.OK) { 
       if(status == google.maps.ElevationStatus.OVER_QUERY_LIMIT) { 
        console.log('Over query limit, retrying in 250ms'); 

        resolve(setTimeout(function() { 
         getRouteElevationChartDataBatchPromise(batch, batchSize); 

        }, 250)); 
       } else { 
        reject(status); 
       } 
      } else { 
       routeElevations = routeElevations.concat(elevations); 
       resolve(); 
      } 
     }); 
    }); 
} 

function addToChain(chain, batch, batchSize){ 
    return chain.then(function(){ 
     console.log('Promise add to chain for batch: ' + batch); 
     return getRouteElevationChartDataBatchPromise(batch, batchSize); 
    }); 
} 

Примечание стороны;

Я также заказываю запрос DirectionService для обращения к 8-ми путевым ограничениям, которые имеет сервис, но я могу подтвердить, что это не проблема, так как я также столкнулся с проблемой с 8 или менее путевыми точками.

Problem;

Проблемы я сталкиваюсь являются:

  • Данные о высоте не всегда после полного пути маршрута, а это означает последнюю точку возвышения на графике (далеко) от конца маршрута;
  • Данные о высоте иногда отображаются в случайном порядке, как будто кажется, что обещания все еще не ожидали выполнения следующей задачи;
  • Данные о высоте не всегда соответствуют данным LatLng от overview_path, предоставленных в данной партии (см. Снимок экрана);
  • Данные о расстоянии между перекрестными точками очень много. Иногда занимает несколько километров, в то же время запрашивая 512 образцов для равномерно совпадающего размера партии с максимальным количеством 200 LatLng с за партию.

elevation data not following the overview_path it was told to follow

Я полагал дозирование в ElevationService с помощью Promises (и до того времени с setTimtout) будет решать все свои проблемы, но единственная проблема, я решил не превышая запрос URL 2,048 обугленных и перед описанной выше новой вопросы.

Помощь действительно оценили

Кроме того, я хотел бы поставить 250 респ. щедрость по этому вопросу прямо впереди, но это невозможно в данный момент. Поэтому, пожалуйста, не стесняйтесь отвечать, поскольку я могу позже добавить щедрость и наградить ее ответом, который решает описанные проблемы. A 250 rep. награда была награждена, чтобы показать мою признательность за то, что вы указали мне в правильном направлении.

Спасибо за чтение и ответ!

Обновлен 4 апреля оставляя 1 отложенного вопроса (до тех пор, как я могу сказать на данный момент)

Проблема с возвышенностями в случайном порядке, решаемых вниз

Я был в состоянии решить некоторые о проблемах, когда я замечал непоследовательное поведение в результатах маршрутов. Это было вызвано по очевидной причине: асинхронные вызовы не были «обещаны», чтобы быть запланированными, поэтому некоторые из них были правильными, в большинстве случаев это не так. Я не заметил этого сначала, потому что маркеры были отображены правильно (кэшировано).

Проблема с подъемом между расстоянием решать вниз

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

Проблема с данными высот не показывая по маршруту

Как-то куда-то вниз по линии Я также решил эту проблему, но я не уверен, если больше ширины или «Перспективный» порядок направления решил это.

До выпуска: данные о высоте не всегда полная

Единственный оставшийся вопрос заключается в том, что данные высота не всегда покрывает полный путь. Я считаю, что это связано с тем, что ошибка в логике Promising, потому что запись некоторых сообщений в консоли говорит мне, что диаграмма высот рисуется в точке, где не все Promise-then завершены, и я думаю, что это вызвано повторением пакетного вызова, когда Over Ошибка ограничения запроса возвращается API Карт Google.

Как я могу восстановить одну и ту же цепочку при возврате ошибки с превышением запроса? Я попытался не разрешить эту же функцию снова, но просто запустил setTimeout(...), но тогда Promise, похоже, не разрешает обновленную партию в настоящий момент, когда она больше не получает Over Over Query Limit. В настоящее время это, как я поставил его (в обоих направлениях и возвышения):

function getRouteElevationChartDataBatchPromise(batch, batchSize) { 
    return new Promise(function(resolve, reject) { 
     var elevator = new google.maps.ElevationService(); 
     var thisBatchPath = []; 

     for (var j = batch * batchSize; j < batch * batchSize + batchSize; j++) { 
      if (j < directions.routes[0].overview_path.length) { 
       thisBatchPath.push(directions.routes[0].overview_path[j]); 
      } else { 
       break; 
      } 
     } 

     elevator.getElevationAlongPath({ 
      path: thisBatchPath, 
      samples: 512 
     }, function (elevations, status) { 
      if (status != google.maps.ElevationStatus.OK) { 
       if(status == google.maps.ElevationStatus.OVER_QUERY_LIMIT) { 
        console.log('ElevationService: Over Query Limit, retrying in 200ms'); 

        resolve(setTimeout(function() { 
         getRouteElevationChartDataBatchPromise(batch, batchSize); 

        }, 200)); 
       } else { 
        reject(status); 
       } 
      } else { 
       console.log('Elevations Count: ' + elevations.length); 
       routeElevations = routeElevations.concat(elevations); 
       resolve(); 
      } 
     }); 
    }); 
} 

ответ

0

Последняя оставшаяся проблема также была решена с помощью этого вопроса SO: How to re-run a javascript promise when failed?. Так что если jfriend00 отвечает на этот вопрос, я могу присудить ему награду, так как это трюк, который помог мне в конце.

Чтобы быть уверенным, что функция решает в состоянии OK, повторов на OVER_QUERY_LIMIT и отвергает на any other status я должен был поставить логику Promise внутри функции и вызвать эту функцию, например, так:

function getRouteElevationChartDataBatchPromise(batch, batchSize) { 
    return new Promise(function(resolve, reject) { 
     function run(batch, batchSize) { 
      var elevator = new google.maps.ElevationService(); 
      var thisBatchPath = []; 

      for (var j = batch * batchSize; j < batch * batchSize + batchSize; j++) { 
       if (j < directions.routes[0].overview_path.length) { 
        thisBatchPath.push(directions.routes[0].overview_path[j]); 
       } else { 
        break; 
       } 
      } 

      elevator.getElevationAlongPath({ 
       path: thisBatchPath, 
       samples: 512 
      }, function (elevations, status) { 
       if(status == google.maps.ElevationStatus.OK) { 
        routeElevations = routeElevations.concat(elevations); 
        resolve(); 
       } else if (status == google.maps.ElevationStatus.OVER_QUERY_LIMIT) {       
        setTimeout(function() { 
         run(batch, batchSize); 
        }, 200); 
       } else { 
        reject(status); 
       } 
      }); 
     } 

     run(batch, batchSize); 
    }); 
} 
0

затронутым в реализации части, примечания и проблемы, перечисленные все покрыты в Google Maps Elevation API. Полная документация обеспечивает простой интерфейс для запроса местоположений на земле для данных о высоте и будет решать все возникающие проблемы, такие как запросы на высоту, использование параметров, указание местоположений, путей и ответов на возвышения.

Для беспокойства, обсуждаемого в вашем Введении, API высотных карт Google Maps имеет стандартные и максимальные пределы использования. Эти ограничения применяются для предотвращения злоупотребления API надстройки Google Maps. Google Maps Elevation API Usage Limits содержит информацию о лимитах использования и возможности увеличения квоты.

Дополнительные примечания от документации, которая может решить ваши проблемы:

  1. Обратите внимание, что данные высота становится более грубой, когда прошло несколько точек. Чтобы получить наиболее точное значение высоты для точки, ее необходимо запросить независимо.
  2. В тех случаях, когда Google не имеет точных измерений высоты в точном месте, которое вы запрашиваете, служба будет интерполировать и возвращать усредненное значение, используя четыре ближайших местоположения.
  3. Как и в случае с позиционными запросами, параметр path указывает набор значений широты и долготы. Однако, в отличие от позиционного запроса, путь указывает упорядоченный набор вершин. Вместо того, чтобы возвращать данные о высоте в вершинах, запросы маршрута отбираются по длине пути, где каждый образец равноудален друг от друга.
  4. API Elevations Google Maps возвращает данные для одноточечных запросов с максимально возможной точностью. Пакетные запросы с несколькими местоположениями могут возвращать данные с меньшей точностью.
+0

Спасибо за ваш ответ. Но я не соглашаюсь (полностью) с вами. В рамках API Карт Google он обеспечивает отличные данные о высоте вдоль маршрута. Так; когда я выполняю эти запросы для выполнения вызова в заданных границах, ожидается ответ службы высотного обслуживания. Я только конкатенирую результаты, чтобы отображать несколько ответов в диаграмме. По-моему, это должно быть возможно. – Ben

0

Mmmh, с какого количества баллов вам приходится обращаться. Можете ли вы опубликовать этот путь, так что, возможно, некоторые другие могут протестировать его в своих приложениях. Вы пытались уменьшить точки пути с помощью Дугласа-Пеукера или сопоставимых методов. Вы пробовали другие приложения, такие как бесплатный «Routeconverter» (который работает с HGT), чтобы увидеть, есть ли у вас лучшие результаты. Нужны ли вам точки возвышения прямо/на лету? Будет ли использование других бесплатных служб возвышения. Возможно, вам нужно прочитать точки возвышения до ваших точек маршрута, чтобы вы могли сортировать ненужные точки.

Только некоторые думают, на плохом английском языке - боюсь. Удачи, Рейнхард

+0

Спасибо за ваш ответ, но я уже сузил проблемы до вероятной причины. Но мне нравится упоминание о Рамер Дуглас Пиккер, о котором я раньше не слышал;) – Ben

Смежные вопросы