$include_dir="/home/hyper-archives/boost-commit/include"; include("$include_dir/msg-header.inc") ?>
Subject: [Boost-commit] svn:boost r63579 - in sandbox/geometry: boost/geometry/algorithms boost/geometry/algorithms/detail/overlay boost/geometry/algorithms/detail/sections boost/geometry/core boost/geometry/extensions/gis/geographic/strategies boost/geometry/multi/algorithms/detail/sections boost/geometry/strategies boost/geometry/strategies/agnostic boost/geometry/strategies/cartesian boost/geometry/strategies/concepts boost/geometry/strategies/spherical boost/geometry/util libs/geometry/example libs/geometry/test libs/geometry/test/algorithms libs/geometry/test/extensions/gis/latlong libs/geometry/test/strategies
From: barend.gehrels_at_[hidden]
Date: 2010-07-04 06:01:14
Author: barendgehrels
Date: 2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
New Revision: 63579
URL: http://svn.boost.org/trac/boost/changeset/63579
Log:
Added non-const version of get_section
Major changes in distance strategies
Changed double from simplify to template parameter
Added a promote_floating_point
Added a fp_coordinate_type
Added namespaced point in custom example
Added mpl assertion in overlaps (should be done in most algorithms by default)
Added high precision test for various distance algorithms
Added:
   sandbox/geometry/boost/geometry/util/promote_floating_point.hpp   (contents, props changed)
   sandbox/geometry/libs/geometry/test/algorithms/comparable_distance.cpp   (contents, props changed)
   sandbox/geometry/libs/geometry/test/algorithms/comparable_distance.vcproj   (contents, props changed)
   sandbox/geometry/libs/geometry/test/ttmath.vsprops   (contents, props changed)
Text files modified: 
   sandbox/geometry/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp     |     2                                         
   sandbox/geometry/boost/geometry/algorithms/detail/sections/get_section.hpp        |    91 ++++++++---                             
   sandbox/geometry/boost/geometry/algorithms/distance.hpp                           |    29 ++-                                     
   sandbox/geometry/boost/geometry/algorithms/overlaps.hpp                           |    12 +                                       
   sandbox/geometry/boost/geometry/algorithms/simplify.hpp                           |    42 ++--                                    
   sandbox/geometry/boost/geometry/core/coordinate_type.hpp                          |    29 ++-                                     
   sandbox/geometry/boost/geometry/core/radian_access.hpp                            |    10                                         
   sandbox/geometry/boost/geometry/extensions/gis/geographic/strategies/andoyer.hpp  |   247 ++++++++++++++++++++-----------         
   sandbox/geometry/boost/geometry/extensions/gis/geographic/strategies/vincenty.hpp |   274 ++++++++++++++++++++++-------------     
   sandbox/geometry/boost/geometry/multi/algorithms/detail/sections/get_section.hpp  |    20 +                                       
   sandbox/geometry/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp  |    21 +-                                      
   sandbox/geometry/boost/geometry/strategies/cartesian/distance_projected_point.hpp |   188 +++++++++++++++++++++---                
   sandbox/geometry/boost/geometry/strategies/cartesian/distance_pythagoras.hpp      |   231 ++++++++++++++++++++++++++++-           
   sandbox/geometry/boost/geometry/strategies/concepts/distance_concept.hpp          |    48 ++++++                                  
   sandbox/geometry/boost/geometry/strategies/distance.hpp                           |    65 ++++++++                                
   sandbox/geometry/boost/geometry/strategies/distance_result.hpp                    |   306 +-------------------------------------- 
   sandbox/geometry/boost/geometry/strategies/spherical/distance_cross_track.hpp     |   146 +++++++++++++++---                      
   sandbox/geometry/boost/geometry/strategies/spherical/distance_haversine.hpp       |   251 +++++++++++++++++++++++++++++---        
   sandbox/geometry/libs/geometry/example/c01_custom_point_example.cpp               |    22 ++                                      
   sandbox/geometry/libs/geometry/test/algorithms/algorithms_tests.sln               |     6                                         
   sandbox/geometry/libs/geometry/test/algorithms/distance.cpp                       |    54 ++++---                                 
   sandbox/geometry/libs/geometry/test/algorithms/intersection.cpp                   |     5                                         
   sandbox/geometry/libs/geometry/test/algorithms/overlaps.cpp                       |     4                                         
   sandbox/geometry/libs/geometry/test/algorithms/simplify.cpp                       |     2                                         
   sandbox/geometry/libs/geometry/test/algorithms/simplify.vcproj                    |     9                                         
   sandbox/geometry/libs/geometry/test/extensions/gis/latlong/andoyer.cpp            |     9 +                                       
   sandbox/geometry/libs/geometry/test/extensions/gis/latlong/latlong.sln            |     6                                         
   sandbox/geometry/libs/geometry/test/strategies/cross_track.cpp                    |    19 ++                                      
   sandbox/geometry/libs/geometry/test/strategies/cross_track.vcproj                 |     4                                         
   sandbox/geometry/libs/geometry/test/strategies/haversine.cpp                      |   200 ++++++++++++++++++++++++-               
   sandbox/geometry/libs/geometry/test/strategies/haversine.vcproj                   |     4                                         
   sandbox/geometry/libs/geometry/test/strategies/projected_point.cpp                |   103 +++++++++---                            
   sandbox/geometry/libs/geometry/test/strategies/projected_point.vcproj             |     4                                         
   sandbox/geometry/libs/geometry/test/strategies/pythagoras.cpp                     |   252 ++++++++++++++++++++++++--------        
   sandbox/geometry/libs/geometry/test/strategies/pythagoras.vcproj                  |     4                                         
   35 files changed, 1912 insertions(+), 807 deletions(-)
Modified: sandbox/geometry/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp
==============================================================================
--- sandbox/geometry/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp	(original)
+++ sandbox/geometry/boost/geometry/algorithms/detail/overlay/enrichment_info.hpp	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -36,7 +36,7 @@
         : travels_to_vertex_index(-1)
         , travels_to_ip_index(-1)
         , next_ip_index(-1)
-        , distance(geometry::make_distance_result<distance_type>(0))
+        , distance(distance_type())
     {}
 
     // vertex to which is free travel after this IP,
Modified: sandbox/geometry/boost/geometry/algorithms/detail/sections/get_section.hpp
==============================================================================
--- sandbox/geometry/boost/geometry/algorithms/detail/sections/get_section.hpp	(original)
+++ sandbox/geometry/boost/geometry/algorithms/detail/sections/get_section.hpp	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -15,10 +15,8 @@
 #include <boost/geometry/core/access.hpp>
 #include <boost/geometry/core/exterior_ring.hpp>
 #include <boost/geometry/core/interior_rings.hpp>
-
 #include <boost/geometry/iterators/range_type.hpp>
-
-#include <boost/geometry/geometries/segment.hpp>
+#include <boost/geometry/util/add_const_if_c.hpp>
 
 
 
@@ -30,15 +28,26 @@
 namespace dispatch
 {
 
-template <typename Tag, typename Geometry, typename Section>
+// Generic case (linestring/linear ring)
+template <typename Tag, typename Geometry, typename Section, bool IsConst>
 struct get_section
 {
+    typedef typename add_const_if_c
+        <
+            IsConst,
+            Geometry
+        >::type geometry_type;
+
     typedef typename boost::range_iterator
         <
-            typename geometry::range_type<Geometry>::type const
+            typename add_const_if_c
+            <
+                IsConst,
+                typename geometry::range_type<Geometry>::type
+            >::type 
         >::type iterator_type;
 
-    static inline void apply(Geometry const& geometry, Section const& section,
+    static inline void apply(geometry_type& geometry, Section const& section,
                 iterator_type& begin, iterator_type& end)
     {
         begin = boost::begin(geometry) + section.begin_index;
@@ -46,33 +55,45 @@
     }
 };
 
-template <typename Polygon, typename Section>
-struct get_section<polygon_tag, Polygon, Section>
+template <typename Polygon, typename Section, bool IsConst>
+struct get_section<polygon_tag, Polygon, Section, IsConst>
 {
-    typedef typename boost::range_const_iterator
+    typedef typename add_const_if_c
+        <
+            IsConst,
+            Polygon
+        >::type polygon_type;
+
+    typedef typename boost::range_iterator
         <
-            typename geometry::range_type<Polygon>::type
+            typename add_const_if_c
+            <
+                IsConst,
+                typename geometry::range_type<Polygon>::type
+            >::type 
         >::type iterator_type;
 
-    static inline void apply(Polygon const& polygon, Section const& section,
+    static inline void apply(polygon_type& polygon, Section const& section,
                 iterator_type& begin, iterator_type& end)
     {
-        typedef typename geometry::ring_type<Polygon>::type ring_type;
-        ring_type const& ring = section.ring_index < 0
-            ? geometry::exterior_ring(polygon)
-            : geometry::interior_rings(polygon)[section.ring_index];
+        typename add_const_if_c
+            <
+                IsConst,
+                typename geometry::ring_type<Polygon>::type
+            >::type& ring = section.ring_index < 0
+                ? geometry::exterior_ring(polygon)
+                : geometry::interior_rings(polygon)[section.ring_index];
 
         begin = boost::begin(ring) + section.begin_index;
         end = boost::begin(ring) + section.end_index + 1;
     }
 };
 
+
 } // namespace dispatch
 #endif
 
 
-
-
 /*!
     \brief Get iterators for a specified section
     \ingroup sectionalize
@@ -82,18 +103,16 @@
     \param section structure with section
     \param begin begin-iterator (const iterator over points of section)
     \param end end-iterator (const iterator over points of section)
-    \todo Create non-const version as well
-
  */
 template <typename Geometry, typename Section>
 inline void get_section(Geometry const& geometry, Section const& section,
-    typename boost::range_const_iterator
+    typename boost::range_iterator
         <
-            typename geometry::range_type<Geometry>::type
+            typename geometry::range_type<Geometry>::type const
         >::type& begin,
-    typename boost::range_const_iterator
+    typename boost::range_iterator
         <
-            typename geometry::range_type<Geometry>::type
+            typename geometry::range_type<Geometry>::type const
         >::type& end)
 {
     concept::check<Geometry const>();
@@ -102,13 +121,37 @@
         <
             typename tag<Geometry>::type,
             Geometry,
-            Section
+            Section,
+            true
         >::apply(geometry, section, begin, end);
 }
 
 
+// non const version
+template <typename Geometry, typename Section>
+inline void get_section(Geometry& geometry, Section const& section,
+    typename boost::range_iterator
+        <
+            typename geometry::range_type<Geometry>::type
+        >::type& begin,
+    typename boost::range_iterator
+        <
+            typename geometry::range_type<Geometry>::type
+        >::type& end)
+{
+    concept::check<Geometry>();
+
+    dispatch::get_section
+        <
+            typename tag<Geometry>::type,
+            Geometry,
+            Section,
+            false
+        >::apply(geometry, section, begin, end);
+}
 
 
 }} // namespace boost::geometry
 
+
 #endif // BOOST_GEOMETRY_ALGORITHMS_DETAIL_SECTIONS_GET_SECTION_HPP
Modified: sandbox/geometry/boost/geometry/algorithms/distance.hpp
==============================================================================
--- sandbox/geometry/boost/geometry/algorithms/distance.hpp	(original)
+++ sandbox/geometry/boost/geometry/algorithms/distance.hpp	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -26,6 +26,9 @@
 #include <boost/geometry/strategies/distance_result.hpp>
 #include <boost/geometry/algorithms/within.hpp>
 
+
+#include <boost/geometry/util/math.hpp>
+
 /*!
 \defgroup distance distance: calculate distance between two geometries
 The distance algorithm returns the distance between two geometries.
@@ -99,19 +102,19 @@
 template<typename Point, typename Range, typename PPStrategy, typename PSStrategy>
 struct point_to_range
 {
-    typedef typename PPStrategy::return_type return_type;
+    typedef typename PSStrategy::return_type return_type;
 
     static inline return_type apply(Point const& point, Range const& range,
             PPStrategy const& pp_strategy, PSStrategy const& ps_strategy)
     {
-        typedef segment<typename point_type<Range>::type const> segment_type;
+        return_type const zero = return_type(0);
 
         if (boost::size(range) == 0)
         {
-            return return_type(0);
+            return zero;
         }
 
-        // line of one point: return point square_distance
+        // line of one point: return point distance
         typedef typename boost::range_iterator<Range const>::type iterator_type;
         iterator_type it = boost::begin(range);
         iterator_type prev = it++;
@@ -120,27 +123,32 @@
             return pp_strategy.apply(point, *boost::begin(range));
         }
 
+        // Create efficient strategy
+        typedef typename strategy::distance::services::comparable_type<PSStrategy>::type eps_strategy_type;
+        eps_strategy_type eps_strategy = strategy::distance::services::get_comparable<PSStrategy>::apply(ps_strategy);
 
         // start with first segment distance
-        return_type d = ps_strategy.apply(point, *prev, *it);
+        return_type d = eps_strategy.apply(point, *prev, *it);
+        return_type rd = ps_strategy.apply(point, *prev, *it);
 
         // check if other segments are closer
         prev = it++;
         while(it != boost::end(range))
         {
-            return_type ds = ps_strategy.apply(point, *prev, *it);
-            if (geometry::close_to_zero(ds))
+            return_type const ds = ps_strategy.apply(point, *prev, *it);
+            if (geometry::math::equals(ds, zero))
             {
-                return return_type(0);
+                return ds;
             }
             else if (ds < d)
             {
                 d = ds;
+                return_type rd = ps_strategy.apply(point, *prev, *it);
             }
             prev = it++;
         }
 
-        return d;
+        return rd;
     }
 };
 
@@ -422,6 +430,9 @@
 inline typename Strategy::return_type distance(Geometry1 const& geometry1,
             Geometry2 const& geometry2, Strategy const& strategy)
 {
+    concept::check<Geometry1 const>();
+    concept::check<Geometry2 const>();
+
     return boost::mpl::if_
         <
             typename geometry::reverse_dispatch<Geometry1, Geometry2>::type,
Modified: sandbox/geometry/boost/geometry/algorithms/overlaps.hpp
==============================================================================
--- sandbox/geometry/boost/geometry/algorithms/overlaps.hpp	(original)
+++ sandbox/geometry/boost/geometry/algorithms/overlaps.hpp	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -22,6 +22,8 @@
 
 #include <cstddef>
 
+#include <boost/mpl/assert.hpp>
+
 #include <boost/geometry/core/access.hpp>
 
 #include <boost/geometry/geometries/concepts/check.hpp>
@@ -142,11 +144,13 @@
 }} // namespace detail::overlaps
 #endif // DOXYGEN_NO_DETAIL
 
+//struct not_implemented_for_this_geometry_type : public boost::false_type {};
 
 #ifndef DOXYGEN_NO_DISPATCH
 namespace dispatch
 {
 
+
 template
 <
     typename Tag1,
@@ -155,7 +159,13 @@
     typename Geometry2
 >
 struct overlaps
-{};
+{
+    BOOST_MPL_ASSERT_MSG
+        (
+            false, NOT_OR_NOT_YET_IMPLEMENT_FOR_THIS_GEOMETRY_TYPE
+            , (types<Geometry1, Geometry2>)
+        );
+};
 
 
 template <typename Box1, typename Box2>
Modified: sandbox/geometry/boost/geometry/algorithms/simplify.hpp
==============================================================================
--- sandbox/geometry/boost/geometry/algorithms/simplify.hpp	(original)
+++ sandbox/geometry/boost/geometry/algorithms/simplify.hpp	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -73,9 +73,9 @@
 template<typename Range, typename Strategy>
 struct simplify_range_inserter
 {
-    template <typename OutputIterator>
+    template <typename OutputIterator, typename Distance>
     static inline void apply(Range const& range, OutputIterator out,
-                    double max_distance, Strategy const& strategy)
+                    Distance const& max_distance, Strategy const& strategy)
     {
         if (boost::size(range) <= 2 || max_distance < 0)
         {
@@ -92,8 +92,9 @@
 template<typename Range, typename Strategy>
 struct simplify_copy
 {
+    template <typename Distance>
     static inline void apply(Range const& range, Range& out,
-                    double max_distance, Strategy const& strategy)
+                    Distance const& max_distance, Strategy const& strategy)
     {
         std::copy
             (
@@ -106,8 +107,9 @@
 template<typename Range, typename Strategy, std::size_t Minimum>
 struct simplify_range
 {
+    template <typename Distance>
     static inline void apply(Range const& range, Range& out,
-                    double max_distance, Strategy const& strategy)
+                    Distance const& max_distance, Strategy const& strategy)
     {
         // Call do_container for a linestring / ring
 
@@ -144,8 +146,9 @@
 template<typename Polygon, typename Strategy>
 struct simplify_polygon
 {
+    template <typename Distance>
     static inline void apply(Polygon const& poly_in, Polygon& poly_out,
-                    double max_distance, Strategy const& strategy)
+                    Distance const& max_distance, Strategy const& strategy)
     {
         typedef typename ring_type<Polygon>::type ring_type;
 
@@ -198,8 +201,9 @@
 template <typename Point, typename Strategy>
 struct simplify<point_tag, Point, Strategy>
 {
+    template <typename Distance>
     static inline void apply(Point const& point, Point& out,
-                    double max_distance, Strategy const& strategy)
+                    Distance const& max_distance, Strategy const& strategy)
     {
         copy_coordinates(point, out);
     }
@@ -275,9 +279,9 @@
     \param strategy simplify strategy to be used for simplification, might
         include point-distance strategy
  */
