File: GridIntersectionPerfTest.cpp

package info (click to toggle)
geos 3.14.1-2
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 31,212 kB
  • sloc: cpp: 199,103; xml: 56,065; ansic: 6,162; sh: 287; makefile: 26
file content (121 lines) | stat: -rw-r--r-- 4,232 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/**********************************************************************
 *
 * GEOS - Geometry Engine Open Source
 * http://geos.osgeo.org
 *
 * Copyright (C) 2025 ISciences LLC
 *
 * 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 <BenchmarkUtils.h>

#include <geos/geom/Envelope.h>
#include <geos/geom/prep/PreparedGeometryFactory.h>
#include <geos/operation/grid/Grid.h>

#include <geos/operation/grid/GridIntersection.h>
#include <geos/operation/intersection/Rectangle.h>
#include <geos/operation/intersection/RectangleIntersection.h>

using geos::geom::CoordinateXY;
using geos::geom::Envelope;
using geos::geom::Geometry;
using Grid = geos::operation::grid::Grid<geos::operation::grid::bounded_extent>;

template<bool AreaOnly>
struct GridIntersection {
    static double Intersection(const Envelope& env, int nx, int ny, const Geometry& g) {
         Grid grid(env, env.getWidth() / nx, env.getHeight() / ny);
         if constexpr (AreaOnly) {
             auto result = geos::operation::grid::GridIntersection::getIntersectionFractions(grid, g);
             float area = 0;
             for (std::size_t i = 0; i < result->getNumRows(); i++) {
                 for (std::size_t j = 0; j < result->getNumCols(); j++) {
                    area += (*result)(i, j);
                 }
             }
            return static_cast<double>(area);
         } else {
             auto subdivided = geos::operation::grid::GridIntersection::subdividePolygon(grid, g, true);
             return subdivided->getArea();
         }
    }
};

using GridIntersectionAreaOnly = GridIntersection<true>;
using GridIntersectionFull = GridIntersection<false>;

template<bool UseRectangleIntersection>
struct SingleIntersection {

    static double Intersection(const Envelope& env, int nx, int ny, const Geometry& g) {
        double dx = env.getWidth() / nx;
        double dy = env.getHeight() / ny;

        double x0 = env.getMinX();
        double y0 = env.getMinY();

        const auto& gfact = *g.getFactory();
        auto prepGeom = geos::geom::prep::PreparedGeometryFactory::prepare(&g);

        double area = 0;

        for (int i = 0; i < nx; i++) {
            for (int j = 0; j < ny; j++) {
                Envelope subEnv(x0 + i*dx, x0 + (i+1)*dx, y0 + j*dy, y0 + (j+1)*dy);
                auto cellGeom = gfact.toGeometry(&subEnv);
                if (!prepGeom->intersects(cellGeom.get())) {
                    continue;
                }

                std::unique_ptr<Geometry> isect;
                if constexpr (UseRectangleIntersection) {
                    geos::operation::intersection::Rectangle rect(x0 + i*dx, y0 + j*dy, x0 + (i+1)*dx, y0 + (j+1)*dy);
                    isect = geos::operation::intersection::RectangleIntersection::clip(g, rect);
                } else {
                    isect = g.intersection(cellGeom.get());
                }

                area += isect->getArea();
            }
        }

        return area;
    }
};

using PolygonIntersection = SingleIntersection<false>;
using RectangleIntersection = SingleIntersection<true>;

template<typename Impl>
static void BM_GridIntersection(benchmark::State& state)
{
    auto nCells = state.range(0);

    auto nx = static_cast<int>(std::ceil(std::sqrt(nCells)));
    auto ny = static_cast<int>(std::ceil(std::sqrt(nCells)));

    CoordinateXY center;
    Envelope env(0, nx, 0, ny);
    env.centre(center);

    auto geom = geos::benchmark::createSineStar(center, env.getWidth() / 2, 500);

    for (auto _ : state) {
        Impl::Intersection(env, nx, ny, *geom);
    }

}

BENCHMARK_TEMPLATE(BM_GridIntersection, GridIntersectionAreaOnly)->Range(1000, 1000000);
BENCHMARK_TEMPLATE(BM_GridIntersection, GridIntersectionFull)->Range(1000, 1000000);
BENCHMARK_TEMPLATE(BM_GridIntersection, RectangleIntersection)->Range(1000, 1000000);
BENCHMARK_TEMPLATE(BM_GridIntersection, PolygonIntersection)->Range(1000, 1000000);

BENCHMARK_MAIN();