[postgis-commits] svn - r3821 - in trunk: liblwgeom regress

postgis-commits at postgis.refractions.net postgis-commits at postgis.refractions.net
Mon Mar 9 17:29:34 PDT 2009


Author: mleslie
Date: 2009-03-09 17:29:32 -0700 (Mon, 09 Mar 2009)
New Revision: 3821

Modified:
   trunk/liblwgeom/lex.yy.c
   trunk/liblwgeom/liblwgeom.h
   trunk/liblwgeom/lwcurvepoly.c
   trunk/liblwgeom/lwgparse.c
   trunk/liblwgeom/lwgunparse.c
   trunk/liblwgeom/lwmcurve.c
   trunk/liblwgeom/wktparse.h
   trunk/liblwgeom/wktparse.tab.c
   trunk/liblwgeom/wktparse.y
   trunk/regress/sql-mm-compoundcurve.sql
   trunk/regress/sql-mm-compoundcurve_expected.in
   trunk/regress/sql-mm-curvepoly.sql
   trunk/regress/sql-mm-curvepoly_expected.in
   trunk/regress/sql-mm-serialize.sql
Log:
Moving parser changes from spike/mleslie/parser to allow the proper nesting of compound curves within curve polygons and the validation of compound curve continuity.  This also resolves GBT#124.

Modified: trunk/liblwgeom/lex.yy.c
===================================================================
--- trunk/liblwgeom/lex.yy.c	2009-03-09 22:01:04 UTC (rev 3820)
+++ trunk/liblwgeom/lex.yy.c	2009-03-10 00:29:32 UTC (rev 3821)
@@ -3448,7 +3448,8 @@
 
 /* Amount of stuff to slurp up with each read. */
 #ifndef YY_READ_BUF_SIZE
-#define YY_READ_BUF_SIZE 8192
+/* On IA-64, the buffer size is 16k, not 8k */
+#define YY_READ_BUF_SIZE 16384
 #endif
 
 /* Copy whatever the last rule matched to the standard output. */
@@ -3536,7 +3537,7 @@
 #line 30 "wktparse.lex"
 
 
-#line 3540 "lex.yy.c"
+#line 3541 "lex.yy.c"
 
 	if ( !(yy_init) )
 		{
@@ -3798,7 +3799,7 @@
 #line 73 "wktparse.lex"
 ECHO;
 	YY_BREAK
-#line 3802 "lex.yy.c"
+#line 3803 "lex.yy.c"
 case YY_STATE_EOF(INITIAL):
 case YY_STATE_EOF(vals_ok):
 	yyterminate();
@@ -4552,8 +4553,8 @@
 
 /** Setup the input buffer state to scan the given bytes. The next call to lwg_parse_yylex() will
  * scan from a @e copy of @a bytes.
- * @param bytes the byte buffer to scan
- * @param len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yybytes the byte buffer to scan
+ * @param _yybytes_len the number of bytes in the buffer pointed to by @a bytes.
  * 
  * @return the newly allocated buffer state object.
  */

Modified: trunk/liblwgeom/liblwgeom.h
===================================================================
--- trunk/liblwgeom/liblwgeom.h	2009-03-09 22:01:04 UTC (rev 3820)
+++ trunk/liblwgeom/liblwgeom.h	2009-03-10 00:29:32 UTC (rev 3821)
@@ -1341,6 +1341,7 @@
 #define PARSER_ERROR_MIXDIMS        4	
 #define PARSER_ERROR_INVALIDGEOM    5
 #define PARSER_ERROR_INVALIDWKBTYPE 6
+#define PARSER_ERROR_INCONTINUOUS	7
 
 
 /*

Modified: trunk/liblwgeom/lwcurvepoly.c
===================================================================
--- trunk/liblwgeom/lwcurvepoly.c	2009-03-09 22:01:04 UTC (rev 3820)
+++ trunk/liblwgeom/lwcurvepoly.c	2009-03-10 00:29:32 UTC (rev 3821)
@@ -54,9 +54,10 @@
         {
                 result->rings[i] = lwgeom_deserialize(insp->sub_geoms[i]);
                 if(lwgeom_getType(result->rings[i]->type) != CIRCSTRINGTYPE 
-                        && lwgeom_getType(result->rings[i]->type) != LINETYPE)
+                        && lwgeom_getType(result->rings[i]->type) != LINETYPE
+                        && lwgeom_getType(result->rings[i]->type) != COMPOUNDTYPE)
                 {
-                        lwerror("Only Circularstrings and Linestrings are currently supported as rings, not %s (%d)", lwgeom_typename(result->rings[i]->type), result->rings[i]->type);
+                        lwerror("Only Circular curves, Linestrings and Compound curves are supported as rings, not %s (%d)", lwgeom_typename(result->rings[i]->type), result->rings[i]->type);
                         lwfree(result);
                         lwfree(insp);
                         return NULL;

Modified: trunk/liblwgeom/lwgparse.c
===================================================================
--- trunk/liblwgeom/lwgparse.c	2009-03-09 22:01:04 UTC (rev 3820)
+++ trunk/liblwgeom/lwgparse.c	2009-03-10 00:29:32 UTC (rev 3821)
@@ -59,7 +59,9 @@
 			int	type;
 			int	num;
 			int	size_here;
+			int parse_location;
 		} nn;
+
 	} uu;
 	struct tag_tuple *next;
 };
@@ -106,15 +108,10 @@
 LWGEOM_PARSER_RESULT *current_lwg_parser_result;
 
 
-/* Parser state flags - these are set automatically by the parser */
-int minpoints;
-int checkclosed;
-
 /*
  * This indicates if the number of points in the geometry is required to
  * be odd (one) or even (zero, currently not enforced) or whatever (-one)
  */
-int isodd;
 double *first_point=NULL;
 double *last_point=NULL;
 
@@ -133,10 +130,22 @@
 	"geometry contains non-closed rings",
 	"can not mix dimensionality in a geometry",
 	"parse error - invalid geometry",
-	"invalid WKB type"
+	"invalid WKB type",
+	"incontinuous compound curve"
 };
 
 /* Macro to return the error message and the current position within WKT */ 
+#define LWGEOM_WKT_VALIDATION_ERROR(errcode, parse_location) \
+	do { \
+		if (!parser_ferror_occured) { \
+			parser_ferror_occured = -1 * errcode; \
+			current_lwg_parser_result->message = parser_error_messages[errcode]; \
+			current_lwg_parser_result->errlocation = parse_location; \
+		} \
+	} while (0);
+
+
+/* Macro to return the error message and the current position within WKT */ 
 #define LWGEOM_WKT_PARSER_ERROR(errcode) \
 	do { \
 		if (!parser_ferror_occured) { \
@@ -190,6 +199,9 @@
 void alloc_linestring_closed(void);
 void alloc_circularstring(void);
 void alloc_circularstring_closed(void);
+void alloc_compoundcurve(void);
+void alloc_compoundcurve_closed(void);
+void alloc_curvepolygon(void);
 void alloc_polygon(void);
 void alloc_multipoint(void);
 void alloc_multilinestring(void);
@@ -199,6 +211,25 @@
 void alloc_geomertycollection(void);
 void alloc_counter(void);
 void alloc_empty(void);
+void check_compoundcurve(void);
+void check_closed_compoundcurve(void);
+void check_linestring(void);
+void check_closed_linestring(void);
+void check_circularstring(void);
+void check_closed_circularstring(void);
+void check_polygon(void);
+void check_curvepolygon(void);
+void check_compoundcurve_continuity(void);
+void check_compoundcurve_closed(void);
+void check_linestring_closed(void);
+void check_circularstring_closed(void);
+void check_polygon_closed(void);
+void check_polygon_minpoints(void);
+void check_curvepolygon_minpoints(void);
+void check_compoundcurve_minpoints(void);
+void check_linestring_minpoints(void);
+void check_circularstring_minpoints(void);
+void check_circularstring_isodd(void);
 void make_serialized_lwgeom(LWGEOM_PARSER_RESULT *lwg_parser_result);
 uchar strhex_readbyte(const char *in);
 uchar read_wkb_byte(const char **in);
@@ -229,6 +260,11 @@
 	srid=(int)(d_srid+0.1);
 }
 
+/*
+ * Begin alloc / free functions
+ */
+
+
 tuple *
 alloc_tuple(output_func of,size_t size)
 {
@@ -262,6 +298,10 @@
 		the_geom.first = the_geom.last = ret;
 	}
 
+	LWDEBUGF(5, "alloc_tuple %p: parse_location = %d", 
+			ret, lwg_parse_yylloc.last_column);
+ 	ret->uu.nn.parse_location = lwg_parse_yylloc.last_column;
+
 	the_geom.alloc_size += size;
 	return ret;
 }
@@ -284,6 +324,81 @@
 }
 
 void
+alloc_lwgeom(int srid)
+{
+		LWDEBUGF(3, "alloc_lwgeom %d", srid);
+
+	the_geom.srid=srid;
+	the_geom.alloc_size=0;
+	the_geom.stack=NULL;
+	the_geom.ndims=0;
+	the_geom.hasZ=0;
+	the_geom.hasM=0;
+
+	/* Free if used already */
+	if ( the_geom.first ){
+		free_tuple(the_geom.first);
+		the_geom.first=the_geom.last=NULL;
+	}
+
+	if ( srid != -1 ){
+		the_geom.alloc_size+=4;
+	}
+
+	/* Setup up an empty tuple as the stack base */
+	the_geom.stack = alloc_tuple(empty_stack, 0);
+}
+
+void
+alloc_point_2d(double x,double y)
+{
+	tuple* p = alloc_tuple(write_point_2,the_geom.lwgi?8:16);
+	p->uu.points[0] = x;
+	p->uu.points[1] = y;
+
+	LWDEBUGF(3, "alloc_point_2d %f,%f", x, y);
+	LWDEBUGF(5, "  * %p", p);
+	
+	/* keep track of point */
+
+	inc_num();
+	check_dims(2);
+}
+
+void
+alloc_point_3d(double x,double y,double z)
+{
+	tuple* p = alloc_tuple(write_point_3,the_geom.lwgi?12:24);
+	p->uu.points[0] = x;
+	p->uu.points[1] = y;
+	p->uu.points[2] = z;
+
+		LWDEBUGF(3, "alloc_point_3d %f, %f, %f", x, y, z);
+	LWDEBUGF(5, "  * %p", p);
+
+	inc_num();
+	check_dims(3);
+}
+
+void
+alloc_point_4d(double x,double y,double z,double m)
+{
+	tuple* p = alloc_tuple(write_point_4,the_geom.lwgi?16:32);
+	p->uu.points[0] = x;
+	p->uu.points[1] = y;
+	p->uu.points[2] = z;
+	p->uu.points[3] = m;
+
+		LWDEBUGF(3, "alloc_point_4d %f, %f, %f, %f", x, y, z, m);
+		LWDEBUGF(5, "  * %p", p);
+
+	inc_num();
+	check_dims(4);
+}
+
+
+
+void
 inc_num(void)
 {
 	the_geom.stack->uu.nn.num++;
@@ -298,65 +413,498 @@
 	tuple*	p;
 	inc_num();
 
-        LWDEBUGF(2, "alloc_stack_tuple %d, %d", type, size);
+		LWDEBUGF(3, "alloc_stack_tuple: type = %d, size = %d", type, size);
 	
 	p = alloc_tuple(of,size);
 	p->uu.nn.stack_next = the_geom.stack;
 	p->uu.nn.type = type;
 	p->uu.nn.size_here = the_geom.alloc_size;
 	p->uu.nn.num = 0;
+
 	the_geom.stack = p;
+
+	LWDEBUGF(4, "alloc_stack_tuple complete: %p", the_geom.stack);
 }
 
+/*
+ * Begin Check functions
+ */
+
+void check_compoundcurve(void)
+{
+	check_compoundcurve_minpoints();
+	check_compoundcurve_continuity();
+}
+
+void check_closed_compoundcurve(void)
+{
+	check_compoundcurve_closed();
+	check_compoundcurve();
+}
+
+void check_linestring(void)
+{
+	check_linestring_minpoints();
+}
+
+void check_closed_linestring(void)
+{
+	check_linestring_closed();
+	check_linestring();
+}
+
+void check_circularstring(void)
+{
+	check_circularstring_minpoints();
+	check_circularstring_isodd();
+}
+
+void check_closed_circularstring(void)
+{
+	check_linestring_closed();
+	check_circularstring();
+}
+
+void check_polygon(void)
+{
+	check_polygon_minpoints();
+	check_polygon_closed();
+}
+
+void check_curvepolygon(void)
+{
+	check_curvepolygon_minpoints();
+}
+
 void
-pop(void)
+check_compoundcurve_continuity(void)
 {
-	the_geom.stack = the_geom.stack->uu.nn.stack_next;
+	tuple* tp = the_geom.stack->next; /* Current tuple on the stack. */
+	int i, j; /* Loop counters */
+	int num, mum= 0; /* sub-geom and point counts */
+	tuple *last=NULL, *first=NULL; /* point tuples */
+
+	LWDEBUG(3, "compound_continuity_check");
+	num = tp->uu.nn.num;
+	for(i = 0; i < num; i++)
+	{
+		tp = tp->next->next;
+		mum = tp->uu.nn.num;
+		LWDEBUGF(5, "sub-geom %d of %d (%d points) at %p", i, num, mum, tp);
+
+		first = tp->next;
+		LWDEBUGF(5, "First point identified: %p", first);
+		if(i > 0)
+		{
+			if(the_geom.ndims > 3)
+			{
+				LWDEBUGF(5, "comparing points (%f,%f,%f,%f), (%f,%f,%f,%f)", 
+						first->uu.points[0], first->uu.points[1],
+						first->uu.points[2], first->uu.points[3],
+						last->uu.points[0], last->uu.points[1],
+						last->uu.points[2], last->uu.points[3]);
+			}
+			else if(the_geom.ndims > 2)
+			{
+				LWDEBUGF(5, "comparing points (%f,%f,%f), (%f,%f,%f)", 
+						first->uu.points[0], first->uu.points[1],
+						first->uu.points[2], last->uu.points[0], 
+						last->uu.points[1], last->uu.points[2]);
+			}
+			else
+			{
+				LWDEBUGF(5, "comparing points (%f,%f), (%f,%f)", 
+						first->uu.points[0], first->uu.points[1],
+						last->uu.points[0], last->uu.points[1]);
+			}
+					
+			if(first->uu.points[0] != last->uu.points[0])
+			{
+				LWDEBUG(5, "x value mismatch");
+				LWGEOM_WKT_VALIDATION_ERROR(PARSER_ERROR_INCONTINUOUS,last->uu.nn.parse_location);
+			}
+			else if(first->uu.points[1] != last->uu.points[1])
+			{
+				LWDEBUG(5, "y value mismatch");
+				LWGEOM_WKT_VALIDATION_ERROR(PARSER_ERROR_INCONTINUOUS,last->uu.nn.parse_location);
+			}
+			else if(the_geom.ndims > 2 &&
+					first->uu.points[2] != last->uu.points[2])
+			{
+				LWDEBUG(5, "z/m value mismatch");
+				LWGEOM_WKT_VALIDATION_ERROR(PARSER_ERROR_INCONTINUOUS,last->uu.nn.parse_location);
+			}
+			else if(the_geom.ndims > 3 &&
+					first->uu.points[3] != last->uu.points[3])
+			{
+				LWDEBUG(5, "m value mismatch");
+				LWGEOM_WKT_VALIDATION_ERROR(PARSER_ERROR_INCONTINUOUS,last->uu.nn.parse_location);
+			}
+		}
+		for(j = 0; j < mum; j++)
+		{
+			tp = tp->next;
+		}
+		last = tp;
+		LWDEBUGF(5, "Last point identified: %p", last);
+	}
 }
 
+void check_circularstring_isodd(void)
+{
+	tuple *tp = the_geom.stack->next;
+	int i, num;
+	
+	LWDEBUG(3, "check_circularstring_isodd");
+	if(tp->uu.nn.num % 2 == 0)
+	{
+		num = tp->uu.nn.num;
+		LWDEBUGF(5, "Odd check failed: pointcount = %d", num);
+		for(i = 0; i < num; i++)
+		{
+			tp = tp->next;
+		}
+	   	LWGEOM_WKT_VALIDATION_ERROR(PARSER_ERROR_ODDPOINTS, tp->uu.nn.parse_location);
+	}
+}
+
+/*
+ * Determines if the compound curve is closed or not.  This is done by finding
+ * the first point tuple of the first sub-geometry then marching through the
+ * tuple list until the last point tuple of the last sub-geometry is found.
+ * The 2d values of these tuples are then compared.
+ */
 void
