#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
#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 */
#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
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);
}
/*
-** segmentIntersects()
+** lw_segment_intersects()
**
** Returns one of
** SEG_ERROR = -1,
** 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;
}
** 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
}
/*
-** lineCrossingDirection()
+** lwline_crossing_direction()
**
** Returns one of
** LINE_NO_CROSS = 0
** 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;
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);
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;
}
** 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;
}
** 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;
}
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;
}
+#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