Yandex.Maps APIを使用して曲線までの最小距離を見つける

こんにちは親愛なる読者。



トピックで説明されているタスクに遭遇したことがある場合、おそらくgetClosestPoint()メソッドの説明への参照以外の投稿があることに驚くでしょう。そのため、私のソリューションは確かにそれに基づいているとすぐに言います。 ただし、共有するのはそれほど多くのアルゴリズムの美しさではなく(APIを作成したYandexチームによって実現されました)、むしろ私に用意されたタスクに対する既成のソリューションとしてです。



当社はまた、IPテレフォニーおよびインターネットサービスの提供、および当社独自の光ファイバーのキロメートル単位の提供にも関与しています。 私たちにとって、目的のクライアントのオフィスがケーブルからどれだけ離れているかという問題は非常に重要です。



光学ルートを含むマップの作成から、カットの下でフォームに組み込まれた最短距離決定の実装まで、既製のソリューションを探します。



すべての作業は基本的に既製のソリューションとサンプルをコンパイルすることで構成されていることを、私はあなたを欺いたり、自分を隠そうとはしません。



タスクは次のとおりです。ユーザーが住所を入力します



または、彼は自分で家を選んで、マウスを正しい場所に突っ込む。



その後、選択した住所と最も近い光ケーブルまでの距離を示すマークが地図に表示されます。 表示を簡単にするために、ケーブルに垂線を描画します(議論の余地のある解決策ですが、視覚的には結果が気に入りました)。



http://www.infotis.ru/maps.htmlに根拠がないように例を挙げます



作業はいくつかの段階に削減されました



  1. ケーブルを物理カードからYandex.Mapに転送します
  2. 曲線(ポリライン)の形でカードにケーブルを引きます
  3. カスタムコントロールを作成する
  4. 距離を計算する関数を書く
  5. 必要な住所と必要な座標を取得します




ステージ1



この段階では、ITの専門家と直接関係のない同僚の手によって、数十キロメートルのケーブルを地図上に配置する必要がありました。 ここでは、 ymikエディターが手伝ってくれました。 この投稿の発見から、最終的な選択は(Googleマップではなく)Yandex.Mapsを支持して行われました。



同僚の仕事をしばらくしてから、次の形式のテキストファイルを受け取りました(場所を散らかさないように、2ポイントの1つの曲線の例)



{ "name": "1", "center": { "lng": 37.62110402807594, "lat": 55.74879798509053, "zoom": 12 }, "styles": [{ "name": "ymikEditor#1315408925757#0", "style": { "lineStyle": { "strokeColor": "0000ff80", "strokeWidth": "5" } } }], "objects": [{ "style": "ymikEditor#1315408925757#0", "name": "1", "description": "1", "type": "Polyline", "points": [{ "lng": 37.62110402807594, "lat": 55.773576281653035 }, { "lng": 37.6235072873533, "lat": 55.74957254620929 }] }] }
      
      







ステージ2





ymikの作品のイメージと肖像で、これらの芸術を地図に描きます。



オブジェクトが変数val、mapにあることに同意します-

次は少しのコードです(シンプルですが、ソリューション自体はシンプルなので、コメントを付けましょう)



マップとシンプルなコントロールを作成します。 コードからわかるように、jQueryはプロセスにロードされます。これは、将来(YMaps.jQueryを使用した$の代わりに)使用します。

 map = new YMaps.Map(YMaps.jQuery("#YMapsID")[0]); map.setCenter(new YMaps.GeoPoint(37.643347, 55.745478), 13); map.addControl(new YMaps.Zoom()); map.addControl(new YMaps.ToolBar()); map.addControl(new YMaps.ScaleLine()); map.addControl(new YMaps.TypeControl()); map.setType(YMaps.MapType.SATELLITE); //     var moscowBounds = new YMaps.GeoBounds( new YMaps.GeoPoint(37.389705, 55.577759), new YMaps.GeoPoint(37.844264, 55.91086) );
      
      







