Skip to content

Commit

Permalink
OverlayNG: Interpolate M values (libgeos#802)
Browse files Browse the repository at this point in the history
* Pull interpolation methods into own class, generalize for M

* LineIntersector: Perform M interpolation

* OverlayNG: Interpolate M values

* GEOSNode: Interpolate M values

* SegmentExtractingNoder: Preserve input dimension

* OverlayEdgeRing: Preseve input dimensionality

* BoundaryChainNoder: Preserve input dimensionality

* SnapRoundingNoder / HotPixelIndex: Preserve coordinate dimension

* Move CoordinateSequence dispatch helper to CoordinateSequences.h, add tests

* Replace CommonCoordinateType with std::common_type specializations, add test

* Polygon::normalize(): Preserve coordinate dimension

* OverlayEdge: Preserve dimension when adding backward edges

* Clean up generic ordinate access
  • Loading branch information
dbaston authored Jan 26, 2023
1 parent 85a1779 commit 4292b12
Show file tree
Hide file tree
Showing 83 changed files with 2,052 additions and 1,116 deletions.
10 changes: 5 additions & 5 deletions benchmarks/BenchmarkUtils.h
Original file line number Diff line number Diff line change
Expand Up @@ -73,16 +73,16 @@ createPoints(const geom::Envelope& env, std::size_t nItems) {
}

std::unique_ptr<geom::CoordinateSequence>
createRandomCoords(const geom::Envelope& env, std::size_t npts, std::size_t seed) {
auto ret = detail::make_unique<geom::CoordinateSequence>(npts, false, false, false);

std::default_random_engine e(seed);
createRandomCoords(const geom::Envelope& env, std::size_t npts, std::default_random_engine& e) {
auto ret = detail::make_unique<geom::CoordinateSequence>(npts, true, true, false);

std::uniform_real_distribution<> xdist(env.getMinX(), env.getMaxX());
std::uniform_real_distribution<> ydist(env.getMinY(), env.getMaxY());
std::uniform_real_distribution<> zdist(0, 1);
std::uniform_real_distribution<> mdist(0, 1);

for (std::size_t i = 0;i < npts; i++) {
ret->setAt(geom::CoordinateXY(xdist(e), ydist(e)), i);
ret->setAt(geom::CoordinateXYZM(xdist(e), ydist(e), zdist(e), mdist(e)), i);
}

return ret;
Expand Down
2 changes: 2 additions & 0 deletions benchmarks/ClassSizes.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
#include <geos/geomgraph/EdgeEnd.h>
#include <geos/geomgraph/PlanarGraph.h>
#include <geos/noding/NodedSegmentString.h>
#include <geos/noding/snapround/HotPixel.h>
#include <geos/profiler.h>
#include <geos/constants.h>
#include <iostream>
Expand Down Expand Up @@ -63,6 +64,7 @@ main()
check(geomgraph::TopologyLocation);
check(geomgraph::index::SweepLineEvent);
check(noding::NodedSegmentString);
check(noding::snapround::HotPixel);
check(geom::Geometry);
check(geom::Point);
check(geom::LineString);
Expand Down
3 changes: 2 additions & 1 deletion benchmarks/algorithm/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,8 @@ if (benchmark_FOUND)
add_executable(perf_line_intersector LineIntersectorPerfTest.cpp)
target_include_directories(perf_line_intersector PUBLIC
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/include>
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>)
$<BUILD_INTERFACE:${PROJECT_BINARY_DIR}/include>
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/benchmarks>)
target_link_libraries(perf_line_intersector PRIVATE
benchmark::benchmark geos)

Expand Down
71 changes: 59 additions & 12 deletions benchmarks/algorithm/LineIntersectorPerfTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,36 +15,83 @@
#include <benchmark/benchmark.h>

#include <geos/algorithm/LineIntersector.h>
#include <geos/geom/Envelope.h>

#include <BenchmarkUtils.h>

#include <array>
#include <random>

using geos::geom::Coordinate;
using geos::geom::CoordinateXY;
using geos::geom::CoordinateXYM;
using geos::geom::CoordinateXYZM;
using geos::geom::CoordinateSequence;
using geos::geom::Envelope;
using geos::algorithm::LineIntersector;

template<typename CoordType>
static void BM_PointIntersection(benchmark::State& state) {
Coordinate p1(10, 10);
Coordinate p2(20, 20);
Coordinate q1(20, 10);
Coordinate q2(10, 20);
std::size_t n = 1000;
std::size_t seed = 12345;

std::default_random_engine e(seed);

std::array<Envelope, 4> envelopes {
Envelope{-1, 0, 0, 1}, // NW
Envelope{0, 1, 0, 1}, // NE
Envelope{-1, 0, -1, 0}, // SW
Envelope{0, 1, -1, 0} // SE
};

std::array<CoordinateSequence, 4> pts;
for (std::size_t i = 0; i < envelopes.size(); i++) {
pts[i] = *geos::benchmark::createRandomCoords(envelopes[i], n, e);
}

LineIntersector li;
std::size_t i = 0;
for (auto _ : state) {
LineIntersector li;
const auto& p1 = pts[0].getAt<CoordType>(i);
const auto& p2 = pts[2].getAt<CoordType>(i);
const auto& q1 = pts[1].getAt<CoordType>(i);
const auto& q2 = pts[3].getAt<CoordType>(i);

li.computeIntersection(p1, p2, q1, q2);
li.computeIntersection(p2, p1, q2, q1);
li.computeIntersection(q2, p1, p2, q1);
li.computeIntersection(q1, p1, p2, q2);

i++;
if (i > n) {
i = 0;
}
}
}

template<typename CoordType>
static void BM_Collinear(benchmark::State& state) {
Coordinate p1(10, 10);
Coordinate p2(20, 10);
Coordinate q1(22, 10);
Coordinate q2(30, 10);
CoordinateXYZM p1_xyzm(10, 10, 1, 8);
CoordinateXYZM p2_xyzm(20, 10, 2, 8);
CoordinateXYZM q1_xyzm(22, 10, 3, 9);
CoordinateXYZM q2_xyzm(30, 10, 4, 11);

CoordType p1(p1_xyzm);
CoordType p2(p2_xyzm);
CoordType q1(q1_xyzm);
CoordType q2(q2_xyzm);

for (auto _ : state) {
LineIntersector li;
li.computeIntersection(p1, p2, q1, q2);
}
}

BENCHMARK(BM_PointIntersection);
BENCHMARK(BM_Collinear);
BENCHMARK_TEMPLATE(BM_PointIntersection, CoordinateXY);
BENCHMARK_TEMPLATE(BM_PointIntersection, Coordinate);
BENCHMARK_TEMPLATE(BM_PointIntersection, CoordinateXYZM);
BENCHMARK_TEMPLATE(BM_Collinear, CoordinateXY);
BENCHMARK_TEMPLATE(BM_Collinear, Coordinate);
BENCHMARK_TEMPLATE(BM_Collinear, CoordinateXYZM);

BENCHMARK_MAIN();

20 changes: 10 additions & 10 deletions benchmarks/algorithm/VoronoiPerfTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -33,12 +33,12 @@ using geos::geom::Envelope;
static void BM_DelaunayFromSeq(benchmark::State& state) {
Envelope e(0, 100, 0, 100);
auto gfact = geos::geom::GeometryFactory::getDefaultInstance();
std::default_random_engine eng(12345);

std::size_t i = 0;
for (auto _ : state) {
state.PauseTiming();
auto nPts = static_cast<std::size_t>(state.range(0));
auto sites = geos::benchmark::createRandomCoords(e, nPts, i++);
auto sites = geos::benchmark::createRandomCoords(e, nPts, eng);
state.ResumeTiming();

geos::triangulate::DelaunayTriangulationBuilder dtb;
Expand All @@ -50,12 +50,12 @@ static void BM_DelaunayFromSeq(benchmark::State& state) {
static void BM_DelaunayFromGeom(benchmark::State& state) {
Envelope e(0, 100, 0, 100);
auto gfact = geos::geom::GeometryFactory::getDefaultInstance();
std::default_random_engine eng(12345);

std::size_t i = 0;
for (auto _ : state) {
state.PauseTiming();
auto nPts = static_cast<std::size_t>(state.range(0));
auto sites = gfact->createLineString(geos::benchmark::createRandomCoords(e, nPts, i++));
auto sites = gfact->createLineString(geos::benchmark::createRandomCoords(e, nPts, eng));
state.ResumeTiming();

geos::triangulate::DelaunayTriangulationBuilder dtb;
Expand All @@ -67,12 +67,12 @@ static void BM_DelaunayFromGeom(benchmark::State& state) {
static void BM_VoronoiFromSeq(benchmark::State& state) {
Envelope e(0, 100, 0, 100);
auto gfact = geos::geom::GeometryFactory::getDefaultInstance();
std::default_random_engine eng(12345);

std::size_t i = 0;
for (auto _ : state) {
state.PauseTiming();
auto nPts = static_cast<std::size_t>(state.range(0));
auto sites = geos::benchmark::createRandomCoords(e, nPts, i++);
auto sites = geos::benchmark::createRandomCoords(e, nPts, eng);
state.ResumeTiming();

geos::triangulate::VoronoiDiagramBuilder vdb;
Expand All @@ -84,12 +84,12 @@ static void BM_VoronoiFromSeq(benchmark::State& state) {
static void BM_VoronoiFromGeom(benchmark::State& state) {
Envelope e(0, 100, 0, 100);
auto gfact = geos::geom::GeometryFactory::getDefaultInstance();
std::default_random_engine eng(12345);

std::size_t i = 0;
for (auto _ : state) {
state.PauseTiming();
auto nPts = static_cast<std::size_t>(state.range(0));
auto sites = gfact->createLineString(geos::benchmark::createRandomCoords(e, nPts, i++));
auto sites = gfact->createLineString(geos::benchmark::createRandomCoords(e, nPts, eng));
state.ResumeTiming();

geos::triangulate::VoronoiDiagramBuilder vdb;
Expand All @@ -101,12 +101,12 @@ static void BM_VoronoiFromGeom(benchmark::State& state) {
static void BM_OrderedVoronoiFromGeom(benchmark::State& state) {
Envelope e(0, 100, 0, 100);
auto gfact = geos::geom::GeometryFactory::getDefaultInstance();
std::default_random_engine eng(12345);

std::size_t i = 0;
for (auto _ : state) {
state.PauseTiming();
auto nPts = static_cast<std::size_t>(state.range(0));
auto sites = gfact->createLineString(geos::benchmark::createRandomCoords(e, nPts, i++));
auto sites = gfact->createLineString(geos::benchmark::createRandomCoords(e, nPts, eng));
state.ResumeTiming();

geos::triangulate::VoronoiDiagramBuilder vdb;
Expand Down
4 changes: 2 additions & 2 deletions benchmarks/algorithm/locate/PointLocatorPerfTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,14 +27,14 @@ auto nTestsRange = benchmark::CreateDenseRange(1, 20, 1);

template<class Locator>
static void BM_PointInAreaLocator(benchmark::State& state) {
constexpr std::size_t seed = 12345;
std::default_random_engine eng(12345);

auto nRingPts = static_cast<std::size_t>(state.range(0));
auto nTestPts = static_cast<std::size_t>(state.range(1));

auto geom = geos::benchmark::createSineStar({0, 0}, 100, nRingPts);

auto test_pts = geos::benchmark::createRandomCoords(*geom->getEnvelopeInternal(), nTestPts, seed);
auto test_pts = geos::benchmark::createRandomCoords(*geom->getEnvelopeInternal(), nTestPts, eng);

for (auto _ : state) {
Locator loc(*geom);
Expand Down
Loading

0 comments on commit 4292b12

Please sign in to comment.