<?xml version="1.0"?>
<!DOCTYPE gcapaper PUBLIC "-//GCA//DTD GCAPAP-X DTD 20021024 Vers 6.2//EN" "../gcapaper.dtd">
<gcapaper secnumbers="1">
  <front>
    <title>Using SVG for Online Digitizing and Editing of Geographic Data</title>
    <subt>Paper for the SVG Open conference, Tokyo, 2004</subt>
    <keyword>Digitizing</keyword>
    <keyword>Editing</keyword>
    <keyword>Open GIS (OGC)</keyword>
    <keyword>PostgeSQL</keyword>
    <keyword>PostGIS</keyword>
    <keyword>Spatial Databases</keyword>
   <author>
      <fname>Andreas</fname>
      <surname>Neumann</surname>
      <suffix>Ph.D. candidate</suffix>
      <jobtitle>Ph.D. student, researcher</jobtitle>
      <address>
        <affil>Institute of Cartography, ETH Zurich</affil>
        <city>Zurich</city>
        <country>Switzerland</country>
        <email>neumann@karto.baug.ethz.ch</email>
        <web>http://www.carto.net/</web>
      </address>
      <bio id="neumann">
        <para>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.</para>
      </bio>
    </author>
    <abstract>
      <para>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.</para>
    </abstract>
  </front>
  <body>
    <section id="intro">
      <title>Introduction and Motivation</title>
      <para>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 <bibref refloc="neumann_2003"/> <bibref refloc="isakowski_neumann_2002"/> 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 &amp; 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.</para>
      <para></para>
    </section>
    <section id="basicMapCient">
      <title>Development of a  Basic DB Driven Webmapping Client</title>
      <para>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 <bibref refloc="neumann_2003"/>.</para>
	<subsec1>
		<title>Spatial Database</title>
		<para>Our work is based on the Open Source Spatial Extension Postgis <bibref refloc="PostGIS"/> and the database PostgreSQL <bibref refloc="PostgreSQL"/>. PostGIS can deliver OGC compliant geometry and stores them as Simple Features for SQL <bibref refloc="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 <bibref refloc="AsSvg"/>. All of the technologies listed above build a powerful foundation for a vector-based webmapping server.</para>
	</subsec1>
	<subsec1>
		<title>Basic DOM Structure of the Application and Coordinate System</title>
		<para>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 <bibref refloc="isakowski_neumann_2002"/> and <bibref refloc="neumann_2003"/>. 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.</para>

<para>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.</para>

<figure id="digiApplication">
            <title>Screenshot Digitizing Application</title>
            <graphic href="screenshot_digi_app.svg" scalefit="1" width="800px" height="650px"/>
