Recently, I got an opportunity to work with OpenLayers and thought it worth sharing. In this article I am going to give you a jump start to visualize spatial data using OpenLayers. In the demo I will be using SQL Server 2008 and OpenLayers 3.
Before start working with OpenLayers and spatial data, let me explain these two buzzwords in short so that you can jump start.
OpenLayers
It’s an open source project for all your mapping needs, which is being update frequently by its community and their (developer) work is really appreciated to bring all GIS mapping needs all together.
It provides tiles and vector layers so that we can work with existing GIS server and map providers like google and bing maps. And using vector layer we can add any geometry in map (which may exist in SQL Server , ORACLE or other databases which support Spatial data types).
Since its open source you can customize and implement as per your need. However it provide great flexibility to extend its feature.
You can read more about OpenLayers.
Spatial Data Types
Definition from msdn:
There are two types of spatial data. The geometry data type supports planar, or Euclidean (flat-earth), data. The geometry data type both conforms to the Open Geospatial Consortium (OGC) Simple Features for SQL Specification version 1.1.0 and is compliant with SQL MM (ISO standard).
In addition, SQL Server supports the geography data type, which stores ellipsoidal (round-earth) data, such as GPS latitude and longitude coordinates.
Actually there are 2 types of spatial data: 1. Represent geometry in 2 dimensions, and another is geography which is ellipsoidal representation of data.
Here is how we differentiate those:
Courtesy: simple-talk.com
It is a vast topic to describe here, but you can read more on msdn.
Now in this article I will explain how you can visualize your raw spatial data on map using openlayer3.
In this demo I will be using SQL Server 2008 and OpenLayers 3, from SQL Server 2008 there is support for spatial data types. Here is my table for this demo:
As you can see I can choose either geography or geometry. For jump start I will be using simple geometry type. Geometry include different types in it, as below
Courtesy: msdn.microsoft.com
So we can use any of the following:
- Point
- LineString
- Plygon
- Multipolygon
- MultilineString
- Multipoint
In this demo we will be working with Point, LineString and Polygon and see the results on map.
Note: While working on Spatial data SRID (which represent Spatial Reference Systems) is important.
As per Wikipedia “A spatial reference system (SRS) or coordinate reference system(CRS) is a coordinate-based local, regional or global system used to locate geographical entities. A spatial reference system defines a specific map projection, as well as transformations between differentspatial reference systems.”
Note: I am not going to use SRID for this example as it is not required in current scenario but while working with real application you must consider the same.
Step 1: Create a simple table in SQL as above screen. Table name is TEST_SPATIAL (script attached).
Step 2: Now we will insert some spatial data in table.
Since SQL Server have lot of function to work with Spatila data, I am going to use STGeomFromText function to get spatial data from text format(known as WKT(well known text))
Inserting Spatial data
Inserting point:
- DECLARE @data nvarchar(max) = 'POINT (1 10)';
- DECLARE @g geometry;
- SET @g = geometry::STGeomFromText(@data, 0);
-
- insert into dbo.TEST_SPATIAL
- values(@g)
Same as we can insert LineString as ‘
LINESTRING (4 4 4 4, 9 0 4 4)’ and Polygon as ‘POLYGON ((0 0, 30 0, 30 30, 0 30, 0 0))’.
Now you will see your spatila data in binary format as below:
You can also see spatial result view as :
Step 3: Now we have our spatial data ready. In order to place data in map, .NET fretwork provide library
Microsoft.SqlServer.Types to work with, which is the same library we are using in SQL (using common language runtime).
The purpose of this library is to manipulate and work with Spatial data in CLR compatible language like C#. Since we just want to represent our data in map without any manipulation we will not use this for now.
Referencing OpenLayers3 in ASP.NET project
In order to reference OpenLayers3 in any ASP.NET website (or web application) we just required the following files:
- ol.js: This file contains core of OpenLayers.
- ol.css: This file contains styles for map.
You can find those file on OpenLayers website or reference, where debug file is for development purpose.
I would also like to mention that there are helper libraries Proj4.js for front end, and proj4net for backend (.net), which can make you GIS development easy.
For this demonstration I am not going to use any of above as I will be using smart feature of OpenLayers which is now available in openlayer3. With the help of this we can read WKT(well known text) from database. STAsText() function provide wkt format of a geometry.
Here is my simple function to query spatial data from SQL in wkt:
- public List < string > GetSpatialData()
- {
- List < string > spatialDataList = new List < string > ();
- dbConnection.Open();
- var command = new SqlCommand("select [GEOMETRY].STAsText() from TEST_SPATIAL where GEOMETRY IS NOT NULL", dbConnection);
- var rdr = command.ExecuteReader();
- while (rdr.Read())
- {
- spatialDataList.Add(Convert.ToString(rdr[0]));
- }
- dbConnection.Close();
- return spatialDataList;
- }
In Default.aspx page first of all we required map object as follows:
- var map = new ol.Map(
- {
- layers: [layer],
- target: 'map',
- view: new ol.View(
- {
- center: [0, 0],
- zoom: 2
- })
- });
This is the base object of map to be rendered. There are 3 keys layers ,target ,view.
- Layer: In a laymen term layer is an another map rendering on existing map, which may contain geometries/objects to be displayed on map.
- Target: this is a html dom element id in which map will be rendered.
- View: This defines the initial position of map and its zoom level.
Apart from above there are several configurations which are not required in this demonstration. As there any many types of layer, I will use OSM (open street map) and Vector layer. We use Vector layer when we need to display geometries from our database.
We create object of OSM layer as follows:
- var osmLayer = new ol.layer.Tile({
- source: new ol.source.OSM()
- });
And will pass osmLayer object to map layer key as:
- var map = new ol.Map(
- {
- layers: [osmLayer],
- target: 'map',
- view: new ol.View(
- {
- center: [0, 0],
- zoom: 2
- })
- });
And here is output:
Next step is to add SQL spatial geometries to map. There are no of ways to render spatial data in openlayer3, we can use json object, we can manually create features (explained below) and add them on map or can read wkt formatted geometry (which we are going to see).
Features are the object we see on the map layer. Feature can be line, polygon point. In order to visualize those features we use style to add color to these geometries.
To visualize spatial data on map, first of all we will put all geometries in a JavaScript array for simplicity.
- var geometries = [];
-
- <% GettingStarted.GeoHelper helper = new GettingStarted.GeoHelper();
-
- foreach (var item in helper.GetSpatialData())
- { %>
-
- geometries.push('<%=item %>');
-
- <% } %>
Now will create object of wkt parser/formatter/reader and will create array of features.
- var wktReader = new ol.format.WKT();
- var featureCollection = [];
To visualize features on map we need to apply styling on features as per geometry type:
- for (var i = 0; i < geometries.length; i++)
- {
- var feature = wktReader.readFeature(geometries[i]);
- feature.getGeometry().transform('EPSG:4326', 'EPSG:3857');
- if (feature.getGeometry().getType() == 'Polygon')
- {
- feature.setStyle(new ol.style.Style(
- {
- stroke: new ol.style.Stroke(
- {
- color: 'blue',
- width: 3
- }),
- fill: new ol.style.Fill(
- {
- color: 'rgba(0, 0, 255, 0.1)'
- })
- }));
- featureCollection.push(feature);
- }
- else if (feature.getGeometry().getType() == 'LineString')
- {
- feature.setStyle(new ol.style.Style(
- {
- stroke: new ol.style.Stroke(
- {
- color: 'red',
- width: 3
- })
- }));
- featureCollection.push(feature);
- }
- else if (feature.getGeometry().getType() == 'Point')
- {
- feature.setStyle(new ol.style.Style(
- {
- image: new ol.style.Icon( (
- {
- anchor: [0.5, 46],
- anchorXUnits: 'fraction',
- anchorYUnits: 'pixels',
- opacity: 0.75,
- src: 'Icons/marker.png'
- }))
- }));
- featureCollection.push(feature);
- }
- }
We use feature.setStyle(style) function to apply style. Also note we must transform all geometries to map transformation( projection) using:
- transform('EPSG:4326', 'EPSG:3857');
Which we configure using SRID in database (as mentioned earlier).
Since we are having 3 types of geometries for we have applied style accordingly. You can use any styling as per your requirement.
Now we will create Vector source using source object and add featureCollection:
- var source = new ol.source.Vector({
- features: featureCollection
- });
Create layer using layer object and add source to it:
- var vectorLayer = new ol.layer.Vector({
- source: source
- });
And at last, add layer to map object:
- var map = new ol.Map({
- layers: [osmLayer, vectorLayer],
- target: 'map',
- view: new ol.View({
- center: [0, 0],
- zoom: 2
- })
- });
Output I would try to create specific geometry for a regions but it’s bit difficult to create coordinates for complex geometries.
Final Words: This was just a jump start demo with OpenLayers and Spatial data. For further reading you can visit
OpenLayers.org where you can find API docs and source code, you can consider MSDN for Spatial data types.
Your ideas and suggestions will be appreciated.
Update:
Source code uploaded.
Read more articles on Spatial Data: