/**********************************************************************
*
* PostGIS - Spatial Types for PostgreSQL
* http://postgis.net
*
* PostGIS is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 2 of the License, or
* (at your option) any later version.
*
* PostGIS is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with PostGIS. If not, see .
*
**********************************************************************
*
* Copyright 2011 Sandro Santilli
* Copyright 2011 Paul Ramsey
* Copyright 2007-2008 Mark Cave-Ayland
* Copyright 2001-2006 Refractions Research Inc.
*
**********************************************************************/
#ifndef _LIBLWGEOM_H
#define _LIBLWGEOM_H 1
#include
#include
#include
#include
#include "../postgis_config.h"
#if POSTGIS_PROJ_VERSION < 61
/* For Proj 6.0 use of old API */
#define ACCEPT_USE_OF_DEPRECATED_PROJ_API_H
#include "proj_api.h"
typedef struct PJ
{
projPJ pj_from;
projPJ pj_to;
} PJ;
typedef PJ LWPROJ;
#else
#include "proj.h"
/* For PROJ6 we cache several extra values to avoid calls to proj_get_source_crs
* or proj_get_target_crs since those are very costly
*/
typedef struct LWPROJ
{
PJ* pj;
/* Source crs is geographic: Used in geography calls (source srid == dst srid) */
uint8_t source_is_latlong;
/* Source ellipsoid parameters */
double source_semi_major_metre;
double source_semi_minor_metre;
} LWPROJ;
#endif
#if POSTGIS_PROJ_VERSION < 49
/* Use the old (pre-2.2) geodesic functions */
#undef PROJ_GEODESIC
#else
/* Enable new geodesic functions API */
#define PROJ_GEODESIC
#endif
/**
* @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 can install their custom memory managers and error
* handlers by calling the lwgeom_set_handlers() function, otherwise the default
* ones will be used.
*/
/**
* liblwgeom versions
*/
#define LIBLWGEOM_VERSION "@POSTGIS_LIB_VERSION@"
#define LIBLWGEOM_VERSION_MAJOR "@POSTGIS_MAJOR_VERSION@"
#define LIBLWGEOM_VERSION_MINOR "@POSTGIS_MINOR_VERSION@"
#define LIBLWGEOM_GEOS_VERSION "@POSTGIS_GEOS_VERSION@"
/** Return lwgeom version string (not to be freed) */
const char* lwgeom_version(void);
/**
* Return types for functions with status returns.
*/
#define LW_TRUE 1
#define LW_FALSE 0
#define LW_UNKNOWN 2
#define LW_FAILURE 0
#define LW_SUCCESS 1
/**
* LWTYPE numbers, used internally by PostGIS
*/
#define POINTTYPE 1
#define LINETYPE 2
#define POLYGONTYPE 3
#define MULTIPOINTTYPE 4
#define MULTILINETYPE 5
#define MULTIPOLYGONTYPE 6
#define COLLECTIONTYPE 7
#define CIRCSTRINGTYPE 8
#define COMPOUNDTYPE 9
#define CURVEPOLYTYPE 10
#define MULTICURVETYPE 11
#define MULTISURFACETYPE 12
#define POLYHEDRALSURFACETYPE 13
#define TRIANGLETYPE 14
#define TINTYPE 15
#define NUMTYPES 16
/**
* Flags applied in EWKB to indicate Z/M dimensions and
* presence/absence of SRID and bounding boxes
*/
#define WKBZOFFSET 0x80000000
#define WKBMOFFSET 0x40000000
#define WKBSRIDFLAG 0x20000000
#define WKBBBOXFLAG 0x10000000
/** Ordinate names */
typedef enum LWORD_T {
LWORD_X = 0,
LWORD_Y = 1,
LWORD_Z = 2,
LWORD_M = 3
} LWORD;
/**********************************************************************
** Spherical radius.
** Moritz, H. (1980). Geodetic Reference System 1980, by resolution of
** the XVII General Assembly of the IUGG in Canberra.
** http://en.wikipedia.org/wiki/Earth_radius
** http://en.wikipedia.org/wiki/World_Geodetic_System
*/
#define WGS84_MAJOR_AXIS 6378137.0
#define WGS84_INVERSE_FLATTENING 298.257223563
#define WGS84_MINOR_AXIS (WGS84_MAJOR_AXIS - WGS84_MAJOR_AXIS / WGS84_INVERSE_FLATTENING)
#define WGS84_RADIUS ((2.0 * WGS84_MAJOR_AXIS + WGS84_MINOR_AXIS ) / 3.0)
#define WGS84_SRID 4326
/**
* Macros for manipulating the 'flags' byte. A uint8_t used as follows:
* VVSRGBMZ
* Version bit, followed by
* Validty, Solid, ReadOnly, Geodetic, HasBBox, HasM and HasZ flags.
*/
#define LWFLAG_Z 0x01
#define LWFLAG_M 0x02
#define LWFLAG_BBOX 0x04
#define LWFLAG_GEODETIC 0x08
#define LWFLAG_READONLY 0x10
#define LWFLAG_SOLID 0x20
#define FLAGS_GET_Z(flags) ((flags) & LWFLAG_Z)
#define FLAGS_GET_M(flags) (((flags) & LWFLAG_M)>>1)
#define FLAGS_GET_BBOX(flags) (((flags) & LWFLAG_BBOX)>>2)
#define FLAGS_GET_GEODETIC(flags) (((flags) & LWFLAG_GEODETIC)>>3)
#define FLAGS_GET_READONLY(flags) (((flags) & LWFLAG_READONLY)>>4)
#define FLAGS_GET_SOLID(flags) (((flags) & LWFLAG_SOLID)>>5)
#define FLAGS_SET_Z(flags, value) ((flags) = (value) ? ((flags) | LWFLAG_Z) : ((flags) & ~LWFLAG_Z))
#define FLAGS_SET_M(flags, value) ((flags) = (value) ? ((flags) | LWFLAG_M) : ((flags) & ~LWFLAG_M))
#define FLAGS_SET_BBOX(flags, value) ((flags) = (value) ? ((flags) | LWFLAG_BBOX) : ((flags) & ~LWFLAG_BBOX))
#define FLAGS_SET_GEODETIC(flags, value) ((flags) = (value) ? ((flags) | LWFLAG_GEODETIC) : ((flags) & ~LWFLAG_GEODETIC))
#define FLAGS_SET_READONLY(flags, value) ((flags) = (value) ? ((flags) | LWFLAG_READONLY) : ((flags) & ~LWFLAG_READONLY))
#define FLAGS_SET_SOLID(flags, value) ((flags) = (value) ? ((flags) | LWFLAG_SOLID) : ((flags) & ~LWFLAG_SOLID))
#define FLAGS_NDIMS(flags) (2 + FLAGS_GET_Z(flags) + FLAGS_GET_M(flags))
#define FLAGS_GET_ZM(flags) (FLAGS_GET_M(flags) + FLAGS_GET_Z(flags) * 2)
#define FLAGS_NDIMS_BOX(flags) (FLAGS_GET_GEODETIC(flags) ? 3 : FLAGS_NDIMS(flags))
/**
* Macros for manipulating the 'typemod' int. An int32_t used as follows:
* Plus/minus = Top bit.
* Spare bits = Next 2 bits.
* SRID = Next 21 bits.
* TYPE = Next 6 bits.
* ZM Flags = Bottom 2 bits.
*/
#define TYPMOD_GET_SRID(typmod) ((((typmod) & 0x0FFFFF00) - ((typmod) & 0x10000000)) >> 8)
#define TYPMOD_SET_SRID(typmod, srid) ((typmod) = (((typmod) & 0xE00000FF) | ((srid & 0x001FFFFF)<<8)))
#define TYPMOD_GET_TYPE(typmod) ((typmod & 0x000000FC)>>2)
#define TYPMOD_SET_TYPE(typmod, type) ((typmod) = (typmod & 0xFFFFFF03) | ((type & 0x0000003F)<<2))
#define TYPMOD_GET_Z(typmod) ((typmod & 0x00000002)>>1)
#define TYPMOD_SET_Z(typmod) ((typmod) = typmod | 0x00000002)
#define TYPMOD_GET_M(typmod) (typmod & 0x00000001)
#define TYPMOD_SET_M(typmod) ((typmod) = typmod | 0x00000001)
#define TYPMOD_GET_NDIMS(typmod) (2+TYPMOD_GET_Z(typmod)+TYPMOD_GET_M(typmod))
/**
* Maximum allowed SRID value in serialized geometry.
* Currently we are using 21 bits (2097152) of storage for SRID.
*/
#define SRID_MAXIMUM @SRID_MAX@
/**
* Maximum valid SRID value for the user
* We reserve 1000 values for internal use
*/
#define SRID_USER_MAXIMUM @SRID_USR_MAX@
/** Unknown SRID value */
#define SRID_UNKNOWN 0
#define SRID_IS_UNKNOWN(x) ((int)x<=0)
/* Invalid SRID value, for internal use */
#define SRID_INVALID (@SRID_MAX@ + 2)
/*
** EPSG WGS84 geographics, OGC standard default SRS, better be in
** the SPATIAL_REF_SYS table!
*/
#define SRID_DEFAULT 4326
#ifndef __GNUC__
# define __attribute__(x)
#endif
/**
* Return a valid SRID from an arbitrary integer
* Raises a notice if what comes out is different from
* what went in.
* Raises an error if SRID value is out of bounds.
*/
extern int32_t clamp_srid(int32_t srid);
/**
* Global functions 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)
__attribute__ (( format(printf, 1, 0) ));
typedef void (*lwdebuglogger)(int level, const char* fmt, va_list ap)
__attribute__ (( format(printf, 2,0) ));
/**
* Install custom memory management and error handling functions you want your
* application to use.
* @ingroup system
* @todo take a structure ?
*/
extern void lwgeom_set_handlers(lwallocator allocator,
lwreallocator reallocator, lwfreeor freeor, lwreporter errorreporter,
lwreporter noticereporter);
extern void lwgeom_set_debuglogger(lwdebuglogger debuglogger);
/**
* Request interruption of any running code
*
* Safe for use from signal handlers
*
* Interrupted code will (as soon as it finds out
* to be interrupted) cleanup and return as soon as possible.
*
* The return value from interrupted code is undefined,
* it is the caller responsibility to not take it in consideration.
*
*/
extern void lwgeom_request_interrupt(void);
/**
* Cancel any interruption request
*/
extern void lwgeom_cancel_interrupt(void);
/**
* Install a callback to be called periodically during
* algorithm execution. Mostly only needed on WIN32 to
* dispatch queued signals.
*
* The callback is invoked before checking for interrupt
* being requested, so you can request interruption from
* the callback, if you want (see lwgeom_request_interrupt).
*
*/
typedef void (lwinterrupt_callback)();
extern lwinterrupt_callback *lwgeom_register_interrupt_callback(lwinterrupt_callback *);
/******************************************************************
* LWGEOM and GBOX both use LWFLAGS bit mask.
* Serializations (may) use different bit mask schemes.
*/
typedef uint16_t lwflags_t;
/******************************************************************
* LWGEOM varlena equivalent type that contains both the size and
* data(see Postgresql c.h)
*/
typedef struct lwvarlena_t
{
uint32_t size; /* Do not touch this field directly! */
char data[]; /* Data content is here */
} lwvarlena_t;
#define LWVARHDRSZ ((int32_t) sizeof(int32_t))
/**
* 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. See SET_VARSIZE_4B / VARSIZE_4B in
* PGSRC/src/include/postgres.h for details.
*/
#ifdef WORDS_BIGENDIAN
#define LWSIZE_GET(varsize) ((varsize) & 0x3FFFFFFF)
#define LWSIZE_SET(varsize, len) ((varsize) = ((len) & 0x3FFFFFFF))
#define IS_BIG_ENDIAN 1
#else
#define LWSIZE_GET(varsize) (((varsize) >> 2) & 0x3FFFFFFF)
#define LWSIZE_SET(varsize, len) ((varsize) = (((uint32_t)(len)) << 2))
#define IS_BIG_ENDIAN 0
#endif
/******************************************************************/
typedef struct {
double afac, bfac, cfac, dfac, efac, ffac, gfac, hfac, ifac, xoff, yoff, zoff;
} AFFINE;
/******************************************************************/
typedef struct
{
double xmin, ymin, zmin;
double xmax, ymax, zmax;
int32_t srid;
}
BOX3D;
/******************************************************************
* GBOX structure.
* We include the flags (information about dimensionality),
* so we don't have to constantly pass them
* into functions that use the GBOX.
*/
typedef struct
{
lwflags_t flags;
double xmin;
double xmax;
double ymin;
double ymax;
double zmin;
double zmax;
double mmin;
double mmax;
} GBOX;
/******************************************************************
* SPHEROID
*
* Standard definition of an ellipsoid (what wkt calls a spheroid)
* f = (a-b)/a
* e_sq = (a*a - b*b)/(a*a)
* b = a - fa
*/
typedef struct
{
double a; /* semimajor axis */
double b; /* semiminor axis b = (a - fa) */
double f; /* flattening f = (a-b)/a */
double e; /* eccentricity (first) */
double e_sq; /* eccentricity squared (first) e_sq = (a*a-b*b)/(a*a) */
double radius; /* spherical average radius = (2*a+b)/3 */
char name[20]; /* name of ellipse */
}
SPHEROID;
/******************************************************************
* POINT2D, POINT3D, POINT3DM, POINT4D
*/
typedef struct
{
double x, y;
}
POINT2D;
typedef struct
{
double x, y, z;
}
POINT3DZ;
typedef struct
{
double x, y, z;
}
POINT3D;
typedef struct
{
double x, y, m;
}
POINT3DM;
typedef struct
{
double x, y, z, m;
}
POINT4D;
/******************************************************************
* POINTARRAY
* Point array abstracts a lot of the complexity of points and point lists.
* It handles 2d/3d translation
* (2d points converted to 3d will have z=0 or NaN)
* DO NOT MIX 2D and 3D POINTS! EVERYTHING* is either one or the other
*/
typedef struct
{
uint32_t npoints; /* how many points we are currently storing */
uint32_t maxpoints; /* how many points we have space for in serialized_pointlist */
/* Use FLAGS_* macros to handle */
lwflags_t flags;
/* Array of POINT 2D, 3D or 4D, possibly misaligned. */
uint8_t *serialized_pointlist;
}
POINTARRAY;
/******************************************************************
* GSERIALIZED
*/
typedef struct
{
uint32_t size; /* For PgSQL use only, use VAR* macros to manipulate. */
uint8_t srid[3]; /* 24 bits of SRID */
uint8_t gflags; /* HasZ, HasM, HasBBox, IsGeodetic */
uint8_t data[1]; /* See gserialized.txt */
} GSERIALIZED;
/******************************************************************
* LWGEOM (any geometry type)
*
* Abstract type, note that 'type', 'bbox' and 'srid' are available in
* all geometry variants.
*/
typedef struct
{
GBOX *bbox;
void *data;
int32_t srid;
lwflags_t flags;
uint8_t type;
char pad[1]; /* Padding to 24 bytes (unused) */
}
LWGEOM;
/* POINTYPE */
typedef struct
{
GBOX *bbox;
POINTARRAY *point; /* hide 2d/3d (this will be an array of 1 point) */
int32_t srid;
lwflags_t flags;
uint8_t type; /* POINTTYPE */
char pad[1]; /* Padding to 24 bytes (unused) */
}
LWPOINT; /* "light-weight point" */
/* LINETYPE */
typedef struct
{
GBOX *bbox;
POINTARRAY *points; /* array of POINT3D */
int32_t srid;
lwflags_t flags;
uint8_t type; /* LINETYPE */
char pad[1]; /* Padding to 24 bytes (unused) */
}
LWLINE; /* "light-weight line" */
/* TRIANGLE */
typedef struct
{
GBOX *bbox;
POINTARRAY *points;
int32_t srid;
lwflags_t flags;
uint8_t type;
char pad[1]; /* Padding to 24 bytes (unused) */
}
LWTRIANGLE;
/* CIRCSTRINGTYPE */
typedef struct
{
GBOX *bbox;
POINTARRAY *points; /* array of POINT(3D/3DM) */
int32_t srid;
lwflags_t flags;
uint8_t type; /* CIRCSTRINGTYPE */
char pad[1]; /* Padding to 24 bytes (unused) */
}
LWCIRCSTRING; /* "light-weight circularstring" */
/* POLYGONTYPE */
typedef struct
{
GBOX *bbox;
POINTARRAY **rings; /* list of rings (list of points) */
int32_t srid;
lwflags_t flags;
uint8_t type; /* POLYGONTYPE */
char pad[1]; /* Padding to 24 bytes (unused) */
uint32_t nrings; /* how many rings we are currently storing */
uint32_t maxrings; /* how many rings we have space for in **rings */
}
LWPOLY; /* "light-weight polygon" */
/* MULTIPOINTTYPE */
typedef struct
{
GBOX *bbox;
LWPOINT **geoms;
int32_t srid;
lwflags_t flags;
uint8_t type; /* MULTYPOINTTYPE */
char pad[1]; /* Padding to 24 bytes (unused) */
uint32_t ngeoms; /* how many geometries we are currently storing */
uint32_t maxgeoms; /* how many geometries we have space for in **geoms */
}
LWMPOINT;
/* MULTILINETYPE */
typedef struct
{
GBOX *bbox;
LWLINE **geoms;
int32_t srid;
lwflags_t flags;
uint8_t type; /* MULTILINETYPE */
char pad[1]; /* Padding to 24 bytes (unused) */
uint32_t ngeoms; /* how many geometries we are currently storing */
uint32_t maxgeoms; /* how many geometries we have space for in **geoms */
}
LWMLINE;
/* MULTIPOLYGONTYPE */
typedef struct
{
GBOX *bbox;
LWPOLY **geoms;
int32_t srid;
lwflags_t flags;
uint8_t type; /* MULTIPOLYGONTYPE */
char pad[1]; /* Padding to 24 bytes (unused) */
uint32_t ngeoms; /* how many geometries we are currently storing */
uint32_t maxgeoms; /* how many geometries we have space for in **geoms */
}
LWMPOLY;
/* COLLECTIONTYPE */
typedef struct
{
GBOX *bbox;
LWGEOM **geoms;
int32_t srid;
lwflags_t flags;
uint8_t type; /* COLLECTIONTYPE */
char pad[1]; /* Padding to 24 bytes (unused) */
uint32_t ngeoms; /* how many geometries we are currently storing */
uint32_t maxgeoms; /* how many geometries we have space for in **geoms */
}
LWCOLLECTION;
/* COMPOUNDTYPE */
typedef struct
{
GBOX *bbox;
LWGEOM **geoms;
int32_t srid;
lwflags_t flags;
uint8_t type; /* COLLECTIONTYPE */
char pad[1]; /* Padding to 24 bytes (unused) */
uint32_t ngeoms; /* how many geometries we are currently storing */
uint32_t maxgeoms; /* how many geometries we have space for in **geoms */
}
LWCOMPOUND; /* "light-weight compound line" */
/* CURVEPOLYTYPE */
typedef struct
{
GBOX *bbox;
LWGEOM **rings;
int32_t srid;
lwflags_t flags;
uint8_t type; /* CURVEPOLYTYPE */
char pad[1]; /* Padding to 24 bytes (unused) */
uint32_t nrings; /* how many rings we are currently storing */
uint32_t maxrings; /* how many rings we have space for in **rings */
}
LWCURVEPOLY; /* "light-weight polygon" */
/* MULTICURVE */
typedef struct
{
GBOX *bbox;
LWGEOM **geoms;
int32_t srid;
lwflags_t flags;
uint8_t type; /* MULTICURVE */
char pad[1]; /* Padding to 24 bytes (unused) */
uint32_t ngeoms; /* how many geometries we are currently storing */
uint32_t maxgeoms; /* how many geometries we have space for in **geoms */
}
LWMCURVE;
/* MULTISURFACETYPE */
typedef struct
{
GBOX *bbox;
LWGEOM **geoms;
int32_t srid;
lwflags_t flags;
uint8_t type; /* MULTISURFACETYPE */
char pad[1]; /* Padding to 24 bytes (unused) */
uint32_t ngeoms; /* how many geometries we are currently storing */
uint32_t maxgeoms; /* how many geometries we have space for in **geoms */
}
LWMSURFACE;
/* POLYHEDRALSURFACETYPE */
typedef struct
{
GBOX *bbox;
LWPOLY **geoms;
int32_t srid;
lwflags_t flags;
uint8_t type; /* POLYHEDRALSURFACETYPE */
char pad[1]; /* Padding to 24 bytes (unused) */
uint32_t ngeoms; /* how many geometries we are currently storing */
uint32_t maxgeoms; /* how many geometries we have space for in **geoms */
}
LWPSURFACE;
/* TINTYPE */
typedef struct
{
GBOX *bbox;
LWTRIANGLE **geoms;
int32_t srid;
lwflags_t flags;
uint8_t type; /* TINTYPE */
char pad[1]; /* Padding to 24 bytes (unused) */
uint32_t ngeoms; /* how many geometries we are currently storing */
uint32_t maxgeoms; /* how many geometries we have space for in **geoms */
}
LWTIN;
/* Casts LWGEOM->LW* (return NULL if cast is illegal) */
extern LWMPOLY *lwgeom_as_lwmpoly(const LWGEOM *lwgeom);
extern LWMLINE *lwgeom_as_lwmline(const LWGEOM *lwgeom);
extern LWMPOINT *lwgeom_as_lwmpoint(const LWGEOM *lwgeom);
extern LWCOLLECTION *lwgeom_as_lwcollection(const LWGEOM *lwgeom);
extern LWPOLY *lwgeom_as_lwpoly(const LWGEOM *lwgeom);
extern LWLINE *lwgeom_as_lwline(const LWGEOM *lwgeom);
extern LWCIRCSTRING *lwgeom_as_lwcircstring(const LWGEOM *lwgeom);
extern LWCURVEPOLY *lwgeom_as_lwcurvepoly(const LWGEOM *lwgeom);
extern LWCOMPOUND *lwgeom_as_lwcompound(const LWGEOM *lwgeom);
extern LWPSURFACE *lwgeom_as_lwpsurface(const LWGEOM *lwgeom);
extern LWTRIANGLE *lwgeom_as_lwtriangle(const LWGEOM *lwgeom);
extern LWTIN *lwgeom_as_lwtin(const LWGEOM *lwgeom);
extern LWGEOM *lwgeom_as_multi(const LWGEOM *lwgeom);
extern LWGEOM *lwgeom_as_curve(const LWGEOM *lwgeom);
/* Casts LW*->LWGEOM (always cast) */
extern LWGEOM *lwtin_as_lwgeom(const LWTIN *obj);
extern LWGEOM *lwtriangle_as_lwgeom(const LWTRIANGLE *obj);
extern LWGEOM *lwpsurface_as_lwgeom(const LWPSURFACE *obj);
extern LWGEOM *lwmpoly_as_lwgeom(const LWMPOLY *obj);
extern LWGEOM *lwmline_as_lwgeom(const LWMLINE *obj);
extern LWGEOM *lwmpoint_as_lwgeom(const LWMPOINT *obj);
extern LWGEOM *lwcollection_as_lwgeom(const LWCOLLECTION *obj);
extern LWGEOM *lwcircstring_as_lwgeom(const LWCIRCSTRING *obj);
extern LWGEOM *lwcompound_as_lwgeom(const LWCOMPOUND *obj);
extern LWGEOM *lwcurvepoly_as_lwgeom(const LWCURVEPOLY *obj);
extern LWGEOM *lwpoly_as_lwgeom(const LWPOLY *obj);
extern LWGEOM *lwline_as_lwgeom(const LWLINE *obj);
extern LWGEOM *lwpoint_as_lwgeom(const LWPOINT *obj);
extern LWCOLLECTION* lwcollection_add_lwgeom(LWCOLLECTION *col, const LWGEOM *geom);
extern LWMPOINT* lwmpoint_add_lwpoint(LWMPOINT *mobj, const LWPOINT *obj);
extern LWMLINE* lwmline_add_lwline(LWMLINE *mobj, const LWLINE *obj);
extern LWMPOLY* lwmpoly_add_lwpoly(LWMPOLY *mobj, const LWPOLY *obj);
extern LWPSURFACE* lwpsurface_add_lwpoly(LWPSURFACE *mobj, const LWPOLY *obj);
extern LWTIN* lwtin_add_lwtriangle(LWTIN *mobj, const LWTRIANGLE *obj);
extern LWCOLLECTION* lwcollection_concat_in_place(LWCOLLECTION* col1, const LWCOLLECTION* col2);
/**
* Construct a new flags bitmask.
*/
extern lwflags_t lwflags(int hasz, int hasm, int geodetic);
/***********************************************************************
** GSERIALIZED API
*/
/**
* Read standard lwflags from gserialized
*/
extern lwflags_t gserialized_get_lwflags(const GSERIALIZED *g);
/**
* Access to the float bounding box, if there is one.
* NULL if there is not.
*/
extern const float * gserialized_get_float_box_p(const GSERIALIZED *g, size_t *ndims);
/**
* Extract the geometry type from the serialized form (it hides in
* the anonymous data area, so this is a handy function).
*/
extern uint32_t gserialized_get_type(const GSERIALIZED *g);
/**
* Returns the size in bytes to read from toast to get the basic
* information from a geometry: GSERIALIZED struct, bbox and type
*/
extern uint32_t gserialized_max_header_size(void);
/**
* Returns a hash code for the srid/type/geometry information
* in the GSERIALIZED. Ignores metadata like flags and optional
* boxes, etc.
*/
extern int32_t gserialized_hash(const GSERIALIZED *g);
/**
* Extract the SRID from the serialized form (it is packed into
* three bytes so this is a handy function).
*/
extern int32_t gserialized_get_srid(const GSERIALIZED *g);
/**
* Write the SRID into the serialized form (it is packed into
* three bytes so this is a handy function).
*/
extern void gserialized_set_srid(GSERIALIZED *g, int32_t srid);
/**
* Check if a #GSERIALIZED is empty without deserializing first.
* Only checks if the number of elements of the parent geometry
* is zero, will not catch collections of empty, eg:
* GEOMETRYCOLLECTION(POINT EMPTY)
*/
extern int gserialized_is_empty(const GSERIALIZED *g);
/**
* Check if a #GSERIALIZED has a bounding box without deserializing first.
*/
extern int gserialized_has_bbox(const GSERIALIZED *gser);
/**
* Check if a #GSERIALIZED has a Z ordinate.
*/
extern int gserialized_has_z(const GSERIALIZED *gser);
/**
* Check if a #GSERIALIZED has an M ordinate.
*/
extern int gserialized_has_m(const GSERIALIZED *gser);
/**
* Check if a #GSERIALIZED is a geography.
*/
extern int gserialized_is_geodetic(const GSERIALIZED *gser);
/**
* Return the number of dimensions (2, 3, 4) in a geometry
*/
extern int gserialized_ndims(const GSERIALIZED *gser);
/**
* Return -1 if g1 is "less than" g2, 1 if g1 is "greater than"
* g2 and 0 if g1 and g2 are the "same". Equality is evaluated
* with a memcmp and size check. So it is possible that two
* identical objects where one lacks a bounding box could be
* evaluated as non-equal initially. Greater and less than
* are evaluated by calculating a sortable key from the center
* point of the object bounds.
*/
extern int gserialized_cmp(const GSERIALIZED *g1, const GSERIALIZED *g2);
/**
* Allocate a new #GSERIALIZED from an #LWGEOM. For all non-point types, a bounding
* box will be calculated and embedded in the serialization. The geodetic flag is used
* to control the box calculation (cartesian or geocentric). If set, the size pointer
* will contain the size of the final output, which is useful for setting the PgSQL
* VARSIZE information.
*/
extern GSERIALIZED* gserialized_from_lwgeom(LWGEOM *geom, size_t *size);
/**
* Allocate a new #LWGEOM from a #GSERIALIZED. The resulting #LWGEOM will have coordinates
* that are double aligned and suitable for direct reading using getPoint2d_cp
*/
extern LWGEOM* lwgeom_from_gserialized(const GSERIALIZED *g);
/**
* Pull a #GBOX from the header of a #GSERIALIZED, if one is available. If
* it is not, calculate it from the geometry. If that doesn't work (null
* or empty) return LW_FAILURE.
*/
extern int gserialized_get_gbox_p(const GSERIALIZED *g, GBOX *box);
/**
* Pull a #GBOX from the header of a #GSERIALIZED, if one is available. If
* it is not, return LW_FAILURE.
*/
extern int gserialized_fast_gbox_p(const GSERIALIZED *g, GBOX *box);
/**
* Copy a new bounding box into an existing gserialized.
* If necessary a new #GSERIALIZED will be allocated. Test
* that input != output before freeing input.
*/
extern GSERIALIZED *gserialized_set_gbox(GSERIALIZED *g, GBOX *gbox);
/**
* Remove the bounding box from a #GSERIALIZED. Returns a freshly
* allocated #GSERIALIZED every time.
*/
extern GSERIALIZED* gserialized_drop_gbox(GSERIALIZED *g);
/**
* Return the serialization version
*/
extern uint32_t gserialized_get_version(const GSERIALIZED *g);
/**
* Pull the first point values of a #GSERIALIZED. Only works for POINTTYPE
*/
extern int gserialized_peek_first_point(const GSERIALIZED *g, POINT4D *out_point);
/*****************************************************************************/
/**
* Call this function to drop BBOX and SRID
* from LWGEOM. If LWGEOM type is *not* flagged
* with the HASBBOX flag and has a bbox, it
* will be released.
*/
extern void lwgeom_drop_bbox(LWGEOM *lwgeom);
extern void lwgeom_drop_srid(LWGEOM *lwgeom);
/**
* Compute a bbox if not already computed
*
* After calling this function lwgeom->bbox is only
* NULL if the geometry is empty.
*/
extern void lwgeom_add_bbox(LWGEOM *lwgeom);
/**
* Drop current bbox and calculate a fresh one.
*/
extern void lwgeom_refresh_bbox(LWGEOM *lwgeom);
/**
* Compute a box for geom and all sub-geometries, if not already computed
*/
extern void lwgeom_add_bbox_deep(LWGEOM *lwgeom, GBOX *gbox);
/**
* Get a non-empty geometry bounding box, computing and
* caching it if not already there
*
* NOTE: empty geometries don't have a bounding box so
* you'd still get a NULL for them.
*/
extern const GBOX *lwgeom_get_bbox(const LWGEOM *lwgeom);
/**
* Determine whether a LWGEOM can contain sub-geometries or not
*/
extern int lwgeom_is_collection(const LWGEOM *lwgeom);
/**
* Check if a LWGEOM has any non-finite (NaN or Inf) coordinates.
*/
extern int lwgeom_isfinite(const LWGEOM *lwgeom);
/******************************************************************/
/* Functions that work on type numbers */
/**
* Determine whether a type number is a collection or not
*/
extern int lwtype_is_collection(uint8_t type);
/**
* Given an lwtype number, what homogeneous collection can hold it?
*/
extern uint32_t lwtype_get_collectiontype(uint8_t type);
/**
* Return the type name string associated with a type number
* (e.g. Point, LineString, Polygon)
*/
extern const char *lwtype_name(uint8_t type);
extern uint8_t lwtype_multitype(uint8_t type);
/******************************************************************/
/*
* copies a point from the point array into the parameter point
* will set point's z=0 (or NaN) if pa is 2d
* will set point's m=0 (or NaN) if pa is 3d or 2d
* NOTE: point is a real POINT3D *not* a pointer
*/
extern POINT4D getPoint4d(const POINTARRAY *pa, uint32_t n);
/*
* copies a point from the point array into the parameter point
* will set point's z=0 (or NaN) if pa is 2d
* will set point's m=0 (or NaN) if pa is 3d or 2d
* NOTE: this will modify the point4d pointed to by 'point'.
*/
extern int getPoint4d_p(const POINTARRAY *pa, uint32_t n, POINT4D *point);
/*
* copies a point from the point array into the parameter point
* will set point's z=0 (or NaN) if pa is 2d
* NOTE: point is a real POINT3D *not* a pointer
*/
extern POINT3DZ getPoint3dz(const POINTARRAY *pa, uint32_t n);
extern POINT3DM getPoint3dm(const POINTARRAY *pa, uint32_t n);
/*
* copies a point from the point array into the parameter point
* will set point's z=0 (or NaN) if pa is 2d
* NOTE: this will modify the point3d pointed to by 'point'.
*/
extern int getPoint3dz_p(const POINTARRAY *pa, uint32_t n, POINT3DZ *point);
extern int getPoint3dm_p(const POINTARRAY *pa, uint32_t n, POINT3DM *point);
/*
* copies a point from the point array into the parameter point
* z value (if present is not returned)
* NOTE: point is a real POINT3D *not* a pointer
*/
extern POINT2D getPoint2d(const POINTARRAY *pa, uint32_t n);
/*
* copies a point from the point array into the parameter point
* z value (if present is not returned)
* NOTE: this will modify the point2d pointed to by 'point'.
*/
extern int getPoint2d_p(const POINTARRAY *pa, uint32_t n, POINT2D *point);
/*
* set point N to the given value
* NOTE that the pointarray can be of any
* dimension, the appropriate ordinate values
* will be extracted from it
*
* N must be a valid point index
*/
extern void ptarray_set_point4d(POINTARRAY *pa, uint32_t n, const POINT4D *p4d);
/**
* Construct an empty pointarray, allocating storage and setting
* the npoints, but not filling in any information. Should be used in conjunction
* with ptarray_set_point4d to fill in the information in the array.
*/
extern POINTARRAY* ptarray_construct(char hasz, char hasm, uint32_t npoints);
/**
* Construct a new #POINTARRAY, copying in the data from ptlist
*/
extern POINTARRAY* ptarray_construct_copy_data(char hasz, char hasm, uint32_t npoints, const uint8_t *ptlist);
/**
* Construct a new #POINTARRAY, referencing to the data from ptlist
*/
extern POINTARRAY* ptarray_construct_reference_data(char hasz, char hasm, uint32_t npoints, uint8_t *ptlist);
/**
* Create a new #POINTARRAY with no points. Allocate enough storage
* to hold maxpoints vertices before having to reallocate the storage
* area.
*/
extern POINTARRAY* ptarray_construct_empty(char hasz, char hasm, uint32_t maxpoints);
/**
* Append a point to the end of an existing #POINTARRAY
* If allow_duplicate is LW_FALSE, then a duplicate point will
* not be added.
*/
extern int ptarray_append_point(POINTARRAY *pa, const POINT4D *pt, int allow_duplicates);
/**
* Append a #POINTARRAY, pa2 to the end of an existing #POINTARRAY, pa1.
*
* If gap_tolerance is >= 0 then the end point of pa1 will be checked for
* being within gap_tolerance 2d distance from start point of pa2 or an
* error will be raised and LW_FAILURE returned.
* A gap_tolerance < 0 disables the check.
*
* If end point of pa1 and start point of pa2 are 2d-equal, then pa2 first
* point will not be appended.
*/
extern int ptarray_append_ptarray(POINTARRAY *pa1, POINTARRAY *pa2, double gap_tolerance);
/**
* Insert a point into an existing #POINTARRAY. Zero
* is the index of the start of the array.
*/
extern int ptarray_insert_point(POINTARRAY *pa, const POINT4D *p, uint32_t where);
/**
* Remove a point from an existing #POINTARRAY. Zero
* is the index of the start of the array.
*/
extern int ptarray_remove_point(POINTARRAY *pa, uint32_t where);
/**
* @brief Add a point in a pointarray.
*
* @param pa the source POINTARRAY
* @param p the point to add
* @param pdims number of ordinates in p (2..4)
* @param where to insert the point. 0 prepends, pa->npoints appends
*
* @returns a newly constructed POINTARRAY using a newly allocated buffer
* for the actual points, or NULL on error.
*/
extern POINTARRAY *ptarray_addPoint(const POINTARRAY *pa, uint8_t *p, size_t pdims, uint32_t where);
/**
* @brief Remove a point from a pointarray.
* @param where - is the offset (starting at 0)
* @return #POINTARRAY is newly allocated
*/
extern POINTARRAY *ptarray_removePoint(POINTARRAY *pa, uint32_t where);
/**
* @brief Merge two given POINTARRAY and returns a pointer
* on the new aggregate one.
* Warning: this function free the two inputs POINTARRAY
* @return #POINTARRAY is newly allocated
*/
extern POINTARRAY *ptarray_merge(POINTARRAY *pa1, POINTARRAY *pa2);
extern int ptarray_is_closed(const POINTARRAY *pa);
extern int ptarray_is_closed_2d(const POINTARRAY *pa);
extern int ptarray_is_closed_3d(const POINTARRAY *pa);
extern int ptarray_is_closed_z(const POINTARRAY *pa);
extern POINTARRAY* ptarray_flip_coordinates(POINTARRAY *pa);
/**
* @d1 start location (distance from start / total distance)
* @d2 end location (distance from start / total distance)
* @param tolerance snap to vertices at locations < tolerance away from given ones
*/
extern POINTARRAY *ptarray_substring(POINTARRAY *pa, double d1, double d2,
double tolerance);
/**
* @param pa the subject pointarray
* @param qp the query point
* @param dist optional output for actual distance from vertex
*/
extern int ptarray_closest_vertex_2d(const POINTARRAY *pa,
const POINT2D *qp, double *dist);
/**
* @param pa the subject pointarray
* @param qp the query point
* @param dist optional output for actual distance from segment
* @return 0-based segment index for the closest segment
* (earliest segment in case of same distance)
*/
extern int ptarray_closest_segment_2d(const POINTARRAY *pa,
const POINT2D *qp, double *dist);
/**
* Strip out the Z/M components of an #LWGEOM
*/
extern LWGEOM* lwgeom_force_2d(const LWGEOM *geom);
extern LWGEOM* lwgeom_force_3dz(const LWGEOM *geom, double zval);
extern LWGEOM* lwgeom_force_3dm(const LWGEOM *geom, double mval);
extern LWGEOM* lwgeom_force_4d(const LWGEOM *geom, double zval, double mval);
extern LWGEOM* lwgeom_set_effective_area(const LWGEOM *igeom, int set_area, double area);
extern LWGEOM* lwgeom_chaikin(const LWGEOM *igeom, int n_iterations, int preserve_endpoint);
extern LWGEOM* lwgeom_filter_m(LWGEOM *geom, double min, double max, int returnm);
/*
* Force to use SFS 1.1 geometry type
* (rather than SFS 1.2 and/or SQL/MM)
*/
extern LWGEOM* lwgeom_force_sfs(LWGEOM *geom, int version);
/*--------------------------------------------------------
* all the base types (point/line/polygon) will have a
* basic constructor, basic de-serializer, basic serializer,
* bounding box finder and (TODO) serialized form size finder.
*--------------------------------------------------------*/
/*
* convenience functions to hide the POINTARRAY
*/
extern int lwpoint_getPoint2d_p(const LWPOINT *point, POINT2D *out);
extern int lwpoint_getPoint3dz_p(const LWPOINT *point, POINT3DZ *out);
extern int lwpoint_getPoint3dm_p(const LWPOINT *point, POINT3DM *out);
extern int lwpoint_getPoint4d_p(const LWPOINT *point, POINT4D *out);
/******************************************************************
* LWLINE functions
******************************************************************/
/**
* Add a LWPOINT to an LWLINE
*/
extern int lwline_add_lwpoint(LWLINE *line, LWPOINT *point, uint32_t where);
/**
* Interpolate one or more points along a line
*/
extern POINTARRAY* lwline_interpolate_points(const LWLINE *line, double length_fraction, char repeat);
/**
* Interpolate one point along a line in 3D
*/
extern LWPOINT* lwline_interpolate_point_3d(const LWLINE *line, double distance);
/******************************************************************
* LWPOLY functions
******************************************************************/
/**
* Add a ring, allocating extra space if necessary. The polygon takes
* ownership of the passed point array.
*/
extern int lwpoly_add_ring(LWPOLY *poly, POINTARRAY *pa);
/**
* Add a ring, allocating extra space if necessary. The curvepolygon takes
* ownership of the passed point array.
*/
extern int lwcurvepoly_add_ring(LWCURVEPOLY *poly, LWGEOM *ring);
/**
* Add a component, allocating extra space if necessary. The compoundcurve
* takes owership of the passed geometry.
*/
extern int lwcompound_add_lwgeom(LWCOMPOUND *comp, LWGEOM *geom);
/**
* Construct an equivalent compound curve from a linestring.
* Compound curves can have linear components, so this works fine
*/
extern LWCOMPOUND* lwcompound_construct_from_lwline(const LWLINE *lwpoly);
/**
* Construct an equivalent curve polygon from a polygon. Curve polygons
* can have linear rings as their rings, so this works fine (in theory?)
*/
extern LWCURVEPOLY* lwcurvepoly_construct_from_lwpoly(LWPOLY *lwpoly);
/******************************************************************
* LWGEOM functions
******************************************************************/
extern int lwcollection_ngeoms(const LWCOLLECTION *col);
/* Given a generic geometry/collection, return the "simplest" form.
* The elements of the homogenized collection are deeply cloned
* */
extern LWGEOM *lwgeom_homogenize(const LWGEOM *geom);
/******************************************************************
* LWMULTIx and LWCOLLECTION functions
******************************************************************/
LWGEOM *lwcollection_getsubgeom(LWCOLLECTION *col, int gnum);
LWCOLLECTION* lwcollection_extract(const LWCOLLECTION *col, uint32_t type);
/******************************************************************
* SERIALIZED FORM functions
******************************************************************/
/**
* Set the SRID on an LWGEOM
* For collections, only the parent gets an SRID, all
* the children get SRID_UNKNOWN.
*/
extern void lwgeom_set_srid(LWGEOM *geom, int32_t srid);
/*------------------------------------------------------
* other stuff
*
* handle the double-to-float conversion. The results of this
* will usually be a slightly bigger box because of the difference
* between float8 and float4 representations.
*/
extern BOX3D* box3d_from_gbox(const GBOX *gbox);
extern GBOX* box3d_to_gbox(const BOX3D *b3d);
void expand_box3d(BOX3D *box, double d);
/****************************************************************
* MEMORY MANAGEMENT
****************************************************************/
/*
* The *_free family of functions frees *all* memory associated
* with the pointer. When the recursion gets to the level of the
* POINTARRAY, the POINTARRAY is only freed if it is not flagged
* as "read only". LWGEOMs constructed on top of GSERIALIZED
* from PgSQL use read only point arrays.
*/
extern void ptarray_free(POINTARRAY *pa);
extern void lwpoint_free(LWPOINT *pt);
extern void lwline_free(LWLINE *line);
extern void lwpoly_free(LWPOLY *poly);
extern void lwtriangle_free(LWTRIANGLE *triangle);
extern void lwmpoint_free(LWMPOINT *mpt);
extern void lwmline_free(LWMLINE *mline);
extern void lwmpoly_free(LWMPOLY *mpoly);
extern void lwpsurface_free(LWPSURFACE *psurf);
extern void lwtin_free(LWTIN *tin);
extern void lwcollection_free(LWCOLLECTION *col);
extern void lwcircstring_free(LWCIRCSTRING *curve);
extern void lwgeom_free(LWGEOM *geom);
/*
* The *_release family of functions frees the LWGEOM structures
* surrounding the POINTARRAYs but leaves the POINTARRAYs
* intact. Useful when re-shaping geometries between types,
* or splicing geometries together.
*/
extern void lwpoint_release(LWPOINT *lwpoint);
extern void lwline_release(LWLINE *lwline);
extern void lwpoly_release(LWPOLY *lwpoly);
extern void lwtriangle_release(LWTRIANGLE *lwtriangle);
extern void lwcircstring_release(LWCIRCSTRING *lwcirc);
extern void lwmpoint_release(LWMPOINT *lwpoint);
extern void lwmline_release(LWMLINE *lwline);
extern void lwmpoly_release(LWMPOLY *lwpoly);
extern void lwpsurface_release(LWPSURFACE *lwpsurface);
extern void lwtin_release(LWTIN *lwtin);
extern void lwcollection_release(LWCOLLECTION *lwcollection);
extern void lwgeom_release(LWGEOM *lwgeom);
/****************************************************************
* Utility
****************************************************************/
extern void printBOX3D(BOX3D *b);
extern void printPA(POINTARRAY *pa);
extern void printLWPOINT(LWPOINT *point);
extern void printLWLINE(LWLINE *line);
extern void printLWPOLY(LWPOLY *poly);
extern void printLWTRIANGLE(LWTRIANGLE *triangle);
extern void printLWPSURFACE(LWPSURFACE *psurf);
extern void printLWTIN(LWTIN *tin);
extern float next_float_down(double d);
extern float next_float_up(double d);
/* general utilities 2D */
extern double distance2d_pt_pt(const POINT2D *p1, const POINT2D *p2);
extern double distance2d_sqr_pt_seg(const POINT2D *p, const POINT2D *A, const POINT2D *B);
extern LWGEOM* lwgeom_closest_line(const LWGEOM *lw1, const LWGEOM *lw2);
extern LWGEOM* lwgeom_furthest_line(const LWGEOM *lw1, const LWGEOM *lw2);
extern LWGEOM* lwgeom_closest_point(const LWGEOM *lw1, const LWGEOM *lw2);
extern LWGEOM* lwgeom_furthest_point(const LWGEOM *lw1, const LWGEOM *lw2);
extern double lwgeom_mindistance2d(const LWGEOM *lw1, const LWGEOM *lw2);
extern double lwgeom_mindistance2d_tolerance(const LWGEOM *lw1, const LWGEOM *lw2, double tolerance);
extern double lwgeom_maxdistance2d(const LWGEOM *lw1, const LWGEOM *lw2);
extern double lwgeom_maxdistance2d_tolerance(const LWGEOM *lw1, const LWGEOM *lw2, double tolerance);
/* 3D */
extern double distance3d_pt_pt(const POINT3D *p1, const POINT3D *p2);
extern double distance3d_pt_seg(const POINT3D *p, const POINT3D *A, const POINT3D *B);
extern LWGEOM* lwgeom_furthest_line_3d(LWGEOM *lw1, LWGEOM *lw2);
extern LWGEOM* lwgeom_closest_line_3d(const LWGEOM *lw1, const LWGEOM *lw2);
extern LWGEOM* lwgeom_closest_point_3d(const LWGEOM *lw1, const LWGEOM *lw2);
extern double lwgeom_mindistance3d(const LWGEOM *lw1, const LWGEOM *lw2);
extern double lwgeom_mindistance3d_tolerance(const LWGEOM *lw1, const LWGEOM *lw2, double tolerance);
extern double lwgeom_maxdistance3d(const LWGEOM *lw1, const LWGEOM *lw2);
extern double lwgeom_maxdistance3d_tolerance(const LWGEOM *lw1, const LWGEOM *lw2, double tolerance);
extern double lwgeom_area(const LWGEOM *geom);
extern double lwgeom_length(const LWGEOM *geom);
extern double lwgeom_length_2d(const LWGEOM *geom);
extern double lwgeom_perimeter(const LWGEOM *geom);
extern double lwgeom_perimeter_2d(const LWGEOM *geom);
extern int lwgeom_dimension(const LWGEOM *geom);
extern LWPOINT* lwline_get_lwpoint(const LWLINE *line, uint32_t where);
extern LWPOINT* lwcircstring_get_lwpoint(const LWCIRCSTRING *circ, uint32_t where);
extern LWPOINT* lwcompound_get_startpoint(const LWCOMPOUND *lwcmp);
extern LWPOINT* lwcompound_get_endpoint(const LWCOMPOUND *lwcmp);
extern LWPOINT* lwcompound_get_lwpoint(const LWCOMPOUND *lwcmp, uint32_t where);
extern double ptarray_length_2d(const POINTARRAY *pts);
extern int pt_in_ring_2d(const POINT2D *p, const POINTARRAY *ring);
extern int azimuth_pt_pt(const POINT2D *p1, const POINT2D *p2, double *ret);
extern int lwpoint_inside_circle(const LWPOINT *p, double cx, double cy, double rad);
extern LWGEOM* lwgeom_reverse(const LWGEOM *lwgeom);
extern char* lwgeom_summary(const LWGEOM *lwgeom, int offset);
extern char* lwpoint_to_latlon(const LWPOINT *p, const char *format);
extern int lwgeom_startpoint(const LWGEOM* lwgeom, POINT4D* pt);
extern void interpolate_point4d(const POINT4D *A, const POINT4D *B, POINT4D *I, double F);
/**
* Ensure the outer ring is clockwise oriented and all inner rings
* are counter-clockwise.
*/
extern int lwgeom_is_clockwise(LWGEOM *lwgeom);
/**
* Simplification
*/
extern LWGEOM* lwgeom_simplify(const LWGEOM *igeom, double dist, int preserve_collapsed);
extern LWGEOM* lwgeom_remove_repeated_points(const LWGEOM *in, double tolerance);
/**
* Snap-to-grid
*/
typedef struct gridspec_t
{
double ipx;
double ipy;
double ipz;
double ipm;
double xsize;
double ysize;
double zsize;
double msize;
}
gridspec;
extern LWGEOM* lwgeom_grid(const LWGEOM *lwgeom, const gridspec *grid);
extern void lwgeom_grid_in_place(LWGEOM *lwgeom, const gridspec *grid);
/****************************************************************
* READ/WRITE FUNCTIONS
*
* Coordinate writing functions, which will alter the coordinates
* and potentially the structure of the input geometry. When
* called from within PostGIS, the LWGEOM argument should be built
* on top of a gserialized copy, created using
* PG_GETARG_GSERIALIZED_P_COPY()
****************************************************************/
extern void lwgeom_reverse_in_place(LWGEOM *lwgeom);
extern void lwgeom_force_clockwise(LWGEOM *lwgeom);
extern void lwgeom_longitude_shift(LWGEOM *lwgeom);
extern int lwgeom_simplify_in_place(LWGEOM *igeom, double dist, int preserve_collapsed);
extern void lwgeom_affine(LWGEOM *geom, const AFFINE *affine);
extern void lwgeom_scale(LWGEOM *geom, const POINT4D *factors);
extern int lwgeom_remove_repeated_points_in_place(LWGEOM *in, double tolerance);
/**
* @brief wrap geometry on given cut x value
*
* For a positive amount, shifts anything that is on the left
* of "cutx" to the right by the given amount.
*
* For a negative amount, shifts anything that is on the right
* of "cutx" to the left by the given absolute amount.
*
* @param cutx the X value to perform wrapping on
* @param amount shift amount and wrapping direction
*/
LWGEOM *lwgeom_wrapx(const LWGEOM *lwgeom, double cutx, double amount);
/**
* @brief Check whether or not a lwgeom is big enough to warrant a bounding box.
*
* Check whether or not a lwgeom is big enough to warrant a bounding box
* when stored in the serialized form on disk. Currently only points are
* considered small enough to not require a bounding box, because the
* index operations can generate a large number of box-retrieval operations
* when scanning keys.
*/
extern int lwgeom_needs_bbox(const LWGEOM *geom);
/**
* Count the total number of vertices in any #LWGEOM.
*/
extern uint32_t lwgeom_count_vertices(const LWGEOM *geom);
/**
* Count the total number of rings in any #LWGEOM. Multipolygons
* and other collections get counted, not the same as OGC st_numrings.
*/
extern uint32_t lwgeom_count_rings(const LWGEOM *geom);
/**
* Return true or false depending on whether a geometry has
* a valid SRID set.
*/
extern int lwgeom_has_srid(const LWGEOM *geom);
/**
* Return true or false depending on whether a geometry is a linear
* feature that closes on itself.
*/
extern int lwgeom_is_closed(const LWGEOM *geom);
/**
* Return the dimensionality (relating to point/line/poly) of an lwgeom
*/
extern int lwgeom_dimensionality(const LWGEOM *geom);
/* Is lwgeom1 geometrically equal to lwgeom2 ? */
extern char lwgeom_same(const LWGEOM *lwgeom1, const LWGEOM *lwgeom2);
/**
* @brief Clone LWGEOM object. Serialized point lists are not copied.
*
* #GBOX are copied
*
* @see ptarray_clone
*/
extern LWGEOM *lwgeom_clone(const LWGEOM *lwgeom);
/**
* Deep clone an LWGEOM, everything is copied
*/
extern LWGEOM *lwgeom_clone_deep(const LWGEOM *lwgeom);
extern POINTARRAY *ptarray_clone_deep(const POINTARRAY *ptarray);
/*
* Geometry constructors. These constructors to not copy the point arrays
* passed to them, they just take references, so do not free them out
* from underneath the geometries.
*/
extern LWPOINT* lwpoint_construct(int32_t srid, GBOX *bbox, POINTARRAY *point);
extern LWMPOINT *lwmpoint_construct(int32_t srid, const POINTARRAY *pa);
extern LWLINE* lwline_construct(int32_t srid, GBOX *bbox, POINTARRAY *points);
extern LWCIRCSTRING* lwcircstring_construct(int32_t srid, GBOX *bbox, POINTARRAY *points);
extern LWPOLY* lwpoly_construct(int32_t srid, GBOX *bbox, uint32_t nrings, POINTARRAY **points);
extern LWCURVEPOLY* lwcurvepoly_construct(int32_t srid, GBOX *bbox, uint32_t nrings, LWGEOM **geoms);
extern LWTRIANGLE* lwtriangle_construct(int32_t srid, GBOX *bbox, POINTARRAY *points);
extern LWCOLLECTION* lwcollection_construct(uint8_t type, int32_t srid, GBOX *bbox, uint32_t ngeoms, LWGEOM **geoms);
/*
* Empty geometry constructors.
*/
extern LWGEOM* lwgeom_construct_empty(uint8_t type, int32_t srid, char hasz, char hasm);
extern LWPOINT* lwpoint_construct_empty(int32_t srid, char hasz, char hasm);
extern LWLINE* lwline_construct_empty(int32_t srid, char hasz, char hasm);
extern LWPOLY* lwpoly_construct_empty(int32_t srid, char hasz, char hasm);
extern LWCURVEPOLY* lwcurvepoly_construct_empty(int32_t srid, char hasz, char hasm);
extern LWCIRCSTRING* lwcircstring_construct_empty(int32_t srid, char hasz, char hasm);
extern LWCOMPOUND* lwcompound_construct_empty(int32_t srid, char hasz, char hasm);
extern LWTRIANGLE* lwtriangle_construct_empty(int32_t srid, char hasz, char hasm);
extern LWMPOINT* lwmpoint_construct_empty(int32_t srid, char hasz, char hasm);
extern LWMLINE* lwmline_construct_empty(int32_t srid, char hasz, char hasm);
extern LWMPOLY* lwmpoly_construct_empty(int32_t srid, char hasz, char hasm);
extern LWCOLLECTION* lwcollection_construct_empty(uint8_t type, int32_t srid, char hasz, char hasm);
/* Other constructors */
extern LWPOINT *lwpoint_make2d(int32_t srid, double x, double y);
extern LWPOINT *lwpoint_make3dz(int32_t srid, double x, double y, double z);
extern LWPOINT *lwpoint_make3dm(int32_t srid, double x, double y, double m);
extern LWPOINT *lwpoint_make4d(int32_t srid, double x, double y, double z, double m);
extern LWPOINT *lwpoint_make(int32_t srid, int hasz, int hasm, const POINT4D *p);
extern LWLINE *lwline_from_lwgeom_array(int32_t srid, uint32_t ngeoms, LWGEOM **geoms);
extern LWLINE *lwline_from_ptarray(int32_t srid, uint32_t npoints, LWPOINT **points); /* TODO: deprecate */
extern LWLINE *lwline_from_lwmpoint(int32_t srid, const LWMPOINT *mpoint);
extern LWLINE *lwline_addpoint(LWLINE *line, LWPOINT *point, uint32_t where);
extern LWLINE *lwline_removepoint(LWLINE *line, uint32_t which);
extern void lwline_setPoint4d(LWLINE *line, uint32_t which, POINT4D *newpoint);
extern LWPOLY *lwpoly_from_lwlines(const LWLINE *shell, uint32_t nholes, const LWLINE **holes);
extern LWPOLY *lwpoly_construct_rectangle(char hasz, char hasm, POINT4D *p1, POINT4D *p2, POINT4D *p3, POINT4D *p4);
extern LWPOLY *lwpoly_construct_envelope(int32_t srid, double x1, double y1, double x2, double y2);
extern LWPOLY *lwpoly_construct_circle(int32_t srid, double x, double y, double radius, uint32_t segments_per_quarter, char exterior);
extern LWTRIANGLE *lwtriangle_from_lwline(const LWLINE *shell);
extern LWMPOINT *lwmpoint_from_lwgeom(const LWGEOM *g); /* Extract the coordinates of an LWGEOM into an LWMPOINT */
/* Some point accessors */
extern double lwpoint_get_x(const LWPOINT *point);
extern double lwpoint_get_y(const LWPOINT *point);
extern double lwpoint_get_z(const LWPOINT *point);
extern double lwpoint_get_m(const LWPOINT *point);
/**
* Return SRID number
*/
extern int32_t lwgeom_get_srid(const LWGEOM *geom);
/**
* Return #LW_TRUE if geometry has Z ordinates
*/
extern int lwgeom_has_z(const LWGEOM *geom);
/**
* Return #LW_TRUE if geometry has M ordinates.
*/
extern int lwgeom_has_m(const LWGEOM *geom);
/**
* Return #LW_TRUE if geometry has SOLID flag.
*/
extern int lwgeom_is_solid(const LWGEOM *geom);
/**
* Return the number of dimensions (2, 3, 4) in a geometry
*/
extern int lwgeom_ndims(const LWGEOM *geom);
/*
* Given a point, returns the location of closest point on pointarray
* as a fraction of total length (0: first point -- 1: last point).
*
* If not-null, the third argument will be set to the actual distance
* of the point from the pointarray.
*/
extern double ptarray_locate_point(const POINTARRAY *pa, const POINT4D *pt, double *dist, POINT4D *p_located);
/**
* Add a measure dimension to a line, interpolating linearly from the start
* to the end value.
*/
extern LWLINE *lwline_measured_from_lwline(const LWLINE *lwline, double m_start, double m_end);
extern LWMLINE* lwmline_measured_from_lwmline(const LWMLINE *lwmline, double m_start, double m_end);
/**
* Determine the location(s) along a measured line where m occurs and
* return as a multipoint. Offset to left (positive) or right (negative).
*/
extern LWGEOM* lwgeom_locate_along(const LWGEOM *lwin, double m, double offset);
/**
* Determine the segments along a measured line that fall within the m-range
* given. Return as a multiline or geometrycollection.
* Offset to left (positive) or right (negative).
*/
extern LWCOLLECTION* lwgeom_locate_between(const LWGEOM *lwin, double from, double to, double offset);
/**
* Find the measure value at the location on the line closest to the point.
*/
extern double lwgeom_interpolate_point(const LWGEOM *lwin, const LWPOINT *lwpt);
/**
* Find the time of closest point of approach
*
* @param mindist if not null will be set to the minimum distance between
* the trajectories at the closest point of approach.
*
* @return the time value in which the minimum distance was reached, -1
* if inputs are invalid (lwerror is called in that case),
* -2 if the trajectories do not share any point in time.
*/
extern double lwgeom_tcpa(const LWGEOM *g1, const LWGEOM *g2, double *mindist);
/**
* Is the closest point of approach within a distance ?
*
* @return LW_TRUE or LW_FALSE
*/
extern int lwgeom_cpa_within(const LWGEOM *g1, const LWGEOM *g2, double maxdist);
/**
* Return LW_TRUE or LW_FALSE depending on whether or not a geometry is
* a linestring with measure value growing from start to end vertex
*/
extern int lwgeom_is_trajectory(const LWGEOM *geom);
extern int lwline_is_trajectory(const LWLINE *geom);
/*
* Ensure every segment is at most 'dist' long.
* Returned LWGEOM might is unchanged if a POINT.
*/
extern LWGEOM *lwgeom_segmentize2d(const LWGEOM *line, double dist);
extern POINTARRAY *ptarray_segmentize2d(const POINTARRAY *ipa, double dist);
extern LWLINE *lwline_segmentize2d(const LWLINE *line, double dist);
extern LWPOLY *lwpoly_segmentize2d(const LWPOLY *line, double dist);
extern LWCOLLECTION *lwcollection_segmentize2d(const LWCOLLECTION *coll, double dist);
/*
* Point density functions
*/
extern LWMPOINT *lwpoly_to_points(const LWPOLY *poly, uint32_t npoints, int32_t seed);
extern LWMPOINT *lwmpoly_to_points(const LWMPOLY *mpoly, uint32_t npoints, int32_t seed);
extern LWMPOINT *lwgeom_to_points(const LWGEOM *lwgeom, uint32_t npoints, int32_t seed);
/*
* Geometric median
*/
extern LWPOINT* lwgeom_median(const LWGEOM *g, double tol, uint32_t maxiter, char fail_if_not_converged);
extern LWPOINT* lwmpoint_median(const LWMPOINT *g, double tol, uint32_t maxiter, char fail_if_not_converged);
/**
* Calculate the GeoHash (http://geohash.org) string for a geometry. Caller must free.
*/
lwvarlena_t *lwgeom_geohash(const LWGEOM *lwgeom, int precision);
unsigned int geohash_point_as_int(POINT2D *pt);
/**
* The return values of lwline_crossing_direction()
*/
enum CG_LINE_CROSS_TYPE {
LINE_NO_CROSS = 0,
LINE_CROSS_LEFT = -1,
LINE_CROSS_RIGHT = 1,
LINE_MULTICROSS_END_LEFT = -2,
LINE_MULTICROSS_END_RIGHT = 2,
LINE_MULTICROSS_END_SAME_FIRST_LEFT = -3,
LINE_MULTICROSS_END_SAME_FIRST_RIGHT = 3
};
/**
* Given two lines, characterize how (and if) they cross each other
*/
int lwline_crossing_direction(const LWLINE *l1, const LWLINE *l2);
/**
* Given a geometry clip based on the from/to range of one of its ordinates (x, y, z, m). Use for m- and z- clipping.
*/
LWCOLLECTION* lwgeom_clip_to_ordinate_range(const LWGEOM *lwin, char ordinate, double from, double to, double offset);
/**
* Macros for specifying GML options.
* @{
*/
/** For GML3 only, include srsDimension attribute in output */
#define LW_GML_IS_DIMS (1<<0)
/** For GML3 only, declare that datas are lat/lon. Swaps axis order */
#define LW_GML_IS_DEGREE (1<<1)
/** For GML3, use rather than for lines */
#define LW_GML_SHORTLINE (1<<2)
/** For GML2 and GML3, output only extent of geometry */
#define LW_GML_EXTENT (1<<4)
#define IS_DIMS(x) ((x) & LW_GML_IS_DIMS)
#define IS_DEGREE(x) ((x) & LW_GML_IS_DEGREE)
/** @} */
/**
* Macros for specifying X3D options.
* @{
*/
/** For flip X/Y coordinates to Y/X */
#define LW_X3D_FLIP_XY (1<<0)
#define LW_X3D_USE_GEOCOORDS (1<<1)
#define X3D_USE_GEOCOORDS(x) ((x) & LW_X3D_USE_GEOCOORDS)
extern lwvarlena_t* lwgeom_to_gml2(const LWGEOM *geom, const char *srs, int precision, const char *prefix);
extern lwvarlena_t* lwgeom_extent_to_gml2(const LWGEOM *geom, const char *srs, int precision, const char *prefix);
/**
* @param opts output options bitfield, see LW_GML macros for meaning
*/
extern lwvarlena_t* lwgeom_extent_to_gml3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *prefix);
extern lwvarlena_t* lwgeom_to_gml3(const LWGEOM *geom, const char *srs, int precision, int opts, const char *prefix, const char *id);
extern lwvarlena_t* lwgeom_to_kml2(const LWGEOM *geom, int precision, const char *prefix);
extern lwvarlena_t* lwgeom_to_geojson(const LWGEOM *geo, const char *srs, int precision, int has_bbox);
extern lwvarlena_t* lwgeom_to_x3d3(const LWGEOM *geom, int precision, int opts, const char *defid);
extern lwvarlena_t* lwgeom_to_svg(const LWGEOM *geom, int precision, int relative);
extern lwvarlena_t* lwgeom_to_encoded_polyline(const LWGEOM *geom, int precision);
/**
* Create an LWGEOM object from a GeoJSON representation
*
* @param geojson the GeoJSON input
* @param srs output parameter. Will be set to a newly allocated
* string holding the spatial reference string, or NULL
* if no such parameter is found in input.
* If not null, the pointer must be freed with lwfree.
*/
extern LWGEOM* lwgeom_from_geojson(const char *geojson, char **srs);
/**
* Create an LWGEOM object from an Encoded Polyline representation
*
* @param encodedpolyline the Encoded Polyline input
*/
extern LWGEOM* lwgeom_from_encoded_polyline(const char *encodedpolyline, int precision);
/**
* Initialize a spheroid object for use in geodetic functions.
*/
extern void spheroid_init(SPHEROID *s, double a, double b);
/**
* Calculate the geodetic distance from lwgeom1 to lwgeom2 on the spheroid.
* A spheroid with major axis == minor axis will be treated as a sphere.
* Pass in a tolerance in spheroid units.
*/
extern double lwgeom_distance_spheroid(const LWGEOM *lwgeom1, const LWGEOM *lwgeom2, const SPHEROID *spheroid, double tolerance);
/**
* Calculate the location of a point on a spheroid, give a start point, bearing and distance.
*/
extern LWPOINT* lwgeom_project_spheroid(const LWPOINT *r, const SPHEROID *spheroid, double distance, double azimuth);
/**
* Derive a new geometry with vertices added to ensure no vertex is more
* than max_seg_length (in radians) from any other vertex.
*/
extern LWGEOM* lwgeom_segmentize_sphere(const LWGEOM *lwg_in, double max_seg_length);
/**
* Calculate the bearing between two points on a spheroid.
*/
extern double lwgeom_azumith_spheroid(const LWPOINT *r, const LWPOINT *s, const SPHEROID *spheroid);
/**
* Calculate the geodetic area of a lwgeom on the sphere. The result
* will be multiplied by the average radius of the supplied spheroid.
*/
extern double lwgeom_area_sphere(const LWGEOM *lwgeom, const SPHEROID *spheroid);
/**
* Calculate the geodetic area of a lwgeom on the spheroid. The result
* will have the squared units of the spheroid axes.
*/
extern double lwgeom_area_spheroid(const LWGEOM *lwgeom, const SPHEROID *spheroid);
/**
* Calculate the geodetic length of a lwgeom on the unit sphere. The result
* will have to by multiplied by the real radius to get the real length.
*/
extern double lwgeom_length_spheroid(const LWGEOM *geom, const SPHEROID *s);
/**
* Calculate covers predicate for two lwgeoms on the sphere. Currently
* only handles point-in-polygon.
*/
extern int lwgeom_covers_lwgeom_sphere(const LWGEOM *lwgeom1, const LWGEOM *lwgeom2);
typedef struct {
POINT2D* center;
double radius;
} LWBOUNDINGCIRCLE;
extern void lwboundingcircle_destroy(LWBOUNDINGCIRCLE* c);
/* Calculates the minimum circle that encloses all of the points in g, using a
* two-dimensional implementation of the algorithm proposed in:
*
* Welzl, Emo (1991), "Smallest enclosing disks (balls and elipsoids)."
* New Results and Trends in Computer Science (H. Maurer, Ed.), Lecture Notes
* in Computer Science, 555 (1991) 359-370.
*
* Available online at the time of this writing at
* https://www.inf.ethz.ch/personal/emo/PublFiles/SmallEnclDisk_LNCS555_91.pdf
*
* Returns NULL if the circle could not be calculated.
*/
extern LWBOUNDINGCIRCLE* lwgeom_calculate_mbc(const LWGEOM* g);
/**
* Swap ordinate values in every vertex of the geometry.
*
* Ordinates to swap are specified using an index with meaning:
* 0=x, 1=y, 2=z, 3=m
*
* Swapping an existing ordinate with an unexisting one results
* in undefined value being written in the existing ordinate.
* Caller should verify and prevent such calls.
*
* Availability: 2.2.0
*/
extern void lwgeom_swap_ordinates(LWGEOM *in, LWORD o1, LWORD o2);
struct LWPOINTITERATOR;
typedef struct LWPOINTITERATOR LWPOINTITERATOR;
/**
* Create a new LWPOINTITERATOR over supplied LWGEOM*
*/
extern LWPOINTITERATOR* lwpointiterator_create(const LWGEOM* g);
/**
* Create a new LWPOINTITERATOR over supplied LWGEOM*
* Supports modification of coordinates during iteration.
*/
extern LWPOINTITERATOR* lwpointiterator_create_rw(LWGEOM* g);
/**
* Free all memory associated with the iterator
*/
extern void lwpointiterator_destroy(LWPOINTITERATOR* s);
/**
* Returns LW_TRUE if there is another point available in the iterator.
*/
extern int lwpointiterator_has_next(LWPOINTITERATOR* s);
/**
* Attempts to replace the next point int the iterator with p, and advances
* the iterator to the next point.
* Returns LW_SUCCESS if the assignment was successful, LW_FAILURE otherwise.
* */
extern int lwpointiterator_modify_next(LWPOINTITERATOR* s, const POINT4D* p);
/**
* Attempts to assign the next point in the iterator to p, and advances
* the iterator to the next point. If p is NULL, the iterator will be
* advanced without reading a point.
* Returns LW_SUCCESS if the assignment was successful, LW_FAILURE otherwise.
* */
extern int lwpointiterator_next(LWPOINTITERATOR* s, POINT4D* p);
/**
* Attempts to assigns the next point in the iterator to p. Does not advance.
* Returns LW_SUCCESS if the assignment was successful, LW_FAILURE otherwise.
*/
extern int lwpointiterator_peek(LWPOINTITERATOR* s, POINT4D* p);
/**
* Convert a single hex digit into the corresponding char
*/
extern uint8_t parse_hex(char *str);
/**
* Convert a char into a human readable hex digit
*/
extern void deparse_hex(uint8_t str, char *result);
/***********************************************************************
** Functions for managing serialized forms and bounding boxes.
*/
/**
* Check that coordinates of LWGEOM are all within the geodetic range (-180, -90, 180, 90)
*/
extern int lwgeom_check_geodetic(const LWGEOM *geom);
/**
* Gently move coordinates of LWGEOM if they are close enough into geodetic range.
*/
extern int lwgeom_nudge_geodetic(LWGEOM *geom);
/**
* Force coordinates of LWGEOM into geodetic range (-180, -90, 180, 90)
*/
extern int lwgeom_force_geodetic(LWGEOM *geom);
/**
* Set the FLAGS geodetic bit on geometry an all sub-geometries and pointlists
*/
extern void lwgeom_set_geodetic(LWGEOM *geom, int value);
/**
* Calculate the geodetic bounding box for an LWGEOM. Z/M coordinates are
* ignored for this calculation. Pass in non-null, geodetic bounding box for function
* to fill out. LWGEOM must have been built from a GSERIALIZED to provide
* double aligned point arrays.
*/
extern int lwgeom_calculate_gbox_geodetic(const LWGEOM *geom, GBOX *gbox);
/**
* Calculate the 2-4D bounding box of a geometry. Z/M coordinates are honored
* for this calculation, though for curves they are not included in calculations
* of curvature.
*/
extern int lwgeom_calculate_gbox_cartesian(const LWGEOM *lwgeom, GBOX *gbox);
/**
* Calculate bounding box of a geometry, automatically taking into account
* whether it is cartesian or geodetic.
*/
extern int lwgeom_calculate_gbox(const LWGEOM *lwgeom, GBOX *gbox);
/**
* Calculate geodetic (x/y/z) box and add values to gbox. Return #LW_SUCCESS on success.
*/
extern int ptarray_calculate_gbox_geodetic(const POINTARRAY *pa, GBOX *gbox);
/**
* Calculate box (x/y) and add values to gbox. Return #LW_SUCCESS on success.
*/
extern int ptarray_calculate_gbox_cartesian(const POINTARRAY *pa, GBOX *gbox );
/**
* Calculate a spherical point that falls outside the geocentric gbox
*/
int gbox_pt_outside(const GBOX *gbox, POINT2D *pt_outside);
/**
* Create a new gbox with the dimensionality indicated by the flags. Caller
* is responsible for freeing.
*/
extern GBOX* gbox_new(lwflags_t flags);
/**
* Zero out all the entries in the #GBOX. Useful for cleaning
* statically allocated gboxes.
*/
extern void gbox_init(GBOX *gbox);
/**
* Update the merged #GBOX to be large enough to include itself and the new box.
*/
extern int gbox_merge(const GBOX *new_box, GBOX *merged_box);
/**
* Update the output #GBOX to be large enough to include both inputs.
*/
extern int gbox_union(const GBOX *g1, const GBOX *g2, GBOX *gout);
/**
* Move the box minimums down and the maximums up by the distance provided.
*/
extern void gbox_expand(GBOX *g, double d);
/**
* Move the box minimums down and the maximums up by the distances provided.
*/
extern void gbox_expand_xyzm(GBOX *g, double dx, double dy, double dz, double dm);
/**
* Initialize a #GBOX using the values of the point.
*/
extern int gbox_init_point3d(const POINT3D *p, GBOX *gbox);
/**
* Update the #GBOX to be large enough to include itself and the new point.
*/
extern int gbox_merge_point3d(const POINT3D *p, GBOX *gbox);
/**
* Return true if the point is inside the gbox
*/
extern int gbox_contains_point3d(const GBOX *gbox, const POINT3D *pt);
/**
* Allocate a string representation of the #GBOX, based on dimensionality of flags.
*/
extern char* gbox_to_string(const GBOX *gbox);
/**
* Return a copy of the #GBOX, based on dimensionality of flags.
*/
extern GBOX* gbox_copy(const GBOX *gbox);
/**
* Warning, do not use this function, it is very particular about inputs.
*/
extern GBOX* gbox_from_string(const char *str);
/**
* Return #LW_TRUE if the #GBOX overlaps, #LW_FALSE otherwise.
*/
extern int gbox_overlaps(const GBOX *g1, const GBOX *g2);
/**
* Return #LW_TRUE if the #GBOX overlaps on the 2d plane, #LW_FALSE otherwise.
*/
extern int gbox_overlaps_2d(const GBOX *g1, const GBOX *g2);
/**
* Return #LW_TRUE if the first #GBOX contains the second on the 2d plane, #LW_FALSE otherwise.
*/
extern int gbox_contains_2d(const GBOX *g1, const GBOX *g2);
/**
* Copy the values of original #GBOX into duplicate.
*/
extern void gbox_duplicate(const GBOX *original, GBOX *duplicate);
/**
* Return the number of bytes necessary to hold a #GBOX of this dimension in
* serialized form.
*/
extern size_t gbox_serialized_size(lwflags_t flags);
/**
* Check if 2 given Gbox are the same
*/
extern int gbox_same(const GBOX *g1, const GBOX *g2);
/**
* Check if 2 given GBOX are the same in x and y
*/
extern int gbox_same_2d(const GBOX *g1, const GBOX *g2);
/**
* Check if two given GBOX are the same in x and y, or would round to the same
* GBOX in x and if serialized in GSERIALIZED
*/
extern int gbox_same_2d_float(const GBOX *g1, const GBOX *g2);
/**
* Round given GBOX to float boundaries
*
* This turns a GBOX into the version it would become
* after a serialize/deserialize round trip.
*/
extern void gbox_float_round(GBOX *gbox);
/**
* Return false if any of the dimensions is NaN or infinite
*/
extern int gbox_is_valid(const GBOX *gbox);
/**
* Return a sortable key based on the center point of the GBOX.
*/
extern uint64_t gbox_get_sortable_hash(const GBOX *g, const int32_t srid);
/**
* Return a sortable key based on gserialized.
*/
extern uint64_t gserialized_get_sortable_hash(const GSERIALIZED *g);
/**
* Utility function to get type number from string. For example, a string 'POINTZ'
* would return type of 1 and z of 1 and m of 0. Valid
*/
extern int geometry_type_from_string(const char *str, uint8_t *type, int *z, int *m);
/**
* Parser check flags
*
* @see lwgeom_from_wkb
* @see lwgeom_from_hexwkb
* @see lwgeom_parse_wkt
*/
#define LW_PARSER_CHECK_MINPOINTS 1
#define LW_PARSER_CHECK_ODD 2
#define LW_PARSER_CHECK_CLOSURE 4
#define LW_PARSER_CHECK_ZCLOSURE 8
#define LW_PARSER_CHECK_NONE 0
#define LW_PARSER_CHECK_ALL (LW_PARSER_CHECK_MINPOINTS | LW_PARSER_CHECK_ODD | LW_PARSER_CHECK_CLOSURE)
/**
* Parser result structure: returns the result of attempting to convert
* (E)WKT/(E)WKB to LWGEOM
*/
typedef struct struct_lwgeom_parser_result
{
const char *wkinput; /* Copy of pointer to input WKT/WKB */
uint8_t *serialized_lwgeom; /* Pointer to serialized LWGEOM */
size_t size; /* Size of serialized LWGEOM in bytes */
LWGEOM *geom; /* Pointer to LWGEOM struct */
const char *message; /* Error/warning message */
int errcode; /* Error/warning number */
int errlocation; /* Location of error */
int parser_check_flags; /* Bitmask of validity checks run during this parse */
}
LWGEOM_PARSER_RESULT;
/*
* Parser error messages (these must match the message array in lwgparse.c)
*/
#define PARSER_ERROR_MOREPOINTS 1
#define PARSER_ERROR_ODDPOINTS 2
#define PARSER_ERROR_UNCLOSED 3
#define PARSER_ERROR_MIXDIMS 4
#define PARSER_ERROR_INVALIDGEOM 5
#define PARSER_ERROR_INVALIDWKBTYPE 6
#define PARSER_ERROR_INCONTINUOUS 7
#define PARSER_ERROR_TRIANGLEPOINTS 8
#define PARSER_ERROR_LESSPOINTS 9
#define PARSER_ERROR_OTHER 10
/*
* Unparser result structure: returns the result of attempting to convert LWGEOM to (E)WKT/(E)WKB
*/
typedef struct struct_lwgeom_unparser_result
{
uint8_t *serialized_lwgeom; /* Copy of pointer to input serialized LWGEOM */
char *wkoutput; /* Pointer to WKT or WKB output */
size_t size; /* Size of serialized LWGEOM in bytes */
const char *message; /* Error/warning message */
int errlocation; /* Location of error */
}
LWGEOM_UNPARSER_RESULT;
/*
* Unparser error messages (these must match the message array in lwgunparse.c)
*/
#define UNPARSER_ERROR_MOREPOINTS 1
#define UNPARSER_ERROR_ODDPOINTS 2
#define UNPARSER_ERROR_UNCLOSED 3
/*
** Variants available for WKB and WKT output types
*/
#define WKB_ISO 0x01
#define WKB_SFSQL 0x02
#define WKB_EXTENDED 0x04
#define WKB_NDR 0x08
#define WKB_XDR 0x10
#define WKB_HEX 0x20
#define WKB_NO_NPOINTS 0x40 /* Internal use only */
#define WKB_NO_SRID 0x80 /* Internal use only */
#define WKT_ISO 0x01
#define WKT_SFSQL 0x02
#define WKT_EXTENDED 0x04
/*
** Variants available for TWKB
*/
#define TWKB_BBOX 0x01 /* User wants bboxes */
#define TWKB_SIZE 0x02 /* User wants sizes */
#define TWKB_ID 0x04 /* User wants id */
#define TWKB_NO_TYPE 0x10 /* No type because it is a sub geometry */
#define TWKB_NO_ID 0x20 /* No ID because it is a subgeometry */
#define TWKB_DEFAULT_PRECISION 0 /* Aim for 1m (or ft) rounding by default */
/*
** New parsing and unparsing functions.
*/
/**
* @param geom geometry to convert to WKT
* @param variant output format to use (WKT_ISO, WKT_SFSQL, WKT_EXTENDED)
* @param precision Double precision
* @param size_out (Out parameter) size of the buffer
*/
extern char* lwgeom_to_wkt(const LWGEOM *geom, uint8_t variant, int precision, size_t *size_out);
/**
* @param geom geometry to convert to WKT
* @param variant output format to use (WKT_ISO, WKT_SFSQL, WKT_EXTENDED)
* @param precision Double precision
*/
extern lwvarlena_t* lwgeom_to_wkt_varlena(const LWGEOM *geom, uint8_t variant, int precision);
/**
* @param geom geometry to convert to WKB
* @param variant output format to use
* (WKB_ISO, WKB_SFSQL, WKB_EXTENDED, WKB_NDR, WKB_XDR)
*/
extern uint8_t* lwgeom_to_wkb_buffer(const LWGEOM *geom, uint8_t variant);
extern lwvarlena_t* lwgeom_to_wkb_varlena(const LWGEOM *geom, uint8_t variant);
/**
* @param geom geometry to convert to HEXWKB
* @param variant output format to use
* (WKB_ISO, WKB_SFSQL, WKB_EXTENDED, WKB_NDR, WKB_XDR)
* @param size_out (Out parameter) size of the buffer
*/
extern char* lwgeom_to_hexwkb_buffer(const LWGEOM *geom, uint8_t variant);
extern lwvarlena_t* lwgeom_to_hexwkb_varlena(const LWGEOM *geom, uint8_t variant);
/**
* @param lwgeom geometry to convert to EWKT
*/
extern char *lwgeom_to_ewkt(const LWGEOM *lwgeom);
/**
* @param wkb_size length of WKB byte buffer
* @param wkb WKB byte buffer
* @param check parser check flags, see LW_PARSER_CHECK_* macros
*/
extern LWGEOM* lwgeom_from_wkb(const uint8_t *wkb, const size_t wkb_size, const char check);
/**
* @param wkt WKT string
* @param check parser check flags, see LW_PARSER_CHECK_* macros
*/
extern LWGEOM* lwgeom_from_wkt(const char *wkt, const char check);
/**
* @param check parser check flags, see LW_PARSER_CHECK_* macros
*/
extern LWGEOM* lwgeom_from_hexwkb(const char *hexwkb, const char check);
extern uint8_t* bytes_from_hexbytes(const char *hexbuf, size_t hexsize);
extern char* hexbytes_from_bytes(const uint8_t *bytes, size_t size);
/*
* WKT detailed parsing support
*/
extern int lwgeom_parse_wkt(LWGEOM_PARSER_RESULT *parser_result, char *wktstr, int parse_flags);
void lwgeom_parser_result_init(LWGEOM_PARSER_RESULT *parser_result);
void lwgeom_parser_result_free(LWGEOM_PARSER_RESULT *parser_result);
/* Memory management */
extern void *lwalloc(size_t size);
extern void *lwrealloc(void *mem, size_t size);
extern void lwfree(void *mem);
/* Utilities */
extern char *lwmessage_truncate(char *str, int startpos, int endpos, int maxlength, int truncdirection);
/*
* TWKB functions
*/
/**
* @param twkb Input twkb buffer
* @param twkb_size parser check flags, see LW_PARSER_CHECK_* macros
* @param check parser check flags, see LW_PARSER_CHECK_* macros
*/
extern LWGEOM* lwgeom_from_twkb(const uint8_t *twkb, size_t twkb_size, char check);
/**
* @param geom input geometry
* @param variant what variations on TWKB are requested?
* @param twkb_size returns the length of the output TWKB in bytes if set
*/
extern lwvarlena_t* lwgeom_to_twkb(const LWGEOM *geom, uint8_t variant, int8_t precision_xy, int8_t precision_z, int8_t precision_m);
extern lwvarlena_t* lwgeom_to_twkb_with_idlist(const LWGEOM *geom, int64_t *idlist, uint8_t variant, int8_t precision_xy, int8_t precision_z, int8_t precision_m);
/**
* Trim the bits of an LWGEOM in place, to optimize it for compression.
* Sets all bits to zero that are not required to maintain a specified
* number of digits after the decimal point. Negative precision values
* indicate digits before the decimal point do not need to be preserved.
*
* @param geom input geometry
* @param prec_x precision (digits after decimal point) in x dimension
* @param prec_y precision (digits after decimal point) in y dimension
* @param prec_z precision (digits after decimal point) in z dimension
* @param prec_m precision (digits after decimal point) in m dimension
*/
extern void lwgeom_trim_bits_in_place(LWGEOM *geom, int32_t prec_x, int32_t prec_y, int32_t prec_z, int32_t prec_m);
extern LWGEOM* lwgeom_boundary(LWGEOM* lwgeom);
/*******************************************************************************
* SQLMM internal functions
******************************************************************************/
/**
* Geometry includes at least one actual circular arc
*/
int lwgeom_has_arc(const LWGEOM *geom);
/**
* Geometry type is one of the potentially "arc containing"
* types (circstring, multicurve, etc) but does not necessarily
* contain an actual arc.
*/
int lwgeom_type_arc(const LWGEOM *geom);
/**
* Convert type with arcs into equivalent linearized type
*/
LWGEOM *lwgeom_stroke(const LWGEOM *geom, uint32_t perQuad);
/**
* Convert linearized type into arc type, de-linearizing the
* strokes where possible.
*/
LWGEOM *lwgeom_unstroke(const LWGEOM *geom);
/**
* Semantic of the `tolerance` argument passed to
* lwcurve_linearize
*/
typedef enum {
/**
* Tolerance expresses the number of segments to use
* for each quarter of circle (quadrant). Must be
* an integer.
*/
LW_LINEARIZE_TOLERANCE_TYPE_SEGS_PER_QUAD = 0,
/**
* Tolerance expresses the maximum distance between
* an arbitrary point on the curve and the closest
* point to it on the resulting approximation, in
* cartesian units.
*/
LW_LINEARIZE_TOLERANCE_TYPE_MAX_DEVIATION = 1,
/**
* Tolerance expresses the maximum angle between
* the radii generating approximation line vertices,
* given in radiuses. A value of 1 would result
* in an approximation of a semicircle composed by
* 180 segments
*/
LW_LINEARIZE_TOLERANCE_TYPE_MAX_ANGLE = 2
} LW_LINEARIZE_TOLERANCE_TYPE;
typedef enum {
/**
* Symmetric linearization means that the output
* vertices would be the same no matter the order
* of the points defining the input curve.
*/
LW_LINEARIZE_FLAG_SYMMETRIC = 1 << 0,
/**
* Retain angle instructs the engine to try its best
* to retain the requested angle between generating
* radii (where angle can be given explicitly with
* LW_LINEARIZE_TOLERANCE_TYPE_MAX_ANGLE or implicitly
* with LW_LINEARIZE_TOLERANCE_TYPE_SEGS_PER_QUAD or
* LW_LINEARIZE_TOLERANCE_TYPE_MAX_DEVIATION).
*
* It only makes sense with LW_LINEARIZE_FLAG_SYMMETRIC
* which would otherwise reduce the angle as needed to
* keep it constant among all radiis so that all
* segments are of the same length.
*
* When this flag is set, the first and last generating
* angles (and thus the first and last segments) may
* instead be smaller (shorter) than the others.
*
*/
LW_LINEARIZE_FLAG_RETAIN_ANGLE = 1 << 1
} LW_LINEARIZE_FLAGS;
/**
* @param geom input geometry
* @param tol tolerance, semantic driven by tolerance_type
* @param type see LW_LINEARIZE_TOLERANCE_TYPE
* @param flags bitwise OR of operational flags, see LW_LINEARIZE_FLAGS
*
* @return a newly allocated LWGEOM
*/
extern LWGEOM* lwcurve_linearize(const LWGEOM *geom, double tol, LW_LINEARIZE_TOLERANCE_TYPE type, int flags);
/*******************************************************************************
* GEOS proxy functions on LWGEOM
******************************************************************************/
/** Return GEOS version string (not to be freed) */
const char* lwgeom_geos_version(void);
/** Convert an LWGEOM to a GEOS Geometry and convert back -- for debug only */
LWGEOM* lwgeom_geos_noop(const LWGEOM *geom) ;
LWGEOM *lwgeom_normalize(const LWGEOM *geom);
LWGEOM *lwgeom_intersection(const LWGEOM *geom1, const LWGEOM *geom2);
LWGEOM *lwgeom_intersection_prec(const LWGEOM *geom1, const LWGEOM *geom2, double gridSize);
LWGEOM *lwgeom_difference(const LWGEOM *geom1, const LWGEOM *geom2);
LWGEOM *lwgeom_difference_prec(const LWGEOM *geom1, const LWGEOM *geom2, double gridSize);
LWGEOM *lwgeom_symdifference(const LWGEOM* geom1, const LWGEOM* geom2);
LWGEOM *lwgeom_symdifference_prec(const LWGEOM* geom1, const LWGEOM* geom2, double gridSize);
LWGEOM *lwgeom_pointonsurface(const LWGEOM* geom);
LWGEOM *lwgeom_reduceprecision(const LWGEOM* geom, double gridSize);
LWGEOM *lwgeom_centroid(const LWGEOM* geom);
LWGEOM *lwgeom_union(const LWGEOM *geom1, const LWGEOM *geom2);
LWGEOM *lwgeom_union_prec(const LWGEOM *geom1, const LWGEOM *geom2, double gridSize);
LWGEOM *lwgeom_linemerge(const LWGEOM *geom1);
LWGEOM *lwgeom_linemerge_directed(const LWGEOM *geom1, int directed);
LWGEOM *lwgeom_unaryunion(const LWGEOM *geom1);
LWGEOM *lwgeom_unaryunion_prec(const LWGEOM *geom1, double gridSize);
LWGEOM *lwgeom_clip_by_rect(const LWGEOM *geom1, double x0, double y0, double x1, double y1);
LWCOLLECTION *lwgeom_subdivide(const LWGEOM *geom, uint32_t maxvertices);
LWCOLLECTION *lwgeom_subdivide_prec(const LWGEOM *geom, uint32_t maxvertices, double gridSize);
/**
* Snap vertices and segments of a geometry to another using a given tolerance.
*
* @param geom1 the geometry to snap
* @param geom2 the geometry to snap to
* @param tolerance the distance under which vertices and segments are snapped
*/
LWGEOM* lwgeom_snap(const LWGEOM* geom1, const LWGEOM* geom2, double tolerance);
/*
* Return the set of paths shared between two linear geometries,
* and their direction (same or opposite).
*
* @param geom1 a lineal geometry
* @param geom2 another lineal geometry
*/
LWGEOM* lwgeom_sharedpaths(const LWGEOM* geom1, const LWGEOM* geom2);
/*
* An offset curve against the input line.
*
* @param geom a lineal geometry or collection of them
* @param size offset distance. Offset left if negative and right if positive
* @param quadsegs number of quadrature segments in curves (try 8)
* @param joinStyle (1 = round, 2 = mitre, 3 = bevel)
* @param mitreLimit (try 5.0)
* @return derived geometry (linestring or multilinestring)
*
*/
LWGEOM* lwgeom_offsetcurve(const LWGEOM *geom, double size, int quadsegs, int joinStyle, double mitreLimit);
/*
* Return true if the input geometry is "simple" as per OGC defn.
*
* @return 1 if simple, 0 if non-simple, -1 on exception (lwerror is called
* in that case)
*/
int lwgeom_is_simple(const LWGEOM *lwgeom);
/*******************************************************************************
* PROJ4-dependent extra functions on LWGEOM
******************************************************************************/
int lwgeom_transform_from_str(LWGEOM *geom, const char* instr, const char* outstr);
/**
* Transform (reproject) a geometry in-place.
* @param geom the geometry to transform
* @param pj the transformation
*/
int lwgeom_transform(LWGEOM *geom, LWPROJ* pj);
int ptarray_transform(POINTARRAY *pa, LWPROJ* pj);
#if POSTGIS_PROJ_VERSION < 61
/**
* Get a projection from a string representation
*
* Eg: "+proj=longlat +ellps=WGS84 +datum=WGS84 +no_defs"
*/
projPJ projpj_from_string(const char* txt);
#else // POSTGIS_PROJ_VERSION >= 61
/**
* Allocate a new LWPROJ containing the reference to the PROJ's PJ
* If extra_geography_data is true, it will generate the following values for
* the source srs: is_latlong (geometric or not) and spheroid values
*/
LWPROJ *lwproj_from_str(const char* str_in, const char* str_out);
#endif
/*******************************************************************************
* GEOS-dependent extra functions on LWGEOM
******************************************************************************/
/**
* Take a geometry and return an areal geometry
* (Polygon or MultiPolygon).
* Actually a wrapper around GEOSpolygonize,
* transforming the resulting collection into
* a valid polygon Geometry.
*/
LWGEOM* lwgeom_buildarea(const LWGEOM *geom) ;
/**
* Attempts to make an invalid geometries valid w/out losing points.
*/
LWGEOM* lwgeom_make_valid(LWGEOM* geom);
LWGEOM* lwgeom_make_valid_params(LWGEOM* geom, char *make_valid_params);
/*
* Split (multi)polygon by line; (multi)line by (multi)line,
* (multi)point or (multi)polygon boundary.
*
* Collections are accepted as first argument.
* Returns all obtained pieces as a collection.
*/
LWGEOM* lwgeom_split(const LWGEOM* lwgeom_in, const LWGEOM* blade_in);
/*
* Fully node a set of linestrings, using the least nodes preserving
* all the input ones.
*/
LWGEOM* lwgeom_node(const LWGEOM* lwgeom_in);
/**
* Take vertices of a geometry and build a delaunay
* triangulation on them.
*
* @param geom the input geometry
* @param tolerance an optional snapping tolerance for improved robustness
* @param edgeOnly if non-zero the result will be a MULTILINESTRING,
* otherwise it'll be a COLLECTION of polygons.
*/
LWGEOM* lwgeom_delaunay_triangulation(const LWGEOM *geom, double tolerance, int32_t edgeOnly);
/**
* Take vertices of a geometry and build the Voronoi diagram
*
* @param g the input geometry
* @param env an optional envelope for clipping the results
* @param tolerance an optional snapping tolerance for improved robustness
* @param output_edges if non-zero the result will be a MULTILINESTRING,
* otherwise it'll be a COLLECTION of polygons.
*/
LWGEOM* lwgeom_voronoi_diagram(const LWGEOM* g, const GBOX* env, double tolerance, int output_edges);
#if POSTGIS_GEOS_VERSION >= 31100
/**
* Take a geometry and build the concave hull. The concave
* hull is smaller than the convex hull, but still encompasses all the points
* of the input. For polygon input the hull encompasses all the input
* area. For line input the hull encompasses all the input lines.
*
* @param g the input geometry
* @param ratio proportion of output vs input
* @param allow_holes can there be holes in the output. large performance penalty.
*/
LWGEOM* lwgeom_concavehull(const LWGEOM* geom, double ratio, uint32_t allow_holes);
/**
* Computes a boundary-respecting hull of a polygonal geometry,
* with hull shape determined by a target parameter
* specifying the fraction of the input vertices retained in the result.
* Larger values produce less concave results.
*
* @param geom the input geometry
* @param vertex_fraction proportion of vertices in output vs input.
* @param is_outer expand geometry while removing edges.
*/
LWGEOM*
lwgeom_simplify_polygonal(const LWGEOM* geom, double vertex_fraction, uint32_t is_outer);
/**
* Take vertices of a polygon and build a constrained triangulation
* that respects the boundary of the polygon.
*
* @param geom the input geometry
*/
LWGEOM* lwgeom_triangulate_polygon(const LWGEOM* geom);
#endif
/**
* Take a list of LWGEOMs and a number of clusters and return an integer
* array indicating which cluster each geometry is in.
*
* @param geoms the input array of LWGEOM pointers
* @param ngeoms the number of elements in the array
* @param k the number of clusters to calculate
* @param max_radius maxmimum radius of cluster before it's split
*/
int * lwgeom_cluster_kmeans(const LWGEOM **geoms, uint32_t n, uint32_t k, double max_radius);
#include "lwinline.h"
#endif /* !defined _LIBLWGEOM_H */