[librttopo] 01/06: Imported Upstream version 1.1.0~rc0

Bas Couwenberg sebastic at debian.org
Mon Nov 14 20:52:18 UTC 2016


This is an automated email from the git hooks/post-receive script.

sebastic pushed a commit to branch master
in repository librttopo.

commit 286ed3261bb64cc87e947df6b4bda9f67333c1b6
Author: Bas Couwenberg <sebastic at xs4all.nl>
Date:   Mon Nov 14 21:38:45 2016 +0100

    Imported Upstream version 1.1.0~rc0
---
 .drone.yml                              |    9 +
 .gitignore                              |    1 +
 .gitlab-ci.yml                          |    2 +-
 ChangeLog                               |  724 -------------
 HOWTO_RELEASE                           |    1 +
 Makefile.am                             |   13 +-
 NEWS.md                                 |   23 +
 README.md                               |    6 +-
 configure.ac                            |    2 +-
 docker/build-test/Dockerfile.debian-sid |    5 +
 docker/build-test/Makefile              |   13 +
 headers/librttopo.h                     |  108 +-
 headers/librttopo_geom.h.in             |   38 +-
 src/Makefile.am                         |   10 +-
 src/box2d.c                             |    2 +-
 src/bytebuffer.c                        |   48 +-
 src/g_box.c                             |    8 +-
 src/g_serialized.c                      |   54 +-
 src/librttopo_geom_internal.h           |   38 +-
 src/librttopo_internal.h                |   22 +-
 src/measures.c                          |   88 +-
 src/measures3d.c                        |   64 +-
 src/ptarray.c                           |  140 +--
 src/rtalgorithm.c                       |   28 +-
 src/rtcircstring.c                      |    2 +-
 src/rtcollection.c                      |   12 +-
 src/rtcompound.c                        |    6 +-
 src/rtcurvepoly.c                       |    8 +-
 src/rtgeodetic.c                        |  184 ++--
 src/rtgeom.c                            |   36 +-
 src/rtgeom_api.c                        |   10 +-
 src/rtgeom_debug.c                      |   12 +-
 src/rtgeom_geos.c                       |  108 +-
 src/rtgeom_geos.h                       |    2 +-
 src/rtgeom_geos_clean.c                 |   34 +-
 src/rtgeom_geos_node.c                  |    2 +-
 src/rtgeom_geos_split.c                 |   87 +-
 src/rtgeom_log.h                        |   14 +-
 src/rtgeom_topo.c                       | 1754 ++++++++++++++++++++++++-------
 src/rtin_geojson.c                      |   24 +-
 src/rtin_twkb.c                         |   38 +-
 src/rtin_wkb.c                          |   34 +-
 src/rtline.c                            |   16 +-
 src/rtlinearreferencing.c               |   48 +-
 src/rtmpoint.c                          |    2 +-
 src/rtout_gml.c                         |    2 +-
 src/rtout_twkb.c                        |   46 +-
 src/rtout_wkb.c                         |   32 +-
 src/rtout_wkt.c                         |    2 +-
 src/rtpoint.c                           |    2 +-
 src/rtpoly.c                            |   20 +-
 src/rtprint.c                           |    2 +-
 src/rtspheroid.c                        |   60 +-
 src/rtstroke.c                          |   60 +-
 src/rtt_tpsnap.c                        |  771 ++++++++++++++
 src/rttree.c                            |   10 +-
 src/rttriangle.c                        |    4 +-
 src/rtutil.c                            |   12 +-
 src/varint.c                            |    2 +-
 src/varint.h                            |    2 +-
 60 files changed, 3103 insertions(+), 1804 deletions(-)

diff --git a/.drone.yml b/.drone.yml
new file mode 100644
index 0000000..96308b8
--- /dev/null
+++ b/.drone.yml
@@ -0,0 +1,9 @@
+# See http://readme.drone.io/usage/overview
+pipeline:
+  build:
+    image: docker.kbt.io/librttopo/build-test:debian-sid
+    commands:
+      - ./autogen.sh
+      - ./configure
+      - make
+      - make distcheck
diff --git a/.gitignore b/.gitignore
index 1300bcc..4daf5da 100644
--- a/.gitignore
+++ b/.gitignore
@@ -32,3 +32,4 @@ rtin_wkt_parse.c
 rtin_wkt_parse.h
 rttopo_config.h
 rttopo_config.h.in
+!/docker/**/Makefile
diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml
index 3b43abb..961ae12 100644
--- a/.gitlab-ci.yml
+++ b/.gitlab-ci.yml
@@ -10,6 +10,6 @@ test:
     - apt-get install -t sid -y libgeos-dev
     - geos-config --version || true
     - ./autogen.sh
-    - ./configure
+    - ./configure CFLAGS="-Wall -g -O2"
     - make
     - make distcheck
diff --git a/ChangeLog b/ChangeLog
deleted file mode 100644
index 9b34946..0000000
--- a/ChangeLog
+++ /dev/null
@@ -1,724 +0,0 @@
-2016-05-18  Sandro Santilli <strk at kbt.io>
-
-	* configure.ac: Release 1.0.0
-
-2016-05-07  Sandro Santilli <strk at keybit.net>
-
-	* ChangeLog: Add ChangeLog file in repository
-
-2016-05-07  Sandro Santilli <strk at keybit.net>
-
-	* HOWTO_RELEASE, Makefile.am: Rework ChangeLog generation rule Generation target is now "cl" and also works when build dir is not
-	below source dir.  ChangeLog is pushed to repo.
-
-2016-05-07  Sandro Santilli <strk at keybit.net>
-
-	* .gitignore: Ignore more generated files
-
-2016-05-07  Sandro Santilli <strk at keybit.net>
-
-	* configure.ac: Set version to 1.0.0-RC3 (and update admin email)
-
-2016-05-07  Sandro Santilli <strk at keybit.net>
-
-	* src/rtutil.c: Release GEOS context on rtgeom_finish Patch by Alessandro Furieri
-
-2016-05-07  Sandro Santilli <strk at keybit.net>
-
-	* headers/librttopo_geom.h.in: Rewrite the introductory section of
-	docs
-
-2016-05-06  Sandro Santilli <strk at keybit.net>
-
-	* src/rtgeom_geos.c: Do not override pre-initialized GEOS handler in
-	rttopo context Fixes leaks of GEOS contexts.  Thanks Alessandro Furieri for
-	spotting this.
-
-2016-05-06  Sandro Santilli <strk at keybit.net>
-
-	* .editorconfig, headers/librttopo.h, headers/librttopo_geom.h.in,
-	src/box2d.c, src/bytebuffer.c, src/bytebuffer.h, src/g_box.c,
-	src/g_serialized.c, src/g_util.c, src/librttopo_geom_internal.h,
-	src/measures.c, src/measures.h, src/measures3d.c, src/measures3d.h,
-	src/ptarray.c, src/rtalgorithm.c, src/rtcircstring.c,
-	src/rtcollection.c, src/rtcompound.c, src/rtcurvepoly.c,
-	src/rtgeodetic.c, src/rtgeodetic.h, src/rtgeom.c, src/rtgeom_api.c,
-	src/rtgeom_debug.c, src/rtgeom_geos.c, src/rtgeom_geos_clean.c,
-	src/rtgeom_geos_node.c, src/rtgeom_geos_split.c, src/rtgeom_log.h,
-	src/rtgeom_topo.c, src/rthomogenize.c, src/rtin_geojson.c,
-	src/rtin_twkb.c, src/rtin_wkb.c, src/rtiterator.c, src/rtline.c,
-	src/rtlinearreferencing.c, src/rtmline.c, src/rtmpoint.c,
-	src/rtmpoly.c, src/rtout_encoded_polyline.c, src/rtout_geojson.c,
-	src/rtout_gml.c, src/rtout_kml.c, src/rtout_svg.c,
-	src/rtout_twkb.c, src/rtout_twkb.h, src/rtout_wkb.c,
-	src/rtout_wkt.c, src/rtout_x3d.c, src/rtpoint.c, src/rtpoly.c,
-	src/rtprint.c, src/rtpsurface.c, src/rtspheroid.c, src/rtstroke.c,
-	src/rttin.c, src/rttree.c, src/rttree.h, src/rttriangle.c,
-	src/rtutil.c, src/stringbuffer.c, src/stringbuffer.h, src/varint.c: 
-	Style only commit: use 2-spaces instead of tabs, trim ending
-	newlines
-
-2016-05-03  Sandro Santilli <strk at keybit.net>
-
-	* HOWTO_RELEASE: Add upload destination
-
-2016-05-01  Sandro Santilli <strk at keybit.net>
-
-	* .gitlab-ci.yml: Have gitlab-ci install git2cl
-
-2016-05-01  Sandro Santilli <strk at keybit.net>
-
-	* Makefile.am: Include an auto-generated ChangeLog file in
-	distribution Closes #9
-
-2016-04-30  Sandro Santilli <strk at keybit.net>
-
-	* CREDITS: Add PSC info
-
-2016-04-30  Sandro Santilli <strk at keybit.net>
-
-	* CREDITS: Add Bas credits
-
-2016-04-30  Sandro Santilli <strk at keybit.net>
-
-	* README.md: Add link to development mailing list
-
-2016-04-26  Sandro Santilli <strk at keybit.net>
-
-	* README.md: Use markdown link for windows build reference
-
-2016-04-26  Sandro Santilli <strk at keybit.net>
-
-	* Makefile.am, README.md, doc/BUILDING-ON-WINDOWS.md: Add windows
-	build instructions
-
-2016-04-26  Sandro Santilli <strk at keybit.net>
-
-	* .gitlab-ci.yml: Install zip tool for dist
-
-2016-04-26  Sandro Santilli <strk at keybit.net>
-
-	* HOWTO_RELEASE: Tweak instruction to push annotated tag
-
-2016-04-26  Sandro Santilli <strk at keybit.net>
-
-	* HOWTO_RELEASE: Add HOWTO_RELEASE file This is not distributed as part of the tarball
-
-2016-04-26  Sandro Santilli <strk at keybit.net>
-
-	* .gitlab-ci.yml: Have gitlab-ci run distcheck The 'distcheck' rule will test for install/uninstall targets
-
-2016-04-26  Sandro Santilli <strk at keybit.net>
-
-	* README.md: Add license info
-
-2016-04-26  Sandro Santilli <strk at keybit.net>
-
-	* CREDITS, Makefile.am, doc/g_serialized.txt, g_serialized.txt: Add
-	credits, move g_serialized under doc
-
-2016-04-26  Sandro Santilli <strk at keybit.net>
-
-	* configure.ac: Set version to 1.0.0-RC2
-
-2016-04-26  Sandro Santilli <strk at keybit.net>
-
-	* configure.ac: Drop trailing newlines, as per .editorconfig
-
-2016-04-26  Sandro Santilli <strk at keybit.net>
-
-	* Makefile.am: Distribute DATASTORES.md
-
-2016-04-25  Sandro Santilli <strk at keybit.net>
-
-	* README.md, doc/DATASTORES.md: Add list of known data stores
-
-2016-04-25  Sandro Santilli <strk at keybit.net>
-
-	* README.md: Reword about section
-
-2016-04-25  Sandro Santilli <strk at keybit.net>
-
-	* src/rtprint.c: Do not use dynamic arrays
-
-2016-04-25  Sandro Santilli <strk at keybit.net>
-
-	* README.md: Reword the About part
-
-2016-04-25  Sandro Santilli <strk at keybit.net>
-
-	* Makefile.am, README.md, README.topo: Merge the two readmes, add
-	info about building
-
-2016-04-25  Sandro Santilli <strk at keybit.net>
-
-	* src/Makefile.am: Remove unexistent file from noinst_HEADERS
-
-2016-04-25  Sandro Santilli <strk at keybit.net>
-
-	* makefile.vc, nmake.opt: Add build scripts for MSVC Files provided by Alessandro Furieri
-
-2016-04-25  Sandro Santilli <strk at keybit.net>
-
-	* src/Makefile.am, src/rtgeodetic_tree.c, src/rtgeodetic_tree.h: 
-	Drop unused geodetic tree files
-
-2016-04-25  Alessandro Furieri <a.furieri at lqt.it>
-
-	* .gitignore, Makefile, Makefile.am, Version.config, aclocal.m4,
-	autogen.sh, configure.ac, headers/Makefile.am, headers/librttopo.h,
-	headers/librttopo_geom.h.in, macros/intltool.m4, macros/lib-ld.m4,
-	macros/lib-link.m4, macros/lib-prefix.m4, macros/libtool.m4,
-	macros/ltoptions.m4, macros/ltsugar.m4, macros/ltversion.m4,
-	macros/lt~obsolete.m4, macros/po.m4, macros/progtest.m4,
-	rttopo.pc.in, src/Makefile.am, src/Makefile.in, src/librttopo.h,
-	src/librttopo_geom.h.in, src/librttopo_geom_internal.h,
-	src/rttopo_config.h.in: Switch to automake based builds
-
-2016-04-21  Sandro Santilli <strk at keybit.net>
-
-	* src/librttopo_geom.h.in: Update copyright info
-
-2016-04-21  Sandro Santilli <strk at keybit.net>
-
-	* src/librttopo_geom.h.in: Remove trailing spaces
-
-2016-04-21  Sandro Santilli <strk at keybit.net>
-
-	* src/rtgeom_topo.c: Update copyright notice
-
-2016-04-21  Sandro Santilli <strk at keybit.net>
-
-	* src/rtgeom_topo.c: Remove trailing spaces
-
-2016-04-21  Sandro Santilli <strk at keybit.net>
-
-	* .editorconfig: Add an EditorConfig configuration See http://editorconfig.org/
-
-2016-04-21  Sandro Santilli <strk at keybit.net>
-
-	* src/rtgeom_topo.c: Add last port info
-
-2016-04-21  Sandro Santilli <strk at keybit.net>
-
-	* src/rtgeom_topo.c: Fix debug print
-
-2016-04-21  Sandro Santilli <strk at keybit.net>
-
-	* src/rtgeom_topo.c: rtt_AddEdge*: avoid db access for edges known
-	to be dangling
-
-2016-04-20  Sandro Santilli <strk at keybit.net>
-
-	* src/rtgeom_topo.c: Fix bogus port of side-location-conflict check Rectifies 891d7bb0b5f25bf73ccd3a304febd96b59279527
-
-2016-04-20  Sandro Santilli <strk at keybit.net>
-
-	* src/rtgeom_topo.c: Improves snapping robustness See http://trac.osgeo.org/postgis/ticket/3402
-
-2016-04-20  Sandro Santilli <strk at keybit.net>
-
-	* src/rtgeom_topo.c: Fixes geometry-intersects-edge exception when
-	snapping twice to the same pointset.  See http://trac.osgeo.org/postgis/ticket/3412
-
-2016-04-19  Sandro Santilli <strk at keybit.net>
-
-	* README.md: Add a mention of the gilab.com mirror
-
-2016-04-19  Sandro Santilli <strk at keybit.net>
-
-	* README.md: Add link to osgeo/gogs as official code repo
-
-2016-04-19  Sandro Santilli <strk at keybit.net>
-
-	* configure.ac, src/Makefile.in, src/box2d.c, src/bytebuffer.c,
-	src/bytebuffer.h, src/g_box.c, src/g_serialized.c, src/g_util.c,
-	src/librttopo.h, src/librttopo_geom.h.in,
-	src/librttopo_geom_internal.h, src/librttopo_internal.h,
-	src/measures.c, src/measures.h, src/measures3d.c, src/measures3d.h,
-	src/ptarray.c, src/rtalgorithm.c, src/rtcircstring.c,
-	src/rtcollection.c, src/rtcompound.c, src/rtcurvepoly.c,
-	src/rtgeodetic.c, src/rtgeodetic.h, src/rtgeodetic_tree.c,
-	src/rtgeodetic_tree.h, src/rtgeom.c, src/rtgeom_api.c,
-	src/rtgeom_debug.c, src/rtgeom_geos.c, src/rtgeom_geos.h,
-	src/rtgeom_geos_clean.c, src/rtgeom_geos_node.c,
-	src/rtgeom_geos_split.c, src/rtgeom_log.h, src/rtgeom_topo.c,
-	src/rthomogenize.c, src/rtin_geojson.c, src/rtin_twkb.c,
-	src/rtin_wkb.c, src/rtiterator.c, src/rtline.c,
-	src/rtlinearreferencing.c, src/rtmcurve.c, src/rtmline.c,
-	src/rtmpoint.c, src/rtmpoly.c, src/rtmsurface.c,
-	src/rtout_encoded_polyline.c, src/rtout_geojson.c, src/rtout_gml.c,
-	src/rtout_kml.c, src/rtout_svg.c, src/rtout_twkb.c,
-	src/rtout_twkb.h, src/rtout_wkb.c, src/rtout_wkt.c,
-	src/rtout_x3d.c, src/rtpoint.c, src/rtpoly.c, src/rtprint.c,
-	src/rtpsurface.c, src/rtspheroid.c, src/rtstroke.c, src/rttin.c,
-	src/rttopo_config.h.in, src/rttree.c, src/rttree.h,
-	src/rttriangle.c, src/rtutil.c, src/stringbuffer.c,
-	src/stringbuffer.h, src/varint.c, src/varint.h: Update homepage to
-	use osgeo/gogs
-
-2016-04-19  Sandro Santilli <strk at keybit.net>
-
-	* src/box2d.c, src/rtgeodetic_tree.c, src/rtgeodetic_tree.h,
-	src/rtprint.c, src/rttopo_config.h.in, src/rttree.c, src/rttree.h,
-	src/rtutil.c: Add missing copyright notices
-
-2016-04-19  Sandro Santilli <strk at keybit.net>
-
-	* src/librttopo_geom.h.in, src/rtutil.c: Add rtgeom_finish function,
-	and improve dox for rtgeom_init
-
-2016-04-19  Sandro Santilli <strk at keybit.net>
-
-	* src/rtutil.c: Allow calling rtgeom_init with all null pointers
-
-2016-04-18  Sandro Santilli <strk at keybit.net>
-
-	* src/rtgeom_topo.c: Fix crash on face-collapsing edge change See https://trac.osgeo.org/postgis/ticket/3463
-
-2016-04-18  Sandro Santilli <strk at keybit.net>
-
-	* src/rtgeom_topo.c: Check for side-location conflicts when adding a
-	new edge It is possible to trigger such failure adding an edge to a corrupted
-	topology. Test added.  See https://trac.osgeo.org/postgis/ticket/3464
-
-2016-04-18  Sandro Santilli <strk at keybit.net>
-
-	* src/rtgeom_topo.c: PRId64 to RTTFMT_ELEMID
-
-2016-04-18  Sandro Santilli <strk at keybit.net>
-
-	* src/rtgeom_topo.c: Give more decimal digits in edge-motion
-	collision detection point
-
-2016-04-18  Sandro Santilli <strk at keybit.net>
-
-	* .gitignore, README.topo, configure.ac, src/Makefile.in,
-	src/box2d.c, src/bytebuffer.c, src/g_box.c, src/g_serialized.c,
-	src/g_util.c, src/librtgeom.h.in, src/librtgeom_internal.h,
-	src/librtgeom_topo.h, src/librtgeom_topo_internal.h,
-	src/librttopo.h, src/librttopo_geom.h.in,
-	src/librttopo_geom_internal.h, src/librttopo_internal.h,
-	src/measures.h, src/ptarray.c, src/rtalgorithm.c,
-	src/rtcircstring.c, src/rtcollection.c, src/rtcompound.c,
-	src/rtcurvepoly.c, src/rtgeodetic.c, src/rtgeodetic_tree.c,
-	src/rtgeom.c, src/rtgeom_api.c, src/rtgeom_debug.c,
-	src/rtgeom_geos.c, src/rtgeom_geos.h, src/rtgeom_geos_clean.c,
-	src/rtgeom_geos_node.c, src/rtgeom_geos_split.c, src/rtgeom_log.h,
-	src/rtgeom_topo.c, src/rthomogenize.c, src/rtin_geojson.c,
-	src/rtin_twkb.c, src/rtin_wkb.c, src/rtiterator.c, src/rtline.c,
-	src/rtlinearreferencing.c, src/rtmcurve.c, src/rtmline.c,
-	src/rtmpoint.c, src/rtmpoly.c, src/rtmsurface.c,
-	src/rtout_encoded_polyline.c, src/rtout_geojson.c, src/rtout_gml.c,
-	src/rtout_kml.c, src/rtout_svg.c, src/rtout_twkb.h,
-	src/rtout_wkb.c, src/rtout_wkt.c, src/rtout_x3d.c, src/rtpoint.c,
-	src/rtpoly.c, src/rtprint.c, src/rtpsurface.c, src/rtspheroid.c,
-	src/rtstroke.c, src/rttin.c, src/rttree.c, src/rttriangle.c,
-	src/rtutil.c, src/stringbuffer.c, src/stringbuffer.h, src/varint.c,
-	src/varint.h: Rename librtgeom to librttopo Renames:  librtgeom.h to librttopo_geom.h  librtgeom_internal.h to librttopo_geom_internal.h  librtgeom_topo*.h to librttopo*.h  librtgeom.{so,a} to librttopo.{so,a} See #1
-
-2016-04-18  Sandro Santilli <strk at keybit.net>
-
-	* configure.ac: Require GEOS-3.5.0 as the minimum version
-
-2016-04-18  Sandro Santilli <strk at keybit.net>
-
-	* .gitlab-ci.yml: Install geos-3.5.0
-
-2016-04-18  Sandro Santilli <strk at keybit.net>
-
-	* README.md: Update build badge
-
-2016-04-18  Sandro Santilli <strk at keybit.net>
-
-	* Makefile: Do not make "clean" and "uninstall" dependent on running
-	configure Fixes #2
-
-2016-04-18  Sandro Santilli <strk at keybit.net>
-
-	* src/Makefile.in: Include varint module in the build
-
-2016-04-18  Sandro Santilli <strk at keybit.net>
-
-	* configure.ac: Drop references to PostGIS/liblwgeom
-
-2015-12-15  Sandro Santilli <strk at keybit.net>
-
-	* Makefile: Add missing Makefile
-
-2015-12-15  Sandro Santilli <strk at keybit.net>
-
-	* .gitlab-ci.yml: See which version of GEOS are available
-
-2015-12-15  Sandro Santilli <strk at keybit.net>
-
-	* src/Makefile.in: Fix clean rule
-
-2015-12-15  Sandro Santilli <strk at keybit.net>
-
-	* src/librtgeom.h.in, src/rtutil.c: Remove the possibility to use a
-	pre-initialized GEOS context This is to allow for intercepting geos messages from the library,
-	which would otherwise require changing the passed context.
-
-2015-12-14  Sandro Santilli <strk at keybit.net>
-
-	* .gitignore: Ignore the right Makefile, not the root one
-
-2015-12-14  Sandro Santilli <strk at keybit.net>
-
-	* src/box2d.c, src/bytebuffer.c, src/bytebuffer.h, src/g_box.c,
-	src/g_serialized.c, src/g_util.c, src/librtgeom.h.in,
-	src/librtgeom_internal.h, src/librtgeom_topo.h,
-	src/librtgeom_topo_internal.h, src/measures.c, src/measures.h,
-	src/measures3d.c, src/measures3d.h, src/ptarray.c,
-	src/rtalgorithm.c, src/rtcircstring.c, src/rtcollection.c,
-	src/rtcompound.c, src/rtcurvepoly.c, src/rtgeodetic.c,
-	src/rtgeodetic.h, src/rtgeodetic_tree.c, src/rtgeodetic_tree.h,
-	src/rtgeom.c, src/rtgeom_api.c, src/rtgeom_debug.c,
-	src/rtgeom_geos.c, src/rtgeom_geos.h, src/rtgeom_geos_clean.c,
-	src/rtgeom_geos_node.c, src/rtgeom_geos_split.c, src/rtgeom_log.h,
-	src/rtgeom_topo.c, src/rthomogenize.c, src/rtin_geojson.c,
-	src/rtin_twkb.c, src/rtin_wkb.c, src/rtiterator.c, src/rtline.c,
-	src/rtlinearreferencing.c, src/rtmcurve.c, src/rtmline.c,
-	src/rtmpoint.c, src/rtmpoly.c, src/rtmsurface.c,
-	src/rtout_encoded_polyline.c, src/rtout_geojson.c, src/rtout_gml.c,
-	src/rtout_kml.c, src/rtout_svg.c, src/rtout_twkb.c,
-	src/rtout_twkb.h, src/rtout_wkb.c, src/rtout_wkt.c,
-	src/rtout_x3d.c, src/rtpoint.c, src/rtpoly.c, src/rtprint.c,
-	src/rtpsurface.c, src/rtspheroid.c, src/rtstroke.c, src/rttin.c,
-	src/rttopo_config.h.in, src/rttree.c, src/rttree.h,
-	src/rttriangle.c, src/rtutil.c, src/snprintf.c, src/stringbuffer.c,
-	src/stringbuffer.h, src/varint.c, src/varint.h: Update copyright
-	headers
-
-2015-12-14  Sandro Santilli <strk at keybit.net>
-
-	* COPYING: Add COPYING file
-
-2015-12-12  Sandro Santilli <strk at keybit.net>
-
-	* README.md: Add build status badge
-
-2015-12-12  Sandro Santilli <strk at keybit.net>
-
-	* TODO: Remove done item
-
-2015-12-12  Sandro Santilli <strk at keybit.net>
-
-	* src/librtgeom.h.in, src/librtgeom_internal.h, src/rtutil.c: Fix
-	re-entrancy of custom allocators and loggers
-
-2015-12-12  Sandro Santilli <strk at keybit.net>
-
-	* TODO: Updated
-
-2015-12-12  Sandro Santilli <strk at keybit.net>
-
-	* Makefile.in, box2d.c, bytebuffer.c, bytebuffer.h, configure.ac,
-	g_box.c, g_serialized.c, g_util.c, librtgeom.h.in,
-	librtgeom_internal.h, librtgeom_topo.h, librtgeom_topo_internal.h,
-	measures.c, measures.h, measures3d.c, measures3d.h, ptarray.c,
-	rtalgorithm.c, rtcircstring.c, rtcollection.c, rtcompound.c,
-	rtcurvepoly.c, rtgeodetic.c, rtgeodetic.h, rtgeodetic_tree.c,
-	rtgeodetic_tree.h, rtgeom.c, rtgeom_api.c, rtgeom_debug.c,
-	rtgeom_geos.c, rtgeom_geos.h, rtgeom_geos_clean.c,
-	rtgeom_geos_node.c, rtgeom_geos_split.c, rtgeom_log.h,
-	rtgeom_topo.c, rthomogenize.c, rtin_geojson.c, rtin_twkb.c,
-	rtin_wkb.c, rtiterator.c, rtline.c, rtlinearreferencing.c,
-	rtmcurve.c, rtmline.c, rtmpoint.c, rtmpoly.c, rtmsurface.c,
-	rtout_encoded_polyline.c, rtout_geojson.c, rtout_gml.c,
-	rtout_kml.c, rtout_svg.c, rtout_twkb.c, rtout_twkb.h, rtout_wkb.c,
-	rtout_wkt.c, rtout_x3d.c, rtpoint.c, rtpoly.c, rtprint.c,
-	rtpsurface.c, rtspheroid.c, rtstroke.c, rttin.c,
-	rttopo_config.h.in, rttree.c, rttree.h, rttriangle.c, rtutil.c,
-	snprintf.c, src/Makefile.in, src/box2d.c, src/bytebuffer.c,
-	src/bytebuffer.h, src/g_box.c, src/g_serialized.c, src/g_util.c,
-	src/librtgeom.h.in, src/librtgeom_internal.h, src/librtgeom_topo.h,
-	src/librtgeom_topo_internal.h, src/measures.c, src/measures.h,
-	src/measures3d.c, src/measures3d.h, src/ptarray.c,
-	src/rtalgorithm.c, src/rtcircstring.c, src/rtcollection.c,
-	src/rtcompound.c, src/rtcurvepoly.c, src/rtgeodetic.c,
-	src/rtgeodetic.h, src/rtgeodetic_tree.c, src/rtgeodetic_tree.h,
-	src/rtgeom.c, src/rtgeom_api.c, src/rtgeom_debug.c,
-	src/rtgeom_geos.c, src/rtgeom_geos.h, src/rtgeom_geos_clean.c,
-	src/rtgeom_geos_node.c, src/rtgeom_geos_split.c, src/rtgeom_log.h,
-	src/rtgeom_topo.c, src/rthomogenize.c, src/rtin_geojson.c,
-	src/rtin_twkb.c, src/rtin_wkb.c, src/rtiterator.c, src/rtline.c,
-	src/rtlinearreferencing.c, src/rtmcurve.c, src/rtmline.c,
-	src/rtmpoint.c, src/rtmpoly.c, src/rtmsurface.c,
-	src/rtout_encoded_polyline.c, src/rtout_geojson.c, src/rtout_gml.c,
-	src/rtout_kml.c, src/rtout_svg.c, src/rtout_twkb.c,
-	src/rtout_twkb.h, src/rtout_wkb.c, src/rtout_wkt.c,
-	src/rtout_x3d.c, src/rtpoint.c, src/rtpoly.c, src/rtprint.c,
-	src/rtpsurface.c, src/rtspheroid.c, src/rtstroke.c, src/rttin.c,
-	src/rttopo_config.h.in, src/rttree.c, src/rttree.h,
-	src/rttriangle.c, src/rtutil.c, src/snprintf.c, src/stringbuffer.c,
-	src/stringbuffer.h, src/varint.c, src/varint.h, stringbuffer.c,
-	stringbuffer.h, varint.c, varint.h: Move sources under a src/ dir
-
-2015-12-12  Sandro Santilli <strk at keybit.net>
-
-	* librtgeom.h.in, librtgeom_internal.h, ptarray.c, rtgeom.c: Prefix
-	AFFINE
-
-2015-12-12  Sandro Santilli <strk at keybit.net>
-
-	* g_box.c, g_serialized.c, librtgeom.h.in, measures.c,
-	measures3d.c, ptarray.c, rtalgorithm.c, rtcircstring.c,
-	rtcompound.c, rtgeodetic.c, rtgeodetic_tree.c, rtgeom.c,
-	rtgeom_api.c, rtgeom_geos.c, rtgeom_geos_clean.c,
-	rtgeom_geos_split.c, rtgeom_topo.c, rtin_twkb.c, rtin_wkb.c,
-	rtiterator.c, rtline.c, rtlinearreferencing.c, rtmpoint.c,
-	rtout_encoded_polyline.c, rtout_geojson.c, rtout_gml.c,
-	rtout_kml.c, rtout_svg.c, rtout_twkb.c, rtout_wkb.c, rtout_wkt.c,
-	rtout_x3d.c, rtpoint.c, rtprint.c, rtpsurface.c, rtspheroid.c,
-	rtstroke.c, rttin.c, rttree.c, rttriangle.c: Prefix getPoint* with
-	rt_
-
-2015-12-11  Sandro Santilli <strk at keybit.net>
-
-	* Makefile.in, librtgeom.h.in, rtgeodetic.c, rtgeodetic.h,
-	rtgeodetic_tree.c, rtgeodetic_tree.h, rtspheroid.c: Revert "Remove
-	geodetic and spheroid functions" This reverts commit cb34f54ca9c15ad2d65eac67dfdd5e94eae475f3.  Conflicts: 	Makefile.in Also adapted all signatures to re-entrancy mode.  Closes #1
-
-2015-12-11  Sandro Santilli <strk at keybit.net>
-
-	* TODO: Add more missing symbols from spatialite
-
-2015-12-11  Sandro Santilli <strk at keybit.net>
-
-	* TODO: Add list of function to expose to public API
-
-2015-12-11  Sandro Santilli <strk at keybit.net>
-
-	* macros/codeset.m4, macros/gettext.m4, macros/gtk-2.0.m4,
-	macros/iconv.m4, macros/intl.m4, macros/intldir.m4,
-	macros/intlmacosx.m4, macros/nls.m4: Remove some unused macros
-
-2015-12-11  Sandro Santilli <strk at keybit.net>
-
-	* Makefile.in, aclocal.m4, configure.ac, librtgeom_internal.h,
-	macros/ac_proj4_version.m4, rtgeom_transform.c: Drop PROJ4
-	dependency, and reprojection support
-
-2015-12-11  Sandro Santilli <strk at keybit.net>
-
-	* configure.ac: Relax GEOS requirement to accept 3.4.0 (mainly for
-	gitlab testing)
-
-2015-12-11  Sandro Santilli <strk at keybit.net>
-
-	* configure.ac, librtgeom.h.in, librtgeom_internal.h,
-	rtgeom_geos.h, rtgeom_geos_split.c: Ensure only the re-entrant API
-	is used Raises GEOS requirement to 3.5.0
-
-2015-12-11  Sandro Santilli <strk at keybit.net>
-
-	* .gitlab-ci.yml: Stop using lsb_release on gitlab-ci
-
-2015-12-11  Sandro Santilli <strk at keybit.net>
-
-	* librtgeom_internal.h, rtgeom_geos.c, rtgeom_geos.h,
-	rtgeom_geos_clean.c, rtgeom_geos_node.c, rtgeom_geos_split.c,
-	rtgeom_topo.c: Make handling of GEOS errors re-entrant
-
-2015-12-10  Sandro Santilli <strk at keybit.net>
-
-	* librtgeom_topo.h: Add info about how to create RTCTX
-
-2015-12-10  Sandro Santilli <strk at keybit.net>
-
-	* librtgeom.h.in, rtgeom_geos.c, rtgeom_geos.h,
-	rtgeom_geos_clean.c, rtgeom_geos_node.c, rtgeom_geos_split.c: Switch
-	to reentrant GEOS interface in rtgeom
-
-2015-12-10  Sandro Santilli <strk at keybit.net>
-
-	* librtgeom.h.in, rtgeom_api.c, rtutil.c: Add RTCTX initializing
-	functions
-
-2015-12-10  Sandro Santilli <strk at keybit.net>
-
-	* librtgeom_internal.h, librtgeom_topo_internal.h, rtgeom_geos.c,
-	rtgeom_geos.h, rtgeom_topo.c: Switch to reentrant GEOS interface in
-	rtgeom_topo
-
-2015-12-10  Sandro Santilli <strk at keybit.net>
-
-	* librtgeom_topo.h, rtgeom_topo.c: Take RTCTX at
-	rtt_CreateBackendIface time
-
-2015-12-10  Sandro Santilli <strk at keybit.net>
-
-	* box2d.c, bytebuffer.c, bytebuffer.h, g_box.c, g_serialized.c,
-	g_util.c, librtgeom.h.in, librtgeom_internal.h, librtgeom_topo.h,
-	measures.c, measures.h, measures3d.c, measures3d.h, ptarray.c,
-	rtalgorithm.c, rtcircstring.c, rtcollection.c, rtcompound.c,
-	rtcurvepoly.c, rtgeom.c, rtgeom_api.c, rtgeom_debug.c,
-	rtgeom_geos.c, rtgeom_geos.h, rtgeom_geos_clean.c,
-	rtgeom_geos_node.c, rtgeom_geos_split.c, rtgeom_log.h,
-	rtgeom_topo.c, rtgeom_transform.c, rthomogenize.c, rtin_geojson.c,
-	rtin_twkb.c, rtin_wkb.c, rtiterator.c, rtline.c,
-	rtlinearreferencing.c, rtmline.c, rtmpoint.c, rtmpoly.c,
-	rtout_encoded_polyline.c, rtout_geojson.c, rtout_gml.c,
-	rtout_kml.c, rtout_svg.c, rtout_twkb.c, rtout_twkb.h, rtout_wkb.c,
-	rtout_wkt.c, rtout_x3d.c, rtpoint.c, rtpoly.c, rtprint.c,
-	rtpsurface.c, rtstroke.c, rttin.c, rttree.c, rttree.h,
-	rttriangle.c, rtutil.c, stringbuffer.c, stringbuffer.h, varint.c,
-	varint.h: Made all RTCTX params const
-
-2015-12-10  Sandro Santilli <strk at keybit.net>
-
-	* rtgeom_log.h, rtgeom_topo.c, rtutil.c: Const correct
-	rtnotice/rtdebug
-
-2015-12-10  Sandro Santilli <strk at keybit.net>
-
-	* g_box.c: do not redefine isfinite
-
-2015-12-10  Sandro Santilli <strk at keybit.net>
-
-	* Makefile.in, librtgeom.h.in, rtgeom_geos.h,
-	rtgeom_geos_cluster.c, rtin_encoded_polyline.c, rtunionfind.c,
-	rtunionfind.h: Remove polyline encoding and clustering functions
-
-2015-12-10  Sandro Santilli <strk at keybit.net>
-
-	* box2d.c, bytebuffer.c, bytebuffer.h, g_box.c, g_serialized.c,
-	g_util.c, librtgeom.h.in, librtgeom_internal.h, librtgeom_topo.h,
-	librtgeom_topo_internal.h, measures.c, measures.h, measures3d.c,
-	measures3d.h, ptarray.c, rtalgorithm.c, rtcircstring.c,
-	rtcollection.c, rtcompound.c, rtcurvepoly.c, rtgeom.c,
-	rtgeom_api.c, rtgeom_debug.c, rtgeom_geos.c, rtgeom_geos.h,
-	rtgeom_geos_clean.c, rtgeom_geos_cluster.c, rtgeom_geos_node.c,
-	rtgeom_geos_split.c, rtgeom_log.h, rtgeom_topo.c,
-	rtgeom_transform.c, rthomogenize.c, rtin_encoded_polyline.c,
-	rtin_geojson.c, rtin_twkb.c, rtin_wkb.c, rtiterator.c, rtline.c,
-	rtlinearreferencing.c, rtmline.c, rtmpoint.c, rtmpoly.c,
-	rtout_encoded_polyline.c, rtout_geojson.c, rtout_gml.c,
-	rtout_kml.c, rtout_svg.c, rtout_twkb.c, rtout_twkb.h, rtout_wkb.c,
-	rtout_wkt.c, rtout_x3d.c, rtpoint.c, rtpoly.c, rtprint.c,
-	rtpsurface.c, rtstroke.c, rttin.c, rttree.c, rttree.h,
-	rttriangle.c, rtunionfind.c, rtunionfind.h, rtutil.c,
-	stringbuffer.c, stringbuffer.h, varint.c, varint.h: Add RTCTX
-	argument to all exposed functions
-
-2015-12-10  Sandro Santilli <strk at keybit.net>
-
-	* Makefile.in, effectivearea.c, effectivearea.h: Drop effective area
-
-2015-12-10  Sandro Santilli <strk at keybit.net>
-
-	* rtgeom_geos.c: Use custom geos error reporter
-
-2015-12-10  Sandro Santilli <strk at keybit.net>
-
-	* rtgeom_log.h, stringbuffer.h: Include internal header
-
-2015-12-10  Sandro Santilli <strk at keybit.net>
-
-	* Makefile.in, librtgeom.h.in, rtgeodetic.c, rtgeodetic.h,
-	rtgeodetic_tree.c, rtgeodetic_tree.h, rtspheroid.c: Remove geodetic
-	and spheroid functions
-
-2015-12-10  Sandro Santilli <strk at keybit.net>
-
-	* Makefile.in, librtgeom.h.in, rtin_wkt.c, rtin_wkt.h,
-	rtin_wkt_lex.l, rtin_wkt_parse.y: Remove WKT parser
-
-2015-12-09  Sandro Santilli <strk at keybit.net>
-
-	* librtgeom.h.in, librtgeom_internal.h: Add RTCTX typedef
-
-2015-12-09  Sandro Santilli <strk at keybit.net>
-
-	* Makefile.in: Fix librtgeom.h build rule
-
-2015-12-09  Sandro Santilli <strk at keybit.net>
-
-	* effectivearea.c, g_box.c, g_serialized.c, g_util.c,
-	librtgeom.h.in, ptarray.c, rtcircstring.c, rtcollection.c,
-	rtcompound.c, rtgeodetic.c, rtgeom.c, rtgeom_api.c, rtgeom_debug.c,
-	rtgeom_geos.c, rtgeom_geos_clean.c, rtgeom_geos_node.c,
-	rtgeom_geos_split.c, rthomogenize.c, rtin_geojson.c, rtin_wkt.c,
-	rtline.c, rtlinearreferencing.c, rtmline.c, rtout_geojson.c,
-	rtout_gml.c, rtout_kml.c, rtout_twkb.c, rtout_wkb.c, rtout_wkt.c,
-	rtout_x3d.c, rtpoint.c, rtpoly.c, rtpsurface.c, rtstroke.c,
-	rttin.c, rttriangle.c: Prefix TYPMOD and FLAG macros
-
-2015-12-09  Sandro Santilli <strk at keybit.net>
-
-	* effectivearea.c, effectivearea.h, g_box.c, g_serialized.c,
-	librtgeom.h.in, librtgeom_internal.h, measures.c, measures.h,
-	measures3d.c, measures3d.h, ptarray.c, rtalgorithm.c,
-	rtcircstring.c, rtcollection.c, rtcompound.c, rtgeodetic.c,
-	rtgeodetic.h, rtgeodetic_tree.c, rtgeodetic_tree.h, rtgeom.c,
-	rtgeom_api.c, rtgeom_geos.c, rtgeom_geos.h, rtgeom_geos_clean.c,
-	rtgeom_geos_split.c, rtgeom_topo.c, rtgeom_transform.c,
-	rtin_encoded_polyline.c, rtin_geojson.c, rtin_twkb.c, rtin_wkb.c,
-	rtin_wkt.c, rtin_wkt.h, rtin_wkt_parse.y, rtiterator.c, rtline.c,
-	rtlinearreferencing.c, rtmpoint.c, rtout_encoded_polyline.c,
-	rtout_geojson.c, rtout_gml.c, rtout_kml.c, rtout_svg.c,
-	rtout_twkb.c, rtout_wkb.c, rtout_wkt.c, rtout_x3d.c, rtpoint.c,
-	rtpoly.c, rtspheroid.c, rtstroke.c, rttree.c, rttree.h,
-	rttriangle.c: Prefix POINTARRAY
-
-2015-12-09  Sandro Santilli <strk at keybit.net>
-
-	* box2d.c, effectivearea.c, g_box.c, g_serialized.c,
-	librtgeom.h.in, librtgeom_internal.h, librtgeom_topo.h, measures.c,
-	measures.h, measures3d.c, measures3d.h, ptarray.c, rtalgorithm.c,
-	rtcircstring.c, rtcollection.c, rtcompound.c, rtgeodetic.c,
-	rtgeodetic.h, rtgeodetic_tree.c, rtgeodetic_tree.h, rtgeom.c,
-	rtgeom_api.c, rtgeom_geos.c, rtgeom_geos.h, rtgeom_geos_cluster.c,
-	rtgeom_geos_split.c, rtgeom_topo.c, rtgeom_transform.c,
-	rtin_encoded_polyline.c, rtin_geojson.c, rtin_twkb.c, rtin_wkb.c,
-	rtin_wkt.c, rtiterator.c, rtline.c, rtlinearreferencing.c,
-	rtmpoint.c, rtout_encoded_polyline.c, rtout_geojson.c, rtout_gml.c,
-	rtout_kml.c, rtout_svg.c, rtout_x3d.c, rtpoint.c, rtpoly.c,
-	rtprint.c, rtpsurface.c, rtspheroid.c, rtstroke.c, rttin.c,
-	rttree.c, rttree.h, rttriangle.c: Prefix GBOX and POINT*
-
-2015-12-09  Sandro Santilli <strk at keybit.net>
-
-	* librtgeom.h.in: Remove unused macros
-
-2015-12-09  Sandro Santilli <strk at keybit.net>
-
-	* librtgeom.h.in, librtgeom_internal.h, rtgeom.c, rthomogenize.c: 
-	Prefix NUMTYPES
-
-2015-12-09  Sandro Santilli <strk at keybit.net>
-
-	* bytebuffer.c, g_serialized.c, g_serialized.txt, librtgeom.h.in,
-	librtgeom_internal.h, rtgeom.c, rtgeom_topo.c, rtin_twkb.c,
-	rtin_wkb.c, rtin_wkt.c, rtin_wkt.h, rtin_wkt_lex.l,
-	rtin_wkt_parse.y, rtout_wkb.c, rtout_wkt.c: Prefix WKT/WKB macros
-	with "RT"
-
-2015-12-09  Sandro Santilli <strk at keybit.net>
-
-	* effectivearea.c, g_box.c, g_serialized.c, g_util.c,
-	librtgeom.h.in, librtgeom_internal.h, measures.c, measures3d.c,
-	rtalgorithm.c, rtcircstring.c, rtcollection.c, rtcompound.c,
-	rtcurvepoly.c, rtgeodetic.c, rtgeodetic_tree.c, rtgeom.c,
-	rtgeom_debug.c, rtgeom_geos.c, rtgeom_geos_clean.c,
-	rtgeom_geos_cluster.c, rtgeom_geos_node.c, rtgeom_geos_split.c,
-	rtgeom_topo.c, rtgeom_transform.c, rthomogenize.c, rtin_geojson.c,
-	rtin_twkb.c, rtin_wkb.c, rtin_wkt.c, rtin_wkt_parse.y,
-	rtiterator.c, rtline.c, rtlinearreferencing.c, rtmline.c,
-	rtmpoint.c, rtmpoly.c, rtout_encoded_polyline.c, rtout_geojson.c,
-	rtout_gml.c, rtout_kml.c, rtout_svg.c, rtout_twkb.c, rtout_twkb.h,
-	rtout_wkb.c, rtout_wkt.c, rtout_x3d.c, rtpoint.c, rtpoly.c,
-	rtpsurface.c, rtspheroid.c, rtstroke.c, rttin.c, rttriangle.c: 
-	Prefix geometry type macros with RT
-
-2015-12-09  Sandro Santilli <strk at keybit.net>
-
-	* Makefile.in, configure.ac, rtgeom_sfcgal.c, rtgeom_sfcgal.h: 
-	Remove SFCGAL support
-
-2015-12-01  Sandro Santilli <strk at keybit.net>
-
-	* Initial import
-
diff --git a/HOWTO_RELEASE b/HOWTO_RELEASE
index da92e13..f203112 100644
--- a/HOWTO_RELEASE
+++ b/HOWTO_RELEASE
@@ -1,4 +1,5 @@
 - Set version in configure.ac
+- Tweak -version-info in src/Makefile.am
 - Run make distcheck, fix if needed
 - Commit all of the above
 - Regenerate ChangeLog (make cl) and commit again
diff --git a/Makefile.am b/Makefile.am
index f044fcb..a8c8855 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -3,7 +3,6 @@ ACLOCAL_AMFLAGS = -I m4
 SUBDIRS = src headers
 
 EXTRA_DIST = \
-  ChangeLog \
   CREDITS \
   doc/BUILDING-ON-WINDOWS.md \
   doc/DATASTORES.md \
@@ -17,6 +16,14 @@ AUTOMAKE_OPTIONS = dist-zip foreign
 pkgconfigdir = $(libdir)/pkgconfig
 pkgconfig_DATA = rttopo.pc
 
-cl:
-	cd $(srcdir) && git2cl > ChangeLog
+dist-hook: gen-ChangeLog
+
+gen-ChangeLog:
+	cd $(distdir) && owd=`pwd` && \
+	cd ../ && cd $(srcdir) && \
+  if test -d .git; then \
+    git2cl > $${owd}/ChangeLog; \
+  elif test -f ChangeLog; then \
+    cp ChangeLog $${owd}/ChangeLog; \
+	fi
 
diff --git a/NEWS.md b/NEWS.md
new file mode 100644
index 0000000..952fdd7
--- /dev/null
+++ b/NEWS.md
@@ -0,0 +1,23 @@
+Release 1.1.0-dev
+YYYY-MM-DD
+
+ # Important / Breaking Changes
+
+ - Support for tolerance/precision=0 added, -1 is the new value
+   for automatic computation of minimal tolerance.
+
+ # New Features
+
+ - Function `rtt_AddLineNoFace`, to add lines w/out determining new
+   faces (WARNING: leaves topology in an invalid state)
+
+ - Function `rtt_Polygonize`, to determine all faces generated by
+   existing edges.
+
+ - Function `rtt_tpsnap`, to snap linear components of a geometry
+   to edges of a topology.
+
+Release 1.0.0
+2016-05-19
+
+  Initial release
diff --git a/README.md b/README.md
index 2ba0b8f..ba94315 100644
--- a/README.md
+++ b/README.md
@@ -3,8 +3,10 @@ RT Topology Library
 
 ## Build status
 
-[![Gitlab-CI](https://gitlab.com/rttopo/rttopo/badges/master/build.svg)]
-(https://gitlab.com/rttopo/rttopo/commits/master)
+| OSGeo | GitLab |
+|:---   |:---    |
+| [![Build Status](https://drone.osgeo.kbt.io/api/badges/rttopo/librttopo/status.svg)] (https://drone.osgeo.kbt.io/rttopo/librttopo) | [![Gitlab-CI](https://gitlab.com/rttopo/rttopo/badges/master/build.svg)] (https://gitlab.com/rttopo/rttopo/commits/master) |
+
 
 ## About
 
diff --git a/configure.ac b/configure.ac
index 40fd268..1ba5764 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2,7 +2,7 @@
 # Process this file with autoconf to produce a configure script.
 
 AC_PREREQ(2.61)
-AC_INIT(librttopo, 1.0.0, strk at kbt.io)
+AC_INIT(librttopo, 1.1.0-dev, strk at kbt.io)
 AC_LANG(C)
 AC_CONFIG_MACRO_DIR([m4])
 
diff --git a/docker/build-test/Dockerfile.debian-sid b/docker/build-test/Dockerfile.debian-sid
new file mode 100644
index 0000000..f34230f
--- /dev/null
+++ b/docker/build-test/Dockerfile.debian-sid
@@ -0,0 +1,5 @@
+FROM debian:sid
+RUN apt-get update -qq && apt-get install -y \
+          build-essential autoconf libtool \
+          zip git2cl libgeos-dev
+
diff --git a/docker/build-test/Makefile b/docker/build-test/Makefile
new file mode 100644
index 0000000..5a38780
--- /dev/null
+++ b/docker/build-test/Makefile
@@ -0,0 +1,13 @@
+DOCKER=docker
+REGISTRY=docker.kbt.io
+NAME=$(REGISTRY)/librttopo/build-test
+
+all: debian-sid
+
+push: debian-sid-push
+
+debian-sid:
+	$(DOCKER) build -t $(NAME):debian-sid - < Dockerfile.debian-sid
+
+debian-sid-push:
+	$(DOCKER) push $(NAME):debian-sid
diff --git a/headers/librttopo.h b/headers/librttopo.h
index 4012037..6c77f34 100644
--- a/headers/librttopo.h
+++ b/headers/librttopo.h
@@ -18,7 +18,7 @@
  *
  **********************************************************************
  *
- * Copyright (C) 2015 Sandro Santilli <strk at keybit.net>
+ * Copyright (C) 2015 Sandro Santilli <strk at kbt.io>
  *
  **********************************************************************/
 
@@ -874,9 +874,11 @@ typedef struct RTT_BE_CALLBACKS_T {
  * Ownership to caller delete with rtt_FreeBackendIface
  *
  * @param ctx librtgeom context, create with rtgeom_init
- * @param data Backend data, passed as first parameter to all callback functions
+ * @param data Backend data, passed as first parameter
+ *             to all callback functions
  */
-RTT_BE_IFACE* rtt_CreateBackendIface(const RTCTX* ctx, const RTT_BE_DATA* data);
+RTT_BE_IFACE* rtt_CreateBackendIface(const RTCTX* ctx,
+                                     const RTT_BE_DATA* data);
 
 /**
  * Register backend callbacks into the opaque iface handler
@@ -884,7 +886,8 @@ RTT_BE_IFACE* rtt_CreateBackendIface(const RTCTX* ctx, const RTT_BE_DATA* data);
  * @param iface the backend interface handler (see rtt_CreateBackendIface)
  * @param cb a pointer to the callbacks structure; ownership left to caller.
  */
-void rtt_BackendIfaceRegisterCallbacks(RTT_BE_IFACE* iface, const RTT_BE_CALLBACKS* cb);
+void rtt_BackendIfaceRegisterCallbacks(RTT_BE_IFACE* iface,
+                                       const RTT_BE_CALLBACKS* cb);
 
 /** Release memory associated with an RTT_BE_IFACE */
 void rtt_FreeBackendIface(RTT_BE_IFACE* iface);
@@ -1031,7 +1034,7 @@ RTT_ELEMID rtt_GetFaceByPoint(RTT_TOPOLOGY *topo, RTPOINT *pt, double tol);
  *
  * @param topo the topology to operate on
  * @param point the point to add
- * @param tol snap tolerance, the topology tolerance will be used if 0
+ * @param tol snap tolerance, the topology tolerance will be used if -1
  *
  * @return identifier of added (or pre-existing) node or -1 on error
  *         (librtgeom error handler will be invoked with error message)
@@ -1046,19 +1049,72 @@ RTT_ELEMID rtt_AddPoint(RTT_TOPOLOGY* topo, RTPOINT* point, double tol);
  *
  * @param topo the topology to operate on
  * @param line the line to add
- * @param tol snap tolerance, the topology tolerance will be used if 0
+ * @param tol snap tolerance, the topology tolerance will be used if -1
  * @param nedges output parameter, will be set to number of edges the
  *               line was split into, or -1 on error
  *               (librtgeom error handler will be invoked with error message)
  *
  * @return an array of <nedges> edge identifiers that sewed togheter
  *         will build up the input linestring (after snapping). Caller
- *         will need to free the array using rtfree(const RTCTX *ctx), if not null.
+ *         will need to free the array using rtfree(const RTCTX *ctx),
+ *         if not null.
  */
 RTT_ELEMID* rtt_AddLine(RTT_TOPOLOGY* topo, RTLINE* line, double tol,
                         int* nedges);
 
 /**
+ * Adds a linestring to the topology without determining generated faces
+ *
+ * The given line will snap to existing nodes or edges within given
+ * tolerance. Existing edges or faces may be split by the line.
+ * Side faces for the new edges will not be determined and no new
+ * faces will be created, effectively leaving the topology in an
+ * invalid state (WARNING!)
+ *
+ * @param topo the topology to operate on
+ * @param line the line to add
+ * @param tol snap tolerance, the topology tolerance will be used if -1
+ * @param nedges output parameter, will be set to number of edges the
+ *               line was split into, or -1 on error
+ *               (librtgeom error handler will be invoked with error message)
+ *
+ * @return an array of <nedges> edge identifiers that sewed togheter
+ *         will build up the input linestring (after snapping). Caller
+ *         will need to free the array using rtfree(const RTCTX *ctx),
+ *         if not null.
+ */
+RTT_ELEMID* rtt_AddLineNoFace(RTT_TOPOLOGY* topo, RTLINE* line, double tol,
+                        int* nedges);
+
+/**
+ * Determine and register all topology faces:
+ *
+ *  - Determines which faces are generated by existing
+ *    edges.
+ *  - Creates face records with correct mbr
+ *  - Update edge left/right face attributes
+ *
+ *  Precondition:
+ *     - the topology edges are correctly linked
+ *
+ *  Postconditions:
+ *     - all left/right face attributes of edges
+ *       reference faces with correct mbr.
+ *
+ *  Notes:
+ *     - does not attempt to assign isolated nodes to their
+ *       containing faces
+ *     - does not remove existing face records
+ *     - loads in memory all the topology edges
+ *
+ * @param topo the topology to operate on
+ *
+ * @return 0 on success, -1 on error
+ *         (librtgeom error handler will be invoked with error message)
+ */
+int rtt_Polygonize(RTT_TOPOLOGY* topo);
+
+/**
  * Adds a polygon to the topology
  *
  * The boundary of the given polygon will snap to existing nodes or
@@ -1067,14 +1123,15 @@ RTT_ELEMID* rtt_AddLine(RTT_TOPOLOGY* topo, RTLINE* line, double tol,
  *
  * @param topo the topology to operate on
  * @param poly the polygon to add
- * @param tol snap tolerance, the topology tolerance will be used if 0
+ * @param tol snap tolerance, the topology tolerance will be used if -1
  * @param nfaces output parameter, will be set to number of faces the
  *               polygon was split into, or -1 on error
  *               (librtgeom error handler will be invoked with error message)
  *
  * @return an array of <nfaces> face identifiers that sewed togheter
  *         will build up the input polygon (after snapping). Caller
- *         will need to free the array using rtfree(const RTCTX *ctx), if not null.
+ *         will need to free the array using rtfree(const RTCTX *ctx),
+ *         if not null.
  */
 RTT_ELEMID* rtt_AddPolygon(RTT_TOPOLOGY* topo, RTPOLY* poly, double tol,
                         int* nfaces);
@@ -1276,7 +1333,8 @@ int rtt_ChangeEdgeGeom(RTT_TOPOLOGY* topo, RTT_ELEMID edge, RTLINE* curve);
  *         (librtgeom error handler will be invoked with error message)
  *
  */
-RTT_ELEMID rtt_ModEdgeSplit(RTT_TOPOLOGY* topo, RTT_ELEMID edge, RTPOINT* pt, int skipChecks);
+RTT_ELEMID rtt_ModEdgeSplit(RTT_TOPOLOGY* topo, RTT_ELEMID edge,
+                            RTPOINT* pt, int skipChecks);
 
 /**
  * Split an edge by a node, replacing it with two new edges
@@ -1291,7 +1349,8 @@ RTT_ELEMID rtt_ModEdgeSplit(RTT_TOPOLOGY* topo, RTT_ELEMID edge, RTPOINT* pt, in
  * @return the id of newly created node
  *
  */
-RTT_ELEMID rtt_NewEdgesSplit(RTT_TOPOLOGY* topo, RTT_ELEMID edge, RTPOINT* pt, int skipChecks);
+RTT_ELEMID rtt_NewEdgesSplit(RTT_TOPOLOGY* topo, RTT_ELEMID edge,
+                             RTPOINT* pt, int skipChecks);
 
 /**
  * Merge two edges, modifying the first and deleting the second
@@ -1349,4 +1408,31 @@ int rtt_GetFaceEdges(RTT_TOPOLOGY* topo, RTT_ELEMID face, RTT_ELEMID **edges);
  */
 RTGEOM* rtt_GetFaceGeometry(RTT_TOPOLOGY* topo, RTT_ELEMID face);
 
+/*******************************************************************
+ *
+ * Utility functions
+ *
+ *******************************************************************/
+
+
+/*
+ * rtt_tpsnap - snap geometry to topology
+ *
+ * Uses Trevisani-Peri algorithm version 7 as reported here:
+ * https://git.osgeo.org/gogs/rttopo/librttopo/wiki/SnapToTopo-algorithm
+ *
+ * @param topo the reference topology
+ * @param gin the input geometry
+ * @param tssnap snap tolerance
+ * @param iterate if non zero, allows snapping to more than a single vertex,
+ *                iteratively
+ * @param remove_vertices if non zero, makes an initial pass removing
+ *                        vertices within tolerance
+ *
+ * @return a new geometry, or NULL on error
+ *
+ */
+RTGEOM* rtt_tpsnap(RTT_TOPOLOGY *topo, const RTGEOM *gin,
+                   double tssnap, int iterate, int remove_vertices);
+
 #endif /* LIBRTGEOM_TOPO_H */
diff --git a/headers/librttopo_geom.h.in b/headers/librttopo_geom.h.in
index bf22b0d..d27c32f 100644
--- a/headers/librttopo_geom.h.in
+++ b/headers/librttopo_geom.h.in
@@ -18,7 +18,7 @@
  *
  **********************************************************************
  *
- * Copyright 2011-2016 Sandro Santilli <strk at keybit.net>
+ * Copyright 2011-2016 Sandro Santilli <strk at kbt.io>
  * Copyright 2011 Paul Ramsey <pramsey at cleverelephant.ca>
  * Copyright 2007-2008 Mark Cave-Ayland
  * Copyright 2001-2006 Refractions Research Inc.
@@ -208,18 +208,6 @@ void rtgeom_finish(RTCTX *ctx);
 /** Return rtgeom version string (not to be freed) */
 const char* rtgeom_version(void);
 
-
-/**
-* 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 int clamp_srid(const RTCTX *ctx, int srid);
-
-/* Raise an rterror if srids do not match */
-void error_if_srid_mismatch(const RTCTX *ctx, int srid1, int srid2);
-
 /**
  * This functions are called by programs which want to set up
  * custom handling for error reporting
@@ -269,15 +257,6 @@ typedef struct {
   double afac, bfac, cfac, dfac, efac, ffac, gfac, hfac, ifac, xoff, yoff, zoff;
 } RTAFFINE;
 
-/******************************************************************/
-
-typedef struct
-{
-  double xmin, ymin, zmin;
-  double xmax, ymax, zmax;
-  int32_t srid;
-}
-BOX3D;
 
 /******************************************************************
 * RTGBOX structure.
@@ -1065,20 +1044,6 @@ RTCOLLECTION* rtcollection_extract(const RTCTX *ctx, RTCOLLECTION *col, int type
 */
 extern void rtgeom_set_srid(const RTCTX *ctx, RTGEOM *geom, int 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 RTCTX *ctx, const RTGBOX *gbox);
-extern RTGBOX* box3d_to_gbox(const RTCTX *ctx, const BOX3D *b3d);
-
-void expand_box3d(BOX3D *box, double d);
-
-
 /****************************************************************
  * MEMORY MANAGEMENT
  ****************************************************************/
@@ -1130,7 +1095,6 @@ extern void rtgeom_release(const RTCTX *ctx, RTGEOM *rtgeom);
 * Utility
 ****************************************************************/
 
-extern void printBOX3D(const RTCTX *ctx, BOX3D *b);
 extern void printPA(const RTCTX *ctx, RTPOINTARRAY *pa);
 extern void printRTPOINT(const RTCTX *ctx, RTPOINT *point);
 extern void printRTLINE(const RTCTX *ctx, RTLINE *line);
diff --git a/src/Makefile.am b/src/Makefile.am
index aee70f9..dd4ff3f 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -10,17 +10,21 @@ librttopo_la_SOURCES = box2d.c bytebuffer.c g_box.c \
 	rtcompound.c rtcurvepoly.c rtgeodetic.c \
 	rtgeom_api.c rtgeom.c rtgeom_debug.c rtgeom_geos.c \
 	rtgeom_geos_clean.c rtgeom_geos_node.c rtgeom_geos_split.c \
-	rtgeom_topo.c rthomogenize.c rtin_geojson.c rtin_twkb.c \
+  rtgeom_topo.c rthomogenize.c rtin_geojson.c rtin_twkb.c \
 	rtin_wkb.c rtiterator.c rtlinearreferencing.c rtline.c \
 	rtmcurve.c rtmline.c rtmpoint.c rtmpoly.c rtmsurface.c \
 	rtout_encoded_polyline.c rtout_geojson.c rtout_gml.c \
 	rtout_kml.c rtout_svg.c rtout_twkb.c rtout_wkb.c \
 	rtout_wkt.c rtout_x3d.c rtpoint.c rtpoly.c rtprint.c \
-	rtpsurface.c rtspheroid.c rtstroke.c rttin.c rttree.c \
+	rtpsurface.c rtspheroid.c rtstroke.c \
+	rtt_tpsnap.c \
+  rttin.c rttree.c \
 	rttriangle.c rtutil.c stringbuffer.c varint.c
 
 
-librttopo_la_LDFLAGS = -version-info 1:0:0 -no-undefined
+# Version info is current:revision:age
+# TODO: have this set from configure.ac
+librttopo_la_LDFLAGS = -version-info 2:0:1 -no-undefined
 
 librttopo_la_LIBADD = -lm
 
diff --git a/src/box2d.c b/src/box2d.c
index 3e2b423..4548091 100644
--- a/src/box2d.c
+++ b/src/box2d.c
@@ -18,7 +18,7 @@
  *
  **********************************************************************
  *
- * Copyright (C) 2004-2015 Sandro Santilli <strk at keybit.net>
+ * Copyright (C) 2004-2015 Sandro Santilli <strk at kbt.io>
  * Copyright (C) 2008-2011 Paul Ramsey <pramsey at cleverelephant.ca>
  * Copyright (C) 2008 Mark Cave-Ayland <mark.cave-ayland at siriusit.co.uk>
  *
diff --git a/src/bytebuffer.c b/src/bytebuffer.c
index d4b55a4..2f6e318 100644
--- a/src/bytebuffer.c
+++ b/src/bytebuffer.c
@@ -34,7 +34,7 @@
 bytebuffer_t*
 bytebuffer_create(const RTCTX *ctx)
 {
-  RTDEBUG(2,"Entered bytebuffer_create");
+  RTDEBUG(ctx, 2,"Entered bytebuffer_create");
   return bytebuffer_create_with_size(ctx, BYTEBUFFER_STARTSIZE);
 }
 
@@ -44,7 +44,7 @@ bytebuffer_create(const RTCTX *ctx)
 bytebuffer_t*
 bytebuffer_create_with_size(const RTCTX *ctx, size_t size)
 {
-  RTDEBUGF(2,"Entered bytebuffer_create_with_size %d", size);
+  RTDEBUGF(ctx, 2,"Entered bytebuffer_create_with_size %d", size);
   bytebuffer_t *s;
 
   s = rtalloc(ctx, sizeof(bytebuffer_t));
@@ -52,7 +52,7 @@ bytebuffer_create_with_size(const RTCTX *ctx, size_t size)
   s->readcursor = s->writecursor = s->buf_start;
   s->capacity = size;
   memset(s->buf_start,0,size);
-  RTDEBUGF(4,"We create a buffer on %p of %d bytes", s->buf_start, size);
+  RTDEBUGF(ctx, 4,"We create a buffer on %p of %d bytes", s->buf_start, size);
   return s;
 }
 
@@ -75,19 +75,19 @@ bytebuffer_init_with_size(const RTCTX *ctx, bytebuffer_t *b, size_t size)
 void
 bytebuffer_destroy(const RTCTX *ctx, bytebuffer_t *s)
 {
-  RTDEBUG(2,"Entered bytebuffer_destroy");
-  RTDEBUGF(4,"The buffer has used %d bytes",bytebuffer_getlength(ctx, s));
+  RTDEBUG(ctx, 2,"Entered bytebuffer_destroy");
+  RTDEBUGF(ctx, 4,"The buffer has used %d bytes",bytebuffer_getlength(ctx, s));
 
   if ( s->buf_start )
   {
-    RTDEBUGF(4,"let's free buf_start %p",s->buf_start);
+    RTDEBUGF(ctx, 4,"let's free buf_start %p",s->buf_start);
     rtfree(ctx, s->buf_start);
-    RTDEBUG(4,"buf_start is freed");
+    RTDEBUG(ctx, 4,"buf_start is freed");
   }
   if ( s )
   {
     rtfree(ctx, s);
-    RTDEBUG(4,"bytebuffer_t is freed");
+    RTDEBUG(ctx, 4,"bytebuffer_t is freed");
   }
   return;
 }
@@ -119,18 +119,18 @@ bytebuffer_clear(const RTCTX *ctx, bytebuffer_t *s)
 static inline void
 bytebuffer_makeroom(const RTCTX *ctx, bytebuffer_t *s, size_t size_to_add)
 {
-  RTDEBUGF(2,"Entered bytebuffer_makeroom with space need of %d", size_to_add);
+  RTDEBUGF(ctx, 2,"Entered bytebuffer_makeroom with space need of %d", size_to_add);
   size_t current_write_size = (s->writecursor - s->buf_start);
   size_t capacity = s->capacity;
   size_t required_size = current_write_size + size_to_add;
 
-  RTDEBUGF(2,"capacity = %d and required size = %d",capacity ,required_size);
+  RTDEBUGF(ctx, 2,"capacity = %d and required size = %d",capacity ,required_size);
   while (capacity < required_size)
     capacity *= 2;
 
   if ( capacity > s->capacity )
   {
-    RTDEBUGF(4,"We need to realloc more memory. New capacity is %d", capacity);
+    RTDEBUGF(ctx, 4,"We need to realloc more memory. New capacity is %d", capacity);
     s->buf_start = rtrealloc(ctx, s->buf_start, capacity);
     s->capacity = capacity;
     s->writecursor = s->buf_start + current_write_size;
@@ -145,7 +145,7 @@ bytebuffer_makeroom(const RTCTX *ctx, bytebuffer_t *s, size_t size_to_add)
 void
 bytebuffer_append_byte(const RTCTX *ctx, bytebuffer_t *s, const uint8_t val)
 {
-  RTDEBUGF(2,"Entered bytebuffer_append_byte with value %d", val);
+  RTDEBUGF(ctx, 2,"Entered bytebuffer_append_byte with value %d", val);
   bytebuffer_makeroom(ctx, s, 1);
   *(s->writecursor)=val;
   s->writecursor += 1;
@@ -159,7 +159,7 @@ bytebuffer_append_byte(const RTCTX *ctx, bytebuffer_t *s, const uint8_t val)
 void
 bytebuffer_append_bulk(const RTCTX *ctx, bytebuffer_t *s, void * start, size_t size)
 {
-  RTDEBUGF(2,"bytebuffer_append_bulk with size %d",size);
+  RTDEBUGF(ctx, 2,"bytebuffer_append_bulk with size %d",size);
   bytebuffer_makeroom(ctx, s, size);
   memcpy(s->writecursor, start, size);
   s->writecursor += size;
@@ -172,7 +172,7 @@ bytebuffer_append_bulk(const RTCTX *ctx, bytebuffer_t *s, void * start, size_t s
 void
 bytebuffer_append_bytebuffer(const RTCTX *ctx, bytebuffer_t *write_to,bytebuffer_t *write_from )
 {
-  RTDEBUG(2,"bytebuffer_append_bytebuffer");
+  RTDEBUG(ctx, 2,"bytebuffer_append_bytebuffer");
   size_t size = bytebuffer_getlength(ctx, write_from);
   bytebuffer_makeroom(ctx, write_to, size);
   memcpy(write_to->writecursor, write_from->buf_start, size);
@@ -214,9 +214,9 @@ bytebuffer_append_uvarint(const RTCTX *ctx, bytebuffer_t *b, const uint64_t val)
 void
 bytebuffer_append_int(const RTCTX *ctx, bytebuffer_t *buf, const int val, int swap)
 {
-  RTDEBUGF(2,"Entered bytebuffer_append_int with value %d, swap = %d", val, swap);
+  RTDEBUGF(ctx, 2,"Entered bytebuffer_append_int with value %d, swap = %d", val, swap);
 
-  RTDEBUGF(4,"buf_start = %p and write_cursor=%p", buf->buf_start,buf->writecursor);
+  RTDEBUGF(ctx, 4,"buf_start = %p and write_cursor=%p", buf->buf_start,buf->writecursor);
   char *iptr = (char*)(&val);
   int i = 0;
 
@@ -229,7 +229,7 @@ bytebuffer_append_int(const RTCTX *ctx, bytebuffer_t *buf, const int val, int sw
   /* Machine/request arch mismatch, so flip byte order */
   if ( swap)
   {
-    RTDEBUG(4,"Ok, let's do the swaping thing");
+    RTDEBUG(ctx, 4,"Ok, let's do the swaping thing");
     for ( i = 0; i < RTWKB_INT_SIZE; i++ )
     {
       *(buf->writecursor) = iptr[RTWKB_INT_SIZE - 1 - i];
@@ -239,12 +239,12 @@ bytebuffer_append_int(const RTCTX *ctx, bytebuffer_t *buf, const int val, int sw
   /* If machine arch and requested arch match, don't flip byte order */
   else
   {
-    RTDEBUG(4,"Ok, let's do the memcopying thing");
+    RTDEBUG(ctx, 4,"Ok, let's do the memcopying thing");
     memcpy(buf->writecursor, iptr, RTWKB_INT_SIZE);
     buf->writecursor += RTWKB_INT_SIZE;
   }
 
-  RTDEBUGF(4,"buf_start = %p and write_cursor=%p", buf->buf_start,buf->writecursor);
+  RTDEBUGF(ctx, 4,"buf_start = %p and write_cursor=%p", buf->buf_start,buf->writecursor);
   return;
 
 }
@@ -259,9 +259,9 @@ bytebuffer_append_int(const RTCTX *ctx, bytebuffer_t *buf, const int val, int sw
 void
 bytebuffer_append_double(const RTCTX *ctx, bytebuffer_t *buf, const double val, int swap)
 {
-  RTDEBUGF(2,"Entered bytebuffer_append_double with value %lf swap = %d", val, swap);
+  RTDEBUGF(ctx, 2,"Entered bytebuffer_append_double with value %lf swap = %d", val, swap);
 
-  RTDEBUGF(4,"buf_start = %p and write_cursor=%p", buf->buf_start,buf->writecursor);
+  RTDEBUGF(ctx, 4,"buf_start = %p and write_cursor=%p", buf->buf_start,buf->writecursor);
   char *dptr = (char*)(&val);
   int i = 0;
 
@@ -275,7 +275,7 @@ bytebuffer_append_double(const RTCTX *ctx, bytebuffer_t *buf, const double val,
   /* Machine/request arch mismatch, so flip byte order */
   if ( swap )
   {
-    RTDEBUG(4,"Ok, let's do the swapping thing");
+    RTDEBUG(ctx, 4,"Ok, let's do the swapping thing");
     for ( i = 0; i < RTWKB_DOUBLE_SIZE; i++ )
     {
       *(buf->writecursor) = dptr[RTWKB_DOUBLE_SIZE - 1 - i];
@@ -285,12 +285,12 @@ bytebuffer_append_double(const RTCTX *ctx, bytebuffer_t *buf, const double val,
   /* If machine arch and requested arch match, don't flip byte order */
   else
   {
-    RTDEBUG(4,"Ok, let's do the memcopying thing");
+    RTDEBUG(ctx, 4,"Ok, let's do the memcopying thing");
     memcpy(buf->writecursor, dptr, RTWKB_DOUBLE_SIZE);
     buf->writecursor += RTWKB_DOUBLE_SIZE;
   }
 
-  RTDEBUG(4,"Return from bytebuffer_append_double");
+  RTDEBUG(ctx, 4,"Return from bytebuffer_append_double");
   return;
 
 }
diff --git a/src/g_box.c b/src/g_box.c
index 036d1b4..69e35a7 100644
--- a/src/g_box.c
+++ b/src/g_box.c
@@ -440,7 +440,7 @@ int rt_arc_calculate_gbox_cartesian_2d(const RTCTX *ctx, const RTPOINT2D *A1, co
   int A2_side;
   double radius_A;
 
-  RTDEBUG(2, "rt_arc_calculate_gbox_cartesian_2d called.");
+  RTDEBUG(ctx, 2, "rt_arc_calculate_gbox_cartesian_2d called.");
 
   radius_A = rt_arc_center(ctx, A1, A2, A3, &C);
 
@@ -506,7 +506,7 @@ static int rt_arc_calculate_gbox_cartesian(const RTCTX *ctx, const RTPOINT4D *p1
 {
   int rv;
 
-  RTDEBUG(2, "rt_arc_calculate_gbox_cartesian called.");
+  RTDEBUG(ctx, 2, "rt_arc_calculate_gbox_cartesian called.");
 
   rv = rt_arc_calculate_gbox_cartesian_2d(ctx, (RTPOINT2D*)p1, (RTPOINT2D*)p2, (RTPOINT2D*)p3, gbox);
     gbox->zmin = FP_MIN(p1->z, p3->z);
@@ -529,7 +529,7 @@ int ptarray_calculate_gbox_cartesian(const RTCTX *ctx, const RTPOINTARRAY *pa, R
   has_z = RTFLAGS_GET_Z(pa->flags);
   has_m = RTFLAGS_GET_M(pa->flags);
   gbox->flags = gflags(ctx, has_z, has_m, 0);
-  RTDEBUGF(4, "ptarray_calculate_gbox Z: %d M: %d", has_z, has_m);
+  RTDEBUGF(ctx, 4, "ptarray_calculate_gbox Z: %d M: %d", has_z, has_m);
 
   rt_getPoint4d_p(ctx, pa, 0, &p);
   gbox->xmin = gbox->xmax = p.x;
@@ -655,7 +655,7 @@ static int rtcollection_calculate_gbox_cartesian(const RTCTX *ctx, RTCOLLECTION
 int rtgeom_calculate_gbox_cartesian(const RTCTX *ctx, const RTGEOM *rtgeom, RTGBOX *gbox)
 {
   if ( ! rtgeom ) return RT_FAILURE;
-  RTDEBUGF(4, "rtgeom_calculate_gbox got type (%d) - %s", rtgeom->type, rttype_name(ctx, rtgeom->type));
+  RTDEBUGF(ctx, 4, "rtgeom_calculate_gbox got type (%d) - %s", rtgeom->type, rttype_name(ctx, rtgeom->type));
 
   switch (rtgeom->type)
   {
diff --git a/src/g_serialized.c b/src/g_serialized.c
index 037663b..1d6da56 100644
--- a/src/g_serialized.c
+++ b/src/g_serialized.c
@@ -72,10 +72,10 @@ uint32_t gserialized_get_type(const RTCTX *ctx, const GSERIALIZED *s)
   uint32_t *ptr;
   assert(s);
   ptr = (uint32_t*)(s->data);
-  RTDEBUG(4,"entered");
+  RTDEBUG(ctx, 4,"entered");
   if ( RTFLAGS_GET_BBOX(s->flags) )
   {
-    RTDEBUGF(4,"skipping forward past bbox (%d bytes)",gbox_serialized_size(ctx, s->flags));
+    RTDEBUGF(ctx, 4,"skipping forward past bbox (%d bytes)",gbox_serialized_size(ctx, s->flags));
     ptr += (gbox_serialized_size(ctx, s->flags) / sizeof(uint32_t));
   }
   return *ptr;
@@ -100,7 +100,7 @@ int32_t gserialized_get_srid(const RTCTX *ctx, const GSERIALIZED *s)
 
 void gserialized_set_srid(const RTCTX *ctx, GSERIALIZED *s, int32_t srid)
 {
-  RTDEBUGF(3, "Called with srid = %d", srid);
+  RTDEBUGF(ctx, 3, "Called with srid = %d", srid);
 
   srid = clamp_srid(ctx, srid);
 
@@ -426,7 +426,7 @@ static size_t gserialized_from_rtpoint_size(const RTCTX *ctx, const RTPOINT *poi
   size += 4; /* Number of points (one or zero (empty)). */
   size += point->point->npoints * RTFLAGS_NDIMS(point->flags) * sizeof(double);
 
-  RTDEBUGF(3, "point size = %d", size);
+  RTDEBUGF(ctx, 3, "point size = %d", size);
 
   return size;
 }
@@ -440,7 +440,7 @@ static size_t gserialized_from_rtline_size(const RTCTX *ctx, const RTLINE *line)
   size += 4; /* Number of points (zero => empty). */
   size += line->points->npoints * RTFLAGS_NDIMS(line->flags) * sizeof(double);
 
-  RTDEBUGF(3, "linestring size = %d", size);
+  RTDEBUGF(ctx, 3, "linestring size = %d", size);
 
   return size;
 }
@@ -454,7 +454,7 @@ static size_t gserialized_from_rttriangle_size(const RTCTX *ctx, const RTTRIANGL
   size += 4; /* Number of points (zero => empty). */
   size += triangle->points->npoints * RTFLAGS_NDIMS(triangle->flags) * sizeof(double);
 
-  RTDEBUGF(3, "triangle size = %d", size);
+  RTDEBUGF(ctx, 3, "triangle size = %d", size);
 
   return size;
 }
@@ -476,7 +476,7 @@ static size_t gserialized_from_rtpoly_size(const RTCTX *ctx, const RTPOLY *poly)
     size += poly->rings[i]->npoints * RTFLAGS_NDIMS(poly->flags) * sizeof(double);
   }
 
-  RTDEBUGF(3, "polygon size = %d", size);
+  RTDEBUGF(ctx, 3, "polygon size = %d", size);
 
   return size;
 }
@@ -490,7 +490,7 @@ static size_t gserialized_from_rtcircstring_size(const RTCTX *ctx, const RTCIRCS
   size += 4; /* Number of points (zero => empty). */
   size += curve->points->npoints * RTFLAGS_NDIMS(curve->flags) * sizeof(double);
 
-  RTDEBUGF(3, "circstring size = %d", size);
+  RTDEBUGF(ctx, 3, "circstring size = %d", size);
 
   return size;
 }
@@ -508,17 +508,17 @@ static size_t gserialized_from_rtcollection_size(const RTCTX *ctx, const RTCOLLE
   {
     size_t subsize = gserialized_from_any_size(ctx, col->geoms[i]);
     size += subsize;
-    RTDEBUGF(3, "rtcollection subgeom(%d) size = %d", i, subsize);
+    RTDEBUGF(ctx, 3, "rtcollection subgeom(%d) size = %d", i, subsize);
   }
 
-  RTDEBUGF(3, "rtcollection size = %d", size);
+  RTDEBUGF(ctx, 3, "rtcollection size = %d", size);
 
   return size;
 }
 
 static size_t gserialized_from_any_size(const RTCTX *ctx, const RTGEOM *geom)
 {
-  RTDEBUGF(2, "Input type: %s", rttype_name(ctx, geom->type));
+  RTDEBUGF(ctx, 2, "Input type: %s", rttype_name(ctx, geom->type));
 
   switch (geom->type)
   {
@@ -560,7 +560,7 @@ size_t gserialized_from_rtgeom_size(const RTCTX *ctx, const RTGEOM *geom)
     size += gbox_serialized_size(ctx, geom->flags);
 
   size += gserialized_from_any_size(ctx, geom);
-  RTDEBUGF(3, "g_serialize size = %d", size);
+  RTDEBUGF(ctx, 3, "g_serialize size = %d", size);
 
   return size;
 }
@@ -585,7 +585,7 @@ static size_t gserialized_from_rtpoint(const RTCTX *ctx, const RTPOINT *point, u
   if ( RTFLAGS_GET_ZM(point->flags) != RTFLAGS_GET_ZM(point->point->flags) )
     rterror(ctx, "Dimensions mismatch in rtpoint");
 
-  RTDEBUGF(2, "rtpoint_to_gserialized(%p, %p) called", point, buf);
+  RTDEBUGF(ctx, 2, "rtpoint_to_gserialized(%p, %p) called", point, buf);
 
   loc = buf;
 
@@ -616,7 +616,7 @@ static size_t gserialized_from_rtline(const RTCTX *ctx, const RTLINE *line, uint
   assert(line);
   assert(buf);
 
-  RTDEBUGF(2, "rtline_to_gserialized(%p, %p) called", line, buf);
+  RTDEBUGF(ctx, 2, "rtline_to_gserialized(%p, %p) called", line, buf);
 
   if ( RTFLAGS_GET_Z(line->flags) != RTFLAGS_GET_Z(line->points->flags) )
     rterror(ctx, "Dimensions mismatch in rtline");
@@ -633,7 +633,7 @@ static size_t gserialized_from_rtline(const RTCTX *ctx, const RTLINE *line, uint
   memcpy(loc, &(line->points->npoints), sizeof(uint32_t));
   loc += sizeof(uint32_t);
 
-  RTDEBUGF(3, "rtline_to_gserialized added npoints (%d)", line->points->npoints);
+  RTDEBUGF(ctx, 3, "rtline_to_gserialized added npoints (%d)", line->points->npoints);
 
   /* Copy in the ordinates. */
   if ( line->points->npoints > 0 )
@@ -642,7 +642,7 @@ static size_t gserialized_from_rtline(const RTCTX *ctx, const RTLINE *line, uint
     memcpy(loc, rt_getPoint_internal(ctx, line->points, 0), size);
     loc += size;
   }
-  RTDEBUGF(3, "rtline_to_gserialized copied serialized_pointlist (%d bytes)", ptsize * line->points->npoints);
+  RTDEBUGF(ctx, 3, "rtline_to_gserialized copied serialized_pointlist (%d bytes)", ptsize * line->points->npoints);
 
   return (size_t)(loc - buf);
 }
@@ -657,7 +657,7 @@ static size_t gserialized_from_rtpoly(const RTCTX *ctx, const RTPOLY *poly, uint
   assert(poly);
   assert(buf);
 
-  RTDEBUG(2, "rtpoly_to_gserialized called");
+  RTDEBUG(ctx, 2, "rtpoly_to_gserialized called");
 
   ptsize = sizeof(double) * RTFLAGS_NDIMS(poly->flags);
   loc = buf;
@@ -710,7 +710,7 @@ static size_t gserialized_from_rttriangle(const RTCTX *ctx, const RTTRIANGLE *tr
   assert(triangle);
   assert(buf);
 
-  RTDEBUGF(2, "rttriangle_to_gserialized(%p, %p) called", triangle, buf);
+  RTDEBUGF(ctx, 2, "rttriangle_to_gserialized(%p, %p) called", triangle, buf);
 
   if ( RTFLAGS_GET_ZM(triangle->flags) != RTFLAGS_GET_ZM(triangle->points->flags) )
     rterror(ctx, "Dimensions mismatch in rttriangle");
@@ -727,7 +727,7 @@ static size_t gserialized_from_rttriangle(const RTCTX *ctx, const RTTRIANGLE *tr
   memcpy(loc, &(triangle->points->npoints), sizeof(uint32_t));
   loc += sizeof(uint32_t);
 
-  RTDEBUGF(3, "rttriangle_to_gserialized added npoints (%d)", triangle->points->npoints);
+  RTDEBUGF(ctx, 3, "rttriangle_to_gserialized added npoints (%d)", triangle->points->npoints);
 
   /* Copy in the ordinates. */
   if ( triangle->points->npoints > 0 )
@@ -736,7 +736,7 @@ static size_t gserialized_from_rttriangle(const RTCTX *ctx, const RTTRIANGLE *tr
     memcpy(loc, rt_getPoint_internal(ctx, triangle->points, 0), size);
     loc += size;
   }
-  RTDEBUGF(3, "rttriangle_to_gserialized copied serialized_pointlist (%d bytes)", ptsize * triangle->points->npoints);
+  RTDEBUGF(ctx, 3, "rttriangle_to_gserialized copied serialized_pointlist (%d bytes)", ptsize * triangle->points->npoints);
 
   return (size_t)(loc - buf);
 }
@@ -815,10 +815,10 @@ static size_t gserialized_from_rtgeom_any(const RTCTX *ctx, const RTGEOM *geom,
   assert(geom);
   assert(buf);
 
-  RTDEBUGF(2, "Input type (%d) %s, hasz: %d hasm: %d",
+  RTDEBUGF(ctx, 2, "Input type (%d) %s, hasz: %d hasm: %d",
     geom->type, rttype_name(ctx, geom->type),
     RTFLAGS_GET_Z(geom->flags), RTFLAGS_GET_M(geom->flags));
-  RTDEBUGF(2, "RTGEOM(%p) uint8_t(%p)", geom, buf);
+  RTDEBUGF(ctx, 2, "RTGEOM(%p) uint8_t(%p)", geom, buf);
 
   switch (geom->type)
   {
@@ -885,7 +885,7 @@ static size_t gserialized_from_gbox(const RTCTX *ctx, const RTGBOX *gbox, uint8_
     loc += sizeof(float);
 
     return_size = (size_t)(loc - buf);
-    RTDEBUGF(4, "returning size %d", return_size);
+    RTDEBUGF(ctx, 4, "returning size %d", return_size);
     return return_size;
   }
 
@@ -912,7 +912,7 @@ static size_t gserialized_from_gbox(const RTCTX *ctx, const RTGBOX *gbox, uint8_
     loc += sizeof(float);
   }
   return_size = (size_t)(loc - buf);
-  RTDEBUGF(4, "returning size %d", return_size);
+  RTDEBUGF(ctx, 4, "returning size %d", return_size);
   return return_size;
 }
 
@@ -1072,7 +1072,7 @@ static RTPOLY* rtpoly_from_gserialized_buffer(const RTCTX *ctx, uint8_t *data_pt
   data_ptr += 4; /* Skip past the polygontype. */
   nrings = rt_get_uint32_t(ctx, data_ptr); /* Zero => empty geometry */
   poly->nrings = nrings;
-  RTDEBUGF(4, "nrings = %d", nrings);
+  RTDEBUGF(ctx, 4, "nrings = %d", nrings);
   data_ptr += 4; /* Skip past the nrings. */
 
   ordinate_ptr = data_ptr; /* Start the ordinate pointer. */
@@ -1230,7 +1230,7 @@ RTGEOM* rtgeom_from_gserialized_buffer(const RTCTX *ctx, uint8_t *data_ptr, uint
 
   type = rt_get_uint32_t(ctx, data_ptr);
 
-  RTDEBUGF(2, "Got type %d (%s), hasz=%d hasm=%d geodetic=%d hasbox=%d", type, rttype_name(ctx, type),
+  RTDEBUGF(ctx, 2, "Got type %d (%s), hasz=%d hasm=%d geodetic=%d hasbox=%d", type, rttype_name(ctx, type),
     RTFLAGS_GET_Z(g_flags), RTFLAGS_GET_M(g_flags), RTFLAGS_GET_GEODETIC(g_flags), RTFLAGS_GET_BBOX(g_flags));
 
   switch (type)
@@ -1277,7 +1277,7 @@ RTGEOM* rtgeom_from_gserialized(const RTCTX *ctx, const GSERIALIZED *g)
   g_srid = gserialized_get_srid(ctx, g);
   g_flags = g->flags;
   g_type = gserialized_get_type(ctx, g);
-  RTDEBUGF(4, "Got type %d (%s), srid=%d", g_type, rttype_name(ctx, g_type), g_srid);
+  RTDEBUGF(ctx, 4, "Got type %d (%s), srid=%d", g_type, rttype_name(ctx, g_type), g_srid);
 
   data_ptr = (uint8_t*)g->data;
   if ( RTFLAGS_GET_BBOX(g_flags) )
diff --git a/src/librttopo_geom_internal.h b/src/librttopo_geom_internal.h
index fd14d39..6e44182 100644
--- a/src/librttopo_geom_internal.h
+++ b/src/librttopo_geom_internal.h
@@ -18,7 +18,7 @@
  *
  **********************************************************************
  *
- * Copyright (C) 2011-2012 Sandro Santilli <strk at keybit.net>
+ * Copyright (C) 2011-2012 Sandro Santilli <strk at kbt.io>
  * Copyright (C) 2011 Paul Ramsey <pramsey at cleverelephant.ca>
  * Copyright (C) 2007-2008 Mark Cave-Ayland
  * Copyright (C) 2001-2006 Refractions Research Inc.
@@ -175,6 +175,14 @@ struct RTCTX_T {
   void * debug_logger_arg;
 };
 
+typedef struct
+{
+  double xmin, ymin, zmin;
+  double xmax, ymax, zmax;
+  int32_t srid;
+}
+BOX3D;
+
 /*
 * Internal prototypes
 */
@@ -456,6 +464,18 @@ int ptarrayarc_contains_point_partial(const RTCTX *ctx, const RTPOINTARRAY *pa,
 int rtcompound_contains_point(const RTCTX *ctx, const RTCOMPOUND *comp, const RTPOINT2D *pt);
 int rtgeom_contains_point(const RTCTX *ctx, const RTGEOM *geom, const RTPOINT2D *pt);
 
+
+/**
+* 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 int clamp_srid(const RTCTX *ctx, int srid);
+
+/* Raise an rterror if srids do not match */
+void error_if_srid_mismatch(const RTCTX *ctx, int srid1, int srid2);
+
 /**
 * Split a line by a point and push components to the provided multiline.
 * If the point doesn't split the line, push nothing to the container.
@@ -500,5 +520,21 @@ extern int _rtgeom_interrupt_requested;
 int ptarray_npoints_in_rect(const RTCTX *ctx, const RTPOINTARRAY *pa, const RTGBOX *gbox);
 int gbox_contains_point2d(const RTCTX *ctx, const RTGBOX *g, const RTPOINT2D *p);
 int rtpoly_contains_point(const RTCTX *ctx, const RTPOLY *poly, const RTPOINT2D *pt);
+double distance2d_pt_seg(const RTCTX *ctx, const RTPOINT2D *p, const RTPOINT2D *A, const RTPOINT2D *B);
+
+/*------------------------------------------------------
+ * 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 RTCTX *ctx, const RTGBOX *gbox);
+extern RTGBOX* box3d_to_gbox(const RTCTX *ctx, const BOX3D *b3d);
+void expand_box3d(BOX3D *box, double d);
+extern void printBOX3D(const RTCTX *ctx, BOX3D *b);
+
+
 
 #endif /* _LIBRTGEOM_INTERNAL_H */
diff --git a/src/librttopo_internal.h b/src/librttopo_internal.h
index 033f2c0..82dd854 100644
--- a/src/librttopo_internal.h
+++ b/src/librttopo_internal.h
@@ -18,7 +18,7 @@
  *
  **********************************************************************
  *
- * Copyright (C) 2015 Sandro Santilli <strk at keybit.net>
+ * Copyright (C) 2015 Sandro Santilli <strk at kbt.io>
  *
  **********************************************************************/
 
@@ -94,4 +94,24 @@ struct RTT_TOPOLOGY_T
   int hasZ;
 };
 
+/************************************************************************
+ *
+ * Backend interaction wrappers
+ *
+ ************************************************************************/
+
+RTT_ISO_EDGE*
+rtt_be_getEdgeWithinBox2D( const RTT_TOPOLOGY* topo,
+                           const RTGBOX* box, int* numelems, int fields,
+                           int limit );
+
+/************************************************************************
+ *
+ * Utility functions
+ *
+ ************************************************************************/
+
+void
+rtt_release_edges(const RTCTX *ctx, RTT_ISO_EDGE *edges, int num_edges);
+
 #endif /* LIBRTGEOM_TOPO_INTERNAL_H */
diff --git a/src/measures.c b/src/measures.c
index e6766ce..7176084 100644
--- a/src/measures.c
+++ b/src/measures.c
@@ -95,7 +95,7 @@ rt_dist2d_distanceline(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM *rt2, i
   thedl.distance = initdistance;
   thedl.tolerance = 0.0;
 
-  RTDEBUG(2, "rt_dist2d_distanceline is called");
+  RTDEBUG(ctx, 2, "rt_dist2d_distanceline is called");
 
   if (!rt_dist2d_comp(ctx,  rt1,rt2,&thedl))
   {
@@ -107,7 +107,7 @@ rt_dist2d_distanceline(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM *rt2, i
   /*if thedl.distance is unchanged there where only empty geometries input*/
   if (thedl.distance == initdistance)
   {
-    RTDEBUG(3, "didn't find geometries to measure between, returning null");
+    RTDEBUG(ctx, 3, "didn't find geometries to measure between, returning null");
     result = (RTGEOM *)rtcollection_construct_empty(ctx, RTCOLLECTIONTYPE, srid, 0, 0);
   }
   else
@@ -140,7 +140,7 @@ rt_dist2d_distancepoint(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM *rt2,i
   thedl.distance= initdistance;
   thedl.tolerance = 0;
 
-  RTDEBUG(2, "rt_dist2d_distancepoint is called");
+  RTDEBUG(ctx, 2, "rt_dist2d_distancepoint is called");
 
   if (!rt_dist2d_comp(ctx,  rt1,rt2,&thedl))
   {
@@ -150,7 +150,7 @@ rt_dist2d_distancepoint(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM *rt2,i
   }
   if (thedl.distance == initdistance)
   {
-    RTDEBUG(3, "didn't find geometries to measure between, returning null");
+    RTDEBUG(ctx, 3, "didn't find geometries to measure between, returning null");
     result = (RTGEOM *)rtcollection_construct_empty(ctx, RTCOLLECTIONTYPE, srid, 0, 0);
   }
   else
@@ -169,7 +169,7 @@ Function initialazing max distance calculation
 double
 rtgeom_maxdistance2d(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM *rt2)
 {
-  RTDEBUG(2, "rtgeom_maxdistance2d is called");
+  RTDEBUG(ctx, 2, "rtgeom_maxdistance2d is called");
 
   return rtgeom_maxdistance2d_tolerance(ctx,  rt1, rt2, 0.0 );
 }
@@ -183,7 +183,7 @@ rtgeom_maxdistance2d_tolerance(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM
 {
   /*double thedist;*/
   DISTPTS thedl;
-  RTDEBUG(2, "rtgeom_maxdistance2d_tolerance is called");
+  RTDEBUG(ctx, 2, "rtgeom_maxdistance2d_tolerance is called");
   thedl.mode = DIST_MAX;
   thedl.distance= -1;
   thedl.tolerance = tolerance;
@@ -202,7 +202,7 @@ rtgeom_maxdistance2d_tolerance(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM
 double
 rtgeom_mindistance2d(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM *rt2)
 {
-  RTDEBUG(2, "rtgeom_mindistance2d is called");
+  RTDEBUG(ctx, 2, "rtgeom_mindistance2d is called");
   return rtgeom_mindistance2d_tolerance(ctx,  rt1, rt2, 0.0 );
 }
 
@@ -214,7 +214,7 @@ double
 rtgeom_mindistance2d_tolerance(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM *rt2, double tolerance)
 {
   DISTPTS thedl;
-  RTDEBUG(2, "rtgeom_mindistance2d_tolerance is called");
+  RTDEBUG(ctx, 2, "rtgeom_mindistance2d_tolerance is called");
   thedl.mode = DIST_MIN;
   thedl.distance= FLT_MAX;
   thedl.tolerance = tolerance;
@@ -245,7 +245,7 @@ Functions preparing geometries for distance-calculations
 int
 rt_dist2d_comp(const RTCTX *ctx, const RTGEOM *rt1,const RTGEOM *rt2, DISTPTS *dl)
 {
-  RTDEBUG(2, "rt_dist2d_comp is called");
+  RTDEBUG(ctx, 2, "rt_dist2d_comp is called");
 
   return rt_dist2d_recursive(ctx, rt1, rt2, dl);
 }
@@ -285,17 +285,17 @@ int rt_dist2d_recursive(const RTCTX *ctx, const RTGEOM *rtg1, const RTGEOM *rtg2
   RTCOLLECTION *c1 = NULL;
   RTCOLLECTION *c2 = NULL;
 
-  RTDEBUGF(2, "rt_dist2d_comp is called with type1=%d, type2=%d", rtg1->type, rtg2->type);
+  RTDEBUGF(ctx, 2, "rt_dist2d_comp is called with type1=%d, type2=%d", rtg1->type, rtg2->type);
 
   if (rt_dist2d_is_collection(ctx, rtg1))
   {
-    RTDEBUG(3, "First geometry is collection");
+    RTDEBUG(ctx, 3, "First geometry is collection");
     c1 = rtgeom_as_rtcollection(ctx, rtg1);
     n1 = c1->ngeoms;
   }
   if (rt_dist2d_is_collection(ctx, rtg2))
   {
-    RTDEBUG(3, "Second geometry is collection");
+    RTDEBUG(ctx, 3, "Second geometry is collection");
     c2 = rtgeom_as_rtcollection(ctx, rtg2);
     n2 = c2->ngeoms;
   }
@@ -316,7 +316,7 @@ int rt_dist2d_recursive(const RTCTX *ctx, const RTGEOM *rtg1, const RTGEOM *rtg2
 
     if (rt_dist2d_is_collection(ctx, g1))
     {
-      RTDEBUG(3, "Found collection inside first geometry collection, recursing");
+      RTDEBUG(ctx, 3, "Found collection inside first geometry collection, recursing");
       if (!rt_dist2d_recursive(ctx, g1, rtg2, dl)) return RT_FALSE;
       continue;
     }
@@ -332,7 +332,7 @@ int rt_dist2d_recursive(const RTCTX *ctx, const RTGEOM *rtg1, const RTGEOM *rtg2
       }
       if (rt_dist2d_is_collection(ctx, g2))
       {
-        RTDEBUG(3, "Found collection inside second geometry collection, recursing");
+        RTDEBUG(ctx, 3, "Found collection inside second geometry collection, recursing");
         if (!rt_dist2d_recursive(ctx, g1, g2, dl)) return RT_FALSE;
         continue;
       }
@@ -498,7 +498,7 @@ We have to check for overlapping bboxes
 int
 rt_dist2d_check_overlap(const RTCTX *ctx, RTGEOM *rtg1,RTGEOM *rtg2)
 {
-  RTDEBUG(2, "rt_dist2d_check_overlap is called");
+  RTDEBUG(ctx, 2, "rt_dist2d_check_overlap is called");
   if ( ! rtg1->bbox )
     rtgeom_calculate_gbox(ctx, rtg1, rtg1->bbox);
   if ( ! rtg2->bbox )
@@ -508,10 +508,10 @@ rt_dist2d_check_overlap(const RTCTX *ctx, RTGEOM *rtg1,RTGEOM *rtg2)
   */
   if ((rtg1->bbox->xmax<rtg2->bbox->xmin||rtg1->bbox->xmin>rtg2->bbox->xmax||rtg1->bbox->ymax<rtg2->bbox->ymin||rtg1->bbox->ymin>rtg2->bbox->ymax))
   {
-    RTDEBUG(3, "geometries bboxes did not overlap");
+    RTDEBUG(ctx, 3, "geometries bboxes did not overlap");
     return RT_FALSE;
   }
-  RTDEBUG(3, "geometries bboxes overlap");
+  RTDEBUG(ctx, 3, "geometries bboxes overlap");
   return RT_TRUE;
 }
 
@@ -526,7 +526,7 @@ rt_dist2d_distribute_fast(const RTCTX *ctx, RTGEOM *rtg1, RTGEOM *rtg2, DISTPTS
   int  type1 = rtg1->type;
   int  type2 = rtg2->type;
 
-  RTDEBUGF(2, "rt_dist2d_distribute_fast is called with typ1=%d, type2=%d", rtg1->type, rtg2->type);
+  RTDEBUGF(ctx, 2, "rt_dist2d_distribute_fast is called with typ1=%d, type2=%d", rtg1->type, rtg2->type);
 
   switch (type1)
   {
@@ -590,7 +590,7 @@ int
 rt_dist2d_point_line(const RTCTX *ctx, RTPOINT *point, RTLINE *line, DISTPTS *dl)
 {
   const RTPOINT2D *p;
-  RTDEBUG(2, "rt_dist2d_point_line is called");
+  RTDEBUG(ctx, 2, "rt_dist2d_point_line is called");
   p = rt_getPoint2d_cp(ctx, point->point, 0);
   return rt_dist2d_pt_ptarray(ctx, p, line->points, dl);
 }
@@ -614,19 +614,19 @@ rt_dist2d_point_poly(const RTCTX *ctx, RTPOINT *point, RTPOLY *poly, DISTPTS *dl
   const RTPOINT2D *p;
   int i;
 
-  RTDEBUG(2, "rt_dist2d_point_poly called");
+  RTDEBUG(ctx, 2, "rt_dist2d_point_poly called");
 
   p = rt_getPoint2d_cp(ctx, point->point, 0);
 
   if (dl->mode == DIST_MAX)
   {
-    RTDEBUG(3, "looking for maxdistance");
+    RTDEBUG(ctx, 3, "looking for maxdistance");
     return rt_dist2d_pt_ptarray(ctx, p, poly->rings[0], dl);
   }
   /* Return distance to outer ring if not inside it */
   if ( ptarray_contains_point(ctx, poly->rings[0], p) == RT_OUTSIDE )
   {
-    RTDEBUG(3, "first point not inside outer-ring");
+    RTDEBUG(ctx, 3, "first point not inside outer-ring");
     return rt_dist2d_pt_ptarray(ctx, p, poly->rings[0], dl);
   }
 
@@ -641,12 +641,12 @@ rt_dist2d_point_poly(const RTCTX *ctx, RTPOINT *point, RTPOLY *poly, DISTPTS *dl
     /* Inside a hole. Distance = pt -> ring */
     if ( ptarray_contains_point(ctx, poly->rings[i], p) != RT_OUTSIDE )
     {
-      RTDEBUG(3, " inside an hole");
+      RTDEBUG(ctx, 3, " inside an hole");
       return rt_dist2d_pt_ptarray(ctx, p, poly->rings[i], dl);
     }
   }
 
-  RTDEBUG(3, " inside the polygon");
+  RTDEBUG(ctx, 3, " inside the polygon");
   if (dl->mode == DIST_MIN)
   {
     dl->distance = 0.0;
@@ -684,12 +684,12 @@ rt_dist2d_point_curvepoly(const RTCTX *ctx, RTPOINT *point, RTCURVEPOLY *poly, D
     /* Inside a hole. Distance = pt -> ring */
     if ( rtgeom_contains_point(ctx, poly->rings[i], p) != RT_OUTSIDE )
     {
-      RTDEBUG(3, " inside a hole");
+      RTDEBUG(ctx, 3, " inside a hole");
       return rt_dist2d_recursive(ctx, (RTGEOM*)point, poly->rings[i], dl);
     }
   }
 
-  RTDEBUG(3, " inside the polygon");
+  RTDEBUG(ctx, 3, " inside the polygon");
   if (dl->mode == DIST_MIN)
   {
     dl->distance = 0.0;
@@ -709,7 +709,7 @@ rt_dist2d_line_line(const RTCTX *ctx, RTLINE *line1, RTLINE *line2, DISTPTS *dl)
 {
   RTPOINTARRAY *pa1 = line1->points;
   RTPOINTARRAY *pa2 = line2->points;
-  RTDEBUG(2, "rt_dist2d_line_line is called");
+  RTDEBUG(ctx, 2, "rt_dist2d_line_line is called");
   return rt_dist2d_ptarray_ptarray(ctx, pa1, pa2, dl);
 }
 
@@ -736,7 +736,7 @@ rt_dist2d_line_poly(const RTCTX *ctx, RTLINE *line, RTPOLY *poly, DISTPTS *dl)
   const RTPOINT2D *pt;
   int i;
 
-  RTDEBUGF(2, "rt_dist2d_line_poly called (%d rings)", poly->nrings);
+  RTDEBUGF(ctx, 2, "rt_dist2d_line_poly called (%d rings)", poly->nrings);
 
   pt = rt_getPoint2d_cp(ctx, line->points, 0);
   if ( ptarray_contains_point(ctx, poly->rings[0], pt) == RT_OUTSIDE )
@@ -748,7 +748,7 @@ rt_dist2d_line_poly(const RTCTX *ctx, RTLINE *line, RTPOLY *poly, DISTPTS *dl)
   {
     if (!rt_dist2d_ptarray_ptarray(ctx, line->points, poly->rings[i], dl)) return RT_FALSE;
 
-    RTDEBUGF(3, " distance from ring %d: %f, mindist: %f",
+    RTDEBUGF(ctx, 3, " distance from ring %d: %f, mindist: %f",
              i, dl->distance, dl->tolerance);
     /* just a check if  the answer is already given */
     if (dl->distance<=dl->tolerance && dl->mode == DIST_MIN) return RT_TRUE;
@@ -847,7 +847,7 @@ rt_dist2d_poly_poly(const RTCTX *ctx, RTPOLY *poly1, RTPOLY *poly2, DISTPTS *dl)
   const RTPOINT2D *pt;
   int i;
 
-  RTDEBUG(2, "rt_dist2d_poly_poly called");
+  RTDEBUG(ctx, 2, "rt_dist2d_poly_poly called");
 
   /*1  if we are looking for maxdistance, just check the outer rings.*/
   if (dl->mode == DIST_MAX)
@@ -973,7 +973,7 @@ rt_dist2d_curvepoly_curvepoly(const RTCTX *ctx, RTCURVEPOLY *poly1, RTCURVEPOLY
   const RTPOINT2D *pt;
   int i;
 
-  RTDEBUG(2, "rt_dist2d_curvepoly_curvepoly called");
+  RTDEBUG(ctx, 2, "rt_dist2d_curvepoly_curvepoly called");
 
   /*1  if we are looking for maxdistance, just check the outer rings.*/
   if (dl->mode == DIST_MAX)
@@ -1053,7 +1053,7 @@ rt_dist2d_pt_ptarray(const RTCTX *ctx, const RTPOINT2D *p, RTPOINTARRAY *pa,DIST
   const RTPOINT2D *start, *end;
   int twist = dl->twisted;
 
-  RTDEBUG(2, "rt_dist2d_pt_ptarray is called");
+  RTDEBUG(ctx, 2, "rt_dist2d_pt_ptarray is called");
 
   start = rt_getPoint2d_cp(ctx, pa, 0);
 
@@ -1085,7 +1085,7 @@ rt_dist2d_pt_ptarrayarc(const RTCTX *ctx, const RTPOINT2D *p, const RTPOINTARRAY
   const RTPOINT2D *A3;
   int twist = dl->twisted;
 
-  RTDEBUG(2, "rt_dist2d_pt_ptarrayarc is called");
+  RTDEBUG(ctx, 2, "rt_dist2d_pt_ptarrayarc is called");
 
   if ( pa->npoints % 2 == 0 || pa->npoints < 3 )
   {
@@ -1136,7 +1136,7 @@ rt_dist2d_ptarray_ptarray(const RTCTX *ctx, RTPOINTARRAY *l1, RTPOINTARRAY *l2,D
   const RTPOINT2D  *start2, *end2;
   int twist = dl->twisted;
 
-  RTDEBUGF(2, "rt_dist2d_ptarray_ptarray called (points: %d-%d)",l1->npoints, l2->npoints);
+  RTDEBUGF(ctx, 2, "rt_dist2d_ptarray_ptarray called (points: %d-%d)",l1->npoints, l2->npoints);
 
   if (dl->mode == DIST_MAX)/*If we are searching for maxdistance we go straight to point-point calculation since the maxdistance have to be between two vertexes*/
   {
@@ -1147,8 +1147,8 @@ rt_dist2d_ptarray_ptarray(const RTCTX *ctx, RTPOINTARRAY *l1, RTPOINTARRAY *l2,D
       {
         start2 = rt_getPoint2d_cp(ctx, l2, u);
         rt_dist2d_pt_pt(ctx, start, start2, dl);
-        RTDEBUGF(4, "maxdist_ptarray_ptarray; seg %i * seg %i, dist = %g\n",t,u,dl->distance);
-        RTDEBUGF(3, " seg%d-seg%d dist: %f, mindist: %f",
+        RTDEBUGF(ctx, 4, "maxdist_ptarray_ptarray; seg %i * seg %i, dist = %g\n",t,u,dl->distance);
+        RTDEBUGF(ctx, 3, " seg%d-seg%d dist: %f, mindist: %f",
                  t, u, dl->distance, dl->tolerance);
       }
     }
@@ -1165,8 +1165,8 @@ rt_dist2d_ptarray_ptarray(const RTCTX *ctx, RTPOINTARRAY *l1, RTPOINTARRAY *l2,D
         end2 = rt_getPoint2d_cp(ctx, l2, u);
         dl->twisted=twist;
         rt_dist2d_seg_seg(ctx, start, end, start2, end2, dl);
-        RTDEBUGF(4, "mindist_ptarray_ptarray; seg %i * seg %i, dist = %g\n",t,u,dl->distance);
-        RTDEBUGF(3, " seg%d-seg%d dist: %f, mindist: %f",
+        RTDEBUGF(ctx, 4, "mindist_ptarray_ptarray; seg %i * seg %i, dist = %g\n",t,u,dl->distance);
+        RTDEBUGF(ctx, 3, " seg%d-seg%d dist: %f, mindist: %f",
                  t, u, dl->distance, dl->tolerance);
         if (dl->distance<=dl->tolerance && dl->mode == DIST_MIN) return RT_TRUE; /*just a check if  the answer is already given*/
         start2 = end2;
@@ -1191,7 +1191,7 @@ rt_dist2d_ptarray_ptarrayarc(const RTCTX *ctx, const RTPOINTARRAY *pa, const RTP
   const RTPOINT2D *B3;
   int twist = dl->twisted;
 
-  RTDEBUGF(2, "rt_dist2d_ptarray_ptarrayarc called (points: %d-%d)",pa->npoints, pb->npoints);
+  RTDEBUGF(ctx, 2, "rt_dist2d_ptarray_ptarrayarc called (points: %d-%d)",pa->npoints, pb->npoints);
 
   if ( pb->npoints % 2 == 0 || pb->npoints < 3 )
   {
@@ -1246,7 +1246,7 @@ rt_dist2d_ptarrayarc_ptarrayarc(const RTCTX *ctx, const RTPOINTARRAY *pa, const
   const RTPOINT2D *B3;
   int twist = dl->twisted;
 
-  RTDEBUGF(2, "rt_dist2d_ptarrayarc_ptarrayarc called (points: %d-%d)",pa->npoints, pb->npoints);
+  RTDEBUGF(ctx, 2, "rt_dist2d_ptarrayarc_ptarrayarc called (points: %d-%d)",pa->npoints, pb->npoints);
 
   if (dl->mode == DIST_MAX)
   {
@@ -1667,7 +1667,7 @@ rt_dist2d_seg_seg(const RTCTX *ctx, const RTPOINT2D *A, const RTPOINT2D *B, cons
   double  s_top, s_bot,s;
   double  r_top, r_bot,r;
 
-  RTDEBUGF(2, "rt_dist2d_seg_seg [%g,%g]->[%g,%g] by [%g,%g]->[%g,%g]",
+  RTDEBUGF(ctx, 2, "rt_dist2d_seg_seg [%g,%g]->[%g,%g] by [%g,%g]->[%g,%g]",
            A->x,A->y,B->x,B->y, C->x,C->y, D->x, D->y);
 
   /*A and B are the same point */
@@ -1805,7 +1805,7 @@ rt_dist2d_fast_ptarray_ptarray(const RTCTX *ctx, RTPOINTARRAY *l1, RTPOINTARRAY
   list1 = (LISTSTRUCT*)rtalloc(ctx, sizeof(LISTSTRUCT)*n1);
   list2 = (LISTSTRUCT*)rtalloc(ctx, sizeof(LISTSTRUCT)*n2);
 
-  RTDEBUG(2, "rt_dist2d_fast_ptarray_ptarray is called");
+  RTDEBUG(ctx, 2, "rt_dist2d_fast_ptarray_ptarray is called");
 
   max1X = box1->xmax;
   min1X = box1->xmin;
@@ -1924,7 +1924,7 @@ rt_dist2d_pre_seg_seg(const RTCTX *ctx, RTPOINTARRAY *l1, RTPOINTARRAY *l2,LISTS
   n1=  l1->npoints;
   n2 = l2->npoints;
 
-  RTDEBUG(2, "rt_dist2d_pre_seg_seg is called");
+  RTDEBUG(ctx, 2, "rt_dist2d_pre_seg_seg is called");
 
   p1 = rt_getPoint2d_cp(ctx, l1, list1[0].pnr);
   p3 = rt_getPoint2d_cp(ctx, l2, list2[0].pnr);
@@ -2005,7 +2005,7 @@ rt_dist2d_pre_seg_seg(const RTCTX *ctx, RTPOINTARRAY *l1, RTPOINTARRAY *l2,LISTS
 int
 rt_dist2d_selected_seg_seg(const RTCTX *ctx, const RTPOINT2D *A, const RTPOINT2D *B, const RTPOINT2D *C, const RTPOINT2D *D, DISTPTS *dl)
 {
-  RTDEBUGF(2, "rt_dist2d_selected_seg_seg [%g,%g]->[%g,%g] by [%g,%g]->[%g,%g]",
+  RTDEBUGF(ctx, 2, "rt_dist2d_selected_seg_seg [%g,%g]->[%g,%g] by [%g,%g]->[%g,%g]",
            A->x,A->y,B->x,B->y, C->x,C->y, D->x, D->y);
 
   /*A and B are the same point */
diff --git a/src/measures3d.c b/src/measures3d.c
index f432f88..550624d 100644
--- a/src/measures3d.c
+++ b/src/measures3d.c
@@ -111,7 +111,7 @@ Function initializing 3dshortestline and 3dlongestline calculations.
 RTGEOM *
 rt_dist3d_distanceline(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM *rt2, int srid, int mode)
 {
-  RTDEBUG(2, "rt_dist3d_distanceline is called");
+  RTDEBUG(ctx, 2, "rt_dist3d_distanceline is called");
   double x1,x2,y1,y2, z1, z2, x, y;
   double initdistance = ( mode == DIST_MIN ? FLT_MAX : -1.0);
   DISTPTS3D thedl;
@@ -188,7 +188,7 @@ rt_dist3d_distanceline(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM *rt2, i
   /*if thedl.distance is unchanged there where only empty geometries input*/
   if (thedl.distance == initdistance)
   {
-    RTDEBUG(3, "didn't find geometries to measure between, returning null");
+    RTDEBUG(ctx, 3, "didn't find geometries to measure between, returning null");
     result = (RTGEOM *)rtcollection_construct_empty(ctx, RTCOLLECTIONTYPE, srid, 0, 0);
   }
   else
@@ -225,7 +225,7 @@ rt_dist3d_distancepoint(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM *rt2,
   thedl.distance= initdistance;
   thedl.tolerance = 0;
 
-  RTDEBUG(2, "rt_dist3d_distancepoint is called");
+  RTDEBUG(ctx, 2, "rt_dist3d_distancepoint is called");
 
   /*Check if we really have 3D geoemtries*/
   /*If not, send it to 2D-calculations which will give the same result*/
@@ -294,7 +294,7 @@ rt_dist3d_distancepoint(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM *rt2,
   }
   if (thedl.distance == initdistance)
   {
-    RTDEBUG(3, "didn't find geometries to measure between, returning null");
+    RTDEBUG(ctx, 3, "didn't find geometries to measure between, returning null");
     result = (RTGEOM *)rtcollection_construct_empty(ctx, RTCOLLECTIONTYPE, srid, 0, 0);
   }
   else
@@ -315,7 +315,7 @@ Function initializing 3d max distance calculation
 double
 rtgeom_maxdistance3d(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM *rt2)
 {
-  RTDEBUG(2, "rtgeom_maxdistance3d is called");
+  RTDEBUG(ctx, 2, "rtgeom_maxdistance3d is called");
 
   return rtgeom_maxdistance3d_tolerance(ctx,  rt1, rt2, 0.0 );
 }
@@ -334,7 +334,7 @@ rtgeom_maxdistance3d_tolerance(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM
   }
   /*double thedist;*/
   DISTPTS3D thedl;
-  RTDEBUG(2, "rtgeom_maxdistance3d_tolerance is called");
+  RTDEBUG(ctx, 2, "rtgeom_maxdistance3d_tolerance is called");
   thedl.mode = DIST_MAX;
   thedl.distance= -1;
   thedl.tolerance = tolerance;
@@ -353,7 +353,7 @@ rtgeom_maxdistance3d_tolerance(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM
 double
 rtgeom_mindistance3d(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM *rt2)
 {
-  RTDEBUG(2, "rtgeom_mindistance3d is called");
+  RTDEBUG(ctx, 2, "rtgeom_mindistance3d is called");
   return rtgeom_mindistance3d_tolerance(ctx,  rt1, rt2, 0.0 );
 }
 
@@ -371,7 +371,7 @@ rtgeom_mindistance3d_tolerance(const RTCTX *ctx, const RTGEOM *rt1, const RTGEOM
     return rtgeom_mindistance2d_tolerance(ctx, rt1, rt2, tolerance);
   }
   DISTPTS3D thedl;
-  RTDEBUG(2, "rtgeom_mindistance3d_tolerance is called");
+  RTDEBUG(ctx, 2, "rtgeom_mindistance3d_tolerance is called");
   thedl.mode = DIST_MIN;
   thedl.distance= FLT_MAX;
   thedl.tolerance = tolerance;
@@ -408,17 +408,17 @@ int rt_dist3d_recursive(const RTCTX *ctx, const RTGEOM *rtg1,const RTGEOM *rtg2,
   RTCOLLECTION *c1 = NULL;
   RTCOLLECTION *c2 = NULL;
 
-  RTDEBUGF(2, "rt_dist3d_recursive is called with type1=%d, type2=%d", rtg1->type, rtg2->type);
+  RTDEBUGF(ctx, 2, "rt_dist3d_recursive is called with type1=%d, type2=%d", rtg1->type, rtg2->type);
 
   if (rtgeom_is_collection(ctx, rtg1))
   {
-    RTDEBUG(3, "First geometry is collection");
+    RTDEBUG(ctx, 3, "First geometry is collection");
     c1 = rtgeom_as_rtcollection(ctx, rtg1);
     n1 = c1->ngeoms;
   }
   if (rtgeom_is_collection(ctx, rtg2))
   {
-    RTDEBUG(3, "Second geometry is collection");
+    RTDEBUG(ctx, 3, "Second geometry is collection");
     c2 = rtgeom_as_rtcollection(ctx, rtg2);
     n2 = c2->ngeoms;
   }
@@ -439,7 +439,7 @@ int rt_dist3d_recursive(const RTCTX *ctx, const RTGEOM *rtg1,const RTGEOM *rtg2,
 
     if (rtgeom_is_collection(ctx, g1))
     {
-      RTDEBUG(3, "Found collection inside first geometry collection, recursing");
+      RTDEBUG(ctx, 3, "Found collection inside first geometry collection, recursing");
       if (!rt_dist3d_recursive(ctx, g1, rtg2, dl)) return RT_FALSE;
       continue;
     }
@@ -455,7 +455,7 @@ int rt_dist3d_recursive(const RTCTX *ctx, const RTGEOM *rtg1,const RTGEOM *rtg2,
       }
       if (rtgeom_is_collection(ctx, g2))
       {
-        RTDEBUG(3, "Found collection inside second geometry collection, recursing");
+        RTDEBUG(ctx, 3, "Found collection inside second geometry collection, recursing");
         if (!rt_dist3d_recursive(ctx, g1, g2, dl)) return RT_FALSE;
         continue;
       }
@@ -485,7 +485,7 @@ rt_dist3d_distribute_bruteforce(const RTCTX *ctx, const RTGEOM *rtg1, const RTGE
   int  t1 = rtg1->type;
   int  t2 = rtg2->type;
 
-  RTDEBUGF(2, "rt_dist3d_distribute_bruteforce is called with typ1=%d, type2=%d", rtg1->type, rtg2->type);
+  RTDEBUGF(ctx, 2, "rt_dist3d_distribute_bruteforce is called with typ1=%d, type2=%d", rtg1->type, rtg2->type);
 
   if  ( t1 == RTPOINTTYPE )
   {
@@ -587,7 +587,7 @@ rt_dist3d_point_point(const RTCTX *ctx, RTPOINT *point1, RTPOINT *point2, DISTPT
 {
   RTPOINT3DZ p1;
   RTPOINT3DZ p2;
-  RTDEBUG(2, "rt_dist3d_point_point is called");
+  RTDEBUG(ctx, 2, "rt_dist3d_point_point is called");
 
   rt_getPoint3dz_p(ctx, point1->point, 0, &p1);
   rt_getPoint3dz_p(ctx, point2->point, 0, &p2);
@@ -603,7 +603,7 @@ rt_dist3d_point_line(const RTCTX *ctx, RTPOINT *point, RTLINE *line, DISTPTS3D *
 {
   RTPOINT3DZ p;
   RTPOINTARRAY *pa = line->points;
-  RTDEBUG(2, "rt_dist3d_point_line is called");
+  RTDEBUG(ctx, 2, "rt_dist3d_point_line is called");
 
   rt_getPoint3dz_p(ctx, point->point, 0, &p);
   return rt_dist3d_pt_ptarray(ctx, &p, pa, dl);
@@ -625,13 +625,13 @@ rt_dist3d_point_poly(const RTCTX *ctx, RTPOINT *point, RTPOLY *poly, DISTPTS3D *
 {
   RTPOINT3DZ p, projp;/*projp is "point projected on plane"*/
   PLANE3D plane;
-  RTDEBUG(2, "rt_dist3d_point_poly is called");
+  RTDEBUG(ctx, 2, "rt_dist3d_point_poly is called");
   rt_getPoint3dz_p(ctx, point->point, 0, &p);
 
   /*If we are lookig for max distance, longestline or dfullywithin*/
   if (dl->mode == DIST_MAX)
   {
-    RTDEBUG(3, "looking for maxdistance");
+    RTDEBUG(ctx, 3, "looking for maxdistance");
     return rt_dist3d_pt_ptarray(ctx, &p, poly->rings[0], dl);
   }
 
@@ -655,7 +655,7 @@ rt_dist3d_line_line(const RTCTX *ctx, RTLINE *line1, RTLINE *line2, DISTPTS3D *d
 {
   RTPOINTARRAY *pa1 = line1->points;
   RTPOINTARRAY *pa2 = line2->points;
-  RTDEBUG(2, "rt_dist3d_line_line is called");
+  RTDEBUG(ctx, 2, "rt_dist3d_line_line is called");
 
   return rt_dist3d_ptarray_ptarray(ctx, pa1, pa2, dl);
 }
@@ -667,7 +667,7 @@ line to polygon calculation
 int rt_dist3d_line_poly(const RTCTX *ctx, RTLINE *line, RTPOLY *poly, DISTPTS3D *dl)
 {
   PLANE3D plane;
-  RTDEBUG(2, "rt_dist3d_line_poly is called");
+  RTDEBUG(ctx, 2, "rt_dist3d_line_poly is called");
 
   if (dl->mode == DIST_MAX)
   {
@@ -687,7 +687,7 @@ polygon to polygon calculation
 int rt_dist3d_poly_poly(const RTCTX *ctx, RTPOLY *poly1, RTPOLY *poly2, DISTPTS3D *dl)
 {
   PLANE3D plane;
-  RTDEBUG(2, "rt_dist3d_poly_poly is called");
+  RTDEBUG(ctx, 2, "rt_dist3d_poly_poly is called");
   if (dl->mode == DIST_MAX)
   {
     return rt_dist3d_ptarray_ptarray(ctx, poly1->rings[0], poly2->rings[0], dl);
@@ -722,7 +722,7 @@ rt_dist3d_pt_ptarray(const RTCTX *ctx, RTPOINT3DZ *p, RTPOINTARRAY *pa,DISTPTS3D
   RTPOINT3DZ  start, end;
   int twist = dl->twisted;
 
-  RTDEBUG(2, "rt_dist3d_pt_ptarray is called");
+  RTDEBUG(ctx, 2, "rt_dist3d_pt_ptarray is called");
 
   rt_getPoint3dz_p(ctx, pa, 0, &start);
 
@@ -817,7 +817,7 @@ rt_dist3d_pt_pt(const RTCTX *ctx, RTPOINT3DZ *thep1, RTPOINT3DZ *thep2,DISTPTS3D
   double dy = thep2->y - thep1->y;
   double dz = thep2->z - thep1->z;
   double dist = sqrt ( dx*dx + dy*dy + dz*dz);
-  RTDEBUGF(2, "rt_dist3d_pt_pt called (with points: p1.x=%f, p1.y=%f,p1.z=%f,p2.x=%f, p2.y=%f,p2.z=%f)",thep1->x,thep1->y,thep1->z,thep2->x,thep2->y,thep2->z );
+  RTDEBUGF(ctx, 2, "rt_dist3d_pt_pt called (with points: p1.x=%f, p1.y=%f,p1.z=%f,p2.x=%f, p2.y=%f,p2.z=%f)",thep1->x,thep1->y,thep1->z,thep2->x,thep2->y,thep2->z );
 
   if (((dl->distance - dist)*(dl->mode))>0) /*multiplication with mode to handle mindistance (mode=1)  and maxdistance (mode = (-1)*/
   {
@@ -849,7 +849,7 @@ rt_dist3d_ptarray_ptarray(const RTCTX *ctx, RTPOINTARRAY *l1, RTPOINTARRAY *l2,D
   RTPOINT3DZ  start, end;
   RTPOINT3DZ  start2, end2;
   int twist = dl->twisted;
-  RTDEBUGF(2, "rt_dist3d_ptarray_ptarray called (points: %d-%d)",l1->npoints, l2->npoints);
+  RTDEBUGF(ctx, 2, "rt_dist3d_ptarray_ptarray called (points: %d-%d)",l1->npoints, l2->npoints);
 
 
 
@@ -862,8 +862,8 @@ rt_dist3d_ptarray_ptarray(const RTCTX *ctx, RTPOINTARRAY *l1, RTPOINTARRAY *l2,D
       {
         rt_getPoint3dz_p(ctx, l2, u, &start2);
         rt_dist3d_pt_pt(ctx, &start,&start2,dl);
-        RTDEBUGF(4, "maxdist_ptarray_ptarray; seg %i * seg %i, dist = %g\n",t,u,dl->distance);
-        RTDEBUGF(3, " seg%d-seg%d dist: %f, mindist: %f",
+        RTDEBUGF(ctx, 4, "maxdist_ptarray_ptarray; seg %i * seg %i, dist = %g\n",t,u,dl->distance);
+        RTDEBUGF(ctx, 3, " seg%d-seg%d dist: %f, mindist: %f",
                  t, u, dl->distance, dl->tolerance);
       }
     }
@@ -880,8 +880,8 @@ rt_dist3d_ptarray_ptarray(const RTCTX *ctx, RTPOINTARRAY *l1, RTPOINTARRAY *l2,D
         rt_getPoint3dz_p(ctx, l2, u, &end2);
         dl->twisted=twist;
         rt_dist3d_seg_seg(ctx, &start, &end, &start2, &end2,dl);
-        RTDEBUGF(4, "mindist_ptarray_ptarray; seg %i * seg %i, dist = %g\n",t,u,dl->distance);
-        RTDEBUGF(3, " seg%d-seg%d dist: %f, mindist: %f",
+        RTDEBUGF(ctx, 4, "mindist_ptarray_ptarray; seg %i * seg %i, dist = %g\n",t,u,dl->distance);
+        RTDEBUGF(ctx, 3, " seg%d-seg%d dist: %f, mindist: %f",
                  t, u, dl->distance, dl->tolerance);
         if (dl->distance<=dl->tolerance && dl->mode == DIST_MIN) return RT_TRUE; /*just a check if  the answer is already given*/
         start2 = end2;
@@ -1023,7 +1023,7 @@ rt_dist3d_pt_poly(const RTCTX *ctx, RTPOINT3DZ *p, RTPOLY *poly, PLANE3D *plane,
 {
   int i;
 
-  RTDEBUG(2, "rt_dist3d_point_poly called");
+  RTDEBUG(ctx, 2, "rt_dist3d_point_poly called");
 
 
   if(pt_in_ring_3d(ctx, projp, poly->rings[0], plane))
@@ -1033,7 +1033,7 @@ rt_dist3d_pt_poly(const RTCTX *ctx, RTPOINT3DZ *p, RTPOLY *poly, PLANE3D *plane,
       /* Inside a hole. Distance = pt -> ring */
       if ( pt_in_ring_3d(ctx, projp, poly->rings[i], plane ))
       {
-        RTDEBUG(3, " inside an hole");
+        RTDEBUG(ctx, 3, " inside an hole");
         return rt_dist3d_pt_ptarray(ctx, p, poly->rings[i], dl);
       }
     }
@@ -1258,7 +1258,7 @@ pt_in_ring_3d(const RTCTX *ctx, const RTPOINT3DZ *p, const RTPOINTARRAY *ring,PL
     return RT_FALSE;
   }
 
-  RTDEBUGF(2, "pt_in_ring_3d called with point: %g %g %g", p->x, p->y, p->z);
+  RTDEBUGF(ctx, 2, "pt_in_ring_3d called with point: %g %g %g", p->x, p->y, p->z);
   /* printPA(ctx, ring); */
 
   /* loop through all edges of the polygon */
@@ -1352,7 +1352,7 @@ pt_in_ring_3d(const RTCTX *ctx, const RTPOINT3DZ *p, const RTPOINTARRAY *ring,PL
         v1 = v2;
       }
   }
-  RTDEBUGF(3, "pt_in_ring_3d returning %d", cn&1);
+  RTDEBUGF(ctx, 3, "pt_in_ring_3d returning %d", cn&1);
 
   return (cn&1);    /* 0 if even (out), and 1 if odd (in) */
 }
diff --git a/src/ptarray.c b/src/ptarray.c
index 9003740..2e082e2 100644
--- a/src/ptarray.c
+++ b/src/ptarray.c
@@ -18,7 +18,7 @@
  *
  **********************************************************************
  *
- * Copyright (C) 2012 Sandro Santilli <strk at keybit.net>
+ * Copyright (C) 2012 Sandro Santilli <strk at kbt.io>
  * Copyright (C) 2001-2006 Refractions Research Inc.
  *
  **********************************************************************/
@@ -54,7 +54,7 @@ ptarray_has_m(const RTCTX *ctx, const RTPOINTARRAY *pa)
 int inline
 ptarray_point_size(const RTCTX *ctx, const RTPOINTARRAY *pa)
 {
-  RTDEBUGF(5, "ptarray_point_size: RTFLAGS_NDIMS(pa->flags)=%x",RTFLAGS_NDIMS(pa->flags));
+  RTDEBUGF(ctx, 5, "ptarray_point_size: RTFLAGS_NDIMS(pa->flags)=%x",RTFLAGS_NDIMS(pa->flags));
 
   return sizeof(double)*RTFLAGS_NDIMS(pa->flags);
 }
@@ -97,8 +97,8 @@ int
 ptarray_insert_point(const RTCTX *ctx, RTPOINTARRAY *pa, const RTPOINT4D *p, int where)
 {
   size_t point_size = ptarray_point_size(ctx, pa);
-  RTDEBUGF(5,"pa = %p; p = %p; where = %d", pa, p, where);
-  RTDEBUGF(5,"pa->npoints = %d; pa->maxpoints = %d", pa->npoints, pa->maxpoints);
+  RTDEBUGF(ctx, 5,"pa = %p; p = %p; where = %d", pa, p, where);
+  RTDEBUGF(ctx, 5,"pa->npoints = %d; pa->maxpoints = %d", pa->npoints, pa->maxpoints);
 
   if ( RTFLAGS_GET_READONLY(pa->flags) )
   {
@@ -140,7 +140,7 @@ ptarray_insert_point(const RTCTX *ctx, RTPOINTARRAY *pa, const RTPOINT4D *p, int
   {
     size_t copy_size = point_size * (pa->npoints - where);
     memmove(rt_getPoint_internal(ctx, pa, where+1), rt_getPoint_internal(ctx, pa, where), copy_size);
-    RTDEBUGF(5,"copying %d bytes to start vertex %d from start vertex %d", copy_size, where+1, where);
+    RTDEBUGF(ctx, 5,"copying %d bytes to start vertex %d from start vertex %d", copy_size, where+1, where);
   }
 
   /* We have one more point */
@@ -148,7 +148,7 @@ ptarray_insert_point(const RTCTX *ctx, RTPOINTARRAY *pa, const RTPOINT4D *p, int
 
   /* Copy the new point into the gap */
   ptarray_set_point4d(ctx, pa, where, p);
-  RTDEBUGF(5,"copying new point to start vertex %d", point_size, where);
+  RTDEBUGF(ctx, 5,"copying new point to start vertex %d", point_size, where);
 
   return RT_SUCCESS;
 }
@@ -169,7 +169,7 @@ ptarray_append_point(const RTCTX *ctx, RTPOINTARRAY *pa, const RTPOINT4D *pt, in
   {
     RTPOINT4D tmp;
     rt_getPoint4d_p(ctx, pa, pa->npoints-1, &tmp);
-    RTDEBUGF(4,"checking for duplicate end point (pt = POINT(%g %g) pa->npoints-q = POINT(%g %g))",pt->x,pt->y,tmp.x,tmp.y);
+    RTDEBUGF(ctx, 4,"checking for duplicate end point (pt = POINT(%g %g) pa->npoints-q = POINT(%g %g))",pt->x,pt->y,tmp.x,tmp.y);
 
     /* Return RT_SUCCESS and do nothing else if previous point in list is equal to this one */
     if ( (pt->x == tmp.x) && (pt->y == tmp.y) &&
@@ -296,7 +296,7 @@ ptarray_remove_point(const RTCTX *ctx, RTPOINTARRAY *pa, int where)
 RTPOINTARRAY* ptarray_construct_reference_data(const RTCTX *ctx, char hasz, char hasm, uint32_t npoints, uint8_t *ptlist)
 {
   RTPOINTARRAY *pa = rtalloc(ctx, sizeof(RTPOINTARRAY));
-  RTDEBUGF(5, "hasz = %d, hasm = %d, npoints = %d, ptlist = %p", hasz, hasm, npoints, ptlist);
+  RTDEBUGF(ctx, 5, "hasz = %d, hasm = %d, npoints = %d, ptlist = %p", hasz, hasm, npoints, ptlist);
   pa->flags = gflags(ctx, hasz, hasm, 0);
   RTFLAGS_SET_READONLY(pa->flags, 1); /* We don't own this memory, so we can't alter or free it. */
   pa->npoints = npoints;
@@ -335,7 +335,7 @@ void ptarray_free(const RTCTX *ctx, RTPOINTARRAY *pa)
     if(pa->serialized_pointlist && ( ! RTFLAGS_GET_READONLY(pa->flags) ) )
       rtfree(ctx, pa->serialized_pointlist);
     rtfree(ctx, pa);
-    RTDEBUG(5,"Freeing a PointArray");
+    RTDEBUG(ctx, 5,"Freeing a PointArray");
   }
 }
 
@@ -488,19 +488,19 @@ ptarray_same(const RTCTX *ctx, const RTPOINTARRAY *pa1, const RTPOINTARRAY *pa2)
   size_t ptsize;
 
   if ( RTFLAGS_GET_ZM(pa1->flags) != RTFLAGS_GET_ZM(pa2->flags) ) return RT_FALSE;
-  RTDEBUG(5,"dimensions are the same");
+  RTDEBUG(ctx, 5,"dimensions are the same");
 
   if ( pa1->npoints != pa2->npoints ) return RT_FALSE;
-  RTDEBUG(5,"npoints are the same");
+  RTDEBUG(ctx, 5,"npoints are the same");
 
   ptsize = ptarray_point_size(ctx, pa1);
-  RTDEBUGF(5, "ptsize = %d", ptsize);
+  RTDEBUGF(ctx, 5, "ptsize = %d", ptsize);
 
   for (i=0; i<pa1->npoints; i++)
   {
     if ( memcmp(rt_getPoint_internal(ctx, pa1, i), rt_getPoint_internal(ctx, pa2, i), ptsize) )
       return RT_FALSE;
-    RTDEBUGF(5,"point #%d is the same",i);
+    RTDEBUGF(ctx, 5,"point #%d is the same",i);
   }
 
   return RT_TRUE;
@@ -513,7 +513,7 @@ ptarray_addPoint(const RTCTX *ctx, const RTPOINTARRAY *pa, uint8_t *p, size_t pd
   RTPOINT4D pbuf;
   size_t ptsize = ptarray_point_size(ctx, pa);
 
-  RTDEBUGF(3, "pa %x p %x size %d where %d",
+  RTDEBUGF(ctx, 3, "pa %x p %x size %d where %d",
            pa, p, pdims, where);
 
   if ( pdims < 2 || pdims > 4 )
@@ -530,12 +530,12 @@ ptarray_addPoint(const RTCTX *ctx, const RTPOINTARRAY *pa, uint8_t *p, size_t pd
     return NULL;
   }
 
-  RTDEBUG(3, "called with a %dD point");
+  RTDEBUG(ctx, 3, "called with a %dD point");
 
   pbuf.x = pbuf.y = pbuf.z = pbuf.m = 0.0;
   memcpy((uint8_t *)&pbuf, p, pdims*sizeof(double));
 
-  RTDEBUG(3, "initialized point buffer");
+  RTDEBUG(ctx, 3, "initialized point buffer");
 
   ret = ptarray_construct(ctx, RTFLAGS_GET_Z(pa->flags),
                           RTFLAGS_GET_M(pa->flags), pa->npoints+1);
@@ -565,7 +565,7 @@ ptarray_removePoint(const RTCTX *ctx, RTPOINTARRAY *pa, uint32_t which)
   RTPOINTARRAY *ret;
   size_t ptsize = ptarray_point_size(ctx, pa);
 
-  RTDEBUGF(3, "pa %x which %d", pa, which);
+  RTDEBUGF(ctx, 3, "pa %x which %d", pa, which);
 
 #if PARANOIA_LEVEL > 0
   if ( which > pa->npoints-1 )
@@ -637,7 +637,7 @@ ptarray_clone_deep(const RTCTX *ctx, const RTPOINTARRAY *in)
   RTPOINTARRAY *out = rtalloc(ctx, sizeof(RTPOINTARRAY));
   size_t size;
 
-  RTDEBUG(3, "ptarray_clone_deep called.");
+  RTDEBUG(ctx, 3, "ptarray_clone_deep called.");
 
   out->flags = in->flags;
   out->npoints = in->npoints;
@@ -660,7 +660,7 @@ ptarray_clone(const RTCTX *ctx, const RTPOINTARRAY *in)
 {
   RTPOINTARRAY *out = rtalloc(ctx, sizeof(RTPOINTARRAY));
 
-  RTDEBUG(3, "ptarray_clone_deep called.");
+  RTDEBUG(ctx, 3, "ptarray_clone_deep called.");
 
   out->flags = in->flags;
   out->npoints = in->npoints;
@@ -1056,7 +1056,7 @@ ptarray_substring(const RTCTX *ctx, RTPOINTARRAY *ipa, double from, double to, d
   length = ptarray_length_2d(ctx, ipa);
 
 
-  RTDEBUGF(3, "Total length: %g", length);
+  RTDEBUGF(ctx, 3, "Total length: %g", length);
 
 
   /* Get 'from' and 'to' lengths */
@@ -1064,7 +1064,7 @@ ptarray_substring(const RTCTX *ctx, RTPOINTARRAY *ipa, double from, double to, d
   to = length*to;
 
 
-  RTDEBUGF(3, "From/To: %g/%g", from, to);
+  RTDEBUGF(ctx, 3, "From/To: %g/%g", from, to);
 
 
   tlength = 0;
@@ -1077,7 +1077,7 @@ ptarray_substring(const RTCTX *ctx, RTPOINTARRAY *ipa, double from, double to, d
     rt_getPoint4d_p(ctx, ipa, i+1, &p2);
 
 
-    RTDEBUGF(3 ,"Segment %d: (%g,%g,%g,%g)-(%g,%g,%g,%g)",
+    RTDEBUGF(ctx, 3 ,"Segment %d: (%g,%g,%g,%g)-(%g,%g,%g,%g)",
              i, p1.x, p1.y, p1.z, p1.m, p2.x, p2.y, p2.z, p2.m);
 
 
@@ -1090,12 +1090,12 @@ ptarray_substring(const RTCTX *ctx, RTPOINTARRAY *ipa, double from, double to, d
     if ( state == 0 ) /* before */
     {
 
-      RTDEBUG(3, " Before start");
+      RTDEBUG(ctx, 3, " Before start");
 
       if ( fabs ( from - ( tlength + slength ) ) <= tolerance )
       {
 
-        RTDEBUG(3, "  Second point is our start");
+        RTDEBUG(ctx, 3, "  Second point is our start");
 
         /*
          * Second point is our start
@@ -1108,7 +1108,7 @@ ptarray_substring(const RTCTX *ctx, RTPOINTARRAY *ipa, double from, double to, d
       else if ( fabs(from - tlength) <= tolerance )
       {
 
-        RTDEBUG(3, "  First point is our start");
+        RTDEBUG(ctx, 3, "  First point is our start");
 
         /*
          * First point is our start
@@ -1131,7 +1131,7 @@ ptarray_substring(const RTCTX *ctx, RTPOINTARRAY *ipa, double from, double to, d
       else  /* tlength < from < tlength+slength */
       {
 
-        RTDEBUG(3, "  Seg contains first point");
+        RTDEBUG(ctx, 3, "  Seg contains first point");
 
         /*
          * Our start is between first and
@@ -1154,7 +1154,7 @@ ptarray_substring(const RTCTX *ctx, RTPOINTARRAY *ipa, double from, double to, d
     if ( state == 1 ) /* inside */
     {
 
-      RTDEBUG(3, " Inside");
+      RTDEBUG(ctx, 3, " Inside");
 
       /*
        * 'to' point is our second point.
@@ -1162,7 +1162,7 @@ ptarray_substring(const RTCTX *ctx, RTPOINTARRAY *ipa, double from, double to, d
       if ( fabs(to - ( tlength + slength ) ) <= tolerance )
       {
 
-        RTDEBUG(3, " Second point is our end");
+        RTDEBUG(ctx, 3, " Second point is our end");
 
         ptarray_append_point(ctx, dpa, &p2, RT_FALSE);
         break; /* substring complete */
@@ -1175,7 +1175,7 @@ ptarray_substring(const RTCTX *ctx, RTPOINTARRAY *ipa, double from, double to, d
       else if ( fabs(to - tlength) <= tolerance )
       {
 
-        RTDEBUG(3, " First point is our end");
+        RTDEBUG(ctx, 3, " First point is our end");
 
         ptarray_append_point(ctx, dpa, &p1, RT_FALSE);
 
@@ -1199,7 +1199,7 @@ ptarray_substring(const RTCTX *ctx, RTPOINTARRAY *ipa, double from, double to, d
       else if ( to < tlength + slength )
       {
 
-        RTDEBUG(3, " Seg contains our end");
+        RTDEBUG(ctx, 3, " Seg contains our end");
 
         dseg = (to - tlength) / slength;
         interpolate_point4d(ctx, &p1, &p2, &pt, dseg);
@@ -1211,7 +1211,7 @@ ptarray_substring(const RTCTX *ctx, RTPOINTARRAY *ipa, double from, double to, d
 
       else
       {
-        RTDEBUG(3, "Unhandled case");
+        RTDEBUG(ctx, 3, "Unhandled case");
       }
     }
 
@@ -1222,7 +1222,7 @@ END:
     memcpy(&p1, &p2, sizeof(RTPOINT4D));
   }
 
-  RTDEBUGF(3, "Out of loop, ptarray has %d points", dpa->npoints);
+  RTDEBUGF(ctx, 3, "Out of loop, ptarray has %d points", dpa->npoints);
 
   return dpa;
 }
@@ -1322,7 +1322,7 @@ ptarray_locate_point(const RTCTX *ctx, const RTPOINTARRAY *pa, const RTPOINT4D *
 
     if ( mindist == 0 )
     {
-      RTDEBUG(3, "Breaking on mindist=0");
+      RTDEBUG(ctx, 3, "Breaking on mindist=0");
       break;
     }
 
@@ -1331,8 +1331,8 @@ ptarray_locate_point(const RTCTX *ctx, const RTPOINTARRAY *pa, const RTPOINT4D *
 
   if ( mindistout ) *mindistout = mindist;
 
-  RTDEBUGF(3, "Closest segment: %d", seg);
-  RTDEBUGF(3, "mindist: %g", mindist);
+  RTDEBUGF(ctx, 3, "Closest segment: %d", seg);
+  RTDEBUGF(ctx, 3, "mindist: %g", mindist);
 
   /*
    * We need to project the
@@ -1346,7 +1346,7 @@ ptarray_locate_point(const RTCTX *ctx, const RTPOINTARRAY *pa, const RTPOINT4D *
   proj.x = proj4d->x;
   proj.y = proj4d->y;
 
-  RTDEBUGF(3, "Closest segment:%d, npoints:%d", seg, pa->npoints);
+  RTDEBUGF(ctx, 3, "Closest segment:%d, npoints:%d", seg, pa->npoints);
 
   /* For robustness, force 1 when closest point == endpoint */
   if ( (seg >= (pa->npoints-2)) && p2d_same(ctx, &proj, end) )
@@ -1354,11 +1354,11 @@ ptarray_locate_point(const RTCTX *ctx, const RTPOINTARRAY *pa, const RTPOINT4D *
     return 1.0;
   }
 
-  RTDEBUGF(3, "Closest point on segment: %g,%g", proj.x, proj.y);
+  RTDEBUGF(ctx, 3, "Closest point on segment: %g,%g", proj.x, proj.y);
 
   tlen = ptarray_length_2d(ctx, pa);
 
-  RTDEBUGF(3, "tlen %g", tlen);
+  RTDEBUGF(ctx, 3, "tlen %g", tlen);
 
   /* Location of any point on a zero-length line is 0 */
   /* See http://trac.osgeo.org/postgis/ticket/1772#comment:2 */
@@ -1371,12 +1371,12 @@ ptarray_locate_point(const RTCTX *ctx, const RTPOINTARRAY *pa, const RTPOINT4D *
     end = rt_getPoint2d_cp(ctx, pa, t+1);
     plen += distance2d_pt_pt(ctx, start, end);
 
-    RTDEBUGF(4, "Segment %d made plen %g", t, plen);
+    RTDEBUGF(ctx, 4, "Segment %d made plen %g", t, plen);
   }
 
   plen+=distance2d_pt_pt(ctx, &proj, start);
 
-  RTDEBUGF(3, "plen %g, tlen %g", plen, tlen);
+  RTDEBUGF(ctx, 3, "plen %g, tlen %g", plen, tlen);
 
   return plen/tlen;
 }
@@ -1424,14 +1424,14 @@ ptarray_remove_repeated_points_minpoints(const RTCTX *ctx, const RTPOINTARRAY *i
 
   if ( minpoints < 1 ) minpoints = 1;
 
-  RTDEBUGF(3, "%s called", __func__);
+  RTDEBUGF(ctx, 3, "%s called", __func__);
 
   /* Single or zero point arrays can't have duplicates */
   if ( in->npoints < 3 ) return ptarray_clone_deep(ctx, in);
 
   ptsize = ptarray_point_size(ctx, in);
 
-  RTDEBUGF(3, " ptsize: %d", ptsize);
+  RTDEBUGF(ctx, 3, " ptsize: %d", ptsize);
 
   /* Allocate enough space for all points */
   out = ptarray_construct(ctx, RTFLAGS_GET_Z(in->flags),
@@ -1442,7 +1442,7 @@ ptarray_remove_repeated_points_minpoints(const RTCTX *ctx, const RTPOINTARRAY *i
   opn=1;
   memcpy(rt_getPoint_internal(ctx, out, 0), rt_getPoint_internal(ctx, in, 0), ptsize);
   last_point = rt_getPoint2d_cp(ctx, in, 0);
-  RTDEBUGF(3, " first point copied, out points: %d", opn);
+  RTDEBUGF(ctx, 3, " first point copied, out points: %d", opn);
   for ( ipn = 1; ipn < in->npoints; ++ipn)
   {
     this_point = rt_getPoint2d_cp(ctx, in, ipn);
@@ -1454,11 +1454,11 @@ ptarray_remove_repeated_points_minpoints(const RTCTX *ctx, const RTPOINTARRAY *i
        * we add it to output */
       memcpy(rt_getPoint_internal(ctx, out, opn++), rt_getPoint_internal(ctx, in, ipn), ptsize);
       last_point = this_point;
-      RTDEBUGF(3, " Point %d differs from point %d. Out points: %d", ipn, ipn-1, opn);
+      RTDEBUGF(ctx, 3, " Point %d differs from point %d. Out points: %d", ipn, ipn-1, opn);
     }
   }
 
-  RTDEBUGF(3, " in:%d out:%d", out->npoints, opn);
+  RTDEBUGF(ctx, 3, " in:%d out:%d", out->npoints, opn);
   out->npoints = opn;
 
   return out;
@@ -1477,7 +1477,7 @@ ptarray_dp_findsplit(const RTCTX *ctx, RTPOINTARRAY *pts, int p1, int p2, int *s
   const RTPOINT2D *pk, *pa, *pb;
   double tmp, d;
 
-  RTDEBUG(4, "function called");
+  RTDEBUG(ctx, 4, "function called");
 
   *split = p1;
   d = -1;
@@ -1488,14 +1488,14 @@ ptarray_dp_findsplit(const RTCTX *ctx, RTPOINTARRAY *pts, int p1, int p2, int *s
     pa = rt_getPoint2d_cp(ctx, pts, p1);
     pb = rt_getPoint2d_cp(ctx, pts, p2);
 
-    RTDEBUGF(4, "P%d(%f,%f) to P%d(%f,%f)",
+    RTDEBUGF(ctx, 4, "P%d(%f,%f) to P%d(%f,%f)",
              p1, pa->x, pa->y, p2, pb->x, pb->y);
 
     for (k=p1+1; k<p2; k++)
     {
       pk = rt_getPoint2d_cp(ctx, pts, k);
 
-      RTDEBUGF(4, "P%d(%f,%f)", k, pk->x, pk->y);
+      RTDEBUGF(ctx, 4, "P%d(%f,%f)", k, pk->x, pk->y);
 
       /* distance computation */
       tmp = distance2d_sqr_pt_seg(ctx, pk, pa, pb);
@@ -1505,7 +1505,7 @@ ptarray_dp_findsplit(const RTCTX *ctx, RTPOINTARRAY *pts, int p1, int p2, int *s
         d = tmp;  /* record the maximum */
         *split = k;
 
-        RTDEBUGF(4, "P%d is farthest (%g)", k, d);
+        RTDEBUGF(ctx, 4, "P%d is farthest (%g)", k, d);
       }
     }
     *dist = d;
@@ -1513,7 +1513,7 @@ ptarray_dp_findsplit(const RTCTX *ctx, RTPOINTARRAY *pts, int p1, int p2, int *s
   } /* length---should be redone if can == 0 */
   else
   {
-    RTDEBUG(3, "segment too short, no split/no dist");
+    RTDEBUG(ctx, 3, "segment too short, no split/no dist");
     *dist = -1;
   }
 
@@ -1537,7 +1537,7 @@ ptarray_simplify(const RTCTX *ctx, RTPOINTARRAY *inpts, double epsilon, unsigned
   p1 = 0;
   stack[++sp] = inpts->npoints-1;
 
-  RTDEBUGF(2, "Input has %d pts and %d dims", inpts->npoints,
+  RTDEBUGF(ctx, 2, "Input has %d pts and %d dims", inpts->npoints,
                                               RTFLAGS_NDIMS(inpts->flags));
 
   /* Allocate output RTPOINTARRAY, and add first point. */
@@ -1545,32 +1545,32 @@ ptarray_simplify(const RTCTX *ctx, RTPOINTARRAY *inpts, double epsilon, unsigned
   rt_getPoint4d_p(ctx, inpts, 0, &pt);
   ptarray_append_point(ctx, outpts, &pt, RT_FALSE);
 
-  RTDEBUG(3, "Added P0 to simplified point array (size 1)");
+  RTDEBUG(ctx, 3, "Added P0 to simplified point array (size 1)");
 
   do
   {
 
     ptarray_dp_findsplit(ctx, inpts, p1, stack[sp], &split, &dist);
 
-    RTDEBUGF(3, "Farthest point from P%d-P%d is P%d (dist. %g)", p1, stack[sp], split, dist);
+    RTDEBUGF(ctx, 3, "Farthest point from P%d-P%d is P%d (dist. %g)", p1, stack[sp], split, dist);
 
     if (dist > eps_sqr || ( outpts->npoints+sp+1 < minpts && dist >= 0 ) )
     {
-      RTDEBUGF(4, "Added P%d to stack (outpts:%d)", split, sp);
+      RTDEBUGF(ctx, 4, "Added P%d to stack (outpts:%d)", split, sp);
       stack[++sp] = split;
     }
     else
     {
       rt_getPoint4d_p(ctx, inpts, stack[sp], &pt);
-      RTDEBUGF(4, "npoints , minpoints %d %d", outpts->npoints, minpts);
+      RTDEBUGF(ctx, 4, "npoints , minpoints %d %d", outpts->npoints, minpts);
       ptarray_append_point(ctx, outpts, &pt, RT_FALSE);
 
-      RTDEBUGF(4, "Added P%d to simplified point array (size: %d)", stack[sp], outpts->npoints);
+      RTDEBUGF(ctx, 4, "Added P%d to simplified point array (size: %d)", stack[sp], outpts->npoints);
 
       p1 = stack[sp--];
     }
 
-    RTDEBUGF(4, "stack pointer = %d", sp);
+    RTDEBUGF(ctx, 4, "stack pointer = %d", sp);
   }
   while (! (sp<0) );
 
@@ -1684,7 +1684,7 @@ rt_getPoint_internal(const RTCTX *ctx, const RTPOINTARRAY *pa, int n)
     return NULL;
   }
 
-  RTDEBUGF(5, "(n=%d, pa.npoints=%d, pa.maxpoints=%d)",n,pa->npoints,pa->maxpoints);
+  RTDEBUGF(ctx, 5, "(n=%d, pa.npoints=%d, pa.maxpoints=%d)",n,pa->npoints,pa->maxpoints);
 
   if ( ( n < 0 ) ||
        ( n > pa->npoints ) ||
@@ -1700,15 +1700,15 @@ rt_getPoint_internal(const RTCTX *ctx, const RTPOINTARRAY *pa, int n)
   ptr = pa->serialized_pointlist + size * n;
   if ( RTFLAGS_NDIMS(pa->flags) == 2)
   {
-    RTDEBUGF(5, "point = %g %g", *((double*)(ptr)), *((double*)(ptr+8)));
+    RTDEBUGF(ctx, 5, "point = %g %g", *((double*)(ptr)), *((double*)(ptr+8)));
   }
   else if ( RTFLAGS_NDIMS(pa->flags) == 3)
   {
-    RTDEBUGF(5, "point = %g %g %g", *((double*)(ptr)), *((double*)(ptr+8)), *((double*)(ptr+16)));
+    RTDEBUGF(ctx, 5, "point = %g %g %g", *((double*)(ptr)), *((double*)(ptr+8)), *((double*)(ptr+16)));
   }
   else if ( RTFLAGS_NDIMS(pa->flags) == 4)
   {
-    RTDEBUGF(5, "point = %g %g %g %g", *((double*)(ptr)), *((double*)(ptr+8)), *((double*)(ptr+16)), *((double*)(ptr+24)));
+    RTDEBUGF(ctx, 5, "point = %g %g %g %g", *((double*)(ptr)), *((double*)(ptr+8)), *((double*)(ptr+16)), *((double*)(ptr+24)));
   }
 
   return ptr;
@@ -1725,11 +1725,11 @@ ptarray_affine(const RTCTX *ctx, RTPOINTARRAY *pa, const RTAFFINE *a)
   double x,y,z;
   RTPOINT4D p4d;
 
-  RTDEBUG(2, "rtgeom_affine_ptarray start");
+  RTDEBUG(ctx, 2, "rtgeom_affine_ptarray start");
 
   if ( RTFLAGS_GET_Z(pa->flags) )
   {
-    RTDEBUG(3, " has z");
+    RTDEBUG(ctx, 3, " has z");
 
     for (i=0; i<pa->npoints; i++)
     {
@@ -1742,12 +1742,12 @@ ptarray_affine(const RTCTX *ctx, RTPOINTARRAY *pa, const RTAFFINE *a)
       p4d.z = a->gfac * x + a->hfac * y + a->ifac * z + a->zoff;
       ptarray_set_point4d(ctx, pa, i, &p4d);
 
-      RTDEBUGF(3, " POINT %g %g %g => %g %g %g", x, y, x, p4d.x, p4d.y, p4d.z);
+      RTDEBUGF(ctx, 3, " POINT %g %g %g => %g %g %g", x, y, x, p4d.x, p4d.y, p4d.z);
     }
   }
   else
   {
-    RTDEBUG(3, " doesn't have z");
+    RTDEBUG(ctx, 3, " doesn't have z");
 
     for (i=0; i<pa->npoints; i++)
     {
@@ -1758,11 +1758,11 @@ ptarray_affine(const RTCTX *ctx, RTPOINTARRAY *pa, const RTAFFINE *a)
       p4d.y = a->dfac * x + a->efac * y + a->yoff;
       ptarray_set_point4d(ctx, pa, i, &p4d);
 
-      RTDEBUGF(3, " POINT %g %g %g => %g %g %g", x, y, x, p4d.x, p4d.y, p4d.z);
+      RTDEBUGF(ctx, 3, " POINT %g %g %g => %g %g %g", x, y, x, p4d.x, p4d.y, p4d.z);
     }
   }
 
-  RTDEBUG(3, "rtgeom_affine_ptarray end");
+  RTDEBUG(ctx, 3, "rtgeom_affine_ptarray end");
 
 }
 
@@ -1775,7 +1775,7 @@ ptarray_scale(const RTCTX *ctx, RTPOINTARRAY *pa, const RTPOINT4D *fact)
   int i;
   RTPOINT4D p4d;
 
-  RTDEBUG(3, "ptarray_scale start");
+  RTDEBUG(ctx, 3, "ptarray_scale start");
 
   for (i=0; i<pa->npoints; ++i)
   {
@@ -1787,7 +1787,7 @@ ptarray_scale(const RTCTX *ctx, RTPOINTARRAY *pa, const RTPOINT4D *fact)
     ptarray_set_point4d(ctx, pa, i, &p4d);
   }
 
-  RTDEBUG(3, "ptarray_scale end");
+  RTDEBUG(ctx, 3, "ptarray_scale end");
 
 }
 
@@ -1815,7 +1815,7 @@ ptarray_grid(const RTCTX *ctx, const RTPOINTARRAY *pa, const gridspec *grid)
   int ipn; /* input point numbers */
   RTPOINTARRAY *dpa;
 
-  RTDEBUGF(2, "ptarray_grid called on %p", pa);
+  RTDEBUGF(ctx, 2, "ptarray_grid called on %p", pa);
 
   dpa = ptarray_construct_empty(ctx, RTFLAGS_GET_Z(pa->flags),RTFLAGS_GET_M(pa->flags), pa->npoints);
 
diff --git a/src/rtalgorithm.c b/src/rtalgorithm.c
index 33144d2..2eb2563 100644
--- a/src/rtalgorithm.c
+++ b/src/rtalgorithm.c
@@ -247,7 +247,7 @@ rt_arc_center(const RTCTX *ctx, const RTPOINT2D *p1, const RTPOINT2D *p2, const
 
   c.x = c.y = 0.0;
 
-  RTDEBUGF(2, "rt_arc_center called (%.16f,%.16f), (%.16f,%.16f), (%.16f,%.16f).", p1->x, p1->y, p2->x, p2->y, p3->x, p3->y);
+  RTDEBUGF(ctx, 2, "rt_arc_center called (%.16f,%.16f), (%.16f,%.16f), (%.16f,%.16f).", p1->x, p1->y, p2->x, p2->y, p3->x, p3->y);
 
   /* Closed circle */
   if (fabs(p1->x - p3->x) < EPSILON_SQLMM &&
@@ -286,7 +286,7 @@ rt_arc_center(const RTCTX *ctx, const RTPOINT2D *p1, const RTPOINT2D *p2, const
   *result = c;
   cr = sqrt(pow(cx - p1->x, 2) + pow(cy - p1->y, 2));
 
-  RTDEBUGF(2, "rt_arc_center center is (%.16f,%.16f)", result->x, result->y);
+  RTDEBUGF(ctx, 2, "rt_arc_center center is (%.16f,%.16f)", result->x, result->y);
 
   return cr;
 }
@@ -309,7 +309,7 @@ pt_in_ring_2d(const RTCTX *ctx, const RTPOINT2D *p, const RTPOINTARRAY *ring)
 
   }
 
-  RTDEBUGF(2, "pt_in_ring_2d called with point: %g %g", p->x, p->y);
+  RTDEBUGF(ctx, 2, "pt_in_ring_2d called with point: %g %g", p->x, p->y);
   /* printPA(ctx, ring); */
 
   /* loop through all edges of the polygon */
@@ -341,7 +341,7 @@ pt_in_ring_2d(const RTCTX *ctx, const RTPOINT2D *p, const RTPOINTARRAY *ring)
     v1 = v2;
   }
 
-  RTDEBUGF(3, "pt_in_ring_2d returning %d", cn&1);
+  RTDEBUGF(ctx, 3, "pt_in_ring_2d returning %d", cn&1);
 
   return (cn&1);    /* 0 if even (out), and 1 if odd (in) */
 }
@@ -421,8 +421,8 @@ int rt_segment_intersects(const RTCTX *ctx, const RTPOINT2D *p1, const RTPOINT2D
   ** location of the other end-point. Only touches by the first point
   ** will be considered "real" to avoid double counting.
   */
-  RTDEBUGF(4, "pq1=%.15g pq2=%.15g", pq1, pq2);
-  RTDEBUGF(4, "qp1=%.15g qp2=%.15g", qp1, qp2);
+  RTDEBUGF(ctx, 4, "pq1=%.15g pq2=%.15g", pq1, pq2);
+  RTDEBUGF(ctx, 4, "qp1=%.15g qp2=%.15g", qp1, qp2);
 
   /* Second point of p or q touches, it's not a crossing. */
   if ( pq2 == 0 || qp2 == 0 )
@@ -489,8 +489,8 @@ int rtline_crossing_direction(const RTCTX *ctx, const RTLINE *l1, const RTLINE *
   if ( pa1->npoints < 2 || pa2->npoints < 2 )
     return LINE_NO_CROSS;
 
-  RTDEBUGF(4, "l1 = %s", rtgeom_to_ewkt(ctx, (RTGEOM*)l1));
-  RTDEBUGF(4, "l2 = %s", rtgeom_to_ewkt(ctx, (RTGEOM*)l2));
+  RTDEBUGF(ctx, 4, "l1 = %s", rtgeom_to_ewkt(ctx, (RTGEOM*)l1));
+  RTDEBUGF(ctx, 4, "l2 = %s", rtgeom_to_ewkt(ctx, (RTGEOM*)l2));
 
   /* Initialize first point of q */
   q1 = rt_getPoint2d_cp(ctx, pa2, 0);
@@ -512,11 +512,11 @@ int rtline_crossing_direction(const RTCTX *ctx, const RTLINE *l1, const RTLINE *
 
       this_cross = rt_segment_intersects(ctx, p1, p2, q1, q2);
 
-      RTDEBUGF(4, "i=%d, j=%d (%.8g %.8g, %.8g %.8g)", this_cross, i, j, p1->x, p1->y, p2->x, p2->y);
+      RTDEBUGF(ctx, 4, "i=%d, j=%d (%.8g %.8g, %.8g %.8g)", this_cross, i, j, p1->x, p1->y, p2->x, p2->y);
 
       if ( this_cross == SEG_CROSS_LEFT )
       {
-        RTDEBUG(4,"this_cross == SEG_CROSS_LEFT");
+        RTDEBUG(ctx, 4,"this_cross == SEG_CROSS_LEFT");
         cross_left++;
         if ( ! first_cross )
           first_cross = SEG_CROSS_LEFT;
@@ -524,7 +524,7 @@ int rtline_crossing_direction(const RTCTX *ctx, const RTLINE *l1, const RTLINE *
 
       if ( this_cross == SEG_CROSS_RIGHT )
       {
-        RTDEBUG(4,"this_cross == SEG_CROSS_RIGHT");
+        RTDEBUG(ctx, 4,"this_cross == SEG_CROSS_RIGHT");
         cross_right++;
         if ( ! first_cross )
           first_cross = SEG_CROSS_LEFT;
@@ -537,13 +537,13 @@ int rtline_crossing_direction(const RTCTX *ctx, const RTLINE *l1, const RTLINE *
       */
       if ( this_cross == SEG_COLINEAR )
       {
-        RTDEBUG(4,"this_cross == SEG_COLINEAR");
+        RTDEBUG(ctx, 4,"this_cross == SEG_COLINEAR");
         /* TODO: Add logic here and in segment_intersects()
         continue;
         */
       }
 
-      RTDEBUG(4,"this_cross == SEG_NO_INTERSECTION");
+      RTDEBUG(ctx, 4,"this_cross == SEG_NO_INTERSECTION");
 
       /* Turn second point of p into first point */
       p1 = p2;
@@ -555,7 +555,7 @@ int rtline_crossing_direction(const RTCTX *ctx, const RTLINE *l1, const RTLINE *
 
   }
 
-  RTDEBUGF(4, "first_cross=%d, cross_left=%d, cross_right=%d", first_cross, cross_left, cross_right);
+  RTDEBUGF(ctx, 4, "first_cross=%d, cross_left=%d, cross_right=%d", first_cross, cross_left, cross_right);
 
   if ( !cross_left && !cross_right )
     return LINE_NO_CROSS;
diff --git a/src/rtcircstring.c b/src/rtcircstring.c
index 6896661..67bd9e3 100644
--- a/src/rtcircstring.c
+++ b/src/rtcircstring.c
@@ -225,7 +225,7 @@ rtcircstring_from_rtmpoint(const RTCTX *ctx, int srid, RTMPOINT *mpoint)
 
   pa = ptarray_construct_reference_data(ctx, zmflag&2, zmflag&1, mpoint->ngeoms, newpoints);
 
-  RTDEBUGF(3, "rtcurve_from_rtmpoint: constructed pointarray for %d points, %d zmflag", mpoint->ngeoms, zmflag);
+  RTDEBUGF(ctx, 3, "rtcurve_from_rtmpoint: constructed pointarray for %d points, %d zmflag", mpoint->ngeoms, zmflag);
 
   return rtcircstring_construct(ctx, srid, NULL, pa);
 }
diff --git a/src/rtcollection.c b/src/rtcollection.c
index 1bff21d..7ac1c80 100644
--- a/src/rtcollection.c
+++ b/src/rtcollection.c
@@ -51,7 +51,7 @@ rtcollection_construct(const RTCTX *ctx, uint8_t type, int srid, RTGBOX *bbox,
   uint32_t i;
 #endif
 
-  RTDEBUGF(2, "rtcollection_construct called with %d, %d, %p, %d, %p.", type, srid, bbox, ngeoms, geoms);
+  RTDEBUGF(ctx, 2, "rtcollection_construct called with %d, %d, %p, %d, %p.", type, srid, bbox, ngeoms, geoms);
 
   if( ! rttype_is_collection(ctx, type) )
     rterror(ctx, "Non-collection type specified in collection constructor!");
@@ -65,11 +65,11 @@ rtcollection_construct(const RTCTX *ctx, uint8_t type, int srid, RTGBOX *bbox,
 #ifdef CHECK_RTGEOM_ZM
     zm = RTFLAGS_GET_ZM(geoms[0]->flags);
 
-    RTDEBUGF(3, "rtcollection_construct type[0]=%d", geoms[0]->type);
+    RTDEBUGF(ctx, 3, "rtcollection_construct type[0]=%d", geoms[0]->type);
 
     for (i=1; i<ngeoms; i++)
     {
-      RTDEBUGF(3, "rtcollection_construct type=[%d]=%d", i, geoms[i]->type);
+      RTDEBUGF(ctx, 3, "rtcollection_construct type=[%d]=%d", i, geoms[i]->type);
 
       if ( zm != RTFLAGS_GET_ZM(geoms[i]->flags) )
         rterror(ctx, "rtcollection_construct: mixed dimension geometries: %d/%d", zm, RTFLAGS_GET_ZM(geoms[i]->flags));
@@ -220,7 +220,7 @@ RTCOLLECTION* rtcollection_add_rtgeom(const RTCTX *ctx, RTCOLLECTION *col, const
   {
     if ( col->geoms[i] == geom )
     {
-      RTDEBUGF(4, "Found duplicate geometry in collection %p == %p", col->geoms[i], geom);
+      RTDEBUGF(ctx, 4, "Found duplicate geometry in collection %p == %p", col->geoms[i], geom);
       return col;
     }
   }
@@ -263,7 +263,7 @@ rtcollection_same(const RTCTX *ctx, const RTCOLLECTION *c1, const RTCOLLECTION *
 {
   uint32_t i;
 
-  RTDEBUG(2, "rtcollection_same called");
+  RTDEBUG(ctx, 2, "rtcollection_same called");
 
   if ( c1->type != c2->type ) return RT_FALSE;
   if ( c1->ngeoms != c2->ngeoms ) return RT_FALSE;
@@ -348,7 +348,7 @@ void rtcollection_free(const RTCTX *ctx, RTCOLLECTION *col)
   }
   for ( i = 0; i < col->ngeoms; i++ )
   {
-    RTDEBUGF(4,"freeing geom[%d]", i);
+    RTDEBUGF(ctx, 4,"freeing geom[%d]", i);
     if ( col->geoms && col->geoms[i] )
       rtgeom_free(ctx, col->geoms[i]);
   }
diff --git a/src/rtcompound.c b/src/rtcompound.c
index 7bcb4d7..85fe19a 100644
--- a/src/rtcompound.c
+++ b/src/rtcompound.c
@@ -98,7 +98,7 @@ int rtcompound_add_rtgeom(const RTCTX *ctx, RTCOMPOUND *comp, RTGEOM *geom)
   /* Empty things can't continuously join up with other things */
   if ( rtgeom_is_empty(ctx, geom) )
   {
-    RTDEBUG(4, "Got an empty component for a compound curve!");
+    RTDEBUG(ctx, 4, "Got an empty component for a compound curve!");
     return RT_FAILURE;
   }
 
@@ -115,8 +115,8 @@ int rtcompound_add_rtgeom(const RTCTX *ctx, RTCOMPOUND *comp, RTGEOM *geom)
 
     if ( !(FP_EQUALS(first.x,last.x) && FP_EQUALS(first.y,last.y)) )
     {
-      RTDEBUG(4, "Components don't join up end-to-end!");
-      RTDEBUGF(4, "first pt (%g %g %g %g) last pt (%g %g %g %g)", first.x, first.y, first.z, first.m, last.x, last.y, last.z, last.m);
+      RTDEBUG(ctx, 4, "Components don't join up end-to-end!");
+      RTDEBUGF(ctx, 4, "first pt (%g %g %g %g) last pt (%g %g %g %g)", first.x, first.y, first.z, first.m, last.x, last.y, last.z, last.m);
       return RT_FAILURE;
     }
   }
diff --git a/src/rtcurvepoly.c b/src/rtcurvepoly.c
index 59b6702..8288757 100644
--- a/src/rtcurvepoly.c
+++ b/src/rtcurvepoly.c
@@ -77,21 +77,21 @@ int rtcurvepoly_add_ring(const RTCTX *ctx, RTCURVEPOLY *poly, RTGEOM *ring)
   /* Can't do anything with NULLs */
   if( ! poly || ! ring )
   {
-    RTDEBUG(4,"NULL inputs!!! quitting");
+    RTDEBUG(ctx, 4,"NULL inputs!!! quitting");
     return RT_FAILURE;
   }
 
   /* Check that we're not working with garbage */
   if ( poly->rings == NULL && (poly->nrings || poly->maxrings) )
   {
-    RTDEBUG(4,"mismatched nrings/maxrings");
+    RTDEBUG(ctx, 4,"mismatched nrings/maxrings");
     rterror(ctx, "Curvepolygon is in inconsistent state. Null memory but non-zero collection counts.");
   }
 
   /* Check that we're adding an allowed ring type */
   if ( ! ( ring->type == RTLINETYPE || ring->type == RTCIRCSTRINGTYPE || ring->type == RTCOMPOUNDTYPE ) )
   {
-    RTDEBUGF(4,"got incorrect ring type: %s",rttype_name(ctx, ring->type));
+    RTDEBUGF(ctx, 4,"got incorrect ring type: %s",rttype_name(ctx, ring->type));
     return RT_FAILURE;
   }
 
@@ -116,7 +116,7 @@ int rtcurvepoly_add_ring(const RTCTX *ctx, RTCURVEPOLY *poly, RTGEOM *ring)
   {
     if ( poly->rings[i] == ring )
     {
-      RTDEBUGF(4, "Found duplicate geometry in collection %p == %p", poly->rings[i], ring);
+      RTDEBUGF(ctx, 4, "Found duplicate geometry in collection %p == %p", poly->rings[i], ring);
       return RT_SUCCESS;
     }
   }
diff --git a/src/rtgeodetic.c b/src/rtgeodetic.c
index aae4887..6a7ef7d 100644
--- a/src/rtgeodetic.c
+++ b/src/rtgeodetic.c
@@ -308,20 +308,20 @@ gbox_centroid(const RTCTX *ctx, const RTGBOX* gbox, RTPOINT2D* out)
 static int gbox_check_poles(const RTCTX *ctx, RTGBOX *gbox)
 {
   int rv = RT_FALSE;
-  RTDEBUG(4, "checking poles");
-  RTDEBUGF(4, "gbox %s", gbox_to_string(ctx, gbox));
+  RTDEBUG(ctx, 4, "checking poles");
+  RTDEBUGF(ctx, 4, "gbox %s", gbox_to_string(ctx, gbox));
   /* Z axis */
   if ( gbox->xmin < 0.0 && gbox->xmax > 0.0 &&
        gbox->ymin < 0.0 && gbox->ymax > 0.0 )
   {
     if ( (gbox->zmin + gbox->zmax) > 0.0 )
     {
-      RTDEBUG(4, "enclosed positive z axis");
+      RTDEBUG(ctx, 4, "enclosed positive z axis");
       gbox->zmax = 1.0;
     }
     else
     {
-      RTDEBUG(4, "enclosed negative z axis");
+      RTDEBUG(ctx, 4, "enclosed negative z axis");
       gbox->zmin = -1.0;
     }
     rv = RT_TRUE;
@@ -333,12 +333,12 @@ static int gbox_check_poles(const RTCTX *ctx, RTGBOX *gbox)
   {
     if ( gbox->ymin + gbox->ymax > 0.0 )
     {
-      RTDEBUG(4, "enclosed positive y axis");
+      RTDEBUG(ctx, 4, "enclosed positive y axis");
       gbox->ymax = 1.0;
     }
     else
     {
-      RTDEBUG(4, "enclosed negative y axis");
+      RTDEBUG(ctx, 4, "enclosed negative y axis");
       gbox->ymin = -1.0;
     }
     rv = RT_TRUE;
@@ -350,12 +350,12 @@ static int gbox_check_poles(const RTCTX *ctx, RTGBOX *gbox)
   {
     if ( gbox->xmin + gbox->xmax > 0.0 )
     {
-      RTDEBUG(4, "enclosed positive x axis");
+      RTDEBUG(ctx, 4, "enclosed positive x axis");
       gbox->xmax = 1.0;
     }
     else
     {
-      RTDEBUG(4, "enclosed negative x axis");
+      RTDEBUG(ctx, 4, "enclosed negative x axis");
       gbox->xmin = -1.0;
     }
     rv = RT_TRUE;
@@ -667,10 +667,10 @@ edge_point_side(const RTCTX *ctx, const GEOGRAPHIC_EDGE *e, const GEOGRAPHIC_POI
   geog2cart(ctx, p, &pt);
   /* We expect the dot product of with normal with any vector in the plane to be zero */
   w = dot_product(ctx, &normal, &pt);
-  RTDEBUGF(4,"dot product %.9g",w);
+  RTDEBUGF(ctx, 4,"dot product %.9g",w);
   if ( FP_IS_ZERO(w) )
   {
-    RTDEBUG(4, "point is on plane (dot product is zero)");
+    RTDEBUG(ctx, 4, "point is on plane (dot product is zero)");
     return 0;
   }
 
@@ -766,12 +766,12 @@ int edge_point_in_cone(const RTCTX *ctx, const GEOGRAPHIC_EDGE *e, const GEOGRAP
   normalize(ctx, &vcp);
   /* The projection of start onto the center defines the minimum similarity */
   vs_dot_vcp = dot_product(ctx, &vs, &vcp);
-  RTDEBUGF(4,"vs_dot_vcp %.19g",vs_dot_vcp);
+  RTDEBUGF(ctx, 4,"vs_dot_vcp %.19g",vs_dot_vcp);
   /* The projection of candidate p onto the center */
   vp_dot_vcp = dot_product(ctx, &vp, &vcp);
-  RTDEBUGF(4,"vp_dot_vcp %.19g",vp_dot_vcp);
+  RTDEBUGF(ctx, 4,"vp_dot_vcp %.19g",vp_dot_vcp);
   /* If p is more similar than start then p is inside the cone */
-  RTDEBUGF(4,"fabs(vp_dot_vcp - vs_dot_vcp) %.39g",fabs(vp_dot_vcp - vs_dot_vcp));
+  RTDEBUGF(ctx, 4,"fabs(vp_dot_vcp - vs_dot_vcp) %.39g",fabs(vp_dot_vcp - vs_dot_vcp));
 
   /*
   ** We want to test that vp_dot_vcp is >= vs_dot_vcp but there are
@@ -788,10 +788,10 @@ int edge_point_in_cone(const RTCTX *ctx, const GEOGRAPHIC_EDGE *e, const GEOGRAP
 
   if ( vp_dot_vcp > vs_dot_vcp || fabs(vp_dot_vcp - vs_dot_vcp) < 2e-16 )
   {
-    RTDEBUG(4, "point is in cone");
+    RTDEBUG(ctx, 4, "point is in cone");
     return RT_TRUE;
   }
-  RTDEBUG(4, "point is not in cone");
+  RTDEBUG(ctx, 4, "point is not in cone");
   return RT_FALSE;
 }
 
@@ -806,9 +806,9 @@ int edge_contains_coplanar_point(const RTCTX *ctx, const GEOGRAPHIC_EDGE *e, con
   double dlon = fabs(fabs((e->start).lon) - fabs((e->end).lon));
   double slat = (e->start).lat + (e->end).lat;
 
-  RTDEBUGF(4, "e.start == GPOINT(%.6g %.6g) ", (e->start).lat, (e->start).lon);
-  RTDEBUGF(4, "e.end == GPOINT(%.6g %.6g) ", (e->end).lat, (e->end).lon);
-  RTDEBUGF(4, "p == GPOINT(%.6g %.6g) ", p->lat, p->lon);
+  RTDEBUGF(ctx, 4, "e.start == GPOINT(%.6g %.6g) ", (e->start).lat, (e->start).lon);
+  RTDEBUGF(ctx, 4, "e.end == GPOINT(%.6g %.6g) ", (e->end).lat, (e->end).lon);
+  RTDEBUGF(ctx, 4, "p == GPOINT(%.6g %.6g) ", p->lat, p->lon);
 
   /* Copy values into working registers */
   g = *e;
@@ -817,7 +817,7 @@ int edge_contains_coplanar_point(const RTCTX *ctx, const GEOGRAPHIC_EDGE *e, con
   /* Vertical plane, we need to do this calculation in latitude */
   if ( FP_EQUALS( g.start.lon, g.end.lon ) )
   {
-    RTDEBUG(4, "vertical plane, we need to do this calculation in latitude");
+    RTDEBUG(ctx, 4, "vertical plane, we need to do this calculation in latitude");
     /* Supposed to be co-planar... */
     if ( ! FP_EQUALS( q.lon, g.start.lon ) )
       return RT_FALSE;
@@ -836,7 +836,7 @@ int edge_contains_coplanar_point(const RTCTX *ctx, const GEOGRAPHIC_EDGE *e, con
   /* Over the pole, we need normalize latitude and do this calculation in latitude */
   if ( FP_EQUALS( slon, M_PI ) && ( signum(g.start.lon) != signum(g.end.lon) || FP_EQUALS(dlon, M_PI) ) )
   {
-    RTDEBUG(4, "over the pole...");
+    RTDEBUG(ctx, 4, "over the pole...");
     /* Antipodal, everything (or nothing?) is inside */
     if ( FP_EQUALS( slat, 0.0 ) )
       return RT_TRUE;
@@ -849,18 +849,18 @@ int edge_contains_coplanar_point(const RTCTX *ctx, const GEOGRAPHIC_EDGE *e, con
     if ( slat < 0.0 && FP_EQUALS(q.lat, -1.0 * M_PI_2) )
       return RT_TRUE;
 
-    RTDEBUG(4, "coplanar?...");
+    RTDEBUG(ctx, 4, "coplanar?...");
 
     /* Supposed to be co-planar... */
     if ( ! FP_EQUALS( q.lon, g.start.lon ) )
       return RT_FALSE;
 
-    RTDEBUG(4, "north or south?...");
+    RTDEBUG(ctx, 4, "north or south?...");
 
     /* Over north pole, test based on south pole */
     if ( slat > 0.0 )
     {
-      RTDEBUG(4, "over the north pole...");
+      RTDEBUG(ctx, 4, "over the north pole...");
       if ( q.lat > FP_MIN(g.start.lat, g.end.lat) )
         return RT_TRUE;
       else
@@ -869,7 +869,7 @@ int edge_contains_coplanar_point(const RTCTX *ctx, const GEOGRAPHIC_EDGE *e, con
     else
       /* Over south pole, test based on north pole */
     {
-      RTDEBUG(4, "over the south pole...");
+      RTDEBUG(ctx, 4, "over the south pole...");
       if ( q.lat < FP_MAX(g.start.lat, g.end.lat) )
         return RT_TRUE;
       else
@@ -880,7 +880,7 @@ int edge_contains_coplanar_point(const RTCTX *ctx, const GEOGRAPHIC_EDGE *e, con
   /* Dateline crossing, flip everything to the opposite hemisphere */
   else if ( slon > M_PI && ( signum(g.start.lon) != signum(g.end.lon) ) )
   {
-    RTDEBUG(4, "crosses dateline, flip longitudes...");
+    RTDEBUG(ctx, 4, "crosses dateline, flip longitudes...");
     if ( g.start.lon > 0.0 )
       g.start.lon -= M_PI;
     else
@@ -899,11 +899,11 @@ int edge_contains_coplanar_point(const RTCTX *ctx, const GEOGRAPHIC_EDGE *e, con
   if ( ( g.start.lon <= q.lon && q.lon <= g.end.lon ) ||
        ( g.end.lon <= q.lon && q.lon <= g.start.lon ) )
   {
-    RTDEBUG(4, "true, this edge contains point");
+    RTDEBUG(ctx, 4, "true, this edge contains point");
     return RT_TRUE;
   }
 
-  RTDEBUG(4, "false, this edge does not contain point");
+  RTDEBUG(ctx, 4, "false, this edge does not contain point");
   return RT_FALSE;
 }
 
@@ -952,7 +952,7 @@ double sphere_direction(const RTCTX *ctx, const GEOGRAPHIC_POINT *s, const GEOGR
     heading = 0.0;
   else if ( fabs(f) > 1.0 )
   {
-    RTDEBUGF(4, "f = %g", f);
+    RTDEBUGF(ctx, 4, "f = %g", f);
     heading = acos(f);
   }
   else
@@ -1000,10 +1000,10 @@ int edge_contains_point(const RTCTX *ctx, const GEOGRAPHIC_EDGE *e, const GEOGRA
   if ( edge_point_in_cone(ctx, e, p) && edge_point_on_plane(ctx, e, p) )
     /*  if ( edge_contains_coplanar_point(ctx, e, p) && edge_point_on_plane(ctx, e, p) ) */
   {
-    RTDEBUG(4, "point is on edge");
+    RTDEBUG(ctx, 4, "point is on edge");
     return RT_TRUE;
   }
-  RTDEBUG(4, "point is not on edge");
+  RTDEBUG(ctx, 4, "point is not on edge");
   return RT_FALSE;
 }
 
@@ -1014,7 +1014,7 @@ double z_to_latitude(const RTCTX *ctx, double z, int top)
 {
   double sign = signum(z);
   double tlat = acos(z);
-  RTDEBUGF(4, "inputs: z(%.8g) sign(%.8g) tlat(%.8g)", z, sign, tlat);
+  RTDEBUGF(ctx, 4, "inputs: z(%.8g) sign(%.8g) tlat(%.8g)", z, sign, tlat);
   if (FP_IS_ZERO(z))
   {
     if (top) return M_PI_2;
@@ -1028,7 +1028,7 @@ double z_to_latitude(const RTCTX *ctx, double z, int top)
   {
     tlat = sign * tlat;
   }
-  RTDEBUGF(4, "output: tlat(%.8g)", tlat);
+  RTDEBUGF(ctx, 4, "output: tlat(%.8g)", tlat);
   return tlat;
 }
 
@@ -1041,19 +1041,19 @@ int clairaut_cartesian(const RTCTX *ctx, const POINT3D *start, const POINT3D *en
 {
   POINT3D t1, t2;
   GEOGRAPHIC_POINT vN1, vN2;
-  RTDEBUG(4,"entering function");
+  RTDEBUG(ctx, 4,"entering function");
   unit_normal(ctx, start, end, &t1);
   unit_normal(ctx, end, start, &t2);
-  RTDEBUGF(4, "unit normal t1 == POINT(%.8g %.8g %.8g)", t1.x, t1.y, t1.z);
-  RTDEBUGF(4, "unit normal t2 == POINT(%.8g %.8g %.8g)", t2.x, t2.y, t2.z);
+  RTDEBUGF(ctx, 4, "unit normal t1 == POINT(%.8g %.8g %.8g)", t1.x, t1.y, t1.z);
+  RTDEBUGF(ctx, 4, "unit normal t2 == POINT(%.8g %.8g %.8g)", t2.x, t2.y, t2.z);
   cart2geog(ctx, &t1, &vN1);
   cart2geog(ctx, &t2, &vN2);
   g_top->lat = z_to_latitude(ctx, t1.z,RT_TRUE);
   g_top->lon = vN2.lon;
   g_bottom->lat = z_to_latitude(ctx, t2.z,RT_FALSE);
   g_bottom->lon = vN1.lon;
-  RTDEBUGF(4, "clairaut top == GPOINT(%.6g %.6g)", g_top->lat, g_top->lon);
-  RTDEBUGF(4, "clairaut bottom == GPOINT(%.6g %.6g)", g_bottom->lat, g_bottom->lon);
+  RTDEBUGF(ctx, 4, "clairaut top == GPOINT(%.6g %.6g)", g_top->lat, g_top->lon);
+  RTDEBUGF(ctx, 4, "clairaut bottom == GPOINT(%.6g %.6g)", g_bottom->lat, g_bottom->lon);
   return RT_SUCCESS;
 }
 
@@ -1066,21 +1066,21 @@ int clairaut_geographic(const RTCTX *ctx, const GEOGRAPHIC_POINT *start, const G
 {
   POINT3D t1, t2;
   GEOGRAPHIC_POINT vN1, vN2;
-  RTDEBUG(4,"entering function");
+  RTDEBUG(ctx, 4,"entering function");
   robust_cross_product(ctx, start, end, &t1);
   normalize(ctx, &t1);
   robust_cross_product(ctx, end, start, &t2);
   normalize(ctx, &t2);
-  RTDEBUGF(4, "unit normal t1 == POINT(%.8g %.8g %.8g)", t1.x, t1.y, t1.z);
-  RTDEBUGF(4, "unit normal t2 == POINT(%.8g %.8g %.8g)", t2.x, t2.y, t2.z);
+  RTDEBUGF(ctx, 4, "unit normal t1 == POINT(%.8g %.8g %.8g)", t1.x, t1.y, t1.z);
+  RTDEBUGF(ctx, 4, "unit normal t2 == POINT(%.8g %.8g %.8g)", t2.x, t2.y, t2.z);
   cart2geog(ctx, &t1, &vN1);
   cart2geog(ctx, &t2, &vN2);
   g_top->lat = z_to_latitude(ctx, t1.z,RT_TRUE);
   g_top->lon = vN2.lon;
   g_bottom->lat = z_to_latitude(ctx, t2.z,RT_FALSE);
   g_bottom->lon = vN1.lon;
-  RTDEBUGF(4, "clairaut top == GPOINT(%.6g %.6g)", g_top->lat, g_top->lon);
-  RTDEBUGF(4, "clairaut bottom == GPOINT(%.6g %.6g)", g_bottom->lat, g_bottom->lon);
+  RTDEBUGF(ctx, 4, "clairaut top == GPOINT(%.6g %.6g)", g_top->lat, g_top->lon);
+  RTDEBUGF(ctx, 4, "clairaut bottom == GPOINT(%.6g %.6g)", g_bottom->lat, g_bottom->lon);
   return RT_SUCCESS;
 }
 
@@ -1091,11 +1091,11 @@ int clairaut_geographic(const RTCTX *ctx, const GEOGRAPHIC_POINT *start, const G
 int edge_intersection(const RTCTX *ctx, const GEOGRAPHIC_EDGE *e1, const GEOGRAPHIC_EDGE *e2, GEOGRAPHIC_POINT *g)
 {
   POINT3D ea, eb, v;
-  RTDEBUGF(4, "e1 start(%.20g %.20g) end(%.20g %.20g)", e1->start.lat, e1->start.lon, e1->end.lat, e1->end.lon);
-  RTDEBUGF(4, "e2 start(%.20g %.20g) end(%.20g %.20g)", e2->start.lat, e2->start.lon, e2->end.lat, e2->end.lon);
+  RTDEBUGF(ctx, 4, "e1 start(%.20g %.20g) end(%.20g %.20g)", e1->start.lat, e1->start.lon, e1->end.lat, e1->end.lon);
+  RTDEBUGF(ctx, 4, "e2 start(%.20g %.20g) end(%.20g %.20g)", e2->start.lat, e2->start.lon, e2->end.lat, e2->end.lon);
 
-  RTDEBUGF(4, "e1 start(%.20g %.20g) end(%.20g %.20g)", rad2deg(e1->start.lon), rad2deg(e1->start.lat), rad2deg(e1->end.lon), rad2deg(e1->end.lat));
-  RTDEBUGF(4, "e2 start(%.20g %.20g) end(%.20g %.20g)", rad2deg(e2->start.lon), rad2deg(e2->start.lat), rad2deg(e2->end.lon), rad2deg(e2->end.lat));
+  RTDEBUGF(ctx, 4, "e1 start(%.20g %.20g) end(%.20g %.20g)", rad2deg(e1->start.lon), rad2deg(e1->start.lat), rad2deg(e1->end.lon), rad2deg(e1->end.lat));
+  RTDEBUGF(ctx, 4, "e2 start(%.20g %.20g) end(%.20g %.20g)", rad2deg(e2->start.lon), rad2deg(e2->start.lat), rad2deg(e2->end.lon), rad2deg(e2->end.lat));
 
   if ( geographic_point_equals(ctx, &(e1->start), &(e2->start)) )
   {
@@ -1122,12 +1122,12 @@ int edge_intersection(const RTCTX *ctx, const GEOGRAPHIC_EDGE *e1, const GEOGRAP
   normalize(ctx, &ea);
   robust_cross_product(ctx, &(e2->start), &(e2->end), &eb);
   normalize(ctx, &eb);
-  RTDEBUGF(4, "e1 cross product == POINT(%.12g %.12g %.12g)", ea.x, ea.y, ea.z);
-  RTDEBUGF(4, "e2 cross product == POINT(%.12g %.12g %.12g)", eb.x, eb.y, eb.z);
-  RTDEBUGF(4, "fabs(dot_product(ctx, ea, eb)) == %.14g", fabs(dot_product(ctx, &ea, &eb)));
+  RTDEBUGF(ctx, 4, "e1 cross product == POINT(%.12g %.12g %.12g)", ea.x, ea.y, ea.z);
+  RTDEBUGF(ctx, 4, "e2 cross product == POINT(%.12g %.12g %.12g)", eb.x, eb.y, eb.z);
+  RTDEBUGF(ctx, 4, "fabs(dot_product(ctx, ea, eb)) == %.14g", fabs(dot_product(ctx, &ea, &eb)));
   if ( FP_EQUALS(fabs(dot_product(ctx, &ea, &eb)), 1.0) )
   {
-    RTDEBUGF(4, "parallel edges found! dot_product = %.12g", dot_product(ctx, &ea, &eb));
+    RTDEBUGF(ctx, 4, "parallel edges found! dot_product = %.12g", dot_product(ctx, &ea, &eb));
     /* Parallel (maybe equal) edges! */
     /* Hack alert, only returning ONE end of the edge right now, most do better later. */
     /* Hack alart #2, returning a value of 2 to indicate a co-linear crossing event. */
@@ -1153,18 +1153,18 @@ int edge_intersection(const RTCTX *ctx, const GEOGRAPHIC_EDGE *e1, const GEOGRAP
     }
   }
   unit_normal(ctx, &ea, &eb, &v);
-  RTDEBUGF(4, "v == POINT(%.12g %.12g %.12g)", v.x, v.y, v.z);
+  RTDEBUGF(ctx, 4, "v == POINT(%.12g %.12g %.12g)", v.x, v.y, v.z);
   g->lat = atan2(v.z, sqrt(v.x * v.x + v.y * v.y));
   g->lon = atan2(v.y, v.x);
-  RTDEBUGF(4, "g == GPOINT(%.12g %.12g)", g->lat, g->lon);
-  RTDEBUGF(4, "g == POINT(%.12g %.12g)", rad2deg(g->lon), rad2deg(g->lat));
+  RTDEBUGF(ctx, 4, "g == GPOINT(%.12g %.12g)", g->lat, g->lon);
+  RTDEBUGF(ctx, 4, "g == POINT(%.12g %.12g)", rad2deg(g->lon), rad2deg(g->lat));
   if ( edge_contains_point(ctx, e1, g) && edge_contains_point(ctx, e2, g) )
   {
     return RT_TRUE;
   }
   else
   {
-    RTDEBUG(4, "flipping point to other side of sphere");
+    RTDEBUG(ctx, 4, "flipping point to other side of sphere");
     g->lat = -1.0 * g->lat;
     g->lon = g->lon + M_PI;
     if ( g->lon > M_PI )
@@ -1316,7 +1316,7 @@ int edge_calculate_gbox_slow(const RTCTX *ctx, const GEOGRAPHIC_EDGE *e, RTGBOX
   /* Edge is zero length, just return the naive box */
   if ( FP_IS_ZERO(distance) )
   {
-    RTDEBUG(4, "edge is zero length. returning");
+    RTDEBUG(ctx, 4, "edge is zero length. returning");
     geog2cart(ctx, &(e->start), &start);
     geog2cart(ctx, &(e->end), &end);
     gbox_init_point3d(ctx, &start, gbox);
@@ -1328,7 +1328,7 @@ int edge_calculate_gbox_slow(const RTCTX *ctx, const GEOGRAPHIC_EDGE *e, RTGBOX
      set the box to contain the whole world and return */
   if ( FP_EQUALS(distance, M_PI) )
   {
-    RTDEBUG(4, "edge is antipodal. setting to maximum size box, and returning");
+    RTDEBUG(ctx, 4, "edge is antipodal. setting to maximum size box, and returning");
     gbox->xmin = gbox->ymin = gbox->zmin = -1.0;
     gbox->xmax = gbox->ymax = gbox->zmax = 1.0;
     return RT_SUCCESS;
@@ -1510,20 +1510,20 @@ void gbox_pt_outside(const RTCTX *ctx, const RTGBOX *gbox, RTPOINT2D *pt_outside
     corners[7].y = ge.ymax;
     corners[7].z = ge.zmax;
 
-    RTDEBUG(4, "trying to use a box corner point...");
+    RTDEBUG(ctx, 4, "trying to use a box corner point...");
     for ( i = 0; i < 8; i++ )
     {
       normalize(ctx, &(corners[i]));
-      RTDEBUGF(4, "testing corner %d: POINT(%.8g %.8g %.8g)", i, corners[i].x, corners[i].y, corners[i].z);
+      RTDEBUGF(ctx, 4, "testing corner %d: POINT(%.8g %.8g %.8g)", i, corners[i].x, corners[i].y, corners[i].z);
       if ( ! gbox_contains_point3d(ctx, gbox, &(corners[i])) )
       {
-        RTDEBUGF(4, "corner %d is outside our gbox", i);
+        RTDEBUGF(ctx, 4, "corner %d is outside our gbox", i);
         pt = corners[i];
         normalize(ctx, &pt);
         cart2geog(ctx, &pt, &g);
         pt_outside->x = rad2deg(g.lon);
         pt_outside->y = rad2deg(g.lat);
-        RTDEBUGF(4, "returning POINT(%.8g %.8g) as outside point", pt_outside->x, pt_outside->y);
+        RTDEBUGF(ctx, 4, "returning POINT(%.8g %.8g) as outside point", pt_outside->x, pt_outside->y);
         return;
       }
     }
@@ -1882,18 +1882,18 @@ static double ptarray_distance_spheroid(const RTCTX *ctx, const RTPOINTARRAY *pa
       geographic_point_init(ctx, p->x, p->y, &(e2.end));
       geog2cart(ctx, &(e2.end), &B2);
 
-      RTDEBUGF(4, "e1.start == GPOINT(%.6g %.6g) ", e1.start.lat, e1.start.lon);
-      RTDEBUGF(4, "e1.end == GPOINT(%.6g %.6g) ", e1.end.lat, e1.end.lon);
-      RTDEBUGF(4, "e2.start == GPOINT(%.6g %.6g) ", e2.start.lat, e2.start.lon);
-      RTDEBUGF(4, "e2.end == GPOINT(%.6g %.6g) ", e2.end.lat, e2.end.lon);
+      RTDEBUGF(ctx, 4, "e1.start == GPOINT(%.6g %.6g) ", e1.start.lat, e1.start.lon);
+      RTDEBUGF(ctx, 4, "e1.end == GPOINT(%.6g %.6g) ", e1.end.lat, e1.end.lon);
+      RTDEBUGF(ctx, 4, "e2.start == GPOINT(%.6g %.6g) ", e2.start.lat, e2.start.lon);
+      RTDEBUGF(ctx, 4, "e2.end == GPOINT(%.6g %.6g) ", e2.end.lat, e2.end.lon);
 
       if ( check_intersection && edge_intersects(ctx, &A1, &A2, &B1, &B2) )
       {
-        RTDEBUG(4,"edge intersection! returning 0.0");
+        RTDEBUG(ctx, 4,"edge intersection! returning 0.0");
         return 0.0;
       }
       d = s->radius * edge_distance_to_edge(ctx, &e1, &e2, &g1, &g2);
-      RTDEBUGF(4,"got edge_distance_to_edge %.8g", d);
+      RTDEBUGF(ctx, 4,"got edge_distance_to_edge %.8g", d);
 
       if ( d < distance )
       {
@@ -1924,7 +1924,7 @@ static double ptarray_distance_spheroid(const RTCTX *ctx, const RTPOINTARRAY *pa
     e1.start = e1.end;
     A1 = A2;
   }
-  RTDEBUGF(4,"finished all loops, returning %.8g", distance);
+  RTDEBUGF(ctx, 4,"finished all loops, returning %.8g", distance);
 
   if ( use_sphere )
     return distance;
@@ -2037,7 +2037,7 @@ RTPOINT* rtgeom_project_spheroid(const RTCTX *ctx, const RTPOINT *r, const SPHER
   /* Try the projection */
   if( spheroid_project(ctx, &geo_source, spheroid, distance, azimuth, &geo_dest) == RT_FAILURE )
   {
-    RTDEBUGF(3, "Unable to project from (%g %g) with azimuth %g and distance %g", x, y, azimuth, distance);
+    RTDEBUGF(ctx, 3, "Unable to project from (%g %g) with azimuth %g and distance %g", x, y, azimuth, distance);
     rterror(ctx, "Unable to project from (%g %g) with azimuth %g and distance %g", x, y, azimuth, distance);
     return NULL;
   }
@@ -2105,7 +2105,7 @@ double rtgeom_distance_spheroid(const RTCTX *ctx, const RTGEOM *rtgeom1, const R
   assert(rtgeom1);
   assert(rtgeom2);
 
-  RTDEBUGF(4, "entered function, tolerance %.8g", tolerance);
+  RTDEBUGF(ctx, 4, "entered function, tolerance %.8g", tolerance);
 
   /* What's the distance to an empty geometry? We don't know.
      Return a negative number so the caller can catch this case. */
@@ -2214,25 +2214,25 @@ double rtgeom_distance_spheroid(const RTCTX *ctx, const RTGEOM *rtgeom1, const R
     }
     p = rt_getPoint2d_cp(ctx, rtline->points, 0);
 
-    RTDEBUG(4, "checking if a point of line is in polygon");
+    RTDEBUG(ctx, 4, "checking if a point of line is in polygon");
 
     /* Point in polygon implies zero distance */
     if ( rtpoly_covers_point2d(ctx, rtpoly, p) )
       return 0.0;
 
-    RTDEBUG(4, "checking ring distances");
+    RTDEBUG(ctx, 4, "checking ring distances");
 
     /* Not contained, so what's the actual distance? */
     for ( i = 0; i < rtpoly->nrings; i++ )
     {
       double ring_distance = ptarray_distance_spheroid(ctx, rtpoly->rings[i], rtline->points, spheroid, tolerance, check_intersection);
-      RTDEBUGF(4, "ring[%d] ring_distance = %.8g", i, ring_distance);
+      RTDEBUGF(ctx, 4, "ring[%d] ring_distance = %.8g", i, ring_distance);
       if ( ring_distance < distance )
         distance = ring_distance;
       if ( distance < tolerance )
         return distance;
     }
-    RTDEBUGF(4, "all rings checked, returning distance = %.8g", distance);
+    RTDEBUGF(ctx, 4, "all rings checked, returning distance = %.8g", distance);
     return distance;
 
   }
@@ -2412,7 +2412,7 @@ int rtpoly_covers_point2d(const RTCTX *ctx, const RTPOLY *poly, const RTPOINT2D
   /* Nulls and empties don't contain anything! */
   if ( ! poly || rtgeom_is_empty(ctx, (RTGEOM*)poly) )
   {
-    RTDEBUG(4,"returning false, geometry is empty or null");
+    RTDEBUG(ctx, 4,"returning false, geometry is empty or null");
     return RT_FALSE;
   }
 
@@ -2427,45 +2427,45 @@ int rtpoly_covers_point2d(const RTCTX *ctx, const RTPOLY *poly, const RTPOINT2D
   geog2cart(ctx, &gpt_to_test, &p);
   if ( ! gbox_contains_point3d(ctx, &gbox, &p) )
   {
-    RTDEBUG(4, "the point is not in the box!");
+    RTDEBUG(ctx, 4, "the point is not in the box!");
     return RT_FALSE;
   }
 
   /* Calculate our outside point from the gbox */
   gbox_pt_outside(ctx, &gbox, &pt_outside);
 
-  RTDEBUGF(4, "pt_outside POINT(%.18g %.18g)", pt_outside.x, pt_outside.y);
-  RTDEBUGF(4, "pt_to_test POINT(%.18g %.18g)", pt_to_test->x, pt_to_test->y);
-  RTDEBUGF(4, "polygon %s", rtgeom_to_ewkt(ctx, (RTGEOM*)poly));
-  RTDEBUGF(4, "gbox %s", gbox_to_string(ctx, &gbox));
+  RTDEBUGF(ctx, 4, "pt_outside POINT(%.18g %.18g)", pt_outside.x, pt_outside.y);
+  RTDEBUGF(ctx, 4, "pt_to_test POINT(%.18g %.18g)", pt_to_test->x, pt_to_test->y);
+  RTDEBUGF(ctx, 4, "polygon %s", rtgeom_to_ewkt(ctx, (RTGEOM*)poly));
+  RTDEBUGF(ctx, 4, "gbox %s", gbox_to_string(ctx, &gbox));
 
   /* Not in outer ring? We're done! */
   if ( ! ptarray_contains_point_sphere(ctx, poly->rings[0], &pt_outside, pt_to_test) )
   {
-    RTDEBUG(4,"returning false, point is outside ring");
+    RTDEBUG(ctx, 4,"returning false, point is outside ring");
     return RT_FALSE;
   }
 
-  RTDEBUGF(4, "testing %d rings", poly->nrings);
+  RTDEBUGF(ctx, 4, "testing %d rings", poly->nrings);
 
   /* But maybe point is in a hole... */
   for ( i = 1; i < poly->nrings; i++ )
   {
-    RTDEBUGF(4, "ring test loop %d", i);
+    RTDEBUGF(ctx, 4, "ring test loop %d", i);
     /* Count up hole containment. Odd => outside boundary. */
     if ( ptarray_contains_point_sphere(ctx, poly->rings[i], &pt_outside, pt_to_test) )
       in_hole_count++;
   }
 
-  RTDEBUGF(4, "in_hole_count == %d", in_hole_count);
+  RTDEBUGF(ctx, 4, "in_hole_count == %d", in_hole_count);
 
   if ( in_hole_count % 2 )
   {
-    RTDEBUG(4,"returning false, inner ring containment count is odd");
+    RTDEBUG(ctx, 4,"returning false, inner ring containment count is odd");
     return RT_FALSE;
   }
 
-  RTDEBUG(4,"returning true, inner ring containment count is even");
+  RTDEBUG(ctx, 4,"returning true, inner ring containment count is even");
   return RT_TRUE;
 }
 
@@ -2630,7 +2630,7 @@ static int rtcollection_calculate_gbox_geodetic(const RTCTX *ctx, const RTCOLLEC
 int rtgeom_calculate_gbox_geodetic(const RTCTX *ctx, const RTGEOM *geom, RTGBOX *gbox)
 {
   int result = RT_FAILURE;
-  RTDEBUGF(4, "got type %d", geom->type);
+  RTDEBUGF(ctx, 4, "got type %d", geom->type);
 
   /* Add a geodetic flag to the incoming gbox */
   gbox->flags = gflags(ctx, RTFLAGS_GET_Z(geom->flags),RTFLAGS_GET_M(geom->flags),1);
@@ -3238,8 +3238,8 @@ int ptarray_contains_point_sphere(const RTCTX *ctx, const RTPOINTARRAY *pa, cons
   /* Walk every edge and see if the stab line hits it */
   for ( i = 1; i < pa->npoints; i++ )
   {
-    RTDEBUGF(4, "testing edge (%d)", i);
-    RTDEBUGF(4, "  start point == POINT(%.12g %.12g)", p.x, p.y);
+    RTDEBUGF(ctx, 4, "testing edge (%d)", i);
+    RTDEBUGF(ctx, 4, "  start point == POINT(%.12g %.12g)", p.x, p.y);
 
     /* Read next point. */
     rt_getPoint2d_p(ctx, pa, i, &p);
@@ -3275,25 +3275,25 @@ int ptarray_contains_point_sphere(const RTCTX *ctx, const RTPOINTARRAY *pa, cons
       if ( inter & PIR_B_TOUCH_RIGHT || inter & PIR_COLINEAR )
       {
         /* Do nothing, to avoid double counts. */
-        RTDEBUGF(4,"    edge (%d) crossed, disregarding to avoid double count", i, count);
+        RTDEBUGF(ctx, 4,"    edge (%d) crossed, disregarding to avoid double count", i, count);
       }
       else
       {
         /* Increment crossingn count. */
         count++;
-        RTDEBUGF(4,"    edge (%d) crossed, count == %d", i, count);
+        RTDEBUGF(ctx, 4,"    edge (%d) crossed, count == %d", i, count);
       }
     }
     else
     {
-      RTDEBUGF(4,"    edge (%d) did not cross", i);
+      RTDEBUGF(ctx, 4,"    edge (%d) did not cross", i);
     }
 
     /* Increment to next edge */
     E1 = E2;
   }
 
-  RTDEBUGF(4,"final count == %d", count);
+  RTDEBUGF(ctx, 4,"final count == %d", count);
 
   /* An odd number of crossings implies containment! */
   if ( count % 2 )
diff --git a/src/rtgeom.c b/src/rtgeom.c
index c534d43..e1f2386 100644
--- a/src/rtgeom.c
+++ b/src/rtgeom.c
@@ -388,12 +388,12 @@ rtgeom_release(const RTCTX *ctx, RTGEOM *rtgeom)
   if ( ! rtgeom )
     rterror(ctx, "rtgeom_release: someone called on 0x0");
 
-  RTDEBUGF(3, "releasing type %s", rttype_name(ctx, rtgeom->type));
+  RTDEBUGF(ctx, 3, "releasing type %s", rttype_name(ctx, rtgeom->type));
 
   /* Drop bounding box (artays a copy) */
   if ( rtgeom->bbox )
   {
-    RTDEBUGF(3, "rtgeom_release: releasing bbox. %p", rtgeom->bbox);
+    RTDEBUGF(ctx, 3, "rtgeom_release: releasing bbox. %p", rtgeom->bbox);
     rtfree(ctx, rtgeom->bbox);
   }
   rtfree(ctx, rtgeom);
@@ -408,7 +408,7 @@ rtgeom_release(const RTCTX *ctx, RTGEOM *rtgeom)
 RTGEOM *
 rtgeom_clone(const RTCTX *ctx, const RTGEOM *rtgeom)
 {
-  RTDEBUGF(2, "rtgeom_clone called with %p, %s",
+  RTDEBUGF(ctx, 2, "rtgeom_clone called with %p, %s",
            rtgeom, rttype_name(ctx, rtgeom->type));
 
   switch (rtgeom->type)
@@ -446,7 +446,7 @@ rtgeom_clone(const RTCTX *ctx, const RTGEOM *rtgeom)
 RTGEOM *
 rtgeom_clone_deep(const RTCTX *ctx, const RTGEOM *rtgeom)
 {
-  RTDEBUGF(2, "rtgeom_clone called with %p, %s",
+  RTDEBUGF(ctx, 2, "rtgeom_clone called with %p, %s",
            rtgeom, rttype_name(ctx, rtgeom->type));
 
   switch (rtgeom->type)
@@ -508,20 +508,20 @@ rtgeom_to_ewkt(const RTCTX *ctx, const RTGEOM *rtgeom)
 char
 rtgeom_same(const RTCTX *ctx, const RTGEOM *rtgeom1, const RTGEOM *rtgeom2)
 {
-  RTDEBUGF(2, "rtgeom_same(ctx, %s, %s) called",
+  RTDEBUGF(ctx, 2, "rtgeom_same(ctx, %s, %s) called",
            rttype_name(ctx, rtgeom1->type),
            rttype_name(ctx, rtgeom2->type));
 
   if ( rtgeom1->type != rtgeom2->type )
   {
-    RTDEBUG(3, " type differ");
+    RTDEBUG(ctx, 3, " type differ");
 
     return RT_FALSE;
   }
 
   if ( RTFLAGS_GET_ZM(rtgeom1->flags) != RTFLAGS_GET_ZM(rtgeom2->flags) )
   {
-    RTDEBUG(3, " ZM flags differ");
+    RTDEBUG(ctx, 3, " ZM flags differ");
 
     return RT_FALSE;
   }
@@ -532,7 +532,7 @@ rtgeom_same(const RTCTX *ctx, const RTGEOM *rtgeom1, const RTGEOM *rtgeom2)
     /*rtnotice(ctx, "bbox1:%p, bbox2:%p", rtgeom1->bbox, rtgeom2->bbox);*/
     if ( ! gbox_same(ctx, rtgeom1->bbox, rtgeom2->bbox) )
     {
-      RTDEBUG(3, " bounding boxes differ");
+      RTDEBUG(ctx, 3, " bounding boxes differ");
 
       return RT_FALSE;
     }
@@ -1067,7 +1067,7 @@ void rtgeom_free(const RTCTX *ctx, RTGEOM *rtgeom)
   /* There's nothing here to free... */
   if( ! rtgeom ) return;
 
-  RTDEBUGF(5,"freeing a %s",rttype_name(ctx, rtgeom->type));
+  RTDEBUGF(ctx, 5,"freeing a %s",rttype_name(ctx, rtgeom->type));
 
   switch (rtgeom->type)
   {
@@ -1158,7 +1158,7 @@ int rtgeom_count_vertices(const RTCTX *ctx, const RTGEOM *geom)
   /* Null? Zero. */
   if( ! geom ) return 0;
 
-  RTDEBUGF(4, "rtgeom_count_vertices got type %s",
+  RTDEBUGF(ctx, 4, "rtgeom_count_vertices got type %s",
            rttype_name(ctx, geom->type));
 
   /* Empty? Zero. */
@@ -1194,7 +1194,7 @@ int rtgeom_count_vertices(const RTCTX *ctx, const RTGEOM *geom)
             __func__, rttype_name(ctx, geom->type));
     break;
   }
-  RTDEBUGF(3, "counted %d vertices", result);
+  RTDEBUGF(ctx, 3, "counted %d vertices", result);
   return result;
 }
 
@@ -1209,7 +1209,7 @@ int rtgeom_dimension(const RTCTX *ctx, const RTGEOM *geom)
   /* Null? Zero. */
   if( ! geom ) return -1;
 
-  RTDEBUGF(4, "rtgeom_dimension got type %s",
+  RTDEBUGF(ctx, 4, "rtgeom_dimension got type %s",
            rttype_name(ctx, geom->type));
 
   /* Empty? Zero. */
@@ -1304,14 +1304,14 @@ int rtgeom_count_rings(const RTCTX *ctx, const RTGEOM *geom)
     rterror(ctx, "rtgeom_count_rings: unsupported input geometry type: %s", rttype_name(ctx, geom->type));
     break;
   }
-  RTDEBUGF(3, "counted %d rings", result);
+  RTDEBUGF(ctx, 3, "counted %d rings", result);
   return result;
 }
 
 int rtgeom_is_empty(const RTCTX *ctx, const RTGEOM *geom)
 {
   int result = RT_FALSE;
-  RTDEBUGF(4, "rtgeom_is_empty: got type %s",
+  RTDEBUGF(ctx, 4, "rtgeom_is_empty: got type %s",
            rttype_name(ctx, geom->type));
 
   switch (geom->type)
@@ -1377,7 +1377,7 @@ extern int rtgeom_dimensionality(const RTCTX *ctx, RTGEOM *geom)
 {
   int dim;
 
-  RTDEBUGF(3, "rtgeom_dimensionality got type %s",
+  RTDEBUGF(ctx, 3, "rtgeom_dimensionality got type %s",
            rttype_name(ctx, geom->type));
 
   switch (geom->type)
@@ -1420,7 +1420,7 @@ extern int rtgeom_dimensionality(const RTCTX *ctx, RTGEOM *geom)
 
 extern RTGEOM* rtgeom_remove_repeated_points(const RTCTX *ctx, const RTGEOM *in, double tolerance)
 {
-  RTDEBUGF(4, "rtgeom_remove_repeated_points got type %s",
+  RTDEBUGF(ctx, 4, "rtgeom_remove_repeated_points got type %s",
            rttype_name(ctx, in->type));
 
   if(rtgeom_is_empty(ctx, in))
@@ -1490,7 +1490,7 @@ void rtgeom_swap_ordinates(const RTCTX *ctx, RTGEOM *in, RTORD o1, RTORD o2)
 
   /* TODO: check for rtgeom NOT having the specified dimension ? */
 
-  RTDEBUGF(4, "rtgeom_flip_coordinates, got type: %s",
+  RTDEBUGF(ctx, 4, "rtgeom_flip_coordinates, got type: %s",
            rttype_name(ctx, in->type));
 
   switch (in->type)
@@ -1554,7 +1554,7 @@ void rtgeom_set_srid(const RTCTX *ctx, RTGEOM *geom, int32_t srid)
 {
   int i;
 
-  RTDEBUGF(4,"entered with srid=%d",srid);
+  RTDEBUGF(ctx, 4,"entered with srid=%d",srid);
 
   geom->srid = srid;
 
diff --git a/src/rtgeom_api.c b/src/rtgeom_api.c
index c361fcf..c698ee1 100644
--- a/src/rtgeom_api.c
+++ b/src/rtgeom_api.c
@@ -256,13 +256,13 @@ rt_getPoint4d_p(const RTCTX *ctx, const RTPOINTARRAY *pa, int n, RTPOINT4D *op)
   }
 #endif
 
-  RTDEBUG(4, "rt_getPoint4d_p called.");
+  RTDEBUG(ctx, 4, "rt_getPoint4d_p called.");
 
   /* Get a pointer to nth point offset and zmflag */
   ptr=rt_getPoint_internal(ctx, pa, n);
   zmflag=RTFLAGS_GET_ZM(pa->flags);
 
-  RTDEBUGF(4, "ptr %p, zmflag %d", ptr, zmflag);
+  RTDEBUGF(ctx, 4, "ptr %p, zmflag %d", ptr, zmflag);
 
   switch (zmflag)
   {
@@ -339,12 +339,12 @@ rt_getPoint3dz_p(const RTCTX *ctx, const RTPOINTARRAY *pa, int n, RTPOINT3DZ *op
 
   if ( (n<0) || (n>=pa->npoints))
   {
-    RTDEBUGF(4, "%d out of numpoint range (%d)", n, pa->npoints);
+    RTDEBUGF(ctx, 4, "%d out of numpoint range (%d)", n, pa->npoints);
     return 0; /*error */
   }
 #endif
 
-  RTDEBUGF(2, "rt_getPoint3dz_p called on array of %d-dimensions / %u pts",
+  RTDEBUGF(ctx, 2, "rt_getPoint3dz_p called on array of %d-dimensions / %u pts",
            RTFLAGS_NDIMS(pa->flags), pa->npoints);
 
   /* Get a pointer to nth point offset */
@@ -395,7 +395,7 @@ rt_getPoint3dm_p(const RTCTX *ctx, const RTPOINTARRAY *pa, int n, RTPOINT3DM *op
   }
 #endif
 
-  RTDEBUGF(2, "rt_getPoint3dm_p(ctx, %d) called on array of %d-dimensions / %u pts",
+  RTDEBUGF(ctx, 2, "rt_getPoint3dm_p(ctx, %d) called on array of %d-dimensions / %u pts",
            n, RTFLAGS_NDIMS(pa->flags), pa->npoints);
 
 
diff --git a/src/rtgeom_debug.c b/src/rtgeom_debug.c
index 225d2f2..e3bfe5f 100644
--- a/src/rtgeom_debug.c
+++ b/src/rtgeom_debug.c
@@ -44,7 +44,7 @@ rtgeom_flagchars(const RTCTX *ctx, RTGEOM *rtg)
   if ( rtg->srid != SRID_UNKNOWN ) tflags[flagno++] = 'S';
   tflags[flagno] = '\0';
 
-  RTDEBUGF(4, "Flags: %s - returning %p", rtg->flags, tflags);
+  RTDEBUGF(ctx, 4, "Flags: %s - returning %p", rtg->flags, tflags);
 
   return tflags;
 }
@@ -95,7 +95,7 @@ rtcollection_summary(const RTCTX *ctx, RTCOLLECTION *col, int offset)
   char *pad="";
   char *zmflags = rtgeom_flagchars(ctx, (RTGEOM*)col);
 
-  RTDEBUG(2, "rtcollection_summary called");
+  RTDEBUG(ctx, 2, "rtcollection_summary called");
 
   result = (char *)rtalloc(ctx, size);
 
@@ -110,14 +110,14 @@ rtcollection_summary(const RTCTX *ctx, RTCOLLECTION *col, int offset)
     size += strlen(tmp)+1;
     result = rtrealloc(ctx, result, size);
 
-    RTDEBUGF(4, "Reallocated %d bytes for result", size);
+    RTDEBUGF(ctx, 4, "Reallocated %d bytes for result", size);
     if ( i > 0 ) strcat(result,nl);
 
     strcat(result, tmp);
     rtfree(ctx, tmp);
   }
 
-  RTDEBUG(3, "rtcollection_summary returning");
+  RTDEBUG(ctx, 3, "rtcollection_summary returning");
 
   return result;
 }
@@ -133,7 +133,7 @@ rtpoly_summary(const RTCTX *ctx, RTPOLY *poly, int offset)
   static char *nl = "\n";
   char *zmflags = rtgeom_flagchars(ctx, (RTGEOM*)poly);
 
-  RTDEBUG(2, "rtpoly_summary called");
+  RTDEBUG(ctx, 2, "rtpoly_summary called");
 
   result = (char *)rtalloc(ctx, size);
 
@@ -150,7 +150,7 @@ rtpoly_summary(const RTCTX *ctx, RTPOLY *poly, int offset)
     strcat(result,tmp);
   }
 
-  RTDEBUG(3, "rtpoly_summary returning");
+  RTDEBUG(ctx, 3, "rtpoly_summary returning");
 
   return result;
 }
diff --git a/src/rtgeom_geos.c b/src/rtgeom_geos.c
index d59e525..4e66082 100644
--- a/src/rtgeom_geos.c
+++ b/src/rtgeom_geos.c
@@ -18,7 +18,7 @@
  *
  **********************************************************************
  *
- * Copyright 2011-2014 Sandro Santilli <strk at keybit.net>
+ * Copyright 2011-2014 Sandro Santilli <strk at kbt.io>
  *
  **********************************************************************/
 
@@ -89,25 +89,25 @@ ptarray_from_GEOSCoordSeq(const RTCTX *ctx, const GEOSCoordSequence *cs, char wa
   RTPOINTARRAY *pa;
   RTPOINT4D point;
 
-  RTDEBUG(2, "ptarray_fromGEOSCoordSeq called");
+  RTDEBUG(ctx, 2, "ptarray_fromGEOSCoordSeq called");
 
   if ( ! GEOSCoordSeq_getSize_r(ctx->gctx, cs, &size) )
     rterror(ctx, "Exception thrown");
 
-  RTDEBUGF(4, " GEOSCoordSeq size: %d", size);
+  RTDEBUGF(ctx, 4, " GEOSCoordSeq size: %d", size);
 
   if ( want3d )
   {
     if ( ! GEOSCoordSeq_getDimensions_r(ctx->gctx, cs, &dims) )
       rterror(ctx, "Exception thrown");
 
-    RTDEBUGF(4, " GEOSCoordSeq dimensions: %d", dims);
+    RTDEBUGF(ctx, 4, " GEOSCoordSeq dimensions: %d", dims);
 
     /* forget higher dimensions (if any) */
     if ( dims > 3 ) dims = 3;
   }
 
-  RTDEBUGF(4, " output dimensions: %d", dims);
+  RTDEBUGF(ctx, 4, " output dimensions: %d", dims);
 
   pa = ptarray_construct(ctx, (dims==3), 0, size);
 
@@ -138,7 +138,7 @@ GEOS2RTGEOM(const RTCTX *ctx, const GEOSGeometry *geom, char want3d)
     hasZ = GEOSHasZ_r(ctx->gctx, geom);
     if ( ! hasZ )
     {
-      RTDEBUG(3, "Geometry has no Z, won't provide one");
+      RTDEBUG(ctx, 3, "Geometry has no Z, won't provide one");
 
       want3d = 0;
     }
@@ -160,7 +160,7 @@ GEOS2RTGEOM(const RTCTX *ctx, const GEOSGeometry *geom, char want3d)
     uint32_t i, ngeoms;
 
   case GEOS_POINT:
-    RTDEBUG(4, "rtgeom_from_geometry: it's a Point");
+    RTDEBUG(ctx, 4, "rtgeom_from_geometry: it's a Point");
     cs = GEOSGeom_getCoordSeq_r(ctx->gctx, geom);
     if ( GEOSisEmpty_r(ctx->gctx, geom) )
       return (RTGEOM*)rtpoint_construct_empty(ctx, SRID, want3d, 0);
@@ -169,7 +169,7 @@ GEOS2RTGEOM(const RTCTX *ctx, const GEOSGeometry *geom, char want3d)
 
   case GEOS_LINESTRING:
   case GEOS_LINEARRING:
-    RTDEBUG(4, "rtgeom_from_geometry: it's a LineString or LinearRing");
+    RTDEBUG(ctx, 4, "rtgeom_from_geometry: it's a LineString or LinearRing");
     if ( GEOSisEmpty_r(ctx->gctx, geom) )
       return (RTGEOM*)rtline_construct_empty(ctx, SRID, want3d, 0);
 
@@ -178,7 +178,7 @@ GEOS2RTGEOM(const RTCTX *ctx, const GEOSGeometry *geom, char want3d)
     return (RTGEOM *)rtline_construct(ctx, SRID, NULL, pa);
 
   case GEOS_POLYGON:
-    RTDEBUG(4, "rtgeom_from_geometry: it's a Polygon");
+    RTDEBUG(ctx, 4, "rtgeom_from_geometry: it's a Polygon");
     if ( GEOSisEmpty_r(ctx->gctx, geom) )
       return (RTGEOM*)rtpoly_construct_empty(ctx, SRID, want3d, 0);
     ngeoms = GEOSGetNumInteriorRings_r(ctx->gctx, geom);
@@ -200,7 +200,7 @@ GEOS2RTGEOM(const RTCTX *ctx, const GEOSGeometry *geom, char want3d)
   case GEOS_MULTILINESTRING:
   case GEOS_MULTIPOLYGON:
   case GEOS_GEOMETRYCOLLECTION:
-    RTDEBUG(4, "rtgeom_from_geometry: it's a Collection or Multi");
+    RTDEBUG(ctx, 4, "rtgeom_from_geometry: it's a Collection or Multi");
 
     ngeoms = GEOSGetNumGeometries_r(ctx->gctx, geom);
     geoms = NULL;
@@ -245,12 +245,12 @@ ptarray_to_GEOSCoordSeq(const RTCTX *ctx, const RTPOINTARRAY *pa)
     {
       p3d = rt_getPoint3dz_cp(ctx, pa, i);
       p2d = (const RTPOINT2D *)p3d;
-      RTDEBUGF(4, "Point: %g,%g,%g", p3d->x, p3d->y, p3d->z);
+      RTDEBUGF(ctx, 4, "Point: %g,%g,%g", p3d->x, p3d->y, p3d->z);
     }
     else
     {
       p2d = rt_getPoint2d_cp(ctx, pa, i);
-      RTDEBUGF(4, "Point: %g,%g", p2d->x, p2d->y);
+      RTDEBUGF(ctx, 4, "Point: %g,%g", p2d->x, p2d->y);
     }
 
 #if RTGEOM_GEOS_VERSION < 33
@@ -359,7 +359,7 @@ RTGEOM2GEOS(const RTCTX *ctx, const RTGEOM *rtgeom, int autofix)
   char *wkt;
 #endif
 
-  RTDEBUGF(4, "RTGEOM2GEOS got a %s", rttype_name(ctx, rtgeom->type));
+  RTDEBUGF(ctx, 4, "RTGEOM2GEOS got a %s", rttype_name(ctx, rtgeom->type));
 
   if (rtgeom_has_arc(ctx, rtgeom))
   {
@@ -507,7 +507,7 @@ RTGEOM2GEOS(const RTCTX *ctx, const RTGEOM *rtgeom, int autofix)
 
 #if RTDEBUG_LEVEL >= 4
   wkt = GEOSGeomToWKT_r(ctx->gctx, g);
-  RTDEBUGF(4, "RTGEOM2GEOS: GEOSGeom: %s", wkt);
+  RTDEBUGF(ctx, 4, "RTGEOM2GEOS: GEOSGeom: %s", wkt);
   free(wkt);
 #endif
 
@@ -585,7 +585,7 @@ rtgeom_intersection(const RTCTX *ctx, const RTGEOM *geom1, const RTGEOM *geom2)
 
   rtgeom_geos_ensure_init(ctx);
 
-  RTDEBUG(3, "intersection() START");
+  RTDEBUG(ctx, 3, "intersection() START");
 
   g1 = RTGEOM2GEOS(ctx, geom1, 0);
   if ( 0 == g1 )   /* exception thrown at construction */
@@ -602,15 +602,15 @@ rtgeom_intersection(const RTCTX *ctx, const RTGEOM *geom1, const RTGEOM *geom2)
     return NULL ;
   }
 
-  RTDEBUG(3, " constructed geometrys - calling geos");
-  RTDEBUGF(3, " g1 = %s", GEOSGeomToWKT_r(ctx->gctx, g1));
-  RTDEBUGF(3, " g2 = %s", GEOSGeomToWKT_r(ctx->gctx, g2));
-  /*RTDEBUGF(3, "g2 is valid = %i",GEOSisvalid_r(ctx->gctx, g2)); */
-  /*RTDEBUGF(3, "g1 is valid = %i",GEOSisvalid_r(ctx->gctx, g1)); */
+  RTDEBUG(ctx, 3, " constructed geometrys - calling geos");
+  RTDEBUGF(ctx, 3, " g1 = %s", GEOSGeomToWKT_r(ctx->gctx, g1));
+  RTDEBUGF(ctx, 3, " g2 = %s", GEOSGeomToWKT_r(ctx->gctx, g2));
+  /*RTDEBUGF(ctx, 3, "g2 is valid = %i",GEOSisvalid_r(ctx->gctx, g2)); */
+  /*RTDEBUGF(ctx, 3, "g1 is valid = %i",GEOSisvalid_r(ctx->gctx, g1)); */
 
   g3 = GEOSIntersection_r(ctx->gctx, g1,g2);
 
-  RTDEBUG(3, " intersection finished");
+  RTDEBUG(ctx, 3, " intersection finished");
 
   if (g3 == NULL)
   {
@@ -621,7 +621,7 @@ rtgeom_intersection(const RTCTX *ctx, const RTGEOM *geom1, const RTGEOM *geom2)
     return NULL; /* never get here */
   }
 
-  RTDEBUGF(3, "result: %s", GEOSGeomToWKT_r(ctx->gctx, g3) ) ;
+  RTDEBUGF(ctx, 3, "result: %s", GEOSGeomToWKT_r(ctx->gctx, g3) ) ;
 
   GEOSSetSRID_r(ctx->gctx, g3, srid);
 
@@ -659,7 +659,7 @@ rtgeom_linemerge(const RTCTX *ctx, const RTGEOM *geom1)
 
   rtgeom_geos_ensure_init(ctx);
 
-  RTDEBUG(3, "linemerge() START");
+  RTDEBUG(ctx, 3, "linemerge() START");
 
   g1 = RTGEOM2GEOS(ctx, geom1, 0);
   if ( 0 == g1 )   /* exception thrown at construction */
@@ -668,13 +668,13 @@ rtgeom_linemerge(const RTCTX *ctx, const RTGEOM *geom1)
     return NULL ;
   }
 
-  RTDEBUG(3, " constructed geometrys - calling geos");
-  RTDEBUGF(3, " g1 = %s", GEOSGeomToWKT_r(ctx->gctx, g1));
-  /*RTDEBUGF(3, "g1 is valid = %i",GEOSisvalid_r(ctx->gctx, g1)); */
+  RTDEBUG(ctx, 3, " constructed geometrys - calling geos");
+  RTDEBUGF(ctx, 3, " g1 = %s", GEOSGeomToWKT_r(ctx->gctx, g1));
+  /*RTDEBUGF(ctx, 3, "g1 is valid = %i",GEOSisvalid_r(ctx->gctx, g1)); */
 
   g3 = GEOSLineMerge_r(ctx->gctx, g1);
 
-  RTDEBUG(3, " linemerge finished");
+  RTDEBUG(ctx, 3, " linemerge finished");
 
   if (g3 == NULL)
   {
@@ -684,7 +684,7 @@ rtgeom_linemerge(const RTCTX *ctx, const RTGEOM *geom1)
     return NULL; /* never get here */
   }
 
-  RTDEBUGF(3, "result: %s", GEOSGeomToWKT_r(ctx->gctx, g3) ) ;
+  RTDEBUGF(ctx, 3, "result: %s", GEOSGeomToWKT_r(ctx->gctx, g3) ) ;
 
   GEOSSetSRID_r(ctx->gctx, g3, srid);
 
@@ -736,7 +736,7 @@ rtgeom_unaryunion(const RTCTX *ctx, const RTGEOM *geom1)
     return NULL; /* never get here */
   }
 
-  RTDEBUGF(3, "result: %s", GEOSGeomToWKT_r(ctx->gctx, g3) ) ;
+  RTDEBUGF(ctx, 3, "result: %s", GEOSGeomToWKT_r(ctx->gctx, g3) ) ;
 
   GEOSSetSRID_r(ctx->gctx, g3, srid);
 
@@ -806,7 +806,7 @@ rtgeom_difference(const RTCTX *ctx, const RTGEOM *geom1, const RTGEOM *geom2)
     return NULL ; /* never get here */
   }
 
-  RTDEBUGF(3, "result: %s", GEOSGeomToWKT_r(ctx->gctx, g3) ) ;
+  RTDEBUGF(ctx, 3, "result: %s", GEOSGeomToWKT_r(ctx->gctx, g3) ) ;
 
   GEOSSetSRID_r(ctx->gctx, g3, srid);
 
@@ -882,7 +882,7 @@ rtgeom_symdifference(const RTCTX *ctx, const RTGEOM* geom1, const RTGEOM* geom2)
     return NULL; /*never get here */
   }
 
-  RTDEBUGF(3, "result: %s", GEOSGeomToWKT_r(ctx->gctx, g3));
+  RTDEBUGF(ctx, 3, "result: %s", GEOSGeomToWKT_r(ctx->gctx, g3));
 
   GEOSSetSRID_r(ctx->gctx, g3, srid);
 
@@ -912,7 +912,7 @@ rtgeom_union(const RTCTX *ctx, const RTGEOM *geom1, const RTGEOM *geom2)
   GEOSGeometry *g1, *g2, *g3;
   RTGEOM *result;
 
-  RTDEBUG(2, "in geomunion");
+  RTDEBUG(ctx, 2, "in geomunion");
 
   /* A.Union(empty) == A */
   if ( rtgeom_is_empty(ctx, geom1) )
@@ -948,12 +948,12 @@ rtgeom_union(const RTCTX *ctx, const RTGEOM *geom1, const RTGEOM *geom2)
     return NULL;
   }
 
-  RTDEBUGF(3, "g1=%s", GEOSGeomToWKT_r(ctx->gctx, g1));
-  RTDEBUGF(3, "g2=%s", GEOSGeomToWKT_r(ctx->gctx, g2));
+  RTDEBUGF(ctx, 3, "g1=%s", GEOSGeomToWKT_r(ctx->gctx, g1));
+  RTDEBUGF(ctx, 3, "g2=%s", GEOSGeomToWKT_r(ctx->gctx, g2));
 
   g3 = GEOSUnion_r(ctx->gctx, g1,g2);
 
-  RTDEBUGF(3, "g3=%s", GEOSGeomToWKT_r(ctx->gctx, g3));
+  RTDEBUGF(ctx, 3, "g3=%s", GEOSGeomToWKT_r(ctx->gctx, g3));
 
   GEOSGeom_destroy_r(ctx->gctx, g1);
   GEOSGeom_destroy_r(ctx->gctx, g2);
@@ -1003,7 +1003,7 @@ rtgeom_clip_by_rect(const RTCTX *ctx, const RTGEOM *geom1, double x0, double y0,
 
   rtgeom_geos_ensure_init(ctx);
 
-  RTDEBUG(3, "clip_by_rect() START");
+  RTDEBUG(ctx, 3, "clip_by_rect() START");
 
   g1 = RTGEOM2GEOS(ctx, geom1, 1); /* auto-fix structure */
   if ( 0 == g1 )   /* exception thrown at construction */
@@ -1012,14 +1012,14 @@ rtgeom_clip_by_rect(const RTCTX *ctx, const RTGEOM *geom1, double x0, double y0,
     return NULL ;
   }
 
-  RTDEBUG(3, " constructed geometrys - calling geos");
-  RTDEBUGF(3, " g1 = %s", GEOSGeomToWKT_r(ctx->gctx, g1));
-  /*RTDEBUGF(3, "g1 is valid = %i",GEOSisvalid_r(ctx->gctx, g1)); */
+  RTDEBUG(ctx, 3, " constructed geometrys - calling geos");
+  RTDEBUGF(ctx, 3, " g1 = %s", GEOSGeomToWKT_r(ctx->gctx, g1));
+  /*RTDEBUGF(ctx, 3, "g1 is valid = %i",GEOSisvalid_r(ctx->gctx, g1)); */
 
   g3 = GEOSClipByRect_r(ctx->gctx, g1,x0,y0,x1,y1);
   GEOSGeom_destroy_r(ctx->gctx, g1);
 
-  RTDEBUG(3, " clip_by_rect finished");
+  RTDEBUG(ctx, 3, " clip_by_rect finished");
 
   if (g3 == NULL)
   {
@@ -1027,7 +1027,7 @@ rtgeom_clip_by_rect(const RTCTX *ctx, const RTGEOM *geom1, double x0, double y0,
     return NULL;
   }
 
-  RTDEBUGF(3, "result: %s", GEOSGeomToWKT_r(ctx->gctx, g3) ) ;
+  RTDEBUGF(ctx, 3, "result: %s", GEOSGeomToWKT_r(ctx->gctx, g3) ) ;
 
   result = GEOS2RTGEOM(ctx, g3, is3d);
   GEOSGeom_destroy_r(ctx->gctx, g3);
@@ -1116,10 +1116,10 @@ findFaceHoles(const RTCTX *ctx, Face** faces, int nfaces)
   for (i=0; i<nfaces; ++i) {
     Face* f = faces[i];
     int nholes = GEOSGetNumInteriorRings_r(ctx->gctx, f->geom);
-    RTDEBUGF(2, "Scanning face %d with env area %g and %d holes", i, f->envarea, nholes);
+    RTDEBUGF(ctx, 2, "Scanning face %d with env area %g and %d holes", i, f->envarea, nholes);
     for (h=0; h<nholes; ++h) {
       const GEOSGeometry *hole = GEOSGetInteriorRingN_r(ctx->gctx, f->geom, h);
-      RTDEBUGF(2, "Looking for hole %d/%d of face %d among %d other faces", h+1, nholes, i, nfaces-i-1);
+      RTDEBUGF(ctx, 2, "Looking for hole %d/%d of face %d among %d other faces", h+1, nholes, i, nfaces-i-1);
       for (j=i+1; j<nfaces; ++j) {
     const GEOSGeometry *f2er;
         Face* f2 = faces[j];
@@ -1131,7 +1131,7 @@ findFaceHoles(const RTCTX *ctx, Face** faces, int nfaces)
          *       useful.
          */
         if ( GEOSEquals_r(ctx->gctx, f2er, hole) ) {
-          RTDEBUGF(2, "Hole %d/%d of face %d is face %d", h+1, nholes, i, j);
+          RTDEBUGF(ctx, 2, "Hole %d/%d of face %d is face %d", h+1, nholes, i, j);
           f2->parent = f;
           break;
         }
@@ -1175,7 +1175,7 @@ RTGEOM_GEOS_buildArea(const RTCTX *ctx, const GEOSGeometry* geom_in)
 #endif
   geos_result = GEOSPolygonize_r(ctx->gctx, vgeoms, 1);
 
-  RTDEBUGF(3, "GEOSpolygonize returned @ %p", geos_result);
+  RTDEBUGF(ctx, 3, "GEOSpolygonize returned @ %p", geos_result);
 
   /* Null return from GEOSpolygonize _r(ctx->gctx, an exception) */
   if ( ! geos_result ) return 0;
@@ -1198,8 +1198,8 @@ RTGEOM_GEOS_buildArea(const RTCTX *ctx, const GEOSGeometry* geom_in)
 #endif
 
 
-  RTDEBUGF(3, "GEOSpolygonize: ngeoms in polygonize output: %d", ngeoms);
-  RTDEBUGF(3, "GEOSpolygonize: polygonized:%s",
+  RTDEBUGF(ctx, 3, "GEOSpolygonize: ngeoms in polygonize output: %d", ngeoms);
+  RTDEBUGF(ctx, 3, "GEOSpolygonize: polygonized:%s",
               rtgeom_to_ewkt(ctx, GEOS2RTGEOM(ctx, geos_result, 0)));
 
   /*
@@ -1229,7 +1229,7 @@ RTGEOM_GEOS_buildArea(const RTCTX *ctx, const GEOSGeometry* geom_in)
     return shp;
   }
 
-  RTDEBUGF(2, "Polygonize returned %d geoms", ngeoms);
+  RTDEBUGF(ctx, 2, "Polygonize returned %d geoms", ngeoms);
 
   /*
    * Polygonizer returns a polygon for each face in the built topology.
@@ -1333,9 +1333,9 @@ rtgeom_buildarea(const RTCTX *ctx, const RTGEOM *geom)
     return (RTGEOM*)rtpoly_construct_empty(ctx, SRID, is3d, 0);
   }
 
-  RTDEBUG(3, "buildarea called");
+  RTDEBUG(ctx, 3, "buildarea called");
 
-  RTDEBUGF(3, "ST_BuildArea got geom @ %p", geom);
+  RTDEBUGF(ctx, 3, "ST_BuildArea got geom @ %p", geom);
 
   rtgeom_geos_ensure_init(ctx);
 
@@ -1597,7 +1597,7 @@ rtgeom_offsetcurve(const RTCTX *ctx, const RTLINE *rtline, double size, int quad
     return NULL;
   }
 
-  RTDEBUGF(3, "result: %s", GEOSGeomToWKT_r(ctx->gctx, g3));
+  RTDEBUGF(ctx, 3, "result: %s", GEOSGeomToWKT_r(ctx->gctx, g3));
 
   GEOSSetSRID_r(ctx->gctx, g3, rtgeom_get_srid(ctx, rtgeom_in));
   rtgeom_result = GEOS2RTGEOM(ctx, g3, rtgeom_has_z(ctx, rtgeom_in));
@@ -1625,7 +1625,7 @@ RTTIN * rttin_from_geos(const RTCTX *ctx, const GEOSGeometry *geom, int want3d)
   if ( want3d ) {
     hasZ = GEOSHasZ_r(ctx->gctx, geom);
     if ( ! hasZ ) {
-      RTDEBUG(3, "Geometry has no Z, won't provide one");
+      RTDEBUG(ctx, 3, "Geometry has no Z, won't provide one");
       want3d = 0;
     }
   }
@@ -1634,7 +1634,7 @@ RTTIN * rttin_from_geos(const RTCTX *ctx, const GEOSGeometry *geom, int want3d)
     RTTRIANGLE **geoms;
     uint32_t i, ngeoms;
   case GEOS_GEOMETRYCOLLECTION:
-    RTDEBUG(4, "rtgeom_from_geometry: it's a Collection or Multi");
+    RTDEBUG(ctx, 4, "rtgeom_from_geometry: it's a Collection or Multi");
 
     ngeoms = GEOSGetNumGeometries_r(ctx->gctx, geom);
     geoms = NULL;
@@ -1713,7 +1713,7 @@ RTGEOM* rtgeom_delaunay_triangulation(const RTCTX *ctx, const RTGEOM *rtgeom_in,
     return NULL;
   }
 
-  /* RTDEBUGF(3, "result: %s", GEOSGeomToWKT_r(ctx->gctx, g3)); */
+  /* RTDEBUGF(ctx, 3, "result: %s", GEOSGeomToWKT_r(ctx->gctx, g3)); */
 
   GEOSSetSRID_r(ctx->gctx, g3, rtgeom_get_srid(ctx, rtgeom_in));
 
diff --git a/src/rtgeom_geos.h b/src/rtgeom_geos.h
index 135eb32..d202cc8 100644
--- a/src/rtgeom_geos.h
+++ b/src/rtgeom_geos.h
@@ -18,7 +18,7 @@
  *
  **********************************************************************
  *
- * Copyright 2011 Sandro Santilli <strk at keybit.net>
+ * Copyright 2011 Sandro Santilli <strk at kbt.io>
  *
  **********************************************************************/
 
diff --git a/src/rtgeom_geos_clean.c b/src/rtgeom_geos_clean.c
index d62c53c..d352b1a 100644
--- a/src/rtgeom_geos_clean.c
+++ b/src/rtgeom_geos_clean.c
@@ -18,7 +18,7 @@
  *
  **********************************************************************
  *
- * Copyright 2009-2010 Sandro Santilli <strk at keybit.net>
+ * Copyright 2009-2010 Sandro Santilli <strk at kbt.io>
  *
  **********************************************************************/
 
@@ -128,7 +128,7 @@ RTPOINTARRAY* ring_make_geos_friendly(const RTCTX *ctx, RTPOINTARRAY* ring);
 static RTGEOM *
 rtgeom_make_geos_friendly(const RTCTX *ctx, RTGEOM *geom)
 {
-  RTDEBUGF(2, "rtgeom_make_geos_friendly enter (type %d)", geom->type);
+  RTDEBUGF(ctx, 2, "rtgeom_make_geos_friendly enter (type %d)", geom->type);
   switch (geom->type)
   {
   case RTPOINTTYPE:
@@ -209,7 +209,7 @@ ring_make_geos_friendly(const RTCTX *ctx, RTPOINTARRAY* ring)
   while ( ring->npoints < 4 )
   {
     RTPOINTARRAY *oring = ring;
-    RTDEBUGF(4, "ring has %d points, adding another", ring->npoints);
+    RTDEBUGF(ctx, 4, "ring has %d points, adding another", ring->npoints);
     /* let's add another... */
     ring = ptarray_addPoint(ctx, ring,
                             rt_getPoint_internal(ctx, ring, 0),
@@ -246,12 +246,12 @@ rtpoly_make_geos_friendly(const RTCTX *ctx, RTPOLY *poly)
 
     if ( ring_in != ring_out )
     {
-      RTDEBUGF(3, "rtpoly_make_geos_friendly: ring %d cleaned, now has %d points", i, ring_out->npoints);
+      RTDEBUGF(ctx, 3, "rtpoly_make_geos_friendly: ring %d cleaned, now has %d points", i, ring_out->npoints);
       ptarray_free(ctx, ring_in);
     }
     else
     {
-      RTDEBUGF(3, "rtpoly_make_geos_friendly: ring %d untouched", i);
+      RTDEBUGF(ctx, 3, "rtpoly_make_geos_friendly: ring %d untouched", i);
     }
 
     assert ( ring_out );
@@ -349,7 +349,7 @@ RTGEOM_GEOS_nodeLines(const RTCTX *ctx, const GEOSGeometry* lines)
   point = RTGEOM_GEOS_getPointN(ctx, lines, 0);
   if ( ! point ) return NULL;
 
-  RTDEBUGF(3,
+  RTDEBUGF(ctx, 3,
                  "Boundary point: %s",
                  rtgeom_to_ewkt(ctx, GEOS2RTGEOM(ctx, point, 0)));
 
@@ -362,7 +362,7 @@ RTGEOM_GEOS_nodeLines(const RTCTX *ctx, const GEOSGeometry* lines)
 
   GEOSGeom_destroy_r(ctx->gctx, point);
 
-  RTDEBUGF(3,
+  RTDEBUGF(ctx, 3,
                  "RTGEOM_GEOS_nodeLines: in[%s] out[%s]",
                  rtgeom_to_ewkt(ctx, GEOS2RTGEOM(ctx, lines, 0)),
                  rtgeom_to_ewkt(ctx, GEOS2RTGEOM(ctx, noded, 0)));
@@ -394,7 +394,7 @@ RTGEOM_GEOS_makeValidPolygon(const RTCTX *ctx, const GEOSGeometry* gin)
     return NULL;
   }
 
-  RTDEBUGF(3,
+  RTDEBUGF(ctx, 3,
                  "Boundaries: %s",
                  rtgeom_to_ewkt(ctx, GEOS2RTGEOM(ctx, geos_bound, 0)));
 
@@ -432,7 +432,7 @@ RTGEOM_GEOS_makeValidPolygon(const RTCTX *ctx, const GEOSGeometry* gin)
       return NULL;
     }
 
-    RTDEBUGF(3,
+    RTDEBUGF(ctx, 3,
                    "Boundaries input points %s",
                    rtgeom_to_ewkt(ctx, GEOS2RTGEOM(ctx, pi, 0)));
 
@@ -450,7 +450,7 @@ RTGEOM_GEOS_makeValidPolygon(const RTCTX *ctx, const GEOSGeometry* gin)
       return NULL;
     }
 
-    RTDEBUGF(3,
+    RTDEBUGF(ctx, 3,
                    "Boundaries output points %s",
                    rtgeom_to_ewkt(ctx, GEOS2RTGEOM(ctx, po, 0)));
 
@@ -468,7 +468,7 @@ RTGEOM_GEOS_makeValidPolygon(const RTCTX *ctx, const GEOSGeometry* gin)
       return NULL;
     }
 
-    RTDEBUGF(3,
+    RTDEBUGF(ctx, 3,
                    "Collapse points: %s",
                    rtgeom_to_ewkt(ctx, GEOS2RTGEOM(ctx, collapse_points, 0)));
 
@@ -481,7 +481,7 @@ RTGEOM_GEOS_makeValidPolygon(const RTCTX *ctx, const GEOSGeometry* gin)
   }
   GEOSGeom_destroy_r(ctx->gctx, geos_bound);
 
-  RTDEBUGF(3,
+  RTDEBUGF(ctx, 3,
                  "Noded Boundaries: %s",
                  rtgeom_to_ewkt(ctx, GEOS2RTGEOM(ctx, geos_cut_edges, 0)));
 
@@ -857,7 +857,7 @@ RTGEOM_GEOS_makeValid(const RTCTX *ctx, const GEOSGeometry* gin)
   }
   else if ( ret_char )
   {
-    RTDEBUGF(3,
+    RTDEBUGF(ctx, 3,
                    "Geometry [%s] is valid. ",
                    rtgeom_to_ewkt(ctx, GEOS2RTGEOM(ctx, gin, 0)));
 
@@ -865,7 +865,7 @@ RTGEOM_GEOS_makeValid(const RTCTX *ctx, const GEOSGeometry* gin)
     return GEOSGeom_clone_r(ctx->gctx, gin);
   }
 
-  RTDEBUGF(3,
+  RTDEBUGF(ctx, 3,
                  "Geometry [%s] is still not valid: %s. "
                  "Will try to clean up further.",
                  rtgeom_to_ewkt(ctx, GEOS2RTGEOM(ctx, gin, 0)), rtgeom_get_last_geos_error(ctx));
@@ -997,7 +997,7 @@ rtgeom_make_valid(const RTCTX *ctx, RTGEOM* rtgeom_in)
   geosgeom = RTGEOM2GEOS(ctx, rtgeom_out, 0);
   if ( ! geosgeom )
   {
-    RTDEBUGF(4,
+    RTDEBUGF(ctx, 4,
                    "Original geom can't be converted to GEOS _r(ctx->gctx, %s)"
                    " - will try cleaning that up first",
                    rtgeom_get_last_geos_error(ctx));
@@ -1022,7 +1022,7 @@ rtgeom_make_valid(const RTCTX *ctx, RTGEOM* rtgeom_in)
   }
   else
   {
-    RTDEBUG(4, "original geom converted to GEOS");
+    RTDEBUG(ctx, 4, "original geom converted to GEOS");
     rtgeom_out = rtgeom_in;
   }
 
@@ -1040,7 +1040,7 @@ rtgeom_make_valid(const RTCTX *ctx, RTGEOM* rtgeom_in)
   {{
     RTGEOM **ogeoms = rtalloc(ctx, sizeof(RTGEOM*));
     RTGEOM *ogeom;
-    RTDEBUG(3, "rtgeom_make_valid: forcing multi");
+    RTDEBUG(ctx, 3, "rtgeom_make_valid: forcing multi");
     /* NOTE: this is safe because rtgeom_out is surely not rtgeom_in or
      * otherwise we couldn't have a collection and a non-collection */
     assert(rtgeom_in != rtgeom_out);
diff --git a/src/rtgeom_geos_node.c b/src/rtgeom_geos_node.c
index 6cedeb8..777ac0a 100644
--- a/src/rtgeom_geos_node.c
+++ b/src/rtgeom_geos_node.c
@@ -18,7 +18,7 @@
  *
  **********************************************************************
  *
- * Copyright (C) 2011 Sandro Santilli <strk at keybit.net>
+ * Copyright (C) 2011 Sandro Santilli <strk at kbt.io>
  *
  **********************************************************************/
 
diff --git a/src/rtgeom_geos_split.c b/src/rtgeom_geos_split.c
index ef4a4a8..472b4ea 100644
--- a/src/rtgeom_geos_split.c
+++ b/src/rtgeom_geos_split.c
@@ -18,7 +18,11 @@
  *
  **********************************************************************
  *
- * Copyright 2011-2015 Sandro Santilli <strk at keybit.net>
+ * Copyright 2011-2015 Sandro Santilli <strk at kbt.io>
+ *
+ **********************************************************************
+ *
+ * Last port: lwgeom_geos_split.c r14594
  *
  **********************************************************************/
 
@@ -209,11 +213,13 @@ int
 rtline_split_by_point_to(const RTCTX *ctx, const RTLINE* rtline_in, const RTPOINT* blade_in,
                          RTMLINE* v)
 {
-  double loc, dist;
+  double mindist = -1;
   RTPOINT4D pt, pt_projected;
+  RTPOINT4D p1, p2;
+  RTPOINTARRAY *ipa = rtline_in->points;
   RTPOINTARRAY* pa1;
   RTPOINTARRAY* pa2;
-  double vstol; /* vertex snap tolerance */
+  int i, nsegs, seg = -1;
 
   /* Possible outcomes:
    *
@@ -229,30 +235,77 @@ rtline_split_by_point_to(const RTCTX *ctx, const RTLINE* rtline_in, const RTPOIN
    */
 
   rt_getPoint4d_p(ctx, blade_in->point, 0, &pt);
-  loc = ptarray_locate_point(ctx, rtline_in->points, &pt, &dist, &pt_projected);
 
-  /* rtnotice(ctx, "Location: %g -- Distance: %g", loc, dist); */
-
-  if ( dist > 0 )   /* TODO: accept a tolerance ? */
+  /* Find closest segment */
+  rt_getPoint4d_p(ctx, ipa, 0, &p1);
+  nsegs = ipa->npoints - 1;
+  for ( i = 0; i < nsegs; i++ )
   {
-    /* No intersection */
-    return 0;
+    rt_getPoint4d_p(ctx, ipa, i+1, &p2);
+    double dist;
+    dist = distance2d_pt_seg(ctx, (RTPOINT2D*)&pt, (RTPOINT2D*)&p1, (RTPOINT2D*)&p2);
+    RTDEBUGF(ctx, 4, " Distance of point %g %g to segment %g %g, %g %g: %g", pt.x, pt.y, p1.x, p1.y, p2.x, p2.y, dist);
+    if (i==0 || dist < mindist )
+    {
+      mindist = dist;
+      seg=i;
+      if ( mindist == 0.0 ) break; /* can't be closer than ON line */
+    }
+    p1 = p2;
   }
 
-  if ( loc == 0 || loc == 1 )
+  RTDEBUGF(ctx, 3, "Closest segment: %d", seg);
+  RTDEBUGF(ctx, 3, "mindist: %g", mindist);
+
+  /* No intersection */
+  if ( mindist > 0 ) return 0;
+
+  /* empty or single-point line, intersection on boundary */
+  if ( seg < 0 ) return 1;
+
+  /*
+   * We need to project the
+   * point on the closest segment,
+   * to interpolate Z and M if needed
+   */
+  rt_getPoint4d_p(ctx, ipa, seg, &p1);
+  rt_getPoint4d_p(ctx, ipa, seg+1, &p2);
+  closest_point_on_segment(ctx, &pt, &p1, &p2, &pt_projected);
+  /* But X and Y we want the ones of the input point,
+   * as on some architectures the interpolation math moves the
+   * coordinates (see postgis#3422)
+   */
+  pt_projected.x = pt.x;
+  pt_projected.y = pt.y;
+
+  RTDEBUGF(ctx, 3, "Projected point:(%g %g), seg:%d, p1:(%g %g), p2:(%g %g)", pt_projected.x, pt_projected.y, seg, p1.x, p1.y, p2.x, p2.y);
+
+  /* When closest point == an endpoint, this is a boundary intersection */
+  if ( ( (seg == nsegs-1) && p4d_same(ctx, &pt_projected, &p2) ) ||
+       ( (seg == 0)       && p4d_same(ctx, &pt_projected, &p1) ) )
   {
-    /* Intersection is on the boundary */
     return 1;
   }
 
-  /* There is a real intersection, let's get two substrings */
+  /* This is an internal intersection, let's build the two new pointarrays */
 
-  /* Compute vertex snap tolerance based on line length
-   * TODO: take as parameter ? */
-  vstol = ptarray_length_2d(ctx, rtline_in->points) / 1e14;
+  pa1 = ptarray_construct_empty(ctx, RTFLAGS_GET_Z(ipa->flags), RTFLAGS_GET_M(ipa->flags), seg+2);
+  /* TODO: replace with a memcpy ? */
+  for (i=0; i<=seg; ++i)
+  {
+    rt_getPoint4d_p(ctx, ipa, i, &p1);
+    ptarray_append_point(ctx, pa1, &p1, RT_FALSE);
+  }
+  ptarray_append_point(ctx, pa1, &pt_projected, RT_FALSE);
 
-  pa1 = ptarray_substring(ctx, rtline_in->points, 0, loc, vstol);
-  pa2 = ptarray_substring(ctx, rtline_in->points, loc, 1, vstol);
+  pa2 = ptarray_construct_empty(ctx, RTFLAGS_GET_Z(ipa->flags), RTFLAGS_GET_M(ipa->flags), ipa->npoints-seg);
+  ptarray_append_point(ctx, pa2, &pt_projected, RT_FALSE);
+  /* TODO: replace with a memcpy (if so need to check for duplicated point) ? */
+  for (i=seg+1; i<ipa->npoints; ++i)
+  {
+    rt_getPoint4d_p(ctx, ipa, i, &p1);
+    ptarray_append_point(ctx, pa2, &p1, RT_FALSE);
+  }
 
   /* NOTE: I've seen empty pointarrays with loc != 0 and loc != 1 */
   if ( pa1->npoints == 0 || pa2->npoints == 0 ) {
diff --git a/src/rtgeom_log.h b/src/rtgeom_log.h
index 9c0d84a..c920395 100644
--- a/src/rtgeom_log.h
+++ b/src/rtgeom_log.h
@@ -18,7 +18,7 @@
  *
  **********************************************************************
  *
- * Copyright 2011 Sandro Santilli <strk at keybit.net>
+ * Copyright 2011 Sandro Santilli <strk at kbt.io>
  * Copyright 2008 Paul Ramsey <pramsey at cleverelephant.ca>
  * Copyright 2007-2008 Mark Cave-Ayland
  * Copyright 2001-2006 Refractions Research Inc.
@@ -39,18 +39,18 @@
 #if RTGEOM_DEBUG_LEVEL > 0
 
 /* Display a notice at the given debug level */
-#define RTDEBUG(level, msg) \
+#define RTDEBUG(ctx, level, msg) \
         do { \
             if (RTGEOM_DEBUG_LEVEL >= level) \
-              rtdebug(const RTCTX *ctx, level, "[%s:%s:%d] " msg, __FILE__, __func__, __LINE__); \
+              rtdebug(ctx, level, "[%s:%s:%d] " msg, __FILE__, __func__, __LINE__); \
         } while (0);
 
 /* Display a formatted notice at the given debug level
  * (like printf, with variadic arguments) */
-#define RTDEBUGF(level, msg, ...) \
+#define RTDEBUGF(ctx, level, msg, ...) \
         do { \
             if (RTGEOM_DEBUG_LEVEL >= level) \
-              rtdebug(const RTCTX *ctx, level, "[%s:%s:%d] " msg, \
+              rtdebug(ctx, level, "[%s:%s:%d] " msg, \
                 __FILE__, __func__, __LINE__, __VA_ARGS__); \
         } while (0);
 
@@ -58,12 +58,12 @@
 
 /* Empty prototype that can be optimised away by the compiler
  * for non-debug builds */
-#define RTDEBUG(level, msg) \
+#define RTDEBUG(ctx, level, msg) \
         ((void) 0)
 
 /* Empty prototype that can be optimised away by the compiler
  * for non-debug builds */
-#define RTDEBUGF(level, msg, ...) \
+#define RTDEBUGF(ctx, level, msg, ...) \
         ((void) 0)
 
 #endif /* RTGEOM_DEBUG_LEVEL <= 0 */
diff --git a/src/rtgeom_topo.c b/src/rtgeom_topo.c
index 1c60b06..92e4687 100644
--- a/src/rtgeom_topo.c
+++ b/src/rtgeom_topo.c
@@ -18,7 +18,7 @@
  *
  **********************************************************************
  *
- * Copyright (C) 2015-2016 Sandro Santilli <strk at keybit.net>
+ * Copyright (C) 2015-2016 Sandro Santilli <strk at kbt.io>
  *
  **********************************************************************
  *
@@ -50,14 +50,14 @@
 #endif
 
 /* TODO: move this to rtgeom_log.h */
-#define RTDEBUGG(level, geom, msg) \
+#define RTDEBUGG(ctx, level, geom, msg) \
   if (RTGEOM_DEBUG_LEVEL >= level) \
   do { \
     size_t sz; \
-    char *wkt1 = rtgeom_to_wkt(iface->ctx, geom, RTWKT_EXTENDED, 15, &sz); \
+    char *wkt1 = rtgeom_to_wkt(ctx, geom, RTWKT_EXTENDED, 15, &sz); \
     /* char *wkt1 = rtgeom_to_hexwkb(iface->ctx, geom, RTWKT_EXTENDED, &sz); */ \
-    RTDEBUGF(level, msg ": %s", wkt1); \
-    rtfree(iface->ctx, wkt1); \
+    RTDEBUGF(ctx, level, msg ": %s", wkt1); \
+    rtfree(ctx, wkt1); \
   } while (0);
 
 
@@ -198,7 +198,7 @@ rtt_be_getNodeWithinBox2D( const RTT_TOPOLOGY* topo,
   CBT4(topo, getNodeWithinBox2D, box, numelems, fields, limit);
 }
 
-static RTT_ISO_EDGE*
+RTT_ISO_EDGE*
 rtt_be_getEdgeWithinBox2D( const RTT_TOPOLOGY* topo,
                            const RTGBOX* box, int* numelems, int fields,
                            int limit )
@@ -465,12 +465,12 @@ _rtt_toposnap(const RTCTX *ctx, RTGEOM *src, RTGEOM *tgt, double tol)
       changed = ( rtgeom_count_vertices(ctx, tmp2) != rtgeom_count_vertices(ctx, tmp) );
     }
 #endif /* GEOS_NUMERIC_VERSION < 30309 */
-    RTDEBUGF(2, "After iteration %d, geometry changed ? %d (%d vs %d vertices)", iterations, changed, rtgeom_count_vertices(ctx, tmp2), rtgeom_count_vertices(ctx, tmp));
+    RTDEBUGF(ctx, 2, "After iteration %d, geometry changed ? %d (%d vs %d vertices)", iterations, changed, rtgeom_count_vertices(ctx, tmp2), rtgeom_count_vertices(ctx, tmp));
     if ( tmp != src ) rtgeom_free(ctx, tmp);
     tmp = tmp2;
   } while ( changed && iterations <= maxiterations );
 
-  RTDEBUGF(1, "It took %d/%d iterations to properly snap",
+  RTDEBUGF(ctx, 1, "It took %d/%d iterations to properly snap",
               iterations, maxiterations);
 
   return tmp;
@@ -486,8 +486,8 @@ _rtt_release_faces(const RTCTX *ctx, RTT_ISO_FACE *faces, int num_faces)
   rtfree(ctx, faces);
 }
 
-static void
-_rtt_release_edges(const RTCTX *ctx, RTT_ISO_EDGE *edges, int num_edges)
+void
+rtt_release_edges(const RTCTX *ctx, RTT_ISO_EDGE *edges, int num_edges)
 {
   int i;
   for ( i=0; i<num_edges; ++i ) {
@@ -546,9 +546,17 @@ rtt_FreeTopology( RTT_TOPOLOGY* topo )
   rtfree(iface->ctx, topo);
 }
 
-RTT_ELEMID
-rtt_AddIsoNode( RTT_TOPOLOGY* topo, RTT_ELEMID face,
-                RTPOINT* pt, int skipISOChecks )
+/**
+ * @param checkFace if non zero will check the given face
+ *        for really containing the point or determine the
+ *        face when given face is -1. Use 0 to simply use
+ *        the given face value, no matter what (effectively
+ *        allowing adding a non-isolated point when used
+ *        with face=-1).
+ */
+static RTT_ELEMID
+_rtt_AddIsoNode( RTT_TOPOLOGY* topo, RTT_ELEMID face,
+                RTPOINT* pt, int skipISOChecks, int checkFace )
 {
   RTT_ELEMID foundInFace = -1;
   const RTT_BE_IFACE *iface = topo->be_iface;
@@ -567,7 +575,7 @@ rtt_AddIsoNode( RTT_TOPOLOGY* topo, RTT_ELEMID face,
     }
   }
 
-  if ( face == -1 || ! skipISOChecks )
+  if ( checkFace && ( face == -1 || ! skipISOChecks ) )
   {
     foundInFace = rtt_be_getFaceContainingPoint(topo, pt); /*x*/
     if ( foundInFace == -2 ) {
@@ -603,6 +611,13 @@ rtt_AddIsoNode( RTT_TOPOLOGY* topo, RTT_ELEMID face,
   return node.node_id;
 }
 
+RTT_ELEMID
+rtt_AddIsoNode( RTT_TOPOLOGY* topo, RTT_ELEMID face,
+                RTPOINT* pt, int skipISOChecks )
+{
+  return _rtt_AddIsoNode( topo, face, pt, skipISOChecks, 1 );
+}
+
 /* Check that an edge does not cross an existing node or edge
  *
  * @param myself the id of an edge to skip, if any
@@ -641,7 +656,7 @@ _rtt_CheckEdgeCrossing( RTT_TOPOLOGY* topo,
   /* loop over each node within the edge's gbox */
   nodes = rtt_be_getNodeWithinBox2D( topo, edgebox, &num_nodes,
                                             RTT_COL_NODE_ALL, 0 );
-  RTDEBUGF(1, "rtt_be_getNodeWithinBox2D returned %d nodes", num_nodes);
+  RTDEBUGF(iface->ctx, 1, "rtt_be_getNodeWithinBox2D returned %d nodes", num_nodes);
   if ( num_nodes == -1 ) {
     GEOSPreparedGeom_destroy_r(iface->ctx->gctx, prepared_edge);
     GEOSGeom_destroy_r(iface->ctx->gctx, edgegg);
@@ -682,7 +697,7 @@ _rtt_CheckEdgeCrossing( RTT_TOPOLOGY* topo,
 
   /* loop over each edge within the edge's gbox */
   edges = rtt_be_getEdgeWithinBox2D( topo, edgebox, &num_edges, RTT_COL_EDGE_ALL, 0 );
-  RTDEBUGF(1, "rtt_be_getEdgeWithinBox2D returned %d edges", num_edges);
+  RTDEBUGF(iface->ctx, 1, "rtt_be_getEdgeWithinBox2D returned %d edges", num_edges);
   if ( num_edges == -1 ) {
     GEOSPreparedGeom_destroy_r(iface->ctx->gctx, prepared_edge);
     GEOSGeom_destroy_r(iface->ctx->gctx, edgegg);
@@ -700,7 +715,7 @@ _rtt_CheckEdgeCrossing( RTT_TOPOLOGY* topo,
     if ( edge_id == myself ) continue;
 
     if ( ! edge->geom ) {
-      _rtt_release_edges(iface->ctx, edges, num_edges);
+      rtt_release_edges(iface->ctx, edges, num_edges);
       rterror(iface->ctx, "Edge %d has NULL geometry!", edge_id);
       return -1;
     }
@@ -709,12 +724,12 @@ _rtt_CheckEdgeCrossing( RTT_TOPOLOGY* topo,
     if ( ! eegg ) {
       GEOSPreparedGeom_destroy_r(iface->ctx->gctx, prepared_edge);
       GEOSGeom_destroy_r(iface->ctx->gctx, edgegg);
-      _rtt_release_edges(iface->ctx, edges, num_edges);
+      rtt_release_edges(iface->ctx, edges, num_edges);
       rterror(iface->ctx, "Could not convert edge geometry to GEOS: %s", rtgeom_get_last_geos_error(iface->ctx));
       return -1;
     }
 
-    RTDEBUGF(2, "Edge %d converted to GEOS", edge_id);
+    RTDEBUGF(iface->ctx, 2, "Edge %d converted to GEOS", edge_id);
 
     /* check if the edge crosses our edge (not boundary-boundary) */
 
@@ -723,12 +738,12 @@ _rtt_CheckEdgeCrossing( RTT_TOPOLOGY* topo,
       GEOSGeom_destroy_r(iface->ctx->gctx, eegg);
       GEOSPreparedGeom_destroy_r(iface->ctx->gctx, prepared_edge);
       GEOSGeom_destroy_r(iface->ctx->gctx, edgegg);
-      _rtt_release_edges(iface->ctx, edges, num_edges);
+      rtt_release_edges(iface->ctx, edges, num_edges);
       rterror(iface->ctx, "GEOSRelateBoundaryNodeRule error: %s", rtgeom_get_last_geos_error(iface->ctx));
       return -1;
     }
 
-    RTDEBUGF(2, "Edge %d relate pattern is %s", edge_id, relate);
+    RTDEBUGF(iface->ctx, 2, "Edge %d relate pattern is %s", edge_id, relate);
 
     match = GEOSRelatePatternMatch_r(iface->ctx->gctx, relate, "F********");
     if ( match ) {
@@ -736,7 +751,7 @@ _rtt_CheckEdgeCrossing( RTT_TOPOLOGY* topo,
       GEOSGeom_destroy_r(iface->ctx->gctx, eegg);
       GEOSFree_r(iface->ctx->gctx, relate);
       if ( match == 2 ) {
-        _rtt_release_edges(iface->ctx, edges, num_edges);
+        rtt_release_edges(iface->ctx, edges, num_edges);
         GEOSPreparedGeom_destroy_r(iface->ctx->gctx, prepared_edge);
         GEOSGeom_destroy_r(iface->ctx->gctx, edgegg);
         rterror(iface->ctx, "GEOSRelatePatternMatch error: %s", rtgeom_get_last_geos_error(iface->ctx));
@@ -747,7 +762,7 @@ _rtt_CheckEdgeCrossing( RTT_TOPOLOGY* topo,
 
     match = GEOSRelatePatternMatch_r(iface->ctx->gctx, relate, "1FFF*FFF2");
     if ( match ) {
-      _rtt_release_edges(iface->ctx, edges, num_edges);
+      rtt_release_edges(iface->ctx, edges, num_edges);
       GEOSPreparedGeom_destroy_r(iface->ctx->gctx, prepared_edge);
       GEOSGeom_destroy_r(iface->ctx->gctx, edgegg);
       GEOSGeom_destroy_r(iface->ctx->gctx, eegg);
@@ -763,7 +778,7 @@ _rtt_CheckEdgeCrossing( RTT_TOPOLOGY* topo,
 
     match = GEOSRelatePatternMatch_r(iface->ctx->gctx, relate, "1********");
     if ( match ) {
-      _rtt_release_edges(iface->ctx, edges, num_edges);
+      rtt_release_edges(iface->ctx, edges, num_edges);
       GEOSPreparedGeom_destroy_r(iface->ctx->gctx, prepared_edge);
       GEOSGeom_destroy_r(iface->ctx->gctx, edgegg);
       GEOSGeom_destroy_r(iface->ctx->gctx, eegg);
@@ -779,7 +794,7 @@ _rtt_CheckEdgeCrossing( RTT_TOPOLOGY* topo,
 
     match = GEOSRelatePatternMatch_r(iface->ctx->gctx, relate, "T********");
     if ( match ) {
-      _rtt_release_edges(iface->ctx, edges, num_edges);
+      rtt_release_edges(iface->ctx, edges, num_edges);
       GEOSPreparedGeom_destroy_r(iface->ctx->gctx, prepared_edge);
       GEOSGeom_destroy_r(iface->ctx->gctx, edgegg);
       GEOSGeom_destroy_r(iface->ctx->gctx, eegg);
@@ -793,12 +808,12 @@ _rtt_CheckEdgeCrossing( RTT_TOPOLOGY* topo,
       return -1;
     }
 
-    RTDEBUGF(2, "Edge %d analisys completed, it does no harm", edge_id);
+    RTDEBUGF(iface->ctx, 2, "Edge %d analisys completed, it does no harm", edge_id);
 
     GEOSFree_r(iface->ctx->gctx, relate);
     GEOSGeom_destroy_r(iface->ctx->gctx, eegg);
   }
-  if ( edges ) _rtt_release_edges(iface->ctx, edges, num_edges);
+  if ( edges ) rtt_release_edges(iface->ctx, edges, num_edges);
               /* would be NULL if num_edges was 0 */
 
   GEOSPreparedGeom_destroy_r(iface->ctx->gctx, prepared_edge);
@@ -984,12 +999,12 @@ _rtt_EdgeSplit( RTT_TOPOLOGY* topo, RTT_ELEMID edge, RTPOINT* pt, int skipISOChe
 
   /* Get edge */
   i = 1;
-  RTDEBUG(1, "calling rtt_be_getEdgeById");
+  RTDEBUG(iface->ctx, 1, "calling rtt_be_getEdgeById");
   *oldedge = rtt_be_getEdgeById(topo, &edge, &i, RTT_COL_EDGE_ALL);
-  RTDEBUGF(1, "rtt_be_getEdgeById returned %p", *oldedge);
+  RTDEBUGF(iface->ctx, 1, "rtt_be_getEdgeById returned %p", *oldedge);
   if ( ! *oldedge )
   {
-    RTDEBUGF(1, "rtt_be_getEdgeById returned NULL and set i=%d", i);
+    RTDEBUGF(iface->ctx, 1, "rtt_be_getEdgeById returned NULL and set i=%d", i);
     if ( i == -1 )
     {
       rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
@@ -1015,34 +1030,34 @@ _rtt_EdgeSplit( RTT_TOPOLOGY* topo, RTT_ELEMID edge, RTPOINT* pt, int skipISOChe
    */
   if ( ! skipISOChecks )
   {
-    RTDEBUG(1, "calling rtt_be_ExistsCoincidentNode");
+    RTDEBUG(iface->ctx, 1, "calling rtt_be_ExistsCoincidentNode");
     if ( rtt_be_ExistsCoincidentNode(topo, pt) ) /*x*/
     {
-      RTDEBUG(1, "rtt_be_ExistsCoincidentNode returned");
-      _rtt_release_edges(iface->ctx, *oldedge, 1);
+      RTDEBUG(iface->ctx, 1, "rtt_be_ExistsCoincidentNode returned");
+      rtt_release_edges(iface->ctx, *oldedge, 1);
       rterror(iface->ctx, "SQL/MM Spatial exception - coincident node");
       return NULL;
     }
-    RTDEBUG(1, "rtt_be_ExistsCoincidentNode returned");
+    RTDEBUG(iface->ctx, 1, "rtt_be_ExistsCoincidentNode returned");
   }
 
   /* Split edge */
   split = rtgeom_split(iface->ctx, (RTGEOM*)(*oldedge)->geom, (RTGEOM*)pt);
   if ( ! split )
   {
-    _rtt_release_edges(iface->ctx, *oldedge, 1);
+    rtt_release_edges(iface->ctx, *oldedge, 1);
     rterror(iface->ctx, "could not split edge by point ?");
     return NULL;
   }
   split_col = rtgeom_as_rtcollection(iface->ctx, split);
   if ( ! split_col ) {
-    _rtt_release_edges(iface->ctx, *oldedge, 1);
+    rtt_release_edges(iface->ctx, *oldedge, 1);
     rtgeom_free(iface->ctx, split);
     rterror(iface->ctx, "rtgeom_as_rtcollection returned NULL");
     return NULL;
   }
   if (split_col->ngeoms < 2) {
-    _rtt_release_edges(iface->ctx, *oldedge, 1);
+    rtt_release_edges(iface->ctx, *oldedge, 1);
     rtgeom_free(iface->ctx, split);
     rterror(iface->ctx, "SQL/MM Spatial exception - point not on edge");
     return NULL;
@@ -1052,7 +1067,7 @@ _rtt_EdgeSplit( RTT_TOPOLOGY* topo, RTT_ELEMID edge, RTPOINT* pt, int skipISOChe
   {
   size_t sz;
   char *wkt = rtgeom_to_wkt(iface->ctx, (RTGEOM*)split_col, RTWKT_EXTENDED, 2, &sz);
-  RTDEBUGF(1, "returning split col: %s", wkt);
+  RTDEBUGF(iface->ctx, 1, "returning split col: %s", wkt);
   rtfree(iface->ctx, wkt);
   }
 #endif
@@ -1087,14 +1102,14 @@ rtt_ModEdgeSplit( RTT_TOPOLOGY* topo, RTT_ELEMID edge,
   node.geom = pt;
   if ( ! rtt_be_insertNodes(topo, &node, 1) )
   {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rtcollection_free(iface->ctx, split_col);
     rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
     return -1;
   }
   if (node.node_id == -1) {
     /* should have been set by backend */
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rtcollection_free(iface->ctx, split_col);
     rterror(iface->ctx, "Backend coding error: "
             "insertNodes callback did not return node_id");
@@ -1104,7 +1119,7 @@ rtt_ModEdgeSplit( RTT_TOPOLOGY* topo, RTT_ELEMID edge,
   /* Insert the new edge */
   newedge1.edge_id = rtt_be_getNextEdgeId(topo);
   if ( newedge1.edge_id == -1 ) {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rtcollection_free(iface->ctx, split_col);
     rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
     return -1;
@@ -1119,19 +1134,19 @@ rtt_ModEdgeSplit( RTT_TOPOLOGY* topo, RTT_ELEMID edge,
   newedge1.geom = rtgeom_as_rtline(iface->ctx, newedge_geom);
   /* rtgeom_split of a line should only return lines ... */
   if ( ! newedge1.geom ) {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rtcollection_free(iface->ctx, split_col);
     rterror(iface->ctx, "first geometry in rtgeom_split output is not a line");
     return -1;
   }
   ret = rtt_be_insertEdges(topo, &newedge1, 1);
   if ( ret == -1 ) {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rtcollection_free(iface->ctx, split_col);
     rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
     return -1;
   } else if ( ret == 0 ) {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rtcollection_free(iface->ctx, split_col);
     rterror(iface->ctx, "Insertion of split edge failed (no reason)");
     return -1;
@@ -1141,7 +1156,7 @@ rtt_ModEdgeSplit( RTT_TOPOLOGY* topo, RTT_ELEMID edge,
   updedge.geom = rtgeom_as_rtline(iface->ctx, oldedge_geom);
   /* rtgeom_split of a line should only return lines ... */
   if ( ! updedge.geom ) {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rtcollection_free(iface->ctx, split_col);
     rterror(iface->ctx, "second geometry in rtgeom_split output is not a line");
     return -1;
@@ -1153,17 +1168,17 @@ rtt_ModEdgeSplit( RTT_TOPOLOGY* topo, RTT_ELEMID edge,
       &updedge, RTT_COL_EDGE_GEOM|RTT_COL_EDGE_NEXT_LEFT|RTT_COL_EDGE_END_NODE,
       NULL, 0);
   if ( ret == -1 ) {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rtcollection_free(iface->ctx, split_col);
     rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
     return -1;
   } else if ( ret == 0 ) {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rtcollection_free(iface->ctx, split_col);
     rterror(iface->ctx, "Edge being split (%d) disappeared during operations?", oldedge->edge_id);
     return -1;
   } else if ( ret > 1 ) {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rtcollection_free(iface->ctx, split_col);
     rterror(iface->ctx, "More than a single edge found with id %d !", oldedge->edge_id);
     return -1;
@@ -1180,7 +1195,7 @@ rtt_ModEdgeSplit( RTT_TOPOLOGY* topo, RTT_ELEMID edge,
       &updedge, RTT_COL_EDGE_NEXT_RIGHT,
       &excedge, RTT_COL_EDGE_EDGE_ID);
   if ( ret == -1 ) {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rtcollection_free(iface->ctx, split_col);
     rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
     return -1;
@@ -1195,7 +1210,7 @@ rtt_ModEdgeSplit( RTT_TOPOLOGY* topo, RTT_ELEMID edge,
       &updedge, RTT_COL_EDGE_NEXT_LEFT,
       &excedge, RTT_COL_EDGE_EDGE_ID);
   if ( ret == -1 ) {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rtcollection_free(iface->ctx, split_col);
     rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
     return -1;
@@ -1204,13 +1219,13 @@ rtt_ModEdgeSplit( RTT_TOPOLOGY* topo, RTT_ELEMID edge,
   /* Update TopoGeometries composition */
   ret = rtt_be_updateTopoGeomEdgeSplit(topo, oldedge->edge_id, newedge1.edge_id, -1);
   if ( ! ret ) {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rtcollection_free(iface->ctx, split_col);
     rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
     return -1;
   }
 
-  _rtt_release_edges(iface->ctx, oldedge, 1);
+  rtt_release_edges(iface->ctx, oldedge, 1);
   rtcollection_free(iface->ctx, split_col);
 
   /* return new node id */
@@ -1245,13 +1260,13 @@ rtt_NewEdgesSplit( RTT_TOPOLOGY* topo, RTT_ELEMID edge,
   node.geom = pt;
   if ( ! rtt_be_insertNodes(topo, &node, 1) )
   {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rtcollection_free(iface->ctx, split_col);
     rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
     return -1;
   }
   if (node.node_id == -1) {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rtcollection_free(iface->ctx, split_col);
     /* should have been set by backend */
     rterror(iface->ctx, "Backend coding error: "
@@ -1263,7 +1278,7 @@ rtt_NewEdgesSplit( RTT_TOPOLOGY* topo, RTT_ELEMID edge,
   seledge.edge_id = edge;
   ret = rtt_be_deleteEdges(topo, &seledge, RTT_COL_EDGE_EDGE_ID);
   if ( ret == -1 ) {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rtcollection_free(iface->ctx, split_col);
     rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
     return -1;
@@ -1272,14 +1287,14 @@ rtt_NewEdgesSplit( RTT_TOPOLOGY* topo, RTT_ELEMID edge,
   /* Get new edges identifiers */
   newedges[0].edge_id = rtt_be_getNextEdgeId(topo);
   if ( newedges[0].edge_id == -1 ) {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rtcollection_free(iface->ctx, split_col);
     rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
     return -1;
   }
   newedges[1].edge_id = rtt_be_getNextEdgeId(topo);
   if ( newedges[1].edge_id == -1 ) {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rtcollection_free(iface->ctx, split_col);
     rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
     return -1;
@@ -1300,7 +1315,7 @@ rtt_NewEdgesSplit( RTT_TOPOLOGY* topo, RTT_ELEMID edge,
   newedges[0].geom = rtgeom_as_rtline(iface->ctx, oldedge_geom);
   /* rtgeom_split of a line should only return lines ... */
   if ( ! newedges[0].geom ) {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rtcollection_free(iface->ctx, split_col);
     rterror(iface->ctx, "first geometry in rtgeom_split output is not a line");
     return -1;
@@ -1321,7 +1336,7 @@ rtt_NewEdgesSplit( RTT_TOPOLOGY* topo, RTT_ELEMID edge,
   newedges[1].geom = rtgeom_as_rtline(iface->ctx, newedge_geom);
   /* rtgeom_split of a line should only return lines ... */
   if ( ! newedges[1].geom ) {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rtcollection_free(iface->ctx, split_col);
     rterror(iface->ctx, "second geometry in rtgeom_split output is not a line");
     return -1;
@@ -1330,11 +1345,11 @@ rtt_NewEdgesSplit( RTT_TOPOLOGY* topo, RTT_ELEMID edge,
   /* Insert both new edges */
   ret = rtt_be_insertEdges(topo, newedges, 2);
   if ( ret == -1 ) {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
     return -1;
   } else if ( ret == 0 ) {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rtcollection_free(iface->ctx, split_col);
     rterror(iface->ctx, "Insertion of split edge failed (no reason)");
     return -1;
@@ -1350,7 +1365,7 @@ rtt_NewEdgesSplit( RTT_TOPOLOGY* topo, RTT_ELEMID edge,
       &updedge, RTT_COL_EDGE_NEXT_RIGHT,
       NULL, 0);
   if ( ret == -1 ) {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rtcollection_free(iface->ctx, split_col);
     rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
     return -1;
@@ -1364,7 +1379,7 @@ rtt_NewEdgesSplit( RTT_TOPOLOGY* topo, RTT_ELEMID edge,
       &updedge, RTT_COL_EDGE_NEXT_RIGHT,
       NULL, 0);
   if ( ret == -1 ) {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rtcollection_free(iface->ctx, split_col);
     rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
     return -1;
@@ -1378,7 +1393,7 @@ rtt_NewEdgesSplit( RTT_TOPOLOGY* topo, RTT_ELEMID edge,
       &updedge, RTT_COL_EDGE_NEXT_LEFT,
       NULL, 0);
   if ( ret == -1 ) {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rtcollection_free(iface->ctx, split_col);
     rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
     return -1;
@@ -1392,7 +1407,7 @@ rtt_NewEdgesSplit( RTT_TOPOLOGY* topo, RTT_ELEMID edge,
       &updedge, RTT_COL_EDGE_NEXT_LEFT,
       NULL, 0);
   if ( ret == -1 ) {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rtcollection_release(iface->ctx, split_col);
     rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
     return -1;
@@ -1401,13 +1416,13 @@ rtt_NewEdgesSplit( RTT_TOPOLOGY* topo, RTT_ELEMID edge,
   /* Update TopoGeometries composition */
   ret = rtt_be_updateTopoGeomEdgeSplit(topo, oldedge->edge_id, newedges[0].edge_id, newedges[1].edge_id);
   if ( ! ret ) {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rtcollection_free(iface->ctx, split_col);
     rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
     return -1;
   }
 
-  _rtt_release_edges(iface->ctx, oldedge, 1);
+  rtt_release_edges(iface->ctx, oldedge, 1);
   rtcollection_free(iface->ctx, split_col);
 
   /* return new node id */
@@ -1454,11 +1469,11 @@ _rtt_FirstDistinctVertex2D(const RTCTX *ctx, const RTPOINTARRAY* pa, RTPOINT2D *
     inc = -1;
   }
 
-  RTDEBUGF(1, "first point is index %d", from);
+  RTDEBUGF(ctx, 1, "first point is index %d", from);
   fp = *ref; /* rt_getPoint2d_p(ctx, pa, from, &fp); */
   for ( i = from+inc; i != toofar; i += inc )
   {
-    RTDEBUGF(1, "testing point %d", i);
+    RTDEBUGF(ctx, 1, "testing point %d", i);
     rt_getPoint2d_p(ctx, pa, i, op); /* pick next point */
     if ( p2d_same(ctx, op, &fp) ) continue; /* equal to startpoint */
     /* this is a good one, neither same of start nor of end point */
@@ -1489,7 +1504,7 @@ _rtt_InitEdgeEndByLine(const RTCTX *ctx, edgeend *fee, edgeend *lee, RTLINE *edg
   lee->cwFace = lee->ccwFace = -1;
 
   /* Compute azimuth of first edge end */
-  RTDEBUG(1, "computing azimuth of first edge end");
+  RTDEBUG(ctx, 1, "computing azimuth of first edge end");
   if ( ! _rtt_FirstDistinctVertex2D(ctx, pa, fp, 0, 1, &pt) )
   {
     rterror(ctx, "Invalid edge (no two distinct vertices exist)");
@@ -1500,11 +1515,11 @@ _rtt_InitEdgeEndByLine(const RTCTX *ctx, edgeend *fee, edgeend *lee, RTLINE *edg
             fp->x, fp->y, pt.x, pt.y);
     return -2;
   }
-  RTDEBUGF(1, "azimuth of first edge end [%g %g,%g %g] is %g",
+  RTDEBUGF(ctx, 1, "azimuth of first edge end [%g %g,%g %g] is %g",
             fp->x, fp->y, pt.x, pt.y, fee->myaz);
 
   /* Compute azimuth of second edge end */
-  RTDEBUG(1, "computing azimuth of second edge end");
+  RTDEBUG(ctx, 1, "computing azimuth of second edge end");
   if ( ! _rtt_FirstDistinctVertex2D(ctx, pa, lp, pa->npoints-1, -1, &pt) )
   {
     rterror(ctx, "Invalid edge (no two distinct vertices exist)");
@@ -1515,7 +1530,7 @@ _rtt_InitEdgeEndByLine(const RTCTX *ctx, edgeend *fee, edgeend *lee, RTLINE *edg
             lp->x, lp->y, pt.x, pt.y);
     return -2;
   }
-  RTDEBUGF(1, "azimuth of last edge end [%g %g,%g %g] is %g",
+  RTDEBUGF(ctx, 1, "azimuth of last edge end [%g %g,%g %g] is %g",
             lp->x, lp->y, pt.x, pt.y, lee->myaz);
 
   return 0;
@@ -1553,13 +1568,13 @@ _rtt_FindAdjacentEdges( RTT_TOPOLOGY* topo, RTT_ELEMID node, edgeend *data,
     if ( azdif < 0 ) azdif += 2 * M_PI;
     minaz = maxaz = azdif;
     /* TODO: set nextCW/nextCCW/cwFace/ccwFace to other->something ? */
-    RTDEBUGF(1, "Other edge end has cwFace=%d and ccwFace=%d",
+    RTDEBUGF(iface->ctx, 1, "Other edge end has cwFace=%d and ccwFace=%d",
                 other->cwFace, other->ccwFace);
   } else {
     minaz = maxaz = -1;
   }
 
-  RTDEBUGF(1, "Looking for edges incident to node %" RTTFMT_ELEMID
+  RTDEBUGF(iface->ctx, 1, "Looking for edges incident to node %" RTTFMT_ELEMID
               " and adjacent to azimuth %g", node, data->myaz);
 
   /* Get incident edges */
@@ -1569,7 +1584,7 @@ _rtt_FindAdjacentEdges( RTT_TOPOLOGY* topo, RTT_ELEMID node, edgeend *data,
     return 0;
   }
 
-  RTDEBUGF(1, "getEdgeByNode returned %d edges, minaz=%g, maxaz=%g",
+  RTDEBUGF(iface->ctx, 1, "getEdgeByNode returned %d edges, minaz=%g, maxaz=%g",
               numedges, minaz, maxaz);
 
   /* For each incident edge-end (1 or 2): */
@@ -1593,7 +1608,7 @@ _rtt_FindAdjacentEdges( RTT_TOPOLOGY* topo, RTT_ELEMID node, edgeend *data,
 
     if ( pa->npoints < 2 ) {{
       RTT_ELEMID id = edge->edge_id;
-      _rtt_release_edges(iface->ctx, edges, numedges);
+      rtt_release_edges(iface->ctx, edges, numedges);
       rtgeom_free(iface->ctx, cleangeom);
       rterror(iface->ctx, "corrupted topology: edge %" RTTFMT_ELEMID
               " does not have two distinct points", id);
@@ -1603,20 +1618,20 @@ _rtt_FindAdjacentEdges( RTT_TOPOLOGY* topo, RTT_ELEMID node, edgeend *data,
     if ( edge->start_node == node ) {
       rt_getPoint2d_p(iface->ctx, pa, 0, &p1);
       rt_getPoint2d_p(iface->ctx, pa, 1, &p2);
-      RTDEBUGF(1, "edge %" RTTFMT_ELEMID
+      RTDEBUGF(iface->ctx, 1, "edge %" RTTFMT_ELEMID
                   " starts on node %" RTTFMT_ELEMID
                   ", edgeend is %g,%g-%g,%g",
                   edge->edge_id, node, p1.x, p1.y, p2.x, p2.y);
       if ( ! azimuth_pt_pt(iface->ctx, &p1, &p2, &az) ) {{
         RTT_ELEMID id = edge->edge_id;
-        _rtt_release_edges(iface->ctx, edges, numedges);
+        rtt_release_edges(iface->ctx, edges, numedges);
         rtgeom_free(iface->ctx, cleangeom);
         rterror(iface->ctx, "error computing azimuth of edge %d first edgeend [%g,%g-%g,%g]",
                 id, p1.x, p1.y, p2.x, p2.y);
         return -1;
       }}
       azdif = az - data->myaz;
-      RTDEBUGF(1, "azimuth of edge %" RTTFMT_ELEMID
+      RTDEBUGF(iface->ctx, 1, "azimuth of edge %" RTTFMT_ELEMID
                   ": %g (diff: %g)", edge->edge_id, az, azdif);
 
       if ( azdif < 0 ) azdif += 2 * M_PI;
@@ -1625,7 +1640,7 @@ _rtt_FindAdjacentEdges( RTT_TOPOLOGY* topo, RTT_ELEMID node, edgeend *data,
         data->nextCW = data->nextCCW = edge->edge_id; /* outgoing */
         data->cwFace = edge->face_left;
         data->ccwFace = edge->face_right;
-        RTDEBUGF(1, "new nextCW and nextCCW edge is %" RTTFMT_ELEMID
+        RTDEBUGF(iface->ctx, 1, "new nextCW and nextCCW edge is %" RTTFMT_ELEMID
                     ", outgoing, "
                     "with face_left %" RTTFMT_ELEMID " and face_right %" RTTFMT_ELEMID
                     " (face_right is new ccwFace, face_left is new cwFace)",
@@ -1635,7 +1650,7 @@ _rtt_FindAdjacentEdges( RTT_TOPOLOGY* topo, RTT_ELEMID node, edgeend *data,
         if ( azdif < minaz ) {
           data->nextCW = edge->edge_id; /* outgoing */
           data->cwFace = edge->face_left;
-          RTDEBUGF(1, "new nextCW edge is %" RTTFMT_ELEMID
+          RTDEBUGF(iface->ctx, 1, "new nextCW edge is %" RTTFMT_ELEMID
                       ", outgoing, "
                       "with face_left %" RTTFMT_ELEMID " and face_right %" RTTFMT_ELEMID
                       " (previous had minaz=%g, face_left is new cwFace)",
@@ -1646,7 +1661,7 @@ _rtt_FindAdjacentEdges( RTT_TOPOLOGY* topo, RTT_ELEMID node, edgeend *data,
         else if ( azdif > maxaz ) {
           data->nextCCW = edge->edge_id; /* outgoing */
           data->ccwFace = edge->face_right;
-          RTDEBUGF(1, "new nextCCW edge is %" RTTFMT_ELEMID
+          RTDEBUGF(iface->ctx, 1, "new nextCCW edge is %" RTTFMT_ELEMID
                       ", outgoing, "
                       "with face_left %" RTTFMT_ELEMID " and face_right %" RTTFMT_ELEMID
                       " (previous had maxaz=%g, face_right is new ccwFace)",
@@ -1660,19 +1675,19 @@ _rtt_FindAdjacentEdges( RTT_TOPOLOGY* topo, RTT_ELEMID node, edgeend *data,
     if ( edge->end_node == node ) {
       rt_getPoint2d_p(iface->ctx, pa, pa->npoints-1, &p1);
       rt_getPoint2d_p(iface->ctx, pa, pa->npoints-2, &p2);
-      RTDEBUGF(1, "edge %" RTTFMT_ELEMID " ends on node %" RTTFMT_ELEMID
+      RTDEBUGF(iface->ctx, 1, "edge %" RTTFMT_ELEMID " ends on node %" RTTFMT_ELEMID
                   ", edgeend is %g,%g-%g,%g",
                   edge->edge_id, node, p1.x, p1.y, p2.x, p2.y);
       if ( ! azimuth_pt_pt(iface->ctx, &p1, &p2, &az) ) {{
         RTT_ELEMID id = edge->edge_id;
-        _rtt_release_edges(iface->ctx, edges, numedges);
+        rtt_release_edges(iface->ctx, edges, numedges);
         rtgeom_free(iface->ctx, cleangeom);
         rterror(iface->ctx, "error computing azimuth of edge %d last edgeend [%g,%g-%g,%g]",
                 id, p1.x, p1.y, p2.x, p2.y);
         return -1;
       }}
       azdif = az - data->myaz;
-      RTDEBUGF(1, "azimuth of edge %" RTTFMT_ELEMID
+      RTDEBUGF(iface->ctx, 1, "azimuth of edge %" RTTFMT_ELEMID
                   ": %g (diff: %g)", edge->edge_id, az, azdif);
       if ( azdif < 0 ) azdif += 2 * M_PI;
       if ( minaz == -1 ) {
@@ -1680,7 +1695,7 @@ _rtt_FindAdjacentEdges( RTT_TOPOLOGY* topo, RTT_ELEMID node, edgeend *data,
         data->nextCW = data->nextCCW = -edge->edge_id; /* incoming */
         data->cwFace = edge->face_right;
         data->ccwFace = edge->face_left;
-        RTDEBUGF(1, "new nextCW and nextCCW edge is %" RTTFMT_ELEMID
+        RTDEBUGF(iface->ctx, 1, "new nextCW and nextCCW edge is %" RTTFMT_ELEMID
                     ", incoming, "
                     "with face_left %" RTTFMT_ELEMID " and face_right %" RTTFMT_ELEMID
                     " (face_right is new cwFace, face_left is new ccwFace)",
@@ -1690,7 +1705,7 @@ _rtt_FindAdjacentEdges( RTT_TOPOLOGY* topo, RTT_ELEMID node, edgeend *data,
         if ( azdif < minaz ) {
           data->nextCW = -edge->edge_id; /* incoming */
           data->cwFace = edge->face_right;
-          RTDEBUGF(1, "new nextCW edge is %" RTTFMT_ELEMID
+          RTDEBUGF(iface->ctx, 1, "new nextCW edge is %" RTTFMT_ELEMID
                       ", incoming, "
                       "with face_left %" RTTFMT_ELEMID " and face_right %" RTTFMT_ELEMID
                       " (previous had minaz=%g, face_right is new cwFace)",
@@ -1701,7 +1716,7 @@ _rtt_FindAdjacentEdges( RTT_TOPOLOGY* topo, RTT_ELEMID node, edgeend *data,
         else if ( azdif > maxaz ) {
           data->nextCCW = -edge->edge_id; /* incoming */
           data->ccwFace = edge->face_left;
-          RTDEBUGF(1, "new nextCCW edge is %" RTTFMT_ELEMID
+          RTDEBUGF(iface->ctx, 1, "new nextCCW edge is %" RTTFMT_ELEMID
                       ", outgoing, from start point, "
                       "with face_left %" RTTFMT_ELEMID " and face_right %" RTTFMT_ELEMID
                       " (previous had maxaz=%g, face_left is new ccwFace)",
@@ -1714,9 +1729,9 @@ _rtt_FindAdjacentEdges( RTT_TOPOLOGY* topo, RTT_ELEMID node, edgeend *data,
 
     rtgeom_free(iface->ctx, cleangeom);
   }
-  if ( numedges ) _rtt_release_edges(iface->ctx, edges, numedges);
+  if ( numedges ) rtt_release_edges(iface->ctx, edges, numedges);
 
-  RTDEBUGF(1, "edges adjacent to azimuth %g"
+  RTDEBUGF(iface->ctx, 1, "edges adjacent to azimuth %g"
               " (incident to node %" RTTFMT_ELEMID ")"
               ": CW:%" RTTFMT_ELEMID "(%g) CCW:%" RTTFMT_ELEMID "(%g)",
               data->myaz, node, data->nextCW, minaz,
@@ -1818,19 +1833,19 @@ _rtt_AddFaceSplit( RTT_TOPOLOGY* topo,
             sedge, rtt_be_lastErrorMessage(topo->be_iface));
     return -2;
   }
-  RTDEBUGF(1, "getRingEdges returned %d edges", num_signed_edge_ids);
+  RTDEBUGF(iface->ctx, 1, "getRingEdges returned %d edges", num_signed_edge_ids);
 
   /* You can't get to the other side of an edge forming a ring */
   for (i=0; i<num_signed_edge_ids; ++i) {
     if ( signed_edge_ids[i] == -sedge ) {
       /* No split here */
-      RTDEBUG(1, "not a ring");
+      RTDEBUG(iface->ctx, 1, "not a ring");
       rtfree(iface->ctx,  signed_edge_ids );
       return 0;
     }
   }
 
-  RTDEBUGF(1, "Edge %" RTTFMT_ELEMID " split face %" RTTFMT_ELEMID " (mbr_only:%d)",
+  RTDEBUGF(iface->ctx, 1, "Edge %" RTTFMT_ELEMID " split face %" RTTFMT_ELEMID " (mbr_only:%d)",
            sedge, face, mbr_only);
 
   /* Construct a polygon using edges of the ring */
@@ -1862,7 +1877,7 @@ _rtt_AddFaceSplit( RTT_TOPOLOGY* topo,
   else if ( i != numedges )
   {
     rtfree(iface->ctx,  signed_edge_ids );
-    _rtt_release_edges(iface->ctx, ring_edges, numedges);
+    rtt_release_edges(iface->ctx, ring_edges, numedges);
     rterror(iface->ctx, "Unexpected error: %d edges found when expecting %d", i, numedges);
     return -2;
   }
@@ -1874,7 +1889,7 @@ _rtt_AddFaceSplit( RTT_TOPOLOGY* topo,
   for ( i=0; i<num_signed_edge_ids; ++i )
   {
     RTT_ELEMID eid = signed_edge_ids[i];
-    RTDEBUGF(1, "Edge %d in ring of edge %" RTTFMT_ELEMID " is edge %" RTTFMT_ELEMID,
+    RTDEBUGF(iface->ctx, 1, "Edge %d in ring of edge %" RTTFMT_ELEMID " is edge %" RTTFMT_ELEMID,
                 i, sedge, eid);
     RTT_ISO_EDGE *edge = NULL;
     RTPOINTARRAY *epa;
@@ -1889,7 +1904,7 @@ _rtt_AddFaceSplit( RTT_TOPOLOGY* topo,
     if ( edge == NULL )
     {
       rtfree(iface->ctx,  signed_edge_ids );
-      _rtt_release_edges(iface->ctx, ring_edges, numedges);
+      rtt_release_edges(iface->ctx, ring_edges, numedges);
       rterror(iface->ctx, "missing edge that was found in ring edges loop");
       return -2;
     }
@@ -1923,7 +1938,7 @@ _rtt_AddFaceSplit( RTT_TOPOLOGY* topo,
   RTPOLY* shell = rtpoly_construct(iface->ctx, 0, 0, 1, points);
 
   int isccw = ptarray_isccw(iface->ctx, pa);
-  RTDEBUGF(1, "Ring of edge %" RTTFMT_ELEMID " is %sclockwise",
+  RTDEBUGF(iface->ctx, 1, "Ring of edge %" RTTFMT_ELEMID " is %sclockwise",
               sedge, isccw ? "counter" : "");
   const RTGBOX* shellbox = rtgeom_get_bbox(iface->ctx, rtpoly_as_rtgeom(iface->ctx, shell));
 
@@ -1934,11 +1949,11 @@ _rtt_AddFaceSplit( RTT_TOPOLOGY* topo,
     {
       rtpoly_free(iface->ctx, shell);
       rtfree(iface->ctx,  signed_edge_ids );
-      _rtt_release_edges(iface->ctx, ring_edges, numedges);
+      rtt_release_edges(iface->ctx, ring_edges, numedges);
       /* Face on the left side of this ring is the universe face.
        * Next call (for the other side) should create the split face
        */
-      RTDEBUG(1, "The left face of this clockwise ring is the universe, "
+      RTDEBUG(iface->ctx, 1, "The left face of this clockwise ring is the universe, "
                  "won't create a new face there");
       return -1;
     }
@@ -1955,7 +1970,7 @@ _rtt_AddFaceSplit( RTT_TOPOLOGY* topo,
       if ( ret == -1 )
       {
         rtfree(iface->ctx,  signed_edge_ids );
-        _rtt_release_edges(iface->ctx, ring_edges, numedges);
+        rtt_release_edges(iface->ctx, ring_edges, numedges);
         rtpoly_free(iface->ctx, shell); /* NOTE: owns shellbox above */
         rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
         return -2;
@@ -1963,14 +1978,14 @@ _rtt_AddFaceSplit( RTT_TOPOLOGY* topo,
       if ( ret != 1 )
       {
         rtfree(iface->ctx,  signed_edge_ids );
-        _rtt_release_edges(iface->ctx, ring_edges, numedges);
+        rtt_release_edges(iface->ctx, ring_edges, numedges);
         rtpoly_free(iface->ctx, shell); /* NOTE: owns shellbox above */
         rterror(iface->ctx, "Unexpected error: %d faces found when expecting 1", ret);
         return -2;
       }
     }}
     rtfree(iface->ctx,  signed_edge_ids );
-    _rtt_release_edges(iface->ctx, ring_edges, numedges);
+    rtt_release_edges(iface->ctx, ring_edges, numedges);
     rtpoly_free(iface->ctx, shell); /* NOTE: owns shellbox above */
     return -1; /* mbr only was requested */
   }
@@ -1987,7 +2002,7 @@ _rtt_AddFaceSplit( RTT_TOPOLOGY* topo,
     {
       rtfree(iface->ctx,  signed_edge_ids );
       rtpoly_free(iface->ctx, shell); /* NOTE: owns shellbox */
-      _rtt_release_edges(iface->ctx, ring_edges, numedges);
+      rtt_release_edges(iface->ctx, ring_edges, numedges);
       rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
       return -2;
     }
@@ -1995,7 +2010,7 @@ _rtt_AddFaceSplit( RTT_TOPOLOGY* topo,
     {
       rtfree(iface->ctx,  signed_edge_ids );
       rtpoly_free(iface->ctx, shell); /* NOTE: owns shellbox */
-      _rtt_release_edges(iface->ctx, ring_edges, numedges);
+      rtt_release_edges(iface->ctx, ring_edges, numedges);
       rterror(iface->ctx, "Unexpected error: %d faces found when expecting 1", nfaces);
       return -2;
     }
@@ -2012,7 +2027,7 @@ _rtt_AddFaceSplit( RTT_TOPOLOGY* topo,
   {
     rtfree(iface->ctx,  signed_edge_ids );
     rtpoly_free(iface->ctx, shell); /* NOTE: owns shellbox */
-    _rtt_release_edges(iface->ctx, ring_edges, numedges);
+    rtt_release_edges(iface->ctx, ring_edges, numedges);
     rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
     return -2;
   }
@@ -2020,7 +2035,7 @@ _rtt_AddFaceSplit( RTT_TOPOLOGY* topo,
   {
     rtfree(iface->ctx,  signed_edge_ids );
     rtpoly_free(iface->ctx, shell); /* NOTE: owns shellbox */
-    _rtt_release_edges(iface->ctx, ring_edges, numedges);
+    rtt_release_edges(iface->ctx, ring_edges, numedges);
     rterror(iface->ctx, "Unexpected error: %d faces inserted when expecting 1", ret);
     return -2;
   }
@@ -2034,11 +2049,11 @@ _rtt_AddFaceSplit( RTT_TOPOLOGY* topo,
   /* We want the new face to be on the left, if possible */
   if ( face != 0 && ! isccw ) { /* ring is clockwise in a real face */
     /* face shrinked, must update all non-contained edges and nodes */
-    RTDEBUG(1, "New face is on the outside of the ring, updating rings in former shell");
+    RTDEBUG(iface->ctx, 1, "New face is on the outside of the ring, updating rings in former shell");
     newface_outside = 1;
     /* newface is outside */
   } else {
-    RTDEBUG(1, "New face is on the inside of the ring, updating forward edges in new ring");
+    RTDEBUG(iface->ctx, 1, "New face is on the inside of the ring, updating forward edges in new ring");
     newface_outside = 0;
     /* newface is inside */
   }
@@ -2054,19 +2069,19 @@ _rtt_AddFaceSplit( RTT_TOPOLOGY* topo,
   edges = rtt_be_getEdgeByFace( topo, &face, &numfaceedges, fields, newface.mbr );
   if ( numfaceedges == -1 ) {
     rtfree(iface->ctx,  signed_edge_ids );
-    _rtt_release_edges(iface->ctx, ring_edges, numedges);
+    rtt_release_edges(iface->ctx, ring_edges, numedges);
     rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
     return -2;
   }
-  RTDEBUGF(1, "rtt_be_getEdgeByFace returned %d edges", numfaceedges);
+  RTDEBUGF(iface->ctx, 1, "rtt_be_getEdgeByFace returned %d edges", numfaceedges);
   GEOSGeometry *shellgg = 0;
   const GEOSPreparedGeometry* prepshell = 0;
   shellgg = RTGEOM2GEOS(iface->ctx,  rtpoly_as_rtgeom(iface->ctx, shell), 0);
   if ( ! shellgg ) {
     rtpoly_free(iface->ctx, shell);
     rtfree(iface->ctx, signed_edge_ids);
-    _rtt_release_edges(iface->ctx, ring_edges, numedges);
-    _rtt_release_edges(iface->ctx, edges, numfaceedges);
+    rtt_release_edges(iface->ctx, ring_edges, numedges);
+    rtt_release_edges(iface->ctx, edges, numfaceedges);
     rterror(iface->ctx, "Could not convert shell geometry to GEOS: %s", rtgeom_get_last_geos_error(iface->ctx));
     return -2;
   }
@@ -2075,8 +2090,8 @@ _rtt_AddFaceSplit( RTT_TOPOLOGY* topo,
     GEOSGeom_destroy_r(iface->ctx->gctx, shellgg);
     rtpoly_free(iface->ctx, shell);
     rtfree(iface->ctx, signed_edge_ids);
-    _rtt_release_edges(iface->ctx, ring_edges, numedges);
-    _rtt_release_edges(iface->ctx, edges, numfaceedges);
+    rtt_release_edges(iface->ctx, ring_edges, numedges);
+    rtt_release_edges(iface->ctx, edges, numfaceedges);
     rterror(iface->ctx, "Could not prepare shell geometry: %s", rtgeom_get_last_geos_error(iface->ctx));
     return -2;
   }
@@ -2105,7 +2120,7 @@ _rtt_AddFaceSplit( RTT_TOPOLOGY* topo,
         if ( seid == e->edge_id )
         {
           /* IDEA: remove entry from signed_edge_ids ? */
-          RTDEBUGF(1, "Edge %d is a forward edge of the new ring", e->edge_id);
+          RTDEBUGF(iface->ctx, 1, "Edge %d is a forward edge of the new ring", e->edge_id);
           forward_edges[forward_edges_count].edge_id = e->edge_id;
           forward_edges[forward_edges_count++].face_left = newface.face_id;
           found++;
@@ -2114,7 +2129,7 @@ _rtt_AddFaceSplit( RTT_TOPOLOGY* topo,
         else if ( -seid == e->edge_id )
         {
           /* IDEA: remove entry from signed_edge_ids ? */
-          RTDEBUGF(1, "Edge %d is a backward edge of the new ring", e->edge_id);
+          RTDEBUGF(iface->ctx, 1, "Edge %d is a backward edge of the new ring", e->edge_id);
           backward_edges[backward_edges_count].edge_id = e->edge_id;
           backward_edges[backward_edges_count++].face_right = newface.face_id;
           found++;
@@ -2136,8 +2151,8 @@ _rtt_AddFaceSplit( RTT_TOPOLOGY* topo,
         rtpoly_free(iface->ctx, shell);
         rtfree(iface->ctx, forward_edges); /* contents owned by ring_edges */
         rtfree(iface->ctx, backward_edges); /* contents owned by ring_edges */
-        _rtt_release_edges(iface->ctx, ring_edges, numedges);
-        _rtt_release_edges(iface->ctx, edges, numfaceedges);
+        rtt_release_edges(iface->ctx, ring_edges, numedges);
+        rtt_release_edges(iface->ctx, edges, numfaceedges);
         rterror(iface->ctx, "Could not find interior point for edge %d: %s",
                 e->edge_id, rtgeom_get_last_geos_error(iface->ctx));
         return -2;
@@ -2153,8 +2168,8 @@ _rtt_AddFaceSplit( RTT_TOPOLOGY* topo,
         rtpoly_free(iface->ctx, shell);
         rtfree(iface->ctx, forward_edges); /* contents owned by ring_edges */
         rtfree(iface->ctx, backward_edges); /* contents owned by ring_edges */
-        _rtt_release_edges(iface->ctx, ring_edges, numedges);
-        _rtt_release_edges(iface->ctx, edges, numfaceedges);
+        rtt_release_edges(iface->ctx, ring_edges, numedges);
+        rtt_release_edges(iface->ctx, edges, numfaceedges);
         rterror(iface->ctx, "Could not convert edge geometry to GEOS: %s",
                 rtgeom_get_last_geos_error(iface->ctx));
         return -2;
@@ -2173,12 +2188,12 @@ _rtt_AddFaceSplit( RTT_TOPOLOGY* topo,
         rtpoly_free(iface->ctx, shell);
         rtfree(iface->ctx, forward_edges); /* contents owned by ring_edges */
         rtfree(iface->ctx, backward_edges); /* contents owned by ring_edges */
-        _rtt_release_edges(iface->ctx, ring_edges, numedges);
-        _rtt_release_edges(iface->ctx, edges, numfaceedges);
+        rtt_release_edges(iface->ctx, ring_edges, numedges);
+        rtt_release_edges(iface->ctx, edges, numfaceedges);
         rterror(iface->ctx, "GEOS exception on PreparedContains: %s", rtgeom_get_last_geos_error(iface->ctx));
         return -2;
       }
-      RTDEBUGF(1, "Edge %d %scontained in new ring", e->edge_id,
+      RTDEBUGF(iface->ctx, 1, "Edge %d %scontained in new ring", e->edge_id,
                   (contains?"":"not "));
 
       /* (2.2) skip edges (NOT, if newface_outside) contained in shell */
@@ -2186,7 +2201,7 @@ _rtt_AddFaceSplit( RTT_TOPOLOGY* topo,
       {
         if ( contains )
         {
-          RTDEBUGF(1, "Edge %d contained in an hole of the new face",
+          RTDEBUGF(iface->ctx, 1, "Edge %d contained in an hole of the new face",
                       e->edge_id);
           continue;
         }
@@ -2195,7 +2210,7 @@ _rtt_AddFaceSplit( RTT_TOPOLOGY* topo,
       {
         if ( ! contains )
         {
-          RTDEBUGF(1, "Edge %d not contained in the face shell",
+          RTDEBUGF(iface->ctx, 1, "Edge %d not contained in the face shell",
                       e->edge_id);
           continue;
         }
@@ -2204,7 +2219,7 @@ _rtt_AddFaceSplit( RTT_TOPOLOGY* topo,
       /* (2.3) push to forward_edges if left_face = oface */
       if ( e->face_left == face )
       {
-        RTDEBUGF(1, "Edge %d has new face on the left side", e->edge_id);
+        RTDEBUGF(iface->ctx, 1, "Edge %d has new face on the left side", e->edge_id);
         forward_edges[forward_edges_count].edge_id = e->edge_id;
         forward_edges[forward_edges_count++].face_left = newface.face_id;
       }
@@ -2212,7 +2227,7 @@ _rtt_AddFaceSplit( RTT_TOPOLOGY* topo,
       /* (2.4) push to backward_edges if right_face = oface */
       if ( e->face_right == face )
       {
-        RTDEBUGF(1, "Edge %d has new face on the right side", e->edge_id);
+        RTDEBUGF(iface->ctx, 1, "Edge %d has new face on the right side", e->edge_id);
         backward_edges[backward_edges_count].edge_id = e->edge_id;
         backward_edges[backward_edges_count++].face_right = newface.face_id;
       }
@@ -2265,8 +2280,8 @@ _rtt_AddFaceSplit( RTT_TOPOLOGY* topo,
 
   }
 
-  _rtt_release_edges(iface->ctx, ring_edges, numedges);
-  _rtt_release_edges(iface->ctx, edges, numfaceedges);
+  rtt_release_edges(iface->ctx, ring_edges, numedges);
+  rtt_release_edges(iface->ctx, edges, numfaceedges);
 
   /* Update isolated nodes which are now in new face */
   int numisonodes = 1;
@@ -2309,14 +2324,14 @@ _rtt_AddFaceSplit( RTT_TOPOLOGY* topo,
         rterror(iface->ctx, "GEOS exception on PreparedContains: %s", rtgeom_get_last_geos_error(iface->ctx));
         return -2;
       }
-      RTDEBUGF(1, "Node %d is %scontained in new ring, newface is %s",
+      RTDEBUGF(iface->ctx, 1, "Node %d is %scontained in new ring, newface is %s",
                   n->node_id, contains ? "" : "not ",
                   newface_outside ? "outside" : "inside" );
       if ( newface_outside )
       {
         if ( contains )
         {
-          RTDEBUGF(1, "Node %d contained in an hole of the new face",
+          RTDEBUGF(iface->ctx, 1, "Node %d contained in an hole of the new face",
                       n->node_id);
           continue;
         }
@@ -2325,7 +2340,7 @@ _rtt_AddFaceSplit( RTT_TOPOLOGY* topo,
       {
         if ( ! contains )
         {
-          RTDEBUGF(1, "Node %d not contained in the face shell",
+          RTDEBUGF(iface->ctx, 1, "Node %d not contained in the face shell",
                       n->node_id);
           continue;
         }
@@ -2333,7 +2348,7 @@ _rtt_AddFaceSplit( RTT_TOPOLOGY* topo,
       updated_nodes[nodes_to_update].node_id = n->node_id;
       updated_nodes[nodes_to_update++].containing_face =
                                        newface.face_id;
-      RTDEBUGF(1, "Node %d will be updated", n->node_id);
+      RTDEBUGF(iface->ctx, 1, "Node %d will be updated", n->node_id);
     }
     _rtt_release_nodes(iface->ctx, nodes, numisonodes);
     if ( nodes_to_update )
@@ -2358,6 +2373,13 @@ _rtt_AddFaceSplit( RTT_TOPOLOGY* topo,
   return newface.face_id;
 }
 
+/**
+ * @param modFace can be
+ *    0 - have two new faces replace a splitted face
+ *    1 - modify a splitted face, adding a new one
+ *   -1 - do not check at all for face splitting
+ *
+ */
 static RTT_ELEMID
 _rtt_AddEdge( RTT_TOPOLOGY* topo,
               RTT_ELEMID start_node, RTT_ELEMID end_node,
@@ -2424,7 +2446,7 @@ _rtt_AddEdge( RTT_TOPOLOGY* topo,
             p1.x, p1.y, pn.x, pn.y);
     return -1;
   }
-  RTDEBUGF(1, "edge's start node is %g,%g", p1.x, p1.y);
+  RTDEBUGF(iface->ctx, 1, "edge's start node is %g,%g", p1.x, p1.y);
 
   /* Compute azimuth of last edge end on end node */
   rt_getPoint2d_p(iface->ctx, pa, pa->npoints-1, &p2);
@@ -2435,7 +2457,7 @@ _rtt_AddEdge( RTT_TOPOLOGY* topo,
             p2.x, p2.y, pn.x, pn.y);
     return -1;
   }
-  RTDEBUGF(1, "edge's end node is %g,%g", p2.x, p2.y);
+  RTDEBUGF(iface->ctx, 1, "edge's end node is %g,%g", p2.x, p2.y);
 
   /*
    * Check endpoints existance, match with Curve geometry
@@ -2467,14 +2489,15 @@ _rtt_AddEdge( RTT_TOPOLOGY* topo,
       }
       else if ( newedge.face_left != node->containing_face )
       {
-        _rtt_release_nodes(iface->ctx, endpoints, num_nodes);
         rterror(iface->ctx, "SQL/MM Spatial exception - geometry crosses an edge"
                 " (endnodes in faces %" RTTFMT_ELEMID " and %" RTTFMT_ELEMID ")",
                 newedge.face_left, node->containing_face);
+        _rtt_release_nodes(iface->ctx, endpoints, num_nodes);
+        return -1;
       }
     }
 
-    RTDEBUGF(1, "Node %d, with geom %p (looking for %d and %d)",
+    RTDEBUGF(iface->ctx, 1, "Node %d, with geom %p (looking for %d and %d)",
              node->node_id, node->geom, start_node, end_node);
     if ( node->node_id == start_node ) {
       start_node_geom = node->geom;
@@ -2554,7 +2577,7 @@ _rtt_AddEdge( RTT_TOPOLOGY* topo,
     span.was_isolated = 0;
     newedge.next_right = span.nextCW ? span.nextCW : -newedge.edge_id;
     prev_left = span.nextCCW ? -span.nextCCW : newedge.edge_id;
-    RTDEBUGF(1, "New edge %d is connected on start node, "
+    RTDEBUGF(iface->ctx, 1, "New edge %d is connected on start node, "
                 "next_right is %d, prev_left is %d",
                 newedge.edge_id, newedge.next_right, prev_left);
     if ( newedge.face_right == -1 ) {
@@ -2567,7 +2590,7 @@ _rtt_AddEdge( RTT_TOPOLOGY* topo,
     span.was_isolated = 1;
     newedge.next_right = isclosed ? -newedge.edge_id : newedge.edge_id;
     prev_left = isclosed ? newedge.edge_id : -newedge.edge_id;
-    RTDEBUGF(1, "New edge %d is isolated on start node, "
+    RTDEBUGF(iface->ctx, 1, "New edge %d is isolated on start node, "
                 "next_right is %d, prev_left is %d",
                 newedge.edge_id, newedge.next_right, prev_left);
   }
@@ -2578,12 +2601,12 @@ _rtt_AddEdge( RTT_TOPOLOGY* topo,
     epan.was_isolated = 0;
     newedge.next_left = epan.nextCW ? epan.nextCW : newedge.edge_id;
     prev_right = epan.nextCCW ? -epan.nextCCW : -newedge.edge_id;
-    RTDEBUGF(1, "New edge %d is connected on end node, "
+    RTDEBUGF(iface->ctx, 1, "New edge %d is connected on end node, "
                 "next_left is %d, prev_right is %d",
                 newedge.edge_id, newedge.next_left, prev_right);
     if ( newedge.face_right == -1 ) {
       newedge.face_right = span.ccwFace;
-    } else if ( newedge.face_right != epan.ccwFace ) {
+    } else if ( modFace != -1 && newedge.face_right != epan.ccwFace ) {
       /* side-location conflict */
       rterror(iface->ctx, "Side-location conflict: "
               "new edge starts in face"
@@ -2595,7 +2618,7 @@ _rtt_AddEdge( RTT_TOPOLOGY* topo,
     }
     if ( newedge.face_left == -1 ) {
       newedge.face_left = span.cwFace;
-    } else if ( newedge.face_left != epan.cwFace ) {
+    } else if ( modFace != -1 && newedge.face_left != epan.cwFace ) {
       /* side-location conflict */
       rterror(iface->ctx, "Side-location conflict: "
               "new edge starts in face"
@@ -2609,7 +2632,7 @@ _rtt_AddEdge( RTT_TOPOLOGY* topo,
     epan.was_isolated = 1;
     newedge.next_left = isclosed ? newedge.edge_id : -newedge.edge_id;
     prev_right = isclosed ? -newedge.edge_id : newedge.edge_id;
-    RTDEBUGF(1, "New edge %d is isolated on end node, "
+    RTDEBUGF(iface->ctx, 1, "New edge %d is isolated on end node, "
                 "next_left is %d, prev_right is %d",
                 newedge.edge_id, newedge.next_left, prev_right);
   }
@@ -2626,7 +2649,7 @@ _rtt_AddEdge( RTT_TOPOLOGY* topo,
             newedge.face_left, newedge.face_right);
     return -1;
   }
-  else if ( newedge.face_left == -1 )
+  else if ( newedge.face_left == -1 && modFace > -1 )
   {
     rterror(iface->ctx, "Could not derive edge face from linked primitives:"
             " invalid topology ?");
@@ -2738,11 +2761,13 @@ _rtt_AddEdge( RTT_TOPOLOGY* topo,
     }
   }
 
-  /* Check face splitting */
+  /* Check face splitting, if required */
+
+  if ( modFace > -1 ) {
 
   if ( ! isclosed && ( epan.was_isolated || span.was_isolated ) )
   {
-    RTDEBUG(1, "New edge is dangling, so it cannot split any face");
+    RTDEBUG(iface->ctx, 1, "New edge is dangling, so it cannot split any face");
     return newedge.edge_id; /* no split */
   }
 
@@ -2755,7 +2780,7 @@ _rtt_AddEdge( RTT_TOPOLOGY* topo,
   {
     newface1 = _rtt_AddFaceSplit( topo, -newedge.edge_id, newedge.face_left, 0 );
     if ( newface1 == 0 ) {
-      RTDEBUG(1, "New edge does not split any face");
+      RTDEBUG(iface->ctx, 1, "New edge does not split any face");
       return newedge.edge_id; /* no split */
     }
   }
@@ -2765,7 +2790,7 @@ _rtt_AddEdge( RTT_TOPOLOGY* topo,
   if ( modFace )
   {
     if ( newface == 0 ) {
-      RTDEBUG(1, "New edge does not split any face");
+      RTDEBUG(iface->ctx, 1, "New edge does not split any face");
       return newedge.edge_id; /* no split */
     }
 
@@ -2806,6 +2831,8 @@ _rtt_AddEdge( RTT_TOPOLOGY* topo,
     }
   }
 
+  } // end of face split checking
+
   return newedge.edge_id;
 }
 
@@ -2849,7 +2876,7 @@ _rtt_FaceByEdges(RTT_TOPOLOGY *topo, RTT_ISO_EDGE *edges, int numfaceedges)
     /* Face has no valid boundary edges, we'll return EMPTY, see
      * https://trac.osgeo.org/postgis/ticket/3221 */
     if ( numfaceedges ) rtfree(iface->ctx, geoms);
-    RTDEBUG(1, "_rtt_FaceByEdges returning empty polygon");
+    RTDEBUG(iface->ctx, 1, "_rtt_FaceByEdges returning empty polygon");
     return rtpoly_as_rtgeom(iface->ctx,
             rtpoly_construct_empty(iface->ctx, topo->srid, topo->hasZ, 0)
            );
@@ -2866,7 +2893,7 @@ _rtt_FaceByEdges(RTT_TOPOLOGY *topo, RTT_ISO_EDGE *edges, int numfaceedges)
   {
   size_t sz;
   char *wkt = rtgeom_to_wkt(iface->ctx, outg, RTWKT_EXTENDED, 2, &sz);
-  RTDEBUGF(1, "_rtt_FaceByEdges returning area: %s", wkt);
+  RTDEBUGF(iface->ctx, 1, "_rtt_FaceByEdges returning area: %s", wkt);
   rtfree(iface->ctx, wkt);
   }
 #endif
@@ -2928,7 +2955,7 @@ rtt_GetFaceGeometry(RTT_TOPOLOGY* topo, RTT_ELEMID faceid)
   }
 
   outg = _rtt_FaceByEdges( topo, edges, numfaceedges );
-  _rtt_release_edges(iface->ctx, edges, numfaceedges);
+  rtt_release_edges(iface->ctx, edges, numfaceedges);
 
   return outg;
 }
@@ -2957,7 +2984,7 @@ _rtt_FindNextRingEdge(const RTCTX *ctx, const RTPOINTARRAY *ring, int from,
   /* Get starting ring point */
   rt_getPoint2d_p(ctx, ring, from, &p1);
 
-  RTDEBUGF(1, "Ring's 'from' point (%d) is %g,%g", from, p1.x, p1.y);
+  RTDEBUGF(ctx, 1, "Ring's 'from' point (%d) is %g,%g", from, p1.x, p1.y);
 
   /* find the edges defining the next portion of ring starting from
    * vertex "from" */
@@ -2973,7 +3000,7 @@ _rtt_FindNextRingEdge(const RTCTX *ctx, const RTPOINTARRAY *ring, int from,
     /* Skip if the edge is a dangling one */
     if ( isoe->face_left == isoe->face_right )
     {
-      RTDEBUGF(3, "_rtt_FindNextRingEdge: edge %" RTTFMT_ELEMID
+      RTDEBUGF(ctx, 3, "_rtt_FindNextRingEdge: edge %" RTTFMT_ELEMID
                   " has same face (%" RTTFMT_ELEMID
                   ") on both sides, skipping",
                   isoe->edge_id, isoe->face_left);
@@ -2982,7 +3009,7 @@ _rtt_FindNextRingEdge(const RTCTX *ctx, const RTPOINTARRAY *ring, int from,
 
 #if 0
     size_t sz;
-    RTDEBUGF(1, "Edge %" RTTFMT_ELEMID " is %s",
+    RTDEBUGF(ctx, 1, "Edge %" RTTFMT_ELEMID " is %s",
                 isoe->edge_id,
                 rtgeom_to_wkt(ctx, rtline_as_rtgeom(ctx, edge), RTWKT_EXTENDED, 2, &sz));
 #endif
@@ -2990,35 +3017,35 @@ _rtt_FindNextRingEdge(const RTCTX *ctx, const RTPOINTARRAY *ring, int from,
     /* ptarray_remove_repeated_points ? */
 
     rt_getPoint2d_p(ctx, epa, 0, &p2);
-    RTDEBUGF(1, "Edge %" RTTFMT_ELEMID " 'first' point is %g,%g",
+    RTDEBUGF(ctx, 1, "Edge %" RTTFMT_ELEMID " 'first' point is %g,%g",
                 isoe->edge_id, p2.x, p2.y);
-    RTDEBUGF(1, "Rings's 'from' point is still %g,%g", p1.x, p1.y);
+    RTDEBUGF(ctx, 1, "Rings's 'from' point is still %g,%g", p1.x, p1.y);
     if ( p2d_same(ctx, &p1, &p2) )
     {
-      RTDEBUG(1, "p2d_same(ctx, p1,p2) returned true");
-      RTDEBUGF(1, "First point of edge %" RTTFMT_ELEMID
+      RTDEBUG(ctx, 1, "p2d_same(ctx, p1,p2) returned true");
+      RTDEBUGF(ctx, 1, "First point of edge %" RTTFMT_ELEMID
                   " matches ring vertex %d", isoe->edge_id, from);
       /* first point matches, let's check next non-equal one */
       for ( j=1; j<epa->npoints; ++j )
       {
         rt_getPoint2d_p(ctx, epa, j, &p2);
-        RTDEBUGF(1, "Edge %" RTTFMT_ELEMID " 'next' point %d is %g,%g",
+        RTDEBUGF(ctx, 1, "Edge %" RTTFMT_ELEMID " 'next' point %d is %g,%g",
                     isoe->edge_id, j, p2.x, p2.y);
         /* we won't check duplicated edge points */
         if ( p2d_same(ctx, &p1, &p2) ) continue;
         /* we assume there are no duplicated points in ring */
         rt_getPoint2d_p(ctx, ring, from+1, &pt);
-        RTDEBUGF(1, "Ring's point %d is %g,%g",
+        RTDEBUGF(ctx, 1, "Ring's point %d is %g,%g",
                     from+1, pt.x, pt.y);
         match = p2d_same(ctx, &pt, &p2);
         break; /* we want to check a single non-equal next vertex */
       }
 #if RTGEOM_DEBUG_LEVEL > 0
       if ( match ) {
-        RTDEBUGF(1, "Prev point of edge %" RTTFMT_ELEMID
+        RTDEBUGF(ctx, 1, "Prev point of edge %" RTTFMT_ELEMID
                     " matches ring vertex %d", isoe->edge_id, from+1);
       } else {
-        RTDEBUGF(1, "Prev point of edge %" RTTFMT_ELEMID
+        RTDEBUGF(ctx, 1, "Prev point of edge %" RTTFMT_ELEMID
                     " does not match ring vertex %d", isoe->edge_id, from+1);
       }
 #endif
@@ -3026,26 +3053,26 @@ _rtt_FindNextRingEdge(const RTCTX *ctx, const RTPOINTARRAY *ring, int from,
 
     if ( ! match )
     {
-      RTDEBUGF(1, "Edge %" RTTFMT_ELEMID " did not match as forward",
+      RTDEBUGF(ctx, 1, "Edge %" RTTFMT_ELEMID " did not match as forward",
                  isoe->edge_id);
       rt_getPoint2d_p(ctx, epa, epa->npoints-1, &p2);
-      RTDEBUGF(1, "Edge %" RTTFMT_ELEMID " 'last' point is %g,%g",
+      RTDEBUGF(ctx, 1, "Edge %" RTTFMT_ELEMID " 'last' point is %g,%g",
                   isoe->edge_id, p2.x, p2.y);
       if ( p2d_same(ctx, &p1, &p2) )
       {
-        RTDEBUGF(1, "Last point of edge %" RTTFMT_ELEMID
+        RTDEBUGF(ctx, 1, "Last point of edge %" RTTFMT_ELEMID
                     " matches ring vertex %d", isoe->edge_id, from);
         /* last point matches, let's check next non-equal one */
         for ( j=epa->npoints-2; j>=0; --j )
         {
           rt_getPoint2d_p(ctx, epa, j, &p2);
-          RTDEBUGF(1, "Edge %" RTTFMT_ELEMID " 'prev' point %d is %g,%g",
+          RTDEBUGF(ctx, 1, "Edge %" RTTFMT_ELEMID " 'prev' point %d is %g,%g",
                       isoe->edge_id, j, p2.x, p2.y);
           /* we won't check duplicated edge points */
           if ( p2d_same(ctx, &p1, &p2) ) continue;
           /* we assume there are no duplicated points in ring */
           rt_getPoint2d_p(ctx, ring, from+1, &pt);
-          RTDEBUGF(1, "Ring's point %d is %g,%g",
+          RTDEBUGF(ctx, 1, "Ring's point %d is %g,%g",
                       from+1, pt.x, pt.y);
           match = p2d_same(ctx, &pt, &p2);
           break; /* we want to check a single non-equal next vertex */
@@ -3053,10 +3080,10 @@ _rtt_FindNextRingEdge(const RTCTX *ctx, const RTPOINTARRAY *ring, int from,
       }
 #if RTGEOM_DEBUG_LEVEL > 0
       if ( match ) {
-        RTDEBUGF(1, "Prev point of edge %" RTTFMT_ELEMID
+        RTDEBUGF(ctx, 1, "Prev point of edge %" RTTFMT_ELEMID
                     " matches ring vertex %d", isoe->edge_id, from+1);
       } else {
-        RTDEBUGF(1, "Prev point of edge %" RTTFMT_ELEMID
+        RTDEBUGF(ctx, 1, "Prev point of edge %" RTTFMT_ELEMID
                     " does not match ring vertex %d", isoe->edge_id, from+1);
       }
 #endif
@@ -3128,14 +3155,14 @@ rtt_GetFaceEdges(RTT_TOPOLOGY* topo, RTT_ELEMID face_id, RTT_ELEMID **out )
   if ( ! face )
   {
     /* _rtt_FaceByEdges should have already invoked rterror in this case */
-    _rtt_release_edges(iface->ctx, edges, numfaceedges);
+    rtt_release_edges(iface->ctx, edges, numfaceedges);
     return -1;
   }
 
   if ( rtgeom_is_empty(iface->ctx, face) )
   {
     /* no edges in output */
-    _rtt_release_edges(iface->ctx, edges, numfaceedges);
+    rtt_release_edges(iface->ctx, edges, numfaceedges);
     rtgeom_free(iface->ctx, face);
     return 0;
   }
@@ -3149,7 +3176,7 @@ rtt_GetFaceEdges(RTT_TOPOLOGY* topo, RTT_ELEMID face_id, RTT_ELEMID **out )
   {
   size_t sz;
   char *wkt = rtgeom_to_wkt(iface->ctx, face, RTWKT_EXTENDED, 6, &sz);
-  RTDEBUGF(1, "Geometry of face %" RTTFMT_ELEMID " is: %s",
+  RTDEBUGF(ctx, 1, "Geometry of face %" RTTFMT_ELEMID " is: %s",
               face_id, wkt);
   rtfree(iface->ctx, wkt);
   }
@@ -3158,7 +3185,7 @@ rtt_GetFaceEdges(RTT_TOPOLOGY* topo, RTT_ELEMID face_id, RTT_ELEMID **out )
   facepoly = rtgeom_as_rtpoly(iface->ctx, face);
   if ( ! facepoly )
   {
-    _rtt_release_edges(iface->ctx, edges, numfaceedges);
+    rtt_release_edges(iface->ctx, edges, numfaceedges);
     rtgeom_free(iface->ctx, face);
     rterror(iface->ctx, "Geometry of face %" RTTFMT_ELEMID " is not a polygon", face_id);
     return -1;
@@ -3175,18 +3202,18 @@ rtt_GetFaceEdges(RTT_TOPOLOGY* topo, RTT_ELEMID face_id, RTT_ELEMID **out )
     RTT_ISO_EDGE *nextedge;
     RTLINE *nextline;
 
-    RTDEBUGF(1, "Ring %d has %d points", i, ring->npoints);
+    RTDEBUGF(iface->ctx, 1, "Ring %d has %d points", i, ring->npoints);
 
     while ( j < ring->npoints-1 )
     {
-      RTDEBUGF(1, "Looking for edge covering ring %d from vertex %d",
+      RTDEBUGF(iface->ctx, 1, "Looking for edge covering ring %d from vertex %d",
                   i, j);
 
       int edgeno = _rtt_FindNextRingEdge(iface->ctx, ring, j, edges, numfaceedges);
       if ( edgeno == -1 )
       {
         /* should never happen */
-        _rtt_release_edges(iface->ctx, edges, numfaceedges);
+        rtt_release_edges(iface->ctx, edges, numfaceedges);
         rtgeom_free(iface->ctx, face);
         rtfree(iface->ctx, seid);
         rterror(iface->ctx, "No edge (among %d) found to be defining geometry of face %"
@@ -3197,7 +3224,7 @@ rtt_GetFaceEdges(RTT_TOPOLOGY* topo, RTT_ELEMID face_id, RTT_ELEMID **out )
       nextedge = &(edges[edgeno]);
       nextline = nextedge->geom;
 
-      RTDEBUGF(1, "Edge %" RTTFMT_ELEMID
+      RTDEBUGF(iface->ctx, 1, "Edge %" RTTFMT_ELEMID
                   " covers ring %d from vertex %d to %d",
                   nextedge->edge_id, i, j, j + nextline->points->npoints - 1);
 
@@ -3205,7 +3232,7 @@ rtt_GetFaceEdges(RTT_TOPOLOGY* topo, RTT_ELEMID face_id, RTT_ELEMID **out )
       {
       size_t sz;
       char *wkt = rtgeom_to_wkt(iface->ctx, rtline_as_rtgeom(iface->ctx, nextline), RTWKT_EXTENDED, 6, &sz);
-      RTDEBUGF(1, "Edge %" RTTFMT_ELEMID " is %s",
+      RTDEBUGF(iface->ctx, 1, "Edge %" RTTFMT_ELEMID " is %s",
                   nextedge->edge_id, wkt);
       rtfree(iface->ctx, wkt);
       }
@@ -3229,19 +3256,19 @@ rtt_GetFaceEdges(RTT_TOPOLOGY* topo, RTT_ELEMID face_id, RTT_ELEMID **out )
     {{
       RTT_ELEMID minid = 0;
       int minidx = 0;
-      RTDEBUGF(1, "Looking for smallest id among the %d edges "
+      RTDEBUGF(iface->ctx, 1, "Looking for smallest id among the %d edges "
                   "composing ring %d", (nseid-prevseid), i);
       for ( j=prevseid; j<nseid; ++j )
       {
         RTT_ELEMID id = llabs(seid[j]);
-        RTDEBUGF(1, "Abs id of edge in pos %d is %" RTTFMT_ELEMID, j, id);
+        RTDEBUGF(iface->ctx, 1, "Abs id of edge in pos %d is %" RTTFMT_ELEMID, j, id);
         if ( ! minid || id < minid )
         {
           minid = id;
           minidx = j;
         }
       }
-      RTDEBUGF(1, "Smallest id is %" RTTFMT_ELEMID
+      RTDEBUGF(iface->ctx, 1, "Smallest id is %" RTTFMT_ELEMID
                   " at position %d", minid, minidx);
       if ( minidx != prevseid )
       {
@@ -3253,7 +3280,7 @@ rtt_GetFaceEdges(RTT_TOPOLOGY* topo, RTT_ELEMID face_id, RTT_ELEMID **out )
   }
 
   rtgeom_free(iface->ctx, face);
-  _rtt_release_edges(iface->ctx, edges, numfaceedges);
+  rtt_release_edges(iface->ctx, edges, numfaceedges);
 
   *out = seid;
   return nseid;
@@ -3336,7 +3363,7 @@ rtt_ChangeEdgeGeom(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, RTLINE *geom)
   oldedge = rtt_be_getEdgeById(topo, &edge_id, &i, RTT_COL_EDGE_ALL);
   if ( ! oldedge )
   {
-    RTDEBUGF(1, "rtt_ChangeEdgeGeom: "
+    RTDEBUGF(iface->ctx, 1, "rtt_ChangeEdgeGeom: "
                 "rtt_be_getEdgeById returned NULL and set i=%d", i);
     if ( i == -1 )
     {
@@ -3358,7 +3385,7 @@ rtt_ChangeEdgeGeom(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, RTLINE *geom)
     }
   }
 
-  RTDEBUGF(1, "rtt_ChangeEdgeGeom: "
+  RTDEBUGF(iface->ctx, 1, "rtt_ChangeEdgeGeom: "
               "old edge has %d points, new edge has %d points",
               oldedge->geom->points->npoints, geom->points->npoints);
 
@@ -3369,7 +3396,7 @@ rtt_ChangeEdgeGeom(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, RTLINE *geom)
   rt_getPoint2d_p(iface->ctx, geom->points, 0, &pt);
   if ( ! p2d_same(iface->ctx, &p1, &pt) )
   {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rterror(iface->ctx, "SQL/MM Spatial exception - "
             "start node not geometry start point.");
     return -1;
@@ -3380,7 +3407,7 @@ rtt_ChangeEdgeGeom(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, RTLINE *geom)
    */
   if ( oldedge->geom->points->npoints < 2 )
   {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rterror(iface->ctx, "Corrupted topology: edge %" RTTFMT_ELEMID
             " has less than 2 vertices", oldedge->edge_id);
     return -1;
@@ -3388,14 +3415,14 @@ rtt_ChangeEdgeGeom(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, RTLINE *geom)
   rt_getPoint2d_p(iface->ctx, oldedge->geom->points, oldedge->geom->points->npoints-1, &p2);
   if ( geom->points->npoints < 2 )
   {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rterror(iface->ctx, "Invalid edge: less than 2 vertices");
     return -1;
   }
   rt_getPoint2d_p(iface->ctx, geom->points, geom->points->npoints-1, &pt);
   if ( ! p2d_same(iface->ctx, &pt, &p2) )
   {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rterror(iface->ctx, "SQL/MM Spatial exception - "
             "end node not geometry end point.");
     return -1;
@@ -3412,7 +3439,7 @@ rtt_ChangeEdgeGeom(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, RTLINE *geom)
     /* check for valid edge (distinct vertices must exist) */
     if ( ! _rtt_GetInteriorEdgePoint(iface->ctx, geom, &pt) )
     {
-      _rtt_release_edges(iface->ctx, oldedge, 1);
+      rtt_release_edges(iface->ctx, oldedge, 1);
       rterror(iface->ctx, "Invalid edge (no two distinct vertices exist)");
       return -1;
     }
@@ -3421,7 +3448,7 @@ rtt_ChangeEdgeGeom(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, RTLINE *geom)
     if ( ptarray_isccw(iface->ctx, oldedge->geom->points) !=
          ptarray_isccw(iface->ctx, geom->points) )
     {
-      _rtt_release_edges(iface->ctx, oldedge, 1);
+      rtt_release_edges(iface->ctx, oldedge, 1);
       rterror(iface->ctx, "Edge twist at node POINT(%g %g)", p1.x, p1.y);
       return -1;
     }
@@ -3431,11 +3458,11 @@ rtt_ChangeEdgeGeom(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, RTLINE *geom)
                                     oldedge->end_node, geom, edge_id ) )
   {
     /* would have called rterror already, leaking :( */
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     return -1;
   }
 
-  RTDEBUG(1, "rtt_ChangeEdgeGeom: "
+  RTDEBUG(iface->ctx, 1, "rtt_ChangeEdgeGeom: "
              "edge crossing check passed ");
 
   /*
@@ -3454,9 +3481,9 @@ rtt_ChangeEdgeGeom(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, RTLINE *geom)
   int numnodes;
   nodes = rtt_be_getNodeWithinBox2D(topo, &mbox, &numnodes,
                                           RTT_COL_NODE_ALL, 0);
-  RTDEBUGF(1, "rtt_be_getNodeWithinBox2D returned %d nodes", numnodes);
+  RTDEBUGF(iface->ctx, 1, "rtt_be_getNodeWithinBox2D returned %d nodes", numnodes);
   if ( numnodes == -1 ) {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
     return -1;
   }
@@ -3471,7 +3498,7 @@ rtt_ChangeEdgeGeom(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, RTLINE *geom)
     oarea = _rtt_EdgeMotionArea(iface->ctx, oldedge->geom, isclosed);
     if ( ! oarea )
     {
-      _rtt_release_edges(iface->ctx, oldedge, 1);
+      rtt_release_edges(iface->ctx, oldedge, 1);
       rterror(iface->ctx, "Could not compute edge motion area for old edge");
       return -1;
     }
@@ -3480,7 +3507,7 @@ rtt_ChangeEdgeGeom(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, RTLINE *geom)
     if ( ! narea )
     {
       GEOSGeom_destroy_r(iface->ctx->gctx, oarea);
-      _rtt_release_edges(iface->ctx, oldedge, 1);
+      rtt_release_edges(iface->ctx, oldedge, 1);
       rterror(iface->ctx, "Could not compute edge motion area for new edge");
       return -1;
     }
@@ -3531,7 +3558,7 @@ rtt_ChangeEdgeGeom(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, RTLINE *geom)
   }}
   if ( numnodes ) _rtt_release_nodes(iface->ctx, nodes, numnodes);
 
-  RTDEBUG(1, "nodes containment check passed");
+  RTDEBUG(iface->ctx, 1, "nodes containment check passed");
 
   /*
    * Check edge adjacency before
@@ -3548,7 +3575,7 @@ rtt_ChangeEdgeGeom(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, RTLINE *geom)
   _rtt_FindAdjacentEdges( topo, oldedge->end_node, &epan_pre,
                                   isclosed ? &span_pre : NULL, edge_id );
 
-  RTDEBUGF(1, "edges adjacent to old edge are %" RTTFMT_ELEMID
+  RTDEBUGF(iface->ctx, 1, "edges adjacent to old edge are %" RTTFMT_ELEMID
               " and %" RTTFMT_ELEMID " (first point), %" RTTFMT_ELEMID
               " and %" RTTFMT_ELEMID " (last point)" RTTFMT_ELEMID,
               span_pre.nextCW, span_pre.nextCCW,
@@ -3560,13 +3587,13 @@ rtt_ChangeEdgeGeom(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, RTLINE *geom)
   i = rtt_be_updateEdgesById(topo, &newedge, 1, RTT_COL_EDGE_GEOM);
   if ( i == -1 )
   {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
     return -1;
   }
   if ( ! i )
   {
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rterror(iface->ctx, "Unexpected error: %d edges updated when expecting 1", i);
     return -1;
   }
@@ -3586,7 +3613,7 @@ rtt_ChangeEdgeGeom(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, RTLINE *geom)
   _rtt_FindAdjacentEdges( topo, oldedge->end_node, &epan_post,
                           isclosed ? &span_post : NULL, edge_id );
 
-  RTDEBUGF(1, "edges adjacent to new edge are %" RTTFMT_ELEMID
+  RTDEBUGF(iface->ctx, 1, "edges adjacent to new edge are %" RTTFMT_ELEMID
               " and %" RTTFMT_ELEMID " (first point), %" RTTFMT_ELEMID
               " and %" RTTFMT_ELEMID " (last point)" RTTFMT_ELEMID,
               span_pre.nextCW, span_pre.nextCCW,
@@ -3598,7 +3625,7 @@ rtt_ChangeEdgeGeom(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, RTLINE *geom)
        span_pre.nextCCW != span_post.nextCCW )
   {{
     RTT_ELEMID nid = oldedge->start_node;
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rterror(iface->ctx, "Edge changed disposition around start node %"
             RTTFMT_ELEMID, nid);
     return -1;
@@ -3609,7 +3636,7 @@ rtt_ChangeEdgeGeom(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, RTLINE *geom)
        epan_pre.nextCCW != epan_post.nextCCW )
   {{
     RTT_ELEMID nid = oldedge->end_node;
-    _rtt_release_edges(iface->ctx, oldedge, 1);
+    rtt_release_edges(iface->ctx, oldedge, 1);
     rterror(iface->ctx, "Edge changed disposition around end node %"
             RTTFMT_ELEMID, nid);
     return -1;
@@ -3627,7 +3654,7 @@ rtt_ChangeEdgeGeom(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, RTLINE *geom)
   RTT_ISO_FACE faces[2];
   RTGEOM *nface1 = NULL;
   RTGEOM *nface2 = NULL;
-  if ( oldedge->face_left != 0 )
+  if ( oldedge->face_left > 0 )
   {
     nface1 = rtt_GetFaceGeometry(topo, oldedge->face_left);
     if ( ! nface1 )
@@ -3641,7 +3668,7 @@ rtt_ChangeEdgeGeom(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, RTLINE *geom)
     {
     size_t sz;
     char *wkt = rtgeom_to_wkt(iface->ctx, nface1, RTWKT_EXTENDED, 2, &sz);
-    RTDEBUGF(1, "new geometry of face left (%d): %s", (int)oldedge->face_left, wkt);
+    RTDEBUGF(iface->ctx, 1, "new geometry of face left (%d): %s", (int)oldedge->face_left, wkt);
     rtfree(iface->ctx, wkt);
     }
 #endif
@@ -3650,7 +3677,7 @@ rtt_ChangeEdgeGeom(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, RTLINE *geom)
     /* ownership left to nface */
     faces[facestoupdate++].mbr = nface1->bbox;
   }
-  if ( oldedge->face_right != 0
+  if ( oldedge->face_right > 0
        /* no need to update twice the same face.. */
        && oldedge->face_right != oldedge->face_left )
   {
@@ -3666,7 +3693,7 @@ rtt_ChangeEdgeGeom(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, RTLINE *geom)
     {
     size_t sz;
     char *wkt = rtgeom_to_wkt(iface->ctx, nface2, RTWKT_EXTENDED, 2, &sz);
-    RTDEBUGF(1, "new geometry of face right (%d): %s", (int)oldedge->face_right, wkt);
+    RTDEBUGF(iface->ctx, 1, "new geometry of face right (%d): %s", (int)oldedge->face_right, wkt);
     rtfree(iface->ctx, wkt);
     }
 #endif
@@ -3674,7 +3701,7 @@ rtt_ChangeEdgeGeom(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, RTLINE *geom)
     faces[facestoupdate].face_id = oldedge->face_right;
     faces[facestoupdate++].mbr = nface2->bbox; /* ownership left to nface */
   }
-  RTDEBUGF(1, "%d faces to update", facestoupdate);
+  RTDEBUGF(iface->ctx, 1, "%d faces to update", facestoupdate);
   if ( facestoupdate )
   {
     i = rtt_be_updateFacesById( topo, &(faces[0]), facestoupdate );
@@ -3682,7 +3709,7 @@ rtt_ChangeEdgeGeom(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, RTLINE *geom)
     {
       if ( nface1 ) rtgeom_free(iface->ctx, nface1);
       if ( nface2 ) rtgeom_free(iface->ctx, nface2);
-      _rtt_release_edges(iface->ctx, oldedge, 1);
+      rtt_release_edges(iface->ctx, oldedge, 1);
       if ( i == -1 )
         rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
       else
@@ -3693,9 +3720,9 @@ rtt_ChangeEdgeGeom(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, RTLINE *geom)
   if ( nface1 ) rtgeom_free(iface->ctx, nface1);
   if ( nface2 ) rtgeom_free(iface->ctx, nface2);
 
-  RTDEBUG(1, "all done, cleaning up edges");
+  RTDEBUG(iface->ctx, 1, "all done, cleaning up edges");
 
-  _rtt_release_edges(iface->ctx, oldedge, 1);
+  rtt_release_edges(iface->ctx, oldedge, 1);
   return 0; /* success */
 }
 
@@ -3990,7 +4017,7 @@ _rtt_RemEdge(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, int modFace )
   edge = rtt_be_getEdgeById(topo, &edge_id, &i, RTT_COL_EDGE_ALL);
   if ( ! edge )
   {
-    RTDEBUGF(1, "rtt_be_getEdgeById returned NULL and set i=%d", i);
+    RTDEBUGF(iface->ctx, 1, "rtt_be_getEdgeById returned NULL and set i=%d", i);
     if ( i == -1 )
     {
       rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
@@ -4018,7 +4045,7 @@ _rtt_RemEdge(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, int modFace )
     return -1;
   }
 
-  RTDEBUG(1, "Updating next_{right,left}_face of ring edges...");
+  RTDEBUG(iface->ctx, 1, "Updating next_{right,left}_face of ring edges...");
 
   /* Update edge linking */
 
@@ -4078,13 +4105,13 @@ _rtt_RemEdge(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, int modFace )
 
   if ( nedge_left )
   {
-    RTDEBUGF(1, "updating %d 'next_left' edges", nedge_left);
+    RTDEBUGF(iface->ctx, 1, "updating %d 'next_left' edges", nedge_left);
     /* update edges in upd_edge_left set next_left */
     i = rtt_be_updateEdgesById(topo, &(upd_edge_left[0]), nedge_left,
                                RTT_COL_EDGE_NEXT_LEFT);
     if ( i == -1 )
     {
-      _rtt_release_edges(iface->ctx, edge, 1);
+      rtt_release_edges(iface->ctx, edge, 1);
       rtfree(iface->ctx, upd_edge);
       rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
       return -1;
@@ -4092,19 +4119,19 @@ _rtt_RemEdge(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, int modFace )
   }
   if ( nedge_right )
   {
-    RTDEBUGF(1, "updating %d 'next_right' edges", nedge_right);
+    RTDEBUGF(iface->ctx, 1, "updating %d 'next_right' edges", nedge_right);
     /* update edges in upd_edge_right set next_right */
     i = rtt_be_updateEdgesById(topo, &(upd_edge_right[0]), nedge_right,
                                RTT_COL_EDGE_NEXT_RIGHT);
     if ( i == -1 )
     {
-      _rtt_release_edges(iface->ctx, edge, 1);
+      rtt_release_edges(iface->ctx, edge, 1);
       rtfree(iface->ctx, upd_edge);
       rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
       return -1;
     }
   }
-  RTDEBUGF(1, "releasing %d updateable edges in %p", nedges, upd_edge);
+  RTDEBUGF(iface->ctx, 1, "releasing %d updateable edges in %p", nedges, upd_edge);
   rtfree(iface->ctx, upd_edge);
 
   /* Id of face that will take up all the space previously
@@ -4122,14 +4149,14 @@ _rtt_RemEdge(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, int modFace )
     if ( edge->face_left == 0 || edge->face_right == 0 )
     {
       floodface = 0;
-      RTDEBUG(1, "floodface is universe");
+      RTDEBUG(iface->ctx, 1, "floodface is universe");
     }
     else
     {
       /* we choose right face as the face that will remain
        * to be symmetric with ST_AddEdgeModFace */
       floodface = edge->face_right;
-      RTDEBUGF(1, "floodface is %" RTTFMT_ELEMID, floodface);
+      RTDEBUGF(iface->ctx, 1, "floodface is %" RTTFMT_ELEMID, floodface);
       /* update mbr of floodface as union of mbr of both faces */
       face_ids[0] = edge->face_left;
       face_ids[1] = edge->face_right;
@@ -4150,7 +4177,7 @@ _rtt_RemEdge(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, int modFace )
           else
           {
             i = edge->face_left;
-            _rtt_release_edges(iface->ctx, edge, 1);
+            rtt_release_edges(iface->ctx, edge, 1);
             _rtt_release_faces(iface->ctx, faces, nfaces);
             rterror(iface->ctx, "corrupted topology: more than 1 face have face_id=%"
                     RTTFMT_ELEMID, i);
@@ -4163,7 +4190,7 @@ _rtt_RemEdge(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, int modFace )
           else
           {
             i = edge->face_right;
-            _rtt_release_edges(iface->ctx, edge, 1);
+            rtt_release_edges(iface->ctx, edge, 1);
             _rtt_release_faces(iface->ctx, faces, nfaces);
             rterror(iface->ctx, "corrupted topology: more than 1 face have face_id=%"
                     RTTFMT_ELEMID, i);
@@ -4173,7 +4200,7 @@ _rtt_RemEdge(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, int modFace )
         else
         {
           i = faces[i].face_id;
-          _rtt_release_edges(iface->ctx, edge, 1);
+          rtt_release_edges(iface->ctx, edge, 1);
           _rtt_release_faces(iface->ctx, faces, nfaces);
           rterror(iface->ctx, "Backend coding error: getFaceById returned face "
                   "with non-requested id %" RTTFMT_ELEMID, i);
@@ -4182,7 +4209,7 @@ _rtt_RemEdge(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, int modFace )
       }
       if ( ! box1 ) {
         i = edge->face_left;
-        _rtt_release_edges(iface->ctx, edge, 1);
+        rtt_release_edges(iface->ctx, edge, 1);
         _rtt_release_faces(iface->ctx, faces, nfaces);
         rterror(iface->ctx, "corrupted topology: no face have face_id=%"
                 RTTFMT_ELEMID " (left face for edge %"
@@ -4191,7 +4218,7 @@ _rtt_RemEdge(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, int modFace )
       }
       if ( ! box2 ) {
         i = edge->face_right;
-        _rtt_release_edges(iface->ctx, edge, 1);
+        rtt_release_edges(iface->ctx, edge, 1);
         _rtt_release_faces(iface->ctx, faces, nfaces);
         rterror(iface->ctx, "corrupted topology: no face have face_id=%"
                 RTTFMT_ELEMID " (right face for edge %"
@@ -4207,13 +4234,13 @@ _rtt_RemEdge(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, int modFace )
         _rtt_release_faces(iface->ctx, faces, 2);
         if ( i == -1 )
         {
-          _rtt_release_edges(iface->ctx, edge, 1);
+          rtt_release_edges(iface->ctx, edge, 1);
           rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
           return -1;
         }
         if ( i != 1 )
         {
-          _rtt_release_edges(iface->ctx, edge, 1);
+          rtt_release_edges(iface->ctx, edge, 1);
           rterror(iface->ctx, "Unexpected error: %d faces updated when expecting 1", i);
           return -1;
         }
@@ -4226,13 +4253,13 @@ _rtt_RemEdge(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, int modFace )
         _rtt_release_faces(iface->ctx, faces, 2);
         if ( i == -1 )
         {
-          _rtt_release_edges(iface->ctx, edge, 1);
+          rtt_release_edges(iface->ctx, edge, 1);
           rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
           return -1;
         }
         if ( i != 1 )
         {
-          _rtt_release_edges(iface->ctx, edge, 1);
+          rtt_release_edges(iface->ctx, edge, 1);
           rterror(iface->ctx, "Unexpected error: %d faces inserted when expecting 1", i);
           return -1;
         }
@@ -4247,13 +4274,13 @@ _rtt_RemEdge(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, int modFace )
     {
       if ( -1 == _rtt_UpdateEdgeFaceRef(topo, edge->face_left, floodface) )
       {
-        _rtt_release_edges(iface->ctx, edge, 1);
+        rtt_release_edges(iface->ctx, edge, 1);
         rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
         return -1;
       }
       if ( -1 == _rtt_UpdateNodeFaceRef(topo, edge->face_left, floodface) )
       {
-        _rtt_release_edges(iface->ctx, edge, 1);
+        rtt_release_edges(iface->ctx, edge, 1);
         rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
         return -1;
       }
@@ -4263,13 +4290,13 @@ _rtt_RemEdge(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, int modFace )
     {
       if ( -1 == _rtt_UpdateEdgeFaceRef(topo, edge->face_right, floodface) )
       {
-        _rtt_release_edges(iface->ctx, edge, 1);
+        rtt_release_edges(iface->ctx, edge, 1);
         rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
         return -1;
       }
       if ( -1 == _rtt_UpdateNodeFaceRef(topo, edge->face_right, floodface) )
       {
-        _rtt_release_edges(iface->ctx, edge, 1);
+        rtt_release_edges(iface->ctx, edge, 1);
         rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
         return -1;
       }
@@ -4280,7 +4307,7 @@ _rtt_RemEdge(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, int modFace )
                                   edge->face_right, edge->face_left,
                                   floodface) )
     {
-      _rtt_release_edges(iface->ctx, edge, 1);
+      rtt_release_edges(iface->ctx, edge, 1);
       rterror(iface->ctx, "%s", rtt_be_lastErrorMessage(topo->be_iface));
       return -1;
     }
@@ -4289,7 +4316,7 @@ _rtt_RemEdge(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, int modFace )
   /* Delete the edge */
   i = rtt_be_deleteEdges(topo, edge, RTT_COL_EDGE_EDGE_ID);
   if ( i == -1 ) {
-    _rtt_release_edges(iface->ctx, edge, 1);
+    rtt_release_edges(iface->ctx, edge, 1);
     rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
     return -1;
   }
@@ -4314,7 +4341,7 @@ _rtt_RemEdge(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, int modFace )
     i = rtt_be_updateNodesById(topo, upd_node, nnode,
                                RTT_COL_NODE_CONTAINING_FACE);
     if ( i == -1 ) {
-      _rtt_release_edges(iface->ctx, edge, 1);
+      rtt_release_edges(iface->ctx, edge, 1);
       rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
       return -1;
     }
@@ -4331,13 +4358,13 @@ _rtt_RemEdge(RTT_TOPOLOGY* topo, RTT_ELEMID edge_id, int modFace )
       ids[nids++] = edge->face_left;
     i = rtt_be_deleteFacesById(topo, ids, nids);
     if ( i == -1 ) {
-      _rtt_release_edges(iface->ctx, edge, 1);
+      rtt_release_edges(iface->ctx, edge, 1);
       rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
       return -1;
     }
   }
 
-  _rtt_release_edges(iface->ctx, edge, 1);
+  rtt_release_edges(iface->ctx, edge, 1);
   return modFace ? floodface : newface.face_id;
 }
 
@@ -4397,7 +4424,7 @@ _rtt_HealEdges( RTT_TOPOLOGY* topo, RTT_ELEMID eid1, RTT_ELEMID eid2,
   {
     if ( edges[i].edge_id == eid1 ) {
       if ( e1 ) {
-        _rtt_release_edges(iface->ctx, edges, nedges);
+        rtt_release_edges(iface->ctx, edges, nedges);
         rterror(iface->ctx, "Corrupted topology: multiple edges have id %"
                 RTTFMT_ELEMID, eid1);
         return -1;
@@ -4406,7 +4433,7 @@ _rtt_HealEdges( RTT_TOPOLOGY* topo, RTT_ELEMID eid1, RTT_ELEMID eid2,
     }
     else if ( edges[i].edge_id == eid2 ) {
       if ( e2 ) {
-        _rtt_release_edges(iface->ctx, edges, nedges);
+        rtt_release_edges(iface->ctx, edges, nedges);
         rterror(iface->ctx, "Corrupted topology: multiple edges have id %"
                 RTTFMT_ELEMID, eid2);
         return -1;
@@ -4416,14 +4443,14 @@ _rtt_HealEdges( RTT_TOPOLOGY* topo, RTT_ELEMID eid1, RTT_ELEMID eid2,
   }
   if ( ! e1 )
   {
-    if ( edges ) _rtt_release_edges(iface->ctx, edges, nedges);
+    if ( edges ) rtt_release_edges(iface->ctx, edges, nedges);
     rterror(iface->ctx, "SQL/MM Spatial exception - non-existent edge %"
             RTTFMT_ELEMID, eid1);
     return -1;
   }
   if ( ! e2 )
   {
-    if ( edges ) _rtt_release_edges(iface->ctx, edges, nedges);
+    if ( edges ) rtt_release_edges(iface->ctx, edges, nedges);
     rterror(iface->ctx, "SQL/MM Spatial exception - non-existent edge %"
             RTTFMT_ELEMID, eid2);
     return -1;
@@ -4432,14 +4459,14 @@ _rtt_HealEdges( RTT_TOPOLOGY* topo, RTT_ELEMID eid1, RTT_ELEMID eid2,
   /* NOT IN THE SPECS: See if any of the two edges are closed. */
   if ( e1->start_node == e1->end_node )
   {
-    _rtt_release_edges(iface->ctx, edges, nedges);
+    rtt_release_edges(iface->ctx, edges, nedges);
     rterror(iface->ctx, "Edge %" RTTFMT_ELEMID " is closed, cannot heal to edge %"
             RTTFMT_ELEMID, eid1, eid2);
     return -1;
   }
   if ( e2->start_node == e2->end_node )
   {
-    _rtt_release_edges(iface->ctx, edges, nedges);
+    rtt_release_edges(iface->ctx, edges, nedges);
     rterror(iface->ctx, "Edge %" RTTFMT_ELEMID " is closed, cannot heal to edge %"
             RTTFMT_ELEMID, eid2, eid1);
     return -1;
@@ -4464,7 +4491,7 @@ _rtt_HealEdges( RTT_TOPOLOGY* topo, RTT_ELEMID eid1, RTT_ELEMID eid2,
     node_edges = rtt_be_getEdgeByNode( topo, &commonnode,
                                        &num_node_edges, RTT_COL_EDGE_EDGE_ID );
     if ( num_node_edges == -1 ) {
-      _rtt_release_edges(iface->ctx, edges, nedges);
+      rtt_release_edges(iface->ctx, edges, nedges);
       rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
       return -1;
     }
@@ -4515,7 +4542,7 @@ _rtt_HealEdges( RTT_TOPOLOGY* topo, RTT_ELEMID eid1, RTT_ELEMID eid2,
       node_edges = rtt_be_getEdgeByNode( topo, &commonnode,
                                          &num_node_edges, RTT_COL_EDGE_EDGE_ID );
       if ( num_node_edges == -1 ) {
-        _rtt_release_edges(iface->ctx, edges, nedges);
+        rtt_release_edges(iface->ctx, edges, nedges);
         rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
         return -1;
       }
@@ -4550,7 +4577,7 @@ _rtt_HealEdges( RTT_TOPOLOGY* topo, RTT_ELEMID eid1, RTT_ELEMID eid2,
 
   if ( commonnode == -1 )
   {
-    _rtt_release_edges(iface->ctx, edges, nedges);
+    rtt_release_edges(iface->ctx, edges, nedges);
     if ( ptr != buf )
     {
       rterror(iface->ctx, "SQL/MM Spatial exception - other edges connected (%s)",
@@ -4566,7 +4593,7 @@ _rtt_HealEdges( RTT_TOPOLOGY* topo, RTT_ELEMID eid1, RTT_ELEMID eid2,
   if ( ! rtt_be_checkTopoGeomRemNode(topo, commonnode,
                                      eid1, eid2 ) )
   {
-    _rtt_release_edges(iface->ctx, edges, nedges);
+    rtt_release_edges(iface->ctx, edges, nedges);
     rterror(iface->ctx, "%s", rtt_be_lastErrorMessage(topo->be_iface));
     return -1;
   }
@@ -4634,7 +4661,7 @@ _rtt_HealEdges( RTT_TOPOLOGY* topo, RTT_ELEMID eid1, RTT_ELEMID eid2,
       e1freenode = 0;
       e2freenode = 0;
       e2sign = 0;
-      _rtt_release_edges(iface->ctx, edges, nedges);
+      rtt_release_edges(iface->ctx, edges, nedges);
       rterror(iface->ctx, "Coding error: caseno=%d should never happen", caseno);
       break;
   }
@@ -4653,14 +4680,14 @@ _rtt_HealEdges( RTT_TOPOLOGY* topo, RTT_ELEMID eid1, RTT_ELEMID eid2,
     if ( i == -1 )
     {
       rtline_free(iface->ctx, newedge.geom);
-      _rtt_release_edges(iface->ctx, edges, nedges);
+      rtt_release_edges(iface->ctx, edges, nedges);
       rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
       return -1;
     }
     else if ( i != 1 )
     {
       rtline_free(iface->ctx, newedge.geom);
-      if ( edges ) _rtt_release_edges(iface->ctx, edges, nedges);
+      if ( edges ) rtt_release_edges(iface->ctx, edges, nedges);
       rterror(iface->ctx, "Unexpected error: %d edges updated when expecting 1", i);
       return -1;
     }
@@ -4674,12 +4701,12 @@ _rtt_HealEdges( RTT_TOPOLOGY* topo, RTT_ELEMID eid1, RTT_ELEMID eid2,
     i = rtt_be_insertEdges(topo, &newedge, 1);
     if ( i == -1 ) {
       rtline_free(iface->ctx, newedge.geom);
-      _rtt_release_edges(iface->ctx, edges, nedges);
+      rtt_release_edges(iface->ctx, edges, nedges);
       rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
       return -1;
     } else if ( i == 0 ) {
       rtline_free(iface->ctx, newedge.geom);
-      _rtt_release_edges(iface->ctx, edges, nedges);
+      rtt_release_edges(iface->ctx, edges, nedges);
       rterror(iface->ctx, "Insertion of split edge failed (no reason)");
       return -1;
     }
@@ -4708,7 +4735,7 @@ _rtt_HealEdges( RTT_TOPOLOGY* topo, RTT_ELEMID eid1, RTT_ELEMID eid2,
                                NULL, 0);
   if ( i == -1 )
   {
-    _rtt_release_edges(iface->ctx, edges, nedges);
+    rtt_release_edges(iface->ctx, edges, nedges);
     rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
     return -1;
   }
@@ -4721,7 +4748,7 @@ _rtt_HealEdges( RTT_TOPOLOGY* topo, RTT_ELEMID eid1, RTT_ELEMID eid2,
                                NULL, 0);
   if ( i == -1 )
   {
-    _rtt_release_edges(iface->ctx, edges, nedges);
+    rtt_release_edges(iface->ctx, edges, nedges);
     rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
     return -1;
   }
@@ -4736,7 +4763,7 @@ _rtt_HealEdges( RTT_TOPOLOGY* topo, RTT_ELEMID eid1, RTT_ELEMID eid2,
                                  NULL, 0);
     if ( i == -1 )
     {
-      _rtt_release_edges(iface->ctx, edges, nedges);
+      rtt_release_edges(iface->ctx, edges, nedges);
       rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
       return -1;
     }
@@ -4749,7 +4776,7 @@ _rtt_HealEdges( RTT_TOPOLOGY* topo, RTT_ELEMID eid1, RTT_ELEMID eid2,
                                  NULL, 0);
     if ( i == -1 )
     {
-      _rtt_release_edges(iface->ctx, edges, nedges);
+      rtt_release_edges(iface->ctx, edges, nedges);
       rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
       return -1;
     }
@@ -4759,7 +4786,7 @@ _rtt_HealEdges( RTT_TOPOLOGY* topo, RTT_ELEMID eid1, RTT_ELEMID eid2,
   i = rtt_be_deleteEdges(topo, e2, RTT_COL_EDGE_EDGE_ID);
   if ( i == -1 )
   {
-    _rtt_release_edges(iface->ctx, edges, nedges);
+    rtt_release_edges(iface->ctx, edges, nedges);
     rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
     return -1;
   }
@@ -4767,13 +4794,13 @@ _rtt_HealEdges( RTT_TOPOLOGY* topo, RTT_ELEMID eid1, RTT_ELEMID eid2,
     i = rtt_be_deleteEdges(topo, e1, RTT_COL_EDGE_EDGE_ID);
     if ( i == -1 )
     {
-      _rtt_release_edges(iface->ctx, edges, nedges);
+      rtt_release_edges(iface->ctx, edges, nedges);
       rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
       return -1;
     }
   }
 
-  _rtt_release_edges(iface->ctx, edges, nedges);
+  rtt_release_edges(iface->ctx, edges, nedges);
 
   /* delete the common node */
   i = rtt_be_deleteNodesById( topo, &commonnode, 1 );
@@ -4879,7 +4906,7 @@ rtt_GetEdgeByPoint(RTT_TOPOLOGY *topo, RTPOINT *pt, double tol)
 
     if ( ! e->geom )
     {
-      _rtt_release_edges(iface->ctx, elem, num);
+      rtt_release_edges(iface->ctx, elem, num);
       rtnotice(iface->ctx, "Corrupted topology: edge %" RTTFMT_ELEMID
                " has null geometry", e->edge_id);
       continue;
@@ -4894,14 +4921,14 @@ rtt_GetEdgeByPoint(RTT_TOPOLOGY *topo, RTPOINT *pt, double tol)
 
     if ( id )
     {
-      _rtt_release_edges(iface->ctx, elem, num);
+      rtt_release_edges(iface->ctx, elem, num);
       rterror(iface->ctx, "Two or more edges found");
       return -1;
     }
     else id = e->edge_id;
   }
 
-  if ( num ) _rtt_release_edges(iface->ctx, elem, num);
+  if ( num ) rtt_release_edges(iface->ctx, elem, num);
 
   return id;
 }
@@ -4931,7 +4958,7 @@ rtt_GetFaceByPoint(RTT_TOPOLOGY *topo, RTPOINT *pt, double tol)
   }
   id = 0; /* or it'll be -1 for not found */
 
-  RTDEBUG(1, "No face properly contains query point,"
+  RTDEBUG(iface->ctx, 1, "No face properly contains query point,"
              " looking for edges");
 
   /* Not in a face, may be in universe or on edge, let's check
@@ -4953,7 +4980,7 @@ rtt_GetFaceByPoint(RTT_TOPOLOGY *topo, RTPOINT *pt, double tol)
 
     if ( ! e->geom )
     {
-      _rtt_release_edges(iface->ctx, elem, num);
+      rtt_release_edges(iface->ctx, elem, num);
       rtnotice(iface->ctx, "Corrupted topology: edge %" RTTFMT_ELEMID
                " has null geometry", e->edge_id);
       continue;
@@ -4962,7 +4989,7 @@ rtt_GetFaceByPoint(RTT_TOPOLOGY *topo, RTPOINT *pt, double tol)
     /* don't consider dangling edges */
     if ( e->face_left == e->face_right )
     {
-      RTDEBUGF(1, "Edge %" RTTFMT_ELEMID
+      RTDEBUGF(iface->ctx, 1, "Edge %" RTTFMT_ELEMID
                   " is dangling, won't consider it", e->edge_id);
       continue;
     }
@@ -4970,7 +4997,7 @@ rtt_GetFaceByPoint(RTT_TOPOLOGY *topo, RTPOINT *pt, double tol)
     geom = rtline_as_rtgeom(iface->ctx, e->geom);
     dist = rtgeom_mindistance2d_tolerance(iface->ctx, geom, qp, tol);
 
-    RTDEBUGF(1, "Distance from edge %" RTTFMT_ELEMID
+    RTDEBUGF(iface->ctx, 1, "Distance from edge %" RTTFMT_ELEMID
                 " is %g (tol=%g)", e->edge_id, dist, tol);
 
     /* we won't consider edges too far */
@@ -4982,14 +5009,14 @@ rtt_GetFaceByPoint(RTT_TOPOLOGY *topo, RTPOINT *pt, double tol)
       eface = e->face_left;
     }
     else {
-      _rtt_release_edges(iface->ctx, elem, num);
+      rtt_release_edges(iface->ctx, elem, num);
       rterror(iface->ctx, "Two or more faces found");
       return -1;
     }
 
     if ( id && id != eface )
     {
-      _rtt_release_edges(iface->ctx, elem, num);
+      rtt_release_edges(iface->ctx, elem, num);
       rterror(iface->ctx, "Two or more faces found"
 #if 0 /* debugging */
               " (%" RTTFMT_ELEMID
@@ -5000,7 +5027,7 @@ rtt_GetFaceByPoint(RTT_TOPOLOGY *topo, RTPOINT *pt, double tol)
     }
     else id = eface;
   }
-  if ( num ) _rtt_release_edges(iface->ctx, elem, num);
+  if ( num ) rtt_release_edges(iface->ctx, elem, num);
 
   return id;
 }
@@ -5028,7 +5055,7 @@ _rtt_minTolerance(const RTCTX *ctx,  RTGEOM *g )
 }
 
 #define _RTT_MINTOLERANCE( topo, geom ) ( \
-  topo->precision ?  topo->precision : _rtt_minTolerance(topo->be_iface->ctx, geom) )
+  topo->precision >= 0 ?  topo->precision : _rtt_minTolerance(topo->be_iface->ctx, geom) )
 
 typedef struct scored_pointer_t {
   void *ptr;
@@ -5048,8 +5075,13 @@ compare_scored_pointer(const void *si1, const void *si2)
     return 0;
 }
 
-RTT_ELEMID
-rtt_AddPoint(RTT_TOPOLOGY* topo, RTPOINT* point, double tol)
+/*
+ * @param findFace if non-zero the code will determine which face
+ *        contains the given point (unless it is known to be NOT
+ *        isolated)
+ */
+static RTT_ELEMID
+_rtt_AddPoint(RTT_TOPOLOGY* topo, RTPOINT* point, double tol, int findFace)
 {
   int num, i;
   double mindist = FLT_MAX;
@@ -5061,10 +5093,10 @@ rtt_AddPoint(RTT_TOPOLOGY* topo, RTPOINT* point, double tol)
   RTT_ELEMID id = 0;
   scored_pointer *sorted;
 
-  /* Get tolerance, if 0 was given */
-  if ( ! tol ) tol = _RTT_MINTOLERANCE( topo, pt );
+  /* Get tolerance, if -1 was given */
+  if ( tol == -1 ) tol = _RTT_MINTOLERANCE( topo, pt );
 
-  RTDEBUGG(1, pt, "Adding point");
+  RTDEBUGG(iface->ctx, 1, pt, "Adding point");
 
   /*
   -- 1. Check if any existing node is closer than the given precision
@@ -5080,7 +5112,7 @@ rtt_AddPoint(RTT_TOPOLOGY* topo, RTPOINT* point, double tol)
   }
   if ( num )
   {
-    RTDEBUGF(1, "New point is within %.15g units of %d nodes", tol, num);
+    RTDEBUGF(iface->ctx, 1, "New point is within %.15g units of %d nodes", tol, num);
     /* Order by distance if there are more than a single return */
     if ( num > 1 )
     {{
@@ -5089,7 +5121,7 @@ rtt_AddPoint(RTT_TOPOLOGY* topo, RTPOINT* point, double tol)
       {
         sorted[i].ptr = nodes+i;
         sorted[i].score = rtgeom_mindistance2d(iface->ctx, rtpoint_as_rtgeom(iface->ctx, nodes[i].geom), pt);
-        RTDEBUGF(1, "Node %" RTTFMT_ELEMID " distance: %.15g",
+        RTDEBUGF(iface->ctx, 1, "Node %" RTTFMT_ELEMID " distance: %.15g",
           ((RTT_ISO_NODE*)(sorted[i].ptr))->node_id, sorted[i].score);
       }
       qsort(sorted, num, sizeof(scored_pointer), compare_scored_pointer);
@@ -5109,7 +5141,8 @@ rtt_AddPoint(RTT_TOPOLOGY* topo, RTPOINT* point, double tol)
       RTGEOM *g = rtpoint_as_rtgeom(iface->ctx, n->geom);
       double dist = rtgeom_mindistance2d(iface->ctx, g, pt);
       /* TODO: move this check in the previous sort scan ... */
-      if ( dist >= tol ) continue; /* must be closer than tolerated */
+      /* must be closer than tolerated, unless distance is zero */
+      if ( dist && dist >= tol ) continue;
       if ( ! id || dist < mindist )
       {
         id = n->node_id;
@@ -5140,7 +5173,7 @@ rtt_AddPoint(RTT_TOPOLOGY* topo, RTPOINT* point, double tol)
   }
   if ( num )
   {
-  RTDEBUGF(1, "New point is within %.15g units of %d edges", tol, num);
+  RTDEBUGF(iface->ctx, 1, "New point is within %.15g units of %d edges", tol, num);
 
   /* Order by distance if there are more than a single return */
   if ( num > 1 )
@@ -5151,7 +5184,7 @@ rtt_AddPoint(RTT_TOPOLOGY* topo, RTPOINT* point, double tol)
     {
       sorted[i].ptr = edges+i;
       sorted[i].score = rtgeom_mindistance2d(iface->ctx, rtline_as_rtgeom(iface->ctx, edges[i].geom), pt);
-      RTDEBUGF(1, "Edge %" RTTFMT_ELEMID " distance: %.15g",
+      RTDEBUGF(iface->ctx, 1, "Edge %" RTTFMT_ELEMID " distance: %.15g",
         ((RTT_ISO_EDGE*)(sorted[i].ptr))->edge_id, sorted[i].score);
     }
     qsort(sorted, num, sizeof(scored_pointer), compare_scored_pointer);
@@ -5183,7 +5216,7 @@ rtt_AddPoint(RTT_TOPOLOGY* topo, RTPOINT* point, double tol)
     GEOSGeometry *prjg, *gg;
     RTT_ELEMID edge_id = e->edge_id;
 
-    RTDEBUGF(1, "Splitting edge %" RTTFMT_ELEMID, edge_id);
+    RTDEBUGF(iface->ctx, 1, "Splitting edge %" RTTFMT_ELEMID, edge_id);
 
     /* project point to line, split edge by point */
     prj = rtgeom_closest_point(iface->ctx, g, pt);
@@ -5211,14 +5244,14 @@ rtt_AddPoint(RTT_TOPOLOGY* topo, RTPOINT* point, double tol)
     prjg = RTGEOM2GEOS(iface->ctx, prj, 0);
     if ( ! prjg ) {
       rtgeom_free(iface->ctx, prj);
-      _rtt_release_edges(iface->ctx, edges, num);
+      rtt_release_edges(iface->ctx, edges, num);
       rterror(iface->ctx, "Could not convert edge geometry to GEOS: %s", rtgeom_get_last_geos_error(iface->ctx));
       return -1;
     }
     gg = RTGEOM2GEOS(iface->ctx, g, 0);
     if ( ! gg ) {
       rtgeom_free(iface->ctx, prj);
-      _rtt_release_edges(iface->ctx, edges, num);
+      rtt_release_edges(iface->ctx, edges, num);
       GEOSGeom_destroy_r(iface->ctx->gctx, prjg);
       rterror(iface->ctx, "Could not convert edge geometry to GEOS: %s", rtgeom_get_last_geos_error(iface->ctx));
       return -1;
@@ -5229,7 +5262,7 @@ rtt_AddPoint(RTT_TOPOLOGY* topo, RTPOINT* point, double tol)
     if ( contains == 2 )
     {
       rtgeom_free(iface->ctx, prj);
-      _rtt_release_edges(iface->ctx, edges, num);
+      rtt_release_edges(iface->ctx, edges, num);
       rterror(iface->ctx, "GEOS exception on Contains: %s", rtgeom_get_last_geos_error(iface->ctx));
       return -1;
     }
@@ -5240,7 +5273,7 @@ rtt_AddPoint(RTT_TOPOLOGY* topo, RTPOINT* point, double tol)
       RTLINE *snapline;
       RTPOINT4D p1, p2;
 
-      RTDEBUGF(1, "Edge %" RTTFMT_ELEMID
+      RTDEBUGF(iface->ctx, 1, "Edge %" RTTFMT_ELEMID
                   " does not contain projected point to it",
                   edge_id);
 
@@ -5248,7 +5281,7 @@ rtt_AddPoint(RTT_TOPOLOGY* topo, RTPOINT* point, double tol)
        * an edge that contains the projected point, if possible */
       if ( i+1 < num )
       {
-        RTDEBUG(1, "But there's another to check");
+        RTDEBUG(iface->ctx, 1, "But there's another to check");
         rtgeom_free(iface->ctx, prj);
         continue;
       }
@@ -5263,7 +5296,7 @@ rtt_AddPoint(RTT_TOPOLOGY* topo, RTPOINT* point, double tol)
       snapedge = _rtt_toposnap(iface->ctx, g, prj, snaptol);
       snapline = rtgeom_as_rtline(iface->ctx, snapedge);
 
-      RTDEBUGF(1, "Edge snapped with tolerance %g", snaptol);
+      RTDEBUGF(iface->ctx, 1, "Edge snapped with tolerance %g", snaptol);
 
       /* TODO: check if snapping did anything ? */
 #if RTGEOM_DEBUG_LEVEL > 0
@@ -5271,7 +5304,7 @@ rtt_AddPoint(RTT_TOPOLOGY* topo, RTPOINT* point, double tol)
       size_t sz;
       char *wkt1 = rtgeom_to_wkt(iface->ctx, g, RTWKT_EXTENDED, 15, &sz);
       char *wkt2 = rtgeom_to_wkt(iface->ctx, snapedge, RTWKT_EXTENDED, 15, &sz);
-      RTDEBUGF(1, "Edge %s snapped became %s", wkt1, wkt2);
+      RTDEBUGF(iface->ctx, 1, "Edge %s snapped became %s", wkt1, wkt2);
       rtfree(iface->ctx, wkt1);
       rtfree(iface->ctx, wkt2);
       }
@@ -5284,17 +5317,17 @@ rtt_AddPoint(RTT_TOPOLOGY* topo, RTPOINT* point, double tol)
       */
       rt_getPoint4d_p(iface->ctx, e->geom->points, 0, &p1);
       rt_getPoint4d_p(iface->ctx, snapline->points, 0, &p2);
-      RTDEBUGF(1, "Edge first point is %g %g, "
+      RTDEBUGF(iface->ctx, 1, "Edge first point is %g %g, "
                   "snapline first point is %g %g",
                   p1.x, p1.y, p2.x, p2.y);
       if ( p1.x != p2.x || p1.y != p2.y )
       {
-        RTDEBUG(1, "Snapping moved first point, re-adding it");
+        RTDEBUG(iface->ctx, 1, "Snapping moved first point, re-adding it");
         if ( RT_SUCCESS != ptarray_insert_point(iface->ctx, snapline->points, &p1, 0) )
         {
           rtgeom_free(iface->ctx, prj);
           rtgeom_free(iface->ctx, snapedge);
-          _rtt_release_edges(iface->ctx, edges, num);
+          rtt_release_edges(iface->ctx, edges, num);
           rterror(iface->ctx, "GEOS exception on Contains: %s", rtgeom_get_last_geos_error(iface->ctx));
           return -1;
         }
@@ -5302,14 +5335,14 @@ rtt_AddPoint(RTT_TOPOLOGY* topo, RTPOINT* point, double tol)
         {
         size_t sz;
         char *wkt1 = rtgeom_to_wkt(iface->ctx, g, RTWKT_EXTENDED, 15, &sz);
-        RTDEBUGF(1, "Tweaked snapline became %s", wkt1);
+        RTDEBUGF(iface->ctx, 1, "Tweaked snapline became %s", wkt1);
         rtfree(iface->ctx, wkt1);
         }
 #endif
       }
 #if RTGEOM_DEBUG_LEVEL > 0
       else {
-        RTDEBUG(1, "Snapping did not move first point");
+        RTDEBUG(iface->ctx, 1, "Snapping did not move first point");
       }
 #endif
 
@@ -5318,7 +5351,7 @@ rtt_AddPoint(RTT_TOPOLOGY* topo, RTPOINT* point, double tol)
         /* TODO: should have invoked rterror already, leaking memory */
         rtgeom_free(iface->ctx, prj);
         rtgeom_free(iface->ctx, snapedge);
-        _rtt_release_edges(iface->ctx, edges, num);
+        rtt_release_edges(iface->ctx, edges, num);
         rterror(iface->ctx, "rtt_ChangeEdgeGeom failed");
         return -1;
       }
@@ -5330,7 +5363,7 @@ rtt_AddPoint(RTT_TOPOLOGY* topo, RTPOINT* point, double tol)
       size_t sz;
       char *wkt1 = rtgeom_to_wkt(iface->ctx, g, RTWKT_EXTENDED, 15, &sz);
       char *wkt2 = rtgeom_to_wkt(iface->ctx, prj, RTWKT_EXTENDED, 15, &sz);
-      RTDEBUGF(1, "Edge %s contains projected point %s", wkt1, wkt2);
+      RTDEBUGF(iface->ctx, 1, "Edge %s contains projected point %s", wkt1, wkt2);
       rtfree(iface->ctx, wkt1);
       rtfree(iface->ctx, wkt2);
     }}
@@ -5342,7 +5375,7 @@ rtt_AddPoint(RTT_TOPOLOGY* topo, RTPOINT* point, double tol)
     {
       /* TODO: should have invoked rterror already, leaking memory */
       rtgeom_free(iface->ctx, prj);
-      _rtt_release_edges(iface->ctx, edges, num);
+      rtt_release_edges(iface->ctx, edges, num);
       rterror(iface->ctx, "rtt_ModEdgeSplit failed");
       return -1;
     }
@@ -5364,13 +5397,13 @@ rtt_AddPoint(RTT_TOPOLOGY* topo, RTPOINT* point, double tol)
 
     break; /* we only want to snap a single edge */
   }
-  _rtt_release_edges(iface->ctx, edges, num);
+  rtt_release_edges(iface->ctx, edges, num);
   }
   else
   {
     /* The point is isolated, add it as such */
     /* TODO: pass 1 as last argument (skipChecks) ? */
-    id = rtt_AddIsoNode(topo, -1, point, 0);
+    id = _rtt_AddIsoNode(topo, -1, point, 0, findFace);
     if ( -1 == id )
     {
       /* should have invoked rterror already, leaking memory */
@@ -5382,6 +5415,12 @@ rtt_AddPoint(RTT_TOPOLOGY* topo, RTPOINT* point, double tol)
   return id;
 }
 
+RTT_ELEMID
+rtt_AddPoint(RTT_TOPOLOGY* topo, RTPOINT* point, double tol)
+{
+  return _rtt_AddPoint( topo, point, tol, 1 );
+}
+
 /* Return identifier of an equal edge, 0 if none or -1 on error
  * (and rterror gets called on error)
  */
@@ -5409,7 +5448,7 @@ _rtt_GetEqualEdge( RTT_TOPOLOGY *topo, RTLINE *edge )
     edgeg = RTGEOM2GEOS(iface->ctx,  rtline_as_rtgeom(iface->ctx, edge), 0 );
     if ( ! edgeg )
     {
-      _rtt_release_edges(iface->ctx, edges, num);
+      rtt_release_edges(iface->ctx, edges, num);
       rterror(iface->ctx, "Could not convert edge geometry to GEOS: %s", rtgeom_get_last_geos_error(iface->ctx));
       return -1;
     }
@@ -5423,7 +5462,7 @@ _rtt_GetEqualEdge( RTT_TOPOLOGY *topo, RTLINE *edge )
       if ( ! gg )
       {
         GEOSGeom_destroy_r(iface->ctx->gctx, edgeg);
-        _rtt_release_edges(iface->ctx, edges, num);
+        rtt_release_edges(iface->ctx, edges, num);
         rterror(iface->ctx, "Could not convert edge geometry to GEOS: %s", rtgeom_get_last_geos_error(iface->ctx));
         return -1;
       }
@@ -5432,7 +5471,7 @@ _rtt_GetEqualEdge( RTT_TOPOLOGY *topo, RTLINE *edge )
       if ( equals == 2 )
       {
         GEOSGeom_destroy_r(iface->ctx->gctx, edgeg);
-        _rtt_release_edges(iface->ctx, edges, num);
+        rtt_release_edges(iface->ctx, edges, num);
         rterror(iface->ctx, "GEOSEquals exception: %s", rtgeom_get_last_geos_error(iface->ctx));
         return -1;
       }
@@ -5440,12 +5479,12 @@ _rtt_GetEqualEdge( RTT_TOPOLOGY *topo, RTLINE *edge )
       {
         id = e->edge_id;
         GEOSGeom_destroy_r(iface->ctx->gctx, edgeg);
-        _rtt_release_edges(iface->ctx, edges, num);
+        rtt_release_edges(iface->ctx, edges, num);
         return id;
       }
     }
     GEOSGeom_destroy_r(iface->ctx->gctx, edgeg);
-    _rtt_release_edges(iface->ctx, edges, num);
+    rtt_release_edges(iface->ctx, edges, num);
   }
 
   return 0;
@@ -5454,9 +5493,16 @@ _rtt_GetEqualEdge( RTT_TOPOLOGY *topo, RTLINE *edge )
 /*
  * Add a pre-noded pre-split line edge. Used by rtt_AddLine
  * Return edge id, 0 if none added (empty edge), -1 on error
+ *
+ * @param handleFaceSplit if non-zero the code will check
+ *        if the newly added edge would split a face and if so
+ *        would create new faces accordingly. Otherwise it will
+ *        set left_face and right_face to null (-1)
+ *
  */
 static RTT_ELEMID
-_rtt_AddLineEdge( RTT_TOPOLOGY* topo, RTLINE* edge, double tol )
+_rtt_AddLineEdge( RTT_TOPOLOGY* topo, RTLINE* edge, double tol,
+                  int handleFaceSplit )
 {
   const RTT_BE_IFACE *iface = topo->be_iface;
   RTCOLLECTION *col;
@@ -5468,8 +5514,8 @@ _rtt_AddLineEdge( RTT_TOPOLOGY* topo, RTLINE* edge, double tol )
   RTPOINT4D p4d;
   int nn, i;
 
-  RTDEBUGG(1, rtline_as_rtgeom(iface->ctx, edge), "_lwtAddLineEdge");
-  RTDEBUGF(1, "_lwtAddLineEdge with tolerance %g", tol);
+  RTDEBUGG(iface->ctx, 1, rtline_as_rtgeom(iface->ctx, edge), "_lwtAddLineEdge");
+  RTDEBUGF(iface->ctx, 1, "_lwtAddLineEdge with tolerance %g", tol);
 
   start_point = rtline_get_rtpoint(iface->ctx, edge, 0);
   if ( ! start_point )
@@ -5477,7 +5523,7 @@ _rtt_AddLineEdge( RTT_TOPOLOGY* topo, RTLINE* edge, double tol )
     rtnotice(iface->ctx, "Empty component of noded line");
     return 0; /* must be empty */
   }
-  nid[0] = rtt_AddPoint( topo, start_point, tol );
+  nid[0] = _rtt_AddPoint( topo, start_point, tol, handleFaceSplit );
   rtpoint_free(iface->ctx, start_point); /* too late if rtt_AddPoint calls rterror */
   if ( nid[0] == -1 ) return -1; /* rterror should have been called */
 
@@ -5488,7 +5534,7 @@ _rtt_AddLineEdge( RTT_TOPOLOGY* topo, RTLINE* edge, double tol )
             "after successfully getting first point !?");
     return -1;
   }
-  nid[1] = rtt_AddPoint( topo, end_point, tol );
+  nid[1] = _rtt_AddPoint( topo, end_point, tol, handleFaceSplit );
   rtpoint_free(iface->ctx, end_point); /* too late if rtt_AddPoint calls rterror */
   if ( nid[1] == -1 ) return -1; /* rterror should have been called */
 
@@ -5543,7 +5589,7 @@ _rtt_AddLineEdge( RTT_TOPOLOGY* topo, RTLINE* edge, double tol )
     {
       rtcollection_free(iface->ctx, col);
       rtgeom_free(iface->ctx, tmp);
-      RTDEBUG(1, "Made-valid snapped edge collapsed");
+      RTDEBUG(iface->ctx, 1, "Made-valid snapped edge collapsed");
       return 0;
     }
 
@@ -5564,7 +5610,7 @@ _rtt_AddLineEdge( RTT_TOPOLOGY* topo, RTLINE* edge, double tol )
     edge = rtgeom_as_rtline(iface->ctx, tmp);
     if ( ! edge )
     {
-      RTDEBUGF(1, "Made-valid snapped edge collapsed to %s",
+      RTDEBUGF(iface->ctx, 1, "Made-valid snapped edge collapsed to %s",
                   rttype_name(iface->ctx, rtgeom_get_type(iface->ctx, tmp)));
       rtgeom_free(iface->ctx, tmp);
       return 0;
@@ -5573,7 +5619,7 @@ _rtt_AddLineEdge( RTT_TOPOLOGY* topo, RTLINE* edge, double tol )
 
   /* check if the so-snapped edge _now_ exists */
   id = _rtt_GetEqualEdge ( topo, edge );
-  RTDEBUGF(1, "_rtt_GetEqualEdge returned %" RTTFMT_ELEMID, id);
+  RTDEBUGF(iface->ctx, 1, "_rtt_GetEqualEdge returned %" RTTFMT_ELEMID, id);
   if ( id == -1 )
   {
     rtgeom_free(iface->ctx, tmp); /* probably too late, due to internal rterror */
@@ -5592,14 +5638,14 @@ _rtt_AddLineEdge( RTT_TOPOLOGY* topo, RTLINE* edge, double tol )
   if ( tol )
   {{
     tmp2 = rtline_remove_repeated_points(iface->ctx, edge, tol);
-    RTDEBUGG(1, tmp2, "Repeated-point removed");
+    RTDEBUGG(iface->ctx, 1, tmp2, "Repeated-point removed");
     edge = rtgeom_as_rtline(iface->ctx, tmp2);
     rtgeom_free(iface->ctx, tmp);
     tmp = tmp2;
 
     /* check if the so-decimated edge _now_ exists */
     id = _rtt_GetEqualEdge ( topo, edge );
-    RTDEBUGF(1, "_rtt_GetEqualEdge returned %" RTTFMT_ELEMID, id);
+    RTDEBUGF(iface->ctx, 1, "_rtt_GetEqualEdge returned %" RTTFMT_ELEMID, id);
     if ( id == -1 )
     {
       rtgeom_free(iface->ctx, tmp); /* probably too late, due to internal lwerror */
@@ -5613,8 +5659,8 @@ _rtt_AddLineEdge( RTT_TOPOLOGY* topo, RTLINE* edge, double tol )
   }}
 
   /* TODO: skip checks ? */
-  id = rtt_AddEdgeModFace( topo, nid[0], nid[1], edge, 0 );
-  RTDEBUGF(1, "rtt_AddEdgeModFace returned %" RTTFMT_ELEMID, id);
+  id = _rtt_AddEdge( topo, nid[0], nid[1], edge, 0, handleFaceSplit ?  1 : -1 );
+  RTDEBUGF(iface->ctx, 1, "rtt_AddEdgeModFace returned %" RTTFMT_ELEMID, id);
   if ( id == -1 )
   {
     rtgeom_free(iface->ctx, tmp); /* probably too late, due to internal rterror */
@@ -5649,8 +5695,15 @@ _rtt_split_by_nodes(const RTCTX *ctx, const RTGEOM *g, const RTGEOM *nodes)
   return bg;
 }
 
-RTT_ELEMID*
-rtt_AddLine(RTT_TOPOLOGY* topo, RTLINE* line, double tol, int* nedges)
+/*
+ * @param handleFaceSplit if non-zero the code will check
+ *        if the newly added edge would split a face and if so
+ *        would create new faces accordingly. Otherwise it will
+ *        set left_face and right_face to null (-1)
+ */
+static RTT_ELEMID*
+_rtt_AddLine(RTT_TOPOLOGY* topo, RTLINE* line, double tol, int* nedges,
+             int handleFaceSplit)
 {
   const RTT_BE_IFACE *iface = topo->be_iface;
   RTGEOM *geomsbuf[1];
@@ -5667,30 +5720,30 @@ rtt_AddLine(RTT_TOPOLOGY* topo, RTLINE* line, double tol, int* nedges)
 
   *nedges = -1; /* error condition, by default */
 
-  /* Get tolerance, if 0 was given */
-  if ( ! tol ) tol = _RTT_MINTOLERANCE( topo, (RTGEOM*)line );
-  RTDEBUGF(1, "Working tolerance:%.15g", tol);
-  RTDEBUGF(1, "Input line has srid=%d", line->srid);
+  /* Get tolerance, if -1 was given */
+  if ( tol == -1 ) tol = _RTT_MINTOLERANCE( topo, (RTGEOM*)line );
+  RTDEBUGF(iface->ctx, 1, "Working tolerance:%.15g", tol);
+  RTDEBUGF(iface->ctx, 1, "Input line has srid=%d", line->srid);
 
   /* Remove consecutive vertices below given tolerance upfront */
   if ( tol )
   {{
     RTLINE *clean = rtgeom_as_rtline(iface->ctx, rtline_remove_repeated_points(iface->ctx, line, tol));
     tmp = rtline_as_rtgeom(iface->ctx, clean); /* NOTE: might collapse to non-simple */
-    RTDEBUGG(1, tmp, "Repeated-point removed");
+    RTDEBUGG(iface->ctx, 1, tmp, "Repeated-point removed");
   }} else tmp=(RTGEOM*)line;
 
   /* 1. Self-node */
   noded = rtgeom_node(iface->ctx, (RTGEOM*)tmp);
   if ( tmp != (RTGEOM*)line ) rtgeom_free(iface->ctx, tmp);
   if ( ! noded ) return NULL; /* should have called rterror already */
-  RTDEBUGG(1, noded, "Noded");
+  RTDEBUGG(iface->ctx, 1, noded, "Noded");
 
   qbox = *rtgeom_get_bbox(iface->ctx,  rtline_as_rtgeom(iface->ctx, line) );
-  RTDEBUGF(1, "Line BOX is %.15g %.15g, %.15g %.15g", qbox.xmin, qbox.ymin,
+  RTDEBUGF(iface->ctx, 1, "Line BOX is %.15g %.15g, %.15g %.15g", qbox.xmin, qbox.ymin,
                                           qbox.xmax, qbox.ymax);
   gbox_expand(iface->ctx, &qbox, tol);
-  RTDEBUGF(1, "BOX expanded by %g is %.15g %.15g, %.15g %.15g",
+  RTDEBUGF(iface->ctx, 1, "BOX expanded by %g is %.15g %.15g, %.15g %.15g",
               tol, qbox.xmin, qbox.ymin, qbox.xmax, qbox.ymax);
 
   /* 2. Node to edges falling within tol distance */
@@ -5701,7 +5754,7 @@ rtt_AddLine(RTT_TOPOLOGY* topo, RTLINE* line, double tol, int* nedges)
     rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
     return NULL;
   }
-  RTDEBUGF(1, "Line bbox intersects %d edges bboxes", num);
+  RTDEBUGF(iface->ctx, 1, "Line bbox intersects %d edges bboxes", num);
   if ( num )
   {{
     /* collect those whose distance from us is < tol */
@@ -5712,7 +5765,8 @@ rtt_AddLine(RTT_TOPOLOGY* topo, RTLINE* line, double tol, int* nedges)
       RTT_ISO_EDGE *e = &(edges[i]);
       RTGEOM *g = rtline_as_rtgeom(iface->ctx, e->geom);
       double dist = rtgeom_mindistance2d(iface->ctx, g, noded);
-      if ( dist >= tol ) continue; /* must be closer than tolerated */
+      /* must be closer than tolerated, unless distance is zero */
+      if ( dist && dist >= tol ) continue;
       nearby[nn++] = g;
     }
     if ( nn )
@@ -5722,47 +5776,47 @@ rtt_AddLine(RTT_TOPOLOGY* topo, RTLINE* line, double tol, int* nedges)
       RTGEOM *snapped;
       RTGEOM *set1, *set2;
 
-      RTDEBUGF(1, "Line intersects %d edges", nn);
+      RTDEBUGF(iface->ctx, 1, "Line intersects %d edges", nn);
 
       col = rtcollection_construct(iface->ctx, RTCOLLECTIONTYPE, topo->srid,
                                    NULL, nn, nearby);
       iedges = rtcollection_as_rtgeom(iface->ctx, col);
-      RTDEBUGG(1, iedges, "Collected edges");
-      RTDEBUGF(1, "Snapping noded, with srid=%d "
+      RTDEBUGG(iface->ctx, 1, iedges, "Collected edges");
+      RTDEBUGF(iface->ctx, 1, "Snapping noded, with srid=%d "
                   "to interesecting edges, with srid=%d",
                   noded->srid, iedges->srid);
       snapped = _rtt_toposnap(iface->ctx, noded, iedges, tol);
       rtgeom_free(iface->ctx, noded);
-      RTDEBUGG(1, snapped, "Snapped");
-      RTDEBUGF(1, "Diffing snapped, with srid=%d "
+      RTDEBUGG(iface->ctx, 1, snapped, "Snapped");
+      RTDEBUGF(iface->ctx, 1, "Diffing snapped, with srid=%d "
                   "and interesecting edges, with srid=%d",
                   snapped->srid, iedges->srid);
       noded = rtgeom_difference(iface->ctx, snapped, iedges);
-      RTDEBUGG(1, noded, "Differenced");
-      RTDEBUGF(1, "Intersecting snapped, with srid=%d "
+      RTDEBUGG(iface->ctx, 1, noded, "Differenced");
+      RTDEBUGF(iface->ctx, 1, "Intersecting snapped, with srid=%d "
                   "and interesecting edges, with srid=%d",
                   snapped->srid, iedges->srid);
       set1 = rtgeom_intersection(iface->ctx, snapped, iedges);
-      RTDEBUGG(1, set1, "Intersected");
+      RTDEBUGG(iface->ctx, 1, set1, "Intersected");
       rtgeom_free(iface->ctx, snapped);
-      RTDEBUGF(1, "Linemerging set1, with srid=%d", set1->srid);
+      RTDEBUGF(iface->ctx, 1, "Linemerging set1, with srid=%d", set1->srid);
       set2 = rtgeom_linemerge(iface->ctx, set1);
-      RTDEBUGG(1, set2, "Linemerged");
-      RTDEBUGG(1, noded, "Noded");
+      RTDEBUGG(iface->ctx, 1, set2, "Linemerged");
+      RTDEBUGG(iface->ctx, 1, noded, "Noded");
       rtgeom_free(iface->ctx, set1);
-      RTDEBUGF(1, "Unioning noded, with srid=%d "
+      RTDEBUGF(iface->ctx, 1, "Unioning noded, with srid=%d "
                   "and set2, with srid=%d", noded->srid, set2->srid);
       set1 = rtgeom_union(iface->ctx, noded, set2);
       rtgeom_free(iface->ctx, set2);
       rtgeom_free(iface->ctx, noded);
       noded = set1;
-      RTDEBUGG(1, set1, "Unioned");
+      RTDEBUGG(iface->ctx, 1, set1, "Unioned");
 
       /* will not release the geoms array */
       rtcollection_release(iface->ctx, col);
     }}
     rtfree(iface->ctx, nearby);
-    _rtt_release_edges(iface->ctx, edges, num);
+    rtt_release_edges(iface->ctx, edges, num);
   }}
 
   /* 2.1. Node with existing nodes within tol
@@ -5774,7 +5828,7 @@ rtt_AddLine(RTT_TOPOLOGY* topo, RTLINE* line, double tol, int* nedges)
     rterror(iface->ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
     return NULL;
   }
-  RTDEBUGF(1, "Line bbox intersects %d nodes bboxes", num);
+  RTDEBUGF(iface->ctx, 1, "Line bbox intersects %d nodes bboxes", num);
   if ( num )
   {{
     /* collect those whose distance from us is < tol */
@@ -5785,7 +5839,8 @@ rtt_AddLine(RTT_TOPOLOGY* topo, RTLINE* line, double tol, int* nedges)
       RTT_ISO_NODE *n = &(nodes[i]);
       RTGEOM *g = rtpoint_as_rtgeom(iface->ctx, n->geom);
       double dist = rtgeom_mindistance2d(iface->ctx, g, noded);
-      if ( dist >= tol ) continue; /* must be closer than tolerated */
+      /* must be closer than tolerated, unless distance is zero */
+      if ( dist && dist >= tol ) continue;
       nearby[nn++] = g;
     }
     if ( nn )
@@ -5794,26 +5849,26 @@ rtt_AddLine(RTT_TOPOLOGY* topo, RTLINE* line, double tol, int* nedges)
       RTGEOM *inodes; /* just an alias for col */
       RTGEOM *tmp;
 
-      RTDEBUGF(1, "Line intersects %d nodes", nn);
+      RTDEBUGF(iface->ctx, 1, "Line intersects %d nodes", nn);
 
       col = rtcollection_construct(iface->ctx, RTMULTIPOINTTYPE, topo->srid,
                                    NULL, nn, nearby);
       inodes = rtcollection_as_rtgeom(iface->ctx, col);
 
-      RTDEBUGG(1, inodes, "Collected nodes");
+      RTDEBUGG(iface->ctx, 1, inodes, "Collected nodes");
 
       /* TODO: consider snapping once against all elements
        *      (rather than once with edges and once with nodes) */
       tmp = _rtt_toposnap(iface->ctx, noded, inodes, tol);
       rtgeom_free(iface->ctx, noded);
       noded = tmp;
-      RTDEBUGG(1, noded, "Node-snapped");
+      RTDEBUGG(iface->ctx, 1, noded, "Node-snapped");
 
       tmp = _rtt_split_by_nodes(iface->ctx, noded, inodes);
           /* rtgeom_split(iface->ctx, noded, inodes); */
       rtgeom_free(iface->ctx, noded);
       noded = tmp;
-      RTDEBUGG(1, noded, "Node-split");
+      RTDEBUGG(iface->ctx, 1, noded, "Node-split");
 
       /* will not release the geoms array */
       rtcollection_release(iface->ctx, col);
@@ -5826,32 +5881,32 @@ rtt_AddLine(RTT_TOPOLOGY* topo, RTLINE* line, double tol, int* nedges)
       tmp = rtgeom_unaryunion(iface->ctx, noded);
       rtgeom_free(iface->ctx, noded);
       noded = tmp;
-      RTDEBUGG(1, noded, "Unary-unioned");
+      RTDEBUGG(iface->ctx, 1, noded, "Unary-unioned");
 
     }}
     rtfree(iface->ctx, nearby);
     _rtt_release_nodes(iface->ctx, nodes, num);
   }}
 
-  RTDEBUGG(1, noded, "Finally-noded");
+  RTDEBUGG(iface->ctx, 1, noded, "Finally-noded");
 
   /* 3. For each (now-noded) segment, insert an edge */
   col = rtgeom_as_rtcollection(iface->ctx, noded);
   if ( col )
   {
-    RTDEBUG(1, "Noded line was a collection");
+    RTDEBUG(iface->ctx, 1, "Noded line was a collection");
     geoms = col->geoms;
     ngeoms = col->ngeoms;
   }
   else
   {
-    RTDEBUG(1, "Noded line was a single geom");
+    RTDEBUG(iface->ctx, 1, "Noded line was a single geom");
     geomsbuf[0] = noded;
     geoms = geomsbuf;
     ngeoms = 1;
   }
 
-  RTDEBUGF(1, "Line was split into %d edges", ngeoms);
+  RTDEBUGF(iface->ctx, 1, "Line was split into %d edges", ngeoms);
 
   /* TODO: refactor to first add all nodes (re-snapping edges if
    * needed) and then check all edges for existing already
@@ -5869,13 +5924,13 @@ rtt_AddLine(RTT_TOPOLOGY* topo, RTLINE* line, double tol, int* nedges)
     {
       size_t sz;
       char *wkt1 = rtgeom_to_wkt(iface->ctx, g, RTWKT_EXTENDED, 15, &sz);
-      RTDEBUGF(1, "Component %d of split line is: %s", i, wkt1);
+      RTDEBUGF(iface->ctx, 1, "Component %d of split line is: %s", i, wkt1);
       rtfree(iface->ctx, wkt1);
     }
 #endif
 
-    id = _rtt_AddLineEdge( topo, rtgeom_as_rtline(iface->ctx, g), tol );
-    RTDEBUGF(1, "_rtt_AddLineEdge returned %" RTTFMT_ELEMID, id);
+    id = _rtt_AddLineEdge( topo, rtgeom_as_rtline(iface->ctx, g), tol, handleFaceSplit );
+    RTDEBUGF(iface->ctx, 1, "_rtt_AddLineEdge returned %" RTTFMT_ELEMID, id);
     if ( id < 0 )
     {
       rtgeom_free(iface->ctx, noded);
@@ -5884,16 +5939,16 @@ rtt_AddLine(RTT_TOPOLOGY* topo, RTLINE* line, double tol, int* nedges)
     }
     if ( ! id )
     {
-      RTDEBUGF(1, "Component %d of split line collapsed", i);
+      RTDEBUGF(iface->ctx, 1, "Component %d of split line collapsed", i);
       continue;
     }
 
-    RTDEBUGF(1, "Component %d of split line is edge %" RTTFMT_ELEMID,
+    RTDEBUGF(iface->ctx, 1, "Component %d of split line is edge %" RTTFMT_ELEMID,
                   i, id);
     ids[num++] = id; /* TODO: skip duplicates */
   }
 
-  RTDEBUGG(1, noded, "Noded before free");
+  RTDEBUGG(iface->ctx, 1, noded, "Noded before free");
   rtgeom_free(iface->ctx, noded);
 
   /* TODO: XXX remove duplicated ids if not done before */
@@ -5903,6 +5958,58 @@ rtt_AddLine(RTT_TOPOLOGY* topo, RTLINE* line, double tol, int* nedges)
 }
 
 RTT_ELEMID*
+rtt_AddLine(RTT_TOPOLOGY* topo, RTLINE* line, double tol, int* nedges)
+{
+  return _rtt_AddLine(topo, line, tol, nedges, 1);
+}
+
+/*
+ * @return -1 on error (and report error),
+ *          1 if faces beside the universal one exist
+ *          0 otherwise
+ */
+static int
+_rtt_CheckFacesExist(RTT_TOPOLOGY *topo)
+{
+  RTT_ISO_FACE *faces;
+  int fields = RTT_COL_FACE_FACE_ID;
+  int nelems = 1;
+  RTGBOX qbox;
+  const RTCTX *ctx = topo->be_iface->ctx;
+
+  qbox.xmin = qbox.ymin = -DBL_MAX;
+  qbox.xmax = qbox.ymax = DBL_MAX;
+  faces = rtt_be_getFaceWithinBox2D( topo, &qbox, &nelems, fields, 1);
+  if ( nelems == -1 ) {
+    rterror(ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
+    return -1;
+  }
+  if ( faces ) _rtt_release_faces(ctx, faces, nelems);
+  return nelems;
+}
+
+RTT_ELEMID*
+rtt_AddLineNoFace(RTT_TOPOLOGY* topo, RTLINE* line, double tol, int* nedges)
+{
+  /*
+   Check if Topology already contains some Face
+   (ignoring the Universal Face)
+  */
+  const RTT_BE_IFACE *iface = topo->be_iface;
+  int numfaces = _rtt_CheckFacesExist(topo);
+  if ( numfaces != 0 ) {
+    if ( numfaces > 0 ) {
+      /* Faces exist */
+      rterror(iface->ctx, "rtt_AddLineNoFace - table <topo>Face is not empty.");
+    }
+    /* Backend error, message should have been printed already */
+    return NULL;
+  }
+  
+  return _rtt_AddLine(topo, line, tol, nedges, 0);
+}
+
+RTT_ELEMID*
 rtt_AddPolygon(RTT_TOPOLOGY* topo, RTPOLY* poly, double tol, int* nfaces)
 {
   const RTT_BE_IFACE *iface = topo->be_iface;
@@ -5916,9 +6023,9 @@ rtt_AddPolygon(RTT_TOPOLOGY* topo, RTPOLY* poly, double tol, int* nfaces)
   const GEOSPreparedGeometry *ppoly;
   GEOSGeometry *polyg;
 
-  /* Get tolerance, if 0 was given */
-  if ( ! tol ) tol = _RTT_MINTOLERANCE( topo, (RTGEOM*)poly );
-  RTDEBUGF(1, "Working tolerance:%.15g", tol);
+  /* Get tolerance, if -1 was given */
+  if ( tol == -1 ) tol = _RTT_MINTOLERANCE( topo, (RTGEOM*)poly );
+  RTDEBUGF(iface->ctx, 1, "Working tolerance:%.15g", tol);
 
   /* Add each ring as an edge */
   for ( i=0; i<poly->nrings; ++i )
@@ -6037,3 +6144,924 @@ rtt_AddPolygon(RTT_TOPOLOGY* topo, RTPOLY* poly, double tol, int* nfaces)
 
   return ids;
 }
+
+/*
+ *---- polygonizer
+ */
+
+/* An array of pointers to EDGERING structures */
+typedef struct RTT_ISO_EDGE_TABLE_T {
+  RTT_ISO_EDGE *edges;
+  int size;
+} RTT_ISO_EDGE_TABLE;
+
+static int
+compare_iso_edges_by_id(const void *si1, const void *si2)
+{
+	int a = ((RTT_ISO_EDGE *)si1)->edge_id;
+	int b = ((RTT_ISO_EDGE *)si2)->edge_id;
+	if ( a < b )
+		return -1;
+	else if ( a > b )
+		return 1;
+	else
+		return 0;
+}
+
+static RTT_ISO_EDGE *
+_rtt_getIsoEdgeById(RTT_ISO_EDGE_TABLE *tab, RTT_ELEMID id)
+{
+  RTT_ISO_EDGE key;
+  key.edge_id = id;
+
+  void *match = bsearch( &key, tab->edges, tab->size,
+                     sizeof(RTT_ISO_EDGE),
+                     compare_iso_edges_by_id);
+  return match;
+}
+
+typedef struct RTT_EDGERING_ELEM_T {
+  /* externally owned */
+  RTT_ISO_EDGE *edge;
+  int left;
+} RTT_EDGERING_ELEM;
+
+/* A ring of edges */
+typedef struct RTT_EDGERING_T {
+  /* Signed edge identifiers
+   * positive ones are walked in their direction, negative ones
+   * in the opposite direction */
+  RTT_EDGERING_ELEM **elems;
+  /* Number of edges in the ring */
+  int size;
+  int capacity;
+  /* Bounding box of the ring */
+  RTGBOX *env;
+  /* Bounding box of the ring in GEOS format (for STRTree) */
+  GEOSGeometry *genv;
+} RTT_EDGERING;
+
+#define RTT_EDGERING_INIT(c, a) { \
+  (a)->size = 0; \
+  (a)->capacity = 1; \
+  (a)->elems = rtalloc((c), sizeof(RTT_EDGERING_ELEM *) * (a)->capacity); \
+  (a)->env = NULL; \
+  (a)->genv = NULL; \
+}
+
+#define RTT_EDGERING_PUSH(c, a, r) { \
+  if ( (a)->size + 1 > (a)->capacity ) { \
+    (a)->capacity *= 2; \
+    (a)->elems = rtrealloc((c), (a)->elems, sizeof(RTT_EDGERING_ELEM *) * (a)->capacity); \
+  } \
+  /* rtdebug(1, "adding elem %d (%p) of edgering %p", (a)->size, (r), (a)); */ \
+  (a)->elems[(a)->size++] = (r); \
+}
+
+#define RTT_EDGERING_CLEAN(c, a) { \
+  int i; for (i=0; i<(a)->size; ++i) { \
+    if ( (a)->elems[i] ) { \
+      /* rtdebug(1, "freeing elem %d (%p) of edgering %p", i, (a)->elems[i], (a)); */ \
+      rtfree(ctx,(a)->elems[i]); \
+    } \
+  } \
+  if ( (a)->elems ) { rtfree(ctx,(a)->elems); (a)->elems = NULL; } \
+  (a)->size = 0; \
+  (a)->capacity = 0; \
+  if ( (a)->env ) { rtfree(ctx,(a)->env); (a)->env = NULL; } \
+  if ( (a)->genv ) { GEOSGeom_destroy_r( (c)->gctx, (a)->genv); (a)->genv = NULL; } \
+}
+
+/* An array of pointers to EDGERING structures */
+typedef struct RTT_EDGERING_ARRAY_T {
+  RTT_EDGERING **rings;
+  int size;
+  int capacity;
+  GEOSSTRtree* tree;
+} RTT_EDGERING_ARRAY;
+
+#define RTT_EDGERING_ARRAY_INIT(c, a) { \
+  (a)->size = 0; \
+  (a)->capacity = 1; \
+  (a)->rings = rtalloc((c), sizeof(RTT_EDGERING *) * (a)->capacity); \
+  (a)->tree = NULL; \
+}
+
+/* WARNING: use of 'j' is intentional, no to clash with
+ * 'i' used in RTT_EDGERING_CLEAN */
+#define RTT_EDGERING_ARRAY_CLEAN(c, a) { \
+  int j; for (j=0; j<(a)->size; ++j) { \
+    RTT_EDGERING_CLEAN((c), (a)->rings[j]); \
+    rtfree( (c), (a)->rings[j]); \
+  } \
+  if ( (a)->capacity ) rtfree(ctx,(a)->rings); \
+  if ( (a)->tree ) { \
+    GEOSSTRtree_destroy_r( (c)->gctx, (a)->tree ); \
+    (a)->tree = NULL; \
+  } \
+}
+
+#define RTT_EDGERING_ARRAY_PUSH(c, a, r) { \
+  if ( (a)->size + 1 > (a)->capacity ) { \
+    (a)->capacity *= 2; \
+    (a)->rings = rtrealloc((c), (a)->rings, sizeof(RTT_EDGERING *) * (a)->capacity); \
+  } \
+  (a)->rings[(a)->size++] = (r); \
+}
+
+typedef struct RTT_EDGERING_POINT_ITERATOR_T {
+  RTT_EDGERING *ring;
+  RTT_EDGERING_ELEM *curelem;
+  int curelemidx;
+  int curidx;
+} RTT_EDGERING_POINT_ITERATOR;
+
+static int
+_rtt_EdgeRingIterator_next(const RTCTX *ctx, RTT_EDGERING_POINT_ITERATOR *it, RTPOINT2D *pt)
+{
+  RTT_EDGERING_ELEM *el = it->curelem;
+  RTPOINTARRAY *pa;
+
+  if ( ! el ) return 0; /* finished */
+
+  pa = el->edge->geom->points;
+
+  int tonext = 0;
+  RTDEBUGF(ctx, 3, "iterator fetching idx %d from pa of %d points", it->curidx, pa->npoints);
+  rt_getPoint2d_p(ctx,pa, it->curidx, pt);
+  if ( el->left ) {
+    it->curidx++;
+    if ( it->curidx >= pa->npoints ) tonext = 1;
+  } else {
+    it->curidx--;
+    if ( it->curidx < 0 ) tonext = 1;
+  }
+
+  if ( tonext )
+  {
+    RTDEBUG(ctx, 3, "iterator moving to next element");
+    it->curelemidx++;
+    if ( it->curelemidx < it->ring->size )
+    {
+      el = it->curelem = it->ring->elems[it->curelemidx];
+      it->curidx = el->left ? 0 : el->edge->geom->points->npoints - 1;
+    }
+    else
+    {
+      it->curelem = NULL;
+    }
+  }
+
+  return 1;
+}
+
+/* Release return with rtfree */
+static RTT_EDGERING_POINT_ITERATOR *
+_rtt_EdgeRingIterator_begin(const RTCTX *ctx, RTT_EDGERING *er)
+{
+  RTT_EDGERING_POINT_ITERATOR *ret = rtalloc(ctx, sizeof(RTT_EDGERING_POINT_ITERATOR));
+  ret->ring = er;
+  if ( er->size ) ret->curelem = er->elems[0];
+  else ret->curelem = NULL;
+  ret->curelemidx = 0;
+  ret->curidx = ret->curelem->left ? 0 : ret->curelem->edge->geom->points->npoints - 1;
+  return ret;
+}
+
+/* Identifier for a placeholder face that will be
+ * used to mark hole rings */
+#define RTT_HOLES_FACE_PLACEHOLDER INT32_MIN
+
+static int
+_rtt_FetchNextUnvisitedEdge(RTT_TOPOLOGY *topo, RTT_ISO_EDGE_TABLE *etab, int from)
+{
+  while (
+    from < etab->size &&
+    etab->edges[from].face_left != -1 &&
+    etab->edges[from].face_right != -1
+  ) from++;
+  return from < etab->size ? from : -1;
+}
+
+static RTT_ISO_EDGE *
+_rtt_FetchAllEdges(RTT_TOPOLOGY *topo, int *numedges)
+{
+  RTT_ISO_EDGE *edge;
+  int fields = RTT_COL_EDGE_ALL;
+  int nelems = 1;
+  RTGBOX qbox;
+  const RTCTX *ctx = topo->be_iface->ctx;
+
+  qbox.xmin = qbox.ymin = -DBL_MAX;
+  qbox.xmax = qbox.ymax = DBL_MAX;
+  edge = rtt_be_getEdgeWithinBox2D( topo, &qbox, &nelems, fields, 0);
+  *numedges = nelems;
+  if ( nelems == -1 ) {
+    rterror(ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
+    return NULL;
+  }
+  return edge;
+}
+
+/* Update the side face of given ring edges
+ *
+ * Edge identifiers are signed, those with negative identifier
+ * need to be updated their right_face, those with positive
+ * identifier need to be updated their left_face.
+ *
+ * @param face identifier of the face bound by the ring
+ * @return 0 on success, -1 on error
+ */
+static int
+_rtt_UpdateEdgeRingSideFace(RTT_TOPOLOGY *topo, RTT_EDGERING *ring,
+                            RTT_ELEMID face)
+{
+  RTT_ISO_EDGE *forward_edges = NULL;
+  int forward_edges_count = 0;
+  RTT_ISO_EDGE *backward_edges = NULL;
+  int backward_edges_count = 0;
+  int i, ret;
+  const RTCTX *ctx = topo->be_iface->ctx;
+
+  /* Make a list of forward_edges and backward_edges */
+
+  forward_edges = rtalloc(ctx, sizeof(RTT_ISO_EDGE) * ring->size);
+  forward_edges_count = 0;
+  backward_edges = rtalloc(ctx, sizeof(RTT_ISO_EDGE) * ring->size);
+  backward_edges_count = 0;
+
+  for ( i=0; i<ring->size; ++i )
+  {
+    RTT_EDGERING_ELEM *elem = ring->elems[i];
+    RTT_ISO_EDGE *edge = elem->edge;
+    RTT_ELEMID id = edge->edge_id;
+    if ( elem->left )
+    {
+      RTDEBUGF(ctx, 3, "Forward edge %d is %d", forward_edges_count, id);
+      forward_edges[forward_edges_count].edge_id = id;
+      forward_edges[forward_edges_count++].face_left = face;
+      edge->face_left = face;
+    }
+    else
+    {
+      RTDEBUGF(ctx, 3, "Backward edge %d is %d", forward_edges_count, id);
+      backward_edges[backward_edges_count].edge_id = id;
+      backward_edges[backward_edges_count++].face_right = face;
+      edge->face_right = face;
+    }
+  }
+
+  /* Update forward edges */
+  if ( forward_edges_count )
+  {
+    ret = rtt_be_updateEdgesById(topo, forward_edges,
+                                 forward_edges_count,
+                                 RTT_COL_EDGE_FACE_LEFT);
+    if ( ret == -1 )
+    {
+      rtfree(ctx, forward_edges );
+      rtfree(ctx, backward_edges );
+      rterror(ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
+      return -1;
+    }
+    if ( ret != forward_edges_count )
+    {
+      rtfree(ctx, forward_edges );
+      rtfree(ctx, backward_edges );
+      rterror(ctx, "Unexpected error: %d edges updated when expecting %d (forward)",
+              ret, forward_edges_count);
+      return -1;
+    }
+  }
+
+  /* Update backward edges */
+  if ( backward_edges_count )
+  {
+    ret = rtt_be_updateEdgesById(topo, backward_edges,
+                                 backward_edges_count,
+                                 RTT_COL_EDGE_FACE_RIGHT);
+    if ( ret == -1 )
+    {
+      rtfree(ctx, forward_edges );
+      rtfree(ctx, backward_edges );
+      rterror(ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
+      return -1;
+    }
+    if ( ret != backward_edges_count )
+    {
+      rtfree(ctx, forward_edges );
+      rtfree(ctx, backward_edges );
+      rterror(ctx, "Unexpected error: %d edges updated when expecting %d (backward)",
+              ret, backward_edges_count);
+      return -1;
+    }
+  }
+
+  rtfree(ctx, forward_edges );
+  rtfree(ctx, backward_edges );
+
+  return 0;
+}
+
+/*
+ * @param side 1 for left side, -1 for right side
+ */
+static RTT_EDGERING *
+_rtt_BuildEdgeRing(RTT_TOPOLOGY *topo, RTT_ISO_EDGE_TABLE *edges,
+                   RTT_ISO_EDGE *edge, int side)
+{
+  RTT_EDGERING *ring;
+  RTT_EDGERING_ELEM *elem;
+  RTT_ISO_EDGE *cur;
+  int curside;
+  const RTCTX *ctx = topo->be_iface->ctx;
+
+  ring = rtalloc(ctx, sizeof(RTT_EDGERING));
+  RTT_EDGERING_INIT(ctx, ring);
+
+  cur = edge;
+  curside = side;
+
+  RTDEBUGF(ctx, 2, "Building rings for edge %d (side %d)", cur->edge_id, side);
+
+  do {
+    RTT_ELEMID next;
+
+    elem = rtalloc(ctx, sizeof(RTT_EDGERING_ELEM));
+    elem->edge = cur;
+    elem->left = ( curside == 1 );
+
+    /* Mark edge as "visited" */
+    if ( elem->left ) cur->face_left = RTT_HOLES_FACE_PLACEHOLDER;
+    else cur->face_right = RTT_HOLES_FACE_PLACEHOLDER;
+
+    RTT_EDGERING_PUSH(ctx, ring, elem);
+    next = elem->left ? cur->next_left : cur->next_right;
+
+    RTDEBUGF(ctx, 3, " next edge is %d", next);
+
+    if ( next > 0 ) curside = 1;
+    else { curside = -1; next = -next; }
+    cur = _rtt_getIsoEdgeById(edges, next);
+    if ( ! cur )
+    {
+      RTT_EDGERING_CLEAN(ctx, ring);
+      rterror(ctx, "Could not find edge with id %d", next);
+      break;
+    }
+  } while (cur != edge || curside != side);
+
+  RTDEBUGF(ctx, 1, "Ring for edge %d has %d elems", edge->edge_id, ring->size);
+
+  return ring;
+}
+
+static double
+_rtt_EdgeRingSignedArea(const RTCTX *ctx, RTT_EDGERING_POINT_ITERATOR *it)
+{
+	RTPOINT2D P1;
+	RTPOINT2D P2;
+	RTPOINT2D P3;
+	double sum = 0.0;
+	double x0, x, y1, y2;
+
+  if ( ! _rtt_EdgeRingIterator_next(ctx, it, &P1) ) return 0.0;
+  if ( ! _rtt_EdgeRingIterator_next(ctx, it, &P2) ) return 0.0;
+
+  RTDEBUG(ctx, 2, "_rtt_EdgeRingSignedArea");
+
+  x0 = P1.x;
+  while ( _rtt_EdgeRingIterator_next(ctx, it, &P3)  )
+  {
+    x = P2.x - x0;
+    y1 = P3.y;
+    y2 = P1.y;
+    sum += x * (y2-y1);
+
+    /* Move forwards! */
+    P1 = P2;
+    P2 = P3;
+  }
+
+	return sum / 2.0;
+}
+
+
+/* Return 1 for true, 0 for false */
+static int
+_rtt_EdgeRingIsCCW(const RTCTX *ctx, RTT_EDGERING *ring)
+{
+  double sa;
+
+  RTDEBUGF(ctx, 2, "_rtt_EdgeRingIsCCW, ring has %d elems", ring->size);
+  RTT_EDGERING_POINT_ITERATOR *it = _rtt_EdgeRingIterator_begin(ctx, ring);
+  sa = _rtt_EdgeRingSignedArea(ctx, it);
+  RTDEBUGF(ctx, 2, "_rtt_EdgeRingIsCCW, signed area is %g", sa);
+  rtfree(ctx,it);
+  if ( sa >= 0 ) return 0;
+  else return 1;
+}
+
+static int
+_rtt_EdgeRingCrossingCount(const RTCTX *ctx, const RTPOINT2D *p, RTT_EDGERING_POINT_ITERATOR *it)
+{
+	int cn = 0;    /* the crossing number counter */
+	RTPOINT2D v1, v2;
+#ifndef RELAX
+  RTPOINT2D v0;
+#endif
+
+  if ( ! _rtt_EdgeRingIterator_next(ctx, it, &v1) ) return cn;
+  v0 = v1;
+	while ( _rtt_EdgeRingIterator_next(ctx, it, &v2) )
+	{
+		double vt;
+
+		/* edge from vertex i to vertex i+1 */
+		if
+		(
+		    /* an upward crossing */
+		    ((v1.y <= p->y) && (v2.y > p->y))
+		    /* a downward crossing */
+		    || ((v1.y > p->y) && (v2.y <= p->y))
+		)
+		{
+
+			vt = (double)(p->y - v1.y) / (v2.y - v1.y);
+
+			/* P->x <intersect */
+			if (p->x < v1.x + vt * (v2.x - v1.x))
+			{
+				/* a valid crossing of y=p->y right of p->x */
+				++cn;
+			}
+		}
+		v1 = v2;
+	}
+
+	RTDEBUGF(ctx, 3, "_rtt_EdgeRingCrossingCount returning %d", cn);
+
+#ifndef RELAX
+  if ( memcmp(&v1, &v0, sizeof(RTPOINT2D)) )
+  {
+    rterror(ctx, "_rtt_EdgeRingCrossingCount: V[n] != V[0] (%g %g != %g %g)",
+      v1.x, v1.y, v0.x, v0.y);
+    return -1;
+  }
+#endif
+
+  return cn;
+}
+
+/* Return 1 for true, 0 for false */
+static int
+_rtt_EdgeRingContainsPoint(const RTCTX *ctx, RTT_EDGERING *ring, RTPOINT2D *p)
+{
+  int cn = 0;
+
+  RTT_EDGERING_POINT_ITERATOR *it = _rtt_EdgeRingIterator_begin(ctx, ring);
+  cn = _rtt_EdgeRingCrossingCount(ctx, p, it);
+  rtfree(ctx, it);
+	return (cn&1);    /* 0 if even (out), and 1 if odd (in) */
+}
+
+static RTGBOX *
+_rtt_EdgeRingGetBbox(const RTCTX *ctx, RTT_EDGERING *ring)
+{
+  int i;
+
+  if ( ! ring->env )
+  {
+    RTDEBUGF(ctx, 2, "Computing RTGBOX for ring %p", ring);
+    for (i=0; i<ring->size; ++i)
+    {
+      RTT_EDGERING_ELEM *elem = ring->elems[i];
+      RTLINE *g = elem->edge->geom;
+      const RTGBOX *newbox = rtgeom_get_bbox(ctx, rtline_as_rtgeom(ctx, g));
+      if ( ! i ) ring->env = gbox_clone( ctx, newbox );
+      else gbox_merge( ctx, newbox, ring->env );
+    }
+  }
+
+  return ring->env;
+}
+
+static RTT_ELEMID
+_rtt_EdgeRingGetFace(RTT_EDGERING *ring)
+{
+  RTT_EDGERING_ELEM *el = ring->elems[0];
+  return el->left ? el->edge->face_left : el->edge->face_right;
+}
+
+
+/*
+ * Register a face on an edge side
+ *
+ * Create and register face to shell (CCW) walks,
+ * register arbitrary negative face_id to CW rings.
+ *
+ * Push CCW rings to shells, CW rings to holes.
+ *
+ * The ownership of the "geom" and "ids" members of the
+ * RTT_EDGERING pushed to the given RTT_EDGERING_ARRAYS
+ * are transferred to caller.
+ *
+ * @param side 1 for left side, -1 for right side
+ *
+ * @param holes an array where holes will be pushed
+ *
+ * @param shells an array where shells will be pushed
+ *
+ * @param registered id of registered face. It will be a negative number
+ *  for holes or isolated edge strips (still registered in the face
+ *  table, but only temporary).
+ *
+ * @return 0 on success, -1 on error.
+ *
+ */
+static int
+_rtt_RegisterFaceOnEdgeSide(RTT_TOPOLOGY *topo, RTT_ISO_EDGE *edge,
+                            int side, RTT_ISO_EDGE_TABLE *edges,
+                            RTT_EDGERING_ARRAY *holes,
+                            RTT_EDGERING_ARRAY *shells,
+                            RTT_ELEMID *registered)
+{
+  const RTT_BE_IFACE *iface = topo->be_iface;
+  int sedge = edge->edge_id * side;
+  /* this is arbitrary, could be taken as parameter */
+  static const int placeholder_faceid = RTT_HOLES_FACE_PLACEHOLDER;
+  RTT_EDGERING *ring;
+  const RTCTX *ctx = topo->be_iface->ctx;
+
+  /* Get edge ring */
+  ring = _rtt_BuildEdgeRing(topo, edges, edge, side);
+
+	RTDEBUG(ctx, 2, "Ring built, calling EdgeRingIsCCW");
+
+  /* Compute winding (CW or CCW?) */
+  int isccw = _rtt_EdgeRingIsCCW(ctx, ring);
+
+  if ( isccw )
+  {
+    /* Create new face */
+    RTT_ISO_FACE newface;
+
+    RTDEBUGF(ctx, 1, "Ring of edge %d is a shell", sedge);
+
+    newface.mbr = _rtt_EdgeRingGetBbox(ctx, ring);
+
+    newface.face_id = -1;
+    /* Insert the new face */
+    int ret = rtt_be_insertFaces( topo, &newface, 1 );
+    newface.mbr = NULL;
+    if ( ret == -1 )
+    {
+      RTT_EDGERING_CLEAN(ctx, ring);
+      rterror(ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
+      return -1;
+    }
+    if ( ret != 1 )
+    {
+      RTT_EDGERING_CLEAN(ctx, ring);
+      rterror(ctx, "Unexpected error: %d faces inserted when expecting 1", ret);
+      return -1;
+    }
+    /* return new face_id */
+    *registered = newface.face_id;
+    RTT_EDGERING_ARRAY_PUSH(ctx, shells, ring);
+
+    /* update ring edges set new face_id on resp. side to *registered */
+    ret = _rtt_UpdateEdgeRingSideFace(topo, ring, *registered);
+    if ( ret )
+    {
+        rterror(ctx, "Errors updating edgering side face: %s",
+                rtt_be_lastErrorMessage(iface));
+        return -1;
+    }
+
+  }
+  else /* cw, so is an hole */
+  {
+    RTDEBUGF(ctx, 1, "Ring of edge %d is a hole", sedge);
+    *registered = placeholder_faceid;
+    RTT_EDGERING_ARRAY_PUSH(ctx, holes, ring);
+  }
+
+  return 0;
+}
+
+typedef struct RING_ACCUMULATOR_T {
+  RTT_EDGERING_ARRAY *target;
+  const RTCTX *ctx;
+} RING_ACCUMULATOR;
+
+static void
+_rtt_AccumulateCanditates(void* item, void* userdata)
+{
+  RING_ACCUMULATOR *acc = userdata;
+  RTT_EDGERING_ARRAY *candidates = acc->target;
+  const RTCTX *ctx = acc->ctx;
+  RTT_EDGERING *sring = item;
+  RTT_EDGERING_ARRAY_PUSH(ctx, candidates, sring);
+}
+
+static RTT_ELEMID
+_rtt_FindFaceContainingRing(RTT_TOPOLOGY* topo, RTT_EDGERING *ring,
+                            RTT_EDGERING_ARRAY *shells)
+{
+  RTT_ELEMID foundInFace = -1;
+  int i;
+  const RTGBOX *minenv = NULL;
+  RTPOINT2D pt;
+  const RTGBOX *testbox;
+  GEOSGeometry *ghole;
+  const RTCTX *ctx = topo->be_iface->ctx;
+
+  rt_getPoint2d_p(ctx, ring->elems[0]->edge->geom->points, 0, &pt );
+
+  testbox = _rtt_EdgeRingGetBbox(ctx, ring);
+
+  /* Create a GEOS Point from a vertex of the hole ring */
+  {
+    RTPOINT *point = rtpoint_make2d(ctx, topo->srid, pt.x, pt.y);
+    ghole = RTGEOM2GEOS(ctx,  rtpoint_as_rtgeom(ctx, point), 1 );
+    rtpoint_free(ctx, point);
+    if ( ! ghole ) {
+      rterror(ctx, "Could not convert edge geometry to GEOS: %s", rtgeom_get_last_geos_error(ctx));
+      return -1;
+    }
+  }
+
+  /* Build STRtree of shell envelopes */
+  if ( ! shells->tree )
+  {
+    static const int STRTREE_NODE_CAPACITY = 10;
+    RTDEBUG(ctx, 1, "Building STRtree");
+	  shells->tree = GEOSSTRtree_create_r(ctx->gctx, STRTREE_NODE_CAPACITY);
+    if (shells->tree == NULL)
+    {
+      rterror(ctx, "Could not create GEOS STRTree: %s", rtgeom_get_last_geos_error(ctx));
+      return -1;
+    }
+    for (i=0; i<shells->size; ++i)
+    {
+      RTT_EDGERING *sring = shells->rings[i];
+      const RTGBOX* shellbox = _rtt_EdgeRingGetBbox(ctx, sring);
+      RTDEBUGF(ctx, 2, "RTGBOX of shell %p for edge %d is %g %g,%g %g",
+        sring, sring->elems[0]->edge->edge_id, shellbox->xmin,
+        shellbox->ymin, shellbox->xmax, shellbox->ymax);
+      RTPOINTARRAY *pa = ptarray_construct(ctx, 0, 0, 2);
+      RTPOINT4D pt;
+      RTLINE *diag;
+      pt.x = shellbox->xmin;
+      pt.y = shellbox->ymin;
+      ptarray_set_point4d(ctx, pa, 0, &pt);
+      pt.x = shellbox->xmax;
+      pt.y = shellbox->ymax;
+      ptarray_set_point4d(ctx, pa, 1, &pt);
+      diag = rtline_construct(ctx, topo->srid, NULL, pa);
+      /* Record just envelope in ggeom */
+      /* making valid, probably not needed */
+      sring->genv = RTGEOM2GEOS(ctx, rtline_as_rtgeom(ctx, diag), 1 );
+      rtline_free(ctx, diag);
+      GEOSSTRtree_insert_r(ctx->gctx, shells->tree, sring->genv, sring);
+    }
+    RTDEBUG(ctx, 1, "STRtree build completed");
+  }
+
+  RTT_EDGERING_ARRAY candidates;
+  RING_ACCUMULATOR accumulator;
+  accumulator.target = &candidates;
+  accumulator.ctx = ctx;
+  RTT_EDGERING_ARRAY_INIT(ctx, &candidates);
+	GEOSSTRtree_query_r(ctx->gctx, shells->tree, ghole, &_rtt_AccumulateCanditates, &accumulator);
+  RTDEBUGF(ctx, 1, "Found %d candidate shells for containement of ring %d point",
+          candidates.size, ring->elems[0]->edge->edge_id);
+
+  /* TODO: sort candidates by bounding box size */
+
+  for (i=0; i<candidates.size; ++i)
+  {
+    RTT_EDGERING *sring = candidates.rings[i];
+    const RTGBOX* shellbox = _rtt_EdgeRingGetBbox(ctx, sring);
+    int contains = 0;
+
+    if ( sring->elems[0]->edge->edge_id == ring->elems[0]->edge->edge_id )
+    {
+      RTDEBUGF(ctx, 1, "Shell %d is on other side of ring", _rtt_EdgeRingGetFace(sring));
+      continue;
+    }
+
+    /* Skip if test point is not in shellbox */
+    if ( ! gbox_contains_2d(ctx, shellbox, testbox) )
+    {
+      /* TODO: skip this, should never happen, as we're candidates! */
+      RTDEBUGF(ctx, 1, "Bbox of shell %d does not contain bbox of ring point", _rtt_EdgeRingGetFace(sring));
+      continue;
+    }
+
+    /* Skip test if a containing shell was already found
+     * and this shell's bbox is not contained in the other */
+    if ( minenv && ! gbox_contains_2d(ctx, minenv, shellbox) )
+    {
+      RTDEBUGF(ctx, 2, "Bbox of shell %d (face %d) not contained by bbox "
+                  "of last shell found to contain the point",
+                  i, _rtt_EdgeRingGetFace(sring));
+      continue;
+    }
+
+    contains = _rtt_EdgeRingContainsPoint(ctx, sring, &pt);
+    if ( contains )
+    {
+      /* Continue until all shells are tested, as we want to
+       * use the one with the smallest bounding box */
+      /* IDEA: sort shells by bbox size, stopping on first match */
+      RTDEBUGF(ctx, 1, "Shell %d contains hole of edge %d",
+               _rtt_EdgeRingGetFace(sring),
+               ring->elems[0]->edge->edge_id);
+      minenv = shellbox;
+      foundInFace = _rtt_EdgeRingGetFace(sring);
+    }
+  }
+  if ( foundInFace == -1 ) foundInFace = 0;
+
+  candidates.size = 0; /* Avoid destroying the actual shell rings */
+  RTT_EDGERING_ARRAY_CLEAN(ctx, &candidates);
+
+  GEOSGeom_destroy_r(ctx->gctx, ghole);
+
+  return foundInFace;
+}
+
+/*
+ * Determine and register all topology faces:
+ *
+ *  - Determines which faces are generated by existing
+ *    edges.
+ *  - Creates face records with correct mbr
+ *  - Update edge left/right face attributes
+ *
+ *  Precondition:
+ *     - the topology edges are correctly linked
+ *
+ *  Postconditions:
+ *     - all left/right face attributes of edges
+ *       reference faces with correct mbr.
+ *
+ *  Notes:
+ *     - does not attempt to assign isolated nodes to their
+ *       containing faces
+ *     - does not remove existing face records
+ *     - loads in memory all the topology edges
+ *
+ * @param topo the topology to operate on
+ *
+ * @return 0 on success, -1 on error
+ *         (librtgeom error handler will be invoked with error message)
+ */
+int
+rtt_Polygonize(RTT_TOPOLOGY* topo)
+{
+  /*
+     Iteratively:
+       Fetch next edge with null left-or-right face
+       For each NULL side:
+         Find ring on its side
+         If ring is CCW:
+            create a new face, assign to the ring edges' appropriate side
+         If ring is CW (face needs to be same of external):
+            assign a negative face_id the ring edges' appropriate side
+     Now for each edge with a negative face_id on the side:
+       Find containing face (mbr cache and all)
+       Update with id of containing face
+   */
+
+  const RTT_BE_IFACE *iface = topo->be_iface;
+  RTT_ISO_EDGE *edge;
+  int numfaces = -1;
+  RTT_ISO_EDGE_TABLE edgetable;
+  RTT_EDGERING_ARRAY holes, shells;
+  int i;
+  int err = 0;
+  const RTCTX *ctx = iface->ctx;
+
+  _rtt_EnsureGeos(iface->ctx);
+
+  RTT_EDGERING_ARRAY_INIT(ctx, &holes);
+  RTT_EDGERING_ARRAY_INIT(ctx, &shells);
+
+  /*
+   Check if Topology already contains some Face
+   (ignoring the Universal Face)
+  */
+  numfaces = _rtt_CheckFacesExist(topo);
+  if ( numfaces != 0 ) {
+    if ( numfaces > 0 ) {
+      /* Faces exist */
+      rterror(iface->ctx, "rtt_Polygonize exception - table <topo>Face is not empty.");
+    }
+    /* Backend error, message should have been printed already */
+    return -1;
+  }
+
+  edgetable.edges = _rtt_FetchAllEdges(topo, &(edgetable.size));
+  if ( ! edgetable.edges ) {
+    if (edgetable.size == 0) {
+      /* not an error: no Edges */
+      return 0;
+    }
+    /* error should have been printed already */
+    return -1;
+  }
+
+  /* Sort edges by ID (to allow btree searches) */
+  qsort(edgetable.edges, edgetable.size, sizeof(RTT_ISO_EDGE), compare_iso_edges_by_id);
+
+  /* Mark all edges as unvisited */
+  for (i=0; i<edgetable.size; ++i)
+    edgetable.edges[i].face_left = edgetable.edges[i].face_right = -1;
+
+  i = 0;
+  while (1)
+  {
+    i = _rtt_FetchNextUnvisitedEdge(topo, &edgetable, i);
+    if ( i < 0 ) break; /* end of unvisited */
+    edge = &(edgetable.edges[i]);
+
+    RTT_ELEMID newface = -1;
+
+    RTDEBUGF(ctx, 1, "Next face-missing edge has id:%d, face_left:%d, face_right:%d",
+               edge->edge_id, edge->face_left, edge->face_right);
+    if ( edge->face_left == -1 )
+    {
+      err = _rtt_RegisterFaceOnEdgeSide(topo, edge, 1, &edgetable,
+                                        &holes, &shells, &newface);
+      if ( err ) break;
+      RTDEBUGF(ctx, 1, "New face on the left of edge %d is %d",
+                 edge->edge_id, newface);
+      edge->face_left = newface;
+    }
+    if ( edge->face_right == -1 )
+    {
+      err = _rtt_RegisterFaceOnEdgeSide(topo, edge, -1, &edgetable,
+                                        &holes, &shells, &newface);
+      if ( err ) break;
+      RTDEBUGF(ctx, 1, "New face on the right of edge %d is %d",
+                 edge->edge_id, newface);
+      edge->face_right = newface;
+    }
+  }
+
+  if ( err )
+  {
+      rtt_release_edges(ctx, edgetable.edges, edgetable.size);
+      RTT_EDGERING_ARRAY_CLEAN( ctx, &holes );
+      RTT_EDGERING_ARRAY_CLEAN( ctx, &shells );
+      rterror(ctx, "Errors fetching or registering face-missing edges: %s",
+              rtt_be_lastErrorMessage(iface));
+      return -1;
+  }
+
+  RTDEBUGF(ctx, 1, "Found %d holes and %d shells", holes.size, shells.size);
+
+  /* TODO: sort holes by pt.x, sort shells by bbox.xmin */
+
+  /* Assign shells to holes */
+  for (i=0; i<holes.size; ++i)
+  {
+    RTT_ELEMID containing_face;
+    RTT_EDGERING *ring = holes.rings[i];
+
+    containing_face = _rtt_FindFaceContainingRing(topo, ring, &shells);
+    RTDEBUGF(ctx, 1, "Ring %d contained by face %" RTTFMT_ELEMID, i, containing_face);
+    if ( containing_face == -1 )
+    {
+      rtt_release_edges(ctx, edgetable.edges, edgetable.size);
+      RTT_EDGERING_ARRAY_CLEAN( ctx, &holes );
+      RTT_EDGERING_ARRAY_CLEAN( ctx, &shells );
+      rterror(ctx, "Errors finding face containing ring: %s",
+              rtt_be_lastErrorMessage(iface));
+      return -1;
+    }
+    int ret = _rtt_UpdateEdgeRingSideFace(topo, holes.rings[i], containing_face);
+    if ( ret )
+    {
+      rtt_release_edges(ctx, edgetable.edges, edgetable.size);
+      RTT_EDGERING_ARRAY_CLEAN( ctx, &holes );
+      RTT_EDGERING_ARRAY_CLEAN( ctx, &shells );
+      rterror(ctx, "Errors updating edgering side face: %s",
+              rtt_be_lastErrorMessage(iface));
+      return -1;
+    }
+  }
+
+  RTDEBUG(ctx, 1, "All holes assigned, cleaning up");
+
+  rtt_release_edges(ctx, edgetable.edges, edgetable.size);
+
+  /* delete all shell and hole EDGERINGS */
+  RTT_EDGERING_ARRAY_CLEAN( ctx, &holes );
+  RTT_EDGERING_ARRAY_CLEAN( ctx, &shells );
+
+  return 0;
+}
diff --git a/src/rtin_geojson.c b/src/rtin_geojson.c
index 2cc1048..289127b 100644
--- a/src/rtin_geojson.c
+++ b/src/rtin_geojson.c
@@ -18,7 +18,7 @@
  *
  **********************************************************************
  *
- * Copyright 2013 Sandro Santilli <strk at keybit.net>
+ * Copyright 2013 Sandro Santilli <strk at kbt.io>
  * Copyright 2011 Kashif Rasul <kashif.rasul at gmail.com>
  *
  **********************************************************************/
@@ -49,7 +49,7 @@
 
 static void geojson_rterror(char *msg, int error_code)
 {
-  RTDEBUGF(3, "rtgeom_from_geojson ERROR %i", error_code);
+  RTDEBUGF(ctx, 3, "rtgeom_from_geojson ERROR %i", error_code);
   rterror(ctx, "%s", msg);
 }
 
@@ -99,14 +99,14 @@ parse_geojson_coord(json_object *poObj, int *hasz, RTPOINTARRAY *pa)
 {
   RTPOINT4D pt;
 
-  RTDEBUGF(3, "parse_geojson_coord called for object %s.", json_object_to_json_string( poObj ) );
+  RTDEBUGF(ctx, 3, "parse_geojson_coord called for object %s.", json_object_to_json_string( poObj ) );
 
   if( json_type_array == json_object_get_type( poObj ) )
   {
 
     json_object* poObjCoord = NULL;
     const int nSize = json_object_array_length( poObj );
-    RTDEBUGF(3, "parse_geojson_coord called for array size %d.", nSize );
+    RTDEBUGF(ctx, 3, "parse_geojson_coord called for array size %d.", nSize );
 
     if ( nSize < 2 )
     {
@@ -117,19 +117,19 @@ parse_geojson_coord(json_object *poObj, int *hasz, RTPOINTARRAY *pa)
     /* Read X coordinate */
     poObjCoord = json_object_array_get_idx( poObj, 0 );
     pt.x = json_object_get_double( poObjCoord );
-    RTDEBUGF(3, "parse_geojson_coord pt.x = %f.", pt.x );
+    RTDEBUGF(ctx, 3, "parse_geojson_coord pt.x = %f.", pt.x );
 
     /* Read Y coordinate */
     poObjCoord = json_object_array_get_idx( poObj, 1 );
     pt.y = json_object_get_double( poObjCoord );
-    RTDEBUGF(3, "parse_geojson_coord pt.y = %f.", pt.y );
+    RTDEBUGF(ctx, 3, "parse_geojson_coord pt.y = %f.", pt.y );
 
     if( nSize > 2 ) /* should this be >= 3 ? */
     {
       /* Read Z coordinate */
       poObjCoord = json_object_array_get_idx( poObj, 2 );
       pt.z = json_object_get_double( poObjCoord );
-      RTDEBUGF(3, "parse_geojson_coord pt.z = %f.", pt.z );
+      RTDEBUGF(ctx, 3, "parse_geojson_coord pt.z = %f.", pt.z );
       *hasz = RT_TRUE;
     }
     else if ( nSize == 2 )
@@ -164,7 +164,7 @@ parse_geojson_point(json_object *geojson, int *hasz, int root_srid)
   RTPOINTARRAY *pa;
   json_object* coords = NULL;
 
-  RTDEBUGF(3, "parse_geojson_point called with root_srid = %d.", root_srid );
+  RTDEBUGF(ctx, 3, "parse_geojson_point called with root_srid = %d.", root_srid );
 
   coords = findMemberByName( geojson, "coordinates" );
   if ( ! coords )
@@ -177,7 +177,7 @@ parse_geojson_point(json_object *geojson, int *hasz, int root_srid)
   parse_geojson_coord(coords, hasz, pa);
 
   geom = (RTGEOM *) rtpoint_construct(ctx, root_srid, NULL, pa);
-  RTDEBUG(2, "parse_geojson_point finished.");
+  RTDEBUG(ctx, 2, "parse_geojson_point finished.");
   return geom;
 }
 
@@ -189,7 +189,7 @@ parse_geojson_linestring(json_object *geojson, int *hasz, int root_srid)
   json_object* points = NULL;
   int i = 0;
 
-  RTDEBUG(2, "parse_geojson_linestring called.");
+  RTDEBUG(ctx, 2, "parse_geojson_linestring called.");
 
   points = findMemberByName( geojson, "coordinates" );
   if ( ! points )
@@ -213,7 +213,7 @@ parse_geojson_linestring(json_object *geojson, int *hasz, int root_srid)
 
   geom = (RTGEOM *) rtline_construct(ctx, root_srid, NULL, pa);
 
-  RTDEBUG(2, "parse_geojson_linestring finished.");
+  RTDEBUG(ctx, 2, "parse_geojson_linestring finished.");
   return geom;
 }
 
@@ -589,7 +589,7 @@ rtgeom_from_geojson(const RTCTX *ctx, const char *geojson, char **srs)
     rtgeom_free(ctx, rtgeom);
     rtgeom = tmp;
 
-    RTDEBUG(2, "geom_from_geojson called.");
+    RTDEBUG(ctx, 2, "geom_from_geojson called.");
   }
 
   return rtgeom;
diff --git a/src/rtin_twkb.c b/src/rtin_twkb.c
index 5e9eda0..bd48fc1 100644
--- a/src/rtin_twkb.c
+++ b/src/rtin_twkb.c
@@ -177,8 +177,8 @@ static RTPOINTARRAY* ptarray_from_twkb_state(const RTCTX *ctx, twkb_parse_state
   int i;
   double *dlist;
 
-  RTDEBUG(2,"Entering ptarray_from_twkb_state");
-  RTDEBUGF(4,"Pointarray has %d points", npoints);
+  RTDEBUG(ctx, 2,"Entering ptarray_from_twkb_state");
+  RTDEBUGF(ctx, 4,"Pointarray has %d points", npoints);
 
   /* Empty! */
   if( npoints == 0 )
@@ -224,7 +224,7 @@ static RTPOINT* rtpoint_from_twkb_state(const RTCTX *ctx, twkb_parse_state *s)
   static uint32_t npoints = 1;
   RTPOINTARRAY *pa;
 
-  RTDEBUG(2,"Entering rtpoint_from_twkb_state");
+  RTDEBUG(ctx, 2,"Entering rtpoint_from_twkb_state");
 
   if ( s->is_empty )
     return rtpoint_construct_empty(ctx, SRID_UNKNOWN, s->has_z, s->has_m);
@@ -241,7 +241,7 @@ static RTLINE* rtline_from_twkb_state(const RTCTX *ctx, twkb_parse_state *s)
   uint32_t npoints;
   RTPOINTARRAY *pa;
 
-  RTDEBUG(2,"Entering rtline_from_twkb_state");
+  RTDEBUG(ctx, 2,"Entering rtline_from_twkb_state");
 
   if ( s->is_empty )
     return rtline_construct_empty(ctx, SRID_UNKNOWN, s->has_z, s->has_m);
@@ -276,7 +276,7 @@ static RTPOLY* rtpoly_from_twkb_state(const RTCTX *ctx, twkb_parse_state *s)
   int i;
   RTPOLY *poly;
 
-  RTDEBUG(2,"Entering rtpoly_from_twkb_state");
+  RTDEBUG(ctx, 2,"Entering rtpoly_from_twkb_state");
 
   if ( s->is_empty )
     return rtpoly_construct_empty(ctx, SRID_UNKNOWN, s->has_z, s->has_m);
@@ -287,7 +287,7 @@ static RTPOLY* rtpoly_from_twkb_state(const RTCTX *ctx, twkb_parse_state *s)
   /* Start w/ empty polygon */
   poly = rtpoly_construct_empty(ctx, SRID_UNKNOWN, s->has_z, s->has_m);
 
-  RTDEBUGF(4,"Polygon has %d rings", nrings);
+  RTDEBUGF(ctx, 4,"Polygon has %d rings", nrings);
 
   /* Empty polygon? */
   if( nrings == 0 )
@@ -314,7 +314,7 @@ static RTPOLY* rtpoly_from_twkb_state(const RTCTX *ctx, twkb_parse_state *s)
     /* Check for at least four points. */
     if( s->check & RT_PARSER_CHECK_MINPOINTS && pa->npoints < 4 )
     {
-      RTDEBUGF(2, "%s must have at least four points in each ring", rttype_name(ctx, s->rttype));
+      RTDEBUGF(ctx, 2, "%s must have at least four points in each ring", rttype_name(ctx, s->rttype));
       rterror(ctx, "%s must have at least four points in each ring", rttype_name(ctx, s->rttype));
       return NULL;
     }
@@ -322,7 +322,7 @@ static RTPOLY* rtpoly_from_twkb_state(const RTCTX *ctx, twkb_parse_state *s)
     /* Add ring to polygon */
     if ( rtpoly_add_ring(ctx, poly, pa) == RT_FAILURE )
     {
-      RTDEBUG(2, "Unable to add ring to polygon");
+      RTDEBUG(ctx, 2, "Unable to add ring to polygon");
       rterror(ctx, "Unable to add ring to polygon");
     }
 
@@ -340,14 +340,14 @@ static RTCOLLECTION* rtmultipoint_from_twkb_state(const RTCTX *ctx, twkb_parse_s
   RTGEOM *geom = NULL;
   RTCOLLECTION *col = rtcollection_construct_empty(ctx, s->rttype, SRID_UNKNOWN, s->has_z, s->has_m);
 
-  RTDEBUG(2,"Entering rtmultipoint_from_twkb_state");
+  RTDEBUG(ctx, 2,"Entering rtmultipoint_from_twkb_state");
 
   if ( s->is_empty )
     return col;
 
   /* Read number of geometries */
   ngeoms = twkb_parse_state_uvarint(ctx, s);
-  RTDEBUGF(4,"Number of geometries %d", ngeoms);
+  RTDEBUGF(ctx, 4,"Number of geometries %d", ngeoms);
 
   /* It has an idlist, we need to skip that */
   if ( s->has_idlist )
@@ -378,7 +378,7 @@ static RTCOLLECTION* rtmultiline_from_twkb_state(const RTCTX *ctx, twkb_parse_st
   RTGEOM *geom = NULL;
   RTCOLLECTION *col = rtcollection_construct_empty(ctx, s->rttype, SRID_UNKNOWN, s->has_z, s->has_m);
 
-  RTDEBUG(2,"Entering rtmultilinestring_from_twkb_state");
+  RTDEBUG(ctx, 2,"Entering rtmultilinestring_from_twkb_state");
 
   if ( s->is_empty )
     return col;
@@ -386,7 +386,7 @@ static RTCOLLECTION* rtmultiline_from_twkb_state(const RTCTX *ctx, twkb_parse_st
   /* Read number of geometries */
   ngeoms = twkb_parse_state_uvarint(ctx, s);
 
-  RTDEBUGF(4,"Number of geometries %d",ngeoms);
+  RTDEBUGF(ctx, 4,"Number of geometries %d",ngeoms);
 
   /* It has an idlist, we need to skip that */
   if ( s->has_idlist )
@@ -417,14 +417,14 @@ static RTCOLLECTION* rtmultipoly_from_twkb_state(const RTCTX *ctx, twkb_parse_st
   RTGEOM *geom = NULL;
   RTCOLLECTION *col = rtcollection_construct_empty(ctx, s->rttype, SRID_UNKNOWN, s->has_z, s->has_m);
 
-  RTDEBUG(2,"Entering rtmultipolygon_from_twkb_state");
+  RTDEBUG(ctx, 2,"Entering rtmultipolygon_from_twkb_state");
 
   if ( s->is_empty )
     return col;
 
   /* Read number of geometries */
   ngeoms = twkb_parse_state_uvarint(ctx, s);
-  RTDEBUGF(4,"Number of geometries %d",ngeoms);
+  RTDEBUGF(ctx, 4,"Number of geometries %d",ngeoms);
 
   /* It has an idlist, we need to skip that */
   if ( s->has_idlist )
@@ -456,7 +456,7 @@ static RTCOLLECTION* rtcollection_from_twkb_state(const RTCTX *ctx, twkb_parse_s
   RTGEOM *geom = NULL;
   RTCOLLECTION *col = rtcollection_construct_empty(ctx, s->rttype, SRID_UNKNOWN, s->has_z, s->has_m);
 
-  RTDEBUG(2,"Entering rtcollection_from_twkb_state");
+  RTDEBUG(ctx, 2,"Entering rtcollection_from_twkb_state");
 
   if ( s->is_empty )
     return col;
@@ -464,7 +464,7 @@ static RTCOLLECTION* rtcollection_from_twkb_state(const RTCTX *ctx, twkb_parse_s
   /* Read number of geometries */
   ngeoms = twkb_parse_state_uvarint(ctx, s);
 
-  RTDEBUGF(4,"Number of geometries %d",ngeoms);
+  RTDEBUGF(ctx, 4,"Number of geometries %d",ngeoms);
 
   /* It has an idlist, we need to skip that */
   if ( s->has_idlist )
@@ -490,7 +490,7 @@ static RTCOLLECTION* rtcollection_from_twkb_state(const RTCTX *ctx, twkb_parse_s
 
 static void header_from_twkb_state(const RTCTX *ctx, twkb_parse_state *s)
 {
-  RTDEBUG(2,"Entering magicbyte_from_twkb_state");
+  RTDEBUG(ctx, 2,"Entering magicbyte_from_twkb_state");
 
   uint8_t extended_dims;
 
@@ -659,8 +659,8 @@ RTGEOM* rtgeom_from_twkb(const RTCTX *ctx, uint8_t *twkb, size_t twkb_size, char
   int64_t coords[TWKB_IN_MAXCOORDS] = {0, 0, 0, 0};
   twkb_parse_state s;
 
-  RTDEBUG(2,"Entering rtgeom_from_twkb");
-  RTDEBUGF(4,"twkb_size: %d",(int) twkb_size);
+  RTDEBUG(ctx, 2,"Entering rtgeom_from_twkb");
+  RTDEBUGF(ctx, 4,"twkb_size: %d",(int) twkb_size);
 
   /* Zero out the state */
   memset(&s, 0, sizeof(twkb_parse_state));
diff --git a/src/rtin_wkb.c b/src/rtin_wkb.c
index dd0ba42..a19228f 100644
--- a/src/rtin_wkb.c
+++ b/src/rtin_wkb.c
@@ -138,7 +138,7 @@ static void rttype_from_wkb_state(const RTCTX *ctx, wkb_parse_state *s, uint32_t
 {
   uint32_t wkb_simple_type;
 
-  RTDEBUG(4, "Entered function");
+  RTDEBUG(ctx, 4, "Entered function");
 
   s->has_z = RT_FALSE;
   s->has_m = RT_FALSE;
@@ -150,7 +150,7 @@ static void rttype_from_wkb_state(const RTCTX *ctx, wkb_parse_state *s, uint32_t
     if( wkb_type & RTWKBZOFFSET ) s->has_z = RT_TRUE;
     if( wkb_type & RTWKBMOFFSET ) s->has_m = RT_TRUE;
     if( wkb_type & RTWKBSRIDFLAG ) s->has_srid = RT_TRUE;
-    RTDEBUGF(4, "Extended type: has_z=%d has_m=%d has_srid=%d", s->has_z, s->has_m, s->has_srid);
+    RTDEBUGF(ctx, 4, "Extended type: has_z=%d has_m=%d has_srid=%d", s->has_z, s->has_m, s->has_srid);
   }
 
   /* Mask off the flags */
@@ -237,7 +237,7 @@ static void rttype_from_wkb_state(const RTCTX *ctx, wkb_parse_state *s, uint32_t
       break;
   }
 
-  RTDEBUGF(4,"Got rttype %s (%u)", rttype_name(ctx, s->rttype), s->rttype);
+  RTDEBUGF(ctx, 4,"Got rttype %s (%u)", rttype_name(ctx, s->rttype), s->rttype);
 
   return;
 }
@@ -249,13 +249,13 @@ static void rttype_from_wkb_state(const RTCTX *ctx, wkb_parse_state *s, uint32_t
 static char byte_from_wkb_state(const RTCTX *ctx, wkb_parse_state *s)
 {
   char char_value = 0;
-  RTDEBUG(4, "Entered function");
+  RTDEBUG(ctx, 4, "Entered function");
 
   wkb_parse_state_check(ctx, s, RTWKB_BYTE_SIZE);
-  RTDEBUG(4, "Passed state check");
+  RTDEBUG(ctx, 4, "Passed state check");
 
   char_value = s->pos[0];
-  RTDEBUGF(4, "Read byte value: %x", char_value);
+  RTDEBUGF(ctx, 4, "Read byte value: %x", char_value);
   s->pos += RTWKB_BYTE_SIZE;
 
   return char_value;
@@ -337,7 +337,7 @@ static RTPOINTARRAY* ptarray_from_wkb_state(const RTCTX *ctx, wkb_parse_state *s
   /* Calculate the size of this point array. */
   npoints = integer_from_wkb_state(ctx, s);
 
-  RTDEBUGF(4,"Pointarray has %d points", npoints);
+  RTDEBUGF(ctx, 4,"Pointarray has %d points", npoints);
 
   if( s->has_z ) ndims++;
   if( s->has_m ) ndims++;
@@ -498,7 +498,7 @@ static RTPOLY* rtpoly_from_wkb_state(const RTCTX *ctx, wkb_parse_state *s)
   int i = 0;
   RTPOLY *poly = rtpoly_construct_empty(ctx, s->srid, s->has_z, s->has_m);
 
-  RTDEBUGF(4,"Polygon has %d rings", nrings);
+  RTDEBUGF(ctx, 4,"Polygon has %d rings", nrings);
 
   /* Empty polygon? */
   if( nrings == 0 )
@@ -513,7 +513,7 @@ static RTPOLY* rtpoly_from_wkb_state(const RTCTX *ctx, wkb_parse_state *s)
     /* Check for at least four points. */
     if( s->check & RT_PARSER_CHECK_MINPOINTS && pa->npoints < 4 )
     {
-      RTDEBUGF(2, "%s must have at least four points in each ring", rttype_name(ctx, s->rttype));
+      RTDEBUGF(ctx, 2, "%s must have at least four points in each ring", rttype_name(ctx, s->rttype));
       rterror(ctx, "%s must have at least four points in each ring", rttype_name(ctx, s->rttype));
       return NULL;
     }
@@ -521,7 +521,7 @@ static RTPOLY* rtpoly_from_wkb_state(const RTCTX *ctx, wkb_parse_state *s)
     /* Check that first and last points are the same. */
     if( s->check & RT_PARSER_CHECK_CLOSURE && ! ptarray_is_closed_2d(ctx, pa) )
     {
-      RTDEBUGF(2, "%s must have closed rings", rttype_name(ctx, s->rttype));
+      RTDEBUGF(ctx, 2, "%s must have closed rings", rttype_name(ctx, s->rttype));
       rterror(ctx, "%s must have closed rings", rttype_name(ctx, s->rttype));
       return NULL;
     }
@@ -529,7 +529,7 @@ static RTPOLY* rtpoly_from_wkb_state(const RTCTX *ctx, wkb_parse_state *s)
     /* Add ring to polygon */
     if ( rtpoly_add_ring(ctx, poly, pa) == RT_FAILURE )
     {
-      RTDEBUG(2, "Unable to add ring to polygon");
+      RTDEBUG(ctx, 2, "Unable to add ring to polygon");
       rterror(ctx, "Unable to add ring to polygon");
     }
 
@@ -569,7 +569,7 @@ static RTTRIANGLE* rttriangle_from_wkb_state(const RTCTX *ctx, wkb_parse_state *
   /* Check for at least four points. */
   if( s->check & RT_PARSER_CHECK_MINPOINTS && pa->npoints < 4 )
   {
-    RTDEBUGF(2, "%s must have at least four points", rttype_name(ctx, s->rttype));
+    RTDEBUGF(ctx, 2, "%s must have at least four points", rttype_name(ctx, s->rttype));
     rterror(ctx, "%s must have at least four points", rttype_name(ctx, s->rttype));
     return NULL;
   }
@@ -634,7 +634,7 @@ static RTCOLLECTION* rtcollection_from_wkb_state(const RTCTX *ctx, wkb_parse_sta
   RTGEOM *geom = NULL;
   int i;
 
-  RTDEBUGF(4,"Collection has %d components", ngeoms);
+  RTDEBUGF(ctx, 4,"Collection has %d components", ngeoms);
 
   /* Empty collection? */
   if ( ngeoms == 0 )
@@ -670,13 +670,13 @@ RTGEOM* rtgeom_from_wkb_state(const RTCTX *ctx, wkb_parse_state *s)
   char wkb_little_endian;
   uint32_t wkb_type;
 
-  RTDEBUG(4,"Entered function");
+  RTDEBUG(ctx, 4,"Entered function");
 
   /* Fail when handed incorrect starting byte */
   wkb_little_endian = byte_from_wkb_state(ctx, s);
   if( wkb_little_endian != 1 && wkb_little_endian != 0 )
   {
-    RTDEBUG(4,"Leaving due to bad first byte!");
+    RTDEBUG(ctx, 4,"Leaving due to bad first byte!");
     rterror(ctx, "Invalid endian flag value encountered.");
     return NULL;
   }
@@ -696,7 +696,7 @@ RTGEOM* rtgeom_from_wkb_state(const RTCTX *ctx, wkb_parse_state *s)
 
   /* Read the type number */
   wkb_type = integer_from_wkb_state(ctx, s);
-  RTDEBUGF(4,"Got RTWKB type number: 0x%X", wkb_type);
+  RTDEBUGF(ctx, 4,"Got RTWKB type number: 0x%X", wkb_type);
   rttype_from_wkb_state(ctx, s, wkb_type);
 
   /* Read the SRID, if necessary */
@@ -704,7 +704,7 @@ RTGEOM* rtgeom_from_wkb_state(const RTCTX *ctx, wkb_parse_state *s)
   {
     s->srid = clamp_srid(ctx, integer_from_wkb_state(ctx, s));
     /* TODO: warn on explicit UNKNOWN srid ? */
-    RTDEBUGF(4,"Got SRID: %u", s->srid);
+    RTDEBUGF(ctx, 4,"Got SRID: %u", s->srid);
   }
 
   /* Do the right thing */
diff --git a/src/rtline.c b/src/rtline.c
index fb7bf1d..115a541 100644
--- a/src/rtline.c
+++ b/src/rtline.c
@@ -18,7 +18,7 @@
  *
  **********************************************************************
  *
- * Copyright (C) 2012 Sandro Santilli <strk at keybit.net>
+ * Copyright (C) 2012 Sandro Santilli <strk at kbt.io>
  * Copyright (C) 2001-2006 Refractions Research Inc.
  *
  **********************************************************************/
@@ -45,14 +45,14 @@ rtline_construct(const RTCTX *ctx, int srid, RTGBOX *bbox, RTPOINTARRAY *points)
   RTLINE *result;
   result = (RTLINE*) rtalloc(ctx, sizeof(RTLINE));
 
-  RTDEBUG(2, "rtline_construct called.");
+  RTDEBUG(ctx, 2, "rtline_construct called.");
 
   result->type = RTLINETYPE;
 
   result->flags = points->flags;
   RTFLAGS_SET_BBOX(result->flags, bbox?1:0);
 
-  RTDEBUGF(3, "rtline_construct type=%d", result->type);
+  RTDEBUGF(ctx, 3, "rtline_construct type=%d", result->type);
 
   result->srid = srid;
   result->points = points;
@@ -104,7 +104,7 @@ rtline_clone(const RTCTX *ctx, const RTLINE *g)
 {
   RTLINE *ret = rtalloc(ctx, sizeof(RTLINE));
 
-  RTDEBUGF(2, "rtline_clone called with %p", g);
+  RTDEBUGF(ctx, 2, "rtline_clone called with %p", g);
 
   memcpy(ret, g, sizeof(RTLINE));
 
@@ -120,7 +120,7 @@ rtline_clone_deep(const RTCTX *ctx, const RTLINE *g)
 {
   RTLINE *ret = rtalloc(ctx, sizeof(RTLINE));
 
-  RTDEBUGF(2, "rtline_clone_deep called with %p", g);
+  RTDEBUGF(ctx, 2, "rtline_clone_deep called with %p", g);
   memcpy(ret, g, sizeof(RTLINE));
 
   if ( g->bbox ) ret->bbox = gbox_copy(ctx, g->bbox);
@@ -296,7 +296,7 @@ rtline_from_rtmpoint(const RTCTX *ctx, int srid, const RTMPOINT *mpoint)
     ptarray_set_point4d(ctx, pa, i, &pt);
   }
 
-  RTDEBUGF(3, "rtline_from_rtmpoint: constructed pointarray for %d points", mpoint->ngeoms);
+  RTDEBUGF(ctx, 3, "rtline_from_rtmpoint: constructed pointarray for %d points", mpoint->ngeoms);
 
   return rtline_construct(ctx, srid, NULL, pa);
 }
@@ -442,7 +442,7 @@ rtline_remove_repeated_points(const RTCTX *ctx, const RTLINE *rtline, double tol
 {
   RTPOINTARRAY* npts = ptarray_remove_repeated_points_minpoints(ctx, rtline->points, tolerance, 2);
 
-  RTDEBUGF(3, "%s: npts %p", __func__, npts);
+  RTDEBUGF(ctx, 3, "%s: npts %p", __func__, npts);
 
   return (RTGEOM*)rtline_construct(ctx, rtline->srid,
                                    rtline->bbox ? gbox_copy(ctx, rtline->bbox) : 0,
@@ -529,7 +529,7 @@ RTLINE* rtline_simplify(const RTCTX *ctx, const RTLINE *iline, double dist, int
   RTLINE *oline;
   RTPOINTARRAY *pa;
 
-  RTDEBUG(2, "function called");
+  RTDEBUG(ctx, 2, "function called");
 
   /* Skip empty case */
   if( rtline_is_empty(ctx, iline) )
diff --git a/src/rtlinearreferencing.c b/src/rtlinearreferencing.c
index e4a211e..4e45647 100644
--- a/src/rtlinearreferencing.c
+++ b/src/rtlinearreferencing.c
@@ -18,7 +18,7 @@
  *
  **********************************************************************
  *
- * Copyright (C) 2015 Sandro Santilli <strk at keybit.net>
+ * Copyright (C) 2015 Sandro Santilli <strk at kbt.io>
  * Copyright (C) 2011 Paul Ramsey
  *
  **********************************************************************/
@@ -295,7 +295,7 @@ void rtpoint_set_ordinate(const RTCTX *ctx, RTPOINT4D *p, char ordinate, double
     return;
   }
 
-  RTDEBUGF(4, "    setting ordinate %c to %g", ordinate, value);
+  RTDEBUGF(ctx, 4, "    setting ordinate %c to %g", ordinate, value);
 
   switch ( ordinate )
   {
@@ -351,7 +351,7 @@ int point_interpolate(const RTCTX *ctx, const RTPOINT4D *p1, const RTPOINT4D *p2
     p2_value = rtpoint_get_ordinate(ctx, p2, dims[i]);
     newordinate = p1_value + proportion * (p2_value - p1_value);
     rtpoint_set_ordinate(ctx, p, dims[i], newordinate);
-    RTDEBUGF(4, "   clip ordinate(%c) p1_value(%g) p2_value(%g) proportion(%g) newordinate(%g) ", dims[i], p1_value, p2_value, proportion, newordinate );
+    RTDEBUGF(ctx, 4, "   clip ordinate(%c) p1_value(%g) p2_value(%g) proportion(%g) newordinate(%g) ", dims[i], p1_value, p2_value, proportion, newordinate );
   }
 
   return 1;
@@ -582,8 +582,8 @@ rtline_clip_to_ordinate_range(const RTCTX *ctx, const RTLINE *line, char ordinat
     to = t;
   }
 
-  RTDEBUGF(4, "from = %g, to = %g, ordinate = %c", from, to, ordinate);
-  RTDEBUGF(4, "%s", rtgeom_to_ewkt(ctx, (RTGEOM*)line));
+  RTDEBUGF(ctx, 4, "from = %g, to = %g, ordinate = %c", from, to, ordinate);
+  RTDEBUGF(ctx, 4, "%s", rtgeom_to_ewkt(ctx, (RTGEOM*)line));
 
   /* Asking for an ordinate we don't have. Error. */
   if ( (ordinate == 'Z' && ! hasz) || (ordinate == 'M' && ! hasm) )
@@ -605,8 +605,8 @@ rtline_clip_to_ordinate_range(const RTCTX *ctx, const RTLINE *line, char ordinat
 
   for ( i = 0; i < pa_in->npoints; i++ )
   {
-    RTDEBUGF(4, "Point #%d", i);
-    RTDEBUGF(4, "added_last_point %d", added_last_point);
+    RTDEBUGF(ctx, 4, "Point #%d", i);
+    RTDEBUGF(ctx, 4, "added_last_point %d", added_last_point);
     if ( i > 0 )
     {
       *q = *p;
@@ -614,17 +614,17 @@ rtline_clip_to_ordinate_range(const RTCTX *ctx, const RTLINE *line, char ordinat
     }
     rt_getPoint4d_p(ctx, pa_in, i, p);
     ordinate_value_p = rtpoint_get_ordinate(ctx, p, ordinate);
-    RTDEBUGF(4, " ordinate_value_p %g (current)", ordinate_value_p);
-    RTDEBUGF(4, " ordinate_value_q %g (previous)", ordinate_value_q);
+    RTDEBUGF(ctx, 4, " ordinate_value_p %g (current)", ordinate_value_p);
+    RTDEBUGF(ctx, 4, " ordinate_value_q %g (previous)", ordinate_value_q);
 
     /* Is this point inside the ordinate range? Yes. */
     if ( ordinate_value_p >= from && ordinate_value_p <= to )
     {
-      RTDEBUGF(4, " inside ordinate range (%g, %g)", from, to);
+      RTDEBUGF(ctx, 4, " inside ordinate range (%g, %g)", from, to);
 
       if ( ! added_last_point )
       {
-        RTDEBUG(4,"  new ptarray required");
+        RTDEBUG(ctx, 4,"  new ptarray required");
         /* We didn't add the previous point, so this is a new segment.
         *  Make a new point array. */
         dp = ptarray_construct_empty(ctx, hasz, hasm, 32);
@@ -642,7 +642,7 @@ rtline_clip_to_ordinate_range(const RTCTX *ctx, const RTLINE *line, char ordinat
           (ordinate_value_q > to) ? (interpolation_value = to) : (interpolation_value = from);
           point_interpolate(ctx, q, p, r, hasz, hasm, ordinate, interpolation_value);
           ptarray_append_point(ctx, dp, r, RT_FALSE);
-          RTDEBUGF(4, "[0] interpolating between (%g, %g) with interpolation point (%g)", ordinate_value_q, ordinate_value_p, interpolation_value);
+          RTDEBUGF(ctx, 4, "[0] interpolating between (%g, %g) with interpolation point (%g)", ordinate_value_q, ordinate_value_p, interpolation_value);
         }
       }
       /* Add the current vertex to the point array. */
@@ -659,7 +659,7 @@ rtline_clip_to_ordinate_range(const RTCTX *ctx, const RTLINE *line, char ordinat
     /* Is this point inside the ordinate range? No. */
     else
     {
-      RTDEBUGF(4, "  added_last_point (%d)", added_last_point);
+      RTDEBUGF(ctx, 4, "  added_last_point (%d)", added_last_point);
       if ( added_last_point == 1 )
       {
         /* We're transiting out of the range, so add an interpolated point
@@ -668,7 +668,7 @@ rtline_clip_to_ordinate_range(const RTCTX *ctx, const RTLINE *line, char ordinat
         (ordinate_value_p > to) ? (interpolation_value = to) : (interpolation_value = from);
         point_interpolate(ctx, q, p, r, hasz, hasm, ordinate, interpolation_value);
         ptarray_append_point(ctx, dp, r, RT_FALSE);
-        RTDEBUGF(4, " [1] interpolating between (%g, %g) with interpolation point (%g)", ordinate_value_q, ordinate_value_p, interpolation_value);
+        RTDEBUGF(ctx, 4, " [1] interpolating between (%g, %g) with interpolation point (%g)", ordinate_value_q, ordinate_value_p, interpolation_value);
       }
       else if ( added_last_point == 2 )
       {
@@ -683,7 +683,7 @@ rtline_clip_to_ordinate_range(const RTCTX *ctx, const RTLINE *line, char ordinat
           (ordinate_value_p > to) ? (interpolation_value = to) : (interpolation_value = from);
           point_interpolate(ctx, q, p, r, hasz, hasm, ordinate, interpolation_value);
           ptarray_append_point(ctx, dp, r, RT_FALSE);
-          RTDEBUGF(4, " [2] interpolating between (%g, %g) with interpolation point (%g)", ordinate_value_q, ordinate_value_p, interpolation_value);
+          RTDEBUGF(ctx, 4, " [2] interpolating between (%g, %g) with interpolation point (%g)", ordinate_value_q, ordinate_value_p, interpolation_value);
         }
       }
       else if ( i && ordinate_value_q < from && ordinate_value_p > to )
@@ -713,7 +713,7 @@ rtline_clip_to_ordinate_range(const RTCTX *ctx, const RTLINE *line, char ordinat
       /* We have an extant point-array, save it out to a multi-line. */
       if ( dp )
       {
-        RTDEBUG(4, "saving pointarray to multi-line (1)");
+        RTDEBUG(ctx, 4, "saving pointarray to multi-line (1)");
 
         /* Only one point, so we have to make an rtpoint to hold this
         *  and set the overall output type to a generic collection. */
@@ -741,9 +741,9 @@ rtline_clip_to_ordinate_range(const RTCTX *ctx, const RTLINE *line, char ordinat
   /* Still some points left to be saved out. */
   if ( dp && dp->npoints > 0 )
   {
-    RTDEBUG(4, "saving pointarray to multi-line (2)");
-    RTDEBUGF(4, "dp->npoints == %d", dp->npoints);
-    RTDEBUGF(4, "rtgeom_out->ngeoms == %d", rtgeom_out->ngeoms);
+    RTDEBUG(ctx, 4, "saving pointarray to multi-line (2)");
+    RTDEBUGF(ctx, 4, "dp->npoints == %d", dp->npoints);
+    RTDEBUGF(ctx, 4, "rtgeom_out->ngeoms == %d", rtgeom_out->ngeoms);
 
     if ( dp->npoints == 1 )
     {
@@ -1123,7 +1123,7 @@ rtgeom_tcpa(const RTCTX *ctx, const RTGEOM *g1, const RTGEOM *g2, double *mindis
 
   if ( tmax < tmin )
   {
-    RTDEBUG(1, "Inputs never exist at the same time");
+    RTDEBUG(ctx, 1, "Inputs never exist at the same time");
     return -2;
   }
 
@@ -1152,7 +1152,7 @@ rtgeom_tcpa(const RTCTX *ctx, const RTGEOM *g1, const RTGEOM *g2, double *mindis
       /* there's a single time, must be that one... */
       double t0 = mvals[0];
       RTPOINT4D p0, p1;
-      RTDEBUGF(1, "Inputs only exist both at a single time (%g)", t0);
+      RTDEBUGF(ctx, 1, "Inputs only exist both at a single time (%g)", t0);
       if ( mindist )
       {
         if ( -1 == ptarray_locate_along_linear(ctx, l1->points, t0, &p0, 0) )
@@ -1291,7 +1291,7 @@ rtgeom_cpa_within(const RTCTX *ctx, const RTGEOM *g1, const RTGEOM *g2, double m
 
   if ( tmax < tmin )
   {
-    RTDEBUG(1, "Inputs never exist at the same time");
+    RTDEBUG(ctx, 1, "Inputs never exist at the same time");
     return RT_FALSE;
   }
 
@@ -1319,7 +1319,7 @@ rtgeom_cpa_within(const RTCTX *ctx, const RTGEOM *g1, const RTGEOM *g2, double m
     /* there's a single time, must be that one... */
     double t0 = mvals[0];
     RTPOINT4D p0, p1;
-    RTDEBUGF(1, "Inputs only exist both at a single time (%g)", t0);
+    RTDEBUGF(ctx, 1, "Inputs only exist both at a single time (%g)", t0);
     if ( -1 == ptarray_locate_along_linear(ctx, l1->points, t0, &p0, 0) )
     {
       rtnotice(ctx, "Could not find point with M=%g on first geom", t0);
@@ -1385,7 +1385,7 @@ rtgeom_cpa_within(const RTCTX *ctx, const RTGEOM *g1, const RTGEOM *g2, double m
             ( q0.z - p0.z ) * ( q0.z - p0.z );
     if ( dist2 <= maxdist2 )
     {
-      RTDEBUGF(1, "Within distance %g at time %g, breaking", sqrt(dist2), t);
+      RTDEBUGF(ctx, 1, "Within distance %g at time %g, breaking", sqrt(dist2), t);
       within = RT_TRUE;
       break;
     }
diff --git a/src/rtmpoint.c b/src/rtmpoint.c
index cb6997f..47dbaeb 100644
--- a/src/rtmpoint.c
+++ b/src/rtmpoint.c
@@ -45,7 +45,7 @@ rtmpoint_construct_empty(const RTCTX *ctx, int srid, char hasz, char hasm)
 
 RTMPOINT* rtmpoint_add_rtpoint(const RTCTX *ctx, RTMPOINT *mobj, const RTPOINT *obj)
 {
-  RTDEBUG(4, "Called");
+  RTDEBUG(ctx, 4, "Called");
   return (RTMPOINT*)rtcollection_add_rtgeom(ctx, (RTCOLLECTION*)mobj, (RTGEOM*)obj);
 }
 
diff --git a/src/rtout_gml.c b/src/rtout_gml.c
index 4a8357b..40728af 100644
--- a/src/rtout_gml.c
+++ b/src/rtout_gml.c
@@ -18,7 +18,7 @@
  *
  **********************************************************************
  *
- * Copyright 2011 Sandro Santilli <strk at keybit.net>
+ * Copyright 2011 Sandro Santilli <strk at kbt.io>
  * Copyright 2010-2012 Oslandia
  * Copyright 2001-2003 Refractions Research Inc.
  *
diff --git a/src/rtout_twkb.c b/src/rtout_twkb.c
index 6532e02..da48753 100644
--- a/src/rtout_twkb.c
+++ b/src/rtout_twkb.c
@@ -33,7 +33,7 @@ static uint8_t rtgeom_twkb_type(const RTCTX *ctx, const RTGEOM *geom)
 {
   uint8_t twkb_type = 0;
 
-  RTDEBUGF(2, "Entered  rtgeom_twkb_type",0);
+  RTDEBUGF(ctx, 2, "Entered  rtgeom_twkb_type",0);
 
   switch ( geom->type )
   {
@@ -75,7 +75,7 @@ static size_t sizeof_bbox(const RTCTX *ctx, TWKB_STATE *ts, int ndims)
   int i;
   uint8_t buf[16];
   size_t size = 0;
-  RTDEBUGF(2, "Entered %s", __func__);
+  RTDEBUGF(ctx, 2, "Entered %s", __func__);
   for ( i = 0; i < ndims; i++ )
   {
     size += varint_s64_encode_buf(ctx, ts->bbox_min[i], buf);
@@ -90,7 +90,7 @@ static size_t sizeof_bbox(const RTCTX *ctx, TWKB_STATE *ts, int ndims)
 static void write_bbox(const RTCTX *ctx, TWKB_STATE *ts, int ndims)
 {
   int i;
-  RTDEBUGF(2, "Entered %s", __func__);
+  RTDEBUGF(ctx, 2, "Entered %s", __func__);
   for ( i = 0; i < ndims; i++ )
   {
     bytebuffer_append_varint(ctx, ts->header_buf, ts->bbox_min[i]);
@@ -114,12 +114,12 @@ static int ptarray_to_twkb_buf(const RTCTX *ctx, const RTPOINTARRAY *pa, TWKB_GL
   int npoints = 0;
   size_t npoints_offset = 0;
 
-  RTDEBUGF(2, "Entered %s", __func__);
+  RTDEBUGF(ctx, 2, "Entered %s", __func__);
 
   /* Dispense with the empty case right away */
   if ( pa->npoints == 0 && register_npoints )
   {
-    RTDEBUGF(4, "Register npoints:%d", pa->npoints);
+    RTDEBUGF(ctx, 4, "Register npoints:%d", pa->npoints);
     bytebuffer_append_uvarint(ctx, ts->geom_buf, pa->npoints);
     return 0;
   }
@@ -167,7 +167,7 @@ static int ptarray_to_twkb_buf(const RTCTX *ctx, const RTPOINTARRAY *pa, TWKB_GL
       /* last accumulated point. This is important to not build up an */
       /* accumulated error when rounding the coordinates */
       nextdelta[j] = (int64_t) llround(globals->factor[j] * dbl_ptr[j]) - ts->accum_rels[j];
-      RTDEBUGF(4, "deltavalue: %d, ", nextdelta[j]);
+      RTDEBUGF(ctx, 4, "deltavalue: %d, ", nextdelta[j]);
       diff += llabs(nextdelta[j]);
     }
 
@@ -231,7 +231,7 @@ static int ptarray_to_twkb_buf(const RTCTX *ctx, const RTPOINTARRAY *pa, TWKB_GL
 
 static int rtpoint_to_twkb_buf(const RTCTX *ctx, const RTPOINT *pt, TWKB_GLOBALS *globals, TWKB_STATE *ts)
 {
-  RTDEBUGF(2, "Entered %s", __func__);
+  RTDEBUGF(ctx, 2, "Entered %s", __func__);
 
   /* Set the coordinates (don't write npoints) */
   ptarray_to_twkb_buf(ctx, pt->point, globals, ts, 0, 1);
@@ -244,7 +244,7 @@ static int rtpoint_to_twkb_buf(const RTCTX *ctx, const RTPOINT *pt, TWKB_GLOBALS
 
 static int rtline_to_twkb_buf(const RTCTX *ctx, const RTLINE *line, TWKB_GLOBALS *globals, TWKB_STATE *ts)
 {
-  RTDEBUGF(2, "Entered %s", __func__);
+  RTDEBUGF(ctx, 2, "Entered %s", __func__);
 
   /* Set the coordinates (do write npoints) */
   ptarray_to_twkb_buf(ctx, line->points, globals, ts, 1, 2);
@@ -282,8 +282,8 @@ static int rtmulti_to_twkb_buf(const RTCTX *ctx, const RTCOLLECTION *col, TWKB_G
   int i;
   int nempty = 0;
 
-  RTDEBUGF(2, "Entered %s", __func__);
-  RTDEBUGF(4, "Number of geometries in multi is %d", col->ngeoms);
+  RTDEBUGF(ctx, 2, "Entered %s", __func__);
+  RTDEBUGF(ctx, 4, "Number of geometries in multi is %d", col->ngeoms);
 
   /* Deal with special case for MULTIPOINT: skip any empty points */
   if ( col->type == RTMULTIPOINTTYPE )
@@ -331,8 +331,8 @@ static int rtcollection_to_twkb_buf(const RTCTX *ctx, const RTCOLLECTION *col, T
 {
   int i;
 
-  RTDEBUGF(2, "Entered %s", __func__);
-  RTDEBUGF(4, "Number of geometries in collection is %d", col->ngeoms);
+  RTDEBUGF(ctx, 2, "Entered %s", __func__);
+  RTDEBUGF(ctx, 4, "Number of geometries in collection is %d", col->ngeoms);
 
   /* Set the number of geometries */
   bytebuffer_append_uvarint(ctx, ts->geom_buf, (uint64_t) col->ngeoms);
@@ -362,24 +362,24 @@ static int rtcollection_to_twkb_buf(const RTCTX *ctx, const RTCOLLECTION *col, T
 
 static int rtgeom_to_twkb_buf(const RTCTX *ctx, const RTGEOM *geom, TWKB_GLOBALS *globals, TWKB_STATE *ts)
 {
-  RTDEBUGF(2, "Entered %s", __func__);
+  RTDEBUGF(ctx, 2, "Entered %s", __func__);
 
   switch ( geom->type )
   {
     case RTPOINTTYPE:
     {
-      RTDEBUGF(4,"Type found is Point, %d", geom->type);
+      RTDEBUGF(ctx, 4,"Type found is Point, %d", geom->type);
       return rtpoint_to_twkb_buf(ctx, (RTPOINT*) geom, globals, ts);
     }
     case RTLINETYPE:
     {
-      RTDEBUGF(4,"Type found is Linestring, %d", geom->type);
+      RTDEBUGF(ctx, 4,"Type found is Linestring, %d", geom->type);
       return rtline_to_twkb_buf(ctx, (RTLINE*) geom, globals, ts);
     }
     /* Polygon has 'nrings' and 'rings' elements */
     case RTPOLYGONTYPE:
     {
-      RTDEBUGF(4,"Type found is Polygon, %d", geom->type);
+      RTDEBUGF(ctx, 4,"Type found is Polygon, %d", geom->type);
       return rtpoly_to_twkb_buf(ctx, (RTPOLY*)geom, globals, ts);
     }
 
@@ -388,12 +388,12 @@ static int rtgeom_to_twkb_buf(const RTCTX *ctx, const RTGEOM *geom, TWKB_GLOBALS
     case RTMULTILINETYPE:
     case RTMULTIPOLYGONTYPE:
     {
-      RTDEBUGF(4,"Type found is Multi, %d", geom->type);
+      RTDEBUGF(ctx, 4,"Type found is Multi, %d", geom->type);
       return rtmulti_to_twkb_buf(ctx, (RTCOLLECTION*)geom, globals, ts);
     }
     case RTCOLLECTIONTYPE:
     {
-      RTDEBUGF(4,"Type found is collection, %d", geom->type);
+      RTDEBUGF(ctx, 4,"Type found is collection, %d", geom->type);
       return rtcollection_to_twkb_buf(ctx, (RTCOLLECTION*) geom, globals, ts);
     }
     /* Unknown type! */
@@ -513,7 +513,7 @@ static int rtgeom_write_to_buffer(const RTCTX *ctx, const RTGEOM *geom, TWKB_GLO
   /*and put the result to the parent (the collection)*/
   if( (globals->variant & TWKB_BBOX) && parent_state->header_buf )
   {
-    RTDEBUG(4,"Merge bboxes");
+    RTDEBUG(ctx, 4,"Merge bboxes");
     for ( i = 0; i < ndims; i++ )
     {
       if(child_state.bbox_min[i]<parent_state->bbox_min[i])
@@ -527,7 +527,7 @@ static int rtgeom_write_to_buffer(const RTCTX *ctx, const RTGEOM *geom, TWKB_GLO
   bbox_size = 0;
   if( globals->variant & TWKB_BBOX )
   {
-    RTDEBUG(4,"We want boxes and will calculate required size");
+    RTDEBUG(ctx, 4,"We want boxes and will calculate required size");
     bbox_size = sizeof_bbox(ctx, &child_state, ndims);
   }
 
@@ -562,8 +562,8 @@ rtgeom_to_twkb_with_idlist(const RTCTX *ctx, const RTGEOM *geom, int64_t *idlist
                int8_t precision_xy, int8_t precision_z, int8_t precision_m,
                size_t *twkb_size)
 {
-  RTDEBUGF(2, "Entered %s", __func__);
-  RTDEBUGF(2, "variant value %x", variant);
+  RTDEBUGF(ctx, 2, "Entered %s", __func__);
+  RTDEBUGF(ctx, 2, "variant value %x", variant);
 
   TWKB_GLOBALS tg;
   TWKB_STATE ts;
@@ -586,7 +586,7 @@ rtgeom_to_twkb_with_idlist(const RTCTX *ctx, const RTGEOM *geom, int64_t *idlist
 
   if ( ! geom )
   {
-    RTDEBUG(4,"Cannot convert NULL into TWKB.");
+    RTDEBUG(ctx, 4,"Cannot convert NULL into TWKB.");
     rterror(ctx, "Cannot convert NULL into TWKB");
     return NULL;
   }
diff --git a/src/rtout_wkb.c b/src/rtout_wkb.c
index b8c3370..34f8c82 100644
--- a/src/rtout_wkb.c
+++ b/src/rtout_wkb.c
@@ -203,7 +203,7 @@ static uint8_t* integer_to_wkb_buf(const RTCTX *ctx, const int ival, uint8_t *bu
   {
     rterror(ctx, "Machine int size is not %d bytes!", RTWKB_INT_SIZE);
   }
-  RTDEBUGF(4, "Writing value '%u'", ival);
+  RTDEBUGF(ctx, 4, "Writing value '%u'", ival);
   if ( variant & RTWKB_HEX )
   {
     int swap = wkb_swap_bytes(ctx, variant);
@@ -397,16 +397,16 @@ static uint8_t* ptarray_to_wkb_buf(const RTCTX *ctx, const RTPOINTARRAY *pa, uin
   {
     for ( i = 0; i < pa->npoints; i++ )
     {
-      RTDEBUGF(4, "Writing point #%d", i);
+      RTDEBUGF(ctx, 4, "Writing point #%d", i);
       dbl_ptr = (double*)rt_getPoint_internal(ctx, pa, i);
       for ( j = 0; j < dims; j++ )
       {
-        RTDEBUGF(4, "Writing dimension #%d (buf = %p)", j, buf);
+        RTDEBUGF(ctx, 4, "Writing dimension #%d (buf = %p)", j, buf);
         buf = double_to_wkb_buf(ctx, dbl_ptr[j], buf, variant);
       }
     }
   }
-  RTDEBUGF(4, "Done (buf = %p)", buf);
+  RTDEBUGF(ctx, 4, "Done (buf = %p)", buf);
   return buf;
 }
 
@@ -438,21 +438,21 @@ static uint8_t* rtpoint_to_wkb_buf(const RTCTX *ctx, const RTPOINT *pt, uint8_t
     return empty_to_wkb_buf(ctx, (RTGEOM*)pt, buf, variant);
 
   /* Set the endian flag */
-  RTDEBUGF(4, "Entering function, buf = %p", buf);
+  RTDEBUGF(ctx, 4, "Entering function, buf = %p", buf);
   buf = endian_to_wkb_buf(ctx, buf, variant);
-  RTDEBUGF(4, "Endian set, buf = %p", buf);
+  RTDEBUGF(ctx, 4, "Endian set, buf = %p", buf);
   /* Set the geometry type */
   buf = integer_to_wkb_buf(ctx, rtgeom_wkb_type(ctx, (RTGEOM*)pt, variant), buf, variant);
-  RTDEBUGF(4, "Type set, buf = %p", buf);
+  RTDEBUGF(ctx, 4, "Type set, buf = %p", buf);
   /* Set the optional SRID for extended variant */
   if ( rtgeom_wkb_needs_srid(ctx, (RTGEOM*)pt, variant) )
   {
     buf = integer_to_wkb_buf(ctx, pt->srid, buf, variant);
-    RTDEBUGF(4, "SRID set, buf = %p", buf);
+    RTDEBUGF(ctx, 4, "SRID set, buf = %p", buf);
   }
   /* Set the coordinates */
   buf = ptarray_to_wkb_buf(ctx, pt->point, buf, variant | RTWKB_NO_NPOINTS);
-  RTDEBUGF(4, "Pointarray set, buf = %p", buf);
+  RTDEBUGF(ctx, 4, "Pointarray set, buf = %p", buf);
   return buf;
 }
 
@@ -773,18 +773,18 @@ uint8_t* rtgeom_to_wkb(const RTCTX *ctx, const RTGEOM *geom, uint8_t variant, si
 
   if ( geom == NULL )
   {
-    RTDEBUG(4,"Cannot convert NULL into RTWKB.");
+    RTDEBUG(ctx, 4,"Cannot convert NULL into RTWKB.");
     rterror(ctx, "Cannot convert NULL into RTWKB.");
     return NULL;
   }
 
   /* Calculate the required size of the output buffer */
   buf_size = rtgeom_to_wkb_size(ctx, geom, variant);
-  RTDEBUGF(4, "RTWKB output size: %d", buf_size);
+  RTDEBUGF(ctx, 4, "RTWKB output size: %d", buf_size);
 
   if ( buf_size == 0 )
   {
-    RTDEBUG(4,"Error calculating output RTWKB buffer size.");
+    RTDEBUG(ctx, 4,"Error calculating output RTWKB buffer size.");
     rterror(ctx, "Error calculating output RTWKB buffer size.");
     return NULL;
   }
@@ -793,7 +793,7 @@ uint8_t* rtgeom_to_wkb(const RTCTX *ctx, const RTGEOM *geom, uint8_t variant, si
   if ( variant & RTWKB_HEX )
   {
     buf_size = 2 * buf_size + 1;
-    RTDEBUGF(4, "Hex RTWKB output size: %d", buf_size);
+    RTDEBUGF(ctx, 4, "Hex RTWKB output size: %d", buf_size);
   }
 
   /* If neither or both variants are specified, choose the native order */
@@ -811,7 +811,7 @@ uint8_t* rtgeom_to_wkb(const RTCTX *ctx, const RTGEOM *geom, uint8_t variant, si
 
   if ( buf == NULL )
   {
-    RTDEBUGF(4,"Unable to allocate %d bytes for RTWKB output buffer.", buf_size);
+    RTDEBUGF(ctx, 4,"Unable to allocate %d bytes for RTWKB output buffer.", buf_size);
     rterror(ctx, "Unable to allocate %d bytes for RTWKB output buffer.", buf_size);
     return NULL;
   }
@@ -829,12 +829,12 @@ uint8_t* rtgeom_to_wkb(const RTCTX *ctx, const RTGEOM *geom, uint8_t variant, si
     buf++;
   }
 
-  RTDEBUGF(4,"buf (%p) - wkb_out (%p) = %d", buf, wkb_out, buf - wkb_out);
+  RTDEBUGF(ctx, 4,"buf (%p) - wkb_out (%p) = %d", buf, wkb_out, buf - wkb_out);
 
   /* The buffer pointer should now land at the end of the allocated buffer space. Let's check. */
   if ( buf_size != (buf - wkb_out) )
   {
-    RTDEBUG(4,"Output RTWKB is not the same size as the allocated buffer.");
+    RTDEBUG(ctx, 4,"Output RTWKB is not the same size as the allocated buffer.");
     rterror(ctx, "Output RTWKB is not the same size as the allocated buffer.");
     rtfree(ctx, wkb_out);
     return NULL;
diff --git a/src/rtout_wkt.c b/src/rtout_wkt.c
index 65074f8..014085a 100644
--- a/src/rtout_wkt.c
+++ b/src/rtout_wkt.c
@@ -600,7 +600,7 @@ static void rtpsurface_to_wkt_sb(const RTCTX *ctx, const RTPSURFACE *psurf, stri
 */
 static void rtgeom_to_wkt_sb(const RTCTX *ctx, const RTGEOM *geom, stringbuffer_t *sb, int precision, uint8_t variant)
 {
-  RTDEBUGF(4, "rtgeom_to_wkt_sb: type %s, hasz %d, hasm %d",
+  RTDEBUGF(ctx, 4, "rtgeom_to_wkt_sb: type %s, hasz %d, hasm %d",
     rttype_name(ctx, geom->type), (geom->type),
     RTFLAGS_GET_Z(geom->flags)?1:0, RTFLAGS_GET_M(geom->flags)?1:0);
 
diff --git a/src/rtpoint.c b/src/rtpoint.c
index 06e9ff1..8291fd1 100644
--- a/src/rtpoint.c
+++ b/src/rtpoint.c
@@ -223,7 +223,7 @@ rtpoint_clone(const RTCTX *ctx, const RTPOINT *g)
 {
   RTPOINT *ret = rtalloc(ctx, sizeof(RTPOINT));
 
-  RTDEBUG(2, "rtpoint_clone called");
+  RTDEBUG(ctx, 2, "rtpoint_clone called");
 
   memcpy(ret, g, sizeof(RTPOINT));
 
diff --git a/src/rtpoly.c b/src/rtpoly.c
index 643113f..e4924e1 100644
--- a/src/rtpoly.c
+++ b/src/rtpoly.c
@@ -18,7 +18,7 @@
  *
  **********************************************************************
  *
- * Copyright (C) 2012 Sandro Santilli <strk at keybit.net>
+ * Copyright (C) 2012 Sandro Santilli <strk at kbt.io>
  * Copyright (C) 2001-2006 Refractions Research Inc.
  *
  **********************************************************************/
@@ -367,7 +367,7 @@ RTPOLY* rtpoly_simplify(const RTCTX *ctx, const RTPOLY *ipoly, double dist, int
   int i;
   RTPOLY *opoly = rtpoly_construct_empty(ctx, ipoly->srid, RTFLAGS_GET_Z(ipoly->flags), RTFLAGS_GET_M(ipoly->flags));
 
-  RTDEBUGF(2, "%s: simplifying polygon with %d rings", __func__, ipoly->nrings);
+  RTDEBUGF(ctx, 2, "%s: simplifying polygon with %d rings", __func__, ipoly->nrings);
 
   if ( rtpoly_is_empty(ctx, ipoly) )
   {
@@ -387,12 +387,12 @@ RTPOLY* rtpoly_simplify(const RTCTX *ctx, const RTPOLY *ipoly, double dist, int
 
     opts = ptarray_simplify(ctx, ipoly->rings[i], dist, minvertices);
 
-    RTDEBUGF(3, "ring%d simplified from %d to %d points", i, ipoly->rings[i]->npoints, opts->npoints);
+    RTDEBUGF(ctx, 3, "ring%d simplified from %d to %d points", i, ipoly->rings[i]->npoints, opts->npoints);
 
     /* Less points than are needed to form a closed ring, we can't use this */
     if ( opts->npoints < 4 )
     {
-      RTDEBUGF(3, "ring%d skipped (% pts)", i, opts->npoints);
+      RTDEBUGF(ctx, 3, "ring%d skipped (% pts)", i, opts->npoints);
       ptarray_free(ctx, opts);
       if ( i ) continue;
       else break; /* Don't scan holes if shell is collapsed */
@@ -406,7 +406,7 @@ RTPOLY* rtpoly_simplify(const RTCTX *ctx, const RTPOLY *ipoly, double dist, int
     }
   }
 
-  RTDEBUGF(3, "simplified polygon with %d rings", ipoly->nrings);
+  RTDEBUGF(ctx, 3, "simplified polygon with %d rings", ipoly->nrings);
   opoly->type = ipoly->type;
 
   if( rtpoly_is_empty(ctx, opoly) )
@@ -460,7 +460,7 @@ rtpoly_perimeter(const RTCTX *ctx, const RTPOLY *poly)
   double result=0.0;
   int i;
 
-  RTDEBUGF(2, "in rtgeom_polygon_perimeter (%d rings)", poly->nrings);
+  RTDEBUGF(ctx, 2, "in rtgeom_polygon_perimeter (%d rings)", poly->nrings);
 
   for (i=0; i<poly->nrings; i++)
     result += ptarray_length(ctx, poly->rings[i]);
@@ -478,7 +478,7 @@ rtpoly_perimeter_2d(const RTCTX *ctx, const RTPOLY *poly)
   double result=0.0;
   int i;
 
-  RTDEBUGF(2, "in rtgeom_polygon_perimeter (%d rings)", poly->nrings);
+  RTDEBUGF(ctx, 2, "in rtgeom_polygon_perimeter (%d rings)", poly->nrings);
 
   for (i=0; i<poly->nrings; i++)
     result += ptarray_length_2d(ctx, poly->rings[i]);
@@ -555,7 +555,7 @@ RTPOLY* rtpoly_grid(const RTCTX *ctx, const RTPOLY *poly, const gridspec *grid)
   double minvisiblearea = grid->xsize * grid->ysize;
 #endif
 
-  RTDEBUGF(3, "rtpoly_grid: applying grid to polygon with %d rings", poly->nrings);
+  RTDEBUGF(ctx, 3, "rtpoly_grid: applying grid to polygon with %d rings", poly->nrings);
 
   opoly = rtpoly_construct_empty(ctx, poly->srid, rtgeom_has_z(ctx, (RTGEOM*)poly), rtgeom_has_m(ctx, (RTGEOM*)poly));
 
@@ -571,7 +571,7 @@ RTPOLY* rtpoly_grid(const RTCTX *ctx, const RTPOLY *poly, const gridspec *grid)
     {
       ptarray_free(ctx, newring);
 
-      RTDEBUGF(3, "grid_polygon3d: ring%d skipped ( <4 pts )", ri);
+      RTDEBUGF(ctx, 3, "grid_polygon3d: ring%d skipped ( <4 pts )", ri);
 
       if ( ri ) continue;
       else break; /* this is the external ring, no need to work on holes */
@@ -584,7 +584,7 @@ RTPOLY* rtpoly_grid(const RTCTX *ctx, const RTPOLY *poly, const gridspec *grid)
     }
   }
 
-  RTDEBUGF(3, "rtpoly_grid: simplified polygon with %d rings", opoly->nrings);
+  RTDEBUGF(ctx, 3, "rtpoly_grid: simplified polygon with %d rings", opoly->nrings);
 
   if ( ! opoly->nrings )
   {
diff --git a/src/rtprint.c b/src/rtprint.c
index ca419f1..e160fe3 100644
--- a/src/rtprint.c
+++ b/src/rtprint.c
@@ -19,7 +19,7 @@
  **********************************************************************
  *
  * Copyright (C) 2010-2015 Paul Ramsey <pramsey at cleverelephant.ca>
- * Copyright (C) 2011 Sandro Santilli <strk at keybit.net>
+ * Copyright (C) 2011 Sandro Santilli <strk at kbt.io>
  *
  **********************************************************************/
 
diff --git a/src/rtspheroid.c b/src/rtspheroid.c
index 1f1fd3a..9c673fb 100644
--- a/src/rtspheroid.c
+++ b/src/rtspheroid.c
@@ -154,7 +154,7 @@ static double ptarray_area_spheroid(const RTCTX *ctx, const RTPOINTARRAY *pa, co
   {
     rt_getPoint2d_p(ctx, pa, i, &p);
     geod_polygon_addpoint(&gd, &poly, p.y, p.x);
-    RTDEBUGF(4, "geod_polygon_addpoint %d: %.12g %.12g", i, p.y, p.x);
+    RTDEBUGF(ctx, 4, "geod_polygon_addpoint %d: %.12g %.12g", i, p.y, p.x);
   }
   i = geod_polygon_compute(&gd, &poly, 0, 1, &area, 0);
   if ( i != pa->npoints - 1 )
@@ -162,7 +162,7 @@ static double ptarray_area_spheroid(const RTCTX *ctx, const RTPOINTARRAY *pa, co
     rterror(ctx, "ptarray_area_spheroid: different number of points %d vs %d",
         i, pa->npoints - 1);
   }
-  RTDEBUGF(4, "geod_polygon_compute area: %.12g", area);
+  RTDEBUGF(ctx, 4, "geod_polygon_compute area: %.12g", area);
   return fabs(area);
 }
 
@@ -466,26 +466,26 @@ static double spheroid_striparea(const RTCTX *ctx, const GEOGRAPHIC_POINT *a, co
   mL.lon = FP_MIN(A.lon, B.lon);
   nR.lat = FP_MIN(A.lat, B.lat);
   nR.lon = FP_MAX(A.lon, B.lon);
-  RTDEBUGF(4, "mL (%.12g %.12g)", mL.lat, mL.lon);
-  RTDEBUGF(4, "nR (%.12g %.12g)", nR.lat, nR.lon);
+  RTDEBUGF(ctx, 4, "mL (%.12g %.12g)", mL.lat, mL.lon);
+  RTDEBUGF(ctx, 4, "nR (%.12g %.12g)", nR.lat, nR.lon);
   baseArea = spheroid_boundingbox_area(ctx, &mL, &nR, spheroid);
-  RTDEBUGF(4, "baseArea %.12g", baseArea);
+  RTDEBUGF(ctx, 4, "baseArea %.12g", baseArea);
 
   mL.lat = FP_MIN(A.lat, B.lat);
   mL.lon = FP_MIN(A.lon, B.lon);
   nR.lat = FP_MAX(A.lat, B.lat);
   nR.lon = FP_MAX(A.lon, B.lon);
-  RTDEBUGF(4, "mL (%.12g %.12g)", mL.lat, mL.lon);
-  RTDEBUGF(4, "nR (%.12g %.12g)", nR.lat, nR.lon);
+  RTDEBUGF(ctx, 4, "mL (%.12g %.12g)", mL.lat, mL.lon);
+  RTDEBUGF(ctx, 4, "nR (%.12g %.12g)", nR.lat, nR.lon);
   topArea = spheroid_boundingbox_area(ctx, &mL, &nR, spheroid);
-  RTDEBUGF(4, "topArea %.12g", topArea);
+  RTDEBUGF(ctx, 4, "topArea %.12g", topArea);
 
   deltaLng = B.lon - A.lon;
-  RTDEBUGF(4, "deltaLng %.12g", deltaLng);
+  RTDEBUGF(ctx, 4, "deltaLng %.12g", deltaLng);
   bE = spheroid_parallel_arc_length(ctx, A.lat, deltaLng, spheroid);
   tE = spheroid_parallel_arc_length(ctx, B.lat, deltaLng, spheroid);
-  RTDEBUGF(4, "bE %.12g", bE);
-  RTDEBUGF(4, "tE %.12g", tE);
+  RTDEBUGF(ctx, 4, "bE %.12g", bE);
+  RTDEBUGF(ctx, 4, "tE %.12g", tE);
 
   ratio = (bE + tE)/tE;
   sign = signum(B.lon - A.lon);
@@ -519,7 +519,7 @@ static double ptarray_area_spheroid(const RTCTX *ctx, const RTPOINTARRAY *pa, co
   if ( gbox2d.ymax < 0.0 )
     in_south = RT_TRUE;
 
-  RTDEBUGF(4, "gbox2d.ymax %.12g", gbox2d.ymax);
+  RTDEBUGF(ctx, 4, "gbox2d.ymax %.12g", gbox2d.ymax);
 
   /* Tolerance for strip area calculation */
   if ( in_south )
@@ -542,7 +542,7 @@ static double ptarray_area_spheroid(const RTCTX *ctx, const RTPOINTARRAY *pa, co
     GEOGRAPHIC_POINT a1, b1;
     double strip_area = 0.0;
     double delta_lon = 0.0;
-    RTDEBUGF(4, "edge #%d", i);
+    RTDEBUGF(ctx, 4, "edge #%d", i);
 
     rt_getPoint2d_p(ctx, pa, i, &p);
     geographic_point_init(ctx, p.x, p.y, &b);
@@ -557,9 +557,9 @@ static double ptarray_area_spheroid(const RTCTX *ctx, const RTPOINTARRAY *pa, co
       b1.lat = -1.0 * b1.lat;
     }
 
-    RTDEBUGF(4, "in_south %d", in_south);
+    RTDEBUGF(ctx, 4, "in_south %d", in_south);
 
-    RTDEBUGF(4, "crosses_dateline(ctx, a, b) %d", crosses_dateline(ctx, &a, &b) );
+    RTDEBUGF(ctx, 4, "crosses_dateline(ctx, a, b) %d", crosses_dateline(ctx, &a, &b) );
 
     if ( crosses_dateline(ctx, &a, &b) )
     {
@@ -570,27 +570,27 @@ static double ptarray_area_spheroid(const RTCTX *ctx, const RTPOINTARRAY *pa, co
       else
         shift = (M_PI - b1.lon) + 0.088; /* About 5deg more */
 
-      RTDEBUGF(4, "shift: %.8g", shift);
-      RTDEBUGF(4, "before shift a1(%.8g %.8g) b1(%.8g %.8g)", a1.lat, a1.lon, b1.lat, b1.lon);
+      RTDEBUGF(ctx, 4, "shift: %.8g", shift);
+      RTDEBUGF(ctx, 4, "before shift a1(%.8g %.8g) b1(%.8g %.8g)", a1.lat, a1.lon, b1.lat, b1.lon);
       point_shift(ctx, &a1, shift);
       point_shift(ctx, &b1, shift);
-      RTDEBUGF(4, "after shift a1(%.8g %.8g) b1(%.8g %.8g)", a1.lat, a1.lon, b1.lat, b1.lon);
+      RTDEBUGF(ctx, 4, "after shift a1(%.8g %.8g) b1(%.8g %.8g)", a1.lat, a1.lon, b1.lat, b1.lon);
 
     }
 
 
     delta_lon = fabs(b1.lon - a1.lon);
 
-    RTDEBUGF(4, "a1(%.18g %.18g) b1(%.18g %.18g)", a1.lat, a1.lon, b1.lat, b1.lon);
-    RTDEBUGF(4, "delta_lon %.18g", delta_lon);
-    RTDEBUGF(4, "delta_lon_tolerance %.18g", delta_lon_tolerance);
+    RTDEBUGF(ctx, 4, "a1(%.18g %.18g) b1(%.18g %.18g)", a1.lat, a1.lon, b1.lat, b1.lon);
+    RTDEBUGF(ctx, 4, "delta_lon %.18g", delta_lon);
+    RTDEBUGF(ctx, 4, "delta_lon_tolerance %.18g", delta_lon_tolerance);
 
     if ( delta_lon > 0.0 )
     {
       if ( delta_lon < delta_lon_tolerance )
       {
         strip_area = spheroid_striparea(ctx, &a1, &b1, latitude_min, spheroid);
-        RTDEBUGF(4, "strip_area %.12g", strip_area);
+        RTDEBUGF(ctx, 4, "strip_area %.12g", strip_area);
         area += strip_area;
       }
       else
@@ -600,24 +600,24 @@ static double ptarray_area_spheroid(const RTCTX *ctx, const RTPOINTARRAY *pa, co
         double distance = spheroid_distance(ctx, &a1, &b1, spheroid);
         double pDistance = 0.0;
         int j = 0;
-        RTDEBUGF(4, "step %.18g", step);
-        RTDEBUGF(4, "distance %.18g", distance);
+        RTDEBUGF(ctx, 4, "step %.18g", step);
+        RTDEBUGF(ctx, 4, "distance %.18g", distance);
         step = distance / step;
-        RTDEBUGF(4, "step %.18g", step);
+        RTDEBUGF(ctx, 4, "step %.18g", step);
         p = a1;
         while (pDistance < (distance - step * 1.01))
         {
           double azimuth = spheroid_direction(ctx, &p, &b1, spheroid);
           j++;
-          RTDEBUGF(4, "  iteration %d", j);
-          RTDEBUGF(4, "  azimuth %.12g", azimuth);
+          RTDEBUGF(ctx, 4, "  iteration %d", j);
+          RTDEBUGF(ctx, 4, "  azimuth %.12g", azimuth);
           pDistance = pDistance + step;
-          RTDEBUGF(4, "  pDistance %.12g", pDistance);
+          RTDEBUGF(ctx, 4, "  pDistance %.12g", pDistance);
           spheroid_project(ctx, &p, spheroid, step, azimuth, &q);
           strip_area = spheroid_striparea(ctx, &p, &q, latitude_min, spheroid);
-          RTDEBUGF(4, "  strip_area %.12g", strip_area);
+          RTDEBUGF(ctx, 4, "  strip_area %.12g", strip_area);
           area += strip_area;
-          RTDEBUGF(4, "  area %.12g", area);
+          RTDEBUGF(ctx, 4, "  area %.12g", area);
           p.lat = q.lat;
           p.lon = q.lon;
         }
diff --git a/src/rtstroke.c b/src/rtstroke.c
index 2ce0826..06ff361 100644
--- a/src/rtstroke.c
+++ b/src/rtstroke.c
@@ -58,7 +58,7 @@ rtgeom_has_arc(const RTCTX *ctx, const RTGEOM *geom)
   RTCOLLECTION *col;
   int i;
 
-  RTDEBUG(2, "rtgeom_has_arc called.");
+  RTDEBUG(ctx, 2, "rtgeom_has_arc called.");
 
   switch (geom->type)
   {
@@ -94,7 +94,7 @@ rtgeom_has_arc(const RTCTX *ctx, const RTGEOM *geom)
 
 static double interpolate_arc(const RTCTX *ctx, double angle, double a1, double a2, double a3, double zm1, double zm2, double zm3)
 {
-  RTDEBUGF(4,"angle %.05g a1 %.05g a2 %.05g a3 %.05g zm1 %.05g zm2 %.05g zm3 %.05g",angle,a1,a2,a3,zm1,zm2,zm3);
+  RTDEBUGF(ctx, 4,"angle %.05g a1 %.05g a2 %.05g a3 %.05g zm1 %.05g zm2 %.05g zm3 %.05g",angle,a1,a2,a3,zm1,zm2,zm3);
   /* Counter-clockwise sweep */
   if ( a1 < a2 )
   {
@@ -129,7 +129,7 @@ rtcircle_stroke(const RTCTX *ctx, const RTPOINT4D *p1, const RTPOINT4D *p2, cons
   RTPOINTARRAY *pa;
   int is_circle = RT_FALSE;
 
-  RTDEBUG(2, "rtcircle_calculate_gbox called.");
+  RTDEBUG(ctx, 2, "rtcircle_calculate_gbox called.");
 
   radius = rt_arc_center(ctx, t1, t2, t3, &center);
   p2_side = rt_segment_side(ctx, t1, t3, t2);
@@ -210,13 +210,13 @@ rtcircstring_stroke(const RTCTX *ctx, const RTCIRCSTRING *icurve, uint32_t perQu
   uint32_t i, j;
   RTPOINT4D p1, p2, p3, p4;
 
-  RTDEBUGF(2, "rtcircstring_stroke called., dim = %d", icurve->points->flags);
+  RTDEBUGF(ctx, 2, "rtcircstring_stroke called., dim = %d", icurve->points->flags);
 
   ptarray = ptarray_construct_empty(ctx, RTFLAGS_GET_Z(icurve->points->flags), RTFLAGS_GET_M(icurve->points->flags), 64);
 
   for (i = 2; i < icurve->points->npoints; i+=2)
   {
-    RTDEBUGF(3, "rtcircstring_stroke: arc ending at point %d", i);
+    RTDEBUGF(ctx, 3, "rtcircstring_stroke: arc ending at point %d", i);
 
     rt_getPoint4d_p(ctx, icurve->points, i - 2, &p1);
     rt_getPoint4d_p(ctx, icurve->points, i - 1, &p2);
@@ -225,7 +225,7 @@ rtcircstring_stroke(const RTCTX *ctx, const RTCIRCSTRING *icurve, uint32_t perQu
 
     if (tmp)
     {
-      RTDEBUGF(3, "rtcircstring_stroke: generated %d points", tmp->npoints);
+      RTDEBUGF(ctx, 3, "rtcircstring_stroke: generated %d points", tmp->npoints);
 
       for (j = 0; j < tmp->npoints; j++)
       {
@@ -236,7 +236,7 @@ rtcircstring_stroke(const RTCTX *ctx, const RTCIRCSTRING *icurve, uint32_t perQu
     }
     else
     {
-      RTDEBUG(3, "rtcircstring_stroke: points are colinear, returning curve points as line");
+      RTDEBUG(ctx, 3, "rtcircstring_stroke: points are colinear, returning curve points as line");
 
       for (j = i - 2 ; j < i ; j++)
       {
@@ -262,7 +262,7 @@ rtcompound_stroke(const RTCTX *ctx, const RTCOMPOUND *icompound, uint32_t perQua
   uint32_t i, j;
   RTPOINT4D p;
 
-  RTDEBUG(2, "rtcompound_stroke called.");
+  RTDEBUG(ctx, 2, "rtcompound_stroke called.");
 
   ptarray = ptarray_construct_empty(ctx, RTFLAGS_GET_Z(icompound->flags), RTFLAGS_GET_M(icompound->flags), 64);
 
@@ -309,7 +309,7 @@ rtcurvepoly_stroke(const RTCTX *ctx, const RTCURVEPOLY *curvepoly, uint32_t perQ
   RTPOINTARRAY **ptarray;
   int i;
 
-  RTDEBUG(2, "rtcurvepoly_stroke called.");
+  RTDEBUG(ctx, 2, "rtcurvepoly_stroke called.");
 
   ptarray = rtalloc(ctx, sizeof(RTPOINTARRAY *)*curvepoly->nrings);
 
@@ -351,7 +351,7 @@ rtmcurve_stroke(const RTCTX *ctx, const RTMCURVE *mcurve, uint32_t perQuad)
   RTGEOM **lines;
   int i;
 
-  RTDEBUGF(2, "rtmcurve_stroke called, geoms=%d, dim=%d.", mcurve->ngeoms, RTFLAGS_NDIMS(mcurve->flags));
+  RTDEBUGF(ctx, 2, "rtmcurve_stroke called, geoms=%d, dim=%d.", mcurve->ngeoms, RTFLAGS_NDIMS(mcurve->flags));
 
   lines = rtalloc(ctx, sizeof(RTGEOM *)*mcurve->ngeoms);
 
@@ -391,7 +391,7 @@ rtmsurface_stroke(const RTCTX *ctx, const RTMSURFACE *msurface, uint32_t perQuad
   RTPOINTARRAY **ptarray;
   int i, j;
 
-  RTDEBUG(2, "rtmsurface_stroke called.");
+  RTDEBUG(ctx, 2, "rtmsurface_stroke called.");
 
   polys = rtalloc(ctx, sizeof(RTGEOM *)*msurface->ngeoms);
 
@@ -425,7 +425,7 @@ rtcollection_stroke(const RTCTX *ctx, const RTCOLLECTION *collection, uint32_t p
   RTGEOM **geoms;
   int i;
 
-  RTDEBUG(2, "rtcollection_stroke called.");
+  RTDEBUG(ctx, 2, "rtcollection_stroke called.");
 
   geoms = rtalloc(ctx, sizeof(RTGEOM *)*collection->ngeoms);
 
@@ -528,7 +528,7 @@ static int pt_continues_arc(const RTCTX *ctx, const RTPOINT4D *a1, const RTPOINT
 
   b_distance = distance2d_pt_pt(ctx, tb, &center);
   diff = fabs(radius - b_distance);
-  RTDEBUGF(4, "circle_radius=%g, b_distance=%g, diff=%g, percentage=%g", radius, b_distance, diff, diff/radius);
+  RTDEBUGF(ctx, 4, "circle_radius=%g, b_distance=%g, diff=%g, percentage=%g", radius, b_distance, diff, diff/radius);
 
   /* Is the point b on the circle? */
   if ( diff < EPSILON_SQLMM )
@@ -540,7 +540,7 @@ static int pt_continues_arc(const RTCTX *ctx, const RTPOINT4D *a1, const RTPOINT
 
     /* Is the angle similar to the previous one ? */
     diff = fabs(angle1 - angle2);
-    RTDEBUGF(4, " angle1: %g, angle2: %g, diff:%g", angle1, angle2, diff);
+    RTDEBUGF(ctx, 4, " angle1: %g, angle2: %g, diff:%g", angle1, angle2, diff);
     if ( diff > EPSILON_SQLMM )
     {
       return RT_FALSE;
@@ -560,7 +560,7 @@ linestring_from_pa(const RTCTX *ctx, const RTPOINTARRAY *pa, int srid, int start
   int i = 0, j = 0;
   RTPOINT4D p;
   RTPOINTARRAY *pao = ptarray_construct(ctx, ptarray_has_z(ctx, pa), ptarray_has_m(ctx, pa), end-start+2);
-  RTDEBUGF(4, "srid=%d, start=%d, end=%d", srid, start, end);
+  RTDEBUGF(ctx, 4, "srid=%d, start=%d, end=%d", srid, start, end);
   for( i = start; i < end + 2; i++ )
   {
     rt_getPoint4d_p(ctx, pa, i, &p);
@@ -575,7 +575,7 @@ circstring_from_pa(const RTCTX *ctx, const RTPOINTARRAY *pa, int srid, int start
 
   RTPOINT4D p0, p1, p2;
   RTPOINTARRAY *pao = ptarray_construct(ctx, ptarray_has_z(ctx, pa), ptarray_has_m(ctx, pa), 3);
-  RTDEBUGF(4, "srid=%d, start=%d, end=%d", srid, start, end);
+  RTDEBUGF(ctx, 4, "srid=%d, start=%d, end=%d", srid, start, end);
   rt_getPoint4d_p(ctx, pa, start, &p0);
   ptarray_set_point4d(ctx, pao, 0, &p0);
   rt_getPoint4d_p(ctx, pa, (start+end+1)/2, &p1);
@@ -588,7 +588,7 @@ circstring_from_pa(const RTCTX *ctx, const RTPOINTARRAY *pa, int srid, int start
 static RTGEOM*
 geom_from_pa(const RTCTX *ctx, const RTPOINTARRAY *pa, int srid, int is_arc, int start, int end)
 {
-  RTDEBUGF(4, "srid=%d, is_arc=%d, start=%d, end=%d", srid, is_arc, start, end);
+  RTDEBUGF(ctx, 4, "srid=%d, is_arc=%d, start=%d, end=%d", srid, is_arc, start, end);
   if ( is_arc )
     return circstring_from_pa(ctx, pa, srid, start, end);
   else
@@ -648,13 +648,13 @@ pta_unstroke(const RTCTX *ctx, const RTPOINTARRAY *points, int type, int srid)
 
     for( j = i+3; j < num_edges+1; j++ )
     {
-      RTDEBUGF(4, "i=%d, j=%d", i, j);
+      RTDEBUGF(ctx, 4, "i=%d, j=%d", i, j);
       rt_getPoint4d_p(ctx, points, j, &b);
       /* Does this point fall on our candidate arc? */
       if ( pt_continues_arc(ctx, &a1, &a2, &a3, &b) )
       {
         /* Yes. Mark this edge and the two preceding it as arc components */
-        RTDEBUGF(4, "pt_continues_arc #%d", current_arc);
+        RTDEBUGF(ctx, 4, "pt_continues_arc #%d", current_arc);
         found_arc = RT_TRUE;
         for ( k = j-1; k > j-4; k-- )
           edges_in_arcs[k] = current_arc;
@@ -662,7 +662,7 @@ pta_unstroke(const RTCTX *ctx, const RTPOINTARRAY *points, int type, int srid)
       else
       {
         /* No. So we're done with this candidate arc */
-        RTDEBUG(4, "pt_continues_arc = false");
+        RTDEBUG(ctx, 4, "pt_continues_arc = false");
         current_arc++;
         break;
       }
@@ -679,9 +679,9 @@ pta_unstroke(const RTCTX *ctx, const RTPOINTARRAY *points, int type, int srid)
        * See http://trac.osgeo.org/postgis/ticket/2420
        */
       arc_edges = j - 1 - i;
-      RTDEBUGF(4, "arc defined by %d edges found", arc_edges);
+      RTDEBUGF(ctx, 4, "arc defined by %d edges found", arc_edges);
       if ( first.x == b.x && first.y == b.y ) {
-        RTDEBUG(4, "arc is a circle");
+        RTDEBUG(ctx, 4, "arc is a circle");
         num_quadrants = 4;
       }
       else {
@@ -692,11 +692,11 @@ pta_unstroke(const RTCTX *ctx, const RTPOINTARRAY *points, int type, int srid)
 
         if ( angle < 0 ) angle = 2 * M_PI + angle;
         num_quadrants = ( 4 * angle ) / ( 2 * M_PI );
-        RTDEBUGF(4, "arc angle (%g %g, %g %g, %g %g) is %g (side is %d), quandrants:%g", first.x, first.y, center.x, center.y, b.x, b.y, angle, p2_side, num_quadrants);
+        RTDEBUGF(ctx, 4, "arc angle (%g %g, %g %g, %g %g) is %g (side is %d), quandrants:%g", first.x, first.y, center.x, center.y, b.x, b.y, angle, p2_side, num_quadrants);
       }
       /* a1 is first point, b is last point */
       if ( arc_edges < min_quad_edges * num_quadrants ) {
-        RTDEBUGF(4, "Not enough edges for a %g quadrants arc, %g needed", num_quadrants, min_quad_edges * num_quadrants);
+        RTDEBUGF(ctx, 4, "Not enough edges for a %g quadrants arc, %g needed", num_quadrants, min_quad_edges * num_quadrants);
         for ( k = j-1; k >= i; k-- )
           edges_in_arcs[k] = 0;
       }
@@ -722,7 +722,7 @@ pta_unstroke(const RTCTX *ctx, const RTPOINTARRAY *points, int type, int srid)
         edgestr[i] = '.';
     }
     edgestr[num_edges] = 0;
-    RTDEBUGF(3, "edge pattern %s", edgestr);
+    RTDEBUGF(ctx, 3, "edge pattern %s", edgestr);
     rtfree(ctx, edgestr);
   }
 #endif
@@ -760,7 +760,7 @@ pta_unstroke(const RTCTX *ctx, const RTPOINTARRAY *points, int type, int srid)
 RTGEOM *
 rtline_unstroke(const RTCTX *ctx, const RTLINE *line)
 {
-  RTDEBUG(2, "rtline_unstroke called.");
+  RTDEBUG(ctx, 2, "rtline_unstroke called.");
 
   if ( line->points->npoints < 4 ) return rtline_as_rtgeom(ctx, rtline_clone(ctx, line));
   else return pta_unstroke(ctx, line->points, line->flags, line->srid);
@@ -772,7 +772,7 @@ rtpolygon_unstroke(const RTCTX *ctx, const RTPOLY *poly)
   RTGEOM **geoms;
   int i, hascurve = 0;
 
-  RTDEBUG(2, "rtpolygon_unstroke called.");
+  RTDEBUG(ctx, 2, "rtpolygon_unstroke called.");
 
   geoms = rtalloc(ctx, sizeof(RTGEOM *)*poly->nrings);
   for (i=0; i<poly->nrings; i++)
@@ -801,7 +801,7 @@ rtmline_unstroke(const RTCTX *ctx, const RTMLINE *mline)
   RTGEOM **geoms;
   int i, hascurve = 0;
 
-  RTDEBUG(2, "rtmline_unstroke called.");
+  RTDEBUG(ctx, 2, "rtmline_unstroke called.");
 
   geoms = rtalloc(ctx, sizeof(RTGEOM *)*mline->ngeoms);
   for (i=0; i<mline->ngeoms; i++)
@@ -829,7 +829,7 @@ rtmpolygon_unstroke(const RTCTX *ctx, const RTMPOLY *mpoly)
   RTGEOM **geoms;
   int i, hascurve = 0;
 
-  RTDEBUG(2, "rtmpoly_unstroke called.");
+  RTDEBUG(ctx, 2, "rtmpoly_unstroke called.");
 
   geoms = rtalloc(ctx, sizeof(RTGEOM *)*mpoly->ngeoms);
   for (i=0; i<mpoly->ngeoms; i++)
@@ -854,7 +854,7 @@ rtmpolygon_unstroke(const RTCTX *ctx, const RTMPOLY *mpoly)
 RTGEOM *
 rtgeom_unstroke(const RTCTX *ctx, const RTGEOM *geom)
 {
-  RTDEBUG(2, "rtgeom_unstroke called.");
+  RTDEBUG(ctx, 2, "rtgeom_unstroke called.");
 
   switch (geom->type)
   {
diff --git a/src/rtt_tpsnap.c b/src/rtt_tpsnap.c
new file mode 100644
index 0000000..2bab00a
--- /dev/null
+++ b/src/rtt_tpsnap.c
@@ -0,0 +1,771 @@
+/**********************************************************************
+ *
+ * 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/>.
+ *
+ **********************************************************************
+ *
+ * Implementation of Trevisani-Peri snap algoritm
+ *
+ * See
+ * https://git.osgeo.org/gogs/rttopo/librttopo/wiki/SnapToTopo-algorithm
+ *
+ **********************************************************************
+ *
+ * Copyright (C) 2016 Sandro Santilli <strk at kbt.io>
+ *
+ **********************************************************************/
+
+#include "rttopo_config.h"
+
+/*#define RTGEOM_DEBUG_LEVEL 1*/
+#include "rtgeom_log.h"
+
+#include "librttopo_geom.h"
+#include "librttopo_internal.h"
+#include "librttopo_geom_internal.h"
+#include "measures.h"
+#include "rtgeom_geos.h"
+
+/*
+ * Reference vertex
+ *
+ * It is the vertex of a topology edge
+ * which is within snap tolerance distance from
+ * a segment of the input geometry.
+ *
+ * We store the input geometry segment and the distance
+ * (both needed to compute the distance) within the structure.
+ *
+ */
+typedef struct {
+  RTPOINT2D pt;
+  /* Closest segment in input pointarray (0-based index) */
+  int segno;
+  double dist;
+} RTT_SNAPV;
+
+/* An array of RTT_SNAPV structs */
+typedef struct {
+  RTT_SNAPV *pts;
+  int size;
+  int capacity;
+} RTT_SNAPV_ARRAY;
+
+#define RTT_SNAPV_ARRAY_INIT(c, a) { \
+  (a)->size = 0; \
+  (a)->capacity = 1; \
+  (a)->pts = rtalloc((c), sizeof(RTT_SNAPV) * (a)->capacity); \
+}
+
+#define RTT_SNAPV_ARRAY_CLEAN(c, a) { \
+  rtfree((c), (a)->pts); \
+  (a)->pts = NULL; \
+  (a)->size = 0; \
+  (a)->capacity = 0; \
+}
+
+#define RTT_SNAPV_ARRAY_PUSH(c, a, r) { \
+  if ( (a)->size + 1 > (a)->capacity ) { \
+    (a)->capacity *= 2; \
+    (a)->pts = rtrealloc((c), (a)->pts, sizeof(RTT_SNAPV) * (a)->capacity); \
+  } \
+  (a)->pts[(a)->size++] = (r); \
+}
+
+/* A pair of points with their distance */
+typedef struct {
+  RTT_SNAPV *p1;
+  RTT_SNAPV *p2;
+  double totdist; /* sum of the two points distances */
+  double segdist; /* between the two points */
+} RTT_VPAIR;
+
+/* An array of RTT_VPAIR structs */
+typedef struct {
+  RTT_VPAIR *pts;
+  int size;
+  int capacity;
+} RTT_VPAIR_ARRAY;
+
+#define RTT_VPAIR_ARRAY_INIT(c, a) { \
+  (a)->size = 0; \
+  (a)->capacity = 1; \
+  (a)->pts = rtalloc((c), sizeof(RTT_VPAIR) * (a)->capacity); \
+}
+
+#define RTT_VPAIR_ARRAY_CLEAN(c, a) { \
+  rtfree((c), (a)->pts); \
+  (a)->pts = NULL; \
+  (a)->size = 0; \
+  (a)->capacity = 0; \
+}
+
+#define RTT_VPAIR_ARRAY_INIT(c, a) { \
+  (a)->size = 0; \
+  (a)->capacity = 1; \
+  (a)->pts = rtalloc((c), sizeof(RTT_VPAIR) * (a)->capacity); \
+}
+
+#define RTT_VPAIR_ARRAY_PUSH(c, a, r) { \
+  if ( (a)->size + 1 > (a)->capacity ) { \
+    (a)->capacity *= 2; \
+    (a)->pts = rtrealloc((c), (a)->pts, sizeof(RTT_VPAIR) * (a)->capacity); \
+  } \
+  (a)->pts[(a)->size++] = (r); \
+}
+
+typedef struct
+{
+
+  /*
+   * Input parameters / configuration
+   */
+  const RTT_TOPOLOGY *topo;
+  double tssnap;
+  int iterate;
+  int remove_vertices;
+
+  /*
+   * Extent of the geometry being snapped,
+   * will be updated as needed as snapping occurs
+   */
+  RTGBOX workext;
+
+  /*
+   * Edges within workext,
+   * will be updated as needed as workext extends
+   * (maybe should be put in an STRtree)
+   */
+  RTT_ISO_EDGE *workedges;
+  int num_workedges;
+
+} rtgeom_tpsnap_state;
+
+/*
+ * Write number of edges in *num_edges, -1 on error.
+ * @return edges, or NULL if none-or-error (look *num_edges to tell)
+ */
+static const RTT_ISO_EDGE *
+rtgeom_tpsnap_state_get_edges(rtgeom_tpsnap_state *state, int *num_edges)
+{
+  if ( ! state->workedges ) {
+    RTGBOX qbox = state->workext;
+    gbox_expand(state->topo->be_iface->ctx, &qbox, state->tssnap);
+    state->workedges = rtt_be_getEdgeWithinBox2D(state->topo,
+              &qbox,
+              &state->num_workedges,
+              RTT_COL_EDGE_ALL, 0);
+  }
+
+  *num_edges = state->num_workedges;
+  return state->workedges;
+}
+
+/*
+ * Write number of edges in *num_edges, -1 on error.
+ * @return edges, or NULL if none-or-error (look *num_edges to tell)
+ */
+static void
+rtgeom_tpsnap_state_expand_workext_to_include(rtgeom_tpsnap_state *state,
+    RTPOINT2D *pt)
+{
+  const RTCTX *ctx = state->topo->be_iface->ctx;
+  POINT3D p3d;
+
+  /* Nothing to do if the box already contains the point */
+  if ( gbox_contains_point2d(ctx, &state->workext, pt) ) return;
+
+  p3d.x = pt->x;
+  p3d.y = pt->y;
+  p3d.z = 0.0;
+
+  gbox_merge_point3d(ctx, &p3d, &state->workext);
+
+  /* Reset workedges */
+  if ( state->workedges ) {
+    rtt_release_edges(state->topo->be_iface->ctx,
+                      state->workedges, state->num_workedges);
+    state->workedges = NULL;
+  }
+}
+
+static void
+rtgeom_tpsnap_state_destroy(rtgeom_tpsnap_state *state)
+{
+  if ( state->workedges ) {
+    rtt_release_edges(state->topo->be_iface->ctx,
+                      state->workedges, state->num_workedges);
+  }
+}
+
+/*
+ * Find closest segment of pa to a given point
+ *
+ * @return -1 on error, 0 on success
+ */
+static int
+_rt_find_closest_segment(const RTCTX *ctx, RTPOINT2D *pt, RTPOINTARRAY *pa,
+    int *segno, double *dist)
+{
+  int j;
+  RTPOINT2D s0, s1;
+  DISTPTS dl;
+
+  *segno = -1;
+  *dist = FLT_MAX;
+
+  rt_dist2d_distpts_init(ctx, &dl, DIST_MIN);
+
+  /* Find closest segment */
+  for (j=0; j<pa->npoints-1; ++j)
+  {
+    rt_getPoint2d_p(ctx, pa, j, &s0);
+    rt_getPoint2d_p(ctx, pa, j+1, &s1);
+
+    if ( rt_dist2d_pt_seg(ctx, pt, &s0, &s1, &dl) == RT_FALSE )
+    {
+      rterror(ctx, "rt_dist2d_pt_seg failed in _rt_find_closest_segment");
+      return -1;
+    }
+
+    /* Segment is too far, check next */
+    if ( dl.distance < *dist )
+    {
+      *segno = j;
+      *dist = dl.distance;
+    }
+  }
+
+  return 0;
+}
+
+/*
+ * Extract from edge all vertices where distance from pa <= tssnap
+ *
+ * @return -1 on error, 0 on success
+ */
+static int
+_rt_extract_vertices_within_dist(rtgeom_tpsnap_state *state,
+    RTT_SNAPV_ARRAY *vset, RTLINE *edge, RTPOINTARRAY *pa)
+{
+  int i;
+  RTPOINTARRAY *epa = edge->points; /* edge's point array */
+  const RTT_TOPOLOGY *topo = state->topo;
+  const RTCTX *ctx = topo->be_iface->ctx;
+
+  RTT_SNAPV vert;
+  for (i=0; i<epa->npoints; ++i)
+  {
+    int ret;
+
+    rt_getPoint2d_p(ctx, edge->points, i, &(vert.pt));
+
+    ret = _rt_find_closest_segment(ctx, &(vert.pt), pa, &vert.segno, &vert.dist);
+    if ( ret == -1 ) return -1;
+
+    if ( vert.dist <= state->tssnap )
+    {
+      /* push vert to array */
+      RTT_SNAPV_ARRAY_PUSH(ctx, vset, vert);
+    }
+
+  }
+
+  return 0;
+}
+
+/*
+ * Find all topology edge vertices where distance from
+ * given pointarray <= tssnap
+ *
+ * @return -1 on error, 0 on success
+ */
+static int
+_rt_find_vertices_within_dist(
+      RTT_SNAPV_ARRAY *vset, RTPOINTARRAY *pa,
+      rtgeom_tpsnap_state *state)
+{
+  int num_edges;
+  const RTT_ISO_EDGE *edges;
+  const RTT_TOPOLOGY *topo = state->topo;
+  const RTCTX *ctx = topo->be_iface->ctx;
+  int i;
+
+  edges = rtgeom_tpsnap_state_get_edges(state, &num_edges);
+  if ( num_edges == -1 ) {
+    rterror(ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
+    return -1;
+  }
+
+  for (i=0; i<num_edges; ++i)
+  {
+    int ret;
+    ret = _rt_extract_vertices_within_dist(state, vset, edges[i].geom, pa);
+    if ( ret < 0 ) return ret;
+  }
+
+  return 0;
+}
+
+static int
+compare_vpairs(const void *si1, const void *si2)
+{
+  RTT_VPAIR *a = (RTT_VPAIR *)si1;
+  RTT_VPAIR *b = (RTT_VPAIR *)si2;
+
+  if ( a->totdist < b->totdist )
+    return -1;
+  else if ( a->totdist > b->totdist )
+    return 1;
+
+  if ( a->segdist < b->segdist )
+    return -1;
+  else if ( a->segdist > b->segdist )
+    return 1;
+
+  return 0;
+}
+
+/*
+ * Let *VPlist* be a list of all vertices pairs (*VP*) in *Vset*
+ * For each element *VP* in *VPlist*:
+ *   Let *VP.TotDist* be the sum of the distances of each of the vertices in *VP*
+ *   Let *VP.SegDist* be the distances between the two vertices in *VP*
+ * Order *VPlist* by growing *VP.TotDist*, *VP.SegDist*
+ *
+ * @return 0 on success, -1 on error.
+ *
+ */
+static int
+_rt_make_sorted_vertices_pairs(const RTCTX *ctx,
+      RTT_SNAPV_ARRAY *vset,
+      RTT_VPAIR_ARRAY *vplist)
+{
+  int i, j, ret;
+  DISTPTS dl;
+  rt_dist2d_distpts_init(ctx, &dl, DIST_MIN);
+  for (i=0; i<vset->size; ++i)
+  {
+    for (j=i+1; j<vset->size; ++j)
+    {
+      RTT_VPAIR pair;
+      pair.p1 = &(vset->pts[i]);
+      pair.p2 = &(vset->pts[j]);
+      ret = rt_dist2d_pt_pt(ctx, &(pair.p1->pt), &(pair.p2->pt), &dl);
+      pair.segdist = dl.distance;
+      pair.totdist = pair.p1->dist + pair.p2->dist;
+      if ( ret == RT_FALSE ) return -1;
+      RTT_VPAIR_ARRAY_PUSH(ctx, vplist, pair);
+    }
+  }
+
+  /* Now sort it */
+  qsort(vplist->pts, vplist->size, sizeof(RTT_VPAIR), compare_vpairs);
+
+  return 0;
+}
+
+/*
+ * @return 0 on success, -1 on error
+ */
+typedef int (*rtptarray_visitor)(const RTCTX *ctx, RTPOINTARRAY *pa, void *userdata);
+
+/*
+ * Pass each PTARRAY defining linear components of RTGEOM to the given
+ * visitor function
+ *
+ * This is a mutating visit, where pointarrays are passed as non-const
+ *
+ * Only (multi)linestring and (multi)polygon will be filtered, with
+ * other components simply left unvisited.
+ *
+ * @return 0 on success, -1 on error (if visitor function ever
+ *         returned an error)
+ *
+ * To be exported if useful
+ */
+static int
+rtgeom_visit_lines(const RTCTX *ctx, RTGEOM *rtgeom,
+                   rtptarray_visitor visitor, void *userdata)
+{
+  int i;
+  int ret;
+  RTCOLLECTION *coll;
+  RTPOLY *poly;
+  RTLINE *line;
+
+  switch (rtgeom->type)
+  {
+  case RTPOLYGONTYPE:
+    poly = (RTPOLY*)rtgeom;
+    for (i=0; i<poly->nrings; ++i) {
+      ret = visitor(ctx, poly->rings[i], userdata);
+      if ( ret != 0 ) return ret;
+    }
+    break;
+
+  case RTLINETYPE:
+    line = (RTLINE*)rtgeom;
+    return visitor(ctx, line->points, userdata);
+
+  case RTMULTILINETYPE:
+  case RTMULTIPOLYGONTYPE:
+  case RTCOLLECTIONTYPE:
+    coll = (RTCOLLECTION *)rtgeom;
+    for (i=0; i<coll->ngeoms; i++) {
+      ret = rtgeom_visit_lines(ctx, coll->geoms[i], visitor, userdata);
+      if ( ret != 0 ) return ret;
+    }
+    break;
+  }
+
+  return 0;
+}
+
+/*
+ * Vertex removal phase
+ *
+ * @return 0 on success, -1 on error.
+ */
+static int
+_rtgeom_tpsnap_ptarray_remove(const RTCTX *ctx, RTPOINTARRAY *pa,
+                  rtgeom_tpsnap_state *state)
+{
+  int num_edges, i, j, ret;
+  const RTT_ISO_EDGE *edges;
+  const RTT_TOPOLOGY *topo = state->topo;
+
+  /* Let *Eset* be the set of edges of *Topo-ref*
+   *             with distance from *Gcomp* <= *TSsnap*
+   */
+  edges = rtgeom_tpsnap_state_get_edges(state, &num_edges);
+  if ( num_edges == -1 ) {
+    rterror(ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
+    return -1;
+  }
+
+  /* For each non-endpoint vertex *V* of *Gcomp* */
+  for (i=1; i<pa->npoints-1; ++i)
+  {
+    RTPOINT2D V;
+    rt_getPoint2d_p(ctx, pa, i, &V);
+
+    /* For each edge *E* of *Eset* */
+    for (j=0; j<num_edges; ++j)
+    {
+      RTLINE *E = edges[j].geom;
+      RTPOINT4D p, sp1, sp2, proj;
+      int segno;
+      double dist;
+
+      ret = _rt_find_closest_segment(ctx, &V, E->points, &segno, &dist);
+      if ( ret < 0 ) return ret; /* error */
+
+      /* Edge is too far */
+      if ( dist > state->tssnap ) continue;
+
+      /* Let *Proj* be the closest point in *E* to *V* */
+      p.x = V.x; p.y = V.y; p.m = p.z = 0.0;
+      rt_getPoint4d_p(ctx, pa, segno, &sp1);
+      rt_getPoint4d_p(ctx, pa, segno+1, &sp2);
+      closest_point_on_segment(ctx, &p, &sp1, &sp2, &proj);
+
+      /* Closest point here matches segment endpoint */
+      if ( p4d_same(ctx, &p, &sp1) || p4d_same(ctx, &p, &sp2) ) {
+        continue;
+      }
+
+      /* Remove vertex *V* from *Gcomp* */
+      ret = ptarray_remove_point(ctx, pa, i);
+      if ( ret == RT_FAILURE ) return -1;
+      /* rewind i */
+      --i;
+      break;
+    }
+  }
+
+  return 0;
+}
+
+/* Return NULL on error, or a GEOSGeometry on success */
+static GEOSGeometry *
+_rt_segment_to_geosgeom(const RTCTX *ctx, RTPOINT4D *p1, RTPOINT4D *p2)
+{
+  RTPOINTARRAY *pa = ptarray_construct(ctx, 0, 0, 2);
+  RTLINE *line;
+  GEOSGeometry *ret;
+  ptarray_set_point4d(ctx, pa, 0, p1);
+  ptarray_set_point4d(ctx, pa, 1, p2);
+  line = rtline_construct(ctx, 0, NULL, pa);
+  ret = RTGEOM2GEOS(ctx, rtline_as_rtgeom(ctx, line), 0);
+  rtline_free(ctx, line);
+  return ret;
+}
+
+/*
+ *
+ * @return -1 on error, 1 if covered, 0 if not covered
+ */
+static int
+_rt_segment_covered(rtgeom_tpsnap_state *state,
+    RTPOINT4D *p1, RTPOINT4D *p2)
+{
+  const RTT_TOPOLOGY *topo = state->topo;
+  const RTCTX *ctx = topo->be_iface->ctx;
+  int num_edges, i;
+  const RTT_ISO_EDGE *edges;
+  GEOSGeometry *sg;
+
+  edges = rtgeom_tpsnap_state_get_edges(state, &num_edges);
+  if ( num_edges == -1 ) {
+    rterror(ctx, "Backend error: %s", rtt_be_lastErrorMessage(topo->be_iface));
+    return -1;
+  }
+
+  /* OPTIMIZE: use prepared geometries */
+  /* OPTIMIZE: cache cover state of segments */
+
+  sg = _rt_segment_to_geosgeom(ctx, p1, p2);
+  for (i=0; i<num_edges; ++i)
+  {
+    RTGEOM *eg = rtline_as_rtgeom(ctx, edges[i].geom);
+    GEOSGeometry *geg = RTGEOM2GEOS(ctx, eg, 0);
+    int covers = GEOSCovers_r(ctx->gctx, geg, sg);
+    GEOSGeom_destroy_r(ctx->gctx, geg);
+    if (covers == 2) {
+      GEOSGeom_destroy_r(ctx->gctx, sg);
+      rterror(ctx, "Covers error: %s", rtgeom_get_last_geos_error(ctx));
+      return -1;
+    }
+    if ( covers ) {
+      GEOSGeom_destroy_r(ctx->gctx, sg);
+      return 1;
+    }
+  }
+  GEOSGeom_destroy_r(ctx->gctx, sg);
+
+  return 0;
+}
+
+/*
+  Let *Point.Proj* be the closest point in *Gcomp* to the point
+  Let *Point.InSeg* be the segment of *Gcomp* containing *Point.Proj*'
+  IF *Point.InSeg* is NOT COVERED BY *Topo-ref* edges:
+      IF *Point.Proj* is NOT cohincident with a vertex of *Gcomp*:
+         Insert *Point* after the first vertex of *Point.InSeg*
+
+ at return 0 if no valid snap was found, <0 on error, >0 if snapped
+
+*/
+static int
+_rt_snap_to_valid_vertex(const RTCTX *ctx, RTPOINTARRAY *pa,
+  const RTT_SNAPV *v, rtgeom_tpsnap_state *state)
+{
+  int ret;
+  RTPOINT4D p, sp1, sp2, proj;
+  p.x = v->pt.x; p.y = v->pt.y; p.m = p.z = 0.0;
+  rt_getPoint4d_p(ctx, pa, v->segno, &sp1);
+  rt_getPoint4d_p(ctx, pa, v->segno+1, &sp2);
+  closest_point_on_segment(ctx, &p, &sp1, &sp2, &proj);
+
+  /* Check if closest point matches segment endpoint (could be cached) */
+  if ( p4d_same(ctx, &p, &sp1) || p4d_same(ctx, &p, &sp2) ) {
+    return 0;
+  }
+
+  /* Skip if closest segment is covered by topo-ref */
+  ret = _rt_segment_covered(state, &sp1, &sp2);
+  if ( ret == -1 ) return -1;
+  if ( ret == 1 ) {
+    /* it is covered */
+    return 0;
+  }
+
+  /* Snap ! */
+  ret = ptarray_insert_point(ctx, pa, &p, 0);
+  if ( ret == RT_FAILURE ) return -1;
+
+  return 1;
+
+}
+
+/*
+ * @return 0 if no valid snap was found, <0 on error, >0 if snapped
+ */
+static int
+_rt_snap_to_valid_pair(const RTCTX *ctx, RTPOINTARRAY *pa,
+  RTT_VPAIR *pair, rtgeom_tpsnap_state *state)
+{
+  int snapCount = 0, ret;
+
+  ret = _rt_snap_to_valid_vertex(ctx, pa, pair->p1, state);
+  if ( ret < 0 ) return ret;
+  snapCount += ret;
+
+  if ( ret ) {
+    /* Expand working extent */
+    rtgeom_tpsnap_state_expand_workext_to_include(state,
+      &(pair->p1->pt));
+
+    /* Recompute distance from second point, if first was snapped */
+    ret = _rt_find_closest_segment(ctx, &(pair->p2->pt), pa,
+              &(pair->p2->segno), &(pair->p2->dist));
+    if ( ret < 0 ) return ret; /* error */
+
+  }
+
+  ret = _rt_snap_to_valid_vertex(ctx, pa, pair->p2, state);
+  if ( ret < 0 ) return ret;
+  snapCount += ret;
+
+  if ( ret ) {
+    /* Expand working extent */
+    rtgeom_tpsnap_state_expand_workext_to_include(state,
+      &(pair->p2->pt));
+  }
+
+  return snapCount;
+}
+
+/* @return 0 if no valid snap was found, <0 on error, >0 if snapped */
+static int
+_rt_snap_to_first_valid_pair(const RTCTX *ctx, RTPOINTARRAY *pa,
+  RTT_VPAIR_ARRAY *vplist, rtgeom_tpsnap_state *state)
+{
+  int foundSnap = 0;
+  int i;
+
+  for (i=0; i<vplist->size; ++i)
+  {
+    RTT_VPAIR *pair = &(vplist->pts[i]);
+    foundSnap = _rt_snap_to_valid_pair(ctx, pa, pair, state);
+    if ( foundSnap ) break;
+  }
+
+  return foundSnap;
+}
+
+/*
+ * Vertex addition phase
+ *
+ * @return 0 on success, -1 on error.
+ *
+ */
+int
+_rtgeom_tpsnap_ptarray_add(const RTCTX *ctx, RTPOINTARRAY *pa,
+                  rtgeom_tpsnap_state *state)
+{
+  int ret;
+  int lookingForSnap = 1;
+  while (lookingForSnap)
+  {
+    int foundSnap;
+    RTT_SNAPV_ARRAY vset;
+    RTT_VPAIR_ARRAY vplist;
+
+    lookingForSnap = 0;
+    RTT_SNAPV_ARRAY_INIT(ctx, &vset);
+    RTT_VPAIR_ARRAY_INIT(ctx, &vplist);
+
+    ret = _rt_find_vertices_within_dist(&vset, pa, state);
+    if ( ret < 0 ) {
+      RTT_SNAPV_ARRAY_CLEAN(ctx, &vset);
+      RTT_VPAIR_ARRAY_CLEAN(ctx, &vplist);
+      return -1;
+    }
+    RTDEBUGF(ctx, 1, "vertices within dist: %d", vset.size);
+    if ( vset.size < 2 ) {
+      RTT_SNAPV_ARRAY_CLEAN(ctx, &vset);
+      RTT_VPAIR_ARRAY_CLEAN(ctx, &vplist);
+      break;
+    }
+
+    ret = _rt_make_sorted_vertices_pairs(ctx, &vset, &vplist);
+    if ( ret < 0 ) {
+      RTT_SNAPV_ARRAY_CLEAN(ctx, &vset);
+      RTT_VPAIR_ARRAY_CLEAN(ctx, &vplist);
+      return -1;
+    }
+    RTDEBUGF(ctx, 1, "vertices pairs: %d", vplist->size);
+
+    foundSnap = _rt_snap_to_first_valid_pair(ctx, pa, &vplist, state);
+    RTDEBUGF(ctx, 1, "foundSnap: %d", foundSnap);
+
+    RTT_SNAPV_ARRAY_CLEAN(ctx, &vset);
+    RTT_VPAIR_ARRAY_CLEAN(ctx, &vplist);
+
+    if ( foundSnap < 0 ) return foundSnap; /* error */
+    if ( foundSnap && state->iterate ) {
+      lookingForSnap = 1;
+    }
+  }
+
+  return 0;
+}
+
+/*
+ * Process a single pointarray with the snap algorithm
+ *
+ * @return 0 on success, -1 on error.
+ */
+int
+_rtgeom_tpsnap_ptarray(const RTCTX *ctx, RTPOINTARRAY *pa,
+                  void *udata)
+{
+  int ret;
+  rtgeom_tpsnap_state *state = udata;
+
+  if ( state->remove_vertices )
+  {
+    ret = _rtgeom_tpsnap_ptarray_remove(ctx, pa, state);
+    if ( ret != 0 ) return ret;
+  }
+
+  ret = _rtgeom_tpsnap_ptarray_add(ctx, pa, state);
+  return ret;
+
+}
+
+
+/* public, exported */
+RTGEOM *
+rtt_tpsnap(RTT_TOPOLOGY *topo, const RTGEOM *gin,
+                         double tssnap, int iterate, int remove_vertices)
+{
+  rtgeom_tpsnap_state state;
+  const RTCTX *ctx = topo->be_iface->ctx;
+  RTGEOM *gtmp = rtgeom_clone_deep(ctx, gin);
+  int ret;
+
+  state.topo = topo;
+  state.tssnap = tssnap;
+  state.iterate = iterate;
+  state.remove_vertices = remove_vertices;
+  state.workext = *rtgeom_get_bbox(ctx, gin);
+  state.workedges = NULL;
+
+  ret = rtgeom_visit_lines(ctx, gtmp, _rtgeom_tpsnap_ptarray, &state);
+
+  rtgeom_tpsnap_state_destroy(&state);
+
+  if ( ret ) {
+    rtgeom_free(ctx, gtmp);
+    return NULL;
+  }
+
+  return gtmp;
+}
diff --git a/src/rttree.c b/src/rttree.c
index 370f58f..5ae38dc 100644
--- a/src/rttree.c
+++ b/src/rttree.c
@@ -79,15 +79,15 @@ int rect_tree_contains_point(const RTCTX *ctx, const RECT_NODE *node, const RTPO
 
 int rect_tree_intersects_tree(const RTCTX *ctx, const RECT_NODE *n1, const RECT_NODE *n2)
 {
-  RTDEBUGF(4,"n1 (%.9g %.9g,%.9g %.9g) vs n2 (%.9g %.9g,%.9g %.9g)",n1->xmin,n1->ymin,n1->xmax,n1->ymax,n2->xmin,n2->ymin,n2->xmax,n2->ymax);
+  RTDEBUGF(ctx, 4,"n1 (%.9g %.9g,%.9g %.9g) vs n2 (%.9g %.9g,%.9g %.9g)",n1->xmin,n1->ymin,n1->xmax,n1->ymax,n2->xmin,n2->ymin,n2->xmax,n2->ymax);
   /* There can only be an edge intersection if the rectangles overlap */
   if ( ! ( FP_GT(n1->xmin, n2->xmax) || FP_GT(n2->xmin, n1->xmax) || FP_GT(n1->ymin, n2->ymax) || FP_GT(n2->ymin, n1->ymax) ) )
   {
-    RTDEBUG(4," interaction found");
+    RTDEBUG(ctx, 4," interaction found");
     /* We can only test for a true intersection if the nodes are both leaf nodes */
     if ( rect_node_is_leaf(ctx, n1) && rect_node_is_leaf(ctx, n2) )
     {
-      RTDEBUG(4,"  leaf node test");
+      RTDEBUG(ctx, 4,"  leaf node test");
       /* Check for true intersection */
       if ( rt_segment_intersects(ctx, n1->p1, n1->p2, n2->p1, n2->p2) )
         return RT_TRUE;
@@ -96,7 +96,7 @@ int rect_tree_intersects_tree(const RTCTX *ctx, const RECT_NODE *n1, const RECT_
     }
     else
     {
-      RTDEBUG(4,"  internal node found, recursing");
+      RTDEBUG(ctx, 4,"  internal node found, recursing");
       /* Recurse to children */
       if ( rect_node_is_leaf(ctx, n1) )
       {
@@ -116,7 +116,7 @@ int rect_tree_intersects_tree(const RTCTX *ctx, const RECT_NODE *n1, const RECT_
   }
   else
   {
-    RTDEBUG(4," no interaction found");
+    RTDEBUG(ctx, 4," no interaction found");
     return RT_FALSE;
   }
 }
diff --git a/src/rttriangle.c b/src/rttriangle.c
index f7ff313..20950eb 100644
--- a/src/rttriangle.c
+++ b/src/rttriangle.c
@@ -99,7 +99,7 @@ void printRTTRIANGLE(const RTCTX *ctx, RTTRIANGLE *triangle)
 RTTRIANGLE *
 rttriangle_clone(const RTCTX *ctx, const RTTRIANGLE *g)
 {
-  RTDEBUGF(2, "rttriangle_clone called with %p", g);
+  RTDEBUGF(ctx, 2, "rttriangle_clone called with %p", g);
   return (RTTRIANGLE *)rtline_clone(ctx, (const RTLINE *)g);
 }
 
@@ -128,7 +128,7 @@ char
 rttriangle_same(const RTCTX *ctx, const RTTRIANGLE *t1, const RTTRIANGLE *t2)
 {
   char r = ptarray_same(ctx, t1->points, t2->points);
-  RTDEBUGF(5, "returning %d", r);
+  RTDEBUGF(ctx, 5, "returning %d", r);
   return r;
 }
 
diff --git a/src/rtutil.c b/src/rtutil.c
index 6ecd29d..5137ca1 100644
--- a/src/rtutil.c
+++ b/src/rtutil.c
@@ -18,7 +18,7 @@
  *
  **********************************************************************
  *
- * Copyright (C) 2004-2016 Sandro Santilli <strk at keybit.net>
+ * Copyright (C) 2004-2016 Sandro Santilli <strk at kbt.io>
  * Copyright (C) 2006 Mark Leslie <mark.leslie at lisasoft.com>
  * Copyright (C) 2008-2009 Mark Cave-Ayland <mark.cave-ayland at siriusit.co.uk>
  * Copyright (C) 2009-2015 Paul Ramsey <pramsey at cleverelephant.ca>
@@ -244,14 +244,14 @@ void *
 rtalloc(const RTCTX *ctx, size_t size)
 {
   void *mem = ctx->rtalloc_var(size);
-  RTDEBUGF(5, "rtalloc: %d@%p", size, mem);
+  RTDEBUGF(ctx, 5, "rtalloc: %d@%p", size, mem);
   return mem;
 }
 
 void *
 rtrealloc(const RTCTX *ctx, void *mem, size_t size)
 {
-  RTDEBUGF(5, "rtrealloc: %d@%p", size, mem);
+  RTDEBUGF(ctx, 5, "rtrealloc: %d@%p", size, mem);
   return ctx->rtrealloc_var(mem, size);
 }
 
@@ -272,12 +272,12 @@ trim_trailing_zeros(const RTCTX *ctx, char *str)
   int len;
   int i;
 
-  RTDEBUGF(3, "input: %s", str);
+  RTDEBUGF(ctx, 3, "input: %s", str);
 
   ptr = strchr(str, '.');
   if ( ! ptr ) return; /* no dot, no decimal digits */
 
-  RTDEBUGF(3, "ptr: %s", ptr);
+  RTDEBUGF(ctx, 3, "ptr: %s", ptr);
 
   len = strlen(ptr);
   for (i=len-1; i; i--)
@@ -291,7 +291,7 @@ trim_trailing_zeros(const RTCTX *ctx, char *str)
     else *totrim = '\0';
   }
 
-  RTDEBUGF(3, "output: %s", str);
+  RTDEBUGF(ctx, 3, "output: %s", str);
 }
 
 /*
diff --git a/src/varint.c b/src/varint.c
index a1b48c9..dc465a3 100644
--- a/src/varint.c
+++ b/src/varint.c
@@ -18,7 +18,7 @@
  *
  **********************************************************************
  *
- * Copyright (C) 2014 Sandro Santilli <strk at keybit.net>
+ * Copyright (C) 2014 Sandro Santilli <strk at kbt.io>
  * Copyright (C) 2013 Nicklas Avén
  *
  **********************************************************************/
diff --git a/src/varint.h b/src/varint.h
index 97cd293..1100d6e 100644
--- a/src/varint.h
+++ b/src/varint.h
@@ -18,7 +18,7 @@
  *
  **********************************************************************
  *
- * Copyright (C) 2014 Sandro Santilli <strk at keybit.net>
+ * Copyright (C) 2014 Sandro Santilli <strk at kbt.io>
  * Copyright (C) 2013 Nicklas Avén
  *
  **********************************************************************/

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-grass/librttopo.git



More information about the Pkg-grass-devel mailing list