[geos-commits] [SCM] GEOS branch master updated. b36f6f2f7ef2e8f1cbf7c9387b3f4a51fb575e13

git at osgeo.org git at osgeo.org
Mon Dec 17 10:45:08 PST 2018


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  b36f6f2f7ef2e8f1cbf7c9387b3f4a51fb575e13 (commit)
      from  694aa42d9e0905ac44809a79da0afac34f9fb1c7 (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 b36f6f2f7ef2e8f1cbf7c9387b3f4a51fb575e13
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date:   Mon Dec 17 10:44:47 2018 -0800

    Move area functions to Area class
    JTS e06c0c9ce27abdf84f8dc897baac06cc70a2eed7

diff --git a/include/geos/algorithm/Area.h b/include/geos/algorithm/Area.h
new file mode 100644
index 0000000..7608c3f
--- /dev/null
+++ b/include/geos/algorithm/Area.h
@@ -0,0 +1,81 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2018 Paul Ramsey <pramsey at cleverlephant.ca>
+ *
+ * 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.
+ *
+ **********************************************************************
+ *
+ * Last port: algorithm/Area.java @ 2017-09-04
+ *
+ **********************************************************************/
+
+#ifndef GEOS_ALGORITHM_AREA_H
+#define GEOS_ALGORITHM_AREA_H
+
+#include <geos/export.h>
+#include <geos/geom/Coordinate.h>
+#include <geos/geom/CoordinateSequence.h>
+
+namespace geos {
+namespace algorithm { // geos::algorithm
+
+/// Utility functions for working with angles.
+//
+/// Unless otherwise noted, methods in this class express angles in radians.
+///
+class GEOS_DLL Area {
+public:
+
+    /**
+    * Computes the area for a ring.
+    *
+    * @param ring the coordinates forming the ring
+    * @return the area of the ring
+    */
+    static double ofRing(const std::vector<geom::Coordinate> &ring);
+
+    /**
+    * Computes the area for a ring.
+    *
+    * @param ring the coordinates forming the ring
+    * @return the area of the ring
+    */
+    static double ofRing(const geom::CoordinateSequence *ring);
+
+    /**
+    * Computes the signed area for a ring. The signed area is positive if the
+    * ring is oriented CW, negative if the ring is oriented CCW, and zero if the
+    * ring is degenerate or flat.
+    *
+    * @param ring
+    *          the coordinates forming the ring
+    * @return the signed area of the ring
+    */
+    static double ofRingSigned(const std::vector<geom::Coordinate> &ring);
+
+    /**
+    * Computes the signed area for a ring. The signed area is positive if the
+    * ring is oriented CW, negative if the ring is oriented CCW, and zero if the
+    * ring is degenerate or flat.
+    *
+    * @param ring
+    *          the coordinates forming the ring
+    * @return the signed area of the ring
+    */
+    static double ofRingSigned(const geom::CoordinateSequence *ring);
+
+};
+
+
+} // namespace geos::algorithm
+} // namespace geos
+
+
+#endif // GEOS_ALGORITHM_AREA_H
diff --git a/include/geos/algorithm/Makefile.am b/include/geos/algorithm/Makefile.am
index 6309cec..0c9d319 100644
--- a/include/geos/algorithm/Makefile.am
+++ b/include/geos/algorithm/Makefile.am
@@ -12,6 +12,7 @@ geosdir = $(includedir)/geos/algorithm
 
 geos_HEADERS = \
 	Angle.h \
+	Area.h \
 	BoundaryNodeRule.h \
 	CentralEndpointIntersector.h \
 	Centroid.h \
diff --git a/src/algorithm/Area.cpp b/src/algorithm/Area.cpp
new file mode 100644
index 0000000..e203953
--- /dev/null
+++ b/src/algorithm/Area.cpp
@@ -0,0 +1,96 @@
+/**********************************************************************
+ *
+ * GEOS - Geometry Engine Open Source
+ * http://geos.osgeo.org
+ *
+ * Copyright (C) 2018 Paul Ramsey <pramsey at cleverlephant.ca>
+ *
+ * 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.
+ *
+ **********************************************************************
+ *
+ * Last port: algorithm/Area.java @ 2017-09-04
+ *
+ **********************************************************************/
+
+#include <cmath>
+#include <vector>
+
+#include <geos/algorithm/Area.h>
+
+namespace geos {
+namespace algorithm { // geos.algorithm
+
+/* public static */
+double
+Area::ofRing(const std::vector<geom::Coordinate> &ring)
+{
+    return abs(ofRingSigned(ring));
+}
+
+/* public static */
+double
+Area::ofRing(const geom::CoordinateSequence *ring)
+{
+    return abs(ofRingSigned(ring));
+}
+
+/* public static */
+double
+Area::ofRingSigned(const std::vector<geom::Coordinate> &ring)
+{
+    size_t rlen = ring.size();
+    if (rlen < 3)
+        return 0.0;
+
+    double sum = 0.0;
+    /**
+     * Based on the Shoelace formula.
+     * http://en.wikipedia.org/wiki/Shoelace_formula
+     */
+    double x0 = ring[0].x;
+    for (size_t i = 1; i < rlen - 1; i++) {
+        double x = ring[i].x - x0;
+        double y1 = ring[i + 1].y;
+        double y2 = ring[i - 1].y;
+        sum += x * (y2 - y1);
+    }
+    return sum / 2.0;
+}
+
+/* public static */
+double
+Area::ofRingSigned(const geom::CoordinateSequence *ring)
+{
+    size_t n = ring->size();
+    if (n < 3)
+        return 0.0;
+    /**
+    * Based on the Shoelace formula.
+    * http://en.wikipedia.org/wiki/Shoelace_formula
+    */
+    geom::Coordinate p0, p1, p2;
+    p1 = ring->getAt(0);
+    p2 = ring->getAt(1);
+    double x0 = p1.x;
+    p2.x -= x0;
+    double sum = 0.0;
+    for (size_t i = 1; i < n - 1; i++) {
+        p0.y = p1.y;
+        p1.x = p2.x;
+        p1.y = p2.y;
+        p2 = ring->getAt(i + 1);
+        p2.x -= x0;
+        sum += p1.x * (p0.y - p2.y);
+    }
+    return sum / 2.0;
+}
+
+
+
+} // namespace geos.algorithm
+} //namespace geos
+
diff --git a/src/algorithm/Makefile.am b/src/algorithm/Makefile.am
index 749cbe5..7f84e78 100644
--- a/src/algorithm/Makefile.am
+++ b/src/algorithm/Makefile.am
@@ -11,6 +11,7 @@ AM_CPPFLAGS = -I$(top_srcdir)/include
 
 libalgorithm_la_SOURCES = \
 	Angle.cpp \
+	Area.cpp \
 	BoundaryNodeRule.cpp \
 	Centroid.cpp \
 	CGAlgorithms.cpp \
diff --git a/src/geom/Polygon.cpp b/src/geom/Polygon.cpp
index 85082c7..7b8fea5 100644
--- a/src/geom/Polygon.cpp
+++ b/src/geom/Polygon.cpp
@@ -18,6 +18,7 @@
  *
  **********************************************************************/
 
+#include <geos/algorithm/Area.h>
 #include <geos/algorithm/CGAlgorithms.h>
 #include <geos/util/IllegalArgumentException.h>
 #include <geos/geom/Coordinate.h>
@@ -366,13 +367,13 @@ Polygon::getCoordinate() const
 double
 Polygon::getArea() const
 {
-	double area=0.0;
-	area+=fabs(algorithm::CGAlgorithms::signedArea(shell->getCoordinatesRO()));
+	double area = 0.0;
+	area += fabs(algorithm::Area::ofRing(shell->getCoordinatesRO()));
 	for(size_t i=0, n=holes->size(); i<n; ++i)
 	{
 		const LinearRing *lr = dynamic_cast<const LinearRing *>((*holes)[i]);
-		const CoordinateSequence *h=lr->getCoordinatesRO();
-        	area-=fabs(algorithm::CGAlgorithms::signedArea(h));
+		const CoordinateSequence *h = lr->getCoordinatesRO();
+    	area -= fabs(algorithm::Area::ofRing(h));
 	}
 	return area;
 }
diff --git a/tests/unit/Makefile.am b/tests/unit/Makefile.am
index 9c48b02..9064b1f 100644
--- a/tests/unit/Makefile.am
+++ b/tests/unit/Makefile.am
@@ -40,6 +40,7 @@ geos_unit_LDADD = \
 geos_unit_SOURCES = \
 	geos_unit.cpp \
 	algorithm/AngleTest.cpp \
+	algorithm/AreaTest.cpp \
 	algorithm/CGAlgorithms/computeOrientationTest.cpp \
 	algorithm/CGAlgorithms/isCCWTest.cpp \
 	algorithm/CGAlgorithms/isPointInRingTest.cpp \
diff --git a/tests/unit/algorithm/AreaTest.cpp b/tests/unit/algorithm/AreaTest.cpp
new file mode 100644
index 0000000..361ac4b
--- /dev/null
+++ b/tests/unit/algorithm/AreaTest.cpp
@@ -0,0 +1,153 @@
+//
+// Test Suite for geos::algorithm::Area
+// Ported from JTS junit/algorithm/AreaTest.java
+
+#include <tut/tut.hpp>
+// geos
+#include <geos/algorithm/Area.h>
+#include <geos/geom/Coordinate.h>
+#include <geos/geom/CoordinateArraySequence.h>
+#include <geos/geom/Dimension.h>
+#include <geos/geom/Geometry.h>
+#include <geos/geom/GeometryFactory.h>
+#include <geos/geom/LineString.h>
+#include <geos/geom/PrecisionModel.h>
+#include <geos/io/WKTReader.h>
+// std
+#include <sstream>
+#include <string>
+#include <memory>
+
+using namespace geos;
+using namespace geos::geom;
+
+namespace tut
+{
+	//
+	// Test Group
+	//
+
+	// dummy data, not used
+	struct test_area_data {
+        geos::geom::Geometry *geom_;
+        geos::geom::PrecisionModel pm_;
+        geos::geom::GeometryFactory::Ptr factory_;
+        geos::io::WKTReader reader_;
+        test_area_data():
+            geom_(nullptr),
+            pm_(1),
+            factory_(GeometryFactory::create(&pm_, 0)), reader_(factory_.get())
+        {
+            assert(nullptr == geom_);
+        }
+
+        ~test_area_data()
+        {
+            factory_->destroyGeometry(geom_);
+            geom_ = nullptr;
+        }
+
+        void checkAreaOfRing(std::string wkt, double expectedArea) {
+            std::unique_ptr<Geometry> lineGeom(reader_.read(wkt));
+            std::unique_ptr<LineString> line(dynamic_cast<LineString*>(lineGeom.release()));
+            ensure(nullptr != line.get());
+            const CoordinateSequence *ringSeq = line->getCoordinatesRO();
+
+            std::vector<Coordinate> ringCoords;
+            ringSeq->toVector(ringCoords);
+
+            double actual1 = algorithm::Area::ofRing(ringCoords);
+            double actual2 = algorithm::Area::ofRing(ringSeq);
+
+            ensure_equals(actual1, expectedArea);
+            ensure_equals(actual2, expectedArea);
+        }
+
+        void checkAreaOfRingSigned(std::string wkt, double expectedArea) {
+            std::unique_ptr<Geometry> lineGeom(reader_.read(wkt));
+            std::unique_ptr<LineString> line(dynamic_cast<LineString*>(lineGeom.release()));
+            ensure(nullptr != line.get());
+            const CoordinateSequence *ringSeq = line->getCoordinatesRO();
+
+            std::vector<Coordinate> ringCoords;
+            ringSeq->toVector(ringCoords);
+
+            double actual1 = algorithm::Area::ofRingSigned(ringCoords);
+            double actual2 = algorithm::Area::ofRingSigned(ringSeq);
+
+            ensure_equals(actual1, expectedArea);
+            ensure_equals(actual2, expectedArea);
+        }
+    };
+
+        // using geos::geom::LineString;
+
+        // Geometry::Ptr lineGeom(reader_.read("LINESTRING (30 220, 240 220, 240 220)"));
+        // LineString::Ptr line(dynamic_cast<LineString*>(lineGeom.release()));
+        // ensure(nullptr != line.get());
+
+        // Geometry::Ptr hullGeom(reader_.read("LINESTRING (30 220, 240 220)"));
+        // LineString::Ptr convexHull(dynamic_cast<LineString*>(hullGeom.release()));
+        // ensure(nullptr != convexHull.get());
+
+        // geom_ = line->convexHull();
+        // ensure( convexHull->equalsExact(geom_) );
+
+
+
+
+
+    typedef test_group<test_area_data> group;
+    typedef group::object object;
+
+    group test_area_group("geos::algorithm::Area");
+
+
+    //
+    // Test Cases
+    //
+    template<>
+    template<>
+    void object::test<1>()
+    {
+        checkAreaOfRing("LINESTRING (100 200, 200 200, 200 100, 100 100, 100 200)", 10000.0);
+    }
+
+    template<>
+    template<>
+    void object::test<2>()
+    {
+        checkAreaOfRingSigned("LINESTRING (100 200, 200 200, 200 100, 100 100, 100 200)", 10000.0);
+    }
+
+    template<>
+    template<>
+    void object::test<3>()
+    {
+        checkAreaOfRingSigned("LINESTRING (100 200, 100 100, 200 100, 200 200, 100 200)", -10000.0);
+    }
+
+    // // testIsAcute()
+    // template<>
+    // template<>
+    // void object::test<2>()
+    // {
+    // ensure_equals("7", Angle::angle(Coordinate(-10,-10)), -0.75*PI, TOL);
+    //     ensure(Area::isAcute(
+    //       Coordinate(10,0), Coordinate(0,0), Coordinate(5,10)));
+    //     ensure(Area::isAcute(
+    //       Coordinate(10,0), Coordinate(0,0), Coordinate(5,-10)));
+    //     // angle of 0
+    //     ensure(Area::isAcute(
+    //       Coordinate(10,0), Coordinate(0,0), Coordinate(10,0)));
+    //     ensure_not(Area::isAcute(
+    //       Coordinate(10,0), Coordinate(0,0), Coordinate(-5,10)));
+    //     ensure_not(Area::isAcute(
+    //       Coordinate(10,0), Coordinate(0,0), Coordinate(-5,-10)));
+    // }
+
+
+
+
+} // namespace tut
+

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

Summary of changes:
 include/geos/algorithm/Area.h      |  81 ++++++++++++++++++++
 include/geos/algorithm/Makefile.am |   1 +
 src/algorithm/Area.cpp             |  96 +++++++++++++++++++++++
 src/algorithm/Makefile.am          |   1 +
 src/geom/Polygon.cpp               |   9 ++-
 tests/unit/Makefile.am             |   1 +
 tests/unit/algorithm/AreaTest.cpp  | 153 +++++++++++++++++++++++++++++++++++++
 7 files changed, 338 insertions(+), 4 deletions(-)
 create mode 100644 include/geos/algorithm/Area.h
 create mode 100644 src/algorithm/Area.cpp
 create mode 100644 tests/unit/algorithm/AreaTest.cpp


hooks/post-receive
-- 
GEOS


More information about the geos-commits mailing list