44// Boost.Geometry equivalents using `cs::spherical_equatorial<degree>` —
55// the same sphere-based model we use, so this is a fair head-to-head.
66//
7+ // Conversion policy (matches bench_s2.cpp):
8+ // * Streams of points: converted INSIDE the timed loop.
9+ // * Long-lived polygon: pre-converted ONCE outside the loop.
10+ //
711// Coordinate convention reminder: Boost.Geometry expects (lng, lat) order
812// for spherical_equatorial points.
13+ //
14+ // Strategy note for `contains`: bg::within with cs::spherical_equatorial
15+ // auto-selects strategy::within::spherical_winding, which traces great-circle
16+ // edges and classifies crossings carefully. Our own `geo::contains` defaults
17+ // to rhumb-line edges (geodesic=false), which is significantly cheaper.
18+ // The performance gap on `contains` reflects this algorithmic difference,
19+ // not a Boost misconfiguration.
920
1021#include < benchmark/benchmark.h>
1122
@@ -85,24 +96,21 @@ static void BM_Boost_Heading(benchmark::State& state) {
8596}
8697BENCHMARK (BM_Boost_Heading)->Arg(1000 )->Arg(100000 );
8798
88- // --- contains (within) --------------------------------------------------- --
99+ // --- contains: polygon converted once; queries converted inside the loop --
89100
90101static void BM_Boost_Contains (benchmark::State& state) {
91102 const auto poly_ll = geo::bench::regular_polygon (
92103 static_cast <std::size_t >(state.range (0 )), 40.0 , -74.0 , 5.0 );
93104 const Polygon poly = to_boost_polygon (poly_ll);
94105
95106 const auto queries_ll = geo::bench::queries_around (40.0 , -74.0 , 5.0 , 1000 );
96- std::vector<Point> queries;
97- queries.reserve (queries_ll.size ());
98- for (const auto & q : queries_ll) queries.push_back (to_boost_point (q));
99107
100108 for (auto _ : state) {
101- for (const auto & q : queries ) {
102- benchmark::DoNotOptimize (bg::within (q , poly));
109+ for (const auto & q : queries_ll ) {
110+ benchmark::DoNotOptimize (bg::within (to_boost_point (q) , poly));
103111 }
104112 }
105- state.SetItemsProcessed (state.iterations () * static_cast <std::int64_t >(queries .size ()));
113+ state.SetItemsProcessed (state.iterations () * static_cast <std::int64_t >(queries_ll .size ()));
106114}
107115BENCHMARK (BM_Boost_Contains)->Arg(10 )->Arg(100 )->Arg(1000 );
108116
@@ -122,13 +130,13 @@ static void BM_Boost_Area(benchmark::State& state) {
122130}
123131BENCHMARK (BM_Boost_Area)->Arg(10 )->Arg(100 )->Arg(1000 );
124132
125- // --- path_length -------------------------------------------------------- ---
133+ // --- path_length: input is lat/lng; convert + sum inside the timed loop ---
126134
127135static void BM_Boost_PathLength (benchmark::State& state) {
128136 const auto path_ll = geo::bench::random_points (static_cast <std::size_t >(state.range (0 )));
129- const LineString ls = to_boost_linestring (path_ll);
130137 bg::strategy::distance::haversine<double > haversine (kEarthRadius );
131138 for (auto _ : state) {
139+ LineString ls = to_boost_linestring (path_ll);
132140 benchmark::DoNotOptimize (bg::length (ls, haversine));
133141 }
134142 state.SetItemsProcessed (state.iterations () * state.range (0 ));
0 commit comments