NOTE: This has been replaced with the the new WFS-T based editor in GeoMOOSE 2.6. Using GeoServer with GeoMOOSE
The GeoMOOSE Feature Editor allows the user to create, modify, and delete the geometry and attributes of vector features stored in a PostGIS database. The feature layers can be points, lines, or polygons. You can have as many layers set up for editing as you like, each with a separate table.
To setup a layer for editing in GeoMOOSE it requires configuring ahead of time. First, the layer needs to be stored in a PostGIS database. Other relational database systems may be supported in the future. Shapefiles are not editable as they cannot be properly shared for editing amongst multiple users. Second, the layer’s table in PostGIS needs to have a primary key, a sequence for generating keys, and have an entry in the PostGIS geometry_columns table. Finally, the layer must be configured for the GeoMosse Feature Editor by creating an “ini” for the editor script, adding the proper service entries to the mapbook, and finally configuring a Mapserver identify record template.
Teh layer’s table requires a primary key in the table, a sequence that works as the iterator for that primary key, and a geometry column. You may add other columns as well. The SQL to create an example would be as follows:
To create the table, the CONSTRAINT .. PRIMARY KEY directive specifies the primary key (in this example, polygon_id) for the table:
CREATE TABLE test_polygons
(
polygon_id integer NOT NULL,
title character varying(100),
owner character varying(100),
wkb_geometry geometry,
CONSTRAINT pk_test_polygons PRIMARY KEY (polygon_id)
)
To create the sequence:
CREATE SEQUENCE test_polygons_seq;
Now add the table to the PostGIS register of geometry_columns. This may vary depending on your dataset, but for the purposes of the example this is what was used:
insert into geometry_columns values ('', 'public', 'test_polygons', 'wkb_geometry', 2, -1, 'GEOMETRY');
There are two files you must create for each editable layer: a mapfile and a .ini file. It is highly recommended keeping these named the same as the PostGIS table to prevent confusion. In this example the mapfile name would be “test_polygons.map”. To keep things organized you may wish to put the files for each layer into their own folder. For example, create a “test_polygons” directory and then place “test_polygons.map” and “identify.html” (see details below) in the “test_polygons” directory. A sample mapfile:
MAP SIZE 400 400 EXTENT 427632.500000 4893613.330000 560300.922104 5015936.680000 UNITS METERS SYMBOLSET '../symbols/symbol.sym' STATUS ON IMAGETYPE GIF TRANSPARENT TRUE LAYER NAME 'polygons' TYPE POLYGON STATUS ON CONNECTIONTYPE POSTGIS CONNECTION 'host=192.168.52.1 dbname=geomoose_test user=postgres password=postgres22' DATA 'wkb_geometry from (select polygon_id, title, owner, astext(wkb_geometry) as wkt_geometry, wkb_geometry from test_polygons) as mytable using unique feature_id' CLASS STYLE SYMBOL 'circle' OUTLINECOLOR 255 255 0 SIZE 10 END END METADATA 'identify_record' 'identify.html' END END END
The first step is to create map-source entry in the GeoMOOSE mapbook that points to the test_polygons mapfile:
<map-source name="poly_editor" type="mapserver">
<file>/var/www/geomoose2/maps/test_polygon/test_polygon.map</file>
<layer name="polygons"/>
</map-source>
Then add a Layer entry to the catalog:
<group title="Editing Layers" expand="true">
<layer title="Polygons" src="poly_editor/polygons"/>
</group>
The .INI file is where all the vital information about the layer’s table is stored for the Feature Editor. All of the .INI files are stored in GeoMOOSE’s “conf/editor” folder. To continue with the example from earlier, create a “test_polygons.ini” file. Since each table has a separate host/dbname configuration it is possible for a single GeoMOOSE interface to edit layers on multiple different servers without the user knowing the difference.
Example INI file:
; Basic Connection Information
host=192.168.52.1
dbname=geomoose_test
username=postgres
password=postgres22
; Table Information
tablename=test_polygons ; Database table name
geometry_column=wkb_geometry ; Column name from the CREATE TABLE SQL
primary_key_column=polygon_id ; Primary Key Column from CREATE TABLE
primary_key_sequence=test_polygons_seq ; Sequence name from CREATE SEQUENCE
srid=26915 ; SRID for the Dataset in the database
; GeoMOOSE Information
layerpath=poly_editor/polygons ; The full path in GeoMOOSE (same as catalog)
This may be the most difficult part of setting up the service as it requires the most amount of knowledge on how GeoMOOSE services are configured. But all tables should follow roughly the same pattern. All of the columns in the layer’s table are referred to as “feature:[COLUMN NAME]” so if the table as a column named “owner” it is referenced as “feature:owner” for the name to be used with the editor script.
The service definition starts simple with the header:: <service name=”add_polygon”>
And add a reference to the editor url:
<url>php/editor.php</url>
Now, we need a step to tell GeoMOOSE to draw a polygon:
<step type='spatial' name='feature:wkb_geometry' line='false' polygon='true' point='false' default='polygon'>
</step>
You can see, above, that the “name” references the name of the geometry column. We also turn off all of the tools except the polygon drawing tool by specifying “false” values for the “line” and “polygon” attributes. This would change depending on the dataset (as some layers have a geometry type of points and others lines). The “default” attribute tells GeoMOOSE to start this step with the “polygon” tool enabled instead of Navigation or other tools.
Then there is a required step to describe which operation we’re performing and the attributes that will be edited:
<step type="input"> <!-- This tells GeoMOOSE there will be user input -->
<input type="hidden" name="op" value="create"/>
<!-- The "op" variable tells the editor which operation to perform: create, update, or delete -->
<input type="hidden" name="table" value="test_polygons"/>
<!-- The "table" refers to the name of the "ini" file. -->
<input type="user" name="feature:title" title="Title:"/>
<input type="user" name="feature:owner" title="Owner:"/>
<!-- These previous two lines refer to columns in the table. -->
</step>
Putting it all together:
<service name="add_polygon">
<url>php/editor.php</url>
<step type='spatial' name='feature:wkb_geometry' line='false' polygon='true' point='false' default='polygon'>
</step>
<step type="input">
<input type="hidden" name="op" value="create"/>
<input type="hidden" name="table" value="test_polygons"/>
<input type="user" name="feature:title" title="Title:"/>
<input type="user" name="feature:owner" title="Owner:"/>
</step>
</service>
Finally, the service needs to be exposed on the toolbar with an “Add Polygon” tool:
<toolbar>
...
<tool name=”add_polygon” title=”Add Polygon” type=”service” service=”add_polygon”/>
...
</toolbar>
It’s usually nice to add some CSS to decorate up the Polygon Tool, so something like this might be prudent in htdocs/css/user_tools.css:
#tool-add_polygon {
background-image: url('../images/toolbar/add.png');
background-position: 2 2;
background-repeat: no-repeat;
padding-left: 2px;
}
#tool-add_polygon .ToolText {
padding: 2px;
display: block;
width: auto;
}
#tool-add_polygon .ToolContent {
width: auto;
}
While it is nice to create features, it may be necessay to edit those features. The user workflow for modifying (and deleting features) is different than for creating them. For modify and delete, the user must first identify the feature (using the Identify button) with a mouse click, then select the edit or delete link shown in the Information tab.
Modifying requires setting up a similar service to creating.
The entry for the Modify Polygon service will look like this:
<service name="modify_polygon">
<url>php/editor.php</url>
<step type='spatial' name='feature:wkb_geometry' line='false' polygon='true' point='false' default='point' edit-polygon='true'> <!-- It's necessary to specify that the polygon editor be turned on, the rest of the options are CREATION functions -->
<input type="hidden" name="op" value="update"/>
<!-- This just changes the option to 'update' instead of 'create' -->
<input type="hidden" name="table" value="test_polygons"/>
<input type="hidden" name="feature:polygon_id"/>
<input type="user" name="feature:title" title="Title:"/>
<input type="user" name="feature:owner" title="Owner:"/>
</step>
</service>
This is the easiest service to create as there are no user inputs or spatial steps to define:
<service name="delete_polygon">
<url>php/editor.php</url>
<step type='input'>
<input type="hidden" name="op" value="delete"/>
<input type="hidden" name="table" value="test_polygons"/>
<input type="hidden" name="feature:polygon_id"/>
</step>
</service>
Now get the layer properly identifying in the interface.
identify.html:
<tr bgcolor="#AA55AA">
<td colspan="2"><b>[title] ([polygon_id])</b></td>
</tr>
<tr>
<td>Owner:</td><td>[owner]</td>
</tr>
<tr>
<td>
<a href="javascript:GeoMOOSE.startService('modify_polygon', {'feature:polygon_id' : '[polygon_id]','feature:wkb_geometry' : '[wkt_geometry]', 'feature:title' : '[title]', 'feature:owner' : '[owner]'})">Edit</a>
</td>
<td>
<a href="javascript:if(confirm('Are you sure you want to delete this?')) { GeoMOOSE.startService('delete_polygon', {'feature:polygon_id' : '[polygon_id]'}); }">Delete</a>
</td>
</tr>
The key to the editing functionality is in the <a href=”javascript...”> links. These links are calling the editing service definitions with the values “filled in” for the selected object from the identify result. Every different feature type (i.e table) requires changing this list of attributes to reflect the column names of the specific table.