[svn-commits] r167 - branches/geospatial/wkt-wkb
thich01 at ingres.com
thich01 at ingres.com
Fri Jul 18 14:18:38 PDT 2008
Author: thich01
Date: 2008-07-18 14:18:38 -0700 (Fri, 18 Jul 2008)
New Revision: 167
Modified:
branches/geospatial/wkt-wkb/main.c
branches/geospatial/wkt-wkb/makefile
branches/geospatial/wkt-wkb/wkbOps.c
branches/geospatial/wkt-wkb/wkbOps.h
branches/geospatial/wkt-wkb/wkbTypes.h
branches/geospatial/wkt-wkb/wktToWkb.y
Log:
#107 - Create a binary stream and clean up and comment the code.
Modified: branches/geospatial/wkt-wkb/main.c
===================================================================
--- branches/geospatial/wkt-wkb/main.c 2008-07-18 15:06:25 UTC (rev 166)
+++ branches/geospatial/wkt-wkb/main.c 2008-07-18 21:18:38 UTC (rev 167)
@@ -6,19 +6,24 @@
#include <stdlib.h>
#include "wkbOps.h"
-main(int argc,char *argv[])
+int main(int argc,char *argv[])
{
- if(argc<2)
- {
- printf("Please specify the input file\n");
- exit(0);
- }
- FILE *fp=fopen(argv[1],"r");
- if(!fp)
- {
- printf("couldn't open file for reading\n");
- exit(0);
- }
- wkbParseFile( fp );
- fclose(fp);
+ char *wkbStream;
+ size_t streamSize = 0;
+
+ if(argc<2)
+ {
+ printf("Please specify the input file\n");
+ exit(0);
+ }
+ FILE *fp=fopen(argv[1],"r");
+ if(!fp)
+ {
+ printf("couldn't open file for reading\n");
+ exit(0);
+ }
+ wkbParseFile( fp, wkbStream, &streamSize );
+ fclose(fp);
+
+ return 1;
}
Modified: branches/geospatial/wkt-wkb/makefile
===================================================================
--- branches/geospatial/wkt-wkb/makefile 2008-07-18 15:06:25 UTC (rev 166)
+++ branches/geospatial/wkt-wkb/makefile 2008-07-18 21:18:38 UTC (rev 167)
@@ -1,7 +1,8 @@
wktToWkb.o : wktToWkb.l wktToWkb.y
bison -d -o wktToWkb.tab.c wktToWkb.y
flex -o wktToWkb.Flex.c --header-file=wktToWkb.Flex.h wktToWkb.l
- gcc -g main.c wktToWkb.Flex.c wktToWkb.tab.c wkbOps.c -ll -o wktToWkb
+ gcc -Wall -g main.c wktToWkb.Flex.c wktToWkb.tab.c wkbOps.c -ll -o wktToWkb
+
clean:
rm wktToWkb.tab.c wktToWkb.tab.h wktToWkb.Flex.c wktToWkb.Flex.h wktToWkb
Modified: branches/geospatial/wkt-wkb/wkbOps.c
===================================================================
--- branches/geospatial/wkt-wkb/wkbOps.c 2008-07-18 15:06:25 UTC (rev 166)
+++ branches/geospatial/wkt-wkb/wkbOps.c 2008-07-18 21:18:38 UTC (rev 167)
@@ -5,27 +5,216 @@
#include "wktToWkb.Flex.h"
#include "wkbOps.h"
-void initByteOrder( void )
+/*****************************************************************************
+ * Detects and returns the byte order of the current machine.
+ * Used for well known binary stream.
+ ****************************************************************************/
+static wkbByteOrderT getByteOrder( void )
{
+ // Create an unsigned integer and data fill it.
uint8_t orderTest[2] = { 1, 0 };
+ // Test the first part of the integer to determin byte order.
if ( *(uint8_t *)orderTest == 1 )
{
- printf("Little Endian.\n");
- gByteOrder = wkbNDR; // Little Endian system.
+ return wkbNDR; // Little Endian system.
}
else
{
- printf("Big Endian.\n");
- gByteOrder = wkbXDR; // Big Endian system.
+ return wkbXDR; // Big Endian system.
}
}
-void freeLinePoints( wkbLineT *line )
+/*****************************************************************************
+ * Given a geometry collection and the size of the collection this will
+ * allocate and create a well known binary stream.
+ ****************************************************************************/
+static int createBinaryStream( wkbGeometryCollectionT *geometryCollection,
+ size_t *streamSize, char *stream )
{
- wkbLineT *next;
- wkbLineT *current;
+ wkbGeometryCollectionT *current;
+ wkbGeometryT *geometry;
+ wkbLinearRingT *linearRing;
+ wkbPointListT *line;
+ wkbPolygonT *polygon;
+ wkbMultiPolygonT *multiPolygon;
+ wkbByteOrderT byteOrder;
+ char *streamPtr;
+ wkbGeometryTypeT tempType;
+ uint32_t tempNum, x, y;
+ printf( "Stream size %d.\n", *streamSize );
+ // Allocate the binary stream size.
+ stream = malloc( *streamSize );
+ if( stream == NULL )
+ {
+ printf( "Error allocating stream.\n" );
+ return 1;
+ }
+ // Start the 'mobile' pointer at the beginning of the stream.
+ streamPtr = stream;
+
+ // wkb streams start with the byte order that the values were encoded in.
+ byteOrder = getByteOrder();
+ // Copy into the stream and move the pointer up.
+ memcpy( streamPtr, &byteOrder, sizeof( uint8_t ));
+ streamPtr += sizeof( uint8_t );
+
+ // Start the geometry collection traversal.
+ current = geometryCollection;
+ while ( current != NULL )
+ {
+ // Extract the geometry stucture from the current collection.
+ geometry = current->geometry;
+ // Create a temporary variable to hold the geoType to make it easier
+ // to copy the data into the wkb stream.
+ tempType = current->geoType;
+ switch ( tempType )
+ {
+ // Copy the type data into the stream.
+ // Use temporary variables to hold any data to be encoded to make
+ // it easier to copy the data into the wkb stream.
+ case wkbGeometryCollection:
+ tempNum = current->numGeometries;
+ memcpy( streamPtr, &tempType, sizeof( uint8_t ));
+ streamPtr += sizeof( uint8_t );
+ memcpy( streamPtr, &tempNum, sizeof( uint32_t ));
+ streamPtr += sizeof( uint32_t );
+ break;
+
+ case wkbPoint:
+ // If the geometry stucture is null, then it's an empty point.
+ if( geometry != NULL )
+ {
+ memcpy( streamPtr, &tempType, sizeof( uint8_t ));
+ streamPtr += sizeof( uint8_t );
+ x = geometry->point.x;
+ y = geometry->point.y;
+ memcpy( streamPtr, &x, sizeof( uint32_t ));
+ streamPtr += sizeof( uint32_t );
+ memcpy( streamPtr, &y, sizeof( uint32_t ));
+ streamPtr += sizeof( uint32_t );
+ }
+ else
+ {
+ tempType = wkbEmptyPoint;
+ memcpy( streamPtr, &tempType, sizeof( uint8_t ));
+ streamPtr += sizeof( uint8_t );
+ }
+ break;
+
+ case wkbLineString:
+ case wkbMultiPoint:
+ // Line strings and multi points use the same basic structure
+ // so can be encoded to wkb in the same way.
+ memcpy( streamPtr, &tempType, sizeof( uint8_t ));
+ streamPtr += sizeof( uint8_t );
+ linearRing = &geometry->linearRing;
+ tempNum = linearRing->numPoints;
+ memcpy( streamPtr, &tempNum, sizeof( uint32_t ));
+ streamPtr += sizeof( uint32_t );
+ // Continue through every point in the line.
+ line = linearRing->pointList;
+ while( line != NULL )
+ {
+ x = line->point.x;
+ y = line->point.y;
+ memcpy( streamPtr, &x, sizeof( uint32_t ));
+ streamPtr += sizeof( uint32_t );
+ memcpy( streamPtr, &y, sizeof( uint32_t ));
+ streamPtr += sizeof( uint32_t );
+ line = line->next;
+ }
+ break;
+
+ case wkbPolygon:
+ case wkbMultiLineString:
+ // Polygons and multi line strings use the same basic structure
+ // so can be encoded to wkb in the same way.
+ memcpy( streamPtr, &tempType, sizeof( uint8_t ));
+ streamPtr += sizeof( uint8_t );
+ polygon = &geometry->polygon;
+ tempNum = polygon->numLines;
+ memcpy( streamPtr, &tempNum, sizeof( uint32_t ));
+ streamPtr += sizeof( uint32_t );
+ // Continue through every ring in the polygon/line string.
+ linearRing = polygon->linearRing;
+ while( linearRing != NULL )
+ {
+ tempNum = linearRing->numPoints;
+ memcpy( streamPtr, &tempNum, sizeof( uint32_t ));
+ streamPtr += sizeof( uint32_t );
+ // Continue through every point in the line.
+ line = linearRing->pointList;
+ while( line != NULL )
+ {
+ x = line->point.x;
+ y = line->point.y;
+ memcpy( streamPtr, &x, sizeof( uint32_t ));
+ streamPtr += sizeof( uint32_t );
+ memcpy( streamPtr, &y, sizeof( uint32_t ));
+ streamPtr += sizeof( uint32_t );
+ line = line->next;
+ }
+ linearRing = linearRing->next;
+ }
+ break;
+
+ case wkbMultiPolygon:
+ memcpy( streamPtr, &tempType, sizeof( uint8_t ));
+ streamPtr += sizeof( uint8_t );
+ multiPolygon = &geometry->multiPolygon;
+ tempNum = multiPolygon->numPolygons;
+ memcpy( streamPtr, &tempNum, sizeof( uint32_t ));
+ streamPtr += sizeof( uint32_t );
+ // Continue through every polygon in the multi polygon.
+ polygon = multiPolygon->polygon;
+ while( polygon != NULL )
+ {
+ tempNum = polygon->numLines;
+ memcpy( streamPtr, &tempNum, sizeof( uint32_t ));
+ streamPtr += sizeof( uint32_t );
+ // Continue through every ring in the polygon
+ linearRing = polygon->linearRing;
+ while( linearRing != NULL )
+ {
+ tempNum = linearRing->numPoints;
+ memcpy( streamPtr, &tempNum, sizeof( uint32_t ));
+ streamPtr += sizeof( uint32_t );
+ // Continue through every point in the line
+ line = linearRing->pointList;
+ while( line != NULL )
+ {
+ x = line->point.x;
+ y = line->point.y;
+ memcpy( streamPtr, &x, sizeof( uint32_t ));
+ streamPtr += sizeof( uint32_t );
+ memcpy( streamPtr, &y, sizeof( uint32_t ));
+ streamPtr += sizeof( uint32_t );
+ line = line->next;
+ }
+ linearRing = linearRing->next;
+ }
+ polygon = polygon->next;
+ }
+ break;
+
+ default:
+ break;
+ }
+ current=current->next;
+ }
+ return 0;
+}
+
+/*****************************************************************************
+ * Free allocated memory for the points in a line structure
+ ****************************************************************************/
+static void freeLinePoints( wkbPointListT *line )
+{
+ wkbPointListT *next;
+ wkbPointListT *current;
+
current = line;
while( current != NULL )
{
@@ -35,7 +224,10 @@
}
}
-void freeLine( wkbLinearRingT *line )
+/*****************************************************************************
+ * Free allocated memory for the line structure
+ ****************************************************************************/
+static void freeLine( wkbLinearRingT *line )
{
wkbLinearRingT *next;
wkbLinearRingT *current;
@@ -45,13 +237,16 @@
while( current != NULL )
{
next = current->next;
- freeLinePoints( current->line );
+ freeLinePoints( current->pointList );
free( current );
current = next;
}
}
-void freePolygon( wkbPolygonT *polygon )
+/*****************************************************************************
+ * Free allocated memory for the polygon structure
+ ****************************************************************************/
+static void freePolygon( wkbPolygonT *polygon )
{
wkbPolygonT *next;
wkbPolygonT *current;
@@ -67,7 +262,10 @@
}
}
-void freeMultiPolygon( wkbMultiPolygonT *multiPolygon )
+/*****************************************************************************
+ * Free allocated memory for the multi polygon structure
+ ****************************************************************************/
+static void freeMultiPolygon( wkbMultiPolygonT *multiPolygon )
{
wkbMultiPolygonT *next;
wkbMultiPolygonT *current;
@@ -83,7 +281,11 @@
}
}
-void traverseGeoFree( wkbGeometryCollectionT *geometryCollection )
+/*****************************************************************************
+ * Traverse the geometry collection and free all allocated memory for each
+ * geometry in the collection.
+ ****************************************************************************/
+static void traverseGeoFree( wkbGeometryCollectionT *geometryCollection )
{
wkbGeometryCollectionT *next;
wkbGeometryCollectionT *current;
@@ -99,16 +301,22 @@
switch ( current->geoType )
{
case wkbPoint:
+ // Point geometries have no other memory except the
+ // geometry stucture itself.
free( geometry );
break;
case wkbLineString:
case wkbMultiPoint:
+ // Line strings and multi points use the same basic
+ // structure so can be encoded to wkb in the same way.
freeLine( &geometry->linearRing );
break;
case wkbPolygon:
case wkbMultiLineString:
+ // Polygons and multi line strings use the same basic
+ // structure so can be encoded to wkb in the same way.
freePolygon( &geometry->polygon );
break;
@@ -128,7 +336,10 @@
}
}
-void printTabs( int tabs )
+/*****************************************************************************
+ * Print a given number of tabs to align a geometry collection debug output.
+ ****************************************************************************/
+static void printTabs( int tabs )
{
int pTabs;
for( pTabs = 0; pTabs < tabs; ++pTabs )
@@ -137,7 +348,10 @@
}
}
-void displayPoint( wkbPointT *point, int tabs )
+/*****************************************************************************
+ * Print out the given point data.
+ ****************************************************************************/
+static void displayPoint( wkbPointT *point, int tabs )
{
printTabs( tabs );
if( point == NULL )
@@ -150,9 +364,12 @@
}
}
-void displayLinePoints( wkbLineT *line, int tabs )
+/*****************************************************************************
+ * Traverse a point list and display each point.
+ ****************************************************************************/
+static void displayPointList( wkbPointListT *line, int tabs )
{
- wkbLineT *current;
+ wkbPointListT *current;
current = line;
@@ -163,7 +380,10 @@
}
}
-void printRingHeader( wkbGeometryTypeT type, int numPoints )
+/*****************************************************************************
+ * Print header for a ring. Detects if this is a multi point or line string.
+ ****************************************************************************/
+static void printRingHeader( wkbGeometryTypeT type, int numPoints )
{
if( type == wkbLineString )
{
@@ -181,6 +401,9 @@
printf( "(%d):\n", numPoints );
}
+/*****************************************************************************
+ * Traverse line or multi point and display each point list data.
+ ****************************************************************************/
void displayRing( wkbLinearRingT *ring, int tabs, wkbGeometryTypeT type )
{
wkbLinearRingT *current;
@@ -189,7 +412,9 @@
while( current != NULL )
{
- if(( current->line == NULL ) && ( current->numPoints == 0 ))
+ // If the current line is null and there are no points in the line
+ // then it's an empty line.
+ if(( current->pointList == NULL ) && ( current->numPoints == 0 ))
{
printTabs( tabs );
printf( "EMPTY " );
@@ -202,12 +427,16 @@
printTabs( tabs );
printRingHeader( type, current->numPoints );
}
- displayLinePoints( current->line, (tabs + 1) );
+ displayPointList( current->pointList, (tabs + 1) );
}
current = current->next;
}
}
+/*****************************************************************************
+ * Print header for a polygon. Detects if this is a polygon or multi line
+ * string.
+ ****************************************************************************/
void printPolygonHeader( wkbGeometryTypeT type, int numLines )
{
if( type == wkbPolygon )
@@ -226,6 +455,9 @@
printf( "(%d):\n", numLines );
}
+/*****************************************************************************
+ * Traverse the polygon or multi line string and display each ring/line's data.
+ ****************************************************************************/
void displayPolygon( wkbPolygonT *polygon, int tabs, wkbGeometryTypeT type )
{
wkbPolygonT *current;
@@ -234,6 +466,8 @@
while( current != NULL )
{
+ // If the current ring/line is null and there are no lines in the
+ // polygon/multi line string then it's empty.
if(( current->linearRing ) == NULL && ( current->numLines == 0 ))
{
printTabs( tabs );
@@ -253,6 +487,9 @@
}
}
+/*****************************************************************************
+ * Traverse a multipolygon and display each polygon's data.
+ ****************************************************************************/
void displayMultiPolygon( wkbMultiPolygonT *multiPolygon, int tabs )
{
wkbMultiPolygonT *current;
@@ -261,6 +498,8 @@
while( current != NULL )
{
+ // If the current polygon is null and there are no polygons in the
+ // multi polygon then it's empty.
if(( current->polygon == NULL ) && ( current->numPolygons == 0 ))
{
printTabs( tabs );
@@ -279,6 +518,9 @@
}
}
+/*****************************************************************************
+ * Traverse the geometry collection and display the appropriate data.
+ ****************************************************************************/
void wkbTraverseGeoDisplay( wkbGeometryCollectionT *geometryCollection )
{
wkbGeometryCollectionT *current;
@@ -294,6 +536,8 @@
{
case wkbGeometryCollection:
printTabs( tabs );
+ // If the geometry is null and there are no geometries in the
+ // geometry collection then it's empty.
if(( geometry == NULL ) && ( current->numGeometries == 0 ))
{
printf( "EMPTY " );
@@ -335,51 +579,93 @@
}
}
-int wkbParseFile( FILE* fp )
+/*****************************************************************************
+ * Given a file pointer, attempt to convert the contents from well known text
+ * to a well known binary stream.
+ ****************************************************************************/
+int wkbParseFile( FILE* fp, char *wkbStream, size_t *streamSize )
{
+ extern int yyparse( void*, void*, size_t* );
yyscan_t scanner;
wkbGeometryCollectionT *geoCollection;
+ // Allocate the start of the geometry collection.
geoCollection = malloc( sizeof( wkbGeometryCollectionT ));
if( geoCollection == NULL )
{
printf( "Could not allocate geometry collection.\n" );
+ return 1;
}
geoCollection->numGeometries = 0;
geoCollection->geoType = wkbTypeInvalid;
- yylex_init( &scanner );
+ if( yylex_init( &scanner ) != 0 )
+ {
+ printf( "Could not initialize scanner.\n" );
+ return 10;
+ }
+
yyset_in( fp, scanner );
yyrestart( fp, scanner );
- yyparse( scanner, (void *)geoCollection );
+ // Parse the well known text into a linked list containing all the
+ // geometry collection data.
+ if( yyparse( scanner, (void *)geoCollection, streamSize ) != 0 )
+ {
+ printf( "Error parsing grammar.\n" );
+ return 20;
+ }
- yylex_destroy( scanner );
+ if( yylex_destroy( scanner ) != 0 )
+ {
+ printf( "Could not destroy scanner.\n" );
+ }
+ // Add a byte to the stream size to hold the byte order data.
+ *streamSize = *streamSize + ( sizeof( uint8_t ));
+
+ // Traverse the linked list and convert to a wkb stream.
+ if( createBinaryStream( geoCollection, streamSize, wkbStream ) != 0 )
+ {
+ printf( "Error creating binary stream.\n" );
+ return 2;
+ }
+
+ printf( "Geocollection size for wkb is %d.\n", *streamSize );
+ // Display the linked list for debugging.
wkbTraverseGeoDisplay( geoCollection );
+
+ // Clean up the memory allocated for the linked lists.
traverseGeoFree( geoCollection );
return 0;
}
-int wkbInsertGeo( void *geoColl, wkbGeometryTypeT geoType )
+/*****************************************************************************
+ * Insert a new geometry into the geometry collection. Add to the stream
+ * size as required.
+ ****************************************************************************/
+int wkbInsertGeo( void *geoColl, wkbGeometryTypeT geoType, size_t *streamSize )
{
wkbGeometryCollectionT *newGeo;
wkbGeometryCollectionT *current;
wkbGeometryCollectionT *head;
wkbGeometryCollectionT *currentChild;
+ // Can't add to a NULL collection.
if( geoColl == NULL )
{
printf( "Invalid pointer.\n" );
return 1;
}
+ // Assign pointers to the head and current position in geometry collection.
head = (wkbGeometryCollectionT *)geoColl;
current = head;
+ // Allocate a new geometry collection structure.
newGeo = malloc( sizeof( wkbGeometryCollectionT ));
if( newGeo == NULL )
{
@@ -387,6 +673,7 @@
return 1;
}
+ // Initialize the starting values.
newGeo->numGeometries = 0;
newGeo->geoType = geoType;
newGeo->geometry = NULL;
@@ -394,6 +681,10 @@
newGeo->parent = NULL;
newGeo->next = NULL;
+ // If the first item in the collection is still invalid it means it's just
+ // beginning. Since the first item is already allocated in wkbParseFile
+ // just copy the new data to the current head.
+ // Remember to free the new memory since it's no longer required.
if ( head->geoType == wkbTypeInvalid )
{
memcpy( head, newGeo, sizeof( wkbGeometryCollectionT ));
@@ -401,6 +692,8 @@
}
else
{
+ // This isn't the first addition, so move current to the end of the
+ // list.
while( current->next != NULL )
{
current = current->next;
@@ -409,8 +702,14 @@
current = current->next;
}
+ // In order to detect geometry collections contained in other geometry
+ // collection a child pointer is used. This will point from the parent
+ // collection to the head of the child collection.
if( head->child != NULL )
{
+ // Currently there is a child collection in process, traverse down
+ // each child to the end. Add one to the number of geometries in the
+ // latest child collection.
currentChild = head->child;
while( currentChild->child != NULL )
@@ -421,27 +720,43 @@
}
else
{
+ // Not currently processing a child collection, so add one to the
+ // number of geometries in the head collection.
head->numGeometries++;
currentChild = NULL;
}
+ // Only looking for geometry collection types for child/parent processing.
+ // All other types of geometries are handled in specific functions.
switch( geoType )
{
case wkbGeometryCollection:
+ // The new geometry is a geometry collection.
+ // Add a byte to the stream size for geo type.
+ *streamSize = *streamSize + ( sizeof( uint8_t ));
if( currentChild != NULL )
{
+ // If there is a child geometry collection already in progress
+ // then add the new collection as a child of the in progress
+ // collection.
current->parent = currentChild;
currentChild->child = current;
}
else
{
+ // No current child in progress.
if( head != current )
{
+ // This is not the first geometry collection, so it
+ // becomes the child of the head collection.
current->parent = head;
head->child = current;
}
else
{
+ // This is the first collection found. The number of
+ // geometries contained in this collection does not include
+ // itself.
head->numGeometries--;
}
}
@@ -450,12 +765,19 @@
case wkbGeometryCollectionEnd:
if( currentChild != NULL )
{
+ // Found the end of a child collection. The end tag is not a
+ // countable geometry, so subtract it. Make the parent of
+ // the finished collection the new current child in progress.
+ // Remove the finished collection from the parent's (now
+ // current) child pointer.
currentChild->numGeometries--;
currentChild = currentChild->parent;
currentChild->child = NULL;
}
else
{
+ // This terminates the head collection. The end tag is not a
+ // countable geometry, so subtract it.
head->numGeometries--;
}
break;
@@ -467,23 +789,26 @@
return 0;
}
-int wkbInsertMultiPolygon( void *geoColl )
+/*****************************************************************************
+ * Insert a multipolygon into the latest geometry in the collection. Add to
+ * the stream size as required.
+ ****************************************************************************/
+int wkbInsertMultiPolygon( void *geoColl, size_t *streamSize )
{
wkbGeometryCollectionT *currGeo;
- wkbGeometryCollectionT *headGeo;
- wkbMultiPolygonT *current;
- wkbMultiPolygonT *head;
wkbMultiPolygonT *newMultiPolygon;
wkbGeometryT *geometry;
- headGeo = (wkbGeometryCollectionT*)geoColl;
- currGeo = headGeo;
+ // Move the current collection pointer to the latest in the list.
+ currGeo = (wkbGeometryCollectionT*)geoColl;
while( currGeo->next != NULL )
{
currGeo = currGeo->next;
}
+ // If the latest is not a multi polygon, then this function is being
+ // called by mistake.
if( currGeo->geoType != wkbMultiPolygon )
{
printf( "%s: Improper insert call.\n", __FUNCTION__ );
@@ -492,62 +817,56 @@
if( currGeo->geometry == NULL )
{
+ // Allocate a new geometry structure.
geometry = malloc( sizeof( wkbGeometryT ));
if( geometry == NULL )
{
printf( "%s: Cannot allocate a new geometry.\n", __FUNCTION__ );
return 1;
}
+
+ // Initialize the data in the new multi polygon
newMultiPolygon = &geometry->multiPolygon;
newMultiPolygon->numPolygons = 0;
newMultiPolygon->polygon = NULL;
newMultiPolygon->next = NULL;
+ // Add a byte to the stream size for the geometry type
+ *streamSize = *streamSize + ( sizeof( uint8_t ));
+ // Add four bytes to the stream size for the number of polygons
+ // contained in this multipolygon.
+ *streamSize = *streamSize + ( sizeof( uint32_t ));
+
+ // Assign the new geometry to the current collection pointer.
currGeo->geometry = geometry;
- return 0;
}
else
{
- newMultiPolygon = malloc( sizeof( wkbMultiPolygonT ));
- if( newMultiPolygon == NULL )
- {
- printf( "Cannot allocate new multi polygon.\n" );
- return 1;
- }
-
- newMultiPolygon->numPolygons = 0;
- newMultiPolygon->polygon = NULL;
- newMultiPolygon->next = NULL;
-
- geometry = currGeo->geometry;
- head = &geometry->multiPolygon;
- current = head;
-
- while( current->next != NULL )
- {
- current = current->next;
- }
- current->next = newMultiPolygon;
+ // If the geometry is not null, then there's already a multi polygon
+ // here.
+ printf( "Error, a multi polygon cannot contain a multipolygon.\n" );
+ return 1;
}
return 0;
}
-int wkbInsertPolygon( void *geoColl )
+/*****************************************************************************
+ * Insert a polygon or multi line string into either the latest geometry in the
+ * collection or into the current multipolygon. Add to the stream size as
+ * required.
+ ****************************************************************************/
+int wkbInsertPolygon( void *geoColl, size_t *streamSize )
{
wkbGeometryCollectionT *currGeo;
- wkbGeometryCollectionT *headGeo;
- wkbPolygonT *head;
wkbPolygonT *current;
wkbPolygonT *newPolygon;
wkbGeometryT *geometry;
-
wkbMultiPolygonT *currMultiPoly;
- wkbMultiPolygonT *headMultiPoly;
- headGeo = (wkbGeometryCollectionT*)geoColl;
- currGeo = headGeo;
+ // Move the current collection pointer to the latest in the list.
+ currGeo = (wkbGeometryCollectionT*)geoColl;
while( currGeo->next != NULL )
{
@@ -556,23 +875,34 @@
if( currGeo->geometry == NULL )
{
+ // If the current geometry is null then it's a new polygon/multi
+ // line string geometry, allocate it.
geometry = malloc( sizeof( wkbGeometryT ));
if( geometry == NULL )
{
printf( "%s: Cannot allocate a new geometry.\n", __FUNCTION__ );
return 1;
}
+
+ // Initialize the new polygon/multi line string data.
newPolygon = &geometry->polygon;
newPolygon->numLines = 0;
newPolygon->linearRing = NULL;
newPolygon->next = NULL;
+ // Add a byte to the stream size for the geometry type
+ *streamSize = *streamSize + ( sizeof( uint8_t ));
+ // Add four bytes to the stream size for the number of lines
+ // contained in this polygon/multi line string.
+ *streamSize = *streamSize + ( sizeof( uint32_t ));
currGeo->geometry = geometry;
return 0;
}
else
{
+ // This is a member of a multi polygon. Allocate a new polygon
+ // structure.
newPolygon = malloc( sizeof( wkbPolygonT ));
if( newPolygon == NULL )
{
@@ -580,6 +910,7 @@
return 1;
}
+ // Initialize the new polygon data.
newPolygon->numLines = 0;
newPolygon->linearRing = NULL;
newPolygon->next = NULL;
@@ -587,57 +918,62 @@
geometry = currGeo->geometry;
switch( currGeo->geoType )
{
- case wkbPolygon:
- case wkbMultiLineString:
- head = &geometry->polygon;
- break;
-
case wkbMultiPolygon:
- headMultiPoly = &geometry->multiPolygon;
- currMultiPoly = headMultiPoly;
- while( currMultiPoly->next != NULL )
- {
- currMultiPoly = currMultiPoly->next;
- }
-
+ // Add one to the number of polygons in the multipolygon.
+ currMultiPoly = &geometry->multiPolygon;
currMultiPoly->numPolygons++;
if( currMultiPoly->polygon == NULL )
{
+ // This is the first polygon in the multipolygon. Add it
+ // as the first in the list.
newPolygon->numLines = 0;
currMultiPoly->polygon = newPolygon;
+ // Add four bytes to the stream size for the number
+ // of lines contained in the new polygon.
+ *streamSize = *streamSize + ( sizeof( uint32_t ));
+ // No further processing required, exit.
return 0;
}
- head = currMultiPoly->polygon;
+ current = currMultiPoly->polygon;
break;
default:
- printf( "%s: Unknown geometry type: %d\n",
+ printf( "%s: Incorrect geometry type: %d\n",
__FUNCTION__, currGeo->geoType );
return 1;
break;
}
- current = head;
+ // Move to the latest polygon in the multipolygon and add the new one
+ // to the end of the list.
while( current->next != NULL )
{
current = current->next;
}
current->next = newPolygon;
+ // Add four bytes to the stream size for the number of lines
+ // contained in this polygon.
+ *streamSize = *streamSize + ( sizeof( uint32_t ));
}
return 0;
}
-int wkbInsertLine( void *geoColl )
+/*****************************************************************************
+ * Insert a line or multi point into the latest geometry in the collection or
+ * to the current polygon/multi line string. Add to the stream size as
+ * required.
+ ****************************************************************************/
+int wkbInsertLine( void *geoColl, size_t *streamSize )
{
wkbGeometryCollectionT *currGeo;
wkbPolygonT *currPoly;
wkbMultiPolygonT *currMultiPoly;
wkbLinearRingT *current;
-
wkbLinearRingT *newRing;
wkbGeometryT *geometry;
+ // Move the current collection pointer to the latest in the list.
currGeo = (wkbGeometryCollectionT*)geoColl;
while( currGeo->next != NULL )
@@ -647,112 +983,131 @@
if( currGeo->geometry == NULL )
{
+ // If the current geometry is null then it's a new line/multi
+ // point geometry, allocate it.
geometry = malloc( sizeof( wkbGeometryT ));
if( geometry == NULL )
{
printf( "%s: Cannot allocate a new geometry.\n", __FUNCTION__ );
return 1;
}
+
+ // Initialize the new line/multi point data.
newRing = &geometry->linearRing;
newRing->numPoints = 0;
- newRing->line = NULL;
+ newRing->pointList = NULL;
newRing->next = NULL;
+ // Add a byte to the stream size for the geometry type
+ *streamSize = *streamSize + ( sizeof( uint8_t ));
+ // Add four bytes to the stream size for the number of points
+ // contained in this line/multi point.
+ *streamSize = *streamSize + ( sizeof( uint32_t ));
currGeo->geometry = geometry;
return 0;
}
else
{
+ // This new line is a member of a polygon. Allocate it.
newRing = malloc( sizeof( wkbLinearRingT ));
if( newRing == NULL )
{
printf( "Cannot allocate a new ring.\n" );
return 1;
}
+
+ // Initialize the new line data.
newRing->numPoints = 0;
- newRing->line = NULL;
+ newRing->pointList = NULL;
newRing->next = NULL;
geometry = currGeo->geometry;
switch( currGeo->geoType )
{
- case wkbLineString:
- case wkbMultiPoint:
- current = &geometry->linearRing;
- break;
-
case wkbPolygon:
case wkbMultiLineString:
+ // Add one to the number of lines.
currPoly = &geometry->polygon;
- while( currPoly->next != NULL )
- {
- currPoly = currPoly->next;
- }
-
currPoly->numLines++;
if( currPoly->linearRing == NULL )
{
+ // This is the first line, add it at the start of the list.
newRing->numPoints = 0;
currPoly->linearRing = newRing;
+ // Add four bytes to the stream size for the number of
+ // points contained in this line.
+ *streamSize = *streamSize + ( sizeof( uint32_t ));
+ // No further processing required, exit.
return 0;
}
current = currPoly->linearRing;
break;
case wkbMultiPolygon:
+ // It's a multipolygon, so move to the last polygon in the
+ // multipolygon.
currMultiPoly = &geometry->multiPolygon;
- while( currMultiPoly->next != NULL )
- {
- currMultiPoly = currMultiPoly->next;
- }
currPoly = currMultiPoly->polygon;
while( currPoly->next != NULL )
{
currPoly = currPoly->next;
}
+ // Add one to the number of lines.
currPoly->numLines++;
if( currPoly->linearRing == NULL )
{
+ // This is the first line, add it at the start of the list.
newRing->numPoints = 0;
currPoly->linearRing = newRing;
+ // Add four bytes to the stream size for the number of
+ // points contained in this line.
+ *streamSize = *streamSize + ( sizeof( uint32_t ));
+ // No further processing required, exit.
return 0;
}
current = currPoly->linearRing;
break;
default:
- printf( "%s: Unknown geometry type: %d\n",
+ printf( "%s: Incorrect geometry type: %d\n",
__FUNCTION__, currGeo->geoType );
return 1;
break;
}
+ // Move to the last line in the polygon and add the new line to the
+ // end of the list.
while( current->next != NULL )
{
current = current->next;
}
current->next = newRing;
+ // Add four bytes to the stream size for the number of points
+ // contained in this line.
+ *streamSize = *streamSize + ( sizeof( uint32_t ));
}
return 0;
}
-int wkbInsertPoint( void *geoColl, wkbPointT point )
+/*****************************************************************************
+ * Insert a point into the latest geometry in the collection or to the current
+ * line. Add to the stream size as required.
+ ****************************************************************************/
+int wkbInsertPoint( void *geoColl, wkbPointT *point, size_t *streamSize )
{
wkbGeometryCollectionT *currGeo;
wkbMultiPolygonT *currMultiPoly;
wkbPolygonT *currPoly;
wkbLinearRingT *currRing;
- wkbLinearRingT *headRing;
- wkbLineT *head;
- wkbLineT *current;
-
+ wkbPointListT *current;
wkbGeometryT *geometry;
wkbPointT *newPoint;
- wkbLineT *newLine;
+ wkbPointListT *newPointList;
+ // Move the current collection pointer to the latest in the list.
currGeo = (wkbGeometryCollectionT*)geoColl;
while( currGeo->next != NULL )
@@ -762,56 +1117,73 @@
if( currGeo->geometry == NULL )
{
- geometry = malloc( sizeof( wkbGeometryT ));
- if( geometry == NULL )
+ // Add one byte to the stream size for the geo type.
+ *streamSize = *streamSize + ( sizeof( uint8_t ));
+
+ // If the point is not null, initialize the new point with
+ // the data provided. If it is null, leave the geometry as null to
+ // indicate an empty point.
+ if( point != NULL )
{
- printf( "%s: Cannot allocate a new geometry.\n", __FUNCTION__ );
- return 1;
+ // If the current geometry is null then it's a new point geometry.
+ // Allocate it.
+ geometry = malloc( sizeof( wkbGeometryT ));
+ if( geometry == NULL )
+ {
+ printf( "%s: Cannot allocate a new geometry.\n", __FUNCTION__ );
+ return 1;
+ }
+ newPoint = &geometry->point;
+
+ newPoint->x = point->x;
+ newPoint->y = point->y;
+ // Add 8 bytes to the stream size, for both x and y data.
+ *streamSize = *streamSize + ( sizeof( uint32_t ) * 2 );
+ currGeo->geometry = geometry;
}
-
- newPoint = &geometry->point;
-
- newPoint->x = point.x;
- newPoint->y = point.y;
-
- currGeo->geometry = geometry;
}
else
{
- newLine = malloc( sizeof( wkbLineT ));
- if( newLine == NULL )
+ // This is a member of a line, allocate a new point list stucture.
+ newPointList = malloc( sizeof( wkbPointListT ));
+ if( newPointList == NULL )
{
printf( "Cannot allocate new line.\n" );
return 1;
}
- newLine->point.x = point.x;
- newLine->point.y = point.y;
+ if( point != NULL )
+ {
+ // Initialize the new point list point data with the given data.
+ newPointList->point.x = point->x;
+ newPointList->point.y = point->y;
+ }
+ else
+ {
+ printf( "Points in lines cannot be empty.\n" );
+ return 1;
+ }
geometry = currGeo->geometry;
switch( currGeo->geoType )
{
case wkbLineString:
case wkbMultiPoint:
+ // Set the start point.
currRing = &geometry->linearRing;
break;
case wkbPolygon:
case wkbMultiLineString:
+ // Set the start point from the polygon.
currPoly = &geometry->polygon;
- while( currPoly->next != NULL )
- {
- currPoly = currPoly->next;
- }
currRing = currPoly->linearRing;
break;
case wkbMultiPolygon:
+ // Move to the latest polygon in the multi polygon and set
+ // the start point.
currMultiPoly = &geometry->multiPolygon;
- while( currMultiPoly->next != NULL )
- {
- currMultiPoly = currMultiPoly->next;
- }
currPoly = currMultiPoly->polygon;
while( currPoly->next != NULL )
{
@@ -821,31 +1193,38 @@
break;
default:
- printf( "%s: Unknown geometry type: %d\n",
+ printf( "%s: Incorrect geometry type: %d\n",
__FUNCTION__, currGeo->geoType );
return 1;
break;
}
+ // From the start point set above, move to the last line.
while( currRing->next != NULL )
{
currRing = currRing->next;
}
- if( currRing->line != NULL )
+ if( currRing->pointList != NULL )
{
- current = currRing->line;
+ // This is not the first point, so move to the last point in the
+ // line and add the new one to the end of the list.
+ current = currRing->pointList;
while( current->next != NULL )
{
current = current->next;
}
- current->next = newLine;
+ current->next = newPointList;
}
else
{
- currRing->line = newLine;
+ // If the point list is null, it's the first point in the line.
+ currRing->pointList = newPointList;
}
+ // Add one to the number of points in the line.
currRing->numPoints++;
+ // Add 8 bytes to the stream size, for both x and y data.
+ *streamSize = *streamSize + ( sizeof( uint32_t ) * 2 );
}
return 0;
}
Modified: branches/geospatial/wkt-wkb/wkbOps.h
===================================================================
--- branches/geospatial/wkt-wkb/wkbOps.h 2008-07-18 15:06:25 UTC (rev 166)
+++ branches/geospatial/wkt-wkb/wkbOps.h 2008-07-18 21:18:38 UTC (rev 167)
@@ -3,8 +3,42 @@
#include "wkbTypes.h"
-wkbByteOrderT gByteOrder;
+/*****************************************************************************
+ * Given a file pointer, attempt to convert the contents from well known text
+ * to a well known binary stream.
+ ****************************************************************************/
+int wkbParseFile( FILE* fp, char *wkbStream, size_t *streamSize );
-int wkbParseFile( FILE* fp );
+/*****************************************************************************
+ * Insert a new geometry into the geometry collection. Add to the stream
+ * size as required.
+ ****************************************************************************/
+int wkbInsertGeo( void *geoColl, wkbGeometryTypeT geoType, size_t *streamSize );
+/*****************************************************************************
+ * Insert a multipolygon into the latest geometry in the collection. Add to
+ * the stream size as required.
+ ****************************************************************************/
+int wkbInsertMultiPolygon( void *geoColl, size_t *streamSize );
+
+/*****************************************************************************
+ * Insert a polygon or multi line string into either the latest geometry in the
+ * collection or into the current multipolygon. Add to the stream size as
+ * required.
+ ****************************************************************************/
+int wkbInsertPolygon( void *geoColl, size_t *streamSize );
+
+/*****************************************************************************
+ * Insert a line or multi point into the latest geometry in the collection or
+ * to the current polygon/multi line string. Add to the stream size as
+ * required.
+ ****************************************************************************/
+int wkbInsertLine( void *geoColl, size_t *streamSize );
+
+/*****************************************************************************
+ * Insert a point into the latest geometry in the collection or to the current
+ * line. Add to the stream size as required.
+ ****************************************************************************/
+int wkbInsertPoint( void *geoColl, wkbPointT *point, size_t *streamSize );
+
#endif // ifndef WKBOPS_H
Modified: branches/geospatial/wkt-wkb/wkbTypes.h
===================================================================
--- branches/geospatial/wkt-wkb/wkbTypes.h 2008-07-18 15:06:25 UTC (rev 166)
+++ branches/geospatial/wkt-wkb/wkbTypes.h 2008-07-18 21:18:38 UTC (rev 167)
@@ -3,22 +3,43 @@
#include <stdint.h>
+typedef enum
+{
+ wkbXDR = 0, // Big Endian
+ wkbNDR = 1 // Little Endian
+} wkbByteOrderT;
+
+typedef enum
+{
+ wkbTypeInvalid = 0,
+ wkbPoint = 1,
+ wkbLineString = 2,
+ wkbPolygon = 3,
+ wkbMultiPoint = 4,
+ wkbMultiLineString = 5,
+ wkbMultiPolygon = 6,
+ wkbGeometryCollection = 7,
+ wkbGeometryCollectionEnd = 8,
+ wkbEmptyPoint = 9,
+ wkbTypeMax = 10
+} wkbGeometryTypeT;
+
typedef struct Point
{
double x;
double y;
} wkbPointT;
-typedef struct Line
+typedef struct PointList
{
wkbPointT point;
- struct Line *next;
-} wkbLineT;
+ struct PointList *next;
+} wkbPointListT;
typedef struct LinearRing
{
uint32_t numPoints;
- wkbLineT *line;
+ wkbPointListT *pointList;
struct LinearRing *next;
} wkbLinearRingT;
@@ -47,29 +68,6 @@
wkbMultiPolygonT multiPolygon;
} wkbGeometryT;
-typedef enum
-{
- wkbTypeInvalid = 0,
- wkbPoint = 1,
- wkbLineString = 2,
- wkbPolygon = 3,
- wkbMultiPoint = 4,
- wkbMultiLineString = 5,
- wkbMultiPolygon = 6,
- wkbGeometryCollection = 7,
- wkbLineStringEnd = 8,
- wkbPolygonEnd = 9,
- wkbMultiPolygonEnd = 10,
- wkbGeometryCollectionEnd = 11,
- wkbTypeMax = 12
-} wkbGeometryTypeT;
-
-typedef enum
-{
- wkbXDR = 0, // Big Endian
- wkbNDR = 1 // Little Endian
-} wkbByteOrderT;
-
typedef struct GeometryCollection
{
uint32_t numGeometries;
Modified: branches/geospatial/wkt-wkb/wktToWkb.y
===================================================================
--- branches/geospatial/wkt-wkb/wktToWkb.y 2008-07-18 15:06:25 UTC (rev 166)
+++ branches/geospatial/wkt-wkb/wktToWkb.y 2008-07-18 21:18:38 UTC (rev 167)
@@ -1,8 +1,10 @@
+/* TODO: Error checking on insert calls. */
%pure_parser
-%parse-param { void* scanner }
-%lex-param { void* scanner }
-%parse-param { void* geoColl }
+%parse-param { void *scanner }
+%lex-param { void *scanner }
+%parse-param { void *geoColl }
+%parse-param { size_t *streamSize }
%{
#include <unistd.h>
@@ -51,37 +53,37 @@
pointTaggedText :
{
- wkbInsertGeo( geoColl, wkbPoint );
+ wkbInsertGeo( geoColl, wkbPoint, streamSize );
}
POINT pointText
lineStringTaggedText :
{
- wkbInsertGeo( geoColl, wkbLineString );
+ wkbInsertGeo( geoColl, wkbLineString, streamSize );
}
LINESTRING lineStringText
polygonTaggedText :
{
- wkbInsertGeo( geoColl, wkbPolygon );
+ wkbInsertGeo( geoColl, wkbPolygon, streamSize );
}
POLYGON polygonText
multiPointTaggedText :
{
- wkbInsertGeo( geoColl, wkbMultiPoint );
+ wkbInsertGeo( geoColl, wkbMultiPoint, streamSize );
}
MULTIPOINT multiPointText
multiLineStringTaggedText :
{
- wkbInsertGeo( geoColl, wkbMultiLineString );
+ wkbInsertGeo( geoColl, wkbMultiLineString, streamSize );
}
MULTILINESTRING multiLineStringText
multiPolygonTaggedText :
{
- wkbInsertGeo( geoColl, wkbMultiPolygon );
+ wkbInsertGeo( geoColl, wkbMultiPolygon, streamSize );
}
MULTIPOLYGON multiPolygonText
@@ -90,6 +92,9 @@
pointText :
empty
+ {
+ wkbInsertPoint( geoColl, NULL, streamSize );
+ }
|
LPAR point RPAR
@@ -102,17 +107,17 @@
wkbPointT point;
point.x = $1;
point.y = $2;
- wkbInsertPoint( geoColl, point );
+ wkbInsertPoint( geoColl, &point, streamSize );
}
lineStringText :
empty
{
- wkbInsertLine( geoColl );
+ wkbInsertLine( geoColl, streamSize );
}
|
{
- wkbInsertLine( geoColl );
+ wkbInsertLine( geoColl, streamSize );
}
LPAR lineString RPAR
@@ -124,11 +129,11 @@
polygonText :
empty
{
- wkbInsertPolygon( geoColl );
+ wkbInsertPolygon( geoColl, streamSize );
}
|
{
- wkbInsertPolygon( geoColl );
+ wkbInsertPolygon( geoColl, streamSize );
}
LPAR polygon RPAR
@@ -140,11 +145,11 @@
multiPointText :
empty
{
- wkbInsertLine( geoColl );
+ wkbInsertLine( geoColl, streamSize );
}
|
{
- wkbInsertLine( geoColl );
+ wkbInsertLine( geoColl, streamSize );
}
LPAR multiPoint RPAR
@@ -156,11 +161,11 @@
multiLineStringText :
empty
{
- wkbInsertPolygon( geoColl );
+ wkbInsertPolygon( geoColl, streamSize );
}
|
{
- wkbInsertPolygon( geoColl );
+ wkbInsertPolygon( geoColl, streamSize );
}
LPAR multiLineString RPAR
@@ -172,11 +177,11 @@
multiPolygonText :
empty
{
- wkbInsertMultiPolygon( geoColl );
+ wkbInsertMultiPolygon( geoColl, streamSize );
}
|
{
- wkbInsertMultiPolygon( geoColl );
+ wkbInsertMultiPolygon( geoColl, streamSize );
}
LPAR multiPolygon RPAR
@@ -187,19 +192,19 @@
geometryCollectionText :
{
- wkbInsertGeo( geoColl, wkbGeometryCollection );
+ wkbInsertGeo( geoColl, wkbGeometryCollection, streamSize );
}
empty
{
- wkbInsertGeo( geoColl, wkbGeometryCollectionEnd );
+ wkbInsertGeo( geoColl, wkbGeometryCollectionEnd, streamSize );
}
|
{
- wkbInsertGeo( geoColl, wkbGeometryCollection );
+ wkbInsertGeo( geoColl, wkbGeometryCollection, streamSize );
}
LPAR geometry RPAR
{
- wkbInsertGeo( geoColl, wkbGeometryCollectionEnd );
+ wkbInsertGeo( geoColl, wkbGeometryCollectionEnd, streamSize );
}
geometry :
@@ -211,10 +216,12 @@
EMPTY
%%
#include "wktToWkb.Flex.h"
-yyerror( void *scanner, void* geoColl, char* msg )
+int yyerror( void *scanner, void* geoColl, size_t *streamSize, char* msg )
{
yyscan_t *thisScanner;
thisScanner = (yyscan_t*)scanner;
printf("\n%s\n", msg);
+
+ return 0;
}
More information about the svn-commits
mailing list