annotate DEPENDENCIES/generic/include/boost/geometry/algorithms/centroid.hpp @ 125:34e428693f5d vext

Vext -> Repoint
author Chris Cannam
date Thu, 14 Jun 2018 11:15:39 +0100
parents c530137014c0
children
rev   line source
Chris@16 1 // Boost.Geometry (aka GGL, Generic Geometry Library)
Chris@16 2
Chris@16 3 // Copyright (c) 2007-2012 Barend Gehrels, Amsterdam, the Netherlands.
Chris@16 4 // Copyright (c) 2008-2012 Bruno Lalande, Paris, France.
Chris@16 5 // Copyright (c) 2009-2012 Mateusz Loskot, London, UK.
Chris@101 6 // Copyright (c) 2014 Adam Wulkiewicz, Lodz, Poland.
Chris@101 7
Chris@101 8 // This file was modified by Oracle on 2014, 2015.
Chris@101 9 // Modifications copyright (c) 2014-2015 Oracle and/or its affiliates.
Chris@101 10
Chris@101 11 // Contributed and/or modified by Adam Wulkiewicz, on behalf of Oracle
Chris@16 12
Chris@16 13 // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library
Chris@16 14 // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands.
Chris@16 15
Chris@16 16 // Use, modification and distribution is subject to the Boost Software License,
Chris@16 17 // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at
Chris@16 18 // http://www.boost.org/LICENSE_1_0.txt)
Chris@16 19
Chris@16 20 #ifndef BOOST_GEOMETRY_ALGORITHMS_CENTROID_HPP
Chris@16 21 #define BOOST_GEOMETRY_ALGORITHMS_CENTROID_HPP
Chris@16 22
Chris@16 23
Chris@16 24 #include <cstddef>
Chris@16 25
Chris@101 26 #include <boost/core/ignore_unused.hpp>
Chris@16 27 #include <boost/range.hpp>
Chris@101 28
Chris@101 29 #include <boost/variant/apply_visitor.hpp>
Chris@101 30 #include <boost/variant/static_visitor.hpp>
Chris@101 31 #include <boost/variant/variant_fwd.hpp>
Chris@16 32
Chris@16 33 #include <boost/geometry/core/closure.hpp>
Chris@16 34 #include <boost/geometry/core/cs.hpp>
Chris@16 35 #include <boost/geometry/core/coordinate_dimension.hpp>
Chris@16 36 #include <boost/geometry/core/exception.hpp>
Chris@16 37 #include <boost/geometry/core/exterior_ring.hpp>
Chris@16 38 #include <boost/geometry/core/interior_rings.hpp>
Chris@16 39 #include <boost/geometry/core/tag_cast.hpp>
Chris@101 40 #include <boost/geometry/core/tags.hpp>
Chris@101 41 #include <boost/geometry/core/point_type.hpp>
Chris@16 42
Chris@101 43 #include <boost/geometry/geometries/concepts/check.hpp>
Chris@101 44
Chris@101 45 #include <boost/geometry/algorithms/assign.hpp>
Chris@16 46 #include <boost/geometry/algorithms/convert.hpp>
Chris@101 47 #include <boost/geometry/algorithms/detail/interior_iterator.hpp>
Chris@101 48 #include <boost/geometry/algorithms/detail/point_on_border.hpp>
Chris@16 49 #include <boost/geometry/algorithms/not_implemented.hpp>
Chris@16 50 #include <boost/geometry/strategies/centroid.hpp>
Chris@16 51 #include <boost/geometry/strategies/concepts/centroid_concept.hpp>
Chris@101 52 #include <boost/geometry/strategies/default_strategy.hpp>
Chris@16 53 #include <boost/geometry/views/closeable_view.hpp>
Chris@16 54
Chris@16 55 #include <boost/geometry/util/for_each_coordinate.hpp>
Chris@16 56 #include <boost/geometry/util/select_coordinate_type.hpp>
Chris@16 57
Chris@101 58 #include <boost/geometry/algorithms/num_points.hpp>
Chris@101 59 #include <boost/geometry/multi/algorithms/num_points.hpp>
Chris@101 60
Chris@101 61 #include <boost/geometry/algorithms/detail/centroid/translating_transformer.hpp>
Chris@16 62
Chris@16 63
Chris@16 64 namespace boost { namespace geometry
Chris@16 65 {
Chris@16 66
Chris@16 67
Chris@16 68 #if ! defined(BOOST_GEOMETRY_CENTROID_NO_THROW)
Chris@16 69
Chris@16 70 /*!
Chris@16 71 \brief Centroid Exception
Chris@16 72 \ingroup centroid
Chris@16 73 \details The centroid_exception is thrown if the free centroid function is called with
Chris@16 74 geometries for which the centroid cannot be calculated. For example: a linestring
Chris@16 75 without points, a polygon without points, an empty multi-geometry.
Chris@16 76 \qbk{
Chris@16 77 [heading See also]
Chris@16 78 \* [link geometry.reference.algorithms.centroid the centroid function]
Chris@16 79 }
Chris@16 80
Chris@16 81 */
Chris@16 82 class centroid_exception : public geometry::exception
Chris@16 83 {
Chris@16 84 public:
Chris@16 85
Chris@101 86 /*!
Chris@101 87 \brief The default constructor
Chris@101 88 */
Chris@16 89 inline centroid_exception() {}
Chris@16 90
Chris@101 91 /*!
Chris@101 92 \brief Returns the explanatory string.
Chris@101 93 \return Pointer to a null-terminated string with explanatory information.
Chris@101 94 */
Chris@16 95 virtual char const* what() const throw()
Chris@16 96 {
Chris@16 97 return "Boost.Geometry Centroid calculation exception";
Chris@16 98 }
Chris@16 99 };
Chris@16 100
Chris@16 101 #endif
Chris@16 102
Chris@16 103
Chris@16 104 #ifndef DOXYGEN_NO_DETAIL
Chris@16 105 namespace detail { namespace centroid
Chris@16 106 {
Chris@16 107
Chris@16 108 struct centroid_point
Chris@16 109 {
Chris@16 110 template<typename Point, typename PointCentroid, typename Strategy>
Chris@16 111 static inline void apply(Point const& point, PointCentroid& centroid,
Chris@16 112 Strategy const&)
Chris@16 113 {
Chris@16 114 geometry::convert(point, centroid);
Chris@16 115 }
Chris@16 116 };
Chris@16 117
Chris@16 118 template
Chris@16 119 <
Chris@16 120 typename Indexed,
Chris@16 121 typename Point,
Chris@101 122 std::size_t Dimension = 0,
Chris@101 123 std::size_t DimensionCount = dimension<Indexed>::type::value
Chris@16 124 >
Chris@16 125 struct centroid_indexed_calculator
Chris@16 126 {
Chris@16 127 typedef typename select_coordinate_type
Chris@16 128 <
Chris@16 129 Indexed, Point
Chris@16 130 >::type coordinate_type;
Chris@16 131 static inline void apply(Indexed const& indexed, Point& centroid)
Chris@16 132 {
Chris@16 133 coordinate_type const c1 = get<min_corner, Dimension>(indexed);
Chris@16 134 coordinate_type const c2 = get<max_corner, Dimension>(indexed);
Chris@16 135 coordinate_type m = c1 + c2;
Chris@16 136 coordinate_type const two = 2;
Chris@16 137 m /= two;
Chris@16 138
Chris@16 139 set<Dimension>(centroid, m);
Chris@16 140
Chris@16 141 centroid_indexed_calculator
Chris@16 142 <
Chris@101 143 Indexed, Point, Dimension + 1
Chris@16 144 >::apply(indexed, centroid);
Chris@16 145 }
Chris@16 146 };
Chris@16 147
Chris@16 148
Chris@16 149 template<typename Indexed, typename Point, std::size_t DimensionCount>
Chris@16 150 struct centroid_indexed_calculator<Indexed, Point, DimensionCount, DimensionCount>
Chris@16 151 {
Chris@16 152 static inline void apply(Indexed const& , Point& )
Chris@16 153 {
Chris@16 154 }
Chris@16 155 };
Chris@16 156
Chris@16 157
Chris@16 158 struct centroid_indexed
Chris@16 159 {
Chris@16 160 template<typename Indexed, typename Point, typename Strategy>
Chris@16 161 static inline void apply(Indexed const& indexed, Point& centroid,
Chris@16 162 Strategy const&)
Chris@16 163 {
Chris@16 164 centroid_indexed_calculator
Chris@16 165 <
Chris@101 166 Indexed, Point
Chris@16 167 >::apply(indexed, centroid);
Chris@16 168 }
Chris@16 169 };
Chris@16 170
Chris@16 171
Chris@16 172 // There is one thing where centroid is different from e.g. within.
Chris@16 173 // If the ring has only one point, it might make sense that
Chris@16 174 // that point is the centroid.
Chris@16 175 template<typename Point, typename Range>
Chris@16 176 inline bool range_ok(Range const& range, Point& centroid)
Chris@16 177 {
Chris@16 178 std::size_t const n = boost::size(range);
Chris@16 179 if (n > 1)
Chris@16 180 {
Chris@16 181 return true;
Chris@16 182 }
Chris@16 183 else if (n <= 0)
Chris@16 184 {
Chris@16 185 #if ! defined(BOOST_GEOMETRY_CENTROID_NO_THROW)
Chris@16 186 throw centroid_exception();
Chris@101 187 #else
Chris@101 188 return false;
Chris@16 189 #endif
Chris@16 190 }
Chris@16 191 else // if (n == 1)
Chris@16 192 {
Chris@16 193 // Take over the first point in a "coordinate neutral way"
Chris@16 194 geometry::convert(*boost::begin(range), centroid);
Chris@16 195 return false;
Chris@16 196 }
Chris@101 197 //return true; // unreachable
Chris@16 198 }
Chris@16 199
Chris@16 200 /*!
Chris@101 201 \brief Calculate the centroid of a Ring or a Linestring.
Chris@16 202 */
Chris@16 203 template <closure_selector Closure>
Chris@16 204 struct centroid_range_state
Chris@16 205 {
Chris@101 206 template<typename Ring, typename PointTransformer, typename Strategy>
Chris@16 207 static inline void apply(Ring const& ring,
Chris@101 208 PointTransformer const& transformer,
Chris@101 209 Strategy const& strategy,
Chris@101 210 typename Strategy::state_type& state)
Chris@16 211 {
Chris@101 212 boost::ignore_unused(strategy);
Chris@101 213
Chris@101 214 typedef typename geometry::point_type<Ring const>::type point_type;
Chris@16 215 typedef typename closeable_view<Ring const, Closure>::type view_type;
Chris@16 216
Chris@16 217 typedef typename boost::range_iterator<view_type const>::type iterator_type;
Chris@16 218
Chris@16 219 view_type view(ring);
Chris@16 220 iterator_type it = boost::begin(view);
Chris@16 221 iterator_type end = boost::end(view);
Chris@16 222
Chris@101 223 typename PointTransformer::result_type
Chris@101 224 previous_pt = transformer.apply(*it);
Chris@101 225
Chris@101 226 for ( ++it ; it != end ; ++it)
Chris@16 227 {
Chris@101 228 typename PointTransformer::result_type
Chris@101 229 pt = transformer.apply(*it);
Chris@101 230
Chris@101 231 strategy.apply(static_cast<point_type const&>(previous_pt),
Chris@101 232 static_cast<point_type const&>(pt),
Chris@101 233 state);
Chris@101 234
Chris@101 235 previous_pt = pt;
Chris@16 236 }
Chris@16 237 }
Chris@16 238 };
Chris@16 239
Chris@16 240 template <closure_selector Closure>
Chris@16 241 struct centroid_range
Chris@16 242 {
Chris@16 243 template<typename Range, typename Point, typename Strategy>
Chris@101 244 static inline bool apply(Range const& range, Point& centroid,
Chris@101 245 Strategy const& strategy)
Chris@16 246 {
Chris@16 247 if (range_ok(range, centroid))
Chris@16 248 {
Chris@101 249 // prepare translation transformer
Chris@101 250 translating_transformer<Range> transformer(*boost::begin(range));
Chris@101 251
Chris@16 252 typename Strategy::state_type state;
Chris@101 253 centroid_range_state<Closure>::apply(range, transformer,
Chris@101 254 strategy, state);
Chris@101 255
Chris@101 256 if ( strategy.result(state, centroid) )
Chris@101 257 {
Chris@101 258 // translate the result back
Chris@101 259 transformer.apply_reverse(centroid);
Chris@101 260 return true;
Chris@101 261 }
Chris@16 262 }
Chris@101 263
Chris@101 264 return false;
Chris@16 265 }
Chris@16 266 };
Chris@16 267
Chris@16 268
Chris@16 269 /*!
Chris@16 270 \brief Centroid of a polygon.
Chris@16 271 \note Because outer ring is clockwise, inners are counter clockwise,
Chris@16 272 triangle approach is OK and works for polygons with rings.
Chris@16 273 */
Chris@16 274 struct centroid_polygon_state
Chris@16 275 {
Chris@101 276 template<typename Polygon, typename PointTransformer, typename Strategy>
Chris@16 277 static inline void apply(Polygon const& poly,
Chris@101 278 PointTransformer const& transformer,
Chris@101 279 Strategy const& strategy,
Chris@101 280 typename Strategy::state_type& state)
Chris@16 281 {
Chris@16 282 typedef typename ring_type<Polygon>::type ring_type;
Chris@16 283 typedef centroid_range_state<geometry::closure<ring_type>::value> per_ring;
Chris@16 284
Chris@101 285 per_ring::apply(exterior_ring(poly), transformer, strategy, state);
Chris@16 286
Chris@101 287 typename interior_return_type<Polygon const>::type
Chris@101 288 rings = interior_rings(poly);
Chris@101 289
Chris@101 290 for (typename detail::interior_iterator<Polygon const>::type
Chris@101 291 it = boost::begin(rings); it != boost::end(rings); ++it)
Chris@16 292 {
Chris@101 293 per_ring::apply(*it, transformer, strategy, state);
Chris@16 294 }
Chris@16 295 }
Chris@16 296 };
Chris@16 297
Chris@16 298 struct centroid_polygon
Chris@16 299 {
Chris@16 300 template<typename Polygon, typename Point, typename Strategy>
Chris@101 301 static inline bool apply(Polygon const& poly, Point& centroid,
Chris@101 302 Strategy const& strategy)
Chris@16 303 {
Chris@16 304 if (range_ok(exterior_ring(poly), centroid))
Chris@16 305 {
Chris@101 306 // prepare translation transformer
Chris@101 307 translating_transformer<Polygon>
Chris@101 308 transformer(*boost::begin(exterior_ring(poly)));
Chris@101 309
Chris@16 310 typename Strategy::state_type state;
Chris@101 311 centroid_polygon_state::apply(poly, transformer, strategy, state);
Chris@101 312
Chris@101 313 if ( strategy.result(state, centroid) )
Chris@101 314 {
Chris@101 315 // translate the result back
Chris@101 316 transformer.apply_reverse(centroid);
Chris@101 317 return true;
Chris@101 318 }
Chris@101 319 }
Chris@101 320
Chris@101 321 return false;
Chris@101 322 }
Chris@101 323 };
Chris@101 324
Chris@101 325
Chris@101 326 /*!
Chris@101 327 \brief Building block of a multi-point, to be used as Policy in the
Chris@101 328 more generec centroid_multi
Chris@101 329 */
Chris@101 330 struct centroid_multi_point_state
Chris@101 331 {
Chris@101 332 template <typename Point, typename PointTransformer, typename Strategy>
Chris@101 333 static inline void apply(Point const& point,
Chris@101 334 PointTransformer const& transformer,
Chris@101 335 Strategy const& strategy,
Chris@101 336 typename Strategy::state_type& state)
Chris@101 337 {
Chris@101 338 boost::ignore_unused(strategy);
Chris@101 339 strategy.apply(static_cast<Point const&>(transformer.apply(point)),
Chris@101 340 state);
Chris@101 341 }
Chris@101 342 };
Chris@101 343
Chris@101 344
Chris@101 345 /*!
Chris@101 346 \brief Generic implementation which calls a policy to calculate the
Chris@101 347 centroid of the total of its single-geometries
Chris@101 348 \details The Policy is, in general, the single-version, with state. So
Chris@101 349 detail::centroid::centroid_polygon_state is used as a policy for this
Chris@101 350 detail::centroid::centroid_multi
Chris@101 351
Chris@101 352 */
Chris@101 353 template <typename Policy>
Chris@101 354 struct centroid_multi
Chris@101 355 {
Chris@101 356 template <typename Multi, typename Point, typename Strategy>
Chris@101 357 static inline bool apply(Multi const& multi,
Chris@101 358 Point& centroid,
Chris@101 359 Strategy const& strategy)
Chris@101 360 {
Chris@101 361 #if ! defined(BOOST_GEOMETRY_CENTROID_NO_THROW)
Chris@101 362 // If there is nothing in any of the ranges, it is not possible
Chris@101 363 // to calculate the centroid
Chris@101 364 if (geometry::num_points(multi) == 0)
Chris@101 365 {
Chris@101 366 throw centroid_exception();
Chris@101 367 }
Chris@101 368 #endif
Chris@101 369
Chris@101 370 // prepare translation transformer
Chris@101 371 translating_transformer<Multi> transformer(multi);
Chris@101 372
Chris@101 373 typename Strategy::state_type state;
Chris@101 374
Chris@101 375 for (typename boost::range_iterator<Multi const>::type
Chris@101 376 it = boost::begin(multi);
Chris@101 377 it != boost::end(multi);
Chris@101 378 ++it)
Chris@101 379 {
Chris@101 380 Policy::apply(*it, transformer, strategy, state);
Chris@101 381 }
Chris@101 382
Chris@101 383 if ( strategy.result(state, centroid) )
Chris@101 384 {
Chris@101 385 // translate the result back
Chris@101 386 transformer.apply_reverse(centroid);
Chris@101 387 return true;
Chris@101 388 }
Chris@101 389
Chris@101 390 return false;
Chris@101 391 }
Chris@101 392 };
Chris@101 393
Chris@101 394
Chris@101 395 template <typename Algorithm>
Chris@101 396 struct centroid_linear_areal
Chris@101 397 {
Chris@101 398 template <typename Geometry, typename Point, typename Strategy>
Chris@101 399 static inline void apply(Geometry const& geom,
Chris@101 400 Point& centroid,
Chris@101 401 Strategy const& strategy)
Chris@101 402 {
Chris@101 403 if ( ! Algorithm::apply(geom, centroid, strategy) )
Chris@101 404 {
Chris@101 405 geometry::point_on_border(centroid, geom);
Chris@16 406 }
Chris@16 407 }
Chris@16 408 };
Chris@16 409
Chris@16 410
Chris@16 411 }} // namespace detail::centroid
Chris@16 412 #endif // DOXYGEN_NO_DETAIL
Chris@16 413
Chris@16 414
Chris@16 415 #ifndef DOXYGEN_NO_DISPATCH
Chris@16 416 namespace dispatch
Chris@16 417 {
Chris@16 418
Chris@16 419 template
Chris@16 420 <
Chris@16 421 typename Geometry,
Chris@16 422 typename Tag = typename tag<Geometry>::type
Chris@16 423 >
Chris@16 424 struct centroid: not_implemented<Tag>
Chris@16 425 {};
Chris@16 426
Chris@16 427 template <typename Geometry>
Chris@16 428 struct centroid<Geometry, point_tag>
Chris@16 429 : detail::centroid::centroid_point
Chris@16 430 {};
Chris@16 431
Chris@16 432 template <typename Box>
Chris@16 433 struct centroid<Box, box_tag>
Chris@16 434 : detail::centroid::centroid_indexed
Chris@16 435 {};
Chris@16 436
Chris@16 437 template <typename Segment>
Chris@16 438 struct centroid<Segment, segment_tag>
Chris@16 439 : detail::centroid::centroid_indexed
Chris@16 440 {};
Chris@16 441
Chris@16 442 template <typename Ring>
Chris@16 443 struct centroid<Ring, ring_tag>
Chris@101 444 : detail::centroid::centroid_linear_areal
Chris@101 445 <
Chris@101 446 detail::centroid::centroid_range<geometry::closure<Ring>::value>
Chris@101 447 >
Chris@16 448 {};
Chris@16 449
Chris@16 450 template <typename Linestring>
Chris@16 451 struct centroid<Linestring, linestring_tag>
Chris@101 452 : detail::centroid::centroid_linear_areal
Chris@101 453 <
Chris@101 454 detail::centroid::centroid_range<closed>
Chris@101 455 >
Chris@101 456 {};
Chris@16 457
Chris@16 458 template <typename Polygon>
Chris@16 459 struct centroid<Polygon, polygon_tag>
Chris@101 460 : detail::centroid::centroid_linear_areal
Chris@101 461 <
Chris@101 462 detail::centroid::centroid_polygon
Chris@101 463 >
Chris@101 464 {};
Chris@101 465
Chris@101 466 template <typename MultiLinestring>
Chris@101 467 struct centroid<MultiLinestring, multi_linestring_tag>
Chris@101 468 : detail::centroid::centroid_linear_areal
Chris@101 469 <
Chris@101 470 detail::centroid::centroid_multi
Chris@101 471 <
Chris@101 472 detail::centroid::centroid_range_state<closed>
Chris@101 473 >
Chris@101 474 >
Chris@101 475 {};
Chris@101 476
Chris@101 477 template <typename MultiPolygon>
Chris@101 478 struct centroid<MultiPolygon, multi_polygon_tag>
Chris@101 479 : detail::centroid::centroid_linear_areal
Chris@101 480 <
Chris@101 481 detail::centroid::centroid_multi
Chris@101 482 <
Chris@101 483 detail::centroid::centroid_polygon_state
Chris@101 484 >
Chris@101 485 >
Chris@101 486 {};
Chris@101 487
Chris@101 488 template <typename MultiPoint>
Chris@101 489 struct centroid<MultiPoint, multi_point_tag>
Chris@101 490 : detail::centroid::centroid_multi
Chris@101 491 <
Chris@101 492 detail::centroid::centroid_multi_point_state
Chris@101 493 >
Chris@101 494 {};
Chris@101 495
Chris@16 496
Chris@16 497 } // namespace dispatch
Chris@16 498 #endif // DOXYGEN_NO_DISPATCH
Chris@16 499
Chris@16 500
Chris@101 501 namespace resolve_strategy {
Chris@101 502
Chris@101 503 template <typename Geometry>
Chris@101 504 struct centroid
Chris@101 505 {
Chris@101 506 template <typename Point, typename Strategy>
Chris@101 507 static inline void apply(Geometry const& geometry, Point& out, Strategy const& strategy)
Chris@101 508 {
Chris@101 509 dispatch::centroid<Geometry>::apply(geometry, out, strategy);
Chris@101 510 }
Chris@101 511
Chris@101 512 template <typename Point>
Chris@101 513 static inline void apply(Geometry const& geometry, Point& out, default_strategy)
Chris@101 514 {
Chris@101 515 typedef typename strategy::centroid::services::default_strategy
Chris@101 516 <
Chris@101 517 typename cs_tag<Geometry>::type,
Chris@101 518 typename tag_cast
Chris@101 519 <
Chris@101 520 typename tag<Geometry>::type,
Chris@101 521 pointlike_tag,
Chris@101 522 linear_tag,
Chris@101 523 areal_tag
Chris@101 524 >::type,
Chris@101 525 dimension<Geometry>::type::value,
Chris@101 526 Point,
Chris@101 527 Geometry
Chris@101 528 >::type strategy_type;
Chris@101 529
Chris@101 530 dispatch::centroid<Geometry>::apply(geometry, out, strategy_type());
Chris@101 531 }
Chris@101 532 };
Chris@101 533
Chris@101 534 } // namespace resolve_strategy
Chris@101 535
Chris@101 536
Chris@101 537 namespace resolve_variant {
Chris@101 538
Chris@101 539 template <typename Geometry>
Chris@101 540 struct centroid
Chris@101 541 {
Chris@101 542 template <typename Point, typename Strategy>
Chris@101 543 static inline void apply(Geometry const& geometry, Point& out, Strategy const& strategy)
Chris@101 544 {
Chris@101 545 concept::check_concepts_and_equal_dimensions<Point, Geometry const>();
Chris@101 546 resolve_strategy::centroid<Geometry>::apply(geometry, out, strategy);
Chris@101 547 }
Chris@101 548 };
Chris@101 549
Chris@101 550 template <BOOST_VARIANT_ENUM_PARAMS(typename T)>
Chris@101 551 struct centroid<boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> >
Chris@101 552 {
Chris@101 553 template <typename Point, typename Strategy>
Chris@101 554 struct visitor: boost::static_visitor<void>
Chris@101 555 {
Chris@101 556 Point& m_out;
Chris@101 557 Strategy const& m_strategy;
Chris@101 558
Chris@101 559 visitor(Point& out, Strategy const& strategy)
Chris@101 560 : m_out(out), m_strategy(strategy)
Chris@101 561 {}
Chris@101 562
Chris@101 563 template <typename Geometry>
Chris@101 564 void operator()(Geometry const& geometry) const
Chris@101 565 {
Chris@101 566 centroid<Geometry>::apply(geometry, m_out, m_strategy);
Chris@101 567 }
Chris@101 568 };
Chris@101 569
Chris@101 570 template <typename Point, typename Strategy>
Chris@101 571 static inline void
Chris@101 572 apply(boost::variant<BOOST_VARIANT_ENUM_PARAMS(T)> const& geometry,
Chris@101 573 Point& out,
Chris@101 574 Strategy const& strategy)
Chris@101 575 {
Chris@101 576 boost::apply_visitor(visitor<Point, Strategy>(out, strategy), geometry);
Chris@101 577 }
Chris@101 578 };
Chris@101 579
Chris@101 580 } // namespace resolve_variant
Chris@101 581
Chris@101 582
Chris@16 583 /*!
Chris@16 584 \brief \brief_calc{centroid} \brief_strategy
Chris@16 585 \ingroup centroid
Chris@16 586 \details \details_calc{centroid,geometric center (or: center of mass)}. \details_strategy_reasons
Chris@16 587 \tparam Geometry \tparam_geometry
Chris@16 588 \tparam Point \tparam_point
Chris@16 589 \tparam Strategy \tparam_strategy{Centroid}
Chris@16 590 \param geometry \param_geometry
Chris@16 591 \param c \param_point \param_set{centroid}
Chris@16 592 \param strategy \param_strategy{centroid}
Chris@16 593
Chris@16 594 \qbk{distinguish,with strategy}
Chris@16 595 \qbk{[include reference/algorithms/centroid.qbk]}
Chris@16 596 \qbk{[include reference/algorithms/centroid_strategies.qbk]}
Chris@16 597 }
Chris@16 598
Chris@16 599 */
Chris@16 600 template<typename Geometry, typename Point, typename Strategy>
Chris@16 601 inline void centroid(Geometry const& geometry, Point& c,
Chris@16 602 Strategy const& strategy)
Chris@16 603 {
Chris@101 604 resolve_variant::centroid<Geometry>::apply(geometry, c, strategy);
Chris@16 605 }
Chris@16 606
Chris@16 607
Chris@16 608 /*!
Chris@16 609 \brief \brief_calc{centroid}
Chris@16 610 \ingroup centroid
Chris@16 611 \details \details_calc{centroid,geometric center (or: center of mass)}. \details_default_strategy
Chris@16 612 \tparam Geometry \tparam_geometry
Chris@16 613 \tparam Point \tparam_point
Chris@16 614 \param geometry \param_geometry
Chris@16 615 \param c The calculated centroid will be assigned to this point reference
Chris@16 616
Chris@16 617 \qbk{[include reference/algorithms/centroid.qbk]}
Chris@16 618 \qbk{
Chris@16 619 [heading Example]
Chris@16 620 [centroid]
Chris@16 621 [centroid_output]
Chris@16 622 }
Chris@16 623 */
Chris@16 624 template<typename Geometry, typename Point>
Chris@16 625 inline void centroid(Geometry const& geometry, Point& c)
Chris@16 626 {
Chris@101 627 centroid(geometry, c, default_strategy());
Chris@16 628 }
Chris@16 629
Chris@16 630
Chris@16 631 /*!
Chris@16 632 \brief \brief_calc{centroid}
Chris@16 633 \ingroup centroid
Chris@16 634 \details \details_calc{centroid,geometric center (or: center of mass)}. \details_return{centroid}.
Chris@16 635 \tparam Point \tparam_point
Chris@16 636 \tparam Geometry \tparam_geometry
Chris@16 637 \param geometry \param_geometry
Chris@16 638 \return \return_calc{centroid}
Chris@16 639
Chris@16 640 \qbk{[include reference/algorithms/centroid.qbk]}
Chris@16 641 */
Chris@16 642 template<typename Point, typename Geometry>
Chris@16 643 inline Point return_centroid(Geometry const& geometry)
Chris@16 644 {
Chris@16 645 Point c;
Chris@16 646 centroid(geometry, c);
Chris@16 647 return c;
Chris@16 648 }
Chris@16 649
Chris@16 650 /*!
Chris@16 651 \brief \brief_calc{centroid} \brief_strategy
Chris@16 652 \ingroup centroid
Chris@16 653 \details \details_calc{centroid,geometric center (or: center of mass)}. \details_return{centroid}. \details_strategy_reasons
Chris@16 654 \tparam Point \tparam_point
Chris@16 655 \tparam Geometry \tparam_geometry
Chris@16 656 \tparam Strategy \tparam_strategy{centroid}
Chris@16 657 \param geometry \param_geometry
Chris@16 658 \param strategy \param_strategy{centroid}
Chris@16 659 \return \return_calc{centroid}
Chris@16 660
Chris@16 661 \qbk{distinguish,with strategy}
Chris@16 662 \qbk{[include reference/algorithms/centroid.qbk]}
Chris@16 663 \qbk{[include reference/algorithms/centroid_strategies.qbk]}
Chris@16 664 */
Chris@16 665 template<typename Point, typename Geometry, typename Strategy>
Chris@16 666 inline Point return_centroid(Geometry const& geometry, Strategy const& strategy)
Chris@16 667 {
Chris@16 668 Point c;
Chris@16 669 centroid(geometry, c, strategy);
Chris@16 670 return c;
Chris@16 671 }
Chris@16 672
Chris@16 673
Chris@16 674 }} // namespace boost::geometry
Chris@16 675
Chris@16 676
Chris@16 677 #endif // BOOST_GEOMETRY_ALGORITHMS_CENTROID_HPP