[geos-commits] [SCM] GEOS branch master updated. 9dfef81cb651449287f95ea67510bfcdc03924a0

git at osgeo.org git at osgeo.org
Mon Jan 25 15:56:48 PST 2021


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GEOS".

The branch, master has been updated
       via  9dfef81cb651449287f95ea67510bfcdc03924a0 (commit)
       via  230df6e52151dfb7adef7165fa0256c12d2ac6ae (commit)
      from  15954750ae442e132b36a0bbdd6d4157455184a8 (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 9dfef81cb651449287f95ea67510bfcdc03924a0
Merge: 230df6e 1595475
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Mon Jan 25 15:56:39 2021 -0800

    Merge branch 'master' of https://git.osgeo.org/gitea/geos/geos


commit 230df6e52151dfb7adef7165fa0256c12d2ac6ae
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Mon Jan 25 15:56:16 2021 -0800

    Add example of using the CAPI Strtree.

diff --git a/examples/CMakeLists.txt b/examples/CMakeLists.txt
index c72e8c5..8e6f5e6 100644
--- a/examples/CMakeLists.txt
+++ b/examples/CMakeLists.txt
@@ -16,11 +16,14 @@ find_package(GEOS 3.9 REQUIRED)
 add_executable(cpp_read cpp_read.cpp)
 target_link_libraries(cpp_read PRIVATE GEOS::geos)
 
-add_executable(capi_read capi_read.cpp)
+add_executable(capi_read capi_read.c)
 target_link_libraries(capi_read PRIVATE GEOS::geos_c)
 
-add_executable(capi_prepared capi_prepared.cpp)
+add_executable(capi_prepared capi_prepared.c)
 target_link_libraries(capi_prepared PRIVATE GEOS::geos_c)
 
-add_executable(capi_read_ts capi_read_ts.cpp)
+add_executable(capi_strtree capi_strtree.c)
+target_link_libraries(capi_strtree PRIVATE GEOS::geos_c)
+
+add_executable(capi_read_ts capi_read_ts.c)
 target_link_libraries(capi_read_ts PRIVATE GEOS::geos_c)
diff --git a/examples/README.md b/examples/README.md
index e4622fc..de3e474 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -3,8 +3,10 @@
 * `capi_read` uses the standard C API to read two WKT geometries, calculate the intersection and print the result
 * `capi_read_ts` uses the "re-entrant" C API (threadsafe) to read two WKT geometries, calculate the intersection and print the result
 * `capi_prepared` uses the standard C API to read one WKT geometry, and fill it with a point grid, applying a high performance "prepared" geometry to speed up intersection testing
+* `capi_strtree` uses the standard C API to build a random collection of points, and then search that collection quickly to find the nearest to a query point
 * `cpp_read` uses the C++ API to read two WKT geometries, calculate the intersection and print the result
 
+
 ## Build
 
 To build the examples _in situ_:
@@ -39,4 +41,3 @@ cc -I/usr/local/include \
     -L/usr/local/lib \
     -lgeos
 ```
-
diff --git a/examples/capi_prepared.cpp b/examples/capi_prepared.cpp
new file mode 100644
index 0000000..a1ffd12
--- /dev/null
+++ b/examples/capi_prepared.cpp
@@ -0,0 +1,137 @@
+/*
+* # GEOS C API example 2
+*
+* Reads one geometry and does a high-performance
+* prepared geometry operations to place random
+* points inside it.
+*/
+
+/* To print to stdout */
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+/* Only the CAPI header is required */
+#include <geos_c.h>
+
+/*
+* GEOS requires two message handlers to return
+* error and notice message to the calling program.
+*
+*   typedef void(* GEOSMessageHandler) (const char *fmt,...)
+*
+* Here we stub out an example that just prints the
+* messages to stdout.
+*/
+static void
+geos_message_handler(const char* fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    vprintf (fmt, ap);
+    va_end(ap);
+}
+
+
+int main()
+{
+    /* Send notice and error messages to our stdout handler */
+    initGEOS(geos_message_handler, geos_message_handler);
+
+    /* One concave polygon */
+    const char* wkt = "POLYGON ((189 115, 200 170, 130 170, 35 242, 156 215, 210 290, 274 256, 360 190, 267 215, 300 50, 200 60, 189 115))";
+
+    /* Read the WKT into geometry objects */
+    GEOSWKTReader* reader = GEOSWKTReader_create();
+    GEOSGeometry* geom = GEOSWKTReader_read(reader, wkt);
+    GEOSWKTReader_destroy(reader);
+
+    /* Check for parse success */
+    if (!geom) {
+        finishGEOS();
+        return 1;
+    }
+
+    /* Prepare the geometry */
+    const GEOSPreparedGeometry* prep_geom = GEOSPrepare(geom);
+
+    /* Read bounds of geometry */
+    double xmin, xmax, ymin, ymax;
+    GEOSGeom_getXMin(geom, &xmin);
+    GEOSGeom_getXMax(geom, &xmax);
+    GEOSGeom_getYMin(geom, &ymin);
+    GEOSGeom_getYMax(geom, &ymax);
+
+    /*
+    * Set up the point generator
+    * Generate all the points in the bounding box
+    * of the input polygon.
+    */
+    const int steps = 10;
+    double xstep = (xmax - xmin) / steps;
+    double ystep = (ymax - ymin) / steps;
+
+    /* Place to hold points to output */
+    GEOSGeometry** geoms = (GEOSGeometry**)malloc(steps*steps*sizeof(GEOSGeometry*));
+    size_t ngeoms = 0;
+
+    /*
+    * Test all the points in the polygon bounding box
+    * and only keep those that intersect the actual polygon
+    */
+    int i, j;
+    for (i = 0; i < steps; i++) {
+        for (j = 0; j < steps; j++) {
+            /* Make a point in the point grid */
+            GEOSGeometry* pt = GEOSGeom_createPointFromXY(
+                                    xmin + xstep*i,
+                                    ymin + ystep*j);
+            /* Check if the point and polygon intersect */
+            if (GEOSPreparedIntersects(prep_geom, pt)) {
+                /* Save the ones that do */
+                geoms[ngeoms++] = pt;
+            }
+            else {
+                /* Clean up the ones that don't */
+                GEOSGeom_destroy(pt);
+            }
+
+        }
+    }
+
+    /* Put the successful geoms inside a geometry for WKT output */
+    GEOSGeometry* result = GEOSGeom_createCollection(GEOS_MULTIPOINT, geoms, ngeoms);
+
+    /*
+    * The GEOSGeom_createCollection() only takes ownership of the
+    * geometries, not the array container, so we can free the container
+    * now
+    */
+    free(geoms);
+
+    /* Convert result to WKT */
+    GEOSWKTWriter* writer = GEOSWKTWriter_create();
+    /* Trim trailing zeros off output */
+    GEOSWKTWriter_setTrim(writer, 1);
+    GEOSWKTWriter_setRoundingPrecision(writer, 3);
+    char* wkt_result = GEOSWKTWriter_write(writer, result);
+    GEOSWKTWriter_destroy(writer);
+
+    /* Print answer */
+    printf("Input Polygon:\n");
+    printf("%s\n\n", wkt);
+    printf("Output Points:\n");
+    printf("%s\n\n", wkt_result);
+
+    /* Clean up everything we allocated */
+    GEOSPreparedGeom_destroy(prep_geom);
+    GEOSGeom_destroy(geom);
+    GEOSGeom_destroy(result);
+    GEOSFree(wkt_result);
+
+    /* Clean up the global context */
+    finishGEOS();
+
+    /* Done */
+    return 0;
+}
diff --git a/examples/capi_read.cpp b/examples/capi_read.cpp
new file mode 100644
index 0000000..691dd9b
--- /dev/null
+++ b/examples/capi_read.cpp
@@ -0,0 +1,75 @@
+/*
+* # GEOS C API example 1
+*
+* Reads two WKT representations and calculates the
+* intersection, prints it out, and cleans up.
+*/
+
+/* To print to stdout */
+#include <stdio.h>
+#include <stdarg.h>
+
+/* Only the CAPI header is required */
+#include <geos_c.h>
+
+/*
+* GEOS requires two message handlers to return
+* error and notice message to the calling program.
+*
+*   typedef void(* GEOSMessageHandler) (const char *fmt,...)
+*
+* Here we stub out an example that just prints the
+* messages to stdout.
+*/
+static void
+geos_message_handler(const char* fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    vprintf (fmt, ap);
+    va_end(ap);
+}
+
+
+int main()
+{
+    /* Send notice and error messages to our stdout handler */
+    initGEOS(geos_message_handler, geos_message_handler);
+
+    /* Two squares that overlap */
+    const char* wkt_a = "POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))";
+    const char* wkt_b = "POLYGON((5 5, 15 5, 15 15, 5 15, 5 5))";
+
+    /* Read the WKT into geometry objects */
+    GEOSWKTReader* reader = GEOSWKTReader_create();
+    GEOSGeometry* geom_a = GEOSWKTReader_read(reader, wkt_a);
+    GEOSGeometry* geom_b = GEOSWKTReader_read(reader, wkt_b);
+
+    /* Calculate the intersection */
+    GEOSGeometry* inter = GEOSIntersection(geom_a, geom_b);
+
+    /* Convert result to WKT */
+    GEOSWKTWriter* writer = GEOSWKTWriter_create();
+    /* Trim trailing zeros off output */
+    GEOSWKTWriter_setTrim(writer, 1);
+    char* wkt_inter = GEOSWKTWriter_write(writer, inter);
+
+    /* Print answer */
+    printf("Geometry A:         %s\n", wkt_a);
+    printf("Geometry B:         %s\n", wkt_b);
+    printf("Intersection(A, B): %s\n", wkt_inter);
+
+    /* Clean up everything we allocated */
+    GEOSWKTReader_destroy(reader);
+    GEOSWKTWriter_destroy(writer);
+    GEOSGeom_destroy(geom_a);
+    GEOSGeom_destroy(geom_b);
+    GEOSGeom_destroy(inter);
+    GEOSFree(wkt_inter);
+
+    /* Clean up the global context */
+    finishGEOS();
+
+    /* Done */
+    return 0;
+}
diff --git a/examples/capi_read_ts.cpp b/examples/capi_read_ts.cpp
new file mode 100644
index 0000000..b351159
--- /dev/null
+++ b/examples/capi_read_ts.cpp
@@ -0,0 +1,86 @@
+/*
+* # GEOS C API example 2
+*
+* Thread-safe version of example 1. Uses the
+* re-entrant API.
+* Reads two WKT representations and calculates the
+* intersection, prints it out, and cleans up.
+*/
+
+/* To print to stdout */
+#include <stdio.h>
+#include <stdarg.h>
+
+/* Only the CAPI header is required */
+#include <geos_c.h>
+
+/*
+* GEOS requires two message handlers to return
+* error and notice message to the calling program.
+*
+*   typedef void(* GEOSMessageHandler) (const char *fmt,...)
+*
+* Here we stub out an example that just prints the
+* messages to stdout.
+*/
+static void
+geos_message_handler(const char* fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    vprintf (fmt, ap);
+    va_end(ap);
+}
+
+
+int main()
+{
+    /*
+    * Each thread using the re-entrant API must get its
+    * own context handle
+    */
+    GEOSContextHandle_t context = GEOS_init_r();
+    /*
+    * The notice/error handlers route message back to the calling
+    * application. Here they just print to stdout.
+    */
+    GEOSContext_setNoticeHandler_r(context, geos_message_handler);
+    GEOSContext_setErrorHandler_r(context, geos_message_handler);
+
+    /* Two squares that overlap */
+    const char* wkt_a = "POLYGON((0 0, 10 0, 10 10, 0 10, 0 0))";
+    const char* wkt_b = "POLYGON((5 5, 15 5, 15 15, 5 15, 5 5))";
+
+    /* Read the WKT into geometry objects */
+    GEOSWKTReader* reader = GEOSWKTReader_create_r(context);
+    GEOSGeometry* geom_a = GEOSWKTReader_read_r(context, reader, wkt_a);
+    GEOSGeometry* geom_b = GEOSWKTReader_read_r(context, reader, wkt_b);
+
+    /* Calculate the intersection */
+    GEOSGeometry* inter = GEOSIntersection_r(context, geom_a, geom_b);
+
+    /* Convert result to WKT */
+    GEOSWKTWriter* writer = GEOSWKTWriter_create_r(context);
+    /* Trim trailing zeros off output */
+    GEOSWKTWriter_setTrim(writer, 1);
+    char* wkt_inter = GEOSWKTWriter_write_r(context, writer, inter);
+
+    /* Print answer */
+    printf("Geometry A:         %s\n", wkt_a);
+    printf("Geometry B:         %s\n", wkt_b);
+    printf("Intersection(A, B): %s\n", wkt_inter);
+
+    /* Clean up everything we allocated */
+    GEOSWKTReader_destroy_r(context, reader);
+    GEOSWKTWriter_destroy_r(context, writer);
+    GEOSGeom_destroy_r(context, geom_a);
+    GEOSGeom_destroy_r(context, geom_b);
+    GEOSGeom_destroy_r(context, inter);
+    GEOSFree_r(context, wkt_inter);
+
+    /* Clean up the global context */
+    GEOS_finish_r(context);
+
+    /* Done */
+    return 0;
+}
diff --git a/examples/capi_strtree.c b/examples/capi_strtree.c
new file mode 100644
index 0000000..f654bfb
--- /dev/null
+++ b/examples/capi_strtree.c
@@ -0,0 +1,118 @@
+/*
+* # GEOS C API example 3
+*
+* Build a spatial index and search it for a
+* nearest pair.
+*/
+
+/* To print to stdout */
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+
+/* Only the CAPI header is required */
+#include <geos_c.h>
+
+/*
+* GEOS requires two message handlers to return
+* error and notice message to the calling program.
+*
+*   typedef void(* GEOSMessageHandler) (const char *fmt,...)
+*
+* Here we stub out an example that just prints the
+* messages to stdout.
+*/
+static void
+geos_message_handler(const char* fmt, ...)
+{
+    va_list ap;
+    va_start(ap, fmt);
+    vprintf (fmt, ap);
+    va_end(ap);
+}
+
+/*
+* Generate a random point in the range of
+* POINT(0..range, 0..range). Caller must
+* free.
+*/
+static GEOSGeometry*
+geos_random_point(double range)
+{
+    double x = range * rand() / RAND_MAX;
+    double y = range * rand() / RAND_MAX;
+    /* Make a point in the point grid */
+    return GEOSGeom_createPointFromXY(x, y);
+}
+
+
+int main()
+{
+    /* Send notice and error messages to our stdout handler */
+    initGEOS(geos_message_handler, geos_message_handler);
+
+    /* How many points to add to our random field */
+    const size_t npoints = 10000;
+    /* The coordinate range of the field (0->100.0) */
+    const double range = 100.0;
+
+    /*
+    * The tree doesn't take ownership of inputs just
+    * holds references, so we keep our point field
+    * handy in an array
+    */
+    GEOSGeometry* geoms[npoints];
+    /*
+    * The create parameter for the tree is not the
+    * number of inputs, it is the number of entries
+    * per node. 10 is a good default number to use.
+    */
+    GEOSSTRtree* tree = GEOSSTRtree_create(10);
+    for (size_t i = 0; i < npoints; i++) {
+        /* Make a random point */
+        GEOSGeometry* geom = geos_random_point(range);
+        /* Store away a reference so we can free it after */
+        geoms[i] = geom;
+        /* Add an entry for it to the tree */
+        GEOSSTRtree_insert(tree, geom, geom);
+    }
+
+    /* Random point to compare to the field */
+    GEOSGeometry* geom_random = geos_random_point(range);
+    /* Nearest point in the field to our test point */
+    const GEOSGeometry* geom_nearest = GEOSSTRtree_nearest(tree, geom_random);
+
+    /* Convert results to WKT */
+    GEOSWKTWriter* writer = GEOSWKTWriter_create();
+    /* Trim trailing zeros off output */
+    GEOSWKTWriter_setTrim(writer, 1);
+    GEOSWKTWriter_setRoundingPrecision(writer, 3);
+    char* wkt_random = GEOSWKTWriter_write(writer, geom_random);
+    char* wkt_nearest = GEOSWKTWriter_write(writer, geom_nearest);
+    GEOSWKTWriter_destroy(writer);
+
+    /* Print answer */
+    printf(" Random Point: %s\n", wkt_random);
+    printf("Nearest Point: %s\n", wkt_nearest);
+
+    /* Clean up all allocated objects */
+    /* Destroying tree does not destroy inputs */
+    GEOSSTRtree_destroy(tree);
+    GEOSGeom_destroy(geom_random);
+    /* Destroy all the points in our random field */
+    for (size_t i = 0; i < npoints; i++) {
+        GEOSGeom_destroy(geoms[i]);
+    }
+    /*
+    * Don't forget to free memory allocated by the
+    * printing functions!
+    */
+    GEOSFree(wkt_random);
+    GEOSFree(wkt_nearest);
+
+    /* Clean up the global context */
+    finishGEOS();
+
+    /* Done */
+    return 0;
+}

-----------------------------------------------------------------------

Summary of changes:
 examples/CMakeLists.txt                         |   9 +-
 examples/README.md                              |   3 +-
 examples/{capi_prepared.c => capi_prepared.cpp} |   0
 examples/{capi_read.c => capi_read.cpp}         |   0
 examples/{capi_read_ts.c => capi_read_ts.cpp}   |   0
 examples/capi_strtree.c                         | 118 ++++++++++++++++++++++++
 6 files changed, 126 insertions(+), 4 deletions(-)
 copy examples/{capi_prepared.c => capi_prepared.cpp} (100%)
 copy examples/{capi_read.c => capi_read.cpp} (100%)
 copy examples/{capi_read_ts.c => capi_read_ts.cpp} (100%)
 create mode 100644 examples/capi_strtree.c


hooks/post-receive
-- 
GEOS


More information about the geos-commits mailing list