]> granicus.if.org Git - postgis/commitdiff
Partial work into SVN where I can get at it elsewhere.
authorPaul Ramsey <pramsey@cleverelephant.ca>
Wed, 17 Dec 2008 20:47:36 +0000 (20:47 +0000)
committerPaul Ramsey <pramsey@cleverelephant.ca>
Wed, 17 Dec 2008 20:47:36 +0000 (20:47 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@3439 b70326c6-7e19-0410-871a-916f4a2858ee

TODO
liblwgeom/liblwgeom.h
liblwgeom/lwalgorithm.c
liblwgeom/lwalgorithm.h

diff --git a/TODO b/TODO
index 59faeac7d278ec0332655093477270ed39bd596f..992e8f7f0925f633b569284d4a01486fed099bc4 100644 (file)
--- a/TODO
+++ b/TODO
@@ -91,4 +91,5 @@ See,
 * 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.
index b6b4eaaf70953c7c0fced9c2559e8aced4ada25e..62533480d046947264f11373f1b6050a993531ef 100644 (file)
@@ -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
 
 /*
 #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);
-
-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, ...);
+#define NO_VALUE 0.0
+#define NO_Z_VALUE NO_VALUE
+#define NO_M_VALUE NO_VALUE
 
 #ifndef C_H
 
@@ -47,29 +57,54 @@ typedef int int32;
 
 #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);
+
+
+/**
+* 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, ...);
 
-/* 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 */
+/* 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 */
index f5a02c6b51a9ab78744d4d2957d46348328c48d0..63e9b3c044aec899cdd418c7f6dd48af271b6645 100644 (file)
@@ -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 @@ double lw_segment_side(POINT2D *p1, POINT2D *p2, POINT2D *q)
        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 @@ int lw_segment_envelope_intersects(POINT2D *p1, POINT2D *p2, POINT2D *q1, POINT2
 }
 
 /*
-** segmentIntersects()
+** lw_segment_intersects()
 ** 
 ** Returns one of
 **     SEG_ERROR = -1,
@@ -56,31 +57,36 @@ int lw_segment_envelope_intersects(POINT2D *p1, POINT2D *p2, POINT2D *q1, POINT2
 **     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 @@ int lw_segment_intersects(POINT2D *p1, POINT2D *p2, POINT2D *q1, POINT2D *q2) {
        ** 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 @@ int lw_segment_intersects(POINT2D *p1, POINT2D *p2, POINT2D *q1, POINT2D *q2) {
 }
 
 /*
-** lineCrossingDirection()
+** lwline_crossing_direction()
 ** 
 ** Returns one of
 **   LINE_NO_CROSS = 0
@@ -127,7 +135,8 @@ int lw_segment_intersects(POINT2D *p1, POINT2D *p2, POINT2D *q1, POINT2D *q2) {
 **   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 @@ int lwline_crossing_direction(LWLINE *l1, LWLINE *l2) {
        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 @@ int lwline_crossing_direction(LWLINE *l1, LWLINE *l2) {
                        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 @@ int lwline_crossing_direction(LWLINE *l1, LWLINE *l2) {
                        ** 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 @@ int lwline_crossing_direction(LWLINE *l1, LWLINE *l2) {
                        ** 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 @@ int lwline_crossing_direction(LWLINE *l1, LWLINE *l2) {
                                }
                                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 @@ int lwline_crossing_direction(LWLINE *l1, LWLINE *l2) {
        
 }
 
+#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
index 638fd853e34000ff3a03b05f08091d1dc86bb829..b1ae14eb8f98606b5579fb9d5a3cb258db46354f 100644 (file)
@@ -38,3 +38,5 @@ enum CG_LINE_CROSS_TYPE {
 };
 
 int lwline_crossing_direction(LWLINE *l1, LWLINE *l2);
+
+double lwpoint_get_ordinate(POINT4D *p, int ordinate);