diff -Nur librttopo/headers/librttopo_geom.h ../librttopo/headers/librttopo_geom.h
--- librttopo/headers/librttopo_geom.h	1970-01-01 01:00:00.000000000 +0100
+++ ../librttopo/headers/librttopo_geom.h	2023-07-03 16:57:51.487442800 +0200
@@ -0,0 +1,2162 @@
+/**********************************************************************
+ *
+ * rttopo - topology library
+ * http://git.osgeo.org/gogs/rttopo/librttopo
+ *
+ * rttopo 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.
+ *
+ * rttopo 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 rttopo.  If not, see <http://www.gnu.org/licenses/>.
+ *
+ **********************************************************************
+ *
+ * Copyright 2011-2016 Sandro Santilli <strk@kbt.io>
+ * Copyright 2011 Paul Ramsey <pramsey@cleverelephant.ca>
+ * Copyright 2007-2008 Mark Cave-Ayland
+ * Copyright 2001-2006 Refractions Research Inc.
+ *
+ **********************************************************************/
+
+
+
+#ifndef _LIBRTGEOM_H
+#define _LIBRTGEOM_H 1
+
+#define GEOS_USE_ONLY_R_API 1
+#include <geos_c.h>
+
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdint.h>
+
+/**
+* @file librttopo_geom.h
+*
+* This library is the generic geometry handling section of librttopo.
+* The geometry objects, constructors, destructors, and a set of spatial
+* processing functions, are implemented here.
+*
+* Programs using this library can install their custom memory managers
+* passing them to the rtgeom_init function, and their custom message
+* handlers using the appropriate rtgeom_set_*_logger functions.
+*/
+
+/**
+* Return types for functions with status returns.
+*/
+#define RT_TRUE 1
+#define RT_FALSE 0
+#define RT_UNKNOWN 2
+#define RT_FAILURE 0
+#define RT_SUCCESS 1
+
+/**
+* RTRTTYPE numbers
+*/
+#define  RTPOINTTYPE                1
+#define  RTLINETYPE                 2
+#define  RTPOLYGONTYPE              3
+#define  RTMULTIPOINTTYPE           4
+#define  RTMULTILINETYPE            5
+#define  RTMULTIPOLYGONTYPE         6
+#define  RTCOLLECTIONTYPE           7
+#define RTCIRCSTRINGTYPE           8
+#define RTCOMPOUNDTYPE             9
+#define RTCURVEPOLYTYPE           10
+#define RTMULTICURVETYPE          11
+#define RTMULTISURFACETYPE        12
+#define RTPOLYHEDRALSURFACETYPE   13
+#define RTTRIANGLETYPE            14
+#define RTTINTYPE                 15
+
+#define RTNUMTYPES                16
+
+/**
+* Flags applied in EWKB to indicate Z/M dimensions and
+* presence/absence of SRID and bounding boxes
+*/
+#define RTWKBZOFFSET  0x80000000
+#define RTWKBMOFFSET  0x40000000
+#define RTWKBSRIDFLAG 0x20000000
+#define RTWKBBBOXFLAG 0x10000000
+
+/** Ordinate names */
+typedef enum RTORD_T {
+  RTORD_X = 0,
+  RTORD_Y = 1,
+  RTORD_Z = 2,
+  RTORD_M = 3
+} RTORD;
+
+/**
+* Macros for manipulating the 'flags' byte. A uint8_t used as follows:
+* ---RGBMZ
+* Three unused bits, followed by ReadOnly, Geodetic, HasBBox, HasM and HasZ flags.
+*/
+#define RTFLAGS_GET_Z(flags) ((flags) & 0x01)
+#define RTFLAGS_GET_M(flags) (((flags) & 0x02)>>1)
+#define RTFLAGS_GET_BBOX(flags) (((flags) & 0x04)>>2)
+#define RTFLAGS_GET_GEODETIC(flags) (((flags) & 0x08)>>3)
+#define RTFLAGS_GET_READONLY(flags) (((flags) & 0x10)>>4)
+#define RTFLAGS_GET_SOLID(flags) (((flags) & 0x20)>>5)
+#define RTFLAGS_SET_Z(flags, value) ((flags) = (value) ? ((flags) | 0x01) : ((flags) & 0xFE))
+#define RTFLAGS_SET_M(flags, value) ((flags) = (value) ? ((flags) | 0x02) : ((flags) & 0xFD))
+#define RTFLAGS_SET_BBOX(flags, value) ((flags) = (value) ? ((flags) | 0x04) : ((flags) & 0xFB))
+#define RTFLAGS_SET_GEODETIC(flags, value) ((flags) = (value) ? ((flags) | 0x08) : ((flags) & 0xF7))
+#define RTFLAGS_SET_READONLY(flags, value) ((flags) = (value) ? ((flags) | 0x10) : ((flags) & 0xEF))
+#define RTFLAGS_SET_SOLID(flags, value) ((flags) = (value) ? ((flags) | 0x20) : ((flags) & 0xDF))
+#define RTFLAGS_NDIMS(flags) (2 + RTFLAGS_GET_Z(flags) + RTFLAGS_GET_M(flags))
+#define RTFLAGS_GET_ZM(flags) (RTFLAGS_GET_M(flags) + RTFLAGS_GET_Z(flags) * 2)
+#define RTFLAGS_NDIMS_BOX(flags) (RTFLAGS_GET_GEODETIC(flags) ? 3 : RTFLAGS_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.
+* RTTYPE = Next 6 bits.
+* ZM Flags = Bottom 2 bits.
+*/
+
+#define RTTYPMOD_GET_SRID(typmod) ((((typmod) & 0x1FFFFF00)<<3)>>11)
+#define RTTYPMOD_SET_SRID(typmod, srid) ((typmod) = (((typmod) & 0xE00000FF) | ((srid & 0x001FFFFF)<<8)))
+#define RTTYPMOD_GET_TYPE(typmod) ((typmod & 0x000000FC)>>2)
+#define RTTYPMOD_SET_TYPE(typmod, type) ((typmod) = (typmod & 0xFFFFFF03) | ((type & 0x0000003F)<<2))
+#define RTTYPMOD_GET_Z(typmod) ((typmod & 0x00000002)>>1)
+#define RTTYPMOD_SET_Z(typmod) ((typmod) = typmod | 0x00000002)
+#define RTTYPMOD_GET_M(typmod) (typmod & 0x00000001)
+#define RTTYPMOD_SET_M(typmod) ((typmod) = typmod | 0x00000001)
+#define RTTYPMOD_GET_NDIMS(typmod) (2+RTTYPMOD_GET_Z(typmod)+RTTYPMOD_GET_M(typmod))
+
+/**
+* Maximum allowed SRID value in serialized geometry.
+* Currently we are using 21 bits (2097152) of storage for SRID.
+*/
+#define SRID_MAXIMUM 999999
+
+/**
+ * Maximum valid SRID value for the user
+ * We reserve 1000 values for internal use
+ */
+#define SRID_USER_MAXIMUM 998999
+
+/** Unknown SRID value */
+#define SRID_UNKNOWN 0
+#define SRID_IS_UNKNOWN(x) ((int)x<=0)
+
+/*
+** 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
+
+/**
+ * RT library context
+ */
+typedef struct RTCTX_T RTCTX;
+
+/**
+ * Global functions for memory/logging handlers.
+ */
+typedef void* (*rtallocator)(size_t size);
+typedef void* (*rtreallocator)(void *mem, size_t size);
+typedef void (*rtfreeor)(void* mem);
+typedef void (*rtreporter)(const char* fmt, va_list ap, void *arg)
+  __attribute__ (( format(printf, 1, 0) ));
+typedef void (*rtdebuglogger)(int level, const char* fmt, va_list ap, void *arg)
+  __attribute__ (( format(printf, 2,0) ));
+
+
+/**
+ * Initialize the library with custom memory management functions
+ * you want your application to use.
+ * @param allocator function for allocating memory,
+ *                  or NULL to use the default
+ * @param reallocator function for reallocating memory,
+ *                    or NULL to use the default
+ * @param freeor function for release memory,
+ *               or NULL to use the default
+ * @return a context object to use in subsequent calls
+ *         to the library
+ * @see rtgeom_finish to destroy the created context
+ * @ingroup system
+ */
+RTCTX *rtgeom_init(rtallocator allocator,
+                   rtreallocator reallocator,
+                   rtfreeor freeor);
+
+/**
+ * Deinitialize the library, releasing all context memory
+ *
+ * @param ctx a context returned by rtgeom_init
+ *
+ */
+void rtgeom_finish(RTCTX *ctx);
+
+/** Return rtgeom version string (not to be freed) */
+const char* rtgeom_version(void);
+
+/**
+ * This functions are called by programs which want to set up
+ * custom handling for error reporting
+ */
+extern void rtgeom_set_error_logger(RTCTX *ctx,
+          rtreporter logger, void *arg);
+extern void rtgeom_set_notice_logger(RTCTX *ctx,
+          rtreporter logger, void *arg);
+extern void rtgeom_set_debug_logger(RTCTX *ctx,
+          rtdebuglogger logger, void *arg);
+
+/**
+ * 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 rtgeom_request_interrupt(const RTCTX *ctx);
+
+/**
+ * Cancel any interruption request
+ */
+extern void rtgeom_cancel_interrupt(const RTCTX *ctx);
+
+/**
+ * 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 rtgeom_request_interrupt).
+ *
+ */
+typedef void (rtinterrupt_callback)();
+extern rtinterrupt_callback *rtgeom_register_interrupt_callback(const RTCTX *ctx, rtinterrupt_callback *);
+
+/******************************************************************/
+
+typedef struct {
+  double afac, bfac, cfac, dfac, efac, ffac, gfac, hfac, ifac, xoff, yoff, zoff;
+} RTAFFINE;
+
+
+/******************************************************************
+* RTGBOX structure.
+* We include the flags (information about dimensinality),
+* so we don't have to constantly pass them
+* into functions that use the RTGBOX.
+*/
+typedef struct
+{
+  uint8_t flags;
+  double xmin;
+  double xmax;
+  double ymin;
+  double ymax;
+  double zmin;
+  double zmax;
+  double mmin;
+  double mmax;
+} RTGBOX;
+
+
+/******************************************************************
+* 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;
+
+/******************************************************************
+* RTPOINT2D, POINT3D, RTPOINT3DM, RTPOINT4D
+*/
+typedef struct
+{
+  double x, y;
+}
+RTPOINT2D;
+
+typedef struct
+{
+  double x, y, z;
+}
+RTPOINT3DZ;
+
+typedef struct
+{
+  double x, y, z;
+}
+POINT3D;
+
+typedef struct
+{
+  double x, y, m;
+}
+RTPOINT3DM;
+
+typedef struct
+{
+  double x, y, z, m;
+}
+RTPOINT4D;
+
+/******************************************************************
+*  RTPOINTARRAY
+*  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
+{
+  /* Array of POINT 2D, 3D or 4D, possibly missaligned. */
+  uint8_t *serialized_pointlist;
+
+  /* Use RTFLAGS_* macros to handle */
+  uint8_t  flags;
+
+  int npoints;   /* how many points we are currently storing */
+  int maxpoints; /* how many points we have space for in serialized_pointlist */
+}
+RTPOINTARRAY;
+
+/******************************************************************
+* 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 flags; /* HasZ, HasM, HasBBox, IsGeodetic, IsReadOnly */
+  uint8_t data[1]; /* See gserialized.txt */
+} GSERIALIZED;
+
+
+/******************************************************************
+* RTGEOM (any geometry type)
+*
+* Abstract type, note that 'type', 'bbox' and 'srid' are available in
+* all geometry variants.
+*/
+typedef struct
+{
+  uint8_t type;
+  uint8_t flags;
+  RTGBOX *bbox;
+  int32_t srid;
+  void *data;
+}
+RTGEOM;
+
+/* RTPOINTYPE */
+typedef struct
+{
+  uint8_t type; /* RTPOINTTYPE */
+  uint8_t flags;
+  RTGBOX *bbox;
+  int32_t srid;
+  RTPOINTARRAY *point;  /* hide 2d/3d (this will be an array of 1 point) */
+}
+RTPOINT; /* "light-weight point" */
+
+/* RTLINETYPE */
+typedef struct
+{
+  uint8_t type; /* RTLINETYPE */
+  uint8_t flags;
+  RTGBOX *bbox;
+  int32_t srid;
+  RTPOINTARRAY *points; /* array of POINT3D */
+}
+RTLINE; /* "light-weight line" */
+
+/* TRIANGLE */
+typedef struct
+{
+  uint8_t type;
+  uint8_t flags;
+  RTGBOX *bbox;
+  int32_t srid;
+  RTPOINTARRAY *points;
+}
+RTTRIANGLE;
+
+/* RTCIRCSTRINGTYPE */
+typedef struct
+{
+  uint8_t type; /* RTCIRCSTRINGTYPE */
+  uint8_t flags;
+  RTGBOX *bbox;
+  int32_t srid;
+  RTPOINTARRAY *points; /* array of POINT(3D/3DM) */
+}
+RTCIRCSTRING; /* "light-weight circularstring" */
+
+/* RTPOLYGONTYPE */
+typedef struct
+{
+  uint8_t type; /* RTPOLYGONTYPE */
+  uint8_t flags;
+  RTGBOX *bbox;
+  int32_t srid;
+  int nrings;   /* how many rings we are currently storing */
+  int maxrings; /* how many rings we have space for in **rings */
+  RTPOINTARRAY **rings; /* list of rings (list of points) */
+}
+RTPOLY; /* "light-weight polygon" */
+
+/* RTMULTIPOINTTYPE */
+typedef struct
+{
+  uint8_t type;
+  uint8_t flags;
+  RTGBOX *bbox;
+  int32_t srid;
+  int ngeoms;   /* how many geometries we are currently storing */
+  int maxgeoms; /* how many geometries we have space for in **geoms */
+  RTPOINT **geoms;
+}
+RTMPOINT;
+
+/* RTMULTILINETYPE */
+typedef struct
+{
+  uint8_t type;
+  uint8_t flags;
+  RTGBOX *bbox;
+  int32_t srid;
+  int ngeoms;   /* how many geometries we are currently storing */
+  int maxgeoms; /* how many geometries we have space for in **geoms */
+  RTLINE **geoms;
+}
+RTMLINE;
+
+/* RTMULTIPOLYGONTYPE */
+typedef struct
+{
+  uint8_t type;
+  uint8_t flags;
+  RTGBOX *bbox;
+  int32_t srid;
+  int ngeoms;   /* how many geometries we are currently storing */
+  int maxgeoms; /* how many geometries we have space for in **geoms */
+  RTPOLY **geoms;
+}
+RTMPOLY;
+
+/* RTCOLLECTIONTYPE */
+typedef struct
+{
+  uint8_t type;
+  uint8_t flags;
+  RTGBOX *bbox;
+  int32_t srid;
+  int ngeoms;   /* how many geometries we are currently storing */
+  int maxgeoms; /* how many geometries we have space for in **geoms */
+  RTGEOM **geoms;
+}
+RTCOLLECTION;
+
+/* RTCOMPOUNDTYPE */
+typedef struct
+{
+  uint8_t type; /* RTCOMPOUNDTYPE */
+  uint8_t flags;
+  RTGBOX *bbox;
+  int32_t srid;
+  int ngeoms;   /* how many geometries we are currently storing */
+  int maxgeoms; /* how many geometries we have space for in **geoms */
+  RTGEOM **geoms;
+}
+RTCOMPOUND; /* "light-weight compound line" */
+
+/* RTCURVEPOLYTYPE */
+typedef struct
+{
+  uint8_t type; /* RTCURVEPOLYTYPE */
+  uint8_t flags;
+  RTGBOX *bbox;
+  int32_t srid;
+  int nrings;    /* how many rings we are currently storing */
+  int maxrings;  /* how many rings we have space for in **rings */
+  RTGEOM **rings; /* list of rings (list of points) */
+}
+RTCURVEPOLY; /* "light-weight polygon" */
+
+/* MULTICURVE */
+typedef struct
+{
+  uint8_t type;
+  uint8_t flags;
+  RTGBOX *bbox;
+  int32_t srid;
+  int ngeoms;   /* how many geometries we are currently storing */
+  int maxgeoms; /* how many geometries we have space for in **geoms */
+  RTGEOM **geoms;
+}
+RTMCURVE;
+
+/* RTMULTISURFACETYPE */
+typedef struct
+{
+  uint8_t type;
+  uint8_t flags;
+  RTGBOX *bbox;
+  int32_t srid;
+  int ngeoms;   /* how many geometries we are currently storing */
+  int maxgeoms; /* how many geometries we have space for in **geoms */
+  RTGEOM **geoms;
+}
+RTMSURFACE;
+
+/* RTPOLYHEDRALSURFACETYPE */
+typedef struct
+{
+  uint8_t type;
+  uint8_t flags;
+  RTGBOX *bbox;
+  int32_t srid;
+  int ngeoms;   /* how many geometries we are currently storing */
+  int maxgeoms; /* how many geometries we have space for in **geoms */
+  RTPOLY **geoms;
+}
+RTPSURFACE;
+
+/* RTTINTYPE */
+typedef struct
+{
+  uint8_t type;
+  uint8_t flags;
+  RTGBOX *bbox;
+  int32_t srid;
+  int ngeoms;   /* how many geometries we are currently storing */
+  int maxgeoms; /* how many geometries we have space for in **geoms */
+  RTTRIANGLE **geoms;
+}
+RTTIN;
+
+/* Casts RTGEOM->RT* (return NULL if cast is illegal) */
+extern RTMPOLY *rtgeom_as_rtmpoly(const RTCTX *ctx, const RTGEOM *rtgeom);
+extern RTMLINE *rtgeom_as_rtmline(const RTCTX *ctx, const RTGEOM *rtgeom);
+extern RTMPOINT *rtgeom_as_rtmpoint(const RTCTX *ctx, const RTGEOM *rtgeom);
+extern RTCOLLECTION *rtgeom_as_rtcollection(const RTCTX *ctx, const RTGEOM *rtgeom);
+extern RTPOLY *rtgeom_as_rtpoly(const RTCTX *ctx, const RTGEOM *rtgeom);
+extern RTLINE *rtgeom_as_rtline(const RTCTX *ctx, const RTGEOM *rtgeom);
+extern RTPOINT *rtgeom_as_rtpoint(const RTCTX *ctx, const RTGEOM *rtgeom);
+extern RTCIRCSTRING *rtgeom_as_rtcircstring(const RTCTX *ctx, const RTGEOM *rtgeom);
+extern RTCURVEPOLY *rtgeom_as_rtcurvepoly(const RTCTX *ctx, const RTGEOM *rtgeom);
+extern RTCOMPOUND *rtgeom_as_rtcompound(const RTCTX *ctx, const RTGEOM *rtgeom);
+extern RTPSURFACE *rtgeom_as_rtpsurface(const RTCTX *ctx, const RTGEOM *rtgeom);
+extern RTTRIANGLE *rtgeom_as_rttriangle(const RTCTX *ctx, const RTGEOM *rtgeom);
+extern RTTIN *rtgeom_as_rttin(const RTCTX *ctx, const RTGEOM *rtgeom);
+extern RTGEOM *rtgeom_as_multi(const RTCTX *ctx, const RTGEOM *rtgeom);
+extern RTGEOM *rtgeom_as_curve(const RTCTX *ctx, const RTGEOM *rtgeom);
+
+/* Casts RT*->RTGEOM (artays cast) */
+extern RTGEOM *rttin_as_rtgeom(const RTCTX *ctx, const RTTIN *obj);
+extern RTGEOM *rttriangle_as_rtgeom(const RTCTX *ctx, const RTTRIANGLE *obj);
+extern RTGEOM *rtpsurface_as_rtgeom(const RTCTX *ctx, const RTPSURFACE *obj);
+extern RTGEOM *rtmpoly_as_rtgeom(const RTCTX *ctx, const RTMPOLY *obj);
+extern RTGEOM *rtmline_as_rtgeom(const RTCTX *ctx, const RTMLINE *obj);
+extern RTGEOM *rtmpoint_as_rtgeom(const RTCTX *ctx, const RTMPOINT *obj);
+extern RTGEOM *rtcollection_as_rtgeom(const RTCTX *ctx, const RTCOLLECTION *obj);
+extern RTGEOM *rtcircstring_as_rtgeom(const RTCTX *ctx, const RTCIRCSTRING *obj);
+extern RTGEOM *rtcompound_as_rtgeom(const RTCTX *ctx, const RTCOMPOUND *obj);
+extern RTGEOM *rtcurvepoly_as_rtgeom(const RTCTX *ctx, const RTCURVEPOLY *obj);
+extern RTGEOM *rtpoly_as_rtgeom(const RTCTX *ctx, const RTPOLY *obj);
+extern RTGEOM *rtline_as_rtgeom(const RTCTX *ctx, const RTLINE *obj);
+extern RTGEOM *rtpoint_as_rtgeom(const RTCTX *ctx, const RTPOINT *obj);
+
+
+extern RTCOLLECTION* rtcollection_add_rtgeom(const RTCTX *ctx, RTCOLLECTION *col, const RTGEOM *geom);
+extern RTMPOINT* rtmpoint_add_rtpoint(const RTCTX *ctx, RTMPOINT *mobj, const RTPOINT *obj);
+extern RTMLINE* rtmline_add_rtline(const RTCTX *ctx, RTMLINE *mobj, const RTLINE *obj);
+extern RTMPOLY* rtmpoly_add_rtpoly(const RTCTX *ctx, RTMPOLY *mobj, const RTPOLY *obj);
+extern RTPSURFACE* rtpsurface_add_rtpoly(const RTCTX *ctx, RTPSURFACE *mobj, const RTPOLY *obj);
+extern RTTIN* rttin_add_rttriangle(const RTCTX *ctx, RTTIN *mobj, const RTTRIANGLE *obj);
+
+
+
+/***********************************************************************
+** Utility functions for flag byte and srid_flag integer.
+*/
+
+/**
+* Construct a new flags char.
+*/
+extern uint8_t gflags(const RTCTX *ctx, int hasz, int hasm, int geodetic);
+
+/**
+* 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 RTCTX *ctx, 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(const RTCTX *ctx);
+
+/**
+* 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 RTCTX *ctx, 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(const RTCTX *ctx, 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 RTCTX *ctx, const GSERIALIZED *g);
+
+/**
+* Check if a #GSERIALIZED has a bounding box without deserializing first.
+*/
+extern int gserialized_has_bbox(const RTCTX *ctx, const GSERIALIZED *gser);
+
+/**
+* Check if a #GSERIALIZED has a Z ordinate.
+*/
+extern int gserialized_has_z(const RTCTX *ctx, const GSERIALIZED *gser);
+
+/**
+* Check if a #GSERIALIZED has an M ordinate.
+*/
+extern int gserialized_has_m(const RTCTX *ctx, const GSERIALIZED *gser);
+
+/**
+* Check if a #GSERIALIZED is a geography.
+*/
+extern int gserialized_is_geodetic(const RTCTX *ctx, const GSERIALIZED *gser);
+
+/**
+* Return a number indicating presence of Z and M coordinates.
+* 0 = None, 1 = M, 2 = Z, 3 = ZM
+*/
+extern int gserialized_get_zm(const RTCTX *ctx, const GSERIALIZED *gser);
+
+/**
+* Return the number of dimensions (2, 3, 4) in a geometry
+*/
+extern int gserialized_ndims(const RTCTX *ctx, const GSERIALIZED *gser);
+
+
+/**
+* Call this function to drop BBOX and SRID
+* from RTGEOM. If RTGEOM type is *not* flagged
+* with the HASBBOX flag and has a bbox, it
+* will be released.
+*/
+extern void rtgeom_drop_bbox(const RTCTX *ctx, RTGEOM *rtgeom);
+extern void rtgeom_drop_srid(const RTCTX *ctx, RTGEOM *rtgeom);
+
+/**
+ * Compute a bbox if not already computed
+ *
+ * After calling this function rtgeom->bbox is only
+ * NULL if the geometry is empty.
+ */
+extern void rtgeom_add_bbox(const RTCTX *ctx, RTGEOM *rtgeom);
+/**
+* Compute a box for geom and all sub-geometries, if not already computed
+*/
+extern void rtgeom_add_bbox_deep(const RTCTX *ctx, RTGEOM *rtgeom, RTGBOX *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 RTGBOX *rtgeom_get_bbox(const RTCTX *ctx, const RTGEOM *rtgeom);
+
+/**
+* Determine whether a RTGEOM can contain sub-geometries or not
+*/
+extern int rtgeom_is_collection(const RTCTX *ctx, const RTGEOM *rtgeom);
+
+/******************************************************************/
+/* Functions that work on type numbers */
+
+/**
+* Determine whether a type number is a collection or not
+*/
+extern int rttype_is_collection(const RTCTX *ctx, uint8_t type);
+
+/**
+* Given an rttype number, what homogeneous collection can hold it?
+*/
+extern int rttype_get_collectiontype(const RTCTX *ctx, uint8_t type);
+
+/**
+* Return the type name string associated with a type number
+* (e.g. Point, LineString, Polygon)
+*/
+extern const char *rttype_name(const RTCTX *ctx, 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 RTPOINT4D rt_getPoint4d(const RTCTX *ctx, const RTPOINTARRAY *pa, int 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 rt_getPoint4d_p(const RTCTX *ctx, const RTPOINTARRAY *pa, int n, RTPOINT4D *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 RTPOINT3DZ rt_getPoint3dz(const RTCTX *ctx, const RTPOINTARRAY *pa, int n);
+extern RTPOINT3DM rt_getPoint3dm(const RTCTX *ctx, const RTPOINTARRAY *pa, int 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 rt_getPoint3dz_p(const RTCTX *ctx, const RTPOINTARRAY *pa, int n, RTPOINT3DZ *point);
+extern int rt_getPoint3dm_p(const RTCTX *ctx, const RTPOINTARRAY *pa, int n, RTPOINT3DM *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 RTPOINT2D rt_getPoint2d(const RTCTX *ctx, const RTPOINTARRAY *pa, int 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 rt_getPoint2d_p(const RTCTX *ctx, const RTPOINTARRAY *pa, int n, RTPOINT2D *point);
+
+/**
+* Returns a RTPOINT2D pointer into the RTPOINTARRAY serialized_ptlist,
+* suitable for reading from. This is very high performance
+* and declared const because you aren't allowed to muck with the
+* values, only read them.
+*/
+extern const RTPOINT2D* rt_getPoint2d_cp(const RTCTX *ctx, const RTPOINTARRAY *pa, int n);
+
+/**
+* Returns a RTPOINT3DZ pointer into the RTPOINTARRAY serialized_ptlist,
+* suitable for reading from. This is very high performance
+* and declared const because you aren't allowed to muck with the
+* values, only read them.
+*/
+extern const RTPOINT3DZ* rt_getPoint3dz_cp(const RTCTX *ctx, const RTPOINTARRAY *pa, int n);
+
+/**
+* Returns a RTPOINT4D pointer into the RTPOINTARRAY serialized_ptlist,
+* suitable for reading from. This is very high performance
+* and declared const because you aren't allowed to muck with the
+* values, only read them.
+*/
+extern const RTPOINT4D* rt_getPoint4d_cp(const RTCTX *ctx, const RTPOINTARRAY *pa, int n);
+
+/*
+ * 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(const RTCTX *ctx, RTPOINTARRAY *pa, int n, const RTPOINT4D *p4d);
+
+/*
+ * get a pointer to nth point of a RTPOINTARRAY
+ * You'll need to cast it to appropriate dimensioned point.
+ * Note that if you cast to a higher dimensional point you'll
+ * possibly corrupt the RTPOINTARRAY.
+ *
+ * WARNING: Don't cast this to a POINT !
+ * it would not be reliable due to memory alignment constraints
+ */
+extern uint8_t *rt_getPoint_internal(const RTCTX *ctx, const RTPOINTARRAY *pa, int n);
+
+/*
+ * size of point represeneted in the RTPOINTARRAY
+ * 16 for 2d, 24 for 3d, 32 for 4d
+ */
+extern int ptarray_point_size(const RTCTX *ctx, const RTPOINTARRAY *pa);
+
+
+/**
+* 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 RTPOINTARRAY* ptarray_construct(const RTCTX *ctx, char hasz, char hasm, uint32_t npoints);
+
+/**
+* Construct a new #RTPOINTARRAY, <em>copying</em> in the data from ptlist
+*/
+extern RTPOINTARRAY* ptarray_construct_copy_data(const RTCTX *ctx, char hasz, char hasm, uint32_t npoints, const uint8_t *ptlist);
+
+/**
+* Construct a new #RTPOINTARRAY, <em>referencing</em> to the data from ptlist
+*/
+extern RTPOINTARRAY* ptarray_construct_reference_data(const RTCTX *ctx, char hasz, char hasm, uint32_t npoints, uint8_t *ptlist);
+
+/**
+* Create a new #RTPOINTARRAY with no points. Allocate enough storage
+* to hold maxpoints vertices before having to reallocate the storage
+* area.
+*/
+extern RTPOINTARRAY* ptarray_construct_empty(const RTCTX *ctx, char hasz, char hasm, uint32_t maxpoints);
+
+/**
+* Append a point to the end of an existing #RTPOINTARRAY
+* If allow_duplicate is RT_TRUE, then a duplicate point will
+* not be added.
+*/
+extern int ptarray_append_point(const RTCTX *ctx, RTPOINTARRAY *pa, const RTPOINT4D *pt, int allow_duplicates);
+
+/**
+ * Append a #RTPOINTARRAY, pa2 to the end of an existing #RTPOINTARRAY, 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 RT_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(const RTCTX *ctx, RTPOINTARRAY *pa1, RTPOINTARRAY *pa2, double gap_tolerance);
+
+/**
+* Insert a point into an existing #RTPOINTARRAY. Zero
+* is the index of the start of the array.
+*/
+extern int ptarray_insert_point(const RTCTX *ctx, RTPOINTARRAY *pa, const RTPOINT4D *p, int where);
+
+/**
+* Remove a point from an existing #RTPOINTARRAY. Zero
+* is the index of the start of the array.
+*/
+extern int ptarray_remove_point(const RTCTX *ctx, RTPOINTARRAY *pa, int where);
+
+/**
+ * @brief Add a point in a pointarray.
+ *
+ * @param pa the source RTPOINTARRAY
+ * @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 RTPOINTARRAY using a newly allocated buffer
+ *          for the actual points, or NULL on error.
+ */
+extern RTPOINTARRAY *ptarray_addPoint(const RTCTX *ctx, const RTPOINTARRAY *pa, uint8_t *p, size_t pdims, uint32_t where);
+
+/**
+ * @brief Remove a point from a pointarray.
+ *   @param which -  is the offset (starting at 0)
+ * @return #RTPOINTARRAY is newly allocated
+ */
+extern RTPOINTARRAY *ptarray_removePoint(const RTCTX *ctx, RTPOINTARRAY *pa, uint32_t where);
+
+/**
+ * @brief Merge two given RTPOINTARRAY and returns a pointer
+ * on the new aggregate one.
+ * Warning: this function free the two inputs RTPOINTARRAY
+ * @return #RTPOINTARRAY is newly allocated
+ */
+extern RTPOINTARRAY *ptarray_merge(const RTCTX *ctx, RTPOINTARRAY *pa1, RTPOINTARRAY *pa2);
+
+extern int ptarray_is_closed(const RTCTX *ctx, const RTPOINTARRAY *pa);
+extern int ptarray_is_closed_2d(const RTCTX *ctx, const RTPOINTARRAY *pa);
+extern int ptarray_is_closed_3d(const RTCTX *ctx, const RTPOINTARRAY *pa);
+extern int ptarray_is_closed_z(const RTCTX *ctx, const RTPOINTARRAY *pa);
+extern void ptarray_longitude_shift(const RTCTX *ctx, RTPOINTARRAY *pa);
+extern int ptarray_isccw(const RTCTX *ctx, const RTPOINTARRAY *pa);
+extern void ptarray_reverse(const RTCTX *ctx, RTPOINTARRAY *pa);
+extern RTPOINTARRAY* ptarray_flip_coordinates(const RTCTX *ctx, RTPOINTARRAY *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 RTPOINTARRAY *ptarray_substring(const RTCTX *ctx, RTPOINTARRAY *pa, double d1, double d2,
+                                                          double tolerance);
+
+
+/**
+* Strip out the Z/M components of an #RTGEOM
+*/
+extern RTGEOM* rtgeom_force_2d(const RTCTX *ctx, const RTGEOM *geom);
+extern RTGEOM* rtgeom_force_3dz(const RTCTX *ctx, const RTGEOM *geom);
+extern RTGEOM* rtgeom_force_3dm(const RTCTX *ctx, const RTGEOM *geom);
+extern RTGEOM* rtgeom_force_4d(const RTCTX *ctx, const RTGEOM *geom);
+
+extern RTGEOM* rtgeom_simplify(const RTCTX *ctx, const RTGEOM *igeom, double dist, int preserve_collapsed);
+extern RTGEOM* rtgeom_set_effective_area(const RTCTX *ctx, const RTGEOM *igeom, int set_area, double area);
+
+/*
+ * Force to use SFS 1.1 geometry type
+ * (rather than SFS 1.2 and/or SQL/MM)
+ */
+extern RTGEOM* rtgeom_force_sfs(const RTCTX *ctx, RTGEOM *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 RTPOINTARRAY
+ */
+extern int rtpoint_getPoint2d_p(const RTCTX *ctx, const RTPOINT *point, RTPOINT2D *out);
+extern int rtpoint_getPoint3dz_p(const RTCTX *ctx, const RTPOINT *point, RTPOINT3DZ *out);
+extern int rtpoint_getPoint3dm_p(const RTCTX *ctx, const RTPOINT *point, RTPOINT3DM *out);
+extern int rtpoint_getPoint4d_p(const RTCTX *ctx, const RTPOINT *point, RTPOINT4D *out);
+
+/******************************************************************
+ * RTLINE functions
+ ******************************************************************/
+
+/**
+ * Add a RTPOINT to an RTLINE
+ */
+extern int rtline_add_rtpoint(const RTCTX *ctx, RTLINE *line, RTPOINT *point, int where);
+
+/******************************************************************
+ * RTPOLY functions
+ ******************************************************************/
+
+/**
+* Add a ring, allocating extra space if necessary. The polygon takes
+* ownership of the passed point array.
+*/
+extern int rtpoly_add_ring(const RTCTX *ctx, RTPOLY *poly, RTPOINTARRAY *pa);
+
+/**
+* Add a ring, allocating extra space if necessary. The curvepolygon takes
+* ownership of the passed point array.
+*/
+extern int rtcurvepoly_add_ring(const RTCTX *ctx, RTCURVEPOLY *poly, RTGEOM *ring);
+
+/**
+* Add a component, allocating extra space if necessary. The compoundcurve
+* takes owership of the passed geometry.
+*/
+extern int rtcompound_add_rtgeom(const RTCTX *ctx, RTCOMPOUND *comp, RTGEOM *geom);
+
+/**
+* Construct an equivalent compound curve from a linestring.
+* Compound curves can have linear components, so this works fine
+*/
+extern RTCOMPOUND* rtcompound_construct_from_rtline(const RTCTX *ctx, const RTLINE *rtpoly);
+
+/**
+* Construct an equivalent curve polygon from a polygon. Curve polygons
+* can have linear rings as their rings, so this works fine (in theory?)
+*/
+extern RTCURVEPOLY* rtcurvepoly_construct_from_rtpoly(const RTCTX *ctx, RTPOLY *rtpoly);
+
+
+/******************************************************************
+ * RTGEOM functions
+ ******************************************************************/
+
+extern int rtcollection_ngeoms(const RTCTX *ctx, const RTCOLLECTION *col);
+
+/* Given a generic geometry/collection, return the "simplest" form. */
+extern RTGEOM *rtgeom_homogenize(const RTCTX *ctx, const RTGEOM *geom);
+
+
+/******************************************************************
+ * RTMULTIx and RTCOLLECTION functions
+ ******************************************************************/
+
+RTGEOM *rtcollection_getsubgeom(const RTCTX *ctx, RTCOLLECTION *col, int gnum);
+RTCOLLECTION* rtcollection_extract(const RTCTX *ctx, RTCOLLECTION *col, int type);
+
+
+/******************************************************************
+ * SERIALIZED FORM functions
+ ******************************************************************/
+
+/**
+* Set the SRID on an RTGEOM
+* For collections, only the parent gets an SRID, all
+* the children get SRID_UNKNOWN.
+*/
+extern void rtgeom_set_srid(const RTCTX *ctx, RTGEOM *geom, int srid);
+
+/****************************************************************
+ * MEMORY MANAGEMENT
+ ****************************************************************/
+
+/*
+* The *_free family of functions frees *all* memory associated
+* with the pointer. When the recursion gets to the level of the
+* RTPOINTARRAY, the RTPOINTARRAY is only freed if it is not flagged
+* as "read only". RTGEOMs constructed on top of GSERIALIZED
+* from PgSQL use read only point arrays.
+*/
+
+extern void ptarray_free(const RTCTX *ctx, RTPOINTARRAY *pa);
+extern void rtpoint_free(const RTCTX *ctx, RTPOINT *pt);
+extern void rtline_free(const RTCTX *ctx, RTLINE *line);
+extern void rtpoly_free(const RTCTX *ctx, RTPOLY *poly);
+extern void rttriangle_free(const RTCTX *ctx, RTTRIANGLE *triangle);
+extern void rtmpoint_free(const RTCTX *ctx, RTMPOINT *mpt);
+extern void rtmline_free(const RTCTX *ctx, RTMLINE *mline);
+extern void rtmpoly_free(const RTCTX *ctx, RTMPOLY *mpoly);
+extern void rtpsurface_free(const RTCTX *ctx, RTPSURFACE *psurf);
+extern void rttin_free(const RTCTX *ctx, RTTIN *tin);
+extern void rtcollection_free(const RTCTX *ctx, RTCOLLECTION *col);
+extern void rtcircstring_free(const RTCTX *ctx, RTCIRCSTRING *curve);
+extern void rtgeom_free(const RTCTX *ctx, RTGEOM *geom);
+
+/*
+* The *_release family of functions frees the RTGEOM structures
+* surrounding the RTPOINTARRAYs but leaves the RTPOINTARRAYs
+* intact. Useful when re-shaping geometries between types,
+* or splicing geometries together.
+*/
+
+extern void rtpoint_release(const RTCTX *ctx, RTPOINT *rtpoint);
+extern void rtline_release(const RTCTX *ctx, RTLINE *rtline);
+extern void rtpoly_release(const RTCTX *ctx, RTPOLY *rtpoly);
+extern void rttriangle_release(const RTCTX *ctx, RTTRIANGLE *rttriangle);
+extern void rtcircstring_release(const RTCTX *ctx, RTCIRCSTRING *rtcirc);
+extern void rtmpoint_release(const RTCTX *ctx, RTMPOINT *rtpoint);
+extern void rtmline_release(const RTCTX *ctx, RTMLINE *rtline);
+extern void rtmpoly_release(const RTCTX *ctx, RTMPOLY *rtpoly);
+extern void rtpsurface_release(RTPSURFACE *rtpsurface);
+extern void rttin_release(RTTIN *rttin);
+extern void rtcollection_release(const RTCTX *ctx, RTCOLLECTION *rtcollection);
+extern void rtgeom_release(const RTCTX *ctx, RTGEOM *rtgeom);
+
+
+/****************************************************************
+* Utility
+****************************************************************/
+
+extern void printPA(const RTCTX *ctx, RTPOINTARRAY *pa);
+extern void printRTPOINT(const RTCTX *ctx, RTPOINT *point);
+extern void printRTLINE(const RTCTX *ctx, RTLINE *line);
+extern void printRTPOLY(const RTCTX *ctx, RTPOLY *poly);
+extern void printRTTRIANGLE(const RTCTX *ctx, RTTRIANGLE *triangle);
+extern void printRTPSURFACE(const RTCTX *ctx, RTPSURFACE *psurf);
+extern void printRTTIN(const RTCTX *ctx, RTTIN *tin);
+
+extern float  next_float_down(const RTCTX *ctx, double d);
+extern float  next_float_up(const RTCTX *ctx, double d);
+extern double next_double_down(const RTCTX *ctx, float d);
+extern double next_double_up(const RTCTX *ctx, float d);
+
+/* general utilities 2D */
+extern double  distance2d_pt_pt(const RTCTX *ctx, const RTPOINT2D *p1, const RTPOINT2D *p2);
+extern double  distance2d_sqr_pt_pt(const RTCTX *ctx, const RTPOINT2D *p1, const RTPOINT2D *p2);
+extern double  distance2d_pt_seg(const RTCTX *ctx, const RTPOINT2D *p, const RTPOINT2D *A, const RTPOINT2D *B);
+extern double  distance2d_sqr_pt_seg(const RTCTX *ctx, const RTPOINT2D *p, const RTPOINT2D *A, const RTPOINT2D *B);
+extern RTGEOM* rtgeom_closest_line(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM *rt2);
+extern RTGEOM* rtgeom_furthest_line(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM *rt2);
+extern RTGEOM* rtgeom_closest_point(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM *rt2);
+extern RTGEOM* rtgeom_furthest_point(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM *rt2);
+extern double  rtgeom_mindistance2d(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM *rt2);
+extern double  rtgeom_mindistance2d_tolerance(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM *rt2, double tolerance);
+extern double  rtgeom_maxdistance2d(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM *rt2);
+extern double  rtgeom_maxdistance2d_tolerance(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM *rt2, double tolerance);
+
+/* 3D */
+extern double distance3d_pt_pt(const RTCTX *ctx, const POINT3D *p1, const POINT3D *p2);
+extern double distance3d_pt_seg(const POINT3D *p, const POINT3D *A, const POINT3D *B);
+
+extern RTGEOM* rtgeom_furthest_line_3d(const RTCTX *ctx, RTGEOM *rt1, RTGEOM *rt2);
+extern RTGEOM* rtgeom_closest_line_3d(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM *rt2);
+extern RTGEOM* rtgeom_closest_point_3d(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM *rt2);
+
+
+extern double rtgeom_mindistance3d(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM *rt2);
+extern double rtgeom_mindistance3d_tolerance(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM *rt2, double tolerance);
+extern double rtgeom_maxdistance3d(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM *rt2);
+extern double rtgeom_maxdistance3d_tolerance(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM *rt2, double tolerance);
+
+extern double rtgeom_area(const RTCTX *ctx, const RTGEOM *geom);
+extern double rtgeom_length(const RTCTX *ctx, const RTGEOM *geom);
+extern double rtgeom_length_2d(const RTCTX *ctx, const RTGEOM *geom);
+extern double rtgeom_perimeter(const RTCTX *ctx, const RTGEOM *geom);
+extern double rtgeom_perimeter_2d(const RTCTX *ctx, const RTGEOM *geom);
+extern void rtgeom_affine(const RTCTX *ctx, RTGEOM *geom, const RTAFFINE *affine);
+extern void rtgeom_scale(const RTCTX *ctx, RTGEOM *geom, const RTPOINT4D *factors);
+extern int rtgeom_dimension(const RTCTX *ctx, const RTGEOM *geom);
+
+extern RTPOINT* rtline_get_rtpoint(const RTCTX *ctx, const RTLINE *line, int where);
+extern RTPOINT* rtcircstring_get_rtpoint(const RTCTX *ctx, const RTCIRCSTRING *circ, int where);
+
+extern RTPOINT* rtcompound_get_startpoint(const RTCTX *ctx, const RTCOMPOUND *rtcmp);
+extern RTPOINT* rtcompound_get_endpoint(const RTCTX *ctx, const RTCOMPOUND *rtcmp);
+extern RTPOINT* rtcompound_get_rtpoint(const RTCTX *ctx, const RTCOMPOUND *rtcmp, int where);
+
+
+extern double ptarray_length_2d(const RTCTX *ctx, const RTPOINTARRAY *pts);
+extern double ptarray_length(const RTCTX *ctx, const RTPOINTARRAY *pts);
+extern double ptarray_arc_length_2d(const RTCTX *ctx, const RTPOINTARRAY *pts);
+
+
+extern int pt_in_ring_2d(const RTCTX *ctx, const RTPOINT2D *p, const RTPOINTARRAY *ring);
+extern int azimuth_pt_pt(const RTCTX *ctx, const RTPOINT2D *p1, const RTPOINT2D *p2, double *ret);
+extern int rtpoint_inside_circle(const RTCTX *ctx, const RTPOINT *p, double cx, double cy, double rad);
+extern void rtgeom_reverse(const RTCTX *ctx, RTGEOM *rtgeom);
+extern void rtline_reverse(const RTCTX *ctx, RTLINE *line);
+extern void rtpoly_reverse(const RTCTX *ctx, RTPOLY *poly);
+extern void rttriangle_reverse(const RTCTX *ctx, RTTRIANGLE *triangle);
+extern char* rtgeom_summary(const RTCTX *ctx, const RTGEOM *rtgeom, int offset);
+extern char* rtpoint_to_latlon(const RTCTX *ctx, const RTPOINT *p, const char *format);
+extern int rtgeom_startpoint(const RTCTX *ctx, const RTGEOM* rtgeom, RTPOINT4D* pt);
+
+/**
+* Ensure the outer ring is clockwise oriented and all inner rings
+* are counter-clockwise.
+*/
+extern void rtgeom_force_clockwise(const RTCTX *ctx, RTGEOM *rtgeom);
+extern void rtpoly_force_clockwise(const RTCTX *ctx, RTPOLY *poly);
+extern void rttriangle_force_clockwise(const RTCTX *ctx, RTTRIANGLE *triangle);
+
+
+extern void interpolate_point4d(const RTCTX *ctx, RTPOINT4D *A, RTPOINT4D *B, RTPOINT4D *I, double F);
+
+void rtgeom_longitude_shift(const RTCTX *ctx, RTGEOM *rtgeom);
+
+
+/**
+* @brief Check whether or not a rtgeom is big enough to warrant a bounding box.
+*
+* Check whether or not a rtgeom 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 rtgeom_needs_bbox(const RTCTX *ctx, const RTGEOM *geom);
+
+/**
+* Count the total number of vertices in any #RTGEOM.
+*/
+extern int rtgeom_count_vertices(const RTCTX *ctx, const RTGEOM *geom);
+
+/**
+* Count the total number of rings in any #RTGEOM. Multipolygons
+* and other collections get counted, not the same as OGC st_numrings.
+*/
+extern int rtgeom_count_rings(const RTCTX *ctx, const RTGEOM *geom);
+
+/**
+* Return true or false depending on whether a geometry has
+* a valid SRID set.
+*/
+extern int rtgeom_has_srid(const RTCTX *ctx, const RTGEOM *geom);
+
+/**
+* Return true or false depending on whether a geometry is an "empty"
+* geometry (no vertices members)
+*/
+extern int rtgeom_is_empty(const RTCTX *ctx, const RTGEOM *geom);
+
+/**
+* Return true or false depending on whether a geometry is a linear
+* feature that closes on itself.
+*/
+extern int rtgeom_is_closed(const RTCTX *ctx, const RTGEOM *geom);
+
+/**
+* Return the dimensionality (relating to point/line/poly) of an rtgeom
+*/
+extern int rtgeom_dimensionality(const RTCTX *ctx, RTGEOM *geom);
+
+/* Is rtgeom1 geometrically equal to rtgeom2 ? */
+char rtgeom_same(const RTCTX *ctx, const RTGEOM *rtgeom1, const RTGEOM *rtgeom2);
+char ptarray_same(const RTCTX *ctx, const RTPOINTARRAY *pa1, const RTPOINTARRAY *pa2);
+char rtpoint_same(const RTCTX *ctx, const RTPOINT *p1, const RTPOINT *p2);
+char rtline_same(const RTCTX *ctx, const RTLINE *p1, const RTLINE *p2);
+char rtpoly_same(const RTCTX *ctx, const RTPOLY *p1, const RTPOLY *p2);
+char rttriangle_same(const RTCTX *ctx, const RTTRIANGLE *p1, const RTTRIANGLE *p2);
+char rtcollection_same(const RTCTX *ctx, const RTCOLLECTION *p1, const RTCOLLECTION *p2);
+char rtcircstring_same(const RTCTX *ctx, const RTCIRCSTRING *p1, const RTCIRCSTRING *p2);
+
+
+/**
+ * @brief Clone RTGEOM object. Serialized point lists are not copied.
+ *
+ * #RTGBOX are copied
+ *
+ * @see ptarray_clone
+ */
+extern RTGEOM *rtgeom_clone(const RTCTX *ctx, const RTGEOM *rtgeom);
+
+/**
+* Deep clone an RTGEOM, everything is copied
+*/
+extern RTGEOM *rtgeom_clone_deep(const RTCTX *ctx, const RTGEOM *rtgeom);
+
+/* TODO Move to Internal */
+RTPOINT *rtpoint_clone(const RTCTX *ctx, const RTPOINT *rtgeom);
+RTPOINTARRAY *ptarray_clone_deep(const RTCTX *ctx, const RTPOINTARRAY *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 RTPOINT* rtpoint_construct(const RTCTX *ctx, int srid, RTGBOX *bbox, RTPOINTARRAY *point);
+extern RTMPOINT *rtmpoint_construct(const RTCTX *ctx, int srid, const RTPOINTARRAY *pa);
+extern RTLINE* rtline_construct(const RTCTX *ctx, int srid, RTGBOX *bbox, RTPOINTARRAY *points);
+extern RTCIRCSTRING* rtcircstring_construct(const RTCTX *ctx, int srid, RTGBOX *bbox, RTPOINTARRAY *points);
+extern RTPOLY* rtpoly_construct(const RTCTX *ctx, int srid, RTGBOX *bbox, uint32_t nrings, RTPOINTARRAY **points);
+extern RTCURVEPOLY* rtcurvepoly_construct(int srid, RTGBOX *bbox, uint32_t nrings, RTGEOM **geoms);
+extern RTTRIANGLE* rttriangle_construct(const RTCTX *ctx, int srid, RTGBOX *bbox, RTPOINTARRAY *points);
+extern RTCOLLECTION* rtcollection_construct(const RTCTX *ctx, uint8_t type, int srid, RTGBOX *bbox, uint32_t ngeoms, RTGEOM **geoms);
+/*
+* Empty geometry constructors.
+*/
+extern RTGEOM* rtgeom_construct_empty(const RTCTX *ctx, uint8_t type, int srid, char hasz, char hasm);
+extern RTPOINT* rtpoint_construct_empty(const RTCTX *ctx, int srid, char hasz, char hasm);
+extern RTLINE* rtline_construct_empty(const RTCTX *ctx, int srid, char hasz, char hasm);
+extern RTPOLY* rtpoly_construct_empty(const RTCTX *ctx, int srid, char hasz, char hasm);
+extern RTCURVEPOLY* rtcurvepoly_construct_empty(const RTCTX *ctx, int srid, char hasz, char hasm);
+extern RTCIRCSTRING* rtcircstring_construct_empty(const RTCTX *ctx, int srid, char hasz, char hasm);
+extern RTCOMPOUND* rtcompound_construct_empty(const RTCTX *ctx, int srid, char hasz, char hasm);
+extern RTTRIANGLE* rttriangle_construct_empty(const RTCTX *ctx, int srid, char hasz, char hasm);
+extern RTMPOINT* rtmpoint_construct_empty(const RTCTX *ctx, int srid, char hasz, char hasm);
+extern RTMLINE* rtmline_construct_empty(const RTCTX *ctx, int srid, char hasz, char hasm);
+extern RTMPOLY* rtmpoly_construct_empty(const RTCTX *ctx, int srid, char hasz, char hasm);
+extern RTCOLLECTION* rtcollection_construct_empty(const RTCTX *ctx, uint8_t type, int srid, char hasz, char hasm);
+
+
+/* Other constructors */
+extern RTPOINT *rtpoint_make2d(const RTCTX *ctx, int srid, double x, double y);
+extern RTPOINT *rtpoint_make3dz(const RTCTX *ctx, int srid, double x, double y, double z);
+extern RTPOINT *rtpoint_make3dm(const RTCTX *ctx, int srid, double x, double y, double m);
+extern RTPOINT *rtpoint_make4d(const RTCTX *ctx, int srid, double x, double y, double z, double m);
+extern RTPOINT *rtpoint_make(const RTCTX *ctx, int srid, int hasz, int hasm, const RTPOINT4D *p);
+extern RTLINE *rtline_from_rtgeom_array(const RTCTX *ctx, int srid, uint32_t ngeoms, RTGEOM **geoms);
+extern RTLINE *rtline_from_ptarray(const RTCTX *ctx, int srid, uint32_t npoints, RTPOINT **points); /* TODO: deprecate */
+extern RTLINE *rtline_from_rtmpoint(const RTCTX *ctx, int srid, const RTMPOINT *mpoint);
+extern RTLINE *rtline_addpoint(RTLINE *line, RTPOINT *point, uint32_t where);
+extern RTLINE *rtline_removepoint(const RTCTX *ctx, RTLINE *line, uint32_t which);
+extern void rtline_setPoint4d(const RTCTX *ctx, RTLINE *line, uint32_t which, RTPOINT4D *newpoint);
+extern RTPOLY *rtpoly_from_rtlines(const RTCTX *ctx, const RTLINE *shell, uint32_t nholes, const RTLINE **holes);
+extern RTTRIANGLE *rttriangle_from_rtline(const RTCTX *ctx, const RTLINE *shell);
+
+
+/* Some point accessors */
+extern double rtpoint_get_x(const RTCTX *ctx, const RTPOINT *point);
+extern double rtpoint_get_y(const RTCTX *ctx, const RTPOINT *point);
+extern double rtpoint_get_z(const RTCTX *ctx, const RTPOINT *point);
+extern double rtpoint_get_m(const RTCTX *ctx, const RTPOINT *point);
+
+/**
+* Return SRID number
+*/
+extern int32_t rtgeom_get_srid(const RTCTX *ctx, const RTGEOM *geom);
+
+/**
+* Return RTRTTYPE number
+*/
+extern uint32_t rtgeom_get_type(const RTCTX *ctx, const RTGEOM *geom);
+
+/**
+* Return #RT_TRUE if geometry has Z ordinates
+*/
+extern int rtgeom_has_z(const RTCTX *ctx, const RTGEOM *geom);
+
+/**
+* Return #RT_TRUE if geometry has M ordinates.
+*/
+extern int rtgeom_has_m(const RTCTX *ctx, const RTGEOM *geom);
+
+/**
+* Return the number of dimensions (2, 3, 4) in a geometry
+*/
+extern int rtgeom_ndims(const RTCTX *ctx, const RTGEOM *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 RTCTX *ctx, const RTPOINTARRAY *pa, const RTPOINT4D *pt, double *dist, RTPOINT4D *p_located);
+
+/**
+* Add a measure dimension to a line, interpolating linearly from the start
+* to the end value.
+*/
+extern RTLINE *rtline_measured_from_rtline(const RTCTX *ctx, const RTLINE *rtline, double m_start, double m_end);
+extern RTMLINE* rtmline_measured_from_rtmline(const RTCTX *ctx, const RTMLINE *rtmline, 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 RTGEOM* rtgeom_locate_along(const RTCTX *ctx, const RTGEOM *rtin, 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 RTCOLLECTION* rtgeom_locate_between(const RTCTX *ctx, const RTGEOM *rtin, double from, double to, double offset);
+
+/**
+* Find the measure value at the location on the line closest to the point.
+*/
+extern double rtgeom_interpolate_point(const RTCTX *ctx, const RTGEOM *rtin, const RTPOINT *rtpt);
+
+/**
+* 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 (rterror is called in that case),
+*         -2 if the trajectories do not share any point in time.
+*/
+extern double rtgeom_tcpa(const RTCTX *ctx, const RTGEOM *g1, const RTGEOM *g2, double *mindist);
+
+/**
+* Is the closest point of approach within a distance ?
+*
+* @return RT_TRUE or RT_FALSE
+*/
+extern int rtgeom_cpa_within(const RTCTX *ctx, const RTGEOM *g1, const RTGEOM *g2, double maxdist);
+
+/**
+* Return RT_TRUE or RT_FALSE depending on whether or not a geometry is
+* a linestring with measure value growing from start to end vertex
+*/
+extern int rtgeom_is_trajectory(const RTCTX *ctx, const RTGEOM *geom);
+extern int rtline_is_trajectory(const RTCTX *ctx, const RTLINE *geom);
+
+/*
+ * Ensure every segment is at most 'dist' long.
+ * Returned RTGEOM might is unchanged if a POINT.
+ */
+extern RTGEOM *rtgeom_segmentize2d(const RTCTX *ctx, RTGEOM *line, double dist);
+extern RTPOINTARRAY *ptarray_segmentize2d(const RTCTX *ctx, const RTPOINTARRAY *ipa, double dist);
+extern RTLINE *rtline_segmentize2d(const RTCTX *ctx, RTLINE *line, double dist);
+extern RTPOLY *rtpoly_segmentize2d(const RTCTX *ctx, RTPOLY *line, double dist);
+extern RTCOLLECTION *rtcollection_segmentize2d(const RTCTX *ctx, RTCOLLECTION *coll, double dist);
+
+/**
+* Calculate the GeoHash (http://geohash.org) string for a geometry. Caller must free.
+*/
+char *rtgeom_geohash(const RTCTX *ctx, const RTGEOM *rtgeom, int precision);
+unsigned int geohash_point_as_int(const RTCTX *ctx, RTPOINT2D *pt);
+
+
+/**
+* The return values of rtline_crossing_direction(const RTCTX *ctx)
+*/
+enum RTCG_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 rtline_crossing_direction(const RTCTX *ctx, const RTLINE *l1, const RTLINE *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.
+*/
+RTCOLLECTION* rtgeom_clip_to_ordinate_range(const RTCTX *ctx, const RTGEOM *rtin, char ordinate, double from, double to, double offset);
+
+/**
+ * Macros for specifying GML options.
+ * @{
+ */
+/** For GML3 only, include srsDimension attribute in output */
+#define RT_GML_IS_DIMS     (1<<0)
+/** For GML3 only, declare that datas are lat/lon. Swaps axis order */
+#define RT_GML_IS_DEGREE   (1<<1)
+/** For GML3, use <LineString> rather than <Curve> for lines */
+#define RT_GML_SHORTLINE   (1<<2)
+/** For GML2 and GML3, output only extent of geometry */
+#define RT_GML_EXTENT      (1<<4)
+
+
+#define IS_DIMS(x) ((x) & RT_GML_IS_DIMS)
+#define IS_DEGREE(x) ((x) & RT_GML_IS_DEGREE)
+/** @} */
+
+/**
+ * Macros for specifying X3D options.
+ * @{
+ */
+/** For flip X/Y coordinates to Y/X */
+#define RT_X3D_FLIP_XY     (1<<0)
+#define RT_X3D_USE_GEOCOORDS     (1<<1)
+#define X3D_USE_GEOCOORDS(x) ((x) & RT_X3D_USE_GEOCOORDS)
+
+
+
+extern char* rtgeom_to_gml2(const RTCTX *ctx, const RTGEOM *geom, const char *srs, int precision, const char *prefix);
+extern char* rtgeom_extent_to_gml2(const RTCTX *ctx, const RTGEOM *geom, const char *srs, int precision, const char *prefix);
+/**
+ * @param opts output options bitfield, see RT_GML macros for meaning
+ */
+extern char* rtgeom_extent_to_gml3(const RTCTX *ctx, const RTGEOM *geom, const char *srs, int precision, int opts, const char *prefix);
+extern char* rtgeom_to_gml3(const RTCTX *ctx, const RTGEOM *geom, const char *srs, int precision, int opts, const char *prefix, const char *id);
+extern char* rtgeom_to_kml2(const RTCTX *ctx, const RTGEOM *geom, int precision, const char *prefix);
+extern char* rtgeom_to_geojson(const RTCTX *ctx, const RTGEOM *geo, char *srs, int precision, int has_bbox);
+extern char* rtgeom_to_svg(const RTCTX *ctx, const RTGEOM *geom, int precision, int relative);
+extern char* rtgeom_to_x3d3(const RTCTX *ctx, const RTGEOM *geom, char *srs, int precision, int opts, const char *defid);
+
+/**
+ * Create an RTGEOM 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 rtfree.
+ */
+extern RTGEOM* rtgeom_from_geojson(const RTCTX *ctx, const char *geojson, char **srs);
+
+/**
+* Initialize a spheroid object for use in geodetic functions.
+*/
+extern void spheroid_init(const RTCTX *ctx, SPHEROID *s, double a, double b);
+
+/**
+* Calculate the geodetic distance from rtgeom1 to rtgeom2 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 rtgeom_distance_spheroid(const RTCTX *ctx, const RTGEOM *rtgeom1, const RTGEOM *rtgeom2, const SPHEROID *spheroid, double tolerance);
+
+/**
+* Calculate the location of a point on a spheroid, give a start point, bearing and distance.
+*/
+extern RTPOINT* rtgeom_project_spheroid(const RTCTX *ctx, const RTPOINT *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 RTGEOM* rtgeom_segmentize_sphere(const RTCTX *ctx, const RTGEOM *rtg_in, double max_seg_length);
+
+/**
+* Calculate the bearing between two points on a spheroid.
+*/
+extern double rtgeom_azumith_spheroid(const RTCTX *ctx, const RTPOINT *r, const RTPOINT *s, const SPHEROID *spheroid);
+
+/**
+* Calculate the geodetic area of a rtgeom on the sphere. The result
+* will be multiplied by the average radius of the supplied spheroid.
+*/
+extern double rtgeom_area_sphere(const RTCTX *ctx, const RTGEOM *rtgeom, const SPHEROID *spheroid);
+
+/**
+* Calculate the geodetic area of a rtgeom on the spheroid. The result
+* will have the squared units of the spheroid axes.
+*/
+extern double rtgeom_area_spheroid(const RTCTX *ctx, const RTGEOM *rtgeom, const SPHEROID *spheroid);
+
+/**
+* Calculate the geodetic length of a rtgeom on the unit sphere. The result
+* will have to by multiplied by the real radius to get the real length.
+*/
+extern double rtgeom_length_spheroid(const RTCTX *ctx, const RTGEOM *geom, const SPHEROID *s);
+
+/**
+* Calculate covers predicate for two rtgeoms on the sphere. Currently
+* only handles point-in-polygon.
+*/
+extern int rtgeom_covers_rtgeom_sphere(const RTCTX *ctx, const RTGEOM *rtgeom1, const RTGEOM *rtgeom2);
+
+/**
+* Remove repeated points!
+*/
+extern RTGEOM* rtgeom_remove_repeated_points(const RTCTX *ctx, const RTGEOM *in, double tolerance);
+
+extern char rttriangle_is_repeated_points(const RTCTX *ctx, RTTRIANGLE *triangle);
+
+/**
+ * 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 rtgeom_swap_ordinates(const RTCTX *ctx, RTGEOM *in, RTORD o1, RTORD o2);
+
+/**
+* Reverse the X and Y coordinate order. Useful for geometries in lat/lon order
+* than need to be converted to lon/lat order.
+*
+* NOTE: uses rtgeom_swap_ordinates internally,
+*       kept for backward compatibility
+*/
+extern RTGEOM* rtgeom_flip_coordinates(const RTCTX *ctx, RTGEOM *in);
+
+struct RTPOINTITERATOR;
+typedef struct RTPOINTITERATOR RTPOINTITERATOR;
+
+/**
+ * Create a new RTPOINTITERATOR over supplied RTGEOM*
+ */
+extern RTPOINTITERATOR* rtpointiterator_create(const RTCTX *ctx, const RTGEOM* g);
+
+/**
+ * Create a new RTPOINTITERATOR over supplied RTGEOM*
+ * Supports modification of coordinates during iteration.
+ */
+extern RTPOINTITERATOR* rtpointiterator_create_rw(const RTCTX *ctx, RTGEOM* g);
+
+/**
+ * Free all memory associated with the iterator
+ */
+extern void rtpointiterator_destroy(const RTCTX *ctx, RTPOINTITERATOR* s);
+
+/**
+ * Returns RT_TRUE if there is another point available in the iterator.
+ */
+extern int rtpointiterator_has_next(const RTCTX *ctx, RTPOINTITERATOR* s);
+
+/**
+ * Attempts to replace the next point int the iterator with p, and advances
+ * the iterator to the next point.
+ * Returns RT_SUCCESS if the assignment was successful, RT_FAILURE otherwise.
+ * */
+extern int rtpointiterator_modify_next(const RTCTX *ctx, RTPOINTITERATOR* s, const RTPOINT4D* 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 RT_SUCCESS if the assignment was successful, RT_FAILURE otherwise.
+ * */
+extern int rtpointiterator_next(const RTCTX *ctx, RTPOINTITERATOR* s, RTPOINT4D* p);
+
+/**
+ * Attempts to assigns the next point in the iterator to p.  Does not advance.
+ * Returns RT_SUCCESS if the assignment was successful, RT_FAILURE otherwise.
+ */
+extern int rtpointiterator_peek(const RTCTX *ctx, RTPOINTITERATOR* s, RTPOINT4D* p);
+
+
+/**
+* Convert a single hex digit into the corresponding char
+*/
+extern uint8_t parse_hex(const RTCTX *ctx, char *str);
+
+/**
+* Convert a char into a human readable hex digit
+*/
+extern void deparse_hex(const RTCTX *ctx, uint8_t str, char *result);
+
+
+
+/***********************************************************************
+** Functions for managing serialized forms and bounding boxes.
+*/
+
+/**
+* Calculate the geocentric bounding box directly from the serialized
+* form of the geodetic coordinates. Only accepts serialized geographies
+* flagged as geodetic. Caller is responsible for disposing of the RTGBOX.
+*/
+extern RTGBOX* gserialized_calculate_gbox_geocentric(const GSERIALIZED *g);
+
+/**
+* Calculate the geocentric bounding box directly from the serialized
+* form of the geodetic coordinates. Only accepts serialized geographies
+* flagged as geodetic.
+*/
+int gserialized_calculate_gbox_geocentric_p(const GSERIALIZED *g, RTGBOX *g_box);
+
+/**
+* Return a RTWKT representation of the gserialized geometry.
+* Caller is responsible for disposing of the char*.
+*/
+extern char* gserialized_to_string(const RTCTX *ctx, const GSERIALIZED *g);
+
+/**
+* Return a copy of the input serialized geometry.
+*/
+extern GSERIALIZED* gserialized_copy(const RTCTX *ctx, const GSERIALIZED *g);
+
+/**
+* Check that coordinates of RTGEOM are all within the geodetic range (-180, -90, 180, 90)
+*/
+extern int rtgeom_check_geodetic(const RTCTX *ctx, const RTGEOM *geom);
+
+/**
+* Gently move coordinates of RTGEOM if they are close enough into geodetic range.
+*/
+extern int rtgeom_nudge_geodetic(const RTCTX *ctx, RTGEOM *geom);
+
+/**
+* Force coordinates of RTGEOM into geodetic range (-180, -90, 180, 90)
+*/
+extern int rtgeom_force_geodetic(const RTCTX *ctx, RTGEOM *geom);
+
+/**
+* Set the RTFLAGS geodetic bit on geometry an all sub-geometries and pointlists
+*/
+extern void rtgeom_set_geodetic(const RTCTX *ctx, RTGEOM *geom, int value);
+
+/**
+* Calculate the geodetic bounding box for an RTGEOM. Z/M coordinates are
+* ignored for this calculation. Pass in non-null, geodetic bounding box for function
+* to fill out. RTGEOM must have been built from a GSERIALIZED to provide
+* double aligned point arrays.
+*/
+extern int rtgeom_calculate_gbox_geodetic(const RTCTX *ctx, const RTGEOM *geom, RTGBOX *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 rtgeom_calculate_gbox_cartesian(const RTCTX *ctx, const RTGEOM *rtgeom, RTGBOX *gbox);
+
+/**
+* Calculate bounding box of a geometry, automatically taking into account
+* whether it is cartesian or geodetic.
+*/
+extern int rtgeom_calculate_gbox(const RTCTX *ctx, const RTGEOM *rtgeom, RTGBOX *gbox);
+
+/**
+* New function to read doubles directly from the double* coordinate array
+* of an aligned rtgeom #RTPOINTARRAY (built by de-serializing a #GSERIALIZED).
+*/
+extern int rt_getPoint2d_p_ro(const RTCTX *ctx, const RTPOINTARRAY *pa, int n, RTPOINT2D **point);
+
+/**
+* Calculate geodetic (x/y/z) box and add values to gbox. Return #RT_SUCCESS on success.
+*/
+extern int ptarray_calculate_gbox_geodetic(const RTCTX *ctx, const RTPOINTARRAY *pa, RTGBOX *gbox);
+
+/**
+* Calculate box (x/y) and add values to gbox. Return #RT_SUCCESS on success.
+*/
+extern int ptarray_calculate_gbox_cartesian(const RTCTX *ctx, const RTPOINTARRAY *pa, RTGBOX *gbox );
+
+/**
+* Calculate a spherical point that falls outside the geocentric gbox
+*/
+void gbox_pt_outside(const RTCTX *ctx, const RTGBOX *gbox, RTPOINT2D *pt_outside);
+
+/**
+* Create a new gbox with the dimensionality indicated by the flags. Caller
+* is responsible for freeing.
+*/
+extern RTGBOX* gbox_new(const RTCTX *ctx, uint8_t flags);
+
+/**
+* Zero out all the entries in the #RTGBOX. Useful for cleaning
+* statically allocated gboxes.
+*/
+extern void gbox_init(const RTCTX *ctx, RTGBOX *gbox);
+
+/**
+* Update the merged #RTGBOX to be large enough to include itself and the new box.
+*/
+extern int gbox_merge(const RTCTX *ctx, const RTGBOX *new_box, RTGBOX *merged_box);
+
+/**
+* Update the output #RTGBOX to be large enough to include both inputs.
+*/
+extern int gbox_union(const RTCTX *ctx, const RTGBOX *g1, const RTGBOX *g2, RTGBOX *gout);
+
+/**
+* Move the box minimums down and the maximums up by the distance provided.
+*/
+extern void gbox_expand(const RTCTX *ctx, RTGBOX *g, double d);
+
+/**
+* Initialize a #RTGBOX using the values of the point.
+*/
+extern int gbox_init_point3d(const RTCTX *ctx, const POINT3D *p, RTGBOX *gbox);
+
+/**
+* Update the #RTGBOX to be large enough to include itself and the new point.
+*/
+extern int gbox_merge_point3d(const RTCTX *ctx, const POINT3D *p, RTGBOX *gbox);
+
+/**
+* Return true if the point is inside the gbox
+*/
+extern int gbox_contains_point3d(const RTCTX *ctx, const RTGBOX *gbox, const POINT3D *pt);
+
+/**
+* Allocate a string representation of the #RTGBOX, based on dimensionality of flags.
+*/
+extern char* gbox_to_string(const RTCTX *ctx, const RTGBOX *gbox);
+
+/**
+* Return a copy of the #RTGBOX, based on dimensionality of flags.
+*/
+extern RTGBOX* gbox_copy(const RTCTX *ctx, const RTGBOX *gbox);
+
+/**
+* Warning, do not use this function, it is very particular about inputs.
+*/
+extern RTGBOX* gbox_from_string(const RTCTX *ctx, const char *str);
+
+/**
+* Return #RT_TRUE if the #RTGBOX overlaps, #RT_FALSE otherwise.
+*/
+extern int gbox_overlaps(const RTCTX *ctx, const RTGBOX *g1, const RTGBOX *g2);
+
+/**
+* Return #RT_TRUE if the #RTGBOX overlaps on the 2d plane, #RT_FALSE otherwise.
+*/
+extern int gbox_overlaps_2d(const RTCTX *ctx, const RTGBOX *g1, const RTGBOX *g2);
+
+/**
+* Return #RT_TRUE if the first #RTGBOX contains the second on the 2d plane, #RT_FALSE otherwise.
+*/
+extern int  gbox_contains_2d(const RTCTX *ctx, const RTGBOX *g1, const RTGBOX *g2);
+
+/**
+* Copy the values of original #RTGBOX into duplicate.
+*/
+extern void gbox_duplicate(const RTCTX *ctx, const RTGBOX *original, RTGBOX *duplicate);
+
+/**
+* Return the number of bytes necessary to hold a #RTGBOX of this dimension in
+* serialized form.
+*/
+extern size_t gbox_serialized_size(const RTCTX *ctx, uint8_t flags);
+
+/**
+* Check if 2 given Gbox are the same
+*/
+extern int gbox_same(const RTCTX *ctx, const RTGBOX *g1, const RTGBOX *g2);
+
+/**
+* Check if 2 given RTGBOX are the same in x and y
+*/
+extern int gbox_same_2d(const RTCTX *ctx, const RTGBOX *g1, const RTGBOX *g2);
+
+/**
+* Check if two given RTGBOX are the same in x and y, or would round to the same
+* RTGBOX in x and if serialized in GSERIALIZED
+*/
+extern int gbox_same_2d_float(const RTCTX *ctx, const RTGBOX *g1, const RTGBOX *g2);
+
+/**
+ * Round given RTGBOX to float boundaries
+ *
+ * This turns a RTGBOX into the version it would become
+ * after a serialize/deserialize round trip.
+ */
+extern void gbox_float_round(const RTCTX *ctx, RTGBOX *gbox);
+
+/**
+* Return false if any of the dimensions is NaN or infinite
+*/
+extern int gbox_is_valid(const RTCTX *ctx, const RTGBOX *gbox);
+
+/**
+* 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 RTCTX *ctx, const char *str, uint8_t *type, int *z, int *m);
+
+/**
+* Calculate required memory segment to contain a serialized form of the RTGEOM.
+* Primarily used internally by the serialization code. Exposed to allow the cunit
+* tests to exercise it.
+*/
+extern size_t gserialized_from_rtgeom_size(const RTCTX *ctx, const RTGEOM *geom);
+
+/**
+* Allocate a new #GSERIALIZED from an #RTGEOM. 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_rtgeom(const RTCTX *ctx, RTGEOM *geom, int is_geodetic, size_t *size);
+
+/**
+* Allocate a new #RTGEOM from a #GSERIALIZED. The resulting #RTGEOM will have coordinates
+* that are double aligned and suitable for direct reading using rt_getPoint2d_p_ro
+*/
+extern RTGEOM* rtgeom_from_gserialized(const RTCTX *ctx, const GSERIALIZED *g);
+
+/**
+* Pull a #RTGBOX 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 RT_FAILURE.
+*/
+extern int gserialized_get_gbox_p(const RTCTX *ctx, const GSERIALIZED *g, RTGBOX *gbox);
+
+
+/**
+ * Parser check flags
+ *
+ *  @see rtgeom_from_wkb
+ *  @see rtgeom_from_hexwkb
+ */
+#define RT_PARSER_CHECK_MINPOINTS  1
+#define RT_PARSER_CHECK_ODD        2
+#define RT_PARSER_CHECK_CLOSURE    4
+#define RT_PARSER_CHECK_ZCLOSURE   8
+
+#define RT_PARSER_CHECK_NONE   0
+#define RT_PARSER_CHECK_ALL  (RT_PARSER_CHECK_MINPOINTS | RT_PARSER_CHECK_ODD | RT_PARSER_CHECK_CLOSURE)
+
+/**
+ * Parser result structure: returns the result of attempting to convert
+ * (E)RTWKT/(E)RTWKB to RTGEOM
+ */
+typedef struct struct_rtgeom_parser_result
+{
+  const char *wkinput;        /* Copy of pointer to input RTWKT/RTWKB */
+  uint8_t *serialized_rtgeom;   /* Pointer to serialized RTGEOM */
+  int size;                   /* Size of serialized RTGEOM in bytes */
+  RTGEOM *geom;               /* Pointer to RTGEOM 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 */
+}
+RTGEOM_PARSER_RESULT;
+
+/*
+ * Parser error messages (these must match the message array in rtgparse.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 RTPARSER_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 RTGEOM to (E)RTWKT/(E)RTWKB
+ */
+typedef struct struct_rtgeom_unparser_result
+{
+  uint8_t *serialized_rtgeom;  /* Copy of pointer to input serialized RTGEOM */
+  char *wkoutput;      /* Pointer to RTWKT or RTWKB output */
+  int size;      /* Size of serialized RTGEOM in bytes */
+  const char *message;    /* Error/warning message */
+  int errlocation;    /* Location of error */
+}
+RTGEOM_UNPARSER_RESULT;
+
+/*
+ * Unparser error messages (these must match the message array in rtgunparse.c)
+ */
+#define UNPARSER_ERROR_MOREPOINTS   1
+#define UNPARSER_ERROR_ODDPOINTS  2
+#define UNPARSER_ERROR_UNCLOSED    3
+
+
+/*
+** Variants available for RTWKB and RTWKT output types
+*/
+
+#define RTWKB_ISO 0x01
+#define RTWKB_SFSQL 0x02
+#define RTWKB_EXTENDED 0x04
+#define RTWKB_NDR 0x08
+#define RTWKB_XDR 0x10
+#define RTWKB_HEX 0x20
+#define RTWKB_NO_NPOINTS 0x40 /* Internal use only */
+#define RTWKB_NO_SRID 0x80 /* Internal use only */
+
+#define RTWKT_ISO 0x01
+#define RTWKT_SFSQL 0x02
+#define RTWKT_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 RTTWKB_NO_TYPE 0x10 /* No type because it is a sub geoemtry */
+#define TWKB_NO_ID 0x20 /* No ID because it is a subgeoemtry */
+#define TWKB_DEFAULT_PRECISION 0 /* Aim for 1m (or ft) rounding by default */
+
+/*
+** New parsing and unparsing functions.
+*/
+
+/**
+* @param rtgeom geometry to convert to RTWKT
+* @param variant output format to use (RTWKT_ISO, RTWKT_SFSQL, RTWKT_EXTENDED)
+*/
+extern char*   rtgeom_to_wkt(const RTCTX *ctx, const RTGEOM *geom, uint8_t variant, int precision, size_t *size_out);
+
+/**
+* @param rtgeom geometry to convert to RTWKT
+* @param variant output format to use
+*                (RTWKB_ISO, RTWKB_SFSQL, RTWKB_EXTENDED, RTWKB_NDR, RTWKB_XDR)
+*/
+extern uint8_t*  rtgeom_to_wkb(const RTCTX *ctx, const RTGEOM *geom, uint8_t variant, size_t *size_out);
+
+/**
+* @param rtgeom geometry to convert to HEXWKB
+* @param variant output format to use
+*                (RTWKB_ISO, RTWKB_SFSQL, RTWKB_EXTENDED, RTWKB_NDR, RTWKB_XDR)
+*/
+extern char*   rtgeom_to_hexwkb(const RTCTX *ctx, const RTGEOM *geom, uint8_t variant, size_t *size_out);
+
+/**
+* @param rtgeom geometry to convert to EWKT
+*/
+extern char *rtgeom_to_ewkt(const RTCTX *ctx, const RTGEOM *rtgeom);
+
+/**
+ * @param check parser check flags, see RT_PARSER_CHECK_* macros
+ * @param size length of RTWKB byte buffer
+ * @param wkb RTWKB byte buffer
+ */
+extern RTGEOM* rtgeom_from_wkb(const RTCTX *ctx, const uint8_t *wkb, const size_t wkb_size, const char check);
+
+/**
+ * @param check parser check flags, see RT_PARSER_CHECK_* macros
+ */
+extern RTGEOM* rtgeom_from_hexwkb(const RTCTX *ctx, const char *hexwkb, const char check);
+
+extern uint8_t*  bytes_from_hexbytes(const RTCTX *ctx, const char *hexbuf, size_t hexsize);
+
+extern char*   hexbytes_from_bytes(const RTCTX *ctx, uint8_t *bytes, size_t size);
+
+
+/* Memory management */
+extern void *rtalloc(const RTCTX *ctx, size_t size);
+extern void *rtrealloc(const RTCTX *ctx, void *mem, size_t size);
+extern void rtfree(const RTCTX *ctx, void *mem);
+
+/* Utilities */
+extern char *rtmessage_truncate(const RTCTX *ctx, char *str, int startpos, int endpos, int maxlength, int truncdirection);
+
+/*
+* TWKB functions
+*/
+
+/**
+ * @param check parser check flags, see RT_PARSER_CHECK_* macros
+ * @param size parser check flags, see RT_PARSER_CHECK_* macros
+ */
+extern RTGEOM* rtgeom_from_twkb(const RTCTX *ctx, 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 uint8_t* rtgeom_to_twkb(const RTCTX *ctx, const RTGEOM *geom, uint8_t variant, int8_t precision_xy, int8_t precision_z, int8_t precision_m, size_t *twkb_size);
+
+extern uint8_t* rtgeom_to_twkb_with_idlist(const RTCTX *ctx, const RTGEOM *geom, int64_t *idlist, uint8_t variant, int8_t precision_xy, int8_t precision_z, int8_t precision_m, size_t *twkb_size);
+
+/*******************************************************************************
+ * SQLMM internal functions - TODO: Move into separate header files
+ ******************************************************************************/
+
+int rtgeom_has_arc(const RTCTX *ctx, const RTGEOM *geom);
+RTGEOM *rtgeom_stroke(const RTCTX *ctx, const RTGEOM *geom, uint32_t perQuad);
+RTGEOM *rtgeom_unstroke(const RTCTX *ctx, const RTGEOM *geom);
+
+/*******************************************************************************
+ * GEOS proxy functions on RTGEOM
+ ******************************************************************************/
+
+/** Return GEOS version string (not to be freed) */
+const char* rtgeom_geos_version(void);
+
+/** Convert an RTGEOM to a GEOS Geometry and convert back -- for debug only */
+RTGEOM* rtgeom_geos_noop(const RTCTX *ctx, const RTGEOM *geom) ;
+
+RTGEOM *rtgeom_normalize(const RTCTX *ctx, const RTGEOM *geom);
+RTGEOM *rtgeom_intersection(const RTCTX *ctx, const RTGEOM *geom1, const RTGEOM *geom2);
+RTGEOM *rtgeom_difference(const RTCTX *ctx, const RTGEOM *geom1, const RTGEOM *geom2);
+RTGEOM *rtgeom_symdifference(const RTCTX *ctx, const RTGEOM* geom1, const RTGEOM* geom2);
+RTGEOM *rtgeom_union(const RTCTX *ctx, const RTGEOM *geom1, const RTGEOM *geom2);
+RTGEOM *rtgeom_linemerge(const RTCTX *ctx, const RTGEOM *geom1);
+RTGEOM *rtgeom_unaryunion(const RTCTX *ctx, const RTGEOM *geom1);
+RTGEOM *rtgeom_clip_by_rect(const RTCTX *ctx, const RTGEOM *geom1, double x0, double y0, double x1, double y1);
+RTCOLLECTION *rtgeom_subdivide(const RTCTX *ctx, const RTGEOM *geom, int maxvertices);
+
+/**
+ * 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
+ *
+ * Requires GEOS-3.3.0+
+ */
+RTGEOM* rtgeom_snap(const RTCTX *ctx, const RTGEOM* geom1, const RTGEOM* 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
+ *
+ * Requires GEOS-3.3.0+
+ */
+RTGEOM* rtgeom_sharedpaths(const RTCTX *ctx, const RTGEOM* geom1, const RTGEOM* geom2);
+
+/*
+ * An offset curve against the input line.
+ *
+ * @param rtline a lineal geometry
+ * @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)
+ *
+ * Requires GEOS-3.2.0+
+ */
+RTGEOM* rtgeom_offsetcurve(const RTCTX *ctx, const RTLINE *rtline, 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 (rterror is called
+ *         in that case)
+ */
+int rtgeom_is_simple(const RTCTX *ctx, const RTGEOM *rtgeom);
+
+
+/*******************************************************************************
+ * GEOS-dependent extra functions on RTGEOM
+ ******************************************************************************/
+
+/**
+ * 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.
+ */
+RTGEOM* rtgeom_buildarea(const RTCTX *ctx, const RTGEOM *geom) ;
+
+
+/**
+ * Attempts to make an invalid geometries valid w/out losing points.
+ *
+ * NOTE: this is only available when librtgeom is built against
+ *       GEOS 3.3.0 or higher
+ */
+RTGEOM* rtgeom_make_valid(const RTCTX *ctx, RTGEOM* geom);
+
+/*
+ * 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.
+ */
+RTGEOM* rtgeom_split(const RTCTX *ctx, const RTGEOM* rtgeom_in, const RTGEOM* blade_in);
+
+/*
+ * Fully node a set of linestrings, using the least nodes preserving
+ * all the input ones.
+ *
+ * Requires GEOS-3.3.0 or higher
+ */
+RTGEOM* rtgeom_node(const RTCTX *ctx, const RTGEOM* rtgeom_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 tolerance
+ * @param edgeOnly if non-zero the result will be a MULTILINESTRING,
+ *                 otherwise it'll be a COLLECTION of polygons.
+ */
+RTGEOM* rtgeom_delaunay_triangulation(const RTCTX *ctx, const RTGEOM *geom, double tolerance, int edgeOnly);
+
+#endif /* !defined _LIBRTGEOM_H  */
+
diff -Nur librttopo/makefile.vc ../librttopo/makefile.vc
--- librttopo/makefile.vc	2019-07-27 08:55:02.000000000 +0200
+++ ../librttopo/makefile.vc	2023-07-03 16:57:56.081697200 +0200
@@ -4,24 +4,25 @@
 #
 !INCLUDE nmake.opt
 
-LIBOBJ	 = src\box2d.obj src\bytebuffer.obj src\g_box.obj \
-	src\g_serialized.obj src\g_util.obj src\measures3d.obj src\measures.obj \
-	src\ptarray.obj src\rtalgorithm.obj src\rtcircstring.obj src\rtcollection.obj \
-	src\rtcompound.obj src\rtcurvepoly.obj src\rtgeodetic.obj \
-	src\rtgeom_api.obj src\rtgeom.obj src\rtgeom_debug.obj src\rtgeom_geos.obj \
-	src\rtgeom_geos_clean.obj src\rtgeom_geos_node.obj src\rtgeom_geos_split.obj \
-	src\rtgeom_topo.obj src\rthomogenize.obj src\rtin_geojson.obj src\rtin_twkb.obj \
-	src\rtin_wkb.obj src\rtiterator.obj src\rtlinearreferencing.obj src\rtline.obj \
-	src\rtmcurve.obj src\rtmline.obj src\rtmpoint.obj src\rtmpoly.obj src\rtmsurface.obj \
-	src\rtout_encoded_polyline.obj src\rtout_geojson.obj src\rtout_gml.obj \
-	src\rtout_kml.obj src\rtout_svg.obj src\rtout_twkb.obj src\rtout_wkb.obj \
-	src\rtout_wkt.obj src\rtout_x3d.obj src\rtpoint.obj src\rtpoly.obj src\rtprint.obj \
-	src\rtpsurface.obj src\rtspheroid.obj src\rtstroke.obj src\rttin.obj src\rttree.obj \
-	src\rttriangle.obj src\rtutil.obj src\stringbuffer.obj src\varint.obj
-
+LIBOBJ = src/box2d.obj src/bytebuffer.obj src/g_box.obj src/g_serialized.obj \
+	 src/g_util.obj src/measures.obj src/measures3d.obj src/ptarray.obj \
+	 src/rtalgorithm.obj src/rtcircstring.obj src/rtcollection.obj \
+	 src/rtcompound.obj src/rtcurvepoly.obj src/rtgeodetic.obj src/rtgeom.obj \
+	 src/rtgeom_api.obj src/rtgeom_debug.obj src/rtgeom_geos.obj \
+	 src/rtgeom_geos_clean.obj src/rtgeom_geos_node.obj src/rtgeom_geos_split.obj \
+	 src/rtgeom_topo.obj src/rthomogenize.obj src/rtin_geojson.obj src/rtin_twkb.obj \
+	 src/rtin_wkb.obj src/rtiterator.obj src/rtline.obj src/rtlinearreferencing.obj \
+	 src/rtmcurve.obj src/rtmline.obj src/rtmpoint.obj src/rtmpoly.obj \
+	 src/rtmsurface.obj src/rtout_encoded_polyline.obj src/rtout_geojson.obj \
+	 src/rtout_gml.obj src/rtout_kml.obj src/rtout_svg.obj src/rtout_twkb.obj \
+	 src/rtout_wkb.obj src/rtout_wkt.obj src/rtout_x3d.obj src/rtpoint.obj \
+	 src/rtpoly.obj src/rtprint.obj src/rtpsurface.obj src/rtspheroid.obj \
+	 src/rtstroke.obj src/rtt_tpsnap.obj src/rttin.obj src/rttree.obj \
+	 src/rttriangle.obj src/rtutil.obj src/stringbuffer.obj src/varint.obj\
+	
 LIBRTTOPO_DLL	 	       =	librttopo$(VERSION).dll
 
-CFLAGS	=	/nologo -IC:\OSGeo4W\include -I. -Iheaders $(OPTFLAGS)
+CFLAGS	=	/nologo -I$(OSGEO4W_ROOT)\include -I. -Iheaders $(OPTFLAGS)
 
 default:	all
 
@@ -36,7 +37,7 @@
 librttopo_i.lib:	$(LIBOBJ)
 	link /debug /dll /out:$(LIBRTTOPO_DLL) \
 		/implib:librrttopo_i.lib $(LIBOBJ) \
-		C:\OSGeo4W\lib\geos_c.lib
+		$(OSGEO4W_ROOT)\lib\geos_c.lib
 	if exist $(LIBRTTOPO_DLL).manifest mt -manifest \
 		$(LIBRTTOPO_DLL).manifest -outputresource:$(LIBRTTOPO_DLL);2
 
diff -Nur librttopo/nmake.opt ../librttopo/nmake.opt
--- librttopo/nmake.opt	2019-07-27 08:55:02.000000000 +0200
+++ ../librttopo/nmake.opt	2023-07-03 16:57:56.109307100 +0200
@@ -1,5 +1,4 @@
 # Directory tree where RTTOPO will be installed.
-INSTDIR=C:\OSGeo4W
 
 # Uncomment the first for an optimized build, or the second for debug.
 OPTFLAGS=	/nologo /Ox /fp:precise /W4 /MD /D_CRT_SECURE_NO_WARNINGS \
diff -Nur librttopo/src/rttopo_config.h ../librttopo/src/rttopo_config.h
--- librttopo/src/rttopo_config.h	1970-01-01 01:00:00.000000000 +0100
+++ ../librttopo/src/rttopo_config.h	2023-07-03 16:57:49.973195000 +0200
@@ -0,0 +1,168 @@
+/* src/rttopo_config.h.  Generated from rttopo_config.h.in by configure.  */
+/* src/rttopo_config.h.in.  Generated from configure.ac by autoheader.  */
+
+/* Define to 1 if you have the <assert.h> header file. */
+#define HAVE_ASSERT_H 1
+
+/* Define to 1 if you have the <ctype.h> header file. */
+#define HAVE_CTYPE_H 1
+
+/* Define to 1 if you have the <dlfcn.h> header file. */
+/* #undef HAVE_DLFCN_H */
+
+/* Define to 1 if you have the <errno.h> header file. */
+#define HAVE_ERRNO_H 1
+
+/* Define to 1 if you have the `fdatasync' function. */
+/* #undef HAVE_FDATASYNC */
+
+/* Define to 1 if you have the <float.h> header file. */
+#define HAVE_FLOAT_H 1
+
+/* Define to 1 if you have the `ftruncate' function. */
+#define HAVE_FTRUNCATE 1
+
+/* Define to 1 if you have the <geos_c.h> header file. */
+#define HAVE_GEOS_C_H 1
+
+/* Define to 1 if you have the `getcwd' function. */
+#define HAVE_GETCWD 1
+
+/* Define to 1 if you have the `gettimeofday' function. */
+#define HAVE_GETTIMEOFDAY 1
+
+/* Define to 1 if you have the <inttypes.h> header file. */
+#define HAVE_INTTYPES_H 1
+
+/* Define to 1 if you have the `localtime_r' function. */
+/* #undef HAVE_LOCALTIME_R */
+
+/* Define to 1 if `lstat' has the bug that it succeeds when given the
+   zero-length file name argument. */
+#define HAVE_LSTAT_EMPTY_STRING_BUG 1
+
+/* Define to 1 if you have the <math.h> header file. */
+#define HAVE_MATH_H 1
+
+/* Define to 1 if you have the `memmove' function. */
+#define HAVE_MEMMOVE 1
+
+/* Define to 1 if you have the <memory.h> header file. */
+#define HAVE_MEMORY_H 1
+
+/* Define to 1 if you have the `memset' function. */
+#define HAVE_MEMSET 1
+
+/* Define to 1 if you have the `sqrt' function. */
+#define HAVE_SQRT 1
+
+/* Define to 1 if `stat' has the bug that it succeeds when given the
+   zero-length file name argument. */
+/* #undef HAVE_STAT_EMPTY_STRING_BUG */
+
+/* Define to 1 if you have the <stdarg.h> header file. */
+#define HAVE_STDARG_H 1
+
+/* Define to 1 if you have the <stdint.h> header file. */
+#define HAVE_STDINT_H 1
+
+/* Define to 1 if you have the <stdio.h> header file. */
+#define HAVE_STDIO_H 1
+
+/* Define to 1 if you have the <stdlib.h> header file. */
+#define HAVE_STDLIB_H 1
+
+/* Define to 1 if you have the `strcasecmp' function. */
+#define HAVE_STRCASECMP 1
+
+/* Define to 1 if you have the `strerror' function. */
+#define HAVE_STRERROR 1
+
+/* Define to 1 if you have the `strftime' function. */
+#define HAVE_STRFTIME 1
+
+/* Define to 1 if you have the <strings.h> header file. */
+#define HAVE_STRINGS_H 1
+
+/* Define to 1 if you have the <string.h> header file. */
+#define HAVE_STRING_H 1
+
+/* Define to 1 if you have the `strncasecmp' function. */
+#define HAVE_STRNCASECMP 1
+
+/* Define to 1 if you have the `strstr' function. */
+#define HAVE_STRSTR 1
+
+/* Define to 1 if you have the <sys/stat.h> header file. */
+#define HAVE_SYS_STAT_H 1
+
+/* Define to 1 if you have the <sys/types.h> header file. */
+#define HAVE_SYS_TYPES_H 1
+
+/* Define to 1 if you have the <unistd.h> header file. */
+#define HAVE_UNISTD_H 1
+
+/* rtgeom version */
+#define LIBRTGEOM_VERSION "1.1.0-dev"
+
+/* Define to 1 if `lstat' dereferences a symlink specified with a trailing
+   slash. */
+/* #undef LSTAT_FOLLOWS_SLASHED_SYMLINK */
+
+/* Define to the sub-directory where libtool stores uninstalled libraries. */
+#define LT_OBJDIR ".libs/"
+
+/* Must be defined in order to disable debug mode. */
+#define NDEBUG 1
+
+/* Name of package */
+#define PACKAGE "librttopo"
+
+/* Define to the address where bug reports for this package should be sent. */
+#define PACKAGE_BUGREPORT "strk@kbt.io"
+
+/* Define to the full name of this package. */
+#define PACKAGE_NAME "librttopo"
+
+/* Define to the full name and version of this package. */
+#define PACKAGE_STRING "librttopo 1.1.0-dev"
+
+/* Define to the one symbol short name of this package. */
+#define PACKAGE_TARNAME "librttopo"
+
+/* Define to the home page for this package. */
+#define PACKAGE_URL ""
+
+/* Define to the version of this package. */
+#define PACKAGE_VERSION "1.1.0-dev"
+
+/* RTGEOM Debug level */
+#define RTGEOM_DEBUG_LEVEL 0
+
+/* GEOS library version */
+#define RTGEOM_GEOS_VERSION 36
+
+/* Define to 1 if you have the ANSI C header files. */
+#define STDC_HEADERS 1
+
+/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
+#define TIME_WITH_SYS_TIME 1
+
+/* Define to 1 if your <sys/time.h> declares `struct tm'. */
+/* #undef TM_IN_SYS_TIME */
+
+/* Version number of package */
+#define VERSION "1.1.0-dev"
+
+/* Define to empty if `const' does not conform to ANSI C. */
+/* #undef const */
+
+/* Define to `long int' if <sys/types.h> does not define. */
+/* #undef off_t */
+
+/* Define to `unsigned int' if <sys/types.h> does not define. */
+/* #undef size_t */
+
+/* Define to empty if the keyword `volatile' does not work. Warning: valid
+   code using `volatile' can become incorrect without. Disable with care. */
+/* #undef volatile */
