In this post I'm going to give some more information about the GeometryVisualizer that I created recently.
The goal of the GeometryVisualizer is to be able to quickly visualize a GeoJson, WKT or ESRI JSON geometry. I created this to be able to quickly see how some ESRI JSON and WKT geometries looked like and visually verify some geometry conversion code I'm writing for my GeometryService in node.js. You can also use this to visualize the WKT or GeoJSON output of a PostGIS geometry query.
The ESRI JSON geometries are rendered with the ArcGIS JavaScript API. The WKT and GeoJSON geometries are rendered with OpenLayers.
Some code
In this section I'll show some parts of the code that made this web application possible and compare the ArcGIS JavaScript API with the OpenLayers API. First we'll take a look at the initialization of the map. The most notable facts about the initialization are that we need to add a layer before we are able to add graphics and that disabling the zoomwheel is less straight forward with the OpenLayers API.ESRI JavaScript API map initialization:
var map = new esri.Map("esriJsonMap"); map.disableScrollWheelZoom(); // add a layer and directly hide it because otherwise we can't create graphics var basemapURL= "http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer" var basemap = new esri.layers.ArcGISDynamicMapServiceLayer(basemapURL); map.addLayer(basemap); basemap.visible = false;
OpenLayers map initialization:
var options = { maxExtent: new OpenLayers.Bounds(-1000000000, -1000000000, 1000000000, 1000000000), } var map = new OpenLayers.Map('openLayersMap', options); var controls = map.getControlsByClass('OpenLayers.Control.Navigation'); for(var i = 0; i<controls.length; ++i){ controls[i].disableZoomWheel(); } var layer = new OpenLayers.Layer.ArcGIS93Rest( "ArcGIS World Street Map", "http://server.arcgisonline.com/ArcGIS/rest/services/World_Street_Map/MapServer", {layers: '0'} ); map.addLayer(layer); layer.setVisibility(false);
To be able to render an ESRI JSON geometry string with the ArcGIS JavaScript API you have to do some specific steps :
- Clear the graphics
- Parse the geometry string representation
- Create a graphic and set its symbol according to the geometry type.
- Update the extent of the map
function addGeometry(geometryText) { if(map.graphics === null) return; // map not loaded yet or something else is wrong map.graphics.clear(); var geometryJson = JSON.parse(geometryText); var graphic = new esri.Graphic(geometryJson); if (!graphic.symbol){ switch(graphic.geometry.type){ case "point": case "multipoint": graphic.setSymbol(new esri.symbol.SimpleMarkerSymbol()); break; case "polyline": graphic.setSymbol(new esri.symbol.SimpleLineSymbol()); break; default: graphic.setSymbol(new esri.symbol.SimpleFillSymbol()); break; } } map.graphics.add(graphic); // use undocumented object var ext = graphic._extent; // if point expand the extent if(ext.getWidth() < 0.00000001 || ext.getHeight() < 0.00000001){ var factor = 1; ext.update(ext.xmin - factor, ext.ymin - factor, ext.xmax + factor, ext.ymax + factor, ext.spatialReference); } map.setExtent(ext.expand(2)); }
The process of adding WKT and GeoJSON geometries was very similar.
- Remove all features
- Parse the geometry string representation with a predefined formatter (OpenLayers.Format.WKT or OpenLayers.Format.GeoJSON)
- Update the extent of the map.
function addGeometry(geometryInput, parser, type){ vectorLayer.removeAllFeatures(); var feature = parser.read(geometryInput); vectorLayer.addFeatures(feature); if(dojo.isArray(feature)){ feature = feature[0]; } var bounds = feature.geometry.getBounds(); bounds = bounds.scale(1.1); map.zoomToExtent(bounds); } function addWkt(geometryText) { var wktFormat = new OpenLayers.Format.WKT(); addGeometry(geometryText, wktFormat); } function addGeoJson(geometryText) { var geoJsonFormat = new OpenLayers.Format.GeoJSON(); var geometry = JSON.parse(geometryText); geometry["type"] = "Feature"; addGeometry(geometry, geoJsonFormat); }
This are the most interesting parts of the code. The full source code is in the GeometryVisualizer.
Any questions/remarks/improvements ? Let me know !