</figure>
	</subsec1>
	<subsec1>
		<title>Navigation Tools</title>
		<para>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:</para>
			<randlist>
				<li>
					<randlist>
						<title>resizing of the map extent through</title>
						<li><para>plus/minus buttons</para></li>
						<li><para>a zoom slider next to the reference map</para></li>
						<li><para>a manual zoom method by drawing a rectangle directly within the map</para></li>
						<li><para>a full view button</para></li>
					</randlist>
				</li>
				<li>
					<randlist>
						<title>panning and recentering by</title>
						<li><para>specifying a new map center directly in the map</para></li>
						<li><para>using the pan arrow buttons (with 3 different pan distances and 8 different pan directions)</para></li>
						<li><para>using a dragable rectangle in the reference map</para></li>
					</randlist>
				</li>
			</randlist>
			<para>Regardless on how the map user navigated the current map extent is always indicated in the linked reference map.</para>
	<figure id="communication">
            <title>Available Navigation Tools</title>
            <graphic href="nav_tools.svg" scalefit="1" width="500px" height="300px"/>
	</figure>

	</subsec1>
	<subsec1>
		<title>Data loading</title>
		<para>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.</para>
	</subsec1>
	<subsec1>
		<title>Scale Dependent Selection and Symbolization</title>
		<para>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.</para>
	</subsec1>
    </section>
    <section id="digitizingComponent">
    <title>Digitizing Component</title>
    <subsec1>
    	<title>Why SVG?</title>
    	<para>SVG offers a number of advantages that makes it attractive for being used as a online digitizing component:</para>
		<randlist>
			<li><para>The combination of vector, raster and text allows the use of vector data for digitizing, vector and raster layers as base layers and text to annotate features</para></li>
			<li><para>Mouse events return coordinates within the map coordinate system that can be used to generate the digitized path elements.</para></li>
			<li><para>The support of viewBox coordinate systems makes more complicated transformations unnecessary. Projecting geographic data can be done on the server using existing open source projection software, e.g. proj4 <bibref refloc="proj4"/>.</para></li>
			<li><para>adequate symbolization options: markers can be used to accentuate vertices; opacity can be used to see the base map layers below filled objects during digitizing.</para></li>
			<li><para>Server-Client communication (e.g. .getURL(), .postURL()) facilitates data communication with a serverside database and ore OGC compatible feature or WMS servers. This can be done without having to reload the SVG application.</para></li>
		</randlist>
    </subsec1>
    <subsec1 id="dataStructure">
    	<title>Data structure</title>
    	<para>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[1][2].x; this.subPaths[1][2].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:</para>
	<randlist>
		<li><para>POINT</para></li>
		<li><para>MULTIPOINT</para></li>
		<li><para>LINESTRING</para></li>
		<li><para>MULTILINESTRING</para></li>
		<li><para>POLYGON</para></li>
		<li><para>MULTIPOLYGON</para></li>
		<li><para>GEOMETRYCOLLECTION</para></li>
	</randlist>
    </subsec1>
    <subsec1>
    	<title>Current Digitizing Functionality</title>
    	<para>The digitizing environment currently supports the following basic features:</para>
		<randlist>
			<li><randlist>
				<title>digitizing functionality</title>
				<li><para>digitizing</para></li>
				<li><para>moving selected vertices</para></li>
				<li><para>deleting selected vertices</para></li>
				<li><para>adding vertices between segments or at the ends of the line/polygon</para></li>
				<li><para>starting new subpath (disjunct polygons or holes)</para></li>
				<li><para>deleting a subpath</para></li>
			</randlist></li>
			<li><randlist>
			<title>changing digitizing appearance</title>
			<li><para>opening closing subpath</para></li>
			<li><para>changing stroke and fill colour and opacity</para></li>
			<li><para>show/hide markers</para></li>
			<li><para>show/hide bounding box</para></li>
			</randlist></li>
		</randlist>
    </subsec1>
    <subsec1>
    	<title>Explanation of Digitizing Technique</title>
    	<subsec2>
    		<title>Digitizing Operations</title>
    		<para>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:</para>
			<randlist>
				<li><para>Digitizing (adding vertices one after the other)</para></li>
				<li><para>move vertex</para></li>
				<li><para>delete vertex</para></li>
				<li><para>delete subpath</para></li>
				<li><para>add vertices</para></li>
			</randlist>
			<subsec3>
				<title>Digitizing</title>
				<para>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.</para>
			</subsec3>
			<subsec3>
				<title>Finding Closest Vertex and Line Segment</title>
				<para>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).</para>
				<para>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.</para>
			<figure id="biSectorPrinciple">
            	<title>Bisector Principle for Finding Closest Segment/Subpath</title>
            	<graphic href="bisector_principle.svg" scalefit="1" width="600px" height="650px"/>
			</figure>
			<para>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.</para>
			</subsec3>
			<subsec3>
				<title>Moving a Vertex</title>
				<para>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.</para>
			</subsec3>
			<subsec3>
				<title>Deleting a Vertex</title>
				<para>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.</para>
			</subsec3>
			<subsec3>
				<title>Deleting a Subpath</title>
				<para>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.</para>
			</subsec3>
			<subsec3>
				<title>Adding a Vertex</title>
				<para>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.</para>
			</subsec3>
		</subsec2>
		<subsec2>
				<title>Parsing the d-attribute of a Path Element</title>
			<para>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.</para>
		</subsec2>
		<subsec2>
				<title>Writing OGC geometry strings</title>
				<para>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 <xref refloc="dataStructure"/>.</para>
   		</subsec2>
    </subsec1>
   </section>
   <section id="futureEnhancements">
   <title>Planned Enhancements</title>
   <subsec1>
   	<title>Snapping</title>
   	<para>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.</para>
   </subsec1>
   <subsec1>
   	<title>Shared Editing</title>
   	<para>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 <bibref refloc="svg12wd"/> for the vector effects syntax and examples for shared boundaries.</para>
   </subsec1>
   </section>
   <section id="futureSpecEnhancements">
   <title>Future SVG Spec Enhancements</title>
    <para>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.</para>
   	<subsec1>
   	<title>Useful Enhancements Planned for SVG 1.2</title>
   	<randlist>
   		<li><para>editable text fields: dditable text will simplify annotating and labeling features</para></li>
   		<li><para>tooltips: will simplify the display of attribute data and hints during digitizing</para></li>
   		<li><para>alternate content based on display resolutions: might help for displaying multiresolution data for reference layers.</para></li>
   		<li><para>vector effects: will allow more complex line and fill styles as well as shared boundaries using the veJoin or vePathRef elements.  veReverse will allow to flip the direction of a path segment. The path segment direction can be visualized using markers (arrows).</para></li>
		<li><para>conversion of mouse coordinates: convertClientXY() helps to convert client space coordinates to user coordinates</para></li>
		<li><para>standardized window object: this was previously used by most SVG viewers, however as non standardized proprietary extensions. For most interactive SVG applications the window object's methods and properties are very important.</para></li>
		<li><para>better network data interface and monitoring download progress: so far we work only with the .getURL() and .postURL() methods for data loading. However these methods only work asynchronously and do not give any feedback on how much data was already transfered, e.g. for displaying a progress bar for loading.</para></li>
		<li><para>file upload: will be useful to allow the user to upload geodata, such as attribute-tables or gps geometry</para></li>
		<li><para>persistent client-side data storage: will help to persistently store user settings, however only in the context of one machine/user account</para></li>
   	</randlist>
   	</subsec1>
   	<subsec1>
   	<title>Discussion of Additional Useful Features</title>
   	<randlist>
   		<li><para>additional marker types: currently the marker-start and marker-end types work only globally, for subpaths starts and ends (defined by move-to commands) only marker-mids are drawn. Additional marker types, such as "marker-inner-start" and "marker-inner-end" would allow to have symbolize those markers differently</para></li>
		<li><para>widget support: many SVG applications make use of SVG based widgets. Developing these widgets is time consuming and unless one really invests a huge amount of time the resulting widgets will usually be inflexible, hard to maintain and not behaving like professional widgets. Better widget support within SVG would really help speeding up SVG application development. Meanwhile other techniques within SVG 1.2 (such as RCC or XBL) will provide foundations for self-written widgets</para></li>
	</randlist>
   	</subsec1>
   </section>
  </body>
  <rear>
    <acknowl>
      <para>The author is grateful for the following groups of individuals for contributing, ideas, hints and code:</para>
      <title>Institute of Cartography, ETH Zurich (<a href="http://www.karto.ethz.ch/"/>)</title>
      <para>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.</para>
      <title>SVG Developers Yahoo-group (<a href="http://groups.yahoo.com/group/svg-developers/" />)</title>
      <para>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.</para>
		<title>The Open Source Community</title>
		<para>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.</para>
    </acknowl>
    <bibliog>
      <bibitem id="isakowski_neumann_2002">
        <bib>SVGTOPOMaps</bib>
        <pub><i>Interactive Topographic Web-Maps Using SVG (<a href="http://www.svgopen.org/papers/2002/isakowski_neumann__svg_for_interactive_topographic_maps/"/>)</i>, Isakowski Yvonne and Andreas Neumann, in: Proceedings of the SVG.Open 2002 Conference, Zurich, July 2002.</pub>
      </bibitem>
      <bibitem id="neumann_2003">
        <bib>DBDrivenTopographicSVGMaps</bib>
        <pub><i>Delivering Interactive Topographic Web-maps using Open-Source Database Technology (<a href="http://www.svgopen.org/papers/2003/neumann__svg_for_interactive_topographic_maps/"/>)</i>, Neumann, Andreas; in: Proceedings of the SVG.Open 2003 Conference, Vancouver, July 2003.</pub>
      </bibitem>
     <bibitem id="PostgreSQL">
        <bib>PostgreSQL</bib>
        <pub><i>PostgreSQL (<a href="http://www.postgresql.org/"/>)</i>,  The most advanced Open Source database system in the world, 2003</pub>
      </bibitem>
     <bibitem id="PostGIS">
        <bib>PostGIS</bib>
        <pub><i>PostGIS (<a href="http://postgis.refractions.net/"/>)</i>,  Geographic Objects for PostgreSQL, 2003</pub>
      </bibitem>
     <bibitem id="SimpleFeaturesSQL">
        <bib>SimpleFeaturesSQL</bib>
        <pub><i>OpenGIS Simple Features Specification For SQL (<a href="http://www.opengis.org/techno/specs/99-049.pdf"/>)</i>,  Open GIS Consortium, Inc., 1999.</pub>
      </bibitem>
     <bibitem id="AsSvg">
        <bib>AsSVG</bib>
        <pub><i>AsSvg() - a Postgres Function to directly output SVG from a Postgis spatial database (<a href="http://svg.cc/assvg/"/>)</i>,  Klaus Förster, 2002</pub>
      </bibitem>
     <bibitem id="proj4">
        <bib>proj4</bib>
        <pub><i>proj4 - a open source projection library (<a href="http://www.remotesensing.org/proj/"/>)</i>.</pub>
      </bibitem>
     <bibitem id="svg12wd">
        <bib>svg12wd</bib>
        <pub><i>Scalable Vector Graphics (SVG) 1.2; W3C Working Draft 10 May 2004 (<a href="http://www.w3.org/TR/SVG12/"/>)</i>.</pub>
      </bibitem>
   </bibliog>
 </rear>
</gcapaper>
