OpenLayers Dynamic POI
OpenLayers Dynamic POI layer "how to"
Basic approach how to make POIs with Openlayers can be found at Openlayers POI layer example. It is easy to do, but is usable only for relatively static and small POI set.
I have developed a more complex dynamic POI layer. Why dynamic?
- on demand POI loading, like tiles
- preprocessed, categorized POIs stored in database
Database schema
- 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;
POIs
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;
Client-side code
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)
Server-side code
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.
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.
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 preprocessing
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)
Alternative get_poi_url javascript function
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;
}
See also
- Openlayers POI layer example - Basic POI overlays without involving server-side logic (easier but more limited)
- Odopoi - A PHP/MySQL web-app for displaying dynamic POIs