エンタープライズシステム用のOSMおよびOpenLayersのビット

こんにちはHabr、今日は企業とB2Bでのosmの使用について少しお話しします。

つまり、GoogleマップAPIからOSM、オープンレイヤー、幸福に切り替える方法と理由です。



間違いなく最初に発生する質問:なぜですか?


まず、非公開サービスでのGoogleマップAPIの使用は、利用規約によって制限されています。 2番目:google maps api-これはまさにgoogle maps apiであり、地図に似たすべてを表示するapiではありません。 つまり 別の背景を表示したり、サーバーによってエンタープライズのローカルネットワークに描画されたラスターレイヤーを追加したい場合は、松葉杖をスカルプトする準備をしてください。 さて、APIに何かが含まれていない場合、追加するのが苦痛になることを覚悟してください。 3つ目:それぞれ地図データを取得することはできません。従業員向けのローカル地図サービスを作成することもできません。 つまり、Googleマップは各クライアントマシンから利用できる必要があります。 奇妙に聞こえますが、従業員は常に外部ネットワークにアクセスできます。



私があなたを納得させたとしましょう。 どこから始めますか?


まず、カードをオープンレイヤーに差し込みます。 すべてがシンプルで、グーグル、ヤンデックス、リーフレットと大差ありません。



//  ,       id='map' var map = new OpenLayers.Map('map'); //     OSM   "OSM mapnik" var layer = new OpenLayers.Layer.OSM('OSM mapnik'); //    map.addLayer(layer); //    ,  ,    . map.zoomToMaxExtent();
      
      







大企業は、多くの場合、マップサーバーとカードを購入し、wmsまたはtmsを介してローカルネットワーク上で配布できます。 WMSおよびTMSは、マップ画像のスライスを取得できる標準です。 主な違い:wmsでは、任意の縮尺のマ​​ップの任意のピースを要求できます。tmsでは、縮尺のセットとマップを正方形に分割します。これは、固定の方法で取得できます。



したがって、wmsのレイヤーを作成する行を次のように変更します。



 //    WMS var wms = new OpenLayers.Layer.WMS( //      "NASA Global Mosaic", // wms    "http://wms.jpl.nasa.gov/wms.cgi", //   wms: // ,  wms      ,       {layers: "modis,global_mosaic"} );
      
      







TMSの場合:



 //    TMS var layer = new OpenLayers.Layer.TMS( //      "My TMS Layer", //  TMS  "http://tilecache.osgeo.org/wms-c/Basic.py/", //   TMS: //    ,     (png/jpeg/gif)  {layername: "basic", type: "png"} );
      
      







また、3つのレイヤーすべてをマップに追加してそれらを切り替えたり、レイヤーの1つを他のレイヤーの上に追加したりする必要はありません。



プロジェクション


ここで、あなたが踏む可能性が高いレーキについてのいくつかの言葉。



osm.org(OpenLayers.Layer.OSM)から1つのマップレイヤーを追加しますが、マップを全世界ではなくモスクワ地域まで開いてほしいとします。 モスクワの緯度と経度を見て、代わりに



 map.zoomToMaxExtent
      
      