-template<typename Geometry, typename Strategy>
+template<typename Geometry, typename Distance, typename Strategy>
 inline void simplify(Geometry const& geometry, Geometry& out,
-                     double max_distance, Strategy const& strategy)
+                     Distance const& max_distance, Strategy const& strategy)
 {
     concept::check<Geometry>();
 
@@ -312,21 +316,15 @@
     \line {
     \until }
  */
-template<typename Geometry>
+template<typename Geometry, typename Distance>
 inline void simplify(Geometry const& geometry, Geometry& out,
-                     double max_distance)
+                     Distance const& max_distance)
 {
     concept::check<Geometry>();
 
     typedef typename point_type<Geometry>::type point_type;
-    typedef typename cs_tag<point_type>::type cs_tag;
-    typedef typename strategy_distance_segment
-        <
-            cs_tag,
-            cs_tag,
-            point_type,
-            point_type
-        >::type ds_strategy_type;
+    typedef typename default_distance_strategy_segment
+                <point_type>::type ds_strategy_type;
 
     typedef strategy::simplify::douglas_peucker
         <
@@ -354,9 +352,9 @@
     \line {
     \until }
  */
-template<typename Geometry, typename OutputIterator, typename Strategy>
+template<typename Geometry, typename OutputIterator, typename Distance, typename Strategy>
 inline void simplify_inserter(Geometry const& geometry, OutputIterator out,
-                              double max_distance, Strategy const& strategy)
+                              Distance const& max_distance, Strategy const& strategy)
 {
     concept::check<Geometry const>();
     BOOST_CONCEPT_ASSERT( (geometry::concept::SimplifyStrategy<Strategy>) );
@@ -377,9 +375,9 @@
     \param max_distance distance (in units of input coordinates) of a vertex
         to other segments to be removed
  */
-template<typename Geometry, typename OutputIterator>
+template<typename Geometry, typename OutputIterator, typename Distance>
 inline void simplify_inserter(Geometry const& geometry, OutputIterator out,
-                              double max_distance)
+                              Distance const& max_distance)
 {
     typedef typename point_type<Geometry>::type point_type;
 
Modified: sandbox/geometry/boost/geometry/core/coordinate_type.hpp
==============================================================================
--- sandbox/geometry/boost/geometry/core/coordinate_type.hpp	(original)
+++ sandbox/geometry/boost/geometry/core/coordinate_type.hpp	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -13,6 +13,7 @@
 #include <boost/type_traits/remove_const.hpp>
 
 #include <boost/geometry/core/point_type.hpp>
+#include <boost/geometry/util/promote_floating_point.hpp>
 
 
 namespace boost { namespace geometry
@@ -38,19 +39,19 @@
 namespace core_dispatch
 {
 
-template <typename GeometryTag, typename G>
+template <typename GeometryTag, typename Geometry>
 struct coordinate_type
 {
-    typedef typename point_type<GeometryTag, G>::type point_type;
+    typedef typename point_type<GeometryTag, Geometry>::type point_type;
 
     // Call its own specialization on point-tag
     typedef typename coordinate_type<point_tag, point_type>::type type;
 };
 
-template <typename P>
-struct coordinate_type<point_tag, P>
+template <typename Point>
+struct coordinate_type<point_tag, Point>
 {
-    typedef typename traits::coordinate_type<P>::type type;
+    typedef typename traits::coordinate_type<Point>::type type;
 };
 
 } // namespace core_dispatch
@@ -60,17 +61,27 @@
     \brief Meta-function which defines coordinate type (int, float, double, etc) of any geometry
     \ingroup core
 */
-template <typename G>
+template <typename Geometry>
 struct coordinate_type
 {
-    typedef typename boost::remove_const<G>::type ncg;
     typedef typename core_dispatch::coordinate_type
         <
-            typename tag<G>::type,
-            ncg
+            typename tag<Geometry>::type,
+            typename boost::remove_const<Geometry>::type
+        >::type type;
+};
+
+template <typename Geometry>
+struct fp_coordinate_type
+{
+    typedef typename promote_floating_point
+        <
+            typename coordinate_type<Geometry>::type
         >::type type;
 };
 
+
 }} // namespace boost::geometry
 
+
 #endif // BOOST_GEOMETRY_CORE_COORDINATE_TYPE_HPP
Modified: sandbox/geometry/boost/geometry/core/radian_access.hpp
==============================================================================
--- sandbox/geometry/boost/geometry/core/radian_access.hpp	(original)
+++ sandbox/geometry/boost/geometry/core/radian_access.hpp	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -17,11 +17,13 @@
 
 #include <boost/geometry/core/access.hpp>
 #include <boost/geometry/core/cs.hpp>
+#include <boost/geometry/core/coordinate_type.hpp>
 
 
 #include <boost/geometry/util/math.hpp>
 
 
