[postgis-commits] svn - r3439 - in trunk: . liblwgeom

postgis-commits at postgis.refractions.net postgis-commits at postgis.refractions.net
Wed Dec 17 12:47:36 PST 2008


Author: pramsey
Date: 2008-12-17 12:47:36 -0800 (Wed, 17 Dec 2008)
New Revision: 3439

Modified:
   trunk/TODO
   trunk/liblwgeom/liblwgeom.h
   trunk/liblwgeom/lwalgorithm.c
   trunk/liblwgeom/lwalgorithm.h
Log:
Partial work into SVN where I can get at it elsewhere.


Modified: trunk/TODO
===================================================================
--- trunk/TODO	2008-12-17 20:22:07 UTC (rev 3438)
+++ trunk/TODO	2008-12-17 20:47:36 UTC (rev 3439)
@@ -91,4 +91,5 @@
 * Convert the LWGEOM struct(s) to have enough padding that the coordinates
   are double-aligned and can be accessed directly as doubles on all
   architectures
-
+* Support all typologies of EMPTY (POINT EMPTY, LINESTRING EMPTY) instead
+  of just using GEOMETRYCOLLECTION EMPTY all the time.

Modified: trunk/liblwgeom/liblwgeom.h
===================================================================
--- trunk/liblwgeom/liblwgeom.h	2008-12-17 20:22:07 UTC (rev 3438)
+++ trunk/liblwgeom/liblwgeom.h	2008-12-17 20:47:36 UTC (rev 3439)
@@ -5,6 +5,23 @@
 #include <stdarg.h>
 #include <stdio.h>
 
+/**
+* @file liblwgeom.h
+* 
+* This library is the generic geometry handling section of PostGIS. The geometry
+* objects, constructors, destructors, and a set of spatial processing functions,
+* are implemented here. 
+* 
+* The library is designed for use in non-PostGIS applications if necessary. The 
+* units tests at cunit/cu_tester.c and the loader/dumper programs at 
+* ../loader/shp2pgsql.c are examples of non-PostGIS applications using liblwgeom.
+* 
+* Programs using this library should set up the default memory managers and error
+* handlers by implementing an lwgeom_init_allocators() function, which can be as 
+* a wrapper around the lwgeom_install_default_allocators() function if you want
+* no special handling for memory management and error reporting.
+*/
+
 #define INTEGRITY_CHECKS 1
 
 /*
@@ -25,21 +42,14 @@
 #define LW_TRUE 1
 #define LW_FALSE 0
 
-
 /*
- * Memory management function types
+ * this will change to NaN when I figure out how to
+ * get NaN in a platform-independent way
  */
-extern void lwgeom_init_allocators(void);
-extern void lwgeom_install_default_allocators(void);
+#define NO_VALUE 0.0
+#define NO_Z_VALUE NO_VALUE
+#define NO_M_VALUE NO_VALUE
 
-typedef void* (*lwallocator)(size_t size);
-typedef void* (*lwreallocator)(void *mem, size_t size);
-typedef void (*lwfreeor)(void* mem);
-typedef void (*lwreporter)(const char* fmt, va_list ap);
-
-void lwnotice(const char *fmt, ...);
-void lwerror(const char *fmt, ...);
-
 #ifndef C_H
 
 typedef unsigned int uint32;
@@ -47,29 +57,54 @@
 
 #endif
 
-/*
- * this will change to NaN when I figure out how to
- * get NaN in a platform-independent way
- */
-#define NO_VALUE 0.0
-#define NO_Z_VALUE NO_VALUE
-#define NO_M_VALUE NO_VALUE
 
+/**
+* Supply the memory management and error handling functions you want your
+* application to use.
+* @ingroup system
+*/
+extern void lwgeom_init_allocators(void);
+/**
+* Apply the default memory management (malloc() and free()) and error handlers.
+* Called inside lwgeom_init_allocators() generally.
+* @ingroup system
+*/
+extern void lwgeom_install_default_allocators(void);
 
