[geos-commits] [SCM] GEOS branch master updated. 8a5d8bac9efde79ef983e0e49683fb16a291ac2c

git at osgeo.org git at osgeo.org
Thu Feb 25 17:27:17 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  8a5d8bac9efde79ef983e0e49683fb16a291ac2c (commit)
       via  c655bb7f1d990e2a8f2560274816dfdb86058417 (commit)
       via  a9d98fa3ff0703fc2dc2169fbf940ad603dda60a (commit)
       via  12e415963cb7d50d473059c722ce0e58d8b7af42 (commit)
       via  35603df5397172e10b32209d00f4ccc950e3adf0 (commit)
       via  093232d4e35c58d79a1724a7696c42600db340a7 (commit)
       via  99030ebad9d803ea300839a615b1512fcc01669a (commit)
       via  7a6411734ad2247eb289cf47fc65fb56e0351f79 (commit)
      from  562bcb28e8b8f8683b5dc8e61347eacaab3e038e (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 8a5d8bac9efde79ef983e0e49683fb16a291ac2c
Merge: 562bcb2 c655bb7
Author: Daniel Baston <dbaston at gmail.com>
Date:   Thu Feb 25 20:27:04 2021 -0500

    Merge branch 'google-bench'


commit c655bb7f1d990e2a8f2560274816dfdb86058417
Author: Daniel Baston <dbaston at gmail.com>
Date:   Sat Feb 20 20:05:25 2021 -0500

    Reimplment MonotoneChainBuilder as a CoordinateFilter
    
    Avoids virtual calls, improving performance by 25%.

diff --git a/benchmarks/index/chain/MonotoneChainBuilderPerfTest.cpp b/benchmarks/index/chain/MonotoneChainBuilderPerfTest.cpp
index a14dabc..5b766a0 100644
--- a/benchmarks/index/chain/MonotoneChainBuilderPerfTest.cpp
+++ b/benchmarks/index/chain/MonotoneChainBuilderPerfTest.cpp
@@ -28,18 +28,21 @@ using geos::index::chain::MonotoneChain;
 using geos::index::chain::MonotoneChainBuilder;
 
 static void BM_MonotoneChainBuilder(benchmark::State& state) {
-    MonotoneChainBuilder mcb;
-
     std::default_random_engine e(12345);
 
+    // distribution of offsets from previous vertex
     std::uniform_real_distribution<> dist(0, 1);
+
+    // determine chain lengths using a geometric distribution with a 30% probability of
+    // a vertex ending a chain.
     std::geometric_distribution<> chain_length_dist(0.3);
+
+    // distribution for determining quadrant of the next chain
     std::uniform_real_distribution<> sign_dist(-1, 1);
 
     std::size_t num_points = 1000;
 
     CoordinateArraySequence cs;
-
     Coordinate prev(0, 0);
     while(cs.size() <= num_points) {
         size_t chain_length = 1 + static_cast<size_t>(chain_length_dist(e));
diff --git a/include/geos/index/chain/MonotoneChainBuilder.h b/include/geos/index/chain/MonotoneChainBuilder.h
index 2d4bb29..684e191 100644
--- a/include/geos/index/chain/MonotoneChainBuilder.h
+++ b/include/geos/index/chain/MonotoneChainBuilder.h
@@ -49,9 +49,6 @@ namespace chain { // geos::index::chain
 class GEOS_DLL MonotoneChainBuilder {
 
 public:
-
-    MonotoneChainBuilder() {}
-
     /** \brief
      * Computes a list of the {@link MonotoneChain}s for a list of coordinates,
      * attaching a context data object to each.
@@ -70,26 +67,6 @@ public:
      */
     MonotoneChainBuilder(const MonotoneChainBuilder&) = delete;
     MonotoneChainBuilder& operator=(const MonotoneChainBuilder&) = delete;
-
-
-private:
-
-    /** \brief
-     * Finds the index of the last point in a monotone chain
-     * starting at a given point.
-     *
-     * Repeated points (0-length segments) are included
-     * in the monotone chain returned.
-     *
-     * @param pts the points to scan
-     * @param start the index of the start of this chain
-     * @return the index of the last point in the monotone chain
-     *         starting at <code>start</code>.
-     *
-     * @note aborts if 'start' is >= pts.getSize()
-     */
-    static std::size_t findChainEnd(const geom::CoordinateSequence& pts,
-                                    std::size_t start);
 };
 
 } // namespace geos::index::chain
diff --git a/src/index/chain/MonotoneChainBuilder.cpp b/src/index/chain/MonotoneChainBuilder.cpp
index 72991e5..cadce9d 100644
--- a/src/index/chain/MonotoneChainBuilder.cpp
+++ b/src/index/chain/MonotoneChainBuilder.cpp
@@ -42,120 +42,67 @@ namespace geos {
 namespace index { // geos.index
 namespace chain { // geos.index.chain
 
-
-/* static public */
-void
-MonotoneChainBuilder::getChains(const CoordinateSequence* pts, void* context,
-                                std::vector<MonotoneChain>& mcList)
-{
-    std::size_t chainStart = 0;
-    do {
-        std::size_t chainEnd = findChainEnd(*pts, chainStart);
-        mcList.emplace_back(*pts, chainStart, chainEnd, context);
-        chainStart = chainEnd;
+/** \brief
+ * Finds the index of the last point in each monotone chain
+ * of the provided coordinate sequence.
+ */
+class ChainBuilder : public CoordinateFilter {
+public:
+    ChainBuilder() : m_prev(nullptr), m_i(0), m_quadrant(-1) {}
+
+    void filter_ro(const Coordinate* c) override final {
+        process(c);
+
+        m_prev = c;
+        m_i++;
     }
-    while (chainStart < (pts->size() - 1));
-}
-
-static std::vector<size_t> getChainEnds(const CoordinateSequence& pts) {
-    struct ChainBuilder : public CoordinateFilter {
-        ChainBuilder() : m_i(0), m_quadrant(-1) {}
 
-        const Coordinate* prev;
+    std::vector<std::size_t> getEnds() {
+        finishChain();
+        return std::move(m_ends);
+    }
 
-        void filter_ro(const Coordinate* c) override final {
-            process(m_i++, c);
-        }
+private:
+    void finishChain() {
+        m_ends.push_back(m_i - 1);
+    }
 
-        std::vector<std::size_t> getEnds() {
-            m_ends.push_back(m_i); // close last chain
-            return std::move(m_ends);
+    void process(const Coordinate* curr) {
+        if (m_prev == nullptr || curr->equals2D(*m_prev)) {
+            return;
         }
 
-        void process(std::size_t i, const Coordinate* curr) {
-            if (prev == nullptr || curr->equals2D(*prev)) {
-                prev = curr;
-                return;
-            }
-
-            int chainQuad = Quadrant::quadrant(*prev, *curr);
-
-            if (m_quadrant < 0) {
-                m_quadrant = chainQuad;
-            }
+        int currQuad = Quadrant::quadrant(*m_prev, *curr);
 
-            if (chainQuad != m_quadrant) {
-                m_ends.push_back(i);
-                m_quadrant = chainQuad;
-            }
-
-            prev = curr;
+        if (m_quadrant < 0) {
+            m_quadrant = currQuad;
         }
 
-        std::size_t m_i;
-        int m_quadrant;
-        std::vector<std::size_t> m_ends;
-    };
-
-    ChainBuilder builder;
-
-    pts.apply_ro(&builder);
-
-    return builder.getEnds();
-}
-
-
-/* private static */
-std::size_t
-MonotoneChainBuilder::findChainEnd(const CoordinateSequence& pts, std::size_t start)
-{
-
-    const std::size_t npts = pts.getSize(); // cache
-
-    assert(start < npts);
-    assert(npts); // should be implied by the assertion above,
-    // 'start' being unsigned
+        if (currQuad != m_quadrant) {
+            finishChain();
+            m_quadrant = currQuad;
+        }
+    }
 
-    std::size_t safeStart = start;
+    std::vector<std::size_t> m_ends;
+    const Coordinate* m_prev;
+    std::size_t m_i;
+    int m_quadrant;
+};
 
-    // skip any zero-length segments at the start of the sequence
-    // (since they cannot be used to establish a quadrant)
-    while(safeStart < npts - 1
-            && pts[safeStart].equals2D(pts[safeStart + 1])) {
-        ++safeStart;
-    }
 
-    // check if there are NO non-zero-length segments
-    if(safeStart >= npts - 1) {
-        return npts - 1;
-    }
+/* static public */
+void
+MonotoneChainBuilder::getChains(const CoordinateSequence* pts, void* context,
+                                std::vector<MonotoneChain>& mcList) {
+    ChainBuilder builder;
+    pts->apply_ro(&builder);
 
-    // determine overall quadrant for chain
-    // (which is the starting quadrant)
-    int chainQuad = Quadrant::quadrant(pts[safeStart],
-                                       pts[safeStart + 1]);
-
-    const Coordinate* prev; // avoid repeated coordinate access by index (virtual call)
-    const Coordinate* curr = &pts[start];
-
-    for(std::size_t last = start + 1; last < npts; last++) {
-        prev = curr;
-        curr = &pts[last];
-
-        // skip zero-length segments, but include them in the chain
-        if(!prev->equals2D(*curr)) {
-            // compute quadrant for next possible segment in chain
-            int quad = Quadrant::quadrant(*prev, *curr);
-            if(quad != chainQuad) {
-                return last - 1;
-            }
-        }
+    size_t chainStart = 0;
+    for (size_t chainEnd : builder.getEnds()) {
+        mcList.emplace_back(*pts, chainStart, chainEnd, context);
+        chainStart = chainEnd;
     }
-#if GEOS_DEBUG
-    std::cerr << "MonotoneChainBuilder::findChainEnd() returning" << std::endl;
-#endif
-
-    return npts - 1;
 }
 
 } // namespace geos.index.chain

commit a9d98fa3ff0703fc2dc2169fbf940ad603dda60a
Author: Daniel Baston <dbaston at gmail.com>
Date:   Sat Feb 20 18:34:59 2021 -0500

    Add MonotoneChainBuilder perf test

diff --git a/benchmarks/index/chain/CMakeLists.txt b/benchmarks/index/chain/CMakeLists.txt
index 98b2ed9..e1a784b 100644
--- a/benchmarks/index/chain/CMakeLists.txt
+++ b/benchmarks/index/chain/CMakeLists.txt
@@ -18,4 +18,11 @@ IF(benchmark_FOUND)
             $<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/include>)
     target_link_libraries(perf_monotone_chain PRIVATE
             benchmark::benchmark geos)
+
+    add_executable(perf_monotone_chain_builder MonotoneChainBuilderPerfTest.cpp)
+    target_include_directories(perf_monotone_chain_builder PUBLIC
+            $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include>
+            $<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/include>)
+    target_link_libraries(perf_monotone_chain_builder PRIVATE
+            benchmark::benchmark geos)
 endif()
diff --git a/benchmarks/index/chain/MonotoneChainBuilderPerfTest.cpp b/benchmarks/index/chain/MonotoneChainBuilderPerfTest.cpp
new file mode 100644
index 0000000..a14dabc
--- /dev/null
+++ b/benchmarks/index/chain/MonotoneChainBuilderPerfTest.cpp
@@ -0,0 +1,66 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2021 Daniel Baston
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU Lesser General Public Licence as published
+ * by the Free Software Foundation.
+ * See the COPYING file for more information.
+ *
+ **********************************************************************/
+
+#include <random>
+
+#include <benchmark/benchmark.h>
+
+#include <geos/geom/CoordinateArraySequence.h>
+#include <geos/index/chain/MonotoneChain.h>
+#include <geos/index/chain/MonotoneChainBuilder.h>
+
+using geos::geom::Coordinate;
+using geos::geom::LineSegment;
+using geos::geom::CoordinateArraySequence;
+using geos::geom::Envelope;
+using geos::index::chain::MonotoneChain;
+using geos::index::chain::MonotoneChainBuilder;
+
+static void BM_MonotoneChainBuilder(benchmark::State& state) {
+    MonotoneChainBuilder mcb;
+
+    std::default_random_engine e(12345);
+
+    std::uniform_real_distribution<> dist(0, 1);
+    std::geometric_distribution<> chain_length_dist(0.3);
+    std::uniform_real_distribution<> sign_dist(-1, 1);
+
+    std::size_t num_points = 1000;
+
+    CoordinateArraySequence cs;
+
+    Coordinate prev(0, 0);
+    while(cs.size() <= num_points) {
+        size_t chain_length = 1 + static_cast<size_t>(chain_length_dist(e));
+
+        double xsign = sign_dist(e) > 0 ? 1 : -1;
+        double ysign = sign_dist(e) > 0 ? 1 : -1;
+
+        for (size_t k = 0; k < chain_length && cs.size() <= num_points; k++) {
+            Coordinate c(prev.x + xsign * dist(e),
+                         prev.y + ysign * dist(e));
+            cs.add(c);
+            prev = c;
+        }
+    }
+
+    for (auto _ : state) {
+        std::vector<MonotoneChain> chains;
+        MonotoneChainBuilder::getChains(&cs, nullptr, chains);
+    }
+}
+
+BENCHMARK(BM_MonotoneChainBuilder);
+
+BENCHMARK_MAIN();
diff --git a/src/index/chain/MonotoneChainBuilder.cpp b/src/index/chain/MonotoneChainBuilder.cpp
index a23b2b4..72991e5 100644
--- a/src/index/chain/MonotoneChainBuilder.cpp
+++ b/src/index/chain/MonotoneChainBuilder.cpp
@@ -19,8 +19,10 @@
 #include <geos/index/chain/MonotoneChainBuilder.h>
 #include <geos/index/chain/MonotoneChain.h>
 #include <geos/geom/CoordinateSequence.h>
+#include <geos/geom/CoordinateFilter.h>
 #include <geos/geom/Quadrant.h>
 
+
 #include <cassert>
 #include <cstdio>
 #include <vector>
@@ -55,6 +57,53 @@ MonotoneChainBuilder::getChains(const CoordinateSequence* pts, void* context,
     while (chainStart < (pts->size() - 1));
 }
 
+static std::vector<size_t> getChainEnds(const CoordinateSequence& pts) {
+    struct ChainBuilder : public CoordinateFilter {
+        ChainBuilder() : m_i(0), m_quadrant(-1) {}
+
+        const Coordinate* prev;
+
+        void filter_ro(const Coordinate* c) override final {
+            process(m_i++, c);
+        }
+
+        std::vector<std::size_t> getEnds() {
+            m_ends.push_back(m_i); // close last chain
+            return std::move(m_ends);
+        }
+
+        void process(std::size_t i, const Coordinate* curr) {
+            if (prev == nullptr || curr->equals2D(*prev)) {
+                prev = curr;
+                return;
+            }
+
+            int chainQuad = Quadrant::quadrant(*prev, *curr);
+
+            if (m_quadrant < 0) {
+                m_quadrant = chainQuad;
+            }
+
+            if (chainQuad != m_quadrant) {
+                m_ends.push_back(i);
+                m_quadrant = chainQuad;
+            }
+
+            prev = curr;
+        }
+
+        std::size_t m_i;
+        int m_quadrant;
+        std::vector<std::size_t> m_ends;
+    };
+
+    ChainBuilder builder;
+
+    pts.apply_ro(&builder);
+
+    return builder.getEnds();
+}
+
 
 /* private static */
 std::size_t

commit 12e415963cb7d50d473059c722ce0e58d8b7af42
Author: Daniel Baston <dbaston at gmail.com>
Date:   Thu Feb 18 20:55:29 2021 -0500

    Add IndexedPointInAreaLocator benchmark (WIP)

diff --git a/benchmarks/algorithm/CMakeLists.txt b/benchmarks/algorithm/CMakeLists.txt
index 725c4ba..d9c8cbc 100644
--- a/benchmarks/algorithm/CMakeLists.txt
+++ b/benchmarks/algorithm/CMakeLists.txt
@@ -37,3 +37,5 @@ if (benchmark_FOUND)
     target_link_libraries(perf_line_intersector PRIVATE
             benchmark::benchmark geos)
 endif()
+
+add_subdirectory(locate)
diff --git a/benchmarks/algorithm/locate/CMakeLists.txt b/benchmarks/algorithm/locate/CMakeLists.txt
new file mode 100644
index 0000000..b4cd9f3
--- /dev/null
+++ b/benchmarks/algorithm/locate/CMakeLists.txt
@@ -0,0 +1,22 @@
+#################################################################################
+#
+# CMake configuration for GEOS benchmarks/operation/predicate tests
+#
+# Copyright (C) 2017 Mateusz Loskot <mateusz at loskot.net>
+#
+# This is free software; you can redistribute and/or modify it under
+# the terms of the GNU Lesser General Public Licence as published
+# by the Free Software Foundation.
+# See the COPYING file for more information.
+#
+#################################################################################
+
+find_package(benchmark)
+if (benchmark_FOUND)
+    add_executable(perf_indexed_point_in_area_locator IndexedPointInAreaLocatorPerfTest.cpp)
+    target_include_directories(perf_indexed_point_in_area_locator PUBLIC
+            $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include>
+            $<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/include>)
+    target_link_libraries(perf_indexed_point_in_area_locator PRIVATE
+            benchmark::benchmark geos)
+endif()
diff --git a/benchmarks/algorithm/locate/IndexedPointInAreaLocatorPerfTest.cpp b/benchmarks/algorithm/locate/IndexedPointInAreaLocatorPerfTest.cpp
new file mode 100644
index 0000000..72dab37
--- /dev/null
+++ b/benchmarks/algorithm/locate/IndexedPointInAreaLocatorPerfTest.cpp
@@ -0,0 +1,51 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2021 Daniel Baston
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU Lesser General Public Licence as published
+ * by the Free Software Foundation.
+ * See the COPYING file for more information.
+ *
+ **********************************************************************/
+
+#include <random>
+
+#include <benchmark/benchmark.h>
+
+#include <geos/algorithm/locate/IndexedPointInAreaLocator.h>
+#include <geos/geom/GeometryFactory.h>
+#include <geos/geom/util/Densifier.h>
+#include <geos/geom/util/SineStarFactory.h>
+
+using geos::geom::Coordinate;
+using geos::geom::GeometryFactory;
+using geos::geom::util::SineStarFactory;
+using geos::geom::util::Densifier;
+using geos::algorithm::locate::IndexedPointInAreaLocator;
+
+static void BM_IndexedPointInAreaLocator(benchmark::State& state) {
+    auto gfact = GeometryFactory::getDefaultInstance();
+    SineStarFactory ssf(gfact);
+    auto poly = ssf.createSineStar();
+    auto geom = Densifier::densify(poly.get(), 1);
+
+    std::default_random_engine e(12345);
+    std::uniform_real_distribution<> xdist(poly->getEnvelopeInternal()->getMinX(), poly->getEnvelopeInternal()->getMaxX());
+    std::uniform_real_distribution<> ydist(poly->getEnvelopeInternal()->getMinY(), poly->getEnvelopeInternal()->getMaxY());
+
+    IndexedPointInAreaLocator ipa(*geom);
+
+    for (auto _ : state) {
+        Coordinate c(0, 0);
+        ipa.locate(&c);
+    }
+}
+
+BENCHMARK(BM_IndexedPointInAreaLocator);
+
+BENCHMARK_MAIN();
+
diff --git a/include/geos/geom/util/Densifier.h b/include/geos/geom/util/Densifier.h
index c78144a..3d88a62 100644
--- a/include/geos/geom/util/Densifier.h
+++ b/include/geos/geom/util/Densifier.h
@@ -59,7 +59,7 @@ class GEOS_DLL Densifier {
 public:
     Densifier(const Geometry* inputGeom);
 
-    Geometry::Ptr densify(const Geometry* geom, double distanceTolerance);
+    static Geometry::Ptr densify(const Geometry* geom, double distanceTolerance);
     void setDistanceTolerance(double distanceTolerance);
     Geometry::Ptr getResultGeometry() const;
 

commit 35603df5397172e10b32209d00f4ccc950e3adf0
Author: Daniel Baston <dbaston at gmail.com>
Date:   Wed Feb 17 22:15:23 2021 -0500

    Add LineIntersector perf test

diff --git a/benchmarks/algorithm/CMakeLists.txt b/benchmarks/algorithm/CMakeLists.txt
index 5533298..725c4ba 100644
--- a/benchmarks/algorithm/CMakeLists.txt
+++ b/benchmarks/algorithm/CMakeLists.txt
@@ -29,4 +29,11 @@ if (benchmark_FOUND)
             $<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/include>)
     target_link_libraries(perf_orientation PRIVATE
             benchmark::benchmark geos_cxx_flags)
+
+    add_executable(perf_line_intersector LineIntersectorPerfTest.cpp)
+    target_include_directories(perf_line_intersector PUBLIC
+            $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include>
+            $<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/include>)
+    target_link_libraries(perf_line_intersector PRIVATE
+            benchmark::benchmark geos)
 endif()
diff --git a/benchmarks/algorithm/LineIntersectorPerfTest.cpp b/benchmarks/algorithm/LineIntersectorPerfTest.cpp
new file mode 100644
index 0000000..91c4120
--- /dev/null
+++ b/benchmarks/algorithm/LineIntersectorPerfTest.cpp
@@ -0,0 +1,50 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2021 Daniel Baston
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU Lesser General Public Licence as published
+ * by the Free Software Foundation.
+ * See the COPYING file for more information.
+ *
+ **********************************************************************/
+
+#include <benchmark/benchmark.h>
+
+#include <geos/algorithm/LineIntersector.h>
+
+using geos::geom::Coordinate;
+using geos::algorithm::LineIntersector;
+
+static void BM_PointIntersection(benchmark::State& state) {
+    Coordinate p1(10, 10);
+    Coordinate p2(20, 20);
+    Coordinate q1(20, 10);
+    Coordinate q2(10, 20);
+
+    for (auto _ : state) {
+        LineIntersector li;
+        li.computeIntersection(p1, p2, q1, q2);
+    }
+}
+
+static void BM_Collinear(benchmark::State& state) {
+    Coordinate p1(10, 10);
+    Coordinate p2(20, 10);
+    Coordinate q1(22, 10);
+    Coordinate q2(30, 10);
+
+    for (auto _ : state) {
+        LineIntersector li;
+        li.computeIntersection(p1, p2, q1, q2);
+    }
+}
+
+BENCHMARK(BM_PointIntersection);
+//BENCHMARK(BM_Collinear);
+
+BENCHMARK_MAIN();
+

commit 093232d4e35c58d79a1724a7696c42600db340a7
Author: Daniel Baston <dbaston at gmail.com>
Date:   Wed Feb 17 19:33:13 2021 -0500

    Inline some LineIntersector methods

diff --git a/include/geos/algorithm/LineIntersector.inl b/include/geos/algorithm/LineIntersector.inl
index 56777fb..371de7b 100644
--- a/include/geos/algorithm/LineIntersector.inl
+++ b/include/geos/algorithm/LineIntersector.inl
@@ -21,7 +21,9 @@
 #define GEOS_ALGORITHM_LINEINTERSECTOR_INL
 
 #include <geos/algorithm/LineIntersector.h>
+#include <geos/algorithm/Intersection.h>
 #include <geos/geom/Coordinate.h>
+#include <geos/geom/Envelope.h>
 
 namespace geos {
 namespace algorithm {
@@ -64,6 +66,27 @@ LineIntersector::isIntersection(const geom::Coordinate& pt) const
     return false;
 }
 
+/*private*/
+INLINE bool
+LineIntersector::isInSegmentEnvelopes(const geom::Coordinate& pt) const
+{
+    geom::Envelope env0(*inputLines[0][0], *inputLines[0][1]);
+    geom::Envelope env1(*inputLines[1][0], *inputLines[1][1]);
+    return env0.contains(pt) && env1.contains(pt);
+}
+
+/*private*/
+INLINE geom::Coordinate
+LineIntersector::intersectionSafe(const geom::Coordinate& p1, const geom::Coordinate& p2,
+                                  const geom::Coordinate& q1, const geom::Coordinate& q2) const
+{
+    geom::Coordinate ptInt = Intersection::intersection(p1, p2, q1, q2);
+    if (ptInt.isNull()) {
+        ptInt = nearestEndpoint(p1, p2, q1, q2);
+    }
+    return ptInt;
+}
+
 /* private static */
 INLINE double
 LineIntersector::zGet(const geom::Coordinate& p, const geom::Coordinate& q)
diff --git a/src/algorithm/LineIntersector.cpp b/src/algorithm/LineIntersector.cpp
index 2448a52..99a9705 100644
--- a/src/algorithm/LineIntersector.cpp
+++ b/src/algorithm/LineIntersector.cpp
@@ -564,27 +564,6 @@ LineIntersector::intersection(const Coordinate& p1, const Coordinate& p2,
     return intPtOut;
 }
 
-/*private*/
-bool
-LineIntersector::isInSegmentEnvelopes(const Coordinate& pt) const
-{
-    Envelope env0(*inputLines[0][0], *inputLines[0][1]);
-    Envelope env1(*inputLines[1][0], *inputLines[1][1]);
-    return env0.contains(pt) && env1.contains(pt);
-}
-
-/*private*/
-Coordinate
-LineIntersector::intersectionSafe(const Coordinate& p1, const Coordinate& p2,
-                                  const Coordinate& q1, const Coordinate& q2) const
-{
-    Coordinate ptInt = Intersection::intersection(p1, p2, q1, q2);
-    if (ptInt.isNull()) {
-        ptInt = nearestEndpoint(p1, p2, q1, q2);
-    }
-    return ptInt;
-}
-
 /* private static */
 double
 LineIntersector::zInterpolate(const Coordinate& p, const Coordinate& p1, const Coordinate& p2)

commit 99030ebad9d803ea300839a615b1512fcc01669a
Author: Daniel Baston <dbaston at gmail.com>
Date:   Wed Feb 17 17:06:52 2021 -0500

    Inline some methods of Envelope and MonotoneChain

diff --git a/include/geos/geom/Envelope.inl b/include/geos/geom/Envelope.inl
index c3661e4..1f6c8f3 100644
--- a/include/geos/geom/Envelope.inl
+++ b/include/geos/geom/Envelope.inl
@@ -342,7 +342,35 @@ bool operator!=(const Envelope& a, const Envelope& b) {
     return !(a == b);
 }
 
-} // namespace geos::geom
+INLINE bool
+Envelope::intersects(const Coordinate& p1, const Coordinate& p2,
+                     const Coordinate& q1, const Coordinate& q2)
+{
+    double minq = std::min(q1.x, q2.x);
+    double maxq = std::max(q1.x, q2.x);
+    double minp = std::min(p1.x, p2.x);
+    double maxp = std::max(p1.x, p2.x);
+    if(minp > maxq) {
+        return false;
+    }
+    if(maxp < minq) {
+        return false;
+    }
+    minq = std::min(q1.y, q2.y);
+    maxq = std::max(q1.y, q2.y);
+    minp = std::min(p1.y, p2.y);
+    maxp = std::max(p1.y, p2.y);
+    if(minp > maxq) {
+        return false;
+    }
+    if(maxp < minq) {
+        return false;
+    }
+    return true;
+}
+
+
+    } // namespace geos::geom
 } // namespace geos
 
 #endif // GEOS_GEOM_ENVELOPE_INL
diff --git a/include/geos/index/chain/MonotoneChain.h b/include/geos/index/chain/MonotoneChain.h
index 531de3f..d71cd2e 100644
--- a/include/geos/index/chain/MonotoneChain.h
+++ b/include/geos/index/chain/MonotoneChain.h
@@ -20,7 +20,9 @@
 #define GEOS_IDX_CHAIN_MONOTONECHAIN_H
 
 #include <geos/export.h>
+#include <geos/geom/CoordinateSequence.h> // for inline
 #include <geos/geom/Envelope.h> // for inline
+#include <geos/geom/LineSegment.h> // for inline
 
 #include <memory> // for unique_ptr
 
@@ -119,7 +121,10 @@ public:
      *  Set given LineSegment with points of the segment starting
      *  at the given index.
      */
-    void getLineSegment(std::size_t index, geom::LineSegment& ls) const;
+    void getLineSegment(std::size_t index, geom::LineSegment& ls) const {
+        ls.p0 = pts[index];
+        ls.p1 = pts[index + 1];
+    }
 
     /**
      * Return the subsequence of coordinates forming this chain.
@@ -161,7 +166,13 @@ private:
 
     bool overlaps(std::size_t start0, std::size_t end0,
                   const MonotoneChain& mc, std::size_t start1, std::size_t end1,
-                  double overlapTolerance) const;
+                  double overlapTolerance) const {
+        if (overlapTolerance > 0.0) {
+            return overlaps(pts[start0], pts[end0], mc.pts[start1], mc.pts[end1], overlapTolerance);
+        }
+        return geom::Envelope::intersects(pts.getAt(start0), pts.getAt(end0),
+                                          mc.pts.getAt(start1), mc.pts.getAt(end1));
+    }
 
     bool overlaps(const geom::Coordinate& p1, const geom::Coordinate& p2,
                   const geom::Coordinate& q1, const geom::Coordinate& q2,
diff --git a/src/geom/Envelope.cpp b/src/geom/Envelope.cpp
index 6288a7b..4563e89 100644
--- a/src/geom/Envelope.cpp
+++ b/src/geom/Envelope.cpp
@@ -55,34 +55,6 @@ Envelope::intersects(const Coordinate& p1, const Coordinate& p2,
 
 /*public*/
 bool
-Envelope::intersects(const Coordinate& p1, const Coordinate& p2,
-                     const Coordinate& q1, const Coordinate& q2)
-{
-    double minq = std::min(q1.x, q2.x);
-    double maxq = std::max(q1.x, q2.x);
-    double minp = std::min(p1.x, p2.x);
-    double maxp = std::max(p1.x, p2.x);
-    if(minp > maxq) {
-        return false;
-    }
-    if(maxp < minq) {
-        return false;
-    }
-    minq = std::min(q1.y, q2.y);
-    maxq = std::max(q1.y, q2.y);
-    minp = std::min(p1.y, p2.y);
-    maxp = std::max(p1.y, p2.y);
-    if(minp > maxq) {
-        return false;
-    }
-    if(maxp < minq) {
-        return false;
-    }
-    return true;
-}
-
-/*public*/
-bool
 Envelope::intersects(const Coordinate& a, const Coordinate& b) const
 {
     // These comparisons look redundant, but an alternative using
diff --git a/src/index/chain/MonotoneChain.cpp b/src/index/chain/MonotoneChain.cpp
index 45630f1..0c364a9 100644
--- a/src/index/chain/MonotoneChain.cpp
+++ b/src/index/chain/MonotoneChain.cpp
@@ -58,13 +58,6 @@ MonotoneChain::getEnvelope(double expansionDistance)
     return env;
 }
 
-void
-MonotoneChain::getLineSegment(std::size_t index, LineSegment& ls) const
-{
-    ls.p0 = pts[index];
-    ls.p1 = pts[index + 1];
-}
-
 std::unique_ptr<CoordinateSequence>
 MonotoneChain::getCoordinates() const
 {
@@ -171,18 +164,6 @@ MonotoneChain::computeOverlaps(std::size_t start0, std::size_t end0,
 
 /*private*/
 bool
-MonotoneChain::overlaps(std::size_t start0, std::size_t end0, const MonotoneChain& mc,
-                        std::size_t start1, std::size_t end1, double overlapTolerance) const
-{
-    if (overlapTolerance > 0.0) {
-        return overlaps(pts[start0], pts[end0], mc.pts[start1], mc.pts[end1], overlapTolerance);
-    }
-    return Envelope::intersects(pts.getAt(start0), pts.getAt(end0),
-                                mc.pts.getAt(start1), mc.pts.getAt(end1));
-}
-
-/*private*/
-bool
 MonotoneChain::overlaps(const Coordinate& p1, const Coordinate& p2,
                         const Coordinate& q1, const Coordinate& q2,
                         double overlapTolerance) const

commit 7a6411734ad2247eb289cf47fc65fb56e0351f79
Author: Daniel Baston <dbaston at gmail.com>
Date:   Wed Feb 17 12:25:27 2021 -0500

    Add some benchmarks using Google Benchmark library

diff --git a/benchmarks/CMakeLists.txt b/benchmarks/CMakeLists.txt
index a7a74a8..bc4dc33 100644
--- a/benchmarks/CMakeLists.txt
+++ b/benchmarks/CMakeLists.txt
@@ -11,6 +11,9 @@
 add_executable(perf_class_sizes ClassSizes.cpp)
 target_link_libraries(perf_class_sizes PRIVATE geos)
 
+add_subdirectory(capi)
+
 add_subdirectory(algorithm)
+add_subdirectory(geom)
+add_subdirectory(index)
 add_subdirectory(operation)
-add_subdirectory(capi)
diff --git a/benchmarks/algorithm/CMakeLists.txt b/benchmarks/algorithm/CMakeLists.txt
index c1ccdaa..5533298 100644
--- a/benchmarks/algorithm/CMakeLists.txt
+++ b/benchmarks/algorithm/CMakeLists.txt
@@ -18,3 +18,15 @@ target_link_libraries(perf_voronoi geos)
 
 add_executable(perf_unaryunion_segments UnaryUnionSegmentsPerfTest.cpp)
 target_link_libraries(perf_unaryunion_segments geos)
+
+find_package(benchmark)
+if (benchmark_FOUND)
+    add_executable(perf_orientation OrientationIndexPerfTest.cpp
+            ${CMAKE_SOURCE_DIR}/src/algorithm/CGAlgorithmsDD.cpp
+            ${CMAKE_SOURCE_DIR}/src/math/DD.cpp)
+    target_include_directories(perf_orientation PUBLIC
+            $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include>
+            $<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/include>)
+    target_link_libraries(perf_orientation PRIVATE
+            benchmark::benchmark geos_cxx_flags)
+endif()
diff --git a/benchmarks/algorithm/OrientationIndexPerfTest.cpp b/benchmarks/algorithm/OrientationIndexPerfTest.cpp
new file mode 100644
index 0000000..b13e459
--- /dev/null
+++ b/benchmarks/algorithm/OrientationIndexPerfTest.cpp
@@ -0,0 +1,47 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2021 Daniel Baston
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU Lesser General Public Licence as published
+ * by the Free Software Foundation.
+ * See the COPYING file for more information.
+ *
+ **********************************************************************/
+
+#include <benchmark/benchmark.h>
+
+#include <geos/geom/Coordinate.h>
+#include <geos/algorithm/CGAlgorithmsDD.h>
+
+using geos::geom::Coordinate;
+using geos::algorithm::CGAlgorithmsDD;
+
+static void BM_OrientationIndexFilter(benchmark::State& state) {
+    Coordinate p0(219.3649559090992, 140.84159161824724);
+    Coordinate p1(168.9018919682399, -5.713787599646864);
+    Coordinate p(186.80814046338352, 46.28973405831556);
+
+    for (auto _ : state) {
+        benchmark::DoNotOptimize(CGAlgorithmsDD::orientationIndexFilter(p0.x, p0.y, p1.x, p1.y, p.x, p.y));
+    }
+}
+
+static void BM_OrientationIndex(benchmark::State& state) {
+    Coordinate p0(219.3649559090992, 140.84159161824724);
+    Coordinate p1(168.9018919682399, -5.713787599646864);
+    Coordinate p(186.80814046338352, 46.28973405831556);
+
+    for (auto _ : state) {
+        benchmark::DoNotOptimize(CGAlgorithmsDD::orientationIndex(p0.x, p0.y, p1.x, p1.y, p.x, p.y));
+    }
+}
+
+BENCHMARK(BM_OrientationIndexFilter);
+BENCHMARK(BM_OrientationIndex);
+
+BENCHMARK_MAIN();
+
diff --git a/benchmarks/geom/CMakeLists.txt b/benchmarks/geom/CMakeLists.txt
new file mode 100644
index 0000000..322d3e3
--- /dev/null
+++ b/benchmarks/geom/CMakeLists.txt
@@ -0,0 +1,23 @@
+################################################################################
+# Part of CMake configuration for GEOS
+#
+# Copyright (C) 2021 Daniel Baston
+#
+# This is free software; you can redistribute and/or modify it under
+# the terms of the GNU Lesser General Public Licence as published
+# by the Free Software Foundation.
+# See the COPYING file for more information.
+################################################################################
+
+find_package(benchmark)
+
+IF(benchmark_FOUND)
+    add_executable(perf_envelope
+            EnvelopePerfTest.cpp
+            ${CMAKE_SOURCE_DIR}/src/geom/Envelope.cpp)
+    target_include_directories(perf_envelope PUBLIC
+            $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include>
+            $<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/include>)
+    target_link_libraries(perf_envelope PRIVATE
+            benchmark::benchmark geos_cxx_flags)
+endif()
diff --git a/benchmarks/geom/EnvelopePerfTest.cpp b/benchmarks/geom/EnvelopePerfTest.cpp
new file mode 100644
index 0000000..be13af5
--- /dev/null
+++ b/benchmarks/geom/EnvelopePerfTest.cpp
@@ -0,0 +1,45 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2021 Daniel Baston
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU Lesser General Public Licence as published
+ * by the Free Software Foundation.
+ * See the COPYING file for more information.
+ *
+ **********************************************************************/
+
+#include <benchmark/benchmark.h>
+
+#include <geos/geom/Envelope.h>
+
+using geos::geom::Coordinate;
+using geos::geom::Envelope;
+
+static void BM_EnvelopeIntersectsEnvelope(benchmark::State& state) {
+    Envelope a = Envelope(2, 3, 4, 5);
+    Envelope b = Envelope(6, 7, 8, 9);
+    for (auto _ : state) {
+        benchmark::DoNotOptimize(a.intersects(&b));
+    }
+}
+
+static void BM_CoordinateEnvelopeIntersectsEnvelope(benchmark::State& state) {
+    Coordinate p0(2, 4);
+    Coordinate p1(3, 5);
+    Coordinate q0(7, 9);
+    Coordinate q1(6, 8);
+
+    for (auto _ : state) {
+        benchmark::DoNotOptimize(Envelope::intersects(p0, p1, q0, q1));
+    }
+}
+
+BENCHMARK(BM_EnvelopeIntersectsEnvelope);
+BENCHMARK(BM_CoordinateEnvelopeIntersectsEnvelope);
+
+BENCHMARK_MAIN();
+
diff --git a/benchmarks/CMakeLists.txt b/benchmarks/index/CMakeLists.txt
similarity index 72%
copy from benchmarks/CMakeLists.txt
copy to benchmarks/index/CMakeLists.txt
index a7a74a8..e401c49 100644
--- a/benchmarks/CMakeLists.txt
+++ b/benchmarks/index/CMakeLists.txt
@@ -8,9 +8,5 @@
 # by the Free Software Foundation.
 # See the COPYING file for more information.
 ################################################################################
-add_executable(perf_class_sizes ClassSizes.cpp)
-target_link_libraries(perf_class_sizes PRIVATE geos)
 
-add_subdirectory(algorithm)
-add_subdirectory(operation)
-add_subdirectory(capi)
+add_subdirectory(chain)
diff --git a/benchmarks/index/chain/CMakeLists.txt b/benchmarks/index/chain/CMakeLists.txt
new file mode 100644
index 0000000..98b2ed9
--- /dev/null
+++ b/benchmarks/index/chain/CMakeLists.txt
@@ -0,0 +1,21 @@
+################################################################################
+# Part of CMake configuration for GEOS
+#
+# Copyright (C) 2021 Daniel Baston
+#
+# This is free software; you can redistribute and/or modify it under
+# the terms of the GNU Lesser General Public Licence as published
+# by the Free Software Foundation.
+# See the COPYING file for more information.
+################################################################################
+
+find_package(benchmark)
+
+IF(benchmark_FOUND)
+    add_executable(perf_monotone_chain MonotoneChainPerfTest.cpp)
+    target_include_directories(perf_monotone_chain PUBLIC
+            $<BUILD_INTERFACE:${CMAKE_SOURCE_DIR}/include>
+            $<BUILD_INTERFACE:${CMAKE_BINARY_DIR}/include>)
+    target_link_libraries(perf_monotone_chain PRIVATE
+            benchmark::benchmark geos)
+endif()
diff --git a/benchmarks/index/chain/MonotoneChainPerfTest.cpp b/benchmarks/index/chain/MonotoneChainPerfTest.cpp
new file mode 100644
index 0000000..f62f658
--- /dev/null
+++ b/benchmarks/index/chain/MonotoneChainPerfTest.cpp
@@ -0,0 +1,71 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2021 Daniel Baston
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU Lesser General Public Licence as published
+ * by the Free Software Foundation.
+ * See the COPYING file for more information.
+ *
+ **********************************************************************/
+
+#include <random>
+
+#include <benchmark/benchmark.h>
+
+#include <geos/geom/CoordinateArraySequence.h>
+#include <geos/index/chain/MonotoneChain.h>
+#include <geos/index/chain/MonotoneChainOverlapAction.h>
+
+using geos::geom::Coordinate;
+using geos::geom::LineSegment;
+using geos::geom::CoordinateArraySequence;
+using geos::geom::Envelope;
+using geos::index::chain::MonotoneChain;
+using geos::index::chain::MonotoneChainOverlapAction;
+
+static void BM_MonotoneChainOverlaps(benchmark::State& state) {
+    CoordinateArraySequence cs1;
+    CoordinateArraySequence cs2;
+
+    std::default_random_engine e(12345);
+    std::uniform_real_distribution<> dist(0, 1);
+
+    Coordinate prev(0, 0);
+    for (size_t i = 0; i < 100; i++) {
+        Coordinate c(prev.x + dist(e), prev.y + dist(e));
+        cs1.add(c);
+        prev = c;
+    }
+
+    prev = Coordinate(0, 100);
+    for (size_t i = 0; i < 100; i++) {
+        Coordinate c(prev.x + dist(e), prev.y - dist(e));
+        cs2.add(c);
+        prev = c;
+    }
+
+    MonotoneChain mc1(cs1, 0, cs1.size(), nullptr);
+    MonotoneChain mc2(cs2, 0, cs1.size(), nullptr);
+
+    struct EmptyOverlapAction : public MonotoneChainOverlapAction {
+        virtual void
+        overlap(const LineSegment& seg1, const LineSegment& seg2) {
+            (void) seg1;
+            (void) seg2;
+        }
+    };
+    EmptyOverlapAction mco;
+
+    for (auto _ : state) {
+        mc1.computeOverlaps(&mc2, &mco);
+    }
+}
+
+BENCHMARK(BM_MonotoneChainOverlaps);
+
+BENCHMARK_MAIN();
+

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

Summary of changes:
 benchmarks/CMakeLists.txt                          |   5 +-
 benchmarks/algorithm/CMakeLists.txt                |  21 ++++
 benchmarks/algorithm/LineIntersectorPerfTest.cpp   |  50 ++++++++++
 benchmarks/algorithm/OrientationIndexPerfTest.cpp  |  47 +++++++++
 benchmarks/algorithm/{ => locate}/CMakeLists.txt   |  16 ++--
 .../locate/IndexedPointInAreaLocatorPerfTest.cpp   |  51 ++++++++++
 benchmarks/geom/CMakeLists.txt                     |  23 +++++
 benchmarks/geom/EnvelopePerfTest.cpp               |  45 +++++++++
 benchmarks/{operation => index}/CMakeLists.txt     |   4 +-
 benchmarks/index/chain/CMakeLists.txt              |  28 ++++++
 .../index/chain/MonotoneChainBuilderPerfTest.cpp   |  69 ++++++++++++++
 benchmarks/index/chain/MonotoneChainPerfTest.cpp   |  71 ++++++++++++++
 include/geos/algorithm/LineIntersector.inl         |  23 +++++
 include/geos/geom/Envelope.inl                     |  30 +++++-
 include/geos/geom/util/Densifier.h                 |   2 +-
 include/geos/index/chain/MonotoneChain.h           |  15 ++-
 include/geos/index/chain/MonotoneChainBuilder.h    |  23 -----
 src/algorithm/LineIntersector.cpp                  |  21 ----
 src/geom/Envelope.cpp                              |  28 ------
 src/index/chain/MonotoneChain.cpp                  |  19 ----
 src/index/chain/MonotoneChainBuilder.cpp           | 106 ++++++++++-----------
 21 files changed, 537 insertions(+), 160 deletions(-)
 create mode 100644 benchmarks/algorithm/LineIntersectorPerfTest.cpp
 create mode 100644 benchmarks/algorithm/OrientationIndexPerfTest.cpp
 copy benchmarks/algorithm/{ => locate}/CMakeLists.txt (53%)
 create mode 100644 benchmarks/algorithm/locate/IndexedPointInAreaLocatorPerfTest.cpp
 create mode 100644 benchmarks/geom/CMakeLists.txt
 create mode 100644 benchmarks/geom/EnvelopePerfTest.cpp
 copy benchmarks/{operation => index}/CMakeLists.txt (90%)
 create mode 100644 benchmarks/index/chain/CMakeLists.txt
 create mode 100644 benchmarks/index/chain/MonotoneChainBuilderPerfTest.cpp
 create mode 100644 benchmarks/index/chain/MonotoneChainPerfTest.cpp


hooks/post-receive
-- 
GEOS


More information about the geos-commits mailing list