+
 namespace boost { namespace geometry
 {
 
@@ -33,7 +35,7 @@
 template<std::size_t Dimension, typename Geometry>
 struct degree_radian_converter
 {
-    typedef typename coordinate_type<Geometry>::type coordinate_type;
+    typedef typename fp_coordinate_type<Geometry>::type coordinate_type;
 
     static inline coordinate_type get(Geometry const& geometry)
     {
@@ -58,7 +60,7 @@
 template <std::size_t Dimension, typename Geometry, typename DegreeOrRadian>
 struct radian_access
 {
-    typedef typename coordinate_type<Geometry>::type coordinate_type;
+    typedef typename fp_coordinate_type<Geometry>::type coordinate_type;
 
     static inline coordinate_type get(Geometry const& geometry)
     {
@@ -111,7 +113,7 @@
         e.g. spherical or geographic coordinate systems
 */
 template <std::size_t Dimension, typename Geometry>
-inline typename coordinate_type<Geometry>::type get_as_radian(Geometry const& geometry)
+inline typename fp_coordinate_type<Geometry>::type get_as_radian(Geometry const& geometry)
 {
     return detail::radian_access<Dimension, Geometry,
             typename coordinate_system<Geometry>::type>::get(geometry);
@@ -132,7 +134,7 @@
 */
 template <std::size_t Dimension, typename Geometry>
 inline void set_from_radian(Geometry& geometry,
-            const typename coordinate_type<Geometry>::type& radians)
+            typename fp_coordinate_type<Geometry>::type const& radians)
 {
     detail::radian_access<Dimension, Geometry,
             typename coordinate_system<Geometry>::type>::set(geometry, radians);
Modified: sandbox/geometry/boost/geometry/extensions/gis/geographic/strategies/andoyer.hpp
==============================================================================
--- sandbox/geometry/boost/geometry/extensions/gis/geographic/strategies/andoyer.hpp	(original)
+++ sandbox/geometry/boost/geometry/extensions/gis/geographic/strategies/andoyer.hpp	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -19,104 +19,172 @@
 
 namespace boost { namespace geometry
 {
-namespace strategy
+
+namespace strategy { namespace distance
 {
 
-    namespace distance
-    {
 
+/*!
+    \brief Point-point distance approximation taking flattening into account
+    \ingroup distance
+    \tparam P1 first point type
+    \tparam P2 optional second point type
+    \author After Andoyer, 19xx, republished 1950, republished by Meeus, 1999
+    \note Although not so well-known, the approximation is very good: in all cases the results
+    are about the same as Vincenty. In my (Barend's) testcases the results didn't differ more than 6 m
+    \see http://nacc.upc.es/tierra/node16.html
+    \see http://sci.tech-archive.net/Archive/sci.geo.satellite-nav/2004-12/2724.html
+    \see http://home.att.net/~srschmitt/great_circle_route.html (implementation)
+    \see http://www.codeguru.com/Cpp/Cpp/algorithms/article.php/c5115 (implementation)
+    \see http://futureboy.homeip.net/frinksamp/navigation.frink (implementation)
+    \see http://www.voidware.com/earthdist.htm (implementation)
+*/
+template 
+<
+    typename P1, 
+    typename P2 = P1
+    // calculation_type
+>
+class andoyer
+{
+    public :
+        typedef P1 first_point_type;
+        typedef P2 second_point_type;
+        typedef double return_type;
+
+        andoyer()
+            : m_ellipsoid()
+        {}
+
+        explicit inline andoyer(double f)
+            : m_ellipsoid(f)
+        {}
+
+        explicit inline andoyer(geometry::detail::ellipsoid const& e)
+            : m_ellipsoid(e)
+        {}
+
+
+        inline return_type apply(P1 const& p1, P2 const& p2) const
+        {
+            return calc(get_as_radian<0>(p1), get_as_radian<1>(p1),
+                            get_as_radian<0>(p2), get_as_radian<1>(p2));
+        }
+
+        inline geometry::detail::ellipsoid ellipsoid() const
+        {
+            return m_ellipsoid;
+        }
+       
+
+    private :
+        typedef typename coordinate_type<P1>::type T1;
+        typedef typename coordinate_type<P2>::type T2;
+        geometry::detail::ellipsoid m_ellipsoid;
 
-        /*!
-            \brief Point-point distance approximation taking flattening into account
-            \ingroup distance
-            \tparam P1 first point type
-            \tparam P2 optional second point type
-            \author After Andoyer, 19xx, republished 1950, republished by Meeus, 1999
-            \note Although not so well-known, the approximation is very good: in all cases the results
-            are about the same as Vincenty. In my (Barend's) testcases the results didn't differ more than 6 m
-            \see http://nacc.upc.es/tierra/node16.html
-            \see http://sci.tech-archive.net/Archive/sci.geo.satellite-nav/2004-12/2724.html
-            \see http://home.att.net/~srschmitt/great_circle_route.html (implementation)
-            \see http://www.codeguru.com/Cpp/Cpp/algorithms/article.php/c5115 (implementation)
-            \see http://futureboy.homeip.net/frinksamp/navigation.frink (implementation)
-            \see http://www.voidware.com/earthdist.htm (implementation)
-        */
-        template <typename P1, typename P2 = P1>
-        class andoyer
+        inline return_type calc(T1 const& lon1, T1 const& lat1, T2 const& lon2, T2 const& lat2) const
         {
-            public :
-                //typedef spherical_distance return_type;
-                typedef P1 first_point_type;
-                typedef P2 second_point_type;
-                typedef double return_type;
-
-                andoyer()
-                    : m_ellipsoid()
-                {}
-                andoyer(double f)
-                    : m_ellipsoid(f)
-                {}
-
-                inline return_type apply(P1 const& p1, P2 const& p2) const
-                {
-                    return calc(get_as_radian<0>(p1), get_as_radian<1>(p1),
-                                    get_as_radian<0>(p2), get_as_radian<1>(p2));
-                }
-
-
-            private :
-                typedef typename coordinate_type<P1>::type T1;
-                typedef typename coordinate_type<P2>::type T2;
-                geometry::detail::ellipsoid m_ellipsoid;
-
-                inline return_type calc(T1 const& lon1, T1 const& lat1, T2 const& lon2, T2 const& lat2) const
-                {
-                    typedef double calculation_type;
-                    calculation_type G = (lat1 - lat2) / 2.0;
-                    calculation_type lambda = (lon1 - lon2) / 2.0;
-
-                    if (geometry::math::equals(lambda, 0.0)
-                        && geometry::math::equals(G, 0.0))
-                    {
-                        return 0.0;
-                    }
-
-                    calculation_type F = (lat1 + lat2) / 2.0;
-
-                    calculation_type sinG2 = math::sqr(sin(G));
-                    calculation_type cosG2 = math::sqr(cos(G));
-                    calculation_type sinF2 = math::sqr(sin(F));
-                    calculation_type cosF2 = math::sqr(cos(F));
-                    calculation_type sinL2 = math::sqr(sin(lambda));
-                    calculation_type cosL2 = math::sqr(cos(lambda));
-
-                    calculation_type S = sinG2 * cosL2 + cosF2 * sinL2;
-                    calculation_type C = cosG2 * cosL2 + sinF2 * sinL2;
-
-                    if (geometry::math::equals(S, 0.0) || geometry::math::equals(C, 0.0))
-                    {
-                        return 0.0;
-                    }
-
-                    calculation_type omega = atan(sqrt(S / C));
-                    calculation_type r = sqrt(S * C) / omega; // not sure if this is r or greek nu
-
-                    calculation_type D = 2.0 * omega * m_ellipsoid.a();
-                    calculation_type H1 = (3 * r - 1.0) / (2.0 * C);
-                    calculation_type H2 = (3 * r + 1.0) / (2.0 * S);
-
-                    return return_type(D
-                        * (1.0 + m_ellipsoid.f() * H1 * sinF2 * cosG2
-                                    - m_ellipsoid.f() * H2 * cosF2 * sinG2));
-                }
-        };
+            typedef double calculation_type;
+            calculation_type G = (lat1 - lat2) / 2.0;
+            calculation_type lambda = (lon1 - lon2) / 2.0;
+
+            if (geometry::math::equals(lambda, 0.0)
+                && geometry::math::equals(G, 0.0))
+            {
+                return 0.0;
+            }
+
+            calculation_type F = (lat1 + lat2) / 2.0;
+
+            calculation_type sinG2 = math::sqr(sin(G));
+            calculation_type cosG2 = math::sqr(cos(G));
+            calculation_type sinF2 = math::sqr(sin(F));
+            calculation_type cosF2 = math::sqr(cos(F));
+            calculation_type sinL2 = math::sqr(sin(lambda));
+            calculation_type cosL2 = math::sqr(cos(lambda));
+
+            calculation_type S = sinG2 * cosL2 + cosF2 * sinL2;
+            calculation_type C = cosG2 * cosL2 + sinF2 * sinL2;
+
+            if (geometry::math::equals(S, 0.0) || geometry::math::equals(C, 0.0))
+            {
+                return 0.0;
+            }
+
+            calculation_type omega = atan(sqrt(S / C));
+            calculation_type r = sqrt(S * C) / omega; // not sure if this is r or greek nu
+
+            calculation_type D = 2.0 * omega * m_ellipsoid.a();
+            calculation_type H1 = (3 * r - 1.0) / (2.0 * C);
+            calculation_type H2 = (3 * r + 1.0) / (2.0 * S);
+
+            return return_type(D
+                * (1.0 + m_ellipsoid.f() * H1 * sinF2 * cosG2
+                            - m_ellipsoid.f() * H2 * cosF2 * sinG2));
+        }
+};
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+namespace services 
+{
+
+template <typename Point1, typename Point2>
+struct tag<strategy::distance::andoyer<Point1, Point2> >
+{
+    typedef strategy_tag_distance_point_point type;
+};
+
 
+template <typename Point1, typename Point2, typename P1, typename P2>
+struct similar_type<andoyer<Point1, Point2>, P1, P2>
+{
+    typedef andoyer<P1, P2> type;
+};
 
 
-    } // namespace distance
+template <typename Point1, typename Point2, typename P1, typename P2>
+struct get_similar<andoyer<Point1, Point2>, P1, P2>
+{
+    static inline andoyer<P1, P2> apply(andoyer<Point1, Point2> const& input)
+    {
+        return andoyer<P1, P2>(input.ellipsoid());
+    }
+};
 
+template <typename Point1, typename Point2>
+struct comparable_type<andoyer<Point1, Point2> >
+{
+    typedef andoyer<Point1, Point2> type;
+};
+
+
+template <typename Point1, typename Point2>
+struct get_comparable<andoyer<Point1, Point2> >
+{
+    static inline andoyer<Point1, Point2> apply(andoyer<Point1, Point2> const& input)
+    {
+        return input;
+    }
+};
+
+template <typename Point1, typename Point2>
+struct result_from_distance<andoyer<Point1, Point2> >
+{
+    template <typename T>
+    static inline typename andoyer<Point1, Point2>::return_type apply(andoyer<Point1, Point2> const& , T const& value)
+    {
+        return value;
+    }
+};
+
+
+} // namespace services
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+}} // namespace strategy::distance
 
-} // namespace strategy
 
 
 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
@@ -133,7 +201,8 @@
     typedef strategy_tag_distance_point_point type;
 };
 
-#endif
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
 
 
 }} // namespace boost::geometry
Modified: sandbox/geometry/boost/geometry/extensions/gis/geographic/strategies/vincenty.hpp
==============================================================================
--- sandbox/geometry/boost/geometry/extensions/gis/geographic/strategies/vincenty.hpp	(original)
+++ sandbox/geometry/boost/geometry/extensions/gis/geographic/strategies/vincenty.hpp	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -19,118 +19,186 @@
 
 namespace boost { namespace geometry
 {
-namespace strategy
+
+namespace strategy { namespace distance
 {
 
-    namespace distance
-    {
+/*!
+    \brief Distance calculation formulae on latlong coordinates, after Vincenty, 1975
+    \ingroup distance
+    \tparam P1 first point type
+    \tparam P2 optional second point type
+    \author See http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
+    \author Adapted from various implementations to get it close to the original document
+        - http://www.movable-type.co.uk/scripts/LatLongVincenty.html
+        - http://exogen.case.edu/projects/geopy/source/geopy.distance.html
+        - http://futureboy.homeip.net/fsp/colorize.fsp?fileName=navigation.frink
+
+*/
+template <typename P1, typename P2 = P1>
+class vincenty
+{
+    public :
+        //typedef spherical_distance return_type;
+        typedef P1 first_point_type;
+        typedef P2 second_point_type;
+        typedef double return_type;
+
+        inline vincenty()
+        {}
+
+        explicit inline vincenty(geometry::detail::ellipsoid const& e)
+            : m_ellipsoid(e)
+        {}
 
-        /*!
-            \brief Distance calculation formulae on latlong coordinates, after Vincenty, 1975
-            \ingroup distance
-            \tparam P1 first point type
-            \tparam P2 optional second point type
-            \author See http://www.ngs.noaa.gov/PUBS_LIB/inverse.pdf
-            \author Adapted from various implementations to get it close to the original document
-                - http://www.movable-type.co.uk/scripts/LatLongVincenty.html
-                - http://exogen.case.edu/projects/geopy/source/geopy.distance.html
-                - http://futureboy.homeip.net/fsp/colorize.fsp?fileName=navigation.frink
-
-        */
-        template <typename P1, typename P2 = P1>
-        class vincenty
+        inline return_type apply(P1 const& p1, P2 const& p2) const
         {
-            public :
-                //typedef spherical_distance return_type;
-                typedef P1 first_point_type;
-                typedef P2 second_point_type;
-                typedef double return_type;
-
-                inline return_type apply(P1 const& p1, P2 const& p2) const
-                {
-                    return calculate(get_as_radian<0>(p1), get_as_radian<1>(p1),
-                                    get_as_radian<0>(p2), get_as_radian<1>(p2));
-                }
-
-            private :
-                typedef typename coordinate_type<P1>::type T1;
-                typedef typename coordinate_type<P2>::type T2;
-                geometry::detail::ellipsoid m_ellipsoid;
-
-                inline return_type calculate(T1 const& lon1, T1 const& lat1, T2 const& lon2, T2 const& lat2) const
-                {
-                    // lambda: difference in longitude on an auxiliary sphere
-                    double L = lon2 - lon1;
-                    double lambda = L;
-
-                    if (L < -math::pi) L += math::two_pi;
-                    if (L > math::pi) L -= math::two_pi;
-
-                    if (lat1 == lat2 && lon1 == lon2)
-                    {
-                      return return_type(0);
-                    }
-
-                    // U: reduced latitude, defined by tan U = (1-f) tan phi
-                    double U1 = atan((1-m_ellipsoid.f()) * tan(lat1)); // above (1)
-                    double U2 = atan((1-m_ellipsoid.f()) * tan(lat2)); // above (1)
-
-                    double cos_U1 = cos(U1);
-                    double cos_U2 = cos(U2);
-                    double sin_U1 = sin(U1);
-                    double sin_U2 = sin(U2);
-
-                    // alpha: azimuth of the geodesic at the equator
-                    double cos2_alpha;
-                    double sin_alpha;
-
-                    // sigma: angular distance p1,p2 on the sphere
-                    // sigma1: angular distance on the sphere from the equator to p1
-                    // sigma_m: angular distance on the sphere from the equator to the midpoint of the line
-                    double sigma;
-                    double sin_sigma;
-                    double cos2_sigma_m;
-
-                    double previous_lambda;
-
-                    do
-                    {
-                        previous_lambda = lambda; // (13)
-                        double sin_lambda = sin(lambda);
-                        double cos_lambda = cos(lambda);
-                        sin_sigma = sqrt(math::sqr(cos_U2 * sin_lambda) + math::sqr(cos_U1 * sin_U2 - sin_U1 * cos_U2 * cos_lambda)); // (14)
-                        double cos_sigma = sin_U1 * sin_U2 + cos_U1 * cos_U2 * cos_lambda; // (15)
-                        sin_alpha = cos_U1 * cos_U2 * sin_lambda / sin_sigma; // (17)
-                        cos2_alpha = 1.0 - math::sqr(sin_alpha);
-                        cos2_sigma_m = cos2_alpha == 0 ? 0 : cos_sigma - 2.0 * sin_U1 * sin_U2 / cos2_alpha; // (18)
-
-                        double C = m_ellipsoid.f()/16.0 * cos2_alpha * (4.0 + m_ellipsoid.f() * (4.0 - 3.0 * cos2_alpha)); // (10)
-                        sigma = atan2(sin_sigma, cos_sigma); // (16)
-                        lambda = L + (1.0 - C) * m_ellipsoid.f() * sin_alpha *
-                            (sigma + C * sin_sigma * ( cos2_sigma_m + C * cos_sigma * (-1.0 + 2.0 * math::sqr(cos2_sigma_m)))); // (11)
-
-                    } while (fabs(previous_lambda - lambda) > 1e-12 && fabs(lambda) < math::pi);
-
-                    double sqr_u = cos2_alpha * (math::sqr(m_ellipsoid.a()) - math::sqr(m_ellipsoid.b())) / math::sqr(m_ellipsoid.b()); // above (1)
-
-                    double A = 1.0 + sqr_u/16384.0 * (4096 + sqr_u * (-768.0 + sqr_u * (320.0 - 175.0 * sqr_u))); // (3)
-                    double B = sqr_u/1024.0 * (256.0 + sqr_u * ( -128.0 + sqr_u * (74.0 - 47.0 * sqr_u))); // (4)
-                    double delta_sigma = B * sin_sigma * ( cos2_sigma_m + (B/4.0) * (cos(sigma)* (-1.0 + 2.0 * cos2_sigma_m)
-                            - (B/6.0) * cos2_sigma_m * (-3.0 + 4.0 * math::sqr(sin_sigma)) * (-3.0 + 4.0 * cos2_sigma_m))); // (6)
-
-                    double dist = m_ellipsoid.b() * A * (sigma - delta_sigma); // (19)
-
-                    return return_type(dist);
-                }
-        };
+            return calculate(get_as_radian<0>(p1), get_as_radian<1>(p1),
+                            get_as_radian<0>(p2), get_as_radian<1>(p2));
+        }
+
+        inline geometry::detail::ellipsoid ellipsoid() const
+        {
+            return m_ellipsoid;
+        }
+
+
+    private :
+        typedef typename coordinate_type<P1>::type T1;
+        typedef typename coordinate_type<P2>::type T2;
+        geometry::detail::ellipsoid m_ellipsoid;
+
+        inline return_type calculate(T1 const& lon1, T1 const& lat1, T2 const& lon2, T2 const& lat2) const
+        {
+            // lambda: difference in longitude on an auxiliary sphere
+            double L = lon2 - lon1;
+            double lambda = L;
+
+            if (L < -math::pi) L += math::two_pi;
+            if (L > math::pi) L -= math::two_pi;
+
+            if (lat1 == lat2 && lon1 == lon2)
+            {
+              return return_type(0);
+            }
+
+            // U: reduced latitude, defined by tan U = (1-f) tan phi
+            double U1 = atan((1-m_ellipsoid.f()) * tan(lat1)); // above (1)
+            double U2 = atan((1-m_ellipsoid.f()) * tan(lat2)); // above (1)
+
+            double cos_U1 = cos(U1);
+            double cos_U2 = cos(U2);
+            double sin_U1 = sin(U1);
+            double sin_U2 = sin(U2);
+
+            // alpha: azimuth of the geodesic at the equator
+            double cos2_alpha;
+            double sin_alpha;
+
+            // sigma: angular distance p1,p2 on the sphere
+            // sigma1: angular distance on the sphere from the equator to p1
+            // sigma_m: angular distance on the sphere from the equator to the midpoint of the line
+            double sigma;
+            double sin_sigma;
+            double cos2_sigma_m;
+
+            double previous_lambda;
+
+            do
+            {
+                previous_lambda = lambda; // (13)
+                double sin_lambda = sin(lambda);
+                double cos_lambda = cos(lambda);
+                sin_sigma = sqrt(math::sqr(cos_U2 * sin_lambda) + math::sqr(cos_U1 * sin_U2 - sin_U1 * cos_U2 * cos_lambda)); // (14)
+                double cos_sigma = sin_U1 * sin_U2 + cos_U1 * cos_U2 * cos_lambda; // (15)
+                sin_alpha = cos_U1 * cos_U2 * sin_lambda / sin_sigma; // (17)
+                cos2_alpha = 1.0 - math::sqr(sin_alpha);
+                cos2_sigma_m = cos2_alpha == 0 ? 0 : cos_sigma - 2.0 * sin_U1 * sin_U2 / cos2_alpha; // (18)
+
+                double C = m_ellipsoid.f()/16.0 * cos2_alpha * (4.0 + m_ellipsoid.f() * (4.0 - 3.0 * cos2_alpha)); // (10)
+                sigma = atan2(sin_sigma, cos_sigma); // (16)
+                lambda = L + (1.0 - C) * m_ellipsoid.f() * sin_alpha *
+                    (sigma + C * sin_sigma * ( cos2_sigma_m + C * cos_sigma * (-1.0 + 2.0 * math::sqr(cos2_sigma_m)))); // (11)
+
+            } while (fabs(previous_lambda - lambda) > 1e-12 && fabs(lambda) < math::pi);
+
+            double sqr_u = cos2_alpha * (math::sqr(m_ellipsoid.a()) - math::sqr(m_ellipsoid.b())) / math::sqr(m_ellipsoid.b()); // above (1)
+
+            double A = 1.0 + sqr_u/16384.0 * (4096 + sqr_u * (-768.0 + sqr_u * (320.0 - 175.0 * sqr_u))); // (3)
+            double B = sqr_u/1024.0 * (256.0 + sqr_u * ( -128.0 + sqr_u * (74.0 - 47.0 * sqr_u))); // (4)
+            double delta_sigma = B * sin_sigma * ( cos2_sigma_m + (B/4.0) * (cos(sigma)* (-1.0 + 2.0 * cos2_sigma_m)
+                    - (B/6.0) * cos2_sigma_m * (-3.0 + 4.0 * math::sqr(sin_sigma)) * (-3.0 + 4.0 * cos2_sigma_m))); // (6)
+
+            double dist = m_ellipsoid.b() * A * (sigma - delta_sigma); // (19)
+
+            return return_type(dist);
+        }
+};
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+namespace services 
+{
+
+template <typename Point1, typename Point2>
+struct tag<strategy::distance::vincenty<Point1, Point2> >
+{
+    typedef strategy_tag_distance_point_point type;
+};
+
+
+template <typename Point1, typename Point2, typename P1, typename P2>
+struct similar_type<vincenty<Point1, Point2>, P1, P2>
+{
+    typedef vincenty<P1, P2> type;
+};
+
+
+template <typename Point1, typename Point2, typename P1, typename P2>
+struct get_similar<vincenty<Point1, Point2>, P1, P2>
+{
+    static inline vincenty<P1, P2> apply(vincenty<Point1, Point2> const& input)
+    {
+        return vincenty<P1, P2>(input.ellipsoid());
+    }
+};
+
+template <typename Point1, typename Point2>
+struct comparable_type<vincenty<Point1, Point2> >
+{
+    typedef vincenty<Point1, Point2> type;
+};
+
+
+template <typename Point1, typename Point2>
+struct get_comparable<vincenty<Point1, Point2> >
+{
+    static inline vincenty<Point1, Point2> apply(vincenty<Point1, Point2> const& input)
+    {
+        return input;
+    }
+};
+
+template <typename Point1, typename Point2>
+struct result_from_distance<vincenty<Point1, Point2> >
+{
+    template <typename T>
+    static inline typename vincenty<Point1, Point2>::return_type apply(vincenty<Point1, Point2> const& , T const& value)
+    {
+        return value;
+    }
+};
+
+
+} // namespace services
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
 
 
-        // We might add a vincenty-like strategy also for point-segment distance, but to calculate the projected point is not trivial
+// We might add a vincenty-like strategy also for point-segment distance, but to calculate the projected point is not trivial
 
-    } // namespace distance
 
 
-} // namespace strategy
+}} // namespace strategy::distance
 
 
 #ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
Modified: sandbox/geometry/boost/geometry/multi/algorithms/detail/sections/get_section.hpp
==============================================================================
--- sandbox/geometry/boost/geometry/multi/algorithms/detail/sections/get_section.hpp	(original)
+++ sandbox/geometry/boost/geometry/multi/algorithms/detail/sections/get_section.hpp	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -28,15 +28,24 @@
 {
 
 
-template <typename MultiPolygon, typename Section>
-struct get_section<multi_polygon_tag, MultiPolygon, Section>
+template <typename MultiPolygon, typename Section, bool IsConst>
+struct get_section<multi_polygon_tag, MultiPolygon, Section, IsConst>
 {
     typedef typename boost::range_iterator
         <
-            typename geometry::range_type<MultiPolygon>::type const
+            typename add_const_if_c
+            <
+                IsConst,
+                typename geometry::range_type<MultiPolygon>::type
+            >::type
         >::type iterator_type;
 
-    static inline void apply(MultiPolygon const& multi_polygon,
+    static inline void apply(
+                typename add_const_if_c
+                    <
+                        IsConst,
+                        MultiPolygon
+                    >::type const& multi_polygon,
                 Section const& section,
                 iterator_type& begin, iterator_type& end)
     {
@@ -49,7 +58,8 @@
             <
                 polygon_tag,
                 typename boost::range_value<MultiPolygon>::type,
-                Section
+                Section,
+                IsConst
             >::apply(multi_polygon[section.multi_index], section, begin, end);
     }
 };
Modified: sandbox/geometry/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp
==============================================================================
--- sandbox/geometry/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp	(original)
+++ sandbox/geometry/boost/geometry/strategies/agnostic/simplify_douglas_peucker.hpp	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -88,15 +88,20 @@
 >
 class douglas_peucker
 {
+public :
+
+    typedef typename strategy::distance::services::comparable_type<PointDistanceStrategy>::type distance_strategy_type;
+    typedef typename distance_strategy_type::return_type return_type;
+
+private :
     typedef detail::douglas_peucker_point<Point> dp_point_type;
     typedef typename std::vector<dp_point_type>::iterator iterator_type;
 
-    typedef typename PointDistanceStrategy::return_type return_type;
 
     static inline void consider(iterator_type begin,
                 iterator_type end,
                 return_type const& max_dist, int& n,
-                PointDistanceStrategy const& ps_distance_strategy)
+                distance_strategy_type const& ps_distance_strategy)
     {
         std::size_t size = end - begin;
 
@@ -125,7 +130,7 @@
 #endif
 
 
-        // Find most distance point, compare to the current segment
+        // Find most far point, compare to the current segment
         //geometry::segment<Point const> s(begin->p, last->p);
         return_type md(-1.0); // any value < 0
         iterator_type candidate;
@@ -166,14 +171,11 @@
 
 public :
 
-    typedef PointDistanceStrategy distance_strategy_type;
-
-
     template <typename Range, typename OutputIterator>
     static inline OutputIterator apply(Range const& range,
                     OutputIterator out, double max_distance)
     {
-        PointDistanceStrategy strategy;
+        distance_strategy_type strategy;
 
         // Copy coordinates, a vector of references to all points
         std::vector<dp_point_type> ref_candidates(boost::begin(range),
@@ -187,10 +189,9 @@
 
         // Get points, recursively, including them if they are further away
         // than the specified distance
-        typedef typename PointDistanceStrategy::return_type return_type;
+        typedef typename distance_strategy_type::return_type return_type;
 
-        consider(boost::begin(ref_candidates), boost::end(ref_candidates),
-            make_distance_result<return_type>(max_distance), n, strategy);
+        consider(boost::begin(ref_candidates), boost::end(ref_candidates), max_distance, n, strategy);
 
         // Copy included elements to the output
         for(typename std::vector<dp_point_type>::const_iterator it
Modified: sandbox/geometry/boost/geometry/strategies/cartesian/distance_projected_point.hpp
==============================================================================
--- sandbox/geometry/boost/geometry/strategies/cartesian/distance_projected_point.hpp	(original)
+++ sandbox/geometry/boost/geometry/strategies/cartesian/distance_projected_point.hpp	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -10,6 +10,7 @@
 #define BOOST_GEOMETRY_STRATEGIES_CARTESIAN_DISTANCE_PROJECTED_POINT_HPP
 
 
+#include <boost/concept_check.hpp>
 #include <boost/mpl/if.hpp>
 #include <boost/type_traits.hpp>
 
@@ -28,7 +29,8 @@
 #include <boost/geometry/util/copy.hpp>
 
 
-// Helper geometry
+// Helper geometries
+#include <boost/geometry/geometries/point.hpp>
 #include <boost/geometry/geometries/segment.hpp>
 
 
@@ -40,7 +42,6 @@
 {
 
 
-
 /*!
     \brief Strategy for distance point to segment
     \ingroup distance
@@ -51,30 +52,65 @@
     \tparam Strategy strategy, optional, defaults to pythagoras
     \par Concepts for Strategy:
     - cartesian_distance operator(Point,Point)
+    \note If the Strategy is a "comparable::pythagoras", this strategy
+        automatically is a comparable projected_point strategy (so without sqrt)
 */
 template
 <
     typename Point,
     typename PointOfSegment,
-    typename Strategy = pythagoras
-        <
-            Point,
-            typename point_type<PointOfSegment>::type
-        >
+    typename CalculationType = void,
+    typename Strategy = pythagoras<Point, PointOfSegment, CalculationType>
 >
-struct projected_point
+class projected_point
 {
+public :
     typedef Point point_type;
     typedef PointOfSegment segment_point_type;
+
     typedef typename select_coordinate_type
         <
             Point,
             PointOfSegment
         >::type coordinate_type;
-    typedef cartesian_distance<coordinate_type> return_type;
+
+    typedef typename Strategy::return_type return_type;
 
     typedef Strategy point_strategy_type;
 
+private :
+
+    // The three typedefs below are necessary to calculate distances
+    // from segments defined in integer coordinates.
+
+    // Integer coordinates can still result in FP distances.
+    // There is a division, which must be represented in FP.
+    // So promote.
+    typedef typename promote_floating_point<coordinate_type>::type fp_type;
+
+    // A projected point of points in Integer coordinates must be able to be
+    // represented in FP.
+    typedef boost::geometry::point
+        <
+            fp_type,
+            dimension<PointOfSegment>::value,
+            typename coordinate_system<PointOfSegment>::type
+        > fp_point_type;
+
+    // For convenience
+    typedef fp_point_type fp_vector_type;
+
+    // We have to use a strategy using FP coordinates (fp-type) which is
+    // not always the same as Strategy (defined as point_strategy_type)
+    // So we create a "similar" one
+    typedef typename strategy::distance::services::similar_type
+        <
+            point_strategy_type,
+            Point,
+            fp_point_type
+        >::type fp_strategy_type;
+
+public :
 
     inline return_type apply(Point const& p,
                     PointOfSegment const& p1, PointOfSegment const& p2) const
@@ -90,49 +126,148 @@
         RETURN POINT(x1 + b * vx, y1 + b * vy);
         */
 
-
-        // Take here the first point type. It should have a default constructor.
-        // That is not required for the second point type.
-        Point v, w;
+        // v is multiplied below with a (possibly) FP-value, so should be in FP
+        // For consistency we define w also in FP
+        fp_vector_type v, w;
 
         copy_coordinates(p2, v);
         copy_coordinates(p, w);
         subtract_point(v, p1);
         subtract_point(w, p1);
 
-        Strategy strategy;
+        point_strategy_type strategy;
+        boost::ignore_unused_variable_warning(strategy);
 
         coordinate_type zero = coordinate_type();
-        coordinate_type c1 = dot_product(w, v);
+        fp_type c1 = dot_product(w, v);
         if (c1 <= zero)
         {
             return strategy.apply(p, p1);
         }
-        coordinate_type c2 = dot_product(v, v);
+        fp_type c2 = dot_product(v, v);
         if (c2 <= c1)
         {
             return strategy.apply(p, p2);
         }
 
-        // Even in case of char's, we have to turn to a point<double/float>
-        // because of the division.
-        typedef typename geometry::select_most_precise<coordinate_type, double>::type divisor_type;
-        divisor_type b = c1 / c2;
-
-        // Note that distances with integer coordinates do NOT work because
-        // - the project point is integer
-        // - if we solve that, the used distance_strategy cannot handle double points
-        PointOfSegment projected;
+        // See above, c1 > 0 AND c2 > c1 so: c2 != 0
+        fp_type b = fp_type(c1) / fp_type(c2);
+
+
+        fp_strategy_type fp_strategy
+            = strategy::distance::services::get_similar
+                <
+                    point_strategy_type, Point, fp_point_type
+                >::apply(strategy);
+
+        fp_point_type projected;
         copy_coordinates(p1, projected);
         multiply_value(v, b);
         add_point(projected, v);
 
-        return strategy.apply(p, projected);
+        //std::cout << "distance " << dsv(p) << " .. " << dsv(projected) << std::endl;
 
+        return fp_strategy.apply(p, projected);
     }
 
 };
 
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+namespace services
+{
+
+template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy>
+struct tag<projected_point<Point, PointOfSegment, CalculationType, Strategy> >
+{
+    typedef strategy_tag_distance_point_segment type;
+};
+
+
+template
+<
+    typename Point,
+    typename PointOfSegment,
+    typename CalculationType,
+    typename Strategy,
+    typename P1,
+    typename P2
+>
+struct similar_type<projected_point<Point, PointOfSegment, CalculationType, Strategy>, P1, P2>
+{
+    typedef projected_point<P1, P2, CalculationType, Strategy> type;
+};
+
+
+template
+<
+    typename Point,
+    typename PointOfSegment,
+    typename CalculationType,
+    typename Strategy,
+    typename P1,
+    typename P2
+>
+struct get_similar<projected_point<Point, PointOfSegment, CalculationType, Strategy>, P1, P2>
+{
+    static inline typename similar_type
+        <
+            projected_point<Point, PointOfSegment, CalculationType, Strategy>, P1, P2
+        >::type apply(projected_point<Point, PointOfSegment, CalculationType, Strategy> const& )
+    {
+        return projected_point<P1, P2, CalculationType, Strategy>();
+    }
+};
+
+
+template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy>
+struct comparable_type<projected_point<Point, PointOfSegment, CalculationType, Strategy> >
+{
+    // Define a projected_point strategy with its underlying point-point-strategy
+    // being comparable
+    typedef projected_point
+        <
+            Point,
+            PointOfSegment,
+            CalculationType,
+            typename comparable_type<Strategy>::type
+        > type;
+};
+
+
+template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy>
+struct get_comparable<projected_point<Point, PointOfSegment, CalculationType, Strategy> >
+{
+    typedef typename comparable_type
+        <
+            projected_point<Point, PointOfSegment, CalculationType, Strategy>
+        >::type comparable_type;
+public :
+    static inline comparable_type apply(projected_point<Point, PointOfSegment, CalculationType, Strategy> const& )
+    {
+        return comparable_type();
+    }
+};
+
+
+template <typename Point, typename PointOfSegment, typename CalculationType, typename Strategy>
+struct result_from_distance<projected_point<Point, PointOfSegment, CalculationType, Strategy> >
+{
+private :
+    typedef typename projected_point<Point, PointOfSegment, CalculationType, Strategy>::return_type return_type;
+public :
+    template <typename T>
+    static inline return_type apply(projected_point<Point, PointOfSegment, CalculationType, Strategy> const& , T const& value)
+    {
+        Strategy s;
+        return result_from_distance<Strategy>::apply(s, value);
+    }
+};
+
+
+} // namespace services
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
 }} // namespace strategy::distance
 
 
@@ -149,6 +284,7 @@
     <
         Point,
         PointOfSegment,
+        void,
         typename strategy_distance
         <
             cartesian_tag, cartesian_tag, Point, segment_point_type
Modified: sandbox/geometry/boost/geometry/strategies/cartesian/distance_pythagoras.hpp
==============================================================================
--- sandbox/geometry/boost/geometry/strategies/cartesian/distance_pythagoras.hpp	(original)
+++ sandbox/geometry/boost/geometry/strategies/cartesian/distance_pythagoras.hpp	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -19,6 +19,8 @@
 #include <boost/geometry/strategies/distance_result.hpp>
 
 #include <boost/geometry/util/select_calculation_type.hpp>
+#include <boost/geometry/util/promote_floating_point.hpp>
+
 #include <boost/geometry/util/copy.hpp>
 
 
@@ -57,8 +59,12 @@
 }
 #endif // DOXYGEN_NO_DETAIL
 
+
+namespace comparable
+{
+
 /*!
-    \brief Strategy for distance point to point: pythagoras
+    \brief Strategy for comparable distance point to point: comparable_pythagoras
     \ingroup distance
     \tparam Point1 first point type
     \tparam Point2 optional, second point type, defaults to first point type
@@ -74,17 +80,16 @@
 struct pythagoras
 {
     typedef typename select_calculation_type
-        <
-            Point1,
-            Point2,
-            CalculationType
-        >::type calculation_type;
+            <
+                Point1,
+                Point2,
+                CalculationType
+            >::type return_type;
 
     typedef Point1 first_point_type;
     typedef Point2 second_point_type;
-    typedef cartesian_distance<calculation_type> return_type;
 
-    inline return_type apply(Point1 const& p1, Point2 const& p2) const
+    static inline return_type apply(Point1 const& p1, Point2 const& p2)
     {
         BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point1>) );
         BOOST_CONCEPT_ASSERT( (concept::ConstPoint<Point2>) );
@@ -94,16 +99,209 @@
 
         assert_dimension_equal<Point1, Point2>();
 
-        return return_type(detail::compute_pythagoras
+        return detail::compute_pythagoras
             <
                 Point1, Point2,
                 dimension<Point1>::value,
-                calculation_type
-            >::apply(p1, p2));
+                return_type
+            >::apply(p1, p2);
+    }
+};
+
+} // namespace comparable
+
+
+/*!
+    \brief Strategy for distance point to point: pythagoras
+    \ingroup distance
+    \tparam Point1 first point type
+    \tparam Point2 optional, second point type, defaults to first point type
+    \par Concepts for Point1 and Point2:
+    - specialized point_traits class
+*/
+template
+<
+    typename Point1,
+    typename Point2 = Point1,
+    typename CalculationType = void
+>
+struct pythagoras
+{
+    typedef comparable::pythagoras<Point1, Point2, CalculationType> comparable_type;
+    typedef typename promote_floating_point
+        <
+            typename comparable_type::return_type
+        >::type return_type;
+
+    typedef Point1 first_point_type;
+    typedef Point2 second_point_type;
+
+    static inline return_type apply(Point1 const& p1, Point2 const& p2)
+    {
+        return_type const t = comparable_type::apply(p1, p2);
+        return sqrt(t);
+    }
+};
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+namespace services
+{
+
+template <typename Point1, typename Point2, typename CalculationType>
+struct tag<pythagoras<Point1, Point2, CalculationType> >
+{
+    typedef strategy_tag_distance_point_point type;
+};
+
+
+template
+<
+    typename Point1,
+    typename Point2,
+    typename CalculationType,
+    typename P1,
+    typename P2
+>
+struct similar_type<pythagoras<Point1, Point2, CalculationType>, P1, P2>
+{
+    typedef pythagoras<P1, P2, CalculationType> type;
+};
+
+
+template
+<
+    typename Point1,
+    typename Point2,
+    typename CalculationType,
+    typename P1,
+    typename P2
+>
+struct get_similar<pythagoras<Point1, Point2, CalculationType>, P1, P2>
+{
+    static inline typename similar_type
+        <
+            pythagoras<Point1, Point2, CalculationType>, P1, P2
+        >::type apply(pythagoras<Point1, Point2, CalculationType> const& )
+    {
+        return pythagoras<P1, P2, CalculationType>();
     }
 };
 
 
+template <typename Point1, typename Point2, typename CalculationType>
+struct comparable_type<pythagoras<Point1, Point2, CalculationType> >
+{
+    typedef comparable::pythagoras<Point1, Point2, CalculationType> type;
+};
+
+
+template <typename Point1, typename Point2, typename CalculationType>
+struct get_comparable<pythagoras<Point1, Point2, CalculationType> >
+{
+    typedef comparable::pythagoras<Point1, Point2, CalculationType> comparable_type;
+public :
+    static inline comparable_type apply(pythagoras<Point1, Point2, CalculationType> const& input)
+    {
+        return comparable_type();
+    }
+};
+
+
+template <typename Point1, typename Point2, typename CalculationType>
+struct result_from_distance<pythagoras<Point1, Point2, CalculationType> >
+{
+private :
+    typedef typename pythagoras<Point1, Point2, CalculationType>::return_type return_type;
+public :
+    template <typename T>
+    static inline return_type apply(pythagoras<Point1, Point2, CalculationType> const& , T const& value)
+    {
+        return return_type(value);
+    }
+};
+
+
+// Specializations for comparable::pythagoras
+template <typename Point1, typename Point2, typename CalculationType>
+struct tag<comparable::pythagoras<Point1, Point2, CalculationType> >
+{
+    typedef strategy_tag_distance_point_point type;
+};
+
+
+template
+<
+    typename Point1,
+    typename Point2,
+    typename CalculationType,
+    typename P1,
+    typename P2
+>
+struct similar_type<comparable::pythagoras<Point1, Point2, CalculationType>, P1, P2>
+{
+    typedef comparable::pythagoras<P1, P2, CalculationType> type;
+};
+
+
+template
+<
+    typename Point1,
+    typename Point2,
+    typename CalculationType,
+    typename P1,
+    typename P2
+>
+struct get_similar<comparable::pythagoras<Point1, Point2, CalculationType>, P1, P2>
+{
+    static inline typename similar_type
+        <
+            comparable::pythagoras<Point1, Point2, CalculationType>, P1, P2
+        >::type apply(comparable::pythagoras<Point1, Point2, CalculationType> const& )
+    {
+        return comparable::pythagoras<P1, P2, CalculationType>();
+    }
+};
+
+
+template <typename Point1, typename Point2, typename CalculationType>
+struct comparable_type<comparable::pythagoras<Point1, Point2, CalculationType> >
+{
+    typedef comparable::pythagoras<Point1, Point2, CalculationType> type;
+};
+
+
+template <typename Point1, typename Point2, typename CalculationType>
+struct get_comparable<comparable::pythagoras<Point1, Point2, CalculationType> >
+{
+    typedef comparable::pythagoras<Point1, Point2, CalculationType> comparable_type;
+public :
+    static inline comparable_type apply(comparable::pythagoras<Point1, Point2, CalculationType> const& input)
+    {
+        return comparable_type();
+    }
+};
+
+
+template <typename Point1, typename Point2, typename CalculationType>
+struct result_from_distance<comparable::pythagoras<Point1, Point2, CalculationType> >
+{
+private :
+    typedef typename comparable::pythagoras<Point1, Point2, CalculationType>::return_type return_type;
+public :
+    template <typename T>
+    static inline return_type apply(comparable::pythagoras<Point1, Point2, CalculationType> const& , T const& value)
+    {
+        return_type const v = value;
+        return v * v;
+    }
+};
+
+
+} // namespace services
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
 }} // namespace strategy::distance
 
 
@@ -115,15 +313,20 @@
 };
 
 
-#endif
-
-
 template <typename Point1, typename Point2>
 struct strategy_tag<strategy::distance::pythagoras<Point1, Point2> >
 {
     typedef strategy_tag_distance_point_point type;
 };
 
+template <typename Point1, typename Point2>
+struct strategy_tag<strategy::distance::comparable::pythagoras<Point1, Point2> >
+{
+    typedef strategy_tag_distance_point_point type;
+};
+
+
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
 
 
 }} // namespace boost::geometry
Modified: sandbox/geometry/boost/geometry/strategies/concepts/distance_concept.hpp
==============================================================================
--- sandbox/geometry/boost/geometry/strategies/concepts/distance_concept.hpp	(original)
+++ sandbox/geometry/boost/geometry/strategies/concepts/distance_concept.hpp	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -63,10 +63,58 @@
             }
         };
 
+        // 5) must define meta-function "similar_type"
+        typedef typename strategy::distance::services::similar_type
+            <
+                Strategy, ptype2, ptype1
+            >::type stype;
+
+        // 6) must define meta-function "comparable_type"
+        typedef typename strategy::distance::services::comparable_type
+            <
+                Strategy
+            >::type ctype;
+
+        // 6) must define meta-function "tag"
+        typedef typename strategy::distance::services::tag
+            <
+                Strategy
+            >::type tag;
+
+
+        // 7) must define (meta)struct "get_similar" with apply
+        // 8) must define (meta)struct "get_comparable" with apply
+        // 9) must define (meta)struct "result_from_distance" with apply
+        struct services_checker
+        {
+            static void check()
+            {
+                Strategy* str;
+                stype s = strategy::distance::services::get_similar
+                    <
+                        Strategy,
+                        ptype2, ptype1
+                    >::apply(*str);
+                ctype c = strategy::distance::services::get_comparable
+                    <
+                        Strategy
+                    >::apply(*str);
+                rtype r = strategy::distance::services::result_from_distance
+                    <
+                        Strategy
+                    >::apply(*str, 1.0);
+
+                boost::ignore_unused_variable_warning(s);
+                boost::ignore_unused_variable_warning(c);
+            }
+        };
+
+
     public :
         BOOST_CONCEPT_USAGE(PointDistanceStrategy)
         {
             apply_checker::check();
+            services_checker::check();
         }
 #endif
 };