-/* prototypes */
-void *default_allocator(size_t size);
-void *default_reallocator(void *mem, size_t size);
-void default_freeor(void *ptr);
-void default_errorreporter(const char *fmt, va_list ap);
-void default_noticereporter(const char *fmt, va_list ap);
 
-/* globals */
+/**
+* Write a notice out to the notice handler. Uses standard printf() substitutions.
+* Use for messages you always want output. For debugging, use LWDEBUG() or LWDEBUGF().
+* @ingroup logging
+*/
+void lwnotice(const char *fmt, ...);
+/**
+* Write a notice out to the error handler. Uses standard printf() substitutions.
+* Use for errors you always want output. For debugging, use LWDEBUG() or LWDEBUGF().
+* @ingroup logging
+*/
+void lwerror(const char *fmt, ...);
+
+
+/* Globals for memory/logging handlers. */
+typedef void* (*lwallocator)(size_t size);
+typedef void* (*lwreallocator)(void *mem, size_t size);
+typedef void (*lwfreeor)(void* mem);
+typedef void (*lwreporter)(const char* fmt, va_list ap);
 extern lwreallocator lwrealloc_var;
 extern lwallocator lwalloc_var;
 extern lwfreeor lwfree_var;
 extern lwreporter lwerror_var;
 extern lwreporter lwnotice_var;
 
+/* The default memory/logging handlers installed by lwgeom_install_default_allocators() */
+void *default_allocator(size_t size);
+void *default_reallocator(void *mem, size_t size);
+void default_freeor(void *ptr);
+void default_errorreporter(const char *fmt, va_list ap);
+void default_noticereporter(const char *fmt, va_list ap);
+
+
 extern int lw_vasprintf (char **result, const char *format, va_list args);
 
 /* Debug macros */

Modified: trunk/liblwgeom/lwalgorithm.c
===================================================================
--- trunk/liblwgeom/lwalgorithm.c	2008-12-17 20:22:07 UTC (rev 3438)
+++ trunk/liblwgeom/lwalgorithm.c	2008-12-17 20:47:36 UTC (rev 3439)
@@ -13,7 +13,7 @@
 #include "lwalgorithm.h"
 
 /*
-** segmentSide()
+** lw_segment_side()
 **
 ** Return < 0.0 if point Q is left of segment P
 ** Return > 0.0 if point Q is right of segment P
@@ -24,7 +24,8 @@
 	return ( (q->x - p1->x) * (p2->y - p1->y) - (p2->x - p1->x) * (q->y - p1->y) );
 }
 
-int lw_segment_envelope_intersects(POINT2D *p1, POINT2D *p2, POINT2D *q1, POINT2D *q2) {
+int lw_segment_envelope_intersects(POINT2D *p1, POINT2D *p2, POINT2D *q1, POINT2D *q2) 
+{
 	double minq=LW_MIN(q1->x,q2->x);
 	double maxq=LW_MAX(q1->x,q2->x);
 	double minp=LW_MIN(p1->x,p2->x);
@@ -45,7 +46,7 @@
 }
 
 /*
-** segmentIntersects()
+** lw_segment_intersects()
 ** 
 ** Returns one of
 **	SEG_ERROR = -1,
@@ -56,31 +57,36 @@
 **	SEG_TOUCH_LEFT = 4, 
 **	SEG_TOUCH_RIGHT = 5
 */
