[Xastir-dev] Spatial database support
Paul J. Morris
mole at morris.net
Fri Jul 6 19:26:42 EDT 2007
I have been working on code to allow xastir to store and retrieve data
from relational databases, including MySQL and PostGIS with support for
spatial objects, indicies, and queries. There are a number of things
this could support, including persistent storage of station data,
persistent storage and spatial querying of CAD objects, logging of
station data into APRSWorld tables, using xastir with other applications
(such as QGIS for GIS, or APRSWorld for webserving), and so on. My main
interest here is in interaction with GIS systems, but data persistence
and running multiple clients over a single database (APRSWorld
webserving plus multiple xastir clients) also seem of potential use.
I have a chunk of code that doesn't yet actually do anything, but I
think is starting to lay out a framework on which we can build some
flexible external database and GIS functionality.
Before I add the code to the cvs repository, I wanted to describe the
direction I'm working in and see if it makes sense to folks.
------------------------
Here's some of the documentation for the code:
Functions supporting connections to databases, including GIS enabled
databases that hold OpenGIS objects and can apply spatial indicies.
XASTIR GIS database code is separated into three layers
1) Supporting XASTIR logic (ui elements, cad integration,
map drawing, etc).
2a) Generic db storage/retrieval code - wrappers for layer 3
2b) Connection management code
3a) DBMS specific db storage/retrieval code for spatial databases
3b) DBMS specific db storage/retrieval code for non-spatial databases
Data structures in an underlying database can be considered as a fourth
level.
Code for layers 2 and 3 is in this file.
Layer 2 functions should be extern and called from elsewhere to
perform spatial database operations. Xastir shouldn't need to care
if an underlying database has spatial support or not for simple data.
Some functionality might require spatial object support and might be
included only if a spatial database is available. Thus 3b code may
only support a subset of the 2a functions, while 3a code should
support all 2a functions.
Layer 2a wrappers should take and return values in xastir
coordinates, and convert them to decimal degrees to pass on to layer
3. Likewise return values from layer 3 to layer 2a should be in
decimal degrees, limiting the number of different places at which the
xastir/decimal degree conversion code needs to be invoked. This
would not be true if data are fed directly from decimal degree feeds
into the database, so there may also be a need for layer 2 functions
that deal only with latitude and longitude in decimal degrees.
Layer 3 functions should not be extern and should only be called
by layer 2 functions from within this file.
Layer 3 functions should take and return values in decimal degrees.
Xastir objects should be passed down into layer 3, as doing
so should make code easier to maintain (but harder to extend) than
using generic structures for transport of data between layers 2 and 3.
Passing a station struct from layer 2 to 3 makes layer 2 a very
simple wrapper, but requires new layer 3 code to write station data to
a map layer rather than to a DataRow (to, for example, prepare a layer
of temperature data at points for analysis and generation of a
temperature grid.) [Using generic structures for transport would let
the layer 3 code remain unchanged while layer 2 functions are added
or extended, but requires added maintainance to synchronise xastir
structs, the generic structs, and database structures.]
A spatially enabled database is expected to support OpenGIS spatial
objects and be able to apply spatial indicies to the data. A
non-spatially enabled database is expected to hold coordinates using
separate fields for latitude and longitude. Layer 3 functions that
interact with a spatial database will need to convert decimal degrees
to well known text (WKT, and perhaps also well known binary, WKB)
representations. Layer 3 functions that interact with non-spatially
enabled databases can just pass raw latitudes and longitudes.
All spatial data are expected to be in WGS84 projection EPSG:4326
Support for five sets of underlying database schema elements is
envisioned - a very simple station at point and time table
- schema elements to support CAD objects with arbitrary associated
data tables.
- a schema capable of holding the full range of aprs data using
spatial elements (Points, Polygons, etc).
- full support for APRSWorld tables (using latitude and longitude
fields rather than spatial elements).
- arbitrary tables with schema discovery for arbitrary GIS databases
such as Tiger data.
The first three of these will require schema version awareness and
will produce compatability/database lifecycle issues.
Descriptions of how to make connections to databases are stored in
connection descriptors. Connection descriptors describe the DBMS,
whether the database has/lacks spatial support, the schema type (simple,
simple+cad, xastir full, APRSWorld, etc for the database, and
connection parameters (server, user, database). The layer 2/3
separation is intended to allow functions (layer 2) to be called from
within xastir (layer 1) without the need to test which function to call
for which dbms. Some functions may be schema specific, others may be
able to use any of several different schemas. Connections can be
opened from a database descriptor, and more than one descriptor can
point to the same database. (Thus a single MySQL database may contain
simple xastir tables, xastir CAD object tables, and APRSWorld tables,
but two different descriptors would be used to define connections to
talk to the APRSWorld tables and the simple+cad tables within what
MySQL considers one schema. A given version of xastir will expect a
particular version or range of versions for database schemas - an older
version of xastir may expect fields that no longer exist in a database
created for a newer version of xastir and vice versa.
Data selected from a spatial database might be brought into xastir as
stations just like an internet feed or findu fetch trail query, as
editable CAD objects, or as map layers.
-------------------
And here's one example of how I'm seeing function calls working:
With xastir running, user turns on logging of packets to external
database (probably implemented through the interface UI), as each
station heard is added to the xastir db, a call is made to a wrapper
function (layer 2a):
storeStationToGisDb(connection, station)
This wrapper determines that the connection is to a MySQL database and
calls
storeStationToGisDbMysql(connection, station)
This function determines that the connection is to tables with the
APRSWorld structures, generates a set of appropriate insert and update
sql queries and uses the MySQL C client library to run the queries
against the database.
On stopping and restarting xastir, the user could then load all stations
from this MySQL database into the internal xastir db - invoking:
retrieveAllStationsFromGisDb(connection)
This wrapper determines that the connection is to a MySQL database and
calls
retrieveAllStationsFromGisDbMySQL(connection)
This function determines that the connection is to tables with the
APRSWorld structures, generates appropriate select statements, runs
them, and steps through the returned results to populate the internal
xastir db.
-------------------------
Comments and suggestions are very welcome.
73,
-Paul
--------------
Paul J. Morris
Biodiversity Informatics Manager
Harvard University Herbaria/Museum of Comparative Zoölogy
mole at morris.net AA3SD PGP public key available
More information about the Xastir-dev
mailing list