線描画機能

 polylines=[]; function draw_lines() { k = 0; //  for (var j = 0; j < val['objects'].length; j++) //        { if (val['objects'][j]['type'] == 'Polyline') //         Points { Points = []; for (var i = 0; i < val['objects'][j]['points'].length; i++) { Points.push(new YMaps.GeoPoint(val['objects'][j]['points'][i]['lng'], val['objects'][j]['points'][i]['lat'])); } //        pl = new YMaps.Polyline(Points, { style: { lineStyle: { strokeColor: val['styles'][k]['style']['lineStyle']['strokeColor'], strokeWidth: val['styles'][k]['style']['lineStyle']['strokeWidth'] } }, hasHint: 1 }); pl.name = val['objects'][j]['name']; pl.description = val['objects'][j]['description']; polylines.push(pl); //    polylines map.addOverlay(pl); //    k++; } if (val['objects'][j]['type'] == 'Placemark') //      { var placemark = new YMaps.Placemark(new YMaps.GeoPoint(val['objects'][j]['points']['lng'], val['objects'][j]['points']['lat']), { style: val['objects'][j]['style'] }); placemark.name = val['objects'][j]['name']; placemark.description = val['objects'][j]['description']; map.addOverlay(placemark); } } }
      
      







ステージ3



この段階で、主な作業を行います。



まず第一に、ユーザーが必要な住所を入力して、ケーブルが労働者が通過する距離を確認できるフォームをマップ上に作成しておくといいでしょう。



次に、Yandexのネイティブコントロールの例を示します。http//api.yandex.ru/maps/jsapi/examples/mapcontrolscustomizing.html



このモデルに従って、行動します。



このコントロールのデザイナーを連れてきます

 function nearest_search(object_address) { //      this.onAddToMap = function (map, position) { this.container = YMaps.jQuery("<div class='YMaps-button'> <i class='YMaps-button-c YMaps-button-l'><i></i></i><i class='YMaps-button-m YMaps-cursor-pointer'><i></i> <form id='find_nearest_form' action='#' class='YMaps-button-caption'>  <input type='text' name='object_address' value='"+object_address+"' id='search_nearest_input' style='border:1px solid green;' size='22'/></form></i><i class='YMaps-button-c YMaps-button-r'><i></i></i></div>"); //          (   )      this.map = map; this.position = position || new YMaps.ControlPosition(YMaps.ControlPosition.TOP_LEFT, new YMaps.Size(0, 40)); //  ,    . // CSS-,     this.container.css({ position: "absolute", zIndex: YMaps.ZIndex.CONTROL, width: "280px", }); this.position.apply(this.container); this.container.appendTo(this.map.getContainer()); } //      this.onRemoveFromMap = function () { //      ,    . }; }
      
      







フォームを送信する代わりに、距離を検索および計算する機能を開始するトリガー。

 YMaps.jQuery('#find_nearest_form').submit(function () { showAddress(YMaps.jQuery("#search_nearest_input").val()); return false; });
      
      







次に、元のmaps.yandex.ruから「情報」要素のバリアントを作成します

完全に行う方法については、 http://api.yandex.ru/maps/articles/tasks/service.xml#how-to-use-create-information-toolで説明しています。



この場所ではジオコーディングは必要ないので、少し削減します



 function InformationControl() { var geoResult, clickPlace, listener, map; //        this.onAddToMap = function (parentMap) { map = parentMap; map.addCursor(YMaps.Cursor.HELP); //      listener = YMaps.Events.observe(map, map.Events.Click, function (map, mEvent) { //    var clickPoint = mEvent.getGeoPoint(); //    (     ) if (geoResult) { map.removeOverlay(geoResult); result = null; } //    -   if (clickPlace) { map.removeOverlay(clickPlace); clickPlace = null; } //       clickPlace = new YMaps.Placemark(clickPoint); clickPlace.description = clickPoint.toString(); map.addOverlay(clickPlace); //     (  ) geotrack(clickPoint, clickPlace); }, this); } //        this.onRemoveFromMap = function () { map.removeCursor(YMaps.Cursor.HELP); //    ,     if (geoResult) {map.removeOverlay(geoResult); } //  if (punchline) {map.removeOverlay(punchline); } if (clickPlace) {map.removeOverlay(clickPlace); } //      listener.cleanup(); map = geoResult = clickPlace = listener = null; } }
      
      







ステージ4



ほら、すべてのボタンがあります-距離を決定するためのメイン関数を書き始めましょう。



 function geotrack(clickPoint, clickPlace) { //    -   if (punchline) { map.removeOverlay(punchline); } nearest = 100000000000; //   .     . nearest_point = new YMaps.GeoPoint(0, 0); //    for (var i = 0; i < polylines.length; i++) //          -  ,      { if (nearest > polylines[i].getClosestPoint(clickPoint)['point'].distance(clickPoint)) { nearest = polylines[i].getClosestPoint(clickPoint)['point'].distance(clickPoint); nearest_point = polylines[i].getClosestPoint(clickPoint)['point']; } } clickPlace.name = "   : " + YMaps.humanDistance(nearest); clickPlace.description = ""; punchline = new YMaps.Polyline([clickPoint, nearest_point], { style: { lineStyle: { strokeColor: "ffffffff", strokeWidth: 2 } }, hashint: 1 }); punchline.name = "      : " + YMaps.humanDistance(nearest); map.addOverlay(punchline); return clickPlace.name; }
      
      







ステージ5



住所で座標を検索しましょう。

再びYandexの例http://api.yandex.ru/maps/jsapi/examples/geocoding.html



 function showAddress(value) { //     map.removeOverlay(geoResult); //   . strictBounds : true -       (moscowBounds) var geocoder = new YMaps.Geocoder(value, { results: 1, boundedBy: moscowBounds, strictBounds : true }); //       YMaps.Events.observe(geocoder, geocoder.Events.Load, function () { //    ,      //         if (this.length()) { geoResult = this.get(0); //,    -   map.addOverlay(geoResult); name = geotrack(geoResult['_point'], geoResult); //  geoResult['text'] = '<b>' + geoResult['text'] + '.<br> ' + name + '</b>'; map.panTo(geoResult['_point'], { flying: 1 }); //     } else { alert("  "); //TODO:   -   } }); //     YMaps.Events.observe(geocoder, geocoder.Events.Fault, function (geocoder, error) { alert(" : " + error); //TODO:   -   }) }
      
      







ええ、何かがGETに来たかどうか(サイトの概念に応じて、そこから来るはずです)を確認し、もしそうなら、探しているアドレスとしてリクエストを使用します。



 var get = location.search; if(get != '') { object_address = decodeURI(get.split('?object_address=')[1]); if(object_address==" ") {object_address=""; } else {YMaps.jQuery('#find_nearest_form').submit(); } } else { object_address=''; }
      
      








ソースコード全体は、例のリンクを使用して表示できます。

コメントさせていただきます。



*更新*最後に、投稿を編集する方法を見つけたので、すべてを修正したいので、すべてを追加しました。

助けてくれたみんなに感謝します。






メソッドとオブジェクトに関する情報:

api.yandex.ru/maps/jsapi/doc/ref/reference/map.xml

api.yandex.ru/maps/jsapi/doc/ref/reference/geopoint.xml

api.yandex.ru/maps/jsapi/doc/ref/reference/polyline.xml



All Articles