Keywords: Digitizing, Editing, Open GIS (OGC), PostgeSQL, PostGIS, Spatial Databases
Andreas Neumann got a masters degree in Geography/Cartography from the University of Vienna, in 2001. In 1999 he joined the Cartographic Institute of the Swiss Federal Institute of Technology (ETH), first as a system administrator and later as a teaching and research assistant. At the same institute Andreas advised several theses and student projects in the webmapping domain. Currently he is working on a PhD as part of a ETH project called "Distributed Publishing of Cartographic Information on Demand". Apart from his job at the university he worked as a GIS and database specialist for Dr. Heinrich Jaeckli AG, Zurich, a consulting company specialized in geology, hydrology, hydrogeology and environmental engineering. Currently he is also a member of the SVG consulting and training company Vectoreal. Andreas was one of the initiators of the SVG.Open 2002 conference in Zurich, the first international SVG developers conference, co-organized by the W3C consortium.
In a time where mapping servers and simple Online GIS services are becoming more and more a commoditiy, there is a wish to also leverage web technologies for online aquisition and editing of geographic data. SVG, as a thin-client technology, does not only offer rich interactivity features but can also be used as a base technology for online digitizing and editing of GIS data, thus allowing to aquire and update geographic databases in a decentralized way. These SVG based GIS clients do not require a software license and can be easily customized to specific editing needs. This paper describes how such a editing system was implemented on top of the PostGIS Open Source spatial database and discusses why SVG was chosen for that prototype. Finally, it will discuss what problems arose during the implementation, where the current SVG specification and implementations might have limitations and where the upcoming SVG 1.2 specification will provide improvements. This paper will also contribute to the "wishlist" for upcoming >1.2 SVG specification releases.
1. Introduction and Motivation
2. Development of a Basic DB Driven Webmapping Client
2.1 Spatial Database
2.2 Basic DOM Structure of the Application and Coordinate System
2.3 Navigation Tools
2.4 Data loading
2.5 Scale Dependent Selection and Symbolization
3. Digitizing Component
3.1 Why SVG?
3.2 Data structure
3.3 Current Digitizing Functionality
3.4 Explanation of Digitizing Technique
3.4.1 Digitizing Operations
188.8.131.52 Finding Closest Vertex and Line Segment
184.108.40.206 Moving a Vertex
220.127.116.11 Deleting a Vertex
18.104.22.168 Deleting a Subpath
22.214.171.124 Adding a Vertex
3.4.2 Parsing the d-attribute of a Path Element
3.4.3 Writing OGC geometry strings
4. Planned Enhancements
4.2 Shared Editing
5. Future SVG Spec Enhancements
5.1 Useful Enhancements Planned for SVG 1.2
5.2 Discussion of Additional Useful Features
After a presentation of interactive webmapping applications and database driven topographic maps at the Alexandria Digital Library (UC Santa Barbara, California), the question came up, whether or not SVG would also be suitable for data aquisition and the editing of geographic data. Knowing about the principal interactivity and scripting features of SVG and after researching about similar projects on the web, we decided it would be worthwile to give it a try and implement a prototype for georeferencing geomorphologic photos in California. The application allows digitizing point, line and area features and later send the aquired geometry to a spatial database. Additionally, the application allows easy spatial navigation and the display of geographic layers and data attributes as reference layers, as described in the previous SVG.Open proceedings [DBDrivenTopographicSVGMaps] [SVGTOPOMaps] The application developed for Alexandria Digital Library was later improved and extended for other data aquisition projects. The component is now good enough to handle basic data aquisition tasks and will be used in a Online-GIS project by Basler & Hofmann, Esslingen, in a contract for the Swiss Federal Railways. Currently there are several similar initiatives under development. The presented work is among the first solutions for online data aquisition. At the time of writing, one cannot buy off-the-shelf web GIS software that offers similar features.
As a base technology for the digitizing application one needs a webmapping client that can communicate with a spatial database. It should load and display reference layers (both raster and vector). Such a webmapping client was described in [DBDrivenTopographicSVGMaps] .
Our work is based on the Open Source Spatial Extension Postgis [PostGIS] and the database PostgreSQL [PostgreSQL] . PostGIS can deliver OGC compliant geometry and stores them as Simple Features for SQL [SimpleFeaturesSQL] . It features spatial queries and many OGC compliant analysis functions, such as "intersect","overlay", etc. Klaus Förster (University of Innsbruck) wrote a PostgreSQL function that can directly output SVG from Postgis databases [AsSVG] . All of the technologies listed above build a powerful foundation for a vector-based webmapping server.
The application uses a screen oriented coordinate system for the application GUI and a nested, map oriented, coordinate system for the main map display and a linked reference map. This approach is described in more detail at [SVGTOPOMaps] and [DBDrivenTopographicSVGMaps] . We disable the zooming and panning of the SVG viewer and implement our own zomming and panning mechanism that is based on changing the viewBox of the main map. This has the advantage that we can bypass zooming limitations set by a few current SVG viewers. To correctly calculate screen coordinates and to handle the resizing of the viewer window, we implemented a mapApp class. The .resetFactors() method is only necessary for viewers that don't implement the .getScreenCTM() method. For these viewers we have to trigger the .resetFactors() method using the "onresize" event on the svg root element. This method takes into account and resets inner width and height of the viewer window, as well as offset values. These parameters are relevant to calculate the coordinates in the application oriented system. The .calcCoord() method returns these correct coordinates translating the event.clientX() and event.clientY properties returned by an event object.
An additional map class reads the initial viewBox settings and features a few methods for navigation and layer handling. The .calcCoord() can calculate screen to map coordinates, the .newViewBox() allows to reset the viewBox after the user used one of the various navigation tools, a .recenter() method allows to recenter the viewBox, and a .zoomManual() method allows to manually drag a rectangle for zooming to a certain extent.
Our philosophy regarding navigation is to give the user a choice. There is no prefered superior navigation mode that is equally well suited for all users. Therefore the map user can choose from the following options:
Regardless on how the map user navigated the current map extent is always indicated in the linked reference map.
Data loading is currently based on the Adobe extension ".getURL()". Every time the map extent changes, a ECMAScript function calls a serverside PHP script and passes the map extent and the layer names along. Data is extracted from the dabase using spatial queries. The data received is parsed by a separate function using the ".parseXML()" method and appended to the document tree within the prepared group elements. Previously loaded data is deleted prior to appending new elements.
Depending on the width and height of the map extent a serverside PHP script will send adequately selected and symbolized data. For example one could take the roads layer. The map author defines threshold values that influence the SQL statement. Depending on the map extent and threshold values, different road levels (function classes) are selected. The line width of the roads remains constant, defined in percentages of the map width. The author may also define threshold values for changing line styles. This means that after zooming in the user receives a different symbolization for the same function class e.g. changing from a single line representation to a double line symbolization.
SVG offers a number of advantages that makes it attractive for being used as a online digitizing component:
A polygon that is in digitizing or editing mode is stored in a nested array. The first (outer) array stores the subpaths, the second (nested) array stores the vertices of one single subpath. A vertex is stored in an object literal, storing the "x" and "y" coordinates. One would reference the third coordinate pair of the second subpath as follows: this.subPaths.x; this.subPaths.y;. This data structure makes it relatively easy to generate SVG as well as OGC simple features for SQL geometry. Whether a subpath is closed or not is stored in a separate array. This is only relevant if the digitizing environment is not restricted to one feature type. Currently the digitizing environment can handle the following simple feature geometry types:
The digitizing environment currently supports the following basic features:
The digizing component is implemented as an object. The object has a few properties and a number of methods. While digitizing, an invisible rectangle receives click, mousemove, mousedown and mouseup events. These events are processed according to the active mode. The following modes are currently used:
Depending on the active mode, different methods of the digitizing component are activated. During the digitizing mode each click event adds a vertex to the array of the current subpath. After each click the method .writePath() creates the "d" attribute of the svg path element and replaces it using .setAttributeNS(). The method .writePath() basically loops over all subpaths and within each subpath over all vertices to concatenate the d-attribute. We use the attribute 'fill-rule="evenodd"' to enable holes in path objects without forcing the digitizing operator to draw them in a particular direction.
For most digitizing operations it is important to select the closest subpath, segment or vertex. Finding the closest vertex to the user's click position is trivial. One has to simply loop over all vertices of a subpath and calculate the distances. The method .getClosestVertex() returns the closest vertex as well as the distance to it. Many Operations, such as "deleteNode" or "moveNode" only work if the distance is within a certain range (percentages of the current viewBox).
Finding the closest segment (important for the "addNode" mode or the selection of subpaths) is more complex. One has to calculate distances to the individual line-segments and make sure that the point lies between the two bisector angles of the current segment with the neighbour segments. For adding nodes it is also important to calculate the distances to the end points and see if they are shorter than the distances to the individual segments, in which case we have to add a vertex at the start or end of a subpath. The following graphic illustrates the bisector principle to determine the closest segment and subpath.
In the above graphic we have two existing subpaths and want to test to which the new vertex that the user entered belongs to. The two rectangles with the purple dashed strokes represent the subpath's bounding box plus a tolerance band. The algorithm first tests whether it should check distances to a subpath's segments. It only tests individual segments if the new point falls within this tolerance rectangle. In the above sample it would only test subpath 1. In a next step it would calculate all distances to each segment. It additionally tests whether the new point is located between the two red lines representing the bisector angles between the active segment and the two neighbour segments. In our example it would add the new vertex in subpath 1, between the vertices 4 and 5.
For moving a vertex one needs to determine which vertex is the closest one. If the closest vertex is within a given tolerance distance we start moving it if the mousedown event occurs, move it constantly while mouse is down and moved and stop moving it after receiving the mouseup event. The .writePath() method is called after each mousemove event.
If the deleteVertex mode is active the onclick event triggers the deletion of a vertex if the closest vertex is within the tolerance distance defined. The corresponding subpath array is sliced, the vertex removed and the two parts of the subpath later joined again. The .writePath() method updates the drawing of the path after each deletion.
For deleting a subpath we need to determine the closest line segment and see whether it is within the tolerance distance. If yes, we simply delete the element of the corresponding subpath. Finding the closest line segment with a bisector method is described above.
For adding a vertex we first have to find the closest line segment and neighbour vertices. After that we slice the array, add the vertex and join it again with the remaining elements of the array. If the new vertex does not fall in between two bisector angles the new vertex is appended at the beginning or the end of the path.
To make a path editable we first need to parse the d-attribute of the selected path-element to build the internal data structure. Kevin Lindseys path parser.
Prior to sending the digitized data to the spatial database we need to convert the internal datastructure to a OGC compatible data format, called Simple Features for SQL. The supported geometry types are listed in Section 3.2 .
For many purposes it would be useful to enable snapping while digitizing. While in digitizing, moveVertex or addVertex mode vertices should snap to vertices of the geometry itself but also to other vector based base geometry. This will be enabled in a future version of the digitizing tool.
If one digitizes or edits a polygon mosaic it would be useful to edit the shared path segment of two polygons at once. The digitizing module should automatically detect the two polygons that belong to a shared segment and modify both polygons at once. Later, as SVG 1.2 supports "vector effects" it should be possible to implement a lightweight GIS data structure with shared boundaries to avoid data redundancy. See [svg12wd] for the vector effects syntax and examples for shared boundaries.
This chapter lists a few SVG enhancements that will simplify and speed up the development of a SVG based digitizing tool. It is split up into enhancements already planned for SVG 1.2 and a discussion of additional features not yet planned for any SVG version. While not all of the listed features are relevant for the current functionality of the digitizing tool, they will simplify the development of future features.
The author is grateful for the following groups of individuals for contributing, ideas, hints and code:
My current employer that gives me time to work on SVG and webmaps. Many colleagues at the institute have contributed ideas, tested prototypes or read my papers and corrected my english.
People from the SVG Developers Yahoo-group gave numerous hints and code examples or participated in discussions on webmapping and SVG. Esp. I'd like to thank Kevin Lindsey and Michel Hirtzler for their excellent SVG sites and examples.
The Project builds on many open-source projects out there: Linux, Apache, PHP, PostgreSQL, Postgis, are only a few examples of the open-source software that had been used during the project. Open Source software had proven to be reliable in many projects that involved alternative Operating Systems and Middleware. Support is usually great and there is lot's of information on the web regarding the use and configuration of open source software.
XHTML rendition created by gcapaper Web Publisher v2.0, © 2001-3 Schema Software Inc.