2009-09-14 20:30:35 +00:00
|
|
|
/**********************************************************************
|
2010-10-31 02:31:34 +00:00
|
|
|
* $Id: liblwgeom_internal.h 4497 2009-09-14 18:33:54Z pramsey $
|
2009-09-14 20:30:35 +00:00
|
|
|
*
|
|
|
|
* PostGIS - Spatial Types for PostgreSQL
|
|
|
|
* http://postgis.refractions.net
|
|
|
|
* Copyright 2001-2006 Refractions Research Inc.
|
|
|
|
* Copyright 2007-2008 Mark Cave-Ayland
|
|
|
|
* Copyright 2008 Paul Ramsey <pramsey@cleverelephant.ca>
|
|
|
|
*
|
|
|
|
* This is free software; you can redistribute and/or modify it under
|
|
|
|
* the terms of the GNU General Public Licence. See the COPYING file.
|
|
|
|
*
|
|
|
|
**********************************************************************/
|
|
|
|
|
|
|
|
#include <assert.h>
|
|
|
|
#include "liblwgeom.h"
|
2010-10-31 02:31:34 +00:00
|
|
|
#include <string.h>
|
|
|
|
#include <math.h>
|
|
|
|
#include <inttypes.h>
|
|
|
|
#if HAVE_IEEEFP_H
|
|
|
|
#include <ieeefp.h>
|
|
|
|
#endif
|
|
|
|
|
2011-08-10 23:16:41 +00:00
|
|
|
#ifndef _LIBLWGEOM_INTERNAL_H
|
|
|
|
#define _LIBLWGEOM_INTERNAL_H 1
|
2010-10-31 02:31:34 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* PI
|
|
|
|
*/
|
|
|
|
#define PI 3.1415926535897932384626433832795
|
|
|
|
|
2011-08-09 14:19:12 +00:00
|
|
|
/**
|
|
|
|
* Floating point comparitors.
|
|
|
|
*/
|
|
|
|
#define FP_TOLERANCE 1e-12
|
|
|
|
#define FP_IS_ZERO(A) (fabs(A) <= FP_TOLERANCE)
|
|
|
|
#define FP_MAX(A, B) (((A) > (B)) ? (A) : (B))
|
|
|
|
#define FP_MIN(A, B) (((A) < (B)) ? (A) : (B))
|
|
|
|
#define FP_EQUALS(A, B) (fabs((A)-(B)) <= FP_TOLERANCE)
|
|
|
|
#define FP_NEQUALS(A, B) (fabs((A)-(B)) > FP_TOLERANCE)
|
|
|
|
#define FP_LT(A, B) (((A) + FP_TOLERANCE) < (B))
|
|
|
|
#define FP_LTEQ(A, B) (((A) - FP_TOLERANCE) <= (B))
|
|
|
|
#define FP_GT(A, B) (((A) - FP_TOLERANCE) > (B))
|
|
|
|
#define FP_GTEQ(A, B) (((A) + FP_TOLERANCE) >= (B))
|
|
|
|
#define FP_CONTAINS_TOP(A, X, B) (FP_LT(A, X) && FP_LTEQ(X, B))
|
|
|
|
#define FP_CONTAINS_BOTTOM(A, X, B) (FP_LTEQ(A, X) && FP_LT(X, B))
|
|
|
|
#define FP_CONTAINS_INCL(A, X, B) (FP_LTEQ(A, X) && FP_LTEQ(X, B))
|
|
|
|
#define FP_CONTAINS_EXCL(A, X, B) (FP_LT(A, X) && FP_LT(X, B))
|
|
|
|
#define FP_CONTAINS(A, X, B) FP_CONTAINS_EXCL(A, X, B)
|
|
|
|
|
2011-08-09 15:12:06 +00:00
|
|
|
/**
|
|
|
|
* Largest float value. Should this be from math.h instead?
|
|
|
|
*/
|
|
|
|
#ifndef MAXFLOAT
|
|
|
|
#define MAXFLOAT 3.402823466e+38F
|
|
|
|
#endif
|
|
|
|
|
2011-08-16 09:25:30 +00:00
|
|
|
/* for the measure functions*/
|
|
|
|
#define DIST_MAX -1
|
|
|
|
#define DIST_MIN 1
|
|
|
|
|
2011-08-16 09:47:32 +00:00
|
|
|
/*
|
|
|
|
* 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
|
|
|
|
|
2010-10-31 02:31:34 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Well-Known Text (WKT) Output Variant Types
|
|
|
|
*/
|
|
|
|
#define WKT_NO_TYPE 0x08 /* Internal use only */
|
|
|
|
#define WKT_NO_PARENS 0x10 /* Internal use only */
|
2010-12-07 21:08:05 +00:00
|
|
|
#define WKT_IS_CHILD 0x20 /* Internal use only */
|
2010-10-31 02:31:34 +00:00
|
|
|
|
|
|
|
/**
|
|
|
|
* Well-Known Binary (WKB) Output Variant Types
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define WKB_DOUBLE_SIZE 8 /* Internal use only */
|
|
|
|
#define WKB_INT_SIZE 4 /* Internal use only */
|
|
|
|
#define WKB_BYTE_SIZE 1 /* Internal use only */
|
2009-09-14 20:30:35 +00:00
|
|
|
|
2010-10-20 22:51:30 +00:00
|
|
|
/**
|
2010-10-31 02:31:34 +00:00
|
|
|
* Well-Known Binary (WKB) Geometry Types
|
2010-10-20 22:51:30 +00:00
|
|
|
*/
|
2010-10-31 02:31:34 +00:00
|
|
|
#define WKB_POINT_TYPE 1
|
|
|
|
#define WKB_LINESTRING_TYPE 2
|
|
|
|
#define WKB_POLYGON_TYPE 3
|
|
|
|
#define WKB_MULTIPOINT_TYPE 4
|
|
|
|
#define WKB_MULTILINESTRING_TYPE 5
|
|
|
|
#define WKB_MULTIPOLYGON_TYPE 6
|
|
|
|
#define WKB_GEOMETRYCOLLECTION_TYPE 7
|
|
|
|
#define WKB_CIRCULARSTRING_TYPE 8
|
|
|
|
#define WKB_COMPOUNDCURVE_TYPE 9
|
|
|
|
#define WKB_CURVEPOLYGON_TYPE 10
|
|
|
|
#define WKB_MULTICURVE_TYPE 11
|
|
|
|
#define WKB_MULTISURFACE_TYPE 12
|
|
|
|
#define WKB_CURVE_TYPE 13 /* from ISO draft, not sure is real */
|
|
|
|
#define WKB_SURFACE_TYPE 14 /* from ISO draft, not sure is real */
|
|
|
|
#define WKB_POLYHEDRALSURFACE_TYPE 15
|
|
|
|
#define WKB_TIN_TYPE 16
|
|
|
|
#define WKB_TRIANGLE_TYPE 17
|
|
|
|
|
2010-10-20 22:51:30 +00:00
|
|
|
/**
|
2010-10-31 02:31:34 +00:00
|
|
|
* Macro for reading the size from the GSERIALIZED size attribute.
|
|
|
|
* Cribbed from PgSQL, top 30 bits are size. Use VARSIZE() when working
|
|
|
|
* internally with PgSQL.
|
2010-10-20 22:51:30 +00:00
|
|
|
*/
|
2010-10-31 02:31:34 +00:00
|
|
|
#define SIZE_GET(varsize) (((varsize) >> 2) & 0x3FFFFFFF)
|
|
|
|
#define SIZE_SET(varsize, size) (((varsize) & 0x00000003)|(((size) & 0x3FFFFFFF) << 2 ))
|
|
|
|
|
|
|
|
|
2010-11-18 05:28:19 +00:00
|
|
|
/*
|
|
|
|
* Internal prototypes
|
|
|
|
*/
|
|
|
|
|
2011-08-08 09:27:09 +00:00
|
|
|
|
|
|
|
/* Machine endianness */
|
|
|
|
#define XDR 0
|
|
|
|
#define NDR 1
|
|
|
|
extern char getMachineEndian(void);
|
|
|
|
|
|
|
|
/* Raise an lwerror if srids do not match */
|
|
|
|
void error_if_srid_mismatch(int srid1, int srid2);
|
|
|
|
|
|
|
|
|
2010-11-18 05:28:19 +00:00
|
|
|
/*
|
|
|
|
* Force dims
|
|
|
|
*/
|
|
|
|
LWGEOM* lwgeom_force_dims(const LWGEOM *lwgeom, int hasz, int hasm);
|
|
|
|
LWPOINT* lwpoint_force_dims(const LWPOINT *lwpoint, int hasz, int hasm);
|
|
|
|
LWLINE* lwline_force_dims(const LWLINE *lwline, int hasz, int hasm);
|
|
|
|
LWPOLY* lwpoly_force_dims(const LWPOLY *lwpoly, int hasz, int hasm);
|
|
|
|
LWCOLLECTION* lwcollection_force_dims(const LWCOLLECTION *lwcol, int hasz, int hasm);
|
|
|
|
POINTARRAY* ptarray_force_dims(const POINTARRAY *pa, int hasz, int hasm);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Is Empty?
|
|
|
|
*/
|
|
|
|
int lwpoly_is_empty(const LWPOLY *poly);
|
|
|
|
int lwcollection_is_empty(const LWCOLLECTION *col);
|
|
|
|
int lwcircstring_is_empty(const LWCIRCSTRING *circ);
|
|
|
|
int lwtriangle_is_empty(const LWTRIANGLE *triangle);
|
|
|
|
int lwline_is_empty(const LWLINE *line);
|
|
|
|
int lwpoint_is_empty(const LWPOINT *point);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Number of vertices?
|
|
|
|
*/
|
|
|
|
int lwline_count_vertices(LWLINE *line);
|
|
|
|
int lwpoly_count_vertices(LWPOLY *poly);
|
|
|
|
int lwcollection_count_vertices(LWCOLLECTION *col);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* DP simplification
|
|
|
|
*/
|
|
|
|
POINTARRAY* ptarray_simplify(POINTARRAY *inpts, double epsilon);
|
|
|
|
LWLINE* lwline_simplify(const LWLINE *iline, double dist);
|
|
|
|
LWPOLY* lwpoly_simplify(const LWPOLY *ipoly, double dist);
|
|
|
|
LWCOLLECTION* lwcollection_simplify(const LWCOLLECTION *igeom, double dist);
|
|
|
|
|
2011-06-25 22:36:51 +00:00
|
|
|
/*
|
|
|
|
* Computational geometry
|
|
|
|
*/
|
|
|
|
int signum(double n);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* The possible ways a pair of segments can interact. Returned by lw_segment_intersects
|
|
|
|
*/
|
|
|
|
enum CG_SEGMENT_INTERSECTION_TYPE {
|
|
|
|
SEG_ERROR = -1,
|
|
|
|
SEG_NO_INTERSECTION = 0,
|
|
|
|
SEG_COLINEAR = 1,
|
|
|
|
SEG_CROSS_LEFT = 2,
|
|
|
|
SEG_CROSS_RIGHT = 3,
|
|
|
|
SEG_TOUCH_LEFT = 4,
|
|
|
|
SEG_TOUCH_RIGHT = 5
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Do the segments intersect? How?
|
|
|
|
*/
|
|
|
|
int lw_segment_intersects(const POINT2D *p1, const POINT2D *p2, const POINT2D *q1, const POINT2D *q2);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* What side of the line formed by p1 and p2 does q fall?
|
|
|
|
* Returns < 0 for left and > 0 for right and 0 for co-linearity
|
|
|
|
*/
|
|
|
|
double lw_segment_side(const POINT2D *p1, const POINT2D *p2, const POINT2D *q);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Do the envelopes of the the segments intersect?
|
|
|
|
*/
|
|
|
|
int lw_segment_envelope_intersects(const POINT2D *p1, const POINT2D *p2, const POINT2D *q1, const POINT2D *q2);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Get/Set an enumeratoed ordinate. (x,y,z,m)
|
|
|
|
*/
|
|
|
|
double lwpoint_get_ordinate(const POINT4D *p, int ordinate);
|
|
|
|
void lwpoint_set_ordinate(POINT4D *p, int ordinate, double value);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Generate an interpolated coordinate p given an interpolation value and ordinate to apply it to
|
|
|
|
*/
|
|
|
|
int lwpoint_interpolate(const POINT4D *p1, const POINT4D *p2, POINT4D *p, int ndims, int ordinate, double interpolation_value);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Geohash
|
|
|
|
*/
|
|
|
|
int lwgeom_geohash_precision(GBOX bbox, GBOX *bounds);
|
|
|
|
char *geohash_point(double longitude, double latitude, int precision);
|
|
|
|
|
2010-11-22 22:23:02 +00:00
|
|
|
/*
|
|
|
|
* Point comparisons
|
|
|
|
*/
|
|
|
|
int p4d_same(POINT4D p1, POINT4D p2);
|
2010-11-18 05:28:19 +00:00
|
|
|
|
2010-11-30 21:54:55 +00:00
|
|
|
/*
|
|
|
|
* Area calculations
|
|
|
|
*/
|
2010-11-30 22:55:54 +00:00
|
|
|
double lwpoly_area(const LWPOLY *poly);
|
|
|
|
double lwcurvepoly_area(const LWCURVEPOLY *curvepoly);
|
|
|
|
double lwtriangle_area(const LWTRIANGLE *triangle);
|
2010-11-23 23:47:44 +00:00
|
|
|
|
2010-11-30 22:55:54 +00:00
|
|
|
/*
|
|
|
|
* Length calculations
|
|
|
|
*/
|
|
|
|
double lwcompound_length(const LWCOMPOUND *comp);
|
|
|
|
double lwcompound_length_2d(const LWCOMPOUND *comp);
|
|
|
|
double lwline_length(const LWLINE *line);
|
|
|
|
double lwline_length_2d(const LWLINE *line);
|
|
|
|
double lwcircstring_length(const LWCIRCSTRING *circ);
|
|
|
|
double lwcircstring_length_2d(const LWCIRCSTRING *circ);
|
2010-12-01 20:28:29 +00:00
|
|
|
double lwpoly_perimeter(const LWPOLY *poly);
|
|
|
|
double lwpoly_perimeter_2d(const LWPOLY *poly);
|
|
|
|
double lwcurvepoly_perimeter(const LWCURVEPOLY *poly);
|
|
|
|
double lwcurvepoly_perimeter_2d(const LWCURVEPOLY *poly);
|
|
|
|
double lwtriangle_perimeter(const LWTRIANGLE *triangle);
|
|
|
|
double lwtriangle_perimeter_2d(const LWTRIANGLE *triangle);
|
2010-11-23 23:47:44 +00:00
|
|
|
|
2010-11-30 22:55:54 +00:00
|
|
|
/*
|
|
|
|
* Segmentization
|
|
|
|
*/
|
|
|
|
LWLINE *lwcircstring_segmentize(const LWCIRCSTRING *icurve, uint32 perQuad);
|
|
|
|
LWLINE *lwcompound_segmentize(const LWCOMPOUND *icompound, uint32 perQuad);
|
|
|
|
LWPOLY *lwcurvepoly_segmentize(const LWCURVEPOLY *curvepoly, uint32 perQuad);
|
2010-12-01 00:53:03 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
* Affine
|
|
|
|
*/
|
|
|
|
void ptarray_affine(POINTARRAY *pa, const AFFINE *affine);
|
|
|
|
|
2010-12-01 20:28:29 +00:00
|
|
|
/*
|
|
|
|
* PointArray
|
|
|
|
*/
|
|
|
|
char ptarray_isccw(const POINTARRAY *pa);
|
|
|
|
|
2010-12-01 00:53:03 +00:00
|
|
|
|
2011-08-10 23:16:41 +00:00
|
|
|
#endif /* _LIBLWGEOM_INTERNAL_H */
|