-popc(void)
+check_compoundcurve_closed(void)
 {
-	/* If the minimum point check has been enabled, perform it */
-	if (current_parser_check_flags & PARSER_CHECK_MINPOINTS) {
-		if ( the_geom.stack->uu.nn.num < minpoints){
-			LWGEOM_WKT_PARSER_ERROR(PARSER_ERROR_MOREPOINTS);
+	tuple *tp = the_geom.stack; /* Current tuple */
+	int i, j; /* Loop counters */
+	int num, mum; /* sub-unit counts */
+	tuple *first, *last; /* First and last tuple of the compount curve */
+
+	LWDEBUG(3, "check_compount_closed");
+	/* tuple counting subgeometries */
+	tp = tp->next;
+	num = tp->uu.nn.num;
+
+	LWDEBUGF(5, "Found %d subgeoms.", num);
+	
+	/* counting tuple -> subgeom tuple -> counting tuple -> first point*/
+	first = tp->next->next->next;
+	for(i = 0; i < num; i++)
+	{
+		/* Advance to the next subgeometry's counting tuple */
+		tp = tp->next->next;
+		mum = tp->uu.nn.num;
+
+		LWDEBUGF(5, "Subgeom %d at %p has %d points.", i, tp, mum);
+		for(j = 0; j < mum; j++)
+		{
+			tp = tp->next;
 		}
 	}
+	last = tp;
+	if(first->uu.points[0] != last->uu.points[0] ||
+			first->uu.points[1] != last->uu.points[1])
+	{
+		LWDEBUGF(4, "Unclosed geometry: (%f, %f) != (%f, %f)",
+				first->uu.points[0], first->uu.points[1],
+				last->uu.points[0], last->uu.points[1]);
+		LWDEBUGF(5, "First %p, last %p", first, last);
+		LWGEOM_WKT_VALIDATION_ERROR(PARSER_ERROR_UNCLOSED, last->uu.nn.parse_location);
+	}
+	else
+	{
+		LWDEBUG(5, "Compound Curve found closed.");
+	}
+}
 
-	/* If the odd number point check has been enabled, perform it */
-	if (current_parser_check_flags & PARSER_CHECK_ODD) {
-        	if(isodd != -1 && the_geom.stack->uu.nn.num % 2 != isodd) {
-                	LWGEOM_WKT_PARSER_ERROR(PARSER_ERROR_ODDPOINTS);
-        	}
+/*
+ * Determines if the current linestring is closed and raises an error if it 
+ * is not.
+ * This is done by walking through the tuple list and identifying the first
+ * and last point tuples, then comparing their 2d values.
+ */
+void
+check_linestring_closed(void)
+{
+	tuple *tp = the_geom.stack; /* Current tuple */
+	int i; /* Loop counter */
+	int num; /* point count */
+	tuple *first, *last; /* First and last tuple of the compount curve */
+
+	/* tuple counting points */
+	tp = tp->next;
+	if(tp->uu.nn.num > 0)
+	{
+		first = tp->next;
+		num = tp->uu.nn.num;
+		for(i = 0; i < num; i++)
+		{	
+			tp = tp->next;
+		}
+		last = tp;
+		if(first->uu.points[0] != last->uu.points[0] || 
+				first->uu.points[1] != last->uu.points[1])
+		{
+			LWDEBUGF(4, "Unclosed geometry: (%f, %f) != (%f, %f)",
+					first->uu.points[0], first->uu.points[1], 
+					last->uu.points[0], last->uu.points[1]);
+			LWDEBUGF(5, "First %p, last %p", first, last);
+			LWGEOM_WKT_VALIDATION_ERROR(PARSER_ERROR_UNCLOSED, last->uu.nn.parse_location);
+		}
+		else
+		{
+			LWDEBUG(5, "Geometry found closed.");
+		}
 	}
+}
 
-	/* If the polygon closure check has been enabled, perform it */
-	if (current_parser_check_flags & PARSER_CHECK_CLOSURE) {
-		if ( checkclosed && first_point && last_point) {
-			if ( memcmp(first_point, last_point,
-				sizeof(double)*the_geom.ndims) )
-			{
-				LWGEOM_WKT_PARSER_ERROR(PARSER_ERROR_UNCLOSED);
-			}
-		}	
+/* 
+ * Determines if all rings of the current polygon are closed.  This is done 
+ * by marching through the tuple list finding the first and last point tuples
+ * of each ring and comparing their 2d values.
+ */
+void
+check_polygon_closed(void)
+{
+	tuple *tp = the_geom.stack; /* Current tuple */
+	int i, j; /* Loop counters */
+	int num, mum; /* sub-unit counts */
+	tuple *first, *last; /* First and last tuple of the current ring. */
+
+	LWDEBUG(3, "check_polygon_closed");
+	/* tuple counting rings */
+	tp = tp->next;
+	num = tp->uu.nn.num;
+	for(i = 0; i < num; i++)
+	{
+		/* ring tuple counting points */
+		tp = tp->next;
+		mum = tp->uu.nn.num;
+		first = tp->next;
+		for(j = 0; j < mum; j++)
+		{
+			tp = tp->next;
+		}
+		last = tp;
+		if(first->uu.points[0] != last->uu.points[0] ||
+				first->uu.points[1] != last->uu.points[1])
+		{
+			LWDEBUGF(4, "Unclosed geometry: (%f, %f) != (%f, %f)",
+					first->uu.points[0], first->uu.points[1],
+					last->uu.points[0], last->uu.points[1]);
+			LWDEBUGF(5, "First %p, last %p", first, last);
+			LWGEOM_WKT_VALIDATION_ERROR(PARSER_ERROR_UNCLOSED, last->uu.nn.parse_location);
+		}
+		else 
+		{
+			LWDEBUGF(5, "Ring %d found closed.", i);
+		}
 	}
+}
 
-	the_geom.stack = the_geom.stack->uu.nn.stack_next;
+/*
+ * Checks to ensure that each ring of the current polygon contains the 
+ * given number of points.  The given number should be four, but 
+ * lets keep things generic here for now.
+ */
+void
+check_polygon_minpoints(void)
+{
+	tuple *tp = the_geom.stack->next; /* Current tuple */
+	int i, j; /* Loop counters */
+	int num, mum; /* ring / point count */
+	int minpoints = 4;
+
+	LWDEBUG(3, "check_polygon_minpoints");
+
+	num = tp->uu.nn.num;
+
+	/* Check each ring for minpoints */
+	for(i = 0; i < num; i++)
+	{
+		/* Step into the point counter tuple */
+		tp = tp->next;
+		mum = tp->uu.nn.num;
+
+		/* Skip the point tuples */
+		for(j = 0; j < mum; j++)
+		{
+			tp = tp->next;
+		}
+
+		if(mum < minpoints)
+		{
+			LWDEBUGF(5, "Minpoint check failed: needed %d, got %d",
+					minpoints, mum);
+			LWDEBUGF(5, "tuple = %p; parse_location = %d; parser reported column = %d",
+					tp, tp->uu.nn.parse_location, lwg_parse_yylloc.last_column);
+			LWGEOM_WKT_VALIDATION_ERROR(PARSER_ERROR_MOREPOINTS, tp->uu.nn.parse_location);
+		}
+
+	}
 }
 
+/*
+ * Checks to ensure that each ring of the curved polygon (itself a proper
+ * geometry) contains the minimum number of points.
+ */
+void
+check_curvepolygon_minpoints()
+{
+	tuple *tp = the_geom.stack->next; /* Current tuple */
+	int i, j, k; /* Loop counters */
+	int num, mum, lum; /* subgeom, point counts */
+	int count = 0; /* Running counter for compound curve */
+	int minpoints = 4;
+	num = tp->uu.nn.num;
 
+	LWDEBUG(3, "check_curvepolygon_minpoints");
+
+	/* Check each sub-geom for minpoints */
+	for(i = 0; i < num; i++)
+	{
+		tp = tp->next;
+		LWDEBUGF(5, "Subgeom type %d: %p", tp->uu.nn.type, tp);
+		switch(TYPE_GETTYPE(tp->uu.nn.type)) {
+			case COMPOUNDTYPE:
+				/* sub-geom counter */
+				tp = tp->next;
+				mum = tp->uu.nn.num;
+
+				/* sub-geom loop */
+				for(j = 0; j < mum; j++)
+				{
+					tp = tp->next->next;
+					lum = tp->uu.nn.num;
+					if(j == 0) count += lum;
+					else count += lum - 1;
+					for(k = 0; k < lum; k++)
+					{
+						tp = tp->next;
+					}
+				}
+				if(count < minpoints)
+				{
+					LWDEBUGF(5, "Minpoint check failed: needed %d, got %d",
+							minpoints, count);
+					LWGEOM_WKT_VALIDATION_ERROR(PARSER_ERROR_MOREPOINTS, tp->uu.nn.parse_location);
+				}
+				break;
+			case LINETYPE:
+			case CIRCSTRINGTYPE:
+				tp = tp->next;
+				mum = tp->uu.nn.num;
+				for(j = 0; j < mum; j++)
+				{
+					tp = tp->next;
+				}
+				if(mum < minpoints)
+				{
+					LWDEBUGF(5, "Minpoint check failed: needed %d, got %d",
+							minpoints, count);
+					LWGEOM_WKT_VALIDATION_ERROR(PARSER_ERROR_MOREPOINTS, tp->uu.nn.parse_location);
+				}
+				break;
+		}
+	}
+}
+
+/*
+ * Determines if the compound curve contains the required minimum number of 
+ * points.  This cannot push off to sub-geometries, as it isn't just a matter
+ * counting their points.  The first point of all but the first geometry are
+ * redundant and shall not be counted.
+ */
 void
+check_compoundcurve_minpoints()
+{
+	tuple *tp = the_geom.stack->next; /* Current tuple */
+	int i, j; /* Loop counters */
+	int num, mum; /* sub-geom / point count */
+	int count = 0; /* Running count of points */
+	int minpoints = 3;
+
+	LWDEBUG(3, "check_compoundcurve_minpoints");
+	num = tp->uu.nn.num;
+	LWDEBUGF(5, "subgeom count %d: %p", num, tp);
+
+	for(i = 0; i < num; i++)
+	{
+		LWDEBUG(5, "loop start");
+		/* Step into the sub-geometry's counting tuple */
+		tp = tp->next->next;
+		mum = tp->uu.nn.num;
+		LWDEBUGF(5, "subgeom %d of %d type %d, point count %d: %p", i, num, tp->uu.nn.type, mum, tp);
+		if(i == 0) count += mum;
+		else count += mum - 1;
+
+		/* Skip the sub-geoms point tuples */
+		for(j = 0; j < mum; j++) 
+		{
+			tp = tp->next;
+			LWDEBUGF(5, "skipping point tuple %p", tp);
+		}
+	}
+	LWDEBUG(5, "loop exit");
+	LWDEBUGF(5, "comparison %d", minpoints);
+	LWDEBUGF(5, "comparison %d", count);
+
+	if(count < minpoints)
+	{
+		LWDEBUGF(5, "Minpoint check failed: needed %d, got %d",
+				minpoints, count);
+		LWGEOM_WKT_VALIDATION_ERROR(PARSER_ERROR_MOREPOINTS, tp->uu.nn.parse_location);
+	}
+	LWDEBUG(4, "check_compoundcurve_minpoints complete");
+}
+
+void
+check_linestring_minpoints()
+{
+	tuple *tp = the_geom.stack->next; /* Current counting tuple */
+	int i, num;
+	int minpoints = 2;
+
+	LWDEBUG(3, "check_linestring_minpoints");
+	if(tp->uu.nn.num < minpoints)
+	{
+		num = tp->uu.nn.num;
+		for(i = 0; i < num; i++)
+		{
+			tp = tp->next;
+		}
+		LWDEBUGF(5, "Minpoint check failed: needed %d, got %d",
+				minpoints, tp->uu.nn.num);
+		LWGEOM_WKT_VALIDATION_ERROR(PARSER_ERROR_MOREPOINTS, tp->uu.nn.parse_location);
+	}
+}
+
+void check_circularstring_minpoints()
+{
+	check_linestring_minpoints();
+}
+
+void
+pop(void)
+{
+	LWDEBUGF(3, "pop: type= %d, tuple= %p", the_geom.stack->uu.nn.type, 
+			the_geom.stack);
+	the_geom.stack = the_geom.stack->uu.nn.stack_next;
+}
+
+void
 check_dims(int num)
 {
-        LWDEBUGF(2, "check_dims the_geom.ndims = %d, num = %d", the_geom.ndims, num);
+	LWDEBUGF(3, "check_dims the_geom.ndims = %d, num = %d", the_geom.ndims, num);
 
 	if( the_geom.ndims != num){
 		if (the_geom.ndims) {
 			LWGEOM_WKT_PARSER_ERROR(PARSER_ERROR_MIXDIMS);
 		} else {
 
-                        LWDEBUGF(3, "check_dims: setting dim %d", num);
+						LWDEBUGF(3, "check_dims: setting dim %d", num);
 
 			the_geom.ndims = num;
 			if ( num > 2 ) the_geom.hasZ = 1;
@@ -425,36 +973,9 @@
 void
 empty_stack(tuple *this,output_state* out)
 {
-    /* Do nothing but provide an empty base for the geometry stack */
+	/* Do nothing but provide an empty base for the geometry stack */
 }
-
 void
-alloc_lwgeom(int srid)
-{
-        LWDEBUGF(2, "alloc_lwgeom %d", srid);
-
-	the_geom.srid=srid;
-	the_geom.alloc_size=0;
-	the_geom.stack=NULL;
-	the_geom.ndims=0;
-	the_geom.hasZ=0;
-	the_geom.hasM=0;
-
-	/* Free if used already */
-	if ( the_geom.first ){
-		free_tuple(the_geom.first);
-		the_geom.first=the_geom.last=NULL;
-	}
-
-	if ( srid != -1 ){
-		the_geom.alloc_size+=4;
-	}
-
-    /* Setup up an empty tuple as the stack base */
-    the_geom.stack = alloc_tuple(empty_stack, 0);
-}
-
-void
 write_point_2(tuple* this,output_state* out)
 {
 	WRITE_DOUBLES(out,this->uu.points,2);
@@ -489,71 +1010,7 @@
 {
 	WRITE_INT4_REAL_MULTIPLE(out,this->uu.points,4);
 }
-
 void
-alloc_point_2d(double x,double y)
-{
-	tuple* p = alloc_tuple(write_point_2,the_geom.lwgi?8:16);
-	p->uu.points[0] = x;
-	p->uu.points[1] = y;
-
-        LWDEBUGF(2, "alloc_point_2d %f,%f", x, y);
-	
-	/* keep track of point */
-	if ( checkclosed ) {
-		if ( ! the_geom.stack->uu.nn.num )
-			first_point = p->uu.points;
-		last_point = p->uu.points;
-	}
-
-	inc_num();
-	check_dims(2);
-}
-
-void
-alloc_point_3d(double x,double y,double z)
-{
-	tuple* p = alloc_tuple(write_point_3,the_geom.lwgi?12:24);
-	p->uu.points[0] = x;
-	p->uu.points[1] = y;
-	p->uu.points[2] = z;
-
-        LWDEBUGF(2, "alloc_point_3d %f, %f, %f", x, y, z);
-	
-	/* keep track of point */
-	if ( checkclosed ) {
-		if ( ! the_geom.stack->uu.nn.num )
-			first_point = p->uu.points;
-		last_point = p->uu.points;
-	}
-
-	inc_num();
-	check_dims(3);
-}
-
-void
-alloc_point_4d(double x,double y,double z,double m)
-{
-	tuple* p = alloc_tuple(write_point_4,the_geom.lwgi?16:32);
-	p->uu.points[0] = x;
-	p->uu.points[1] = y;
-	p->uu.points[2] = z;
-	p->uu.points[3] = m;
-
-        LWDEBUGF(2, "alloc_point_4d %f, %f, %f, %f", x, y, z, m);
-
-	/* keep track of point */
-	if ( checkclosed ) {
-		if ( ! the_geom.stack->uu.nn.num )
-			first_point = p->uu.points;
-		last_point = p->uu.points;
-	}
-
-	inc_num();
-	check_dims(4);
-}
-
-void
 write_type(tuple* this,output_state* out)
 {
 	uchar type=0;
@@ -600,99 +1057,88 @@
 void
 alloc_point(void)
 {
-        LWDEBUG(2, "alloc_point");
+		LWDEBUG(3, "alloc_point");
 
 	if( the_geom.lwgi)
 		alloc_stack_tuple(POINTTYPEI,write_type,1);
 	else
 		alloc_stack_tuple(POINTTYPE,write_type,1);
 
-	minpoints=1;
-	checkclosed=0;
-        isodd=-1;
 }
 
 void
 alloc_linestring(void)
 {
-        LWDEBUG(2, "alloc_linestring");
+		LWDEBUG(3, "alloc_linestring");
 
 	if( the_geom.lwgi)
 		alloc_stack_tuple(LINETYPEI,write_type,1);
 	else
 		alloc_stack_tuple(LINETYPE,write_type,1);
 
-	minpoints=2;
-	checkclosed=0;
-        isodd=-1;
 }
 
 void alloc_linestring_closed(void)
 {
-        LWDEBUG(2, "alloc_linestring_closed called.");
+	LWDEBUG(3, "alloc_linestring_closed called.");
 
-        alloc_linestring();
-        checkclosed=1;
+	alloc_linestring();
 }
 
 void
 alloc_circularstring(void)
 {
-        LWDEBUG(2, "alloc_circularstring");
+	LWDEBUG(3, "alloc_circularstring");
 
-        alloc_stack_tuple(CIRCSTRINGTYPE,write_type,1);
-        minpoints=3;
-        checkclosed=0;
-        isodd=1;
+	alloc_stack_tuple(CIRCSTRINGTYPE,write_type,1);
 }
 
 void alloc_circularstring_closed(void)
 {
-        LWDEBUG(2, "alloc_circularstring_closed");
+	LWDEBUG(3, "alloc_circularstring_closed");
 
-        alloc_circularstring();
-        checkclosed=1;
+	alloc_circularstring();
 }
 
 void
 alloc_polygon(void)
 {
-        LWDEBUG(2, "alloc_polygon");
+	LWDEBUG(3, "alloc_polygon");
 
 	if( the_geom.lwgi)
 		alloc_stack_tuple(POLYGONTYPEI, write_type,1);
 	else
 		alloc_stack_tuple(POLYGONTYPE, write_type,1);
-
-	minpoints=4;
-	checkclosed=1;
-        isodd=-1;
-
 }
 
 void
 alloc_curvepolygon(void)
 {
-        LWDEBUG(2, "alloc_curvepolygon called.");
+	LWDEBUG(3, "alloc_curvepolygon called.");
 
-        alloc_stack_tuple(CURVEPOLYTYPE, write_type, 1);
-        minpoints=4;
-        checkclosed=1;
-        isodd=-1;
+	alloc_stack_tuple(CURVEPOLYTYPE, write_type, 1);
 }
 
 void
 alloc_compoundcurve(void)
 {
-        LWDEBUG(2, "alloc_compoundcurve called.");
+		LWDEBUG(3, "alloc_compoundcurve called.");
 
-        alloc_stack_tuple(COMPOUNDTYPE, write_type, 1);
+	alloc_stack_tuple(COMPOUNDTYPE, write_type, 1);
 }
 
 void
+alloc_compoundcurve_closed(void)
+{
+		LWDEBUG(3, "alloc_compoundcurve called.");
+
+		alloc_stack_tuple(COMPOUNDTYPE, write_type, 1);
+}
+
+void
 alloc_multipoint(void)
 {
-        LWDEBUG(2, "alloc_multipoint");
+		LWDEBUG(3, "alloc_multipoint");
 
 	alloc_stack_tuple(MULTIPOINTTYPE,write_type,1);
 }
@@ -700,7 +1146,7 @@
 void
 alloc_multilinestring(void)
 {
-        LWDEBUG(2, "alloc_multilinestring");
+		LWDEBUG(3, "alloc_multilinestring");
 
 	alloc_stack_tuple(MULTILINETYPE,write_type,1);
 }
@@ -708,15 +1154,15 @@
 void
 alloc_multicurve(void)
 {
-        LWDEBUG(2, "alloc_multicurve");
+		LWDEBUG(3, "alloc_multicurve");
 
-        alloc_stack_tuple(MULTICURVETYPE,write_type,1);
+		alloc_stack_tuple(MULTICURVETYPE,write_type,1);
 }
 
 void
 alloc_multipolygon(void)
 {
-        LWDEBUG(2, "alloc_multipolygon");
+		LWDEBUG(3, "alloc_multipolygon");
 
 	alloc_stack_tuple(MULTIPOLYGONTYPE,write_type,1);
 }
@@ -724,15 +1170,15 @@
 void
 alloc_multisurface(void)
 {
-        LWDEBUG(2, "alloc_multisurface called");
+		LWDEBUG(3, "alloc_multisurface called");
 
-        alloc_stack_tuple(MULTISURFACETYPE,write_type,1);
+		alloc_stack_tuple(MULTISURFACETYPE,write_type,1);
 }
 
 void
 alloc_geomertycollection(void)
 {
-        LWDEBUG(2, "alloc_geometrycollection");
+		LWDEBUG(3, "alloc_geometrycollection");
 
 	alloc_stack_tuple(COLLECTIONTYPE,write_type,1);
 }
@@ -740,7 +1186,7 @@
 void
 alloc_counter(void)
 {
-        LWDEBUG(2, "alloc_counter");
+		LWDEBUG(3, "alloc_counter");
 
 	alloc_stack_tuple(0,write_count,4);
 }
@@ -750,7 +1196,7 @@
 {
 	tuple* st = the_geom.stack;
 
-	LWDEBUG(2, "alloc_empty");
+	LWDEBUG(3, "alloc_empty");
 
 	/* Find the last geometry */
 	while(st->uu.nn.type == 0){
@@ -783,7 +1229,7 @@
 	output_state out;
 	tuple* cur;
 	
-	LWDEBUG(2, "make_serialized_lwgeom");
+	LWDEBUG(3, "make_serialized_lwgeom");
 
 	/* Allocate the LWGEOM itself */
 	out_c = (uchar*)local_malloc(the_geom.alloc_size);
@@ -805,7 +1251,7 @@
 void
 lwg_parse_yynotice(char* s)
 {
-        lwnotice(s);
+		lwnotice(s);
 }
 
 int
@@ -940,14 +1386,6 @@
 		}
 	}
 
-
-	/* keep track of point */
-	if ( checkclosed ) {
-		if ( ! the_geom.stack->uu.nn.num )
-			first_point = p->uu.points;
-		last_point = p->uu.points;
-	}
-
 	inc_num();
 	check_dims(the_geom.ndims);
 }
@@ -963,11 +1401,6 @@
 	while(cnt--){
 		if ( parser_ferror_occured )	return;
 
-		/* Things to check for POLYGON ORDINATE_ARRAYs */
-		minpoints=4;
-		checkclosed=1;
-		isodd=-1;
-
 		read_wkb_ordinate_array(b);
 	}
 
@@ -978,11 +1411,6 @@
 read_wkb_linestring(const char **b)
 {
 
-	/* Things to check for LINESTRING ORDINATE_ARRAYs */
-	minpoints=2;
-	checkclosed=0;
-	isodd=-1;
-
 	read_wkb_ordinate_array(b);
 }
 
@@ -991,11 +1419,6 @@
 read_wkb_circstring(const char **b)
 {
 
-	/* Things to check for CIRCULARSTRING ORDINATE_ARRAYs */
-	minpoints=3;
-	checkclosed=0;
-	isodd=-1;
-
 	read_wkb_ordinate_array(b);
 }
 
@@ -1012,7 +1435,7 @@
 	}
 
 	/* Perform a check of the ordinate array */
-	popc();
+	pop();
 }
 
 void
@@ -1037,7 +1460,7 @@
 	uchar xdr = read_wkb_byte(b);
 	int4 localsrid;
 
-        LWDEBUG(2, "parse_wkb");
+		LWDEBUG(3, "parse_wkb");
 
 	swap_order=0;
 
@@ -1098,32 +1521,28 @@
 		case	POINTTYPE:
 			read_wkb_point(b);
 			break;
-
 		case	LINETYPE:
 			read_wkb_linestring(b);
 			break;
-
-                case    CIRCSTRINGTYPE:
-                        read_wkb_circstring(b);
-                        break;
-
+		case	CIRCSTRINGTYPE:
+			read_wkb_circstring(b);
+			break;
 		case	POLYGONTYPE:
 			read_wkb_polygon(b);
 			break;
 
-                case    COMPOUNDTYPE:
-                        read_collection(b,parse_wkb);
-                        break;
+		case	COMPOUNDTYPE:
+			read_collection(b,parse_wkb);
+			break;
 
-                case    CURVEPOLYTYPE:
-                        read_collection(b,parse_wkb);
-                        break;
-
+		case	CURVEPOLYTYPE:
+			read_collection(b,parse_wkb);
+			break;
 		case	MULTIPOINTTYPE:
 		case	MULTILINETYPE:
-                case    MULTICURVETYPE:
+		case	MULTICURVETYPE:
 		case	MULTIPOLYGONTYPE:
-                case    MULTISURFACETYPE:
+		case	MULTISURFACETYPE:
 		case	COLLECTIONTYPE:
 			read_collection(b,parse_wkb);
 			break;
@@ -1156,7 +1575,7 @@
 void
 alloc_wkb(const char *parser)
 {
-        LWDEBUG(2, "alloc_wkb");
+		LWDEBUG(3, "alloc_wkb");
 
 	parse_wkb(&parser);
 }
@@ -1167,7 +1586,7 @@
 int
 parse_it(LWGEOM_PARSER_RESULT *lwg_parser_result, const char *geometry, int flags, allocator allocfunc, report_error errfunc)
 {
-        LWDEBUGF(2, "parse_it: %s with parser flags %d", geometry, flags);
+		LWDEBUGF(3, "parse_it: %s with parser flags %d", geometry, flags);
 
 	local_malloc = allocfunc;
 	error_func=errfunc;
@@ -1210,7 +1629,7 @@
 void
 set_zm(char z, char m)
 {
-        LWDEBUGF(2, "set_zm %d, %d", z, m);
+	LWDEBUGF(4, "set_zm %d, %d", z, m);
 
 	the_geom.hasZ = z;
 	the_geom.hasM = m;

Modified: trunk/liblwgeom/lwgunparse.c
===================================================================
--- trunk/liblwgeom/lwgunparse.c	2009-03-09 22:01:04 UTC (rev 3820)
+++ trunk/liblwgeom/lwgunparse.c	2009-03-10 00:29:32 UTC (rev 3821)
@@ -44,6 +44,7 @@
 uchar* output_polygon_collection(uchar* geom,int suppress);
 uchar* output_polygon_ring_collection(uchar* geom,outfunc func,int supress);
 uchar* output_circstring_collection(uchar* geom,outfunc func,int supress);
+uchar* output_curvepoly(uchar* geom, int supress);
 uchar* output_multipoint(uchar* geom,int suppress);
 uchar* output_compound(uchar* geom, int suppress);
 uchar* output_multisurface(uchar* geom, int suppress);
@@ -435,6 +436,32 @@
 	return geom;
 }
 
+/*
+ * Supress linestring but not circularstring and correctly handle compoundcurve
+ */
+uchar *output_curvepoly(uchar* geom, int supress) {
+	unsigned type;
+	type = *geom++;
+
+	LWDEBUG(2, "output_curvepoly.");
+
+	switch(TYPE_GETTYPE(type))
+	{
+		case LINETYPE:
+			geom = output_collection(geom,output_point,0);
+			break;
+		case CIRCSTRINGTYPE:
+			write_str("CIRCULARSTRING");
+			geom = output_circstring_collection(geom,output_point,1);
+			break;
+		case COMPOUNDTYPE:
+			write_str("COMPOUNDCURVE");
+			geom = output_collection(geom,output_compound,1);
+			break;
+	}
+	return geom;
+}
+
 /* Special case for multisurfaces: suppress the POLYGON prefix from a surface if it appears as
    a component of a MULTISURFACE, but not CURVEPOLYGON */
 uchar *output_multisurface(uchar* geom, int suppress) {

Modified: trunk/liblwgeom/lwmcurve.c
===================================================================
--- trunk/liblwgeom/lwmcurve.c	2009-03-09 22:01:04 UTC (rev 3820)
+++ trunk/liblwgeom/lwmcurve.c	2009-03-10 00:29:32 UTC (rev 3821)
@@ -56,9 +56,14 @@
                 {
                         result->geoms[i] = (LWGEOM *)lwline_deserialize(insp->sub_geoms[i]);
                 }
+	            else if(stype == COMPOUNDTYPE)
+ 		        {
+                        result->geoms[i] = (LWGEOM *)lwcompound_deserialize(insp->sub_geoms[i]);
+                }
                 else
                 {
-                        lwerror("Only Circular and Line strings are currenly permitted in a MultiCurve.");
+                        lwerror("Only Circular strings, Line strings or Compound curves are permitted in a MultiCurve.");
+ 
                         lwfree(result);
                         lwfree(insp);
                         return NULL;

Modified: trunk/liblwgeom/wktparse.h
===================================================================
--- trunk/liblwgeom/wktparse.h	2009-03-09 22:01:04 UTC (rev 3820)
+++ trunk/liblwgeom/wktparse.h	2009-03-10 00:29:32 UTC (rev 3821)
@@ -92,6 +92,7 @@
 void alloc_circularstring(void);
 void alloc_circularstring_closed(void);
 void alloc_polygon(void);
+void alloc_polyring_counter(void);
 void alloc_compoundcurve(void);
 void alloc_curvepolygon(void);
 void alloc_multipoint(void);
@@ -103,6 +104,14 @@
 void alloc_empty();
 void alloc_counter(void);
 
+void check_compoundcurve(void);
+void check_linestring(void);
+void check_polygon(void);
+void check_curvepolygon(void);
+void check_circularstring(void);
+void check_closed_compoundcurve(void);
+void check_closed_linestring(void);
+void check_closed_circularstring(void);
 
 void pop(void);
 void popc(void);

Modified: trunk/liblwgeom/wktparse.tab.c
===================================================================
--- trunk/liblwgeom/wktparse.tab.c	2009-03-09 22:01:04 UTC (rev 3820)
+++ trunk/liblwgeom/wktparse.tab.c	2009-03-10 00:29:32 UTC (rev 3821)
@@ -426,16 +426,16 @@
 /* YYFINAL -- State number of the termination state.  */
 #define YYFINAL  6
 /* YYLAST -- Last index in YYTABLE.  */
-#define YYLAST   180
+#define YYLAST   203
 
 /* YYNTOKENS -- Number of terminals.  */
 #define YYNTOKENS  36
 /* YYNNTS -- Number of nonterminals.  */
-#define YYNNTS  107
+#define YYNNTS  118
 /* YYNRULES -- Number of rules.  */
-#define YYNRULES  169
+#define YYNRULES  184
 /* YYNRULES -- Number of states.  */
-#define YYNSTATES  237
+#define YYNSTATES  254
 
 /* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX.  */
 #define YYUNDEFTOK  2
@@ -491,16 +491,18 @@
       93,    95,    96,    99,   102,   103,   107,   109,   111,   112,
      115,   116,   119,   120,   123,   124,   129,   131,   135,   138,
      139,   143,   146,   147,   151,   153,   155,   157,   159,   160,
-     163,   164,   167,   168,   171,   172,   177,   179,   183,   184,
-     188,   189,   193,   195,   196,   201,   203,   205,   209,   213,
-     214,   218,   219,   223,   225,   226,   231,   233,   237,   238,
-     242,   243,   247,   249,   250,   255,   257,   259,   263,   267,
-     270,   271,   275,   277,   279,   280,   283,   284,   287,   288,
-     293,   295,   299,   300,   304,   305,   309,   311,   312,   317,
-     319,   321,   325,   329,   330,   334,   335,   339,   341,   342,
-     347,   349,   353,   354,   358,   359,   363,   365,   366,   371,
-     373,   375,   379,   383,   384,   388,   389,   393,   395,   396,
-     401,   403,   405,   409,   411,   413,   415,   418,   422,   427
+     163,   164,   167,   168,   171,   172,   177,   179,   183,   186,
+     187,   191,   194,   195,   199,   201,   203,   205,   207,   208,
+     211,   212,   215,   216,   219,   220,   223,   224,   229,   231,
+     233,   237,   241,   242,   246,   247,   251,   253,   254,   259,
+     261,   265,   266,   270,   271,   275,   277,   278,   283,   285,
+     287,   291,   295,   298,   299,   303,   305,   307,   308,   311,
+     312,   315,   316,   321,   323,   327,   328,   332,   333,   337,
+     339,   340,   345,   347,   349,   351,   355,   359,   363,   364,
+     368,   369,   373,   375,   376,   381,   383,   387,   388,   392,
+     393,   397,   399,   400,   405,   407,   409,   413,   417,   418,
+     422,   423,   427,   429,   430,   435,   437,   439,   443,   445,
+     447,   449,   452,   456,   461
 };
 
 /* YYRHS -- A `-1'-separated list of the rules' RHS.  */
@@ -508,47 +510,51 @@
 {
       37,     0,    -1,    -1,    41,    34,    38,    40,    -1,    -1,
       39,    40,    -1,    42,    -1,    43,    -1,    59,    -1,    71,
-      -1,   104,    -1,    86,    -1,   114,    -1,    51,    -1,    92,
-      -1,    98,    -1,   120,    -1,   126,    -1,   132,    -1,    27,
+      -1,   115,    -1,    86,    -1,   125,    -1,    51,    -1,   103,
+      -1,   109,    -1,   131,    -1,   137,    -1,   143,    -1,    27,
       33,    29,    -1,    35,    -1,     3,    45,    -1,    -1,    15,
-      44,    45,    -1,    46,    -1,    48,    -1,    -1,    47,   142,
-      -1,    -1,    49,    50,    -1,    30,   138,    31,    -1,    -1,
-       6,    52,    54,    -1,    -1,    18,    53,    54,    -1,   142,
+      44,    45,    -1,    46,    -1,    48,    -1,    -1,    47,   153,
+      -1,    -1,    49,    50,    -1,    30,   149,    31,    -1,    -1,
+       6,    52,    54,    -1,    -1,    18,    53,    54,    -1,   153,
       -1,    -1,    55,    30,    56,    31,    -1,    57,    -1,    56,
-      32,    57,    -1,    48,    -1,    -1,    58,   138,    -1,     4,
+      32,    57,    -1,    48,    -1,    -1,    58,   149,    -1,     4,
       61,    -1,    -1,    16,    60,    61,    -1,    62,    -1,    64,
-      -1,    -1,    63,   142,    -1,    -1,    65,    68,    -1,    -1,
-      67,    68,    -1,    -1,    69,    30,    70,    31,    -1,   138,
-      -1,    70,    32,   138,    -1,    10,    75,    -1,    -1,    22,
+      -1,    -1,    63,   153,    -1,    -1,    65,    68,    -1,    -1,
+      67,    68,    -1,    -1,    69,    30,    70,    31,    -1,   149,
+      -1,    70,    32,   149,    -1,    10,    75,    -1,    -1,    22,
       72,    75,    -1,    10,    76,    -1,    -1,    22,    74,    76,
       -1,    77,    -1,    79,    -1,    77,    -1,    81,    -1,    -1,
-      78,   142,    -1,    -1,    80,    83,    -1,    -1,    82,    83,
-      -1,    -1,    84,    30,    85,    31,    -1,   138,    -1,    85,
-      32,   138,    -1,    -1,    11,    87,    89,    -1,    -1,    23,
-      88,    89,    -1,   142,    -1,    -1,    90,    30,    91,    31,
-      -1,    64,    -1,    71,    -1,    91,    32,    64,    -1,    91,
-      32,    71,    -1,    -1,     7,    93,    95,    -1,    -1,    19,
-      94,    95,    -1,   142,    -1,    -1,    96,    30,    97,    31,
-      -1,    64,    -1,    97,    32,    64,    -1,    -1,    13,    99,
-     101,    -1,    -1,    25,   100,   101,    -1,   142,    -1,    -1,
-     102,    30,   103,    31,    -1,    64,    -1,    71,    -1,   103,
-      32,    64,    -1,   103,    32,    71,    -1,     5,   106,    -1,
-      -1,    17,   105,   106,    -1,   107,    -1,   109,    -1,    -1,
-     108,   142,    -1,    -1,   110,   111,    -1,    -1,   112,    30,
-     113,    31,    -1,    68,    -1,   113,    32,    68,    -1,    -1,
-      12,   115,   117,    -1,    -1,    24,   116,   117,    -1,   142,
-      -1,    -1,   118,    30,   119,    31,    -1,    66,    -1,    73,
-      -1,   119,    32,    66,    -1,   119,    32,    73,    -1,    -1,
-       8,   121,   123,    -1,    -1,    20,   122,   123,    -1,   142,
-      -1,    -1,   124,    30,   125,    31,    -1,   109,    -1,   125,
-      32,   109,    -1,    -1,    14,   127,   129,    -1,    -1,    26,
-     128,   129,    -1,   142,    -1,    -1,   130,    30,   131,    31,
-      -1,   109,    -1,   114,    -1,   131,    32,   109,    -1,   131,
-      32,   114,    -1,    -1,     9,   133,   135,    -1,    -1,    21,
-     134,   135,    -1,   142,    -1,    -1,   136,    30,   137,    31,
-      -1,   142,    -1,    40,    -1,   137,    32,    40,    -1,   139,
-      -1,   140,    -1,   141,    -1,    29,    29,    -1,    29,    29,
-      29,    -1,    29,    29,    29,    29,    -1,    28,    -1
+      78,   153,    -1,    -1,    80,    83,    -1,    -1,    82,    83,
+      -1,    -1,    84,    30,    85,    31,    -1,   149,    -1,    85,
+      32,   149,    -1,    11,    90,    -1,    -1,    23,    87,    90,
+      -1,    11,    91,    -1,    -1,    23,    89,    91,    -1,    92,
+      -1,    96,    -1,    94,    -1,    98,    -1,    -1,    93,   153,
+      -1,    -1,    95,   153,    -1,    -1,    97,   100,    -1,    -1,
+      99,   100,    -1,    -1,   101,    30,   102,    31,    -1,    64,
+      -1,    71,    -1,   102,    32,    64,    -1,   102,    32,    71,
+      -1,    -1,     7,   104,   106,    -1,    -1,    19,   105,   106,
+      -1,   153,    -1,    -1,   107,    30,   108,    31,    -1,    64,
+      -1,   108,    32,    64,    -1,    -1,    13,   110,   112,    -1,
+      -1,    25,   111,   112,    -1,   153,    -1,    -1,   113,    30,
+     114,    31,    -1,    64,    -1,    71,    -1,   114,    32,    64,
+      -1,   114,    32,    71,    -1,     5,   117,    -1,    -1,    17,
+     116,   117,    -1,   118,    -1,   120,    -1,    -1,   119,   153,
+      -1,    -1,   121,   122,    -1,    -1,   123,    30,   124,    31,
+      -1,    68,    -1,   124,    32,    68,    -1,    -1,    12,   126,
+     128,    -1,    -1,    24,   127,   128,    -1,   153,    -1,    -1,
+     129,    30,   130,    31,    -1,    66,    -1,    73,    -1,    88,
+      -1,   130,    32,    66,    -1,   130,    32,    73,    -1,   130,
+      32,    88,    -1,    -1,     8,   132,   134,    -1,    -1,    20,
+     133,   134,    -1,   153,    -1,    -1,   135,    30,   136,    31,
+      -1,   120,    -1,   136,    32,   120,    -1,    -1,    14,   138,
+     140,    -1,    -1,    26,   139,   140,    -1,   153,    -1,    -1,
+     141,    30,   142,    31,    -1,   120,    -1,   125,    -1,   142,
+      32,   120,    -1,   142,    32,   125,    -1,    -1,     9,   144,
+     146,    -1,    -1,    21,   145,   146,    -1,   153,    -1,    -1,
+     147,    30,   148,    31,    -1,   153,    -1,    40,    -1,   148,
+      32,    40,    -1,   150,    -1,   151,    -1,   152,    -1,    29,
+      29,    -1,    29,    29,    29,    -1,    29,    29,    29,    29,
+      -1,    28,    -1
 };
 
 /* YYRLINE[YYN] -- source line where rule number YYN was defined.  */
@@ -561,16 +567,18 @@
      115,   118,   118,   124,   126,   126,   129,   131,   134,   134,
      137,   137,   140,   140,   143,   143,   146,   148,   153,   155,
      155,   158,   160,   160,   163,   165,   168,   170,   173,   173,
-     176,   176,   179,   179,   182,   182,   185,   187,   192,   192,
-     194,   194,   197,   199,   199,   202,   204,   206,   208,   213,
-     213,   216,   216,   220,   222,   222,   225,   227,   232,   232,
-     235,   235,   239,   241,   241,   244,   246,   248,   250,   255,
-     257,   257,   260,   262,   265,   265,   268,   268,   271,   271,
-     274,   276,   281,   281,   283,   283,   287,   289,   289,   292,
-     294,   296,   298,   303,   303,   305,   305,   309,   311,   311,
-     314,   316,   321,   321,   323,   323,   327,   329,   329,   332,
-     334,   336,   338,   343,   343,   346,   346,   350,   352,   352,
-     356,   358,   360,   364,   366,   368,   371,   374,   377,   380
+     176,   176,   179,   179,   182,   182,   185,   187,   192,   194,
+     194,   197,   199,   199,   202,   204,   207,   209,   212,   212,
+     215,   215,   218,   218,   221,   221,   224,   224,   227,   229,
+     231,   233,   238,   238,   241,   241,   245,   247,   247,   250,
+     252,   257,   257,   260,   260,   264,   266,   266,   269,   271,
+     273,   275,   280,   282,   282,   285,   287,   290,   290,   293,
+     293,   296,   296,   300,   303,   308,   308,   310,   310,   314,
+     316,   316,   319,   321,   323,   325,   327,   329,   334,   334,
+     336,   336,   340,   342,   342,   345,   347,   352,   352,   354,
+     354,   358,   360,   360,   363,   365,   367,   369,   374,   374,
+     377,   377,   381,   383,   383,   387,   389,   391,   395,   397,
+     399,   402,   405,   408,   411
 };
 #endif
 
@@ -598,16 +606,19 @@
   "circularstring_closed", "empty_circularstring", "@17",
   "nonempty_circularstring", "@18", "nonempty_circularstring_closed",
   "@19", "circularstring_1", "@20", "circularstring_int",
-  "geom_compoundcurve", "@21", "@22", "compoundcurve", "@23",
-  "compoundcurve_int", "geom_multilinestring", "@24", "@25",
-  "multilinestring", "@26", "multilinestring_int", "geom_multicurve",
-  "@27", "@28", "multicurve", "@29", "multicurve_int", "geom_polygon",
-  "@30", "polygon", "empty_polygon", "@31", "nonempty_polygon", "@32",
-  "polygon_1", "@33", "polygon_int", "geom_curvepolygon", "@34", "@35",
-  "curvepolygon", "@36", "curvepolygon_int", "geom_multipolygon", "@37",
-  "@38", "multipolygon", "@39", "multipolygon_int", "geom_multisurface",
-  "@40", "@41", "multisurface", "@42", "multisurface_int",
-  "geom_geometrycollection", "@43", "@44", "geometrycollection", "@45",
+  "geom_compoundcurve", "@21", "geom_compoundcurve_closed", "@22",
+  "compoundcurve", "compoundcurve_closed", "empty_compoundcurve", "@23",
+  "empty_compoundcurve_closed", "@24", "nonempty_compoundcurve", "@25",
+  "nonempty_compoundcurve_closed", "@26", "compoundcurve_1", "@27",
+  "compoundcurve_int", "geom_multilinestring", "@28", "@29",
+  "multilinestring", "@30", "multilinestring_int", "geom_multicurve",
+  "@31", "@32", "multicurve", "@33", "multicurve_int", "geom_polygon",
+  "@34", "polygon", "empty_polygon", "@35", "nonempty_polygon", "@36",
+  "polygon_1", "@37", "polygon_int", "geom_curvepolygon", "@38", "@39",
+  "curvepolygon", "@40", "curvepolygon_int", "geom_multipolygon", "@41",
+  "@42", "multipolygon", "@43", "multipolygon_int", "geom_multisurface",
+  "@44", "@45", "multisurface", "@46", "multisurface_int",
+  "geom_geometrycollection", "@47", "@48", "geometrycollection", "@49",
   "geometrycollection_int", "a_point", "point_2d", "point_3d", "point_4d",
   "empty", 0
 };
@@ -635,16 +646,18 @@
       57,    58,    57,    59,    60,    59,    61,    61,    63,    62,
       65,    64,    67,    66,    69,    68,    70,    70,    71,    72,
       71,    73,    74,    73,    75,    75,    76,    76,    78,    77,
-      80,    79,    82,    81,    84,    83,    85,    85,    87,    86,
-      88,    86,    89,    90,    89,    91,    91,    91,    91,    93,
-      92,    94,    92,    95,    96,    95,    97,    97,    99,    98,
-     100,    98,   101,   102,   101,   103,   103,   103,   103,   104,
-     105,   104,   106,   106,   108,   107,   110,   109,   112,   111,
-     113,   113,   115,   114,   116,   114,   117,   118,   117,   119,
-     119,   119,   119,   121,   120,   122,   120,   123,   124,   123,
-     125,   125,   127,   126,   128,   126,   129,   130,   129,   131,
-     131,   131,   131,   133,   132,   134,   132,   135,   136,   135,
-     137,   137,   137,   138,   138,   138,   139,   140,   141,   142
+      80,    79,    82,    81,    84,    83,    85,    85,    86,    87,
+      86,    88,    89,    88,    90,    90,    91,    91,    93,    92,
+      95,    94,    97,    96,    99,    98,   101,   100,   102,   102,
+     102,   102,   104,   103,   105,   103,   106,   107,   106,   108,
+     108,   110,   109,   111,   109,   112,   113,   112,   114,   114,
+     114,   114,   115,   116,   115,   117,   117,   119,   118,   121,
+     120,   123,   122,   124,   124,   126,   125,   127,   125,   128,
+     129,   128,   130,   130,   130,   130,   130,   130,   132,   131,
+     133,   131,   134,   135,   134,   136,   136,   138,   137,   139,
+     137,   140,   141,   140,   142,   142,   142,   142,   144,   143,
+     145,   143,   146,   147,   146,   148,   148,   148,   149,   149,
+     149,   150,   151,   152,   153
 };
 
 /* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN.  */
@@ -657,16 +670,18 @@
        1,     0,     2,     2,     0,     3,     1,     1,     0,     2,
        0,     2,     0,     2,     0,     4,     1,     3,     2,     0,
        3,     2,     0,     3,     1,     1,     1,     1,     0,     2,
-       0,     2,     0,     2,     0,     4,     1,     3,     0,     3,
-       0,     3,     1,     0,     4,     1,     1,     3,     3,     0,
-       3,     0,     3,     1,     0,     4,     1,     3,     0,     3,
-       0,     3,     1,     0,     4,     1,     1,     3,     3,     2,
-       0,     3,     1,     1,     0,     2,     0,     2,     0,     4,
-       1,     3,     0,     3,     0,     3,     1,     0,     4,     1,
-       1,     3,     3,     0,     3,     0,     3,     1,     0,     4,
-       1,     3,     0,     3,     0,     3,     1,     0,     4,     1,
-       1,     3,     3,     0,     3,     0,     3,     1,     0,     4,
-       1,     1,     3,     1,     1,     1,     2,     3,     4,     1
+       0,     2,     0,     2,     0,     4,     1,     3,     2,     0,
+       3,     2,     0,     3,     1,     1,     1,     1,     0,     2,
+       0,     2,     0,     2,     0,     2,     0,     4,     1,     1,
+       3,     3,     0,     3,     0,     3,     1,     0,     4,     1,
+       3,     0,     3,     0,     3,     1,     0,     4,     1,     1,
+       3,     3,     2,     0,     3,     1,     1,     0,     2,     0,
+       2,     0,     4,     1,     3,     0,     3,     0,     3,     1,
+       0,     4,     1,     1,     1,     3,     3,     3,     0,     3,
+       0,     3,     1,     0,     4,     1,     3,     0,     3,     0,
+       3,     1,     0,     4,     1,     1,     3,     3,     0,     3,
+       0,     3,     1,     0,     4,     1,     1,     3,     1,     1,
+       1,     2,     3,     4,     1
 };
 
 /* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
@@ -674,144 +689,154 @@
    means the default is an error.  */
 static const yytype_uint8 yydefact[] =
 {
-       4,     0,     0,     0,     0,     0,     1,    26,    48,   114,
-      31,    89,   133,   153,    68,    78,   122,    98,   142,    22,
-      44,   110,    33,    91,   135,   155,    59,    80,   124,   100,
-     144,    20,     5,     6,     7,    13,     8,     9,    11,    14,
+       4,     0,     0,     0,     0,     0,     1,    26,    48,   127,
+      31,   102,   148,   168,    68,    88,   135,   111,   157,    22,
+      44,   123,    33,   104,   150,   170,    59,    79,   137,   113,
+     159,    20,     5,     6,     7,    13,     8,     9,    11,    14,
       15,    10,    12,    16,    17,    18,     2,    19,    21,    24,
-       0,    25,     0,    43,    46,     0,    47,    54,   109,   112,
-       0,   113,   118,    36,    94,   138,   158,    58,    64,     0,
-      65,    74,    83,   127,   103,   147,    26,    48,   114,    36,
-      94,   138,   158,    68,    83,   127,   103,   147,     0,   169,
-      27,     0,    29,    49,    51,     0,   115,   117,     0,    32,
-       0,    35,    90,     0,    93,   134,     0,   137,   154,     0,
-     157,    69,    71,     0,    79,     0,    82,   123,     0,   126,
-      99,     0,   102,   143,     0,   146,    23,    45,   111,    34,
-      92,   136,   156,    60,    81,   125,   101,   145,     3,     0,
-       0,   163,   164,   165,     0,    54,    28,    50,   116,     0,
-       0,    50,    52,    50,   116,   166,    30,     0,    56,   120,
-       0,    40,     0,    38,     0,    96,     0,   140,     0,   161,
-       0,   160,     0,    76,    85,    86,     0,    68,    62,   129,
-      54,   130,     0,   105,   106,     0,   149,   150,     0,   167,
-      55,     0,   119,    54,    37,    28,    42,    95,    50,   139,
-     116,   159,     0,    75,     0,    84,    50,    61,    66,    67,
-      74,    68,    53,   128,    52,   104,    50,   148,   116,   168,
-      57,   121,    39,    97,   141,   162,    77,    87,    88,    73,
-      63,   131,   132,   107,   108,   151,   152
+       0,    25,     0,    43,    46,     0,    47,    54,   122,   125,
+       0,   126,   131,    36,   107,   153,   173,    58,    64,     0,
+      65,    74,    78,    84,     0,    85,    96,   140,   116,   162,
+      26,    48,   127,    36,   107,   153,   173,    68,    88,   140,
+     116,   162,     0,   184,    27,     0,    29,    49,    51,     0,
+     128,   130,     0,    32,     0,    35,   103,     0,   106,   149,
+       0,   152,   169,     0,   172,    69,    71,     0,    89,    93,
+       0,   136,     0,   139,   112,     0,   115,   158,     0,   161,
+      23,    45,   124,    34,   105,   151,   171,    60,    80,   138,
+     114,   160,     3,     0,     0,   178,   179,   180,     0,    54,
+      28,    50,   129,     0,     0,    50,    52,    50,   129,   181,
+      30,     0,    56,   133,     0,    40,     0,    38,     0,   109,
+       0,   155,     0,   176,     0,   175,     0,    76,    98,    99,
+       0,    68,    90,    62,    82,   142,    54,   143,   144,     0,
+     118,   119,     0,   164,   165,     0,   182,    55,     0,   132,
+      54,    37,    28,    42,   108,    50,   154,   129,   174,     0,
+      75,     0,    97,    50,    61,    66,    67,    74,    81,    86,
+       0,    87,    96,    68,    90,    53,   141,    52,   117,    50,
+     163,   129,   183,    57,   134,    39,   110,   156,   177,    77,
+     100,   101,    73,    91,    95,    63,    83,   145,   146,   147,
+     120,   121,   166,   167
 };
 
 /* YYDEFGOTO[NTERM-NUM].  */
 static const yytype_int16 yydefgoto[] =
 {
-      -1,     2,    88,     3,    32,     4,    33,    34,    76,    48,
-      49,    50,    51,    52,    92,    35,    63,    79,    99,   100,
-     162,   163,   164,    36,    77,    53,    54,    55,    56,    57,
-     179,   180,    94,    95,   157,    37,    83,   181,   211,    67,
-     207,    68,    69,    70,    71,   209,   210,   112,   113,   172,
-      38,    72,    84,   114,   115,   176,    39,    64,    80,   102,
-     103,   166,    40,    74,    86,   120,   121,   185,    41,    78,
-      58,    59,    60,    61,    62,    97,    98,   160,    42,    73,
-      85,   117,   118,   182,    43,    65,    81,   105,   106,   168,
-      44,    75,    87,   123,   124,   188,    45,    66,    82,   108,
-     109,   170,   140,   141,   142,   143,   101
+      -1,     2,    92,     3,    32,     4,    33,    34,    80,    48,
+      49,    50,    51,    52,    96,    35,    63,    83,   103,   104,
+     166,   167,   168,    36,    81,    53,    54,    55,    56,    57,
+     185,   186,    98,    99,   161,    37,    87,   187,   223,    67,
+     214,    68,    69,    70,    71,   216,   217,   116,   117,   176,
+      38,    88,   188,   224,    72,   218,    73,    74,   219,   220,
+      75,    76,   221,   222,   119,   120,   180,    39,    64,    84,
+     106,   107,   170,    40,    78,    90,   124,   125,   192,    41,
+      82,    58,    59,    60,    61,    62,   101,   102,   164,    42,
+      77,    89,   121,   122,   189,    43,    65,    85,   109,   110,
+     172,    44,    79,    91,   127,   128,   195,    45,    66,    86,
+     112,   113,   174,   144,   145,   146,   147,   105
 };
 
 /* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
    STATE-NUM.  */
-#define YYPACT_NINF -166
+#define YYPACT_NINF -176
 static const yytype_int16 yypact[] =
 {
-     -17,   -14,    21,   145,    -7,     5,  -166,    29,    30,    40,
-    -166,  -166,  -166,  -166,    51,  -166,  -166,  -166,  -166,  -166,
-    -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,
-    -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,
-    -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,
-      23,  -166,    53,  -166,  -166,    23,  -166,  -166,  -166,  -166,
-      23,  -166,  -166,    23,    23,    23,    23,  -166,  -166,    23,
-    -166,  -166,    23,    23,    23,    23,    29,    30,    40,    23,
-      23,    23,    23,    51,    23,    23,    23,    23,   145,  -166,
-    -166,    55,  -166,  -166,  -166,    56,  -166,  -166,    57,  -166,
-      58,  -166,  -166,    59,  -166,  -166,    61,  -166,  -166,    62,
-    -166,  -166,  -166,    63,  -166,    64,  -166,  -166,    65,  -166,
-    -166,    66,  -166,  -166,    67,  -166,  -166,  -166,  -166,  -166,
-    -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,    70,
-      54,  -166,  -166,  -166,    55,  -166,    72,  -166,  -166,   112,
-      55,     8,    19,     8,    28,    73,  -166,   -18,  -166,  -166,
-      16,  -166,    18,  -166,    55,  -166,    24,  -166,    31,  -166,
-      33,  -166,    35,  -166,  -166,  -166,    42,    74,  -166,  -166,
-    -166,  -166,    44,  -166,  -166,    46,  -166,  -166,    48,    76,
-    -166,    55,  -166,  -166,  -166,    72,  -166,  -166,  -166,  -166,
-    -166,  -166,   145,  -166,    55,  -166,     8,  -166,  -166,  -166,
-    -166,    74,  -166,  -166,    19,  -166,     8,  -166,    28,  -166,
-    -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,  -166,
-    -166,  -166,  -166,  -166,  -166,  -166,  -166
+      -5,    16,    52,   168,    13,    31,  -176,    33,    35,    37,
+    -176,  -176,  -176,  -176,    50,    54,  -176,  -176,  -176,  -176,
+    -176,  -176,  -176,  -176,  -176,  -176,  -176,  -176,  -176,  -176,
+    -176,  -176,  -176,  -176,  -176,  -176,  -176,  -176,  -176,  -176,
+    -176,  -176,  -176,  -176,  -176,  -176,  -176,  -176,  -176,  -176,
+      58,  -176,    57,  -176,  -176,    58,  -176,  -176,  -176,  -176,
+      58,  -176,  -176,    58,    58,    58,    58,  -176,  -176,    58,
+    -176,  -176,  -176,  -176,    58,  -176,  -176,    58,    58,    58,
+      33,    35,    37,    58,    58,    58,    58,    50,    54,    58,
+      58,    58,   168,  -176,  -176,    59,  -176,  -176,  -176,    60,
+    -176,  -176,    61,  -176,    63,  -176,  -176,    64,  -176,  -176,
+      65,  -176,  -176,    66,  -176,  -176,  -176,    67,  -176,  -176,
+      68,  -176,    69,  -176,  -176,    70,  -176,  -176,    71,  -176,
+    -176,  -176,  -176,  -176,  -176,  -176,  -176,  -176,  -176,  -176,
+    -176,  -176,  -176,    73,    74,  -176,  -176,  -176,    59,  -176,
+      75,  -176,  -176,   116,    59,    11,    15,    11,    18,    77,
+    -176,     0,  -176,  -176,    12,  -176,    14,  -176,    59,  -176,
+      19,  -176,    24,  -176,    27,  -176,    39,  -176,  -176,  -176,
+      41,    78,    79,  -176,  -176,  -176,  -176,  -176,  -176,    43,
+    -176,  -176,    47,  -176,  -176,    51,    81,  -176,    59,  -176,
+    -176,  -176,    75,  -176,  -176,  -176,  -176,  -176,  -176,   168,
+    -176,    59,  -176,    11,  -176,  -176,  -176,  -176,  -176,  -176,
+      58,  -176,  -176,    78,    79,  -176,  -176,    15,  -176,    11,
+    -176,    18,  -176,  -176,  -176,  -176,  -176,  -176,  -176,  -176,
+    -176,  -176,  -176,  -176,  -176,  -176,  -176,  -176,  -176,  -176,
+    -176,  -176,  -176,  -176
 };
 
 /* YYPGOTO[NTERM-NUM].  */
 static const yytype_int16 yypgoto[] =
 {
-    -166,  -166,  -166,  -166,   -88,  -166,  -166,  -166,  -166,    27,
-    -166,  -166,  -142,  -166,  -166,  -166,  -166,  -166,    32,  -166,
-    -166,   -89,  -166,  -166,  -166,    36,  -166,  -166,  -108,  -166,
-    -107,  -166,  -136,  -166,  -166,  -148,  -166,  -105,  -166,    60,
-    -101,  -165,  -166,  -166,  -166,  -166,  -166,   -98,  -166,  -166,
-    -166,  -166,  -166,    88,  -166,  -166,  -166,  -166,  -166,    93,
-    -166,  -166,  -166,  -166,  -166,    89,  -166,  -166,  -166,  -166,
-      68,  -166,  -166,  -146,  -166,  -166,  -166,  -166,  -147,  -166,
-    -166,    91,  -166,  -166,  -166,  -166,  -166,    96,  -166,  -166,
-    -166,  -166,  -166,    52,  -166,  -166,  -166,  -166,  -166,    92,
-    -166,  -166,  -122,  -166,  -166,  -166,   -49
+    -176,  -176,  -176,  -176,   -91,  -176,  -176,  -176,  -176,     9,
+    -176,  -176,  -138,  -176,  -176,  -176,  -176,  -176,    28,  -176,
+    -176,   -95,  -176,  -176,  -176,    32,  -176,  -176,  -144,  -176,
+    -115,  -176,  -132,  -176,  -176,  -137,  -176,  -113,  -176,    29,
+    -108,  -175,  -176,  -176,  -176,  -176,  -176,  -100,  -176,  -176,
+    -176,  -176,   -84,  -176,    62,   -79,  -176,  -176,  -176,  -176,
+    -176,  -176,  -176,  -176,   -76,  -176,  -176,  -176,  -176,  -176,
+      72,  -176,  -176,  -176,  -176,  -176,    76,  -176,  -176,  -176,
+    -176,    80,  -176,  -176,  -150,  -176,  -176,  -176,  -176,  -154,
+    -176,  -176,   106,  -176,  -176,  -176,  -176,  -176,    82,  -176,
+    -176,  -176,  -176,  -176,    56,  -176,  -176,  -176,  -176,  -176,
+      83,  -176,  -176,  -145,  -176,  -176,  -176,   -50
 };
 
 /* YYTABLE[YYPACT[STATE-NUM]].  What to do in state STATE-NUM.  If
    positive, shift that token.  If negative, reduce the rule which
    number is the opposite.  If zero, do what YYDEFACT says.
    If YYTABLE_NINF, syntax error.  */
-#define YYTABLE_NINF -117
+#define YYTABLE_NINF -130
 static const yytype_int16 yytable[] =
 {
-     138,    90,   167,   175,   161,   184,    93,   187,   186,   159,
-       1,    96,   208,   190,   191,   104,   107,   110,    14,     5,
-     111,     6,   158,   116,   119,   122,   125,    46,   173,   177,
-      26,   104,   107,   110,    47,   116,   119,   122,   125,   165,
-      16,   178,   196,   174,   212,   183,   208,   192,   193,   194,
-     195,    89,    28,   161,   224,   197,   198,   221,   228,   -28,
-     -50,   169,   199,   200,   201,   202,   203,   204,   234,   220,
-    -116,   236,   235,   205,   206,   213,   214,   215,   216,   217,
-     218,   -70,   226,    91,   139,   156,   144,   145,   146,   147,
-     223,   148,   149,   150,   151,   152,   153,   154,   227,   155,
-     171,   -41,   189,   126,   -72,   219,   222,   231,   233,   232,
-     230,   129,   229,   127,   225,     7,     8,     9,    10,    11,
-      12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
-      22,    23,    24,    25,    26,    27,    28,    29,    30,   137,
-      89,     0,     0,   133,     0,     0,   128,    31,     7,     8,
-       9,    10,    11,    12,    13,    14,    15,    16,    17,    18,
-      19,    20,    21,    22,    23,    24,    25,    26,    27,    28,
-      29,    30,   134,   130,   132,   136,   135,   131,     0,     0,
-      31
+      94,   142,   171,   162,   194,    97,   215,   169,   193,   177,
+     100,   178,   165,   190,   108,   111,   114,   163,   179,   115,
+     191,    14,     1,   203,   118,   181,   182,   123,   126,   129,
+      16,   197,   198,    26,   108,   111,   114,   183,   184,   123,
+     126,   129,    28,   199,   200,   201,   202,    46,   215,     5,
+     204,   205,     6,   233,   225,   206,   207,   237,   208,   209,
+      47,   236,   173,   -28,   165,   -50,   239,  -129,   234,   240,
+     210,   211,   212,   213,   226,   227,   241,   253,   228,   229,
+     -70,   252,   230,   231,   -92,   250,    93,    95,   143,   130,
+     148,   149,   251,   150,   151,   152,   153,   154,   155,   156,
+     157,   158,   159,   175,   -41,   160,   196,   235,   -72,   -94,
+     232,   133,   247,   131,   248,   245,   137,   242,   238,     7,
+       8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
+      18,    19,    20,    21,    22,    23,    24,    25,    26,    27,
+      28,    29,    30,   249,    93,   246,   244,   141,     0,     0,
+     138,    31,     0,     0,     0,     0,   134,     0,     0,     0,
+       0,     0,   132,     0,     0,     0,   140,   135,     0,   136,
+     243,     7,     8,     9,    10,    11,    12,    13,    14,    15,
+      16,    17,    18,    19,    20,    21,    22,    23,    24,    25,
+      26,    27,    28,    29,    30,   139,     0,     0,     0,     0,
+       0,     0,     0,    31
 };
 
 static const yytype_int16 yycheck[] =
 {
-      88,    50,   148,   151,   146,   153,    55,   154,   154,   145,
-      27,    60,   177,    31,    32,    64,    65,    66,    10,    33,
-      69,     0,   144,    72,    73,    74,    75,    34,   150,    10,
-      22,    80,    81,    82,    29,    84,    85,    86,    87,   147,
-      12,    22,   164,   151,   180,   153,   211,    31,    32,    31,
-      32,    28,    24,   195,   200,    31,    32,   193,   206,    30,
-      30,   149,    31,    32,    31,    32,    31,    32,   216,   191,
-      30,   218,   218,    31,    32,    31,    32,    31,    32,    31,
-      32,    30,   204,    30,    29,    31,    30,    30,    30,    30,
-     198,    30,    30,    30,    30,    30,    30,    30,   206,    29,
-     149,    29,    29,    76,    30,    29,   195,   214,   216,   214,
-     211,    79,   210,    77,   202,     3,     4,     5,     6,     7,
-       8,     9,    10,    11,    12,    13,    14,    15,    16,    17,
-      18,    19,    20,    21,    22,    23,    24,    25,    26,    87,
-      28,    -1,    -1,    83,    -1,    -1,    78,    35,     3,     4,
-       5,     6,     7,     8,     9,    10,    11,    12,    13,    14,
-      15,    16,    17,    18,    19,    20,    21,    22,    23,    24,
-      25,    26,    84,    80,    82,    86,    85,    81,    -1,    -1,
-      35
+      50,    92,   152,   148,   158,    55,   181,   151,   158,   154,
+      60,   155,   150,   157,    64,    65,    66,   149,   155,    69,
+     157,    10,    27,   168,    74,    10,    11,    77,    78,    79,
+      12,    31,    32,    22,    84,    85,    86,    22,    23,    89,
+      90,    91,    24,    31,    32,    31,    32,    34,   223,    33,
+      31,    32,     0,   198,   186,    31,    32,   207,    31,    32,
+      29,   205,   153,    30,   202,    30,   211,    30,   200,   213,
+      31,    32,    31,    32,    31,    32,   213,   231,    31,    32,
+      30,   231,    31,    32,    30,   229,    28,    30,    29,    80,
+      30,    30,   229,    30,    30,    30,    30,    30,    30,    30,
+      30,    30,    29,   153,    29,    31,    29,   202,    30,    30,
+      29,    83,   227,    81,   227,   223,    87,   217,   209,     3,
+       4,     5,     6,     7,     8,     9,    10,    11,    12,    13,
+      14,    15,    16,    17,    18,    19,    20,    21,    22,    23,
+      24,    25,    26,   227,    28,   224,   222,    91,    -1,    -1,
+      88,    35,    -1,    -1,    -1,    -1,    84,    -1,    -1,    -1,
+      -1,    -1,    82,    -1,    -1,    -1,    90,    85,    -1,    86,
+     220,     3,     4,     5,     6,     7,     8,     9,    10,    11,
+      12,    13,    14,    15,    16,    17,    18,    19,    20,    21,
+      22,    23,    24,    25,    26,    89,    -1,    -1,    -1,    -1,
+      -1,    -1,    -1,    35
 };
 
 /* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
@@ -821,27 +846,29 @@
        0,    27,    37,    39,    41,    33,     0,     3,     4,     5,
        6,     7,     8,     9,    10,    11,    12,    13,    14,    15,
       16,    17,    18,    19,    20,    21,    22,    23,    24,    25,
-      26,    35,    40,    42,    43,    51,    59,    71,    86,    92,
-      98,   104,   114,   120,   126,   132,    34,    29,    45,    46,
-      47,    48,    49,    61,    62,    63,    64,    65,   106,   107,
-     108,   109,   110,    52,    93,   121,   133,    75,    77,    78,
-      79,    80,    87,   115,    99,   127,    44,    60,   105,    53,
-      94,   122,   134,    72,    88,   116,   100,   128,    38,    28,
-     142,    30,    50,   142,    68,    69,   142,   111,   112,    54,
-      55,   142,    95,    96,   142,   123,   124,   142,   135,   136,
-     142,   142,    83,    84,    89,    90,   142,   117,   118,   142,
-     101,   102,   142,   129,   130,   142,    45,    61,   106,    54,
-      95,   123,   135,    75,    89,   117,   101,   129,    40,    29,
-     138,   139,   140,   141,    30,    30,    30,    30,    30,    30,
-      30,    30,    30,    30,    30,    29,    31,    70,   138,    68,
-     113,    48,    56,    57,    58,    64,    97,   109,   125,    40,
-     137,   142,    85,   138,    64,    71,    91,    10,    22,    66,
-      67,    73,   119,    64,    71,   103,   109,   114,   131,    29,
-      31,    32,    31,    32,    31,    32,   138,    31,    32,    31,
-      32,    31,    32,    31,    32,    31,    32,    76,    77,    81,
-      82,    74,    68,    31,    32,    31,    32,    31,    32,    29,
-     138,    68,    57,    64,   109,    40,   138,    64,    71,    83,
-      76,    66,    73,    64,    71,   109,   114
+      26,    35,    40,    42,    43,    51,    59,    71,    86,   103,
+     109,   115,   125,   131,   137,   143,    34,    29,    45,    46,
+      47,    48,    49,    61,    62,    63,    64,    65,   117,   118,
+     119,   120,   121,    52,   104,   132,   144,    75,    77,    78,
+      79,    80,    90,    92,    93,    96,    97,   126,   110,   138,
+      44,    60,   116,    53,   105,   133,   145,    72,    87,   127,
+     111,   139,    38,    28,   153,    30,    50,   153,    68,    69,
+     153,   122,   123,    54,    55,   153,   106,   107,   153,   134,
+     135,   153,   146,   147,   153,   153,    83,    84,   153,   100,
+     101,   128,   129,   153,   112,   113,   153,   140,   141,   153,
+      45,    61,   117,    54,   106,   134,   146,    75,    90,   128,
+     112,   140,    40,    29,   149,   150,   151,   152,    30,    30,
+      30,    30,    30,    30,    30,    30,    30,    30,    30,    29,
+      31,    70,   149,    68,   124,    48,    56,    57,    58,    64,
+     108,   120,   136,    40,   148,   153,    85,   149,    64,    71,
+     102,    10,    11,    22,    23,    66,    67,    73,    88,   130,
+      64,    71,   114,   120,   125,   142,    29,    31,    32,    31,
+      32,    31,    32,   149,    31,    32,    31,    32,    31,    32,
+      31,    32,    31,    32,    76,    77,    81,    82,    91,    94,
+      95,    98,    99,    74,    89,    68,    31,    32,    31,    32,
+      31,    32,    29,   149,    68,    57,    64,   120,    40,   149,
+      64,    71,    83,   153,   100,    76,    91,    66,    73,    88,
+      64,    71,   120,   125
 };
 
 #define yyerrok		(yyerrstatus = 0)
@@ -1784,7 +1811,7 @@
 
   case 51:
 #line 137 "wktparse.y"
-    { pop(); }
+    { check_linestring(); pop(); }
     break;
 
   case 52:
@@ -1794,7 +1821,7 @@
 
   case 53:
 #line 140 "wktparse.y"
-    { pop(); }
+    { check_closed_linestring(); pop(); }
     break;
 
   case 54:
@@ -1804,7 +1831,7 @@
 
   case 55:
 #line 143 "wktparse.y"
-    { popc(); }
+    { pop(); }
     break;
 
   case 59:
@@ -1834,7 +1861,7 @@
 
   case 71:
 #line 176 "wktparse.y"
-    { pop(); }
+    { check_circularstring(); pop(); }
     break;
 
   case 72:
@@ -1844,7 +1871,7 @@
 
   case 73:
 #line 179 "wktparse.y"
-    { pop(); }
+    { check_closed_circularstring(); pop(); }
     break;
 
   case 74:
@@ -1854,277 +1881,307 @@
 
   case 75:
 #line 182 "wktparse.y"
-    { popc(); }
+    { pop(); }
     break;
 
-  case 78:
-#line 192 "wktparse.y"
+  case 79:
+#line 194 "wktparse.y"
+    { set_zm(0, 1); }
+    break;
+
+  case 82:
+#line 199 "wktparse.y"
+    { set_zm(0, 1); }
+    break;
+
+  case 88:
+#line 212 "wktparse.y"
     { alloc_compoundcurve(); }
     break;
 
-  case 79:
-#line 192 "wktparse.y"
+  case 89:
+#line 212 "wktparse.y"
     { pop(); }
     break;
 
-  case 80:
-#line 194 "wktparse.y"
-    {set_zm(0, 1); alloc_compoundcurve(); }
+  case 90:
+#line 215 "wktparse.y"
+    { alloc_compoundcurve_closed(); }
     break;
 
-  case 81:
-#line 194 "wktparse.y"
+  case 91:
+#line 215 "wktparse.y"
     { pop(); }
     break;
 
-  case 83:
-#line 199 "wktparse.y"
+  case 92:
+#line 218 "wktparse.y"
+    { alloc_compoundcurve(); }
+    break;
+
+  case 93:
+#line 218 "wktparse.y"
+    {  check_compoundcurve(); pop(); }
+    break;
+
+  case 94:
+#line 221 "wktparse.y"
+    { alloc_compoundcurve_closed(); }
+    break;
+
+  case 95:
+#line 221 "wktparse.y"
+    {  check_closed_compoundcurve(); pop(); }
+    break;
+
+  case 96:
+#line 224 "wktparse.y"
     { alloc_counter(); }
     break;
 
-  case 84:
-#line 199 "wktparse.y"
-    { pop(); }
+  case 97:
+#line 224 "wktparse.y"
+    {pop();}
     break;
 
-  case 89:
-#line 213 "wktparse.y"
+  case 102:
+#line 238 "wktparse.y"
     { alloc_multilinestring(); }
     break;
 
-  case 90:
-#line 214 "wktparse.y"
+  case 103:
+#line 239 "wktparse.y"
     { pop(); }
     break;
 
-  case 91:
-#line 216 "wktparse.y"
+  case 104:
+#line 241 "wktparse.y"
     { set_zm(0, 1); alloc_multilinestring(); }
     break;
 
-  case 92:
-#line 217 "wktparse.y"
+  case 105:
+#line 242 "wktparse.y"
     { pop(); }
     break;
 
-  case 94:
-#line 222 "wktparse.y"
+  case 107:
+#line 247 "wktparse.y"
     { alloc_counter(); }
     break;
 
-  case 95:
-#line 222 "wktparse.y"
+  case 108:
+#line 247 "wktparse.y"
     { pop();}
     break;
 
-  case 98:
-#line 232 "wktparse.y"
+  case 111:
+#line 257 "wktparse.y"
     { alloc_multicurve(); }
     break;
 
-  case 99:
-#line 233 "wktparse.y"
+  case 112:
+#line 258 "wktparse.y"
     { pop(); }
     break;
 
-  case 100:
-#line 235 "wktparse.y"
+  case 113:
+#line 260 "wktparse.y"
     { set_zm(0, 1); alloc_multicurve(); }
     break;
 
-  case 101:
-#line 236 "wktparse.y"
+  case 114:
+#line 261 "wktparse.y"
     { pop(); }
     break;
 
-  case 103:
-#line 241 "wktparse.y"
+  case 116:
+#line 266 "wktparse.y"
     { alloc_counter(); }
     break;
 
-  case 104:
-#line 241 "wktparse.y"
+  case 117:
+#line 266 "wktparse.y"
     { pop(); }
     break;
 
-  case 110:
-#line 257 "wktparse.y"
+  case 123:
+#line 282 "wktparse.y"
     { set_zm(0, 1); }
     break;
 
-  case 114:
-#line 265 "wktparse.y"
+  case 127:
+#line 290 "wktparse.y"
     { alloc_polygon(); }
     break;
 
-  case 115:
-#line 265 "wktparse.y"
+  case 128:
+#line 290 "wktparse.y"
     { pop(); }
     break;
 
-  case 116:
-#line 268 "wktparse.y"
+  case 129:
+#line 293 "wktparse.y"
     { alloc_polygon(); }
     break;
 
-  case 117:
-#line 268 "wktparse.y"
-    { pop(); }
+  case 130:
+#line 293 "wktparse.y"
+    { check_polygon(); pop(); }
     break;
 
-  case 118:
-#line 271 "wktparse.y"
+  case 131:
+#line 296 "wktparse.y"
     { alloc_counter(); }
     break;
 
-  case 119:
-#line 271 "wktparse.y"
+  case 132:
+#line 296 "wktparse.y"
     { pop();}
     break;
 
-  case 122:
-#line 281 "wktparse.y"
+  case 135:
+#line 308 "wktparse.y"
     { alloc_curvepolygon(); }
     break;
 
-  case 123:
-#line 281 "wktparse.y"
-    { pop(); }
+  case 136:
+#line 308 "wktparse.y"
+    { check_curvepolygon(); pop(); }
     break;
 
-  case 124:
-#line 283 "wktparse.y"
+  case 137:
+#line 310 "wktparse.y"
     { set_zm(0, 1); alloc_curvepolygon(); }
     break;
 
-  case 125:
-#line 284 "wktparse.y"
-    { pop(); }
+  case 138:
+#line 311 "wktparse.y"
+    { check_curvepolygon(); pop(); }
     break;
 
-  case 127:
-#line 289 "wktparse.y"
+  case 140:
+#line 316 "wktparse.y"
     { alloc_counter(); }
     break;
 
-  case 128:
-#line 289 "wktparse.y"
+  case 141:
+#line 316 "wktparse.y"
     { pop(); }
     break;
 
-  case 133:
-#line 303 "wktparse.y"
+  case 148:
+#line 334 "wktparse.y"
     { alloc_multipolygon(); }
     break;
 
-  case 134:
-#line 303 "wktparse.y"
+  case 149:
+#line 334 "wktparse.y"
     { pop(); }
     break;
 
-  case 135:
-#line 305 "wktparse.y"
+  case 150:
+#line 336 "wktparse.y"
     { set_zm(0, 1); alloc_multipolygon(); }
     break;
 
-  case 136:
-#line 306 "wktparse.y"
+  case 151:
+#line 337 "wktparse.y"
     { pop();}
     break;
 
-  case 138:
-#line 311 "wktparse.y"
+  case 153:
+#line 342 "wktparse.y"
     { alloc_counter(); }
     break;
 
-  case 139:
-#line 311 "wktparse.y"
+  case 154:
+#line 342 "wktparse.y"
     { pop(); }
     break;
 
-  case 142:
-#line 321 "wktparse.y"
+  case 157:
+#line 352 "wktparse.y"
     {alloc_multisurface(); }
     break;
 
-  case 143:
-#line 321 "wktparse.y"
+  case 158:
+#line 352 "wktparse.y"
     { pop(); }
     break;
 
-  case 144:
-#line 323 "wktparse.y"
+  case 159:
+#line 354 "wktparse.y"
     { set_zm(0, 1); alloc_multisurface(); }
     break;
 
-  case 145:
-#line 324 "wktparse.y"
+  case 160:
+#line 355 "wktparse.y"
     { pop(); }
     break;
 
-  case 147:
-#line 329 "wktparse.y"
+  case 162:
+#line 360 "wktparse.y"
     { alloc_counter(); }
     break;
 
-  case 148:
-#line 329 "wktparse.y"
+  case 163:
+#line 360 "wktparse.y"
     { pop(); }
     break;
 
-  case 153:
-#line 343 "wktparse.y"
+  case 168:
+#line 374 "wktparse.y"
     { alloc_geomertycollection(); }
     break;
 
-  case 154:
-#line 344 "wktparse.y"
+  case 169:
+#line 375 "wktparse.y"
     { pop(); }
     break;
 
-  case 155:
-#line 346 "wktparse.y"
+  case 170:
+#line 377 "wktparse.y"
     { set_zm(0, 1); alloc_geomertycollection(); }
     break;
 
-  case 156:
-#line 347 "wktparse.y"
+  case 171:
+#line 378 "wktparse.y"
     { pop();}
     break;
 
-  case 158:
-#line 352 "wktparse.y"
+  case 173:
+#line 383 "wktparse.y"
     { alloc_counter(); }
     break;
 
-  case 159:
-#line 352 "wktparse.y"
+  case 174:
+#line 383 "wktparse.y"
     { pop(); }
     break;
 
-  case 166:
-#line 371 "wktparse.y"
+  case 181:
+#line 402 "wktparse.y"
     {alloc_point_2d((yyvsp[(1) - (2)].value),(yyvsp[(2) - (2)].value)); }
     break;
 
-  case 167:
-#line 374 "wktparse.y"
+  case 182:
+#line 405 "wktparse.y"
     {alloc_point_3d((yyvsp[(1) - (3)].value),(yyvsp[(2) - (3)].value),(yyvsp[(3) - (3)].value)); }
     break;
 
-  case 168:
-#line 377 "wktparse.y"
+  case 183:
+#line 408 "wktparse.y"
     {alloc_point_4d((yyvsp[(1) - (4)].value),(yyvsp[(2) - (4)].value),(yyvsp[(3) - (4)].value),(yyvsp[(4) - (4)].value)); }
     break;
 
-  case 169:
-#line 380 "wktparse.y"
+  case 184:
+#line 411 "wktparse.y"
     { alloc_empty(); }
     break;
 
 
 /* Line 1267 of yacc.c.  */
-#line 2128 "y.tab.c"
+#line 2185 "y.tab.c"
       default: break;
     }
   YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
@@ -2344,7 +2401,7 @@
 }
 
 
-#line 381 "wktparse.y"
+#line 412 "wktparse.y"
 
 
 

Modified: trunk/liblwgeom/wktparse.y
===================================================================
--- trunk/liblwgeom/wktparse.y	2009-03-09 22:01:04 UTC (rev 3820)
+++ trunk/liblwgeom/wktparse.y	2009-03-10 00:29:32 UTC (rev 3821)
@@ -134,13 +134,13 @@
 	{ alloc_linestring(); } empty { pop(); } 
 
 nonempty_linestring :
-	{ alloc_linestring(); } linestring_1 { pop(); } 
+	{ alloc_linestring(); } linestring_1 { check_linestring(); pop(); } 
 
 nonempty_linestring_closed :
-        { alloc_linestring_closed(); } linestring_1 { pop(); }
+        { alloc_linestring_closed(); } linestring_1 { check_closed_linestring(); pop(); }
 
 linestring_1 :
-	{ alloc_counter(); } LPAREN linestring_int RPAREN { popc(); }
+	{ alloc_counter(); } LPAREN linestring_int RPAREN { pop(); }
 
 linestring_int :
 	a_point
@@ -173,13 +173,13 @@
         { alloc_circularstring(); } empty { pop(); }
 
 nonempty_circularstring :
-        { alloc_circularstring(); } circularstring_1 { pop(); }
+        { alloc_circularstring(); } circularstring_1 { check_circularstring(); pop(); }
 
 nonempty_circularstring_closed :
-        { alloc_circularstring_closed(); } circularstring_1 { pop(); }
+        { alloc_circularstring_closed(); } circularstring_1 { check_closed_circularstring(); pop(); }
 
 circularstring_1 :
-        { alloc_counter(); } LPAREN circularstring_int RPAREN { popc(); }
+        { alloc_counter(); } LPAREN circularstring_int RPAREN { pop(); }
 
 circularstring_int :
         a_point
@@ -189,15 +189,40 @@
 /* COMPOUNDCURVE */
 
 geom_compoundcurve:
-        COMPOUNDCURVE { alloc_compoundcurve(); } compoundcurve { pop(); }
-        |
-        COMPOUNDCURVEM {set_zm(0, 1); alloc_compoundcurve(); } compoundcurve { pop(); }
+	COMPOUNDCURVE compoundcurve
+	|
+	COMPOUNDCURVEM { set_zm(0, 1); } compoundcurve
 
+geom_compoundcurve_closed:
+	COMPOUNDCURVE compoundcurve_closed
+	|
+	COMPOUNDCURVEM { set_zm(0, 1); } compoundcurve_closed
+
 compoundcurve:
-        empty
-        |
-        { alloc_counter(); } LPAREN compoundcurve_int RPAREN { pop(); }
+	empty_compoundcurve
+	|
+	nonempty_compoundcurve
 
+compoundcurve_closed:
+	empty_compoundcurve_closed
+	|
+	nonempty_compoundcurve_closed
+
+empty_compoundcurve:
+	{ alloc_compoundcurve(); } empty { pop(); }
+
+empty_compoundcurve_closed:
+	{ alloc_compoundcurve_closed(); } empty { pop(); }
+
+nonempty_compoundcurve:
+	{ alloc_compoundcurve(); } compoundcurve_1 {  check_compoundcurve(); pop(); }
+
+nonempty_compoundcurve_closed:
+	{ alloc_compoundcurve_closed(); } compoundcurve_1 {  check_closed_compoundcurve(); pop(); }
+
+compoundcurve_1:
+	{ alloc_counter(); } LPAREN compoundcurve_int RPAREN {pop();}
+
 compoundcurve_int:
         nonempty_linestring
         |
@@ -265,23 +290,25 @@
 	{ alloc_polygon(); } empty  { pop(); } 
 
 nonempty_polygon :
-	{ alloc_polygon(); } polygon_1  { pop(); } 
+	{ alloc_polygon(); } polygon_1  { check_polygon(); pop(); } 
 
 polygon_1 :
 	{ alloc_counter(); } LPAREN polygon_int RPAREN { pop();} 
 
 polygon_int :
+	/* nonempty_linestring_closed */
 	linestring_1
 	|
+	/* polygon_int COMMA nonempty_linestring_closed */
 	polygon_int COMMA linestring_1
 
 /* CURVEPOLYGON */
 
 geom_curvepolygon :
-        CURVEPOLYGON { alloc_curvepolygon(); } curvepolygon { pop(); }
+        CURVEPOLYGON { alloc_curvepolygon(); } curvepolygon { check_curvepolygon(); pop(); }
         |
         CURVEPOLYGONM { set_zm(0, 1); alloc_curvepolygon(); } 
-                        curvepolygon { pop(); }
+                        curvepolygon { check_curvepolygon(); pop(); }
 
 curvepolygon :
         empty
@@ -293,9 +320,13 @@
         |
         geom_circularstring_closed
         |
+	geom_compoundcurve_closed
+	|
         curvepolygon_int COMMA nonempty_linestring_closed
         |
         curvepolygon_int COMMA geom_circularstring_closed
+	|
+	curvepolygon_int COMMA geom_compoundcurve_closed
 
 /* MULTIPOLYGON */
 

Modified: trunk/regress/sql-mm-compoundcurve.sql
===================================================================
--- trunk/regress/sql-mm-compoundcurve.sql	2009-03-09 22:01:04 UTC (rev 3820)
+++ trunk/regress/sql-mm-compoundcurve.sql	2009-03-10 00:29:32 UTC (rev 3821)
@@ -301,3 +301,18 @@
 SELECT DropGeometryColumn('public', 'compoundcurve', 'the_geom_3dm');
 SELECT DropGeometryColumn('public', 'compoundcurve', 'the_geom_2d');
 DROP TABLE public.compoundcurve;
+
+SELECT 'valid wkt compound curve 1', ST_GeomFromEWKT('COMPOUNDCURVE((153.72942375 -27.21757040, 152.29285719 -29.23940482, 154.74034096 -30.51635287),(154.74034096 -30.51635287, 152.39926953 -32.16574411, 155.11278414 -34.08116619, 151.86720784 -35.62414508))');
+SELECT 'valid wkt compound curve 2', ST_GeomFromEWKT('COMPOUNDCURVE((153.72942375 -27.21757040, 152.29285719 -29.23940482, 154.74034096 -30.51635287, 152.39926953 -32.16574411, 155.11278414 -34.08116619, 151.86720784 -35.62414508))');
+SELECT 'valid wkt compound curve 3', ST_GeomFromEWKT('COMPOUNDCURVE((151.60117699 -27.32398274, 151.22873381 -35.94338210, 150.74987829 -27.80283826))');
+SELECT 'valid wkt compound curve 4', ST_GeomFromEWKT('COMPOUNDCURVE((153.72942375 -27.21757040, 152.29285719 -29.23940482, 154.74034096 -30.51635287),CIRCULARSTRING(154.74034096 -30.51635287, 154.74034096 -30.51635287, 152.39926953 -32.16574411, 155.11278414 -34.08116619, 151.86720784 -35.62414508))');
+SELECT 'valid wkt compound curve 5', ST_GeomFromEWKT('COMPOUNDCURVE(CIRCULARSTRING(157.87950492 -27.59001358, 156.01728901 -28.28169378, 155.59163966 -26.52589021),(155.59163966 -26.52589021, 153.72942375 -27.21757040, 152.29285719 -29.23940482, 154.74034096 -30.51635287),CIRCULARSTRING(154.74034096 -30.51635287, 154.74034096 -30.51635287, 152.39926953 -32.16574411, 155.11278414 -34.08116619, 151.86720784 -35.62414508))');
+SELECT 'invalid wkt compound curve 1', ST_GeomFromEWKT('COMPOUNDCURVE((153.72942375 -27.21757040, 152.29285719 -29.23940482, 154.74034096 -30.51635287),(152.39926953 -32.16574411, 155.11278414 -34.08116619, 151.86720784 -35.62414508))');
+SELECT 'invalid wkt compound curve 2', ST_GeomFromEWKT('COMPOUNDCURVE((153.72942375 -27.21757040, 152.29285719 -29.23940482),CIRCULARSTRING(154.74034096 -30.51635287, 154.74034096 -30.51635287, 152.39926953 -32.16574411, 155.11278414 -34.08116619, 151.86720784 -35.62414508))');
+SELECT 'invalid wkt compound curve 3', ST_GeomFromEWKT('COMPOUNDCURVE(CIRCULARSTRING(157.87950492 -27.59001358, 156.01728901 -28.28169378, 155.59163966 -26.52589021, 153.72942375 -27.21757040),(153.72942375 -27.21757040, 152.29285719 -29.23940482),CIRCULARSTRING(154.74034096 -30.51635287, 154.74034096 -30.51635287, 152.39926953 -32.16574411, 155.11278414 -34.08116619, 151.86720784 -35.62414508))');
+SELECT 'valid wkb compound curve 1', ST_asEWKT(ST_GeomFromEWKB(decode('0109000000020000000102000000030000009FE5797057376340E09398B1B2373BC05AAE0A165F0963409F6760A2493D3DC0DB6286DFB057634082D8A1B32F843EC0010200000004000000DB6286DFB057634082D8A1B32F843EC075B4E4D0C60C634031FA5D1A371540C0D7197CED9B636340A3CB59A7630A41C050F4A72AC0FB6240974769FCE3CF41C0', 'hex')));
+SELECT 'valid wkb compound curve 2', ST_asEWKT(ST_GeomFromEWKB(decode('0109000000010000000102000000060000009FE5797057376340E09398B1B2373BC05AAE0A165F0963409F6760A2493D3DC0DB6286DFB057634082D8A1B32F843EC075B4E4D0C60C634031FA5D1A371540C0D7197CED9B636340A3CB59A7630A41C050F4A72AC0FB6240974769FCE3CF41C0', 'hex')));
+SELECT 'valid wkb compound curve 3', ST_asEWKT(ST_GeomFromEWKB(decode('0109000000010000000102000000030000000CE586D73CF36240BBC46888F0523BC0102E91C951E76240DF90A1BEC0F841C0F970C100FFD7624074ADE6CE86CD3BC0', 'hex')));
+SELECT 'valid wkb compound curve 4', ST_asEWKT(ST_GeomFromEWKB(decode('0109000000020000000102000000030000009FE5797057376340E09398B1B2373BC05AAE0A165F0963409F6760A2493D3DC0DB6286DFB057634082D8A1B32F843EC0010800000005000000DB6286DFB057634082D8A1B32F843EC0DB6286DFB057634082D8A1B32F843EC075B4E4D0C60C634031FA5D1A371540C0D7197CED9B636340A3CB59A7630A41C050F4A72AC0FB6240974769FCE3CF41C0', 'hex')));
+SELECT 'valid wkb compound curve 5', ST_asEWKT(ST_GeomFromEWKB(decode('010900000003000000010800000003000000468280E724BC6340BF4B46210B973BC0F890AEA18D8063402D9664151D483CC0EED64BB6EE726340903CA5BDA0863AC0010200000004000000EED64BB6EE726340903CA5BDA0863AC09FE5797057376340E09398B1B2373BC05AAE0A165F0963409F6760A2493D3DC0DB6286DFB057634082D8A1B32F843EC0010800000005000000DB6286DFB057634082D8A1B32F843EC0DB6286DFB057634082D8A1B32F843EC075B4E4D0C60C634031FA5D1A371540C0D7197CED9B636340A3CB59A7630A41C050F4A72AC0FB6240974769FCE3CF41C0', 'hex')));
+

Modified: trunk/regress/sql-mm-compoundcurve_expected.in
===================================================================
--- trunk/regress/sql-mm-compoundcurve_expected.in	2009-03-09 22:01:04 UTC (rev 3820)
+++ trunk/regress/sql-mm-compoundcurve_expected.in	2009-03-10 00:29:32 UTC (rev 3821)
@@ -119,3 +119,19 @@
 public.compoundcurve.the_geom_3dz effectively removed.
 public.compoundcurve.the_geom_3dm effectively removed.
 public.compoundcurve.the_geom_2d effectively removed.
+valid wkt compound curve 1|0109000000020000000102000000030000009FE5797057376340E09398B1B2373BC05AAE0A165F0963409F6760A2493D3DC0DB6286DFB057634082D8A1B32F843EC0010200000004000000DB6286DFB057634082D8A1B32F843EC075B4E4D0C60C634031FA5D1A371540C0D7197CED9B636340A3CB59A7630A41C050F4A72AC0FB6240974769FCE3CF41C0
+valid wkt compound curve 2|0109000000010000000102000000060000009FE5797057376340E09398B1B2373BC05AAE0A165F0963409F6760A2493D3DC0DB6286DFB057634082D8A1B32F843EC075B4E4D0C60C634031FA5D1A371540C0D7197CED9B636340A3CB59A7630A41C050F4A72AC0FB6240974769FCE3CF41C0
+valid wkt compound curve 3|0109000000010000000102000000030000000CE586D73CF36240BBC46888F0523BC0102E91C951E76240DF90A1BEC0F841C0F970C100FFD7624074ADE6CE86CD3BC0
+valid wkt compound curve 4|0109000000020000000102000000030000009FE5797057376340E09398B1B2373BC05AAE0A165F0963409F6760A2493D3DC0DB6286DFB057634082D8A1B32F843EC0010800000005000000DB6286DFB057634082D8A1B32F843EC0DB6286DFB057634082D8A1B32F843EC075B4E4D0C60C634031FA5D1A371540C0D7197CED9B636340A3CB59A7630A41C050F4A72AC0FB6240974769FCE3CF41C0
+valid wkt compound curve 5|010900000003000000010800000003000000468280E724BC6340BF4B46210B973BC0F890AEA18D8063402D9664151D483CC0EED64BB6EE726340903CA5BDA0863AC0010200000004000000EED64BB6EE726340903CA5BDA0863AC09FE5797057376340E09398B1B2373BC05AAE0A165F0963409F6760A2493D3DC0DB6286DFB057634082D8A1B32F843EC0010800000005000000DB6286DFB057634082D8A1B32F843EC0DB6286DFB057634082D8A1B32F843EC075B4E4D0C60C634031FA5D1A371540C0D7197CED9B636340A3CB59A7630A41C050F4A72AC0FB6240974769FCE3CF41C0
+ERROR:  incontinuous compound curve
+HINT:  "....23940482, 154.74034096 -30.51635287)" <-- parse error at position 95 within geometry
+ERROR:  incontinuous compound curve
+HINT:  "....21757040, 152.29285719 -29.23940482)" <-- parse error at position 68 within geometry
+ERROR:  geometry must have an odd number of points
+HINT:  "....52589021, 153.72942375 -27.21757040)" <-- parse error at position 136 within geometry
+valid wkb compound curve 1|COMPOUNDCURVE((153.72942375 -27.2175704,152.29285719 -29.23940482,154.74034096 -30.51635287),(154.74034096 -30.51635287,152.39926953 -32.16574411,155.11278414 -34.08116619,151.86720784 -35.62414508))
+valid wkb compound curve 2|COMPOUNDCURVE((153.72942375 -27.2175704,152.29285719 -29.23940482,154.74034096 -30.51635287,152.39926953 -32.16574411,155.11278414 -34.08116619,151.86720784 -35.62414508))
+valid wkb compound curve 3|COMPOUNDCURVE((151.60117699 -27.32398274,151.22873381 -35.9433821,150.74987829 -27.80283826))
+valid wkb compound curve 4|COMPOUNDCURVE((153.72942375 -27.2175704,152.29285719 -29.23940482,154.74034096 -30.51635287),CIRCULARSTRING(154.74034096 -30.51635287,154.74034096 -30.51635287,152.39926953 -32.16574411,155.11278414 -34.08116619,151.86720784 -35.62414508))
+valid wkb compound curve 5|COMPOUNDCURVE(CIRCULARSTRING(157.87950492 -27.59001358,156.01728901 -28.28169378,155.59163966 -26.52589021),(155.59163966 -26.52589021,153.72942375 -27.2175704,152.29285719 -29.23940482,154.74034096 -30.51635287),CIRCULARSTRING(154.74034096 -30.51635287,154.74034096 -30.51635287,152.39926953 -32.16574411,155.11278414 -34.08116619,151.86720784 -35.62414508))

Modified: trunk/regress/sql-mm-curvepoly.sql
===================================================================
--- trunk/regress/sql-mm-curvepoly.sql	2009-03-09 22:01:04 UTC (rev 3820)
+++ trunk/regress/sql-mm-curvepoly.sql	2009-03-10 00:29:32 UTC (rev 3821)
@@ -102,7 +102,16 @@
                 1 0,
                 0 1,
                 -1 0))'));