Modified: sandbox/geometry/boost/geometry/strategies/distance.hpp
==============================================================================
--- sandbox/geometry/boost/geometry/strategies/distance.hpp	(original)
+++ sandbox/geometry/boost/geometry/strategies/distance.hpp	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -10,6 +10,7 @@
 #define BOOST_GEOMETRY_STRATEGIES_DISTANCE_HPP
 
 
+#include <boost/geometry/core/cs.hpp>
 #include <boost/geometry/strategies/tags.hpp>
 
 
@@ -37,9 +38,9 @@
     \tparam CsTag1 tag of coordinate system of point type
     \tparam CsTag2 tag of coordinate system of segment type, usually same as CsTag1
     \tparam Point point-type
-    \tparam Segment segment-type
+    \tparam PointOfSegment segment-point-type
 */
-template <typename CsTag1, typename CsTag2, typename Point, typename Segment>
+template <typename CsTag1, typename CsTag2, typename Point, typename PointOfSegment>
 struct strategy_distance_segment
 {
     typedef strategy::not_implemented type;
@@ -47,6 +48,66 @@
 
 
 
+// New functionality:
+template 
+<
+    typename Point1, 
+    typename Point2 = Point1,
+    typename Tag1 = typename cs_tag<Point1>::type,
+    typename Tag2 = typename cs_tag<Point2>::type
+>
+struct default_distance_strategy
+{
+    typedef typename strategy_distance<Tag1, Tag2, Point1, Point2>::type type;
+};
+
+template 
+<
+    typename Point, 
+    typename PointOfSegment,
+    typename Tag1 = typename cs_tag<Point>::type,
+    typename Tag2 = typename cs_tag<PointOfSegment>::type
+>
+struct default_distance_strategy_segment
+{
+    typedef typename strategy_distance_segment<Tag1, Tag2, Point, PointOfSegment>::type type;
+};
+
+
+
+namespace strategy { namespace distance { namespace services 
+{
+
+template <typename Strategy> struct tag {};
+
+
+/*!
+    \brief Metafunction delivering a similar strategy with other input point types
+*/
+template 
+<
+    typename Strategy, 
+    typename Point1, 
+    typename Point2
+> 
+struct similar_type {};
+
+template 
+<
+    typename Strategy, 
+    typename Point1, 
+    typename Point2
+> 
+struct get_similar {};
+
+template <typename Strategy> struct comparable_type {};
+template <typename Strategy> struct get_comparable {};
+
+template <typename Strategy> struct result_from_distance {};
+
+
+}}} // namespace strategy::distance::services
+
 
 }} // namespace boost::geometry
 
Modified: sandbox/geometry/boost/geometry/strategies/distance_result.hpp
==============================================================================
--- sandbox/geometry/boost/geometry/strategies/distance_result.hpp	(original)
+++ sandbox/geometry/boost/geometry/strategies/distance_result.hpp	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -9,325 +9,35 @@
 #ifndef BOOST_GEOMETRY_STRATEGIES_DISTANCE_RESULT_HPP
 #define BOOST_GEOMETRY_STRATEGIES_DISTANCE_RESULT_HPP
 
-#include <utility>
-#include <cmath>
-#include <limits>
-
-#include <boost/mpl/if.hpp>
-#include <boost/numeric/conversion/cast.hpp>
-#include <boost/type_traits.hpp>
 
 #include <boost/geometry/core/cs.hpp>
 #include <boost/geometry/core/point_type.hpp>
 #include <boost/geometry/strategies/distance.hpp>
