[postgis-users] Light WeightLight Weight Geometry (LWGEOM) Proposal

David Blasby dblasby at refractions.net
Fri Feb 20 12:22:36 PST 2004


As per our current discussions, I'm proposing a new Light-Weight 
Geometry.  This will be 'as-well-as' the current PostGIS so no one will 
lose anything.  I'm not going to back-port this, so we'll only support 
it in postgresql 7.4+.

Disk Representation (serialized form)

int32 size; //postgresql variable-length requirement
char  type; // this type (see below)
<data>

Where the 8-byte 'type' is defined bit-wise as:

xSBDtttt

WHERE
	x = unused
	S = 4 byte SRID attached (0= not attached (-1), 1= attached)
	B = bounding box attached (0=no, 1=yes) (32 bytes)
	D = dimentionality (0=2d, 1=3d)
	tttt = actual type (as per the WKB type):
	
	enum wkbGeometryType {
		wkbPoint = 1,
		wkbLineString = 2,
		wkbPolygon = 3,
		wkbMultiPoint = 4,
		wkbMultiLineString = 5,
		wkbMultiPolygon = 6,
		wkbGeometryCollection = 7
	};


In general, data will be exactly like the 3d-extended WKB representation 
(except there's no endian flag and the WKB type is defined as above).

The bounding box flag is an optional component for large geometries - 
for small (<1000 point geometries) it will not be present.  This allows 
for small storage of small geometries (where bounding boxes can be 
quickly calculated on-the-fly) but enhanced performance for large 
geometries.  This will probably be a compile-time option.


Examples (c.f. OGC SF SQL defintion of WKB (section 3.3.2.6))
-------------------------------------------------------------

A. 2D point w/o bounding box

<int32> size  = 21 bytes
<char> type:  S=0,B=0,D=0, tttt= 1
<double> X
<double> Y

B. 3D point w/o bounding box

<int32> size = 29 bytes
<char> type:  S=0,B=0,D=1, tttt= 1
<double> X
<double> Y
<double> Z


C. 2D point WITH bounding box
     (you would never put on with a points, but this is just an example)

<int32> size = 53 bytes
<char> type:  S=0,B=1,D=0, tttt= 1
<double> xmin
<double> ymin
<double> xmax
<double> ymax
<double> X
<double> Y


D. 2D line String w/o bounding box

<int32> size = npoints*16 + 9
<char> type:  S=0,B=0,D=0, tttt= 2
<uint32> npoints
<double> X1
<double> Y1
<double> X2
<double> Y2
...

E. 2D line String with bounding box

<int32> size = npoints*16 + 9 + 32
<char> type:  S=0,B=1,D=0, tttt= 2
<double> xmin
<double> ymin
<double> xmax
<double> ymax
<uint32> npoints
<double> X1
<double> Y1
<double> X2
<double> Y2
...

F. 3D polygon w/o bounding box
    NOTE: I havent explicitly put in the ogcLinearRing

<int32> size =
<char> type:  S=0,B=1,D=0, tttt= 3
<uint32> nrings
<uint32> npoints in ring1
<double> X1
<double> Y1
<double> X2
<double> Y2
...
<uint32> npoints in ring3
<double> X1
<double> Y1
<double> X2
<double> Y2
...
...


G. 2d multilines string w/o bounding boxes

     NOTE: this is like the OGC spec - we duplicate type info
           in the sub-geometries.  This is arguably not a good idea,
           but it does allow us to treat all the multi* and
           geometrycollection types equivelently.
           It also allows us to represent GeometryCollections of
           GeometryCollections (which postgis doesnt support).

<int32> size =
<char> type:  S=0,B=0,D=0, tttt= 5
<uint32> nlines
<char> type:  S=0,B=0,D=0, tttt= 2
<uint32> npoints in line 1
<double> X1
<double> Y1
<double> X2
<double> Y2
....
<char> type:  S=0,B=0,D=0, tttt= 2
<uint32> npoints in line 2
<double> X1
<double> Y1
<double> X2
<double> Y2
....


G. 2d multilines string with main bounding box
<int32> size =
<char> type:  S=0,B=0,D=0, tttt= 5
<double> xmin
<double> ymin
<double> xmax
<double> ymax
<uint32> nlines
<char> type:  S=0,B=0,D=0, tttt= 2
<uint32> npoints in line 1
<double> X1
<double> Y1
<double> X2
<double> Y2
....
<char> type:  S=0,B=0,D=0, tttt= 2
<uint32> npoints in line 2
<double> X1
<double> Y1
<double> X2
<double> Y2
....

G. 2d multilines string with main and sub bounding boxes
     NOTE: since our types are defined recursive manner, this
           type is possible.  I dont think we should construct them in
           general.

<int32> size =
<char> type:  S=0,B=0,D=0, tttt= 5
<double> xmin
<double> ymin
<double> xmax
<double> ymax
<uint32> nlines
<char> type:  S=0,B=1,D=0, tttt= 2
<double> xmin
<double> ymin
<double> xmax
<double> ymax
<uint32> npoints in line 1
<double> X1
<double> Y1
<double> X2
<double> Y2
....
<char> type:  S=0,B=1,D=0, tttt= 2
<double> xmin
<double> ymin
<double> xmax
<double> ymax
<uint32> npoints in line 2
<double> X1
<double> Y1
<double> X2
<double> Y2
....

H. 2D point w/o bounding box (with SRID)

<int32> size  = 25 bytes
<char> type:  S=1,B=0,D=0, tttt= 1
<int32> SRID
<double> X
<double> Y

I. 3D point w/o bounding box (with SRID)

<int32> size = 33 bytes
<char> type:  S=1,B=0,D=1, tttt= 1
<int32> SRID
<double> X
<double> Y
<double> Z


J. 2D point WITH bounding box (with SRID)
     (you would never put on with a points, but this is just an example)
     (note: SRID comes before bounding box)

<int32> size = 57 bytes
<char> type:  S=1,B=1,D=0, tttt= 1
<int32> SRID
<double> xmin
<double> ymin
<double> xmax
<double> ymax
<double> X
<double> Y




Other notes:

Cannonical form will be very much like the current WKB type (ie. looks 
like '000000FF001A..').  This means your pg_dumps will look strange, but 
you'll find it faster and there will not be any numberic drift as you 
move to and from WKT.

We'll need to write a WKB to LWGEOM and LWGEOM to WKB.  Since LWGEOM is 
very close to WKB, this should be simple.

To get to WKT, we can do a LWGEOM->WKB->PostGIS GEOMETRY->WKB.  For 
parsing WKT, we can WKT->PostGIS GEOMETRY->WKB->LWGEOM.  The PostGIS 
conversion functions already exist, so this will be very easy.

We'll also need to write something to convert a LWGEOM to a bounding box 
plus all the indexing support functions (based on BOX2DFLOAT4s).

One of the design issues I have with PostGIS is that all the analysis 
functions deal directly with the serialized GEOMETRY form.  This makes 
them more complex and difficult to maintain.  I suggest we have soup-up 
versions of the current PostGIS geometry types (i.e. POLYGON3D, 
LINESTRING3D, POINT3D) for LWGEOM (i.e. LW_POLYGON, LW_LINE, LW_POINT) 
which would hide things like 2d vs 3d and make construction easier.

What think?

dave




More information about the postgis-users mailing list