Skip to content

Commit 7251ca5

Browse files
committed
[experimental] update test-demo with version with lambdas
1 parent a8bd9a0 commit 7251ca5

File tree

3 files changed

+185
-110
lines changed

3 files changed

+185
-110
lines changed

test/robustness/within/Jamfile

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# Boost.Geometry (aka GGL, Generic Geometry Library)
2+
# Robustness Test - partition and within
3+
#
4+
# Copyright (c) 2023 Barend Gehrels, Amsterdam, the Netherlands.
5+
6+
# Use, modification and distribution is subject to the Boost Software License,
7+
# Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
8+
# http://www.boost.org/LICENSE_1_0.txt)
9+
10+
11+
project partition_within
12+
: requirements
13+
<include>.
14+
<link>static
15+
;
16+
17+
exe partition_within : partition_within.cpp ;
+110
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,110 @@
1+
// Boost.Geometry (aka GGL, Generic Geometry Library)
2+
3+
// Copyright (c) 2023 Barend Gehrels, Amsterdam, the Netherlands.
4+
// Use, modification and distribution is subject to the Boost Software License,
5+
// Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
6+
// http://www.boost.org/LICENSE_1_0.txt)
7+
8+
#ifndef BOOST_GEOMETRY_EXPERIMENTAL_LAMBDA_PARTITION_HPP
9+
#define BOOST_GEOMETRY_EXPERIMENTAL_LAMBDA_PARTITION_HPP
10+
11+
#include <boost/range.hpp>
12+
#include <boost/geometry/algorithms/detail/partition.hpp>
13+
14+
#include <functional>
15+
16+
namespace boost { namespace geometry
17+
{
18+
19+
namespace experimental
20+
{
21+
22+
template <typename F>
23+
struct adapt_partition_visitor
24+
{
25+
F m_f;
26+
27+
explicit adapt_partition_visitor(F&& f)
28+
: m_f(std::move(f))
29+
{}
30+
31+
template <typename ...Ts>
32+
decltype(auto) apply(Ts&& ...is) const
33+
{
34+
return m_f(std::forward<Ts>(is)...);
35+
}
36+
};
37+
38+
struct partition_options
39+
{
40+
// Include policy for the first range
41+
using include_policy1 = detail::partition::include_all_policy;
42+
43+
// Include policy for the second range
44+
using include_policy2 = detail::partition::include_all_policy;
45+
46+
// Defines the end of the iteration (as soon as range 1 or range 2 has
47+
// these number of elements, or less, it will switch to iterative mode)
48+
std::size_t min_elements = 16;
49+
};
50+
51+
template
52+
<
53+
typename BoxType,
54+
typename ForwardRange1,
55+
typename ForwardRange2,
56+
typename Options = partition_options
57+
>
58+
bool partition(ForwardRange1 const& forward_range1,
59+
ForwardRange2 const& forward_range2,
60+
const std::function
61+
<
62+
void(BoxType&,
63+
typename boost::range_value<ForwardRange1>::type const&)
64+
>& expand_policy1,
65+
const std::function
66+
<
67+
bool(BoxType const&,
68+
typename boost::range_value<ForwardRange1>::type const&)
69+
>& overlaps_policy1,
70+
const std::function
71+
<
72+
void(BoxType&,
73+
typename boost::range_value<ForwardRange2>::type const&)
74+
>& expand_policy2,
75+
const std::function
76+
<
77+
bool(BoxType const&,
78+
typename boost::range_value<ForwardRange2>::type const&)
79+
>& overlaps_policy2,
80+
const std::function
81+
<
82+
bool(typename boost::range_value<ForwardRange1>::type const&,
83+
typename boost::range_value<ForwardRange2>::type const&)
84+
>& visitor,
85+
const std::function
86+
<
87+
void(BoxType const&, int level)
88+
>& box_visitor = [](auto const&, int) {},
89+
const Options& options = {})
90+
{
91+
adapt_partition_visitor<decltype(visitor)> av(visitor);
92+
adapt_partition_visitor<decltype(expand_policy1)> aev1(expand_policy1);
93+
adapt_partition_visitor<decltype(expand_policy2)> aev2(expand_policy2);
94+
adapt_partition_visitor<decltype(overlaps_policy1)> aov1(overlaps_policy1);
95+
adapt_partition_visitor<decltype(overlaps_policy2)> aov2(overlaps_policy2);
96+
adapt_partition_visitor<decltype(box_visitor)> apbv(box_visitor);
97+
98+
return geometry::partition
99+
<
100+
BoxType,
101+
typename Options::include_policy1,
102+
typename Options::include_policy2
103+
>::apply(forward_range1, forward_range2, av,
104+
aev1, aov1,
105+
aev2, aov2, options.min_elements, apbv);
106+
}
107+
108+
}}} // namespace boost::geometry::experimental
109+
110+
#endif // BOOST_GEOMETRY_EXPERIMENTAL_LAMBDA_PARTITION_HPP

