cl-wkb implements the OGC Well-Known Binary geographic geometry data model, and provides WKB encoding and decoding functionality.
cl-wkb is used by the En Route public transit trip planner to read street and city-boundary features from a PostGIS database. En Route powers En Route Spokane.
A independent fork of cl-wkb adds PostGIS 3D and 4D extensions, and includes SRIDs in data structures: cl-ewkb
IEEE754-DOUBLE: a deftype intended to
represent the best CL numeric type that will accurately convey
IEEE-754 double-precision floating-point values. All
coordinates must be of this type.POINT-PRIMITIVE: a primitive point, expressed
as X and Y values. It is customary for Y to represent latitude,
and X to represent longitude.LINEAR-RING: a primitive polygon, represented
as a sequence of POINT-PRIMITIVE instances.GEOMETRY: the base type of all other high-level
classes.POINTLINE-STRING: a sequence of connected line
segments, represented as a sequence
of POINT-PRIMITIVE instances.POLYGON: an area defined by a number
of LINEAR-RINGs.MULTI-POINT: a set of POINTs.MULTI-LINE-STRING: a set of LINE-STRINGs.MULTI-POLYGON: a set of POLYGONs.GEOMETRY-COLLECTION: a set of GEOMETRY instances.GEOMETRY as big-endian, returning a
vector of octets.GEOMETRY as the
specified endianness (:BIG-ENDIAN
or :LITTLE-ENDIAN), writing the result
to stream (an (UNSIGNED-BYTE 8) stream
open for writing).GEOMETRY instance from the given sequence
of octets.GEOMETRY instance from the
given stream (an (UNSIGNED-BYTE 8) stream
open for reading).To pull WKB-format geometry data out of PostGIS, you might run a query like this:
(postmodern:query (:select 'dxf_text (:AsBinary (:Transform 'the_geom 4326))
:from 'cities_p
:where (:not (:is-null 'dxf_text))))
The geometry data will be encoded in WKB. To work with it, you'll want to decode it:
(let ((multipolygon (wkb:decode multipolygon-e))) ...)
And then access the data:
(defun multipolygon->boundary-list (mpg)
(reduce #'append (map 'list #'polygon->boundary-list
(wkb:polygons mpg))))
(defun polygon->boundary-list (pg)
(map 'list #'linear-ring->boundary
(wkb:linear-rings pg)))
(defun linear-ring->boundary (lr)
(geo:polygon (map 'list #'point-from-primitive
(wkb:points-primitive lr))))
(defun point-from-primitive (point-p)
(geo:point-deg (wkb:y point-p) (wkb:x point-p)))
(let* ((multipolygon (wkb:decode multipolygon-e))
(boundary-list (multipolygon->boundary-list multipolygon)))
...)
For now, the best way to learn the structure of a data type is
to examine wkb.lisp, under "High-Level Classes" and
"Semi-Primitive Classes," and/or to read the WKB
specification.
The most recent release is 0.1, released 2009-07-27. It depends on: ieee-floats, flexi-streams (Debian: cl-flexi-streams), cl-jpl-util.
I sign all my software with OpenPGP, key ID 0x80555CED7394F948, fingerprint 2771 AF53 5D09 BDFB A8D0 BEF3 8055 5CED 7394 F948.
This software is licensed under permissive, BSD-like terms, copied from the ISC license:
Copyright (c) 2009, Jean-Paul Guy Larocque
Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
I'm reachable via e-mail for feedback, questions, help requests, and bug reports: jpl-software at surejourney.com
— J.P. Larocque