-
Notifications
You must be signed in to change notification settings - Fork 98
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
perf: to_geos/from_geos without using WKT
Runtime on total of all the gerbv examples is decreased by 20%
- Loading branch information
Showing
360 changed files
with
98,534 additions
and
98,348 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,57 +1,142 @@ | ||
#ifdef GEOS_VERSION | ||
|
||
#include "geos_helpers.hpp" | ||
#include "geometry.hpp" | ||
#include <geos/io/WKTReader.h> | ||
#include <geos/io/WKTReader.inl> | ||
#include <geos/io/WKTWriter.h> | ||
#include <geos/geom/CoordinateSequenceFactory.h> | ||
#include <geos/geom/Coordinate.h> | ||
#include <geos/geom/Coordinate.inl> | ||
#include <geos/geom/GeometryFactory.h> | ||
#include <geos/geom/GeometryFactory.inl> | ||
#include <boost/pointer_cast.hpp> | ||
|
||
template <typename T> | ||
std::unique_ptr<geos::geom::Geometry> to_geos(const T& mp) { | ||
geos::io::WKTReader reader; | ||
std::stringstream ss; | ||
ss << bg::wkt(mp); | ||
return reader.read(ss.str()); | ||
linestring_type_fp from_geos(const geos::geom::LineString* ls) { | ||
linestring_type_fp ret; | ||
ret.reserve(ls->getNumPoints()); | ||
for (size_t i = 0; i < ls->getNumPoints(); i++) { | ||
const auto& p = ls->getPointN(i); | ||
ret.push_back(point_type_fp(p->getX(), p->getY())); | ||
} | ||
return ret; | ||
} | ||
template std::unique_ptr<geos::geom::Geometry> to_geos(const multi_polygon_type_fp& mp); | ||
template std::unique_ptr<geos::geom::Geometry> to_geos(const multi_linestring_type_fp& mls); | ||
template std::unique_ptr<geos::geom::Geometry> to_geos(const linestring_type_fp& mls); | ||
|
||
linestring_type_fp from_geos(const std::unique_ptr<geos::geom::LineString>& ls) { | ||
return from_geos(ls.get()); | ||
} | ||
|
||
template <typename T> | ||
T from_geos(const std::unique_ptr<geos::geom::Geometry>& g); | ||
ring_type_fp from_geos(const geos::geom::LinearRing* ring) { | ||
ring_type_fp ret; | ||
ret.reserve(ring->getNumPoints()); | ||
for (size_t i = 0; i < ring->getNumPoints(); i++) { | ||
const auto& p = ring->getPointN(i); | ||
ret.push_back(point_type_fp(p->getX(), p->getY())); | ||
} | ||
return ret; | ||
} | ||
|
||
template <> | ||
multi_polygon_type_fp from_geos(const std::unique_ptr<geos::geom::Geometry>& g) { | ||
geos::io::WKTWriter writer; | ||
std::string geos_wkt = writer.write(g.get()); | ||
boost::replace_all(geos_wkt, "EMPTY, ", ""); | ||
boost::replace_all(geos_wkt, ", EMPTY", ""); | ||
ring_type_fp from_geos(const std::unique_ptr<geos::geom::LinearRing>& ring) { | ||
return from_geos(ring.get()); | ||
} | ||
|
||
polygon_type_fp from_geos(const geos::geom::Polygon* poly) { | ||
polygon_type_fp ret; | ||
ret.outer() = from_geos(poly->getExteriorRing()); | ||
ret.inners().reserve(poly->getNumInteriorRing()); | ||
for (size_t i = 0; i < poly->getNumInteriorRing(); i++) { | ||
ret.inners().push_back(from_geos(poly->getInteriorRingN(i))); | ||
} | ||
return ret; | ||
} | ||
|
||
polygon_type_fp from_geos(const std::unique_ptr<geos::geom::Polygon>& poly) { | ||
return from_geos(poly.get()); | ||
} | ||
|
||
multi_polygon_type_fp from_geos(const std::unique_ptr<geos::geom::MultiPolygon>& mpoly) { | ||
multi_polygon_type_fp ret; | ||
if (strncmp(geos_wkt.c_str(), "MULTIPOLYGON", 12) == 0) { | ||
bg::read_wkt(geos_wkt, ret); | ||
} else { | ||
polygon_type_fp poly; | ||
bg::read_wkt(geos_wkt, poly); | ||
ret.push_back(poly); | ||
ret.reserve(mpoly->getNumGeometries()); | ||
for (size_t i = 0; i < mpoly->getNumGeometries(); i++) { | ||
ret.push_back(from_geos(mpoly->getGeometryN(i))); | ||
} | ||
return ret; | ||
} | ||
|
||
template <> | ||
multi_linestring_type_fp from_geos(const std::unique_ptr<geos::geom::Geometry>& g) { | ||
geos::io::WKTWriter writer; | ||
std::string geos_wkt = writer.write(g.get()); | ||
boost::replace_all(geos_wkt, "EMPTY, ", ""); | ||
boost::replace_all(geos_wkt, ", EMPTY", ""); | ||
multi_linestring_type_fp from_geos(const std::unique_ptr<geos::geom::MultiLineString>& mls) { | ||
multi_linestring_type_fp ret; | ||
if (strncmp(geos_wkt.c_str(), "MULTILINESTRING", 12) == 0) { | ||
bg::read_wkt(geos_wkt, ret); | ||
} else { | ||
linestring_type_fp ls; | ||
bg::read_wkt(geos_wkt, ls); | ||
ret.push_back(ls); | ||
ret.reserve(mls->getNumGeometries()); | ||
for (size_t i = 0; i < mls->getNumGeometries(); i++) { | ||
ret.push_back(from_geos(mls->getGeometryN(i))); | ||
} | ||
return ret; | ||
} | ||
|
||
template <> | ||
multi_polygon_type_fp from_geos(const std::unique_ptr<geos::geom::Geometry>& g) { | ||
auto mp = boost::dynamic_pointer_cast<geos::geom::MultiPolygon>(g->clone()); | ||
if (mp) { | ||
return from_geos(mp); | ||
} | ||
auto p = boost::dynamic_pointer_cast<geos::geom::Polygon>(g->clone()); | ||
if (p) { | ||
return multi_polygon_type_fp{from_geos(p)}; | ||
} | ||
geos::io::WKTWriter writer; | ||
throw std::logic_error("Can't convert to multi_polygon_type_fp: " + writer.write(g.get())); | ||
} | ||
|
||
std::unique_ptr<geos::geom::LineString> to_geos( | ||
const linestring_type_fp& ls) { | ||
auto geom_factory = geos::geom::GeometryFactory::create(); | ||
auto coord_factory = geom_factory->getCoordinateSequenceFactory(); | ||
auto coords = coord_factory->create(ls.size(), 2 /* dimensions */); | ||
for (size_t i = 0; i < ls.size(); i++) { | ||
coords->setAt(geos::geom::Coordinate(ls[i].x(), ls[i].y()), i); | ||
} | ||
return geom_factory->createLineString(std::move(coords)); | ||
} | ||
|
||
std::unique_ptr<geos::geom::LinearRing> to_geos(const ring_type_fp& ring) { | ||
auto geom_factory = geos::geom::GeometryFactory::create(); | ||
auto coord_factory = geom_factory->getCoordinateSequenceFactory(); | ||
auto coords = coord_factory->create(ring.size(), 2 /* dimensions */); | ||
for (size_t i = 0; i < ring.size(); i++) { | ||
// reverse rings for geos. | ||
coords->setAt(geos::geom::Coordinate(ring[i].x(), ring[i].y()), i); | ||
} | ||
return geom_factory->createLinearRing(std::move(coords)); | ||
} | ||
|
||
std::unique_ptr<geos::geom::Polygon> to_geos(const polygon_type_fp& poly) { | ||
auto shell = to_geos(poly.outer()); | ||
std::vector<std::unique_ptr<geos::geom::LinearRing>> holes; | ||
holes.reserve(poly.inners().size()); | ||
for (const auto& inner : poly.inners()) { | ||
holes.push_back(to_geos(inner)); | ||
} | ||
auto geom_factory = geos::geom::GeometryFactory::create(); | ||
return geom_factory->createPolygon(std::move(shell), std::move(holes)); | ||
} | ||
|
||
std::unique_ptr<geos::geom::MultiPolygon> to_geos(const multi_polygon_type_fp& mpoly) { | ||
std::vector<std::unique_ptr<geos::geom::Polygon>> polys; | ||
polys.reserve(mpoly.size()); | ||
for (const auto& p : mpoly) { | ||
polys.push_back(to_geos(p)); | ||
} | ||
auto geom_factory = geos::geom::GeometryFactory::create(); | ||
return geom_factory->createMultiPolygon(std::move(polys)); | ||
} | ||
|
||
std::unique_ptr<geos::geom::MultiLineString> to_geos(const multi_linestring_type_fp& mls) { | ||
std::vector<std::unique_ptr<geos::geom::LineString>> polys; | ||
polys.reserve(mls.size()); | ||
for (const auto& p : mls) { | ||
polys.push_back(to_geos(p)); | ||
} | ||
auto geom_factory = geos::geom::GeometryFactory::create(); | ||
return geom_factory->createMultiLineString(std::move(polys)); | ||
} | ||
|
||
#endif //GEOS_VERSION |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
#define BOOST_TEST_MODULE geos helpers tests | ||
#include <boost/test/unit_test.hpp> | ||
|
||
#include "geometry.hpp" | ||
#include "geos_helpers.hpp" | ||
#include "bg_operators.hpp" | ||
#ifdef GEOS_VERSION | ||
#include <geos/io/WKTReader.h> | ||
#endif // GEOS_VERSION | ||
|
||
BOOST_AUTO_TEST_SUITE(geos_helpers_tests) | ||
|
||
// Confirm that both geos and boost support clockwise rings. | ||
BOOST_AUTO_TEST_CASE(direction) { | ||
auto box = bg::return_envelope<box_type_fp>(point_type_fp(0,0)); | ||
bg::expand(box, point_type_fp(10,10)); | ||
polygon_type_fp poly; | ||
bg::convert(box, poly); | ||
BOOST_CHECK_EQUAL(poly.outer()[1], point_type_fp(0,10)); | ||
bg::reverse(poly); | ||
bg::correct(poly); | ||
BOOST_CHECK_EQUAL(poly.outer()[1], point_type_fp(0,10)); | ||
#ifdef GEOS_VERSION | ||
// Convert it through well-known text, which is sure to create a | ||
// valid polygon in geos. | ||
geos::io::WKTReader reader; | ||
std::stringstream ss; | ||
ss << bg::wkt(poly); | ||
auto geos_geo = reader.read(ss.str()); | ||
const auto* geos_poly = dynamic_cast<geos::geom::Polygon*>(geos_geo.get()); | ||
BOOST_CHECK_EQUAL(geos_poly->getExteriorRing()->getPointN(1)->getX(), 0); | ||
BOOST_CHECK_EQUAL(geos_poly->getExteriorRing()->getPointN(1)->getY(), 10); | ||
#endif // GEOS_VERSION | ||
} | ||
|
||
BOOST_AUTO_TEST_SUITE_END() |
Oops, something went wrong.