-#include <boost/geometry/util/math.hpp>
-#include <boost/geometry/util/select_most_precise.hpp>
 
 
 namespace boost { namespace geometry
 {
 
 /*!
-    \brief Encapsulate the results of distance calculation
+    \brief Meta-function defining return type of distance function
     \ingroup distance
-    \details Distance calculation for xy points or xyz points is done by taking the square
-    root. However, for distance comparison drawing the square root is not necessary.
-    Therefore the distance strategies are allowed to return the squares of the distance.
-    This structure contains the distance, and a boolean to indicate if it is squared.
-    It has an automatic conversion to a double value, which does the square root if necessary.
-    \note Thanks to Phil Endecott for his suggestion to change the pair to the double-convertable
-    http://article.gmane.org/gmane.comp.lib.boost.devel/172709/match=greatcircle_distance
-*/
-template<typename T = double>
-struct cartesian_distance
-{
-    private :
-        T m_squared_distance;
-
-        // Because result is square-rooted, for integer, the cast should
-        // go to double and NOT to T
-        typedef typename
-            boost::mpl::if_c
-            <
-                boost::is_integral<T>::type::value,
-                double,
-                T
-            >::type cast_type;
-
-
-
-
-    public :
-
-
-        /// Constructor with a value
-        explicit cartesian_distance(T const& v) : m_squared_distance(v) {}
-
-        /// Automatic conversion to double or higher precision,
-        /// taking squareroot if necessary
-        inline operator cast_type() const
-        {
-            return boost::numeric_cast<cast_type>
-                (
-#if defined(NUMERIC_ADAPTOR_INCLUDED)
-                    boost::sqrt(
-#else
-                    std::sqrt(
-#endif
-                        boost::numeric_cast
-                            <
-                                typename select_most_precise<cast_type, double>::type
-                            >(m_squared_distance)
-                            )
-                );
-        }
-
-        // Compare squared values
-        inline bool operator<(cartesian_distance<T> const& other) const
-        {
-            return this->m_squared_distance < other.m_squared_distance;
-        }
-        inline bool operator>(cartesian_distance<T> const& other) const
-        {
-            return this->m_squared_distance > other.m_squared_distance;
-        }
-        inline bool operator==(cartesian_distance<T> const& other) const
-        {
-            return math::equals(this->m_squared_distance, other.m_squared_distance);
-        }
-
-        // Compare just with a corresponding POD value
-        // Note: this is NOT possible because of the cast to double,
-        // it makes it for the compiler ambiguous which to take
-        /*
-        inline bool operator<(T const& value) const
-        {
-            return this->m_squared_distance < (value * value);
-        }
-        inline bool operator>(T const& value) const
-        {
-            return this->m_squared_distance > (value * value);
-        }
-        inline bool operator==(T const& value) const
-        {
-            return this->m_squared_distance == (value * value);
-        }
-        */
-
-        // Utility method to compare without SQRT, but not with method above because for epsilon that
-        // makes no sense...
-        inline bool very_small() const
-        {
-            return m_squared_distance <= std::numeric_limits<T>::epsilon();
-        }
-
-        /// The "squared_value" method returns the internal squared value
-        inline T squared_value() const
-        {
-            return m_squared_distance;
-        }
-
-        /// Make streamable to enable std::cout << geometry::distance( )
-        template <typename Char, typename Traits>
-        inline friend std::basic_ostream<Char, Traits>&
-                operator<<(std::basic_ostream<Char, Traits>& os,
-                cartesian_distance<T> const& d)
-        {
-            // Avoid "ambiguous function call" for MSVC
-            cast_type const sq = d.m_squared_distance;
-
-            os <<
-#if defined(NUMERIC_ADAPTOR_INCLUDED)
-                boost::sqrt(sq);
-#else
-                sqrt(sq);
-#endif
-            return os;
-        }
-
-};
-
-
-
-/*
-
-    From Phil Endecott, on the list:
-
-    You can go further.  If I'm searching through a long list of points to
-    find the closest to P then I'll avoid the squaring (and conversion to
-    double if my co-ordinates are integers) whenever possible.  You can
-    achieve this with a more complex distance proxy:
-
-    class distance_proxy {
-       double dx;
-       double dy;
-       distance_proxy(double dx_, double dy_): dx(dx_), dy(dy_) {}
-       friend pythag_distance(point,point);
-    public:
-       operator double() { return sqrt(dx*dx+dy*dy); }
-       bool operator>(double d) {
-         return dx>d
-             || dy>d
-             || (dx*dx+dy*dy > d*d);
-       }
-    };
-
-    So this is convertible to double, but can be compared to a distance
-    without any need for sqrt() and only multiplication in some cases.
-    Further refinement is possible.
-
-
-    Barend:
-    feasable, needs to be templatized by the number of dimensions. For distance it
-    results in a nice "delayed calculation".
-    For searching you might take another approach, first calculate dx, if OK then dy,
-    if OK then the sqrs. So as above but than distance does not need to be calculated.
-    So it is in fact another strategy.
-
-
-*/
-
-
-
-#ifndef DOXYGEN_NO_DETAIL
-namespace detail
-{
-    namespace distance
-    {
-        template <typename R, typename T>
-        struct distance_result_maker
-        {
-        };
-
-        template <typename R, typename T>
-        struct distance_result_maker<geometry::cartesian_distance<R>, T>
-        {
-            static inline geometry::cartesian_distance<R> apply(T const& value)
-            {
-                return cartesian_distance<R>(value * value);
-            }
-        };
-
-        template <typename T>
-        struct distance_result_maker<double, T>
-        {
-            static inline double apply(T const& value)
-            {
-                return value;
-            }
-        };
-
-
-        template <typename T>
-        struct close_to_zero
-        {
-            static inline bool apply(T const& value)
-            {
-                return value <= std::numeric_limits<T>::epsilon();
-            }
-        };
-
-
-        template <typename T>
-        struct close_to_zero<geometry::cartesian_distance<T> >
-        {
-            static inline bool apply(geometry::cartesian_distance<T> const& value)
-            {
-                return value.very_small();
-            }
-        };
-
-
-        template <typename T>
-        struct fuzzy_equals
-        {
-            static inline bool apply(T const& left, T const& right)
-            {
-                return std::abs(left - right) < 0.01;
-            }
-        };
-
-
-        template <typename T>
-        struct fuzzy_equals<geometry::cartesian_distance<T> >
-        {
-            typedef geometry::cartesian_distance<T> D;
-            static inline bool apply(D const& left, D const& right)
-            {
-                return std::abs(left.squared_value() - right.squared_value()) < 1;
-            }
-        };
-
-    }
-}
-#endif
-
+    \note The strategy defines the return-type (so this situation is different
+        from length, where distance is sqr/sqrt, but length always squared)
 
-
-/*!
-    \brief Shortcut to define return type of distance strategy
-    \ingroup distance
-    \tparam Geometry1 first geometry
-    \tparam Geometry2 second geometry
  */
-template <typename Geometry1, typename Geometry2 = Geometry1>
+template <typename Geometry1, typename Geometry2>
 struct distance_result
 {
-    typedef typename point_type<Geometry1>::type point_type1;
-    typedef typename point_type<Geometry2>::type point_type2;
-    typedef typename strategy_distance
+    typedef typename default_distance_strategy
         <
-            typename cs_tag<point_type1>::type,
-            typename cs_tag<point_type2>::type,
-            point_type1,
-            point_type2
+            typename point_type<Geometry1>::type,
+            typename point_type<Geometry2>::type
         >::type strategy_type;
+
     typedef typename strategy_type::return_type type;
 };
 
 
-
-
-
-/*!
-    \brief Object generator to create instance which can be compared
-    \ingroup distance
-    \details If distance results have to be compared to a certain value it makes sense to use
-    this function to generate a distance result of a certain value, and compare the distance
-    result with this instance. SQRT calculations are then avoided
-    \tparam R distance result type
-    \tparam T arithmetic type, e.g. double
-    \param value the distance to compare with
-    \return the distance result
-*/
-template <typename R, typename T>
-inline R make_distance_result(T const& value)
-{
-    return detail::distance::distance_result_maker<R, T>::apply(value);
-}
-
-
-/*!
-    \brief Utility function to check if a distance is very small
-    \ingroup distance
-    \details Depending on the "distance result" type it checks if it is smaller than epsilon,
-    or (for Cartesian distances) if the square is smaller than epsilon
-    \tparam R the distance result type, either arithmetic or cartesian distance
-    \param value the distance result to check
-*/
-template <typename T>
-inline bool close_to_zero(T const& value)
-{
-    return detail::distance::close_to_zero<T>::apply(value);
-}
-
-template <typename T>
-inline bool fuzzy_equals(T const& left, T const& right)
-{
-    return detail::distance::fuzzy_equals<T>::apply(left, right);
-}
-
-
 }} // namespace boost::geometry
 
 
Modified: sandbox/geometry/boost/geometry/strategies/spherical/distance_cross_track.hpp
==============================================================================
--- sandbox/geometry/boost/geometry/strategies/spherical/distance_cross_track.hpp	(original)
+++ sandbox/geometry/boost/geometry/strategies/spherical/distance_cross_track.hpp	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -20,11 +20,13 @@
 #include <boost/geometry/strategies/distance.hpp>
 #include <boost/geometry/strategies/concepts/distance_concept.hpp>
 
+#include <boost/geometry/util/promote_floating_point.hpp>
 #include <boost/geometry/util/math.hpp>
 //#include <boost/geometry/util/write_dsv.hpp>
 
 
 
+
 namespace boost { namespace geometry
 {
 
@@ -39,20 +41,30 @@
     \tparam P point type
     \tparam S segment type
 */
-template <typename Point, typename PointOfSegment>
+template
+<
+    typename Point,
+    typename PointOfSegment = Point,
+    typename CalculationType = void,
+    typename Strategy = typename default_distance_strategy<Point>::type
+>
 class cross_track
 {
 public :
-    typedef double return_type;
+    typedef typename promote_floating_point
+        <
+            typename select_calculation_type
+                <
+                    Point,
+                    PointOfSegment,
+                    CalculationType
+                >::type
+        >::type return_type;
+
     typedef Point point_type;
     typedef PointOfSegment segment_point_type;
 
-    typedef typename strategy_distance
-        <
-            typename geometry::cs_tag<Point>::type,
-            typename geometry::cs_tag<Point>::type,
-            Point, Point
-        >::type point_strategy_type;
+    typedef Strategy point_strategy_type;
 
     BOOST_CONCEPT_ASSERT
         (
@@ -61,7 +73,7 @@
 
 
 
-    inline cross_track(double r = 1.0)
+    inline cross_track(return_type const& r = 1.0)
         : m_radius(r)
         , m_strategy(1.0) // Keep this 1.0 and not r
     {}
@@ -76,14 +88,14 @@
                 PointOfSegment const& sp1, PointOfSegment const& sp2) const
     {
         // http://williams.best.vwh.net/avform.htm#XTE
-        double d1 = m_strategy.apply(sp1, p);
+        return_type d1 = m_strategy.apply(sp1, p);
 
         // Actually, calculation of d2 not necessary if we know that the projected point is on the great circle...
-        double d2 = m_strategy.apply(sp2, p);
+        return_type d2 = m_strategy.apply(sp2, p);
 
-        double crs_AD = course(sp1, p);
-        double crs_AB = course(sp1, sp2);
-        double XTD = std::abs(asin(sin(d1) * sin(crs_AD - crs_AB)));
+        return_type crs_AD = course(sp1, p);
+        return_type crs_AB = course(sp1, sp2);
+        return_type XTD = abs(asin(sin(d1) * sin(crs_AD - crs_AB)));
 
 //std::cout << "Course " << dsv(sp1) << " to " << dsv(p) << " " << crs_AD * geometry::math::r2d << std::endl;
 //std::cout << "Course " << dsv(sp1) << " to " << dsv(sp2) << " " << crs_AB * geometry::math::r2d << std::endl;
@@ -94,18 +106,20 @@
         return return_type(m_radius * (std::min)((std::min)(d1, d2), XTD));
     }
 
+    inline return_type radius() const { return m_radius; }
+
 private :
-    double m_radius;
+    return_type m_radius;
 
     // Point-point distances are calculated in radians, on the unit sphere
     point_strategy_type m_strategy;
 
     /// Calculate course (bearing) between two points. Might be moved to a "course formula" ...
-    inline double course(Point const& p1, Point const& p2) const
+    inline return_type course(Point const& p1, Point const& p2) const
     {
         // http://williams.best.vwh.net/avform.htm#Crs
-        double dlon = get_as_radian<0>(p2) - get_as_radian<0>(p1);
-        double cos_p2lat = cos(get_as_radian<1>(p2));
+        return_type dlon = get_as_radian<0>(p2) - get_as_radian<0>(p1);
+        return_type cos_p2lat = cos(get_as_radian<1>(p2));
 
         // "An alternative formula, not requiring the pre-computation of d"
         return atan2(sin(dlon) * cos_p2lat,
@@ -116,6 +130,91 @@
 };
 
 
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+namespace services
+{
+
+template <typename Point, typename PointOfSegment>
+struct tag<cross_track<Point, PointOfSegment> >
+{
+    typedef strategy_tag_distance_point_segment type;
+};
+
+
+template
+<
+    typename Point,
+    typename PointOfSegment,
+    typename P,
+    typename PS
+>
+struct similar_type<cross_track<Point, PointOfSegment>, P, PS>
+{
+    typedef cross_track<Point, PointOfSegment> type;
+};
+
+
+template
+<
+    typename Point,
+    typename PointOfSegment,
+    typename P,
+    typename PS
+>
+struct get_similar<cross_track<Point, PointOfSegment>, P, PS>
+{
+    static inline typename similar_type
+        <
+            cross_track<Point, PointOfSegment>, P, PS
+        >::type apply(cross_track<Point, PointOfSegment> const& strategy)
+    {
+        return cross_track<P, PS>(strategy.radius());
+    }
+};
+
+
+template <typename Point, typename PointOfSegment>
+struct comparable_type<cross_track<Point, PointOfSegment> >
+{
+    // Comparable type is here just the strategy
+    typedef typename similar_type<cross_track<Point, PointOfSegment>, Point, PointOfSegment>::type type;
+};
+
+
+template <typename Point, typename PointOfSegment>
+struct get_comparable<cross_track<Point, PointOfSegment> >
+{
+    typedef typename comparable_type
+        <
+            cross_track<Point, PointOfSegment>
+        >::type comparable_type;
+public :
+    static inline comparable_type apply(cross_track<Point, PointOfSegment> const& strategy)
+    {
+        return comparable_type(strategy.radius());
+    }
+};
+
+
+template <typename Point, typename PointOfSegment>
+struct result_from_distance<cross_track<Point, PointOfSegment> >
+{
+private :
+    typedef typename cross_track<Point, PointOfSegment>::return_type return_type;
+public :
+    template <typename T>
+    static inline return_type apply(cross_track<Point, PointOfSegment> const& , T const& distance)
+    {
+        return distance;
+    }
+};
+
+
+} // namespace services
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
 }} // namespace strategy::distance
 
 
@@ -131,10 +230,10 @@
 
 
 // Use this point-segment for geographic as well. TODO: change this, extension!
-template <typename Point, typename Segment>
-struct strategy_distance_segment<geographic_tag, geographic_tag, Point, Segment>
+template <typename Point, typename PointOfSegment>
+struct strategy_distance_segment<geographic_tag, geographic_tag, Point, PointOfSegment>
 {
-    typedef strategy::distance::cross_track<Point, Segment> type;
+    typedef strategy::distance::cross_track<Point, PointOfSegment> type;
 };
 
 
@@ -145,14 +244,9 @@
 };
 
 
-
 #endif
 
 
-
-
-
-
 }} // namespace boost::geometry
 
 
Modified: sandbox/geometry/boost/geometry/strategies/spherical/distance_haversine.hpp
==============================================================================
--- sandbox/geometry/boost/geometry/strategies/spherical/distance_haversine.hpp	(original)
+++ sandbox/geometry/boost/geometry/strategies/spherical/distance_haversine.hpp	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -14,6 +14,8 @@
 #include <boost/geometry/core/access.hpp>
 #include <boost/geometry/core/radian_access.hpp>
 
+#include <boost/geometry/util/select_calculation_type.hpp>
+#include <boost/geometry/util/promote_floating_point.hpp>
 
 #include <boost/geometry/strategies/distance.hpp>
 
@@ -23,9 +25,77 @@
 namespace boost { namespace geometry
 {
 
+
 namespace strategy { namespace distance
 {
 
+
+namespace comparable
+{
+
+// Comparable haversine.
+// To compare distances, we can avoid:
+// - multiplication with radius and 2.0
+// - applying sqrt
+// - applying asin (which is strictly (monotone) increasing)
+template
+<
+    typename Point1,
+    typename Point2 = Point1,
+    typename CalculationType = void
+>
+class haversine
+{
+public :
+    typedef typename promote_floating_point
+        <
+            typename select_calculation_type
+                <
+                    Point1,
+                    Point2,
+                    CalculationType
+                >::type
+        >::type return_type;
+
+    typedef Point1 first_point_type;
+    typedef Point2 second_point_type;
+
+    inline haversine(return_type const& r = 1.0)
+        : m_radius(r)
+    {}
+
+
+    static inline return_type apply(Point1 const& p1, Point2 const& p2)
+    {
+        return calculate(get_as_radian<0>(p1), get_as_radian<1>(p1),
+                        get_as_radian<0>(p2), get_as_radian<1>(p2));
+    }
+
+    inline return_type radius() const
+    {
+        return m_radius;
+    }
+
+
+private :
+    typedef return_type promoted_type;
+
+    static inline return_type calculate(promoted_type const& lon1,
+            promoted_type const& lat1,
+            promoted_type const& lon2,
+            promoted_type const& lat2)
+    {
+        return math::hav(lat2 - lat1)
+                + cos(lat1) * cos(lat2) * math::hav(lon2 - lon1);
+    }
+
+    return_type m_radius;
+};
+
+
+
+} // namespace comparable
+
 /*!
     \brief Distance calculation for spherical coordinates
         on a perfect sphere using haversine
@@ -43,71 +113,200 @@
                 + cos(lat1)*cos(lat2)*(sin((lon1-lon2)/2))^2))
                 </em>
 */
-template <typename Point1, typename Point2 = Point1>
+template
+<
+    typename Point1,
+    typename Point2 = Point1,
+    typename CalculationType = void
+>
 class haversine
 {
+    typedef comparable::haversine<Point1, Point2, CalculationType> comparable_type;
+
 public :
     typedef Point1 first_point_type;
     typedef Point2 second_point_type;
-    typedef double return_type;
 
-    inline haversine(double r = 1.0)
+    typedef typename comparable_type::return_type return_type;
+
+    inline haversine(return_type const& r = 1.0)
         : m_radius(r)
     {}
 
     inline return_type apply(Point1 const& p1, Point2 const& p2) const
     {
-        return calculate(get_as_radian<0>(p1), get_as_radian<1>(p1),
-                        get_as_radian<0>(p2), get_as_radian<1>(p2));
+        return_type const a = comparable_type::apply(p1, p2);
+        return_type const c = return_type(2.0) * asin(sqrt(a));
+        return m_radius * c;
     }
 
-private :
-    double m_radius;
-    typedef typename coordinate_type<Point1>::type coordinate_type1;
-    typedef typename coordinate_type<Point2>::type coordinate_type2;
-
-    inline return_type calculate(coordinate_type1 const& lon1,
-            coordinate_type1 const& lat1,
-            coordinate_type2 const& lon2,
-            coordinate_type2 const& lat2) const
+    inline return_type radius() const
     {
-        double a = math::hav(lat2 - lat1)
-                + cos(lat1) * cos(lat2) * math::hav(lon2 - lon1);
-        double c = 2.0 * asin(sqrt(a));
-        return return_type(m_radius * c);
+        return m_radius;
     }
+
+private :
+    return_type m_radius;
 };
 
 
-}} // namespace strategy::distance
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+namespace services
+{
 
+template <typename Point1, typename Point2, typename CalculationType>
+struct tag<haversine<Point1, Point2, CalculationType> >
+{
+    typedef strategy_tag_distance_point_point type;
+};
 
-#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
-template <typename P1, typename P2>
-struct strategy_distance<spherical_tag, spherical_tag, P1, P2>
+
+template <typename Point1, typename Point2, typename CalculationType, typename P1, typename P2>
+struct similar_type<haversine<Point1, Point2, CalculationType>, P1, P2>
+{
+    typedef haversine<P1, P2, CalculationType> type;
+};
+
+
+template <typename Point1, typename Point2, typename CalculationType, typename P1, typename P2>
+struct get_similar<haversine<Point1, Point2, CalculationType>, P1, P2>
+{
+private :
+    typedef haversine<Point1, Point2, CalculationType> this_type;
+public :
+    static inline typename similar_type<this_type, P1, P2>::type apply(this_type const& input)
+    {
+        return haversine<P1, P2, CalculationType>(input.radius());
+    }
+};
+
+template <typename Point1, typename Point2, typename CalculationType>
+struct comparable_type<haversine<Point1, Point2, CalculationType> >
 {
-    typedef strategy::distance::haversine<P1, P2> type;
+    typedef comparable::haversine<Point1, Point2, CalculationType> type;
 };
 
 
+template <typename Point1, typename Point2, typename CalculationType>
+struct get_comparable<haversine<Point1, Point2, CalculationType> >
+{
+private :
+    typedef haversine<Point1, Point2, CalculationType> this_type;
+    typedef comparable::haversine<Point1, Point2, CalculationType> comparable_type;
+public :
+    static inline comparable_type apply(this_type const& input)
+    {
+        return comparable_type(input.radius());
+    }
+};
 
+template <typename Point1, typename Point2, typename CalculationType>
+struct result_from_distance<haversine<Point1, Point2, CalculationType> >
+{
+private :
+    typedef haversine<Point1, Point2, CalculationType> this_type;
+public :
+    template <typename T>
+    static inline typename this_type::return_type apply(this_type const& , T const& value)
+    {
+        return  typename this_type::return_type(value);
+    }
+};
 
 
 
-template <typename P1, typename P2>
-struct strategy_tag<strategy::distance::haversine<P1, P2> >
+// Specializations for comparable::haversine
+template <typename Point1, typename Point2, typename CalculationType>
+struct tag<comparable::haversine<Point1, Point2, CalculationType> >
 {
     typedef strategy_tag_distance_point_point type;
 };
 
 
+template <typename Point1, typename Point2, typename CalculationType, typename P1, typename P2>
+struct similar_type<comparable::haversine<Point1, Point2, CalculationType>, P1, P2>
+{
+    typedef comparable::haversine<P1, P2, CalculationType> type;
+};
 
 
-#endif
+template <typename Point1, typename Point2, typename CalculationType, typename P1, typename P2>
+struct get_similar<comparable::haversine<Point1, Point2, CalculationType>, P1, P2>
+{
+private :
+    typedef comparable::haversine<Point1, Point2, CalculationType> this_type;
+public :
+    static inline typename similar_type<this_type, P1, P2>::type apply(this_type const& input)
+    {
+        return comparable::haversine<P1, P2, CalculationType>(input.radius());
+    }
+};
 
+template <typename Point1, typename Point2, typename CalculationType>
+struct comparable_type<comparable::haversine<Point1, Point2, CalculationType> >
+{
+    typedef comparable::haversine<Point1, Point2, CalculationType> type;
+};
 
 
+template <typename Point1, typename Point2, typename CalculationType>
+struct get_comparable<comparable::haversine<Point1, Point2, CalculationType> >
+{
+private :
+    typedef comparable::haversine<Point1, Point2, CalculationType> this_type;
+public :
+    static inline this_type apply(this_type const& input)
+    {
+        return input;
+    }
+};
+
+
+template <typename Point1, typename Point2, typename CalculationType>
+struct result_from_distance<comparable::haversine<Point1, Point2, CalculationType> >
+{
+private :
+    typedef comparable::haversine<Point1, Point2, CalculationType> strategy_type;
+    typedef typename strategy_type::return_type return_type;
+public :
+    template <typename T>
+    static inline return_type apply(strategy_type const& strategy, T const& distance)
+    {
+        return_type const s = sin((distance / strategy.radius()) / return_type(2));
+        return s * s;
+    }
+};
+
+
+} // namespace services
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+
+
+}} // namespace strategy::distance
+
+
+#ifndef DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
+template <typename Point1, typename Point2>
+struct strategy_distance<spherical_tag, spherical_tag, Point1, Point2>
+{
+    typedef strategy::distance::haversine<Point1, Point2> type;
+};
+
+
+template <typename Point1, typename Point2>
+struct strategy_tag<strategy::distance::haversine<Point1, Point2> >
+{
+    typedef strategy_tag_distance_point_point type;
+};
+
+template <typename Point1, typename Point2>
+struct strategy_tag<strategy::distance::comparable::haversine<Point1, Point2> >
+{
+    typedef strategy_tag_distance_point_point type;
+};
+
 
+#endif // DOXYGEN_NO_STRATEGY_SPECIALIZATIONS
 
 
 }} // namespace boost::geometry
