Точки (Placemark) вдоль маршрута

271
12 декабря 2017, 21:31

Вопрос таков, как можно лучше и быстрее показать точки рядом с маршрутом (multiRoute).

Делал 2 варианта, первый это обрисовать маршрут прямоугольниками и показать те точки что попали в них, однако в рамках города это не подходит ибо криво.

Варианта 2 это разбить на сегменты и найти ближайшие точки, однако и тут не все гладко.

Делаю вот так, но что то не то, а именно дистанция считается не верно, вопрос почему . Может от Плейсмарка до сегмента не верно считает ? Но как он вообще считает?

В myCollection лежат PlaceMark.

Код ниже:

  $scope.mMap.geoObjects.add($scope.multiRoute);

        $scope.multiRoute.events.add("update",function () {
                    var wayPoints = $scope.multiRoute.getWayPoints();

                    $scope.myCollection.each(function (GeoPoint) {
                        GeoPoint.options.set('visible',0);
                    });


                    $scope.multiRoute.getRoutes().each(function (route) {
                        console.log('route data:', route.properties.getAll());
                        route.getPaths().each(function (path) {
                            //console.log('path data:', path.properties.getAll());
                            path.getSegments().each(function (segment) {
                                //console.log('segment data:', segment.properties.getAll());
                                 $scope.myCollection.each(function (GeoPoint) {
                                       console.log(GeoPoint.geometry.getType()); 
                                      if(GeoPoint.geometry && GeoPoint.geometry.getType() === 'Point') { 
                                        var obj=segment.geometry.getClosest(GeoPoint.geometry.getCoordinates());
                                        //console.log(obj.distance);
                                        if (obj.distance < 1000){
                                            console.log(obj.distance,GeoPoint.geometry.getCoordinates(),"DIST");
                                            GeoPoint.options.set('visible',1);
                                        } else {
                                          GeoPoint.options.set('visible',0);
                                        }
                                      }

                                    });

                            });
                        });
                    });
        });
Answer 1

Считается неправильно, скорее всего, потому что вы прячете и показываете каждый Placemark для каждого сегмента.

Попробуйте вначале собрать маршрут в линию, а затем делать фильтрацию:

ymaps.ready([ 
  'Map', 'multiRouter.MultiRoute', 'GeoObjectCollection', 'Polyline' 
]).then(function() { 
  const map = new ymaps.Map('map', { 
    center: [55.75, 37.62], 
    zoom: 8, 
    controls: [] 
  }); 
   
  // Создаем мульти-маршрут. 
  var multiRoute = new ymaps.multiRouter.MultiRoute({ 
    referencePoints: ['Шереметьево', 'Домодедово'] 
  }); 
  map.geoObjects.add(multiRoute); 
   
  // Создаем метки. 
  const placemarks = new ymaps.GeoObjectCollection({ 
    children: generatePlacemarks(map.getBounds(), 10) 
  }); 
  map.geoObjects.add(placemarks); 
   
  // Пороговое расстояние в метрах. 
  const threshold = 7500; 
 
  // Как только мульти-маршрут загрузится. 
  multiRoute.events.once('update', function() { 
    // Собираем по линии для каждой нитки маршрута. 
    const lineGeoObjects = multiRoute.getRoutes().toArray() 
      .map(route => new ymaps.Polyline(routeToLineString(route))); 
     
    // Добавляем линии на карту, т.к. getClosest нужна информация о проекции. 
    const lines =  new ymaps.GeoObjectCollection( 
      { children: lineGeoObjects }, 
      { visible: false }); 
    map.geoObjects.add(lines); 
     
    // Обновляем visible для каждой метки. 
    placemarks.each(function(placemark) { 
      const coords = placemark.geometry.getCoordinates(); 
       
      // Вычисляем если расстояние хотя бы до одной нитки меньше порогового. 
      const isNearSomeRoute = lines.toArray() 
        .some(line => { 
          const closest = line.geometry.getClosest(coords); 
          return closest.distance < threshold; 
        }); 
 
      placemark.options.set('visible', isNearSomeRoute); 
    }); 
  }); 
}).catch(console.error); 
 
function routeToLineString(route) { 
  const points = route.getPaths().toArray() 
    .map(x => x.getSegments().toArray()) 
    .reduce((s, x) => s.concat(x), []) // flatten 
    .map(x => x.geometry.getCoordinates()) 
    .reduce((s, x) => s.concat(x), []); // flatten 
 
  // Сюда можно добавить симплификацию линии для ускорения 
  // поиска расстояния. 
 
  return { type: 'LineString', coordinates: points }; 
} 
 
/** Генерирует n x n меток */ 
function generatePlacemarks(bounds, n) { 
  const result = []; 
  const latstep = (bounds[1][0] - bounds[0][0]) / n; 
  const lonstep = (bounds[1][1] - bounds[0][1]) / n; 
  for (let row = 0; row < n; row++) { 
    for (let col = 0; col < n; col++) { 
      result.push(new ymaps.Placemark([ 
          bounds[0][0] + latstep * (0.5 + row), 
          bounds[0][1] + lonstep * (0.5 + col) 
        ], 
        { iconContent: row + ',' + col }, 
        { preset: 'islands#circleIcon' }) 
      ); 
    } 
  } 
 
  return result; 
}
<script src="https://api-maps.yandex.ru/2.1/?lang=ru_RU&mode=debug"></script> 
<div id="map" style="width: 300px; height: 300px"></div>

READ ALSO
Изменение css в jquery

Изменение css в jquery

Не происходит изменение css свойств у элементов при изменении размера окнаСобственно код на js

329
анимация с увеличением и скроллом

анимация с увеличением и скроллом

Как сделать анимацию zoom контейнера со скролом? как на этом сайте https://wwwetq-amsterdam

297