// Boost.Geometry (aka GGL, Generic Geometry Library) // Copyright (c) 2009-2012 Mateusz Loskot, London, UK. // Copyright (c) 2009-2012 Barend Gehrels, Amsterdam, the Netherlands. // Parts of Boost.Geometry are redesigned from Geodan's Geographic Library // (geolib/GGL), copyright (c) 1995-2010 Geodan, Amsterdam, the Netherlands. // Use, modification and distribution is subject to the Boost Software License, // Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #ifndef BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_WEIGHTED_LENGTH_HPP #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_WEIGHTED_LENGTH_HPP #include #include #include #include #include // Helper geometry #include namespace boost { namespace geometry { namespace strategy { namespace centroid { namespace detail { template struct weighted_length_sums { typedef typename geometry::model::point < Type, DimensionCount, cs::cartesian > work_point; Type length; work_point average_sum; inline weighted_length_sums() : length(Type()) { geometry::assign_zero(average_sum); } }; } template < typename Point, typename PointOfSegment = Point > class weighted_length { private : typedef typename select_most_precise < typename default_distance_result::type, typename default_distance_result::type >::type distance_type; public : typedef detail::weighted_length_sums < distance_type, geometry::dimension::type::value > state_type; static inline void apply(PointOfSegment const& p1, PointOfSegment const& p2, state_type& state) { distance_type const d = geometry::distance(p1, p2); state.length += d; typename state_type::work_point weighted_median; geometry::assign_zero(weighted_median); geometry::add_point(weighted_median, p1); geometry::add_point(weighted_median, p2); geometry::multiply_value(weighted_median, d/2); geometry::add_point(state.average_sum, weighted_median); } static inline bool result(state_type const& state, Point& centroid) { distance_type const zero = distance_type(); if (! geometry::math::equals(state.length, zero)) { assign_zero(centroid); add_point(centroid, state.average_sum); divide_value(centroid, state.length); return true; } return false; } }; #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS namespace services { // Register this strategy for linear geometries, in all dimensions template struct default_strategy < cartesian_tag, linear_tag, N, Point, Geometry > { typedef weighted_length < Point, typename point_type::type > type; }; } // namespace services #endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS }} // namespace strategy::centroid }} // namespace boost::geometry #endif // BOOST_GEOMETRY_STRATEGIES_CARTESIAN_CENTROID_WEIGHTED_LENGTH_HPP