test/robustness/within/partition_within.cpp

+58-110
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
# include <boost/geometry/io/svg/svg_mapper.hpp>
1818
#endif
1919

20+
#include "lambda_partition.hpp"
21+
2022
#include <chrono>
2123
#include <random>
2224
#include <fstream>
@@ -43,112 +45,41 @@ struct ring_item
4345

4446
BOOST_GEOMETRY_REGISTER_POINT_2D(point_item, double, cs::cartesian, x, y)
4547

46-
47-
struct expand_for_point
48-
{
49-
template <typename Box, typename InputItem>
50-
static inline void apply(Box& total, InputItem const& item)
51-
{
52-
bg::expand(total, item);
53-
}
54-
};
55-
56-
struct overlaps_point
48+
#if defined(TEST_WITH_SVG)
49+
template <typename Points, typename Rings, typename Box, typename Boxes>
50+
void create_svg(std::size_t size, Points const& points, Rings const& rings, std::size_t index,
51+
Box const& box, int level,
52+
Boxes& boxes)
5753
{
58-
template <typename Box, typename InputItem>
59-
static inline bool apply(Box const& box, InputItem const& item)
60-
{
61-
return ! bg::disjoint(item, box);
62-
}
63-
};
54+
std::ostringstream filename;
55+
filename << "partition_demo_" << std::setfill('0') << std::setw(3) << index << "_" << level << ".svg";
56+
std::ofstream svg(filename.str());
6457

58+
bg::svg_mapper<point_item> mapper(svg, 800, 800);
6559

66-
struct expand_for_ring
67-
{
68-
template <typename Box, typename InputItem>
69-
static inline void apply(Box& total, InputItem const& item)
7060
{
71-
bg::expand(total, item.box);
61+
point_item p;
62+
p.x = -1; p.y = -1; mapper.add(p);
63+
p.x = size + 1; p.y = size + 1; mapper.add(p);
7264
}
73-
};
7465

75-
struct overlaps_ring
76-
{
77-
template <typename Box, typename InputItem>
78-
static inline bool apply(Box const& box, InputItem const& item)
66+
for (auto const& item : rings)
7967
{
80-
typename bg::strategy::disjoint::services::default_strategy
81-
<
82-
Box, Box
83-
>::type strategy;
84-
85-
return ! bg::detail::disjoint::disjoint_box_box(box, item.box, strategy);
68+
mapper.map(item.ring, "opacity:0.6;fill:rgb(0,255,0);stroke:rgb(0,0,0);stroke-width:0.1");
8669
}
87-
};
88-
89-
struct point_in_ring_visitor
90-
{
91-
std::size_t count = 0;
92-
93-
template <typename Point, typename BoxItem>
94-
inline bool apply(Point const& point, BoxItem const& ring_item)
70+
for (auto const& point : points)
9571
{
96-
if (bg::within(point, ring_item.ring))
97-
{
98-
count++;
99-
}
100-
return true;
72+
mapper.map(point, "fill:rgb(0,0,255);stroke:rgb(0,0,100);stroke-width:0.1", 3);
10173
}
102-
};
10374

104-
#if defined(TEST_WITH_SVG)
105-
template <typename Box, typename Points, typename Rings>
106-
struct svg_visitor
107-
{
108-
std::vector<Box> boxes;
109-
Points const& m_points;
110-
Rings const& m_rings;
111-
std::size_t m_size = 0;
112-
std::size_t m_index = 0;
113-
114-
svg_visitor(std::size_t size, Points const& points, Rings const& rings)
115-
: m_points(points)
116-
, m_rings(rings)
117-
, m_size(size)
118-
{}
119-
120-
inline void apply(Box const& box, int level)
75+
for (auto const& b : boxes)
12176
{
122-
std::ostringstream filename;
123-
filename << "partition_demo_" << std::setfill('0') << std::setw(3) << m_index++ << "_" << level << ".svg";
124-
std::ofstream svg(filename.str());
125-
126-
bg::svg_mapper<point_item> mapper(svg, 800, 800);
127-
128-
{
129-
point_item p;
130-
p.x = -1; p.y = -1; mapper.add(p);
131-
p.x = m_size + 1; p.y = m_size + 1; mapper.add(p);
132-
}
133-
134-
for (auto const& item : m_rings)
135-
{
136-
mapper.map(item.ring, "opacity:0.6;fill:rgb(0,255,0);stroke:rgb(0,0,0);stroke-width:0.1");
137-
}
138-
for (auto const& point : m_points)
139-
{
140-
mapper.map(point, "fill:rgb(0,0,255);stroke:rgb(0,0,100);stroke-width:0.1", 3);
141-
}
142-
143-
for (auto const& b : boxes)
144-
{
145-
mapper.map(b, "fill:none;stroke-width:2;stroke:rgb(64,64,64);");
146-
}
147-
mapper.map(box, "fill:none;stroke-width:4;stroke:rgb(255, 0, 0);");
148-
149-
boxes.push_back(box);
77+
mapper.map(b, "fill:none;stroke-width:2;stroke:rgb(64,64,64);");
15078
}
151-
};
79+
mapper.map(box, "fill:none;stroke-width:4;stroke:rgb(255, 0, 0);");
80+
81+
boxes.push_back(box);
82+
}
15283
#endif
15384

