Boost logo

Boost-Commit :

From: mariano.consoni_at_[hidden]
Date: 2008-06-04 15:44:31


Author: mconsoni
Date: 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
New Revision: 46139
URL: http://svn.boost.org/trac/boost/changeset/46139

Log:
- Initial Geometry Library integration.
 -> we add the current code
 -> the quadtree code was modificated to adapt to the new point and box classes.
 -> simple_test was adapted to the new style (the other tests are pending)

Added:
   sandbox/SOC/2008/spacial_indexing/geometry/LICENSE_1_0.txt (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/area.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/arithmetic.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/assign.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/aswkt.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/box.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/centroid.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/circle.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/concepts/
   sandbox/SOC/2008/spacial_indexing/geometry/concepts/point_concept.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/concepts/point_traits.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/copy.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/correct.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/dev/
   sandbox/SOC/2008/spacial_indexing/geometry/dev/geometry_dev.cpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/dev/geometry_dev.sln (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/dev/geometry_dev.vcproj (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/dev/projection.cpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/dev/projection.vcproj (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/distance.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/dot_product.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/envelope.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/for_each_coordinate.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/foreach.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/fromwkt.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/geometry.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/grow.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/intersection.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/intersection_linestring.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/intersection_polygon.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/intersection_segment.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/labelinfo.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/latlong.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/length.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/loop.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/overlaps.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/point_on_line.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/segment.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/simplify.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/strategies/
   sandbox/SOC/2008/spacial_indexing/geometry/strategies/strategies_point_ll.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/strategies/strategies_point_xy.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/strategies/strategy_traits.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/streamwkt.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/test/
   sandbox/SOC/2008/spacial_indexing/geometry/test/Jamroot (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/test/arithmetic.cpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/test/common.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/test/compile_test.cpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/test/compile_test.vcproj (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/test/dot_product.cpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/test/for_each_coordinate.cpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/test/geometry_tests.cpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/test/geometry_tests.sln (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/test/geometry_tests.vcproj (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/test/intersection_test.cpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/
   sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/Jamroot (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/array_point.cpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/function_requiring_a_point.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/point_with_incorrect_coord_count.cpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/point_without_coord_count.cpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/point_without_coord_type.cpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/point_without_getter.cpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/point_without_setter.cpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/well_formed_point.cpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/well_formed_point_traits.cpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/test/pythagoras.cpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/test/within_test.cpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/util/
   sandbox/SOC/2008/spacial_indexing/geometry/util/builder.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/util/math.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/util/promotion_traits.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/util/reserve.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/util/return_types.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/util/side.hpp (contents, props changed)
   sandbox/SOC/2008/spacial_indexing/geometry/within.hpp (contents, props changed)

Added: sandbox/SOC/2008/spacial_indexing/geometry/LICENSE_1_0.txt
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/LICENSE_1_0.txt 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,23 @@
+Boost Software License - Version 1.0 - August 17th, 2003
+
+Permission is hereby granted, free of charge, to any person or organization
+obtaining a copy of the software and accompanying documentation covered by
+this license (the "Software") to use, reproduce, display, distribute,
+execute, and transmit the Software, and to prepare derivative works of the
+Software, and to permit third-parties to whom the Software is furnished to
+do so, all subject to the following:
+
+The copyright notices in the Software and this entire statement, including
+the above license grant, this restriction and the following disclaimer,
+must be included in all copies of the Software, in whole or in part, and
+all derivative works of the Software, unless such copies or derivative
+works are solely in the form of machine-executable object code generated by
+a source language processor.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
+SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
+FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
+ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+DEALINGS IN THE SOFTWARE.

Added: sandbox/SOC/2008/spacial_indexing/geometry/area.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/area.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,175 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_AREA_HPP
+#define _GEOMETRY_AREA_HPP
+
+#include <geometry/geometry.hpp>
+#include <geometry/box.hpp>
+#include <geometry/circle.hpp>
+#include <geometry/loop.hpp>
+#include <geometry/segment.hpp>
+
+#include <geometry/strategies/strategy_traits.hpp>
+
+#include <geometry/util/math.hpp>
+
+/*!
+\defgroup area area: area calculation algorithms
+The area of a geometry calculates the surface area of all geometries having a surface:
+box, circle, polygon, multi_polygon. The units are the square of the units used for the points
+defining the surface. If the polygon is defined in meters, the area is in square meters.
+*/
+namespace geometry
+{
+ namespace impl
+ {
+ namespace area
+ {
+ template<typename B>
+ inline typename B::coordinate_type area_box(const B& b)
+ {
+ typename B::coordinate_type dx = b.max().x() - b.min().x();
+ typename B::coordinate_type dy = b.max().y() - b.min().y();
+ return dx * dy;
+ }
+
+ template<typename C>
+ inline double area_circle(const C& c)
+ {
+ return geometry::math::pi * c.radius() * c.radius();
+ }
+
+ // Area of a linear linear_ring, assuming a closed linear_ring
+ template<typename R, typename S>
+ inline double area_ring(const R& r, const S& strategy)
+ {
+ // A closed linear_ring has at least four points, if not there is no area
+ if (r.size() >= 4)
+ {
+ typename S::state_type state;
+ if (loop(r, strategy, state))
+ {
+ return state.area();
+ }
+ }
+
+ return 0;
+ }
+
+ // Area of a polygon, assuing a closed clockwise polygon (with holes counter clockwise)
+ template<typename Y, typename S>
+ inline double area_polygon(const Y& poly, const S& strategy)
+ {
+ double a = fabs(area_ring(poly.outer(), strategy));
+ for (typename Y::inner_container_type::const_iterator i = poly.inners().begin(); i != poly.inners().end(); i++)
+ {
+ a -= fabs(area_ring(*i, strategy));
+ }
+ return a;
+ }
+ } // namespace area
+ } // namespace impl
+
+
+ /*!
+ \brief Calculate area of box
+ \ingroup area
+ */
+ template<typename P>
+ inline double area(const box<P> & b)
+ {
+ return impl::area::area_box(b);
+ }
+
+ /*!
+ \brief Calculate area of circle
+ \ingroup area
+ */
+ template<typename P, typename T>
+ inline double area(const circle<P, T> & c)
+ {
+ return impl::area::area_circle(c);
+ }
+
+ /*!
+ \brief Calculate area of linear_ring
+ \ingroup area
+ \details The function area returns the area of a linear_ring, a strategy is specified
+ \param ring a closed linear_ring
+ \param strategy strategy to be used for area calculations.
+ \return the area
+ */
+ template<typename P, template<typename,typename> class V, template<typename> class A, typename S>
+ inline double area(const linear_ring<P, V, A> & ring, const S& strategy)
+ {
+ return impl::area::area_ring(ring, strategy);
+ }
+
+ /*!
+ \brief Calculate area of linear_ring
+ \ingroup area
+ \details The function area returns the area of a linear_ring, using the default strategy
+ \param ring a closed linear_ring
+ \return the area
+ */
+ template<typename P, template<typename,typename> class V, template<typename> class A>
+ inline double area(const linear_ring<P, V, A> & ring)
+ {
+ return impl::area::area_ring(ring, typename strategy_traits<P>::area());
+ }
+
+ /*!
+ \brief Calculate area of polygon
+ \ingroup area
+ \details The function area returns the area of a polygon, using the specified strategy
+ The polygon should be closed and orientated clockwise, holes, if any, must be orientated
+ counter clockwise
+ \param poly a closed polygon
+ \param strategy strategy to be used for area calculations.
+ \return the area
+ */
+ template<typename P,
+ template<typename,typename> class VP,
+ template<typename,typename> class VR,
+ template<typename> class AP,
+ template<typename> class AR, typename S>
+ inline double area(const polygon<P, VP, VR, AP, AR>& poly, const S& strategy)
+ {
+ return impl::area::area_polygon(poly, strategy);
+ }
+
+ /*!
+ \brief Calculate area of polygon
+ \ingroup area
+ \details The function area returns the area of a polygon, using the default area-calculation strategy. Default strategies are
+ provided for point_xy and for point_ll.
+ The polygon should be closed and orientated clockwise, holes, if any, must be orientated
+ counter clockwise
+ \param poly a closed polygon
+ \return the area
+ \par Example:
+ Example showing area calculation of polygons built of xy-points and of latlong-points
+ \dontinclude doxygen_examples.cpp
+ \skip example_area_polygon()
+ \line {
+ \until }
+ */
+ template<typename P,
+ template<typename,typename> class VP,
+ template<typename,typename> class VR,
+ template<typename> class AP,
+ template<typename> class AR>
+ inline double area(const polygon<P, VP, VR, AP, AR>& poly)
+ {
+ return impl::area::area_polygon(poly, typename strategy_traits<P>::area());
+ }
+
+} // namespace geometry
+
+
+#endif // _GEOMETRY_AREA_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/arithmetic.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/arithmetic.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,102 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008
+// 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 _GEOMETRY_ARITHMETIC_HPP
+#define _GEOMETRY_ARITHMETIC_HPP
+
+
+#include <functional>
+#include <boost/call_traits.hpp>
+#include <geometry/for_each_coordinate.hpp>
+
+
+namespace geometry
+{
+ namespace impl
+ {
+ template <typename P>
+ struct param
+ {
+ typedef typename boost::call_traits
+ <typename point_traits<P>::coordinate_type>
+ ::param_type type;
+ };
+
+
+ template <typename C, template <typename> class Function>
+ struct value_operation
+ {
+ C m_value;
+ value_operation(C value): m_value(value) {}
+
+ template <typename P, int I>
+ void operator()(P& point) const
+ { get<I>(point) = Function<C>()(get<I>(point), m_value); }
+ };
+
+ template <typename PS, template <typename> class Function>
+ struct point_operation
+ {
+ typedef typename point_traits<PS>::coordinate_type T;
+ const PS& m_source_point;
+ point_operation(const PS& point): m_source_point(point) {}
+
+ template <typename PD, int I>
+ void operator()(PD& dest_point) const
+ {
+ get<I>(dest_point) = Function<T>()(get<I>(dest_point), get<I>(m_source_point));
+ }
+ };
+
+ } // namespace impl
+
+
+ template <typename P>
+ void add_value(P& p, typename impl::param<P>::type value)
+ { for_each_coordinate(p, impl::value_operation<typename point_traits<P>::coordinate_type, std::plus>(value)); }
+
+ template <typename P1, typename P2>
+ void add_point(P1& p1, const P2& p2)
+ { for_each_coordinate(p1, impl::point_operation<P2, std::plus>(p2)); }
+
+
+
+ template <typename P>
+ void subtract_value(P& p, typename impl::param<P>::type value)
+ { for_each_coordinate(p, impl::value_operation<typename point_traits<P>::coordinate_type, std::minus>(value)); }
+
+ template <typename P1, typename P2>
+ void subtract_point(P1& p1, const P2& p2)
+ { for_each_coordinate(p1, impl::point_operation<P2, std::minus>(p2)); }
+
+
+
+ template <typename P>
+ void multiply_value(P& p, typename impl::param<P>::type value)
+ { for_each_coordinate(p, impl::value_operation<typename point_traits<P>::coordinate_type, std::multiplies>(value)); }
+
+ template <typename P1, typename P2>
+ void multiply_point(P1& p1, const P2& p2)
+ { for_each_coordinate(p1, impl::point_operation<P2, std::multiplies>(p2)); }
+
+
+
+ template <typename P>
+ void divide_value(P& p, typename impl::param<P>::type value)
+ { for_each_coordinate(p, impl::value_operation<typename point_traits<P>::coordinate_type, std::divides>(value)); }
+
+ template <typename P1, typename P2>
+ void divide_point(P1& p1, const P2& p2)
+ { for_each_coordinate(p1, impl::point_operation<P2, std::divides>(p2)); }
+
+
+} // namespace geometry
+
+
+#endif

Added: sandbox/SOC/2008/spacial_indexing/geometry/assign.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/assign.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,102 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_ASSIGN_HPP
+#define _GEOMETRY_ASSIGN_HPP
+
+#include <geometry/geometry.hpp>
+
+/*!
+\defgroup utility Utility: utilities (copy coordinates, assign coordinates in "neutral" way)
+*/
+
+namespace geometry
+{
+ namespace impl
+ {
+ namespace assign
+ {
+ template <typename P, size_t I, size_t N>
+ struct assign_coordinate
+ {
+ static void assign(P& p, size_t i, const typename P::coordinate_type& v)
+ {
+ if (i == I)
+ {
+ p.template get<I>() = v;
+ }
+ else
+ {
+ assign_coordinate<P, I+1, N>::assign(p, i, v);
+ }
+ }
+ };
+
+ template <typename P, size_t N>
+ struct assign_coordinate<P, N, N>
+ {
+ static void assign(P& p, size_t i, const typename P::coordinate_type& v)
+ {}
+ };
+
+
+
+ template <typename C>
+ struct assign_operation
+ {
+ assign_operation(C value) : m_value(value) {}
+
+ template <typename P, int I>
+ void operator()(P& point) const
+ {
+ get<I>(point) = m_value;
+ }
+
+ private :
+ C m_value;
+ };
+
+
+ } // namespace assign
+
+ } // namespace impl
+
+
+
+ /*!
+ \brief Assigns a coordinate
+ \ingroup utility
+ \details
+ \param p Point
+ \param i index
+ \param v Value which is assigned to coordinate i of point p
+ */
+ template <typename P>
+ void assign_coordinate(P& p, size_t i, const typename P::coordinate_type& v)
+ {
+ impl::assign::assign_coordinate<P, 0, P::coordinate_count>::assign(p, i, v);
+ }
+
+ /*!
+ \brief Assigns all coordinates of a specific point to a value
+ \ingroup utility
+ \details
+ \param p Point
+ \param value Value which is assigned to all coordinates of point p
+ */
+ template <typename P>
+ void assign_value(P& p, const typename point_traits<P>::coordinate_type& value)
+ {
+ for_each_coordinate(p, impl::assign::assign_operation<typename point_traits<P>::coordinate_type>(value));
+ }
+
+
+
+} // namespace geometry
+
+
+#endif // _GEOMETRY_ASSIGN_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/aswkt.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/aswkt.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,235 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_ASWKT_HPP
+#define _GEOMETRY_ASWKT_HPP
+
+#include <geometry/geometry.hpp>
+#include <iostream>
+#include <string>
+
+/*!
+\defgroup wkt wkt: Well-Known Text algorithms
+The as_wkt class streams the specified geometry as \ref OGC Well Known Text (\ref WKT). It is defined for OGC geometries.
+It is therefore not defined for box and circle.
+\note The implementation is independant from point type, point_xy and point_ll are supported,
+as well as points with more than two coordinates.
+
+*/
+
+
+namespace geometry
+{
+ namespace impl
+ {
+ namespace wkt
+ {
+ namespace impl
+ {
+ template <typename CH, typename TR, typename P, int I, int Count>
+ struct dump_coordinate
+ {
+ static void dump(std::basic_ostream<CH,TR>& os, const P& p)
+ {
+ os << (I > 0 ? " " : "") << p.template get<I>();
+ dump_coordinate<CH, TR, P, I+1, Count>::dump(os, p);
+ }
+ };
+
+ template <typename CH, typename TR, typename P, int Count>
+ struct dump_coordinate<CH, TR, P, Count, Count>
+ {
+ static void dump(std::basic_ostream<CH, TR>&, const P&)
+ {}
+ };
+ }
+
+ /*!
+ \brief Manipulator helper class to stream points as \ref WKT
+ */
+ template <typename P>
+ class stream_point
+ {
+ public :
+ inline stream_point(const P& p) : m_point(p) {}
+
+ template <typename CH, typename TR>
+ inline void stream(std::basic_ostream<CH,TR>& os)
+ {
+ os << "POINT(";
+ impl::dump_coordinate<CH, TR, P, 0, P::coordinate_count>::dump(os, m_point);
+ os << ")";
+ }
+
+ private :
+ P m_point;
+ };
+
+
+ /*!
+ \brief Manipulator helper class to stream containers as WKT
+ */
+ template <typename V>
+ class stream_container
+ {
+ public :
+ inline stream_container(const V& container, const std::string& prefix, const std::string& postfix)
+ : m_container(container)
+ , m_prefix(prefix)
+ , m_postfix(postfix)
+ {}
+
+ template <typename CH, typename TR>
+ inline void stream(std::basic_ostream<CH, TR>& os)
+ {
+ bool first = true;
+ os << m_prefix;
+ for (typename V::const_iterator it = m_container.begin(); it != m_container.end(); it++)
+ {
+ if (! first)
+ {
+ os << ",";
+ }
+ first = false;
+
+ typedef typename V::point_type P;
+ impl::dump_coordinate<CH, TR, P, 0, P::coordinate_count>::dump(os, *it);
+ }
+ os << m_postfix;
+ }
+
+ private :
+ V m_container;
+ std::string m_prefix;
+ std::string m_postfix;
+
+ };
+
+ /*!
+ \brief Manipulator helper class to stream linestring as WKT
+ */
+ template <typename L>
+ class stream_linestring : public stream_container<L>
+ {
+ public :
+ inline stream_linestring(const L& ls) : stream_container<L>(ls, "LINESTRING(", ")") {}
+ };
+
+
+ /*!
+ \brief Manipulator helper class to stream polygon as WKT
+ */
+ template <typename P>
+ class stream_polygon
+ {
+ public :
+ inline stream_polygon(const P poly) : m_poly(poly) {}
+
+ template <typename CH, typename TR>
+ inline void stream(std::basic_ostream<CH, TR>& os)
+ {
+ os << "POLYGON(";
+
+ stream_container<typename P::ring_type> wkt(m_poly.outer(), "(", ")");
+ wkt.stream(os);
+
+ for (typename P::inner_container_type::const_iterator it = m_poly.inners().begin();
+ it != m_poly.inners().end(); it++)
+ {
+ os << ",";
+ stream_container<typename P::ring_type> wkt(*it, "(", ")");
+ wkt.stream(os);
+ }
+
+ os << ")";
+ }
+
+ private :
+ P m_poly;
+ };
+
+
+ } // namespace wkt
+ } // namespace impl
+
+
+ /*!
+ \brief Traits class to select wkt-implementations
+ */
+ template <typename G>
+ struct wkt_traits
+ {
+ // Todo: define stream_type as not_implemented
+ };
+
+
+ // specializations for point, linestring, polygon
+ template <typename T, size_t D>
+ struct wkt_traits<geometry::point<T, D> >
+ {
+ typedef impl::wkt::stream_point<geometry::point<T, D> > stream_type;
+ };
+
+ // Alas it must be specialized for each derived type
+ template <typename T>
+ struct wkt_traits<geometry::point_xy<T> >
+ {
+ typedef impl::wkt::stream_point<geometry::point_xy<T> > stream_type;
+ };
+
+ template <typename P, template<typename,typename> class V, template<typename> class A>
+ struct wkt_traits<geometry::linestring<P, V, A> >
+ {
+ typedef impl::wkt::stream_linestring<geometry::linestring<P, V, A> > stream_type;
+ };
+
+ template<typename P,
+ template<typename,typename> class VP,
+ template<typename,typename> class VR,
+ template<typename> class AP,
+ template<typename> class AR>
+ struct wkt_traits<geometry::polygon<P, VP, VR, AP, AR> >
+ {
+ typedef impl::wkt::stream_polygon<geometry::polygon<P, VP, VR, AP, AR> > stream_type;
+ };
+
+
+ /*!
+ \brief Generic geometry template manipulator class, takes corresponding output class from traits class
+ \ingroup wkt
+ \details Stream manipulator, streams geometry classes as \ref WKT streams
+ \par Example:
+ Small example showing how to use the as_wkt class
+ \dontinclude doxygen_examples.cpp
+ \skip example_as_wkt_point
+ \line {
+ \until }
+ \note the template parameter must be specified. If that is inconvient, users might use streamwkt
+ which streams geometries as manipulators.
+ */
+ template <typename G>
+ class as_wkt
+ {
+ public :
+ as_wkt(const G& g) : m_geometry(g) {}
+
+ template <typename CH, typename TR>
+ inline friend std::basic_ostream<CH,TR>& operator<<(std::basic_ostream<CH,TR>& os, const as_wkt& m)
+ {
+ typename wkt_traits<G>::stream_type w(m.m_geometry);
+ w.stream(os);
+ os.flush();
+ return os;
+ }
+
+ private :
+ G m_geometry;
+ };
+
+}
+
+#endif // _GEOMETRY_ASWKT_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/box.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/box.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,87 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_BOX_HPP
+#define _GEOMETRY_BOX_HPP
+
+#include <geometry/geometry.hpp>
+#include <geometry/assign.hpp>
+
+namespace geometry
+{
+
+ /*!
+ \brief Class box: two points describing a box
+ \details Box is always described by a min() and a max() point. If another
+ rectangle is used, use linear_ring or polygon.
+ The point can be a point_xy or a point_ll point.
+ \note Used for selections and for calculating the evnvelope. Not all algorithms
+ are implemented for box
+ \par Template parameters:
+ - \a P point type of the minimum and maximum box
+ */
+
+ template<typename P>
+ class box : public geometry_traits<P>
+ {
+ public :
+
+ inline box()
+ {
+ // Initialize to zero (?), we might change this to nothing, because
+ // there is already another constructor which does this.
+ assign_value(m_min, T());
+ assign_value(m_max, T());
+ }
+
+ inline box(const P& min, const P& max)
+ : m_min(min)
+ , m_max(max)
+ {}
+
+ /* Removed because not coordinate neutral
+ and makes assumptions about constructor of P
+ inline box(T& x1, T& y1, T& x2, T& y2)
+ : m_min(x1, y1)
+ , m_max(x2, y2)
+ {}
+ */
+
+ inline box(init option)
+ {
+ switch(option)
+ {
+ case init_inverse :
+ assign_value(m_min, boost::numeric::bounds<T>::highest());
+ assign_value(m_max, boost::numeric::bounds<T>::lowest());
+ break;
+ case init_zero :
+ assign_value(m_min, T());
+ assign_value(m_max, T());
+ break;
+ default :
+ // no construction at all
+ break;
+ }
+ }
+
+
+ inline const P& min() const { return m_min; }
+ inline const P& max() const { return m_max; }
+
+ inline P& min() { return m_min; }
+ inline P& max() { return m_max; }
+
+ private :
+ P m_min, m_max;
+ typedef typename point_traits<P>::coordinate_type T;
+ };
+
+
+};
+
+#endif // _GEOMETRY_BOX_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/centroid.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/centroid.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,175 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_CENTROID_HPP
+#define _GEOMETRY_CENTROID_HPP
+
+#include <geometry/geometry.hpp>
+#include <geometry/box.hpp>
+#include <geometry/loop.hpp>
+#include <geometry/copy.hpp>
+
+#include <geometry/strategies/strategy_traits.hpp>
+
+/*!
+\defgroup centroid centroid: centroid calculation algorithms
+The centroid of a surface geometry returns a point which is the centroid the geometry.
+*/
+
+namespace geometry
+{
+ // Move elsewhere?
+ class centroid_exception : public std::exception
+ {
+ public:
+ centroid_exception() {}
+ virtual const char *what() const throw()
+ {
+ return "centroid calculation exception";
+ }
+ };
+
+ namespace impl
+ {
+
+
+ namespace centroid
+ {
+
+ /*!
+ \brief Generic function which checks if enough points are present
+ */
+ template<typename P, typename R>
+ inline bool ring_ok(const R& ring, P& c)
+ {
+ if (ring.size() == 1)
+ {
+ // Take over the first point in a "coordinate neutral way"
+ copy_coordinates(ring.front(), c);
+ return false;
+ }
+ else if (ring.size() <= 0)
+ {
+ throw centroid_exception();
+ }
+ return true;
+ }
+
+
+ /*!
+ \brief Calculate the centroid of a ring.
+ */
+ template<typename P, typename R, typename S>
+ inline void centroid_ring(const R& ring, P& c, const S& strategy)
+ {
+ if (ring_ok(ring, c))
+ {
+ typename S::state_type state;
+ loop(ring, strategy, state);
+ state.centroid(c);
+ }
+ }
+
+ /*!
+ \brief Centroid of a polygon.
+ \note Because outer ring is clockwise, inners are counter clockwise,
+ triangle approach is OK and works for polygons with rings.
+ */
+ template<typename P, typename Y, typename S>
+ inline void centroid_polygon(const Y& poly, P& c, const S& strategy)
+ {
+ if (ring_ok(poly.outer(), c))
+ {
+ typename S::state_type state;
+ loop(poly.outer(), strategy, state);
+ for (typename Y::inner_container_type::const_iterator it = poly.inners().begin(); it != poly.inners().end(); it++)
+ {
+ loop(*it, strategy, state);
+ }
+ state.centroid(c);
+ }
+ }
+
+
+ /*!
+ \brief Calculate centroid (==center) of a box
+ \todo Implement strategy
+ */
+ template<typename P, typename B>
+ inline void centroid_box(const B& box, P& c)
+ {
+ c.x((box.min().x() + box.max().x()) / 2);
+ c.y((box.min().y() + box.max().y()) / 2);
+ }
+
+ } // namespace centroid
+ } // namespace impl
+
+
+ template<typename PC, typename PB>
+ inline void centroid(const box<PB>& b, PC& c)
+ {
+ impl::centroid::centroid_box<PC>(b, c);
+ }
+
+ /*!
+ \brief Calculate centroid of polygon
+ \ingroup centroid
+ \details The function centroid calculates the centroid of a polygon using the default strategy.
+ The polygon should be closed and orientated clockwise, holes, if any, must be orientated
+ counter clockwise
+ \param poly a closed polygon
+ \param c reference to point which will contain the centroid
+ \exception centroid_exception if calculation is not successful, e.g. because polygon didn't contain points
+ \note It does not RETURN the centroid. The type of the centroid-point might be different
+ from the type of the polygon-points. Therefore it is a reference, this avoids inconvenient calls
+ as center = centroid<geometry::point_xy<double> >(poly);
+ \par Example:
+ Example showing centroid calculation
+ \dontinclude doxygen_examples.cpp
+ \skip example_centroid_polygon
+ \line {
+ \until }
+ */
+ template<typename PC, typename PP,
+ template<typename,typename> class VP,
+ template<typename,typename> class VR,
+ template<typename> class AP,
+ template<typename> class AR>
+ inline void centroid(const polygon<PP, VP, VR, AP, AR>& poly, PC& c)
+ {
+ impl::centroid::centroid_polygon(poly, c,
+ typename strategy_traits<PC, PP>::centroid());
+ }
+
+
+ /*!
+ \brief Calculate centroid of polygon
+ \ingroup centroid
+ \details The function centroid calculates the centroid of a polygon. This version takes a specified
+ strategy for centroid calculation. The polygon should be closed and orientated clockwise, holes, if
+ any, must be orientated counter clockwise
+ \param poly a closed polygon
+ \param c reference to point which will contain the centroid
+ \param strategy Calculation strategy for centroid
+ \exception centroid_exception if calculation is not successful, e.g. because polygon didn't contain points
+ */
+ template<typename PC, typename PP,
+ template<typename,typename> class VP,
+ template<typename,typename> class VR,
+ template<typename> class AP,
+ template<typename> class AR,
+ typename S>
+ inline void centroid(const polygon<PP, VP, VR, AP, AR>& poly, PC& c, const S& strategy)
+ {
+ impl::centroid::centroid_polygon(poly, c, strategy);
+ }
+
+} // namespace geometry
+
+
+#endif // _GEOMETRY_CENTROID_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/circle.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/circle.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,61 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_CIRCLE_HPP
+#define _GEOMETRY_CIRCLE_HPP
+
+#include <geometry/geometry.hpp>
+
+namespace geometry
+{
+ /*!
+ \brief Class circle: point with radius
+ \details Currently only implemented for point_xy with a radius in the units
+ of the coordinate system.
+ \note Used for selections, for example polygon_in_circle. Currently not all
+ algorithms are implemented for circles.
+ \par Template parameters:
+ - \a P point type of the circle center
+ - \a T number type of the radius
+ */
+ template <typename P, typename T>
+ class circle : public geometry_traits<P>
+ {
+ public :
+ typedef T radius_type;
+
+ circle()
+ : m_center(init_zero)
+ , m_radius(0.0)
+ {}
+
+ circle(const P& center, const T& radius)
+ : m_center(center)
+ , m_radius(radius)
+ {}
+
+ circle(const typename point_traits<P>::coordinate_type& x,
+ const typename point_traits<P>::coordinate_type& y,
+ const T& radius)
+ : m_center(x, y)
+ , m_radius(radius)
+ {}
+
+ inline const P& center() const { return m_center; }
+ inline const T radius() const { return m_radius; }
+
+ inline void radius(const T& r) { m_radius = r; }
+ inline P& center() { return m_center; }
+
+ private :
+ P m_center;
+ T m_radius;
+ };
+
+}
+
+#endif // _GEOMETRY_CIRCLE_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/concepts/point_concept.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/concepts/point_concept.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,56 @@
+// Geometry Library Point concept
+//
+// Copyright Bruno Lalande 2008
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_POINT_CONCEPT_HPP
+#define _GEOMETRY_POINT_CONCEPT_HPP
+
+
+#include <boost/concept_check.hpp>
+#include <geometry/concepts/point_traits.hpp>
+
+
+namespace geometry
+{
+ template <typename X>
+ struct Point
+ {
+ typedef typename point_traits<X>::coordinate_type ctype;
+ enum { ccount = point_traits<X>::coordinate_count };
+
+
+ template <typename P, int I, int Count>
+ struct dimension_checker
+ {
+ static void check()
+ {
+ const P* point;
+ ctype coord = point_traits<const X>::template get<I>(*point);
+ P* point2;
+ point_traits<X>::template get<I>(*point2) = coord;
+
+ dimension_checker<P, I+1, Count>::check();
+ }
+ };
+
+ template <typename P, int Count>
+ struct dimension_checker<P, Count, Count>
+ {
+ static void check() {}
+ };
+
+
+ BOOST_CONCEPT_USAGE(Point)
+ {
+ dimension_checker<X, 0, ccount>::check();
+ }
+ };
+}
+
+
+#endif

Added: sandbox/SOC/2008/spacial_indexing/geometry/concepts/point_traits.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/concepts/point_traits.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,84 @@
+// Geometry Library Point traits
+//
+// Copyright Bruno Lalande 2008
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_POINT_TRAITS_HPP
+#define _GEOMETRY_POINT_TRAITS_HPP
+
+
+namespace geometry
+{
+ // Fall-back definition, using the point class' nested properties
+
+ template <typename P>
+ struct point_traits
+ {
+ typedef typename P::coordinate_type coordinate_type;
+ enum { coordinate_count = P::coordinate_count };
+
+ template <int I>
+ static coordinate_type& get(P& p)
+ { return p.template get<I>(); }
+ };
+
+ template <typename P>
+ struct point_traits<const P>
+ {
+ typedef typename P::coordinate_type coordinate_type;
+ enum { coordinate_count = P::coordinate_count };
+
+ template <int I>
+ static const coordinate_type& get(const P& p)
+ { return p.template get<I>(); }
+ };
+
+
+ // Specialization for arrays
+
+ template <typename T, int N>
+ struct point_traits<T[N]>
+ {
+ typedef T coordinate_type;
+ enum { coordinate_count = N };
+
+ template <int I>
+ static T& get(T p[N])
+ { return p[I]; }
+ };
+
+ template <typename T, int N>
+ struct point_traits<const T[N]>
+ {
+ typedef T coordinate_type;
+ enum { coordinate_count = N };
+
+ template <int I>
+ static const T& get(const T p[N])
+ { return p[I]; }
+ };
+
+
+ // Global get<>() functions
+
+ template <int I, typename P>
+ static typename point_traits<P>::coordinate_type&
+ get(P& p)
+ {
+ return point_traits<P>::template get<I>(p);
+ }
+
+ template <int I, typename P>
+ static const typename point_traits<const P>::coordinate_type&
+ get(const P& p)
+ {
+ return point_traits<const P>::template get<I>(p);
+ }
+}
+
+
+#endif

Added: sandbox/SOC/2008/spacial_indexing/geometry/copy.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/copy.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,67 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_COPY_HPP
+#define _GEOMETRY_COPY_HPP
+
+#include <geometry/geometry.hpp>
+
+/*!
+\defgroup copy copy: copy utility
+The copy utility method copies coordinate values
+*/
+
+namespace geometry
+{
+ namespace impl
+ {
+ namespace copy
+ {
+ template <typename PS, typename PD, int I, int N>
+ struct copy_coordinates
+ {
+ static void copy(const PS& source, PD& dest)
+ {
+ // Todo: use boost-conversion-tool for the cast
+ get<I>(dest) = (typename point_traits<PD>::coordinate_type) get<I>(source);
+ copy_coordinates<PS, PD, I+1, N>::copy(source, dest);
+ }
+ };
+
+ template <typename PS, typename PD, int N>
+ struct copy_coordinates<PS, PD, N, N>
+ {
+ static void copy(const PS& source, PD& dest)
+ {}
+ };
+
+ } // namespace copy
+
+ } // namespace impl
+
+
+ /*!
+ \brief Copies coordinates from source to destination point
+ \ingroup copy
+ \details The function copy_coordinates copies coordinates from one point to another point.
+ Source point and destination point might be of different types.
+ \param source Source point
+ \param dest Destination point
+ \note If destination type differs from source type, they must have the same coordinate count
+ */
+ template <typename PS, typename PD>
+ void copy_coordinates(const PS& source, PD& dest)
+ {
+ BOOST_STATIC_ASSERT(point_traits<PD>::coordinate_count == point_traits<PS>::coordinate_count);
+ impl::copy::copy_coordinates<PS, PD, 0, point_traits<PS>::coordinate_count>::copy(source, dest);
+ }
+
+
+} // namespace geometry
+
+
+#endif // _GEOMETRY_COPY_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/correct.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/correct.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,119 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_CORRECT_HPP
+#define _GEOMETRY_CORRECT_HPP
+
+#include <algorithm>
+
+#include <geometry/geometry.hpp>
+#include <geometry/box.hpp>
+
+
+namespace geometry
+{
+ namespace impl
+ {
+ namespace correct
+ {
+ // correct an box: make min/max are correct
+ template <typename B>
+ inline void correct_box(B& b)
+ {
+ typedef typename B::coordinate_type T;
+ if (b.min().x() > b.max().x())
+ {
+ T max = b.min().x();
+ T min = b.max().x();
+ b.min().x(min);
+ b.max().x(max);
+ }
+ if (b.min().y() > b.max().y())
+ {
+ T max = b.min().y();
+ T min = b.max().y();
+ b.min().y(min);
+ b.max().y(max);
+ }
+ }
+
+
+ // close a linear_ring, if not closed
+ template <typename R>
+ inline void ensure_closed_ring(R& r)
+ {
+ if (r.size() > 2)
+ {
+ // check if closed, if not, close it
+ if (r.front() != r.back())
+ {
+ r.push_back(r.front());
+ }
+ }
+ }
+
+
+ // correct a polygon: normalizes all rings, sets outer linear_ring clockwise, sets all
+ // inner rings counter clockwise
+ template <typename Y>
+ inline void correct_polygon(Y& poly)
+ {
+ typename Y::ring_type& outer = poly.outer();
+ ensure_closed_ring(outer);
+
+ typename strategy_traits<typename Y::point_type>::area strategy;
+
+ if (impl::area::area_ring(outer, strategy) < 0)
+ {
+ std::reverse(outer.begin(), outer.end());
+ }
+
+ for (typename Y::inner_container_type::iterator it = poly.inners().begin();
+ it != poly.inners().end(); it++)
+ {
+ ensure_closed_ring(*it);
+ if (impl::area::area_ring(*it, strategy) > 0)
+ {
+ std::reverse(it->begin(), it->end());
+ }
+ }
+ }
+
+ }
+ }
+
+
+ //---------------------------------------------------------------------------------------------
+ template <typename P>
+ inline void correct(box<P>& b)
+ {
+ impl::correct::correct_box(b);
+ }
+
+
+ template <typename P, template <typename,typename> class V, template<typename> class A>
+ inline void correct(linear_ring<P, V, A>& r)
+ {
+ impl::correct::ensure_closed_ring(r);
+ }
+
+
+ template <typename P,
+ template<typename,typename> class VP,
+ template<typename,typename> class VR,
+ template<typename> class AP,
+ template<typename> class AR>
+ inline void correct(polygon<P, VP, VR, AP, AR>& poly)
+ {
+ impl::correct::correct_polygon(poly);
+ }
+
+
+} // namespace geometry
+
+
+#endif // _GEOMETRY_CORRECT_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/dev/geometry_dev.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/dev/geometry_dev.cpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,44 @@
+#include <vector>
+#include <string>
+#include <iostream>
+
+#include <boost/numeric/conversion/bounds.hpp>
+#include <boost/limits.hpp>
+
+#include <geometry/geometry.hpp>
+
+
+
+int main()
+{
+
+ std::cout << "numeric::bounds versus numeric_limits example.\n";
+
+ std::cout << "The maximum value for float:\n";
+ std::cout << boost::numeric::bounds<float>::highest() << "\n";
+ std::cout << std::numeric_limits<float>::max() << "\n";
+
+ std::cout << "The minimum value for float:\n";
+ std::cout << boost::numeric::bounds<float>::lowest() << "\n";
+ std::cout << -std::numeric_limits<float>::max() << "\n";
+
+ std::cout << "The smallest positive value for float:\n";
+ std::cout << boost::numeric::bounds<float>::smallest() << "\n";
+ std::cout << std::numeric_limits<float>::min() << "\n";
+
+ try
+ {
+ //typedef geometry::point<double, 2> XYZ ;
+ typedef geometry::point_xy<double> XYZ;
+ XYZ xyz(1,2);
+ XYZ p2(1,4);
+ std::cout << ((p2 < xyz) ? "kleiner" : "groter") << std::endl;
+ }
+ catch(...)
+ {
+ std::cout << "error!";
+ }
+
+ return 0;
+}
+

Added: sandbox/SOC/2008/spacial_indexing/geometry/dev/geometry_dev.sln
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/dev/geometry_dev.sln 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,37 @@
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual C++ Express 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "use_o_iterator", "use_o_iterator.vcproj", "{E013A5EB-2EC9-4B99-84D7-C1CCAE53671C}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "compare_great_circle", "compare_great_circle.vcproj", "{41D4268B-3BE4-48FC-8D94-BCEBFD82FAA9}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "crtp", "crtp.vcproj", "{083A9118-DFE9-405D-A2C2-892DF86C57CE}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "multi", "multi.vcproj", "{8DD51862-4F44-4371-B7E2-C93A9F4AC564}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {E013A5EB-2EC9-4B99-84D7-C1CCAE53671C}.Debug|Win32.ActiveCfg = Debug|Win32
+ {E013A5EB-2EC9-4B99-84D7-C1CCAE53671C}.Debug|Win32.Build.0 = Debug|Win32
+ {E013A5EB-2EC9-4B99-84D7-C1CCAE53671C}.Release|Win32.ActiveCfg = Release|Win32
+ {E013A5EB-2EC9-4B99-84D7-C1CCAE53671C}.Release|Win32.Build.0 = Release|Win32
+ {41D4268B-3BE4-48FC-8D94-BCEBFD82FAA9}.Debug|Win32.ActiveCfg = Debug|Win32
+ {41D4268B-3BE4-48FC-8D94-BCEBFD82FAA9}.Debug|Win32.Build.0 = Debug|Win32
+ {41D4268B-3BE4-48FC-8D94-BCEBFD82FAA9}.Release|Win32.ActiveCfg = Release|Win32
+ {41D4268B-3BE4-48FC-8D94-BCEBFD82FAA9}.Release|Win32.Build.0 = Release|Win32
+ {083A9118-DFE9-405D-A2C2-892DF86C57CE}.Debug|Win32.ActiveCfg = Debug|Win32
+ {083A9118-DFE9-405D-A2C2-892DF86C57CE}.Debug|Win32.Build.0 = Debug|Win32
+ {083A9118-DFE9-405D-A2C2-892DF86C57CE}.Release|Win32.ActiveCfg = Release|Win32
+ {083A9118-DFE9-405D-A2C2-892DF86C57CE}.Release|Win32.Build.0 = Release|Win32
+ {8DD51862-4F44-4371-B7E2-C93A9F4AC564}.Debug|Win32.ActiveCfg = Debug|Win32
+ {8DD51862-4F44-4371-B7E2-C93A9F4AC564}.Debug|Win32.Build.0 = Debug|Win32
+ {8DD51862-4F44-4371-B7E2-C93A9F4AC564}.Release|Win32.ActiveCfg = Release|Win32
+ {8DD51862-4F44-4371-B7E2-C93A9F4AC564}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal

Added: sandbox/SOC/2008/spacial_indexing/geometry/dev/geometry_dev.vcproj
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/dev/geometry_dev.vcproj 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,273 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="geometry_dev"
+ ProjectGUID="{618D4B05-A06E-443B-87C0-94964CEA7164}"
+ RootNamespace="geometry_dev"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)/geometry_dev"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=".;..;../..;C:\svn\geolib\trunk\src\cpp\contrib"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="0"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="kernel32.lib $(NoInherit)"
+ LinkIncremental="2"
+ 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)/geometry_dev"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=".;..;../..;C:\svn\geolib\trunk\src\cpp\contrib"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="0"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="kernel32.lib $(NoInherit)"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ 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>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\geometry_dev.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\area.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\astext.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\box.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\centroid.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\circle.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\distance.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\envelope.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\geometry.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\grow.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\intersection_linestring.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\intersection_polygon.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\intersection_segment.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\length.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\normalize.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\overlaps.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\point_on_line.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\segment.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\within.hpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>

Added: sandbox/SOC/2008/spacial_indexing/geometry/dev/projection.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/dev/projection.cpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,585 @@
+#include <vector>
+#include <algorithm>
+#include <functional>
+#include <string>
+#include <iostream>
+
+#include <boost/numeric/conversion/bounds.hpp>
+#include <boost/limits.hpp>
+#include <boost/function_output_iterator.hpp>
+
+
+#include <geometry/geometry.hpp>
+#include <geometry/latlong.hpp>
+#include <geometry/streamwkt.hpp>
+#include <geometry/distance.hpp>
+#include <geometry/length.hpp>
+
+typedef int int32;
+typedef int32 GL_PROJPARAM_TYPE;
+typedef int32 GL_PROJECTION_TYPE;
+
+
+struct PROJECTION_PARAM
+{
+ // int-parameters
+ int32 Zone;
+ int32 i1; // General parameter
+
+ // double-parameters
+ double FalseEast;
+ double FalseNorth;
+ double MajorAxis;
+ double MinorAxis;
+ double CenterLatitude; // radian
+ double CenterLongitude; // radian
+ double FirstParallel; // radian
+ double SecondParallel; // radian
+ double ScaleFactor;
+ double Azimuth; // radian
+ double d1; // General parameter
+ double d2; // General parameter
+
+public:
+ double Get(GL_PROJPARAM_TYPE Param) const;
+ void Set(GL_PROJPARAM_TYPE Param, double value);
+};
+
+//static const double d2r = M_PI / 180.0;
+//static const double TWO_PI = M_PI + M_PI;
+
+
+
+
+/* Coordinates of Amersfoort in degrees: 5 23' 15.5'', 52 9' 22.178'' */
+// Original geolib:
+//const double AmersfoortXll = 5.0 + (23.0 / 60.0) + (15.500 / 3600.0);
+//const double AmersfoortYll = 52.0 + ( 9.0 / 60.0) + (22.178 / 3600.0);
+
+// Second approach:
+//const double AmersfoortXll = from_dms(5, 23, 15.5);
+//const double AmersfoortYll = from_dms(52.0, 9.0, 22.178);
+
+// Third approach (now in namespace geometry), explicitly initialized with lat/long, safer:
+/*
+ const geometry::point_ll<double> AmersfoortLL(geometry::graticule<geometry::longitude, double>(geometry::dms(5, 23, 15.5)),
+ geometry::graticule<geometry::latitude, double>(geometry::dms(52.0, 9.0, 22.178)));
+*/
+
+// Fourth approach, same, less verbose
+namespace
+{
+ // Note thate "using geometry" will result in a globally available namespace, but stated like this it is only here
+ using geometry::graticule;
+ using geometry::dms;
+ using geometry::latitude;
+ using geometry::longitude;
+ const geometry::point_ll<geometry::degree, double> AmersfoortLL(
+ longitude<>(dms( 5.0, 23.0, 15.500)),
+ latitude<>(dms(52.0, 9.0, 22.178)));
+}
+
+
+/***
+class datum_transformation
+{
+ point_ll to_wgs84(point_ll)
+ point_ll from_wgs84(point_ll)
+}
+
+class amersfoort_dt :public datum_transformation
+{
+ // geen parameters
+}
+
+class vector7_dt :public datum_transformation
+{
+ parameter[7]
+ //matrixbereking: schaling, rotatie en translatie
+}
+
+class vector3_dt :public datum_transformation
+{
+ parameter[3]
+ //matrixbereking: translatie
+}
+
+
+class coordinate_system
+{
+ point_ll to_wgs84(point_ll)
+ point_ll from_wgs84(point_ll)
+}
+
+class gg_coordinate_system:public coordinate_system
+{
+ std::vector<datum_transformation> m_dts;
+
+ point_ll to_wgs84(point_ll)
+ {
+ // for iterator etc
+ point_ll = dts[0].to_wgs85(point_ll);
+ point_ll = dts[1].to_wgs85(point_ll);
+ }
+ point_ll from_wgs84(point_ll)
+ {
+ // backward
+ }
+};
+
+class project_parameter
+{
+}
+
+class ellipsoid : public project_parameter
+{
+ double MajorAxis;
+ double MinorAxis;
+ 2 -> 3 getallen?
+}
+
+class zone : public project_parameter
+{
+ int32 Zone;
+}
+
+class offsets : public project_parameter
+ double FalseEast;
+ double FalseNorth;
+
+class centers : public project_parameter
+{
+ radian CenterLatitude; // radian
+ radian CenterLongitude; // radian
+}
+
+class parallells (?) : public project_parameter
+{
+ // lat long?
+ radian FirstParallel; // radian
+ radian SecondParallel; // radian
+}
+
+class azimuth? : public project_parameter
+{
+ radian Azimuth; // radian
+};
+class scalefactor? : public project_parameter
+{
+ // double-parameters
+ double ScaleFactor;
+}
+
+
+
+class projection_method
+{
+ // parameters
+ point_ll unproject(point_xy)
+ point_xy project(point_ll)
+};
+
+
+template <typename P1, typename C1, typename P2, typename C2>
+public static Transform (const P1&, const C1 cs2, P2&, const C2 cs2)
+{
+ coordinate_system s1 = coordinatesystem_factory(cs1);
+ coordinate_system s2 = coordinatesystem_factory(cs2);
+
+ s1.from_wgs84();
+ s2.to_wgs84();
+}
+
+public static Transform (point_ll, int cs1, point_ll, int cs2)
+public static Transform (point_xy, int cs1, point_xy, int cs2)
+public static Transform (point_ll, int cs1, point_xy, int cs2)
+
+
+
+//class projected_cs:public coordinate_system
+class projection
+{
+ gg_coordinate_system m_gg_coordinate_system;
+ project_method m_method;
+
+ point_ll to_wgs84(pointxy)
+ {
+ pointll = m_method.unproject(pointxy);
+ return m_gg_coordinate_system.to_wgs84(pointll);
+ }
+
+ point_xy from_wgs84(point_ll)
+ {
+ pointll=m_gg_coordinate_system.from_wgs84(point_ll);
+ return m_method.project(pointll);
+ }
+};
+
+***/
+
+/* Coordinates of Amersfoort in Rijksdriehoek meting */
+//const double AmersfoortXrd = 155000.0;
+//const double AmersfoortYrd = 463000.0;
+const geometry::point_xy<double> AmersfoortRD(155000.0, 463000.0);
+
+
+// Lat-long in DEGREE
+template <geometry::dr_selector D, typename T>
+inline void BesselToWGS84(const geometry::point_ll<D, T>& in, geometry::point_ll<D, T>& out)
+{
+ // delta(WGSlat, WGSlong) = (c1, c2) + A * delta(Blat, Blong)
+ // in which A is the matrix:
+ // a11 a12
+ // a21 a22
+ // and the deltas are offsets from (52, 5)
+
+ // formula from an article by ir.T.G.Schut
+ // published in NGT Geodesia, june 1992.
+
+ geometry::point_ll<geometry::degree, T> in_deg = in.convert<geometry::degree>();
+
+ const double c1 = -96.862/100000.0;
+ const double c2 = -37.902/100000.0;
+ const double a11 = -11.714/100000.0 + 1.0;
+ const double a12 = - 0.125/100000.0;
+ const double a21 = 0.329/100000.0;
+ const double a22 = -14.667/100000.0 + 1.0;
+
+ //const double Lat0 = 52.0; // North
+ //const double Long0 = 5.0; // East
+ //const LL ll0(geometry::longitude<>(5), geometry::latitude<>(52));
+ //const LL ll1(5.0, 52.0); // won't compile
+ const geometry::point_ll<geometry::degree, T> ll0(geometry::longitude<>(5), geometry::latitude<>(52));
+
+ double DeltaLat = in_deg.lat() - ll0.lat();
+ double DeltaLong = in_deg.lon() - ll0.lon();
+
+ geometry::point_ll<geometry::degree, T> out_deg;
+ out_deg.lat( c1 + ll0.lat() + a11 * DeltaLat + a12 * DeltaLong);
+ out_deg.lon (c2 + ll0.lon() + a21 * DeltaLat + a22 * DeltaLong);
+ out = out_deg.convert<D>();
+}
+
+template <typename T>
+inline void WGS84ToBessel(const geometry::point_ll<geometry::degree, T>& in, geometry::point_ll<geometry::degree, T>& out)
+{
+ // delta(Blat, Blong) = D * { delta(WGSlat, WGSlong) - (c1, c2) }
+ // in which D is the inverse van matrix A
+ // and the deltas are offsets from (52, 5)
+
+ const double c1 = -96.862/100000.0;
+ const double c2 = -37.902/100000.0;
+ const double a11 = -11.714/100000.0 + 1.0;
+ const double a12 = - 0.125/100000.0;
+ const double a21 = 0.329/100000.0;
+ const double a22 = -14.667/100000.0 + 1.0;
+
+ const geometry::point_ll<geometry::degree, T> ll0(geometry::longitude<>(5), geometry::latitude<>(52));
+
+ const double NormA = 1.0 / (a11 * a22 - a12 * a21);
+ const double d11 = + a22 * NormA;
+ const double d12 = - a12 * NormA;
+ const double d21 = - a21 * NormA;
+ const double d22 = + a11 * NormA;
+
+ double DeltaLat = in.lat() - ll0.lat() - c1;
+ double DeltaLong = in.lon() - ll0.lon() - c2;
+
+ out.lat (ll0.lat() + d11 * DeltaLat + d12 * DeltaLong);
+ out.lon (ll0.lon() + d21 * DeltaLat + d22 * DeltaLong);
+}
+
+
+template <typename P, typename LL>
+class projection_rd
+{
+ public :
+
+ typedef typename LL::coordinate_type T;
+
+ GL_PROJECTION_TYPE ParamsGet(PROJECTION_PARAM &Params) const
+ {
+ Params.MajorAxis = 6377397.155000;
+ Params.MinorAxis = 6356078.962818;
+ Params.CenterLongitude = 0.094032;
+ Params.CenterLatitude = 0.910297;
+ Params.ScaleFactor = 0.999908;
+ Params.FalseEast = 155000.000000;
+ Params.FalseNorth = 463000.000000;
+ return 28992;
+ }
+ bool Project(const LL& lola, P& p) const
+ {
+ BOOST_STATIC_ASSERT(LL::angle_type == geometry::radian);
+ double Phi1, Lambda1, Phi2, Lambda2, Phi3, Lambda3, Phi4, Lambda4, Lambda5;
+
+ double TWO_PI = geometry::math::two_pi;
+ if (lola.lon() < -TWO_PI || lola.lon() > TWO_PI || lola.lat() < -TWO_PI || lola.lat() > TWO_PI)
+ {
+ p.x(0.0);
+ p.y(0.0);
+ return false;
+ }
+
+ // Calculate x and y in units of 10000 seconds
+ // (lat, lon might be converted to degrees (0-360))
+ geometry::point_ll<geometry::degree, LL::coordinate_type> lola_deg = lola.convert<geometry::degree>();
+ Lambda1 = (lola_deg.lon() - AmersfoortLL.lon() ) * 3600.0 / 10000.0;
+ Phi1 = (lola_deg.lat() - AmersfoortLL.lat() ) * 3600.0 / 10000.0;
+
+ /* Precompute powers */
+ Phi2 = Phi1 * Phi1;
+ Phi3 = Phi2 * Phi1;
+ Phi4 = Phi3 * Phi1;
+ Lambda2 = Lambda1 * Lambda1;
+ Lambda3 = Lambda2 * Lambda1;
+ Lambda4 = Lambda3 * Lambda1;
+ Lambda5 = Lambda4 * Lambda1;
+
+ /* Calculate coordinates in meters
+ * "DG Rijkswaterstaat. Coordinaattransformaties en kaartprojecties. 1993, p. 19"
+ */
+ p.x(AmersfoortRD.x()
+ + 190066.98903 * Lambda1
+ - 11830.85831 * Phi1 * Lambda1
+ - 144.19754 * Phi2 * Lambda1
+ - 32.38360 * Lambda3
+ - 2.34078 * Phi3 * Lambda1
+ - 0.60639 * Phi1 * Lambda3
+ + 0.15774 * Phi2 * Lambda3
+ - 0.04158 * Phi4 * Lambda1
+ - 0.00661 * Lambda5);
+
+ p.y(AmersfoortRD.y()
+ + 309020.31810 * Phi1
+ + 3638.36193 * Lambda2
+ - 157.95222 * Phi1 * Lambda2
+ + 72.97141 * Phi2
+ + 59.79734 * Phi3
+ - 6.43481 * Phi2 * Lambda2
+ + 0.09351 * Lambda4
+ - 0.07379 * Phi3 * Lambda2
+ - 0.05419 * Phi1 * Lambda4
+ - 0.03444 * Phi4);
+
+ return true;
+ }
+
+ bool LatLong(const P& p, LL& lola) const
+ {
+ BOOST_STATIC_ASSERT(LL::angle_type == geometry::radian);
+ double x2, x3, x4, x5, y2, y3, y4, y5, Phi, Lambda;
+
+ /* Calculate coordinates in 100 kilometers units
+ * with Amersfoort(155,463) as origin
+ */
+ typename P::coordinate_type x = (p.x() - AmersfoortRD.x()) / 100000.0;
+ typename P::coordinate_type y = (p.y() - AmersfoortRD.y()) / 100000.0;
+
+ /* Precompute second, third and fourth power */
+ x2 = x * x;
+ x3 = x2 * x;
+ x4 = x3 * x;
+ x5 = x4 * x;
+
+ y2 = y * y;
+ y3 = y2 * y;
+ y4 = y3 * y;
+ y5 = y4 * y;
+
+ /*
+ * Calculate coordinates in lat-long seconds
+ * "DG Rijkswaterstaat. Coordinaattransformaties en kaartprojecties. 1993, p. 20"
+ * (Lambda = X direction, phi is Y direction)
+ */
+ Lambda =
+ + 5261.3028966 * x
+ + 105.9780241 * x * y
+ + 2.4576469 * x * y2
+ - 0.8192156 * x3
+ - 0.0560092 * x3 * y
+ + 0.0560089 * x * y3
+ - 0.0025614 * x3 * y2
+ + 0.0012770 * x * y4
+ + 0.0002574 * x5
+ - 0.0000973 * x3 * y3
+ + 0.0000293 * x5 * y
+ + 0.0000291 * x * y5;
+
+ Phi =
+ + 3236.0331637 * y
+ - 32.5915821 * x2
+ - 0.2472814 * y2
+ - 0.8501341 * x2 * y
+ - 0.0655238 * y3
+ - 0.0171137 * x2 * y2
+ + 0.0052771 * x4
+ - 0.0003859 * x2 * y3
+ + 0.0003314 * x4 * y
+ + 0.0000371 * y4
+ + 0.0000143 * x4 * y2
+ - 0.0000090 * x2 * y4;
+
+ /* x and y are in seconds from Amersfoort. Recompute degrees
+ * and add Amersfoort in degrees
+ */
+ lola.lon(geometry::math::d2r * (AmersfoortLL.lon() + (Lambda / 3600.0)));
+ lola.lat(geometry::math::d2r * (AmersfoortLL.lat() + (Phi / 3600.0)));
+ return true;
+ }
+
+ bool TransformToWGS84(const LL& in, LL& out) const
+ {
+ //if (m_transformations.size()==0)
+ {
+ //out.lat() = in.lat();
+ //out.lon() = in.lon();
+
+ //in.lon( in.lon()*180/M_PI );
+ //in.lat( in.lat()*180/M_PI );
+ geometry::point_ll<geometry::degree, LL::coordinate_type> in_deg = in.convert<geometry::degree>();
+
+ LL out_deg;
+ BesselToWGS84(in_deg, out_deg);
+ // out_deg.as_<geometry::in>
+ out = out_deg.as_radian();
+
+ //out.lon( out.lon() *M_PI / 180);
+ //out.lat( out.lat() *M_PI / 180);
+
+ }
+ /***
+ else
+ {
+ BASE_PROJECTION::TransformToWGS84(in.lon(), in.lat(), out.lon(), out.lat());
+ }
+ ***/
+
+ return true;
+ }
+
+ bool TransformFromWGS84(const LL& in, LL& out) const
+ {
+ //if (m_transformations.size()==0)
+ {
+ //out.lat() = in.lat();
+ //out.lon() = in.lon();
+
+ in.lon( in.lon()*180/M_PI );
+ in.lat( in.lat()*180/M_PI );
+ WGS84ToBessel(in, out);
+ out.lon(out.lon() *M_PI / 180);
+ out.lat(out.lat() *M_PI / 180);
+ }
+ /*
+ else
+ {
+ BASE_PROJECTION::TransformFromWGS84(in.lon(), in.lat(), out.lon(), out.lat());
+ }
+ */
+ return true;
+ }
+};
+
+
+
+void PrintGrad(double Angle)
+{
+ int Degree = (int)Angle;
+ Angle -= Degree;
+ Angle *= 60;
+ int Minutes = (int)Angle;
+ Angle -= Minutes;
+ Angle *= 60;
+
+ printf("%d %d' %lf%c", Degree, Minutes, Angle, '"');
+}
+
+
+
+int main()
+{
+ /*
+ double Lat = 53.0;
+ double Long = 6.0;
+
+ double LatTemp;
+ double LongTemp;
+
+ double LatResult;
+ double LongResult;
+ */
+ geometry::point_ll<geometry::degree, double> latlon(geometry::longitude<>(6), geometry::latitude<>(53));
+ geometry::point_ll<geometry::degree, double> ll_temp;
+ geometry::point_ll<geometry::degree, double> ll_result;
+
+ BesselToWGS84(latlon, ll_temp);
+ WGS84ToBessel(ll_temp, ll_result);
+ printf("lat = ");
+ PrintGrad(latlon.lat());
+ printf(" -> ");
+ PrintGrad(ll_temp.lat());
+ printf(" -> ");
+ PrintGrad(ll_result.lat());
+ printf("\n");
+ printf("long = ");
+ PrintGrad(latlon.lon());
+ printf(" -> ");
+ PrintGrad(ll_temp.lon());
+ printf(" -> ");
+ PrintGrad(ll_result.lon());
+ printf("\n");
+
+ projection_rd<geometry::point_xy<double>, geometry::point_ll<geometry::radian, double> > rd;
+
+ geometry::point_xy<double> p;
+ geometry::point_ll<geometry::radian, double> ll;
+
+ ll.lat(52 * geometry::math::d2r);
+ ll.lon(5 * geometry::math::d2r);
+
+ rd.Project(ll, p);
+ std::cout << p.x() << " " << p.y() << std::endl;
+
+ geometry::point_ll<geometry::degree, double> lld = ll.convert<geometry::degree>();
+ //rd.Project(lld, p); //will NOT compile because it is a latlong!
+
+ geometry::point_ll<geometry::radian, double> ll2;
+ rd.LatLong(p, ll2);
+ std::cout << ll2.lon() / geometry::math::d2r << " " << ll2.lat() / geometry::math::d2r << std::endl;
+
+ //latitude lt = as_lat(3);
+ //double d = lt();
+ // will not compile!
+ //lon ln = lt;
+
+ {
+ typedef geometry::point_ll<geometry::degree, double> lola;
+ lola a, r;
+ // Amsterdam 52 22'23"N 4 53'32"E
+ a.lat(geometry::dms(52, 22, 23));
+ a.lon(geometry::dms(4, 53, 32));
+
+ // Rotterdam 51 55'51"N 4 28'45"E
+ r.lat(geometry::dms(51, 55, 51));
+ r.lon(geometry::dms(4, 28, 45));
+
+ // Project points to Dutch coordinate-system, which is in meters
+ typedef geometry::point_xy<double> XY;
+ XY a1, r1;
+ rd.Project(a.convert<geometry::radian>(), a1);
+ rd.Project(r.convert<geometry::radian>(), r1);
+
+ std::cout << "Amsterdam: " << a1 << " Rotterdam: " << r1 << std::endl;
+
+ std::cout << "Distance Amsterdam-Rotterdam: " << std::endl;
+ std::cout << "vincenty: " << 0.001 * geometry::distance(a, r, geometry::formulae::distance::vincenty<>() ) << " km" << std::endl;
+ std::cout << "RD, pythagoras: " << 0.001 * geometry::distance(a1, r1) << " km" << std::endl;
+
+
+ }
+
+
+ return 0;
+}
+

Added: sandbox/SOC/2008/spacial_indexing/geometry/dev/projection.vcproj
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/dev/projection.vcproj 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,285 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="projection"
+ ProjectGUID="{673CA502-9E2B-49A0-9A75-D8D70C287A6B}"
+ RootNamespace="projection"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)/projection"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=".;..;../..;C:\svn\geolib\trunk\src\cpp\contrib"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="0"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="kernel32.lib $(NoInherit)"
+ LinkIncremental="2"
+ 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)/projection"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=".;..;../..;C:\svn\geolib\trunk\src\cpp\contrib"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="0"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="kernel32.lib $(NoInherit)"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ 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>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\projection.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\area.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\astext.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\box.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\centroid.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\circle.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\distance.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\envelope.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\foreach.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\geometry.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\grow.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\intersection_linestring.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\intersection_polygon.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\intersection_segment.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\length.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\normalize.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\overlaps.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\point_on_line.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\segment.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\within.hpp"
+ >
+ </File>
+ <Filter
+ Name="predicate"
+ >
+ <File
+ RelativePath="..\predicate\predicate_distance.hpp"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>

Added: sandbox/SOC/2008/spacial_indexing/geometry/distance.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/distance.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,180 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_DISTANCE_HPP
+#define _GEOMETRY_DISTANCE_HPP
+
+#include <cmath>
+
+#include <geometry/geometry.hpp>
+#include <geometry/segment.hpp>
+
+#include <geometry/strategies/strategy_traits.hpp>
+
+#include <geometry/util/promotion_traits.hpp>
+
+/*!
+\defgroup distance distance: distance calculation algorithms
+The distance algorithm returns the distance between two geometries. The distance is always returned
+as a double type, regardless of the input type, because the distance between integer coordinates is
+a square root and might be a double.
+\note
+All primary distance functions return a std::pair<double, bool> with (distance, squared)
+if squared=true, it is the squared distance, otherwise it is the distance.
+This is for efficiency, often distance is used for comparisons only and then squared is OK.
+However, some algorithms such as great circle do NOT use sqrt in their formula and then
+it is not necessary to first calculate the sqr and lateron take the sqrt
+*/
+
+namespace geometry
+{
+
+
+ namespace impl
+ {
+ namespace distance
+ {
+ template <typename P1, typename P2, typename S>
+ inline distance_result point_to_point(const P1& p1, const P2& p2, const S& strategy)
+ {
+ return strategy(p1, p2);
+ }
+
+ template<typename P, typename L, typename S>
+ inline distance_result point_to_linestring(const P& p, const L& ln, const S& strategy)
+ {
+ if (ln.size() <= 0)
+ {
+ return distance_result(0, false);
+ }
+
+ // line of one point: return point square_distance
+ typename L::const_iterator it = ln.begin();
+ if (ln.size() == 1)
+ {
+ typename S::distance_strategy_type pp;
+ return pp(p, *it);
+ }
+
+ typedef const_segment<typename L::point_type> CS;
+
+ // start with first segment distance
+ typename L::const_iterator prev = it++;
+
+ typename strategy_traits<P>::point_segment_distance f2;
+ distance_result d = f2(p, CS(*prev, *it));
+
+ // check if other segments are closer
+ prev = it++;
+ while(it != ln.end())
+ {
+ distance_result ds = f2(p, CS(*prev, *it));
+ if (ds.first <= std::numeric_limits<double>::epsilon())
+ {
+ return distance_result(0, false);
+ }
+ else if (ds.first < d.first)
+ {
+ d = ds;
+ }
+ prev = it++;
+ }
+ return d;
+ }
+
+ } // namespace distance
+
+ } // namespace impl
+
+
+
+ /*!
+ \brief Calculate distance between two points
+ \ingroup distance
+ \details This version of distance calculates the distance between two points, using the specified strategy
+ \param p1 first point
+ \param p2 second point
+ \param strategy strategy to calculate distance between two points
+ \return the distance
+ \par Example:
+ Example showing distance calculation of two lat long points, using the accurate Vincenty approximation
+ \dontinclude doxygen_examples.cpp
+ \skip example_distance_point_point_strategy
+ \line {
+ \until }
+ */
+ template <typename P1, typename P2, typename S>
+ inline double distance(const P1& p1, const P2& p2, const S& strategy)
+ {
+ distance_result result = impl::distance::point_to_point(p1, p2, strategy);
+ return result;
+ }
+
+ /*!
+ \brief Calculate distance between two points
+ \ingroup distance
+ \details This version of distance calculates the distance between two points, using the default distance-calculation-strategy
+ \param p1 first point
+ \param p2 second point
+ \return the distance
+ \note The two point may be of different types, if there is a strategy_traits specialization for this type combination
+ \par Example:
+ Example showing distance calculation of two points, in xy and in latlong coordinates
+ \dontinclude doxygen_examples.cpp
+ \skip example_distance_point_point
+ \line {
+ \until }
+ */
+ template <typename P1, typename P2>
+ inline double distance(const P1& p1, const P2& p2)
+ {
+ return distance(p1, p2, typename strategy_traits<P1, P2>::point_distance());
+ }
+
+
+ /*!
+ \brief Calculate distance between a point and a linestring
+ \ingroup distance
+ \details This version of distance calculates the distance between a point and a linestring, using the default strategy
+ \param p point
+ \param ln linestring
+ \return the distance
+ \note The point might be of another type the points in the linestring, if there is a strategy_traits
+ specialization for this type combination
+ */
+ template<typename P1, typename P2,
+ template<typename,typename> class V, template<typename> class A>
+ inline double distance(const P1& p, const linestring<P2, V, A>& ln)
+ {
+ return distance(p, ln,
+ typename strategy_traits<P1, P2>::point_segment_distance());
+ }
+
+ /*!
+ \brief Calculate distance between a point and a linestring
+ \ingroup distance
+ \details This version of distance calculates the distance between a point and a linestring, using the specified strategy
+ \param p point
+ \param ln linestring
+ \param strategy strategy to calculate distance of point to segment
+ \return the distance
+ \note The point might be of another type the points in the linestring, if the specified strategy allows this
+ \note The strategy might implement an enclosed point-point distance strategy
+ */
+ template<typename P1, typename P2,
+ template<typename,typename> class V, template<typename> class A, typename S>
+ inline double distance(const P1& p, const linestring<P2, V, A>& ln, const S& strategy)
+ {
+ distance_result result = impl::distance::point_to_linestring(p, ln, strategy);
+ return result;
+ }
+
+
+} // namespace geometry
+
+
+#endif // _GEOMETRY_DISTANCE_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/dot_product.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/dot_product.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,57 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008
+// 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 _GEOMETRY_DOT_PRODUCT_HPP
+#define _GEOMETRY_DOT_PRODUCT_HPP
+
+
+#include <geometry/concepts/point_traits.hpp>
+
+
+namespace geometry
+{
+ namespace impl
+ {
+ template <int I, int N>
+ struct dot_product_maker
+ {
+ template <typename P1, typename P2>
+ static typename point_traits<P1>::coordinate_type
+ run(const P1& p1, const P2& p2)
+ {
+ return get<I>(p1)*get<I>(p2)
+ + dot_product_maker<I+1, N>::run(p1, p2);
+ }
+ };
+
+ template <int N>
+ struct dot_product_maker<N, N>
+ {
+ template <typename P1, typename P2>
+ static typename point_traits<P1>::coordinate_type
+ run(const P1& p1, const P2& p2)
+ {
+ return get<N>(p1)*get<N>(p2);
+ }
+ };
+
+ } // namespace impl
+
+
+ template <typename P1, typename P2>
+ typename point_traits<P1>::coordinate_type
+ dot_product(const P1& p1, const P2& p2)
+ {
+ return impl::dot_product_maker<0, point_traits<P1>::coordinate_count - 1>::run(p1, p2);
+ }
+
+} // namespace geometry
+
+
+#endif

Added: sandbox/SOC/2008/spacial_indexing/geometry/envelope.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/envelope.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,208 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_ENVELOPE_HPP
+#define _GEOMETRY_ENVELOPE_HPP
+
+
+#include <geometry/geometry.hpp>
+#include <geometry/circle.hpp>
+#include <geometry/box.hpp>
+#include <geometry/grow.hpp>
+#include <geometry/copy.hpp>
+
+#include <geometry/strategies/strategy_traits.hpp>
+
+
+/*!
+\defgroup envelope envelope: envelope calculation algorithms
+The envelope algorithm calculates the bounding box, or envelope, of a geometry.
+It is defined for all geometries.
+- The envelope of a point is a box with zero area, the maximum and the minimum point of the box are
+set to the point itself.
+- The envelope of a linestring is the smalles box that contains all points of the specified linestring.
+If the linestring is empty, the envelope is the inverse infinite box, that is, the minimum point is very
+large (max infinite) and the maximum point is very small (min infinite).
+- The envelope for polygon, and for all multi geometries, are defined as the envelope of the linestring
+described above.
+
+According to OGC: Envelope (): Geometry - The minimum bounding box for this Geometry,
+returned as a Geometry. The polygon is defined by the corner points of the bounding
+box [(MINX, MINY), (MAXX, MINY), (MAXX, MAXY), (MINX, MAXY), (MINX, MINY)].
+
+Implemented in the Geometry library: The minimum bounding box, always as a box, having min <= max
+
+Todo:
+- add versions having iterators
+- add strategy as an option in most algorithms
+*/
+
+namespace geometry
+{
+
+ namespace impl
+ {
+ namespace envelope
+ {
+ // Calculate envelope of a point. It is coordinate-neutral, should work
+ // for both point_xy and point_ll
+ template<typename B, typename P>
+ inline void envelope_point(const P& p, B& mbr)
+ {
+ copy_coordinates(p, mbr.min());
+ copy_coordinates(p, mbr.max());
+ }
+
+ // Calculate envelope of a circle, currently only for point_xy
+ template<typename B, typename C>
+ inline void envelope_circle(const C& c, B& mbr)
+ {
+ mbr.min().x(c.center().x() - c.radius());
+ mbr.min().y(c.center().y() - c.radius());
+ mbr.max().x(c.center().x() + c.radius());
+ mbr.max().y(c.center().y() + c.radius());
+ }
+
+ // Generic vector/container versions, working for linear_ring/line
+ template<typename B, typename V, typename S>
+ inline void envelope_container(const V& v, B& mbr, const S& strategy, typename S::state_type& state)
+ {
+ for (typename V::const_iterator i = v.begin(); i != v.end(); i++)
+ {
+ strategy(*i, state);
+ }
+ }
+ template<typename B, typename V, typename S>
+ inline void envelope_container(const V& v, B& mbr, const S& strategy)
+ {
+ typename S::state_type state;
+ for (typename V::const_iterator i = v.begin(); i != v.end(); i++)
+ {
+ strategy(*i, state);
+ }
+ state.envelope(mbr);
+ }
+
+ // For polygon inspecting outer linear_ring is sufficient
+ template<typename B, typename Y, typename S>
+ inline void envelope_polygon(const Y& poly, B& mbr, const S& strategy)
+ {
+ typename S::state_type state;
+ envelope_container(poly.outer(), mbr, strategy, state);
+ state.envelope(mbr);
+ }
+
+ } // namespace envelope
+ } // namespace impl
+
+
+
+ /*!
+ \brief Calculate envelope of a point
+ \ingroup envelope
+ \details The envelope of a point is a box containing just the point itself. It is provided
+ for consistence, on itself it is not useful.
+ \param p the point
+ \param b the box receiving the envelope
+ \note It does not RETURN the envelope. The type of the envelope-points might be different
+ from the type of the specified point.
+ */
+ template<typename PB, typename T, size_t D>
+ inline void envelope(const point<T, D>& p, box<PB>& b)
+ {
+ impl::envelope::envelope_point(p, b);
+ }
+
+
+ /*!
+ \brief Calculate envelope of a circle
+ \ingroup envelope
+ \details The envelope of a circle is a box containing enclosing the circle
+ \param c the circle
+ \param b the box receiving the envelope
+ \note Currently only implemented for point_xy
+ */
+ template<typename PB, typename C, typename T>
+ inline void envelope(const circle<C, T>& c, box<PB>& b)
+ {
+ impl::envelope::envelope_circle(c, b);
+ }
+
+ /*!
+ \brief Calculate envelope of a linestring
+ \ingroup envelope
+ \details The envelope of a linestring just contains all points of the linestring,
+ using the default strategy
+ \param ls the linestring
+ \param b the box receiving the envelope
+ \par Example:
+ Example showing envelope calculation
+ \dontinclude doxygen_examples.cpp
+ \skip example_envelope_linestring
+ \line {
+ \until }
+ */
+ template<typename PB, typename P, template<typename,typename> class V, template<typename> class A>
+ inline void envelope(const linestring<P, V, A>& ls, box<PB>& b)
+ {
+ impl::envelope::envelope_container(ls, b, typename strategy_traits<PB, P>::envelope());
+ }
+
+ /*!
+ \brief Calculate envelope of a linear ring
+ \ingroup envelope
+ \details The envelope of a linear ring just contains all points of the ring,
+ using the default strategy
+ \param ring the linear_ring
+ \param b the box receiving the envelope
+ */
+ template<typename PB, typename P, template<typename,typename> class V, template<typename> class A>
+ inline void envelope(const linear_ring<P, V, A>& ring, box<PB>& b)
+ {
+ impl::envelope::envelope_container(ring, b, typename strategy_traits<PB, P>::envelope());
+ }
+
+ /*!
+ \brief Calculate envelope of a polygon
+ \ingroup envelope
+ \details The envelope of a linestring just contains all points of the polygon,
+ using the default strategy
+ \param poly the polygon
+ \param b the box receiving the envelope
+ \par Example:
+ Example showing envelope calculation, using point_ll latlong points
+ \dontinclude doxygen_examples.cpp
+ \skip example_envelope_polygon
+ \line {
+ \until }
+ */
+ template<typename PB, typename PP,
+ template<typename,typename> class VP,
+ template<typename,typename> class VR,
+ template<typename> class AP,
+ template<typename> class AR>
+ inline void envelope(const polygon<PP, VP, VR, AP, AR>& poly, box<PB>& b)
+ {
+ impl::envelope::envelope_polygon(poly, b, typename strategy_traits<PB, PP>::envelope());
+ }
+
+ template<typename PB, typename PP,
+ template<typename,typename> class VP,
+ template<typename,typename> class VR,
+ template<typename> class AP,
+ template<typename> class AR,
+ typename S>
+ inline void envelope(const polygon<PP, VP, VR, AP, AR>& poly, box<PB>& b, const S& strategy)
+ {
+ impl::envelope::envelope_polygon(poly, b, strategy);
+ }
+
+
+} // namespace geometry
+
+
+#endif // _GEOMETRY_ENVELOPE_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/for_each_coordinate.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/for_each_coordinate.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,59 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008
+// 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 _GEOMETRY_FOR_EACH_COORDINATE_HPP
+#define _GEOMETRY_FOR_EACH_COORDINATE_HPP
+
+#include "boost/config.hpp"
+
+#include <geometry/concepts/point_traits.hpp>
+
+
+namespace geometry
+{
+ namespace impl
+ {
+ template <typename P, int I, int N>
+ struct coordinates_scanner
+ {
+ template <typename F>
+ static void apply(P& point, F function)
+ {
+#if defined(BOOST_MSVC)
+ function.operator()<P, I>(point);
+#else
+ function.template operator()<P, I>(point);
+#endif
+ coordinates_scanner<P, I+1, N>::apply(point, function);
+ }
+ };
+
+ template <typename P, int N>
+ struct coordinates_scanner<P, N, N>
+ {
+ template <typename F>
+ static void apply(P&, F)
+ {}
+ };
+
+ } // namespace impl
+
+
+ template <typename P, typename F>
+ void for_each_coordinate(P& point, F function)
+ {
+ impl::coordinates_scanner<
+ P, 0, point_traits<P>::coordinate_count
+ >::apply(point, function);
+ }
+
+} // namespace geometry
+
+
+#endif

Added: sandbox/SOC/2008/spacial_indexing/geometry/foreach.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/foreach.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,330 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_FOREACH_HPP
+#define _GEOMETRY_FOREACH_HPP
+
+/*!
+\defgroup loop loop: Loops and for-each functionality
+There are several algorithms provided which walk through the points or segments
+of linestrings and polygons. They are called for_each_point, for_each_segment, after
+the standard library, and \b loop which is more adapted and of which the functor
+could break out if necessary.
+Of the for_each algorithms there is a \b const and a non-const version provided.
+*/
+
+
+#include <geometry/geometry.hpp>
+#include <geometry/segment.hpp>
+
+#include <algorithm>
+
+namespace geometry
+{
+ namespace impl
+ {
+ namespace for_each
+ {
+
+ // -----------------------------------------------------------------------------------------------
+ // Versions for visiting points
+ // -----------------------------------------------------------------------------------------------
+ template<typename P, typename F>
+ inline F each_point_point(P& p, F f)
+ {
+ f(p);
+ return (f);
+ }
+
+ template<typename V, typename F>
+ inline F each_point_container(V& v, F f)
+ {
+ return (std::for_each(v.begin(), v.end(), f));
+ }
+
+ template<typename L, typename F>
+ inline F each_point_linestring(L& ls, F f)
+ {
+ return (each_point_container(ls, f));
+ }
+
+ template<typename Y, typename F>
+ inline F each_point_polygon(Y& poly, F f)
+ {
+ f = each_point_container(poly.outer(), f);
+ for (typename Y::inner_container_type::iterator it = poly.inners().begin();
+ it != poly.inners().end(); it++)
+ {
+ f = each_point_container(*it, f);
+ }
+ return (f);
+ }
+
+
+ // -----------------------------------------------------------------------------------------------
+ // Const versions for visiting points
+ // -----------------------------------------------------------------------------------------------
+ template<typename P, typename F>
+ inline F each_point_point(const P& p, F f)
+ {
+ f(p);
+ return (f);
+ }
+
+ template<typename V, typename F>
+ inline F each_point_container(const V& v, F f)
+ {
+ return (each(v.begin(), v.end(), f));
+ }
+
+ template<typename L, typename F>
+ inline F each_point_linestring(const L& ls, F f)
+ {
+ return (each_point_container(ls, f));
+ }
+
+ template<typename Y, typename F>
+ inline F each_point_polygon(const Y& poly, F f)
+ {
+ f = each_point_container(poly.outer(), f);
+ for (typename Y::inner_container_type::const_iterator it = poly.inners().begin();
+ it != poly.inners().end(); it++)
+ {
+ f = each_point_container(*it, f);
+ }
+ return (f);
+ }
+
+
+ // -----------------------------------------------------------------------------------------------
+ // Versions for visiting segments.
+ // -----------------------------------------------------------------------------------------------
+ template<typename V, typename F>
+ inline F each_segment_container(V& v, F f)
+ {
+ typename V::iterator it = v.begin();
+ typename V::iterator previous = it++;
+ while(it != v.end())
+ {
+ segment<typename V::point_type> s(*previous, *it);
+ f(s);
+ previous = it++;
+ }
+
+ return (f);
+ }
+
+ template<typename L, typename F>
+ inline F each_segment_linestring(L& ls, F f)
+ {
+ return (each_segment_container(ls, f));
+ }
+
+ template<typename Y, typename F>
+ inline F each_segment_polygon(Y& poly, F f)
+ {
+ f = each_segment_container(poly.outer(), f);
+ for (typename Y::inner_container_type::iterator it = poly.inners().begin();
+ it != poly.inners().end(); it++)
+ {
+ f = each_segment_container(*it, f);
+ }
+ return (f);
+ }
+
+
+ // -----------------------------------------------------------------------------------------------
+ // Const versions for visiting segments.
+ // -----------------------------------------------------------------------------------------------
+ template<typename V, typename F>
+ inline F each_segment_container(const V& v, F f)
+ {
+ typename V::const_iterator it = v.begin();
+ if (it != v.end())
+ {
+ typename V::const_iterator previous = it++;
+ while(it != v.end())
+ {
+ const_segment<typename V::point_type> s(*previous, *it);
+ f(s);
+ previous = it++;
+ }
+ }
+
+ return (f);
+ }
+
+ template<typename L, typename F>
+ inline F each_segment_linestring(const L& ls, F f)
+ {
+ return (each_segment_container(ls, f));
+ }
+
+ template<typename Y, typename F>
+ inline F each_segment_polygon(const Y& poly, F f)
+ {
+ f = each_segment_container(poly.outer(), f);
+ for (typename Y::inner_container_type::const_iterator it = poly.inners().begin();
+ it != poly.inners().end(); it++)
+ {
+ f = each_segment_container(*it, f);
+ }
+ return (f);
+ }
+
+ } // namespace for_each
+
+ } // namespace impl
+
+
+ /*!
+ \brief Calls functor for point
+ \ingroup loop
+ \details Calls the functor for the specified point. Not useful on itself, provided
+ for consistance with other geometry classes.
+ */
+ template<typename P, typename F>
+ inline F for_each_point(P& p, F f)
+ {
+ return (impl::for_each::each_point_point(p, f));
+ }
+
+ /*!
+ \brief Calls functor for linestring
+ \ingroup loop
+ \details Calls the functor all points of the specified linestring
+ */
+ template<typename P,
+ template<typename,typename> class V, template<typename> class A,
+ typename F>
+ inline F for_each_point(linestring<P, V, A>& ls, F f)
+ {
+ return (impl::for_each::each_point_container(ls, f));
+ }
+
+ /*!
+ \brief Calls functor for polygon
+ \ingroup loop
+ \details Calls the functor all points of the specified polygon
+ */
+ template<typename P,
+ template<typename,typename> class VP,
+ template<typename,typename> class VR,
+ template<typename> class AP,
+ template<typename> class AR,
+ typename F>
+ inline F for_each_point(polygon<P, VP, VR, AP, AR>& poly, F f)
+ {
+ return (impl::for_each::each_point_polygon(poly, f));
+ }
+
+
+ /*!
+ \brief Calls functor for point
+ \ingroup loop
+ \details Calls the functor the specified \b const point.
+ */
+ template<typename P, typename F>
+ inline F for_each_point(const P& p, F f)
+ {
+ return (impl::for_each::each_point_point(p, f));
+ }
+
+ /*!
+ \brief Calls functor for linestring
+ \ingroup loop
+ \details Calls the functor all points of the specified \b const linestring
+ */
+ template<typename P,
+ template<typename,typename> class V, template<typename> class A,
+ typename F>
+ inline F for_each_point(const linestring<P, V, A>& ls, F f)
+ {
+ return (impl::for_each::each_point_container(ls, f));
+ }
+
+ /*!
+ \brief Calls functor for polygon
+ \ingroup loop
+ \details Calls the functor all points of the specified \b const polygon
+ */
+ template<typename P,
+ template<typename,typename> class VP,
+ template<typename,typename> class VR,
+ template<typename> class AP,
+ template<typename> class AR,
+ typename F>
+ inline F for_each_point(const polygon<P, VP, VR, AP, AR>& poly, F f)
+ {
+ return (impl::for_each::each_point_polygon(poly, f));
+ }
+
+
+ /*!
+ \brief Calls functor for linestring segments
+ \ingroup loop
+ \details Calls the functor all segments of the specified linestring
+ */
+ template<typename P,
+ template<typename,typename> class V, template<typename> class A,
+ typename F>
+ inline F for_each_segment(linestring<P, V, A>& ls, F f)
+ {
+ return (impl::for_each::each_segment_container(ls, f));
+ }
+
+ /*!
+ \brief Calls functor for polygon segments
+ \ingroup loop
+ \details Calls the functor all segments of the specified polygon
+ */
+ template<typename P,
+ template<typename,typename> class VP,
+ template<typename,typename> class VR,
+ template<typename> class AP,
+ template<typename> class AR,
+ typename F>
+ inline F for_each_segment(polygon<P, VP, VR, AP, AR>& poly, F f)
+ {
+ return (impl::for_each::each_segment_polygon(poly, f));
+ }
+
+
+
+ /*!
+ \brief Calls functor for linestring segments
+ \ingroup loop
+ \details Calls the functor all segments of the specified \b const linestring
+ */
+ template<typename P,
+ template<typename,typename> class V, template<typename> class A,
+ typename F>
+ inline F for_each_segment(const linestring<P, V, A>& ls, F f)
+ {
+ return (impl::for_each::each_segment_container(ls, f));
+ }
+
+ /*!
+ \brief Calls functor for polygon segments
+ \ingroup loop
+ \details Calls the functor all segments of the specified \b const polygon
+ */
+ template<typename P,
+ template<typename,typename> class VP,
+ template<typename,typename> class VR,
+ template<typename> class AP,
+ template<typename> class AR,
+ typename F>
+ inline F for_each_segment(const polygon<P, VP, VR, AP, AR>& poly, F f)
+ {
+ return (impl::for_each::each_segment_polygon(poly, f));
+ }
+
+
+}
+
+#endif // _GEOMETRY_FOREACH_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/fromwkt.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/fromwkt.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,304 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_FROMWKT_HPP
+#define _GEOMETRY_FROMWKT_HPP
+
+#include <geometry/geometry.hpp>
+#include <geometry/concepts/point_traits.hpp>
+#include <boost/tokenizer.hpp>
+#include <boost/lexical_cast.hpp>
+#include <boost/algorithm/string.hpp>
+
+#include <string>
+
+namespace geometry
+{
+ namespace impl
+ {
+ namespace wkt
+ {
+ // (wkt: Well Known Text, defined by OGC for all geometries and implemented by e.g. databases (MySQL, PostgreSQL))
+
+ typedef boost::tokenizer<boost::char_separator<char> > TOK;
+
+ namespace impl
+ {
+ template <typename P, int I, int N>
+ struct parsing_assigner
+ {
+ static void run(TOK::iterator& it, TOK::iterator end, P& point)
+ {
+ typedef typename point_traits<P>::coordinate_type ctype;
+
+ // Stop at end of tokens, or at "," ot ")"
+ bool finished = (it == end || *it == "," || *it == ")");
+
+ point_traits<P>::template get<I>(point) =
+ finished ?
+ // Initialize missing coordinates to default constructor (zero)
+ ctype():
+ // Use lexical_cast for conversion to double/int
+ // Note that it is much slower than atof. However, it is more standard
+ // and in parsing the change in performance falls probably away against
+ // the tokenizing
+ boost::lexical_cast<ctype>(it->c_str());
+
+ parsing_assigner<P, I+1, N>::run(finished ? it : ++it, end, point);
+ }
+ };
+
+ template <typename P, int N>
+ struct parsing_assigner<P, N, N>
+ {
+ static void run(TOK::iterator&, TOK::iterator, P&) {}
+ };
+ }
+
+ /*!
+ \brief Internal, parses coordinate sequences, strings are formated like "(1 2,3 4,...)"
+ \param it token-iterator, should be pre-positioned at "(", is post-positions after last ")"
+ \param end end-token-iterator
+ \param out Output itererator receiving coordinates
+ \return true if string starts with "(" and ends with ")" and all coordinates are parsed
+ */
+ template <typename P, typename O_IT>
+ inline bool parse_container(TOK::iterator& it, TOK::iterator end, O_IT out)
+ {
+ // Start with "("
+ if (it == end || *it != "(")
+ {
+ return false;
+ }
+ it++;
+
+ // Stop at ")"
+ while (it != end && *it != ")")
+ {
+ P point;
+ impl::parsing_assigner<P, 0, point_traits<P>::coordinate_count>::run(it, end, point);
+ //container.push_back(point);
+ out = point;
+ out++;
+ if (it != end && *it == ",")
+ {
+ it++;
+ }
+ }
+ // Should end with ")"
+ if (it != end && *it == ")")
+ {
+ it++;
+ return true;
+ }
+ return false;
+ }
+
+ /*!
+ \brief Internal, starts parsing
+ \param tokens boost tokens, parsed with separator " " and keeping separator "()"
+ \param geometry string to compare with first token
+ \return iterator put after geometry and/or optional m, z modifiers
+ */
+ inline TOK::iterator parse_begin(const TOK& tokens, const std::string& geometry)
+ {
+ TOK::iterator it = tokens.begin();
+ if (it != tokens.end() && boost::iequals(*it++, geometry))
+ {
+ while (it != tokens.end() && (boost::iequals(*it, "M")
+ || boost::iequals(*it, "Z")
+ || boost::iequals(*it, "MZ")
+ || boost::iequals(*it, "ZM")))
+ {
+ it++;
+ }
+ }
+ return it;
+ }
+
+ /*!
+ \brief Parses point from \ref WKT
+ \param wkt string containing Well-Known Text
+ \param point point receiving coordinates, if string has less than point, rest is initialized to zero
+ \return true if string starts with "POINT(". It is forgiving for last ")"
+ \note It is case insensitive and can have the WKT forms "point", "point m", "point z", "point zm", "point mz"
+ */
+ template <typename P>
+ inline bool parse_point(const std::string& wkt, P& point)
+ {
+ // Break it apart into "POINT" "(" c1 c2 c3 ... ")"
+ // WKT Coordinate string is space separated. Points in a sequence are comma separated
+ // Token iterator is thus created with " ", ",()"
+
+ TOK tokens(wkt, boost::char_separator<char>(" ", "()"));
+ TOK::iterator it = parse_begin(tokens, "point");
+ if (it != tokens.end() && *it == "(")
+ {
+ it++;
+ }
+ impl::parsing_assigner<P, 0, point_traits<P>::coordinate_count>::run(it, tokens.end(), point);
+ return true;
+ }
+
+
+
+ /*!
+ \brief Parses linestring from \ref WKT
+ \param wkt string containing Well-Known Text
+ \param line linestring which will receive the parsed coordinates
+ \return true if string starts with "LINESTRING(" (case-insensitive) and coordinate-string can be parsed
+ */
+ template <typename P, typename L>
+ inline bool parse_linestring(const std::string& wkt, L& line)
+ {
+ // Break it apart into "LINESTRING" "(" point(s) ")"
+ TOK tokens(wkt, boost::char_separator<char>(" ", ",()"));
+ TOK::iterator it = parse_begin(tokens, "linestring");
+ line.clear();
+ return parse_container<P>(it, tokens.end(), std::back_inserter(line));
+ }
+
+
+
+ /*!
+ \brief Parses polygon from \ref WKT
+ \param wkt string containing Well-Known Text
+ \param poly polygon which will be cleared and set to the specified coordinates
+ \return true if string starts with "POLYGON(" (case-insensitive) and rings can be parsed
+ */
+ template <typename Y>
+ inline bool parse_polygon(const std::string& wkt, Y& poly)
+ {
+ poly.clear();
+
+ TOK tokens(wkt, boost::char_separator<char>(" ", ",()"));
+ TOK::iterator it = parse_begin(tokens, "polygon");
+ // Polygon string begin
+ if (it != tokens.end() && *it++ == "(")
+ {
+ int n = -1;
+ // For each ring
+ while (it != tokens.end())
+ {
+ if (++n == 0)
+ {
+ parse_container<typename Y::point_type>(it, tokens.end(), std::back_inserter(poly.outer()));
+ }
+ else
+ {
+ poly.inners().resize(n);
+ parse_container<typename Y::point_type>(it, tokens.end(), std::back_inserter(poly.inners().back()));
+ }
+ if (it != tokens.end())
+ {
+ // Skip "," or ")" after container is parsed
+ it++;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+
+ } // namespace wkt
+ } // namespace impl
+
+
+ /*!
+ \brief Build a point from OGC Well-Known Text (\ref WKT)
+ \ingroup wkt
+ \param wkt string containing \ref WKT
+ \param p point which will be cleared and set to the specified point
+ \return true if \ref WKT can be parsed
+ \par Example:
+ Small example showing how to use from_wkt to build a point
+ \dontinclude doxygen_examples.cpp
+ \skip example_from_wkt_point
+ \line {
+ \until }
+ */
+ template <typename T, size_t D>
+ inline bool from_wkt(const std::string& wkt, point<T, D>& p)
+ {
+ return impl::wkt::parse_point(wkt, p);
+ }
+
+ /*!
+ \brief Parses OGC Well-Known Text (\ref WKT) and outputs using an output iterator
+ \ingroup wkt
+ \param wkt string containing \ref WKT
+ \param out output iterator
+ \return true if \ref WKT can be parsed
+ \note Because the output iterator doesn't always have the type value_type, it should be
+ specified in the function call.
+ \par Example:
+ Small example showing how to use from_wkt with an output iterator
+ \dontinclude doxygen_examples.cpp
+ \skip example_from_wkt_output_iterator
+ \line {
+ \until }
+ */
+ template<typename P, typename O_IT>
+ inline bool from_wkt(const std::string& wkt, O_IT out)
+ {
+ // Todo: maybe take this from the string, or do not call parse_begin, such that
+ // any coordinate string is parsed and outputted
+ const std::string& tag = "linestring";
+
+ impl::wkt::TOK tokens(wkt, boost::char_separator<char>(" ", ",()"));
+ impl::wkt::TOK::iterator it = impl::wkt::parse_begin(tokens, tag);
+ return impl::wkt::parse_container<P>(it, tokens.end(), out);
+ }
+
+
+ /*!
+ \brief Build a linestring from OGC Well-Known Text (\ref WKT)
+ \ingroup wkt
+ \param wkt string containing \ref WKT
+ \param line linestring which will be cleared and set to the specified points
+ \return true if \ref WKT can be parsed
+ \par Example:
+ Small example showing how to use from_wkt to build a linestring
+ \dontinclude doxygen_examples.cpp
+ \skip example_from_wkt_linestring
+ \line {
+ \until }
+ */
+ template<typename P, template<typename,typename> class V, template<typename> class A>
+ inline bool from_wkt(const std::string& wkt, linestring<P, V, A>& line)
+ {
+ return impl::wkt::parse_linestring<P>(wkt, line);
+ }
+
+ /*!
+ \brief Build a polygon from OGC Well-Known Text (\ref WKT)
+ \ingroup wkt
+ \param wkt string containing \ref WKT
+ \param poly polygon which will be cleared and set to the specified polygon
+ \return true if \ref WKT can be parsed to the polygon (starts with "POLYGON", has valid rings and coordinates)
+ \par Example:
+ Small example showing how to use from_wkt to build a polygon
+ \dontinclude doxygen_examples.cpp
+ \skip example_from_wkt_polygon
+ \line {
+ \until }
+ */
+ template<typename P,
+ template<typename,typename> class VP,
+ template<typename,typename> class VR,
+ template<typename> class AP,
+ template<typename> class AR>
+ inline bool from_wkt(const std::string& wkt, geometry::polygon<P, VP, VR, AP, AR>& poly)
+ {
+ return impl::wkt::parse_polygon(wkt, poly);
+ }
+
+
+}
+
+#endif // _GEOMETRY_FROMWKT_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/geometry.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/geometry.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,273 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_GEOMETRY_HPP
+#define _GEOMETRY_GEOMETRY_HPP
+
+#include <vector>
+#include <limits>
+#include <cmath>
+#include <stdexcept>
+
+#include <geometry/concepts/point_traits.hpp>
+#include <geometry/util/math.hpp>
+
+#include <boost/numeric/conversion/bounds.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/assert.hpp>
+
+namespace geometry
+{
+
+ /// Enumeration to initialize in constructor for point/envelope
+ enum init {init_zero, init_min_infinite, init_max_infinite, init_inverse};
+
+
+
+
+ /*!
+ \brief Basic point class, having coordinates dfined in a neutral way
+ \par Template parameters:
+ - \a T numeric type, for example double, float, int
+ - \a D number of coordinates, for example 2
+ */
+ template<typename T, size_t D>
+ class point
+ {
+ public :
+ // Member type/const
+ typedef T coordinate_type;
+ static const size_t coordinate_count = D;
+
+
+ /// Default constructor, no initialization at all
+ inline point()
+ {}
+
+ /// Constructs with one, or optionally two or three values
+ inline point(const T& v0, const T& v1 = 0, const T& v2 = 0)
+ {
+ if (D >= 1) m_values[0] = v0;
+ if (D >= 2) m_values[1] = v1;
+ if (D >= 3) m_values[2] = v2;
+ }
+
+ /// Constructs with an option
+ inline point(init option)
+ {
+ switch(option)
+ {
+ case init_zero :
+ {
+ for (register size_t i = 0; i < D; i++)
+ {
+ // Use the template-init-zero-construction to init at zero
+ m_values[i] = T();
+ }
+ }
+ break;
+ case init_min_infinite :
+ {
+ for (register size_t i = 0; i < D; i++)
+ {
+ m_values[i] = boost::numeric::bounds<T>::lowest();
+ }
+ }
+ break;
+ case init_max_infinite :
+ {
+ for (register size_t i = 0; i < D; i++)
+ {
+ m_values[i] = boost::numeric::bounds<T>::highest();
+ }
+ }
+ break;
+ case init_inverse :
+ throw std::invalid_argument("The init_reverse option cannot be used here");
+ break;
+ }
+ }
+
+ /// Compile time access to coordinate values
+ template <size_t K>
+ //inline void value(T const& v)
+ inline T& get()
+ {
+ BOOST_STATIC_ASSERT(K < D);
+ //m_values[K] = v;
+ return m_values[K];
+ }
+
+ template <size_t K>
+ inline const T& get() const
+ {
+ BOOST_STATIC_ASSERT(K < D);
+ return m_values[K];
+ }
+
+
+ /// Examine if point is equal to other point
+ inline bool operator==(const point& other) const
+ {
+ for (register size_t i = 0; i < D; i++)
+ {
+ if (! equals(m_values[i], other.m_values[i]))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /// Examine if points are NOT equal
+ inline bool operator!=(const point& other) const
+ {
+ return ! operator==(other);
+ }
+
+ private :
+ T m_values[D];
+ };
+
+
+ /*!
+ \brief 2D point in Cartesian coordinate system
+ \par Template parameters:
+ - \a T numeric type, arguments can be, for example, double, float, int
+ */
+ template<typename T>
+ class point_xy : public point<T, 2>
+ {
+ public :
+ /// Default constructor, does not initialize anything
+ inline point_xy() : point<T, 2>() {}
+ /// Constructor with x/y values
+ inline point_xy(const T& x, const T& y) : point<T, 2>(x, y) {}
+ /// Constructor with an option
+ inline point_xy(init option) : point<T, 2>(option) {}
+
+ // Note that the this->template qualifiers are not necessary for MS VS 2005, but they
+ // are required for GCC, and are standard (C++ templates, The Complete Guide, page 132)
+
+ /// Get x-value
+ inline const T& x() const { return this->template get<0>(); }
+ /// Get y-value
+ inline const T& y() const { return this->template get<1>(); }
+
+ /// Set x-value
+ inline void x(T const & v) { this->template get<0>() = v; }
+ /// Set y-value
+ inline void y(T const & v) { this->template get<1>() = v; }
+
+ /// Compare two points
+ inline bool operator<(const point_xy& other) const
+ {
+ return equals(x(), other.x()) ? y() < other.y() : x() < other.x();
+ }
+ };
+
+
+ /*!
+ \brief Helper class for derived classes or algorithms to conveniently define member characteristics
+ \details Defines the following:
+ - point_type
+ - coordinate_type
+ - coordinate_count (size_t)
+ Linestring, polygon, etc can be derived from this class and, hence, define these characteristics
+ \par Template parameters:
+ - \a P point type
+ */
+ template<typename P>
+ class geometry_traits
+ {
+ public :
+ typedef P point_type;
+ typedef typename point_traits<P>::coordinate_type coordinate_type;
+ static const size_t coordinate_count = point_traits<P>::coordinate_count;
+ };
+
+
+ /*!
+ \brief A linestring (named so by OGC) is a collection (probably a vector) of points.
+ \par Template parameters:
+ - \a P point type
+ - \a V optional container type, for example std::vector, std::list, std::deque
+ - \a A optional container-allocator-type
+ (see http://accu.org/index.php/journals/427#ftn.d0e249 )
+ \note This small but complex class is enough to define a linestring
+ */
+ template<typename P,
+ template<typename,typename> class V = std::vector,
+ template<typename> class A = std::allocator>
+ class linestring : public V<P, A<P> >, public geometry_traits<P>
+ {
+ };
+
+
+
+ /*!
+ \brief A linear_ring (linear linear_ring) is a closed line which should not be selfintersecting
+ \par Template parameters:
+ - \a P point type
+ - \a V optional container type, for example std::vector, std::list, std::deque
+ - \a A optional container-allocator-type
+ */
+ template<typename P,
+ template<typename,typename> class V = std::vector,
+ template<typename> class A = std::allocator>
+ class linear_ring : public V<P, A<P> >, public geometry_traits<P>
+ {
+ };
+
+
+ /*!
+ \brief The \b polygon contains an outer ring and zero or more inner rings.
+ \par Template parameters:
+ - \a P point type
+ - \a VR optional container type for inner rings, for example std::vector, std::list, std::deque
+ - \a VP optional container type for points, for example std::vector, std::list, std::deque
+ - \a AR container-allocator-type
+ - \a AP container-allocator-type
+ \note The container collecting the points in the rings can be different from the
+ container collecting the inner rings. They all default to vector.
+ */
+ template<typename P,
+ template<typename,typename> class VP = std::vector,
+ template<typename,typename> class VR = std::vector,
+ template<typename> class AP = std::allocator,
+ template<typename> class AR = std::allocator>
+ class polygon : public geometry_traits<P>
+ {
+ public :
+ // Member types
+ typedef linear_ring<P, VP, AP> ring_type;
+ typedef VR<ring_type , AR<ring_type > > inner_container_type;
+
+ inline const ring_type& outer() const { return m_outer; }
+ inline const inner_container_type & inners() const { return m_inners; }
+
+ inline ring_type& outer() { return m_outer; }
+ inline inner_container_type & inners() { return m_inners; }
+
+ /// Utility method, clears outer and inner rings
+ inline void clear()
+ {
+ m_outer.clear();
+ m_inners.clear();
+ }
+
+ private :
+ ring_type m_outer;
+ inner_container_type m_inners;
+ };
+
+
+
+} // namespace geometry
+
+
+#endif // _GEOMETRY_GEOMETRY_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/grow.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/grow.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,102 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_GROW_HPP
+#define _GEOMETRY_GROW_HPP
+
+// Grow functions for boxes
+
+#include <geometry/geometry.hpp>
+#include <geometry/arithmetic.hpp>
+#include <geometry/box.hpp>
+
+namespace geometry
+{
+ namespace impl
+ {
+ namespace grow
+ {
+
+ template <typename PS, typename PD, int I, int N>
+ struct check_minmax
+ {
+ static void check(const PS& source, PD& min, PD& max)
+ {
+ typedef typename point_traits<PS>::coordinate_type T;
+ const T& coordinate = get<I>(source);
+
+ if (coordinate < get<I>(min))
+ {
+ get<I>(min) = coordinate;
+ }
+ if (coordinate > get<I>(max))
+ {
+ get<I>(max) = coordinate;
+ }
+
+ check_minmax<PS, PD, I+1, N>::check(source, min, max);
+ }
+ };
+
+ template <typename PS, typename PD, int N>
+ struct check_minmax<PS, PD, N, N>
+ {
+ static void check(const PS& source, PD& min, PD& max)
+ {}
+ };
+
+ // Changes an box b such that it also contains point p
+ template<typename B, typename P>
+ inline void grow_p(B& b, const P& p)
+ {
+ check_minmax<typename B::point_type, P, 0,
+ point_traits<P>::coordinate_count>::check(p, b.min(), b.max());
+ }
+
+ // Changes an box such that box is also contained by the box
+ template<typename B1, typename B2>
+ inline void grow_b(B1& b, const B2& other)
+ {
+ grow_p(b, other.min());
+ grow_p(b, other.max());
+ }
+
+ // Extends an box with the same amount in all directions
+ template<typename B, typename T>
+ inline void grow_t(B& b, const T& value)
+ {
+ add_value(b.min(), -value);
+ add_value(b.max(), +value);
+ }
+
+ } // namespace grow
+ } // namespace impl
+
+ // Changes an box such that point p is also contained by the box
+ template<typename P>
+ inline void grow(box<P>& b, const P& p)
+ {
+ impl::grow::grow_p(b, p);
+ }
+
+ // Changes an box such that box is also contained by the box
+ template<typename P>
+ inline void grow(box<P>& b, const box<P>& other)
+ {
+ impl::grow::grow_b(b, other);
+ }
+
+ // Extends an box with the same amout in all directions
+ template<typename P, typename T>
+ inline void grow(box<P>& b, const T& value)
+ {
+ impl::grow::grow_t(b, value);
+ }
+
+};
+
+#endif // _GEOMETRY_GROW_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/intersection.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/intersection.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,25 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_INTERSECTION_HPP
+#define _GEOMETRY_INTERSECTION_HPP
+
+#include <geometry/intersection_segment.hpp>
+#include <geometry/intersection_linestring.hpp>
+//#include <geometry/intersection_polygon.hpp> not in preview
+
+
+
+/*!
+\defgroup intersection intersection: intersection algorithms
+The intersection algorithm intersects two geometries, resulting in a third geometry. Intersection
+can be implemented for OGC geometries. Besides that an often used intersection is the intersection
+of a linestring or a polygon with a box. This is normally called a clip.
+*/
+
+
+#endif //_GEOMETRY_INTERSECTION_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/intersection_linestring.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/intersection_linestring.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,248 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_INTERSECTION_LINESTRING_HPP
+#define _GEOMETRY_INTERSECTION_LINESTRING_HPP
+
+#include <geometry/geometry.hpp>
+#include <geometry/segment.hpp>
+#include <geometry/box.hpp>
+
+namespace geometry
+{
+ namespace strategy
+ {
+ namespace intersection
+ {
+ /*!
+ \brief Linestring clipping algorithm after Liang Barsky
+ \details The Liang-Barsky lien clipping algorithm clips a line with a clipping box.
+ It is slightly adapted in the sense that it returns which points are clipped
+ \author Barend Gehrels, and the following recourses
+ - A tutorial: http://www.skytopia.com/project/articles/compsci/clipping.html
+ - a German applet: http://ls7-www.cs.uni-dortmund.de/students/projectgroups/acit/lineclip.shtml
+ \par Template parameters:
+ - \a PB point type of clipping box
+ - \a PS point type of segments to be clipped
+ */
+ template<typename PB, typename PS>
+ class liang_barsky
+ {
+ private :
+ inline bool check_edge(const double& p, const double& q, double &t1, double &t2) const
+ {
+ bool visible = true;
+
+ if(p < 0)
+ {
+ double r = q / p;
+ if(r > t2) visible = false;
+ else if(r > t1) t1 = r;
+ }
+ else if(p > 0)
+ {
+ double r = q / p;
+ if(r < t1) visible = false;
+ else if(r < t2) t2 = r;
+ }
+ else
+ {
+ if(q < 0) visible = false;
+ }
+
+ return visible;
+ }
+
+ public :
+ bool clip_segment(const box<PB>& b, segment<PS>& s, bool& sp1_clipped, bool& sp2_clipped) const
+ {
+ typedef typename select_type_traits<typename PB::coordinate_type, typename PS::coordinate_type>::type T;
+
+ double t1 = 0;
+ double t2 = 1;
+
+ T dx = s.second.x() - s.first.x();
+ T dy = s.second.y() - s.first.y();
+
+ T p1 = -dx;
+ T p2 = dx;
+ T p3 = -dy;
+ T p4 = dy;
+
+ T q1 = s.first.x() - b.min().x();
+ T q2 = b.max().x() - s.first.x();
+ T q3 = s.first.y() - b.min().y();
+ T q4 = b.max().y() - s.first.y();
+
+ if(check_edge(p1, q1, t1, t2) // left
+ && check_edge(p2, q2, t1, t2) // right
+ && check_edge(p3, q3, t1, t2) // bottom
+ && check_edge(p4, q4, t1, t2) // top
+ )
+ {
+ sp1_clipped = t1 > 0;
+ sp2_clipped = t2 < 1;
+
+ // Todo, maybe: round coordinates in case of integer? define some round_traits<> or so?
+ // Take boost-round of Fernando
+ if (sp2_clipped)
+ {
+ s.second.x(s.first.x() + t2 * dx);
+ s.second.y(s.first.y() + t2 * dy);
+ }
+
+ if(sp1_clipped)
+ {
+ s.first.x(s.first.x() + t1 * dx);
+ s.first.y(s.first.y() + t1 * dy);
+ }
+
+ return true;
+ }
+
+ return false;
+ }
+
+ template<typename L, typename O_IT>
+ inline void add(L& line_out, O_IT out) const
+ {
+ if (! line_out.empty())
+ {
+ *out = line_out;
+ out++;
+ line_out.clear();
+ }
+ }
+ };
+ }
+ }
+
+
+ namespace impl
+ {
+ namespace intersection
+ {
+
+
+ /*!
+ \brief Clips a linestring with a box
+ \details A linestring, defined by an iterator pair, is intersected (clipped) by the specified box
+ and the resulting linestring, or pieces of linestrings, are sent to the specified output operator.
+ \par Template parameters:
+ - \a L linestring type, could be "linestring" or std::vector<point>, it should match the output iterator
+ - \a B box type
+ - \a IT in iterator type
+ - \a O_IT output iterator type
+ - \a S strategy, a clipping strategy which should implement the methods "clip_segment" and "add"
+ \note The first template parameter should be specified, it cannot be deduced from the parameters and
+ there is no convenient way (I see) to construct it by a traits class
+ */
+ template <typename L, typename B, typename IT, typename O_IT, typename S>
+ O_IT clip_linestring_with_box(const B& b, IT begin, IT end, O_IT out, const S& strategy)
+ {
+ if (begin == end)
+ {
+ return (out);
+ }
+
+ L line_out;
+
+ IT vertex = begin;
+ IT previous = vertex++;
+ while(vertex != end)
+ {
+ typename IT::value_type p1 = *previous;
+ typename IT::value_type p2 = *vertex;
+
+ // Clip the segment. Five situations:
+ // 1. Segment is invisible, finish line if any (shouldn't occur)
+ // 2. Segment is completely visible. Add (p1)-p2 to line
+ // 3. Point 1 is invisible (clipped), point 2 is visible. Start new line from p1-p2...
+ // 4. Point 1 is visible, point 2 is invisible (clipped). End the line with ...p2
+ // 5. Point 1 and point 2 are both invisible (clipped). Start/finish an independant line p1-p2
+ //
+ // This results in:
+ // a. if p1 is clipped, start new line
+ // b. if segment is partly or completely visible, add the segment
+ // c. if p2 is clipped, end the line
+
+ bool c1, c2;
+ segment<typename IT::value_type> s(p1, p2);
+ if (! strategy.clip_segment(b, s, c1, c2))
+ {
+ strategy.add(line_out, out);
+ }
+ else
+ {
+ // a. If necessary, finish the line and add a start a new one
+ if (c1)
+ {
+ strategy.add(line_out, out);
+ }
+
+ // b. Add p1 only if it is the first point, then add p2
+ if (line_out.empty())
+ {
+ line_out.push_back(p1);
+ }
+ line_out.push_back(p2);
+
+ // c. If c2 is clipped, finish the line
+ if (c2)
+ {
+ strategy.add(line_out, out);
+ }
+ }
+ previous = vertex++;
+ }
+ // Add last part
+ strategy.add(line_out, out);
+ return (out);
+ }
+
+ } // namespace intersection
+ } // namespace impl
+
+
+ /*!
+ \brief Clips a linestring with a box
+ \ingroup intersection
+ \details A linestring is intersected (clipped) by the specified box
+ and the resulting linestring, or pieces of linestrings, are sent to the specified output operator.
+ \param b the clipping box
+ \param ls the linestring to be clipped
+ \param out the output iterator
+ \return the output iterator
+ \par Template parameters:
+ - \a PB point type of box
+ - \a PL point type of linestring
+ - \a V container type
+ - \a A allocator type
+ - \a O_IT output iterator
+ \note The default clipping strategy, Liang-Barsky, is used. The algorithm is currently only
+ implemented for 2D xy points. It could be generic for most ll cases, but not across the 180
+ meridian so that issue is still on the todo-list.
+ \par Example:
+ Example showing clipping of linestring with box
+ \dontinclude doxygen_examples.cpp
+ \skip example_intersection_linestring1
+ \line {
+ \until }
+ */
+ template<typename PB, typename PL,
+ template<typename,typename> class V, template<typename> class A,
+ typename O_IT>
+ inline O_IT intersection(const box<PB>& b, const linestring<PL, V, A>& ls, O_IT out)
+ {
+ strategy::intersection::liang_barsky<PB, PL> strategy;
+ return (impl::intersection::clip_linestring_with_box<linestring<PL, V, A> > (b, ls.begin(), ls.end(), out, strategy));
+ }
+
+} // namespace
+
+
+#endif //_GEOMETRY_INTERSECTION_LINESTRING_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/intersection_polygon.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/intersection_polygon.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,617 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_INTERSECTION_POLYGON_HPP
+#define _GEOMETRY_INTERSECTION_POLYGON_HPP
+
+#include <geometry/geometry.hpp>
+#include <geometry/box.hpp>
+#include <geometry/segment.hpp>
+#include <geometry/area.hpp>
+#include <geometry/distance.hpp>
+#include <geometry/within.hpp>
+
+#include <geometry/intersection_segment.hpp>
+
+#include <exception>
+
+namespace geometry
+{
+
+ //------------------------------------------------------------------------------------------------------------------------
+ // Weiler-Atherton approach to clip a polygon within a rectangle
+ // Can be relatively easily extended to clip polygon-polygon
+ // (Somewhat combined with "segment-code" idea of Cohen-Sutherland to see which segment needs clipping)
+
+ // Keep bitwise.
+ // See, e.g., http://www.sunshine2k.de/stuff/Java/CohenSutherland/CohenSutherland.html
+ const char cohen_sutherland_top = 1; // 0001
+ const char cohen_sutherland_bottom = 2; // 0010
+ const char cohen_sutherland_right = 4; // 0100
+ const char cohen_sutherland_left = 8; // 1000
+
+
+ // Extend point type with "tag" information
+ // Weiler-Atherton:
+ // "The new vertices are tagged to indicate they are intersection vertices." --> intersection_id > 0
+ // and
+ // "Repeat steps "b" to "e" until the starting point has been reached." --> is_visited
+ template<typename P>
+ struct weiler_atherton_point : public P
+ {
+ public :
+ inline weiler_atherton_point()
+ : P(init_zero)
+ , outside(false)
+ , ring_index(-1)
+ , intersection_id(-1)
+ , is_visited(false)
+ {}
+
+ // Constructor with point
+ inline weiler_atherton_point(const P& p)
+ : P(p)
+ , outside(false)
+ , ring_index(-1)
+ , intersection_id(-1)
+ , vertex_index(-1)
+ , square_distance(0)
+ , is_visited(false)
+ {}
+
+ // Constructor with coordinates
+ inline weiler_atherton_point(const typename P::coordinate_type& x,
+ const typename P::coordinate_type& y)
+ : P(x, y)
+ , outside(false)
+ , ring_index(-1)
+ , intersection_id(-1)
+ , vertex_index(-1)
+ , square_distance(0)
+ , is_visited(false)
+ {}
+
+ // Constructor with point, Cohen-Sutherland code and linear_ring-index
+ inline weiler_atherton_point(const P& p, bool os, int r)
+ : P(p)
+ , outside(os)
+ , ring_index(r)
+ , intersection_id(-1)
+ , vertex_index(-1)
+ , square_distance(0)
+ , is_visited(false)
+ {}
+
+ inline weiler_atherton_point(const P& p, int si, double d)
+ : P(p)
+ , outside(false)
+ , ring_index(-1)
+ , intersection_id(-1)
+ , vertex_index(si)
+ , square_distance(d)
+ , is_visited(false)
+ {}
+
+
+ // Operator to sort on "start vertex", then on distance
+ inline bool operator<(const weiler_atherton_point& other) const
+ {
+ if (other.vertex_index == this->vertex_index)
+ {
+ return this->square_distance < other.square_distance;
+ }
+ return this->vertex_index < other.vertex_index;
+ }
+
+ int ring_index;
+ int vertex_index;
+ bool outside;
+
+ bool is_visited;
+
+ // For intersections:
+ int intersection_id; // 1-based intersection ID
+ double square_distance; // distance to corresponding startpoing of segment
+ };
+
+
+ // Small structure to keep two indices and an ID, public
+ struct _intersection_indices
+ {
+ inline _intersection_indices(int an_id)
+ : id(an_id)
+ , subject_index(-1)
+ , clip_index(-1)
+ {}
+
+ int id;
+ int subject_index;
+ int clip_index;
+ };
+ typedef std::vector<_intersection_indices> _ii_vector;
+
+
+
+
+ template<typename P>
+ inline std::ostream& operator<< (std::ostream &s, const weiler_atherton_point<P>& p)
+ {
+ s << "(" << p.x() << ", " << p.y() << " S=" << p.vertex_index;
+
+ if (p.square_distance >= 0)
+ {
+ s << " D=" << sqrt(p.square_distance);
+ }
+ if (p.outside)
+ {
+ s << " outside";
+ }
+ if (p.intersection_id > 0)
+ {
+ s << " I=" << p.intersection_id;
+ }
+ if (p.is_visited)
+ {
+ s << " visited";
+ }
+ return s << ")";
+ }
+
+
+ template<typename B, typename P>
+ inline void _cs_clip_code(const B& b, const P& p,
+ char& code, bool& is_inside,
+ char& code_and, char& code_or, bool& has_inside)
+ {
+ code = 0;
+
+ // Note: border has to be included because of boundary cases
+ // Therefore we need a second variable to see if it is inside (including on boundary)
+
+ // Compare left/right.
+ if (p.x() <= b.min().x()) code = cohen_sutherland_left;
+ else if (p.x() >= b.max().x()) code = cohen_sutherland_right;
+
+ // Compare top/bottom
+ if (p.y() <= b.min().y()) code |= cohen_sutherland_bottom;
+ else if (p.y() >= b.max().y()) code |= cohen_sutherland_top;
+
+ code_and &= code;
+ code_or |= code;
+
+ // Check if point is lying inside clip, or on boundary
+ is_inside = within_point_in_box(p, b);
+ if (is_inside)
+ {
+ has_inside = true;
+ }
+ }
+
+
+
+ // Small utility to advance an iterator, considering the container circular
+ template<typename I>
+ void circular_next(I& it, const I& begin, const I& end)
+ {
+ it++;
+ if (it == end)
+ {
+ it = begin;
+ }
+ }
+
+ // Traverse to an unvisited intersection point on the subject polygon.
+ template<typename W>
+ void traverse_to_intersection(W& subject, W& clip, _ii_vector& indices, typename W::iterator& it)
+ {
+ for (_ii_vector::iterator iit = indices.begin(); iit != indices.end(); iit++)
+ {
+ typename W::iterator next = subject.begin() + iit->subject_index;
+ // Check both for being visited - we don't know which one was taken
+ if (! next->is_visited && ! clip[iit->clip_index].is_visited)
+ {
+ it = next;
+ std::cout << "Start with " << *it << std::endl;
+ return;
+ }
+ }
+ }
+
+ template<typename W>
+ void traverse_to_after_id(W& subject, W& clip,
+ _ii_vector& indices, bool on_subject, int id, typename W::iterator& it)
+ {
+ for (_ii_vector::iterator iit = indices.begin(); iit != indices.end(); iit++)
+ {
+ if (iit->id == id)
+ {
+ if (on_subject)
+ {
+ it = subject.begin() + iit->subject_index;
+ circular_next(it, subject.begin(), subject.end());
+ }
+ else
+ {
+ it = clip.begin() + iit->clip_index;
+ circular_next(it, clip.begin(), clip.end());
+ }
+ return;
+ }
+ }
+ throw std::exception("internal error - intersection ID not found");
+ }
+
+ template<typename W>
+ void traverse_next(W& subject, W& clip,
+ _ii_vector& indices, bool& on_subject, typename W::iterator& it)
+ {
+ // 1. Go to next point
+ typename W::iterator next = it;
+ if (on_subject)
+ {
+ circular_next(next, subject.begin(), subject.end());
+ }
+ else
+ {
+ circular_next(next, clip.begin(), clip.end());
+ }
+
+ // 2. If current was not an intersection point,
+ // or next is an intersection point, we take this next point (but only on subject)
+ // or we are on the subject polygon and next is inside the clip
+ if (it->intersection_id <= 0
+ || (on_subject && next->intersection_id > 0)
+ || (on_subject && ! next->outside))
+ {
+ it = next;
+
+ // TEMP
+ if (it->intersection_id <= 0) std::cout << "just take next " << *it << std::endl;
+ else if (on_subject && next->intersection_id > 0) std::cout << "next intersection on subject " << *it << std::endl;
+ else if (on_subject && ! next->outside) std::cout << "next inside " << *it << std::endl;
+ else std::cout << "other " << *it << std::endl;
+ // END TEMP
+ }
+ else
+ {
+ // we are on subject or on clip, on intersection, next is not an intersection,
+ // navigate to the corresponding ID on the other polygon
+ traverse_to_after_id(subject, clip, indices, !on_subject, it->intersection_id, next);
+
+ // It may never be outside polygon
+ if (!on_subject && next->outside)
+ {
+ std::cout << "return because of " << *next << std::endl;
+ return;
+ }
+
+ on_subject = ! on_subject;
+ it = next;
+
+ // TEMP
+ std::cout << "traverse to " << (on_subject ? "subject " : "clip ") << *it << std::endl;
+ // END TEMP
+ }
+ }
+
+
+ template<typename S1, typename S2, typename WAP>
+ void clip_ring_weiler_atherton_intersect_segment(
+ const S1& subject, int subject_index, std::vector<WAP>& subject_points,
+ const S2& clip, int clip_index, std::vector<WAP>& clip_points,
+ int& id, _ii_vector& indices)
+ {
+ std::vector<WAP> ip;
+ double ra, rb;
+ intersection_result r = intersection_segment(subject, clip, ra, rb, ip);
+
+ // If there are two intersection points (== overlap), discard:
+ // 1) it can be in opposite direction, they share their border there
+ // but do not intersect -> return
+ // 2) it can be in same direction, it is OK but the intersection points are calculated
+ // before/after overlap (see figure)
+
+ if (ip.size() != 1)
+ {
+ return;
+ }
+
+ std::cout << "CHECK: " << subject.first << "-" << subject.second
+ << " x " << clip.first << "-" << clip.second << std::endl;
+
+
+ // If segment of subject intersects clip, and intersection point is on the clip,
+ // we examine further
+ if (r == is_intersect)
+ {
+ r = geometry::intersection_connect_result(r, ra, rb);
+ if (r != is_intersect)
+ {
+ std::cout << "CONNECT: " << subject.first << "-" << subject.second
+ << " x " << clip.first << "-" << clip.second << std::endl;
+
+ switch(r)
+ {
+ // If it connects at at one end, always consider the subject-point:
+ // only continue if it is RIGHT of the clip
+ case is_intersect_connect_s1p1 :
+ if (point_side(clip, subject.second) >= 0) return;
+ break;
+ case is_intersect_connect_s1p2 :
+ if (point_side(clip, subject.second) >= 0) return;
+ break;
+ case is_intersect_connect_s2p1 :
+ case is_intersect_connect_s2p2 :
+ // Consider both points, at least one must be right of the clip
+ if (point_side(clip, subject.first) >= 0 && point_side(clip, subject.second) >= 0)
+ {
+ return;
+ }
+ break;
+ }
+ }
+
+ }
+
+ // Add intersection points, if any
+ for (typename std::vector<WAP>::iterator it = ip.begin(); it != ip.end(); it++)
+ {
+ // Tag the point(s) with unique id
+ it->intersection_id = ++id;
+ // Add it to intersection
+ indices.push_back(_intersection_indices(id));
+ std::cout << "INTERSECTION: " << id << " " << *it << std::endl;
+
+ // Assign index, calc distance and store for addition to subject and to clip lateron
+ it->vertex_index = subject_index;
+ it->square_distance = square_distance(subject.first, *it);
+ subject_points.push_back(*it);
+
+ it->vertex_index = clip_index;
+ it->square_distance = square_distance(clip.first, *it);
+ clip_points.push_back(*it);
+ }
+ }
+
+
+ template<typename B, typename R, typename WAP, typename WAR>
+ int clip_ring_weiler_atherton_intersect(const B& b, const R& in, int ring_index,
+ WAR& subject, std::vector<WAP>& clip, // todo, change to WAR
+ int& id, _ii_vector& indices)
+ {
+ // Some book keeping variables
+ char code_and = cohen_sutherland_left
+ | cohen_sutherland_right
+ | cohen_sutherland_top
+ | cohen_sutherland_bottom;
+ char code_or = 0;
+ bool has_inside = false;
+
+ // Define points upperleft and lowerright. Lowerleft is min, upperright is max
+ typedef typename R::point_type P;
+ P upper_left(b.min().x(), b.max().y());
+ P lower_right(b.max().x(), b.min().y());
+
+ char code_previous = 0;
+ //R::const_iterator last = in.end() - 1;
+
+ typename R::const_iterator it = in.begin();
+ typename R::const_iterator prev = it++;
+ while(it != in.end())
+ {
+ bool is_inside;
+ if (subject.empty())
+ {
+ // Add first point of out-polygon
+ _cs_clip_code(b, *prev, code_previous, is_inside, code_and, code_or, has_inside);
+ subject.push_back(WAP(*prev, !is_inside, ring_index));
+ }
+ const_segment<P> ss(*prev, *it);
+
+ char code_current;
+ _cs_clip_code(b, *it, code_current, is_inside, code_and, code_or, has_inside);
+
+ std::cout << "SGMNT: " << ss.first << "-" << ss.second << " cs " << int(code_previous) << "," << int(code_current) << std::endl;
+
+
+ // If both segments are not in same Cohen-Suth. segment, check for intersections
+ // Todo: check better, check if they are lying on same side
+ if (code_previous != code_current)
+ {
+ // Intersections are first stored in a vector, then sorted, then added, see Weiler-Atherton:
+ // "If care is taken in placement of intersections where the subject and clip polygon
+ // contours are identical in the x-y plane, no degenerate polygons will be produced by
+ // the clipping process."
+ std::vector<WAP> ips;
+
+ // Clip all four sides of box
+ clip_ring_weiler_atherton_intersect_segment(ss, -1, ips,
+ const_segment<P>(b.min(), upper_left), 0, clip, id, indices);
+ clip_ring_weiler_atherton_intersect_segment(ss, -1, ips,
+ const_segment<P>(upper_left, b.max()), 1, clip, id, indices);
+ clip_ring_weiler_atherton_intersect_segment(ss, -1, ips,
+ const_segment<P>(b.max(), lower_right), 2, clip, id, indices);
+ clip_ring_weiler_atherton_intersect_segment(ss, -1, ips,
+ const_segment<P>(lower_right, b.min()), 3, clip, id, indices);
+
+ // Add all found intersection points to subject polygon, after sorting
+ // on distance from first point. There might be up to 4 intersection points
+ // in rectangular clips, and much more on polygon clips. However, often there are zero or one
+ // intersections, sorting is not a big issue here
+ std::sort(ips.begin(), ips.end());
+ for (typename std::vector<WAP>::const_iterator pit = ips.begin(); pit != ips.end(); pit++)
+ {
+ indices[pit->intersection_id - 1].subject_index = subject.size();
+ subject.push_back(*pit);
+ }
+ }
+
+ // After intersections, add endpoint of segment to subject vector
+ subject.push_back(WAP(*it, !is_inside, ring_index));
+
+ code_previous = code_current;
+ prev = it++;
+ //circular_next(last, in.begin(), in.end());
+ }
+
+ // If all points are inside, output is original, quit
+ if (code_or == 0)
+ {
+ return 1;
+ }
+
+ // If all points are on the same side, there is no intersection possible -> output is zero and quit
+ if (code_and & cohen_sutherland_left == cohen_sutherland_left
+ || code_and & cohen_sutherland_right == cohen_sutherland_right
+ || code_and & cohen_sutherland_top == cohen_sutherland_top
+ || code_and & cohen_sutherland_bottom == cohen_sutherland_bottom)
+ {
+ return 0;
+ }
+
+ // Special case: if no points are inside, the clip box might be inside the polygon
+ // -> output clip box and quit
+ if (! has_inside)
+ {
+ // Take any point of clip and check if it is within the linear_ring
+ if (within_point_in_ring(b.min(), in))
+ {
+ return 2;
+ }
+ // If clip is not in the linear_ring, there no intersection
+ return 0;
+ }
+
+ // TODO
+
+ // Some points are inside, some are outside, clipping should go on
+ return 3;
+ }
+
+
+ template<typename B, typename Y>
+ void clip_poly_weiler_atherton(const B& b, const Y& in, std::vector<Y>& outlist)
+ {
+ typedef weiler_atherton_point<typename Y::point_type> wap;
+ typedef linear_ring<wap> wapoly;
+
+ // Weiler-Atherton:
+ // "A link is established between each pair of new vertices, permitting travel between two
+ // polygons wherever they intersect on the x-y plane."
+ // We keep this link in an index-vector
+ _ii_vector indices;
+
+ int id = 0;
+
+ // 1: create a copy of the polygon and, at the same time, add all points of "subject" and intersections with clip
+ // The copy is called, after Weiler-Atherton, the "subject"
+ // Check the Cohen-Suth.segment
+ // - to avoid unnecessary intersections (in a BOX, two consecutive inside points doesn't need to be checked)
+ // - to choose the path, lateron
+ wapoly subject, clip;
+
+ // For outerring and all rings
+ int r = clip_ring_weiler_atherton_intersect(b, in, -1, subject, clip, id, indices);
+
+
+ // If there are clip intersection points, build up the clip polyon. Add all corner points,
+ // then sort on segment-index and distance, then the clip is OK
+ clip.push_back(wap(b.min(), 0, 0.0));
+ clip.push_back(wap(typename Y::point_type(b.min().x(), b.max().y()), 1, 0.0));
+ clip.push_back(wap(b.max(), 2, 0.0));
+ clip.push_back(wap(typename Y::point_type(b.max().x(), b.min().y()), 3, 0.0));
+ clip.push_back(wap(b.min(), 4, 0.0));
+
+ std::sort(clip.begin(), clip.end());
+
+ // Update the id's of clip intersection points, now we have it
+ for (int j = 0; j < clip.size(); j++)
+ {
+ if (clip[j].intersection_id > 0)
+ {
+ indices[clip[j].intersection_id - 1].clip_index = j;
+ }
+ }
+
+ // CHECK
+ for (_ii_vector::const_iterator it = indices.begin(); it != indices.end(); it++)
+ {
+ std::cout
+ << "subj:" << it->subject_index << " " << subject[it->subject_index] << std::endl
+ << "clip:" << it->clip_index << " " << clip[it->clip_index] << std::endl;
+ }
+
+ std::cout
+ << "WA: " << std::endl
+ << "in: " << in << std::endl
+ << "subject " << subject << std::endl
+ << "clip " << clip << std::endl;
+ // END CHECK
+
+
+ // 4. build output polygon or polygons, start with an intersected point
+ // "4. The actual clipping is now performed
+ // a) An intersection vertex is removed from the first intersection list to be used as a
+ // starting point. If the list is exhausted, the clipping is complete; Go to step 5.
+ Y out;
+ typename wapoly::iterator it = subject.begin();
+ traverse_to_intersection(subject, clip, indices, it);
+ bool on_subject = true;
+ while(! it->is_visited)
+ {
+ // Add the point, but only if it differs from previous point
+ typename Y::point_type p(it->x(), it->y());
+ if (out.empty() || ! (out.back() == p))
+ {
+ out.push_back(p);
+ }
+
+ it->is_visited = true;
+
+ //std::cout << (on_subject ? "subj" : "clip") << *it << std::endl;
+
+ traverse_next(subject, clip, indices, on_subject, it);
+
+ if (it->is_visited)
+ {
+ // Close (if not closed)
+ if (! out.empty() && ! (out.front() == out.back()))
+ {
+ out.push_back(out.front());
+ }
+
+
+ outlist.push_back(out);
+ std::cout << "out: " << out << std::endl;
+ out.clear();
+
+ // Go to first unvisited intersection point, if any
+ // Else the iterator will result is_visited and it will stop
+ traverse_to_intersection(subject, clip, indices, it);
+ on_subject = true;
+ }
+ }
+ }
+
+
+
+ template<typename B, typename R, typename O>
+ void clip_y(const B& b, const R& ring_in, O out)
+ {
+ typename R::const_iterator vertex = ring_in.begin();
+ typename R::const_iterator previous = vertex++;
+ R ring_out;
+ while(vertex != ring_in.end())
+ {
+
+ }
+ }
+
+} // namespace
+
+
+#endif //_GEOMETRY_INTERSECTION_POLYGON_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/intersection_segment.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/intersection_segment.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,248 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_INTERSECTION_SEGMENT_HPP
+#define _GEOMETRY_INTERSECTION_SEGMENT_HPP
+
+#include <limits>
+#include <vector>
+
+#include <geometry/geometry.hpp>
+#include <geometry/segment.hpp>
+#include <geometry/util/math.hpp>
+#include <geometry/util/side.hpp>
+#include <geometry/util/promotion_traits.hpp>
+
+
+namespace geometry
+{
+
+
+
+ /*!
+ \brief Enumeration containing intersection types
+ */
+ enum intersection_type {is_intersect_no,
+ is_intersect,
+ is_parallel,
+ is_collinear_no, is_collinear_one, is_collinear_connect, is_collinear_overlap,
+ is_collinear_overlap_opposite, is_collinear_connect_opposite};
+
+ /*!
+ \brief Enumeration containing connection types of intersected segments
+ */
+ enum connection_type { is_connect_no,
+ is_connect_s1p1, is_connect_s1p2,
+ is_connect_s2p1, is_connect_s2p2
+ };
+
+ /*!
+ \brief Encapsulates the result of a segment intersection.
+ \details The class contains the intersection type and two parameters
+ ra and rb, indicating how the two segments connect (if they connect).
+ This connection type can be examined with the method connection_type.
+ */
+ struct intersection_result
+ {
+ intersection_result()
+ : is_type(is_intersect_no)
+ , ra(0)
+ , rb(0)
+ {}
+
+ intersection_type is_type;
+ double ra;
+ double rb;
+
+ inline connection_type get_connection_type()
+ {
+ if (is_type == is_intersect)
+ {
+ if (equals(rb, 0.0)) return is_connect_s2p1;
+ if (equals(rb, 1.0)) return is_connect_s2p2;
+ if (equals(ra, 0.0)) return is_connect_s1p1;
+ if (equals(ra, 1.0)) return is_connect_s1p2;
+ }
+ return is_connect_no;
+ }
+
+ };
+
+
+
+
+ /*!
+ \brief Calculate zero, one or two intersections of two linesegments, using Cramer's rule.
+ \ingroup intersection
+ \details Two intersections are returned if segments are on same line and (partially) overlap.
+ One intersection is returned if segments intersect
+ Intersection points is vector of points, might be yet another pointtype then points making up segment
+ \param s1 first segment
+ \param s2 second segment
+ \param out output iterator
+ \return the intersection result, a struct containing the intersection type, and two calculated
+ values which can be examined further if necessary
+ \par Template parameters:
+ - \a P type of outputted intersection point(s). Must be specified, cannot be deducted
+ from parameters. Type might be different from segment points.
+ - \a S1 first segment type, can be segment or const_segment
+ - \a S2 second segment type, can be segment or const_segment
+ - \a O_IT output iterator
+ \note <b>The algorithm is currently only implemented for 2D Cartesian points, point_xy. It
+ will be redesigned to work with strategies.</b> Algorithms to calculate segment intersections
+ on a sphere are available, see http://williams.best.vwh.net/avform.htm. This might use
+ either a point_xyz class or vector calculations from ublas.
+ \par Example:
+ Example showing intersection of two segments
+ \dontinclude doxygen_examples.cpp
+ \skip example_intersection_segment1
+ \line {
+ \until }
+ */
+ template <typename P, typename S1, typename S2, typename O_IT>
+ inline intersection_result intersection_segment(const S1& s1, const S2& s2,
+ O_IT out)
+ {
+ intersection_result result;
+
+ typedef typename select_type_traits<typename S1::coordinate_type, typename S2::coordinate_type>::type T;
+ T dx1 = s1.second.x() - s1.first.x();
+ T dx2 = s2.second.x() - s2.first.x();
+ T dy1 = s1.second.y() - s1.first.y();
+ T dy2 = s2.second.y() - s2.first.y();
+
+ T wx = s1.first.x() - s2.first.x();
+ T wy = s1.first.y() - s2.first.y();
+
+ // Calculate determinants - Cramers rule
+ T d = (dy2 * dx1) - (dx2 * dy1);
+ T a = (dx2 * wy) - (dy2 * wx);
+ T b = (dx1 * wy) - (dy1 * wx);
+
+ if(equals(d, 0))
+ {
+ if(equals(a, 0) && equals(b, 0))
+ {
+ bool vertical = equals(dx2, 0);
+
+ // Maybe change this by boost::minmax construct(s)
+
+ if (! vertical
+ && (std::min(s1.first.x(), s1.second.x()) > std::max(s2.first.x(), s2.second.x())
+ || std::min(s2.first.x(), s2.second.x()) > std::max(s1.first.x(), s1.second.x())))
+ {
+ // No overlap, segments are not connected
+ result.is_type = is_collinear_no;
+ return result;
+ }
+ else if (vertical
+ && (std::min(s1.first.y(), s1.second.y()) > std::max(s2.first.y(), s2.second.y())
+ || std::min(s2.first.y(), s2.second.y()) > std::max(s1.first.y(), s1.second.y())))
+ {
+ // No overlap, vertical segments are not connected
+ result.is_type = is_collinear_no;
+ return result;
+ }
+ else
+ {
+ // Partial or full overlap, calculate ratio in x-direction, for vertical lines in y-direction
+ // Adapted from http://www.geometryalgorithms.com/Archive/algorithm_0104/algorithm_0104B.htm
+ // Copyright 2001, softSurfer (www.softsurfer.com)
+ // This code may be freely used and modified for any purpose
+ // providing that this copyright notice is included with it.
+ // SoftSurfer makes no warranty for this code, and cannot be held
+ // liable for any real or imagined damage resulting from its use.
+ // Users of this code must verify correctness for their application.
+
+ // Segments of single point, with overlap
+ if (equals(dx1, 0) && equals(dy1, 0))
+ {
+ // Take point on first segment
+ // TODO: copy constructor only works for points with same type. Change.
+ P p(s1.first);
+ *out = p;
+ out++;
+ result.is_type = is_collinear_one;
+ return result;
+ }
+ if (equals(dx2, 0) && equals(dy2, 0))
+ {
+ P p(s2.first);
+ *out = p;
+ out++;
+ result.is_type = is_collinear_one;
+ return result;
+ }
+
+ result.ra = vertical
+ ? wy / dy2
+ : wx / dx2;
+ result.rb = vertical
+ ? (s1.second.y() - s2.first.y()) / dy2
+ : (s1.second.x() - s2.first.x()) / dx2;
+
+ result.is_type = is_collinear_overlap;
+ // Make sure a<b and a>= 0 and b<=1
+ if (result.ra > result.rb)
+ {
+ std::swap(result.ra, result.rb);
+ result.is_type = is_collinear_overlap_opposite;
+ }
+ if (result.ra < 0.0) result.ra = 0.0;
+ if (result.rb > 1.0) result.rb = 1.0;
+
+ // Calculate first intersection point
+ *out = P(s2.first.x() + result.ra * dx2, s2.first.y() + result.ra * dy2);
+ out++;
+
+ if (equals(result.ra, result.rb))
+ {
+ // Intersect with overlap at one point, segments connect
+ // They might connect in opposite direction and give different result (TODO)
+ result.is_type = is_collinear_connect;
+ return result;
+ }
+
+ // Calculate second intersection point
+ *out = P(s2.first.x() + result.rb * dx2, s2.first.y() + result.rb * dy2);
+ out++;
+ return result;
+ }
+ }
+
+ // Segments are parallel
+ result.is_type = is_parallel;
+ return result;
+ }
+
+ // Segments do intersect. Determinant d is nonzero.
+ result.ra = double(a) / double(d);
+ result.rb = double(b) / double(d);
+
+ // Check if intersection is on segment
+ if(result.ra >= 0.0 && result.ra <= 1.0
+ && result.rb >= 0.0 && result.rb <= 1.0)
+ {
+ // This is the normal case. All above are exceptions. Calculate intersection point.
+ *out = P(s1.first.x() + result.ra * dx1, s1.first.y() + result.ra * dy1);
+ out++;
+
+ result.is_type = is_intersect;
+ return result;
+ }
+
+ result.is_type = is_intersect_no;
+ return result;
+ }
+
+
+} // namespace
+
+
+#endif //_GEOMETRY_INTERSECTION_SEGMENT_HPP
+
+

Added: sandbox/SOC/2008/spacial_indexing/geometry/labelinfo.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/labelinfo.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,98 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_LABELINFO_HPP
+#define _GEOMETRY_LABELINFO_HPP
+
+
+// Algorithms to generate appropriate labelpoint(s) for all geometries
+
+
+
+#include <geometry/geometry.hpp>
+#include <geometry/centroid.hpp>
+
+namespace geometry
+{
+
+ // For a polygon the broadest line is probably the best, so two points (left/right)
+ // For a line either the centerpoint, of the longest line, or the most horizontal line,
+ // or more than two points to smooth the text around some points. So one/two or more points.
+ // For a point just return the point.
+
+ // The algorithms output to an output iterator
+ // They have a label_option to influence behaviour. Not yet implemented.
+ // Is there a better approach? Class?
+
+
+ enum label_option {label_default,
+ // line
+ label_longest, label_horizontal,
+ // polygon
+ label_centroid, label_broadest
+ };
+
+
+ template<typename P, typename MP>
+ inline void label_info_point(const P& point, label_option option, MP& mp)
+ {
+ mp.resize(1);
+ mp.front().x(point.x());
+ mp.front().y(point.y());
+ }
+
+
+ template<typename Y, typename MP>
+ inline void label_info_polygon(const Y& poly, label_option option, MP& mp)
+ {
+ mp.resize(0);
+ mp.push_back(centroid_polygon<typename MP::point_type>(poly));
+ }
+
+ template<typename B, typename MP>
+ inline void label_info_box(const B& box, label_option option, MP& mp)
+ {
+ mp.resize(0);
+ mp.push_back(centroid_box(box));
+ }
+
+
+
+
+ //-------------------------------------------------------------------------------------------------------
+ // General "label_info" versions
+ //-------------------------------------------------------------------------------------------------------
+ template<typename P, typename MP>
+ inline void label_info(const P& p, label_option option, MP& mp)
+ {
+ label_info_point(p, option, mp);
+ }
+
+
+
+ template<typename P, typename MP>
+ inline void label_info(const box<P>& b, label_option option, MP& mp)
+ {
+ label_info_box(b, option, mp);
+ }
+
+
+ template<typename P,
+ template<typename,typename> class VP,
+ template<typename,typename> class VR,
+ template<typename> class AP,
+ template<typename> class AR,
+ typename MP>
+ inline void label_info(const polygon<P, VP, VR, AP, AR>& poly, label_option option, MP& mp)
+ {
+ label_info_polygon(poly, option, mp);
+ }
+
+} // namespace geometry
+
+
+#endif // _GEOMETRY_LABELINFO_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/latlong.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/latlong.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,283 @@
+// Geometry Library
+//
+// Copyright XXX Geodan Holding B.V. 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 _GEOMETRY_LATLONG_HPP
+#define _GEOMETRY_LATLONG_HPP
+
+#include <geometry/geometry.hpp>
+#include <geometry/util/math.hpp>
+
+#include <sstream>
+
+
+namespace geometry
+{
+ /*!
+ \brief Unit of plan angles: degrees or radians
+ */
+ enum dr_selector {degree, radian};
+
+ /*!
+ \brief Cardinal directions.
+ \details They are used in the dms-class. When specified by the library user,
+ north/east/south/west is, in general, enough. When parsed or received by an algorithm,
+ the user knows it it is lat/long but not more
+ */
+ enum cd_selector {/*cd_none, */ north, east, south, west, cd_lat, cd_lon};
+
+ /*!
+ \brief Utility class to construct latlong points point_ll with degree,minute,second
+ \note Normally combined with latitude and longitude classes
+ \par Template parameters:
+ - \a CD selects if it is north/south/west/east
+ - \a coordinate value, double/float, should correspond to latitude/longitude or point_ll class
+ \par Example:
+ Example showing how to use the dms class
+ \dontinclude doxygen_examples.cpp
+ \skip example_dms
+ \line {
+ \until }
+ */
+ template <cd_selector CD, typename T = double>
+ class dms
+ {
+ public :
+ /// Constructs with a value
+ inline explicit dms(T v)
+ : m_value(v)
+ {}
+ /// Constructs with a degree, minute, optional second
+ inline explicit dms(int d, int m, T s = 0.0)
+ : m_value(T(
+ (CD == west || CD == south) ? -1.0 : 1.0)
+ * (d + (m / 60.0) + (s / 3600.0)))
+ {
+ }
+
+ // Prohibit automatic conversion to T
+ // because this would enable lon(dms<south>)
+ // inline operator T() const { return m_value; }
+
+ /// Explicit conversion to T (double/float)
+ inline const T& as_value() const
+ {
+ return m_value;
+ }
+
+ /// Get degrees as integer, minutes as integer, seconds as double.
+ inline void get_dms(int& d, int& m, double& s,
+ bool& positive, char& cardinal) const
+ {
+ double value = m_value;
+
+ // Set to normal earth latlong coordinates
+ while (value < -180)
+ {
+ value += 360;
+ }
+ while (value > 180)
+ {
+ value -= 360;
+ }
+ // Make positive and indicate this
+ positive = value > 0;
+
+ // Todo: we might implment template/specializations here
+ // Todo: if it is "west" and "positive", make east? or keep minus sign then?
+
+ cardinal = ((CD == cd_lat && positive) ? 'N'
+ : (CD == cd_lat && !positive) ? 'S'
+ : (CD == cd_lon && positive) ? 'E'
+ : (CD == cd_lon && !positive) ? 'W'
+ : (CD == east) ? 'E'
+ : (CD == west) ? 'W'
+ : (CD == north) ? 'N'
+ : (CD == south) ? 'S'
+ : ' ');
+
+ value = fabs(value);
+
+ // Calculate the values
+ double fraction, integer;
+ fraction = modf(value, &integer);
+ d = int(integer);
+ s = 60.0 * modf(fraction * 60.0, &integer);
+ m = int(integer);
+ }
+
+ /// Get degrees, minutes, seconds as a string, separators can be specified optionally
+ inline std::string get_dms(const std::string& ds = " ",
+ const std::string& ms = "'",
+ const std::string& ss = "\"") const
+ {
+ double s;
+ int d, m;
+ bool positive;
+ char cardinal;
+ get_dms(d, m, s, positive, cardinal);
+ std::ostringstream out;
+ out << d << ds << m << ms << s << ss << " " << cardinal;
+
+
+ return out.str();
+ }
+
+ private :
+ T m_value;
+ };
+
+
+ namespace impl
+ {
+ /*!
+ \brief internal base class for latitude and longitude classes
+ \details The latitude longitude classes define different types for lat and lon. This is convenient
+ to construct latlong class without ambiguity.
+ \note It is called graticule, after <em>"This latitude/longitude "webbing" is known as the common
+ graticule" (http://en.wikipedia.org/wiki/Geographic_coordinate_system)</em>
+ \par Template parameters:
+ - \a S latitude/longitude
+ - \a T coordinate type, double float or int, should correspond to point_ll type
+ */
+ template <typename T>
+ class graticule
+ {
+ public :
+ inline explicit graticule(T v) : m_v(v) {}
+ inline operator T() const { return m_v; }
+ private :
+ T m_v;
+ };
+ }
+
+ /*!
+ \brief Class to construct point_ll with latitude value (north/south)
+ \par Template parameters:
+ - \a T coordinate type, double / float, should correspond to point_ll type
+ \note Often combined with dms class
+ */
+ template <typename T = double> class latitude : public impl::graticule<T>
+ {
+ public :
+ /// Can be constructed with a value
+ inline explicit latitude(T v) : impl::graticule<T>(v) {}
+ /// Can be constructed with a NORTH dms-class
+ inline explicit latitude(const dms<north,T>& v) : impl::graticule<T>(v.as_value()) {}
+ /// Can be constructed with a SOUTH dms-class
+ inline explicit latitude(const dms<south,T>& v) : impl::graticule<T>(v.as_value()) {}
+ };
+ /*!
+ \brief Class to construct point_ll with longitude value (west/east)
+ \par Template parameters:
+ - \a T coordinate type, double / float, should correspond to point_ll type
+ \note Often combined with dms class
+ */
+ template <typename T = double> class longitude : public impl::graticule<T>
+ {
+ public :
+ /// Can be constructed with a value
+ inline explicit longitude(T v) : impl::graticule<T>(v) {}
+ /// Can be constructed with a WEST dms-class
+ inline explicit longitude(const dms<west, T>& v) : impl::graticule<T>(v.as_value()) {}
+ /// Can be constructed with an EAST dms-class
+ inline explicit longitude(const dms<east, T>& v) : impl::graticule<T>(v.as_value()) {}
+ };
+
+
+
+ /*!
+ \brief Point using spherical coordinates \a lat and \a lon, on Earth
+ \details The point_ll class implements a point with lat and lon functions. It can be constructed
+ using latitude and longitude classes. The latlong class can be defined in degrees or in radians.
+ There is a conversion method from degree to radian, and from radian to degree.
+ \par Template parameters:
+ - \a D degree/radian enumeration
+ - \a T coordinate type, double (the default) or float (it might be int as well)
+ \note There is NO constructor with two values to avoid exchanging lat and long
+ \note Construction with latitude and longitude can be done in both orders, so lat/long and long/lat
+ \par Example:
+ Example showing how the point_ll class can be constructed. Note that it can also be constructed using
+ decimal degrees (43.123).
+ \dontinclude doxygen_examples.cpp
+ \skip example_point_ll_construct
+ \line {
+ \until }
+ */
+ template <dr_selector D, typename T = double>
+ class point_ll : public point<T, 2>
+ {
+ public :
+ static const dr_selector angle_type = D;
+
+ /// Default constructor, does not initialize anything
+ inline point_ll() : point<T, 2>() {}
+
+ /// Constructor with an option, e.g. init_zero
+ inline point_ll(init option) : point<T, 2>(option) {}
+
+ /// Constructor with longitude/latitude
+ inline point_ll(const longitude<T>& lo, const latitude<T>& la) : point<T, 2>(lo, la) {}
+
+ /// Constructor with latitude/longitude
+ inline point_ll(const latitude<T>& la, const longitude<T>& lo) : point<T, 2>(lo, la) {}
+
+
+
+ /// Get longitude
+ inline const T& lon() const { return this->template get<0>(); }
+ /// Get latitude
+ inline const T& lat() const { return this->template get<1>(); }
+
+ /// Set longitude
+ inline void lon(const T& v) { this->template get<0>() = v; }
+ /// Set latitude
+ inline void lat(const T& v) { this->template get<1>() = v; }
+
+ // Set longitude using DMS classes
+ inline void lon(const dms<east, T>& v) { this->template get<0>() = v.as_value(); }
+ inline void lon(const dms<west, T>& v) { this->template get<0>() = v.as_value(); }
+
+ inline void lat(const dms<north, T>& v) { this->template get<1>() = v.as_value(); }
+ inline void lat(const dms<south, T>& v) { this->template get<1>() = v.as_value(); }
+
+ /*!
+ \brief Method to convert degree or radian
+ \details Template method to convert to a new point_ll class instance.
+ Degree/radian is specified as a template parameter. Latlong points are usually
+ specified in degrees. They are often stored in degrees as well. Algorithms
+ usually use points in radians. The convert method conveniently does the conversion
+ from degree to radian, or from radian to degree, or, if it is already in the
+ spherical coordinate type specified, it returns just a copy.
+ \par Example:
+ Example showing how to convert a point in degrees to latlong.
+ \dontinclude doxygen_examples.cpp
+ \skip example_point_ll_convert
+ \line {
+ \until }
+ */
+ template <dr_selector CD>
+ inline point_ll<CD, T> convert() const
+ {
+ static const double c = (CD == D) ? 1.0 : CD == radian ? geometry::math::d2r : geometry::math::r2d;
+ return point_ll<CD, T>(longitude<T>(T(c * this->lon())), latitude<T>(T(c * this->lat())));
+ }
+
+ /* for latlong comparison is not so obvious!
+ inline bool operator<(const point_xy& other) const
+ {
+ return equals(x(), other.x()) ? y() < other.y() : x() < other.x();
+ }
+ */
+
+ };
+
+
+
+} // namespace geometry
+
+
+#endif // _GEOMETRY_LATLONG_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/length.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/length.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,152 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_LENGTH_HPP
+#define _GEOMETRY_LENGTH_HPP
+
+#include <geometry/geometry.hpp>
+#include <geometry/strategies/strategy_traits.hpp>
+
+/*!
+\defgroup length length: length calculation algorithms
+The length algorithm is implemented for the linestring and the multi_linestring geometry and results
+in the length of the linestring. If the points of a linestring have coordinates expressed in kilometers,
+the length of the line is expressed in kilometers as well.
+*/
+
+namespace geometry
+{
+ namespace impl
+ {
+ namespace length
+ {
+
+ /*!
+ \brief Internal, calculates length of a linestring using iterator pairs and specified strategy
+ \note for_each is not used here, then it will stop it working for std::vector<P> because of ::point_type
+ */
+ template<typename IT, typename S>
+ inline double length_linestring(IT const& begin, IT const& end, S const& strategy)
+ {
+ double sum = 0.0;
+ IT it = begin;
+ if (it != end)
+ {
+ IT previous = it++;
+ while(it != end)
+ {
+ sum += geometry::distance(*previous, *it, strategy);
+ previous = it++;
+ }
+ }
+ return sum;
+ }
+ }
+ }
+
+ /*!
+ \brief Calculate length of a linestring
+ \ingroup length
+ \details The function length returns the length of a linestring, using the default distance-calculation-strategy
+ \param ls linestring
+ \return the length
+ \par Example:
+ Example showing length calculation of linestrings built of xy-points and of latlong-points
+ \dontinclude doxygen_examples.cpp
+ \skip example_length_linestring
+ \line {
+ \until }
+ */
+ template<typename P, template<typename,typename> class V, template<typename> class A>
+ inline double length(const linestring<P, V, A>& ls)
+ {
+ return impl::length::length_linestring(ls.begin(), ls.end(),
+ typename strategy_traits<P>::point_distance());
+ }
+
+ /*!
+ \brief Calculate length of a linestring
+ \ingroup length
+ \details The function length returns the length of a linestring, using the specified strategy
+ to calculate the distance between the points of the linestring
+ \param ls linestring
+ \param strategy strategy to be used for distance calculations.
+ \return the length, in units defined by the strategy
+ \par Example:
+ Example showing length calculation of latlong linestrings using the accurate Vincenty strategy
+ for distance calculations
+ \dontinclude doxygen_examples.cpp
+ \skip example_length_linestring_strategy
+ \line {
+ \until }
+ */
+ template<typename P, template<typename,typename> class V, template<typename> class A, typename S>
+ inline double length(const linestring<P, V, A>& ls, S const& strategy)
+ {
+ return impl::length::length_linestring(ls.begin(), ls.end(), strategy);
+ }
+
+
+ // Iterator versions.
+ // They turn out to be exactly the same as in implementation
+ // Versions of linestring<P,V,A>::const_iterator do not work here, somehow
+ // Specifying abstract iterators works here because there is only one version specified
+ // For algorithms with more than one versions, such as intersection, this will not work.
+
+
+ /*!
+ \brief Calculate length of a series of points, specified by an iterator pair
+ \ingroup length
+ \details The function length returns the length of a point container, using the default distance-calculation-strategy
+ \param begin iterator positioned at first point
+ \param end iterator positioned after last point
+ \return the length
+ \par Example:
+ Example showing length calculation using iterators
+ \dontinclude doxygen_examples.cpp
+ \skip example_length_linestring_iterators1
+ \line {
+ \until }
+ Example showing length calculation on a vector
+ \dontinclude doxygen_examples.cpp
+ \skip example_length_linestring_iterators2
+ \line {
+ \until }
+ */
+ template<typename IT>
+ inline double length(IT begin, IT end)
+ {
+ return impl::length::length_linestring(begin, end,
+ typename strategy_traits<typename IT::value_type>::point_distance());
+ }
+
+ /*!
+ \brief Calculate length of a series of points, specified by an iterator pair and a strategy
+ \ingroup length
+ \details The function length returns the length of a point container between specified iterators, using specified strategy
+ \param begin iterator positioned at first point
+ \param end iterator positioned after last point
+ \param strategy strategy to be used for distance calculations.
+ \return the length
+ \par Example:
+ Example showing length calculation using iterators and the Vincenty strategy
+ \dontinclude doxygen_examples.cpp
+ \skip example_length_linestring_iterators3
+ \line {
+ \until }
+ */
+ template<typename IT, typename S>
+ inline double length(IT begin, IT end, S const& strategy)
+ {
+ return impl::length::length_linestring(begin, end, strategy);
+ }
+
+
+} // namespace geometry
+
+
+#endif // _GEOMETRY_LENGTH_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/loop.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/loop.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,85 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_LOOP_HPP
+#define _GEOMETRY_LOOP_HPP
+
+#include <geometry/segment.hpp>
+
+
+
+namespace geometry
+{
+
+
+
+ /*!
+ \brief Loops through segments of a container and call specified functor for all segments.
+ \ingroup loop
+ \details for_each like implementation to:
+ - walk over const segments of a linestring/polygon
+ - be able to break out the loop (if the functor returns false)
+ - have a const functor and keep state in separate state-object
+ - we still keep the "functor" here so it might be a function or an object, at this place
+ - in most algorithms the typename F::state_type is used; in those places it must be an object
+
+ \param v container (vector,list,deque) containing points
+ \param functor functor which is called at each const segment
+ \param state state, specified separately from the strategy functor
+ \return false if the functor returns false, otherwise true
+ \par Template parameters:
+ - \a V container type, for example a vector, linestring, linear_ring
+ - \a F functor type, class or function, not modified by the algorithm
+ - \a S state type, might be modified
+ \par Concepts
+ - \a V
+ - const_iterator begin()
+ - const_iterator end()
+ - value_type
+ - \a F
+ - <em>if it is a function functor</em>: bool \b function (const const_segment&, state&)
+ - <em>if it is a class functor</em>: bool operator()(const const_segment&, state&) const
+ - \a S
+ - no specific requirements here, requirments given by F
+ \note Some algorithms from the Geometry Library, for example within, centroid,
+ use this method.
+ \par Examples:
+ First example, using a class functor
+ \dontinclude doxygen_examples.cpp
+ \skip example_loop1
+ \line {
+ \until //:\\
+ Second example, using a function functor and latlong coordinates
+ \dontinclude doxygen_examples.cpp
+ \skip example_loop2
+ \line {
+ \until //:\\
+ */
+ template<typename V, typename F, typename S>
+ inline bool loop(const V& v, const F& functor, S& state)
+ {
+ typename V::const_iterator it = v.begin();
+ if (it != v.end())
+ {
+ typename V::const_iterator previous = it++;
+ while(it != v.end())
+ {
+ const_segment<typename V::value_type> s(*previous, *it);
+ if (! functor(s, state))
+ {
+ return false;
+ }
+ previous = it++;
+ }
+ }
+ return true;
+ }
+
+} // namespace geometry
+
+
+#endif // _GEOMETRY_LOOP_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/overlaps.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/overlaps.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,32 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_OVERLAPS_HPP
+#define _GEOMETRY_OVERLAPS_HPP
+
+#include <geometry/geometry.hpp>
+#include <geometry/box.hpp>
+
+namespace geometry
+{
+ template <typename P>
+ bool overlaps(const box<P>& r1, const box<P>& r2)
+ {
+ return !(
+ r1.max().x() <= r2.min().x() ||
+ r1.min().x() >= r2.max().x() ||
+ r1.max().y() <= r2.min().y() ||
+ r1.min().y() >= r2.max().y()
+ );
+
+ }
+
+
+} // namespace geometry
+
+
+#endif // _GEOMETRY_OVERLAPS_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/point_on_line.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/point_on_line.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,71 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_POINT_ON_LINE_HPP
+#define _GEOMETRY_POINT_ON_LINE_HPP
+
+#include <geometry/geometry.hpp>
+#include <geometry/distance.hpp>
+
+namespace geometry
+{
+
+ //----------------------------------------------------------------------
+ // Function : point_on_linestring -> rename to alongLine?
+ //----------------------------------------------------------------------
+ // Purpose : Calculates coordinates of a point along a given line
+ // on a specified distance
+ // Parameters : const L& : line,
+ // float position: position to calculate point
+ // P& point: point to calculate
+ // Return : true if point lies on line
+ //----------------------------------------------------------------------
+ // Author : Barend, Geodan BV Amsterdam
+ // Date : spring 1996
+ //----------------------------------------------------------------------
+ template <typename P, typename L>
+ bool point_on_linestring(const L& line, const double& position, P& point)
+ {
+ double current_distance = 0.0;
+ if (line.size() < 2)
+ {
+ return false;
+ }
+
+ typename L::const_iterator vertex = line.begin();
+ typename L::const_iterator previous = vertex++;
+
+ while(vertex != line.end())
+ {
+ double dist = distance(*previous, *vertex);
+ current_distance += dist;
+
+ if (current_distance > position)
+ {
+ // It is not possible that dist == 0 here because otherwise
+ // the current_distance > position would not become true (current_distance is increased by dist)
+ double fraction = 1.0 - ((current_distance - position) / dist);
+
+ // point i is too far, point i-1 to near, add fraction of
+ // distance in each direction
+ point.x ( previous->x() + (vertex->x() - previous->x()) * fraction);
+ point.y ( previous->y() + (vertex->y() - previous->y()) * fraction);
+
+ return true;
+ }
+ previous = vertex++;
+ }
+
+ // point at specified position does not lie on line
+ return false;
+ }
+
+}
+
+
+#endif // _GEOMETRY_POINT_ON_LINE_HPP
+

Added: sandbox/SOC/2008/spacial_indexing/geometry/segment.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/segment.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,57 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_SEGMENT_HPP
+#define _GEOMETRY_SEGMENT_HPP
+
+#include <geometry/geometry.hpp>
+
+namespace geometry
+{
+
+ /*!
+ \brief Class segment: small containing two (templatized) point references
+ \details From Wikipedia: In geometry, a line segment is a part of a line that is bounded
+ by two distinct end points, and contains every point on the line between its end points
+ \note The structure is like std::pair, and can often be used interchangeable.
+ So points are public available. We cannot derive from std::pair<P&, P&> because of reference
+ assignments. Points are not const and might be changed by the algorithm
+ (used in intersection_linestring)
+ \par Template parameters:
+ - \a P point type of the circle center
+ */
+ template<typename P>
+ struct segment : public geometry_traits<P>
+ {
+ P& first;
+ P& second;
+ inline segment(P& p1, P& p2)
+ : first(p1), second(p2)
+ {}
+ };
+
+ /*!
+ \brief Class const_segment: small containing two (templatized) point references
+ \details Same as segment, but const (used in intersection_polygon, used in distance)
+ \par Template parameters:
+ - \a P point type of the circle center
+ */
+ template<typename P>
+ struct const_segment : public geometry_traits<P>
+ {
+ const P& first;
+ const P& second;
+ inline const_segment(const P& p1, const P& p2)
+ : first(p1), second(p2)
+ {}
+ };
+
+
+} // namespace geometry
+
+
+#endif //_GEOMETRY_SEGMENT_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/simplify.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/simplify.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,339 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_SIMPLIFY_HPP
+#define _GEOMETRY_SIMPLIFY_HPP
+
+#include <geometry/geometry.hpp>
+#include <geometry/distance.hpp>
+
+//#define GL_DEBUG_SIMPLIFY
+
+#ifdef GL_DEBUG_SIMPLIFY
+#include <geometry/astext.hpp>
+#include <iostream>
+#endif
+
+/*!
+\defgroup simplify simplify: line/polygon simplification algorithms
+The simplify algorithm implements the Douglas Peucker algorithm (or another simplification
+algorithm) to simplify linestrings. It is implemented for linestrings, multi_linestrings,
+linear rings, polygons and multi_polygons. Note, however, that simplifying
+a valid simple polygon (which never intersects itself) might result in an invalid polygon,
+where the simplified rings intersect themselves or one of the other outer or inner rings.
+*/
+
+namespace geometry
+{
+ namespace strategy
+ {
+ namespace simplify
+ {
+ /*!
+ \brief Small wrapper around a point, with an extra member "included"
+ \details
+ - We could implement a complete point as well but that is not necessary
+ - We could derive from geometry::point but we need the original later on, including extra members;
+ besides that it is not necessary to copy points during the algorithm
+ \par Template parameters:
+ - \a P the enclosed point type
+ */
+ template<typename P>
+ struct douglas_peucker_point
+ {
+ const P& p;
+ bool included;
+
+ inline douglas_peucker_point(const P& ap)
+ : p(ap)
+ , included(false)
+ {}
+
+ inline douglas_peucker_point<P> operator=(const douglas_peucker_point<P>& other)
+ {
+ return douglas_peucker_point<P>(*this);
+ }
+ };
+
+
+ /*!
+ \brief Implements the simplify algorithm.
+ \details The douglas_peucker strategy simplifies a linestring, ring or vector of points
+ using the well-known Douglas-Peucker algorithm. For the algorithm, see for example:
+ - http://de.wikipedia.org/wiki/Douglas-Peucker-Algorithmus
+ - http://www2.dcs.hull.ac.uk/CISRG/projects/Royal-Inst/demos/dp.html
+
+ \note This strategy uses itself a point-segment-distance strategy which can be specified
+ \author Barend and Maarten, 1995/1996
+ \author Revised using templates/iterators 2008
+ \par Template parameters:
+ - \a V container with points, should have "value_type"
+ - \a O_IT output iterator
+ - \a S point-segment distance strategy to be used
+
+ \par Template concepts for V
+ - typename value_type, should define the used point type
+ */
+ template<typename V, typename O_IT, typename S>
+ class douglas_peucker
+ {
+ typedef typename V::value_type P;
+ typedef douglas_peucker_point<P> DP;
+ typedef typename std::vector<DP>::iterator IT;
+
+ inline void consider(IT begin, IT end, double max_dist, int& n, const S& strategy) const
+ {
+ size_t size = end - begin;
+ // size must be at least 3 here: we want to consider a candidate point between begin and end
+ if (size <= 2)
+ {
+#ifdef GL_DEBUG_SIMPLIFY
+ if (begin != end)
+ {
+ std::cout << "ignore between " << begin->p << " and " << (end - 1)->p << " size=" << size << std::endl;
+ }
+ std::cout << "return because size=" << size << std::endl;
+#endif
+ return;
+ }
+
+ IT last = end - 1;
+
+#ifdef GL_DEBUG_SIMPLIFY
+ std::cout << "find between " << begin->p << " and " << last->p << " size=" << size << std::endl;
+#endif
+
+
+ // Find most distance point, compare to the current segment
+ geometry::const_segment<P> s(begin->p, last->p);
+ double max = -1.0; // any value < 0
+ IT candidate;
+ for(IT it = begin + 1; it != last; it++)
+ {
+ typename strategy_traits<P>::point_segment_distance f2;
+ distance_result dist = f2(it->p, s);
+#ifdef GL_DEBUG_SIMPLIFY
+ std::cout << "consider " << it->p << " at " << dist.first << (dist.first > max_dist ? " maybe" : " no") << std::endl;
+#endif
+ if (dist.first > max)
+ {
+ max = dist.first;
+ candidate = it;
+ }
+ }
+
+ // If a point is found, set the include flag and handle segments in between recursively
+ if (max > max_dist)
+ {
+#ifdef GL_DEBUG_SIMPLIFY
+ std::cout << "use " << candidate->p << std::endl;
+#endif
+
+ candidate->included = true;
+ n++;
+
+ consider(begin, candidate + 1, max_dist, n, strategy);
+ consider(candidate, end, max_dist, n, strategy);
+ }
+ }
+
+
+ public :
+ typedef typename V::const_iterator CIT;
+
+
+ /*!
+ \brief Call simplification on an iterator pair
+ */
+ inline void simplify(CIT begin, CIT end, O_IT out, double max_distance, const S& strategy) const
+ {
+ // Init the output, a vector of references to all points
+
+ // Note Geometry Algorithms suggest here
+ // http://geometryalgorithms.com/Archive/algorithm_0205/algorithm_0205.htm
+ // to "STAGE 1: Vertex Reduction within max_distance of prior vertex cluster"
+ // However, that is not correct: a vertex within the specified distance might be
+ // excluded here, but might be a better candidate for final inclusion than the point before.
+
+ std::vector<DP> ref_candidates(begin, end);
+
+ // Include first and last point of line, they are always part of the line
+ int n = 2;
+ ref_candidates.front().included = true;
+ ref_candidates.back().included = true;
+
+ // Get points, recursively, including them if they are further away than the specified distance
+ consider(ref_candidates.begin(), ref_candidates.end(),
+ strategy.squared() ? max_distance * max_distance : max_distance, n, strategy);
+
+ // Copy included elements to the output (might be changed using copy_if)
+ for(typename std::vector<DP>::const_iterator it = ref_candidates.begin();
+ it != ref_candidates.end(); it++)
+ {
+ if (it->included)
+ {
+ //v_out.push_back(it->p);
+ *out = it->p;
+ out++;
+ }
+ }
+ }
+
+ };
+
+ }
+ }
+
+
+ namespace impl
+ {
+ namespace simplify
+ {
+
+ template<typename L, typename O_IT, typename S>
+ inline void simplify_linestring(const L& l_in, O_IT out, double max_distance, const S& strategy)
+ {
+ if (l_in.size() <= 2 || max_distance < 0)
+ {
+ std::copy(l_in.begin(), l_in.end(), out);
+ return;
+ }
+ strategy::simplify::douglas_peucker<L, O_IT, S> simplify_strategy;
+ simplify_strategy.simplify(l_in.begin(), l_in.end(), out, max_distance, strategy);
+ }
+
+ template<typename R, typename O_IT, typename S>
+ inline void simplify_ring(const R& r_in, O_IT out, double max_distance, const S& strategy)
+ {
+ // Call do_container for a ring
+ // Efficient simplification of a ring/polygon is still an "Open Problem"
+ // See http://maven.smith.edu/~orourke/TOPP/P24.html#Problem.24
+ // The first/last point (the closing point of the ring) should maybe be excluded because it
+ // lies on a line with second/one but last. Here it is never excluded.
+
+ // Note also that, especially if max_distance is too large, the output ring might be self intersecting
+ // while the input ring is not, although chances are low in normal polygons
+
+ // Finally the inputring might have 4 points (=correct), the output < 4(=wrong)
+ if (r_in.size() <= 4 || max_distance < 0)
+ {
+ std::copy(r_in.begin(), r_in.end(), out);
+ return;
+ }
+
+ strategy::simplify::douglas_peucker<R, O_IT, S> simplify_strategy;
+ simplify_strategy.simplify(r_in.begin(), r_in.end(), out, max_distance, strategy);
+ }
+
+ template<typename Y, typename S>
+ inline void simplify_polygon(const Y& poly_in, Y& poly_out, double max_distance, const S& strategy)
+ {
+ // Note that if there are inner rings, and distance is too large, they might intersect with the
+ // outer ring in the output, while it didn't in the input.
+ simplify_ring(poly_in.outer(), poly_out.outer(), max_distance, strategy);
+
+ poly_out.inners().resize(poly_in.inners().size());
+ typename Y::inner_container_type::const_iterator it_in = poly_in.inners().begin();
+ typename Y::inner_container_type::iterator it_out = poly_out.inners().begin();
+
+ for (; it_in != poly_in.inners().end(); it_in++, it_out++)
+ {
+ simplify_ring(*it_in, std::back_inserter(*it_out), max_distance, strategy);
+ }
+ }
+
+ } // namespace simplify
+
+ } // namespace impl
+
+
+ /*!
+ \brief Simplify a (piece of a) linestring using input/output iterator.
+ \ingroup simplify
+ \details The simplify algorithm removes points, keeping the shape as much as possible.
+ This version of simplify is the most basic version, working on an iterator pair, an
+ output iterator and two strategies to be specified.
+ \param begin iterator pointed at first element to be simplified
+ \param end iterator pointed after last element to be simplified
+ \param out output iterator, outputs all simplified points
+ \param max_distance distance (in units of input coordinates) of a vertex to the linestring to be removed
+ \param simplify_strategy strategy to be used for simplification
+ \param point_segment_distance_strategy strategy to be used for point-segment-distance calculation
+ \par Example:
+ The simplify algorithm can be used as following:
+ \dontinclude doxygen_examples.cpp
+ \skip example_simplify_linestring2
+ \line {
+ \until }
+ or, using a std::vector instead of a linestring, as following:
+ \dontinclude doxygen_examples.cpp
+ \skip example_simplify_linestring3
+ \line {
+ \until }
+ */
+ template<typename IT, typename O_IT, typename SS, typename DS>
+ inline void simplify(IT begin, IT end,
+ O_IT out, double max_distance,
+ const SS& simplify_strategy,
+ const DS& point_segment_distance_strategy)
+ {
+ simplify_strategy.simplify(begin, end, out, max_distance, point_segment_distance_strategy);
+ }
+
+
+
+ /*!
+ \brief Simplify a linestring.
+ \ingroup simplify
+ \details The simplify algorithm removes points from a linestring, keeping the shape as
+ much as possible. This version of simplify uses the default strategy for point-segment-distance calculation,
+ and uses the Douglas Peucker (douglas_peucker) strategy for simplification.
+ \param l_in linestring to simplify
+ \param l_out simplified linestring
+ \param max_distance distance (in units of input coordinates) of a vertex to the linestring to be removed
+ \par Example:
+ The simplify algorithm can be used as following:
+ \dontinclude doxygen_examples.cpp
+ \skip example_simplify_linestring1
+ \line {
+ \until }
+ */
+ template<typename P, template<typename,typename> class V, template<typename> class A>
+ inline void simplify(const linestring<P, V, A>& l_in, linestring<P, V, A>& l_out, double max_distance)
+ {
+ impl::simplify::simplify_linestring(l_in, std::back_inserter(l_out),
+ max_distance, typename strategy_traits<P>::point_distance());
+ }
+
+ template<typename P,
+ template<typename,typename> class VP,
+ template<typename,typename> class VR,
+ template<typename> class AP,
+ template<typename> class AR,
+ typename S>
+ inline void simplify(const polygon<P, VP, VR, AP, AR>& poly_in,
+ polygon<P, VP, VR, AP, AR>& poly_out, double max_distance,
+ const S& point_segment_distance_strategy)
+ {
+ impl::simplify::simplify_polygon(poly_in, poly_out, max_distance, point_segment_distance_strategy);
+ }
+
+ template<typename P,
+ template<typename,typename> class VP,
+ template<typename,typename> class VR,
+ template<typename> class AP,
+ template<typename> class AR>
+ inline void simplify(const polygon<P, VP, VR, AP, AR>& poly_in,
+ polygon<P, VP, VR, AP, AR>& poly_out, double max_distance)
+ {
+ impl::simplify::simplify_polygon(poly_in, poly_out, max_distance,
+ typename strategy_traits<P>::point_distance());
+ }
+
+} // namespace geometry
+
+#endif // _GEOMETRY_SIMPLIFY_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/strategies/strategies_point_ll.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/strategies/strategies_point_ll.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,604 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_STRATEGIES_POINT_LL_HPP
+#define _GEOMETRY_STRATEGIES_POINT_LL_HPP
+
+#include <utility>
+
+#include <geometry/geometry.hpp>
+#include <geometry/latlong.hpp>
+#include <geometry/util/math.hpp>
+#include <geometry/util/return_types.hpp>
+
+namespace geometry
+{
+ // To be moved somewhere.
+ namespace constants
+ {
+ static const double average_earth_radius = 6372795.0;
+ }
+
+ namespace strategy
+ {
+ namespace distance
+ {
+
+ /*!
+ \brief Distance calculation for spherical coordinates on a perfect sphere using haversine
+ \par Template parameters:
+ - \a P1 first point type
+ - \a P2 optional second point type
+ \author Adapted from: http://williams.best.vwh.net/avform.htm
+ \note See also http://en.wikipedia.org/wiki/Great-circle_distance
+ \note It says: <em>The great circle distance d between two points with coordinates {lat1,lon1} and {lat2,lon2} is given by:
+ d=acos(sin(lat1)*sin(lat2)+cos(lat1)*cos(lat2)*cos(lon1-lon2))
+ A mathematically equivalent formula, which is less subject to rounding error for short distances is:
+ d=2*asin(sqrt((sin((lat1-lat2)/2))^2 + cos(lat1)*cos(lat2)*(sin((lon1-lon2)/2))^2))</em>
+ */
+ template <typename P1, typename P2 = P1>
+ class haversine
+ {
+ public :
+ inline haversine(double r = constants::average_earth_radius)
+ : m_radius(r)
+ {}
+
+ inline bool squared() const { return false; }
+
+ inline distance_result operator()(const P1& p1, const P2& p2) const
+ {
+ // TODO: be sure we calc in radian's
+ //return calc(p1.template convert<radian>(), p2.template convert<radian>());
+ return calc(p1, p2);
+ }
+
+ private :
+ double m_radius;
+ typedef point_ll<radian, typename point_traits<P1>::coordinate_type> PR;
+
+ inline distance_result calc(const P1& p1, const P2& p2) const
+ {
+ double a = math::hav(get<1>(p2) - get<1>(p1))
+ + cos(get<1>(p1)) * cos(get<1>(p2)) * math::hav(get<0>(p2) - get<0>(p1));
+ double c = 2.0 * asin(sqrt(a));
+ return distance_result(m_radius * c, false);
+ }
+ };
+
+
+ /*!
+ \brief Defines ellipsoid values for use in distance calculations
+ \details They have a constructor with the earth radius
+ \par Template parameters:
+ - \a P1 first point type
+ - \a P2 optional second point type
+ \note Might be moved to separated projection:: namespace, or elsewhere
+ \todo Optionally specify earth model, defaulting to WGS84
+ - See http://en.wikipedia.org/wiki/Figure_of_the_Earth
+ - and http://en.wikipedia.org/wiki/World_Geodetic_System#A_new_World_Geodetic_System:_WGS84
+ \note
+ */
+ class ellipsoid
+ {
+ public :
+ ellipsoid(double a, double b)
+ : m_a(a)
+ , m_b(b)
+ , m_f((a - b) / a)
+ {}
+ ellipsoid()
+ : m_a(6378137.0)
+ , m_b(6356752.314245)
+ , m_f((m_a - m_b) / m_a)
+ {}
+ // Unit sphere
+ ellipsoid(double f)
+ : m_a(1.0)
+ , m_f(f)
+ {}
+
+ double a() const { return m_a; }
+ double b() const { return m_b; }
+ double f() const { return m_f; }
+
+ private :
+ double m_a, m_b, m_f; // equatorial radius, polar radius, flattening
+ };
+
+
+ /*!
+ \brief Point-point distance approximation taking flattening into account
+ \par Template parameters:
+ - \a P1 first point type
+ - \a 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
+ \note See also:
+ - http://nacc.upc.es/tierra/node16.html
+ - http://sci.tech-archive.net/Archive/sci.geo.satellite-nav/2004-12/2724.html
+ \note See also the implementations
+ - http://home.att.net/~srschmitt/great_circle_route.html
+ - http://www.codeguru.com/Cpp/Cpp/algorithms/article.php/c5115
+ - http://futureboy.homeip.net/frinksamp/navigation.frink
+ - http://www.voidware.com/earthdist.htm
+ */
+ template <typename P1, typename P2 = P1>
+ class andoyer
+ {
+ public :
+ andoyer()
+ : m_ellipsoid()
+ {}
+ andoyer(double f)
+ : m_ellipsoid(f)
+ {}
+
+ inline bool squared() const { return false; }
+
+ inline distance_result operator()(const P1& p1, const P2& p2) const
+ {
+ return calc(p1.template convert<radian>(), p2.template convert<radian>());
+ }
+
+
+ private :
+ typedef point_ll<radian, typename point_traits<P1>::coordinate_type> PR;
+ ellipsoid m_ellipsoid;
+
+ inline distance_result calc(const PR& p1, const PR& p2) const
+ {
+ double F = (p1.lat() + p2.lat()) / 2.0;
+ double G = (p1.lat() - p2.lat()) / 2.0;
+ double lambda = (p1.lon() - p2.lon()) / 2.0;
+
+ double sinG2 = math::sqr(sin(G));
+ double cosG2 = math::sqr(cos(G));
+ double sinF2 = math::sqr(sin(F));
+ double cosF2 = math::sqr(cos(F));
+ double sinL2 = math::sqr(sin(lambda));
+ double cosL2 = math::sqr(cos(lambda));
+
+ double S = sinG2 * cosL2 + cosF2 * sinL2;
+ double C = cosG2 * cosL2 + sinF2 * sinL2;
+
+ double omega = atan(sqrt(S / C));
+ double r = sqrt(S * C) / omega; // not sure if this is r or greek nu
+
+ double D = 2.0 * omega * m_ellipsoid.a();
+ double H1 = (3 * r - 1.0) / (2.0 * C);
+ double H2 = (3 * r + 1.0) / (2.0 * S);
+
+ return distance_result(D * (1.0 + m_ellipsoid.f() * H1 * sinF2 * cosG2 - m_ellipsoid.f() * H2 * cosF2 * sinG2), false);
+ }
+ };
+
+
+ /*!
+ \brief Distance calculation formulae on latlong coordinates, after Vincenty, 1975
+ \par Template parameters:
+ - \a P1 first point type
+ - \a 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 :
+ inline bool squared() const { return false; }
+
+ inline distance_result operator()(const P1& p1, const P2& p2) const
+ {
+ return calc(p1.template convert<radian>(), p2.template convert<radian>());
+ }
+
+ private :
+ typedef point_ll<radian, typename point_traits<P1>::coordinate_type> PR;
+ ellipsoid m_ellipsoid;
+ inline distance_result calc(const PR& p1, const PR& p2) const
+ {
+ // lambda: difference in longitude on an auxiliary sphere
+ double L = p2.lon() - p1.lon();
+ double lambda = L;
+
+ if (L < -math::pi) L += math::two_pi;
+ if (L > math::pi) L -= math::two_pi;
+
+ if (p1.lat() == p2.lat() && p1.lon() == p2.lon())
+ {
+ return distance_result(0, false);
+ }
+
+ // U: reduced latitude, defined by tan U = (1-f) tan phi
+ double U1 = atan((1-m_ellipsoid.f()) * tan(p1.lat())); // above (1)
+ double U2 = atan((1-m_ellipsoid.f()) * tan(p2.lat())); // 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 distance_result(dist, false);
+ }
+ };
+
+
+ /*!
+ \brief Strategy functor for distance point to segment calculation
+ \details Class which calculates the distance of a point to a segment, using latlong points
+ \par Template parameters:
+ - \a P point type
+ - \a PS segment-point type
+ */
+ template <typename P, typename PS>
+ class ll_point_segment
+ {
+ public :
+ inline ll_point_segment(double r = constants::average_earth_radius) : m_radius(r)
+ {}
+
+ inline bool squared() const { return false; }
+
+ inline distance_result operator()(const P& p, const const_segment<PS>& s) const
+ {
+
+ return calc(p.template convert<radian>(),
+ s.first.template convert<radian>(),
+ s.second.template convert<radian>());
+ }
+
+ private :
+ typedef point_ll<radian, typename point_traits<P>::coordinate_type> PR;
+ double m_radius;
+
+ /// Calculate course (bearing) between two points. Might be moved to a "course formula" ...
+ inline double course(const PR& p1, const PR& p2) const
+ {
+ /***
+ Course between points
+
+ We obtain the initial course, tc1, (at point 1) from point 1 to point 2 by the following. The formula fails if the initial point is a pole. We can special case this with:
+
+ IF (cos(lat1) < EPS) // EPS a small number ~ machine precision
+ IF (lat1 > 0): tc1= pi // starting from N pole
+ ELSE: tc1= 2*pi // starting from S pole
+ ENDIF
+ ENDIF
+
+ For starting points other than the poles:
+ IF sin(lon2-lon1)<0: tc1=acos((sin(lat2)-sin(lat1)*cos(d))/(sin(d)*cos(lat1)))
+ ELSE: tc1=2*pi-acos((sin(lat2)-sin(lat1)*cos(d))/(sin(d)*cos(lat1)))
+ ENDIF
+
+ An alternative formula, not requiring the pre-computation of d, the distance between the points, is:
+ tc1=mod(atan2(sin(lon1-lon2)*cos(lat2),
+ cos(lat1)*sin(lat2)-sin(lat1)*cos(lat2)*cos(lon1-lon2))
+ , 2*pi)
+ ***/
+ double dlon = p2.lon() - p1.lon();
+ double cos_p2lat = cos(p2.lat());
+ return atan2(sin(dlon) * cos_p2lat, cos(p1.lat()) * sin(p2.lat()) - sin(p1.lat()) * cos_p2lat * cos(dlon));
+ }
+
+ inline distance_result calc(const PR& p, const PR& sp1, const PR& sp2) const
+ {
+ /***
+ Cross track error:
+ Suppose you are proceeding on a great circle route from A to B (course =crs_AB) and end up at D, perhaps off course.
+ (We presume that A is ot a pole!) You can calculate the course from A to D (crs_AD) and the distance from A to D (dist_AD)
+ using the formulae above. In shifteds of these the cross track error, XTD, (distance off course) is given by
+
+ XTD =asin(sin(dist_AD)*sin(crs_AD-crs_AB))
+
+ (positive XTD means right of course, negative means left)
+ (If the point A is the N. or S. Pole replace crs_AD-crs_AB with
+ lon_D-lon_B or lon_B-lon_D, respectively.)
+ ***/
+
+ // Calculate distances, in radians, on the unit sphere
+ // It seems not useful to let this strategy be templatized, it should be in radians and on the unit sphere
+ strategy::distance::haversine<PR, PR> strategy(1.0);
+ double d1 = strategy(sp1, p);
+
+ // Actually, calculation of d2 not necessary if we know that the projected point is on the great circle...
+ double d2 = strategy(sp2, p);
+
+
+ double crs_AD = course(sp1, p);
+ double crs_AB = course(sp1, sp2);
+ double XTD = fabs(asin(sin(d1) * sin(crs_AD - crs_AB)));
+
+ // Return shortest distance, either to projected point on segment sp1-sp2, or to sp1, or to sp2
+ return distance_result(m_radius * std::min(std::min(d1, d2), XTD), false);
+ }
+ };
+
+
+
+ // We might add a vincenty-like strategy also for point-segment distance, but to calculate the projected point is not trivial
+
+ } // namespace distance
+
+
+
+ namespace area
+ {
+ /*!
+ \brief Area calculation by spherical excess
+ \par Template parameters:
+ - \a P type of points of rings/polygons
+ \author Barend Gehrels. Adapted from:
+ - http://www.soe.ucsc.edu/~pang/160/f98/Gems/GemsIV/sph_poly.c
+ - http://williams.best.vwh.net/avform.htm
+ \note The version in Gems didn't account for polygons crossing the 180 meridian.
+ \note This version works for convex and non-convex polygons, for 180 meridian
+ crossing polygons and for polygons with holes. However, some cases (especially
+ 180 meridian cases) must still be checked.
+ \note The version which sums angles, which is often seen, doesn't handle non-convex
+ polygons correctly.
+ \note The version which sums longitudes, see
+ http://trs-new.jpl.nasa.gov/dspace/bitstream/2014/40409/1/07-03.pdf, is simple
+ and works well in most cases but not in 180 meridian crossing cases. This probably
+ could be solved.
+ */
+ template<typename P>
+ class by_spherical_excess
+ {
+ private :
+ struct excess_sum
+ {
+ double sum;
+ inline excess_sum() : sum(0) {}
+ inline double area() const
+ {
+ return - sum * constants::average_earth_radius * constants::average_earth_radius;
+ }
+ };
+
+ // Distances are calculated on unit sphere here
+ strategy::distance::haversine<P, P> m_unit_sphere;
+
+ public :
+ typedef excess_sum state_type;
+
+ by_spherical_excess()
+ : m_unit_sphere(1)
+ {}
+
+ inline bool operator()(const const_segment<P>& segment, state_type& state) const
+ {
+ if (segment.first.lon() != segment.second.lon())
+ {
+
+ typedef point_ll<radian, typename point_traits<P>::coordinate_type> PR;
+ PR p1 = segment.first.template convert<radian>();
+ PR p2 = segment.second.template convert<radian>();
+
+ // Distance p1 p2
+ double a = m_unit_sphere(segment.first, segment.second);
+ // Sides on unit sphere to south pole
+ double b = 0.5 * math::pi - p2.lat();
+ double c = 0.5 * math::pi - p1.lat();
+ // Semi parameter
+ double s = 0.5 * (a + b + c);
+
+ // E: spherical excess, using l’Huiller’s formula
+ // [tg(e / 4)]2 = tg[s / 2] tg[(s-a) / 2] tg[(s-b) / 2] tg[(s-c) / 2]
+ double E = 4.0 * atan(sqrt(fabs(tan(s / 2) * tan((s - a) / 2) * tan((s - b) / 2) * tan((s - c) / 2))));
+
+ E = fabs(E);
+
+ // In right direction: positive, add area. In left direction: negative, subtract area.
+ // Longitude comparisons are not so obvious. If one is negative, other is positive,
+ // we have to take the date into account.
+ // TODO: check this / enhance this, should be more robust. See also the "grow" for ll
+ double lon1 = p1.lon() < 0 ? p1.lon() + math::two_pi : p1.lon();
+ double lon2 = p2.lon() < 0 ? p2.lon() + math::two_pi : p2.lon();
+
+ if (lon2 < lon1)
+ {
+ E= -E;
+ }
+
+ state.sum += E;
+ }
+ return true;
+ }
+ };
+
+ } // namespace area
+
+
+ namespace envelope
+ {
+ // envelope calculation strategy for latlong-points
+ namespace shift
+ {
+ template <dr_selector D>
+ struct shifted
+ {
+ };
+
+ template<>
+ struct shifted<radian>
+ {
+ inline static double shift() { return math::two_pi; }
+ };
+ template<>
+ struct shifted<degree>
+ {
+ inline static double shift() { return 360.0; }
+ };
+
+ }
+
+ /*!
+ \par Algorithm:
+ The envelope of latlong-points cannot be implemented as for xy-points. Suppose the
+ envelope of the Aleutian Islands must be calculated. The span from 170E to 170W, from -170 to 170.
+ Of course the real envelope is not -170..170 but 170..-170.
+ On the other hand, there might be geometries that indeed span from -170 to 170. If there are
+ two points, it is not known. If there are points in between, we probably should take the shorter
+ range. So we do that for the moment.
+ We shift coordinates and do as if we live in a world with longitude coordinates from 0 - 360,
+ where 0 is still at Greenwich. Longitude ranges are then calculated twice: one for real world,
+ one for the shifted world.
+ The shortest range is taken for the bounding box. This might have coordinates > 180
+ */
+
+ template <typename PB, typename P = PB>
+ struct grow_ll
+ {
+
+ struct state
+ {
+ typedef typename point_traits<PB>::coordinate_type T;
+ bool has_west;
+ T min_lat, max_lat;
+ T min_lon1, min_lon2, max_lon1, max_lon2;
+
+ state()
+ : has_west(false)
+ , min_lat(boost::numeric::bounds<T>::highest())
+ , min_lon1(boost::numeric::bounds<T>::highest())
+ , min_lon2(boost::numeric::bounds<T>::highest())
+ , max_lat(boost::numeric::bounds<T>::lowest())
+ , max_lon1(boost::numeric::bounds<T>::lowest())
+ , max_lon2(boost::numeric::bounds<T>::lowest())
+ {}
+
+ template <typename T>
+ void take_minmax(const T& value, T& min, T& max)
+ {
+ if (value < min)
+ {
+ min = value;
+ }
+ if (value > max)
+ {
+ max = value;
+ }
+ }
+
+ void grow(const P& p)
+ {
+ // For latitude, we can take the min/max
+ take_minmax(p.lat(), min_lat, max_lat);
+
+
+ // For longitude, we do the same...
+ take_minmax(p.lon(), min_lon1, max_lon1);
+
+ // But we also add 360 (2pi) if it is negative
+ T value = p.lon();
+ while(value < 0)
+ {
+ has_west = true;
+ value += shift::shifted<PB::angle_type>::shift();
+ }
+ while (value > math::two_pi)
+ {
+ value -= shift::shifted<PB::angle_type>::shift();
+ }
+ take_minmax(value, min_lon2, max_lon2);
+ }
+
+ void envelope(box<PB>& mbr)
+ {
+ // For latitude it is easy
+ mbr.min().lat(min_lat);
+ mbr.max().lat(max_lat);
+ if (! has_west)
+ {
+ mbr.min().lon(min_lon1);
+ mbr.max().lon(max_lon1);
+ }
+ else
+ {
+ // Get both ranges
+ T diff1 = max_lon1 - min_lon1;
+ T diff2 = max_lon2 - min_lon2;
+
+ //std::cout << "range 1: " << min_lon1 * math::r2d << ".." << max_lon1 * math::r2d << std::endl;
+ //std::cout << "range 2: " << min_lon2 * math::r2d << ".." << max_lon2 * math::r2d << std::endl;
+
+ if (diff1 <= diff2)
+ {
+ mbr.min().lon(min_lon1);
+ mbr.max().lon(max_lon1);
+ }
+ else
+ {
+ mbr.min().lon(min_lon2);
+ mbr.max().lon(max_lon2);
+ }
+ }
+ }
+ };
+
+ typedef state state_type;
+
+ void operator()(const P& p, state_type& s) const
+ {
+ s.grow(p);
+ }
+ };
+ } // namespace envelope
+
+
+ } // namespace strategy
+
+} // namespace geometry
+
+
+#endif // _GEOMETRY_STRATEGIES_POINT_LL_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/strategies/strategies_point_xy.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/strategies/strategies_point_xy.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,579 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_STRATEGIES_POINT_XY_HPP
+#define _GEOMETRY_STRATEGIES_POINT_XY_HPP
+
+#include <utility>
+
+#include <geometry/geometry.hpp>
+#include <geometry/segment.hpp>
+#include <geometry/grow.hpp>
+#include <geometry/arithmetic.hpp>
+#include <geometry/assign.hpp>
+#include <geometry/copy.hpp>
+#include <geometry/dot_product.hpp>
+#include <geometry/concepts/point_traits.hpp>
+#include <geometry/util/promotion_traits.hpp>
+#include <geometry/util/return_types.hpp>
+#include <geometry/util/side.hpp>
+
+namespace geometry
+{
+ namespace strategy
+ {
+ namespace distance
+ {
+ namespace impl
+ {
+ template <typename P1, typename P2, size_t I, typename T>
+ struct compute_pythagoras
+ {
+ static T result(const P1& p1, const P2& p2)
+ {
+ T d = get<I-1>(p2) - get<I-1>(p1);
+ return d*d + compute_pythagoras<P1, P2, I-1, T>::result(p1, p2);
+ }
+ };
+
+ template <typename P1, typename P2, typename T>
+ struct compute_pythagoras<P1, P2, 0, T>
+ {
+ static T result(const P1&, const P2&)
+ {
+ return 0;
+ }
+ };
+ }
+
+ /*!
+ \brief Strategy functor for distance point to point: pythagoras
+ \par Template parameters:
+ - \a P1 first point type
+ - \a P2 optional, second point type, defaults to first point type
+ \par Concepts for P1 and P2:
+ - specialized point_traits class
+ */
+ template <typename P1, typename P2 = P1>
+ struct pythagoras
+ {
+ static inline bool squared() { return true; }
+
+ inline distance_result operator()(const P1& p1, const P2& p2) const
+ {
+ BOOST_STATIC_ASSERT(point_traits<P1>::coordinate_count == point_traits<P2>::coordinate_count);
+
+ // Calculate distance using Pythagoras
+ // (Leave comment above for Doxygen)
+ typedef typename select_type_traits<
+ typename point_traits<P1>::coordinate_type,
+ typename point_traits<P2>::coordinate_type
+ >::type T;
+ return distance_result(impl::compute_pythagoras<P1, P2, point_traits<P1>::coordinate_count, T>::result(p1, p2), true);
+ }
+ };
+
+
+ /*!
+ \brief Strategy functor for distance point to segment
+ \details Calculates distance using projected-point method, and (optionally) Pythagoras
+ \author Adapted from: http://geometryalgorithms.com/Archive/algorithm_0102/algorithm_0102.htm
+ \par Template parameters:
+ - \a P point type
+ - \a PS point type of segments, optional, defaults to point type
+ - \a S strategy, optional, defaults to pythagoras
+ \par Concepts for P and PS:
+ - specialized point_traits class
+ \par Concepts for S:
+ - distance_result operator(P,P)
+ */
+ template <typename P, typename PS = P, typename S = pythagoras<P, PS> >
+ struct xy_point_segment
+ {
+ typedef S distance_strategy_type;
+
+ static inline bool squared() { return S::squared(); }
+
+ inline distance_result operator()(const P& p, const const_segment<PS>& s) const
+ {
+ BOOST_STATIC_ASSERT(point_traits<P>::coordinate_count == point_traits<PS>::coordinate_count);
+
+ S distance_strategy;
+
+ /* Algorithm
+ POINT v(x2 - x1, y2 - y1);
+ POINT w(px - x1, py - y1);
+ c1 = w . v
+ c2 = v . v
+ b = c1 / c2
+ RETURN POINT(x1 + b * vx, y1 + b * vy);
+ */
+
+ PS v, w;
+ copy_coordinates(s.second, v);
+ copy_coordinates(p, w);
+ subtract_point(v, s.first);
+ subtract_point(w, s.first);
+
+ typedef typename point_traits<PS>::coordinate_type T;
+
+ T c1 = dot_product(w, v);
+ if (c1 <= 0)
+ {
+ return distance_strategy(p, s.first);
+ }
+ T c2 = dot_product(v, v);
+ if (c2 <= c1)
+ {
+ return distance_strategy(p, s.second);
+ }
+
+ // Even in case of char's, we have to turn to a point<double/float>
+ // because of the division.
+ double b = c1 / c2;
+
+ PS projected;
+ copy_coordinates(s.first, projected);
+ multiply_value(v, b);
+ add_point(projected, v);
+
+ return distance_strategy(p, projected);
+
+ }
+ };
+
+ } // namespace distance
+
+
+ namespace area
+ {
+
+ /*!
+ \brief Strategy functor for area calculation on point_xy points
+ \details Calculates area using well-known triangulation algorithm
+ \par Template parameters:
+ - \a PS point type of segments
+ \par Concepts for PS:
+ - specialized point_traits class
+ */
+ template<typename PS>
+ class by_triangles
+ {
+ private :
+ struct summation
+ {
+ typedef typename point_traits<PS>::coordinate_type T;
+ T sum;
+ inline summation() : sum(T()) {}
+ inline double area() const { return 0.5 * double(sum); }
+ };
+
+ public :
+ typedef summation state_type;
+
+ inline bool operator()(const const_segment<PS>& s, state_type& state) const
+ {
+ // SUM += x2 * y1 - x1 * y2;
+
+ // Currently only 2D areas are supported
+ BOOST_STATIC_ASSERT(point_traits<PS>::coordinate_count == 2);
+ state.sum += get<0>(s.second) * get<1>(s.first) - get<0>(s.first) * get<1>(s.second);
+ return true;
+ }
+
+ };
+
+ } // namespace area
+
+
+ namespace within
+ {
+ /*!
+ \brief Within detection using cross counting
+
+ \author adapted from Randolph Franklin algorithm
+ \author Barend and Maarten, 1995
+ \author Revised for templatized library, Barend Gehrels, 2007
+ \return true if point is in ring, works for closed rings in both directions
+ \note Does NOT work correctly for point ON border
+ */
+
+ template<typename P, typename PS = P>
+ struct franklin
+ {
+ private :
+ /*! subclass to keep state */
+ struct crossings
+ {
+ P p;
+ bool crosses;
+ explicit crossings(const P& ap)
+ : p(ap)
+ , crosses(false)
+ {}
+ bool within() const
+ {
+ return crosses;
+ }
+ };
+
+ public :
+
+ typedef crossings state_type;
+
+ inline bool operator()(const const_segment<PS>& s, state_type& state) const
+ {
+ /* Algorithm:
+ if (
+ ( (y2 <= py && py < y1)
+ || (y1 <= py && py < y2) )
+ && (px < (x1 - x2)
+ * (py - y2)
+ / (y1 - y2) + x2)
+ )
+ crosses = ! crosses
+ */
+
+
+ if (
+ ((get<1>(s.second) <= get<1>(state.p) && get<1>(state.p) < get<1>(s.first))
+ || (get<1>(s.first) <= get<1>(state.p) && get<1>(state.p) < get<1>(s.second)))
+ && (get<0>(state.p) < (get<0>(s.first) - get<0>(s.second))
+ * (get<1>(state.p) - get<1>(s.second))
+ / (get<1>(s.first) - get<1>(s.second)) + get<0>(s.second))
+ )
+ {
+ state.crosses = ! state.crosses;
+ }
+ return true;
+ }
+ };
+
+
+ /*!
+ \brief Within detection using winding rule
+ \par Template parameters:
+ - \a P point type of point to examine
+ - \a PS point type of segments, defaults to P
+ \par Concepts for P and PS:
+ - specialized point_traits class
+ \author The implementation is inspired by terralib http://www.terralib.org (LGPL)
+ and http://geometryalgorithms.com/Archive/algorithm_0103/algorithm_0103.htm
+ \note Added the horizontal case, for "completely within"
+ \note Is tested for points ON border, more tests have to be done.
+ \note More efficient (less comparisons and no divison) than the cross count algorithm
+ */
+ template<typename P, typename PS = P>
+ class winding
+ {
+ private :
+ /*! subclass to keep state */
+ struct windings
+ {
+ int count;
+ bool touches;
+ P p;
+ explicit windings(const P& ap)
+ : p(ap)
+ , count(0)
+ , touches(false)
+ {}
+ bool within() const
+ {
+ return ! touches && count != 0;
+ }
+ };
+
+ public :
+
+ typedef windings state_type;
+
+ inline bool operator()(const const_segment<PS>& s, state_type& state) const
+ {
+ bool up = false;
+ bool down = false;
+
+ if (equals(get<1>(s.first), get<1>(state.p)) && equals(get<1>(s.first), get<1>(s.second)))
+ {
+ // Horizontal case
+ if (get<0>(s.first) <= get<0>(state.p) && get<0>(s.second) > get<0>(state.p))
+ {
+ up = true; // "up" means from left to right here
+ }
+ else if (get<0>(s.second) < get<0>(state.p) && get<0>(s.first) >= get<0>(state.p))
+ {
+ down = true; // from right to left
+ }
+ }
+ else if (get<1>(s.first) <= get<1>(state.p) && get<1>(s.second) > get<1>(state.p))
+ {
+ up = true;
+ }
+ else if (get<1>(s.second) < get<1>(state.p) && get<1>(s.first) >= get<1>(state.p))
+ {
+ down = true;
+ }
+
+ if (up || down)
+ {
+ typedef typename point_traits<P>::coordinate_type T;
+ T side = point_side(s, state.p);
+ if (equals<T>(side, 0))
+ {
+ state.touches = true;
+ return false;
+ }
+ else if (up && side > 0)
+ {
+ state.count++;
+ }
+ else if (down && side < 0)
+ {
+ state.count--;
+ }
+ }
+ return true;
+ }
+
+ };
+
+ } // namespace within
+
+
+ namespace centroid
+ {
+ /*!
+ \brief Centroid calculation
+ \details Geolib original version,
+ \par Template parameters and concepts: see bashein_detmer
+ \author Barend and Maarten, 1995/1996
+ \author Revised for templatized library, Barend Gehrels, 2007
+ \note The results are slightly different from Bashein/Detmer, so probably slightly wrong.
+ */
+
+ template<typename PC, typename PS = PC>
+ class geolib1995
+ {
+ private :
+ typedef typename point_traits<PS>::coordinate_type T;
+
+ /*! subclass to keep state */
+ struct sums
+ {
+ PC sum_ms, sum_m;
+
+ sums()
+ {
+ assign_point(sum_m, T());
+ assign_point(sum_ms, T());
+ }
+ void centroid(PC& point)
+ {
+ point = sum_ms;
+
+ if (get<0>(sum_m) != 0 && get<1>(sum_m) != 0)
+ {
+ multiply_value(point, 0.5);
+ divide_point(point, sum_m);
+ }
+ else
+ {
+ // exception?
+ }
+ }
+ };
+
+ public :
+ typedef sums state_type;
+ inline bool operator()(const const_segment<PS>& s, state_type& state) const
+ {
+ /* Algorithm:
+ For each segment:
+ begin
+ dx = x2 - x1;
+ dy = y2 - y1;
+ sx = x2 + x1;
+ sy = y2 + y1;
+ mx = dx * sy;
+ my = sx * dy;
+
+ sum_mx += mx;
+ sum_my += my;
+ sum_msx += mx * sx;
+ sum_msy += my * sy;
+ end;
+ return POINT(0.5 * sum_msx / sum_mx, 0.5 * sum_msy / sum_my);
+ */
+
+ PS diff = s.second, sum = s.second;
+ subtract_point(diff, s.first);
+ add_point(sum, s.first);
+
+ // We might create an arithmatic operation for this.
+ PS m;
+ get<0>(m) = get<0>(diff) * get<1>(sum);
+ get<1>(m) = get<0>(sum) * get<1>(diff);
+
+ add_point(state.sum_m, m);
+ multiply_point(m, sum);
+ add_point(state.sum_ms, m);
+
+ return true;
+ }
+
+ };
+
+
+ /*!
+ \brief Centroid calculation using algorith Bashein / Detmer
+ \details Calculates centroid using triangulation method published by Bashein / Detmer
+ \par Template parameters:
+ - \a PC point type of centroid to calculate
+ - \a PS point type of segments, defaults to PC
+ \par Concepts for PC and PS:
+ - specialized point_traits class
+ \author Adapted from "Centroid of a Polygon" by Gerard Bashein and Paul R. Detmer<em>,
+ in "Graphics Gems IV", Academic Press, 1994</em>
+ \par Research notes
+ The algorithm gives the same results as Oracle and PostgreSQL but differs from MySQL
+ (tried 5.0.21 / 5.0.45 / 5.0.51a / 5.1.23).
+
+ Without holes:
+ - this: POINT(4.06923 1.65056)
+ - geolib: POINT(4.07254 1.66819)
+ - MySQL: 'POINT(3.6636363636364 1.6272727272727)'
+ - PostgreSQL: "POINT(4.06923363095238 1.65055803571429)"
+ - Oracle: 4.06923363095238, 1.65055803571429
+
+ Statements:
+ - \b MySQL/PostgreSQL: select AsText(Centroid(GeomFromText('POLYGON((2 1.3,2.4 1.7,2.8 1.8,3.4 1.2
+ ,3.7 1.6,3.4 2,4.1 3,5.3 2.6,5.4 1.2,4.9 0.8,2.9 0.7,2 1.3))')))
+ - \b Oracle: select sdo_geom.sdo_centroid(sdo_geometry(2003, null, null,
+ sdo_elem_info_array(1, 1003, 1), sdo_ordinate_array(2,1.3,2.4,1.7,2.8,1.8
+ ,3.4,1.2,3.7,1.6,3.4,2,4.1,3,5.3,2.6,5.4,1.2,4.9,0.8,2.9,0.7,2,1.3))
+ , mdsys.sdo_dim_array(mdsys.sdo_dim_element('x',0,10,.00000005)
+ ,mdsys.sdo_dim_element('y',0,10,.00000005)))
+ from dual
+
+ With holes:
+ - this: POINT(4.04663 1.6349)
+ - geolib: POINT(4.04675 1.65735)
+ - MySQL: 'POINT(3.6090580503834 1.607573932092)'
+ - PostgresSQL: "POINT(4.0466265060241 1.63489959839357)"
+ - Oracle: 4.0466265060241, 1.63489959839357
+
+ Statements:
+ - \b MySQL/PostgreSQL: select AsText(Centroid(GeomFromText('POLYGON((2 1.3,2.4 1.7,2.8 1.8,3.4 1.2
+ ,3.7 1.6,3.4 2,4.1 3,5.3 2.6,5.4 1.2,4.9 0.8,2.9 0.7,2 1.3)
+ ,(4 2,4.2 1.4,4.8 1.9,4.4 2.2,4 2))')));
+ - \b Oracle: select sdo_geom.sdo_centroid(sdo_geometry(2003, null, null
+ , sdo_elem_info_array(1, 1003, 1, 25, 2003, 1)
+ , sdo_ordinate_array(2,1.3,2.4,1.7,2.8,1.8,3.4,1.2,3.7,1.6,3.4,2,4.1,3,5.3
+ ,2.6,5.4,1.2,4.9,0.8,2.9,0.7,2,1.3,4,2, 4.2,1.4, 4.8,1.9, 4.4,2.2, 4,2))
+ , mdsys.sdo_dim_array(mdsys.sdo_dim_element('x',0,10,.00000005)
+ ,mdsys.sdo_dim_element('y',0,10,.00000005)))
+ from dual
+ */
+ template<typename PC, typename PS = PC>
+ class bashein_detmer
+ {
+ private :
+ typedef typename point_traits<PS>::coordinate_type T;
+
+ /*! subclass to keep state */
+ struct sums
+ {
+ T sum_a2;
+ PC sum;
+ sums()
+ : sum_a2(T())
+ {
+ assign_value(sum, T());
+ }
+
+ void centroid(PC& point)
+ {
+ typedef typename point_traits<PC>::coordinate_type TPC;
+ point = sum;
+ if (sum_a2 != 0)
+ {
+ divide_value(point, double(3.0 * sum_a2));
+ }
+ else
+ {
+ // exception?
+ }
+ }
+
+ };
+
+ public :
+ typedef sums state_type;
+
+ inline bool operator()(const const_segment<PS>& s, state_type& state) const
+ {
+ /* Algorithm:
+ For each segment:
+ begin
+ ai = x1 * y2 - x2 * y1;
+ sum_a2 += ai;
+ sum_x += ai * (x1 + x2);
+ sum_y += ai * (y1 + y2);
+ end
+ return POINT(sum_x / (3 * sum_a2), sum_y / (3 * sum_a2) )
+ */
+
+ T ai = get<0>(s.first) * get<1>(s.second) - get<0>(s.second) * get<1>(s.first);
+ state.sum_a2 += ai;
+
+ PC p;
+ copy_coordinates(s.first, p);
+ add_point(p, s.second);
+ multiply_value(p, ai);
+ add_point(state.sum, p);
+
+ return true;
+ }
+
+ };
+ } // namespace centroid
+
+
+ namespace envelope
+ {
+ // envelope calculation strategy for xy-points
+ template <typename PB, typename P = PB>
+ struct grow_xy
+ {
+ struct state
+ {
+ box<PB> b;
+ state() : b(init_inverse) {}
+ void envelope(box<PB>& mbr)
+ {
+ mbr.min() = b.min();
+ mbr.max() = b.max();
+ }
+ };
+
+ typedef state state_type;
+
+ void operator()(const P& p, state_type& s) const
+ {
+ impl::grow::grow_p(s.b, p);
+ }
+ };
+ } // namespace envelope
+
+
+ } // namespace strategy
+
+
+} // namespace geometry
+
+
+#endif // _GEOMETRY_STRATEGIES_POINT_XY_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/strategies/strategy_traits.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/strategies/strategy_traits.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,99 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_STRATEGY_TRAITS_HPP
+#define _GEOMETRY_STRATEGY_TRAITS_HPP
+
+#include <geometry/strategies/strategies_point_xy.hpp>
+#include <geometry/strategies/strategies_point_ll.hpp>
+
+
+namespace geometry
+{
+
+ namespace strategy
+ {
+ /*!
+ \brief Indicate compiler/library user that strategy is not implemented.
+ \details The strategy_traits class define strategies for point types or for point type
+ combinations. If there is no implementation for that specific point type, or point type
+ combination, the calculation cannot be done. To indicate this, this not_implemented
+ class is used as a typedef stub.
+
+ */
+ struct not_implemented {};
+ }
+
+ /*!
+ \brief Base strategy class, defines not_implemented for all strategies.
+ \details The strategy_traits class defines strategies for:
+ - distance point to point
+ - distance point to line
+ - area calculation
+ - centroid calculation
+ - envelope calculation
+ - within detection
+ \note This is a base class, does NOT compile because doesn't define anything useful.
+ Specializations should define the correct implementations classes.
+ \note In case of compiler errors here, implement the correct specializations
+ */
+ template <typename P1, typename P2 = P1>
+ struct strategy_traits
+ {
+ typedef strategy::not_implemented point_distance;
+ typedef strategy::not_implemented point_segment_distance;
+ typedef strategy::not_implemented area;
+ typedef strategy::not_implemented within;
+ typedef strategy::not_implemented centroid;
+ typedef strategy::not_implemented envelope;
+ };
+
+
+ /*!
+ \brief Specialization for point_ll<degree/radian, T>
+ */
+ template <dr_selector D1, typename T1, dr_selector D2, typename T2>
+ struct strategy_traits<point_ll<D1, T1>, point_ll<D2, T2> >
+ {
+ typedef strategy::distance::haversine<point_ll<D1, T1>, point_ll<D2,T2> > point_distance;
+
+ // The point-segment calculation also uses a point-point calculation.
+ // For latlong, that encapsulated point-point calculation should always be defined in radian
+ typedef strategy::distance::ll_point_segment<point_ll<D1, T1>, point_ll<D2, T2> > point_segment_distance;
+
+ typedef strategy::area::by_spherical_excess<point_ll<D1, T1> > area;
+
+ typedef strategy::not_implemented within;
+ typedef strategy::not_implemented centroid;
+ typedef strategy::envelope::grow_ll<point_ll<D1, T1>, point_ll<D2, T2> > envelope;
+
+ };
+
+
+ /*!
+ \brief Specialization for point_xy<T>
+ */
+ template <typename T1, typename T2>
+ struct strategy_traits<point_xy<T1>, point_xy<T2> >
+ {
+ typedef strategy::distance::pythagoras<point_xy<T1>, point_xy<T2> > point_distance;
+ typedef strategy::distance::xy_point_segment<point_xy<T1>, point_xy<T2>, point_distance> point_segment_distance;
+
+ typedef strategy::area::by_triangles<point_xy<T1> > area;
+ typedef strategy::within::winding<point_xy<T1>, point_xy<T2> > within;
+
+ typedef strategy::centroid::bashein_detmer<point_xy<T1>, point_xy<T2> > centroid;
+
+ typedef strategy::envelope::grow_xy<point_xy<T1>, point_xy<T2> > envelope;
+
+ };
+
+
+} // namespace geometry
+
+
+#endif // _GEOMETRY_STRATEGY_TRAITS_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/streamwkt.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/streamwkt.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,57 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_STREAMWKT_HPP
+#define _GEOMETRY_STREAMWKT_HPP
+
+#include <geometry/aswkt.hpp>
+
+
+namespace geometry
+{
+
+ /*!
+ \brief Streams a point as Well-Known Text
+ \ingroup wkt
+ */
+ template <typename CH, typename TR, typename T, size_t D>
+ inline std::basic_ostream<CH,TR>& operator<<(std::basic_ostream<CH,TR> &os, const point<T, D> &p)
+ {
+ os << as_wkt<point<T, D> >(p);
+ return os;
+ }
+
+ /*!
+ \brief Streams a linestring as Well-Known Text
+ \ingroup wkt
+ */
+ template<typename CH, typename TR, typename P, template<typename,typename> class V, template<typename> class A>
+ inline std::basic_ostream<CH,TR>& operator<<(std::basic_ostream<CH,TR> &os, const linestring<P, V, A> &ls)
+ {
+ os << as_wkt<linestring<P, V, A> >(ls);
+ return os;
+ }
+
+ /*!
+ \brief Streams a polygon as Well-Known Text
+ \ingroup wkt
+ */
+ template<typename CH, typename TR, typename P,
+ template<typename,typename> class VP,
+ template<typename,typename> class VR,
+ template<typename> class AP,
+ template<typename> class AR>
+ inline std::basic_ostream<CH,TR>& operator<<(std::basic_ostream<CH,TR> &os, const polygon<P, VP, VR, AP, AR>& poly)
+ {
+ os << as_wkt<polygon<P, VP, VR, AP, AR> >(poly);
+ return os;
+ }
+
+}
+
+
+#endif // _GEOMETRY_ASTEXT_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/test/Jamroot
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/test/Jamroot 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,22 @@
+# Geometry Library unit tests
+#
+# Copyright Bruno Lalande 2008
+# Copyright Barend Gehrels, Geodan Holding B.V. 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)
+
+
+lib boost_unit_test_framework ;
+
+project : requirements
+ <include>../..
+ <library>boost_unit_test_framework
+;
+
+import testing ;
+
+run for_each_coordinate.cpp ;
+run arithmetic.cpp ;
+run dot_product.cpp ;
+run pythagoras.cpp ;

Added: sandbox/SOC/2008/spacial_indexing/geometry/test/arithmetic.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/test/arithmetic.cpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,95 @@
+// Geometry Library test file
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008
+// 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)
+
+
+#define BOOST_TEST_MODULE
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+#include <geometry/arithmetic.hpp>
+#include "common.hpp"
+
+
+using namespace geometry;
+
+
+template <typename P>
+void test_addition()
+{
+ P p1;
+ init_point(p1, 1, 2, 3);
+ geometry::add_value(p1, 10);
+ BOOST_CHECK(get<0>(p1) == 11);
+ BOOST_CHECK(get<1>(p1) == 12);
+ BOOST_CHECK(get<2>(p1) == 13);
+
+ P p2;
+ init_point(p2, 4, 5, 6);
+ geometry::add_point(p1, p2);
+ BOOST_CHECK(get<0>(p1) == 15);
+ BOOST_CHECK(get<1>(p1) == 17);
+ BOOST_CHECK(get<2>(p1) == 19);
+}
+
+template <typename P>
+void test_subtraction()
+{
+ P p1;
+ init_point(p1, 1, 2, 3);
+ geometry::subtract_value(p1, 10);
+ BOOST_CHECK(get<0>(p1) == -9);
+ BOOST_CHECK(get<1>(p1) == -8);
+ BOOST_CHECK(get<2>(p1) == -7);
+
+ P p2;
+ init_point(p2, 4, 6, 8);
+ geometry::subtract_point(p1, p2);
+ BOOST_CHECK(get<0>(p1) == -13);
+ BOOST_CHECK(get<1>(p1) == -14);
+ BOOST_CHECK(get<2>(p1) == -15);
+}
+
+template <typename P>
+void test_multiplication()
+{
+ P p;
+ init_point(p, 1, 2, 3);
+ geometry::multiply(p, 5);
+ BOOST_CHECK(get<0>(p) == 5);
+ BOOST_CHECK(get<1>(p) == 10);
+ BOOST_CHECK(get<2>(p) == 15);
+}
+
+template <typename P>
+void test_division()
+{
+ P p;
+ init_point(p, 50, 100, 150);
+ geometry::divide(p, 5);
+ BOOST_CHECK(get<0>(p) == 10);
+ BOOST_CHECK(get<1>(p) == 20);
+ BOOST_CHECK(get<2>(p) == 30);
+}
+
+
+template <typename P>
+void test_all()
+{
+ test_addition<P>();
+ test_subtraction<P>();
+ test_multiplication<P>();
+ test_division<P>();
+}
+
+
+BOOST_AUTO_TEST_CASE(arithmetic_test)
+{
+ test_all<int[3]>();
+ test_all<float[3]>();
+ test_all<double[3]>();
+ test_all<test_point>();
+}

Added: sandbox/SOC/2008/spacial_indexing/geometry/test/common.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/test/common.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,41 @@
+// Geometry Library test file
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008
+// 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 _GEOMETRY_TEST_COMMON_HPP
+#define _GEOMETRY_TEST_COMMON_HPP
+
+
+#include <boost/tuple/tuple.hpp>
+#include <geometry/concepts/point_traits.hpp>
+
+
+// Test point class
+
+struct test_point: public boost::tuple<float, float, float>
+{
+ typedef float coordinate_type;
+ enum { coordinate_count = 3 };
+};
+
+
+// Generic initialization function
+
+template <typename P>
+void init_point(P& p,
+ typename geometry::point_traits<P>::coordinate_type c1,
+ typename geometry::point_traits<P>::coordinate_type c2,
+ typename geometry::point_traits<P>::coordinate_type c3)
+{
+ geometry::get<0>(p) = c1;
+ geometry::get<1>(p) = c2;
+ geometry::get<2>(p) = c3;
+}
+
+
+#endif

Added: sandbox/SOC/2008/spacial_indexing/geometry/test/compile_test.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/test/compile_test.cpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,219 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan B.V. 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)
+
+#include <vector>
+#include <deque>
+#include <list>
+
+
+#include <string>
+
+#include <limits>
+
+#include <iostream>
+#include <sstream>
+
+#include <geometry/area.hpp>
+//#include <geometry/astext.hpp>
+#include <geometry/box.hpp>
+#include <geometry/centroid.hpp>
+#include <geometry/circle.hpp>
+#include <geometry/correct.hpp>
+#include <geometry/distance.hpp>
+#include <geometry/envelope.hpp>
+#include <geometry/foreach.hpp>
+#include <geometry/geometry.hpp>
+#include <geometry/intersection.hpp>
+#include <geometry/length.hpp>
+#include <geometry/overlaps.hpp>
+#include <geometry/simplify.hpp>
+#include <geometry/within.hpp>
+#include <geometry/util/side.hpp>
+
+
+template<typename P>
+struct modifying_functor
+{
+ double sum;
+ modifying_functor() : sum(0)
+ {}
+ inline void operator()(P& p)
+ {
+ p.x(1);
+ }
+
+ inline void operator()(geometry::segment<P>& s)
+ {
+ s.first.x(1);
+ }
+};
+
+template<typename P>
+struct const_functor
+{
+ double sum;
+ const_functor() : sum(0)
+ {}
+ inline void operator()(const P& p)
+ {
+ sum += p.x();
+ }
+
+ inline void operator()(const geometry::const_segment<P>& s)
+ {
+ sum += s.first.x() - s.second.x();
+ }
+};
+
+
+template <typename T, template<typename,typename> class V>
+void check_linestring()
+{
+ typedef geometry::point<T> P;
+ typedef geometry::linestring<P, V, std::allocator> L;
+ L line;
+ line.push_back(P(0,0));
+ line.push_back(P(1,1));
+
+ typedef geometry::multi_linestring<L, V, std::allocator> ML;
+ ML multi;
+ multi.push_back(line);
+
+ double len = geometry::length(line);
+ len = geometry::length(multi);
+ double d = geometry::distance(P(0,1), line);
+ //d = geometry::distance(P(0,1), multi); not defined yet!
+
+ L simp;
+ geometry::simplify(line, simp, 3);
+ ML simpm;
+ geometry::simplify(multi, simpm, 3);
+
+ typedef geometry::box<P> B;
+ B b = geometry::envelope(line);
+ b = geometry::envelope(multi);
+
+ std::stringstream out;
+ out << line << std::endl;
+ //out << multi << std::endl;
+
+ // For each, const
+ const_functor<P> cf;
+ std::for_each(line.begin(), line.end(), cf);
+
+ const L& cl = line;
+ const ML& cm = multi;
+
+ geometry::for_each_point(cl, cf);
+ geometry::for_each_point(cm, cf);
+ geometry::for_each_segment(cl, cf);
+ geometry::for_each_segment(cm, cf);
+
+ // For each, modifying
+ modifying_functor<P> mf;
+ L& ml = line;
+ ML& mm = multi;
+ std::for_each(line.begin(), line.end(), mf);
+ geometry::for_each_point(ml, mf);
+ geometry::for_each_point(mm, mf);
+ geometry::for_each_segment(ml, mf);
+ geometry::for_each_segment(mm, mf);
+}
+
+
+template <typename T, template<typename,typename> class VP,
+ template<typename,typename> class VR>
+void check_polygon()
+{
+ typedef geometry::point<T> P;
+ typedef geometry::polygon<P, VP, VR, std::allocator, std::allocator> Y;
+ Y poly;
+ poly.outer().push_back(P(0,0));
+ poly.outer().push_back(P(2,0));
+ poly.outer().push_back(P(2,2));
+ poly.outer().push_back(P(0,2));
+
+ geometry::correct(poly);
+
+ // multi
+ typedef geometry::multi_polygon<Y, VP, std::allocator> MY;
+ MY multi;
+ multi.push_back(poly);
+
+ double a = geometry::area(poly);
+ a = geometry::area(multi);
+
+ //double d = geometry::distance(P(0,1), poly);
+
+ Y simp;
+ geometry::simplify(poly, simp, 3);
+ MY msimp;
+ geometry::simplify(multi, msimp, 3);
+
+ typedef geometry::box<P> B;
+ B b = geometry::envelope(poly);
+ b = geometry::envelope(multi);
+ P ctr = geometry::centroid(poly);
+
+ // within
+ typedef geometry::circle<P, T> C;
+ C circ(P(10,10), 10);
+
+ bool w = geometry::within(P(1, 1), poly);
+ w = geometry::within(poly, circ);
+ //w = geometry::within(poly, b); tbd
+ w = geometry::within(P(1, 1), multi);
+ w = geometry::within(multi, circ);
+ //w = geometry::within(multi, b); tbd
+
+ // For each, const
+ const_functor<P> cf;
+ std::for_each(poly.outer().begin(), poly.outer().end(), cf);
+
+ const Y& cp = poly;
+ const MY& cm = multi;
+
+ geometry::for_each_point(cp, cf);
+ geometry::for_each_point(cm, cf);
+ geometry::for_each_segment(cp, cf);
+ geometry::for_each_segment(cm, cf);
+
+ // For each, modifying
+ modifying_functor<P> mf;
+ Y& mp = poly;
+ MY& mm = multi;
+ std::for_each(poly.outer().begin(), poly.outer().end(), mf);
+ geometry::for_each_point(mp, mf);
+ geometry::for_each_point(mm, mf);
+ geometry::for_each_segment(mp, mf);
+ geometry::for_each_segment(mm, mf);
+}
+
+
+int main()
+{
+ check_linestring<double, std::vector>();
+ check_linestring<float, std::vector>();
+ check_linestring<int, std::vector>();
+ check_linestring<char, std::vector>();
+
+ check_linestring<double, std::list>();
+ check_linestring<double, std::deque>();
+
+ check_polygon<double, std::vector, std::vector>();
+ check_polygon<float, std::vector, std::vector>();
+ check_polygon<int, std::vector, std::vector>();
+ check_polygon<char, std::vector, std::vector>();
+
+ check_polygon<double, std::list, std::vector>();
+ check_polygon<double, std::deque, std::vector>();
+ check_polygon<double, std::list, std::list>();
+ check_polygon<double, std::deque, std::deque>();
+
+ return 0;
+}
+

Added: sandbox/SOC/2008/spacial_indexing/geometry/test/compile_test.vcproj
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/test/compile_test.vcproj 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,297 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="compile_test"
+ ProjectGUID="{618D4B05-A06E-443B-87C0-94964CEA7164}"
+ RootNamespace="compile_test"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=".;..;../..;../../..;C:\svn\geolib\trunk\src\cpp\contrib"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="0"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="kernel32.lib $(NoInherit)"
+ LinkIncremental="2"
+ 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)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=".;..;../..;../../..;C:\svn\geolib\trunk\src\cpp\contrib"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="0"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="kernel32.lib $(NoInherit)"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ 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>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\compile_test.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\area.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\astext.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\box.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\centroid.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\circle.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\distance.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\envelope.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\foreach.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\geometry.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\grow.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\intersection_linestring.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\intersection_polygon.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\intersection_segment.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\length.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\normalize.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\overlaps.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\segment.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\simplify.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\within.hpp"
+ >
+ </File>
+ <Filter
+ Name="util"
+ >
+ <File
+ RelativePath="..\util\equals.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\util\reserve.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\util\selecttypetraits.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\util\side.hpp"
+ >
+ </File>
+ </Filter>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>

Added: sandbox/SOC/2008/spacial_indexing/geometry/test/dot_product.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/test/dot_product.cpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,37 @@
+// Geometry Library test file
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008
+// 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)
+
+
+#define BOOST_TEST_MODULE
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+#include <geometry/dot_product.hpp>
+#include "common.hpp"
+
+
+using namespace geometry;
+
+
+template <typename P>
+void test_all()
+{
+ P p1;
+ init_point(p1, 1, 2, 3);
+ P p2;
+ init_point(p2, 4, 5, 6);
+ BOOST_CHECK(geometry::dot_product(p1, p2) == 1*4 + 2*5 + 3*6);
+}
+
+
+BOOST_AUTO_TEST_CASE(dot_product_test)
+{
+ test_all<int[3]>();
+ test_all<float[3]>();
+ test_all<double[3]>();
+ test_all<test_point>();
+}

Added: sandbox/SOC/2008/spacial_indexing/geometry/test/for_each_coordinate.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/test/for_each_coordinate.cpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,46 @@
+// Geometry Library test file
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008
+// 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)
+
+
+#define BOOST_TEST_MODULE
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+#include <geometry/for_each_coordinate.hpp>
+#include "common.hpp"
+
+
+using namespace geometry;
+
+
+struct test_operation
+{
+ template <typename P, int I>
+ void operator()(P& p) const
+ { get<I>(p) *= 10; }
+};
+
+
+template <typename P>
+void test_all()
+{
+ P p;
+ init_point(p, 1, 2, 3);
+ geometry::for_each_coordinate(p, test_operation());
+ BOOST_CHECK(get<0>(p) == 10);
+ BOOST_CHECK(get<1>(p) == 20);
+ BOOST_CHECK(get<2>(p) == 30);
+}
+
+
+BOOST_AUTO_TEST_CASE(for_each_coordinate_test)
+{
+ test_all<int[3]>();
+ test_all<float[3]>();
+ test_all<double[3]>();
+ test_all<test_point>();
+}

Added: sandbox/SOC/2008/spacial_indexing/geometry/test/geometry_tests.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/test/geometry_tests.cpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,213 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan B.V. 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)
+
+#include <vector>
+#include <string>
+#include <deque>
+#include <list>
+#include <limits>
+
+#include <cmath>
+
+#include <geometry/geometry.hpp>
+#include <geometry/box.hpp>
+#include <geometry/circle.hpp>
+#include <geometry/envelope.hpp>
+#include <geometry/within.hpp>
+#include <geometry/area.hpp>
+#include <geometry/distance.hpp>
+#include <geometry/length.hpp>
+#include <geometry/overlaps.hpp>
+#include <geometry/correct.hpp>
+#include <geometry/centroid.hpp>
+
+#include <geometry/intersection_segment.hpp>
+#include <geometry/intersection_linestring.hpp>
+#include <geometry/intersection_polygon.hpp>
+
+#include <geometry/astext.hpp>
+#include <geometry/point_on_line.hpp>
+
+
+void test_equals()
+{
+ geometry::point<double> p1(1, 1), p2(1,1 + std::numeric_limits<double>::epsilon() * 2.0);
+ geometry::point<int> p3(1,1), p4(1,1);
+
+ std::cout << (p1 == p2 ? "true" : "false" ) << std::endl;
+ std::cout << (p3 == p4 ? "true" : "false" ) << std::endl;
+}
+
+
+
+
+void test(double x1, double y1, double x2, double y2)
+{
+ //geometry::box<geometry::point<double> > e(70,60, 230,150);
+ geometry::box<geometry::point<double> > e(0.30, 0.30, 0.70, 0.70);
+ geometry::point<double> p1(x1, y1);
+ geometry::point<double> p2(x2, y2);
+
+ bool c1, c2;
+ geometry::segment<geometry::point<double> >s(p1, p2);
+ if (geometry::_clip_segment_liang_barsky(e, s, c1, c2))
+ {
+ if (c1) std::cout << "p1 clipped ";
+ if (c2) std::cout << "p2 clipped ";
+ std::cout
+ << p1.x() << ", "
+ << p1.y() << ", "
+ << p2.x() << ", "
+ << p2.y() << std::endl;
+ }
+ else
+ {
+ std::cout << "not visible" << std::endl;
+ }
+ std::cout << std::endl;
+}
+
+void test_line(const geometry::linestring<geometry::point<double> >& line)
+{
+ //geometry::box<geometry::point<double> > e(70,60, 230,150);
+ geometry::box<geometry::point<double> > e(0.30, 0.30, 0.70, 0.70);
+
+ geometry::multi_linestring<geometry::linestring<geometry::point<double> >> out;
+
+ geometry::clip_linestring(e, line, out);
+ for (int i = 0; i < out.size(); i++)
+ {
+ const geometry::linestring<geometry::point<double> >& ol = out[i];
+ for (int j = 0; j < ol.size(); j++)
+ {
+ const geometry::point<double>& p = ol[j];
+ std::cout << "("
+ << p.x() << ", "
+ << p.y() << ") " ;
+
+ }
+ std::cout << std::endl;
+ }
+}
+
+void test_ring(const geometry::linear_ring<geometry::point<double> >& linear_ring)
+{
+ std::cout << "linear_ring" << std::endl;
+ // normal: geometry::box<geometry::point<double> > e(0.30, 0.25, 0.70, 0.75); -> 0.01, 0.06
+ // difficult 1: geometry::box<geometry::point<double> > e(0.30, 0.30, 0.70, 0.70); --> 0.05
+ // difficult 2: geometry::box<geometry::point<double> > e(0.50, 0.30, 0.70, 0.70);
+ geometry::box<geometry::point<double> > e(0.50, 0.30, 0.70, 0.70);
+
+ std::cout << "linear_ring: " << linear_ring << std::endl;
+
+ std::vector<geometry::linear_ring<geometry::point<double> >> v;
+ clip_poly_weiler_atherton(e, linear_ring, v);
+
+ for (int i = 0; i < v.size(); i++)
+ {
+ //set_ordered(v[i]);
+ std::cout << "linear_ring " << i+1 << ": " << v[i] << std::endl;
+ }
+}
+
+
+
+void test_side(double x1, double y1, double x2, double y2, double x, double y)
+{
+ typedef geometry::point<double> glp ;
+ typedef geometry::const_segment<glp> gls;
+ glp p1(x1,y1);
+ glp p2(x2,y2);
+ glp p(x,y);
+ double r = geometry::point_side(gls(p1, p2), p);
+ std::cout << r << " " << p1 << "-" << p2 << ": " << p << std::endl;
+}
+
+
+
+
+
+int main1(void)
+{
+ test_equals();
+
+ test_side(0,1, 2,1, 0,0);
+ test_side(0,1, 2,1, 1,0);
+ test_side(0,1, 2,1, 1,2);
+ test_side(0,1, 2,1, 2,1);
+ test_side(0,1, 2,1, 3,1);
+
+/*
+ test_intersection(0,0, 0,2, 0,1, 1,1, 1, 0,1, 0,0);
+ test_intersection(0,1, 1,1, 0,0, 0,2, 1, 0,1, 0,0);
+ test_intersection(0,2, 2,2, 1,1, 1,2, 1, 1,2, 0,0);
+ test_intersection(1,1, 1,2, 0,2, 2,2, 1, 1,2, 0,0);
+ test_intersections();
+ */
+ //return 0;
+
+
+ //geometry::point<double> p1(30,20); geometry::point<double> p2(280,160);
+ //geometry::box<geometry::point<double> > e(0.30, 0.30, 0.70, 0.70);
+ //geometry::point<double> p1(0.052, 0.674); geometry::point<double> p2(0.902, 0.744);
+ //geometry::point<double> p1(0.4, 0.4); geometry::point<double> p2(0.6, 0.6);
+ test(0.4, 0.4, 0.6, 0.6); // inside
+ test(0.052, 0.674, 0.902, 0.744); // both clipped
+ test(0.45, 0.45, 0.15, 0.15); // second clipped
+ test(0.5, 0.8, 0.4, 0.4); // first clipped
+ test(0.0, 0.0, 0.5, 0.5); // first clipped
+
+ geometry::linestring<geometry::point<double> > l;
+ l.push_back(geometry::point<double>(0.0, 0.0));
+ l.push_back(geometry::point<double>(0.5, 0.5));
+ l.push_back(geometry::point<double>(1.0, 0.0));
+ test_line(l);
+
+ l.clear();
+ l.push_back(geometry::point<double>(0.1, 0.0));
+ l.push_back(geometry::point<double>(0.5, 0.8));
+ l.push_back(geometry::point<double>(0.9, 0.0));
+ test_line(l);
+
+ l.clear();
+ l.push_back(geometry::point<double>(0.5, 0.5));
+ l.push_back(geometry::point<double>(0.3, 0.3));
+ l.push_back(geometry::point<double>(0.4, 0.7));
+ l.push_back(geometry::point<double>(0.7, 0.3));
+ test_line(l);
+
+ geometry::linear_ring<geometry::point<double> > r;
+ r.push_back(geometry::point<double>(0.5, 0.5));
+ r.push_back(geometry::point<double>(0.8, 0.71));
+ r.push_back(geometry::point<double>(0.9, 0.6));
+ r.push_back(geometry::point<double>(0.6, 0.2));
+ r.push_back(geometry::point<double>(0.5, 0.5));
+// test_ring(r);
+
+ r.clear();
+ r.push_back(geometry::point<double>(0.5, 0.2));
+ r.push_back(geometry::point<double>(0.5, 0.3));
+ r.push_back(geometry::point<double>(0.8, 0.3));
+ r.push_back(geometry::point<double>(0.8, 0.4));
+ r.push_back(geometry::point<double>(0.5, 0.4));
+ r.push_back(geometry::point<double>(0.5, 0.8));
+ r.push_back(geometry::point<double>(0.9, 0.8));
+
+ // case x
+ r.push_back(geometry::point<double>(0.9, 0.7));
+ r.push_back(geometry::point<double>(0.6, 0.7));
+ r.push_back(geometry::point<double>(0.6, 0.6));
+ r.push_back(geometry::point<double>(0.9, 0.6));
+
+ // end case x
+
+ r.push_back(geometry::point<double>(0.9, 0.2));
+ r.push_back(geometry::point<double>(0.5, 0.2));
+ test_ring(r);
+
+ return 0;
+}
\ No newline at end of file

Added: sandbox/SOC/2008/spacial_indexing/geometry/test/geometry_tests.sln
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/test/geometry_tests.sln 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,25 @@
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual C++ Express 2005
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "compile_test", "compile_test.vcproj", "{618D4B05-A06E-443B-87C0-94964CEA7164}"
+EndProject
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "well_formed_point", "point_concept_tests\well_formed_point.vcproj", "{B63710DE-960E-4C00-B79A-7C8F80D6BC15}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {618D4B05-A06E-443B-87C0-94964CEA7164}.Debug|Win32.ActiveCfg = Debug|Win32
+ {618D4B05-A06E-443B-87C0-94964CEA7164}.Debug|Win32.Build.0 = Debug|Win32
+ {618D4B05-A06E-443B-87C0-94964CEA7164}.Release|Win32.ActiveCfg = Release|Win32
+ {618D4B05-A06E-443B-87C0-94964CEA7164}.Release|Win32.Build.0 = Release|Win32
+ {B63710DE-960E-4C00-B79A-7C8F80D6BC15}.Debug|Win32.ActiveCfg = Debug|Win32
+ {B63710DE-960E-4C00-B79A-7C8F80D6BC15}.Debug|Win32.Build.0 = Debug|Win32
+ {B63710DE-960E-4C00-B79A-7C8F80D6BC15}.Release|Win32.ActiveCfg = Release|Win32
+ {B63710DE-960E-4C00-B79A-7C8F80D6BC15}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal

Added: sandbox/SOC/2008/spacial_indexing/geometry/test/geometry_tests.vcproj
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/test/geometry_tests.vcproj 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,289 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="8.00"
+ Name="geometry_tests"
+ ProjectGUID="{618D4B05-A06E-443B-87C0-94964CEA7164}"
+ RootNamespace="geometry_tests"
+ Keyword="Win32Proj"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=".;..;../..;C:\svn\geolib\trunk\src\cpp\contrib"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="0"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="kernel32.lib $(NoInherit)"
+ LinkIncremental="2"
+ 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)"
+ ConfigurationType="1"
+ CharacterSet="1"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ AdditionalIncludeDirectories=".;..;../..;C:\svn\geolib\trunk\src\cpp\contrib"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ UsePrecompiledHeader="0"
+ WarningLevel="0"
+ Detect64BitPortabilityProblems="true"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="kernel32.lib $(NoInherit)"
+ LinkIncremental="1"
+ GenerateDebugInformation="true"
+ 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>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\geometry_tests.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\intersection_test.cpp"
+ >
+ </File>
+ <File
+ RelativePath=".\within_test.cpp"
+ >
+ <FileConfiguration
+ Name="Debug|Win32"
+ ExcludedFromBuild="true"
+ >
+ <Tool
+ Name="VCCLCompilerTool"
+ />
+ </FileConfiguration>
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\area.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\astext.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\box.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\centroid.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\circle.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\distance.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\envelope.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\geometry.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\grow.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\intersection_linestring.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\intersection_polygon.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\intersection_segment.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\length.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\normalize.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\overlaps.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\point_on_line.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\segment.hpp"
+ >
+ </File>
+ <File
+ RelativePath="..\within.hpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>

Added: sandbox/SOC/2008/spacial_indexing/geometry/test/intersection_test.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/test/intersection_test.cpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,129 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan B.V. 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)
+
+#include <sstream>
+
+#include <geometry/geometry.hpp>
+#include <geometry/within.hpp>
+#include <geometry/correct.hpp>
+
+#include <geometry/intersection_segment.hpp>
+
+#include <geometry/astext.hpp>
+
+#include <boost/config.hpp>
+#include <boost/test/included/test_exec_monitor.hpp>
+//#include <boost/test/unit_test.hpp>
+
+
+static std::ostream & operator<<(std::ostream &s, const geometry::intersection_result& r)
+{
+ switch(r)
+ {
+ case geometry::is_intersect_no : s << "is_intersect_no"; break;
+ case geometry::is_intersect : s << "is_intersect"; break;
+ case geometry::is_parallel : s << "is_parallel"; break;
+ case geometry::is_collinear_no : s << "is_collinear_no"; break;
+ case geometry::is_collinear_one : s << "is_collinear_one"; break;
+ case geometry::is_collinear_connect : s << "is_collinear_connect"; break;
+ case geometry::is_collinear_overlap : s << "is_collinear_overlap"; break;
+ case geometry::is_collinear_overlap_opposite : s << "is_collinear_overlap_opposite"; break;
+ case geometry::is_collinear_connect_opposite : s << "is_collinear_connect_opposite"; break;
+
+ // detailed connection results:
+ case geometry::is_intersect_connect_s1p1 : s << "is_intersect_connect_s1p1"; break;
+ case geometry::is_intersect_connect_s1p2 : s << "is_intersect_connect_s1p2"; break;
+ case geometry::is_intersect_connect_s2p1 : s << "is_intersect_connect_s2p1"; break;
+ case geometry::is_intersect_connect_s2p2 : s << "is_intersect_connect_s2p2"; break;
+ }
+ return s;
+}
+
+static std::string as_string(const geometry::intersection_result& r)
+{
+ std::stringstream out;
+ out << r;
+ return out.str();
+}
+
+typedef geometry::point<double> P;
+typedef geometry::const_segment<P> S;
+
+
+static void test_intersection(double s1x1, double s1y1, double s1x2, double s1y2,
+ double s2x1, double s2y1, double s2x2, double s2y2,
+ // Expected results
+ geometry::intersection_result expected_result,
+ int exptected_count, const P& exp_p1, const P& exp_p2)
+{
+ S s1(P(s1x1, s1y1), P(s1x2, s1y2));
+ S s2(P(s2x1, s2y1), P(s2x2, s2y2));
+ std::vector<P> ip;
+ double ra, rb;
+ geometry::intersection_result r = geometry::intersection_s(s1, s2, ra, rb, ip);
+ r = geometry::intersection_connect_result(r, ra, rb);
+
+ BOOST_CHECK_EQUAL(ip.size(), exptected_count);
+ BOOST_CHECK_EQUAL(as_string(expected_result), as_string(r));
+
+ if (ip.size() == 2 && ip[0] != exp_p1)
+ {
+ // Swap results, second point is not as expected, swap results, order is not prescribed,
+ // it might be OK.
+ std::reverse(ip.begin(), ip.end());
+ }
+
+ if (ip.size() >= 1)
+ {
+ BOOST_CHECK_EQUAL(ip[0], exp_p1);
+ }
+ if (ip.size() >= 2)
+ {
+ BOOST_CHECK_EQUAL(ip[1], exp_p2);
+ }
+
+
+ /*
+ std::cout << exptected_count << " " << r;
+ if (exptected_count >= 1) std::cout << " " << ip[0];
+ if (exptected_count >= 2) std::cout << " " << ip[1];
+ std::cout << std::endl;
+ */
+}
+
+//BOOST_AUTO_TEST_CASE( test1 )
+int test_main( int , char* [] )
+{
+ // Identical cases
+ test_intersection(0,0, 1,1, 0,0, 1,1, geometry::is_collinear_overlap, 2, P(0,0), P(1,1));
+ test_intersection(1,1, 0,0, 0,0, 1,1, geometry::is_collinear_overlap_opposite, 2, P(1,1), P(0,0));
+ test_intersection(0,1, 0,2, 0,1, 0,2, geometry::is_collinear_overlap, 2, P(0,1), P(0,2)); // Vertical
+ test_intersection(0,2, 0,1, 0,1, 0,2, geometry::is_collinear_overlap_opposite, 2, P(0,2), P(0,1)); // Vertical
+ // Overlap cases
+ test_intersection(0,0, 1,1, -0.5,-0.5, 2,2, geometry::is_collinear_overlap, 2, P(0,0), P(1,1));
+ test_intersection(0,0, 1,1, 0.5,0.5, 1.5,1.5, geometry::is_collinear_overlap, 2, P(0.5,0.5), P(1,1));
+ test_intersection(0,0, 0,1, 0,-10, 0,10, geometry::is_collinear_overlap, 2, P(0,0), P(0,1)); // Vertical
+ test_intersection(0,0, 0,1, 0,10, 0,-10, geometry::is_collinear_overlap_opposite, 2, P(0,0), P(0,1)); // Vertical
+ test_intersection(0,0, 1,1, 1,1, 2,2, geometry::is_collinear_connect, 1, P(1,1), P(0,0)); // Single point
+ // Colinear, non overlap cases
+ test_intersection(0,0, 1,1, 1.5,1.5, 2.5,2.5, geometry::is_collinear_no, 0, P(0,0), P(0,0));
+ test_intersection(0,0, 0,1, 0,5, 0,6, geometry::is_collinear_no, 0, P(0,0), P(0,0)); // Vertical
+ // Parallel cases
+ test_intersection(0,0, 1,1, 1,0, 2,1, geometry::is_parallel, 0, P(0,0), P(0,1));
+ // Intersect cases
+ test_intersection(0,2, 4,2, 3,0, 3,4, geometry::is_intersect, 1, P(3,2), P(0,0));
+ // Non intersect cases
+
+ // Single point cases
+ test_intersection(0,0, 0,0, 1,1, 2,2, geometry::is_collinear_no, 0, P(1,1), P(0,0)); // Colinear/no
+ test_intersection(2,2, 2,2, 1,1, 3,3, geometry::is_collinear_one, 1, P(2,2.01), P(0,0)); // On segment
+ test_intersection(1,1, 3,3, 2,2, 2,2, geometry::is_collinear_one, 1, P(2,2), P(0,0)); // On segment
+ test_intersection(1,1, 3,3, 1,1, 1,1, geometry::is_collinear_one, 1, P(1,1), P(0,0)); // On segment, start
+ test_intersection(1,1, 3,3, 3,3, 3,3, geometry::is_collinear_one, 1, P(3,3), P(0,0)); // On segment, end
+
+ return 0;
+}

Added: sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/Jamroot
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/Jamroot 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,21 @@
+# Geometry Library Point concept unit tests
+#
+# Copyright Bruno Lalande 2008
+# Copyright Barend Gehrels, Geodan Holding B.V. 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)
+
+
+project : requirements <include>../../.. ;
+
+import testing ;
+
+compile well_formed_point.cpp ;
+compile well_formed_point_traits.cpp ;
+compile array_point.cpp ;
+compile-fail point_without_coord_type.cpp ;
+compile-fail point_without_coord_count.cpp ;
+compile-fail point_without_getter.cpp ;
+compile-fail point_without_setter.cpp ;
+compile-fail point_with_incorrect_coord_count.cpp ;

Added: sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/array_point.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/array_point.cpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,18 @@
+// Geometry Library Point concept test file
+//
+// Copyright Bruno Lalande 2008
+// Copyright Barend Gehrels, Geodan Holding B.V. 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)
+
+
+#include "function_requiring_a_point.hpp"
+
+
+int main()
+{
+ float p1[3] = { 0, 0, 0 };
+ const float p2[3] = { 0, 0, 0 };
+ geometry::function_requiring_a_point(p1, p2);
+}

Added: sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/function_requiring_a_point.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/function_requiring_a_point.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,32 @@
+// Geometry Library Point concept unit tests
+//
+// Copyright Bruno Lalande 2008
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_FUNCTION_REQUIRING_A_POINT_HPP
+#define _GEOMETRY_FUNCTION_REQUIRING_A_POINT_HPP
+
+
+#include <boost/concept/requires.hpp>
+#include <geometry/concepts/point_concept.hpp>
+
+
+namespace geometry
+{
+ template <typename P>
+ BOOST_CONCEPT_REQUIRES(
+ ((Point<P>)),
+ (void))
+ function_requiring_a_point(P& p1, const P& p2)
+ {
+ point_traits<P>::template get<0>(p1) =
+ point_traits<const P>::template get<0>(p2);
+ }
+}
+
+
+#endif

Added: sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/point_with_incorrect_coord_count.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/point_with_incorrect_coord_count.cpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,26 @@
+// Geometry Library Point concept test file
+//
+// Copyright Bruno Lalande 2008
+// Copyright Barend Gehrels, Geodan Holding B.V. 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)
+
+
+#include <boost/tuple/tuple.hpp>
+#include "function_requiring_a_point.hpp"
+
+
+struct point: public boost::tuple<float, float>
+{
+ typedef float coordinate_type;
+ enum { coordinate_count = 3 };
+};
+
+
+int main()
+{
+ point p1;
+ const point p2;
+ geometry::function_requiring_a_point(p1, p2);
+}

Added: sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/point_without_coord_count.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/point_without_coord_count.cpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,25 @@
+// Geometry Library Point concept test file
+//
+// Copyright Bruno Lalande 2008
+// Copyright Barend Gehrels, Geodan Holding B.V. 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)
+
+
+#include <boost/tuple/tuple.hpp>
+#include "function_requiring_a_point.hpp"
+
+
+struct point: public boost::tuple<float, float>
+{
+ typedef float coordinate_type;
+};
+
+
+int main()
+{
+ point p1;
+ const point p2;
+ geometry::function_requiring_a_point(p1, p2);
+}

Added: sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/point_without_coord_type.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/point_without_coord_type.cpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,25 @@
+// Geometry Library Point concept test file
+//
+// Copyright Bruno Lalande 2008
+// Copyright Barend Gehrels, Geodan Holding B.V. 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)
+
+
+#include <boost/tuple/tuple.hpp>
+#include "function_requiring_a_point.hpp"
+
+
+struct point: public boost::tuple<float, float>
+{
+ enum { coordinate_count = 2 };
+};
+
+
+int main()
+{
+ point p1;
+ const point p2;
+ geometry::function_requiring_a_point(p1, p2);
+}

Added: sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/point_without_getter.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/point_without_getter.cpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,37 @@
+// Geometry Library Point concept test file
+//
+// Copyright Bruno Lalande 2008
+// Copyright Barend Gehrels, Geodan Holding B.V. 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)
+
+
+#include <boost/tuple/tuple.hpp>
+#include "function_requiring_a_point.hpp"
+
+
+struct point: private boost::tuple<float, float>
+{
+ typedef float coordinate_type;
+ enum { coordinate_count = 2 };
+
+ template <int I>
+ float& get()
+ { return boost::tuple<float, float>::get<I>(); }
+
+ /*
+ template <int I>
+ const float& get() const
+ { return boost::tuple<float, float>::get<I>(); }
+ */
+
+};
+
+
+int main()
+{
+ point p1;
+ const point p2;
+ geometry::function_requiring_a_point(p1, p2);
+}

Added: sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/point_without_setter.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/point_without_setter.cpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,36 @@
+// Geometry Library Point concept test file
+//
+// Copyright Bruno Lalande 2008
+// Copyright Barend Gehrels, Geodan Holding B.V. 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)
+
+
+#include <boost/tuple/tuple.hpp>
+#include "function_requiring_a_point.hpp"
+
+
+struct point: private boost::tuple<float, float>
+{
+ typedef float coordinate_type;
+ enum { coordinate_count = 2 };
+
+ /*
+ template <int I>
+ float& get()
+ { return boost::tuple<float, float>::get<I>(); }
+ */
+
+ template <int I>
+ const float& get() const
+ { return boost::tuple<float, float>::get<I>(); }
+};
+
+
+int main()
+{
+ point p1;
+ const point p2;
+ geometry::function_requiring_a_point(p1, p2);
+}

Added: sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/well_formed_point.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/well_formed_point.cpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,26 @@
+// Geometry Library Point concept test file
+//
+// Copyright Bruno Lalande 2008
+// Copyright Barend Gehrels, Geodan Holding B.V. 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)
+
+
+#include <boost/tuple/tuple.hpp>
+#include "function_requiring_a_point.hpp"
+
+
+struct point: public boost::tuple<float, float>
+{
+ typedef float coordinate_type;
+ enum { coordinate_count = 2 };
+};
+
+
+int main()
+{
+ point p1;
+ const point p2;
+ geometry::function_requiring_a_point(p1, p2);
+}

Added: sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/well_formed_point_traits.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/test/point_concept_tests/well_formed_point_traits.cpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,68 @@
+// Geometry Library Point concept test file
+//
+// Copyright Bruno Lalande 2008
+// Copyright Barend Gehrels, Geodan Holding B.V. 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)
+
+
+#include "function_requiring_a_point.hpp"
+
+
+struct point
+{
+ point(): x(), y() {}
+ float x, y;
+};
+
+
+template <int I> struct accessor;
+
+template <>
+struct accessor<0>
+{
+ static float& get(point& p) { return p.x; }
+ static const float& get(const point& p) { return p.x; }
+};
+
+template <>
+struct accessor<1>
+{
+ static float& get(point& p) { return p.y; }
+ static const float& get(const point& p) { return p.y; }
+};
+
+
+namespace geometry
+{
+ template <>
+ struct point_traits<point>
+ {
+ typedef float coordinate_type;
+ enum { coordinate_count = 2 };
+
+ template <int I>
+ static float& get(point& p)
+ { return accessor<I>::get(p); }
+ };
+
+ template <>
+ struct point_traits<const point>
+ {
+ typedef float coordinate_type;
+ enum { coordinate_count = 2 };
+
+ template <int I>
+ static const float& get(const point& p)
+ { return accessor<I>::get(p); }
+ };
+}
+
+
+int main()
+{
+ point p1;
+ const point p2;
+ geometry::function_requiring_a_point(p1, p2);
+}

Added: sandbox/SOC/2008/spacial_indexing/geometry/test/pythagoras.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/test/pythagoras.cpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,84 @@
+// Geometry Library test file
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. Amsterdam, the Netherlands.
+// Copyright Bruno Lalande 2008
+// 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)
+
+
+#define BOOST_TEST_MODULE
+#define BOOST_TEST_DYN_LINK
+#include <boost/test/unit_test.hpp>
+#include <boost/test/floating_point_comparison.hpp>
+#include <geometry/strategies/strategies_point_xy.hpp>
+#include "common.hpp"
+
+
+using namespace geometry;
+
+
+template <typename P1, typename P2>
+void test_null_distance()
+{
+ P1 p1;
+ init_point(p1, 1, 2, 3);
+ P2 p2;
+ init_point(p2, 1, 2, 3);
+ BOOST_CHECK((geometry::strategy::distance::pythagoras<P1, P2>()(p1, p2) == 0));
+}
+
+template <typename P1, typename P2>
+void test_axis()
+{
+ P1 p1;
+ init_point(p1, 0, 0, 0);
+
+ P2 p2;
+ init_point(p2, 1, 0, 0);
+ BOOST_CHECK((geometry::strategy::distance::pythagoras<P1, P2>()(p1, p2) == 1));
+ init_point(p2, 0, 1, 0);
+ BOOST_CHECK((geometry::strategy::distance::pythagoras<P1, P2>()(p1, p2) == 1));
+ init_point(p2, 0, 0, 1);
+ BOOST_CHECK((geometry::strategy::distance::pythagoras<P1, P2>()(p1, p2) == 1));
+}
+
+template <typename P1, typename P2>
+void test_arbitrary()
+{
+ P1 p1;
+ init_point(p1, 1, 2, 3);
+ P2 p2;
+ init_point(p2, 9, 8, 7);
+ BOOST_CHECK_CLOSE((double)(geometry::strategy::distance::pythagoras<P1, P2>()(p1, p2)),
+ sqrt(116),
+ 0.001
+ );
+}
+
+
+template <typename P1, typename P2>
+void test_all()
+{
+ test_null_distance<P1, P2>();
+ test_axis<P1, P2>();
+ test_arbitrary<P1, P2>();
+}
+
+template <typename P>
+void test_all()
+{
+ test_all<P, int[3]>();
+ test_all<P, float[3]>();
+ test_all<P, double[3]>();
+ test_all<P, test_point>();
+}
+
+
+BOOST_AUTO_TEST_CASE(pythagoras_test)
+{
+ test_all<int[3]>();
+ test_all<float[3]>();
+ test_all<double[3]>();
+ test_all<test_point>();
+}

Added: sandbox/SOC/2008/spacial_indexing/geometry/test/within_test.cpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/test/within_test.cpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,67 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan B.V. 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)
+
+#include <geometry/within.hpp>
+#include <geometry/normalize.hpp>
+
+#include <boost/config.hpp>
+#include <boost/test/included/test_exec_monitor.hpp>
+
+
+int test_main1( int , char* [] )
+{
+ typedef geometry::point<double> gl_point;
+ typedef geometry::circle<gl_point, double> gl_circle;
+ typedef geometry::box<gl_point> gl_box;
+ typedef geometry::linestring<gl_point> gl_line;
+ typedef geometry::linear_ring<gl_point> gl_ring;
+ typedef geometry::polygon<gl_point> gl_polygon;
+ typedef geometry::multi_polygon<gl_polygon> gl_multi_polygon;
+
+
+ gl_box box(gl_point(0,0), gl_point(2,2));
+ gl_circle circle(gl_point(1, 1), 2.5);
+ gl_line line;
+ line.push_back(gl_point(1,1));
+ line.push_back(gl_point(2,1));
+ line.push_back(gl_point(2,2));
+
+ gl_ring ring;
+ ring.push_back(gl_point(0,0));
+ ring.push_back(gl_point(1,0));
+ ring.push_back(gl_point(1,1));
+ ring.push_back(gl_point(0,1));
+ normalize(ring);
+
+ gl_polygon pol;
+ pol.outer() = ring;
+ gl_multi_polygon multi_polygon;
+ multi_polygon.push_back(pol);
+
+
+ // Point in circle
+ BOOST_CHECK_EQUAL(within(gl_point(2, 1), circle), true);
+ BOOST_CHECK_EQUAL(within(gl_point(12, 1), circle), false);
+
+ // Line in circle
+ BOOST_CHECK_EQUAL(within(line, circle), true);
+
+ line.push_back(gl_point(10,10));
+ BOOST_CHECK_EQUAL(within(line, circle), false);
+
+ // Box/ring/poly/multipoly in circle
+ BOOST_CHECK_EQUAL(within(box, circle), true);
+ BOOST_CHECK_EQUAL(within(ring, circle), true);
+
+ BOOST_CHECK_EQUAL(within(multi_polygon, circle), true);
+
+ // Point in box
+ BOOST_CHECK_EQUAL(within(gl_point(1, 1), box), true);
+ BOOST_CHECK_EQUAL(within(gl_point(12, 1), box), false);
+
+ return 0;
+}

Added: sandbox/SOC/2008/spacial_indexing/geometry/util/builder.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/util/builder.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,318 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_BUILDER_HPP
+#define _GEOMETRY_BUILDER_HPP
+
+#include <boost/scoped_array.hpp>
+
+namespace geometry
+{
+
+ /***
+
+ * probably not necessary, in these cases points can be added directly.
+
+ // Polygon builder version using a vector, to which points/holes can be added
+ // Builds on destruction OR on call to build()
+ template <class P, class Y>
+ class polygon_builder_vector
+ {
+ public :
+ polygon_builder_vector(Y& poly)
+ : m_poly(poly)
+ {}
+
+ virtual ~polygon_builder_vector()
+ {
+ build();
+ }
+
+ void build()
+ {
+ m_poly.outer().clear();
+ m_poly.inners().resize(m_hole_array.size());
+
+ if (m_point_array.size() <= 0)
+ {
+ return;
+ }
+
+ P& first = m_point_array.front();
+ int r = -1;
+ int h = 0;
+ int i = 0;
+ for (std::vector<P>::const_iterator it = m_point_array.begin();
+ it != m_point_array.end(); it++, i++)
+ {
+ // Check hole: if it is a holeindex, increase index r for rings
+ if (m_hole_array.size() > h && i == m_hole_array[h])
+ {
+ r = h++;
+ }
+
+ if (r == -1)
+ {
+ m_poly.outer().push_back(Y::point_type(it->x(), it->y()));
+ }
+ else
+ {
+ // Some files indicate a hole using the very first point of the polygon.
+ // They then also close the complete polygon with the very first point
+ // Those points are skipped
+ if (! (first == *it))
+ {
+ m_poly.inners()[r].push_back(Y::point_type(it->x(), it->y()));
+ }
+ }
+ }
+
+ m_hole_array.clear();
+ m_point_array.clear();
+ }
+
+ inline void add_hole(int h)
+ {
+ m_hole_array.push_back(h);
+ }
+ inline void add_point(const P& p)
+ {
+ m_point_array.push_back(p);
+ }
+
+ private :
+ std::vector<P> m_point_array;
+ std::vector<uint32> m_hole_array;
+ Y& m_poly;
+ };
+ ***/
+
+
+ // Many files need a pointer to an array of points and/or holes
+ // The class below plus the builders below support that
+
+ // a boost scoped array, extended with a count and a size
+ template <typename T>
+ class scoped_array_with_size : public boost::scoped_array<T>
+ {
+ public :
+ scoped_array_with_size(int n)
+ : m_count(n)
+ , boost::scoped_array<T>(n > 0 ? new T[n] : NULL)
+ {}
+ inline void resize(int n)
+ {
+ m_count = n;
+ reset(n > 0 ? new T[n] : NULL);
+ }
+ inline int count() const { return m_count; }
+ inline int memorysize() const { return m_count * sizeof(T); }
+ private :
+ int m_count;
+
+ };
+
+
+ // A linebuilder-pointer class, builds the line on destruction
+ template <typename P, typename L>
+ class line_builder
+ {
+ public :
+ line_builder(L& line, int n)
+ : m_point_array(n)
+ , m_line(line)
+ {
+ }
+
+ virtual ~line_builder()
+ {
+ m_line.clear();
+ P* p = m_point_array.get();
+ for (int i = 0; i < m_point_array.count(); i++)
+ {
+ m_line.push_back(L::point_type(p->x, p->y));
+ p++;
+ }
+ }
+
+ inline int pointarray_size() const { return m_point_array.memorysize(); }
+ inline P* pointarray() { return m_point_array.get(); }
+
+ private :
+ scoped_array_with_size<P> m_point_array;
+ L& m_line;
+ };
+
+ // Polygon builder-pointer class, builds polygons on destruction.
+ // Creates inner rings using array with hole-indexes
+ template <typename P, typename Y>
+ class polygon_builder
+ {
+ public :
+ polygon_builder(Y& poly, int n, int holecount = 0)
+ : m_point_array(n)
+ , m_hole_array(holecount)
+ , m_poly(poly)
+ {}
+
+ virtual ~polygon_builder()
+ {
+ m_poly.outer().clear();
+ m_poly.inners().resize(m_hole_array.count());
+
+ if (m_point_array.count() <= 0)
+ {
+ return;
+ }
+
+ P* p = m_point_array.get();
+ P& first = *p;
+ int r = -1;
+ int h = 0;
+ for (int i = 0; i < m_point_array.count(); i++)
+ {
+ // Check hole: if it is a holeindex, increase index r for rings
+ if (m_hole_array.count() > h && i == m_hole_array[h])
+ {
+ r = h++;
+ }
+
+ if (r == -1)
+ {
+ m_poly.outer().push_back(Y::point_type(p->x, p->y));
+ }
+ else
+ {
+ // Some files indicate a hole using the very first point of the polygon.
+ // They then also close the complete polygon with the very first point
+ // Those points are skipped
+ if (! (first == *p))
+ {
+ m_poly.inners()[r].push_back(Y::point_type(p->x, p->y));
+ }
+ }
+ p++;
+ }
+ }
+
+ inline void set_holecount(int n)
+ {
+ m_hole_array.resize(n);
+ }
+
+ inline int pointarray_size() const { return m_point_array.memorysize(); }
+ inline P* pointarray() { return m_point_array.get(); }
+
+ inline int holearray_size() const { return m_hole_array.memorysize(); }
+ inline uint32* holearray() { return m_hole_array.get(); }
+
+
+ private :
+ scoped_array_with_size<P> m_point_array;
+ scoped_array_with_size<uint32> m_hole_array;
+ Y& m_poly;
+ };
+
+
+
+
+ // A linebuilder-pointer class, builds the line on destruction
+ template <typename P, typename L>
+ class line_extractor
+ {
+ public :
+ line_extractor(const L& line)
+ : m_point_array(line.size())
+ , m_line(line)
+ {
+ P* p = m_point_array.get();
+ for(L::const_iterator it = line.begin(); it != line.end(); it++)
+ {
+ p->x = it->x();
+ p->y = it->y();
+ p++;
+ }
+ }
+
+ inline int pointarray_size() const { return m_point_array.memorysize(); }
+ inline const P* pointarray() const { return m_point_array.get(); }
+
+ private :
+ scoped_array_with_size<P> m_point_array;
+ const L& m_line;
+ };
+
+
+ template <typename P, typename Y>
+ class polygon_extractor
+ {
+ public :
+ polygon_extractor(const Y& poly)
+ : m_poly(poly)
+ , m_point_array(0)
+ , m_hole_array(0)
+ {
+ // Calculate total point-size
+ int n = poly.outer().size();
+ for (int i = 0; i < poly.inners().size(); i++)
+ {
+ n += 1 + poly.inners()[i].size();
+ }
+ m_point_array.resize(n);
+ m_hole_array.resize(poly.inners().size());
+
+ // Fill the points with outer/inner arrays
+ n = 0;
+ add_points(poly.outer(), m_point_array.get(), n);
+ uint32* h = m_hole_array.get();
+ for (int i = 0; i < poly.inners().size(); i++)
+ {
+ h[i] = n;
+ add_points(poly.inners()[i], m_point_array.get(), n);
+ add_very_first(m_point_array.get(), n);
+ }
+ }
+
+ inline int pointarray_count() const { return m_point_array.count(); }
+ inline int pointarray_size() const { return m_point_array.memorysize(); }
+ inline const P* pointarray()const { return m_point_array.get(); }
+
+ inline int holearray_count() const { return m_hole_array.count(); }
+ inline int holearray_size() const { return m_hole_array.memorysize(); }
+ inline const uint32* holearray()const { return m_hole_array.get(); }
+
+
+ private :
+ typedef typename Y::ring_type R;
+
+ scoped_array_with_size<P> m_point_array;
+ scoped_array_with_size<uint32> m_hole_array;
+ const Y& m_poly;
+
+ inline void add_points(const R& r, P* p, int& n)
+ {
+ for(R::const_iterator it = r.begin(); it != r.end(); it++)
+ {
+ p[n].x = it->x();
+ p[n].y = it->y();
+ n++;
+ }
+ }
+
+ // add very first point to denote end-of-hole
+ inline void add_very_first(P* p, int& n)
+ {
+ const P& very_first = *p;
+ p[n++] = very_first;
+ }
+
+ };
+
+
+} // namespace geometry
+
+#endif // _GEOMETRY_BUILDER_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/util/math.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/util/math.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,80 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_MATH_HPP
+#define _GEOMETRY_MATH_HPP
+
+#include <limits>
+#include <cmath>
+#include <geometry/util/promotion_traits.hpp>
+
+namespace geometry
+{
+ // Maybe replace this by boost equals or boost ublas numeric equals or so
+
+ /*!
+ \brief returns true if both arguments are equal.
+
+ equals returns true if both arguments are equal.
+ \param a first argument
+ \param b second argument
+ \return true if a == b
+ \note If both a and b are of an integral type, comparison is done by ==. If one of the types
+ is floating point, comparison is done by abs and comparing with epsilon.
+ */
+ template <typename T1, typename T2>
+ inline bool equals(const T1& a, const T2& b)
+ {
+ typedef typename select_type_traits<T1, T2>::type T;
+ if (std::numeric_limits<T>::is_exact)
+ {
+ return a == b;
+ }
+ else
+ {
+#ifdef __GNUC__
+ return fabs(a - b) < std::numeric_limits<T>::epsilon();
+#else
+ return abs(a - b) < std::numeric_limits<T>::epsilon();
+#endif
+ }
+ }
+
+
+ namespace math
+ {
+ // From boost/.../normal_distribution.hpp : "Can we have a boost::mathconst please?"
+ static double const pi = 2.0 * acos(0.0);
+ static const double two_pi = 2.0 * pi;
+ static const double d2r = pi / 180.0;
+ static const double r2d = 1.0 / d2r;
+
+ /*!
+ \brief Calculates the haversine of an angle
+ \note See http://en.wikipedia.org/wiki/Haversine_formula
+ haversin(alpha) = sin2(alpha/2)
+ */
+ inline double hav(double theta)
+ {
+ double sn = sin(0.5 * theta);
+ return sn * sn;
+ }
+
+ /*!
+ \brief Short utility to return the square
+
+ \param value Value to calculate the square from
+ \return The squared value
+ */
+ inline double sqr(double value) { return value * value; }
+
+ }
+
+
+} // namespace geometry
+
+#endif // _GEOMETRY_MATH_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/util/promotion_traits.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/util/promotion_traits.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,73 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_PROMOTION_TRAITS_HPP
+#define _GEOMETRY_PROMOTION_TRAITS_HPP
+
+
+namespace geometry
+{
+ /*!
+ \brief Traits class to select, of two types, the most accurate type for calculations
+ \details The promotion traits classes, base class and specializations, compares two types on compile time.
+ For example, if an addition must be done with a double and an integer, the result must be a double.
+ If both types are integer, the results can be an integer.
+ The select_type_traits class and its specializations define the appropriate type in the member type <em>type</em>.
+ \note Might be replaced by the new promotion_traits class of boost.
+ */
+ template<typename T1, typename T2>
+ struct select_type_traits
+ {
+ typedef T1 type;
+ };
+
+ // (Partial) specializations
+
+ // Any combination with double will define a double
+ template<typename T> struct select_type_traits<double, T> { typedef double type; };
+ template<typename T> struct select_type_traits<T, double> { typedef double type; };
+ // Avoid ambiguity for the double/double case
+ template<> struct select_type_traits<double, double> { typedef double type; };
+
+ // List other cases
+ template<> struct select_type_traits<int, float> { typedef float type; };
+ template<> struct select_type_traits<float, int> { typedef float type; };
+
+ // to be extended
+
+
+
+ /*!
+ \brief Traits class to select a larger type to avoid overflow in some calculations
+ \details Converts small integer classes to long int, and float to double
+ \note Maybe this class can be replaced by the new (accepted?) promotion_traits class of boost.
+ */
+ template<typename T>
+ struct large_type_traits
+ {
+ typedef T type;
+ };
+
+ template<> struct large_type_traits<float> { typedef double type; };
+ template<> struct large_type_traits<char> { typedef long int type; };
+ template<> struct large_type_traits<short int> { typedef long int type; };
+
+ /*!
+ \brief Combination of select_type_traits and large_type_traits for convenience
+ \details Selects the most appropriate type for calculation on two values of
+ possibly different type, and making them larger if necessary to avoid overflow.
+ \note Maybe this class can be replaced by the new (accepted?) promotion_traits class of boost.
+ */
+ template <typename T1, typename T2>
+ struct calculation_traits
+ {
+ typedef large_type_traits<typename select_type_traits<T1, T2>::type> type;
+ };
+
+}
+
+#endif // _GEOMETRY_PROMOTION_TRAITS_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/util/reserve.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/util/reserve.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,35 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_UTIL_RESERVE_HPP
+#define _GEOMETRY_UTIL_RESERVE_HPP
+
+#include <list>
+#include <deque>
+
+namespace geometry
+{
+ // We would like to have a "reserve" on list. Fixed as a generic function, with overloads/partial specializations
+
+ template <typename T, template<typename> class A, template<typename,typename> class V>
+ void container_reserve(V<T, A<T> >& container, int n)
+ {
+ container.reserve(n);
+ }
+
+ // Partially specialize for list such that calls to container_reserve are OK now
+ template <typename T, template<typename> class A>
+ void container_reserve(std::list<T, A<T> >, int n)
+ {
+ }
+ template <typename T, template<typename> class A>
+ void container_reserve(std::deque<T, A<T> >, int n)
+ {
+ }
+} // namespace geometry
+
+#endif // _GEOMETRY_UTIL_RESERVE_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/util/return_types.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/util/return_types.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,43 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_RETURN_TYPES_HPP
+#define _GEOMETRY_RETURN_TYPES_HPP
+
+#include <utility>
+
+namespace geometry
+{
+ /*!
+ \brief Encapsulate the results of distance calculation
+ \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.
+ */
+ //template <typename T>
+ struct distance_result : public std::pair<double, bool>
+ {
+ public :
+ /// Constructor with a value and a boolean flag
+ distance_result(double v, bool b)
+ : std::pair<double, bool> (v, b)
+ {}
+
+ /// Automatic conversion to double, taking squareroot if necessary
+ inline operator double() const
+ {
+ return second ? sqrt(first) : first;
+ }
+ };
+
+
+} // namespace geometry
+
+
+#endif // _GEOMETRY_RETURN_TYPES_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/util/side.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/util/side.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,39 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_SIDE_HPP
+#define _GEOMETRY_SIDE_HPP
+
+#include <geometry/util/promotion_traits.hpp>
+#include <geometry/concepts/point_traits.hpp>
+
+namespace geometry
+{
+
+ // Check at which side of a segment a point lies:
+ // left of segment (> 0), right of segment (< 0), on segment (0)
+ // In fact this is twice the area of a triangle
+ template <typename S, typename P>
+ inline typename select_type_traits<typename point_traits<S>::coordinate_type,
+ typename point_traits<P>::coordinate_type>::type
+ point_side(const S& s, const P &p)
+ {
+ typedef typename select_type_traits<typename point_traits<S>::coordinate_type,
+ typename point_traits<P>::coordinate_type>::type T;
+
+ // Todo: might be changed to subtract_point
+ T dx = get<0>(s.second) - get<0>(s.first);
+ T dy = get<1>(s.second) - get<1>(s.first);
+ T dpx = get<0>(p) - get<0>(s.first);
+ T dpy = get<1>(p) - get<1>(s.first);
+ return dx * dpy - dy * dpx;
+ }
+
+
+} // namespace geometry
+
+#endif // _GEOMETRY_SIDE_HPP

Added: sandbox/SOC/2008/spacial_indexing/geometry/within.hpp
==============================================================================
--- (empty file)
+++ sandbox/SOC/2008/spacial_indexing/geometry/within.hpp 2008-06-04 15:44:25 EDT (Wed, 04 Jun 2008)
@@ -0,0 +1,298 @@
+// Geometry Library
+//
+// Copyright Barend Gehrels, Geodan Holding B.V. 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 _GEOMETRY_WITHIN_HPP
+#define _GEOMETRY_WITHIN_HPP
+
+#include <boost/static_assert.hpp>
+
+#include <geometry/geometry.hpp>
+#include <geometry/segment.hpp>
+#include <geometry/circle.hpp>
+#include <geometry/box.hpp>
+#include <geometry/distance.hpp>
+#include <geometry/util/side.hpp>
+
+#include <geometry/loop.hpp>
+
+#include <geometry/strategies/strategy_traits.hpp>
+#include <geometry/strategies/strategies_point_xy.hpp>
+
+
+/*!
+\defgroup within within: containment algorithms such as point in polygon
+The within algorithm checks if one geometry is located completely within another geometry.
+A well-known example is point-in-polygon, returning true if a point falls within a polygon.
+Many point-in-polygon algorithms ignore boundary cases (point is situated on boundary of polygon),
+however the within_point_in_polygon method should return true if a point is completely within the
+boundary of the polygon, and not on the boundary.
+*/
+
+
+namespace geometry
+{
+ /*!
+ \ingroup impl
+ */
+ namespace impl
+ {
+ namespace within
+ {
+
+ // Within, should return true if one geometry falls completely within another geometry
+ // Geometries can lie in something with an area, so in an box,circle,linear_ring,polygon
+
+ //-------------------------------------------------------------------------------------------------------
+ // Implementation for boxes. Supports boxes in 2 or 3 dimensions, in Euclidian system
+ // Todo: implement as strategy
+ //-------------------------------------------------------------------------------------------------------
+ template <typename P, typename B, int I, int N>
+ struct point_in_box
+ {
+ static bool inside(const P& p, const B& b)
+ {
+ if (get<I>(p) < get<I>(b.min()) || get<I>(p) > get<I>(b.max()))
+ {
+ return false;
+ }
+
+ return point_in_box<P, B, I+1, N>::inside(p, b);
+ }
+ };
+
+ template <typename P, typename B, int N>
+ struct point_in_box<P, B, N, N>
+ {
+ static bool inside(const P& p, const B& b)
+ {
+ return true;
+ }
+ };
+
+
+ //-------------------------------------------------------------------------------------------------------
+ // Implementation for circles. Supports circles or spheres, in 2 or 3 dimensions, in Euclidian system
+ // Circle center might be of other point-type as geometry
+ // Todo: implement as strategy
+ //-------------------------------------------------------------------------------------------------------
+ template<typename P, typename C>
+ inline bool point_in_circle(const P& p, C& c)
+ {
+ strategy::distance::pythagoras<P, typename C::point_type> s;
+ distance_result r = impl::distance::point_to_point(p, c.center(), s);
+ return r.first < c.radius() * c.radius();
+ }
+
+
+ template<typename B, typename C>
+ inline bool box_in_circle(const B& b, const C& c)
+ {
+ typedef typename B::point_type P;
+
+ // Currently only implemented for 2d points
+ BOOST_STATIC_ASSERT(point_traits<P>::coordinate_count == 2);
+
+ // Box: all four points must lie within circle
+
+ // Check points lower-left and upper-right
+ if (point_in_circle(b.min(), c) && point_in_circle(b.max(), c))
+ {
+ // Check points lower-right and upper-left
+ P p1;
+ P p2;
+ get<0>(p1) = get<0>(b.min());
+ get<1>(p1) = get<1>(b.max());
+ get<0>(p2) = get<0>(b.max());
+ get<1>(p2) = get<1>(b.min());
+ return point_in_circle(p1, c) && point_in_circle(p2, c);
+ }
+ return false;
+ }
+
+
+ // Generic "vector of points - in - circle", true if all points within circle
+ template<typename V, typename C>
+ inline bool container_in_circle(const V& v, const C& c)
+ {
+ for (typename V::const_iterator i = v.begin(); i != v.end(); i++)
+ {
+ if (! point_in_circle(*i, c))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ template<typename Y, typename C>
+ inline bool polygon_in_circle(const Y& poly, const C& c)
+ {
+ return container_in_circle(poly.outer(), c);
+ }
+
+
+
+
+ template<typename P, typename R, typename S>
+ inline bool point_in_ring(const P& p, const R& r, const S& strategy)
+ {
+ if (r.size() < 4)
+ {
+ return false;
+ }
+
+ typename S::state_type state(p);
+ if (loop(r, strategy, state))
+ {
+ return state.within();
+ }
+ return false;
+ }
+
+ // Polygon: in outer linear_ring, and if so, not within inner ring(s)
+ template<typename P, typename Y, typename S>
+ inline bool point_in_polygon(const P& p, const Y& poly, const S& strategy)
+ {
+ if (point_in_ring(p, poly.outer(), strategy))
+ {
+ for (typename Y::inner_container_type::const_iterator i = poly.inners().begin();
+ i != poly.inners().end(); i++)
+ {
+ if (point_in_ring(p, *i, strategy))
+ {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+ }
+
+
+ } // namespace within
+ } // namespace impl
+
+
+
+
+ template<typename P1, typename P2>
+ inline bool within(const P1& p, const box<P2>& b)
+ {
+ BOOST_STATIC_ASSERT(point_traits<P1>::coordinate_count == point_traits<P2>::coordinate_count);
+ return impl::within::point_in_box<P1, box<P2>,
+ 0, point_traits<P1>::coordinate_count>::inside(p, b);
+ }
+
+ template<typename P, typename C, typename T>
+ inline bool within(const P& p, const circle<C, T>& c)
+ {
+ return impl::within::point_in_circle(p, c);
+ }
+
+ template<typename P, typename C, typename T>
+ inline bool within(const box<P>& b, const circle<C, T>& c)
+ {
+ return impl::within::box_in_circle(b, c);
+ }
+
+ template<typename C, typename T,
+ typename P,
+ template<typename,typename> class V,
+ template<typename> class A>
+ inline bool within(const linestring<P, V, A>& ln, const circle<C, T>& c)
+ {
+ return impl::within::container_in_circle(ln, c);
+ }
+
+ template<typename C, typename T,
+ typename P,
+ template<typename,typename> class V,
+ template<typename> class A>
+ inline bool within(const linear_ring<P, V, A>& r, const circle<C, T>& c)
+ {
+ return impl::within::container_in_circle(r, c);
+ }
+
+ template<typename C, typename T,
+ typename P,
+ template<typename,typename> class VP,
+ template<typename,typename> class VR,
+ template<typename> class AP,
+ template<typename> class AR>
+ inline bool within(const polygon<P, VP, VR, AP, AR>& poly, const circle<C, T>& c)
+ {
+ return impl::within::polygon_in_circle(poly, c);
+ }
+
+
+ template<typename P1, typename P2,
+ template<typename,typename> class V,
+ template<typename> class A>
+ inline bool within(const P1& p, const linear_ring<P2, V, A>& r)
+ {
+ return impl::within::point_in_ring(p, r);
+ }
+
+ /*!
+ \brief Examine if point is in polygon
+ \ingroup within
+ \details The function within, for point-polygon, returns the point lies completely within the polygon
+ \param p point to examine
+ \param poly polygon to examine
+ \return true if point is completely contained within the polygon, else false
+ \par Example:
+ The within algorithm is used as following:
+ \dontinclude doxygen_examples.cpp
+ \skip example_within
+ \line {
+ \until }
+ \note The strategy bound by the specialized strategy_traits class is used for within detection
+ */
+ template<typename P1, typename P2,
+ template<typename,typename> class VP,
+ template<typename,typename> class VR,
+ template<typename> class AP,
+ template<typename> class AR>
+ inline bool within(const P1& p, const polygon<P2, VP, VR, AP, AR>& poly)
+ {
+ return impl::within::point_in_polygon(p, poly,
+ typename strategy_traits<P1,P2>::within());
+ }
+
+ /*!
+ \brief Examine if point is in polygon
+ \ingroup within
+ \details The function within, for point-polygon, returns the point lies within the polygon, using a specified strategy
+ \param p point to examine
+ \param poly polygon to examine
+ \param strategy optional strategy to be used for within detection.
+ If not specified, the default within-detection strategy is taken.
+ \return true if point is within the polygon, else false
+ \par Example:
+ Example showing how to use within using a strategy
+ \dontinclude doxygen_examples.cpp
+ \skip example_within_strategy
+ \line {
+ \until }
+ \note The strategy bound by the specialized strategy_traits class is used for within detection
+ */
+ template<typename P1, typename P2,
+ template<typename,typename> class VP,
+ template<typename,typename> class VR,
+ template<typename> class AP,
+ template<typename> class AR,
+ typename S>
+ inline bool within(const P1& p, const polygon<P2, VP, VR, AP, AR>& poly, const S& strategy)
+ {
+ return impl::within::point_in_polygon(p, poly, strategy);
+ }
+
+
+} // namespace geometry
+
+
+#endif // _GEOMETRY_WITHIN_HPP


Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk