Friday, May 29, 2009

Using OpenStreetMap tiles with Oracle FMW MapViewer

The recently uploaded tutorial on using DigitalGlobe's online imagery delivery platform with MapViewer
(http://www.oracle.com/technology/sample_code/products/mapviewer/index.html) discuss the MVCustomMapTileLayer interafce for accessing 3rd party tile providers. This post consists of sample code showing how it can be used with OSM tiles from {tiles|tah}.openstreetmap.org.

The sample html code is listed below.

<html>
<head>
<META http-equiv="Content-Type" content="text/html" charset=UTF-8">
<TITLE>OpenStreetMap as external tile layer</TITLE>
<!--
<link rel="stylesheet" type="text/css" href="/mapviewer/fsmc/tutorial/t.css" />
-->
<link rel="stylesheet" type="text/css" href="http://sdolnx2.us.oracle.com:7777/mapviewer/fsmc/tutorial/t.css" />

<!-- Change to your mapviewer instance e.g. localhost:8888/mapviewer/fsmc/jslib/oraclemaps.js
<script language="Javascript" src="http://localhost:8888/mapviewer/fsmc/jslib/oraclemaps.js"></script>
-->

<script language="Javascript" src="http://sdolnx2.us.oracle.com:7777/mapviewer/fsmc/jslib/oraclemaps.js"></script>

<script language=javascript>

// set up a map tile configuration so MapViewer knows the tiling scheme, i.e.
// the number of zoom levels (20), tile size (256x256)
// the tile width & height in real world coordinates at each zoom level
// the coordinate system (Spherical Mercator EPSG:3785), and
// tile image file format (PNG)
var mapConfig=
{
"mapTileLayer":"OSM_MERCATOR",
"format":"PNG",
"coordSys":
{
"srid":3785,
"type":"PROJECTED",
"distConvFactor":1.0,
"minX":-2.0037508E7,"minY":-2.0037508E7,
"maxX":2.0037508E7,"maxY":2.0037508E7
},
"zoomLevels":
[
{"zoomLevel":0,"name":"","tileWidth":4.00750166855785E7,"tileHeight":4.00750166855785E7,"tileImageWidth":256,"tileImageHeight":256},
{"zoomLevel":1,"name":"","tileWidth":2.0037508E7,"tileHeight":2.0037508E7,"tileImageWidth":256,"tileImageHeight":256},
{"zoomLevel":2,"name":"","tileWidth":1.0018754E7,"tileHeight":1.0018754E7,"tileImageWidth":256,"tileImageHeight":256},
{"zoomLevel":3,"name":"","tileWidth":5009377.0,"tileHeight":5009377.0,"tileImageWidth":256,"tileImageHeight":256},
{"zoomLevel":4,"name":"","tileWidth":2504688.5,"tileHeight":2504688.5,"tileImageWidth":256,"tileImageHeight":256},
{"zoomLevel":5,"name":"","tileWidth":1252344.25,"tileHeight":1252344.25,"tileImageWidth":256,"tileImageHeight":256},
{"zoomLevel":6,"name":"","tileWidth":626172.125,"tileHeight":626172.125,"tileImageWidth":256,"tileImageHeight":256},
{"zoomLevel":7,"name":"","tileWidth":313086.0625,"tileHeight":313086.0625,"tileImageWidth":256,"tileImageHeight":256},
{"zoomLevel":8,"name":"","tileWidth":156543.03125,"tileHeight":156543.03125,"tileImageWidth":256,"tileImageHeight":256},
{"zoomLevel":9,"name":"","tileWidth":78271.515625,"tileHeight":78271.515625,"tileImageWidth":256,"tileImageHeight":256},
{"zoomLevel":10,"name":"","tileWidth":39135.7578125,"tileHeight":39135.7578125,"tileImageWidth":256,"tileImageHeight":256},
{"zoomLevel":11,"name":"","tileWidth":19567.87890625,"tileHeight":19567.87890625,"tileImageWidth":256,"tileImageHeight":256},
{"zoomLevel":12,"name":"","tileWidth":9783.939453125,"tileHeight":9783.939453125,"tileImageWidth":256,"tileImageHeight":256},
{"zoomLevel":13,"name":"","tileWidth":4891.9697265625,"tileHeight":4891.9697265625,"tileImageWidth":256,"tileImageHeight":256},
{"zoomLevel":14,"name":"","tileWidth":2445.98486328125,"tileHeight":2445.98486328125,"tileImageWidth":256,"tileImageHeight":256},
{"zoomLevel":15,"name":"","tileWidth":1222.992431640625,"tileHeight":1222.992431640625,"tileImageWidth":256,"tileImageHeight":256},
{"zoomLevel":16,"name":"","tileWidth":611.4962158203125,"tileHeight":611.4962158203125,"tileImageWidth":256,"tileImageHeight":256},
{"zoomLevel":17,"name":"","tileWidth":305.74810791015625,"tileHeight":305.74810791015625,"tileImageWidth":256,"tileImageHeight":256},
{"zoomLevel":18,"name":"","tileWidth":152.87405395507812,"tileHeight":152.87405395507812,"tileImageWidth":256,"tileImageHeight":256},
{"zoomLevel":19,"name":"","tileWidth":76.43702697753906,"tileHeight":76.43702697753906,"tileImageWidth":256,"tileImageHeight":256}
]
};

// create a custom map tile layer based on the above tile configuration
// the second argument is a function that implements the getTileURL
// interface for this particular map tile service
var osmBasemap = new MVCustomMapTileLayer(mapConfig, getOSMMapTileURL);

<!-- Change to your mapviewer instance e.g. localhost:8888/mapviewer/fsmc/jslib/oraclemaps.js
var baseURL = "http://localhost:8888/mapviewer" ;

-->
var baseURL = "http://sdolnx2.us.oracle.com:7777/mapviewer" ;
var mapview;
var oraTheme = null ;
var oraTileLayer = null;

function showMap()
{
mapview = new MVMapView(document.getElementById("map"), baseURL);
mapview.addMapTileLayer(osmBasemap);
// near london -36793, 6679715 in SRID 3785
var mpoint = MVSdoGeometry.createPoint(-36793.89, 6679715.42, 3785); // near london 0.1,51.5,8307

mapview.setCenter(mpoint);
mapview.setZoomLevel(10);

mapview.addNavigationPanel() ;
mapview.display();
}

function showMapTileLayer(layerName)
{
mapview.removeMapTileLayer(osmBasemap) ;
eval("mapview.addMapTileLayer("+layerName+"Basemap)") ;
}



function getOSMMapTileURL(tx, ty, tw, th, level)
{
var x = (tx-mapConfig.coordSys.minX)/mapConfig.zoomLevels[level].tileWidth ;
// Mapviewer's tile The tile numbering scheme, or mesh codes, for Oracle Maps’
// (see Section 8.2 of the MapViewer User Guide for more details) tiles is similar
// to that for Google Maps. There only difference is that the Y origin is
// at the lower left rather than the upper left, as is the case for Google tiles
var y = (mapConfig.coordSys.maxY-ty)/mapConfig.zoomLevels[level].tileHeight-1 ;
// use mapnik rendered tiles
//return "http://tile.openstreetmap.org/"+(level)+"/"+x+"/"+y+".png";
// use osmarender instead
return "http://tah.openstreetmap.org/Tiles/tile/"+(level)+"/"+x+"/"+y+".png";
}

</script>
</head>

<body onload="javascript:showMap()">
<h3>Oracle Maps example - Custom map tile layer</h3>
This sample shows how the Oracle Maps GetMapTileURL interface could be used to display OSM map tiles.
It implements code samples and technical details described on OSM sample code pages.
This code is purely a sample explaining how to use the GetMapTileURL interface.<br>
<div id="map" style="width:800px;height:600px"></div>
</body>
</html>

Friday, May 1, 2009

Storing your redline geometries in a database

MapViewer's JavaScript API provides a simple Red-line tool that you can use to let user draw simple shapes on the map. The tool can also return the coordinates of the shape, but there is no built-in mechanism to persistently store these shapes.

In this article I will show you how to easily store such hand drawings in a database table, then display them on the map at a later time just as easily.

The mains steps are:

1. Create a database table with a SDO_GEOMETRY column (to store the geometries). Also create spatial index on it so we can query and display the table contents on our map later on.

2. Create a very simple JSP page that will handle the task of storing a single geometry. It will take an geometry in a simple string format, then store it in the table using JDBC.

3. Create a simple HTML-based Oracle Maps demo page, where user can create a shape on the map using a Redline tool. After getting hold of the Redline geometry, the page will issue an AJAX request to the JSP page, passing various aspects of the geometry (such as its type, SRID, and coordinates) as URL parameters.

4. Display the table as a dynamic theme in the same HTML page.

For more details, please download the zip file that includes the following 3 files:

readme.txt: Instructions for running this demo.
store.jsp: The JSP page that handles geometry storage.
store.html: The main demo page that lets you draw things and display stored geometries.

The complete instructions are in the readme.txt file.

If you have the built-in Oracle Maps tutorials running, this demo should be very easy to set up and run. To run the dmeo, simply open the store.html page in your browser. Post your comments below if you run into any issues. The following is a screenshot of the demo:




Finally, note that you can easily expand the demo to store more fields besides the geometry itself. It is also trivial to display these fields as attributes in the info-tip window when user clicks on any geometry displayed on the map.