JA:OpenLayers Dynamic POI

From OpenStreetMap Wiki
Jump to navigation Jump to search
Dynamic Points of Interest

OpenLayers の 動的 POI レイヤー "how to"

Basic approach how to make POIs with Openlayers can be found at Openlayers POI layer example. これは簡単にできますが、比較的静的で少量の POI でのみ有用です。

より複雑な 動的 POI レイヤーを開発しました。なぜ動的か?

  • タイルと同様、オンデマンドの POI 読み込み
  • 前処理され、カテゴリ分けされた、データベースに保存された POI

データベーススキーマ

  • POI_categories - main POI categories
  • POI_subcategories - POI subcategories, each subcategory belongs to one category
  • POIs - each POI belongs at least to category but usually also to subcategory

POI_categories

 
  CREATE TABLE IF NOT EXISTS `POI_categories` (
  `id` int(11) NOT NULL,
  `name` varchar(32) character set utf8 collate utf8_unicode_ci NOT NULL,
  `icon` varchar(128) character set utf8 collate utf8_unicode_ci NOT NULL,
  `iconw` int(11) default NULL,
  `iconh` int(11) default NULL,
  `iconx` int(11) default NULL,
  `icony` int(11) default NULL,
  `list_icon` varchar(128) collate utf8_unicode_ci NOT NULL default '',
  `zoom_level` int(11) NOT NULL default '14',
  `description` varchar(256) character set utf8 collate utf8_unicode_ci NOT NULL,
  `display_order` int(11) NOT NULL,
  `key1` varchar(128) character set utf8 collate utf8_unicode_ci default NULL,
  `value1` varchar(128) character set utf8 collate utf8_unicode_ci default NULL,
  `key2` varchar(128) character set utf8 collate utf8_unicode_ci default NULL,
  `value2` varchar(128) character set utf8 collate utf8_unicode_ci default NULL,
  `param0` varchar(128) collate utf8_unicode_ci default NULL,
  `param1` varchar(128) collate utf8_unicode_ci default NULL,
  `param2` varchar(128) collate utf8_unicode_ci default NULL,
  `param3` varchar(128) collate utf8_unicode_ci default NULL,
  PRIMARY KEY  (`id`),
  KEY `zoom_level` (`zoom_level`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

POI_subcategories

 CREATE TABLE `POI_subcategories` (
  `id` int(11) NOT NULL,
  `category_id` int(11) NOT NULL,
  `subcategory_map` int(11) default NULL,
  `zoom_level` int(11) default NULL,
  `name` varchar(32) collate utf8_unicode_ci NOT NULL,
  `icon` varchar(128) collate utf8_unicode_ci NOT NULL,
  `iconw` int(11) default NULL,
  `iconh` int(11) default NULL,
  `iconx` int(11) default NULL,
  `icony` int(11) default NULL,
  `list_icon` varchar(128) collate utf8_unicode_ci NOT NULL default '',
  `description` varchar(256) collate utf8_unicode_ci NOT NULL,
  `display_order` int(11) NOT NULL,
  `key1` varchar(128) collate utf8_unicode_ci default NULL,
  `value1` varchar(128) collate utf8_unicode_ci default NULL,
  `key2` varchar(128) collate utf8_unicode_ci default NULL,
  `value2` varchar(128) collate utf8_unicode_ci default NULL,
  `param0` varchar(128) collate utf8_unicode_ci default NULL,
  `param1` varchar(128) collate utf8_unicode_ci default NULL,
  `param2` varchar(128) collate utf8_unicode_ci default NULL,
  `param3` varchar(128) collate utf8_unicode_ci default NULL,
  PRIMARY KEY  (`id`),
  KEY `zoom_level` (`zoom_level`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

POI

 CREATE TABLE `POI` (
  `osm_id` int(11) NOT NULL,
  `osm_type` tinyint(4) NOT NULL,
  `category_id` int(11) NOT NULL,
  `subcategory_id` int(11) default NULL,
  `lat` float NOT NULL,
  `lon` float NOT NULL,
  `lat2` float default NULL,
  `lon2` float default NULL,
  `name` varchar(128) collate utf8_unicode_ci default NULL,
  `param0` varchar(128) collate utf8_unicode_ci default NULL,
  `param1` varchar(128) collate utf8_unicode_ci default NULL,
  `param2` varchar(128) collate utf8_unicode_ci default NULL,
  `param3` varchar(128) collate utf8_unicode_ci default NULL,
  KEY `osm_type_id` (`osm_id`,`osm_type`),
  KEY `category_id` (`category_id`),
  KEY `subcategory_id` (`subcategory_id`)
 ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;

クライアント側のコード

In addition to Openlayers.js also

  • Marker Grid (derived from Openlayers.Layer.Grid, code composed from Openlayers.Layer.TMS, Openlayers.Layer.Marker),
  • Marker Tile (derived from OpenLayers.Tile code composed from Openlayers.Layer.Text, Openlayers.Tile.WFS) and
  • Bounds (small helper code with reverse mercator projection)

サーバー側のコード

Marker definition (as plain text file) for particular tiles are loaded with AJAX. Request URL is formed from zoom level, bbox of particular tile and list of features to fetch. List of features consists of semicolon separated pairs of category_id:subcategory_id.

Request URL: http://sandbox.freemap.sk/dynamic_poi/features/?z=12&l=19.07222250718225&t=48.63287483132393&r=19.160113113145684&b=48.5747561300883&f=2:3;1:1;1:2;2:4;5:17;5:18;3:8;3:9;3:10

Server response:

lat	lon	icon	iconSize	iconOffset	title	description	popupSize
48.6142	19.1495	features/icons/rail_station.png	38,38	0,-38	Sliač	[Železnica - železnice]
200,80 48.5884 19.1252 features/icons/fuel.png 38,38 0,-38 Slovnaft [Čerpacie stanice - čerpacie stanice]
200,80 48.5782 19.103 features/icons/fuel.png 38,38 0,-38 Slovnaft [Čerpacie stanice - čerpacie stanice]
200,80

Source for request handling code is here.

Working minimal example

Warning! If you want to run this example from different site, you have to modify POI requesting code to use some http proxy script because of security limitations in crossdomain XHttpRequests.

POI の前処理

I wrote my POI preprocessor prototype for Freemap Slovakia in VB6 :P using non-scalable iterative approach. Use of Xapi is recommended for scalable solution.

Another possible source is "POIs from OSM data" done by Christoph Eckert.

--Dido 17:09, 7 November 2007 (UTC)

代替の javascript 関数 get_poi_url

This get_poi_url function does not use the 'bound.js' function but calculates the boundries with getLatLonFromPixel and the getSize function.

This function gets called for every tile loaded, but requests the markers for the entire screen each time. This means you keep adding lots and lots of the same marker for each point and make lots of requests - most uncool. --H2g2bob 23:28, 9 March 2010 (UTC)
 function get_poi_url() {
    // custom get_poi_url() function that uses the the
    // getLatLonFromPixel function to determine the map
    // boudries and calculates the longitude and latitude
    // using the map projection transform functions of
    // Openlayers.

    // the Zoom Level selected
    var zoom = this.map.getZoom();

    // the top left corner
    var tlLonLat = this.map.getLonLatFromPixel(new OpenLayers.Pixel(1,1)).
          transform(this.map.getProjectionObject(),this.map.displayProjection);

    // the bottom right corner
    var mapsize = this.map.getSize();
    var brLonLat = this.map.getLonLatFromPixel(new OpenLayers.Pixel(mapsize.w - 1, mapsize.h - 1)).
          transform(this.map.getProjectionObject(),this.map.displayProjection);

    return url    + "&zoom=" + zoom
          + "&tllon=" + tlLonLat.lon
          + "&tllat=" + tlLonLat.lat
          + "&brlon=" + brLonLat.lon
          + "&brlat=" + brLonLat.lat
          + "&search="    + zoom + ";"
                + tlLonLat.lon + ";"
                + brLonLat.lat + ";"
                + brLonLat.lon + ";"
                + tlLonLat.lat;
 }

関連項目