15485

@@ -161,7 +92,7 @@ void fill_points(Collection& collection, std::size_t size, std::size_t count)
16192
std::uniform_real_distribution<double> uniform_dist(0, size - 1);
16293
int const mean_x = uniform_dist(rde);
16394
int const mean_y = uniform_dist(rde);
164-
95+
16596
// Generate a normal distribution around these means
16697
std::seed_seq seed2{rd(), rd(), rd(), rd(), rd(), rd(), rd(), rd()};
16798
std::mt19937 e2(seed2);
@@ -302,7 +233,7 @@ void call_within(std::size_t size, std::size_t count)
302233
auto report = [&points, &rings](const char* title, auto const& start, std::size_t within_count)
303234
{
304235
auto const finish = std::chrono::steady_clock::now();
305-
double const elapsed
236+
double const elapsed
306237
= std::chrono::duration_cast<std::chrono::nanoseconds>(finish - start).count();
307238
std::cout << title << " time: " << std::setprecision(6)
308239
<< elapsed / 1000000.0 << " ms" << std::endl;
@@ -311,27 +242,44 @@ void call_within(std::size_t size, std::size_t count)
311242
return elapsed;
312243
};
313244

314-
point_in_ring_visitor count_visitor;
315-
{
316245
#if defined(TEST_WITH_SVG)
317-
318-
using partition_box_visitor_type = svg_visitor<box_type, std::vector<point_item>, std::vector<ring_item<ring_type>>>;
319-
partition_box_visitor_type partition_box_visitor(size, points, rings);
246+
std::size_t index = 0;
247+
std::vector<box_type> boxes;
248+
auto box_visitor = [&](auto const& box, int level)
249+
{
250+
create_svg(size, points, rings, index++, box, level, boxes);
251+
};
320252
#else
321-
using partition_box_visitor_type = bg::detail::partition::visit_no_policy;
322-
partition_box_visitor_type partition_box_visitor;
253+
auto box_visitor = [&](auto const& , int ) {};
323254
#endif
324255

256+
std::size_t partition_count = 0;
257+
{
325258
auto const start = std::chrono::steady_clock::now();
326259

327-
bg::partition
260+
typename bg::strategy::disjoint::services::default_strategy
328261
<
329-
box_type,
330-
bg::detail::partition::include_all_policy,
331-
bg::detail::partition::include_all_policy
332-
>::apply(points, rings, count_visitor, expand_for_point(), overlaps_point(),
333-
expand_for_ring(), overlaps_ring(), 16, partition_box_visitor);
334-
report("Partition", start, count_visitor.count);
262+
box_type, box_type
263+
>::type strategy;
264+
265+
bg::experimental::partition<box_type>(points,
266+
rings,
267+
[](auto& box, auto const& point) { bg::expand(box, point); },
268+
[](auto const& box, auto const& point) { return ! bg::disjoint(point, box); },
269+
[](auto& box, auto const& item) { bg::expand(box, item.box); },
270+
[&strategy](auto const& box, auto const& item) { return ! bg::disjoint(box, item.box, strategy); },
271+
[&partition_count](auto const& p, auto const& ri)
272+
{
273+
if (bg::within(p, ri.ring))
274+
{
275+
partition_count++;
276+
}
277+
return true;
278+
},
279+
box_visitor
280+
);
281+
282+
report("Partition", start, partition_count);
335283
}
336284

337285
{
@@ -350,7 +298,7 @@ void call_within(std::size_t size, std::size_t count)
350298
}
351299
report("Quadratic loop", start, count);
352300

353-
if (count != count_visitor.count)
301+
if (count != partition_count)
354302
{
355303
std::cerr << "ERROR: counts are not equal" << std::endl;
356304
}

0 commit comments

Comments
 (0)