+SELECT 'ndims05', ndims(geomfromewkt('CURVEPOLYGON(
+                COMPOUNDCURVE(
+                    (5 5 1 0,5 0 1 1,0 0 1 2,0 5 1 3),
+                    CIRCULARSTRING(0 5 1 3,1.5 7.5 1 4,5 5 1 0)),
+                (1.5 5 2 0,2.5 6 3 1,3.5 5 2 2,1.5 5 2 0),
+                COMPOUNDCURVE(
+                    CIRCULARSTRING(1.5 2 2 0,1 2.5 3 1,3.5 2 2 2),
+                    (3.5 2 2 2,3.5 4 1 3,1.5 4 1 4,1.5 2 2 0)))'));
 
+
 -- Repeat tests with new function names.
 SELECT 'ndims01', ST_ndims(ST_geomfromewkt('CURVEPOLYGON(CIRCULARSTRING(
                 -2 0 0 0,
@@ -472,3 +481,24 @@
 SELECT DropGeometryColumn('public', 'curvepolygon', 'the_geom_3dz');
 SELECT DropGeometryColumn('public', 'curvepolygon', 'the_geom_4d');
 DROP TABLE public.curvepolygon;
+
+SELECT 'valid wkt curve polygon 1', ST_GeomFromEWKT('CURVEPOLYGON((143.62025166838282 -30.037497356076827, 142.92857147299705 -32.75101196874403, 145.96132309891922 -34.985671061528784, 149.57565307617188 -33.41153335571289, 149.41972407584802 -29.824672680573517, 146.1209416055467 -30.19711586270431, 143.62025166838282 -30.037497356076827))');
+SELECT 'valid wkt curve polygon 2', ST_GeomFromEWKT('CURVEPOLYGON((143.62025166838282 -30.037497356076827, 142.92857147299705 -32.75101196874403, 145.96132309891922 -34.985671061528784, 149.57565307617188 -33.41153335571289, 149.41972407584802 -29.824672680573517, 146.1209416055467 -30.19711586270431, 143.62025166838282 -30.037497356076827),(144.84399355252685 -31.26123924022086, 144.20551952601693 -32.27215644886158, 145.55230712890625 -33.49203872680664, 147.97080993652344 -32.03618621826172, 146.38697244992585 -31.47406391572417, 144.84399355252685 -31.26123924022086))');
+SELECT 'valid wkt curve polygon 3', ST_GeomFromEWKT('CURVEPOLYGON(CIRCULARSTRING(143.62025166838282 -30.037497356076827, 142.92857147299705 -32.75101196874403, 145.96132309891922 -34.985671061528784, 149.57565307617188 -33.41153335571289, 149.41972407584802 -29.824672680573517, 146.1209416055467 -30.19711586270431, 143.62025166838282 -30.037497356076827))');
+SELECT 'valid wkt curve polygon 4',
+  ST_GeomFromEWKT('CURVEPOLYGON(CIRCULARSTRING(143.62025166838282 -30.037497356076827, 142.92857147299705 -32.75101196874403, 145.96132309891922 -34.985671061528784, 149.57565307617188 -33.41153335571289, 149.41972407584802 -29.824672680573517, 146.1209416055467 -30.19711586270431, 143.62025166838282 -30.037497356076827),(144.84399355252685 -31.26123924022086, 144.20551952601693 -32.27215644886158, 145.55230712890625 -33.49203872680664, 147.97080993652344 -32.03618621826172, 146.38697244992585 -31.47406391572417, 144.84399355252685 -31.26123924022086))');
+SELECT 'valid wkt curve polygon 5', ST_GeomFromEWKT('CURVEPOLYGON((143.62025166838282 -30.037497356076827, 142.92857147299705 -32.75101196874403, 145.96132309891922 -34.985671061528784, 149.57565307617188 -33.41153335571289, 149.41972407584802 -29.824672680573517, 146.1209416055467 -30.19711586270431, 143.62025166838282 -30.037497356076827),COMPOUNDCURVE(CIRCULARSTRING(144.84399355252685 -31.26123924022086, 144.20551952601693 -32.27215644886158, 145.55230712890625 -33.49203872680664), (145.55230712890625 -33.49203872680664, 147.97080993652344 -32.03618621826172),CIRCULARSTRING(147.97080993652344 -32.03618621826172, 146.38697244992585 -31.47406391572417, 144.84399355252685 -31.26123924022086)))');
+SELECT 'invalid wkt curve polygon 4', ST_GeomFromEWKT('CURVEPOLYGON((143.62025166838282 -30.037497356076827, 142.92857147299705 -32.75101196874403, 145.96132309891922 -34.985671061528784, 149.57565307617188 -33.41153335571289, 149.41972407584802 -29.824672680573517, 146.1209416055467 -30.19711586270431, 143.62025166838282 -30.037497356076))');
+SELECT 'invalid wkt curve polygon 5', ST_GeomFromEWKT('CURVEPOLYGON((143.62025166838282 -30.037497356076827, 142.92857147299705 -32.75101196874403, 145.96132309891922 -34.985671061528784, 149.57565307617188 -33.41153335571289, 149.41972407584802 -29.824672680573517, 146.1209416055467 -30.19711586270431, 143.62025166838282 -30.037497356076827),(144.84399355252685 -31.26123924022086, 144.20551952601693 -32.27215644886158, 145.55230712890625 -33.49203872680664, 147.97080993652344 -32.03618621826172, 146.38697244992585 -31.47406391572417))');
+SELECT 'invalid wkt curve polygon 6', ST_GeomFromEWKT('CURVEPOLYGON((143.62025166838282 -30.037497356076827, 142.92857147299705 -32.75101196874403, 145.96132309891922 -34.985671061528784, 149.57565307617188 -33.41153335571289, 149.41972407584802 -29.824672680573517, 146.1209416055467 -30.19711586270431),(144.84399355252685 -31.26123924022086, 144.20551952601693 -32.27215644886158, 145.55230712890625 -33.49203872680664, 147.97080993652344 -32.03618621826172, 146.38697244992585 -31.47406391572417, 144.84399355252685 -31.26123924022086))');
+SELECT 'invalid wkt curve polygon 7', ST_GeomFromEWKT('CURVEPOLYGON(CIRCULARSTRING(143.62025166838282 -30.037497356076827, 142.92857147299705 -32.75101196874403, 145.96132309891922 -34.985671061528784, 149.57565307617188 -33.41153335571289, 149.41972407584802 -29.824672680573517, 143.62025166838282 -30.037497356076827))');
+SELECT 'invalid wkt curve polygon 8', ST_GeomFromEWKT('CURVEPOLYGON(CIRCULARSTRING(143.62025166838282 -30.037497356076827, 142.92857147299705 -32.75101196874403, 145.96132309891922 -34.985671061528784, 149.57565307617188 -33.41153335571289, 149.41972407584802 -29.824672680573517, 146.1209416055467 -30.19711586270431),(144.84399355252685 -31.26123924022086, 144.20551952601693 -32.27215644886158, 145.55230712890625 -33.49203872680664, 147.97080993652344 -32.03618621826172, 146.38697244992585 -31.47406391572417, 144.84399355252685 -31.26123924022086))');
+SELECT 'invalid wkt curve polygon 9', ST_GeomFromEWKT('CURVEPOLYGON((143.62025166838282 -30.037497356076827, 142.92857147299705 -32.75101196874403, 145.96132309891922 -34.985671061528784, 149.57565307617188 -33.41153335571289, 149.41972407584802 -29.824672680573517, 146.1209416055467 -30.19711586270431, 143.62025166838282 -30.037497356076827),COMPOUNDCURVE(CIRCULARSTRING(144.84399355252685 -31.26123924022086, 144.20551952601693 -32.27215644886158, 145.55230712890625 -33.49203872680664),CIRCULARSTRING(147.97080993652344 -32.03618621826172, 146.38697244992585 -31.47406391572417, 144.84399355252685 -31.26123924022086))');
+SELECT 'invalid wkt curve polygon a', ST_GeomFromEWKT('CURVEPOLYGON((143.62025166838282 -30.037497356076827, 142.92857147299705 -32.75101196874403, 145.96132309891922 -34.985671061528784, 149.57565307617188 -33.41153335571289, 149.41972407584802 -29.824672680573517, 146.1209416055467 -30.19711586270431, 143.62025166838282 -30.037497356076827),COMPOUNDCURVE(CIRCULARSTRING(144.84399355252685 -31.26123924022086, 144.20551952601693 -32.27215644886158, 145.55230712890625 -33.49203872680664),(145.55230712890625 -33.49203872680664, 147.97080993652344 -32.03618621826172),CIRCULARSTRING(147.97080993652344 -32.03618621826172, 146.38697244992585 -31.47406391572417, 144.84399355252685 -30.76123924022086))');
+SELECT 'invalid wkt curve polygon b', ST_GeomFromEWKT('CURVEPOLYGON((143.62025166838282 -30.037497356076827, 142.92857147299705 -32.75101196874403, 145.96132309891922 -34.985671061528784, 149.57565307617188 -33.41153335571289, 149.41972407584802 -29.824672680573517, 146.1209416055467 -30.19711586270431, 143.62025166838282 -30.037497356076827),COMPOUNDCURVE(CIRCULARSTRING(144.84399355252685 -31.26123924022086, 144.20551952601693 -32.27215644886158, 145.55230712890625 -33.49203872680664),(145.55230712890625 -33.49203872680664),CIRCULARSTRING(147.97080993652344 -32.03618621826172, 146.38697244992585 -31.47406391572417, 144.84399355252685 -31.26123924022086))');
+SELECT 'valid ewkb curve polygon 1', ST_asEWKT(ST_GeomFromEWKB(decode('010d00000001000000010200000007000000ccdf061ad9f3614054093e6d99093ec0ab9085dbb6dd614081540229216040c0ebd7a828c33e62409bf026782a7e41c0000000c06bb2624000000020adb440c08e632f616ead6240c9f7b0bf1dd33dc09011eec0de4362407dd6672f76323ec0ccdf061ad9f3614054093e6d99093ec0', 'hex')));
+SELECT 'valid ewkb curve polygon 2', ST_asEWKT(ST_GeomFromEWKB(decode('010d00000002000000010200000007000000ccdf061ad9f3614054093e6d99093ec0ab9085dbb6dd614081540229216040c0ebd7a828c33e62409bf026782a7e41c0000000c06bb2624000000020adb440c08e632f616ead6240c9f7b0bf1dd33dc09011eec0de4362407dd6672f76323ec0ccdf061ad9f3614054093e6d99093ec00102000000060000006844c4fe011b6240342e2993e0423fc0d45daf9d93066240c4a0c305d62240c000000080ac31624000000020fbbe40c0000000e0107f6240000000c0a10440c04e1c0c14624c6240bf3fb6405c793fc06844c4fe011b6240342e2993e0423fc0', 'hex')));
+SELECT 'valid ewkb curve polygon 3', ST_asEWKT(ST_GeomFromEWKB(decode('010d00000001000000010800000007000000ccdf061ad9f3614054093e6d99093ec0ab9085dbb6dd614081540229216040c0ebd7a828c33e62409bf026782a7e41c0000000c06bb2624000000020adb440c08e632f616ead6240c9f7b0bf1dd33dc09011eec0de4362407dd6672f76323ec0ccdf061ad9f3614054093e6d99093ec0', 'hex')));
+SELECT 'valid ewkb curve polygon 4', ST_asEWKT(ST_GeomFromEWKB(decode('010d00000002000000010800000007000000ccdf061ad9f3614054093e6d99093ec0ab9085dbb6dd614081540229216040c0ebd7a828c33e62409bf026782a7e41c0000000c06bb2624000000020adb440c08e632f616ead6240c9f7b0bf1dd33dc09011eec0de4362407dd6672f76323ec0ccdf061ad9f3614054093e6d99093ec00102000000060000006844c4fe011b6240342e2993e0423fc0d45daf9d93066240c4a0c305d62240c000000080ac31624000000020fbbe40c0000000e0107f6240000000c0a10440c04e1c0c14624c6240bf3fb6405c793fc06844c4fe011b6240342e2993e0423fc0', 'hex')));
+SELECT 'valid ewkb curve polygon 5', ST_asEWKT(ST_GeomFromEWKB(decode('010d00000002000000010200000007000000ccdf061ad9f3614054093e6d99093ec0ab9085dbb6dd614081540229216040c0ebd7a828c33e62409bf026782a7e41c0000000c06bb2624000000020adb440c08e632f616ead6240c9f7b0bf1dd33dc09011eec0de4362407dd6672f76323ec0ccdf061ad9f3614054093e6d99093ec00109000000030000000108000000030000006844c4fe011b6240342e2993e0423fc0d45daf9d93066240c4a0c305d62240c000000080ac31624000000020fbbe40c001020000000200000000000080ac31624000000020fbbe40c0000000e0107f6240000000c0a10440c0010800000003000000000000e0107f6240000000c0a10440c04e1c0c14624c6240bf3fb6405c793fc06844c4fe011b6240342e2993e0423fc0', 'hex')));
+

Modified: trunk/regress/sql-mm-curvepoly_expected.in
===================================================================
--- trunk/regress/sql-mm-curvepoly_expected.in	2009-03-09 22:01:04 UTC (rev 3820)
+++ trunk/regress/sql-mm-curvepoly_expected.in	2009-03-10 00:29:32 UTC (rev 3821)
@@ -7,6 +7,7 @@
 geometrytype03|CURVEPOLYGONM
 ndims04|2
 geometrytype04|CURVEPOLYGON
+ndims05|4
 ndims01|4
 geometrytype01|CURVEPOLYGON
 ndims02|3
@@ -145,3 +146,29 @@
 public.curvepolygon.the_geom_3dm effectively removed.
 public.curvepolygon.the_geom_3dz effectively removed.
 public.curvepolygon.the_geom_4d effectively removed.
+valid wkt curve polygon 1|010D00000001000000010200000007000000CCDF061AD9F3614054093E6D99093EC0AB9085DBB6DD614081540229216040C0EBD7A828C33E62409BF026782A7E41C0000000C06BB2624000000020ADB440C08E632F616EAD6240C9F7B0BF1DD33DC09011EEC0DE4362407DD6672F76323EC0CCDF061AD9F3614054093E6D99093EC0
+valid wkt curve polygon 2|010D00000002000000010200000007000000CCDF061AD9F3614054093E6D99093EC0AB9085DBB6DD614081540229216040C0EBD7A828C33E62409BF026782A7E41C0000000C06BB2624000000020ADB440C08E632F616EAD6240C9F7B0BF1DD33DC09011EEC0DE4362407DD6672F76323EC0CCDF061AD9F3614054093E6D99093EC00102000000060000006844C4FE011B6240342E2993E0423FC0D45DAF9D93066240C4A0C305D62240C000000080AC31624000000020FBBE40C0000000E0107F6240000000C0A10440C04E1C0C14624C6240BF3FB6405C793FC06844C4FE011B6240342E2993E0423FC0
+valid wkt curve polygon 3|010D00000001000000010800000007000000CCDF061AD9F3614054093E6D99093EC0AB9085DBB6DD614081540229216040C0EBD7A828C33E62409BF026782A7E41C0000000C06BB2624000000020ADB440C08E632F616EAD6240C9F7B0BF1DD33DC09011EEC0DE4362407DD6672F76323EC0CCDF061AD9F3614054093E6D99093EC0
+valid wkt curve polygon 4|010D00000002000000010800000007000000CCDF061AD9F3614054093E6D99093EC0AB9085DBB6DD614081540229216040C0EBD7A828C33E62409BF026782A7E41C0000000C06BB2624000000020ADB440C08E632F616EAD6240C9F7B0BF1DD33DC09011EEC0DE4362407DD6672F76323EC0CCDF061AD9F3614054093E6D99093EC00102000000060000006844C4FE011B6240342E2993E0423FC0D45DAF9D93066240C4A0C305D62240C000000080AC31624000000020FBBE40C0000000E0107F6240000000C0A10440C04E1C0C14624C6240BF3FB6405C793FC06844C4FE011B6240342E2993E0423FC0
+valid wkt curve polygon 5|010D00000002000000010200000007000000CCDF061AD9F3614054093E6D99093EC0AB9085DBB6DD614081540229216040C0EBD7A828C33E62409BF026782A7E41C0000000C06BB2624000000020ADB440C08E632F616EAD6240C9F7B0BF1DD33DC09011EEC0DE4362407DD6672F76323EC0CCDF061AD9F3614054093E6D99093EC00109000000030000000108000000030000006844C4FE011B6240342E2993E0423FC0D45DAF9D93066240C4A0C305D62240C000000080AC31624000000020FBBE40C001020000000200000000000080AC31624000000020FBBE40C0000000E0107F6240000000C0A10440C0010800000003000000000000E0107F6240000000C0A10440C04E1C0C14624C6240BF3FB6405C793FC06844C4FE011B6240342E2993E0423FC0
+ERROR:  geometry contains non-closed rings
+HINT:  "... 143.62025166838282 -30.037497356076)" <-- parse error at position 286 within geometry
+ERROR:  geometry contains non-closed rings
+HINT:  "...46.38697244992585 -31.47406391572417)" <-- parse error at position 485 within geometry
+ERROR:  geometry contains non-closed rings
+HINT:  "...146.1209416055467 -30.19711586270431)" <-- parse error at position 249 within geometry
+ERROR:  geometry must have an odd number of points
+HINT:  "...3.62025166838282 -30.037497356076827)" <-- parse error at position 265 within geometry
+ERROR:  geometry contains non-closed rings
+HINT:  "...146.1209416055467 -30.19711586270431)" <-- parse error at position 263 within geometry
+ERROR:  incontinuous compound curve
+HINT:  "...45.55230712890625 -33.49203872680664)" <-- parse error at position 435 within geometry
+ERROR:  geometry contains non-closed rings
+HINT:  "...44.84399355252685 -30.76123924022086)" <-- parse error at position 646 within geometry
+ERROR:  geometry requires more points
+HINT:  "...45.55230712890625 -33.49203872680664)" <-- parse error at position 475 within geometry
+valid ewkb curve polygon 1|CURVEPOLYGON((143.620251668383 -30.0374973560768,142.928571472997 -32.751011968744,145.961323098919 -34.9856710615288,149.575653076172 -33.4115333557129,149.419724075848 -29.8246726805735,146.120941605547 -30.1971158627043,143.620251668383 -30.0374973560768))
+valid ewkb curve polygon 2|CURVEPOLYGON((143.620251668383 -30.0374973560768,142.928571472997 -32.751011968744,145.961323098919 -34.9856710615288,149.575653076172 -33.4115333557129,149.419724075848 -29.8246726805735,146.120941605547 -30.1971158627043,143.620251668383 -30.0374973560768),(144.843993552527 -31.2612392402209,144.205519526017 -32.2721564488616,145.552307128906 -33.4920387268066,147.970809936523 -32.0361862182617,146.386972449926 -31.4740639157242,144.843993552527 -31.2612392402209))
+valid ewkb curve polygon 3|CURVEPOLYGON(CIRCULARSTRING(143.620251668383 -30.0374973560768,142.928571472997 -32.751011968744,145.961323098919 -34.9856710615288,149.575653076172 -33.4115333557129,149.419724075848 -29.8246726805735,146.120941605547 -30.1971158627043,143.620251668383 -30.0374973560768))
+valid ewkb curve polygon 4|CURVEPOLYGON(CIRCULARSTRING(143.620251668383 -30.0374973560768,142.928571472997 -32.751011968744,145.961323098919 -34.9856710615288,149.575653076172 -33.4115333557129,149.419724075848 -29.8246726805735,146.120941605547 -30.1971158627043,143.620251668383 -30.0374973560768),(144.843993552527 -31.2612392402209,144.205519526017 -32.2721564488616,145.552307128906 -33.4920387268066,147.970809936523 -32.0361862182617,146.386972449926 -31.4740639157242,144.843993552527 -31.2612392402209))
+valid ewkb curve polygon 5|CURVEPOLYGON((143.620251668383 -30.0374973560768,142.928571472997 -32.751011968744,145.961323098919 -34.9856710615288,149.575653076172 -33.4115333557129,149.419724075848 -29.8246726805735,146.120941605547 -30.1971158627043,143.620251668383 -30.0374973560768),)

Modified: trunk/regress/sql-mm-serialize.sql
===================================================================
--- trunk/regress/sql-mm-serialize.sql	2009-03-09 22:01:04 UTC (rev 3820)
+++ trunk/regress/sql-mm-serialize.sql	2009-03-10 00:29:32 UTC (rev 3821)
@@ -38,7 +38,7 @@
 INSERT INTO serialize_test (
         id, description, ewkt, serialized
       ) VALUES (
-        6, 'Circular String',
+        6, 'Compound Curve',
         'COMPOUNDCURVE(CIRCULARSTRING(0 0,1 1,1 0),(1 0,0 1))',
         '01090000000200000001080000000300000000000000000000000000000000000000000000000000F03F000000000000F03F000000000000F03F0000000000000000010200000002000000000000000000F03F00000000000000000000000000000000000000000000F03F');
 INSERT INTO serialize_test (
@@ -56,13 +56,13 @@
 INSERT INTO serialize_test (
         id, description, ewkt, serialized
       ) VALUES (
-        9, 'Circular String 3dm, SRID=4326',
+        9, 'Compound Curve 3dm, SRID=4326',
         'SRID=4326;COMPOUNDCURVEM(CIRCULARSTRING(0 0 2,1 1 2,1 0 2),(1 0 2,0 1 2))',
         '0109000060E610000002000000010800004003000000000000000000000000000000000000000000000000000040000000000000F03F000000000000F03F0000000000000040000000000000F03F00000000000000000000000000000040010200004002000000000000000000F03F000000000000000000000000000000400000000000000000000000000000F03F0000000000000040');
 INSERT INTO serialize_test (
         id, description, ewkt, serialized
       ) VALUES (
-        10, 'Circular String 4d, SRID=4326',
+        10, 'Compound Curve 4d, SRID=4326',
         'SRID=4326;COMPOUNDCURVE(CIRCULARSTRING(0 0 2 5,1 1 2 5,1 0 2 5),(1 0 2 5,0 1 2 2))',
         '01090000E0E61000000200000001080000C0030000000000000000000000000000000000000000000000000000400000000000001440000000000000F03F000000000000F03F00000000000000400000000000001440000000000000F03F00000000000000000000000000000040000000000000144001020000C002000000000000000000F03F0000000000000000000000000000004000000000000014400000000000000000000000000000F03F00000000000000400000000000000040');
 INSERT INTO serialize_test(



More information about the postgis-commits mailing list