Клуб API Карт

Поиск близжайших станций метро

Пост в архиве.

Видел, что все пользуются субжем, а готового функционала нет. Я не супер программер, набросал то, что ниже, можно это как-то упростить? Просто загадочно - столько людей используют данный функционал, а какого-то отработанного подхода нет :(

 

var map;
$(function() { // используется в догонку jquery, но не основополагающее ^_^
    map = new YMaps.Map(document.getElementById("YMapsID"));
    map.setCenter(new YMaps.GeoPoint(37.6175712235272, 55.75227460852835), 12);
    YMaps.Events.observe(map,map.Events.Click, function(map, mEvent) { placePoint(map, mEvent); });
});
function placePoint(map, mEvent) {
    var coord = mEvent.getCoordPoint();
    var placemark = new YMaps.Placemark(coord);
    var bounds = new YMaps.GeoBounds(new YMaps.GeoPoint(coord.getX()-0.04,coord.getY()-0.02),new YMaps.GeoPoint(coord.getX()+0.04,coord.getY()+0.02)); // квадрат поиска
    placemark.setBalloonContent('<b>Описание нашей точечки:</b> Ля ля ля');
    find_metro(bounds,placemark);
    map.addOverlay(placemark);
}
function find_metro(bounds,placemark) {
    var geocoder = new YMaps.Geocoder('станция метро', { results: 10, boundedBy: bounds, strictBounds: true});
    YMaps.Events.observe(geocoder, geocoder.Events.Load, function () {
        if (this.length()) {
            addToDesc(placemark,'<br /><b>Близжайшие станции метро: </b>');
            for (var i=0;i<this.length();i++) {
                var router = new YMaps.Router([placemark.getGeoPoint(),this.get(i).getGeoPoint()]);
                router.metroName = this.get(i).AddressDetails.Country.Locality.Thoroughfare.Premise.PremiseName.replace('метро ','');
                router.metroLine = this.get(i).AddressDetails.Country.Locality.Thoroughfare.ThoroughfareName;
                YMaps.Events.observe(router, router.Events.Success, function () {
                    addToDesc(placemark,'<br />'+this.metroName+', '+this.metroLine+', ~'+(this.getDistance()/1000).toFixed(3)+'км');
                });
            }
        }
    });
}
function addToDesc(placemark,str) {
    placemark.setBalloonContent(placemark.getBalloonContent()+str);
}

 

 Пример тут:  ссылка 

Может кто знает более изящное решение?

Попутно вопрос: написал рекурсивную функцию по выцеплению всех станций метро, как часто можно её прогонять? Раз в недельку, для сверки актуальности базы можно?

4 комментария
Гениательно!
В клубе были схожие обсуждения:
http://clubs.ya.ru/mapsapi/replies.xml?item_no=5253
http://clubs.ya.ru/mapsapi/replies.xml?item_no=7205

Возможно, что они помогут вам с реализацией поиска.
Да, я это уже раза по три читал, пытался зацепиться, но не получилось. Но всё равно, Спасибо за ответ. ;)
Проблема в том, что оба метода общаются с заранее подготовленной базой, в которой может быть не всё то, что есть у яндекса, либо не так точно (в первом методе как раз это явно по комментам прослеживается). Мне же нужно НЕ вести базу, а где бы я ни был, получать список метро (если оно есть) прям у яндекса. Собственно, сейчас "дошлифую", выложу результат. Реализация исключительно на javascript, без сервер-сайда.
Выцарапал немного времени, переиначил. Опишу завтра. Проверил на Питере и Мск, в Нижнем Новгороде не работало. Где не прав? И как по событию Load геокодера просто возвращать результат обработки данных из коллбэка, не подскажете? Я с событийностью всю голову сломал. Функция умеет возвращать нужное количество станций (в примере 3 штуки, можно увеличить)  
var map; $(function() {     map = new YMaps.Map(document.getElementById("YMapsID"));     map.setCenter(new YMaps.GeoPoint(30.323850978165893,59.92072836160277), 12);     map.addControl(new YMaps.Zoom()); map.addControl(new YMaps.ScaleLine());     map.enableScrollZoom(); map.enableDblClickZoom();     YMaps.Events.observe(map,map.Events.Click, function(map, mEvent) { placePoint(map, mEvent); }); }); function placePoint(map, mEvent) {     var placemark = new YMaps.Placemark(mEvent.getCoordPoint());     placemark.setBalloonContent('Описание нашей точечки: '+placemark.getGeoPoint().getX()+'  '+placemark.getGeoPoint().getY());     find_metro(placemark,3);     map.addOverlay(placemark); } function find_metro(placemark,num) {     var point = placemark.getGeoPoint(), bounds = new YMaps.GeoBounds(new YMaps.GeoPoint(point.getX()-0.04,point.getY()-0.02),new YMaps.GeoPoint(point.getX()+0.04,point.getY()+0.02));     var geocoder = new YMaps.Geocoder('станция метро', { results: 30, boundedBy: bounds, strictBounds: true});     YMaps.Events.observe(geocoder, geocoder.Events.Load, function () {         if (this.found) {             this.metros = new Array();             for (var i=0,reslen = this.length();i                 this.metros[i] = {                     'name' : this.get(i).AddressDetails.Country.Locality.Thoroughfare.Premise.PremiseName.replace('метро ',''),                     'line' : this.get(i).AddressDetails.Country.Locality.Thoroughfare.ThoroughfareName,                     'coords' : this.get(i).getGeoPoint(),                     'distance' : getPointsDistance(point,this.get(i).getGeoPoint())                 }             }             var sortMethod = function(a,b) { var k; if (b.distance             this.metros = this.metros.sort(sortMethod).slice(0,num);             // на вывод найдённое.             addToDesc(placemark,'
Близжайшие станции метро: ');             for (i in this.metros) { addToDesc(placemark,'
'+this.metros[i].name+', '+this.metros[i].line+' ~'+this.metros[i].distance+' км.'); }             // вывели найденное, но методика кривовата - не могу никак уложить в событийную модель... куда возвращать результирующий массив?         }     }); } function addToDesc(placemark,str) { placemark.setBalloonContent(placemark.getBalloonContent()+str); } function getPointsDistance(a,b){     var lon1 = a.getX()*Math.PI/180; var lat1 = a.getY()*Math.PI/180; var lon2 = b.getX()*Math.PI/180; var lat2 = b.getY()*Math.PI/180;     return (Math.acos(Math.sin(lat1)*Math.sin(lat2)+Math.cos(lat1)*Math.cos(lat2)*Math.cos(lon1-lon2))*6371).toFixed(3); }
  Работает всё там же