-int lw_segment_intersects(POINT2D *p1, POINT2D *p2, POINT2D *q1, POINT2D *q2) {
+int lw_segment_intersects(POINT2D *p1, POINT2D *p2, POINT2D *q1, POINT2D *q2) 
+{
 	
 	double pq1, pq2, qp1, qp2;
 	
 	/* No envelope interaction => we are done. */
-	if (!lw_segment_envelope_intersects(p1, p2, q1, p2))	{
+	if (!lw_segment_envelope_intersects(p1, p2, q1, p2))	
+	{
 		return SEG_NO_INTERSECTION;
 	}
 
 	/* Are the start and end points of q on the same side of p? */
 	pq1=lw_segment_side(p1,p2,q1);
 	pq2=lw_segment_side(p1,p2,q2);
-	if ((pq1>0 && pq2>0) || (pq1<0 && pq2<0)) {
+	if ((pq1>0 && pq2>0) || (pq1<0 && pq2<0)) 
+	{
 		return SEG_NO_INTERSECTION;
 	}
 
 	/* Are the start and end points of p on the same side of q? */
 	qp1=lw_segment_side(q1,q2,p1);
 	qp2=lw_segment_side(q1,q2,p2);
-	if ((qp1>0 && qp2>0) || (qp1<0 && qp2<0)) {
+	if ((qp1>0 && qp2>0) || (qp1<0 && qp2<0)) 
+	{
 		return SEG_NO_INTERSECTION;
 	}
 
 	/* Nobody is on one side or another? Must be colinear. */
-	if (pq1 == 0.0 && pq2 == 0.0 && qp1 == 0.0 && qp2 == 0.0) {
+	if (pq1 == 0.0 && pq2 == 0.0 && qp1 == 0.0 && qp2 == 0.0) 
+	{
 		return SEG_COLINEAR;
 	}
 
@@ -88,13 +94,15 @@
 	** When one end-point touches, the sidedness is determined by the 
 	** location of the other end-point.
 	*/
-	if ( pq2 == 0.0 ) {
+	if ( pq2 == 0.0 ) 
+	{
 		if ( pq1 < 0.0 ) 
 			return SEG_TOUCH_LEFT;
 		else 
 			return SEG_TOUCH_RIGHT;
 	}
-	if ( pq1 == 0.0 ) {
+	if ( pq1 == 0.0 ) 
+	{
 		if ( pq2 < 0.0 ) 
 			return SEG_TOUCH_LEFT;
 		else 
@@ -113,7 +121,7 @@
 }
 
 /*
-** lineCrossingDirection()
+** lwline_crossing_direction()
 ** 
 ** Returns one of
 **   LINE_NO_CROSS = 0
@@ -127,7 +135,8 @@
 **   LINE_TOUCH_RIGHT = 4
 **
 */
-int lwline_crossing_direction(LWLINE *l1, LWLINE *l2) {
+int lwline_crossing_direction(LWLINE *l1, LWLINE *l2) 
+{
 	
 	int i = 0, j = 0, rv = 0;
 	POINT2D *p1;
@@ -159,12 +168,14 @@
 	LWDEBUGF(4, "lineCrossingDirection: l1 = %s", lwgeom_to_ewkt((LWGEOM*)l1,0));
 	LWDEBUGF(4, "lineCrossingDirection: l2 = %s", lwgeom_to_ewkt((LWGEOM*)l2,0));
 
-	for ( i = 1; i < pa2->npoints; i++ ) {
+	for ( i = 1; i < pa2->npoints; i++ ) 
+	{
 		
 		rv = getPoint2d_p(pa2, i-1, q1);
 		rv = getPoint2d_p(pa2, i, q2);
 		
-		for ( j = 1; j < pa1->npoints; j++ ) {   
+		for ( j = 1; j < pa1->npoints; j++ ) 
+		{   
 			
 			rv = getPoint2d_p(pa1, j-1, p1);
 			rv = getPoint2d_p(pa1, j, p2);
@@ -178,12 +189,14 @@
 			if( this_cross ) 
 				final_cross = this_cross;
 				
-			if( this_cross == SEG_CROSS_LEFT ) {
+			if( this_cross == SEG_CROSS_LEFT ) 
+			{
 				cross_left++;
 				break;
 			}
 				
-			if( this_cross == SEG_CROSS_RIGHT ) {
+			if( this_cross == SEG_CROSS_RIGHT ) 
+			{
 				cross_right++;
 				break;
 			}
@@ -193,7 +206,8 @@
 			** a vertex by pulling the original touch point forward along
 			** the co-linearity.
 			*/
-			if( this_cross == SEG_COLINEAR && vertex_touch == (i-1) ) {
+			if( this_cross == SEG_COLINEAR && vertex_touch == (i-1) ) 
+			{
 				vertex_touch = i;
 				break;
 			}
@@ -203,7 +217,8 @@
 			** j-1 and two at j. We avoid incrementing our cross count by ignoring the
 			** second pair.
 			*/
-			if( this_cross == SEG_TOUCH_LEFT ) {
+			if( this_cross == SEG_TOUCH_LEFT ) 
+			{
 				if ( vertex_touch == (i-1) && vertex_touch_type == SEG_TOUCH_RIGHT ) {
 					cross_left++;
 					vertex_touch = -1;
@@ -215,7 +230,8 @@
 				}
 				break;
 			}
-			if( this_cross == SEG_TOUCH_RIGHT ) {
+			if( this_cross == SEG_TOUCH_RIGHT ) 
+			{
 				if ( vertex_touch == (i-1) && vertex_touch_type == SEG_TOUCH_LEFT ) {
 					cross_right++;
 					vertex_touch = -1;
@@ -276,3 +292,97 @@
 	
 }
 
+#if 0 
+/*
+** lwpoint_get_ordinate(point, ordinate) => double
+*/
+double lwpoint_get_ordinate(POINT4D *p, int ordinate) 
+{
+	if( ! p ) 
+	{
+		lwerror("Null input geometry.");
+		return 0.0;
+	}
+	
+	if( ordinate > 3 || ordinate < 0 ) 
+	{
+		lwerror("Cannot extract ordinate %d.", ordinate);
+		return 0.0;
+	}
+
+	if( ordinate == 3 ) 
+		return p->m;
+	if( ordinate == 2 ) 
+		return p->z;
+	if( ordinate == 1 ) 
+		return p->y;
+
+	return p->x;
+	
+}
+
+/*
+** lwline_clip_to_ordinate_range(line, ordinate, from, to) => lwmline
+**
+** Take in a LINESTRING and return a MULTILINESTRING of those portions of the 
+** LINESTRING between the from/to range for the specified ordinate (XYZM)
+*/
+LWLINE *lwline_clip_to_ordinate_range(LWLINE *line, int ordinate, double from, double to) 
+{
+	
+	POINTARRAY *pa_in;
+	LWMLINE *mline_out;
+	POINTARRAY *pa_out;
+	DYNPTARRAY *dp;
+	int i, rv;
+	int last_point = 0;
+	int nparts = 0;
+	POINT4D *p, *q;
+	double ordinate_value;
+
+	
+	/* Null input, nothing we can do. */
+	if( ! line ) 
+	{
+		lwerror("Null input geometry.");
+		return NULL;
+	}
+	
+	/* Ensure 'from' is less than 'to'. */
+	if( to < from ) 
+	{
+		double t = from;
+		from = to;
+		to = t;
+	}
+	
+	int ndims = TYPE_NDIMS(line->type);
+	
+	/* Asking for an ordinate we don't have. */
+	if( ordinate >= ndims ) 
+	{
+		lwerror("Cannot clip on ordinate %d in a %d-d geometry.", ordinate, ndims);
+		return NULL;
+	}
+	
+	p = lwalloc(sizeof(POINT4D));
+	q = lwalloc(sizeof(POINT4D));
+
+	pa_in = (POINTARRAY*)line->points;
+	
+	dp = dynptarray_create(64, ndims);
+
+	
+	for ( i = 1; i < pa_in->npoints; i++ ) 
+	{
+		rv = getPoint4d_p(pa_in, i, p);
+		ordinate_value = lwpoint_get_ordinate(p, ordinate);
+		if ( ordinate_value >= from && ordinate_value <= to )
+		{
+			rv =dynptarray_addPoint4d(dp, p, 1);
+		} 
+	}
+
+	
+}
+#endif

Modified: trunk/liblwgeom/lwalgorithm.h
===================================================================
--- trunk/liblwgeom/lwalgorithm.h	2008-12-17 20:22:07 UTC (rev 3438)
+++ trunk/liblwgeom/lwalgorithm.h	2008-12-17 20:47:36 UTC (rev 3439)
@@ -38,3 +38,5 @@
 };
 
 int lwline_crossing_direction(LWLINE *l1, LWLINE *l2);
+
+double lwpoint_get_ordinate(POINT4D *p, int ordinate);



More information about the postgis-commits mailing list