書きます



 map.moveTo( //    new OpenLayers.LonLat(37.16, 55.604), // 9 );
      
      







そして、私たちは海に落ちます。 座標系がすべてです。 メープルレイヤーの場合、ネイティブ座標系はEPSG:900913です。 基準点はグリニッジ子午線と赤道の交点で、単位はメートルです。 したがって、基準点から東へ37メートル、北へ55メートルでした。



誰もが知っている経度と緯度は、EPSG:4326で指定されていることを意味します。 したがって、座標を再計算する必要があります。



 map.moveTo( //   new OpenLayers.LonLat(37.16, 55.604).transform( //   EPSG:4326 new OpenLayers.Projection('EPSG:4326'), //    (EPSG:900913) map.getProjectionObject() ), 9 );
      
      







世界に多くの座標系があるという事実は、オープンレイヤーで座標を設定するときに覚えておくと良いでしょう。 これにより頭痛の種になりますが、顧客がエキゾチックなもの(たとえばPulkovo 42)を使用している場合、顧客データを操作できます。



これを行うには、proj4js( trac.osgeo.org/proj4js/wiki/Download )を接続し、次の行を追加します



 Proj4js.defs['EPSG:28403'] = '+proj=tmerc +lat_0=0 +lon_0=39 +k=1 ' + '+x_0=500000 +y_0=0 +no_defs +a=6378140 +rf=298,257223563 +units=m ' + '+towgs84=28.000,-130.000,-95.000 +to_meter=1';
      
      







これで、座標を再計算するときに新しい投影を指定できます。



これはPulkovo 42ではありませんが、パラメーターを少し調整するだけで、他の座標系のレイヤーの上にデータを通常表示できます。



レイヤーを追加して表示する方法がわかったので、次にマーカー、ライン、イベント処理に進みましょう。



マーカー


層には2つのタイプがあります。

HTML(OpenLayers.Marker)およびベクター(OpenLayers.Geometry.Point)。 後で、マーカーが何を意味するのか、なぜポイントを説明するのか。



HTMLマーカーは、1つ以上のdivを作成します。divは、画像を配置し、座標に従って地図の上に配置されます。 Googleマップ上のマーカーがどのように機能するかをFirebugや他のデバッガーで見たことがあるなら、すべてに精通しているでしょう。 ポップアップは比較的簡単に接続でき、jQueryから(htmlオブジェクトがあるので)使いやすく、それにもかかわらず、ライブラリの作成者はそれらの使用を推奨していません。 なんで? それらはいくぶん重いです。マーカーが1つある場合はすべてが正常で、1000が悪い場合はすべて正常です。 これらは、olで採用されているデータストレージとディスプレイの一般的な概念から外れています。 まあ、実用的な理由から:私は鹿と仕事を始めたとき、そのようなマーカーのドラッグコントロールはありませんでした。 しかし、彼はまだいません。



ただし、マップにマーカーを追加するコードは次のとおりです。



 //    var markers = new OpenLayers.Layer.Markers( "Markers" ); //    map.addLayer(markers); //,    var lonLat = new OpenLayers.LonLat( 0, 0 ); //       0, 0 //    markers.addMarker(new OpenLayers.Marker(lonLat));
      
      







はい、マーカー付きの複数のレイヤーが存在する場合があります。 はい、レイヤーの可視性を制御し、必要に応じてマーカーのグループを非表示にすることができます。



次に、これらのベクトルマーカーについて、および「データの保存と表示の概念」について説明します。

マップで異なるラスターレイヤーを表示するだけの機能に満足している人はほとんどいません。 それらの上にあなたのユニークなデータを表示することの主な魅力。 そのため、光ケーブル、銅ケーブル、およびこの良品がマップ上を通過するウェル/ポールを表示するとします。 各オブジェクトには、幾何学的情報(ケーブルが実際に通過する方法/ポールまたはウェルの位置)と属性(ケーブルタイプ、ケーブルコアの数、信号減衰、ポールの高さ...リストを無限に補充できます)が含まれます。 実際、このアイデアは層に直接実装されています。



オブジェクト-「OpenLayers.Feature.Vector」は、その属性、ジオメトリ、およびオプションで表示スタイルとともに保存されます。

ポイントフィーチャの場合:



 new OpenLayers.Feature.Vector( // -    x, y (x -longitude, y - latitude) new OpenLayers.Geometry.Point(x, y), //: ,  {'type':'pillon', 'height':100}, //,         . //        null );
      
      







スタイルに関するいくつかの言葉。

スタイルでは、オブジェクトの属性を使用して、ジオメトリの表示方法を指定できます。 タイプに応じて、さまざまなアイコンを使用できます。たとえば、円で井戸を描き、列でサポートします。 塗りつぶしの色、太さ、線の色を定義できます。 属性に基づいて、オブジェクトなどのテキストラベルを表示できます。 特定のオブジェクトのスタイルを設定できます。たとえば、スタイルをレイヤーに割り当てて、レイヤー内のすべてのオブジェクトがそれに応じて表示されるようにすることができます。



そしてまだマーカーに:



 //   . //Markers -      . //     {showInLayerSwitcher: false} //      . var markers = new OpenLayers.Layer.Vector('Markers'); //    map.addLayer(markers); //,     var marker = new OpenLayers.Feature.Vector( /// new OpenLayers.Geometry.Point(0, 0), //   {}, //,   { //  externalGraphic:'http://someware.com/my_favorite_marker_icon.png', //   graphicWidth:16, //   * graphicHeight:16, //   8   //   graphicXOffset:-8, //  16   graphicYOffset:-16, //   (     ) label:'   ', //     -  labelAlign: 'ct', //   5   labelYOffset: '5' } ); markers.addFeatures([marker]);
      
      





*親愛なる文法ナチ、それは子供の歌への暗示でした。



同じスタイルの複数のマーカーを追加する必要がある場合は、1つのスタイルオブジェクトを使用するだけで十分ですが、スタイルインスタンスの変更はすべてのマーカーに影響することに注意してください。



そこで、マーカーを追加しました。 次に、移動、クリック、および他のイベントに応答する機能を追加しましょう。 実際、イベントの処理は、私が一緒に仕事をする機会があった他のライブラリとほとんど異なります(段落を欠かずに記事全体を読む熱心な読者は、まず、これがGoogleであり、Yandexのリーフレットであることがわかります)。



ドラッグを追加:



 //     ,      . var drag = OpenLayers.Control.DragFeature(markers); //      ,     //OpenLayers.Layer.Vector.RootContainer    // //    map.addControl(drag); //  //(      ,  ...) drag.activate();
      
      







私の記憶が私を失敗させないなら、あなたは最終的に地図の周りにマーカーを動かすでしょう。



または、クリックしてマーカーポップアップに追加します。



 selectControl = new OpenLayers.Control.SelectFeature(markers, { //     onSelect: onFeatureSelect, //     onUnselect: onFeatureUnselect }); function onFeatureSelect(feature) { popup = new OpenLayers.Popup.FramedCloud("chicken", feature.geometry.getBounds().getCenterLonLat(), null, "<div style='font-size:.8em'> Habr!</div>", null, true, onPopupClose ); feature.popup = popup; map.addPopup(popup); } function onFeatureUnselect(feature) { map.removePopup(feature.popup); feature.popup.destroy(); feature.popup = null; }
      
      





ここに例を見ることができます: openlayers.org/dev/examples/select-feature-openpopup.html



大きな問題は、次の必要があるときに始まります。





これは解決された災害ですが、解決策はおそらく別の記事に値するでしょう。



ジオコーディング


Fuf、OSMをサイトに追加し、データを一番上に表示することを学びました。 しかし、それでも、Google API(Yandex)の大部分は船外に残っていました。 つまり、ジオコーディング(住所による座標と住所による座標の取得)とルートのレイアウトです。



OSMでのマップのルーティングについては、またジオコーディングについて説明します。 逆ジオコーディング(座標による住所)を行っていないため、ここでは住所による座標の検索に焦点を当てます。



いくつかのオプションがあります:nominatimまたはopenstreetmap.ruから既製の検索を使用して、独自の自転車を作成します。 ジオコーダーが必要になる理由について少し説明します。



1.たとえば、それぞれモスクワにのみ興味があり、データのインポートがより簡単になり、都市を指定せずに検索クエリが簡単になります。

2.何らかの理由で、クライアントマシンまたはサーバーから外部へのアクセスを許可することはできません。

3.クライアントアドレスの独自のデータベースを使用するジオコーダーが必要です。



まあ、魔法はありません:最も簡単なオプションはSolrまたはSphynxを使用することです。 実際、solrでオブジェクトの完全なアドレスと座標とともにドキュメントを保存するだけです。



たとえば、住所のリストを取得するには、興味のある地域をshp形式で取得し、それをpostgisにアップロードし、次の形式のリクエストで住所を取得します。



 select bldng.osm_id, bldng."A_STRT", bldng."A_SBRB", bldng."A_HSNMBR", settle."NAME", ST_AsText(ST_Centroid(bldng.geom)) from building-polygon bldng join settlement-polygon settle on ST_Within(bldng.geom, settle.geom)
      
      







今日は以上です。 次回は、オープンレイヤーのイベントシステムについて詳しく説明します。



参照資料


Openlayersのドキュメント-dev.openlayers.org/docs/files/OpenLayers/Map-js.html



サンプルを含むサンドボックスもあります-openlayers.org/dev/examples



Proj4js-trac.osgeo.org/proj4js



さまざまな形式のさまざまな座標系の説明があるサイト、

proj4形式で含める-spatialreference.org



All Articles