Added: sandbox/geometry/boost/geometry/util/promote_floating_point.hpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/boost/geometry/util/promote_floating_point.hpp	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -0,0 +1,44 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library)
+//
+// Copyright Barend Gehrels 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_UTIL_PROMOTE_FLOATING_POINT_HPP
+#define BOOST_GEOMETRY_UTIL_PROMOTE_FLOATING_POINT_HPP
+
+
+#include <boost/mpl/if.hpp>
+#include <boost/type_traits.hpp>
+
+
+namespace boost { namespace geometry
+{
+
+
+/*!
+    \brief Meta-function converting, if necessary, to "a floating point" type
+    \details
+        - if input type is integer, type is double
+        - else type is input type
+    \ingroup utility
+ */
+
+template <typename T, typename PromoteIntegerTo = double>
+struct promote_floating_point
+{
+    typedef typename
+        boost::mpl::if_
+        <
+            boost::is_integral<T>,
+            PromoteIntegerTo,
+            T
+        >::type type;
+};
+
+
+}} // namespace boost::geometry
+
+
+#endif // BOOST_GEOMETRY_UTIL_PROMOTE_FLOATING_POINT_HPP
Modified: sandbox/geometry/libs/geometry/example/c01_custom_point_example.cpp
==============================================================================
--- sandbox/geometry/libs/geometry/example/c01_custom_point_example.cpp	(original)
+++ sandbox/geometry/libs/geometry/example/c01_custom_point_example.cpp	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -70,6 +70,17 @@
     double m_x, m_y;
 };
 
+// Sample point within a namespace
+namespace my
+{
+    struct my_namespaced_point
+    {
+        double x, y;
+    };
+}
+
+
+
 BOOST_GEOMETRY_REGISTER_POINT_3D(my_color_point, double, cs::cartesian, red, green, blue)
 BOOST_GEOMETRY_REGISTER_POINT_3D(my_array_point, int, cs::cartesian, c[0], c[1], c[2])
 BOOST_GEOMETRY_REGISTER_POINT_2D(my_2d, float, cs::cartesian, x, y)
@@ -77,6 +88,9 @@
 BOOST_GEOMETRY_REGISTER_POINT_2D(my_class_rw, double, cs::cartesian, x(), y())
 BOOST_GEOMETRY_REGISTER_POINT_2D_GET_SET(my_class_gs, double, cs::cartesian, get_x, get_y, set_x, set_y)
 
+BOOST_GEOMETRY_REGISTER_POINT_2D(my::my_namespaced_point, double, cs::cartesian, x, y)
+
+
 int main()
 {
     // Create 2 instances of our custom color point
@@ -132,5 +146,13 @@
         << boost::geometry::dsv(crw2) << " is "
         << boost::geometry::distance(cgs1,cgs2) << std::endl;
 
+    my::my_namespaced_point nsp1 = boost::geometry::make<my::my_namespaced_point>(1, 2);
+    my::my_namespaced_point nsp2 = boost::geometry::make<my::my_namespaced_point>(3, 4);
+    std::cout << "namespaced distance "
+        << boost::geometry::dsv(nsp1) << " to "
+        << boost::geometry::dsv(nsp2) << " is "
+        << boost::geometry::distance(nsp1,nsp2) << std::endl;
+
+
     return 0;
 }
Modified: sandbox/geometry/libs/geometry/test/algorithms/algorithms_tests.sln
==============================================================================
--- sandbox/geometry/libs/geometry/test/algorithms/algorithms_tests.sln	(original)
+++ sandbox/geometry/libs/geometry/test/algorithms/algorithms_tests.sln	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -58,6 +58,8 @@
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "dissolve", "dissolve.vcproj", "{206F83D5-17F9-4856-A1DE-82301DB94439}"
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "comparable_distance", "comparable_distance.vcproj", "{F11970B5-BE16-4FF5-9780-4C15082B76A0}"
+EndProject
 Global
         GlobalSection(SolutionConfigurationPlatforms) = preSolution
                 Debug|Win32 = Debug|Win32
@@ -180,6 +182,10 @@
                 {206F83D5-17F9-4856-A1DE-82301DB94439}.Debug|Win32.Build.0 = Debug|Win32
                 {206F83D5-17F9-4856-A1DE-82301DB94439}.Release|Win32.ActiveCfg = Release|Win32
                 {206F83D5-17F9-4856-A1DE-82301DB94439}.Release|Win32.Build.0 = Release|Win32
+		{F11970B5-BE16-4FF5-9780-4C15082B76A0}.Debug|Win32.ActiveCfg = Debug|Win32
+		{F11970B5-BE16-4FF5-9780-4C15082B76A0}.Debug|Win32.Build.0 = Debug|Win32
+		{F11970B5-BE16-4FF5-9780-4C15082B76A0}.Release|Win32.ActiveCfg = Release|Win32
+		{F11970B5-BE16-4FF5-9780-4C15082B76A0}.Release|Win32.Build.0 = Release|Win32
         EndGlobalSection
         GlobalSection(SolutionProperties) = preSolution
                 HideSolutionNode = FALSE
Added: sandbox/geometry/libs/geometry/test/algorithms/comparable_distance.cpp
==============================================================================
--- (empty file)
+++ sandbox/geometry/libs/geometry/test/algorithms/comparable_distance.cpp	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -0,0 +1,138 @@
+// Boost.Geometry (aka GGL, Generic Geometry Library) test file
+//
+// Copyright Barend Gehrels 2007-2009, Geodan, Amsterdam, the Netherlands
+// Copyright Bruno Lalande 2008, 2009
+// 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)
+
+
+#include <sstream>
+
+#include <boost/mpl/if.hpp>
+#include <geometry_test_common.hpp>
+
+#include <boost/geometry/geometry.hpp>
+
+#include <boost/geometry/geometries/point_xy.hpp>
+#include <boost/geometry/geometries/linestring.hpp>
+
+#include <boost/geometry/algorithms/comparable_distance.hpp>
+#include <boost/geometry/strategies/strategies.hpp>
+
+
+#include <boost/geometry/geometries/geometries.hpp>
+
+namespace bg = boost::geometry;
+
+template <typename P>
+void test_distance_result()
+{
+    typedef typename bg::distance_result<P, P>::type distance_type;
+
+    P p1 = bg::make<P>(0, 0);
+    P p2 = bg::make<P>(3, 0);
+    P p3 = bg::make<P>(0, 4);
+
+    distance_type dr12 = bg::comparable_distance(p1, p2);
+    distance_type dr13 = bg::comparable_distance(p1, p3);
+    distance_type dr23 = bg::comparable_distance(p2, p3);
+
+    BOOST_CHECK_CLOSE(double(dr12), 9.000, 0.001);
+    BOOST_CHECK_CLOSE(double(dr13), 16.000, 0.001);
+    BOOST_CHECK_CLOSE(double(dr23), 25.000, 0.001);
+
+}
+
+template <typename P>
+void test_distance_point()
+{
+    P p1;
+    bg::set<0>(p1, 1);
+    bg::set<1>(p1, 1);
+
+    P p2;
+    bg::set<0>(p2, 2);
+    bg::set<1>(p2, 2);
+
+    double d = bg::comparable_distance(p1, p2);
+    BOOST_CHECK_CLOSE(d, 2.0, 0.001);
+}
+
+template <typename P>
+void test_distance_segment()
+{
+    typedef typename bg::coordinate_type<P>::type coordinate_type;
+
+    P s1 = bg::make<P>(2, 2);
+    P s2 = bg::make<P>(3, 3);
+
+    // Check points left, right, projected-left, projected-right, on segment
+    P p1 = bg::make<P>(0, 0);
+    P p2 = bg::make<P>(4, 4);
+    P p3 = bg::make<P>(2.4, 2.6);
+    P p4 = bg::make<P>(2.6, 2.4);
+    P p5 = bg::make<P>(2.5, 2.5);
+
+    bg::segment<P const> const seg(s1, s2);
+
+    double d1 = bg::comparable_distance(p1, seg); BOOST_CHECK_CLOSE(d1, 2.0, 0.001);
+    double d2 = bg::comparable_distance(p2, seg); BOOST_CHECK_CLOSE(d2, 1.0, 0.001);
+    double d3 = bg::comparable_distance(p3, seg); BOOST_CHECK_CLOSE(d3, 0.02, 0.001);
+    double d4 = bg::comparable_distance(p4, seg); BOOST_CHECK_CLOSE(d4, 0.02, 0.001);
+    double d5 = bg::comparable_distance(p5, seg); BOOST_CHECK_CLOSE(d5, 0.0, 0.001);
+
+    // Reverse case
+    double dr1 = bg::comparable_distance(seg, p1); BOOST_CHECK_CLOSE(dr1, d1, 0.001);
+    double dr2 = bg::comparable_distance(seg, p2); BOOST_CHECK_CLOSE(dr2, d2, 0.001);
+}
+
+template <typename P>
+void test_distance_linestring()
+{
+    bg::linestring<P> points;
+    points.push_back(bg::make<P>(1, 1));
+    points.push_back(bg::make<P>(3, 3));
+
+    P p = bg::make<P>(2, 1);
+
+    double d = bg::comparable_distance(p, points);
+    BOOST_CHECK_CLOSE(d, 0.70710678, 0.001);
+
+    p = bg::make<P>(5, 5);
+    d = bg::comparable_distance(p, points);
+    BOOST_CHECK_CLOSE(d, 2.828427, 0.001);
+
+
+    bg::linestring<P> line;
+    line.push_back(bg::make<P>(1,1));
+    line.push_back(bg::make<P>(2,2));
+    line.push_back(bg::make<P>(3,3));
+
+    p = bg::make<P>(5, 5);
+
+    d = bg::comparable_distance(p, line);
+    BOOST_CHECK_CLOSE(d, 2.828427, 0.001);
+
+    // Reverse case
+    d = bg::comparable_distance(line, p);
+    BOOST_CHECK_CLOSE(d, 2.828427, 0.001);
+}
+
+template <typename P>
+void test_all()
+{
+    test_distance_result<P>();
+    test_distance_point<P>();
+    test_distance_segment<P>();
+    test_distance_linestring<P>();
+}
+
+int test_main(int, char* [])
+{
+    //test_all<bg::point_xy<int> >();
+    test_all<bg::point_xy<float> >();
+    test_all<bg::point_xy<double> >();
+
+    return 0;
+}
Added: sandbox/geometry/libs/geometry/test/algorithms/comparable_distance.vcproj
==============================================================================
--- (empty file)
+++ sandbox/geometry/libs/geometry/test/algorithms/comparable_distance.vcproj	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -0,0 +1,174 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="comparable_distance"
+	ProjectGUID="{F11970B5-BE16-4FF5-9780-4C15082B76A0}"
+	RootNamespace="comparable_distance"
+	Keyword="Win32Proj"
+	>
+	<Platforms>
+		<Platform
+			Name="Win32"
+		/>
+	</Platforms>
+	<ToolFiles>
+	</ToolFiles>
+	<Configurations>
+		<Configuration
+			Name="Debug|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)\comparable_distance"
+			ConfigurationType="1"
+			InheritedPropertySheets="..\boost.vsprops"
+			CharacterSet="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="0"
+				AdditionalIncludeDirectories="../../../..;.."
+				PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+				ExceptionHandling="2"
+				RuntimeLibrary="1"
+				UsePrecompiledHeader="0"
+				DebugInformationFormat="1"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				GenerateDebugInformation="true"
+				SubSystem="1"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+		<Configuration
+			Name="Release|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)\comparable_distance"
+			ConfigurationType="1"
+			InheritedPropertySheets="..\boost.vsprops"
+			CharacterSet="1"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				AdditionalIncludeDirectories="../../../..;.."
+				PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+				ExceptionHandling="2"
+				UsePrecompiledHeader="0"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				SubSystem="1"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
+	</Configurations>
+	<References>
+	</References>
+	<Files>
+		<File
+			RelativePath=".\comparable_distance.cpp"
+			>
+		</File>
+	</Files>
+	<Globals>
+	</Globals>
+</VisualStudioProject>
Modified: sandbox/geometry/libs/geometry/test/algorithms/distance.cpp
==============================================================================
--- sandbox/geometry/libs/geometry/test/algorithms/distance.cpp	(original)
+++ sandbox/geometry/libs/geometry/test/algorithms/distance.cpp	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -52,26 +52,34 @@
     BOOST_CHECK_CLOSE(double(dr13), 4.000, 0.001);
     BOOST_CHECK_CLOSE(double(dr23), 5.000, 0.001);
 
-    // COMPILATION TESTS
-    distance_type comparable = boost::geometry::make_distance_result<distance_type>(3);
-    //BOOST_CHECK_CLOSE(comparable.value(), 9.000, 0.001);
-
-
-    // Question: how to check if the implemented operator is used, and not the auto-conversion to double?
-    if (comparable == dr12) {};
-    if (comparable < dr12) {};
-    if (comparable > dr12) {};
-
-    // Check streamability
-    std::ostringstream s;
-    s << comparable;
-
-    // Check comparisons with plain double
-    double d = 3.0;
-    if (dr12 == d) {};
-    if (dr12 < d) {};
-    if (dr12 > d) {};
+    // COMPARABLE TESTS
+    {
+        namespace services = boost::geometry::strategy::distance::services;
+
+        typedef typename boost::geometry::default_distance_strategy<P>::type strategy_type;
+        typedef typename services::comparable_type<strategy_type>::type comparable_strategy_type;
 
+        strategy_type strategy;
+        comparable_strategy_type comparable_strategy = services::get_comparable<strategy_type>::apply(strategy);
+        distance_type comparable = services::result_from_distance<comparable_strategy_type>::apply(comparable_strategy, 3);
+
+        BOOST_CHECK_CLOSE(comparable, 9.000, 0.001);
+
+        // COMPILATION TESTS (probably obsolete...)
+        if (comparable == dr12) {};
+        if (comparable < dr12) {};
+        if (comparable > dr12) {};
+
+        // Check streamability
+        std::ostringstream s;
+        s << comparable;
+
+        // Check comparisons with plain double
+        double d = 3.0;
+        if (dr12 == d) {};
+        if (dr12 < d) {};
+        if (dr12 > d) {};
+    }
 }
 
 template <typename P>
@@ -180,22 +188,22 @@
 {
     test_distance_result<P>();
     test_distance_point<P>();
-    test_distance_segment<P>();
+//    test_distance_segment<P>();
 #ifndef TEST_ARRAY
-    test_distance_linestring<P>();
+    //test_distance_linestring<P>();
 #endif
 }
 
 int test_main(int, char* [])
 {
 #ifdef TEST_ARRAY
-    //test_all<int[2]>();
+    test_all<int[2]>();
     test_all<float[2]>();
     test_all<double[2]>();
     test_all<test::test_point>(); // located here because of 3D
 #endif
 
-    //test_all<boost::geometry::point_xy<int> >();
+    test_all<boost::geometry::point_xy<int> >();
     test_all<boost::tuple<float, float> >();
     test_all<boost::geometry::point_xy<float> >();
     test_all<boost::geometry::point_xy<double> >();
Modified: sandbox/geometry/libs/geometry/test/algorithms/intersection.cpp
==============================================================================
--- sandbox/geometry/libs/geometry/test/algorithms/intersection.cpp	(original)
+++ sandbox/geometry/libs/geometry/test/algorithms/intersection.cpp	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -29,6 +29,11 @@
 
     std::string clip = "box(2 2,8 8)";
 
+    test_one<polygon, polygon, polygon>("simplex_normal",
+        simplex_normal[0], simplex_normal[1],
+        1, 7, 5.47363293);
+
+
     // Basic check: box/linestring, is clipping OK? should compile in any order
     test_one<linestring, linestring, box>("llb", "LINESTRING(0 0,10 10)", clip, 1, 2, sqrt(2.0 * 6.0 * 6.0));
     test_one<linestring, box, linestring>("lbl", clip, "LINESTRING(0 0,10 10)", 1, 2, sqrt(2.0 * 6.0 * 6.0));
Modified: sandbox/geometry/libs/geometry/test/algorithms/overlaps.cpp
==============================================================================
--- sandbox/geometry/libs/geometry/test/algorithms/overlaps.cpp	(original)
+++ sandbox/geometry/libs/geometry/test/algorithms/overlaps.cpp	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -20,6 +20,10 @@
 template <typename P>
 void test_2d()
 {
+#if defined(BOOST_GEOMETRY_COMPILE_FAIL)
+    test_geometry<P, P>("POINT(1 1)", "POINT(1 1)", true);
+#endif
+
     test_geometry<boost::geometry::box<P>, boost::geometry::box<P> >("BOX(1 1, 3 3)", "BOX(0 0,2 2)", true);
 
     // touch -> false
Modified: sandbox/geometry/libs/geometry/test/algorithms/simplify.cpp
==============================================================================
--- sandbox/geometry/libs/geometry/test/algorithms/simplify.cpp	(original)
+++ sandbox/geometry/libs/geometry/test/algorithms/simplify.cpp	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -77,7 +77,7 @@
 {
     // Integer compiles, but simplify-process fails (due to distances)
     //test_all<boost::geometry::point_xy<int> >();
-    //test_all<boost::geometry::point_xy<float> >();
+    test_all<boost::geometry::point_xy<float> >();
     test_all<boost::geometry::point_xy<double> >();
 
     test_spherical<boost::geometry::point<double, 2, boost::geometry::cs::spherical<boost::geometry::degree> > >();
Modified: sandbox/geometry/libs/geometry/test/algorithms/simplify.vcproj
==============================================================================
--- sandbox/geometry/libs/geometry/test/algorithms/simplify.vcproj	(original)
+++ sandbox/geometry/libs/geometry/test/algorithms/simplify.vcproj	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -6,7 +6,6 @@
         ProjectGUID="{B1760CB8-553B-42AB-B54E-3D0320FF252F}"
         RootNamespace="simplify"
         Keyword="Win32Proj"
-	TargetFrameworkVersion="131072"
 	>
         <Platforms>
                 <Platform
@@ -44,8 +43,8 @@
                                 Optimization="0"
                                 AdditionalIncludeDirectories="../../../..;.."
                                 PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
-				RuntimeLibrary="1"
                                 ExceptionHandling="2"
+				RuntimeLibrary="1"
                                 UsePrecompiledHeader="0"
                                 DebugInformationFormat="1"
                         />
@@ -83,6 +82,9 @@
                                 Name="VCAppVerifierTool"
                         />
                         <Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
                                 Name="VCPostBuildEventTool"
                         />
                 </Configuration>
@@ -152,6 +154,9 @@
                                 Name="VCAppVerifierTool"
                         />
                         <Tool
+				Name="VCWebDeploymentTool"
+			/>
+			<Tool
                                 Name="VCPostBuildEventTool"
                         />
                 </Configuration>
Modified: sandbox/geometry/libs/geometry/test/extensions/gis/latlong/andoyer.cpp
==============================================================================
--- sandbox/geometry/libs/geometry/test/extensions/gis/latlong/andoyer.cpp	(original)
+++ sandbox/geometry/libs/geometry/test/extensions/gis/latlong/andoyer.cpp	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -9,6 +9,8 @@
 
 #include <geometry_test_common.hpp>
 
+#include <boost/concept_check.hpp>
+
 #include <boost/geometry/extensions/gis/geographic/strategies/andoyer.hpp>
 
 #include <boost/geometry/strategies/strategies.hpp>
@@ -20,7 +22,12 @@
 template <typename P1, typename P2>
 void test_andoyer(double lon1, double lat1, double lon2, double lat2, double expected_km)
 {
-    boost::geometry::strategy::distance::andoyer<P1, P2> andoyer;
+    typedef boost::geometry::strategy::distance::andoyer<P1, P2> andoyer_type;
+
+    BOOST_CONCEPT_ASSERT( (boost::geometry::concept::PointDistanceStrategy<andoyer_type>) );
+
+    andoyer_type andoyer;
+
 
     P1 p1, p2;
 
Modified: sandbox/geometry/libs/geometry/test/extensions/gis/latlong/latlong.sln
==============================================================================
--- sandbox/geometry/libs/geometry/test/extensions/gis/latlong/latlong.sln	(original)
+++ sandbox/geometry/libs/geometry/test/extensions/gis/latlong/latlong.sln	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -13,6 +13,8 @@
 EndProject
 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "parse", "parse.vcproj", "{38C7173B-F81D-427D-B236-57611A31656A}"
 EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "vincenty", "vincenty.vcproj", "{F4A5BE68-7213-498D-944B-023B50FB10FD}"
+EndProject
 Global
         GlobalSection(SolutionConfigurationPlatforms) = preSolution
                 Debug|Win32 = Debug|Win32
@@ -43,6 +45,10 @@
                 {38C7173B-F81D-427D-B236-57611A31656A}.Debug|Win32.Build.0 = Debug|Win32
                 {38C7173B-F81D-427D-B236-57611A31656A}.Release|Win32.ActiveCfg = Release|Win32
                 {38C7173B-F81D-427D-B236-57611A31656A}.Release|Win32.Build.0 = Release|Win32
+		{F4A5BE68-7213-498D-944B-023B50FB10FD}.Debug|Win32.ActiveCfg = Debug|Win32
+		{F4A5BE68-7213-498D-944B-023B50FB10FD}.Debug|Win32.Build.0 = Debug|Win32
+		{F4A5BE68-7213-498D-944B-023B50FB10FD}.Release|Win32.ActiveCfg = Release|Win32
+		{F4A5BE68-7213-498D-944B-023B50FB10FD}.Release|Win32.Build.0 = Release|Win32
         EndGlobalSection
         GlobalSection(SolutionProperties) = preSolution
                 HideSolutionNode = FALSE
Modified: sandbox/geometry/libs/geometry/test/strategies/cross_track.cpp
==============================================================================
--- sandbox/geometry/libs/geometry/test/strategies/cross_track.cpp	(original)
+++ sandbox/geometry/libs/geometry/test/strategies/cross_track.cpp	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -9,6 +9,7 @@
 
 #include <geometry_test_common.hpp>
 
+
 #include <boost/geometry/algorithms/assign.hpp>
 
 #include <boost/geometry/strategies/spherical/distance_haversine.hpp>
@@ -19,6 +20,10 @@
 #include <boost/geometry/geometries/point.hpp>
 #include <boost/geometry/geometries/segment.hpp>
 
+#ifdef HAVE_TTMATH
+#  include <boost/geometry/extensions/contrib/ttmath_stub.hpp>
+#endif
+
 
 template <typename Point>
 void test_distance(double lon1, double lat1,
@@ -31,6 +36,8 @@
             Point,
             Point
         > strategy_type;
+    typedef typename strategy_type::return_type return_type;
+
 
 
     BOOST_CONCEPT_ASSERT
@@ -45,9 +52,9 @@
     boost::geometry::assign(p1, lon1, lat1);
     boost::geometry::assign(p2, lon2, lat2);
     boost::geometry::assign(p3, lon3, lat3);
-    typename strategy_type::return_type d = strategy.apply(p1, p2, p3);
+    return_type d = strategy.apply(p1, p2, p3);
 
-    BOOST_CHECK_CLOSE((double) d, expected, tolerance);
+    BOOST_CHECK_CLOSE(d, return_type(expected), tolerance);
 }
 
 template <typename Point>
@@ -63,9 +70,17 @@
     test_distance<Point>(2, 48, 2, 41, 4, 52, average_earth_radius, p_to_ab, 1.0);
 }
 
+
 int test_main(int, char* [])
 {
     test_all<boost::geometry::point<double, 2, boost::geometry::cs::spherical<boost::geometry::degree> > >();
 
+#if defined(HAVE_TTMATH)
+    typedef ttmath::Big<1,4> tt;
+    test_all<boost::geometry::point<tt, 2, boost::geometry::cs::spherical<boost::geometry::degree> > >();
+#endif
+
+
+
     return 0;
 }
Modified: sandbox/geometry/libs/geometry/test/strategies/cross_track.vcproj
==============================================================================
--- sandbox/geometry/libs/geometry/test/strategies/cross_track.vcproj	(original)
+++ sandbox/geometry/libs/geometry/test/strategies/cross_track.vcproj	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -20,7 +20,7 @@
                         OutputDirectory="$(SolutionDir)$(ConfigurationName)"
                         IntermediateDirectory="$(ConfigurationName)\cross_track"
                         ConfigurationType="1"
-			InheritedPropertySheets="..\boost.vsprops"
+			InheritedPropertySheets="..\boost.vsprops;..\ttmath.vsprops"
                         CharacterSet="1"
 			>
                         <Tool
@@ -93,7 +93,7 @@
                         OutputDirectory="$(SolutionDir)$(ConfigurationName)"
                         IntermediateDirectory="$(ConfigurationName)\cross_track"
                         ConfigurationType="1"
-			InheritedPropertySheets="..\boost.vsprops"
+			InheritedPropertySheets="..\boost.vsprops;..\ttmath.vsprops"
                         CharacterSet="1"
                         WholeProgramOptimization="1"
 			>
Modified: sandbox/geometry/libs/geometry/test/strategies/haversine.cpp
==============================================================================
--- sandbox/geometry/libs/geometry/test/strategies/haversine.cpp	(original)
+++ sandbox/geometry/libs/geometry/test/strategies/haversine.cpp	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -19,47 +19,59 @@
 
 #include <boost/geometry/geometries/point.hpp>
 
+#ifdef HAVE_TTMATH
+#  include <boost/geometry/extensions/contrib/ttmath_stub.hpp>
+#endif
+
+namespace bg = boost::geometry;
+
+
+double const average_earth_radius = 6372795.0;
+
 
 template <typename Point>
 struct test_distance
 {
-    typedef boost::geometry::strategy::distance::haversine
+    typedef bg::strategy::distance::haversine
         <
             Point,
             Point
         > haversine_type;
 
+    BOOST_CONCEPT_ASSERT( (boost::geometry::concept::PointDistanceStrategy<haversine_type>) );
+
+
+    typedef typename haversine_type::return_type return_type;
 
     BOOST_CONCEPT_ASSERT
         (
-            (boost::geometry::concept::PointDistanceStrategy<haversine_type>)
+            (bg::concept::PointDistanceStrategy<haversine_type>)
         );
 
 
     static void test(double lon1, double lat1, double lon2, double lat2,
-                       double radius, double expected, double tolerance)
+                       double radius, return_type expected, double tolerance)
     {
         haversine_type strategy(radius);
 
         Point p1, p2;
-        boost::geometry::assign(p1, lon1, lat1);
-        boost::geometry::assign(p2, lon2, lat2);
-        typename haversine_type::return_type d1 = strategy.apply(p1, p2);
+        bg::assign(p1, lon1, lat1);
+        bg::assign(p2, lon2, lat2);
+        return_type d = strategy.apply(p1, p2);
 
-        BOOST_CHECK_CLOSE((double) d1, expected, tolerance);
+        BOOST_CHECK_CLOSE(d, expected, tolerance);
     }
 };
 
 template <typename Point>
 void test_all()
 {
-    double const average_earth_radius = 6372795.0;
 
     // earth to unit-sphere -> divide by earth circumference, then it is from 0-1,
     // then multiply with 2 PI, so effectively just divide by earth radius
     double e2u = 1.0 / average_earth_radius;
 
-    // ~ Amsterdam/Paris
+    // ~ Amsterdam/Paris, 467 kilometers
     double const a_p = 467.2704 * 1000.0;
     test_distance<Point>::test(4, 52, 2, 48, average_earth_radius, a_p, 1.0);
     test_distance<Point>::test(2, 48, 4, 52, average_earth_radius, a_p, 1.0);
@@ -73,9 +85,177 @@
 }
 
 
+template <typename P1, typename P2, typename CalculationType>
+void test_services()
+{
+    P1 p1;
+    bg::assign(p1, 4, 52);
+
+    P2 p2;
+    bg::assign(p2, 2, 48);
+
+    // ~ Amsterdam/Paris, 467 kilometers
+    double const km = 1000.0;
+    double const a_p = 467.2704 * km;
+    double const expected = a_p;
+
+    double const expected_lower = 460.0 * km;
+    double const expected_higher = 470.0 * km;
+
+
+
+    namespace bgsd = bg::strategy::distance;
+    namespace services = bg::strategy::distance::services;
+    // 1: normal, calculate distance:
+
+    typedef bgsd::haversine<P1, P2, CalculationType> strategy_type;
+    typedef typename strategy_type::return_type return_type;
+
+    strategy_type strategy(average_earth_radius);
+    return_type result = strategy.apply(p1, p2);
+    BOOST_CHECK_CLOSE(result, return_type(expected), 0.001);
+
+    // 2: "similar" to construct a similar strategy (similar but with other template-parameters) for, e.g., the reverse P2/P1
+    // 2a: similar_type:
+    typedef typename services::similar_type<strategy_type, P2, P1>::type similar_type;
+    // 2b: get_similar
+    similar_type similar = services::get_similar<strategy_type, P2, P1>::apply(strategy);
+
+    //result = similar.apply(p1, p2); // should NOT compile because p1/p2 should also be reversed here
+    result = similar.apply(p2, p1);
+    BOOST_CHECK_CLOSE(result, return_type(expected), 0.001);
+
+
+    // 3: "comparable" to construct a "comparable strategy" for P1/P2
+    //    a "comparable strategy" is a strategy which does not calculate the exact distance, but 
+    //    which returns results which can be mutually compared (e.g. avoid sqrt)
+
+    // 3a: "comparable_type"
+    typedef typename services::comparable_type<strategy_type>::type comparable_type;
+
+    // 3b: "get_comparable"
+    comparable_type comparable = bgsd::services::get_comparable<strategy_type>::apply(strategy);
+
+    // Check vice versa:
+    // First the result of the comparable strategy
+    return_type c_result = comparable.apply(p1, p2);
+    // Second the comparable result of the expected distance
+    return_type c_expected = services::result_from_distance<comparable_type>::apply(comparable, expected);
+    // And that one should be equa.
+    BOOST_CHECK_CLOSE(c_result, return_type(c_expected), 0.001);
+
+    // 4: the comparable_type should have a distance_strategy_constructor as well, 
+    //    knowing how to compare something with a fixed distance
+    return_type c_dist_lower = services::result_from_distance<comparable_type>::apply(comparable, expected_lower);
+    return_type c_dist_higher = services::result_from_distance<comparable_type>::apply(comparable, expected_higher);
+
+    // If this is the case:
+    BOOST_CHECK(c_dist_lower < c_result && c_result < c_dist_higher);
+
+    // Calculate the Haversine by hand here:
+    return_type c_check = return_type(2.0) * asin(sqrt(c_result)) * average_earth_radius;
+    BOOST_CHECK_CLOSE(c_check, expected, 0.001);
+
+    // This should also be the case
+    return_type dist_lower = services::result_from_distance<strategy_type>::apply(strategy, expected_lower);
+    return_type dist_higher = services::result_from_distance<strategy_type>::apply(strategy, expected_higher);
+    BOOST_CHECK(dist_lower < result && result < dist_higher);
+}
+
+template <typename P, typename Strategy>
+void time_compare_s(int const n)
+{
+    boost::timer t;
+    P p1, p2;
+    bg::assign(p1, 1, 1);
+    bg::assign(p2, 2, 2);
+    Strategy strategy;
+    typename Strategy::return_type s = 0;
+    for (int i = 0; i < n; i++)
+    {
+        for (int j = 0; j < n; j++)
+        {
+            s += strategy.apply(p1, p2);
+        }
+    }
+    std::cout << "s: " << s << " t: " << t.elapsed() << std::endl;
+}
+
+template <typename P>
+void time_compare(int const n)
+{
+    time_compare_s<P, bg::strategy::distance::haversine<P> >(n);
+    time_compare_s<P, bg::strategy::distance::comparable::haversine<P> >(n);
+}
+
+#include <time.h>
+double time_sqrt(int n)
+{
+    clock_t start = clock();
+
+    double v = 2.0;
+    double s = 0.0;
+    for (int i = 0; i < n; i++)
+    {
+        for (int j = 0; j < n; j++)
+        {
+            s += sqrt(v);
+            v += 1.0e-10;
+        }
+    }
+    clock_t end = clock();
+    double diff = double(end - start) / CLOCKS_PER_SEC;
+
+    std::cout << "Check: " << s << " Time: " << diff << std::endl;
+    return diff;
+}
+
+double time_normal(int n)
+{
+    clock_t start = clock();
+
+    double v = 2.0;
+    double s = 0.0;
+    for (int i = 0; i < n; i++)
+    {
+        for (int j = 0; j < n; j++)
+        {
+            s += v;
+            v += 1.0e-10;
+        }
+    }
+    clock_t end = clock();
+    double diff = double(end - start) / CLOCKS_PER_SEC;
+
+    std::cout << "Check: " << s << " Time: " << diff << std::endl;
+    return diff;
+}
+
+
 int test_main(int, char* [])
 {
-    test_all<boost::geometry::point<double, 2, boost::geometry::cs::spherical<boost::geometry::degree> > >();
+    namespace bg = boost::geometry;
+    test_all<bg::point<int, 2, bg::cs::spherical<bg::degree> > >();
+    test_all<bg::point<float, 2, bg::cs::spherical<bg::degree> > >();
+    test_all<bg::point<double, 2, bg::cs::spherical<bg::degree> > >();
+
+    double t1 = time_sqrt(20000);
+    double t2 = time_normal(20000);
+    std::cout << "Factor: " << (t1 / t2) << std::endl;
+    time_compare<bg::point<double, 2, bg::cs::spherical<bg::radian> > >(10000);
+
+#if defined(HAVE_TTMATH)
+    typedef ttmath::Big<1,4> tt;
+    test_all<bg::point<tt, 2, bg::cs::spherical<bg::degree> > >();
+#endif
+
+
+    test_services
+        <
+            bg::point<float, 2, bg::cs::spherical<bg::degree> >,
+            bg::point<double, 2, bg::cs::spherical<bg::degree> >,
+            double
+        >();
 
     return 0;
 }
Modified: sandbox/geometry/libs/geometry/test/strategies/haversine.vcproj
==============================================================================
--- sandbox/geometry/libs/geometry/test/strategies/haversine.vcproj	(original)
+++ sandbox/geometry/libs/geometry/test/strategies/haversine.vcproj	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -20,7 +20,7 @@
                         OutputDirectory="$(SolutionDir)$(ConfigurationName)"
                         IntermediateDirectory="$(ConfigurationName)\haversine"
                         ConfigurationType="1"
-			InheritedPropertySheets="..\boost.vsprops"
+			InheritedPropertySheets="..\boost.vsprops;..\ttmath.vsprops"
                         CharacterSet="1"
 			>
                         <Tool
@@ -93,7 +93,7 @@
                         OutputDirectory="$(SolutionDir)$(ConfigurationName)"
                         IntermediateDirectory="$(ConfigurationName)\haversine"
                         ConfigurationType="1"
-			InheritedPropertySheets="..\boost.vsprops"
+			InheritedPropertySheets="..\boost.vsprops;..\ttmath.vsprops"
                         CharacterSet="1"
                         WholeProgramOptimization="1"
 			>
Modified: sandbox/geometry/libs/geometry/test/strategies/projected_point.cpp
==============================================================================
--- sandbox/geometry/libs/geometry/test/strategies/projected_point.cpp	(original)
+++ sandbox/geometry/libs/geometry/test/strategies/projected_point.cpp	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -20,17 +20,76 @@
 #include <boost/geometry/geometries/adapted/tuple_cartesian.hpp>
 #include <test_common/test_point.hpp>
 
+#ifdef HAVE_TTMATH
+#  include <boost/geometry/extensions/contrib/ttmath_stub.hpp>
+#endif
+
+namespace bg = boost::geometry;
+
+
+template <typename P, typename PS, typename CalculationType>
+void test_services()
+{
+    PS p1, p2;
+    bg::assign(p1, 0, 0);
+    bg::assign(p2, 0, 4);
+
+    P p;
+    bg::assign(p, 2, 0);
+
+    double const sqr_expected = 4; 
+    double const expected = 2;
+
+
+    namespace bgsd = bg::strategy::distance;
+    namespace services = bg::strategy::distance::services;
+    // 1: normal, calculate distance:
+
+    typedef bgsd::projected_point<P, PS, CalculationType> strategy_type;
+
+    BOOST_CONCEPT_ASSERT( (bg::concept::PointSegmentDistanceStrategy<strategy_type>) );
+
+    typedef typename strategy_type::return_type return_type;
+
+    strategy_type strategy;
+    return_type result = strategy.apply(p, p1, p2);
+    BOOST_CHECK_CLOSE(result, return_type(expected), 0.001);
+
+    // 2: "similar" to construct a similar strategy (similar but with other template-parameters) for, e.g., the reverse P2/P1
+    // 2a: similar_type:
+    typedef typename services::similar_type<strategy_type, P, PS>::type similar_type;
+    // 2b: get_similar
+    similar_type similar = services::get_similar<strategy_type, P, PS>::apply(strategy);
+
+    result = similar.apply(p, p1, p2);
+    BOOST_CHECK_CLOSE(result, return_type(expected), 0.001);
+
+
+    // 3: "comparable" to construct a "comparable strategy" for P1/P2
+    //    a "comparable strategy" is a strategy which does not calculate the exact distance, but 
+    //    which returns results which can be mutually compared (e.g. avoid sqrt)
+
+    // 3a: "comparable_type"
+    typedef typename services::comparable_type<strategy_type>::type comparable_type;
+
+    // 3b: "get_comparable"
+    comparable_type comparable = bgsd::services::get_comparable<strategy_type>::apply(strategy);
+
+    return_type c_result = comparable.apply(p, p1, p2);
+    BOOST_CHECK_CLOSE(c_result, return_type(sqr_expected), 0.001);
+}
+
 
 template <typename P1, typename P2>
 void test_all_2d()
 {
     P1 p;
     P2 sp1, sp2;
-    boost::geometry::read_wkt("POINT(1 1)", p);
-    boost::geometry::read_wkt("POINT(0 0)", sp1);
-    boost::geometry::read_wkt("POINT(2 3)", sp2);
+    bg::read_wkt("POINT(1 1)", p);
+    bg::read_wkt("POINT(0 0)", sp1);
+    bg::read_wkt("POINT(2 3)", sp2);
 
-    typedef typename boost::geometry::strategy::distance::projected_point
+    typedef typename bg::strategy::distance::projected_point
         <
             P1,
             P2
@@ -38,61 +97,51 @@
 
     BOOST_CONCEPT_ASSERT
         (
-            (boost::geometry::concept::PointSegmentDistanceStrategy<strategy_type>)
+            (bg::concept::PointSegmentDistanceStrategy<strategy_type>)
         );
 
 
     strategy_type strategy;
-    std::cout << strategy.apply(p, sp1, sp2) << std::endl;
+    typename strategy_type::return_type d = strategy.apply(p, sp1, sp2);
+    BOOST_CHECK_CLOSE(d, 0.27735203958327, 0.001);
 }
 
 
 template <typename P>
 void test_all_2d()
 {
-    using boost::geometry::point;
-    using boost::geometry::cs::cartesian;
+    using bg::point;
+    using bg::cs::cartesian;
 
     //test_all_2d<P, int[2]>();
     //test_all_2d<P, float[2]>();
     //test_all_2d<P, double[2]>();
     //test_all_2d<P, test::test_point>();
-    //test_all_2d<P, point<int, 2, cartesian> >();
-    //test_all_2d<P, point<float, 2, cartesian> >();
+    test_all_2d<P, point<int, 2, cartesian> >();
+    test_all_2d<P, point<float, 2, cartesian> >();
     test_all_2d<P, point<double, 2, cartesian> >();
+    test_all_2d<P, point<long double, 2, cartesian> >();
 }
 
 int test_main(int, char* [])
 {
-    using boost::geometry::point;
-    using boost::geometry::cs::cartesian;
+    using bg::point;
+    using bg::cs::cartesian;
 
-#if ! defined(_MSC_VER)
     test_all_2d<int[2]>();
     test_all_2d<float[2]>();
     test_all_2d<double[2]>();
-#endif
     //test_all_2d<test::test_point>();
 
-#if ! defined(_MSC_VER)
     test_all_2d<point<int, 2, cartesian> >();
-#endif
     test_all_2d<point<float, 2, cartesian> >();
     test_all_2d<point<double, 2, cartesian> >();
 
+    test_services<point<double, 2, cartesian>, point<float, 2, cartesian>, long double>();
 
-#if defined(HAVE_CLN)
-    // combination of CLN with normal types
-    typedef boost::numeric_adaptor::cln_value_type cln_type;
-    typedef point<cln_type, 2, cartesian> cln_point;
-    test_all_2d<cln_point>();
-
-#endif
-#if defined(HAVE_GMP)
-    typedef boost::numeric_adaptor::gmp_value_type gmp_type;
-    typedef point<gmp_type, 2, cartesian> gmp_point;
-    test_all_2d<gmp_point>();
 
+#if defined(HAVE_TTMATH)
+    test_all_2d<point<ttmath_big, 2, cartesian>, point<ttmath_big, 2, cartesian> >();
 #endif
 
     return 0;
Modified: sandbox/geometry/libs/geometry/test/strategies/projected_point.vcproj
==============================================================================
--- sandbox/geometry/libs/geometry/test/strategies/projected_point.vcproj	(original)
+++ sandbox/geometry/libs/geometry/test/strategies/projected_point.vcproj	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -20,7 +20,7 @@
                         OutputDirectory="$(SolutionDir)$(ConfigurationName)"
                         IntermediateDirectory="$(ConfigurationName)\projected_point"
                         ConfigurationType="1"
-			InheritedPropertySheets="..\boost.vsprops"
+			InheritedPropertySheets="..\boost.vsprops;..\ttmath.vsprops"
                         CharacterSet="1"
 			>
                         <Tool
@@ -93,7 +93,7 @@
                         OutputDirectory="$(SolutionDir)$(ConfigurationName)"
                         IntermediateDirectory="$(ConfigurationName)\projected_point"
                         ConfigurationType="1"
-			InheritedPropertySheets="..\boost.vsprops"
+			InheritedPropertySheets="..\boost.vsprops;..\ttmath.vsprops"
                         CharacterSet="1"
                         WholeProgramOptimization="1"
 			>
Modified: sandbox/geometry/libs/geometry/test/strategies/pythagoras.cpp
==============================================================================
--- sandbox/geometry/libs/geometry/test/strategies/pythagoras.cpp	(original)
+++ sandbox/geometry/libs/geometry/test/strategies/pythagoras.cpp	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -9,68 +9,176 @@
 
 #include <geometry_test_common.hpp>
 
+#if defined(_MSC_VER)
+#  pragma warning( disable : 4101 )
+#endif
+
+#include <boost/timer.hpp>
+
+#include <boost/concept/requires.hpp>
+#include <boost/concept_check.hpp>
+
 #include <boost/geometry/algorithms/assign.hpp>
 #include <boost/geometry/strategies/cartesian/distance_pythagoras.hpp>
+#include <boost/geometry/strategies/concepts/distance_concept.hpp>
 
 
 #include <boost/geometry/geometries/point.hpp>
 #include <boost/geometry/geometries/adapted/c_array_cartesian.hpp>
 #include <boost/geometry/geometries/adapted/tuple_cartesian.hpp>
+
 #include <test_common/test_point.hpp>
 
+#ifdef HAVE_TTMATH
+#  include <boost/geometry/extensions/contrib/ttmath_stub.hpp>
+#endif
+
+
+namespace bg = boost::geometry;
+
 template <typename P1, typename P2>
 void test_null_distance_3d()
 {
-    typename boost::geometry::strategy::distance::pythagoras<P1, P2> pythagoras;
-
     P1 p1;
-    boost::geometry::assign(p1, 1, 2, 3);
+    bg::assign(p1, 1, 2, 3);
     P2 p2;
-    boost::geometry::assign(p2, 1, 2, 3);
-    BOOST_CHECK_EQUAL(double(
-            typename boost::geometry::coordinate_type<P1>::type(pythagoras.apply(p1, p2))), 0);
+    bg::assign(p2, 1, 2, 3);
+
+    typedef bg::strategy::distance::pythagoras<P1, P2> pythagoras_type;
+    typedef typename pythagoras_type::return_type return_type;
+
+    pythagoras_type pythagoras;
+    return_type result = pythagoras.apply(p1, p2);
+
+    BOOST_CHECK_EQUAL(result, return_type(0));
 }
 
 template <typename P1, typename P2>
 void test_axis_3d()
 {
-    boost::geometry::strategy::distance::pythagoras<P1, P2> pythagoras;
-
     P1 p1;
-    boost::geometry::assign(p1, 0, 0, 0);
-
+    bg::assign(p1, 0, 0, 0);
     P2 p2;
-    boost::geometry::assign(p2, 1, 0, 0);
-    BOOST_CHECK_EQUAL(double(
-            typename boost::geometry::coordinate_type<P1>::type(pythagoras.apply(p1, p2))), 1);
-    boost::geometry::assign(p2, 0, 1, 0);
-    BOOST_CHECK_EQUAL(double(
-            typename boost::geometry::coordinate_type<P1>::type(pythagoras.apply(p1, p2))), 1);
-    boost::geometry::assign(p2, 0, 0, 1);
-    BOOST_CHECK_EQUAL(double(
-            typename boost::geometry::coordinate_type<P1>::type(pythagoras.apply(p1, p2))), 1);
+    bg::assign(p2, 1, 0, 0);
+
+    typedef bg::strategy::distance::pythagoras<P1, P2> pythagoras_type;
+    typedef typename pythagoras_type::return_type return_type;
+
+    pythagoras_type pythagoras;
+
+    return_type result = pythagoras.apply(p1, p2);
+    BOOST_CHECK_EQUAL(result, return_type(1));
+
+    bg::assign(p2, 0, 1, 0);
+    result = pythagoras.apply(p1, p2);
+    BOOST_CHECK_EQUAL(result, return_type(1));
+
+    bg::assign(p2, 0, 0, 1);
+    result = pythagoras.apply(p1, p2);
+    BOOST_CHECK_CLOSE(result, return_type(1), 0.001);
 }
 
 template <typename P1, typename P2>
 void test_arbitrary_3d()
 {
-    boost::geometry::strategy::distance::pythagoras<P1, P2> pythagoras;
+    P1 p1;
+    bg::assign(p1, 1, 2, 3);
+    P2 p2;
+    bg::assign(p2, 9, 8, 7);
+
+    {
+        typedef bg::strategy::distance::pythagoras<P1, P2> strategy_type;
+        typedef typename strategy_type::return_type return_type;
+
+        strategy_type strategy;
+        return_type result = strategy.apply(p1, p2);
+        BOOST_CHECK_CLOSE(result, return_type(10.77032961427), 0.001);
+    }
+
+    {
+        // Check comparable distance
+        typedef bg::strategy::distance::comparable::pythagoras<P1, P2> strategy_type;
+        typedef typename strategy_type::return_type return_type;
+
+        strategy_type strategy;
+        return_type result = strategy.apply(p1, p2);
+        BOOST_CHECK_EQUAL(result, return_type(116));
+    }
+}
+
+template <typename P1, typename P2, typename CalculationType>
+void test_services()
+{
 
     P1 p1;
-    boost::geometry::assign(p1, 1, 2, 3);
+    bg::assign(p1, 1, 2, 3);
+
     P2 p2;
-    boost::geometry::assign(p2, 9, 8, 7);
-    BOOST_CHECK_CLOSE(double(
-            typename boost::geometry::coordinate_type<P1>::type(pythagoras.apply(p1, p2))),
-            sqrt((double)116), 0.001);
+    bg::assign(p2, 4, 5, 6);
+
+    double const sqr_expected = 3*3 + 3*3 + 3*3; // 27
+    double const expected = sqrt(sqr_expected); // sqrt(27)=5.1961524227
+
+
+    namespace bgsd = boost::geometry::strategy::distance;
+    namespace services = boost::geometry::strategy::distance::services;
+    // 1: normal, calculate distance:
+
+    typedef bgsd::pythagoras<P1, P2, CalculationType> strategy_type;
+
+    BOOST_CONCEPT_ASSERT( (boost::geometry::concept::PointDistanceStrategy<strategy_type>) );
+
+    typedef typename strategy_type::return_type return_type;
+
+    strategy_type strategy;
+    return_type result = strategy.apply(p1, p2);
+    BOOST_CHECK_CLOSE(result, return_type(expected), 0.001);
+
+    // 2: "similar" to construct a similar strategy (similar but with other template-parameters) for, e.g., the reverse P2/P1
+    // 2a: similar_type:
+    typedef typename services::similar_type<strategy_type, P2, P1>::type similar_type;
+    // 2b: get_similar
+    similar_type similar = services::get_similar<strategy_type, P2, P1>::apply(strategy);
+
+    //result = similar.apply(p1, p2); // should NOT compile because p1/p2 should also be reversed here
+    result = similar.apply(p2, p1);
+    BOOST_CHECK_CLOSE(result, return_type(expected), 0.001);
+
+
+    // 3: "comparable" to construct a "comparable strategy" for P1/P2
+    //    a "comparable strategy" is a strategy which does not calculate the exact distance, but 
+    //    which returns results which can be mutually compared (e.g. avoid sqrt)
+
+    // 3a: "comparable_type"
+    typedef typename services::comparable_type<strategy_type>::type comparable_type;
+
+    // 3b: "get_comparable"
+    comparable_type comparable = bgsd::services::get_comparable<strategy_type>::apply(strategy);
+
+    return_type c_result = comparable.apply(p1, p2);
+    BOOST_CHECK_CLOSE(c_result, return_type(sqr_expected), 0.001);
+
+    // 4: the comparable_type should have a distance_strategy_constructor as well, 
+    //    knowing how to compare something with a fixed distance
+    return_type c_dist5 = services::result_from_distance<comparable_type>::apply(comparable, 5.0);
+    return_type c_dist6 = services::result_from_distance<comparable_type>::apply(comparable, 6.0);
+
+    // If this is the case:
+    BOOST_CHECK(c_dist5 < c_result && c_result < c_dist6);
+
+    // This should also be the case
+    return_type dist5 = services::result_from_distance<strategy_type>::apply(strategy, 5.0);
+    return_type dist6 = services::result_from_distance<strategy_type>::apply(strategy, 6.0);
+    BOOST_CHECK(dist5 < result && result < dist6);
 }
 
+
 template <typename CoordinateType, typename CalculationType, typename AssignType>
 void test_big_2d_with(AssignType const& x1, AssignType const& y1,
                  AssignType const& x2, AssignType const& y2)
 {
-    typedef boost::geometry::point<CoordinateType, 2, boost::geometry::cs::cartesian> point_type;
-    typedef boost::geometry::strategy::distance::pythagoras
+    typedef bg::point<CoordinateType, 2, bg::cs::cartesian> point_type;
+    typedef bg::strategy::distance::pythagoras
         <
             point_type,
             point_type,
@@ -78,23 +186,22 @@
         > pythagoras_type;
 
     pythagoras_type pythagoras;
+    typedef typename pythagoras_type::return_type return_type;
 
 
     point_type p1, p2;
-    boost::geometry::assign(p1, x1, y1);
-    boost::geometry::assign(p2, x2, y2);
-    typename pythagoras_type::return_type d1 = pythagoras.apply(p1, p2);
+    bg::assign(p1, x1, y1);
+    bg::assign(p2, x2, y2);
+    return_type d = pythagoras.apply(p1, p2);
 
-    /*
+    /***
     std::cout << typeid(CalculationType).name()
-        << " " << std::fixed << std::setprecision(20) << d1.squared_value()
+        << " " << std::fixed << std::setprecision(20) << d
         << std::endl << std::endl;
-    */
+    ***/
 
-    CalculationType d2 = d1;
 
-    BOOST_CHECK_CLOSE((double) d2,
-            1076554.5485833955678294387789057, 0.001);
+    BOOST_CHECK_CLOSE(d, return_type(1076554.5485833955678294387789057), 0.001);
 }
 
 template <typename CoordinateType, typename CalculationType>
@@ -118,7 +225,6 @@
 template <typename P1, typename P2>
 void test_all_3d()
 {
-return;
     test_null_distance_3d<P1, P2>();
     test_axis_3d<P1, P2>();
     test_arbitrary_3d<P1, P2>();
@@ -127,8 +233,8 @@
 template <typename P>
 void test_all_3d()
 {
-    using boost::geometry::point;
-    using boost::geometry::cs::cartesian;
+    using bg::point;
+    using bg::cs::cartesian;
 
     test_all_3d<P, int[3]>();
     test_all_3d<P, float[3]>();
@@ -139,20 +245,45 @@
     test_all_3d<P, point<double, 3, cartesian> >();
 }
 
+template <typename P, typename Strategy>
+void time_compare_s(int const n)
+{
+    boost::timer t;
+    P p1, p2;
+    bg::assign(p1, 1, 1);
+    bg::assign(p2, 2, 2);
+    Strategy strategy;
+    typename Strategy::return_type s = 0;
+    for (int i = 0; i < n; i++)
+    {
+        for (int j = 0; j < n; j++)
+        {
+            bg::set<0>(p2, bg::get<0>(p2) + 0.001);
+            s += strategy.apply(p1, p2);
+        }
+    }
+    std::cout << "s: " << s << " t: " << t.elapsed() << std::endl;
+}
+
+template <typename P>
+void time_compare(int const n)
+{
+    time_compare_s<P, bg::strategy::distance::pythagoras<P> >(n);
+    time_compare_s<P, bg::strategy::distance::comparable::pythagoras<P> >(n);
+}
+
 int test_main(int, char* [])
 {
-    using boost::geometry::point;
-    using boost::geometry::cs::cartesian;
+    using bg::point;
+    using bg::cs::cartesian;
 
-#if ! defined(_MSC_VER)
     test_all_3d<int[3]>();
-#endif
     test_all_3d<float[3]>();
     test_all_3d<double[3]>();
+
     test_all_3d<test::test_point>();
-#if ! defined(_MSC_VER)
+
     test_all_3d<point<int, 3, cartesian> >();
-#endif
     test_all_3d<point<float, 3, cartesian> >();
     test_all_3d<point<double, 3, cartesian> >();
 
@@ -161,29 +292,22 @@
     test_big_2d<long double, long double>();
     test_big_2d<float, long double>();
 
-/*
-TODO: fix this, assign type should use boost::to etc
+    test_services<point<float, 3, cartesian>, double[3], long double>();
+    test_services<double[3], test::test_point, float>();
 
-#if defined(HAVE_CLN)
-    // combination of CLN with normal types
-    typedef boost::numeric_adaptor::cln_value_type cln_type;
-    typedef point<cln_type, 3, cartesian> cln_point;
-    test_all_3d<cln_point>();
-    test_all_3d<cln_point, cln_point>();
 
-    test_big_2d<cln_type, cln_type>();
-    test_big_2d_string<cln_type, cln_type>();
+    time_compare<point<double, 2, cartesian> >(10000);
 
-#endif
-#if defined(HAVE_GMP)
-    typedef boost::numeric_adaptor::gmp_value_type gmp_type;
-    typedef point<gmp_type, 3, cartesian> gmp_point;
-    test_all_3d<gmp_point>();
-    test_all_3d<gmp_point, gmp_point>();
+#if defined(HAVE_TTMATH)
+
+    typedef ttmath::Big<1,4> tt;
+    typedef point<tt, 3, cartesian> tt_point;
 
-    test_big_2d<gmp_type, gmp_type>();
-    test_big_2d_string<gmp_type, gmp_type>();
+    //test_all_3d<tt[3]>();
+    test_all_3d<tt_point>();
+    test_all_3d<tt_point, tt_point>();
+    test_big_2d<tt, tt>();
+    test_big_2d_string<tt, tt>();
 #endif
-*/
     return 0;
 }
Modified: sandbox/geometry/libs/geometry/test/strategies/pythagoras.vcproj
==============================================================================
--- sandbox/geometry/libs/geometry/test/strategies/pythagoras.vcproj	(original)
+++ sandbox/geometry/libs/geometry/test/strategies/pythagoras.vcproj	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -20,7 +20,7 @@
                         OutputDirectory="$(SolutionDir)$(ConfigurationName)"
                         IntermediateDirectory="$(ConfigurationName)\pythagoras"
                         ConfigurationType="1"
-			InheritedPropertySheets="..\boost.vsprops"
+			InheritedPropertySheets="..\boost.vsprops;..\ttmath.vsprops"
                         CharacterSet="1"
 			>
                         <Tool
@@ -93,7 +93,7 @@
                         OutputDirectory="$(SolutionDir)$(ConfigurationName)"
                         IntermediateDirectory="$(ConfigurationName)\pythagoras"
                         ConfigurationType="1"
-			InheritedPropertySheets="..\boost.vsprops"
+			InheritedPropertySheets="..\boost.vsprops;..\ttmath.vsprops"
                         CharacterSet="1"
                         WholeProgramOptimization="1"
 			>
Added: sandbox/geometry/libs/geometry/test/ttmath.vsprops
==============================================================================
--- (empty file)
+++ sandbox/geometry/libs/geometry/test/ttmath.vsprops	2010-07-04 06:01:10 EDT (Sun, 04 Jul 2010)
@@ -0,0 +1,16 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioPropertySheet
+	ProjectType="Visual C++"
+	Version="8.00"
+	Name="ttmath"
+	>
+	<Tool
+		Name="VCCLCompilerTool"
+		AdditionalIncludeDirectories="$(TTMATH_ROOT)"
+		PreprocessorDefinitions="HAVE_TTMATH"
+	/>
+	<UserMacro
+		Name="TTMATH_ROOT"
+		Value="../../../../boost/geometry/extensions/contrib"
+	/>
+</VisualStudioPropertySheet>